/* ============== R_IQMBuildSkeleton ============== */ static int IQMBuildSkeleton( refSkeleton_t *skel, skelAnimation_t *skelAnim, int startFrame, int endFrame, float frac ) { int i; IQAnim_t *anim; transform_t *newPose, *oldPose; vec3_t mins, maxs; anim = skelAnim->iqm; // Validate the frames so there is no chance of a crash. // This will write directly into the entity structure, so // when the surfaces are rendered, they don't need to be // range checked again. if( anim->flags & IQM_LOOP ) { startFrame %= anim->num_frames; endFrame %= anim->num_frames; } else { Q_clamp( startFrame, 0, anim->num_frames - 1 ); Q_clamp( endFrame, 0, anim->num_frames - 1 ); } // compute frame pointers oldPose = &anim->poses[ startFrame * anim->num_joints ]; newPose = &anim->poses[ endFrame * anim->num_joints ]; // calculate a bounding box in the current coordinate system if( anim->bounds ) { float *bounds = &anim->bounds[ 6 * startFrame ]; VectorCopy( bounds, mins ); VectorCopy( bounds + 3, maxs ); bounds = &anim->bounds[ 6 * endFrame ]; BoundsAdd( mins, maxs, bounds, bounds + 3 ); } for ( i = 0; i < anim->num_joints; i++ ) { TransStartLerp( &skel->bones[ i ].t ); TransAddWeight( 1.0f - frac, &oldPose[ i ], &skel->bones[ i ].t ); TransAddWeight( frac, &newPose[ i ], &skel->bones[ i ].t ); TransEndLerp( &skel->bones[ i ].t ); #if defined( REFBONE_NAMES ) Q_strncpyz( skel->bones[ i ].name, anim->name, sizeof( skel->bones[ i ].name ) ); #endif skel->bones[ i ].parentIndex = anim->jointParents[ i ]; } skel->numBones = anim->num_joints; skel->type = refSkeletonType_t::SK_RELATIVE; VectorCopy( mins, skel->bounds[ 0 ] ); VectorCopy( maxs, skel->bounds[ 1 ] ); return true; }
/* ============== RE_BlendSkeleton ============== */ int RE_BlendSkeleton(refSkeleton_t* skel, const refSkeleton_t* blend, float frac) { int i; vec3_t bounds[2]; if (skel->numBones != blend->numBones) { ri.Printf(PRINT_WARNING, "RE_BlendSkeleton: different number of bones %d != %d\n", skel->numBones, blend->numBones); return false; } // lerp between the 2 bone poses for (i = 0; i < skel->numBones; i++) { transform_t trans; TransStartLerp(&trans); TransAddWeight(1.0f - frac, &skel->bones[i].t, &trans); TransAddWeight(frac, &blend->bones[i].t, &trans); TransEndLerp(&trans); TransCopy(&trans, &skel->bones[i].t); } // calculate a bounding box in the current coordinate system for (i = 0; i < 3; i++) { bounds[0][i] = skel->bounds[0][i] < blend->bounds[0][i] ? skel->bounds[0][i] : blend->bounds[0][i]; bounds[1][i] = skel->bounds[1][i] > blend->bounds[1][i] ? skel->bounds[1][i] : blend->bounds[1][i]; } VectorCopy(bounds[0], skel->bounds[0]); VectorCopy(bounds[1], skel->bounds[1]); return true; }