#include "tr_local.h" /* All bones should be an identity orientation to display the mesh exactly as it is specified. For all other frames, the bones represent the transformation from the orientation of the bone in the base frame to the orientation in this frame. */ /* ============== R_AddAnimSurfaces ============== */ void R_AddAnimSurfaces( trRefEntity_t *ent ) { md4Header_t *header; md4Surface_t *surface; md4LOD_t *lod; shader_t *shader; int i; header = tr.currentModel->md4; lod = (md4LOD_t *)( (byte *)header + header->ofsLODs ); surface = (md4Surface_t *)( (byte *)lod + lod->ofsSurfaces ); for ( i = 0 ; i < lod->numSurfaces ; i++ ) { shader = R_GetShaderByHandle( surface->shaderIndex ); R_AddDrawSurf( (surfaceType_t *)surface, shader, 0 /*fogNum*/, qfalse ); surface = (md4Surface_t *)( (byte *)surface + surface->ofsEnd ); } } /* ============== RB_SurfaceAnim ============== */ void RB_SurfaceAnim( md4Surface_t *surface ) { int i, j, k; float frontlerp, backlerp; int *triangles; int indexes; int baseIndex, baseVertex; int numVerts; md4Vertex_t *v; md4Bone_t bones[MD4_MAX_BONES]; md4Bone_t *bonePtr, *bone; md4Header_t *header; md4Frame_t *frame; md4Frame_t *oldFrame; int frameSize; if ( backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) { backlerp = 0; frontlerp = 1; } else { backlerp = backEnd.currentEntity->e.backlerp; frontlerp = 1.0f - backlerp; } header = (md4Header_t *)((byte *)surface + surface->ofsHeader); frameSize = (int)( &((md4Frame_t *)0)->bones[ header->numBones ] ); frame = (md4Frame_t *)((byte *)header + header->ofsFrames + backEnd.currentEntity->e.frame * frameSize ); oldFrame = (md4Frame_t *)((byte *)header + header->ofsFrames + backEnd.currentEntity->e.oldframe * frameSize ); RB_CheckOverflow( surface->numVerts, surface->numTriangles * 3 ); triangles = (int *) ((byte *)surface + surface->ofsTriangles); indexes = surface->numTriangles * 3; baseIndex = tess.numIndexes; baseVertex = tess.numVertexes; for (j = 0 ; j < indexes ; j++) { tess.indexes[baseIndex + j] = baseIndex + triangles[j]; } tess.numIndexes += indexes; // // lerp all the needed bones // if ( !backlerp ) { // no lerping needed bonePtr = frame->bones; } else { bonePtr = bones; for ( i = 0 ; i < header->numBones*12 ; i++ ) { ((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i] + backlerp * ((float *)oldFrame->bones)[i]; } } // // deform the vertexes by the lerped bones // numVerts = surface->numVerts; v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts); for ( j = 0; j < numVerts; j++ ) { vec3_t tempVert, tempNormal; md4Weight_t *w; VectorClear( tempVert ); VectorClear( tempNormal ); w = v->weights; for ( k = 0 ; k < v->numWeights ; k++, w++ ) { bone = bonePtr + w->boneIndex; tempVert[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] ); tempVert[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] ); tempVert[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] ); tempNormal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal ); tempNormal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal ); tempNormal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal ); } tess.xyz[baseVertex + j][0] = tempVert[0]; tess.xyz[baseVertex + j][1] = tempVert[1]; tess.xyz[baseVertex + j][2] = tempVert[2]; tess.normal[baseVertex + j][0] = tempNormal[0]; tess.normal[baseVertex + j][1] = tempNormal[1]; tess.normal[baseVertex + j][2] = tempNormal[2]; tess.texCoords[baseVertex + j][0][0] = v->texCoords[0]; tess.texCoords[baseVertex + j][0][1] = v->texCoords[1]; v = (md4Vertex_t *)&v->weights[v->numWeights]; } tess.numVertexes += surface->numVerts; }