コード例 #1
0
ファイル: tr_model_iqm.c プロジェクト: coltongit/spearmint
int R_IQMLerpTag( orientation_t *tag, iqmData_t *data,
		  int startTagIndex,
		  qhandle_t frameModel, int startFrame,
		  qhandle_t endFrameModel, int endFrame,
		  float frac, const char *tagName ) {
	iqmData_t	*startSkeleton, *endSkeleton;
	float	jointMats[IQM_MAX_JOINTS * 12];
	int	joint;
	char	*names = data->names;

	// get joint number by reading the joint names
	for( joint = 0; joint < data->num_joints; joint++ ) {
		if( joint >= startTagIndex && !strcmp( tagName, names ) )
			break;
		names += strlen( names ) + 1;
	}
	if( joint >= data->num_joints ) {
		return -1;
	}

	// just checking if tag exists
	if( !tag ) {
		return joint;
	}

	startSkeleton = R_GetIQMModelDataByHandle( frameModel, data );
	endSkeleton = R_GetIQMModelDataByHandle( endFrameModel, data );

	ComputeJointMats( data, startSkeleton, endSkeleton, startFrame, endFrame, frac, jointMats );

	tag->axis[0][0] = jointMats[12 * joint + 0];
	tag->axis[1][0] = jointMats[12 * joint + 1];
	tag->axis[2][0] = jointMats[12 * joint + 2];
	tag->origin[0] = jointMats[12 * joint + 3];
	tag->axis[0][1] = jointMats[12 * joint + 4];
	tag->axis[1][1] = jointMats[12 * joint + 5];
	tag->axis[2][1] = jointMats[12 * joint + 6];
	tag->origin[1] = jointMats[12 * joint + 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[2] = jointMats[12 * joint + 11];

	return joint;
}
コード例 #2
0
ファイル: tr_model_iqm.c プロジェクト: DaneTheory/spearmint
/*
=================
R_AddIQMSurfaces

Add all surfaces of this model
=================
*/
void R_AddIQMSurfaces( trRefEntity_t *ent ) {
	iqmData_t		*data;
	iqmData_t		*skeleton;
	iqmData_t		*oldSkeleton;
	srfIQModel_t		*surface;
	int			i, j;
	qboolean		personalModel;
	int			cull;
	int			fogNum;
	int         cubemapIndex;
	shader_t		*shader;
	skin_t			*skin;
	skinSurface_t	*skinSurf;

	data = tr.currentModel->modelData;
	surface = data->surfaces;

	if ( !data->num_surfaces || !data->num_triangles || !data->num_vertexes ) {
		ri.Printf( PRINT_WARNING, "WARNING: Tried to render IQM '%s' with no surfaces\n", tr.currentModel->name );
		return;
	}

	skeleton = R_GetIQMModelDataByHandle( ent->e.frameModel, data );
	oldSkeleton = R_GetIQMModelDataByHandle( ent->e.oldframeModel, data );

	// don't add mirror only objects if not in a mirror/portal
	personalModel = (ent->e.renderfx & RF_ONLY_MIRROR) && !tr.viewParms.isPortal;

	if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
		ent->e.frame %= skeleton->num_frames;
		ent->e.oldframe %= oldSkeleton->num_frames;
	}

	//
	// 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 ( (ent->e.frame >= skeleton->num_frames) 
	     || (ent->e.frame < 0)
	     || (ent->e.oldframe >= oldSkeleton->num_frames)
	     || (ent->e.oldframe < 0) ) {
		ri.Printf( PRINT_DEVELOPER, "R_AddIQMSurfaces: no such frame %d to %d for '%s'\n",
			   ent->e.oldframe, ent->e.frame,
			   tr.currentModel->name );
		ent->e.frame = 0;
		ent->e.oldframe = 0;
	}

	//
	// cull the entire model if merged bounding box of both frames
	// is outside the view frustum.
	//
	cull = R_CullIQM ( skeleton, oldSkeleton, ent );
	if ( cull == CULL_OUT ) {
		return;
	}

	//
	// set up lighting now that we know we aren't culled
	//
	if ( !personalModel || r_shadows->integer > 1 ) {
		R_SetupEntityLighting( &tr.refdef, ent );
	}

	//
	// see if we are in a fog volume
	//
	fogNum = R_ComputeIQMFogNum( skeleton, ent );

	cubemapIndex = R_CubemapForPoint(ent->e.origin);

	for ( i = 0 ; i < data->num_surfaces ; i++ ) {
		if(ent->e.customShader)
			shader = R_GetShaderByHandle( ent->e.customShader );
		else if(ent->e.customSkin > 0 && ent->e.customSkin <= tr.refdef.numSkins)
		{
			skin = &tr.refdef.skins[ent->e.customSkin - 1];
			shader = tr.defaultShader;

			for(j = 0 ; j < skin->numSurfaces ; j++)
			{
				skinSurf = &tr.skinSurfaces[ skin->surfaces[ j ] ];

				if (!strcmp(skinSurf->name, surface->name))
				{
					shader = skinSurf->shader;
					break;
				}
			}

			if (shader == tr.nodrawShader) {
				surface++;
				continue;
			}
		} else {
			shader = surface->shader;
		}

		// we will add shadows even if the main object isn't visible in the view

		// stencil shadows can't do personal models unless I polyhedron clip
		if ( !personalModel
			&& r_shadows->integer == 2 
			&& fogNum == 0
			&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) ) 
			&& shader->sort == SS_OPAQUE ) {
			R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, 0, 0, 0 );
		}

		// projection shadows work fine with personal models
		if ( r_shadows->integer == 3
			&& fogNum == 0
			&& (ent->e.renderfx & RF_SHADOW_PLANE )
			&& shader->sort == SS_OPAQUE ) {
			R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, 0, 0, 0 );
		}

		if( !personalModel ) {
			R_AddEntDrawSurf( ent, (void *)surface, shader, fogNum, 0, 0, cubemapIndex );
		}

		surface++;
	}
}
コード例 #3
0
ファイル: tr_model_iqm.c プロジェクト: DaneTheory/spearmint
/*
=================
RB_AddIQMSurfaces

Compute vertices for this model surface
=================
*/
void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
	srfIQModel_t	*surf = (srfIQModel_t *)surface;
	iqmData_t	*data = surf->data;
	float		jointMats[IQM_MAX_JOINTS * 12];
	int		i;

	vec4_t		*outXYZ;
	uint32_t	*outNormal;
