# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

mesh_morpher.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 
00028 #include "3d/mesh_morpher.h"
00029 #include "3d/vertex_buffer.h"
00030 #include "3d/vertex_buffer_hard.h"
00031 
00032 
00033 using namespace std;
00034 using namespace NLMISC;
00035 
00036 
00037 namespace NL3D 
00038 {
00039 
00040 // ***************************************************************************
00041 void CBlendShape::serial (NLMISC::IStream &f) throw(NLMISC::EStream)
00042 {
00043         // version 1 : added tangent space support
00044         sint ver = f.serialVersion (1);
00045 
00046         f.serial (Name);
00047 
00048         f.serialCont (deltaPos);
00049         f.serialCont (deltaNorm);
00050         f.serialCont (deltaUV);
00051         f.serialCont (deltaCol);
00052 
00053         if (ver >= 1) f.serialCont(deltaTgSpace);
00054 
00055         f.serialCont (VertRefs);
00056 }
00057 
00058 // ***************************************************************************
00059 CMeshMorpher::CMeshMorpher()
00060 {
00061         _VBOri = NULL;
00062         _VBDst = NULL;
00063         _VBDstHrd = NULL;
00064 
00065         _Vertices = NULL;
00066         _Normals = NULL;
00067         _TgSpace= NULL;
00068         _SkinApplied= false;
00069 }
00070 
00071 // ***************************************************************************
00072 void CMeshMorpher::init (CVertexBuffer *vbOri, CVertexBuffer *vbDst, IVertexBufferHard *vbDstHrd, bool hasTgSpace)
00073 {
00074         _VBOri = vbOri;
00075         _VBDst = vbDst;
00076         _VBDstHrd = vbDstHrd;
00077         _UseTgSpace = hasTgSpace;
00078 }
00079 
00080 // ***************************************************************************
00081 void CMeshMorpher::initSkinned (CVertexBuffer *vbOri,
00082                                                         CVertexBuffer *vbDst,
00083                                                         IVertexBufferHard *vbDstHrd,
00084                                                         bool hasTgSpace,
00085                                                         std::vector<CVector> *vVertices,
00086                                                         std::vector<CVector> *vNormals,
00087                                                         std::vector<CVector> *vTgSpace, /* NULL if none */
00088                                                         bool bSkinApplied       )
00089 {
00090         _VBOri = vbOri;
00091         _VBDst = vbDst;
00092         _VBDstHrd = vbDstHrd;
00093         _UseTgSpace = hasTgSpace;
00094 
00095         _Vertices = vVertices;
00096         _Normals = vNormals;
00097         _TgSpace = vTgSpace;
00098         _SkinApplied = bSkinApplied;
00099 }
00100 
00101 // ***************************************************************************
00102 void CMeshMorpher::update (std::vector<CAnimatedMorph> *pBSFactor)
00103 {
00104         uint32 i, j;
00105 
00106         if (_VBOri == NULL)
00107                 return;
00108         if (BlendShapes.size() == 0)
00109                 return;
00110 
00111         if (_VBOri->getNumVertices() != _VBDst->getNumVertices())
00112         {       // Because the original vertex buffer is not initialized by default
00113                 // we must init it here (if there are some blendshapes)
00114                 *_VBOri = *_VBDst;
00115         }
00116 
00117         // Does the flags are reserved ?
00118         if (_Flags.size() != _VBOri->getNumVertices())
00119         {
00120                 _Flags.resize (_VBOri->getNumVertices());
00121                 for (i = 0; i < _Flags.size(); ++i)
00122                         _Flags[i] = Modified; // Modified to update all
00123         }
00124 
00125         nlassert(_VBOri->getVertexFormat() == _VBDst->getVertexFormat());
00126 
00127         // Cleaning with original vertex buffer
00128         uint32 VBVertexSize = _VBOri->getVertexSize();
00129         uint8 *pOri = (uint8*)_VBOri->getVertexCoordPointer ();
00130         uint8 *pDst = (uint8*)_VBDst->getVertexCoordPointer ();
00131         
00132         for (i= 0; i < _Flags.size(); ++i)
00133         if (_Flags[i] >= Modified)
00134         {
00135                 _Flags[i] = OriginalVBDst;
00136 
00137                 for(j = 0; j < VBVertexSize; ++j)
00138                         pDst[j+i*VBVertexSize] = pOri[j+i*VBVertexSize];
00139         }
00140 
00141         uint tgSpaceStage = 0;
00142         if (_UseTgSpace)
00143         {
00144                 tgSpaceStage = _VBDst->getNumTexCoordUsed() - 1;
00145         }
00146 
00147         // Blending with blendshape
00148         for (i = 0; i < BlendShapes.size(); ++i)
00149         {
00150                 CBlendShape &rBS = BlendShapes[i];
00151                 float rFactor = pBSFactor->operator[](i).getFactor()/100.0f;
00152 
00153                 if (rFactor > 0.0f)
00154                 for (j = 0; j < rBS.VertRefs.size(); ++j)
00155                 {
00156                         uint32 vp = rBS.VertRefs[j];
00157 
00158                         // Modify Pos/Norm/TgSpace.
00159                         //------------
00160                         if (_VBDst->getVertexFormat() & CVertexBuffer::PositionFlag)
00161                         if (rBS.deltaPos.size() > 0)
00162                         {
00163                                 CVector *pV = (CVector*)_VBDst->getVertexCoordPointer (vp);
00164                                 *pV += rBS.deltaPos[j] * rFactor;
00165                         }
00166 
00167                         if (_VBDst->getVertexFormat() & CVertexBuffer::NormalFlag)
00168                         if (rBS.deltaNorm.size() > 0)
00169                         {
00170                                 CVector *pV = (CVector*)_VBDst->getNormalCoordPointer (vp);
00171                                 *pV += rBS.deltaNorm[j] * rFactor;
00172                         }
00173 
00174                         if (_UseTgSpace)
00175                         if (rBS.deltaTgSpace.size() > 0)
00176                         {
00177                                 CVector *pV = (CVector*)_VBDst->getTexCoordPointer (vp, tgSpaceStage);
00178                                 *pV += rBS.deltaTgSpace[j] * rFactor;
00179                         }
00180 
00181                         // Modify UV0 / Color
00182                         //------------
00183                         if (_VBDst->getVertexFormat() & CVertexBuffer::TexCoord0Flag)
00184                         if (rBS.deltaUV.size() > 0)
00185                         {
00186                                 CUV *pUV = (CUV*)_VBDst->getTexCoordPointer (vp);
00187                                 *pUV += rBS.deltaUV[j] * rFactor;
00188                         }
00189 
00190                         if (_VBDst->getVertexFormat() & CVertexBuffer::PrimaryColorFlag)
00191                         if (rBS.deltaCol.size() > 0)
00192                         {
00193                                 CRGBA *pRGBA = (CRGBA*)_VBDst->getColorPointer (vp);
00194                                 CRGBAF rgbf(*pRGBA);
00195                                 rgbf.R += rBS.deltaCol[j].R * rFactor;
00196                                 rgbf.G += rBS.deltaCol[j].G * rFactor;
00197                                 rgbf.B += rBS.deltaCol[j].B * rFactor;
00198                                 rgbf.A += rBS.deltaCol[j].A * rFactor;
00199                                 clamp(rgbf.R, 0.0f, 1.0f);
00200                                 clamp(rgbf.G, 0.0f, 1.0f);
00201                                 clamp(rgbf.B, 0.0f, 1.0f);
00202                                 clamp(rgbf.A, 0.0f, 1.0f);
00203                                 *pRGBA = rgbf;
00204                         }
00205 
00206                         // Modified
00207                         _Flags[vp] = Modified;
00208                 }
00209         }
00210 
00211         // Copying to hardware vertex buffer if some
00212         if (_VBDstHrd != NULL)
00213         {
00214                 uint8 *pDstHrd = (uint8*)_VBDstHrd->lock();
00215                 for (i = 0; i < _Flags.size(); ++i)
00216                 {
00217                         if (_Flags[i] != OriginalAll) // Not OriginalAll ?
00218                         {
00219                                 for(j = 0; j < VBVertexSize; ++j)
00220                                         pDstHrd[j+i*VBVertexSize] = pDst[j+i*VBVertexSize];
00221                         }
00222                         // if this vertex is original in the VBDst
00223                         if (_Flags[i] == OriginalVBDst)
00224                                 // then it is now copied into the VBHard
00225                                 _Flags[i] = OriginalAll;
00226                 }
00227                 _VBDstHrd->unlock();
00228         }
00229 }
00230 
00231 
00232 // ***************************************************************************
00233 void CMeshMorpher::updateSkinned (std::vector<CAnimatedMorph> *pBSFactor)
00234 {
00235         uint32 i, j;
00236 
00237         if (_VBOri == NULL)
00238                 return;
00239         if (BlendShapes.size() == 0)
00240                 return;
00241 
00242         if (_VBOri->getNumVertices() != _VBDst->getNumVertices())
00243         {       // Because the original vertex buffer is not initialized by default
00244                 // we must init it here (if there are some blendshapes)
00245                 *_VBOri = *_VBDst;
00246         }
00247 
00248         // Does the flags are reserved ?
00249         if (_Flags.size() != _VBOri->getNumVertices())
00250         {
00251                 _Flags.resize (_VBOri->getNumVertices());
00252                 for (i = 0; i < _Flags.size(); ++i)
00253                         _Flags[i] = Modified; // Modified to update all
00254         }
00255 
00256         nlassert(_VBOri->getVertexFormat() == _VBDst->getVertexFormat());
00257 
00258         uint tgSpaceStage;
00259         uint tgSpaceOff = 0;
00260         if (_UseTgSpace && _TgSpace)
00261         {
00262                 tgSpaceStage = _VBDst->getNumTexCoordUsed() - 1;
00263                 tgSpaceOff = _VBDst->getTexCoordOff(tgSpaceStage);
00264         }
00265 
00266         // Cleaning with original vertex buffer
00267         uint32 VBVertexSize = _VBOri->getVertexSize();
00268         uint8 *pOri = (uint8*)_VBOri->getVertexCoordPointer ();
00269         uint8 *pDst = (uint8*)_VBDst->getVertexCoordPointer ();
00270         
00271         for (i= 0; i < _Flags.size(); ++i)
00272         if (_Flags[i] >= Modified)
00273         {
00274                 for(j = 0; j < VBVertexSize; ++j)
00275                         pDst[j+i*VBVertexSize] = pOri[j+i*VBVertexSize];
00276                 
00277                 if (_Vertices != NULL)
00278                         _Vertices->operator[](i) = ((CVector*)(pOri+i*VBVertexSize))[0];
00279 
00280                 if (_Normals != NULL)
00281                         _Normals->operator[](i) = ((CVector*)(pOri+i*VBVertexSize))[1];
00282 
00283                 if (_TgSpace != NULL)
00284                         (*_TgSpace)[i] = * (CVector*)(pOri + i * VBVertexSize + tgSpaceOff);
00285                         
00286                 _Flags[i] = OriginalVBDst;
00287         }
00288 
00289         // Blending with blendshape
00290         for (i = 0; i < BlendShapes.size(); ++i)
00291         {
00292                 CBlendShape &rBS = BlendShapes[i];
00293                 float rFactor = pBSFactor->operator[](i).getFactor()/100.0f;
00294 
00295                 if (rFactor > 0.0f)
00296                 for (j = 0; j < rBS.VertRefs.size(); ++j)
00297                 {
00298                         uint32 vp = rBS.VertRefs[j];
00299 
00300                         // Modify Pos/Norm/TgSpace.
00301                         //------------
00302                         if (_Vertices != NULL)
00303                         if (rBS.deltaPos.size() > 0)
00304                         {
00305                                 CVector *pV = &(_Vertices->operator[](vp));
00306                                 *pV += rBS.deltaPos[j] * rFactor;
00307                         }
00308 
00309                         if (_Normals != NULL)
00310                         if (rBS.deltaNorm.size() > 0)
00311                         {
00312                                 CVector *pV = &(_Normals->operator[](vp));
00313                                 *pV += rBS.deltaNorm[j] * rFactor;
00314                         }
00315 
00316                         if (_UseTgSpace && _TgSpace != NULL)
00317                         if (rBS.deltaTgSpace.size() > 0)
00318                         {
00319                                 CVector *pV = &((*_TgSpace)[vp]);
00320                                 *pV += rBS.deltaTgSpace[j] * rFactor;
00321                         }
00322 
00323                         // Modify UV0 / Color
00324                         //------------
00325                         if (_VBDst->getVertexFormat() & CVertexBuffer::TexCoord0Flag)
00326                         if (rBS.deltaUV.size() > 0)
00327                         {
00328                                 CUV *pUV = (CUV*)_VBDst->getTexCoordPointer (vp);
00329                                 *pUV += rBS.deltaUV[j] * rFactor;
00330                         }
00331 
00332                         if (_VBDst->getVertexFormat() & CVertexBuffer::PrimaryColorFlag)
00333                         if (rBS.deltaCol.size() > 0)
00334                         {
00335                                 CRGBA *pRGBA = (CRGBA*)_VBDst->getColorPointer (vp);
00336                                 CRGBAF rgbf(*pRGBA);
00337                                 rgbf.R += rBS.deltaCol[j].R * rFactor;
00338                                 rgbf.G += rBS.deltaCol[j].G * rFactor;
00339                                 rgbf.B += rBS.deltaCol[j].B * rFactor;
00340                                 rgbf.A += rBS.deltaCol[j].A * rFactor;
00341                                 clamp(rgbf.R, 0.0f, 1.0f);
00342                                 clamp(rgbf.G, 0.0f, 1.0f);
00343                                 clamp(rgbf.B, 0.0f, 1.0f);
00344                                 clamp(rgbf.A, 0.0f, 1.0f);
00345                                 *pRGBA = rgbf;
00346                         }
00347 
00348                         // Modified
00349                         _Flags[vp] = Modified;
00350                 }
00351         }
00352 
00353         // Do some transfert to the VBHard if exist.
00354         if (_VBDstHrd != NULL)
00355         {
00356                 // lock.
00357                 uint8 *pDstHrd = (uint8*)_VBDstHrd->lock();
00358 
00359                 // If the skin is applied we have nothing to do 
00360                 // Because the skinning will transfert ALL the vertices of interest
00361                 if (!_SkinApplied) 
00362                 {
00363                         for (i = 0; i < _Flags.size(); ++i)
00364                         {
00365                                 if (_Flags[i] != OriginalAll) // Not OriginalAll ?
00366                                 {
00367                                         // We must write the whole vertex because the skinning may not copy 
00368                                         // vertex and normal changes into VBHard
00369                                         for(j = 0; j < VBVertexSize; ++j)
00370                                                 pDstHrd[j+i*VBVertexSize] = pDst[j+i*VBVertexSize];
00371                                 }
00372                                 if (_Flags[i] == OriginalVBDst) // OriginalVBDst ?
00373                                         _Flags[i] = OriginalAll; // So OriginalAll !
00374                         }
00375                 }
00376 
00377                 // unlock.
00378                 _VBDstHrd->unlock();
00379         }
00380 }
00381 
00382 // ***************************************************************************
00383 void CMeshMorpher::serial (NLMISC::IStream &f) throw(NLMISC::EStream)
00384 {
00385         (void)f.serialVersion (0);
00386 
00387         f.serialCont (BlendShapes);
00388 }
00389 
00390 
00391 } // NL3D
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401