[quake3-commits] r2014 - trunk/code/renderer

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Sat Jun 11 11:16:26 EDT 2011


Author: thilo
Date: 2011-06-11 11:16:25 -0400 (Sat, 11 Jun 2011)
New Revision: 2014

Modified:
   trunk/code/renderer/tr_model_iqm.c
Log:
Fixes to IQM support, by Zack Middleton
 - Bug 5029 - IQM skin support for upper case surface names
 - Bug 5030 - IQM version 2 support
 - Bug 5031 - Animated IQMs cause segfault
 - Bug 5032 - IQM does not setup tag axis/origin correctly
 - Bug 5033 - IQM bounds swap and segfault issues


Modified: trunk/code/renderer/tr_model_iqm.c
===================================================================
--- trunk/code/renderer/tr_model_iqm.c	2011-06-06 21:15:42 UTC (rev 2013)
+++ trunk/code/renderer/tr_model_iqm.c	2011-06-11 15:16:25 UTC (rev 2014)
@@ -67,20 +67,17 @@
 	mat[10] = a[10] * unLerp + b[10] * lerp;
 	mat[11] = a[11] * unLerp + b[11] * lerp;
 }
-static void JointToMatrix( vec3_t rot, vec3_t scale, vec3_t trans,
+static void JointToMatrix( vec4_t rot, vec3_t scale, vec3_t trans,
 			   float *mat ) {
-	float rotLen = DotProduct(rot, rot);
-	float rotW = -SQRTFAST(1.0f - rotLen);
-
 	float xx = 2.0f * rot[0] * rot[0];
 	float yy = 2.0f * rot[1] * rot[1];
 	float zz = 2.0f * rot[2] * rot[2];
 	float xy = 2.0f * rot[0] * rot[1];
 	float xz = 2.0f * rot[0] * rot[2];
 	float yz = 2.0f * rot[1] * rot[2];
-	float wx = 2.0f * rotW * rot[0];
-	float wy = 2.0f * rotW * rot[1];
-	float wz = 2.0f * rotW * rot[2];
+	float wx = 2.0f * rot[3] * rot[0];
+	float wy = 2.0f * rot[3] * rot[1];
+	float wz = 2.0f * rot[3] * rot[2];
 
 	mat[ 0] = scale[0] * (1.0f - (yy + zz));
 	mat[ 1] = scale[0] * (xy - wz);
@@ -95,20 +92,17 @@
 	mat[10] = scale[2] * (1.0f - (xx + yy));
 	mat[11] = trans[2];
 }
-static void JointToMatrixInverse( vec3_t rot, vec3_t scale, vec3_t trans,
+static void JointToMatrixInverse( vec4_t rot, vec3_t scale, vec3_t trans,
 				  float *mat ) {
-	float rotLen = DotProduct(rot, rot);
-	float rotW = -SQRTFAST(1.0f - rotLen);
-
 	float xx = 2.0f * rot[0] * rot[0];
 	float yy = 2.0f * rot[1] * rot[1];
 	float zz = 2.0f * rot[2] * rot[2];
 	float xy = 2.0f * rot[0] * rot[1];
 	float xz = 2.0f * rot[0] * rot[2];
 	float yz = 2.0f * rot[1] * rot[2];
-	float wx = 2.0f * rotW * rot[0];
-	float wy = 2.0f * rotW * rot[1];
-	float wz = 2.0f * rotW * rot[2];
+	float wx = 2.0f * rot[3] * rot[0];
+	float wy = 2.0f * rot[3] * rot[1];
+	float wz = 2.0f * rot[3] * rot[2];
 
 	mat[ 0] = scale[0] * (1.0f - (yy + zz));
 	mat[ 1] = scale[0] * (xy + wz);
@@ -159,6 +153,8 @@
 
 	LL( header->version );
 	if( header->version != IQM_VERSION ) {
+		ri.Printf(PRINT_WARNING, "R_LoadIQM: %s is a unsupported IQM version (%d), only version %d is supported.\n",
+				mod_name, header->version, IQM_VERSION);
 		return qfalse;
 	}
 
@@ -355,6 +351,7 @@
 		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] );
@@ -390,6 +387,7 @@
 		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] );
@@ -399,25 +397,29 @@
 		LL( pose->channelscale[6] );
 		LL( pose->channelscale[7] );
 		LL( pose->channelscale[8] );
+		LL( pose->channelscale[9] );
 	}
 
-	// check and swap model bounds
-	if(IQM_CheckRange(header, header->ofs_bounds,
-			  header->num_frames, sizeof(*bounds)))
+	if (header->ofs_bounds)
 	{
-		return qfalse;
-	}
-	bounds = (iqmBounds_t *) ((byte *) header + header->ofs_bounds);
-	for(i = 0; i < header->num_poses; i++)
-	{
-		LL(bounds->bbmin[0]);
-		LL(bounds->bbmin[1]);
-		LL(bounds->bbmin[2]);
-		LL(bounds->bbmax[0]);
-		LL(bounds->bbmax[1]);
-		LL(bounds->bbmax[2]);
+		// check and swap model bounds
+		if(IQM_CheckRange(header, header->ofs_bounds,
+				  header->num_frames, sizeof(*bounds)))
+		{
+			return qfalse;
+		}
+		bounds = (iqmBounds_t *) ((byte *) header + header->ofs_bounds);
+		for(i = 0; i < header->num_frames; i++)
+		{
+			LL(bounds->bbmin[0]);
+			LL(bounds->bbmin[1]);
+			LL(bounds->bbmin[2]);
+			LL(bounds->bbmax[0]);
+			LL(bounds->bbmax[1]);
+			LL(bounds->bbmax[2]);
 
-		bounds++;
+			bounds++;
+		}
 	}
 
 	// allocate the model and copy the data
