mirror of
https://github.com/UberGames/ioef.git
synced 2025-01-31 13:00:46 +00:00
Fix loading and rendering IQMs with no joints
This commit is contained in:
parent
ecd50f01c2
commit
bf962c516d
2 changed files with 182 additions and 148 deletions
|
@ -334,68 +334,72 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check and swap joints
|
|
||||||
if( IQM_CheckRange( header, header->ofs_joints,
|
|
||||||
header->num_joints, sizeof(iqmJoint_t) ) ) {
|
|
||||||
return qfalse;
|
|
||||||
}
|
|
||||||
joint = (iqmJoint_t *)((byte *)header + header->ofs_joints);
|
|
||||||
joint_names = 0;
|
|
||||||
for( i = 0; i < header->num_joints; i++, joint++ ) {
|
|
||||||
LL( joint->name );
|
|
||||||
LL( joint->parent );
|
|
||||||
LL( joint->translate[0] );
|
|
||||||
LL( joint->translate[1] );
|
|
||||||
LL( joint->translate[2] );
|
|
||||||
LL( joint->rotate[0] );
|
|
||||||
LL( joint->rotate[1] );
|
|
||||||
LL( joint->rotate[2] );
|
|
||||||
LL( joint->rotate[3] );
|
|
||||||
LL( joint->scale[0] );
|
|
||||||
LL( joint->scale[1] );
|
|
||||||
LL( joint->scale[2] );
|
|
||||||
|
|
||||||
if( joint->parent < -1 ||
|
|
||||||
joint->parent >= (int)header->num_joints ||
|
|
||||||
joint->name >= (int)header->num_text ) {
|
|
||||||
return qfalse;
|
|
||||||
}
|
|
||||||
joint_names += strlen( (char *)header + header->ofs_text +
|
|
||||||
joint->name ) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check and swap poses
|
|
||||||
if( header->num_poses != header->num_joints ) {
|
if( header->num_poses != header->num_joints ) {
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
}
|
||||||
if( IQM_CheckRange( header, header->ofs_poses,
|
|
||||||
header->num_poses, sizeof(iqmPose_t) ) ) {
|
if ( header->num_joints )
|
||||||
return qfalse;
|
{
|
||||||
}
|
// check and swap joints
|
||||||
pose = (iqmPose_t *)((byte *)header + header->ofs_poses);
|
if( IQM_CheckRange( header, header->ofs_joints,
|
||||||
for( i = 0; i < header->num_poses; i++, pose++ ) {
|
header->num_joints, sizeof(iqmJoint_t) ) ) {
|
||||||
LL( pose->parent );
|
return qfalse;
|
||||||
LL( pose->mask );
|
}
|
||||||
LL( pose->channeloffset[0] );
|
joint = (iqmJoint_t *)((byte *)header + header->ofs_joints);
|
||||||
LL( pose->channeloffset[1] );
|
joint_names = 0;
|
||||||
LL( pose->channeloffset[2] );
|
for( i = 0; i < header->num_joints; i++, joint++ ) {
|
||||||
LL( pose->channeloffset[3] );
|
LL( joint->name );
|
||||||
LL( pose->channeloffset[4] );
|
LL( joint->parent );
|
||||||
LL( pose->channeloffset[5] );
|
LL( joint->translate[0] );
|
||||||
LL( pose->channeloffset[6] );
|
LL( joint->translate[1] );
|
||||||
LL( pose->channeloffset[7] );
|
LL( joint->translate[2] );
|
||||||
LL( pose->channeloffset[8] );
|
LL( joint->rotate[0] );
|
||||||
LL( pose->channeloffset[9] );
|
LL( joint->rotate[1] );
|
||||||
LL( pose->channelscale[0] );
|
LL( joint->rotate[2] );
|
||||||
LL( pose->channelscale[1] );
|
LL( joint->rotate[3] );
|
||||||
LL( pose->channelscale[2] );
|
LL( joint->scale[0] );
|
||||||
LL( pose->channelscale[3] );
|
LL( joint->scale[1] );
|
||||||
LL( pose->channelscale[4] );
|
LL( joint->scale[2] );
|
||||||
LL( pose->channelscale[5] );
|
|
||||||
LL( pose->channelscale[6] );
|
if( joint->parent < -1 ||
|
||||||
LL( pose->channelscale[7] );
|
joint->parent >= (int)header->num_joints ||
|
||||||
LL( pose->channelscale[8] );
|
joint->name >= (int)header->num_text ) {
|
||||||
LL( pose->channelscale[9] );
|
return qfalse;
|
||||||
|
}
|
||||||
|
joint_names += strlen( (char *)header + header->ofs_text +
|
||||||
|
joint->name ) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check and swap poses
|
||||||
|
if( IQM_CheckRange( header, header->ofs_poses,
|
||||||
|
header->num_poses, sizeof(iqmPose_t) ) ) {
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
pose = (iqmPose_t *)((byte *)header + header->ofs_poses);
|
||||||
|
for( i = 0; i < header->num_poses; i++, pose++ ) {
|
||||||
|
LL( pose->parent );
|
||||||
|
LL( pose->mask );
|
||||||
|
LL( pose->channeloffset[0] );
|
||||||
|
LL( pose->channeloffset[1] );
|
||||||
|
LL( pose->channeloffset[2] );
|
||||||
|
LL( pose->channeloffset[3] );
|
||||||
|
LL( pose->channeloffset[4] );
|
||||||
|
LL( pose->channeloffset[5] );
|
||||||
|
LL( pose->channeloffset[6] );
|
||||||
|
LL( pose->channeloffset[7] );
|
||||||
|
LL( pose->channeloffset[8] );
|
||||||
|
LL( pose->channeloffset[9] );
|
||||||
|
LL( pose->channelscale[0] );
|
||||||
|
LL( pose->channelscale[1] );
|
||||||
|
LL( pose->channelscale[2] );
|
||||||
|
LL( pose->channelscale[3] );
|
||||||
|
LL( pose->channelscale[4] );
|
||||||
|
LL( pose->channelscale[5] );
|
||||||
|
LL( pose->channelscale[6] );
|
||||||
|
LL( pose->channelscale[7] );
|
||||||
|
LL( pose->channelscale[8] );
|
||||||
|
LL( pose->channelscale[9] );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header->ofs_bounds)
|
if (header->ofs_bounds)
|
||||||
|
@ -468,6 +472,9 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
iqmData->triangles = iqmData->jointParents + header->num_joints;
|
iqmData->triangles = iqmData->jointParents + header->num_joints;
|
||||||
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
|
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
|
||||||
|
|
||||||
|
if ( header->num_joints == 0 )
|
||||||
|
iqmData->jointMats = iqmData->poseMats = NULL;
|
||||||
|
|
||||||
// calculate joint matrices and their inverses
|
// calculate joint matrices and their inverses
|
||||||
// joint inverses are needed only until the pose matrices are calculated
|
// joint inverses are needed only until the pose matrices are calculated
|
||||||
mat = iqmData->jointMats;
|
mat = iqmData->jointMats;
|
||||||
|
@ -941,8 +948,8 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
|
||||||
vec2_t (*outTexCoord)[2] = &tess.texCoords[tess.numVertexes];
|
vec2_t (*outTexCoord)[2] = &tess.texCoords[tess.numVertexes];
|
||||||
color4ub_t *outColor = &tess.vertexColors[tess.numVertexes];
|
color4ub_t *outColor = &tess.vertexColors[tess.numVertexes];
|
||||||
|
|
||||||
int frame = backEnd.currentEntity->e.frame % data->num_frames;
|
int frame = data->num_frames ? backEnd.currentEntity->e.frame % data->num_frames : 0;
|
||||||
int oldframe = backEnd.currentEntity->e.oldframe % data->num_frames;
|
int oldframe = data->num_frames ? backEnd.currentEntity->e.oldframe % data->num_frames : 0;
|
||||||
float backlerp = backEnd.currentEntity->e.backlerp;
|
float backlerp = backEnd.currentEntity->e.backlerp;
|
||||||
|
|
||||||
int *tri;
|
int *tri;
|
||||||
|
@ -952,7 +959,9 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
|
||||||
RB_CHECKOVERFLOW( surf->num_vertexes, surf->num_triangles * 3 );
|
RB_CHECKOVERFLOW( surf->num_vertexes, surf->num_triangles * 3 );
|
||||||
|
|
||||||
// compute interpolated joint matrices
|
// compute interpolated joint matrices
|
||||||
ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
|
if ( data->num_joints > 0 ) {
|
||||||
|
ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
|
||||||
|
}
|
||||||
|
|
||||||
// transform vertexes and fill other data
|
// transform vertexes and fill other data
|
||||||
for( i = 0; i < surf->num_vertexes;
|
for( i = 0; i < surf->num_vertexes;
|
||||||
|
@ -962,20 +971,28 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
|
||||||
float nrmMat[9];
|
float nrmMat[9];
|
||||||
int vtx = i + surf->first_vertex;
|
int vtx = i + surf->first_vertex;
|
||||||
|
|
||||||
// compute the vertex matrix by blending the up to
|
if ( data->num_joints == 0 || data->blendWeights[4*vtx] <= 0 ) {
|
||||||
// four blend weights
|
// no blend joint, use identity matrix.
|
||||||
for( k = 0; k < 12; k++ )
|
for( j = 0; j < 3; j++ ) {
|
||||||
vtxMat[k] = data->blendWeights[4*vtx]
|
for( k = 0; k < 4; k++ )
|
||||||
* jointMats[12*data->blendIndexes[4*vtx] + k];
|
vtxMat[4*j+k] = ( k == j ) ? 1 : 0;
|
||||||
for( j = 1; j < 4; j++ ) {
|
}
|
||||||
if( data->blendWeights[4*vtx + j] <= 0 )
|
} else {
|
||||||
break;
|
// compute the vertex matrix by blending the up to
|
||||||
|
// four blend weights
|
||||||
for( k = 0; k < 12; k++ )
|
for( k = 0; k < 12; k++ )
|
||||||
vtxMat[k] += data->blendWeights[4*vtx + j]
|
vtxMat[k] = data->blendWeights[4*vtx]
|
||||||
* jointMats[12*data->blendIndexes[4*vtx + j] + k];
|
* jointMats[12*data->blendIndexes[4*vtx] + k];
|
||||||
|
for( j = 1; j < 4; j++ ) {
|
||||||
|
if( data->blendWeights[4*vtx + j] <= 0 )
|
||||||
|
break;
|
||||||
|
for( k = 0; k < 12; k++ )
|
||||||
|
vtxMat[k] += data->blendWeights[4*vtx + j]
|
||||||
|
* jointMats[12*data->blendIndexes[4*vtx + j] + k];
|
||||||
|
}
|
||||||
|
for( k = 0; k < 12; k++ )
|
||||||
|
vtxMat[k] *= 1.0f / 255.0f;
|
||||||
}
|
}
|
||||||
for( k = 0; k < 12; k++ )
|
|
||||||
vtxMat[k] *= 1.0f / 255.0f;
|
|
||||||
|
|
||||||
// compute the normal matrix as transpose of the adjoint
|
// compute the normal matrix as transpose of the adjoint
|
||||||
// of the vertex matrix
|
// of the vertex matrix
|
||||||
|
|
|
@ -334,68 +334,72 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check and swap joints
|
|
||||||
if( IQM_CheckRange( header, header->ofs_joints,
|
|
||||||
header->num_joints, sizeof(iqmJoint_t) ) ) {
|
|
||||||
return qfalse;
|
|
||||||
}
|
|
||||||
joint = (iqmJoint_t *)((byte *)header + header->ofs_joints);
|
|
||||||
joint_names = 0;
|
|
||||||
for( i = 0; i < header->num_joints; i++, joint++ ) {
|
|
||||||
LL( joint->name );
|
|
||||||
LL( joint->parent );
|
|
||||||
LL( joint->translate[0] );
|
|
||||||
LL( joint->translate[1] );
|
|
||||||
LL( joint->translate[2] );
|
|
||||||
LL( joint->rotate[0] );
|
|
||||||
LL( joint->rotate[1] );
|
|
||||||
LL( joint->rotate[2] );
|
|
||||||
LL( joint->rotate[3] );
|
|
||||||
LL( joint->scale[0] );
|
|
||||||
LL( joint->scale[1] );
|
|
||||||
LL( joint->scale[2] );
|
|
||||||
|
|
||||||
if( joint->parent < -1 ||
|
|
||||||
joint->parent >= (int)header->num_joints ||
|
|
||||||
joint->name >= (int)header->num_text ) {
|
|
||||||
return qfalse;
|
|
||||||
}
|
|
||||||
joint_names += strlen( (char *)header + header->ofs_text +
|
|
||||||
joint->name ) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check and swap poses
|
|
||||||
if( header->num_poses != header->num_joints ) {
|
if( header->num_poses != header->num_joints ) {
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
}
|
||||||
if( IQM_CheckRange( header, header->ofs_poses,
|
|
||||||
header->num_poses, sizeof(iqmPose_t) ) ) {
|
if ( header->num_joints )
|
||||||
return qfalse;
|
{
|
||||||
}
|
// check and swap joints
|
||||||
pose = (iqmPose_t *)((byte *)header + header->ofs_poses);
|
if( IQM_CheckRange( header, header->ofs_joints,
|
||||||
for( i = 0; i < header->num_poses; i++, pose++ ) {
|
header->num_joints, sizeof(iqmJoint_t) ) ) {
|
||||||
LL( pose->parent );
|
return qfalse;
|
||||||
LL( pose->mask );
|
}
|
||||||
LL( pose->channeloffset[0] );
|
joint = (iqmJoint_t *)((byte *)header + header->ofs_joints);
|
||||||
LL( pose->channeloffset[1] );
|
joint_names = 0;
|
||||||
LL( pose->channeloffset[2] );
|
for( i = 0; i < header->num_joints; i++, joint++ ) {
|
||||||
LL( pose->channeloffset[3] );
|
LL( joint->name );
|
||||||
LL( pose->channeloffset[4] );
|
LL( joint->parent );
|
||||||
LL( pose->channeloffset[5] );
|
LL( joint->translate[0] );
|
||||||
LL( pose->channeloffset[6] );
|
LL( joint->translate[1] );
|
||||||
LL( pose->channeloffset[7] );
|
LL( joint->translate[2] );
|
||||||
LL( pose->channeloffset[8] );
|
LL( joint->rotate[0] );
|
||||||
LL( pose->channeloffset[9] );
|
LL( joint->rotate[1] );
|
||||||
LL( pose->channelscale[0] );
|
LL( joint->rotate[2] );
|
||||||
LL( pose->channelscale[1] );
|
LL( joint->rotate[3] );
|
||||||
LL( pose->channelscale[2] );
|
LL( joint->scale[0] );
|
||||||
LL( pose->channelscale[3] );
|
LL( joint->scale[1] );
|
||||||
LL( pose->channelscale[4] );
|
LL( joint->scale[2] );
|
||||||
LL( pose->channelscale[5] );
|
|
||||||
LL( pose->channelscale[6] );
|
if( joint->parent < -1 ||
|
||||||
LL( pose->channelscale[7] );
|
joint->parent >= (int)header->num_joints ||
|
||||||
LL( pose->channelscale[8] );
|
joint->name >= (int)header->num_text ) {
|
||||||
LL( pose->channelscale[9] );
|
return qfalse;
|
||||||
|
}
|
||||||
|
joint_names += strlen( (char *)header + header->ofs_text +
|
||||||
|
joint->name ) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check and swap poses
|
||||||
|
if( IQM_CheckRange( header, header->ofs_poses,
|
||||||
|
header->num_poses, sizeof(iqmPose_t) ) ) {
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
pose = (iqmPose_t *)((byte *)header + header->ofs_poses);
|
||||||
|
for( i = 0; i < header->num_poses; i++, pose++ ) {
|
||||||
|
LL( pose->parent );
|
||||||
|
LL( pose->mask );
|
||||||
|
LL( pose->channeloffset[0] );
|
||||||
|
LL( pose->channeloffset[1] );
|
||||||
|
LL( pose->channeloffset[2] );
|
||||||
|
LL( pose->channeloffset[3] );
|
||||||
|
LL( pose->channeloffset[4] );
|
||||||
|
LL( pose->channeloffset[5] );
|
||||||
|
LL( pose->channeloffset[6] );
|
||||||
|
LL( pose->channeloffset[7] );
|
||||||
|
LL( pose->channeloffset[8] );
|
||||||
|
LL( pose->channeloffset[9] );
|
||||||
|
LL( pose->channelscale[0] );
|
||||||
|
LL( pose->channelscale[1] );
|
||||||
|
LL( pose->channelscale[2] );
|
||||||
|
LL( pose->channelscale[3] );
|
||||||
|
LL( pose->channelscale[4] );
|
||||||
|
LL( pose->channelscale[5] );
|
||||||
|
LL( pose->channelscale[6] );
|
||||||
|
LL( pose->channelscale[7] );
|
||||||
|
LL( pose->channelscale[8] );
|
||||||
|
LL( pose->channelscale[9] );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header->ofs_bounds)
|
if (header->ofs_bounds)
|
||||||
|
@ -468,6 +472,9 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
iqmData->triangles = iqmData->jointParents + header->num_joints;
|
iqmData->triangles = iqmData->jointParents + header->num_joints;
|
||||||
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
|
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
|
||||||
|
|
||||||
|
if ( header->num_joints == 0 )
|
||||||
|
iqmData->jointMats = iqmData->poseMats = NULL;
|
||||||
|
|
||||||
// calculate joint matrices and their inverses
|
// calculate joint matrices and their inverses
|
||||||
// joint inverses are needed only until the pose matrices are calculated
|
// joint inverses are needed only until the pose matrices are calculated
|
||||||
mat = iqmData->jointMats;
|
mat = iqmData->jointMats;
|
||||||
|
@ -941,8 +948,8 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
|
||||||
vec2_t (*outTexCoord)[2] = &tess.texCoords[tess.numVertexes];
|
vec2_t (*outTexCoord)[2] = &tess.texCoords[tess.numVertexes];
|
||||||
vec4_t *outColor = &tess.vertexColors[tess.numVertexes];
|
vec4_t *outColor = &tess.vertexColors[tess.numVertexes];
|
||||||
|
|
||||||
int frame = backEnd.currentEntity->e.frame % data->num_frames;
|
int frame = data->num_frames ? backEnd.currentEntity->e.frame % data->num_frames : 0;
|
||||||
int oldframe = backEnd.currentEntity->e.oldframe % data->num_frames;
|
int oldframe = data->num_frames ? backEnd.currentEntity->e.oldframe % data->num_frames : 0;
|
||||||
float backlerp = backEnd.currentEntity->e.backlerp;
|
float backlerp = backEnd.currentEntity->e.backlerp;
|
||||||
|
|
||||||
int *tri;
|
int *tri;
|
||||||
|
@ -952,7 +959,9 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
|
||||||
RB_CHECKOVERFLOW( surf->num_vertexes, surf->num_triangles * 3 );
|
RB_CHECKOVERFLOW( surf->num_vertexes, surf->num_triangles * 3 );
|
||||||
|
|
||||||
// compute interpolated joint matrices
|
// compute interpolated joint matrices
|
||||||
ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
|
if ( data->num_joints > 0 ) {
|
||||||
|
ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
|
||||||
|
}
|
||||||
|
|
||||||
// transform vertexes and fill other data
|
// transform vertexes and fill other data
|
||||||
for( i = 0; i < surf->num_vertexes;
|
for( i = 0; i < surf->num_vertexes;
|
||||||
|
@ -962,20 +971,28 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
|
||||||
float nrmMat[9];
|
float nrmMat[9];
|
||||||
int vtx = i + surf->first_vertex;
|
int vtx = i + surf->first_vertex;
|
||||||
|
|
||||||
// compute the vertex matrix by blending the up to
|
if ( data->num_joints == 0 || data->blendWeights[4*vtx] <= 0 ) {
|
||||||
// four blend weights
|
// no blend joint, use identity matrix.
|
||||||
for( k = 0; k < 12; k++ )
|
for( j = 0; j < 3; j++ ) {
|
||||||
vtxMat[k] = data->blendWeights[4*vtx]
|
for( k = 0; k < 4; k++ )
|
||||||
* jointMats[12*data->blendIndexes[4*vtx] + k];
|
vtxMat[4*j+k] = ( k == j ) ? 1 : 0;
|
||||||
for( j = 1; j < 4; j++ ) {
|
}
|
||||||
if( data->blendWeights[4*vtx + j] <= 0 )
|
} else {
|
||||||
break;
|
// compute the vertex matrix by blending the up to
|
||||||
|
// four blend weights
|
||||||
for( k = 0; k < 12; k++ )
|
for( k = 0; k < 12; k++ )
|
||||||
vtxMat[k] += data->blendWeights[4*vtx + j]
|
vtxMat[k] = data->blendWeights[4*vtx]
|
||||||
* jointMats[12*data->blendIndexes[4*vtx + j] + k];
|
* jointMats[12*data->blendIndexes[4*vtx] + k];
|
||||||
|
for( j = 1; j < 4; j++ ) {
|
||||||
|
if( data->blendWeights[4*vtx + j] <= 0 )
|
||||||
|
break;
|
||||||
|
for( k = 0; k < 12; k++ )
|
||||||
|
vtxMat[k] += data->blendWeights[4*vtx + j]
|
||||||
|
* jointMats[12*data->blendIndexes[4*vtx + j] + k];
|
||||||
|
}
|
||||||
|
for( k = 0; k < 12; k++ )
|
||||||
|
vtxMat[k] *= 1.0f / 255.0f;
|
||||||
}
|
}
|
||||||
for( k = 0; k < 12; k++ )
|
|
||||||
vtxMat[k] *= 1.0f / 255.0f;
|
|
||||||
|
|
||||||
// compute the normal matrix as transpose of the adjoint
|
// compute the normal matrix as transpose of the adjoint
|
||||||
// of the vertex matrix
|
// of the vertex matrix
|
||||||
|
|
Loading…
Reference in a new issue