| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794 |
- ///////////////////////////////////////////////////////////////////////
- // title: MilkShape 3D Model Viewer Sample
- //
- // copyright: The programs and associated files contained in this
- // distribution were developed by Mete Ciragan. The
- // programs are not in the public domain, but they are
- // freely distributable without licensing fees. These
- // programs are provided without guarantee or warrantee
- // expressed or implied. Use at your own risk!
- //
- // email: [email protected]
- // web: http://www.milkshape3d.com
- ///////////////////////////////////////////////////////////////////////
- #include "msModel.h"
- #include "mathlib.h"
- msModel::msModel()
- {
- Clear();
- }
- msModel::~msModel()
- {
- Clear();
- }
- bool msModel::Load(C Str &filename)
- {
- #if WINDOWS
- FILE *fp = _wfopen(filename, L"rb");
- #else
- FILE *fp = fopen(UnixPathUTF8(filename), "r");
- #endif
- if (!fp)
- return false;
- Clear();
- fseek(fp, 0, SEEK_END);
- long fileSize = ftell(fp);
- fseek(fp, 0, SEEK_SET);
- char id[10];
- fread(id, sizeof(char), 10, fp);
- if (strncmp(id, "MS3D000000", 10) != 0)
- {
- fclose(fp);
- // "This is not a valid MS3D file format!"
- return false;
- }
- int version;
- fread(&version, sizeof(int), 1, fp);
- if (version != 4)
- {
- fclose(fp);
- // "This is not a valid MS3D file version!"
- return false;
- }
- int i, j;
- // vertices
- unsigned short numVertices;
- fread(&numVertices, sizeof(unsigned short), 1, fp);
- m_vertices.resize(numVertices);
- for (i = 0; i < numVertices; i++)
- {
- fread(&m_vertices[i].flags, sizeof(unsigned char), 1, fp);
- fread(&m_vertices[i].vertex, sizeof(float), 3, fp);
- fread(&m_vertices[i].boneId, sizeof(char), 1, fp);
- fread(&m_vertices[i].referenceCount, sizeof(unsigned char), 1, fp);
- }
- // triangles
- unsigned short numTriangles;
- fread(&numTriangles, sizeof(unsigned short), 1, fp);
- m_triangles.resize(numTriangles);
- for (i = 0; i < numTriangles; i++)
- {
- fread(&m_triangles[i].flags, sizeof(unsigned short), 1, fp);
- fread(m_triangles[i].vertexIndices, sizeof(unsigned short), 3, fp);
- fread(m_triangles[i].vertexNormals, sizeof(float), 3 * 3, fp);
- fread(m_triangles[i].s, sizeof(float), 3, fp);
- fread(m_triangles[i].t, sizeof(float), 3, fp);
- fread(&m_triangles[i].smoothingGroup, sizeof(unsigned char), 1, fp);
- fread(&m_triangles[i].groupIndex, sizeof(unsigned char), 1, fp);
- // TODO: calculate triangle normal
- }
- // groups
- unsigned short numGroups;
- fread(&numGroups, sizeof(unsigned short), 1, fp);
- m_groups.resize(numGroups);
- for (i = 0; i < numGroups; i++)
- {
- fread(&m_groups[i].flags, sizeof(unsigned char), 1, fp);
- fread(m_groups[i].name, sizeof(char), 32, fp);
- unsigned short numGroupTriangles;
- fread(&numGroupTriangles, sizeof(unsigned short), 1, fp);
- m_groups[i].triangleIndices.resize(numGroupTriangles);
- if (numGroupTriangles > 0)
- fread(&m_groups[i].triangleIndices[0], sizeof(unsigned short), numGroupTriangles, fp);
- fread(&m_groups[i].materialIndex, sizeof(char), 1, fp);
- }
- // materials
- unsigned short numMaterials;
- fread(&numMaterials, sizeof(unsigned short), 1, fp);
- m_materials.resize(numMaterials);
- for (i = 0; i < numMaterials; i++)
- {
- fread(m_materials[i].name, sizeof(char), 32, fp);
- fread(&m_materials[i].ambient, sizeof(float), 4, fp);
- fread(&m_materials[i].diffuse, sizeof(float), 4, fp);
- fread(&m_materials[i].specular, sizeof(float), 4, fp);
- fread(&m_materials[i].emissive, sizeof(float), 4, fp);
- fread(&m_materials[i].shininess, sizeof(float), 1, fp);
- fread(&m_materials[i].transparency, sizeof(float), 1, fp);
- fread(&m_materials[i].mode, sizeof(unsigned char), 1, fp);
- fread(m_materials[i].texture, sizeof(char), MAX_TEXTURE_FILENAME_SIZE, fp);
- fread(m_materials[i].alphamap, sizeof(char), MAX_TEXTURE_FILENAME_SIZE, fp);
- // set alpha
- m_materials[i].ambient[3] = m_materials[i].transparency;
- m_materials[i].diffuse[3] = m_materials[i].transparency;
- m_materials[i].specular[3] = m_materials[i].transparency;
- m_materials[i].emissive[3] = m_materials[i].transparency;
- }
- // animation
- fread(&m_animationFps, sizeof(float), 1, fp);
- if (m_animationFps < 1.0f)
- m_animationFps = 1.0f;
- fread(&m_currentTime, sizeof(float), 1, fp);
- fread(&m_totalFrames, sizeof(int), 1, fp);
- // joints
- unsigned short numJoints;
- fread(&numJoints, sizeof(unsigned short), 1, fp);
- m_joints.resize(numJoints);
- for (i = 0; i < numJoints; i++)
- {
- fread(&m_joints[i].flags, sizeof(unsigned char), 1, fp);
- fread(m_joints[i].name, sizeof(char), 32, fp);
- fread(m_joints[i].parentName, sizeof(char), 32, fp);
- fread(m_joints[i].rot, sizeof(float), 3, fp);
- fread(m_joints[i].pos, sizeof(float), 3, fp);
-
- unsigned short numKeyFramesRot;
- fread(&numKeyFramesRot, sizeof(unsigned short), 1, fp);
- m_joints[i].rotationKeys.resize(numKeyFramesRot);
- unsigned short numKeyFramesPos;
- fread(&numKeyFramesPos, sizeof(unsigned short), 1, fp);
- m_joints[i].positionKeys.resize(numKeyFramesPos);
- // the frame time is in seconds, so multiply it by the animation fps, to get the frames
- // rotation channel
- for (j = 0; j < numKeyFramesRot; j++)
- {
- fread(&m_joints[i].rotationKeys[j].time, sizeof(float), 1, fp);
- fread(&m_joints[i].rotationKeys[j].key, sizeof(float), 3, fp);
- m_joints[i].rotationKeys[j].time *= m_animationFps;
- }
- // translation channel
- for (j = 0; j < numKeyFramesPos; j++)
- {
- fread(&m_joints[i].positionKeys[j].time, sizeof(float), 1, fp);
- fread(&m_joints[i].positionKeys[j].key, sizeof(float), 3, fp);
- m_joints[i].positionKeys[j].time *= m_animationFps;
- }
- }
- // comments
- long filePos = ftell(fp);
- if (filePos < fileSize)
- {
- int subVersion = 0;
- fread(&subVersion, sizeof(int), 1, fp);
- if (subVersion == 1)
- {
- int numComments = 0;
- size_t commentSize = 0;
- // group comments
- fread(&numComments, sizeof(int), 1, fp);
- for (i = 0; i < numComments; i++)
- {
- int index;
- fread(&index, sizeof(int), 1, fp);
- std__vector<char> comment;
- fread(&commentSize, sizeof(size_t), 1, fp);
- comment.resize(commentSize);
- if (commentSize > 0)
- fread(&comment[0], sizeof(char), commentSize, fp);
- if (index >= 0 && index < (int) m_groups.size())
- m_groups[index].comment = comment;
- }
- // material comments
- fread(&numComments, sizeof(int), 1, fp);
- for (i = 0; i < numComments; i++)
- {
- int index;
- fread(&index, sizeof(int), 1, fp);
- std__vector<char> comment;
- fread(&commentSize, sizeof(size_t), 1, fp);
- comment.resize(commentSize);
- if (commentSize > 0)
- fread(&comment[0], sizeof(char), commentSize, fp);
- if (index >= 0 && index < (int) m_materials.size())
- m_materials[index].comment = comment;
- }
- // joint comments
- fread(&numComments, sizeof(int), 1, fp);
- for (i = 0; i < numComments; i++)
- {
- int index;
- fread(&index, sizeof(int), 1, fp);
- std__vector<char> comment;
- fread(&commentSize, sizeof(size_t), 1, fp);
- comment.resize(commentSize);
- if (commentSize > 0)
- fread(&comment[0], sizeof(char), commentSize, fp);
- if (index >= 0 && index < (int) m_joints.size())
- m_joints[index].comment = comment;
- }
- // model comments
- fread(&numComments, sizeof(int), 1, fp);
- if (numComments == 1)
- {
- std__vector<char> comment;
- fread(&commentSize, sizeof(size_t), 1, fp);
- comment.resize(commentSize);
- if (commentSize > 0)
- fread(&comment[0], sizeof(char), commentSize, fp);
- m_comment = comment;
- }
- }
- else
- {
- // "Unknown subversion for comments %d\n", subVersion);
- }
- }
- // vertex extra
- filePos = ftell(fp);
- if (filePos < fileSize)
- {
- int subVersion = 0;
- fread(&subVersion, sizeof(int), 1, fp);
- if (subVersion == 2)
- {
- for (int i = 0; i < numVertices; i++)
- {
- fread(&m_vertices[i].boneIds[0], sizeof(char), 3, fp);
- fread(&m_vertices[i].weights[0], sizeof(unsigned char), 3, fp);
- fread(&m_vertices[i].extra, sizeof(unsigned int), 1, fp);
- }
- }
- else if (subVersion == 1)
- {
- for (int i = 0; i < numVertices; i++)
- {
- fread(&m_vertices[i].boneIds[0], sizeof(char), 3, fp);
- fread(&m_vertices[i].weights[0], sizeof(unsigned char), 3, fp);
- }
- }
- else
- {
- // "Unknown subversion for vertex extra %d\n", subVersion);
- }
- }
- // joint extra
- filePos = ftell(fp);
- if (filePos < fileSize)
- {
- int subVersion = 0;
- fread(&subVersion, sizeof(int), 1, fp);
- if (subVersion == 1)
- {
- for (int i = 0; i < numJoints; i++)
- {
- fread(&m_joints[i].color, sizeof(float), 3, fp);
- }
- }
- else
- {
- // "Unknown subversion for joint extra %d\n", subVersion);
- }
- }
- // model extra
- filePos = ftell(fp);
- if (filePos < fileSize)
- {
- int subVersion = 0;
- fread(&subVersion, sizeof(int), 1, fp);
- if (subVersion == 1)
- {
- fread(&m_jointSize, sizeof(float), 1, fp);
- fread(&m_transparencyMode, sizeof(int), 1, fp);
- fread(&m_alphaRef, sizeof(float), 1, fp);
- }
- else
- {
- //"Unknown subversion for model extra %d\n", subVersion);
- }
- }
- fclose(fp);
- return true;
- }
- void msModel::Clear()
- {
- m_vertices.clear();
- m_triangles.clear();
- m_groups.clear();
- m_materials.clear();
- m_animationFps = 24.0f;
- m_currentTime = 1.0f;
- m_totalFrames = 30;
- m_joints.clear();
- m_comment.clear();
- m_jointSize = 1.0f;
- m_transparencyMode = TRANSPARENCY_MODE_SIMPLE;
- m_alphaRef = 0.5f;
- }
- int msModel::GetNumGroups() const
- {
- return (int) m_groups.size();
- }
- ms3d_group_t *msModel::GetGroup(int index)
- {
- return &m_groups[index];
- }
- int msModel::GetNumTriangles() const
- {
- return (int) m_triangles.size();
- }
- ms3d_triangle_t *msModel::GetTriangle(int index)
- {
- return &m_triangles[index];
- }
- int msModel::GetNumVertices() const
- {
- return (int) m_vertices.size();
- }
- ms3d_vertex_t *msModel::GetVertex(int index)
- {
- return &m_vertices[index];
- }
- int msModel::GetNumMaterials() const
- {
- return (int) m_materials.size();
- }
- ms3d_material_t *msModel::GetMaterial(int index)
- {
- return &m_materials[index];
- }
- int msModel::GetNumJoints() const
- {
- return (int) m_joints.size();
- }
- ms3d_joint_t *msModel::GetJoint(int index)
- {
- return &m_joints[index];
- }
- float msModel::GetJointSize() const
- {
- return m_jointSize;
- }
- int msModel::GetTransparencyMode() const
- {
- return m_transparencyMode;
- }
- float msModel::GetAlphaRef() const
- {
- return m_alphaRef;
- }
- int msModel::FindJointByName(const char *name)
- {
- for (size_t i = 0; i < m_joints.size(); i++)
- {
- if (strcmp(m_joints[i].name, name) == 0)
- return i;
- }
- return -1;
- }
- void msModel::SetupJoints(bool set_tangents)
- {
- for (size_t i = 0; i < m_joints.size(); i++)
- {
- ms3d_joint_t *joint = &m_joints[i];
- joint->parentIndex = FindJointByName(joint->parentName);
- }
- for (size_t i = 0; i < m_joints.size(); i++)
- {
- ms3d_joint_t *joint = &m_joints[i];
- AngleMatrix(joint->rot, joint->matLocalSkeleton);
- joint->matLocalSkeleton[0][3]= joint->pos[0];
- joint->matLocalSkeleton[1][3]= joint->pos[1];
- joint->matLocalSkeleton[2][3]= joint->pos[2];
-
- if (joint->parentIndex == -1)
- {
- memcpy(joint->matGlobalSkeleton, joint->matLocalSkeleton, sizeof(joint->matGlobalSkeleton));
- }
- else
- {
- ms3d_joint_t *parentJoint = &m_joints[joint->parentIndex];
- R_ConcatTransforms(parentJoint->matGlobalSkeleton, joint->matLocalSkeleton, joint->matGlobalSkeleton);
- }
- if(set_tangents)SetupTangents();
- }
- }
- void msModel::SetupTangents()
- {
- for (size_t j = 0; j < m_joints.size(); j++)
- {
- ms3d_joint_t *joint = &m_joints[j];
- int numPositionKeys = (int) joint->positionKeys.size();
- joint->tangents.resize(numPositionKeys);
- // clear all tangents (zero derivatives)
- for (int k = 0; k < numPositionKeys; k++)
- {
- joint->tangents[k].tangentIn[0] = 0.0f;
- joint->tangents[k].tangentIn[1] = 0.0f;
- joint->tangents[k].tangentIn[2] = 0.0f;
- joint->tangents[k].tangentOut[0] = 0.0f;
- joint->tangents[k].tangentOut[1] = 0.0f;
- joint->tangents[k].tangentOut[2] = 0.0f;
- }
- // if there are more than 2 keys, we can calculate tangents, otherwise we use zero derivatives
- if (numPositionKeys > 2)
- {
- for (int k = 0; k < numPositionKeys; k++)
- {
- // make the curve tangents looped
- int k0 = k - 1;
- if (k0 < 0)
- k0 = numPositionKeys - 1;
- int k1 = k;
- int k2 = k + 1;
- if (k2 >= numPositionKeys)
- k2 = 0;
- // calculate the tangent, which is the vector from key[k - 1] to key[k + 1]
- float tangent[3];
- tangent[0] = (joint->positionKeys[k2].key[0] - joint->positionKeys[k0].key[0]);
- tangent[1] = (joint->positionKeys[k2].key[1] - joint->positionKeys[k0].key[1]);
- tangent[2] = (joint->positionKeys[k2].key[2] - joint->positionKeys[k0].key[2]);
- // weight the incoming and outgoing tangent by their time to avoid changes in speed, if the keys are not within the same interval
- float dt1 = joint->positionKeys[k1].time - joint->positionKeys[k0].time;
- float dt2 = joint->positionKeys[k2].time - joint->positionKeys[k1].time;
- float dt = dt1 + dt2;
- joint->tangents[k1].tangentIn[0] = tangent[0] * dt1 / dt;
- joint->tangents[k1].tangentIn[1] = tangent[1] * dt1 / dt;
- joint->tangents[k1].tangentIn[2] = tangent[2] * dt1 / dt;
- joint->tangents[k1].tangentOut[0] = tangent[0] * dt2 / dt;
- joint->tangents[k1].tangentOut[1] = tangent[1] * dt2 / dt;
- joint->tangents[k1].tangentOut[2] = tangent[2] * dt2 / dt;
- }
- }
- }
- }
- void msModel::SetFrame(float frame)
- {
- if (frame < 0.0f)
- {
- for (size_t i = 0; i < m_joints.size(); i++)
- {
- ms3d_joint_t *joint = &m_joints[i];
- memcpy(joint->matLocal, joint->matLocalSkeleton, sizeof(joint->matLocal));
- memcpy(joint->matGlobal, joint->matGlobalSkeleton, sizeof(joint->matGlobal));
- }
- }
- else
- {
- for (size_t i = 0; i < m_joints.size(); i++)
- {
- EvaluateJoint(i, frame);
- }
- }
- m_currentTime = frame;
- }
- void msModel::EvaluateJoint(int index, float frame)
- {
- ms3d_joint_t *joint = &m_joints[index];
- //
- // calculate joint animation matrix, this matrix will animate matLocalSkeleton
- //
- vec3_t pos = { 0.0f, 0.0f, 0.0f };
- int numPositionKeys = (int) joint->positionKeys.size();
- if (numPositionKeys > 0)
- {
- int i1 = -1;
- int i2 = -1;
- // find the two keys, where "frame" is in between for the position channel
- for (int i = 0; i < (numPositionKeys - 1); i++)
- {
- if (frame >= joint->positionKeys[i].time && frame < joint->positionKeys[i + 1].time)
- {
- i1 = i;
- i2 = i + 1;
- break;
- }
- }
- // if there are no such keys
- if (i1 == -1 || i2 == -1)
- {
- // either take the first
- if (frame < joint->positionKeys[0].time)
- {
- pos[0] = joint->positionKeys[0].key[0];
- pos[1] = joint->positionKeys[0].key[1];
- pos[2] = joint->positionKeys[0].key[2];
- }
- // or the last key
- else if (frame >= joint->positionKeys[numPositionKeys - 1].time)
- {
- pos[0] = joint->positionKeys[numPositionKeys - 1].key[0];
- pos[1] = joint->positionKeys[numPositionKeys - 1].key[1];
- pos[2] = joint->positionKeys[numPositionKeys - 1].key[2];
- }
- }
- // there are such keys, so interpolate using hermite interpolation
- else
- {
- ms3d_keyframe_t *p0 = &joint->positionKeys[i1];
- ms3d_keyframe_t *p1 = &joint->positionKeys[i2];
- ms3d_tangent_t *m0 = &joint->tangents[i1];
- ms3d_tangent_t *m1 = &joint->tangents[i2];
- // normalize the time between the keys into [0..1]
- float t = (frame - joint->positionKeys[i1].time) / (joint->positionKeys[i2].time - joint->positionKeys[i1].time);
- float t2 = t * t;
- float t3 = t2 * t;
- // calculate hermite basis
- float h1 = 2.0f * t3 - 3.0f * t2 + 1.0f;
- float h2 = -2.0f * t3 + 3.0f * t2;
- float h3 = t3 - 2.0f * t2 + t;
- float h4 = t3 - t2;
- // do hermite interpolation
- pos[0] = h1 * p0->key[0] + h3 * m0->tangentOut[0] + h2 * p1->key[0] + h4 * m1->tangentIn[0];
- pos[1] = h1 * p0->key[1] + h3 * m0->tangentOut[1] + h2 * p1->key[1] + h4 * m1->tangentIn[1];
- pos[2] = h1 * p0->key[2] + h3 * m0->tangentOut[2] + h2 * p1->key[2] + h4 * m1->tangentIn[2];
- }
- }
- vec4_t quat = { 0.0f, 0.0f, 0.0f, 1.0f };
- int numRotationKeys = (int) joint->rotationKeys.size();
- if (numRotationKeys > 0)
- {
- int i1 = -1;
- int i2 = -1;
- // find the two keys, where "frame" is in between for the rotation channel
- for (int i = 0; i < (numRotationKeys - 1); i++)
- {
- if (frame >= joint->rotationKeys[i].time && frame < joint->rotationKeys[i + 1].time)
- {
- i1 = i;
- i2 = i + 1;
- break;
- }
- }
- // if there are no such keys
- if (i1 == -1 || i2 == -1)
- {
- // either take the first key
- if (frame < joint->rotationKeys[0].time)
- {
- AngleQuaternion(joint->rotationKeys[0].key, quat);
- }
- // or the last key
- else if (frame >= joint->rotationKeys[numRotationKeys - 1].time)
- {
- AngleQuaternion(joint->rotationKeys[numRotationKeys - 1].key, quat);
- }
- }
- // there are such keys, so do the quaternion slerp interpolation
- else
- {
- float t = (frame - joint->rotationKeys[i1].time) / (joint->rotationKeys[i2].time - joint->rotationKeys[i1].time);
- vec4_t q1;
- AngleQuaternion(joint->rotationKeys[i1].key, q1);
- vec4_t q2;
- AngleQuaternion(joint->rotationKeys[i2].key, q2);
- QuaternionSlerp(q1, q2, t, quat);
- }
- }
- // make a matrix from pos/quat
- float matAnimate[3][4];
- QuaternionMatrix(quat, matAnimate);
- matAnimate[0][3] = pos[0];
- matAnimate[1][3] = pos[1];
- matAnimate[2][3] = pos[2];
- // animate the local joint matrix using: matLocal = matLocalSkeleton * matAnimate
- R_ConcatTransforms(joint->matLocalSkeleton, matAnimate, joint->matLocal);
- // build up the hierarchy if joints
- // matGlobal = matGlobal(parent) * matLocal
- if (joint->parentIndex == -1)
- {
- memcpy(joint->matGlobal, joint->matLocal, sizeof(joint->matGlobal));
- }
- else
- {
- ms3d_joint_t *parentJoint = &m_joints[joint->parentIndex];
- R_ConcatTransforms(parentJoint->matGlobal, joint->matLocal, joint->matGlobal);
- }
- }
- float msModel::GetAnimationFps() const
- {
- return m_animationFps;
- }
- float msModel::GetCurrentFrame() const
- {
- return m_currentTime;
- }
- int msModel::GetTotalFrames() const
- {
- return m_totalFrames;
- }
- void msModel::TransformVertex(const ms3d_vertex_t *vertex, vec3_t out) const
- {
- int jointIndices[4], jointWeights[4];
- FillJointIndicesAndWeights(vertex, jointIndices, jointWeights);
- if (jointIndices[0] < 0 || jointIndices[0] >= (int) m_joints.size() || m_currentTime < 0.0f)
- {
- out[0] = vertex->vertex[0];
- out[1] = vertex->vertex[1];
- out[2] = vertex->vertex[2];
- }
- else
- {
- // count valid weights
- int numWeights = 0;
- for (int i = 0; i < 4; i++)
- {
- if (jointWeights[i] > 0 && jointIndices[i] >= 0 && jointIndices[i] < (int) m_joints.size())
- ++numWeights;
- else
- break;
- }
- // init
- out[0] = 0.0f;
- out[1] = 0.0f;
- out[2] = 0.0f;
- float weights[4] = { (float) jointWeights[0] / 100.0f, (float) jointWeights[1] / 100.0f, (float) jointWeights[2] / 100.0f, (float) jointWeights[3] / 100.0f };
- if (numWeights == 0)
- {
- numWeights = 1;
- weights[0] = 1.0f;
- }
- // add weighted vertices
- for (int i = 0; i < numWeights; i++)
- {
- const ms3d_joint_t *joint = &m_joints[jointIndices[i]];
- vec3_t tmp, vert;
- VectorITransform(vertex->vertex, joint->matGlobalSkeleton, tmp);
- VectorTransform(tmp, joint->matGlobal, vert);
- out[0] += vert[0] * weights[i];
- out[1] += vert[1] * weights[i];
- out[2] += vert[2] * weights[i];
- }
- }
- }
- void msModel::TransformNormal(const ms3d_vertex_t *vertex, const vec3_t normal, vec3_t out) const
- {
- int jointIndices[4], jointWeights[4];
- FillJointIndicesAndWeights(vertex, jointIndices, jointWeights);
- if (jointIndices[0] < 0 || jointIndices[0] >= (int) m_joints.size() || m_currentTime < 0.0f)
- {
- out[0] = normal[0];
- out[1] = normal[1];
- out[2] = normal[2];
- }
- else
- {
- // count valid weights
- int numWeights = 0;
- for (int i = 0; i < 4; i++)
- {
- if (jointWeights[i] > 0 && jointIndices[i] >= 0 && jointIndices[i] < (int) m_joints.size())
- ++numWeights;
- else
- break;
- }
- // init
- out[0] = 0.0f;
- out[1] = 0.0f;
- out[2] = 0.0f;
- float weights[4] = { (float) jointWeights[0] / 100.0f, (float) jointWeights[1] / 100.0f, (float) jointWeights[2] / 100.0f, (float) jointWeights[3] / 100.0f };
- if (numWeights == 0)
- {
- numWeights = 1;
- weights[0] = 1.0f;
- }
- // add weighted vertices
- for (int i = 0; i < numWeights; i++)
- {
- const ms3d_joint_t *joint = &m_joints[jointIndices[i]];
- vec3_t tmp, norm;
- VectorIRotate(normal, joint->matGlobalSkeleton, tmp);
- VectorRotate(tmp, joint->matGlobal, norm);
- out[0] += norm[0] * weights[i];
- out[1] += norm[1] * weights[i];
- out[2] += norm[2] * weights[i];
- }
- }
- }
- void msModel::FillJointIndicesAndWeights(const ms3d_vertex_t *vertex, int jointIndices[4], int jointWeights[4]) const
- {
- jointIndices[0] = vertex->boneId;
- jointIndices[1] = vertex->boneIds[0];
- jointIndices[2] = vertex->boneIds[1];
- jointIndices[3] = vertex->boneIds[2];
- jointWeights[0] = 100;
- jointWeights[1] = 0;
- jointWeights[2] = 0;
- jointWeights[3] = 0;
- if (vertex->weights[0] != 0 || vertex->weights[1] != 0 || vertex->weights[2] != 0)
- {
- jointWeights[0] = vertex->weights[0];
- jointWeights[1] = vertex->weights[1];
- jointWeights[2] = vertex->weights[2];
- jointWeights[3] = 100 - (vertex->weights[0] + vertex->weights[1] + vertex->weights[2]);
- }
- }
|