#ifdef USE_VERT_TANGENT_SPACE
	uint32_t	*outTangent;
#endif
	vec2_t		(*outTexCoord)[2];
	vec4_t	*outColor;

	iqmData_t	*skeleton = R_GetIQMModelDataByHandle( backEnd.currentEntity->e.frameModel, data );
	iqmData_t	*oldSkeleton = R_GetIQMModelDataByHandle( backEnd.currentEntity->e.oldframeModel, data );

	int	frame = skeleton->num_frames ? backEnd.currentEntity->e.frame % skeleton->num_frames : 0;
	int	oldframe = oldSkeleton->num_frames ? backEnd.currentEntity->e.oldframe % oldSkeleton->num_frames : 0;
	float	backlerp = backEnd.currentEntity->e.backlerp;

	int		*tri;
	glIndex_t	*ptr;
	glIndex_t	base;

	if ( data != skeleton && data->num_joints != skeleton->num_poses ) {
		ri.Printf( PRINT_WARNING, "WARNING: frameModel '%s' for model '%s' has different number of joints\n",
				R_GetModelByHandle( backEnd.currentEntity->e.frameModel )->name, R_GetModelByHandle( backEnd.currentEntity->e.hModel )->name );
		skeleton = data;
	}

	if ( data != oldSkeleton && data->num_joints != oldSkeleton->num_poses ) {
		ri.Printf( PRINT_WARNING, "WARNING: oldframeModel '%s' for model '%s' has different number of joints\n",
				R_GetModelByHandle( backEnd.currentEntity->e.oldframeModel )->name, R_GetModelByHandle( backEnd.currentEntity->e.hModel )->name );
		oldSkeleton = data;
	}

	RB_CHECKOVERFLOW( surf->num_vertexes, surf->num_triangles * 3 );

	outXYZ = &tess.xyz[tess.numVertexes];
	outNormal = &tess.normal[tess.numVertexes];
#ifdef USE_VERT_TANGENT_SPACE
	outTangent = &tess.tangent[tess.numVertexes];
