22 #include "precompiled.h"
30 # include <xmmintrin.h>
95 const size_t* blendIndices,
99 char* PositionData = Position.
GetData();
100 size_t PositionStride = Position.
GetStride();
101 char* NormalData = Normal.
GetData();
102 size_t NormalStride = Normal.
GetStride();
104 for (
size_t j = 0; j < numVertices; ++j)
119 memcpy(PositionData + PositionStride*j, &pos.
X, 3*
sizeof(
float));
120 memcpy(NormalData + NormalStride*j, &norm.
X, 3*
sizeof(
float));
125 void CModelDef::SkinPointsAndNormals_SSE(
130 const size_t* blendIndices,
134 char* PositionData = Position.
GetData();
135 size_t PositionStride = Position.
GetStride();
136 char* NormalData = Normal.
GetData();
137 size_t NormalStride = Normal.
GetStride();
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);
146 __m128 col0, col1, col2, col3, vec0, vec1, vec2;
148 for (
size_t j = 0; j < numVertices; ++j)
151 const CMatrix3D& mtx = newPoseMatrices[blendIndices[j]];
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);
161 vec0 = _mm_mul_ps(col0, vec0);
163 vec1 = _mm_mul_ps(col1, vec1);
164 vec0 = _mm_add_ps(vec0, vec1);
166 vec1 = _mm_mul_ps(col2, vec1);
167 vec1 = _mm_add_ps(vec1, col3);
168 vec0 = _mm_add_ps(vec0, vec1);
169 _mm_store_ps((
float*)(PositionData + PositionStride*j), vec0);
172 vec0 = _mm_load1_ps(&vtx.
m_Norm.
X);
173 vec0 = _mm_mul_ps(col0, vec0);
174 vec1 = _mm_load1_ps(&vtx.
m_Norm.
Y);
175 vec1 = _mm_mul_ps(col1, vec1);
176 vec0 = _mm_add_ps(vec0, vec1);
177 vec1 = _mm_load1_ps(&vtx.
m_Norm.
Z);
178 vec1 = _mm_mul_ps(col2, vec1);
179 vec0 = _mm_add_ps(vec0, vec1);
190 vec1 = _mm_mul_ps(vec0, vec0);
192 vec2 = _mm_shuffle_ps(vec1, vec1, _MM_SHUFFLE(3, 0, 2, 1));
193 vec1 = _mm_add_ps(vec1, vec2);
195 vec2 = _mm_shuffle_ps(vec2, vec2, _MM_SHUFFLE(3, 0, 2, 1));
196 vec1 = _mm_add_ps(vec1, vec2);
198 vec1 = _mm_rsqrt_ps(vec1);
199 vec0 = _mm_mul_ps(vec0, vec1);
201 _mm_store_ps((
float*)(NormalData + NormalStride*j), vec0);
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]")
266 unpacker.
Read(filename,
"PSMD");
273 std::auto_ptr<CModelDef> mdef (
new CModelDef());
282 mdef->m_NumUVsPerVertex = 1;
286 mdef->m_NumUVsPerVertex = unpacker.
UnpackSize();
289 mdef->m_pVertices=
new SModelVertex[mdef->m_NumVertices];
291 for (
size_t i = 0; i < mdef->m_NumVertices; ++i)
293 unpacker.
UnpackRaw(&mdef->m_pVertices[i].m_Coords, 12);
294 unpacker.
UnpackRaw(&mdef->m_pVertices[i].m_Norm, 12);
296 for (
size_t s = 0; s < mdef->m_NumUVsPerVertex; ++s)
300 mdef->m_pVertices[i].m_UVs.push_back(uv[0]);
301 mdef->m_pVertices[i].m_UVs.push_back(uv[1]);
308 mdef->m_pFaces=
new SModelFace[mdef->m_NumFaces];
312 if (mdef->m_NumBones)
314 mdef->m_Bones=
new CBoneState[mdef->m_NumBones];
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++)
321 const SVertexBlend &blend = mdef->m_pVertices[i].m_Blend;
322 if (blend.
m_Bone[1] == 0xFF)
324 mdef->m_pBlendIndices[i] = blend.
m_Bone[0];
331 for (j = 0; j < blends.size(); j++)
333 if (blend == blends[j])
break;
335 if (j >= blends.size())
336 blends.push_back(blend);
340 mdef->m_pBlendIndices[i] = mdef->m_NumBones + 1 + j;
344 mdef->m_NumBlends = blends.size();
346 std::copy(blends.begin(), blends.end(), mdef->m_pBlends);
353 mdef->m_PropPoints.resize(numPropPoints);
356 for (
size_t i = 0; i < numPropPoints; i++)
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));
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);
380 mdef->m_PropPoints.push_back(prop);
390 if (mdef->m_NumBones)
392 std::vector<CMatrix3D> bindPose (mdef->m_NumBones);
394 for (
size_t i = 0; i < mdef->m_NumBones; ++i)
396 bindPose[i].SetIdentity();
397 bindPose[i].Rotate(mdef->m_Bones[i].m_Rotation);
398 bindPose[i].Translate(mdef->m_Bones[i].m_Translation);
401 for (
size_t i = 0; i < mdef->m_NumVertices; ++i)
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]);
410 mdef->m_InverseBindBoneMatrices =
new CMatrix3D[mdef->m_NumBones];
412 for (
size_t i = 0; i < mdef->m_NumBones; ++i)
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());
419 return mdef.release();
443 for (
size_t i = 0; i < numPropPoints; i++)
452 packer.
Write(filename);
467 RenderDataMap::const_iterator it =
m_RenderData.find(key);
u8 m_BoneIndex
Index of parent bone to which this prop point is relative, if any.
void UnpackRaw(void *rawData, size_t rawDataSize)
unpack given number of bytes from the input into the given array.
Describes the position of a prop point within its parent model.
RenderDataMap m_RenderData
SModelVertex * m_pVertices
SModelVertex * GetVertices() const
CVector3D Transform(const CVector3D &vector) const
void PackRaw(const void *rawData, size_t rawDataSize)
pack given number of bytes onto the end of the data stream
std::vector< SPropPoint > m_PropPoints
#define ASSERT(expr)
same as ENSURE in debug mode, does nothing in release mode.
helper class for reading binary files
static CVector3D SkinNormal(const SModelVertex &vtx, const CMatrix3D newPoseMatrices[])
Transform the given vertex's normal from the bind pose into the new pose.
void Rotate(const CQuaternion &quat)
size_t GetNumVertices() const
helper class for writing binary files.
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' positions and normals.
static CModelDef * Load(const VfsPath &filename, const VfsPath &name)
Loads a PMD file.
static CVector3D SkinPoint(const SModelVertex &vtx, const CMatrix3D newPoseMatrices[])
Transform the given vertex's position from the bind pose into the new pose.
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...
size_t UnpackSize()
use UnpackRaw to retrieve 32-bits; returns their value as size_t after converting from little endian ...
CStr m_Name
Name of the prop point.
void UnpackString(CStr8 &result)
unpack a string from the raw data stream.
void SetRenderData(const void *key, CModelDefRPrivate *data)
Register renderer private data.
CMatrix3D * m_InverseBindBoneMatrices
void BlendBoneMatrices(CMatrix3D boneMatrices[])
Blend bone matrices together to fill bone palette.
CMatrix3D m_Transform
Object to parent space transformation.
static void Save(const VfsPath &filename, const CModelDef *mdef)
SModelFace * GetFaces() const
void Write(const VfsPath &filename)
write out to file all packed data added so far.
const SPropPoint * FindPropPoint(const char *name) const
void PackSize(size_t value)
convenience: convert a number (almost always a size type) to little-endian u32 and pack that...
size_t GetNumFaces() const
void Blend(const CMatrix3D &m, float f)
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)...
CModelDefRPrivate * GetRenderData(const void *key) const
void AddBlend(const CMatrix3D &m, float f)