static int test_inverse (const vec3_t angles, const vec3_t scale, const vec3_t translation) { int i; quat_t rotation; mat4_t mat, inv, I, res; AngleQuat (angles, rotation); Mat4Init (rotation, scale, translation, mat); Mat4Identity (I); Mat4Inverse (mat, inv); Mat4Mult (mat, inv, res); for (i = 0; i < 4 * 4; i++) if (!compare (I[i], res[i])) goto fail; return 1; fail: printf ("\n\n(%g %g %g) (%g %g %g) (%g %g %g)\n", VectorExpand (angles), VectorExpand (scale), VectorExpand (translation)); printf (" [%g %g %g %g]\n [%g %g %g %g]\n" " [%g %g %g %g]\n [%g %g %g %g]\n\n", Mat4Expand (mat)); printf (" [%g %g %g %g]\n [%g %g %g %g]\n" " [%g %g %g %g]\n [%g %g %g %g]\n\n", Mat4Expand (inv)); printf (" [%g %g %g %g]\n [%g %g %g %g]\n" " [%g %g %g %g]\n [%g %g %g %g]\n\n", Mat4Expand (res)); return 0; }
static qboolean load_iqm_meshes (model_t *mod, const iqmheader *hdr, byte *buffer) { iqm_t *iqm = (iqm_t *) mod->aliashdr; iqmtriangle *tris; iqmmesh *meshes; iqmjoint *joints; uint32_t i; if (!load_iqm_vertex_arrays (mod, hdr, buffer)) return false; if (!(tris = get_triangles (hdr, buffer))) return false; iqm->num_elements = hdr->num_triangles * 3; iqm->elements = malloc (hdr->num_triangles * 3 * sizeof (uint16_t)); for (i = 0; i < hdr->num_triangles; i++) VectorCopy (tris[i].vertex, iqm->elements + i * 3); if (!(meshes = get_meshes (hdr, buffer))) return false; iqm->num_meshes = hdr->num_meshes; iqm->meshes = malloc (hdr->num_meshes * sizeof (iqmmesh)); memcpy (iqm->meshes, meshes, hdr->num_meshes * sizeof (iqmmesh)); if (!(joints = get_joints (hdr, buffer))) return false; iqm->num_joints = hdr->num_joints; iqm->joints = malloc (iqm->num_joints * sizeof (iqmjoint)); iqm->baseframe = malloc (iqm->num_joints * sizeof (mat4_t)); iqm->inverse_baseframe = malloc (iqm->num_joints * sizeof (mat4_t)); memcpy (iqm->joints, joints, iqm->num_joints * sizeof (iqmjoint)); for (i = 0; i < hdr->num_joints; i++) { iqmjoint *j = &iqm->joints[i]; mat4_t *bf = &iqm->baseframe[i]; mat4_t *ibf = &iqm->inverse_baseframe[i]; quat_t t; float ilen; ilen = 1.0 / sqrt(QDotProduct (j->rotate, j->rotate)); QuatScale (j->rotate, ilen, t); Mat4Init (t, j->scale, j->translate, *bf); Mat4Inverse (*bf, *ibf); if (j->parent >= 0) { Mat4Mult (iqm->baseframe[j->parent], *bf, *bf); Mat4Mult (*ibf, iqm->inverse_baseframe[j->parent], *ibf); } } return true; }
//-------------------------------------------------------------------------------------------------------------- //更新节点矩阵 void FKFastcall BoundNode::_UpdateMatrix() { //从根节点递归更新所有需要更新的节点 BoundNode* pNode = NULL; //如果该节点局部坐标矩阵需要更新 if( mbUpdateLocalMatrix ) { //设置旋转矩阵 static Matrix4 matRota; mOrientation.GetRotationMatrix4( &matRota ); //设置缩放矩阵 static Matrix4 matScl; matScl.SetScaling( mScale.x, mScale.y, mScale.z ); //生成当前节点局部坐标矩阵 Mat4TransMat4( &mLocalMatrix, &matScl, &matRota ); //设置局部坐标矩阵平移 mLocalMatrix._41 = mPosition.x; mLocalMatrix._42 = mPosition.y; mLocalMatrix._43 = mPosition.z; mbUpdateLocalMatrix = false; //更新该节点的世界矩阵 goto UpdateWorldMatrix; } //或者该节点的子节点需要更新 else if( mbUpdateChildMatrix ) { //更新所有子节点的矩阵 BoundNodeList::Iterator it = mChildNodeList.Begin(); BoundNodeList::Iterator itend = mChildNodeList.End(); for(; it!=itend; ++it ) (*it)->_UpdateMatrix(); mbUpdateChildMatrix = false; } //如果该节点的世界坐标矩阵需要更新 if( mbUpdateWorldMatrix ) { UpdateWorldMatrix: //与父级矩阵级联生成该节点世界坐标矩阵 if( mpParentNode != NULL ) Mat4TransMat4( &mWorldMatrix, &mLocalMatrix, &mpParentNode->mWorldMatrix ); else mWorldMatrix = mLocalMatrix; Mat4Inverse( &mInvWorldMatrix, &mWorldMatrix ); //更新所有子节点的世界坐标矩阵(如需要则会同时更新其局部坐标矩阵) BoundNodeList::Iterator it = mChildNodeList.Begin(); BoundNodeList::Iterator itend = mChildNodeList.End(); for(; it!=itend; ++it ) { pNode = *it; pNode->mbUpdateWorldMatrix = true; pNode->_UpdateMatrix(); } mbUpdateWorldMatrix = false; //更新所有碰撞体世界坐标包围盒 _UpdateBoundVolumeBox(); } }