mirror of
https://github.com/DrBeef/ioq3quest.git
synced 2024-11-10 23:02:01 +00:00
Support IQMs with joints and no poses
This commit is contained in:
parent
e0a42885d9
commit
1515841b38
4 changed files with 84 additions and 32 deletions
|
@ -610,6 +610,7 @@ typedef struct {
|
||||||
int num_frames;
|
int num_frames;
|
||||||
int num_surfaces;
|
int num_surfaces;
|
||||||
int num_joints;
|
int num_joints;
|
||||||
|
int num_poses;
|
||||||
struct srfIQModel_s *surfaces;
|
struct srfIQModel_s *surfaces;
|
||||||
|
|
||||||
float *positions;
|
float *positions;
|
||||||
|
|
|
@ -25,6 +25,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#define LL(x) x=LittleLong(x)
|
#define LL(x) x=LittleLong(x)
|
||||||
|
|
||||||
|
// 3x4 identity matrix
|
||||||
|
static float identityMatrix[12] = {
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
0, 0, 1, 0
|
||||||
|
};
|
||||||
|
|
||||||
static qboolean IQM_CheckRange( iqmHeader_t *header, int offset,
|
static qboolean IQM_CheckRange( iqmHeader_t *header, int offset,
|
||||||
int count,int size ) {
|
int count,int size ) {
|
||||||
// return true if the range specified by offset, count and size
|
// return true if the range specified by offset, count and size
|
||||||
|
@ -343,7 +350,9 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( header->num_poses != header->num_joints ) {
|
if( header->num_poses != header->num_joints && header->num_poses != 0 ) {
|
||||||
|
ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has %d poses and %d joints, must have the same number or 0 poses\n",
|
||||||
|
mod_name, header->num_poses, header->num_joints );
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,7 +388,10 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
joint_names += strlen( (char *)header + header->ofs_text +
|
joint_names += strlen( (char *)header + header->ofs_text +
|
||||||
joint->name ) + 1;
|
joint->name ) + 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( header->num_poses )
|
||||||
|
{
|
||||||
// check and swap poses
|
// check and swap poses
|
||||||
if( IQM_CheckRange( header, header->ofs_poses,
|
if( IQM_CheckRange( header, header->ofs_poses,
|
||||||
header->num_poses, sizeof(iqmPose_t) ) ) {
|
header->num_poses, sizeof(iqmPose_t) ) ) {
|
||||||
|
@ -438,7 +450,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
size = sizeof(iqmData_t);
|
size = sizeof(iqmData_t);
|
||||||
size += header->num_meshes * sizeof( srfIQModel_t );
|
size += header->num_meshes * sizeof( srfIQModel_t );
|
||||||
size += header->num_joints * 12 * sizeof( float ); // joint mats
|
size += header->num_joints * 12 * sizeof( float ); // joint mats
|
||||||
size += header->num_joints * header->num_frames * 12 * sizeof( float ); // pose mats
|
size += header->num_poses * header->num_frames * 12 * sizeof( float ); // pose mats
|
||||||
if(header->ofs_bounds)
|
if(header->ofs_bounds)
|
||||||
size += header->num_frames * 6 * sizeof(float); // model bounds
|
size += header->num_frames * 6 * sizeof(float); // model bounds
|
||||||
size += header->num_vertexes * 3 * sizeof(float); // positions
|
size += header->num_vertexes * 3 * sizeof(float); // positions
|
||||||
|
@ -462,16 +474,17 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
iqmData->num_frames = header->num_frames;
|
iqmData->num_frames = header->num_frames;
|
||||||
iqmData->num_surfaces = header->num_meshes;
|
iqmData->num_surfaces = header->num_meshes;
|
||||||
iqmData->num_joints = header->num_joints;
|
iqmData->num_joints = header->num_joints;
|
||||||
|
iqmData->num_poses = header->num_poses;
|
||||||
iqmData->surfaces = (srfIQModel_t *)(iqmData + 1);
|
iqmData->surfaces = (srfIQModel_t *)(iqmData + 1);
|
||||||
iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces);
|
iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces);
|
||||||
iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints;
|
iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints;
|
||||||
if(header->ofs_bounds)
|
if(header->ofs_bounds)
|
||||||
{
|
{
|
||||||
iqmData->bounds = iqmData->poseMats + 12 * header->num_joints * header->num_frames;
|
iqmData->bounds = iqmData->poseMats + 12 * header->num_poses * header->num_frames;
|
||||||
iqmData->positions = iqmData->bounds + 6 * header->num_frames;
|
iqmData->positions = iqmData->bounds + 6 * header->num_frames;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
iqmData->positions = iqmData->poseMats + 12 * header->num_joints * header->num_frames;
|
iqmData->positions = iqmData->poseMats + 12 * header->num_poses * header->num_frames;
|
||||||
iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes;
|
iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes;
|
||||||
iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes;
|
iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes;
|
||||||
iqmData->tangents = iqmData->normals + 3 * header->num_vertexes;
|
iqmData->tangents = iqmData->normals + 3 * header->num_vertexes;
|
||||||
|
@ -483,7 +496,10 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
|
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
|
||||||
|
|
||||||
if ( header->num_joints == 0 )
|
if ( header->num_joints == 0 )
|
||||||
iqmData->jointMats = iqmData->poseMats = NULL;
|
iqmData->jointMats = NULL;
|
||||||
|
|
||||||
|
if ( header->num_poses == 0 )
|
||||||
|
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
|
||||||
|
@ -892,9 +908,21 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
|
||||||
int *joint = data->jointParents;
|
int *joint = data->jointParents;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if ( oldframe == frame ) {
|
if ( data->num_poses == 0 ) {
|
||||||
mat1 = data->poseMats + 12 * data->num_joints * frame;
|
|
||||||
for( i = 0; i < data->num_joints; i++, joint++ ) {
|
for( i = 0; i < data->num_joints; i++, joint++ ) {
|
||||||
|
if( *joint >= 0 ) {
|
||||||
|
Matrix34Multiply( mat + 12 * *joint,
|
||||||
|
identityMatrix, mat + 12*i );
|
||||||
|
} else {
|
||||||
|
Com_Memcpy( mat + 12*i, identityMatrix, 12 * sizeof(float) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( oldframe == frame ) {
|
||||||
|
mat1 = data->poseMats + 12 * data->num_poses * frame;
|
||||||
|
for( i = 0; i < data->num_poses; i++, joint++ ) {
|
||||||
if( *joint >= 0 ) {
|
if( *joint >= 0 ) {
|
||||||
Matrix34Multiply( mat + 12 * *joint,
|
Matrix34Multiply( mat + 12 * *joint,
|
||||||
mat1 + 12*i, mat + 12*i );
|
mat1 + 12*i, mat + 12*i );
|
||||||
|
@ -903,10 +931,10 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mat1 = data->poseMats + 12 * data->num_joints * frame;
|
mat1 = data->poseMats + 12 * data->num_poses * frame;
|
||||||
mat2 = data->poseMats + 12 * data->num_joints * oldframe;
|
mat2 = data->poseMats + 12 * data->num_poses * oldframe;
|
||||||
|
|
||||||
for( i = 0; i < data->num_joints; i++, joint++ ) {
|
for( i = 0; i < data->num_poses; i++, joint++ ) {
|
||||||
if( *joint >= 0 ) {
|
if( *joint >= 0 ) {
|
||||||
float tmpMat[12];
|
float tmpMat[12];
|
||||||
InterpolateMatrix( mat1 + 12*i, mat2 + 12*i,
|
InterpolateMatrix( mat1 + 12*i, mat2 + 12*i,
|
||||||
|
@ -974,7 +1002,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
|
||||||
outColor = &tess.vertexColors[tess.numVertexes];
|
outColor = &tess.vertexColors[tess.numVertexes];
|
||||||
|
|
||||||
// compute interpolated joint matrices
|
// compute interpolated joint matrices
|
||||||
if ( data->num_joints > 0 ) {
|
if ( data->num_poses > 0 ) {
|
||||||
ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
|
ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -986,12 +1014,9 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
|
||||||
float nrmMat[9];
|
float nrmMat[9];
|
||||||
int vtx = i + surf->first_vertex;
|
int vtx = i + surf->first_vertex;
|
||||||
|
|
||||||
if ( data->num_joints == 0 || data->blendWeights[4*vtx] <= 0 ) {
|
if ( data->num_poses == 0 || data->blendWeights[4*vtx] <= 0 ) {
|
||||||
// no blend joint, use identity matrix.
|
// no blend joint, use identity matrix.
|
||||||
for( j = 0; j < 3; j++ ) {
|
Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) );
|
||||||
for( k = 0; k < 4; k++ )
|
|
||||||
vtxMat[4*j+k] = ( k == j ) ? 1 : 0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// compute the vertex matrix by blending the up to
|
// compute the vertex matrix by blending the up to
|
||||||
// four blend weights
|
// four blend weights
|
||||||
|
|
|
@ -1086,6 +1086,7 @@ typedef struct {
|
||||||
int num_frames;
|
int num_frames;
|
||||||
int num_surfaces;
|
int num_surfaces;
|
||||||
int num_joints;
|
int num_joints;
|
||||||
|
int num_poses;
|
||||||
struct srfIQModel_s *surfaces;
|
struct srfIQModel_s *surfaces;
|
||||||
|
|
||||||
float *positions;
|
float *positions;
|
||||||
|
|
|
@ -25,6 +25,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#define LL(x) x=LittleLong(x)
|
#define LL(x) x=LittleLong(x)
|
||||||
|
|
||||||
|
// 3x4 identity matrix
|
||||||
|
static float identityMatrix[12] = {
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
0, 0, 1, 0
|
||||||
|
};
|
||||||
|
|
||||||
static qboolean IQM_CheckRange( iqmHeader_t *header, int offset,
|
static qboolean IQM_CheckRange( iqmHeader_t *header, int offset,
|
||||||
int count,int size ) {
|
int count,int size ) {
|
||||||
// return true if the range specified by offset, count and size
|
// return true if the range specified by offset, count and size
|
||||||
|
@ -343,7 +350,9 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( header->num_poses != header->num_joints ) {
|
if( header->num_poses != header->num_joints && header->num_poses != 0 ) {
|
||||||
|
ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has %d poses and %d joints, must have the same number or 0 poses\n",
|
||||||
|
mod_name, header->num_poses, header->num_joints );
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,7 +388,10 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
joint_names += strlen( (char *)header + header->ofs_text +
|
joint_names += strlen( (char *)header + header->ofs_text +
|
||||||
joint->name ) + 1;
|
joint->name ) + 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( header->num_poses )
|
||||||
|
{
|
||||||
// check and swap poses
|
// check and swap poses
|
||||||
if( IQM_CheckRange( header, header->ofs_poses,
|
if( IQM_CheckRange( header, header->ofs_poses,
|
||||||
header->num_poses, sizeof(iqmPose_t) ) ) {
|
header->num_poses, sizeof(iqmPose_t) ) ) {
|
||||||
|
@ -438,7 +450,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
size = sizeof(iqmData_t);
|
size = sizeof(iqmData_t);
|
||||||
size += header->num_meshes * sizeof( srfIQModel_t );
|
size += header->num_meshes * sizeof( srfIQModel_t );
|
||||||
size += header->num_joints * 12 * sizeof( float ); // joint mats
|
size += header->num_joints * 12 * sizeof( float ); // joint mats
|
||||||
size += header->num_joints * header->num_frames * 12 * sizeof( float ); // pose mats
|
size += header->num_poses * header->num_frames * 12 * sizeof( float ); // pose mats
|
||||||
if(header->ofs_bounds)
|
if(header->ofs_bounds)
|
||||||
size += header->num_frames * 6 * sizeof(float); // model bounds
|
size += header->num_frames * 6 * sizeof(float); // model bounds
|
||||||
size += header->num_vertexes * 3 * sizeof(float); // positions
|
size += header->num_vertexes * 3 * sizeof(float); // positions
|
||||||
|
@ -462,16 +474,17 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
iqmData->num_frames = header->num_frames;
|
iqmData->num_frames = header->num_frames;
|
||||||
iqmData->num_surfaces = header->num_meshes;
|
iqmData->num_surfaces = header->num_meshes;
|
||||||
iqmData->num_joints = header->num_joints;
|
iqmData->num_joints = header->num_joints;
|
||||||
|
iqmData->num_poses = header->num_poses;
|
||||||
iqmData->surfaces = (srfIQModel_t *)(iqmData + 1);
|
iqmData->surfaces = (srfIQModel_t *)(iqmData + 1);
|
||||||
iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces);
|
iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces);
|
||||||
iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints;
|
iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints;
|
||||||
if(header->ofs_bounds)
|
if(header->ofs_bounds)
|
||||||
{
|
{
|
||||||
iqmData->bounds = iqmData->poseMats + 12 * header->num_joints * header->num_frames;
|
iqmData->bounds = iqmData->poseMats + 12 * header->num_poses * header->num_frames;
|
||||||
iqmData->positions = iqmData->bounds + 6 * header->num_frames;
|
iqmData->positions = iqmData->bounds + 6 * header->num_frames;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
iqmData->positions = iqmData->poseMats + 12 * header->num_joints * header->num_frames;
|
iqmData->positions = iqmData->poseMats + 12 * header->num_poses * header->num_frames;
|
||||||
iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes;
|
iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes;
|
||||||
iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes;
|
iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes;
|
||||||
iqmData->tangents = iqmData->normals + 3 * header->num_vertexes;
|
iqmData->tangents = iqmData->normals + 3 * header->num_vertexes;
|
||||||
|
@ -483,7 +496,10 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
|
||||||
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
|
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
|
||||||
|
|
||||||
if ( header->num_joints == 0 )
|
if ( header->num_joints == 0 )
|
||||||
iqmData->jointMats = iqmData->poseMats = NULL;
|
iqmData->jointMats = NULL;
|
||||||
|
|
||||||
|
if ( header->num_poses == 0 )
|
||||||
|
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
|
||||||
|
@ -895,9 +911,21 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
|
||||||
int *joint = data->jointParents;
|
int *joint = data->jointParents;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if ( oldframe == frame ) {
|
if ( data->num_poses == 0 ) {
|
||||||
mat1 = data->poseMats + 12 * data->num_joints * frame;
|
|
||||||
for( i = 0; i < data->num_joints; i++, joint++ ) {
|
for( i = 0; i < data->num_joints; i++, joint++ ) {
|
||||||
|
if( *joint >= 0 ) {
|
||||||
|
Matrix34Multiply( mat + 12 * *joint,
|
||||||
|
identityMatrix, mat + 12*i );
|
||||||
|
} else {
|
||||||
|
Com_Memcpy( mat + 12*i, identityMatrix, 12 * sizeof(float) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( oldframe == frame ) {
|
||||||
|
mat1 = data->poseMats + 12 * data->num_poses * frame;
|
||||||
|
for( i = 0; i < data->num_poses; i++, joint++ ) {
|
||||||
if( *joint >= 0 ) {
|
if( *joint >= 0 ) {
|
||||||
Matrix34Multiply( mat + 12 * *joint,
|
Matrix34Multiply( mat + 12 * *joint,
|
||||||
mat1 + 12*i, mat + 12*i );
|
mat1 + 12*i, mat + 12*i );
|
||||||
|
@ -906,10 +934,10 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mat1 = data->poseMats + 12 * data->num_joints * frame;
|
mat1 = data->poseMats + 12 * data->num_poses * frame;
|
||||||
mat2 = data->poseMats + 12 * data->num_joints * oldframe;
|
mat2 = data->poseMats + 12 * data->num_poses * oldframe;
|
||||||
|
|
||||||
for( i = 0; i < data->num_joints; i++, joint++ ) {
|
for( i = 0; i < data->num_poses; i++, joint++ ) {
|
||||||
if( *joint >= 0 ) {
|
if( *joint >= 0 ) {
|
||||||
float tmpMat[12];
|
float tmpMat[12];
|
||||||
InterpolateMatrix( mat1 + 12*i, mat2 + 12*i,
|
InterpolateMatrix( mat1 + 12*i, mat2 + 12*i,
|
||||||
|
@ -977,7 +1005,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
|
||||||
outColor = &tess.vertexColors[tess.numVertexes];
|
outColor = &tess.vertexColors[tess.numVertexes];
|
||||||
|
|
||||||
// compute interpolated joint matrices
|
// compute interpolated joint matrices
|
||||||
if ( data->num_joints > 0 ) {
|
if ( data->num_poses > 0 ) {
|
||||||
ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
|
ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -989,12 +1017,9 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
|
||||||
float nrmMat[9];
|
float nrmMat[9];
|
||||||
int vtx = i + surf->first_vertex;
|
int vtx = i + surf->first_vertex;
|
||||||
|
|
||||||
if ( data->num_joints == 0 || data->blendWeights[4*vtx] <= 0 ) {
|
if ( data->num_poses == 0 || data->blendWeights[4*vtx] <= 0 ) {
|
||||||
// no blend joint, use identity matrix.
|
// no blend joint, use identity matrix.
|
||||||
for( j = 0; j < 3; j++ ) {
|
Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) );
|
||||||
for( k = 0; k < 4; k++ )
|
|
||||||
vtxMat[4*j+k] = ( k == j ) ? 1 : 0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// compute the vertex matrix by blending the up to
|
// compute the vertex matrix by blending the up to
|
||||||
// four blend weights
|
// four blend weights
|
||||||
|
|
Loading…
Reference in a new issue