Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ModelDef.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2012 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /*
19  * Defines a raw 3d model.
20  */
21 
22 #include "precompiled.h"
23 
24 #include "ModelDef.h"
26 #include "ps/FileIo.h"
27 #include "maths/Vector4D.h"
28 
29 #if HAVE_SSE
30 # include <xmmintrin.h>
31 #endif
32 
34  const CMatrix3D newPoseMatrices[])
35 {
36  CVector3D result (0, 0, 0);
37 
38  for (int i = 0; i < SVertexBlend::SIZE && vtx.m_Blend.m_Bone[i] != 0xff; ++i)
39  {
40  result += newPoseMatrices[vtx.m_Blend.m_Bone[i]].Transform(vtx.m_Coords) * vtx.m_Blend.m_Weight[i];
41  }
42 
43  return result;
44 }
45 
47  const CMatrix3D newPoseMatrices[])
48 {
49  // To be correct, the normal vectors apparently need to be multiplied by the
50  // inverse of the transpose. Unfortunately inverses are slow.
51  // If a matrix is orthogonal, M * M^T = I and so the inverse of the transpose
52  // is the original matrix. But that's not entirely relevant here, because
53  // the bone matrices include translation components and so they're not
54  // orthogonal.
55  // But that's okay because we have
56  // M = T * R
57  // and want to find
58  // n' = (M^T^-1) * n
59  // = (T * R)^T^-1 * n
60  // = (R^T * T^T)^-1 * n
61  // = (T^T^-1 * R^T^-1) * n
62  // R is indeed orthogonal so R^T^-1 = R. T isn't orthogonal at all.
63  // But n is only a 3-vector, and from the forms of T and R (which have
64  // lots of zeroes) I can convince myself that replacing T with T^T^-1 has no
65  // effect on anything but the fourth component of M^T^-1 - and the fourth
66  // component is discarded since it has no effect on n', and so we can happily
67  // use n' = M*n.
68  //
69  // (This isn't very good as a proof, but it's better than assuming M is
70  // orthogonal when it's clearly not.)
71 
72  CVector3D result (0, 0, 0);
73 
74  for (int i = 0; i < SVertexBlend::SIZE && vtx.m_Blend.m_Bone[i] != 0xff; ++i)
75  {
76  result += newPoseMatrices[vtx.m_Blend.m_Bone[i]].Rotate(vtx.m_Norm) * vtx.m_Blend.m_Weight[i];
77  }
78 
79  // If there was more than one influence, the result is probably not going
80  // to be of unit length (since it's a weighted sum of several independent
81  // unit vectors), so we need to normalise it.
82  // (It's fairly common to only have one influence, so it seems sensible to
83  // optimise that case a bit.)
84  if (vtx.m_Blend.m_Bone[1] != 0xff) // if more than one influence
85  result.Normalize();
86 
87  return result;
88 }
89 
91  size_t numVertices,
92  const VertexArrayIterator<CVector3D>& Position,
93  const VertexArrayIterator<CVector3D>& Normal,
94  const SModelVertex* vertices,
95  const size_t* blendIndices,
96  const CMatrix3D newPoseMatrices[])
97 {
98  // To avoid some performance overhead, get the raw vertex array pointers
99  char* PositionData = Position.GetData();
100  size_t PositionStride = Position.GetStride();
101  char* NormalData = Normal.GetData();
102  size_t NormalStride = Normal.GetStride();
103 
104  for (size_t j = 0; j < numVertices; ++j)
105  {
106  const SModelVertex& vtx = vertices[j];
107 
108  CVector3D pos = newPoseMatrices[blendIndices[j]].Transform(vtx.m_Coords);
109  CVector3D norm = newPoseMatrices[blendIndices[j]].Rotate(vtx.m_Norm);
110 
111  // If there was more than one influence, the result is probably not going
112  // to be of unit length (since it's a weighted sum of several independent
113  // unit vectors), so we need to normalise it.
114  // (It's fairly common to only have one influence, so it seems sensible to
115  // optimise that case a bit.)
116  if (vtx.m_Blend.m_Bone[1] != 0xff) // if more than one influence
117  norm.Normalize();
118 
119  memcpy(PositionData + PositionStride*j, &pos.X, 3*sizeof(float));
120  memcpy(NormalData + NormalStride*j, &norm.X, 3*sizeof(float));
121  }
122 }
123 
124 #if HAVE_SSE
125 void CModelDef::SkinPointsAndNormals_SSE(
126  size_t numVertices,
127  const VertexArrayIterator<CVector3D>& Position,
128  const VertexArrayIterator<CVector3D>& Normal,
129  const SModelVertex* vertices,
130  const size_t* blendIndices,
131  const CMatrix3D newPoseMatrices[])
132 {
133  // To avoid some performance overhead, get the raw vertex array pointers
134  char* PositionData = Position.GetData();
135  size_t PositionStride = Position.GetStride();
136  char* NormalData = Normal.GetData();
137  size_t NormalStride = Normal.GetStride();
138 
139  // Must be aligned correctly for SSE
140  ASSERT((intptr_t)newPoseMatrices % 16 == 0);
141  ASSERT((intptr_t)PositionData % 16 == 0);
142  ASSERT((intptr_t)PositionStride % 16 == 0);
143  ASSERT((intptr_t)NormalData % 16 == 0);
144  ASSERT((intptr_t)NormalStride % 16 == 0);
145 
146  __m128 col0, col1, col2, col3, vec0, vec1, vec2;
147 
148  for (size_t j = 0; j < numVertices; ++j)
149  {
150  const SModelVertex& vtx = vertices[j];
151  const CMatrix3D& mtx = newPoseMatrices[blendIndices[j]];
152 
153  // Loads matrix to xmm registers.
154  col0 = _mm_load_ps(mtx._data);
155  col1 = _mm_load_ps(mtx._data + 4);
156  col2 = _mm_load_ps(mtx._data + 8);
157  col3 = _mm_load_ps(mtx._data + 12);
158 
159  // Loads and computes vertex coordinates.
160  vec0 = _mm_load1_ps(&vtx.m_Coords.X); // v0 = [x, x, x, x]
161  vec0 = _mm_mul_ps(col0, vec0); // v0 = [_11*x, _21*x, _31*x, _41*x]
162  vec1 = _mm_load1_ps(&vtx.m_Coords.Y); // v1 = [y, y, y, y]
163  vec1 = _mm_mul_ps(col1, vec1); // v1 = [_12*y, _22*y, _32*y, _42*y]
164  vec0 = _mm_add_ps(vec0, vec1); // v0 = [_11*x + _12*y, ...]
165  vec1 = _mm_load1_ps(&vtx.m_Coords.Z); // v1 = [z, z, z, z]
166  vec1 = _mm_mul_ps(col2, vec1); // v1 = [_13*z, _23*z, _33*z, _43*z]
167  vec1 = _mm_add_ps(vec1, col3); // v1 = [_13*z + _14, ...]
168  vec0 = _mm_add_ps(vec0, vec1); // v0 = [_11*x + _12*y + _13*z + _14, ...]
169  _mm_store_ps((float*)(PositionData + PositionStride*j), vec0);
170 
171  // Loads and computes normal vectors.
172  vec0 = _mm_load1_ps(&vtx.m_Norm.X); // v0 = [x, x, x, x]
173  vec0 = _mm_mul_ps(col0, vec0); // v0 = [_11*x, _21*x, _31*x, _41*x]
174  vec1 = _mm_load1_ps(&vtx.m_Norm.Y); // v1 = [y, y, y, y]
175  vec1 = _mm_mul_ps(col1, vec1); // v1 = [_12*y, _22*y, _32*y, _42*y]
176  vec0 = _mm_add_ps(vec0, vec1); // v0 = [_11*x + _12*y, ...]
177  vec1 = _mm_load1_ps(&vtx.m_Norm.Z); // v1 = [z, z, z, z]
178  vec1 = _mm_mul_ps(col2, vec1); // v1 = [_13*z, _23*z, _33*z, _43*z]
179  vec0 = _mm_add_ps(vec0, vec1); // v0 = [_11*x + _12*y + _13*z, ...]
180 
181  // If there was more than one influence, the result is probably not going
182  // to be of unit length (since it's a weighted sum of several independent
183  // unit vectors), so we need to normalise it.
184  // (It's fairly common to only have one influence, so it seems sensible to
185  // optimise that case a bit.)
186  if (vtx.m_Blend.m_Bone[1] != 0xff) // if more than one influence
187  {
188  // Normalization.
189  // vec1 = [x*x, y*y, z*z, ?*?]
190  vec1 = _mm_mul_ps(vec0, vec0);
191  // vec2 = [y*y, z*z, x*x, ?*?]
192  vec2 = _mm_shuffle_ps(vec1, vec1, _MM_SHUFFLE(3, 0, 2, 1));
193  vec1 = _mm_add_ps(vec1, vec2);
194  // vec2 = [z*z, x*x, y*y, ?*?]
195  vec2 = _mm_shuffle_ps(vec2, vec2, _MM_SHUFFLE(3, 0, 2, 1));
196  vec1 = _mm_add_ps(vec1, vec2);
197  // rsqrt(a) = 1 / sqrt(a)
198  vec1 = _mm_rsqrt_ps(vec1);
199  vec0 = _mm_mul_ps(vec0, vec1);
200  }
201  _mm_store_ps((float*)(NormalData + NormalStride*j), vec0);
202  }
203 }
204 #endif
205 
207  CMatrix3D boneMatrices[])
208 {
209  for (size_t i = 0; i < m_NumBlends; ++i)
210  {
211  const SVertexBlend& blend = m_pBlends[i];
212  CMatrix3D& boneMatrix = boneMatrices[m_NumBones + 1 + i];
213 
214  // Note: there is a special case of joint influence, in which the vertex
215  // is influenced by the bind-shape matrix instead of a particular bone,
216  // which we indicate by setting the bone ID to the total number of bones.
217  // It should be blended with the world space transform and we have already
218  // set up this matrix in boneMatrices.
219  // (see http://trac.wildfiregames.com/ticket/1012)
220 
221  boneMatrix.Blend(boneMatrices[blend.m_Bone[0]], blend.m_Weight[0]);
222  for (size_t j = 1; j < SVertexBlend::SIZE && blend.m_Bone[j] != 0xFF; ++j)
223  boneMatrix.AddBlend(boneMatrices[blend.m_Bone[j]], blend.m_Weight[j]);
224  }
225 }
226 
227 // CModelDef Constructor
229  m_NumVertices(0), m_NumUVsPerVertex(0), m_pVertices(0), m_NumFaces(0), m_pFaces(0),
230  m_NumBones(0), m_Bones(0), m_InverseBindBoneMatrices(NULL),
231  m_NumBlends(0), m_pBlends(0), m_pBlendIndices(0),
232  m_Name(L"[not loaded]")
233 {
234 }
235 
236 // CModelDef Destructor
238 {
239  for(RenderDataMap::iterator it = m_RenderData.begin(); it != m_RenderData.end(); ++it)
240  delete it->second;
241  delete[] m_pVertices;
242  delete[] m_pFaces;
243  delete[] m_Bones;
244  delete[] m_InverseBindBoneMatrices;
245  delete[] m_pBlends;
246  delete[] m_pBlendIndices;
247 }
248 
249 // FindPropPoint: find and return pointer to prop point matching given name;
250 // return null if no match (case insensitive search)
251 const SPropPoint* CModelDef::FindPropPoint(const char* name) const
252 {
253  for (size_t i = 0; i < m_PropPoints.size(); ++i)
254  if (m_PropPoints[i].m_Name == name)
255  return &m_PropPoints[i];
256 
257  return 0;
258 }
259 
260 // Load: read and return a new CModelDef initialised with data from given file
261 CModelDef* CModelDef::Load(const VfsPath& filename, const VfsPath& name)
262 {
263  CFileUnpacker unpacker;
264 
265  // read everything in from file
266  unpacker.Read(filename,"PSMD");
267 
268  // check version
269  if (unpacker.GetVersion()<FILE_READ_VERSION) {
271  }
272 
273  std::auto_ptr<CModelDef> mdef (new CModelDef());
274  mdef->m_Name = name;
275 
276  // now unpack everything
277  mdef->m_NumVertices = unpacker.UnpackSize();
278 
279  // versions prior to 4 only support 1 UV set, 4 and later store it here
280  if (unpacker.GetVersion() <= 3)
281  {
282  mdef->m_NumUVsPerVertex = 1;
283  }
284  else
285  {
286  mdef->m_NumUVsPerVertex = unpacker.UnpackSize();
287  }
288 
289  mdef->m_pVertices=new SModelVertex[mdef->m_NumVertices];
290 
291  for (size_t i = 0; i < mdef->m_NumVertices; ++i)
292  {
293  unpacker.UnpackRaw(&mdef->m_pVertices[i].m_Coords, 12);
294  unpacker.UnpackRaw(&mdef->m_pVertices[i].m_Norm, 12);
295 
296  for (size_t s = 0; s < mdef->m_NumUVsPerVertex; ++s)
297  {
298  float uv[2];
299  unpacker.UnpackRaw(&uv[0], 8);
300  mdef->m_pVertices[i].m_UVs.push_back(uv[0]);
301  mdef->m_pVertices[i].m_UVs.push_back(uv[1]);
302  }
303 
304  unpacker.UnpackRaw(&mdef->m_pVertices[i].m_Blend, sizeof(SVertexBlend));
305  }
306 
307  mdef->m_NumFaces = unpacker.UnpackSize();
308  mdef->m_pFaces=new SModelFace[mdef->m_NumFaces];
309  unpacker.UnpackRaw(mdef->m_pFaces,sizeof(SModelFace)*mdef->m_NumFaces);
310 
311  mdef->m_NumBones = unpacker.UnpackSize();
312  if (mdef->m_NumBones)
313  {
314  mdef->m_Bones=new CBoneState[mdef->m_NumBones];
315  unpacker.UnpackRaw(mdef->m_Bones,mdef->m_NumBones*sizeof(CBoneState));
316 
317  mdef->m_pBlendIndices = new size_t[mdef->m_NumVertices];
318  std::vector<SVertexBlend> blends;
319  for (size_t i = 0; i < mdef->m_NumVertices; i++)
320  {
321  const SVertexBlend &blend = mdef->m_pVertices[i].m_Blend;
322  if (blend.m_Bone[1] == 0xFF)
323  {
324  mdef->m_pBlendIndices[i] = blend.m_Bone[0];
325  }
326  else
327  {
328  // If there's already a vertex using the same blend as this, then
329  // reuse its entry from blends; otherwise add the new one to blends
330  size_t j;
331  for (j = 0; j < blends.size(); j++)
332  {
333  if (blend == blends[j]) break;
334  }
335  if (j >= blends.size())
336  blends.push_back(blend);
337  // This index is offset by one to allow the special case of a
338  // weighted influence relative to the bind-shape rather than
339  // a particular bone. See comment in BlendBoneMatrices.
340  mdef->m_pBlendIndices[i] = mdef->m_NumBones + 1 + j;
341  }
342  }
343 
344  mdef->m_NumBlends = blends.size();
345  mdef->m_pBlends = new SVertexBlend[mdef->m_NumBlends];
346  std::copy(blends.begin(), blends.end(), mdef->m_pBlends);
347  }
348 
349  if (unpacker.GetVersion() >= 2)
350  {
351  // versions >=2 also have prop point data
352  size_t numPropPoints = unpacker.UnpackSize();
353  mdef->m_PropPoints.resize(numPropPoints);
354  if (numPropPoints)
355  {
356  for (size_t i = 0; i < numPropPoints; i++)
357  {
358  unpacker.UnpackString(mdef->m_PropPoints[i].m_Name);
359  unpacker.UnpackRaw(&mdef->m_PropPoints[i].m_Position.X, sizeof(mdef->m_PropPoints[i].m_Position));
360  unpacker.UnpackRaw(&mdef->m_PropPoints[i].m_Rotation.m_V.X, sizeof(mdef->m_PropPoints[i].m_Rotation));
361  unpacker.UnpackRaw(&mdef->m_PropPoints[i].m_BoneIndex, sizeof(mdef->m_PropPoints[i].m_BoneIndex));
362 
363  // build prop point transform
364  mdef->m_PropPoints[i].m_Transform.SetIdentity();
365  mdef->m_PropPoints[i].m_Transform.Rotate(mdef->m_PropPoints[i].m_Rotation);
366  mdef->m_PropPoints[i].m_Transform.Translate(mdef->m_PropPoints[i].m_Position);
367  }
368  }
369  }
370 
371  if (unpacker.GetVersion() <= 2)
372  {
373  // Versions <=2 don't include the default 'root' prop point, so add it here
374 
375  SPropPoint prop;
376  prop.m_Name = "root";
377  prop.m_Transform.SetIdentity();
378  prop.m_BoneIndex = 0xFF;
379 
380  mdef->m_PropPoints.push_back(prop);
381  }
382 
383  if (unpacker.GetVersion() <= 2)
384  {
385  // Versions <=2 store the vertexes relative to the bind pose. That
386  // isn't useful when you want to do correct skinning, so later versions
387  // store them in world space. So, fix the old models by skinning each
388  // vertex:
389 
390  if (mdef->m_NumBones) // only do skinned models
391  {
392  std::vector<CMatrix3D> bindPose (mdef->m_NumBones);
393 
394  for (size_t i = 0; i < mdef->m_NumBones; ++i)
395  {
396  bindPose[i].SetIdentity();
397  bindPose[i].Rotate(mdef->m_Bones[i].m_Rotation);
398  bindPose[i].Translate(mdef->m_Bones[i].m_Translation);
399  }
400 
401  for (size_t i = 0; i < mdef->m_NumVertices; ++i)
402  {
403  mdef->m_pVertices[i].m_Coords = SkinPoint(mdef->m_pVertices[i], &bindPose[0]);
404  mdef->m_pVertices[i].m_Norm = SkinNormal(mdef->m_pVertices[i], &bindPose[0]);
405  }
406  }
407  }
408 
409  // Compute the inverse bind-pose matrices, needed by the skinning code
410  mdef->m_InverseBindBoneMatrices = new CMatrix3D[mdef->m_NumBones];
411  CBoneState* defpose = mdef->GetBones();
412  for (size_t i = 0; i < mdef->m_NumBones; ++i)
413  {
414  mdef->m_InverseBindBoneMatrices[i].SetIdentity();
415  mdef->m_InverseBindBoneMatrices[i].Translate(-defpose[i].m_Translation);
416  mdef->m_InverseBindBoneMatrices[i].Rotate(defpose[i].m_Rotation.GetInverse());
417  }
418 
419  return mdef.release();
420 }
421 
422 // Save: write the given CModelDef to the given file
423 void CModelDef::Save(const VfsPath& filename, const CModelDef* mdef)
424 {
425  CFilePacker packer(FILE_VERSION, "PSMD");
426 
427  // pack everything up
428  const size_t numVertices = mdef->GetNumVertices();
429  packer.PackSize(numVertices);
430  packer.PackRaw(mdef->GetVertices(), sizeof(SModelVertex) * numVertices);
431 
432  const size_t numFaces = mdef->GetNumFaces();
433  packer.PackSize(numFaces);
434  packer.PackRaw(mdef->GetFaces(), sizeof(SModelFace) * numFaces);
435 
436  const size_t numBones = mdef->m_NumBones;
437  packer.PackSize(numBones);
438  if (numBones)
439  packer.PackRaw(mdef->m_Bones, sizeof(CBoneState) * numBones);
440 
441  const size_t numPropPoints = mdef->m_PropPoints.size();
442  packer.PackSize(numPropPoints);
443  for (size_t i = 0; i < numPropPoints; i++)
444  {
445  packer.PackString(mdef->m_PropPoints[i].m_Name);
446  packer.PackRaw(&mdef->m_PropPoints[i].m_Position.X, sizeof(mdef->m_PropPoints[i].m_Position));
447  packer.PackRaw(&mdef->m_PropPoints[i].m_Rotation.m_V.X, sizeof(mdef->m_PropPoints[i].m_Rotation));
448  packer.PackRaw(&mdef->m_PropPoints[i].m_BoneIndex, sizeof(mdef->m_PropPoints[i].m_BoneIndex));
449  }
450 
451  // flush everything out to file
452  packer.Write(filename);
453 }
454 
455 // SetRenderData: Set the render data object for the given key,
457 {
458  delete m_RenderData[key];
459  m_RenderData[key] = data;
460 }
461 
462 // GetRenderData: Get the render data object for the given key,
463 // or 0 if no such object exists.
464 // Reference count of the render data object is automatically increased.
466 {
467  RenderDataMap::const_iterator it = m_RenderData.find(key);
468 
469  if (it != m_RenderData.end())
470  return it->second;
471 
472  return 0;
473 }
u8 m_BoneIndex
Index of parent bone to which this prop point is relative, if any.
Definition: ModelDef.h:79
SModelFace * m_pFaces
Definition: ModelDef.h:266
void UnpackRaw(void *rawData, size_t rawDataSize)
unpack given number of bytes from the input into the given array.
Definition: FileIo.cpp:150
Describes the position of a prop point within its parent model.
Definition: ModelDef.h:48
RenderDataMap m_RenderData
Definition: ModelDef.h:284
CVector3D m_Norm
Definition: ModelDef.h:106
SModelVertex * m_pVertices
Definition: ModelDef.h:262
size_t GetStride() const
Definition: VertexArray.h:111
float m_Weight[SIZE]
Definition: ModelDef.h:91
SModelVertex * GetVertices() const
Definition: ModelDef.h:167
CVector3D Transform(const CVector3D &vector) const
Definition: Matrix3D.h:272
void PackRaw(const void *rawData, size_t rawDataSize)
pack given number of bytes onto the end of the data stream
Definition: FileIo.cpp:78
std::vector< SPropPoint > m_PropPoints
Definition: ModelDef.h:276
#define ASSERT(expr)
same as ENSURE in debug mode, does nothing in release mode.
Definition: debug.h:310
void Normalize()
Definition: Vector3D.cpp:77
helper class for reading binary files
Definition: FileIo.h:100
static CVector3D SkinNormal(const SModelVertex &vtx, const CMatrix3D newPoseMatrices[])
Transform the given vertex&#39;s normal from the bind pose into the new pose.
Definition: ModelDef.cpp:46
u32 GetVersion() const
Definition: FileIo.h:115
size_t m_NumBones
Definition: ModelDef.h:268
void Rotate(const CQuaternion &quat)
Definition: Matrix3D.cpp:354
size_t GetNumVertices() const
Definition: ModelDef.h:166
helper class for writing binary files.
Definition: FileIo.h:52
SVertexBlend * m_pBlends
Definition: ModelDef.h:273
static void SkinPointsAndNormals(size_t numVertices, const VertexArrayIterator< CVector3D > &Position, const VertexArrayIterator< CVector3D > &Normal, const SModelVertex *vertices, const size_t *blendIndices, const CMatrix3D newPoseMatrices[])
Transform vertices&#39; positions and normals.
Definition: ModelDef.cpp:90
u8 m_Bone[SIZE]
Definition: ModelDef.h:89
float X
Definition: Vector3D.h:31
static CModelDef * Load(const VfsPath &filename, const VfsPath &name)
Loads a PMD file.
Definition: ModelDef.cpp:261
VfsPath m_Name
Definition: ModelDef.h:279
static CVector3D SkinPoint(const SModelVertex &vtx, const CMatrix3D newPoseMatrices[])
Transform the given vertex&#39;s position from the bind pose into the new pose.
Definition: ModelDef.cpp:33
Definition: path.h:75
float Y
Definition: Vector3D.h:31
void Read(const VfsPath &filename, const char magic[4])
open and read in given file, check magic bits against those given; throw variety of exceptions if ope...
Definition: FileIo.cpp:111
size_t m_NumBlends
Definition: ModelDef.h:272
size_t * m_pBlendIndices
Definition: ModelDef.h:274
pthread_key_t key
Definition: wpthread.cpp:140
size_t UnpackSize()
use UnpackRaw to retrieve 32-bits; returns their value as size_t after converting from little endian ...
Definition: FileIo.cpp:162
void SetIdentity()
Definition: Matrix3D.cpp:30
CStr m_Name
Name of the prop point.
Definition: ModelDef.h:51
void UnpackString(CStr8 &result)
unpack a string from the raw data stream.
Definition: FileIo.cpp:170
void SetRenderData(const void *key, CModelDefRPrivate *data)
Register renderer private data.
Definition: ModelDef.cpp:456
CMatrix3D * m_InverseBindBoneMatrices
Definition: ModelDef.h:270
void BlendBoneMatrices(CMatrix3D boneMatrices[])
Blend bone matrices together to fill bone palette.
Definition: ModelDef.cpp:206
CMatrix3D m_Transform
Object to parent space transformation.
Definition: ModelDef.h:73
static void Save(const VfsPath &filename, const CModelDef *mdef)
Definition: ModelDef.cpp:423
SModelFace * GetFaces() const
Definition: ModelDef.h:174
CVector3D m_Coords
Definition: ModelDef.h:104
void Write(const VfsPath &filename)
write out to file all packed data added so far.
Definition: FileIo.cpp:62
float _data[16]
Definition: Matrix3D.h:47
SVertexBlend m_Blend
Definition: ModelDef.h:110
const SPropPoint * FindPropPoint(const char *name) const
Definition: ModelDef.cpp:251
void PackSize(size_t value)
convenience: convert a number (almost always a size type) to little-endian u32 and pack that...
Definition: FileIo.cpp:83
float Z
Definition: Vector3D.h:31
size_t GetNumFaces() const
Definition: ModelDef.h:173
char * GetData() const
Definition: VertexArray.h:107
void Blend(const CMatrix3D &m, float f)
Definition: Matrix3D.h:194
void PackString(const CStr &str)
pack a string onto the end of the data stream (encoded as a 32-bit length followed by the characters)...
Definition: FileIo.cpp:89
CModelDefRPrivate * GetRenderData(const void *key) const
Definition: ModelDef.cpp:465
void AddBlend(const CMatrix3D &m, float f)
Definition: Matrix3D.h:203
CBoneState * m_Bones
Definition: ModelDef.h:269