00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "nel/misc/bsphere.h"
00029 #include "nel/misc/fast_mem.h"
00030 #include "nel/misc/system_info.h"
00031 #include "3d/mesh_mrm.h"
00032 #include "3d/mrm_builder.h"
00033 #include "3d/mrm_parameters.h"
00034 #include "3d/mesh_mrm_instance.h"
00035 #include "3d/scene.h"
00036 #include "3d/skeleton_model.h"
00037 #include "3d/stripifier.h"
00038 #include "3d/matrix_3x4.h"
00039 #include "3d/raw_skin.h"
00040
00041
00042 using namespace NLMISC;
00043 using namespace std;
00044
00045
00046 namespace NL3D
00047 {
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #define NL3D_SSE_ALIGNEMENT 16
00060
00063 class CMatrix3x4SSEArray
00064 {
00065 private:
00066 void *_AllocData;
00067 void *_Data;
00068 uint _Size;
00069 uint _Capacity;
00070
00071 public:
00072 CMatrix3x4SSEArray()
00073 {
00074 _AllocData= NULL;
00075 _Data= NULL;
00076 _Size= 0;
00077 _Capacity= 0;
00078 }
00079 ~CMatrix3x4SSEArray()
00080 {
00081 clear();
00082 }
00083 CMatrix3x4SSEArray(const CMatrix3x4SSEArray &other)
00084 {
00085 _AllocData= NULL;
00086 _Data= NULL;
00087 _Size= 0;
00088 _Capacity= 0;
00089 *this= other;
00090 }
00091 CMatrix3x4SSEArray &operator=(const CMatrix3x4SSEArray &other)
00092 {
00093 if( this == &other)
00094 return *this;
00095 resize(other.size());
00096
00097 memcpy(_Data, other._Data, size() * sizeof(CMatrix3x4SSE) );
00098
00099 return *this;
00100 }
00101
00102
00103 CMatrix3x4SSE *getPtr()
00104 {
00105 return (CMatrix3x4SSE*)_Data;
00106 }
00107
00108 void clear()
00109 {
00110 free(_AllocData);
00111 _AllocData= NULL;
00112 _Data= NULL;
00113 _Size= 0;
00114 _Capacity= 0;
00115 }
00116
00117 void resize(uint n)
00118 {
00119
00120 if(n>_Capacity)
00121 reserve( max(2*_Capacity, n));
00122 _Size= n;
00123 }
00124
00125 void reserve(uint n)
00126 {
00127 if(n==0)
00128 clear();
00129 else if(n>_Capacity)
00130 {
00131
00132 void *newAllocData;
00133 void *newData;
00134
00135
00136 newAllocData= malloc(n * sizeof(CMatrix3x4SSE) + NL3D_SSE_ALIGNEMENT-1);
00137 if(newAllocData==NULL)
00138 throw Exception("SSE Allocation Failed");
00139
00140
00141 newData= (void*) ( ((uint32)newAllocData+NL3D_SSE_ALIGNEMENT-1) & (~(NL3D_SSE_ALIGNEMENT-1)) );
00142
00143
00144 memcpy(newData, _Data, size() * sizeof(CMatrix3x4SSE) );
00145
00146
00147 _Data= newData;
00148 _AllocData= newAllocData;
00149 _Capacity= n;
00150 }
00151 }
00152
00153 uint size() const {return _Size;}
00154
00155
00156 CMatrix3x4SSE &operator[](uint i) {return ((CMatrix3x4SSE*)_Data)[i];}
00157 };
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 template <class TMatrixArray>
00170 inline void computeBoneMatrixes3x4(TMatrixArray &boneMat3x4, const vector<uint32> &matInfs, const CSkeletonModel *skeleton)
00171 {
00172
00173 for(uint i= 0; i<matInfs.size(); i++)
00174 {
00175
00176 uint matId= matInfs[i];
00177 const CMatrix &boneMat= skeleton->getActiveBoneSkinMatrix(matId);
00178
00179
00180
00181 if(matId>=boneMat3x4.size())
00182 {
00183 boneMat3x4.resize(matId+1);
00184 }
00185 boneMat3x4[matId].set(boneMat);
00186 }
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 void CMeshMRMGeom::applySkin(CLod &lod, const CSkeletonModel *skeleton)
00199 {
00200 nlassert(_Skinned);
00201 if(_SkinWeights.size()==0)
00202 return;
00203
00204
00205
00206 uint8 *destVertexPtr= (uint8*)_VBufferFinal.getVertexCoordPointer();
00207 uint flags= _VBufferFinal.getVertexFormat();
00208 sint32 vertexSize= _VBufferFinal.getVertexSize();
00209
00210 nlassert(flags & CVertexBuffer::PositionFlag);
00211
00212
00213
00214 CMesh::CSkinWeight *srcSkinPtr;
00215 CVector *srcVertexPtr;
00216 srcSkinPtr= &_SkinWeights[0];
00217 srcVertexPtr= &_OriginalSkinVertices[0];
00218
00219
00220
00221
00222
00223
00224 static vector<CMatrix3x4> boneMat3x4;
00225 computeBoneMatrixes3x4(boneMat3x4, lod.MatrixInfluences, skeleton);
00226
00227
00228
00229
00230
00231 nlassert(NL3D_MESH_SKINNING_MAX_MATRIX==4);
00232 for(uint i=0;i<NL3D_MESH_SKINNING_MAX_MATRIX;i++)
00233 {
00234 uint nInf= lod.InfluencedVertices[i].size();
00235 if( nInf==0 )
00236 continue;
00237 uint32 *infPtr= &(lod.InfluencedVertices[i][0]);
00238
00239
00240 switch(i)
00241 {
00242
00243 case 0:
00244
00245
00246 for(;nInf>0;nInf--, infPtr++)
00247 {
00248 uint index= *infPtr;
00249 CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
00250 CVector *srcVertex= srcVertexPtr + index;
00251 uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
00252 CVector *dstVertex= (CVector*)(dstVertexVB);
00253
00254
00255
00256 boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, *dstVertex);
00257 }
00258 break;
00259
00260
00261 case 1:
00262
00263 for(;nInf>0;nInf--, infPtr++)
00264 {
00265 uint index= *infPtr;
00266 CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
00267 CVector *srcVertex= srcVertexPtr + index;
00268 uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
00269 CVector *dstVertex= (CVector*)(dstVertexVB);
00270
00271
00272
00273 boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
00274 boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
00275 }
00276 break;
00277
00278
00279 case 2:
00280
00281 for(;nInf>0;nInf--, infPtr++)
00282 {
00283 uint index= *infPtr;
00284 CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
00285 CVector *srcVertex= srcVertexPtr + index;
00286 uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
00287 CVector *dstVertex= (CVector*)(dstVertexVB);
00288
00289
00290
00291 boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
00292 boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
00293 boneMat3x4[ srcSkin->MatrixId[2] ].mulAddPoint( *srcVertex, srcSkin->Weights[2], *dstVertex);
00294 }
00295 break;
00296
00297
00298 case 3:
00299
00300 for(;nInf>0;nInf--, infPtr++)
00301 {
00302 uint index= *infPtr;
00303 CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
00304 CVector *srcVertex= srcVertexPtr + index;
00305 uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
00306 CVector *dstVertex= (CVector*)(dstVertexVB);
00307
00308
00309
00310 boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
00311 boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
00312 boneMat3x4[ srcSkin->MatrixId[2] ].mulAddPoint( *srcVertex, srcSkin->Weights[2], *dstVertex);
00313 boneMat3x4[ srcSkin->MatrixId[3] ].mulAddPoint( *srcVertex, srcSkin->Weights[3], *dstVertex);
00314 }
00315 break;
00316
00317 }
00318 }
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 const uint NL_BlockByteL1= 4096;
00333
00334
00335 uint CMeshMRMGeom::NumCacheVertexNormal1= NL_BlockByteL1 / sizeof(CRawVertexNormalSkin1);
00336
00337 uint CMeshMRMGeom::NumCacheVertexNormal2= NL_BlockByteL1 / sizeof(CRawVertexNormalSkin2);
00338
00339 uint CMeshMRMGeom::NumCacheVertexNormal4= NL_BlockByteL1 / sizeof(CRawVertexNormalSkin4);
00340
00341
00342
00343 #undef NL_SKIN_SSE
00344 #include "mesh_mrm_skin_template.cpp"
00345 #define NL_SKIN_SSE
00346 #include "mesh_mrm_skin_template.cpp"
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 void CMeshMRMGeom::fillAGPSkinPart(CLod &lod, IVertexBufferHard *currentVBHard)
00360 {
00361
00362 if(currentVBHard)
00363 {
00364
00365 uint8 *vertexDst= (uint8*)currentVBHard->lock();
00366
00367
00368 fillAGPSkinPartWithVBHardPtr(lod, vertexDst);
00369
00370
00371 currentVBHard->unlock();
00372 }
00373 }
00374
00375
00376
00377 void CMeshMRMGeom::fillAGPSkinPartWithVBHardPtr(CLod &lod, uint8 *vertexDst)
00378 {
00379
00380 if( lod.SkinVertexBlocks.size()>0 )
00381 {
00382
00383 uint8 *vertexSrc= (uint8*)_VBufferFinal.getVertexCoordPointer();
00384 uint32 vertexSize= _VBufferFinal.getVertexSize();
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 CVertexBlock *vBlock= &lod.SkinVertexBlocks[0];
00396 uint n= lod.SkinVertexBlocks.size();
00397
00398
00399
00400
00401
00402
00403 for(;n>0; n--, vBlock++)
00404 {
00405
00406 uint8 *src= vertexSrc + vertexSize * vBlock->VertexStart;
00407 uint8 *dst= vertexDst + vertexSize * vBlock->VertexStart;
00408
00409 memcpy(dst, src, vBlock->NVertices * vertexSize);
00410 }
00411 }
00412 }
00413
00414
00415
00416 }
00417