예제 #1
0
파일: tr_backend.c 프로젝트: entdark/q3mme
/*
=============
RB_StretchPic
=============
*/
static void RB_StretchPic ( const void *data ) {
	const stretchPicCommand_t	*cmd;
	shader_t *shader;
	int *indexes;
	vec2_t *texCoords;
	vecSimd_t *xyz;
	color4ub_t *colors;

	cmd = (const stretchPicCommand_t *)data;

	if ( !backEnd.projection2D ) {
		RB_SetGL2D();
	}

	shader = cmd->shader;
	if ( shader != tess.shader ) {
		RB_EndSurface();
		RB_BeginSurface( shader, 0 );
	}

	RB_CheckOverflow( 4, 6 );

	indexes = tess.indexes + tess.numIndexes;
	indexes[0] = tess.numVertexes + 3;
	indexes[1] = tess.numVertexes + 0;
	indexes[2] = tess.numVertexes + 2;
	indexes[3] = tess.numVertexes + 2;
	indexes[4] = tess.numVertexes + 0;
	indexes[5] = tess.numVertexes + 1;

	colors = tess.colors + tess.numVertexes;
	Byte4Copy( backEnd.color2D, colors[0] );
	Byte4Copy( backEnd.color2D, colors[1] );
	Byte4Copy( backEnd.color2D, colors[2] );
	Byte4Copy( backEnd.color2D, colors[3] );

	xyz = tess.xyz + tess.numVertexes;
	VectorSet( xyz[0], cmd->x, cmd->y, 0 );
	VectorSet( xyz[1], cmd->x + cmd->w, cmd->y, 0 );
	VectorSet( xyz[2], cmd->x + cmd->w, cmd->y + cmd->h, 0 );
	VectorSet( xyz[3], cmd->x, cmd->y + cmd->h, 0 );

	texCoords = tess.texCoords + tess.numVertexes;

	texCoords[0][0] = cmd->s1;
	texCoords[0][1] = cmd->t1;
	texCoords[1][0] = cmd->s2;
	texCoords[1][1] = cmd->t1;
	texCoords[2][0] = cmd->s2;
	texCoords[2][1] = cmd->t2;
	texCoords[3][0] = cmd->s1;
	texCoords[3][1] = cmd->t2;

	tess.numVertexes += 4;
	tess.numIndexes += 6;

}
예제 #2
0
파일: animation.c 프로젝트: icanhas/yantar
/*
 * 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 = (size_t)(&((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;
	/* FIXME
	 * This makes TFC's skeletons work.  Shouldn't be necessary anymore, but left
	 * in for reference.
	 * v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts + 12); */
	v = (md4Vertex_t*)((byte*)surface + surface->ofsVerts);
	for(j = 0; j < numVerts; j++){
		Vec3 tempVert, tempNormal;
		md4Weight_t *w;

		clearv3(tempVert);
		clearv3(tempNormal);
		w = v->weights;
		for(k = 0; k < v->numWeights; k++, w++){
			bone = bonePtr + w->boneIndex;

			tempVert[0] += w->boneWeight *
				       (dotv3(bone->matrix[0], w->offset) + bone->matrix[0][3]);
			tempVert[1] += w->boneWeight *
				       (dotv3(bone->matrix[1], w->offset) + bone->matrix[1][3]);
			tempVert[2] += w->boneWeight *
				       (dotv3(bone->matrix[2], w->offset) + bone->matrix[2][3]);

			tempNormal[0]	+= w->boneWeight * dotv3(bone->matrix[0], v->normal);
			tempNormal[1]	+= w->boneWeight * dotv3(bone->matrix[1], v->normal);
			tempNormal[2]	+= w->boneWeight * dotv3(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];

		/* FIXME
		 * This makes TFC's skeletons work.  Shouldn't be necessary anymore, but left
		 * in for reference.
		 * v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 ); */
		v = (md4Vertex_t*)&v->weights[v->numWeights];
	}

	tess.numVertexes += surface->numVerts;
}
예제 #3
0
파일: tr_animation.c 프로젝트: Razish/QtZ
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;
	size_t			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 = offsetof( md4Frame_t, 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;
	// FIXME
	// This makes TFC's skeletons work.  Shouldn't be necessary anymore, but left
	// in for reference.
	//v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts + 12);
	v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts);
	for ( j = 0; j < numVerts; j++ ) {
		vector3	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.x += w->boneWeight * ( DotProduct( (vector3 *)&bone->matrix[0], &w->offset ) + bone->matrix[0][3] );
			tempVert.y += w->boneWeight * ( DotProduct( (vector3 *)&bone->matrix[1], &w->offset ) + bone->matrix[1][3] );
			tempVert.z += w->boneWeight * ( DotProduct( (vector3 *)&bone->matrix[2], &w->offset ) + bone->matrix[2][3] );

			tempNormal.x += w->boneWeight * DotProduct( (vector3 *)&bone->matrix[0], &v->normal );
			tempNormal.y += w->boneWeight * DotProduct( (vector3 *)&bone->matrix[1], &v->normal );
			tempNormal.z += w->boneWeight * DotProduct( (vector3 *)&bone->matrix[2], &v->normal );
		}

		tess.xyz[baseVertex + j].x = tempVert.x;
		tess.xyz[baseVertex + j].y = tempVert.y;
		tess.xyz[baseVertex + j].z = tempVert.z;

		tess.normal[baseVertex + j].x = tempNormal.x;
		tess.normal[baseVertex + j].y = tempNormal.y;
		tess.normal[baseVertex + j].z = tempNormal.z;

		tess.texCoords[baseVertex + j][0].x = v->texCoords.x;
		tess.texCoords[baseVertex + j][0].y = v->texCoords.y;

		// FIXME
		// This makes TFC's skeletons work.  Shouldn't be necessary anymore, but left
		// in for reference.
		//v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 );
		v = (md4Vertex_t *)&v->weights[v->numWeights];
	}

	tess.numVertexes += surface->numVerts;
}
예제 #4
0
파일: tr_animation.c 프로젝트: Razish/QtZ
void RB_MDRSurfaceAnim( md4Surface_t *surface ) {
	int				i, j, k;
	float			frontlerp, backlerp;
	int				*triangles;
	int				indexes;
	int				baseIndex, baseVertex;
	int				numVerts;
	mdrVertex_t		*v;
	mdrHeader_t		*header;
	mdrFrame_t		*frame;
	mdrFrame_t		*oldFrame;
	mdrBone_t		bones[MD4_MAX_BONES], *bonePtr, *bone;

	int			frameSize;

	// don't lerp if lerping off, or this is the only frame, or the last frame...
	//
	if (backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame) 
	{
		backlerp	= 0;	// if backlerp is 0, lerping is off and frontlerp is never used
		frontlerp	= 1;
	} 
	else  
	{
		backlerp	= backEnd.currentEntity->e.backlerp;
		frontlerp	= 1.0f - backlerp;
	}

	header = (mdrHeader_t *)((byte *)surface + surface->ofsHeader);

	frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );

	frame = (mdrFrame_t *)((byte *)header + header->ofsFrames +
		backEnd.currentEntity->e.frame * frameSize );
	oldFrame = (mdrFrame_t *)((byte *)header + header->ofsFrames +
		backEnd.currentEntity->e.oldframe * frameSize );

	RB_CheckOverflow( surface->numVerts, surface->numTriangles );

	triangles	= (int *) ((byte *)surface + surface->ofsTriangles);
	indexes		= surface->numTriangles * 3;
	baseIndex	= tess.numIndexes;
	baseVertex	= tess.numVertexes;
	
	// Set up all triangles.
	for (j = 0 ; j < indexes ; j++) 
	{
		tess.indexes[baseIndex + j] = baseVertex + 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 = (mdrVertex_t *) ((byte *)surface + surface->ofsVerts);
	for ( j = 0; j < numVerts; j++ ) 
	{
		vector3	tempVert, tempNormal;
		mdrWeight_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 = (mdrVertex_t *)&v->weights[v->numWeights];
	}

	tess.numVertexes += surface->numVerts;
}
예제 #5
0
/*
==============
R_CalcBones

    The list of bones[] should only be built and modified from within here
==============
*/
void R_CalcBones(mdsHeader_t *header, const refEntity_t *refent, int *boneList, int numBones)
{
	int   i;
	int   *boneRefs;
	float torsoWeight;

	// if the entity has changed since the last time the bones were built, reset them
	if (memcmp(&lastBoneEntity, refent, sizeof(refEntity_t)))
	{
		// different, cached bones are not valid
		memset(validBones, 0, header->numBones);
		lastBoneEntity = *refent;

		// (SA) also reset these counter statics
		//----(SA)	print stats for the complete model (not per-surface)
		if (r_bonesDebug->integer == 4 && totalrt)
		{
			Ren_Print("Lod %.2f  verts %4d/%4d  tris %4d/%4d  (%.2f%%)\n",
			          lodScale,
			          totalrv,
			          totalv,
			          totalrt,
			          totalt,
			          ( float )(100.0 * totalrt) / (float) totalt);
		}
		totalrv = totalrt = totalv = totalt = 0;
	}

	memset(newBones, 0, header->numBones);

	if (refent->oldframe == refent->frame)
	{
		backlerp  = 0;
		frontlerp = 1;
	}
	else
	{
		backlerp  = refent->backlerp;
		frontlerp = 1.0f - backlerp;
	}

	if (refent->oldTorsoFrame == refent->torsoFrame)
	{
		torsoBacklerp  = 0;
		torsoFrontlerp = 1;
	}
	else
	{
		torsoBacklerp  = refent->torsoBacklerp;
		torsoFrontlerp = 1.0f - torsoBacklerp;
	}

	frameSize = (int) (sizeof(mdsFrame_t) + (header->numBones - 1) * sizeof(mdsBoneFrameCompressed_t));

	frame = ( mdsFrame_t * )((byte *)header + header->ofsFrames +
	                         refent->frame * frameSize);
	torsoFrame = ( mdsFrame_t * )((byte *)header + header->ofsFrames +
	                              refent->torsoFrame * frameSize);
	oldFrame = ( mdsFrame_t * )((byte *)header + header->ofsFrames +
	                            refent->oldframe * frameSize);
	oldTorsoFrame = ( mdsFrame_t * )((byte *)header + header->ofsFrames +
	                                 refent->oldTorsoFrame * frameSize);

	// lerp all the needed bones (torsoParent is always the first bone in the list)
	cBoneList      = frame->bones;
	cBoneListTorso = torsoFrame->bones;

	boneInfo = ( mdsBoneInfo_t * )((byte *)header + header->ofsBones);
	boneRefs = boneList;
	//
	Matrix3Transpose(refent->torsoAxis, torsoAxis);

#ifdef HIGH_PRECISION_BONES
	if (qtrue)
	{
#else
	if (!backlerp && !torsoBacklerp)
	{
#endif
		for (i = 0; i < numBones; i++, boneRefs++)
		{
			if (validBones[*boneRefs])
			{
				// this bone is still in the cache
				bones[*boneRefs] = rawBones[*boneRefs];
				continue;
			}

			// find our parent, and make sure it has been calculated
			if ((boneInfo[*boneRefs].parent >= 0) && (!validBones[boneInfo[*boneRefs].parent] && !newBones[boneInfo[*boneRefs].parent]))
			{
				R_CalcBone(header, refent, boneInfo[*boneRefs].parent);
			}

			R_CalcBone(header, refent, *boneRefs);
		}
	}
	else        // interpolated
	{
		cOldBoneList      = oldFrame->bones;
		cOldBoneListTorso = oldTorsoFrame->bones;

		for (i = 0; i < numBones; i++, boneRefs++)
		{
			if (validBones[*boneRefs])
			{
				// this bone is still in the cache
				bones[*boneRefs] = rawBones[*boneRefs];
				continue;
			}

			// find our parent, and make sure it has been calculated
			if ((boneInfo[*boneRefs].parent >= 0) && (!validBones[boneInfo[*boneRefs].parent] && !newBones[boneInfo[*boneRefs].parent]))
			{
				R_CalcBoneLerp(header, refent, boneInfo[*boneRefs].parent);
			}

			R_CalcBoneLerp(header, refent, *boneRefs);
		}
	}

	// adjust for torso rotations
	torsoWeight = 0;
	boneRefs    = boneList;
	for (i = 0; i < numBones; i++, boneRefs++)
	{
		thisBoneInfo = &boneInfo[*boneRefs];
		bonePtr      = &bones[*boneRefs];
		// add torso rotation
		if (thisBoneInfo->torsoWeight > 0)
		{
			if (!newBones[*boneRefs])
			{
				// just copy it back from the previous calc
				bones[*boneRefs] = oldBones[*boneRefs];
				continue;
			}

			if (!(thisBoneInfo->flags & BONEFLAG_TAG))
			{
				// 1st multiply with the bone->matrix
				// 2nd translation for rotation relative to bone around torso parent offset
				VectorSubtract(bonePtr->translation, torsoParentOffset, t);
				Matrix4FromAxisPlusTranslation(bonePtr->matrix, t, m1);
				// 3rd scaled rotation
				// 4th translate back to torso parent offset
				// use previously created matrix if available for the same weight
				if (torsoWeight != thisBoneInfo->torsoWeight)
				{
					Matrix4FromScaledAxisPlusTranslation(torsoAxis, thisBoneInfo->torsoWeight, torsoParentOffset, m2);
					torsoWeight = thisBoneInfo->torsoWeight;
				}
				// multiply matrices to create one matrix to do all calculations
				Matrix4MultiplyInto3x3AndTranslation(m2, m1, bonePtr->matrix, bonePtr->translation);

			}
			else        // tag's require special handling
			{   // rotate each of the axis by the torsoAngles
				LocalScaledMatrixTransformVector(bonePtr->matrix[0], thisBoneInfo->torsoWeight, torsoAxis, tmpAxis[0]);
				LocalScaledMatrixTransformVector(bonePtr->matrix[1], thisBoneInfo->torsoWeight, torsoAxis, tmpAxis[1]);
				LocalScaledMatrixTransformVector(bonePtr->matrix[2], thisBoneInfo->torsoWeight, torsoAxis, tmpAxis[2]);
				memcpy(bonePtr->matrix, tmpAxis, sizeof(tmpAxis));

				// rotate the translation around the torsoParent
				VectorSubtract(bonePtr->translation, torsoParentOffset, t);
				LocalScaledMatrixTransformVector(t, thisBoneInfo->torsoWeight, torsoAxis, bonePtr->translation);
				VectorAdd(bonePtr->translation, torsoParentOffset, bonePtr->translation);
			}
		}
	}

	// backup the final bones
	memcpy(oldBones, bones, sizeof(bones[0]) * header->numBones);
}

#ifdef DBG_PROFILE_BONES
#define DBG_SHOWTIME    Ren_Print("%i: %i, ", di++, (dt = ri.Milliseconds()) - ldt); ldt = dt;
#else
#define DBG_SHOWTIME    ;
#endif

/*
==============
RB_SurfaceAnim
==============
*/
void RB_SurfaceAnim(mdsSurface_t *surface)
{
	int         j, k;
	refEntity_t *refent;
	int         *boneList;
	mdsHeader_t *header;

#ifdef DBG_PROFILE_BONES
	int di = 0, dt, ldt;

	dt  = ri.Milliseconds();
	ldt = dt;
#endif

	refent   = &backEnd.currentEntity->e;
	boneList = ( int * )((byte *)surface + surface->ofsBoneReferences);
	header   = ( mdsHeader_t * )((byte *)surface + surface->ofsHeader);

	R_CalcBones(header, (const refEntity_t *)refent, boneList, surface->numBoneReferences);

	DBG_SHOWTIME

	// calculate LOD
	// TODO: lerp the radius and origin
	VectorAdd(refent->origin, frame->localOrigin, vec);
	lodRadius = frame->radius;
	lodScale  = RB_CalcMDSLod(refent, vec, lodRadius, header->lodBias, header->lodScale);


//DBG_SHOWTIME

	// modification to allow dead skeletal bodies to go below minlod (experiment)
	if (refent->reFlags & REFLAG_DEAD_LOD)
	{
		if (lodScale < 0.35)       // allow dead to lod down to 35% (even if below surf->minLod) (%35 is arbitrary and probably not good generally.  worked for the blackguard/infantry as a test though)
		{
			lodScale = 0.35;
		}
		render_count = ROUND_INT(surface->numVerts * lodScale);

	}
	else
	{
		render_count = ROUND_INT(surface->numVerts * lodScale);
		if (render_count < surface->minLod)
		{
			if (!(refent->reFlags & REFLAG_DEAD_LOD))
			{
				render_count = surface->minLod;
			}
		}
	}

	if (render_count > surface->numVerts)
	{
		render_count = surface->numVerts;
	}

	RB_CheckOverflow(render_count, surface->numTriangles);

//DBG_SHOWTIME

	// setup triangle list
	RB_CheckOverflow(surface->numVerts, surface->numTriangles * 3);

//DBG_SHOWTIME

	collapse_map = ( int * )(( byte * )surface + surface->ofsCollapseMap);
	triangles    = ( int * )((byte *)surface + surface->ofsTriangles);
	indexes      = surface->numTriangles * 3;
	baseIndex    = tess.numIndexes;
	baseVertex   = tess.numVertexes;
	oldIndexes   = baseIndex;

	tess.numVertexes += render_count;

	pIndexes = &tess.indexes[baseIndex];

//DBG_SHOWTIME

	if (render_count == surface->numVerts)
	{
		memcpy(pIndexes, triangles, sizeof(triangles[0]) * indexes);
		if (baseVertex)
		{
			glIndex_t *indexesEnd;
			for (indexesEnd = pIndexes + indexes ; pIndexes < indexesEnd ; pIndexes++)
			{
				*pIndexes += baseVertex;
			}
		}
		tess.numIndexes += indexes;
	}
	else
	{
		int *collapseEnd;

		pCollapse = collapse;
		for (j = 0; j < render_count; pCollapse++, j++)
		{
			*pCollapse = j;
		}

		pCollapseMap = &collapse_map[render_count];
		for (collapseEnd = collapse + surface->numVerts ; pCollapse < collapseEnd; pCollapse++, pCollapseMap++)
		{
			*pCollapse = collapse[*pCollapseMap];
		}

		for (j = 0 ; j < indexes ; j += 3)
		{
			p0 = collapse[*(triangles++)];
			p1 = collapse[*(triangles++)];
			p2 = collapse[*(triangles++)];

			// FIXME
			// note:  serious optimization opportunity here,
			//  by sorting the triangles the following "continue"
			//  could have been made into a "break" statement.
			if (p0 == p1 || p1 == p2 || p2 == p0)
			{
				continue;
			}

			*(pIndexes++)    = baseVertex + p0;
			*(pIndexes++)    = baseVertex + p1;
			*(pIndexes++)    = baseVertex + p2;
			tess.numIndexes += 3;
		}

		baseIndex = tess.numIndexes;
	}

//DBG_SHOWTIME

	// deform the vertexes by the lerped bones

	numVerts   = surface->numVerts;
	v          = ( mdsVertex_t * )((byte *)surface + surface->ofsVerts);
	tempVert   = ( float * )(tess.xyz + baseVertex);
	tempNormal = ( float * )(tess.normal + baseVertex);
	for (j = 0; j < render_count; j++, tempVert += 4, tempNormal += 4)
	{
		mdsWeight_t *w;

		VectorClear(tempVert);

		w = v->weights;
		for (k = 0 ; k < v->numWeights ; k++, w++)
		{
			bone = &bones[w->boneIndex];
			LocalAddScaledMatrixTransformVectorTranslate(w->offset, w->boneWeight, bone->matrix, bone->translation, tempVert);
		}

		LocalMatrixTransformVector(v->normal, bones[v->weights[0].boneIndex].matrix, tempNormal);

		tess.texCoords0[baseVertex + j].v[0] = v->texCoords[0];
		tess.texCoords0[baseVertex + j].v[1] = v->texCoords[1];

		v = (mdsVertex_t *)&v->weights[v->numWeights];
	}

	DBG_SHOWTIME

	if (r_bonesDebug->integer)
	{
		if (r_bonesDebug->integer < 3)
		{
			int i;

			// DEBUG: show the bones as a stick figure with axis at each bone
			boneRefs = ( int * )((byte *)surface + surface->ofsBoneReferences);
			for (i = 0; i < surface->numBoneReferences; i++, boneRefs++)
			{
				bonePtr = &bones[*boneRefs];

				GL_Bind(tr.whiteImage);
				qglLineWidth(1);
				qglBegin(GL_LINES);
				for (j = 0; j < 3; j++)
				{
					VectorClear(vec);
					vec[j] = 1;
					qglColor3fv(vec);
					qglVertex3fv(bonePtr->translation);
					VectorMA(bonePtr->translation, 5, bonePtr->matrix[j], vec);
					qglVertex3fv(vec);
				}
				qglEnd();

				// connect to our parent if it's valid
				if (validBones[boneInfo[*boneRefs].parent])
				{
					qglLineWidth(2);
					qglBegin(GL_LINES);
					qglColor3f(.6, .6, .6);
					qglVertex3fv(bonePtr->translation);
					qglVertex3fv(bones[boneInfo[*boneRefs].parent].translation);
					qglEnd();
				}

				qglLineWidth(1);
			}
		}

		if (r_bonesDebug->integer == 3 || r_bonesDebug->integer == 4)
		{
			int render_indexes = (tess.numIndexes - oldIndexes);

			// show mesh edges
			tempVert   = ( float * )(tess.xyz + baseVertex);
			tempNormal = ( float * )(tess.normal + baseVertex);

			GL_Bind(tr.whiteImage);
			qglLineWidth(1);
			qglBegin(GL_LINES);
			qglColor3f(.0, .0, .8);

			pIndexes = &tess.indexes[oldIndexes];
			for (j = 0; j < render_indexes / 3; j++, pIndexes += 3)
			{
				qglVertex3fv(tempVert + 4 * pIndexes[0]);
				qglVertex3fv(tempVert + 4 * pIndexes[1]);

				qglVertex3fv(tempVert + 4 * pIndexes[1]);
				qglVertex3fv(tempVert + 4 * pIndexes[2]);

				qglVertex3fv(tempVert + 4 * pIndexes[2]);
				qglVertex3fv(tempVert + 4 * pIndexes[0]);
			}

			qglEnd();

			// track debug stats
			if (r_bonesDebug->integer == 4)
			{
				totalrv += render_count;
				totalrt += render_indexes / 3;
				totalv  += surface->numVerts;
				totalt  += surface->numTriangles;
			}

			if (r_bonesDebug->integer == 3)
			{
				Ren_Print("Lod %.2f  verts %4d/%4d  tris %4d/%4d  (%.2f%%)\n", lodScale, render_count, surface->numVerts, render_indexes / 3, surface->numTriangles,
				          ( float )(100.0 * render_indexes / 3) / (float) surface->numTriangles);
			}
		}
	}

	if (r_bonesDebug->integer > 1)
	{
		// dont draw the actual surface
		tess.numIndexes  = oldIndexes;
		tess.numVertexes = baseVertex;
		return;
	}

#ifdef DBG_PROFILE_BONES
	Ren_Print("\n");
#endif
}
예제 #6
0
/*
==============
RB_SurfaceAnim
==============
*/
void RB_SurfaceAnim( md4Surface_t *surface ) {
	int				i, j, k;
	float			frontlerp, backlerp;
	int				*triangles;
	int				*indexes;
	int				numIndexes;
	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;
	float			*xyz, *normal;
	vec2_t			*texCoords;


	RB_CheckShaderTime( backEnd.refdef->time - backEnd.currentModel->shaderTime, backEnd.refdef->timeFraction );
	if (  backEnd.currentModel->oldframe == backEnd.currentModel->frame ) {
		backlerp = 0;
		frontlerp = 1;
	} else  {
		backlerp = backEnd.currentModel->backlerp;
		frontlerp = 1.0f - backlerp;
	}
	header = (md4Header_t *)((byte *)surface + surface->ofsHeader);

	frameSize = (size_t)( &((md4Frame_t *)0)->bones[ header->numBones ] );

	frame = (md4Frame_t *)((byte *)header + header->ofsFrames + 
		backEnd.currentModel->frame * frameSize );
	oldFrame = (md4Frame_t *)((byte *)header + header->ofsFrames + 
		backEnd.currentModel->oldframe * frameSize );

	numIndexes = surface->numTriangles * 3;
	RB_CheckOverflow( surface->numVerts, numIndexes );

	triangles = (int *) ((byte *)surface + surface->ofsTriangles);
	indexes = tess.indexes + tess.numIndexes;
	for (j = 0 ; j < numIndexes ; j++) {
		indexes[j] = tess.numIndexes + triangles[j];
	}
	tess.numIndexes += numIndexes;

	//
	// 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;
	xyz = (tess.xyz + tess.numVertexes)[0];
	normal = (tess.normal + tess.numVertexes)[0];
	texCoords = tess.texCoords + tess.numVertexes;

	// FIXME
	// This makes TFC's skeletons work.  Shouldn't be necessary anymore, but left
	// in for reference.
	//v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts + 12);
	v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts);
	for ( j = 0; j < numVerts; j++, xyz += VEC_SIMD, normal+= VEC_SIMD, texCoords++ ) {
		md4Weight_t	*w;

		VectorClear( xyz );
		VectorClear( normal );
		w = v->weights;
		for ( k = 0 ; k < v->numWeights ; k++, w++ ) {
			bone = bonePtr + w->boneIndex;

			xyz[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] );
			xyz[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] );
			xyz[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] );

			normal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal );
			normal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal );
			normal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal );
		}
		texCoords[0][0] = v->texCoords[0];
		texCoords[0][1] = v->texCoords[1];

		// FIXME
		// This makes TFC's skeletons work.  Shouldn't be necessary anymore, but left
		// in for reference.
		//v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 );
		v = (md4Vertex_t *)&v->weights[v->numWeights];
	}

	tess.numVertexes += surface->numVerts;
}
예제 #7
0
/*
==============
RB_SurfaceAnim
==============
*/
void RB_SurfaceAnim( mdsSurface_t *surface ) {
	int i, j, k;
	int render_count;
	int p0, p1, p2, indexes;
	refEntity_t     *refent;
	int             *boneList, *triangles;
	glIndex_t       *indexesEnd, *pIndexes;
	mdsHeader_t     *header;
	mdsFrame_t      *backframe;
	mdsBoneFrame_t  *bone;
	mdsVertex_t     *v;
	float *tempVert, *tempNormal;
	int baseIndex, baseVertex, oldIndexes, numVerts;
	int frameSize;

	refent = &backEnd.currentEntity->e;
	boneList = ( int * )( (byte *)surface + surface->ofsBoneReferences );
	header = ( mdsHeader_t * )( (byte *)surface + surface->ofsHeader );
	frameSize = (int) ( sizeof( mdsFrame_t ) + ( header->numBones - 1 ) * sizeof( mdsBoneFrameCompressed_t ) );
	backframe = ( mdsFrame_t * )( (byte *)header + header->ofsFrames + refent->frame * frameSize );

	render_count = surface->numVerts;

	RB_CheckOverflow( render_count, surface->numTriangles );

	//
	// setup triangle list
	//
	RB_CheckOverflow( surface->numVerts, surface->numTriangles * 3 );

	triangles = ( int * )( (byte *)surface + surface->ofsTriangles );
	indexes = surface->numTriangles * 3;
	baseIndex = tess.numIndexes;
	baseVertex = tess.numVertexes;
	oldIndexes = baseIndex;

	tess.numVertexes += render_count;

	pIndexes = &tess.indexes[baseIndex];

	//memcpy( pIndexes, triangles, sizeof( triangles[0] ) * indexes );
	for ( i = 0 ; i < indexes ; i++ ) {
		*pIndexes++ = baseVertex + *triangles++;
	}

	tess.numIndexes += indexes;

	//
	// deform the vertexes by the lerped bones
	//
	numVerts = surface->numVerts;
	v = ( mdsVertex_t * )( (byte *)surface + surface->ofsVerts );
	tempVert = ( float * )( tess.xyz + baseVertex );
	tempNormal = ( float * )( tess.normal + baseVertex );

	//LockBones
	R_CalcBones( header, (const refEntity_t *)refent, boneList, surface->numBoneReferences, 1 );

	for ( j = 0; j < render_count; j++, tempVert += 4, tempNormal += 4 ) {
		mdsWeight_t *w;

		VectorClear( tempVert );

		w = v->weights;
		for ( k = 0 ; k < v->numWeights ; k++, w++ ) {
			bone = &smpbones[1][w->boneIndex];
			LocalAddScaledMatrixTransformVectorTranslate( w->offset, w->boneWeight, bone->matrix, bone->translation, tempVert );
		}
		LocalMatrixTransformVector( v->normal, smpbones[1][v->weights[0].boneIndex].matrix, tempNormal );

		tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
		tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];

		v = (mdsVertex_t *)&v->weights[v->numWeights];
	}
	//UnlockBones
}