1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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/>.
23 # include <xmmintrin.h>
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
;
50 // ***************************************************************************
51 // ***************************************************************************
52 // Simple (slow) skinning version with position only.
53 // ***************************************************************************
54 // ***************************************************************************
57 // ***************************************************************************
58 void CMeshMRMGeom::applySkin(CLod
&lod
, const CSkeletonModel
*skeleton
)
61 if(_SkinWeights
.empty())
65 //===========================
66 CVertexBufferReadWrite vba
;
67 _VBufferFinal
.lock (vba
);
68 uint8
*destVertexPtr
= (uint8
*)vba
.getVertexCoordPointer();
69 uint flags
= _VBufferFinal
.getVertexFormat();
70 sint32 vertexSize
= _VBufferFinal
.getVertexSize();
72 nlassert(flags
& CVertexBuffer::PositionFlag
);
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
);
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();
99 uint32
*infPtr
= &(lod
.InfluencedVertices
[i
][0]);
101 // apply the skin to the vertices
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
++)
111 CMesh::CSkinWeight
*srcSkin
= srcSkinPtr
+ index
;
112 CVector
*srcVertex
= srcVertexPtr
+ index
;
113 uint8
*dstVertexVB
= destVertexPtr
+ index
* vertexSize
;
114 CVector
*dstVertex
= (CVector
*)(dstVertexVB
);
118 boneMat3x4
[ srcSkin
->MatrixId
[0] ].mulSetPoint( *srcVertex
, *dstVertex
);
124 // for all InfluencedVertices only.
125 for(;nInf
>0;nInf
--, infPtr
++)
128 CMesh::CSkinWeight
*srcSkin
= srcSkinPtr
+ index
;
129 CVector
*srcVertex
= srcVertexPtr
+ index
;
130 uint8
*dstVertexVB
= destVertexPtr
+ index
* vertexSize
;
131 CVector
*dstVertex
= (CVector
*)(dstVertexVB
);
135 boneMat3x4
[ srcSkin
->MatrixId
[0] ].mulSetPoint( *srcVertex
, srcSkin
->Weights
[0], *dstVertex
);
136 boneMat3x4
[ srcSkin
->MatrixId
[1] ].mulAddPoint( *srcVertex
, srcSkin
->Weights
[1], *dstVertex
);
142 // for all InfluencedVertices only.
143 for(;nInf
>0;nInf
--, infPtr
++)
146 CMesh::CSkinWeight
*srcSkin
= srcSkinPtr
+ index
;
147 CVector
*srcVertex
= srcVertexPtr
+ index
;
148 uint8
*dstVertexVB
= destVertexPtr
+ index
* vertexSize
;
149 CVector
*dstVertex
= (CVector
*)(dstVertexVB
);
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
);
161 // for all InfluencedVertices only.
162 for(;nInf
>0;nInf
--, infPtr
++)
165 CMesh::CSkinWeight
*srcSkin
= srcSkinPtr
+ index
;
166 CVector
*srcVertex
= srcVertexPtr
+ index
;
167 uint8
*dstVertexVB
= destVertexPtr
+ index
* vertexSize
;
168 CVector
*dstVertex
= (CVector
*)(dstVertexVB
);
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
);
184 // ***************************************************************************
185 // ***************************************************************************
186 // Old school Template skinning: SSE or not.
187 // ***************************************************************************
188 // ***************************************************************************
191 // RawSkin Cache constants
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 // ***************************************************************************
218 // ***************************************************************************
219 // ***************************************************************************