@@ -509,7 +511,9 @@
 	for( i = 0; i < header->num_frames; i++ ) {
 		pose = (iqmPose_t *)((byte *)header + header->ofs_poses);
 		for( j = 0; j < header->num_poses; j++, pose++ ) {
-			vec3_t	translate, rotate, scale;
+			vec3_t	translate;
+			vec4_t	rotate;
+			vec3_t	scale;
 			float	mat1[12], mat2[12];
 
 			translate[0] = pose->channeloffset[0];
@@ -521,6 +525,7 @@
 			translate[2] = pose->channeloffset[2];
 			if( pose->mask & 0x004)
 				translate[2] += *framedata++ * pose->channelscale[2];
+
 			rotate[0] = pose->channeloffset[3];
 			if( pose->mask & 0x008)
 				rotate[0] += *framedata++ * pose->channelscale[3];
@@ -530,15 +535,19 @@
 			rotate[2] = pose->channeloffset[5];
 			if( pose->mask & 0x020)
 				rotate[2] += *framedata++ * pose->channelscale[5];
-			scale[0] = pose->channeloffset[6];
+			rotate[3] = pose->channeloffset[6];
 			if( pose->mask & 0x040)
-				scale[0] += *framedata++ * pose->channelscale[6];
-			scale[1] = pose->channeloffset[7];
+				rotate[3] += *framedata++ * pose->channelscale[6];
+
+			scale[0] = pose->channeloffset[7];
 			if( pose->mask & 0x080)
-				scale[1] += *framedata++ * pose->channelscale[7];
-			scale[2] = pose->channeloffset[8];
+				scale[0] += *framedata++ * pose->channelscale[7];
+			scale[1] = pose->channeloffset[8];
 			if( pose->mask & 0x100)
-				scale[2] += *framedata++ * pose->channelscale[8];
+				scale[1] += *framedata++ * pose->channelscale[8];
+			scale[2] = pose->channeloffset[9];
+			if( pose->mask & 0x200)
+				scale[2] += *framedata++ * pose->channelscale[9];
 
 			// construct transformation matrix
 			JointToMatrix( rotate, scale, translate, mat1 );
@@ -563,6 +572,7 @@
 	for( i = 0; i < header->num_meshes; i++, mesh++, surface++ ) {
 		surface->surfaceType = SF_IQM;
 		Q_strncpyz(surface->name, str + mesh->name, sizeof (surface->name));
+		Q_strlwr(surface->name); // lowercase the surface name so skin compares are faster
 		surface->shader = R_FindShader( str + mesh->material, LIGHTMAP_NONE, qtrue );
 		if( surface->shader->defaultShader )
 			surface->shader = tr.defaultShader;
@@ -677,6 +687,11 @@
 	vec_t		*oldBounds, *newBounds;
 	int		i;
 
+	if (!data->bounds) {
+		tr.pc.c_box_cull_md3_clip++;
+		return CULL_CLIP;
+	}
+
 	// compute bounds pointers
 	oldBounds = data->bounds + 6*ent->e.oldframe;
 	newBounds = data->bounds + 6*ent->e.frame;
@@ -712,6 +727,7 @@
 	int			i, j;
 	fog_t			*fog;
 	vec_t			*bounds;
+	const vec_t		defaultBounds[6] = { -8, -8, -8, 8, 8, 8 };
 	vec3_t			diag, center;
 	vec3_t			localOrigin;
 	vec_t			radius;
@@ -721,7 +737,11 @@
 	}
 
 	// FIXME: non-normalized axis issues
-	bounds = data->bounds + 6*ent->e.frame;
+	if (data->bounds) {
+		bounds = data->bounds + 6*ent->e.frame;
+	} else {
+		bounds = defaultBounds;
+	}
 	VectorSubtract( bounds+3, bounds, diag );
 	VectorMA( bounds, 0.5f, diag, center );
 	VectorAdd( ent->e.origin, center, localOrigin );
@@ -879,7 +899,7 @@
 		mat1 = data->poseMats + 12 * data->num_joints * frame;
 		mat2 = data->poseMats + 12 * data->num_joints * oldframe;
 		
-		for( i = 0; i < 12 * data->num_joints; i++, joint++ ) {
+		for( i = 0; i < data->num_joints; i++, joint++ ) {
 			if( *joint >= 0 ) {
 				float tmpMat[12];
 				InterpolateMatrix( mat1 + 12*i, mat2 + 12*i,
@@ -1031,8 +1051,11 @@
 			break;
 		names += strlen( names ) + 1;
 	}
-	if( joint >= data->num_joints )
+	if( joint >= data->num_joints ) {
+		AxisClear( tag->axis );
+		VectorClear( tag->origin );
 		return qfalse;
+	}
 
 	ComputeJointMats( data, startFrame, endFrame, frac, jointMats );
 
@@ -1047,7 +1070,7 @@
 	tag->axis[0][2] = jointMats[12 * joint + 8];
 	tag->axis[1][2] = jointMats[12 * joint + 9];
 	tag->axis[2][2] = jointMats[12 * joint + 10];
-	tag->origin[0] = jointMats[12 * joint + 11];
+	tag->origin[2] = jointMats[12 * joint + 11];
 
-	return qfalse;
+	return qtrue;
 }



More information about the quake3-commits mailing list