Exemplo n.º 1
0
/*
* R_RenderDebugBounds
*/
static void R_RenderDebugBounds( void )
{
	int i, j;
	vec3_t corner;
	const vec_t *mins, *maxs;
	mesh_t *rb_mesh;
	elem_t elems[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };

	if( !r_num_debug_bounds )
		return;

	RB_EnableTriangleOutlines( qtrue );

	RB_BindShader( rsc.worldent, rsh.whiteShader, NULL );

	RB_BindVBO( RB_VBO_STREAM, GL_TRIANGLE_STRIP );

	for( i = 0; i < r_num_debug_bounds; i++ )
	{
		mins = r_debug_bounds[i].mins;
		maxs = r_debug_bounds[i].maxs;

		rb_mesh = RB_MapBatchMesh( 8, 8 );
		for( j = 0; j < 8; j++ )
		{
			corner[0] = ( ( j & 1 ) ? mins[0] : maxs[0] );
			corner[1] = ( ( j & 2 ) ? mins[1] : maxs[1] );
			corner[2] = ( ( j & 4 ) ? mins[2] : maxs[2] );
			VectorCopy( corner, rb_mesh->xyzArray[j] );
		}

		rb_mesh->numVerts = 8;
		rb_mesh->numElems = 8;
		rb_mesh->elems = elems;
		RB_UploadMesh( rb_mesh );

		RB_EndBatch();
	}

	RB_EnableTriangleOutlines( qfalse );
}
Exemplo n.º 2
0
/*
* R_DrawSkeletalSurf
*/
qboolean R_DrawSkeletalSurf( const entity_t *e, const shader_t *shader, const mfog_t *fog, drawSurfaceSkeletal_t *drawSurf )
{
	unsigned int i, j;
	int framenum = e->frame;
	int oldframenum = e->oldframe;
	float backlerp = e->backlerp;
	float frontlerp = 1.0 - backlerp;
	bonepose_t tempbonepose[256];
	const bonepose_t *bp, *oldbp, *bonepose, *oldbonepose, *lerpedbonepose;
	bonepose_t *out, tp;
	mskbone_t *bone;
	mat4_t *bonePoseRelativeMat;
	dualquat_t *bonePoseRelativeDQ;
	size_t bonePoseRelativeMatSize, bonePoseRelativeDQSize;
	const model_t *mod = drawSurf->model;
	const mskmodel_t *skmodel = ( const mskmodel_t * )mod->extradata;
	const mskmesh_t *skmesh = drawSurf->mesh;
	qboolean hardwareTransform = skmesh->vbo != NULL && glConfig.maxGLSLBones > 0 ? qtrue : qfalse;
	vattribmask_t vattribs;

	bonePoseRelativeMat = NULL;
	bonePoseRelativeDQ = NULL;

	bp = e->boneposes;
	oldbp = e->oldboneposes;

	// not sure if it's really needed
	if( bp == skmodel->frames[0].boneposes )
	{
		bp = NULL;
		framenum = oldframenum = 0;
	}

	// choose boneposes for lerping
	if( bp )
	{
		if( !oldbp )
			oldbp = bp;
	}
	else
	{
		if( ( framenum >= (int)skmodel->numframes ) || ( framenum < 0 ) )
		{
#ifndef PUBLIC_BUILD
			ri.Com_DPrintf( "R_DrawBonesFrameLerp %s: no such frame %d\n", mod->name, framenum );
#endif
			framenum = 0;
		}
		if( ( oldframenum >= (int)skmodel->numframes ) || ( oldframenum < 0 ) )
		{
#ifndef PUBLIC_BUILD
			ri.Com_DPrintf( "R_DrawBonesFrameLerp %s: no such oldframe %d\n", mod->name, oldframenum );
#endif
			oldframenum = 0;
		}

		bp = skmodel->frames[framenum].boneposes;
		oldbp = skmodel->frames[oldframenum].boneposes;
	}

	if( bp == oldbp && !framenum && skmesh->vbo != NULL ) {
		// fastpath: render static frame 0 as is
		RB_BindVBO( skmesh->vbo->index, GL_TRIANGLES );

		RB_DrawElements( 0, skmesh->numverts, 0, skmesh->numtris * 3 );

		return qfalse;
	}

	// see what vertex attribs backend needs
	vattribs = RB_GetVertexAttribs();

	// cache size
	bonePoseRelativeMatSize = sizeof( mat4_t ) * (skmodel->numbones + skmodel->numblends);
	bonePoseRelativeDQSize = sizeof( dualquat_t ) * skmodel->numbones;

	// fetch bones tranforms from cache (both matrices and dual quaternions)
	bonePoseRelativeDQ = ( dualquat_t * )R_GetSketalCache( R_ENT2NUM( e ), mod->lodnum );
	if( bonePoseRelativeDQ ) {
		bonePoseRelativeMat = ( mat4_t * )(( qbyte * )bonePoseRelativeDQ + bonePoseRelativeDQSize);
	}
	else {
		// lerp boneposes and store results in cache

		lerpedbonepose = tempbonepose;
		if( bp == oldbp || frontlerp == 1 )
		{
			if( e->boneposes )
			{
				// assume that parent transforms have already been applied
				lerpedbonepose = bp;
			}
			else
			{
				for( i = 0; i < skmodel->numbones; i++ )
				{
					j = i;
					out = tempbonepose + j;
					bonepose = bp + j;
					bone = skmodel->bones + j;

					if( bone->parent >= 0 ) {
						DualQuat_Multiply( tempbonepose[bone->parent].dualquat, bonepose->dualquat, out->dualquat );
					}
					else {
						DualQuat_Copy( bonepose->dualquat, out->dualquat );
					}
				}
			}
		}
		else
		{
			if( e->boneposes )
			{
				// lerp, assume that parent transforms have already been applied
				for( i = 0, out = tempbonepose, bonepose = bp, oldbonepose = oldbp, bone = skmodel->bones; i < skmodel->numbones; i++, out++, bonepose++, oldbonepose++, bone++ )
				{
					DualQuat_Lerp( oldbonepose->dualquat, bonepose->dualquat, frontlerp, out->dualquat );
				}
			}
			else
			{
				// lerp and transform
				for( i = 0; i < skmodel->numbones; i++ )
				{
					j = i;
					out = tempbonepose + j;
					bonepose = bp + j;
					oldbonepose = oldbp + j;
					bone = skmodel->bones + j;

					DualQuat_Lerp( oldbonepose->dualquat, bonepose->dualquat, frontlerp, out->dualquat );

					if( bone->parent >= 0 ) {
						DualQuat_Copy( out->dualquat, tp.dualquat );
						DualQuat_Multiply( tempbonepose[bone->parent].dualquat, tp.dualquat, out->dualquat );
					}
				}
			}
		}

		bonePoseRelativeDQ = ( dualquat_t * )R_AllocSkeletalDataCache( R_ENT2NUM( e ), mod->lodnum, 
			bonePoseRelativeDQSize + bonePoseRelativeMatSize );

		// generate dual quaternions for all bones
		for( i = 0; i < skmodel->numbones; i++ ) {
			DualQuat_Multiply( lerpedbonepose[i].dualquat, skmodel->invbaseposes[i].dualquat, bonePoseRelativeDQ[i] );
			DualQuat_Normalize( bonePoseRelativeDQ[i] );
		}

		// CPU transforms
		if( !hardwareTransform ) {
			bonePoseRelativeMat = ( mat4_t * )(( qbyte * )bonePoseRelativeDQ + bonePoseRelativeDQSize);

			// generate matrices for all bones
			for( i = 0; i < skmodel->numbones; i++ ) {
				Matrix4_FromDualQuaternion( bonePoseRelativeDQ[i], bonePoseRelativeMat[i] );
			}

			// generate matrices for all blend combinations
			R_SkeletalBlendPoses( skmodel->numblends, skmodel->blends, skmodel->numbones, bonePoseRelativeMat );
		}
	}

	if( hardwareTransform )
	{
		RB_BindVBO( skmesh->vbo->index, GL_TRIANGLES );
		RB_SetBonesData( skmodel->numbones, bonePoseRelativeDQ, skmesh->maxWeights );
		RB_DrawElements( 0, skmesh->numverts, 0, skmesh->numtris * 3 );
	}
	else
	{
		mesh_t *rb_mesh;

		RB_BindVBO( RB_VBO_STREAM, GL_TRIANGLES );

		rb_mesh = RB_MapBatchMesh( skmesh->numverts, skmesh->numtris * 3 );
		if( !rb_mesh ) {
			ri.Com_DPrintf( S_COLOR_YELLOW "R_DrawAliasSurf: RB_MapBatchMesh returned NULL for (%s)(%s)", 
				drawSurf->model->name, skmesh->name );
			return qfalse;
		}

		R_SkeletalTransformVerts( skmesh->numverts, skmesh->vertexBlends, bonePoseRelativeMat,
			( vec_t * )skmesh->xyzArray[0], ( vec_t * )rb_mesh->xyzArray );

		if( vattribs & VATTRIB_SVECTOR_BIT ) {
			R_SkeletalTransformNormalsAndSVecs( skmesh->numverts, skmesh->vertexBlends, bonePoseRelativeMat,
			( vec_t * )skmesh->normalsArray[0], ( vec_t * )rb_mesh->normalsArray,
			( vec_t * )skmesh->sVectorsArray[0], ( vec_t * )rb_mesh->sVectorsArray );
		} else if( vattribs & VATTRIB_NORMAL_BIT ) {
			R_SkeletalTransformNormals( skmesh->numverts, skmesh->vertexBlends, bonePoseRelativeMat,
			( vec_t * )skmesh->normalsArray[0], ( vec_t * )rb_mesh->normalsArray );
		}

		rb_mesh->elems = skmesh->elems;
		rb_mesh->numElems = skmesh->numtris * 3;
		rb_mesh->numVerts = skmesh->numverts;
		rb_mesh->stArray = skmesh->stArray;

		RB_UploadMesh( rb_mesh );
		RB_EndBatch();
	}

	return qfalse;
}
Exemplo n.º 3
0
/*
* R_DrawAliasSurf
* 
* Interpolates between two frames and origins
*/
qboolean R_DrawAliasSurf( const entity_t *e, const shader_t *shader, const mfog_t *fog, drawSurfaceAlias_t *drawSurf )
{
	int i;
	int framenum, oldframenum;
	float backv[3], frontv[3];
	vec3_t normal, oldnormal;
	qboolean calcVerts, calcNormals, calcSTVectors;
	vec3_t move;
	const maliasframe_t *frame, *oldframe;
	const maliasvertex_t *v, *ov;
	float backlerp = e->backlerp;
	const maliasmodel_t *model = ( const maliasmodel_t * )drawSurf->model->extradata;
	const maliasmesh_t *aliasmesh = drawSurf->mesh;
	vattribmask_t vattribs;

	// see what vertex attribs backend needs
	vattribs = RB_GetVertexAttribs();

	framenum = bound( e->frame, 0, model->numframes );
	oldframenum = bound( e->oldframe, 0, model->numframes );

	frame = model->frames + framenum;
	oldframe = model->frames + oldframenum;
	for( i = 0; i < 3; i++ )
		move[i] = frame->translate[i] + ( oldframe->translate[i] - frame->translate[i] ) * backlerp;

	// based on backend's needs
	calcNormals = calcSTVectors = qfalse;
	calcNormals = ( ( vattribs & VATTRIB_NORMAL_BIT ) != 0 ) && ( ( framenum != 0 ) || ( oldframenum != 0 ) );
	calcSTVectors = ( ( vattribs & VATTRIB_SVECTOR_BIT ) != 0 ) && calcNormals;

	if( aliasmesh->vbo != NULL && !framenum && !oldframenum )
	{
		RB_BindVBO( aliasmesh->vbo->index, GL_TRIANGLES );

		RB_DrawElements( 0, aliasmesh->numverts, 0, aliasmesh->numtris * 3 );
	}
	else
	{
		mesh_t *rb_mesh;
		vec3_t *inVertsArray;
		vec3_t *inNormalsArray;
		vec4_t *inSVectorsArray;

		RB_BindVBO( RB_VBO_STREAM, GL_TRIANGLES );

		rb_mesh = RB_MapBatchMesh( aliasmesh->numverts, aliasmesh->numtris * 3 );
		if( !rb_mesh ) {
			ri.Com_DPrintf( S_COLOR_YELLOW "R_DrawAliasSurf: RB_MapBatchMesh returned NULL for (%s)(%s)", 
				drawSurf->model->name, aliasmesh->name );
			return qfalse;
		}

		inVertsArray = rb_mesh->xyzArray;
		inNormalsArray = rb_mesh->normalsArray;
		inSVectorsArray = rb_mesh->sVectorsArray;

		if( !framenum && !oldframenum )
		{
			calcVerts = qfalse;

			if( calcNormals )
			{
				v = aliasmesh->vertexes;
				for( i = 0; i < aliasmesh->numverts; i++, v++ )
					R_LatLongToNorm( v->latlong, inNormalsArray[i] );
			}
		}
		else if( framenum == oldframenum )
		{
			calcVerts = qtrue;

			for( i = 0; i < 3; i++ )
				frontv[i] = frame->scale[i];

			v = aliasmesh->vertexes + framenum * aliasmesh->numverts;
			for( i = 0; i < aliasmesh->numverts; i++, v++ )
			{
				VectorSet( inVertsArray[i],
					move[0] + v->point[0]*frontv[0],
					move[1] + v->point[1]*frontv[1],
					move[2] + v->point[2]*frontv[2] );

				if( calcNormals )
					R_LatLongToNorm( v->latlong, inNormalsArray[i] );
			}
		}
		else
		{
			calcVerts = qtrue;

			for( i = 0; i < 3; i++ )
			{
				backv[i] = backlerp * oldframe->scale[i];
				frontv[i] = ( 1.0f - backlerp ) * frame->scale[i];
			}

			v = aliasmesh->vertexes + framenum * aliasmesh->numverts;
			ov = aliasmesh->vertexes + oldframenum * aliasmesh->numverts;
			for( i = 0; i < aliasmesh->numverts; i++, v++, ov++ )
			{
				VectorSet( inVertsArray[i],
					move[0] + v->point[0]*frontv[0] + ov->point[0]*backv[0],
					move[1] + v->point[1]*frontv[1] + ov->point[1]*backv[1],
					move[2] + v->point[2]*frontv[2] + ov->point[2]*backv[2] );

				if( calcNormals )
				{
					R_LatLongToNorm( v->latlong, normal );
					R_LatLongToNorm( ov->latlong, oldnormal );

					VectorSet( inNormalsArray[i],
						normal[0] + ( oldnormal[0] - normal[0] ) * backlerp,
						normal[1] + ( oldnormal[1] - normal[1] ) * backlerp,
						normal[2] + ( oldnormal[2] - normal[2] ) * backlerp );
				}
			}
		}

		if( calcSTVectors )
			R_BuildTangentVectors( aliasmesh->numverts, inVertsArray, inNormalsArray, aliasmesh->stArray, aliasmesh->numtris, aliasmesh->elems, inSVectorsArray );

		if( !calcVerts ) {
			rb_mesh->xyzArray = aliasmesh->xyzArray;
		}
		rb_mesh->elems = aliasmesh->elems;
		rb_mesh->numElems = aliasmesh->numtris * 3;
		rb_mesh->numVerts = aliasmesh->numverts;

		rb_mesh->stArray = aliasmesh->stArray;
		if( !calcNormals ) {
			rb_mesh->normalsArray = aliasmesh->normalsArray;
		}
		if( !calcSTVectors ) {
			rb_mesh->sVectorsArray = aliasmesh->sVectorsArray;
		}

		RB_UploadMesh( rb_mesh );

		RB_EndBatch();
	}

	return qfalse;
}