qboolean G2API_GetBoltMatrix_SPMethod(CGhoul2Info_v &ghoul2, const int modelIndex, const int boltIndex, mdxaBone_t *matrix, const vec3_t angles, const vec3_t position, const int frameNum, qhandle_t *modelList, const vec3_t scale ) { assert(ghoul2.size() > modelIndex); if ((int)&ghoul2 && (ghoul2.size() > modelIndex)) { CGhoul2Info *ghlInfo = &ghoul2[modelIndex]; //assert(boltIndex < ghlInfo->mBltlist.size()); if (ghlInfo && (boltIndex < ghlInfo->mBltlist.size()) && boltIndex >= 0 ) { // make sure we have transformed the skeleton if (!gG2_GBMNoReconstruct) { G2_ConstructGhoulSkeleton(ghoul2, frameNum, modelList, true, angles, position, scale, false); } gG2_GBMNoReconstruct = qfalse; mdxaBone_t scaled; mdxaBone_t *use; use=&ghlInfo->mBltlist[boltIndex].position; if (scale[0]||scale[1]||scale[2]) { scaled=*use; use=&scaled; // scale the bolt position by the scale factor for this model since at this point its still in model space if (scale[0]) { scaled.matrix[0][3] *= scale[0]; } if (scale[1]) { scaled.matrix[1][3] *= scale[1]; } if (scale[2]) { scaled.matrix[2][3] *= scale[2]; } } // pre generate the world matrix G2_GenerateWorldMatrix(angles, position); VectorNormalize((float*)use->matrix[0]); VectorNormalize((float*)use->matrix[1]); VectorNormalize((float*)use->matrix[2]); Multiply_3x4Matrix(matrix, &worldMatrix, use); return qtrue; } } return qfalse; }
qboolean G2API_GetBoltMatrix(CGhoul2Info_v &ghoul2, const int modelIndex, const int boltIndex, mdxaBone_t *matrix, const vec3_t angles, const vec3_t position, const int frameNum, qhandle_t *modelList, vec3_t scale ) { assert(ghoul2.size() > modelIndex); if (gG2_GBMUseSPMethod) { gG2_GBMUseSPMethod = qfalse; return G2API_GetBoltMatrix_SPMethod(ghoul2, modelIndex, boltIndex, matrix, angles, position, frameNum, modelList, scale); } if ((int)&ghoul2 && (ghoul2.size() > modelIndex)) { CGhoul2Info *ghlInfo = &ghoul2[modelIndex]; //assert(boltIndex < ghlInfo->mBltlist.size()); if (ghlInfo && (boltIndex < ghlInfo->mBltlist.size()) && boltIndex >= 0 ) { // make sure we have transformed the skeleton if (!gG2_GBMNoReconstruct) { G2_ConstructGhoulSkeleton(ghoul2, frameNum, modelList, true, angles, position, scale, false); } gG2_GBMNoReconstruct = qfalse; mdxaBone_t scaled; mdxaBone_t *use; use=&ghlInfo->mBltlist[boltIndex].position; if (scale[0]||scale[1]||scale[2]) { scaled=*use; use=&scaled; // scale the bolt position by the scale factor for this model since at this point its still in model space if (scale[0]) { scaled.matrix[0][3] *= scale[0]; } if (scale[1]) { scaled.matrix[1][3] *= scale[1]; } if (scale[2]) { scaled.matrix[2][3] *= scale[2]; } } // pre generate the world matrix G2_GenerateWorldMatrix(angles, position); // for some reason we get the end matrix rotated by 90 degrees mdxaBone_t rotMat, tempMatrix; vec3_t newangles = {0,270,0}; Create_Matrix(newangles, &rotMat); // make the model space matrix we have for this bolt into a world matrix // Multiply_3x4Matrix(matrix, &worldMatrix,use); Multiply_3x4Matrix(&tempMatrix, &worldMatrix,use); vec3_t origin; origin[0] = tempMatrix.matrix[0][3]; origin[1] = tempMatrix.matrix[1][3]; origin[2] = tempMatrix.matrix[2][3]; tempMatrix.matrix[0][3] = tempMatrix.matrix[1][3] = tempMatrix.matrix[2][3] = 0; Multiply_3x4Matrix(matrix, &tempMatrix, &rotMat); matrix->matrix[0][3] = origin[0]; matrix->matrix[1][3] = origin[1]; matrix->matrix[2][3] = origin[2]; return qtrue; } } return qfalse; }
qboolean G2API_GetBoltMatrix_SPMethod(g2handle_t g2h, const int modelIndex, const int boltIndex, mdxaBone_t *matrix, const vec3_t angles, const vec3_t position, const int frameNum, const qhandle_t *modelList, const vec3_t scale ) { CGhoul2Info_v *ghoul2 = G2API_GetGhoul2Model(g2h); if (ghoul2 && (unsigned)modelIndex < ghoul2->size()) { CGhoul2Info &ghlInfo = (*ghoul2)[modelIndex]; //assert(boltIndex < ghlInfo->mBltlist.size()); if ((unsigned)boltIndex < ghlInfo.mBltlist.size()) { // make sure we have transformed the skeleton if (ghlInfo.mSkelFrameNum != frameNum) { // make sure it's initialized even if noreconstruct is on if (!gG2_GBMNoReconstruct || ghlInfo.mSkelFrameNum == -1) { G2_ConstructGhoulSkeleton(*ghoul2, frameNum, modelList, true, angles, position, scale, false); } } gG2_GBMNoReconstruct = qfalse; mdxaBone_t scaled; mdxaBone_t *use; use = &ghlInfo.mBltlist[boltIndex].position; if (scale[0]||scale[1]||scale[2]) { scaled=*use; use=&scaled; // scale the bolt position by the scale factor for this model since at this point its still in model space if (scale[0]) { scaled.matrix[0][3] *= scale[0]; } if (scale[1]) { scaled.matrix[1][3] *= scale[1]; } if (scale[2]) { scaled.matrix[2][3] *= scale[2]; } } // pre generate the world matrix G2_GenerateWorldMatrix(angles, position); VectorNormalize((float*)use->matrix[0]); VectorNormalize((float*)use->matrix[1]); VectorNormalize((float*)use->matrix[2]); Multiply_3x4Matrix(matrix, &worldMatrix, use); return qtrue; } } return qfalse; }
// generate a matrix for a given bone given some new angles for it. void G2_Generate_Matrix(const model_t *mod, boneInfo_v &blist, int index, const float *angles, int flags, const Eorientations up, const Eorientations left, const Eorientations forward) { mdxaSkel_t *skel; mdxaSkelOffsets_t *offsets; mdxaBone_t temp1; mdxaBone_t permutation; mdxaBone_t *boneOverride = &blist[index].matrix; vec3_t newAngles; if (flags & (BONE_ANGLES_PREMULT | BONE_ANGLES_POSTMULT)) { // build us a matrix out of the angles we are fed - but swap y and z because of wacky Quake setup vec3_t newAngles; // determine what axis newAngles Yaw should revolve around switch (up) { case NEGATIVE_X: newAngles[1] = angles[2] + 180; break; case POSITIVE_X: newAngles[1] = angles[2]; break; case NEGATIVE_Y: newAngles[1] = angles[0]; break; case POSITIVE_Y: newAngles[1] = angles[0]; break; case NEGATIVE_Z: newAngles[1] = angles[1] + 180; break; case POSITIVE_Z: newAngles[1] = angles[1]; break; } // determine what axis newAngles pitch should revolve around switch (left) { case NEGATIVE_X: newAngles[0] = angles[2]; break; case POSITIVE_X: newAngles[0] = angles[2] + 180; break; case NEGATIVE_Y: newAngles[0] = angles[0]; break; case POSITIVE_Y: newAngles[0] = angles[0] + 180; break; case NEGATIVE_Z: newAngles[0] = angles[1]; break; case POSITIVE_Z: newAngles[0] = angles[1]; break; } // determine what axis newAngles Roll should revolve around switch (forward) { case NEGATIVE_X: newAngles[2] = angles[2]; break; case POSITIVE_X: newAngles[2] = angles[2]; break; case NEGATIVE_Y: newAngles[2] = angles[0]; break; case POSITIVE_Y: newAngles[2] = angles[0] + 180; break; case NEGATIVE_Z: newAngles[2] = angles[1]; break; case POSITIVE_Z: newAngles[2] = angles[1] + 180; break; } Create_Matrix(newAngles, boneOverride); // figure out where the bone hirearchy info is offsets = (mdxaSkelOffsets_t *)((byte *)mod->mdxa + sizeof(mdxaHeader_t)); skel = (mdxaSkel_t *)((byte *)mod->mdxa + sizeof(mdxaHeader_t) + offsets->offsets[blist[index].boneNumber]); Multiply_3x4Matrix(&temp1, boneOverride,&skel->BasePoseMatInv); Multiply_3x4Matrix(boneOverride,&skel->BasePoseMat, &temp1); } else { VectorCopy(angles, newAngles); // why I should need do this F**k alone knows. But I do. if (left == POSITIVE_Y) { newAngles[0] +=180; } Create_Matrix(newAngles, &temp1); permutation.matrix[0][0] = permutation.matrix[0][1] = permutation.matrix[0][2] = permutation.matrix[0][3] = 0; permutation.matrix[1][0] = permutation.matrix[1][1] = permutation.matrix[1][2] = permutation.matrix[1][3] = 0; permutation.matrix[2][0] = permutation.matrix[2][1] = permutation.matrix[2][2] = permutation.matrix[2][3] = 0; // determine what axis newAngles Yaw should revolve around switch (forward) { case NEGATIVE_X: permutation.matrix[0][0] = -1; // works break; case POSITIVE_X: permutation.matrix[0][0] = 1; // works break; case NEGATIVE_Y: permutation.matrix[1][0] = -1; break; case POSITIVE_Y: permutation.matrix[1][0] = 1; break; case NEGATIVE_Z: permutation.matrix[2][0] = -1; break; case POSITIVE_Z: permutation.matrix[2][0] = 1; break; } // determine what axis newAngles pitch should revolve around switch (left) { case NEGATIVE_X: permutation.matrix[0][1] = -1; break; case POSITIVE_X: permutation.matrix[0][1] = 1; break; case NEGATIVE_Y: permutation.matrix[1][1] = -1; // works break; case POSITIVE_Y: permutation.matrix[1][1] = 1; // works break; case NEGATIVE_Z: permutation.matrix[2][1] = -1; break; case POSITIVE_Z: permutation.matrix[2][1] = 1; break; } // determine what axis newAngles Roll should revolve around switch (up) { case NEGATIVE_X: permutation.matrix[0][2] = -1; break; case POSITIVE_X: permutation.matrix[0][2] = 1; break; case NEGATIVE_Y: permutation.matrix[1][2] = -1; break; case POSITIVE_Y: permutation.matrix[1][2] = 1; break; case NEGATIVE_Z: permutation.matrix[2][2] = -1; // works break; case POSITIVE_Z: permutation.matrix[2][2] = 1; // works break; } Multiply_3x4Matrix(boneOverride, &temp1,&permutation); } // keep a copy of the matrix in the newmatrix which is actually what we use memcpy(&blist[index].newMatrix, &blist[index].matrix, sizeof(mdxaBone_t)); }