#endif
	outTexCoord = &tess.texCoords[tess.numVertexes];
	outColor = &tess.vertexColors[tess.numVertexes];

	// compute interpolated joint matrices
	if ( skeleton->num_poses > 0 ) {
		ComputePoseMats( data, skeleton, oldSkeleton, frame, oldframe, backlerp, jointMats );
	}

	// transform vertexes and fill other data
	for( i = 0; i < surf->num_vertexes;
	     i++, outXYZ++, outNormal++, outTexCoord++, outColor++ ) {
		int	j, k;
		float	vtxMat[12];
		float	nrmMat[9];
		int	vtx = i + surf->first_vertex;
		float	blendWeights[4];
		int		numWeights;

		for ( numWeights = 0; numWeights < 4; numWeights++ ) {
			if ( data->blendWeightsType == IQM_FLOAT )
				blendWeights[numWeights] = data->blendWeights.f[4*vtx + numWeights];
			else
				blendWeights[numWeights] = (float)data->blendWeights.b[4*vtx + numWeights] / 255.0f;

			if ( blendWeights[numWeights] <= 0 )
				break;
		}

		if ( skeleton->num_poses == 0 || numWeights == 0 ) {
			// no blend joint, use identity matrix.
			Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) );
		} else {
			// compute the vertex matrix by blending the up to
			// four blend weights
			Com_Memset( vtxMat, 0, 12 * sizeof (float) );
			for( j = 0; j < numWeights; j++ ) {
				for( k = 0; k < 12; k++ ) {
					vtxMat[k] += blendWeights[j] * jointMats[12*data->blendIndexes[4*vtx + j] + k];
				}
			}
		}

		// compute the normal matrix as transpose of the adjoint
		// of the vertex matrix
		nrmMat[ 0] = vtxMat[ 5]*vtxMat[10] - vtxMat[ 6]*vtxMat[ 9];
		nrmMat[ 1] = vtxMat[ 6]*vtxMat[ 8] - vtxMat[ 4]*vtxMat[10];
		nrmMat[ 2] = vtxMat[ 4]*vtxMat[ 9] - vtxMat[ 5]*vtxMat[ 8];
		nrmMat[ 3] = vtxMat[ 2]*vtxMat[ 9] - vtxMat[ 1]*vtxMat[10];
		nrmMat[ 4] = vtxMat[ 0]*vtxMat[10] - vtxMat[ 2]*vtxMat[ 8];
		nrmMat[ 5] = vtxMat[ 1]*vtxMat[ 8] - vtxMat[ 0]*vtxMat[ 9];
		nrmMat[ 6] = vtxMat[ 1]*vtxMat[ 6] - vtxMat[ 2]*vtxMat[ 5];
		nrmMat[ 7] = vtxMat[ 2]*vtxMat[ 4] - vtxMat[ 0]*vtxMat[ 6];
		nrmMat[ 8] = vtxMat[ 0]*vtxMat[ 5] - vtxMat[ 1]*vtxMat[ 4];

		(*outTexCoord)[0][0] = data->texcoords[2*vtx + 0];
		(*outTexCoord)[0][1] = data->texcoords[2*vtx + 1];
		(*outTexCoord)[1][0] = (*outTexCoord)[0][0];
		(*outTexCoord)[1][1] = (*outTexCoord)[0][1];

		(*outXYZ)[0] =
			vtxMat[ 0] * data->positions[3*vtx+0] +
			vtxMat[ 1] * data->positions[3*vtx+1] +
			vtxMat[ 2] * data->positions[3*vtx+2] +
			vtxMat[ 3];
		(*outXYZ)[1] =
			vtxMat[ 4] * data->positions[3*vtx+0] +
			vtxMat[ 5] * data->positions[3*vtx+1] +
			vtxMat[ 6] * data->positions[3*vtx+2] +
			vtxMat[ 7];
		(*outXYZ)[2] =
			vtxMat[ 8] * data->positions[3*vtx+0] +
			vtxMat[ 9] * data->positions[3*vtx+1] +
			vtxMat[10] * data->positions[3*vtx+2] +
			vtxMat[11];
		(*outXYZ)[3] = 1.0f;

		{
			vec3_t normal;
			vec4_t tangent;

			normal[0] = DotProduct(&nrmMat[0], &data->normals[3*vtx]);
			normal[1] = DotProduct(&nrmMat[3], &data->normals[3*vtx]);
			normal[2] = DotProduct(&nrmMat[6], &data->normals[3*vtx]);

			*outNormal = R_VboPackNormal(normal);

#ifdef USE_VERT_TANGENT_SPACE
			tangent[0] = DotProduct(&nrmMat[0], &data->tangents[4*vtx]);
			tangent[1] = DotProduct(&nrmMat[3], &data->tangents[4*vtx]);
			tangent[2] = DotProduct(&nrmMat[6], &data->tangents[4*vtx]);
			tangent[3] = data->tangents[4*vtx+3];

			*outTangent++ = R_VboPackTangent(tangent);
#endif
		}

		(*outColor)[0] = data->colors[4*vtx+0] / 255.0f;
		(*outColor)[1] = data->colors[4*vtx+1] / 255.0f;
		(*outColor)[2] = data->colors[4*vtx+2] / 255.0f;
		(*outColor)[3] = data->colors[4*vtx+3] / 255.0f;
	}

	tri = data->triangles + 3 * surf->first_triangle;
	ptr = &tess.indexes[tess.numIndexes];
	base = tess.numVertexes;

	for( i = 0; i < surf->num_triangles; i++ ) {
		*ptr++ = base + (*tri++ - surf->first_vertex);
		*ptr++ = base + (*tri++ - surf->first_vertex);
		*ptr++ = base + (*tri++ - surf->first_vertex);
	}

	tess.numIndexes += 3 * surf->num_triangles;
	tess.numVertexes += surf->num_vertexes;
}