// *************************************************************************** void CMeshMorpher::update (std::vector<CAnimatedMorph> *pBSFactor) { uint32 i, j; if (_VBOri == NULL) return; if (BlendShapes.size() == 0) return; if (_VBOri->getNumVertices() != _VBDst->getNumVertices()) { // Because the original vertex buffer is not initialized by default // we must init it here (if there are some blendshapes) *_VBOri = *_VBDst; } // Does the flags are reserved ? if (_Flags.size() != _VBOri->getNumVertices()) { _Flags.resize (_VBOri->getNumVertices()); for (i = 0; i < _Flags.size(); ++i) _Flags[i] = Modified; // Modified to update all } nlassert(_VBOri->getVertexFormat() == _VBDst->getVertexFormat()); // Cleaning with original vertex buffer uint32 VBVertexSize = _VBOri->getVertexSize(); CVertexBufferRead srcvba; _VBOri->lock (srcvba); CVertexBufferReadWrite dstvba; _VBDst->lock (dstvba); const uint8 *pOri = (const uint8*)srcvba.getVertexCoordPointer (); uint8 *pDst = (uint8*)dstvba.getVertexCoordPointer (); for (i= 0; i < _Flags.size(); ++i) if (_Flags[i] >= Modified) { _Flags[i] = OriginalVBDst; for(j = 0; j < VBVertexSize; ++j) pDst[j+i*VBVertexSize] = pOri[j+i*VBVertexSize]; } uint tgSpaceStage = 0; if (_UseTgSpace) { tgSpaceStage = _VBDst->getNumTexCoordUsed() - 1; } // Blending with blendshape for (i = 0; i < BlendShapes.size(); ++i) { CBlendShape &rBS = BlendShapes[i]; float rFactor = pBSFactor->operator[](i).getFactor()/100.0f; // todo hulud check it works // if (rFactor > 0.0f) if (rFactor != 0.0f) for (j = 0; j < rBS.VertRefs.size(); ++j) { uint32 vp = rBS.VertRefs[j]; // Modify Pos/Norm/TgSpace. //------------ if (_VBDst->getVertexFormat() & CVertexBuffer::PositionFlag) if (rBS.deltaPos.size() > 0) { CVector *pV = dstvba.getVertexCoordPointer (vp); *pV += rBS.deltaPos[j] * rFactor; } if (_VBDst->getVertexFormat() & CVertexBuffer::NormalFlag) if (rBS.deltaNorm.size() > 0) { CVector *pV = dstvba.getNormalCoordPointer (vp); *pV += rBS.deltaNorm[j] * rFactor; } if (_UseTgSpace) if (rBS.deltaTgSpace.size() > 0) { CVector *pV = (CVector*)dstvba.getTexCoordPointer (vp, tgSpaceStage); *pV += rBS.deltaTgSpace[j] * rFactor; } // Modify UV0 / Color //------------ if (_VBDst->getVertexFormat() & CVertexBuffer::TexCoord0Flag) if (rBS.deltaUV.size() > 0) { CUV *pUV = dstvba.getTexCoordPointer (vp); *pUV += rBS.deltaUV[j] * rFactor; } if (_VBDst->getVertexFormat() & CVertexBuffer::PrimaryColorFlag) if (rBS.deltaCol.size() > 0) { // todo hulud d3d vertex color RGBA / BGRA CRGBA *pRGBA = (CRGBA*)dstvba.getColorPointer (vp); CRGBAF rgbf(*pRGBA); rgbf.R += rBS.deltaCol[j].R * rFactor; rgbf.G += rBS.deltaCol[j].G * rFactor; rgbf.B += rBS.deltaCol[j].B * rFactor; rgbf.A += rBS.deltaCol[j].A * rFactor; clamp(rgbf.R, 0.0f, 1.0f); clamp(rgbf.G, 0.0f, 1.0f); clamp(rgbf.B, 0.0f, 1.0f); clamp(rgbf.A, 0.0f, 1.0f); *pRGBA = rgbf; } // Modified _Flags[vp] = Modified; } } }
// *************************************************************************** void CVegetableShape::build(CVegetableShapeBuild &vbuild) { // Must have TexCoord0. nlassert( vbuild.VB.getVertexFormat() & CVertexBuffer::TexCoord0Flag ); // Header //--------- // Lighted ? if(vbuild.Lighted && ( vbuild.VB.getVertexFormat() & CVertexBuffer::NormalFlag) ) Lighted= true; else Lighted= false; // DoubleSided DoubleSided= vbuild.DoubleSided; // PreComputeLighting. PreComputeLighting= Lighted && vbuild.PreComputeLighting; // AlphaBlend: valid only for 2Sided and Unlit (or similar PreComputeLighting) mode AlphaBlend= vbuild.AlphaBlend && DoubleSided && (!Lighted || PreComputeLighting); // BestSidedPreComputeLighting BestSidedPreComputeLighting= PreComputeLighting && vbuild.BestSidedPreComputeLighting; // BendCenterMode BendCenterMode= vbuild.BendCenterMode; // Format of the VB. uint32 format; format= CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag | CVertexBuffer::TexCoord1Flag; // lighted? if(Lighted) format|= CVertexBuffer::NormalFlag; // set VB. VB.setVertexFormat(format); // Fill triangles. //--------- uint i; // resisz TriangleIndices.resize(vbuild.PB.getNumIndexes()); CIndexBufferRead ibaRead; vbuild.PB.lock (ibaRead); const uint32 *srcTri= (const uint32 *) ibaRead.getPtr(); // fill for(i=0; i<vbuild.PB.getNumIndexes()/3; i++) { TriangleIndices[i*3+0]= *(srcTri++); TriangleIndices[i*3+1]= *(srcTri++); TriangleIndices[i*3+2]= *(srcTri++); } // Fill vertices. //--------- // resize uint32 nbVerts= vbuild.VB.getNumVertices(); VB.setNumVertices(nbVerts); CVertexBufferRead vba; vbuild.VB.lock (vba); CVertexBufferReadWrite vbaOut; VB.lock (vbaOut); // if no vertex color, float maxZ= 0; bool bendFromColor= true; if(! (vbuild.VB.getVertexFormat() & CVertexBuffer::PrimaryColorFlag) ) { // must compute bendWeight from z. bendFromColor= false; // get the maximum Z. for(i=0;i<nbVerts;i++) { float z= (vba.getVertexCoordPointer(i))->z; maxZ= max(z, maxZ); } // if no positive value, bend will always be 0. if(maxZ==0) maxZ= 1; } // For all vertices, fill for(i=0;i<nbVerts;i++) { // Position. const CVector *srcPos= vba.getVertexCoordPointer(i); CVector *dstPos= vbaOut.getVertexCoordPointer(i); *dstPos= *srcPos; // Normal if(Lighted) { const CVector *srcNormal= vba.getNormalCoordPointer(i); CVector *dstNormal= vbaOut.getNormalCoordPointer(i); *dstNormal= *srcNormal; } // Texture. const CUV *srcUV= vba.getTexCoordPointer(i, 0); CUV *dstUV= vbaOut.getTexCoordPointer(i, 0); *dstUV= *srcUV; // Bend. // copy to texture stage 1. CUV *dstUVBend= vbaOut.getTexCoordPointer(i, 1); if(bendFromColor) { // todo hulud d3d vertex color RGBA / BGRA const CRGBA *srcColor= (const CRGBA*)vba.getColorPointer(i); // Copy and scale by MaxBendWeight dstUVBend->U= (srcColor->R / 255.f) * vbuild.MaxBendWeight; } else { float w= srcPos->z / maxZ; w= max(w, 0.f); // Copy and scale by MaxBendWeight dstUVBend->U= w * vbuild.MaxBendWeight; } } // Misc. //--------- // prepare for instanciation InstanceVertices.resize(VB.getNumVertices()); }