Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / 3d / mesh_mrm_skin.cpp
blobb8e772516ac3551ced46a3ee33ce3a766f125067
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "std3d.h"
22 #ifdef NL_HAS_SSE2
23 # include <xmmintrin.h>
24 #endif
26 #include "nel/misc/bsphere.h"
27 #include "nel/misc/fast_mem.h"
28 #include "nel/misc/system_info.h"
29 #include "nel/misc/hierarchical_timer.h"
30 #include "nel/3d/mesh_mrm.h"
31 #include "nel/3d/mrm_builder.h"
32 #include "nel/3d/mrm_parameters.h"
33 #include "nel/3d/mesh_mrm_instance.h"
34 #include "nel/3d/scene.h"
35 #include "nel/3d/skeleton_model.h"
36 #include "nel/3d/stripifier.h"
37 #include "nel/3d/matrix_3x4.h"
38 #include "nel/3d/raw_skin.h"
41 using namespace NLMISC;
42 using namespace std;
45 namespace NL3D
50 // ***************************************************************************
51 // ***************************************************************************
52 // Simple (slow) skinning version with position only.
53 // ***************************************************************************
54 // ***************************************************************************
57 // ***************************************************************************
58 void CMeshMRMGeom::applySkin(CLod &lod, const CSkeletonModel *skeleton)
60 nlassert(_Skinned);
61 if(_SkinWeights.empty())
62 return;
64 // get vertexPtr.
65 //===========================
66 CVertexBufferReadWrite vba;
67 _VBufferFinal.lock (vba);
68 uint8 *destVertexPtr= (uint8*)vba.getVertexCoordPointer();
69 uint flags= _VBufferFinal.getVertexFormat();
70 sint32 vertexSize= _VBufferFinal.getVertexSize();
71 // must have XYZ.
72 nlassert(flags & CVertexBuffer::PositionFlag);
75 // compute src array.
76 CMesh::CSkinWeight *srcSkinPtr;
77 CVector *srcVertexPtr;
78 srcSkinPtr= &_SkinWeights[0];
79 srcVertexPtr= &_OriginalSkinVertices[0];
83 // Compute useful Matrix for this lod.
84 //===========================
85 // Those arrays map the array of bones in skeleton.
86 static vector<CMatrix3x4> boneMat3x4;
87 computeBoneMatrixes3x4(boneMat3x4, lod.MatrixInfluences, skeleton);
90 // apply skinning.
91 //===========================
92 // assert, code below is written especially for 4 per vertex.
93 nlassert(NL3D_MESH_SKINNING_MAX_MATRIX==4);
94 for(uint i=0;i<NL3D_MESH_SKINNING_MAX_MATRIX;i++)
96 uint nInf= (uint)lod.InfluencedVertices[i].size();
97 if( nInf==0 )
98 continue;
99 uint32 *infPtr= &(lod.InfluencedVertices[i][0]);
101 // apply the skin to the vertices
102 switch(i)
104 //=========
105 case 0:
106 // Special case for Vertices influenced by one matrix. Just copy result of mul.
107 // for all InfluencedVertices only.
108 for(;nInf>0;nInf--, infPtr++)
110 uint index= *infPtr;
111 CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
112 CVector *srcVertex= srcVertexPtr + index;
113 uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
114 CVector *dstVertex= (CVector*)(dstVertexVB);
117 // Vertex.
118 boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, *dstVertex);
120 break;
122 //=========
123 case 1:
124 // for all InfluencedVertices only.
125 for(;nInf>0;nInf--, infPtr++)
127 uint index= *infPtr;
128 CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
129 CVector *srcVertex= srcVertexPtr + index;
130 uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
131 CVector *dstVertex= (CVector*)(dstVertexVB);
134 // Vertex.
135 boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
136 boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
138 break;
140 //=========
141 case 2:
142 // for all InfluencedVertices only.
143 for(;nInf>0;nInf--, infPtr++)
145 uint index= *infPtr;
146 CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
147 CVector *srcVertex= srcVertexPtr + index;
148 uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
149 CVector *dstVertex= (CVector*)(dstVertexVB);
152 // Vertex.
153 boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
154 boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
155 boneMat3x4[ srcSkin->MatrixId[2] ].mulAddPoint( *srcVertex, srcSkin->Weights[2], *dstVertex);
157 break;
159 //=========
160 case 3:
161 // for all InfluencedVertices only.
162 for(;nInf>0;nInf--, infPtr++)
164 uint index= *infPtr;
165 CMesh::CSkinWeight *srcSkin= srcSkinPtr + index;
166 CVector *srcVertex= srcVertexPtr + index;
167 uint8 *dstVertexVB= destVertexPtr + index * vertexSize;
168 CVector *dstVertex= (CVector*)(dstVertexVB);
171 // Vertex.
172 boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
173 boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
174 boneMat3x4[ srcSkin->MatrixId[2] ].mulAddPoint( *srcVertex, srcSkin->Weights[2], *dstVertex);
175 boneMat3x4[ srcSkin->MatrixId[3] ].mulAddPoint( *srcVertex, srcSkin->Weights[3], *dstVertex);
177 break;
184 // ***************************************************************************
185 // ***************************************************************************
186 // Old school Template skinning: SSE or not.
187 // ***************************************************************************
188 // ***************************************************************************
191 // RawSkin Cache constants
192 //===============
193 // The number of byte to process per block
194 const uint NL_BlockByteL1= 4096;
196 // Number of vertices per block to process with 1 matrix.
197 uint CMeshMRMGeom::NumCacheVertexNormal1= NL_BlockByteL1 / sizeof(CRawVertexNormalSkin1);
198 // Number of vertices per block to process with 2 matrix.
199 uint CMeshMRMGeom::NumCacheVertexNormal2= NL_BlockByteL1 / sizeof(CRawVertexNormalSkin2);
200 // Number of vertices per block to process with 3 matrix.
201 uint CMeshMRMGeom::NumCacheVertexNormal3= NL_BlockByteL1 / sizeof(CRawVertexNormalSkin3);
202 // Number of vertices per block to process with 4 matrix.
203 uint CMeshMRMGeom::NumCacheVertexNormal4= NL_BlockByteL1 / sizeof(CRawVertexNormalSkin4);
206 /* Old School template: include the same file with define switching,
207 Was used before to reuse same code for and without SSE.
208 Useless now because SSE removed, but keep it for possible future work on it.
210 #define ADD_MESH_MRM_SKIN_TEMPLATE
211 #include "mesh_mrm_skin_template.cpp"
215 // ***************************************************************************
216 // ***************************************************************************
217 // Misc.
218 // ***************************************************************************
219 // ***************************************************************************
222 } // NL3D