예제 #1
0
/*
====================
idMD5Mesh::CalcBounds
====================
*/
idBounds idMD5Mesh::CalcBounds( const idJointMat *entJoints ) {
	idBounds	bounds;
	idDrawVert *verts = (idDrawVert *) _alloca16( texCoords.Num() * sizeof( idDrawVert ) );

	TransformVerts( verts, entJoints );

	SIMDProcessor->MinMax( bounds[0], bounds[1], verts, texCoords.Num() );

	return bounds;
}
예제 #2
0
/*
============
idTraceModel::SetupPolygon
============
*/
void idTraceModel::SetupPolygon( const idWinding &w ) {
	int i;
	idVec3 *verts;

	verts = (idVec3 *) _alloca16( w.GetNumPoints() * sizeof( idVec3 ) );
	for ( i = 0; i < w.GetNumPoints(); i++ ) {
		verts[i] = w[i].ToVec3();
	}
	SetupPolygon( verts, w.GetNumPoints() );
}
예제 #3
0
/*
============
idAASLocal::SortWallEdges
============
*/
void idAASLocal::SortWallEdges( int *edges, int numEdges ) const {
	int i, j, k, numSequences;
	wallEdge_t **sequenceFirst, **sequenceLast, *wallEdges, *wallEdge;
	wallEdges = ( wallEdge_t * ) _alloca16( numEdges * sizeof( wallEdge_t ) );
	sequenceFirst = ( wallEdge_t ** )_alloca16( numEdges * sizeof( wallEdge_t * ) );
	sequenceLast = ( wallEdge_t ** )_alloca16( numEdges * sizeof( wallEdge_t * ) );
	for( i = 0; i < numEdges; i++ ) {
		wallEdges[i].edgeNum = edges[i];
		GetEdgeVertexNumbers( edges[i], wallEdges[i].verts );
		wallEdges[i].next = NULL;
		sequenceFirst[i] = &wallEdges[i];
		sequenceLast[i] = &wallEdges[i];
	}
	numSequences = numEdges;
	for( i = 0; i < numSequences; i++ ) {
		for( j = i + 1; j < numSequences; j++ ) {
			if( sequenceFirst[i]->verts[0] == sequenceLast[j]->verts[1] ) {
				sequenceLast[j]->next = sequenceFirst[i];
				sequenceFirst[i] = sequenceFirst[j];
				break;
			}
			if( sequenceLast[i]->verts[1] == sequenceFirst[j]->verts[0] ) {
				sequenceLast[i]->next = sequenceFirst[j];
				break;
			}
		}
		if( j < numSequences ) {
			numSequences--;
			for( k = j; k < numSequences; k++ ) {
				sequenceFirst[k] = sequenceFirst[k + 1];
				sequenceLast[k] = sequenceLast[k + 1];
			}
			i = -1;
		}
	}
	k = 0;
	for( i = 0; i < numSequences; i++ ) {
		for( wallEdge = sequenceFirst[i]; wallEdge; wallEdge = wallEdge->next ) {
			edges[k++] = wallEdge->edgeNum;
		}
	}
}
예제 #4
0
/*
=============
idPolynomial::GetRoots
=============
*/
int idPolynomial::GetRoots( idComplex* roots ) const
{
	int i, j;
	idComplex x, b, c, *coef;
	
	coef = ( idComplex* ) _alloca16( ( degree + 1 ) * sizeof( idComplex ) );
	for( i = 0; i <= degree; i++ )
	{
		coef[i].Set( coefficient[i], 0.0f );
	}
	
	for( i = degree - 1; i >= 0; i-- )
	{
		x.Zero();
		Laguer( coef, i + 1, x );
		if( idMath::Fabs( x.i ) < 2.0f * EPSILON * idMath::Fabs( x.r ) )
		{
			x.i = 0.0f;
		}
		roots[i] = x;
		b = coef[i + 1];
		for( j = i; j >= 0; j-- )
		{
			c = coef[j];
			coef[j] = b;
			b = x * b + c;
		}
	}
	
	for( i = 0; i <= degree; i++ )
	{
		coef[i].Set( coefficient[i], 0.0f );
	}
	for( i = 0; i < degree; i++ )
	{
		Laguer( coef, degree, roots[i] );
	}
	
	for( i = 1; i < degree; i++ )
	{
		x = roots[i];
		for( j = i - 1; j >= 0; j-- )
		{
			if( roots[j].r <= x.r )
			{
				break;
			}
			roots[j + 1] = roots[j];
		}
		roots[j + 1] = x;
	}
	
	return degree;
}
/*
================
idBrittleFracture::DropFloatingIslands
================
*/
void idBrittleFracture::DropFloatingIslands( const idVec3 &point, const idVec3 &impulse, const int time ) {
	int i, j, numIslands;
	int queueStart, queueEnd;
	shard_t *curShard, *nextShard, **queue;
	bool touchesEdge;
	idVec3 dir;
	dir = impulse;
	dir.Normalize();
	numIslands = 0;
	queue = ( shard_t ** ) _alloca16( shards.Num() * sizeof( shard_t ** ) );
	for( i = 0; i < shards.Num(); i++ ) {
		shards[i]->islandNum = 0;
	}
	for( i = 0; i < shards.Num(); i++ ) {
		if( shards[i]->droppedTime != -1 ) {
			continue;
		}
		if( shards[i]->islandNum ) {
			continue;
		}
		queueStart = 0;
		queueEnd = 1;
		queue[0] = shards[i];
		shards[i]->islandNum = numIslands + 1;
		touchesEdge = false;
		if( shards[i]->atEdge ) {
			touchesEdge = true;
		}
		for( curShard = queue[queueStart]; queueStart < queueEnd; curShard = queue[++queueStart] ) {
			for( j = 0; j < curShard->neighbours.Num(); j++ ) {
				nextShard = curShard->neighbours[j];
				if( nextShard->droppedTime != -1 ) {
					continue;
				}
				if( nextShard->islandNum ) {
					continue;
				}
				queue[queueEnd++] = nextShard;
				nextShard->islandNum = numIslands + 1;
				if( nextShard->atEdge ) {
					touchesEdge = true;
				}
			}
		}
		numIslands++;
		// if the island is not connected to the world at any edges
		if( !touchesEdge ) {
			for( j = 0; j < queueEnd; j++ ) {
				DropShard( queue[j], point, dir, 0.0f, time );
			}
		}
	}
}
예제 #6
0
/*
==================
R_CreateVertexProgramShadowCache

This is constant for any number of lights, the vertex program
takes care of projecting the verts to infinity.
==================
*/
void R_CreateVertexProgramShadowCache( srfTriangles_t *tri )
{
	if( tri->verts == NULL )
	{
		return;
	}
	shadowCache_t *temp = ( shadowCache_t * ) _alloca16( tri->numVerts * 2 * sizeof( shadowCache_t ) );
	
	SIMDProcessor->CreateVertexProgramShadowCache( &temp->xyz, tri->verts, tri->numVerts );
	
	vertexCache.Alloc( temp, tri->numVerts * 2 * sizeof( shadowCache_t ), &tri->shadowCache );
}
/*
================
R_CalcPointCull

Also inits the remap[] array to all -1
================
*/
static void R_CalcPointCull(stencilRef_t *st, const srfTriangles_t *tri, const idPlane frustum[6], unsigned short *pointCull) {
	int		i;
	int		frontBits;
	float	*planeSide;
	byte	*side1, *side2;
	SIMDProcessor->Memset(st->remap, -1, tri->numVerts * sizeof(st->remap[0]));
	for (frontBits = 0, i = 0; i < 6; i++) {
		// get front bits for the whole surface
		if (tri->bounds.PlaneDistance(frustum[i]) >= LIGHT_CLIP_EPSILON) {
			frontBits |= 1 << (i + 6);
		}
	}
	// initialize point cull
	for (i = 0; i < tri->numVerts; i++) {
		pointCull[i] = frontBits;
	}
	// if the surface is not completely inside the light frustum
	if (frontBits == (((1 << 6) - 1)) << 6) {
		return;
	}
	planeSide = (float *)_alloca16(tri->numVerts * sizeof(float));
	side1 = (byte *)_alloca16(tri->numVerts * sizeof(byte));
	side2 = (byte *)_alloca16(tri->numVerts * sizeof(byte));
	SIMDProcessor->Memset(side1, 0, tri->numVerts * sizeof(byte));
	SIMDProcessor->Memset(side2, 0, tri->numVerts * sizeof(byte));
	for (i = 0; i < 6; i++) {
		if (frontBits & (1 << (i + 6))) {
			continue;
		}
		SIMDProcessor->Dot(planeSide, frustum[i], tri->verts, tri->numVerts);
		SIMDProcessor->CmpLT(side1, i, planeSide, LIGHT_CLIP_EPSILON, tri->numVerts);
		SIMDProcessor->CmpGT(side2, i, planeSide, -LIGHT_CLIP_EPSILON, tri->numVerts);
	}
	for (i = 0; i < tri->numVerts; i++) {
		pointCull[i] |= side1[i] | (side2[i] << 6);
	}
}
예제 #8
0
/*
=================
R_CreateShadowVolumeInFrustum

Adds new verts and indexes to the shadow volume.

If the frustum completely defines the projected light,
makeClippedPlanes should be true, which will cause sil quads to
be added along all clipped edges.

If the frustum is just part of a point light, clipped planes don't
need to be added.
=================
*/
static void R_CreateShadowVolumeInFrustum( const idRenderEntityLocal *ent, 
										  const srfTriangles_t *tri,
										  const idRenderLightLocal *light,									
										  const idVec3 lightOrigin,
										  const idPlane frustum[6],
										  const idPlane &farPlane,
										  bool makeClippedPlanes ) {
	int		i;
	int		numTris;
	unsigned short		*pointCull;
	int		numCapIndexes;
	int		firstShadowIndex;
	int		firstShadowVert;
	int		cullBits;

	pointCull = (unsigned short *)_alloca16( tri->numVerts * sizeof( pointCull[0] ) );

	// test the vertexes for inside the light frustum, which will allow
	// us to completely cull away some triangles from consideration.
	R_CalcPointCull( tri, frustum, pointCull );

	// this may not be the first frustum added to the volume
	firstShadowIndex = numShadowIndexes;
	firstShadowVert = numShadowVerts;

	// decide which triangles front shadow volumes, clipping as needed
	numClipSilEdges = 0;
	numTris = tri->numIndexes / 3;
	for ( i = 0 ; i < numTris ; i++ ) {
		int		i1, i2, i3;

		faceCastsShadow[i] = 0;	// until shown otherwise

		// if it isn't facing the right way, don't add it
		// to the shadow volume
		if ( globalFacing[i] ) {
			continue;
		}

		i1 = tri->silIndexes[ i*3 + 0 ];
		i2 = tri->silIndexes[ i*3 + 1 ];
		i3 = tri->silIndexes[ i*3 + 2 ];

		// if all the verts are off one side of the frustum,
		// don't add any of them
		if ( TRIANGLE_CULLED( i1, i2, i3 ) ) {
			continue;
		}
예제 #9
0
/*
============
idLCP_Symmetric::AddClamped
============
*/
void idLCP_Symmetric::AddClamped(int r, bool useSolveCache)
{
	float d, dot;

	assert(r >= numClamped);

	if (numClamped < clampedChangeStart) {
		clampedChangeStart = numClamped;
	}

	// add a row at the bottom and a column at the right of the factored
	// matrix for the clamped variables

	Swap(numClamped, r);

	// solve for v in L * v = rowPtr[numClamped]
	if (useSolveCache) {

		// the lower triangular solve was cached in SolveClamped called by CalcForceDelta
		memcpy(clamped[numClamped], solveCache2.ToFloatPtr(), numClamped * sizeof(float));
		// calculate row dot product
		SIMDProcessor->Dot(dot, solveCache2.ToFloatPtr(), solveCache1.ToFloatPtr(), numClamped);

	} else {

		float *v = (float *) _alloca16(numClamped * sizeof(float));

		SIMDProcessor->MatX_LowerTriangularSolve(clamped, v, rowPtrs[numClamped], numClamped);
		// add bottom row to L
		SIMDProcessor->Mul(clamped[numClamped], v, diagonal.ToFloatPtr(), numClamped);
		// calculate row dot product
		SIMDProcessor->Dot(dot, clamped[numClamped], v, numClamped);
	}

	// update diagonal[numClamped]
	d = rowPtrs[numClamped][numClamped] - dot;

	if (d == 0.0f) {
		idLib::common->Printf("idLCP_Symmetric::AddClamped: updating factorization failed\n");
		numClamped++;
		return;
	}

	clamped[numClamped][numClamped] = d;
	diagonal[numClamped] = 1.0f / d;

	numClamped++;
}
예제 #10
0
/*
================
idDict::Copy

  copy all key value pairs without removing existing key/value pairs not present in the other dict
================
*/
void idDict::Copy( const idDict &other )
{
    int i, n, *found;
    idKeyValue kv;

    // check for assignment to self
    if ( this == &other )
    {
        return;
    }

    n = other.args.Num();

    if ( args.Num() )
    {
        found = (int *) _alloca16( other.args.Num() * sizeof( int ) );
        for ( i = 0; i < n; i++ )
        {
            found[i] = FindKeyIndex( other.args[i].GetKey() );
        }
    }
    else
    {
        found = NULL;
    }

    for ( i = 0; i < n; i++ )
    {
        if ( found && found[i] != -1 )
        {
            // first set the new value and then free the old value to allow proper self copying
            const idPoolStr *oldValue = args[found[i]].value;
            args[found[i]].value = globalValues.CopyString( other.args[i].value );
            globalValues.FreeString( oldValue );
        }
        else
        {
            kv.key = globalKeys.CopyString( other.args[i].key );
            kv.value = globalValues.CopyString( other.args[i].value );
            argHash.Add( argHash.GenerateKey( kv.GetKey(), false ), args.Append( kv ) );
        }
    }
}
예제 #11
0
/*
==================
R_SkyboxTexGen
==================
*/
void R_SkyboxTexGen( drawSurf_t *surf, const idVec3 &viewOrg )
{
	idVec3	localViewOrigin;
	
	R_GlobalPointToLocal( surf->space->modelMatrix, viewOrg, localViewOrigin );
	
	int		numVerts = surf->geo->numVerts;
	int		size = numVerts * sizeof( idVec3 );
	idVec3	*texCoords = ( idVec3 * ) _alloca16( size );
	
	const idDrawVert *verts = surf->geo->verts;
	
	for( int i = 0; i < numVerts; i++ )
	{
		texCoords[i][0] = verts[i].xyz[0] - localViewOrigin[0];
		texCoords[i][1] = verts[i].xyz[1] - localViewOrigin[1];
		texCoords[i][2] = verts[i].xyz[2] - localViewOrigin[2];
	}
	surf->dynamicTexCoords = vertexCache.AllocFrameTemp( texCoords, size );
}
예제 #12
0
/*
=====================
R_CalcInteractionCullBits

We want to cull a little on the sloppy side, because the pre-clipping
of geometry to the lights in dmap will give many cases that are right
at the border we throw things out on the border, because if any one
vertex is clearly inside, the entire triangle will be accepted.
=====================
*/
void R_CalcInteractionCullBits( const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo ) {
	int i, frontBits;

	if ( cullInfo.cullBits != NULL ) {
		return;
	}

	frontBits = 0;

	// cull the triangle surface bounding box
	for ( i = 0; i < 6; i++ ) {

		R_GlobalPlaneToLocal( ent->modelMatrix, -light->frustum[i], cullInfo.localClipPlanes[i] );

		// get front bits for the whole surface
		if ( tri->bounds.PlaneDistance( cullInfo.localClipPlanes[i] ) >= LIGHT_CLIP_EPSILON ) {
			frontBits |= 1<<i;
		}
	}

	// if the surface is completely inside the light frustum
	if ( frontBits == ( ( 1 << 6 ) - 1 ) ) {
		cullInfo.cullBits = LIGHT_CULL_ALL_FRONT;
		return;
	}

	cullInfo.cullBits = (byte *) R_StaticAlloc( tri->numVerts * sizeof( cullInfo.cullBits[0] ) );
	SIMDProcessor->Memset( cullInfo.cullBits, 0, tri->numVerts * sizeof( cullInfo.cullBits[0] ) );

	float *planeSide = (float *) _alloca16( tri->numVerts * sizeof( float ) );

	for ( i = 0; i < 6; i++ ) {
		// if completely infront of this clipping plane
		if ( frontBits & ( 1 << i ) ) {
			continue;
		}
		SIMDProcessor->Dot( planeSide, cullInfo.localClipPlanes[i], tri->verts, tri->numVerts );
		SIMDProcessor->CmpLT( cullInfo.cullBits, i, planeSide, LIGHT_CLIP_EPSILON, tri->numVerts );
	}
}
예제 #13
0
/*
=============
idPolynomial::GetRoots
=============
*/
int idPolynomial::GetRoots( float* roots ) const
{
	int i, num;
	idComplex* complexRoots;
	
	switch( degree )
	{
		case 0:
			return 0;
		case 1:
			return GetRoots1( coefficient[1], coefficient[0], roots );
		case 2:
			return GetRoots2( coefficient[2], coefficient[1], coefficient[0], roots );
		case 3:
			return GetRoots3( coefficient[3], coefficient[2], coefficient[1], coefficient[0], roots );
		case 4:
			return GetRoots4( coefficient[4], coefficient[3], coefficient[2], coefficient[1], coefficient[0], roots );
	}
	
	// The Abel-Ruffini theorem states that there is no general solution
	// in radicals to polynomial equations of degree five or higher.
	// A polynomial equation can be solved by radicals if and only if
	// its Galois group is a solvable group.
	
	complexRoots = ( idComplex* ) _alloca16( degree * sizeof( idComplex ) );
	
	GetRoots( complexRoots );
	
	for( num = i = 0; i < degree; i++ )
	{
		if( complexRoots[i].i == 0.0f )
		{
			roots[i] = complexRoots[i].r;
			num++;
		}
	}
	return num;
}
예제 #14
0
/*
=====================
idRenderModelOverlay::CreateOverlay

This projects on both front and back sides to avoid seams
The material should be clamped, because entire triangles are added, some of which
may extend well past the 0.0 to 1.0 texture range
=====================
*/
void idRenderModelOverlay::CreateOverlay( const idRenderModel *model, const idPlane localTextureAxis[2], const idMaterial *mtr ) {
	int i, maxVerts, maxIndexes, surfNum;
	idRenderModelOverlay *overlay = NULL;

	// count up the maximum possible vertices and indexes per surface
	maxVerts = 0;
	maxIndexes = 0;
	for ( surfNum = 0; surfNum < model->NumSurfaces(); surfNum++ ) {
		const modelSurface_t *surf = model->Surface( surfNum );
		if ( surf->geometry->numVerts > maxVerts ) {
			maxVerts = surf->geometry->numVerts;
		}
		if ( surf->geometry->numIndexes > maxIndexes ) {
			maxIndexes = surf->geometry->numIndexes;
		}
	}

	// make temporary buffers for the building process
	overlayVertex_t	*overlayVerts = (overlayVertex_t *)_alloca( maxVerts * sizeof( *overlayVerts ) );
	glIndex_t *overlayIndexes = (glIndex_t *)_alloca16( maxIndexes * sizeof( *overlayIndexes ) );

	// pull out the triangles we need from the base surfaces
	for ( surfNum = 0; surfNum < model->NumBaseSurfaces(); surfNum++ ) {
		const modelSurface_t *surf = model->Surface( surfNum );
		float d;

		if ( !surf->geometry || !surf->shader ) {
			continue;
		}

		// some surfaces can explicitly disallow overlays
		if ( !surf->shader->AllowOverlays() ) {
			continue;
		}

		const srfTriangles_t *stri = surf->geometry;

		// try to cull the whole surface along the first texture axis
		d = stri->bounds.PlaneDistance( localTextureAxis[0] );
		if ( d < 0.0f || d > 1.0f ) {
			continue;
		}

		// try to cull the whole surface along the second texture axis
		d = stri->bounds.PlaneDistance( localTextureAxis[1] );
		if ( d < 0.0f || d > 1.0f ) {
			continue;
		}

		byte *cullBits = (byte *)_alloca16( stri->numVerts * sizeof( cullBits[0] ) );
		idVec2 *texCoords = (idVec2 *)_alloca16( stri->numVerts * sizeof( texCoords[0] ) );

		SIMDProcessor->OverlayPointCull( cullBits, texCoords, localTextureAxis, stri->verts, stri->numVerts );

		glIndex_t *vertexRemap = (glIndex_t *)_alloca16( sizeof( vertexRemap[0] ) * stri->numVerts );
		SIMDProcessor->Memset( vertexRemap, -1,  sizeof( vertexRemap[0] ) * stri->numVerts );

		// find triangles that need the overlay
		int numVerts = 0;
		int numIndexes = 0;
		int triNum = 0;
		for ( int index = 0; index < stri->numIndexes; index += 3, triNum++ ) {
			int v1 = stri->indexes[index+0];
			int	v2 = stri->indexes[index+1];
			int v3 = stri->indexes[index+2];

			// skip triangles completely off one side
			if ( cullBits[v1] & cullBits[v2] & cullBits[v3] ) {
				continue;
			}

			// we could do more precise triangle culling, like the light interaction does, if desired

			// keep this triangle
			for ( int vnum = 0; vnum < 3; vnum++ ) {
				int ind = stri->indexes[index+vnum];
				if ( vertexRemap[ind] == (glIndex_t)-1 ) {
					vertexRemap[ind] = numVerts;

					overlayVerts[numVerts].vertexNum = ind;
					overlayVerts[numVerts].st[0] = texCoords[ind][0];
					overlayVerts[numVerts].st[1] = texCoords[ind][1];

					numVerts++;
				}
				overlayIndexes[numIndexes++] = vertexRemap[ind];
			}
		}

		if ( !numIndexes ) {
			continue;
		}

		overlaySurface_t *s = (overlaySurface_t *) Mem_Alloc( sizeof( overlaySurface_t ) );
		s->surfaceNum = surfNum;
		s->surfaceId = surf->id;
		s->verts = (overlayVertex_t *)Mem_Alloc( numVerts * sizeof( s->verts[0] ) );
		memcpy( s->verts, overlayVerts, numVerts * sizeof( s->verts[0] ) );
		s->numVerts = numVerts;
		s->indexes = (glIndex_t *)Mem_Alloc( numIndexes * sizeof( s->indexes[0] ) );
		memcpy( s->indexes, overlayIndexes, numIndexes * sizeof( s->indexes[0] ) );
		s->numIndexes = numIndexes;

		for ( i = 0; i < materials.Num(); i++ ) {
			if ( materials[i]->material == mtr ) {
				break;
			}
		}
		if ( i < materials.Num() ) {
            materials[i]->surfaces.Append( s );
		} else {
			overlayMaterial_t *mat = new overlayMaterial_t;
			mat->material = mtr;
			mat->surfaces.Append( s );
			materials.Append( mat );
		}
	}

	// remove the oldest overlay surfaces if there are too many per material
	for ( i = 0; i < materials.Num(); i++ ) {
		while( materials[i]->surfaces.Num() > MAX_OVERLAY_SURFACES ) {
			FreeSurface( materials[i]->surfaces[0] );
			materials[i]->surfaces.RemoveIndex( 0 );
		}
	}
}
예제 #15
0
/*
============
idBrush::Split
============
*/
int idBrush::Split( const idPlane& plane, int planeNum, idBrush** front, idBrush** back ) const
{
	int res, i, j;
	idBrushSide* side, *frontSide, *backSide;
	float dist, maxBack, maxFront, *maxBackWinding, *maxFrontWinding;
	idWinding* w, *mid;
	
	assert( windingsValid );
	
	if( front )
	{
		*front = NULL;
	}
	if( back )
	{
		*back = NULL;
	}
	
	res = bounds.PlaneSide( plane, -BRUSH_EPSILON );
	if( res == PLANESIDE_FRONT )
	{
		if( front )
		{
			*front = Copy();
		}
		return res;
	}
	if( res == PLANESIDE_BACK )
	{
		if( back )
		{
			*back = Copy();
		}
		return res;
	}
	
	maxBackWinding = ( float* ) _alloca16( sides.Num() * sizeof( float ) );
	maxFrontWinding = ( float* ) _alloca16( sides.Num() * sizeof( float ) );
	
	maxFront = maxBack = 0.0f;
	for( i = 0; i < sides.Num(); i++ )
	{
		side = sides[i];
		
		w = side->winding;
		
		if( !w )
		{
			continue;
		}
		
		maxBackWinding[i] = 10.0f;
		maxFrontWinding[i] = -10.0f;
		
		for( j = 0; j < w->GetNumPoints(); j++ )
		{
		
			dist = plane.Distance( ( *w )[j].ToVec3() );
			if( dist > maxFrontWinding[i] )
			{
				maxFrontWinding[i] = dist;
			}
			if( dist < maxBackWinding[i] )
			{
				maxBackWinding[i] = dist;
			}
		}
		
		if( maxFrontWinding[i] > maxFront )
		{
			maxFront = maxFrontWinding[i];
		}
		if( maxBackWinding[i] < maxBack )
		{
			maxBack = maxBackWinding[i];
		}
	}
	
	if( maxFront < BRUSH_EPSILON )
	{
		if( back )
		{
			*back = Copy();
		}
		return PLANESIDE_BACK;
	}
	
	if( maxBack > -BRUSH_EPSILON )
	{
		if( front )
		{
			*front = Copy();
		}
		return PLANESIDE_FRONT;
	}
	
	mid = new idWinding( plane.Normal(), plane.Dist() );
	
	for( i = 0; i < sides.Num() && mid; i++ )
	{
		mid = mid->Clip( -sides[i]->plane, BRUSH_EPSILON, false );
	}
	
	if( mid )
	{
		if( mid->IsTiny() )
		{
			delete mid;
			mid = NULL;
		}
		else if( mid->IsHuge() )
		{
			// if the winding is huge then the brush is unbounded
			common->Warning( "brush %d on entity %d is unbounded"
							 "( %1.2f %1.2f %1.2f )-( %1.2f %1.2f %1.2f )-( %1.2f %1.2f %1.2f )", primitiveNum, entityNum,
							 bounds[0][0], bounds[0][1], bounds[0][2], bounds[1][0], bounds[1][1], bounds[1][2],
							 bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1], bounds[1][2] - bounds[0][2] );
			delete mid;
			mid = NULL;
		}
	}
	
	if( !mid )
	{
		if( maxFront > - maxBack )
		{
			if( front )
			{
				*front = Copy();
			}
			return PLANESIDE_FRONT;
		}
		else
		{
			if( back )
			{
				*back = Copy();
			}
			return PLANESIDE_BACK;
		}
	}
	
	if( !front && !back )
	{
		delete mid;
		return PLANESIDE_CROSS;
	}
	
	*front = new idBrush();
	( *front )->SetContents( contents );
	( *front )->SetEntityNum( entityNum );
	( *front )->SetPrimitiveNum( primitiveNum );
	*back = new idBrush();
	( *back )->SetContents( contents );
	( *back )->SetEntityNum( entityNum );
	( *back )->SetPrimitiveNum( primitiveNum );
	
	for( i = 0; i < sides.Num(); i++ )
	{
		side = sides[i];
		
		if( !side->winding )
		{
			continue;
		}
		
		// if completely at the front
		if( maxBackWinding[i] >= BRUSH_EPSILON )
		{
			( *front )->sides.Append( side->Copy() );
		}
		// if completely at the back
		else if( maxFrontWinding[i] <= -BRUSH_EPSILON )
		{
			( *back )->sides.Append( side->Copy() );
		}
		else
		{
			// split the side
			side->Split( plane, &frontSide, &backSide );
			if( frontSide )
			{
				( *front )->sides.Append( frontSide );
			}
			else if( maxFrontWinding[i] > -BRUSH_EPSILON )
			{
				// favor an overconstrained brush
				side = side->Copy();
				side->winding = side->winding->Clip( idPlane( plane.Normal(), ( plane.Dist() - ( BRUSH_EPSILON + 0.02f ) ) ), 0.01f, true );
				assert( side->winding );
				( *front )->sides.Append( side );
			}
			if( backSide )
			{
				( *back )->sides.Append( backSide );
			}
			else if( maxBackWinding[i] < BRUSH_EPSILON )
			{
				// favor an overconstrained brush
				side = side->Copy();
				side->winding = side->winding->Clip( idPlane( -plane.Normal(), -( plane.Dist() + ( BRUSH_EPSILON + 0.02f ) ) ), 0.01f, true );
				assert( side->winding );
				( *back )->sides.Append( side );
			}
		}
	}
	
	side = new idBrushSide( -plane, planeNum ^ 1 );
	side->winding = mid->Reverse();
	side->flags |= SFL_SPLIT;
	( *front )->sides.Append( side );
	( *front )->windingsValid = true;
	( *front )->BoundBrush( this );
	
	side = new idBrushSide( plane, planeNum );
	side->winding = mid;
	side->flags |= SFL_SPLIT;
	( *back )->sides.Append( side );
	( *back )->windingsValid = true;
	( *back )->BoundBrush( this );
	
	return PLANESIDE_CROSS;
}
예제 #16
0
파일: IK.cpp 프로젝트: Deepfreeze32/taken
/*
================
idIK_Reach::Init
================
*/
bool idIK_Reach::Init( idEntity *self, const char *anim, const idVec3 &modelOffset ) {
	int i;
	const char *jointName;
	idTraceModel trm;
	idVec3 dir, handOrigin, elbowOrigin, shoulderOrigin, dirOrigin;
	idMat3 axis, handAxis, elbowAxis, shoulderAxis;

	if ( !self ) {
		return false;
	}

	numArms = Min( self->spawnArgs.GetInt( "ik_numArms", "0" ), MAX_ARMS );
	if ( numArms == 0 ) {
		return true;
	}

	if ( !idIK::Init( self, anim, modelOffset ) ) {
		return false;
	}

	int numJoints = animator->NumJoints();
	idJointMat *joints = ( idJointMat * )_alloca16( numJoints * sizeof( joints[0] ) );

	// create the animation frame used to setup the IK
	gameEdit->ANIM_CreateAnimFrame( animator->ModelHandle(), animator->GetAnim( modifiedAnim )->MD5Anim( 0 ), numJoints, joints, 1, animator->ModelDef()->GetVisualOffset() + modelOffset, animator->RemoveOrigin() );

	enabledArms = 0;

	// get all the joints
	for ( i = 0; i < numArms; i++ ) {

		jointName = self->spawnArgs.GetString( va( "ik_hand%d", i+1 ) );
		handJoints[i] = animator->GetJointHandle( jointName );
		if ( handJoints[i] == INVALID_JOINT ) {
			gameLocal.Error( "idIK_Reach::Init: invalid hand joint '%s'", jointName );
		}

		jointName = self->spawnArgs.GetString( va( "ik_elbow%d", i+1 ) );
		elbowJoints[i] = animator->GetJointHandle( jointName );
		if ( elbowJoints[i] == INVALID_JOINT ) {
			gameLocal.Error( "idIK_Reach::Init: invalid elbow joint '%s'\n", jointName );
		}

		jointName = self->spawnArgs.GetString( va( "ik_shoulder%d", i+1 ) );
		shoulderJoints[i] = animator->GetJointHandle( jointName );
		if ( shoulderJoints[i] == INVALID_JOINT ) {
			gameLocal.Error( "idIK_Reach::Init: invalid shoulder joint '%s'\n", jointName );
		}

		jointName = self->spawnArgs.GetString( va( "ik_elbowDir%d", i+1 ) );
		dirJoints[i] = animator->GetJointHandle( jointName );

		enabledArms |= 1 << i;
	}

	// get the arm bone lengths and rotation matrices
	for ( i = 0; i < numArms; i++ ) {

		handAxis = joints[ handJoints[ i ] ].ToMat3();
		handOrigin = joints[ handJoints[ i ] ].ToVec3();

		elbowAxis = joints[ elbowJoints[ i ] ].ToMat3();
		elbowOrigin = joints[ elbowJoints[ i ] ].ToVec3();

		shoulderAxis = joints[ shoulderJoints[ i ] ].ToMat3();
		shoulderOrigin = joints[ shoulderJoints[ i ] ].ToVec3();

		// get the IK direction
		if ( dirJoints[i] != INVALID_JOINT ) {
			dirOrigin = joints[ dirJoints[ i ] ].ToVec3();
			dir = dirOrigin - elbowOrigin;
		} else {
			dir.Set( -1.0f, 0.0f, 0.0f );
		}

		shoulderForward[i] = dir * shoulderAxis.Transpose();
		elbowForward[i] = dir * elbowAxis.Transpose();

		// conversion from upper arm bone axis to should joint axis
		upperArmLength[i] = GetBoneAxis( shoulderOrigin, elbowOrigin, dir, axis );
		upperArmToShoulderJoint[i] = shoulderAxis * axis.Transpose();

		// conversion from lower arm bone axis to elbow joint axis
		lowerArmLength[i] = GetBoneAxis( elbowOrigin, handOrigin, dir, axis );
		lowerArmToElbowJoint[i] = elbowAxis * axis.Transpose();
	}

	initialized = true;

	return true;
}
예제 #17
0
void OBJExporter::ConvertBrushToOBJ( OBJGroup& group, const idMapBrush* mapBrush, int entityNum, int primitiveNum, const idMat4& transform )
{
	OBJExporter::OBJObject& geometry = group.objects.Alloc();
	
	geometry.name.Format( "Primitive.%i", primitiveNum );
	
	// fix degenerate planes
	idPlane* planes = ( idPlane* ) _alloca16( mapBrush->GetNumSides() * sizeof( planes[0] ) );
	for( int i = 0; i < mapBrush->GetNumSides(); i++ )
	{
		planes[i] = mapBrush->GetSide( i )->GetPlane();
		planes[i].FixDegeneracies( DEGENERATE_DIST_EPSILON );
	}
	
	//idFixedWinding w;
	idList<idFixedWinding> planeWindings;
	idBounds bounds;
	bounds.Clear();
	
	int numVerts = 0;
	int numIndexes = 0;
	
	bool badBrush = false;
	
	
	
	for( int i = 0; i < mapBrush->GetNumSides(); i++ )
	{
		idMapBrushSide* mapSide = mapBrush->GetSide( i );
		
		const idMaterial* material = declManager->FindMaterial( mapSide->GetMaterial() );
		//contents |= ( material->GetContentFlags() & CONTENTS_REMOVE_UTIL );
		materials.AddUnique( material );
		
		// chop base plane by other brush sides
		idFixedWinding& w = planeWindings.Alloc();
		w.BaseForPlane( -planes[i] );
		
		if( !w.GetNumPoints() )
		{
			common->Printf( "Entity %i, Brush %i: base winding has no points\n", entityNum, primitiveNum );
			badBrush = true;
		}
		
		for( int j = 0; j < mapBrush->GetNumSides() && w.GetNumPoints(); j++ )
		{
			if( i == j )
			{
				continue;
			}
			
			
			if( !w.ClipInPlace( -planes[j], 0 ) )
			{
				// no intersection
				//badBrush = true;
				common->Printf( "Entity %i, Brush %i: no intersection with other brush plane\n", entityNum, primitiveNum );
				//break;
			}
		}
		
		if( w.GetNumPoints() <= 2 )
		{
			continue;
		}
		
		for( int j = 0; j < w.GetNumPoints(); j++ )
		{
			const idVec3& v = w[j].ToVec3();
			bounds.AddPoint( v );
		}
	}
	
	// allocate the surface
	
	// copy the data from the windings and build polygons
	for( int i = 0; i < mapBrush->GetNumSides(); i++ )
	{
		idMapBrushSide* mapSide = mapBrush->GetSide( i );
		
		idFixedWinding& w = planeWindings[i];
		if( !w.GetNumPoints() )
		{
			continue;
		}
		
		OBJExporter::OBJFace& face = geometry.faces.Alloc();
		
		face.material = declManager->FindMaterial( mapSide->GetMaterial() );
		
		for( int j = 0; j < w.GetNumPoints(); j++ )
		{
			idDrawVert& dv = face.verts.Alloc();
			
			const idVec3& xyz = w[j].ToVec3();
			
			dv.xyz = ( transform * idVec4( xyz.x, xyz.y, xyz.z, 1 ) ).ToVec3();
			
			// calculate texture s/t from brush primitive texture matrix
			idVec4 texVec[2];
			mapSide->GetTextureVectors( texVec );
			
			idVec2 st;
			st.x = ( xyz * texVec[0].ToVec3() ) + texVec[0][3];
			st.y = ( xyz * texVec[1].ToVec3() ) + texVec[1][3];
			
			// flip y
			st.y = 1.0f - st.y;
			
			dv.SetTexCoord( st );
			
			// copy normal
			dv.SetNormal( transform * mapSide->GetPlane().Normal() );
			
			//if( dv->GetNormal().Length() < 0.9 || dv->GetNormal().Length() > 1.1 )
			//{
			//	common->Error( "Bad normal in TriListForSide" );
			//}
		}
		
#if 0
		// triangulate
		for( int j = 1; j < w.GetNumPoints() - 1; j++ )
		{
			face.indexes.Append( numVerts );
			face.indexes.Append( numVerts + j );
			face.indexes.Append( numVerts + j + 1 );
		}
#else
		// export n-gon
		
		//for( int j = 0; j < w.GetNumPoints(); j++ )
		
		// reverse order, so normal does not point inwards
		for( int j = w.GetNumPoints() - 1; j >= 0; j-- )
		{
			face.indexes.Append( numVerts + j );
		}
#endif
		
		numVerts += w.GetNumPoints();
	}
}
예제 #18
0
/*
=================
R_SortDrawSurfs
=================
*/
static void R_SortDrawSurfs( drawSurf_t ** drawSurfs, const int numDrawSurfs ) {
#if 1

	uint64 * indices = (uint64 *) _alloca16( numDrawSurfs * sizeof( indices[0] ) );

	// sort the draw surfs based on:
	// 1. sort value (largest first)
	// 2. depth (smallest first)
	// 3. index (largest first)
	assert( numDrawSurfs <= 0xFFFF );
	for ( int i = 0; i < numDrawSurfs; i++ ) {
		float sort = SS_POST_PROCESS - drawSurfs[i]->sort;
		assert( sort >= 0.0f );

		uint64 dist = 0;
		if ( drawSurfs[i]->frontEndGeo != NULL ) {
			float min = 0.0f;
			float max = 1.0f;
			idRenderMatrix::DepthBoundsForBounds( min, max, drawSurfs[i]->space->mvp, drawSurfs[i]->frontEndGeo->bounds );
			dist = idMath::Ftoui16( min * 0xFFFF );
		}
		
		indices[i] = ( ( numDrawSurfs - i ) & 0xFFFF ) | ( dist << 16 ) | ( (uint64) ( *(uint32 *)&sort ) << 32 );
	}

	const int64 MAX_LEVELS = 128;
	int64 lo[MAX_LEVELS];
	int64 hi[MAX_LEVELS];

	// Keep the top of the stack in registers to avoid load-hit-stores.
	register int64 st_lo = 0;
	register int64 st_hi = numDrawSurfs - 1;
	register int64 level = 0;

	for ( ; ; ) {
		register int64 i = st_lo;
		register int64 j = st_hi;
		if ( j - i >= 4 && level < MAX_LEVELS - 1 ) {
			register uint64 pivot = indices[( i + j ) / 2];
			do {
				while ( indices[i] > pivot ) i++;
				while ( indices[j] < pivot ) j--;
				if ( i > j ) break;
				uint64 h = indices[i]; indices[i] = indices[j]; indices[j] = h;
			} while ( ++i <= --j );

			// No need for these iterations because we are always sorting unique values.
			//while ( indices[j] == pivot && st_lo < j ) j--;
			//while ( indices[i] == pivot && i < st_hi ) i++;

			assert( level < MAX_LEVELS - 1 );
			lo[level] = i;
			hi[level] = st_hi;
			st_hi = j;
			level++;
		} else {
			for( ; i < j; j-- ) {
				register int64 m = i;
				for ( int64 k = i + 1; k <= j; k++ ) {
					if ( indices[k] < indices[m] ) {
						m = k;
					}
				}
				uint64 h = indices[m]; indices[m] = indices[j]; indices[j] = h;
			}
			if ( --level < 0 ) {
				break;
			}
			st_lo = lo[level];
			st_hi = hi[level];
		}
	}

	drawSurf_t ** newDrawSurfs = (drawSurf_t **) indices;
	for ( int i = 0; i < numDrawSurfs; i++ ) {
		newDrawSurfs[i] = drawSurfs[numDrawSurfs - ( indices[i] & 0xFFFF )];
	}
	memcpy( drawSurfs, newDrawSurfs, numDrawSurfs * sizeof( drawSurfs[0] ) );

#else

	struct local_t {
		static int R_QsortSurfaces( const void *a, const void *b ) {
			const drawSurf_t * ea = *(drawSurf_t **)a;
			const drawSurf_t * eb = *(drawSurf_t **)b;
			if ( ea->sort < eb->sort ) {
				return -1;
			}
			if ( ea->sort > eb->sort ) {
				return 1;
			}
			return 0;
		}
	};

	// Add a sort offset so surfaces with equal sort orders still deterministically
	// draw in the order they were added, at least within a given model.
	float sorfOffset = 0.0f;
	for ( int i = 0; i < numDrawSurfs; i++ ) {
		drawSurf[i]->sort += sorfOffset;
		sorfOffset += 0.000001f;
	}

	// sort the drawsurfs
	qsort( drawSurfs, numDrawSurfs, sizeof( drawSurfs[0] ), local_t::R_QsortSurfaces );

#endif
}
예제 #19
0
파일: Anim.cpp 프로젝트: Keloran/doom3.gpl
/*
====================
idMD5Anim::GetInterpolatedFrame
====================
*/
void idMD5Anim::GetInterpolatedFrame( frameBlend_t &frame, idJointQuat *joints, const int *index, int numIndexes ) const {
	int						i, numLerpJoints;
	const float				*frame1;
	const float				*frame2;
	const float				*jointframe1;
	const float				*jointframe2;
	const jointAnimInfo_t	*infoPtr;
	int						animBits;
	idJointQuat				*blendJoints;
	idJointQuat				*jointPtr;
	idJointQuat				*blendPtr;
	int						*lerpIndex;

	// copy the baseframe
	SIMDProcessor->Memcpy( joints, baseFrame.Ptr(), baseFrame.Num() * sizeof( baseFrame[ 0 ] ) );

	if ( !numAnimatedComponents ) {
		// just use the base frame
		return;
	}

	blendJoints = (idJointQuat *)_alloca16( baseFrame.Num() * sizeof( blendPtr[ 0 ] ) );
	lerpIndex = (int *)_alloca16( baseFrame.Num() * sizeof( lerpIndex[ 0 ] ) );
	numLerpJoints = 0;

	frame1 = &componentFrames[ frame.frame1 * numAnimatedComponents ];
	frame2 = &componentFrames[ frame.frame2 * numAnimatedComponents ];

	for ( i = 0; i < numIndexes; i++ ) {
		int j = index[i];
		jointPtr = &joints[j];
		blendPtr = &blendJoints[j];
		infoPtr = &jointInfo[j];

		animBits = infoPtr->animBits;
		if ( animBits ) {

			lerpIndex[numLerpJoints++] = j;

			jointframe1 = frame1 + infoPtr->firstComponent;
			jointframe2 = frame2 + infoPtr->firstComponent;

			switch( animBits & (ANIM_TX|ANIM_TY|ANIM_TZ) ) {
				case 0:
					blendPtr->t = jointPtr->t;
					break;
				case ANIM_TX:
					jointPtr->t.x = jointframe1[0];
					blendPtr->t.x = jointframe2[0];
					blendPtr->t.y = jointPtr->t.y;
					blendPtr->t.z = jointPtr->t.z;
					jointframe1++;
					jointframe2++;
					break;
				case ANIM_TY:
					jointPtr->t.y = jointframe1[0];
					blendPtr->t.y = jointframe2[0];
					blendPtr->t.x = jointPtr->t.x;
					blendPtr->t.z = jointPtr->t.z;
					jointframe1++;
					jointframe2++;
					break;
				case ANIM_TZ:
					jointPtr->t.z = jointframe1[0];
					blendPtr->t.z = jointframe2[0];
					blendPtr->t.x = jointPtr->t.x;
					blendPtr->t.y = jointPtr->t.y;
					jointframe1++;
					jointframe2++;
					break;
				case ANIM_TX|ANIM_TY:
					jointPtr->t.x = jointframe1[0];
					jointPtr->t.y = jointframe1[1];
					blendPtr->t.x = jointframe2[0];
					blendPtr->t.y = jointframe2[1];
					blendPtr->t.z = jointPtr->t.z;
					jointframe1 += 2;
					jointframe2 += 2;
					break;
				case ANIM_TX|ANIM_TZ:
					jointPtr->t.x = jointframe1[0];
					jointPtr->t.z = jointframe1[1];
					blendPtr->t.x = jointframe2[0];
					blendPtr->t.z = jointframe2[1];
					blendPtr->t.y = jointPtr->t.y;
					jointframe1 += 2;
					jointframe2 += 2;
					break;
				case ANIM_TY|ANIM_TZ:
					jointPtr->t.y = jointframe1[0];
					jointPtr->t.z = jointframe1[1];
					blendPtr->t.y = jointframe2[0];
					blendPtr->t.z = jointframe2[1];
					blendPtr->t.x = jointPtr->t.x;
					jointframe1 += 2;
					jointframe2 += 2;
					break;
				case ANIM_TX|ANIM_TY|ANIM_TZ:
					jointPtr->t.x = jointframe1[0];
					jointPtr->t.y = jointframe1[1];
					jointPtr->t.z = jointframe1[2];
					blendPtr->t.x = jointframe2[0];
					blendPtr->t.y = jointframe2[1];
					blendPtr->t.z = jointframe2[2];
					jointframe1 += 3;
					jointframe2 += 3;
					break;
			}

			switch( animBits & (ANIM_QX|ANIM_QY|ANIM_QZ) ) {
				case 0:
					blendPtr->q = jointPtr->q;
					break;
				case ANIM_QX:
					jointPtr->q.x = jointframe1[0];
					blendPtr->q.x = jointframe2[0];
					blendPtr->q.y = jointPtr->q.y;
					blendPtr->q.z = jointPtr->q.z;
					jointPtr->q.w = jointPtr->q.CalcW();
					blendPtr->q.w = blendPtr->q.CalcW();
					break;
				case ANIM_QY:
					jointPtr->q.y = jointframe1[0];
					blendPtr->q.y = jointframe2[0];
					blendPtr->q.x = jointPtr->q.x;
					blendPtr->q.z = jointPtr->q.z;
					jointPtr->q.w = jointPtr->q.CalcW();
					blendPtr->q.w = blendPtr->q.CalcW();
					break;
				case ANIM_QZ:
					jointPtr->q.z = jointframe1[0];
					blendPtr->q.z = jointframe2[0];
					blendPtr->q.x = jointPtr->q.x;
					blendPtr->q.y = jointPtr->q.y;
					jointPtr->q.w = jointPtr->q.CalcW();
					blendPtr->q.w = blendPtr->q.CalcW();
					break;
				case ANIM_QX|ANIM_QY:
					jointPtr->q.x = jointframe1[0];
					jointPtr->q.y = jointframe1[1];
					blendPtr->q.x = jointframe2[0];
					blendPtr->q.y = jointframe2[1];
					blendPtr->q.z = jointPtr->q.z;
					jointPtr->q.w = jointPtr->q.CalcW();
					blendPtr->q.w = blendPtr->q.CalcW();
					break;
				case ANIM_QX|ANIM_QZ:
					jointPtr->q.x = jointframe1[0];
					jointPtr->q.z = jointframe1[1];
					blendPtr->q.x = jointframe2[0];
					blendPtr->q.z = jointframe2[1];
					blendPtr->q.y = jointPtr->q.y;
					jointPtr->q.w = jointPtr->q.CalcW();
					blendPtr->q.w = blendPtr->q.CalcW();
					break;
				case ANIM_QY|ANIM_QZ:
					jointPtr->q.y = jointframe1[0];
					jointPtr->q.z = jointframe1[1];
					blendPtr->q.y = jointframe2[0];
					blendPtr->q.z = jointframe2[1];
					blendPtr->q.x = jointPtr->q.x;
					jointPtr->q.w = jointPtr->q.CalcW();
					blendPtr->q.w = blendPtr->q.CalcW();
					break;
				case ANIM_QX|ANIM_QY|ANIM_QZ:
					jointPtr->q.x = jointframe1[0];
					jointPtr->q.y = jointframe1[1];
					jointPtr->q.z = jointframe1[2];
					blendPtr->q.x = jointframe2[0];
					blendPtr->q.y = jointframe2[1];
					blendPtr->q.z = jointframe2[2];
					jointPtr->q.w = jointPtr->q.CalcW();
					blendPtr->q.w = blendPtr->q.CalcW();
					break;
			}
		}
	}

	SIMDProcessor->BlendJoints( joints, blendJoints, frame.backlerp, lerpIndex, numLerpJoints );

	if ( frame.cycleCount ) {
		joints[ 0 ].t += totaldelta * ( float )frame.cycleCount;
	}
}
/*
=================
idRenderModelDecal::CreateDecal
=================
*/
void idRenderModelDecal::CreateDecal( const idRenderModel *model, const decalProjectionInfo_t &localInfo ) {
	// check all model surfaces
	for( int surfNum = 0; surfNum < model->NumSurfaces(); surfNum++ ) {
		const modelSurface_t *surf = model->Surface( surfNum );
		// if no geometry or no shader
		if( !surf->geometry || !surf->shader ) {
			continue;
		}
		// decals and overlays use the same rules
		if( !localInfo.force && !surf->shader->AllowOverlays() ) {
			continue;
		}
		srfTriangles_t *stri = surf->geometry;
		// if the triangle bounds do not overlap with projection bounds
		if( !localInfo.projectionBounds.IntersectsBounds( stri->bounds ) ) {
			continue;
		}
		// allocate memory for the cull bits
		byte *cullBits = ( byte * )_alloca16( stri->numVerts * sizeof( cullBits[0] ) );
		// catagorize all points by the planes
		SIMDProcessor->DecalPointCull( cullBits, localInfo.boundingPlanes, stri->verts, stri->numVerts );
		// find triangles inside the projection volume
		for( int triNum = 0, index = 0; index < stri->numIndexes; index += 3, triNum++ ) {
			int v1 = stri->indexes[index + 0];
			int v2 = stri->indexes[index + 1];
			int v3 = stri->indexes[index + 2];
			// skip triangles completely off one side
			if( cullBits[v1] & cullBits[v2] & cullBits[v3] ) {
				continue;
			}
			// skip back facing triangles
			if( stri->facePlanes && stri->facePlanesCalculated &&
					stri->facePlanes[triNum].Normal() * localInfo.boundingPlanes[NUM_DECAL_BOUNDING_PLANES - 2].Normal() < -0.1f ) {
				continue;
			}
			// create a winding with texture coordinates for the triangle
			idFixedWinding fw;
			fw.SetNumPoints( 3 );
			if( localInfo.parallel ) {
				for( int j = 0; j < 3; j++ ) {
					fw[j] = stri->verts[stri->indexes[index + j]].xyz;
					fw[j].s = localInfo.textureAxis[0].Distance( fw[j].ToVec3() );
					fw[j].t = localInfo.textureAxis[1].Distance( fw[j].ToVec3() );
				}
			} else {
				for( int j = 0; j < 3; j++ ) {
					idVec3 dir;
					float scale;
					fw[j] = stri->verts[stri->indexes[index + j]].xyz;
					dir = fw[j].ToVec3() - localInfo.projectionOrigin;
					localInfo.boundingPlanes[NUM_DECAL_BOUNDING_PLANES - 1].RayIntersection( fw[j].ToVec3(), dir, scale );
					dir = fw[j].ToVec3() + scale * dir;
					fw[j].s = localInfo.textureAxis[0].Distance( dir );
					fw[j].t = localInfo.textureAxis[1].Distance( dir );
				}
			}
			int orBits = cullBits[v1] | cullBits[v2] | cullBits[v3];
			// clip the exact surface triangle to the projection volume
			for( int j = 0; j < NUM_DECAL_BOUNDING_PLANES; j++ ) {
				if( orBits & ( 1 << j ) ) {
					if( !fw.ClipInPlace( -localInfo.boundingPlanes[j] ) ) {
						break;
					}
				}
			}
			if( fw.GetNumPoints() == 0 ) {
				continue;
			}
			AddDepthFadedWinding( fw, localInfo.material, localInfo.fadePlanes, localInfo.fadeDepth, localInfo.startTime );
		}
	}
}
예제 #21
0
/*
====================
idMD5Mesh::ParseMesh
====================
*/
void idMD5Mesh::ParseMesh( idLexer &parser, int numJoints, const idJointMat *joints ) {
	idToken		token;
	idToken		name;
	int			num;
	int			count;
	int			jointnum;
	idStr		shaderName;
	int			i, j;
	idList<int>	tris;
	idList<int>	firstWeightForVertex;
	idList<int>	numWeightsForVertex;
	int			maxweight;
	idList<vertexWeight_t> tempWeights;

	parser.ExpectTokenString( "{" );

	//
	// parse name
	//
	if ( parser.CheckTokenString( "name" ) ) {
		parser.ReadToken( &name );
	}

	//
	// parse shader
	//
	parser.ExpectTokenString( "shader" );

	parser.ReadToken( &token );
	shaderName = token;

    shader = declManager->FindMaterial( shaderName );

	//
	// parse texture coordinates
	//
	parser.ExpectTokenString( "numverts" );
	count = parser.ParseInt();
	if ( count < 0 ) {
		parser.Error( "Invalid size: %s", token.c_str() );
	}

	texCoords.SetNum( count );
	firstWeightForVertex.SetNum( count );
	numWeightsForVertex.SetNum( count );

	numWeights = 0;
	maxweight = 0;
	for( i = 0; i < texCoords.Num(); i++ ) {
		parser.ExpectTokenString( "vert" );
		parser.ParseInt();

		parser.Parse1DMatrix( 2, texCoords[ i ].ToFloatPtr() );

		firstWeightForVertex[ i ]	= parser.ParseInt();
		numWeightsForVertex[ i ]	= parser.ParseInt();

		if ( !numWeightsForVertex[ i ] ) {
			parser.Error( "Vertex without any joint weights." );
		}

		numWeights += numWeightsForVertex[ i ];
		if ( numWeightsForVertex[ i ] + firstWeightForVertex[ i ] > maxweight ) {
			maxweight = numWeightsForVertex[ i ] + firstWeightForVertex[ i ];
		}
	}

	//
	// parse tris
	//
	parser.ExpectTokenString( "numtris" );
	count = parser.ParseInt();
	if ( count < 0 ) {
		parser.Error( "Invalid size: %d", count );
	}

	tris.SetNum( count * 3 );
	numTris = count;
	for( i = 0; i < count; i++ ) {
		parser.ExpectTokenString( "tri" );
		parser.ParseInt();

		tris[ i * 3 + 0 ] = parser.ParseInt();
		tris[ i * 3 + 1 ] = parser.ParseInt();
		tris[ i * 3 + 2 ] = parser.ParseInt();
	}

	//
	// parse weights
	//
	parser.ExpectTokenString( "numweights" );
	count = parser.ParseInt();
	if ( count < 0 ) {
		parser.Error( "Invalid size: %d", count );
	}

	if ( maxweight > count ) {
		parser.Warning( "Vertices reference out of range weights in model (%d of %d weights).", maxweight, count );
	}

	tempWeights.SetNum( count );

	for( i = 0; i < count; i++ ) {
		parser.ExpectTokenString( "weight" );
		parser.ParseInt();

		jointnum = parser.ParseInt();
		if ( ( jointnum < 0 ) || ( jointnum >= numJoints ) ) {
			parser.Error( "Joint Index out of range(%d): %d", numJoints, jointnum );
		}

		tempWeights[ i ].joint			= jointnum;
		tempWeights[ i ].jointWeight	= parser.ParseFloat();

		parser.Parse1DMatrix( 3, tempWeights[ i ].offset.ToFloatPtr() );
	}

	// create pre-scaled weights and an index for the vertex/joint lookup
	scaledWeights = (idVec4 *) Mem_Alloc16( numWeights * sizeof( scaledWeights[0] ) );
	weightIndex = (int *) Mem_Alloc16( numWeights * 2 * sizeof( weightIndex[0] ) );
	memset( weightIndex, 0, numWeights * 2 * sizeof( weightIndex[0] ) );

	count = 0;
	for( i = 0; i < texCoords.Num(); i++ ) {
		num = firstWeightForVertex[i];
		for( j = 0; j < numWeightsForVertex[i]; j++, num++, count++ ) {
			scaledWeights[count].ToVec3() = tempWeights[num].offset * tempWeights[num].jointWeight;
			scaledWeights[count].w = tempWeights[num].jointWeight;
			weightIndex[count * 2 + 0] = tempWeights[num].joint * sizeof( idJointMat );
		}
		weightIndex[count * 2 - 1] = 1;
	}

	tempWeights.Clear();
	numWeightsForVertex.Clear();
	firstWeightForVertex.Clear();

	parser.ExpectTokenString( "}" );

	// update counters
	c_numVerts += texCoords.Num();
	c_numWeights += numWeights;
	c_numWeightJoints++;
	for ( i = 0; i < numWeights; i++ ) {
		c_numWeightJoints += weightIndex[i*2+1];
	}

	//
	// build the information that will be common to all animations of this mesh:
	// silhouette edge connectivity and normal / tangent generation information
	//
	idDrawVert *verts = (idDrawVert *) _alloca16( texCoords.Num() * sizeof( idDrawVert ) );
	for ( i = 0; i < texCoords.Num(); i++ ) {
		verts[i].Clear();
		verts[i].st = texCoords[i];
	}
	TransformVerts( verts, joints );
	deformInfo = R_BuildDeformInfo( texCoords.Num(), verts, tris.Num(), tris.Ptr(), shader->UseUnsmoothedTangents() );
}
예제 #22
0
/*
====================
idRenderModelMD5::LoadModel

used for initial loads, reloadModel, and reloading the data of purged models
Upon exit, the model will absolutely be valid, but possibly as a default model
====================
*/
void idRenderModelMD5::LoadModel() {
	int			version;
	int			i;
	int			num;
	int			parentNum;
	idToken		token;
	idLexer		parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS );
	idJointQuat	*pose;
	idMD5Joint	*joint;
	idJointMat *poseMat3;

	if ( !purged ) {
		PurgeModel();
	}
	purged = false;

	if ( !parser.LoadFile( name ) ) {
		MakeDefaultModel();
		return;
	}

	parser.ExpectTokenString( MD5_VERSION_STRING );
	version = parser.ParseInt();

	if ( version != MD5_VERSION ) {
		parser.Error( "Invalid version %d.  Should be version %d\n", version, MD5_VERSION );
	}

	//
	// skip commandline
	//
	parser.ExpectTokenString( "commandline" );
	parser.ReadToken( &token );

	// parse num joints
	parser.ExpectTokenString( "numJoints" );
	num  = parser.ParseInt();
	joints.SetGranularity( 1 );
	joints.SetNum( num );
	defaultPose.SetGranularity( 1 );
	defaultPose.SetNum( num );
	poseMat3 = ( idJointMat * )_alloca16( num * sizeof( *poseMat3 ) );

	// parse num meshes
	parser.ExpectTokenString( "numMeshes" );
	num = parser.ParseInt();
	if ( num < 0 ) {
		parser.Error( "Invalid size: %d", num );
	}
	meshes.SetGranularity( 1 );
	meshes.SetNum( num );

	//
	// parse joints
	//
	parser.ExpectTokenString( "joints" );
	parser.ExpectTokenString( "{" );
	pose = defaultPose.Ptr();
	joint = joints.Ptr();
	for( i = 0; i < joints.Num(); i++, joint++, pose++ ) {
		ParseJoint( parser, joint, pose );
		poseMat3[ i ].SetRotation( pose->q.ToMat3() );
		poseMat3[ i ].SetTranslation( pose->t );
		if ( joint->parent ) {
			parentNum = joint->parent - joints.Ptr();
			pose->q = ( poseMat3[ i ].ToMat3() * poseMat3[ parentNum ].ToMat3().Transpose() ).ToQuat();
			pose->t = ( poseMat3[ i ].ToVec3() - poseMat3[ parentNum ].ToVec3() ) * poseMat3[ parentNum ].ToMat3().Transpose();
		}
	}
	parser.ExpectTokenString( "}" );

	for( i = 0; i < meshes.Num(); i++ ) {
		parser.ExpectTokenString( "mesh" );
		meshes[ i ].ParseMesh( parser, defaultPose.Num(), poseMat3 );
	}

	//
	// calculate the bounds of the model
	//
	CalculateBounds( poseMat3 );

	// set the timestamp for reloadmodels
	fileSystem->ReadFile( name, NULL, &timeStamp );
}
예제 #23
0
/*
==================
R_WobbleskyTexGen
==================
*/
void R_WobbleskyTexGen( drawSurf_t *surf, const idVec3 &viewOrg )
{
	idVec3		localViewOrigin;
	
	const int	*parms = surf->material->GetTexGenRegisters();
	
	float		wobbleDegrees = surf->shaderRegisters[parms[0]];
	float		wobbleSpeed = surf->shaderRegisters[parms[1]];
	float		rotateSpeed = surf->shaderRegisters[parms[2]];
	
	wobbleDegrees = wobbleDegrees * idMath::PI / 180;
	wobbleSpeed = wobbleSpeed * 2 * idMath::PI / 60;
	rotateSpeed = rotateSpeed * 2 * idMath::PI / 60;
	
	// very ad-hoc "wobble" transform
	float	transform[16];
	float	a = tr.viewDef->floatTime * wobbleSpeed;
	float	s = sin( a ) * sin( wobbleDegrees );
	float	c = cos( a ) * sin( wobbleDegrees );
	float	z = cos( wobbleDegrees );
	
	idVec3	axis[3];
	
	axis[2][0] = c;
	axis[2][1] = s;
	axis[2][2] = z;
	
	axis[1][0] = -sin( a * 2 ) * sin( wobbleDegrees );
	axis[1][2] = -s * sin( wobbleDegrees );
	axis[1][1] = sqrt( 1.0f - ( axis[1][0] * axis[1][0] + axis[1][2] * axis[1][2] ) );
	
	// make the second vector exactly perpendicular to the first
	axis[1] -= ( axis[2] * axis[1] ) * axis[2];
	axis[1].Normalize();
	
	// construct the third with a cross
	axis[0].Cross( axis[1], axis[2] );
	
	// add the rotate
	s = sin( rotateSpeed * tr.viewDef->floatTime );
	c = cos( rotateSpeed * tr.viewDef->floatTime );
	
	transform[0] = axis[0][0] * c + axis[1][0] * s;
	transform[4] = axis[0][1] * c + axis[1][1] * s;
	transform[8] = axis[0][2] * c + axis[1][2] * s;
	
	transform[1] = axis[1][0] * c - axis[0][0] * s;
	transform[5] = axis[1][1] * c - axis[0][1] * s;
	transform[9] = axis[1][2] * c - axis[0][2] * s;
	
	transform[2] = axis[2][0];
	transform[6] = axis[2][1];
	transform[10] = axis[2][2];
	
	transform[3] = transform[7] = transform[11] = 0.0f;
	transform[12] = transform[13] = transform[14] = 0.0f;
	
	R_GlobalPointToLocal( surf->space->modelMatrix, viewOrg, localViewOrigin );
	
	int		numVerts = surf->geo->numVerts;
	int		size = numVerts * sizeof( idVec3 );
	idVec3	*texCoords = ( idVec3 * ) _alloca16( size );
	
	const idDrawVert *verts = surf->geo->verts;
	
	for( int i = 0; i < numVerts; i++ )
	{
		idVec3 v;
		
		v[0] = verts[i].xyz[0] - localViewOrigin[0];
		v[1] = verts[i].xyz[1] - localViewOrigin[1];
		v[2] = verts[i].xyz[2] - localViewOrigin[2];
		
		R_LocalPointToGlobal( transform, v, texCoords[i] );
	}
	surf->dynamicTexCoords = vertexCache.AllocFrameTemp( texCoords, size );
}
예제 #24
0
/*
====================
idMD5Mesh::TransformScaledVerts

Special transform to make the mesh seem fat or skinny.  May be used for zombie deaths
====================
*/
void idMD5Mesh::TransformScaledVerts( idDrawVert *verts, const idJointMat *entJoints, float scale ) {
	idVec4 *scaledWeights = (idVec4 *) _alloca16( numWeights * sizeof( scaledWeights[0] ) );
	SIMDProcessor->Mul( scaledWeights[0].ToFloatPtr(), scale, scaledWeights[0].ToFloatPtr(), numWeights * 4 );
	SIMDProcessor->TransformVerts( verts, texCoords.Num(), entJoints, scaledWeights, weightIndex, numWeights );
}
예제 #25
0
파일: AF.cpp 프로젝트: revelator/MHDoom
/*
================
idAF::Load
================
*/
bool idAF::Load( idEntity *ent, const char *fileName )
{
	int i, j;
	const idDeclAF *file;
	const idDeclModelDef *modelDef;
	idRenderModel *model;
	int numJoints;
	idJointMat *joints;
	
	assert( ent );
	
	self = ent;
	physicsObj.SetSelf( self );
	
	if( animator == NULL )
	{
		gameLocal.DWarning( "Couldn't load af '%s' for entity '%s' at (%s): NULL animator\n", name.c_str(), ent->name.c_str(), ent->GetPhysics()->GetOrigin().ToString( 0 ) );
		return false;
	}
	name = fileName;
	name.StripFileExtension();
	
	file = static_cast<const idDeclAF *>( declManager->FindType( DECL_AF, name ) );
	
	if( !file )
	{
		gameLocal.DWarning( "Couldn't load af '%s' for entity '%s' at (%s)\n", name.c_str(), ent->name.c_str(), ent->GetPhysics()->GetOrigin().ToString( 0 ) );
		return false;
	}
	
	if( file->bodies.Num() == 0 || file->bodies[0]->jointName != "origin" )
	{
		gameLocal.DWarning( "idAF::Load: articulated figure '%s' for entity '%s' at (%s) has no body which modifies the origin joint.", name.c_str(), ent->name.c_str(), ent->GetPhysics()->GetOrigin().ToString( 0 ) );
		return false;
	}
	modelDef = animator->ModelDef();
	
	if( modelDef == NULL || modelDef->GetState() == DS_DEFAULTED )
	{
		gameLocal.DWarning( "idAF::Load: articulated figure '%s' for entity '%s' at (%s) has no or defaulted modelDef '%s'", name.c_str(), ent->name.c_str(), ent->GetPhysics()->GetOrigin().ToString( 0 ), modelDef ? modelDef->GetName() : "" );
		return false;
	}
	model = animator->ModelHandle();
	
	if( model == NULL || model->IsDefaultModel() )
	{
		gameLocal.DWarning( "idAF::Load: articulated figure '%s' for entity '%s' at (%s) has no or defaulted model '%s'", name.c_str(), ent->name.c_str(), ent->GetPhysics()->GetOrigin().ToString( 0 ), model ? model->Name() : "" );
		return false;
	}
	
	// get the modified animation
	modifiedAnim = animator->GetAnim( ARTICULATED_FIGURE_ANIM );
	
	if( !modifiedAnim )
	{
		gameLocal.DWarning( "idAF::Load: articulated figure '%s' for entity '%s' at (%s) has no modified animation '%s'", name.c_str(), ent->name.c_str(), ent->GetPhysics()->GetOrigin().ToString( 0 ), ARTICULATED_FIGURE_ANIM );
		return false;
	}
	
	// create the animation frame used to setup the articulated figure
	numJoints = animator->NumJoints();
	joints = ( idJointMat * )_alloca16( numJoints * sizeof( joints[0] ) );
	gameEdit->ANIM_CreateAnimFrame( model, animator->GetAnim( modifiedAnim )->MD5Anim( 0 ), numJoints, joints, 1, animator->ModelDef()->GetVisualOffset(), animator->RemoveOrigin() );
	
	// set all vector positions from model joints
	file->Finish( GetJointTransform, joints, animator );
	
	// initialize articulated figure physics
	physicsObj.SetGravity( gameLocal.GetGravity() );
	physicsObj.SetClipMask( file->clipMask );
	physicsObj.SetDefaultFriction( file->defaultLinearFriction, file->defaultAngularFriction, file->defaultContactFriction );
	physicsObj.SetSuspendSpeed( file->suspendVelocity, file->suspendAcceleration );
	physicsObj.SetSuspendTolerance( file->noMoveTime, file->noMoveTranslation, file->noMoveRotation );
	physicsObj.SetSuspendTime( file->minMoveTime, file->maxMoveTime );
	physicsObj.SetSelfCollision( file->selfCollision );
	
	// clear the list with transforms from joints to bodies
	jointMods.SetNum( 0, false );
	
	// clear the joint to body conversion list
	jointBody.AssureSize( animator->NumJoints() );
	
	for( i = 0; i < jointBody.Num(); i++ )
	{
		jointBody[i] = -1;
	}
	
	// delete any bodies in the physicsObj that are no longer in the idDeclAF
	for( i = 0; i < physicsObj.GetNumBodies(); i++ )
	{
		idAFBody *body = physicsObj.GetBody( i );
		
		for( j = 0; j < file->bodies.Num(); j++ )
		{
			if( file->bodies[j]->name.Icmp( body->GetName() ) == 0 )
			{
				break;
			}
		}
		
		if( j >= file->bodies.Num() )
		{
			physicsObj.DeleteBody( i );
			i--;
		}
	}
	
	// delete any constraints in the physicsObj that are no longer in the idDeclAF
	for( i = 0; i < physicsObj.GetNumConstraints(); i++ )
	{
		idAFConstraint *constraint = physicsObj.GetConstraint( i );
		
		for( j = 0; j < file->constraints.Num(); j++ )
		{
			if( file->constraints[j]->name.Icmp( constraint->GetName() ) == 0 && file->constraints[j]->type == constraint->GetType() )
			{
				break;
			}
		}
		
		if( j >= file->constraints.Num() )
		{
			physicsObj.DeleteConstraint( i );
			i--;
		}
	}
	
	// load bodies from the file
	for( i = 0; i < file->bodies.Num(); i++ )
	{
		LoadBody( file->bodies[i], joints );
	}
	
	// load constraints from the file
	for( i = 0; i < file->constraints.Num(); i++ )
	{
		LoadConstraint( file->constraints[i] );
	}
	
	physicsObj.UpdateClipModels();
	
	// check if each joint is contained by a body
	for( i = 0; i < animator->NumJoints(); i++ )
	{
		if( jointBody[i] == -1 )
		{
			gameLocal.DWarning( "idAF::Load: articulated figure '%s' for entity '%s' at (%s) joint '%s' is not contained by a body", name.c_str(), self->name.c_str(), self->GetPhysics()->GetOrigin().ToString( 0 ), animator->GetJointName( ( jointHandle_t )i ) );
		}
	}
	physicsObj.SetMass( file->totalMass );
	physicsObj.SetChanged();
	
	// disable the articulated figure for collision detection until activated
	physicsObj.DisableClip();
	
	isLoaded = true;
	
	return true;
}
예제 #26
0
/*
=====================
R_CreateVertexProgramTurboShadowVolume

are dangling edges that are outside the light frustum still making planes?
=====================
*/
srfTriangles_t *R_CreateVertexProgramTurboShadowVolume( const idRenderEntityLocal *ent, 
														const srfTriangles_t *tri, const idRenderLightLocal *light,
														srfCullInfo_t &cullInfo ) {
	int		i, j;
	srfTriangles_t	*newTri;
	silEdge_t	*sil;
	const glIndex_t *indexes;
	const byte *facing;

	R_CalcInteractionFacing( ent, tri, light, cullInfo );
	if ( r_useShadowProjectedCull.GetBool() ) {
		R_CalcInteractionCullBits( ent, tri, light, cullInfo );
	}

	int numFaces = tri->numIndexes / 3;
	int	numShadowingFaces = 0;
	facing = cullInfo.facing;

	// if all the triangles are inside the light frustum
	if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.GetBool() ) {

		// count the number of shadowing faces
		for ( i = 0; i < numFaces; i++ ) {
			numShadowingFaces += facing[i];
		}
		numShadowingFaces = numFaces - numShadowingFaces;

	} else {

		// make all triangles that are outside the light frustum "facing", so they won't cast shadows
		indexes = tri->indexes;
		byte *modifyFacing = cullInfo.facing;
		const byte *cullBits = cullInfo.cullBits;
		for ( j = i = 0; i < tri->numIndexes; i += 3, j++ ) {
			if ( !modifyFacing[j] ) {
				int	i1 = indexes[i+0];
				int	i2 = indexes[i+1];
				int	i3 = indexes[i+2];
				if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
					modifyFacing[j] = 1;
				} else {
					numShadowingFaces++;
				}
			}
		}
	}

	if ( !numShadowingFaces ) {
		// no faces are inside the light frustum and still facing the right way
		return NULL;
	}

	// shadowVerts will be NULL on these surfaces, so the shadowVerts will be taken from the ambient surface
	newTri = R_AllocStaticTriSurf();

	newTri->numVerts = tri->numVerts * 2;

	// alloc the max possible size
#ifdef USE_TRI_DATA_ALLOCATOR
	R_AllocStaticTriSurfIndexes( newTri, ( numShadowingFaces + tri->numSilEdges ) * 6 );
	glIndex_t *tempIndexes = newTri->indexes;
	glIndex_t *shadowIndexes = newTri->indexes;
#else
	glIndex_t *tempIndexes = (glIndex_t *)_alloca16( tri->numSilEdges * 6 * sizeof( tempIndexes[0] ) );
	glIndex_t *shadowIndexes = tempIndexes;
#endif

	// create new triangles along sil planes
	for ( sil = tri->silEdges, i = tri->numSilEdges; i > 0; i--, sil++ ) {

		int f1 = facing[sil->p1];
		int f2 = facing[sil->p2];

		if ( !( f1 ^ f2 ) ) {
			continue;
		}

		int v1 = sil->v1 << 1;
		int v2 = sil->v2 << 1;

		// set the two triangle winding orders based on facing
		// without using a poorly-predictable branch

		shadowIndexes[0] = v1;
		shadowIndexes[1] = v2 ^ f1;
		shadowIndexes[2] = v2 ^ f2;
		shadowIndexes[3] = v1 ^ f2;
		shadowIndexes[4] = v1 ^ f1;
		shadowIndexes[5] = v2 ^ 1;

		shadowIndexes += 6;
	}

	int	numShadowIndexes = shadowIndexes - tempIndexes;

	// we aren't bothering to separate front and back caps on these
	newTri->numIndexes = newTri->numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
	newTri->numShadowIndexesNoCaps = numShadowIndexes;
	newTri->shadowCapPlaneBits = SHADOW_CAP_INFINITE;

#ifdef USE_TRI_DATA_ALLOCATOR
	// decrease the size of the memory block to only store the used indexes
	R_ResizeStaticTriSurfIndexes( newTri, newTri->numIndexes );
#else
	// allocate memory for the indexes
	R_AllocStaticTriSurfIndexes( newTri, newTri->numIndexes );
	// copy the indexes we created for the sil planes
	SIMDProcessor->Memcpy( newTri->indexes, tempIndexes, numShadowIndexes * sizeof( tempIndexes[0] ) );
#endif

	// these have no effect, because they extend to infinity
	newTri->bounds.Clear();

	// put some faces on the model and some on the distant projection
	indexes = tri->indexes;
	shadowIndexes = newTri->indexes + numShadowIndexes;
	for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
		if ( facing[j] ) {
			continue;
		}

		int i0 = indexes[i+0] << 1;
		shadowIndexes[2] = i0;
		shadowIndexes[3] = i0 ^ 1;
		int i1 = indexes[i+1] << 1;
		shadowIndexes[1] = i1;
		shadowIndexes[4] = i1 ^ 1;
		int i2 = indexes[i+2] << 1;
		shadowIndexes[0] = i2;
		shadowIndexes[5] = i2 ^ 1;

		shadowIndexes += 6;
	}

	return newTri;
}
예제 #27
0
/*
================
MMX_Memcpy2kB

  240MB/sec
================
*/
void MMX_Memcpy2kB( void *dest, const void *src, const int count ) {
	byte *tbuf = (byte *)_alloca16(2048);
	__asm { 
		push	ebx
        mov		esi, src
        mov		ebx, count
        shr		ebx, 11		// 2048 bytes at a time 
        mov		edi, dest

loop2k:
        push	edi			// copy 2k into temporary buffer
        mov		edi, tbuf
        mov		ecx, 32

loopMemToL1: 
        prefetchnta 64[ESI] // Prefetch next loop, non-temporal
        prefetchnta 96[ESI]

        movq mm1,  0[ESI]	// Read in source data
        movq mm2,  8[ESI]
        movq mm3, 16[ESI]
        movq mm4, 24[ESI]
        movq mm5, 32[ESI]
        movq mm6, 40[ESI]
        movq mm7, 48[ESI]
        movq mm0, 56[ESI]

        movq  0[EDI], mm1	// Store into L1
        movq  8[EDI], mm2
        movq 16[EDI], mm3
        movq 24[EDI], mm4
        movq 32[EDI], mm5
        movq 40[EDI], mm6
        movq 48[EDI], mm7
        movq 56[EDI], mm0
        add		esi, 64
        add		edi, 64
        dec		ecx
        jnz		loopMemToL1

        pop		edi			// Now copy from L1 to system memory
        push	esi
        mov		esi, tbuf
        mov		ecx, 32

loopL1ToMem:
        movq mm1, 0[ESI]	// Read in source data from L1
        movq mm2, 8[ESI]
        movq mm3, 16[ESI]
        movq mm4, 24[ESI]
        movq mm5, 32[ESI]
        movq mm6, 40[ESI]
        movq mm7, 48[ESI]
        movq mm0, 56[ESI]

        movntq 0[EDI], mm1	// Non-temporal stores
        movntq 8[EDI], mm2
        movntq 16[EDI], mm3
        movntq 24[EDI], mm4
        movntq 32[EDI], mm5
        movntq 40[EDI], mm6
        movntq 48[EDI], mm7
        movntq 56[EDI], mm0

        add		esi, 64
        add		edi, 64
        dec		ecx
        jnz		loopL1ToMem

        pop		esi			// Do next 2k block
        dec		ebx
        jnz		loop2k
		pop		ebx
	}
	EMMS_INSTRUCTION
}
예제 #28
0
/*
====================
idRenderModelMD5::LoadModel

used for initial loads, reloadModel, and reloading the data of purged models
Upon exit, the model will absolutely be valid, but possibly as a default model
====================
*/
void idRenderModelMD5::LoadModel()
{

	int			version;
	int			num;
	int			parentNum;
	idToken		token;
	idLexer		parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS );
	
	if( !purged )
	{
		PurgeModel();
	}
	purged = false;
	
	if( !parser.LoadFile( name ) )
	{
		MakeDefaultModel();
		return;
	}
	
	parser.ExpectTokenString( MD5_VERSION_STRING );
	version = parser.ParseInt();
	
	if( version != MD5_VERSION )
	{
		parser.Error( "Invalid version %d.  Should be version %d\n", version, MD5_VERSION );
	}
	
	//
	// skip commandline
	//
	parser.ExpectTokenString( "commandline" );
	parser.ReadToken( &token );
	
	// parse num joints
	parser.ExpectTokenString( "numJoints" );
	num  = parser.ParseInt();
	joints.SetGranularity( 1 );
	joints.SetNum( num );
	defaultPose.SetGranularity( 1 );
	defaultPose.SetNum( num );
	
	// parse num meshes
	parser.ExpectTokenString( "numMeshes" );
	num = parser.ParseInt();
	if( num < 0 )
	{
		parser.Error( "Invalid size: %d", num );
	}
	meshes.SetGranularity( 1 );
	meshes.SetNum( num );
	
	//
	// parse joints
	//
	parser.ExpectTokenString( "joints" );
	parser.ExpectTokenString( "{" );
	idJointMat* poseMat = ( idJointMat* )_alloca16( joints.Num() * sizeof( poseMat[0] ) );
	for( int i = 0; i < joints.Num(); i++ )
	{
		idMD5Joint* joint = &joints[i];
		idJointQuat*	 pose = &defaultPose[i];
		
		ParseJoint( parser, joint, pose );
		poseMat[ i ].SetRotation( pose->q.ToMat3() );
		poseMat[ i ].SetTranslation( pose->t );
		if( joint->parent )
		{
			parentNum = joint->parent - joints.Ptr();
			pose->q = ( poseMat[ i ].ToMat3() * poseMat[ parentNum ].ToMat3().Transpose() ).ToQuat();
			pose->t = ( poseMat[ i ].ToVec3() - poseMat[ parentNum ].ToVec3() ) * poseMat[ parentNum ].ToMat3().Transpose();
		}
	}
	parser.ExpectTokenString( "}" );
	
	//-----------------------------------------
	// create the inverse of the base pose joints to support tech6 style deformation
	// of base pose vertexes, normals, and tangents.
	//
	// vertex * joints * inverseJoints == vertex when joints is the base pose
	// When the joints are in another pose, it gives the animated vertex position
	//-----------------------------------------
	invertedDefaultPose.SetNum( SIMD_ROUND_JOINTS( joints.Num() ) );
	for( int i = 0; i < joints.Num(); i++ )
	{
		invertedDefaultPose[i] = poseMat[i];
		invertedDefaultPose[i].Invert();
	}
	SIMD_INIT_LAST_JOINT( invertedDefaultPose.Ptr(), joints.Num() );
	
	for( int i = 0; i < meshes.Num(); i++ )
	{
		parser.ExpectTokenString( "mesh" );
		meshes[i].ParseMesh( parser, defaultPose.Num(), poseMat );
	}
	
	// calculate the bounds of the model
	bounds.Clear();
	for( int i = 0; i < meshes.Num(); i++ )
	{
		idBounds meshBounds;
		meshes[i].CalculateBounds( poseMat, meshBounds );
		bounds.AddBounds( meshBounds );
	}
	
	// set the timestamp for reloadmodels
	fileSystem->ReadFile( name, NULL, &timeStamp );
	
	common->UpdateLevelLoadPacifier(true);
}
예제 #29
0
/*
=================
R_CreateShadowVolumeInFrustum

Adds new verts and indexes to the shadow volume.

If the frustum completely defines the projected light,
makeClippedPlanes should be true, which will cause sil quads to
be added along all clipped edges.

If the frustum is just part of a point light, clipped planes don't
need to be added.
=================
*/
static void R_CreateShadowVolumeInFrustum( const idRenderEntityLocal *ent, 
										  const srfTriangles_t *tri,
										  const idRenderLightLocal *light,									
										  const idVec3 lightOrigin,
										  const idPlane frustum[6],
										  const idPlane &farPlane,
										  bool makeClippedPlanes ) {
	int		i;
	int		numTris;
	unsigned short		*pointCull;
	int		numCapIndexes;
	int		firstShadowIndex;
	int		firstShadowVert;
	int		cullBits;

	pointCull = (unsigned short *)_alloca16( tri->numVerts * sizeof( pointCull[0] ) );

	// test the vertexes for inside the light frustum, which will allow
	// us to completely cull away some triangles from consideration.
	R_CalcPointCull( tri, frustum, pointCull );

	// this may not be the first frustum added to the volume
	firstShadowIndex = numShadowIndexes;
	firstShadowVert = numShadowVerts;

	// decide which triangles front shadow volumes, clipping as needed
	int numFace = 0;
	numClipSilEdges = 0;
	numTris = tri->numIndexes / 3;
	for ( i = 0 ; i < numTris ; i++ ) {
		int		i1, i2, i3;

		faceCastsShadow[i] = 0;	// until shown otherwise

		// if it isn't facing the right way, don't add it
		// to the shadow volume
		if ( globalFacing[i] ) {
			continue;
		}
		++numFace;

		i1 = tri->silIndexes[ i*3 + 0 ];
		i2 = tri->silIndexes[ i*3 + 1 ];
		i3 = tri->silIndexes[ i*3 + 2 ];

		// if all the verts are off one side of the frustum,
		// don't add any of them
		if ( TRIANGLE_CULLED( i1, i2, i3 ) ) {
			continue;
		}

		// make sure the verts that are not on the negative sides
		// of the frustum are copied over.
		// we need to get the original verts even from clipped triangles
		// so the edges reference correctly, because an edge may be unclipped
		// even when a triangle is clipped.
		if ( numShadowVerts + 6 > MAX_SHADOW_VERTS ) {
			overflowed = true;
			return;
		}

		if ( !POINT_CULLED(i1) && remap[i1] == -1 ) {
			remap[i1] = numShadowVerts;
			shadowVerts[ numShadowVerts ].ToVec3() = tri->verts[i1].xyz;
			numShadowVerts+=2;
		}
		if ( !POINT_CULLED(i2) && remap[i2] == -1 ) {
			remap[i2] = numShadowVerts;
			shadowVerts[ numShadowVerts ].ToVec3() = tri->verts[i2].xyz;
			numShadowVerts+=2;
		}
		if ( !POINT_CULLED(i3) && remap[i3] == -1 ) {
			remap[i3] = numShadowVerts;
			shadowVerts[ numShadowVerts ].ToVec3() = tri->verts[i3].xyz;
			numShadowVerts+=2;
		}

		// clip the triangle if any points are on the negative sides
		if ( TRIANGLE_CLIPPED( i1, i2, i3 ) ) {
			cullBits = ( ( pointCull[ i1 ] ^ 0xfc0 ) | ( pointCull[ i2 ] ^ 0xfc0 ) | ( pointCull[ i3 ] ^ 0xfc0 ) ) >> 6;
			// this will also define clip edges that will become
			// silhouette planes
			if ( R_ClipTriangleToLight( tri->verts[i1].xyz, tri->verts[i2].xyz, 
				tri->verts[i3].xyz, cullBits, frustum ) ) {
				faceCastsShadow[i] = 1;
			}
		} else {
			// instead of overflowing or drawing a streamer shadow, don't draw a shadow at all
			if ( numShadowIndexes + 3 > MAX_SHADOW_INDEXES ) {
				overflowed = true;
				return;
			}
			if ( remap[i1] == -1 || remap[i2] == -1 || remap[i3] == -1 ) {
				common->Error( "R_CreateShadowVolumeInFrustum: bad remap[]" );
			}
			shadowIndexes[numShadowIndexes++] = remap[i3];
			shadowIndexes[numShadowIndexes++] = remap[i2];
			shadowIndexes[numShadowIndexes++] = remap[i1];
			faceCastsShadow[i] = 1;
		}
	}
예제 #30
0
파일: IK.cpp 프로젝트: Deepfreeze32/taken
/*
================
idIK_Walk::Init
================
*/
bool idIK_Walk::Init( idEntity *self, const char *anim, const idVec3 &modelOffset ) {
	int i;
	float footSize;
	idVec3 verts[4];
	idTraceModel trm;
	const char *jointName;
	idVec3 dir, ankleOrigin, kneeOrigin, hipOrigin, dirOrigin;
	idMat3 axis, ankleAxis, kneeAxis, hipAxis;

	static idVec3 footWinding[4] = {
		idVec3(  1.0f,  1.0f, 0.0f ),
		idVec3( -1.0f,  1.0f, 0.0f ),
		idVec3( -1.0f, -1.0f, 0.0f ),
		idVec3(  1.0f, -1.0f, 0.0f )
	};

	if ( !self ) {
		return false;
	}

	numLegs = Min( self->spawnArgs.GetInt( "ik_numLegs", "0" ), MAX_LEGS );
	if ( numLegs == 0 ) {
		return true;
	}

	if ( !idIK::Init( self, anim, modelOffset ) ) {
		return false;
	}

	int numJoints = animator->NumJoints();
	idJointMat *joints = ( idJointMat * )_alloca16( numJoints * sizeof( joints[0] ) );

	// create the animation frame used to setup the IK
	gameEdit->ANIM_CreateAnimFrame( animator->ModelHandle(), animator->GetAnim( modifiedAnim )->MD5Anim( 0 ), numJoints, joints, 1, animator->ModelDef()->GetVisualOffset() + modelOffset, animator->RemoveOrigin() );

	enabledLegs = 0;

	// get all the joints
	for ( i = 0; i < numLegs; i++ ) {

		jointName = self->spawnArgs.GetString( va( "ik_foot%d", i+1 ) );
		footJoints[i] = animator->GetJointHandle( jointName );
		if ( footJoints[i] == INVALID_JOINT ) {
			gameLocal.Error( "idIK_Walk::Init: invalid foot joint '%s'", jointName );
		}

		jointName = self->spawnArgs.GetString( va( "ik_ankle%d", i+1 ) );
		ankleJoints[i] = animator->GetJointHandle( jointName );
		if ( ankleJoints[i] == INVALID_JOINT ) {
			gameLocal.Error( "idIK_Walk::Init: invalid ankle joint '%s'", jointName );
		}

		jointName = self->spawnArgs.GetString( va( "ik_knee%d", i+1 ) );
		kneeJoints[i] = animator->GetJointHandle( jointName );
		if ( kneeJoints[i] == INVALID_JOINT ) {
			gameLocal.Error( "idIK_Walk::Init: invalid knee joint '%s'\n", jointName );
		}

		jointName = self->spawnArgs.GetString( va( "ik_hip%d", i+1 ) );
		hipJoints[i] = animator->GetJointHandle( jointName );
		if ( hipJoints[i] == INVALID_JOINT ) {
			gameLocal.Error( "idIK_Walk::Init: invalid hip joint '%s'\n", jointName );
		}

		jointName = self->spawnArgs.GetString( va( "ik_dir%d", i+1 ) );
		dirJoints[i] = animator->GetJointHandle( jointName );

		enabledLegs |= 1 << i;
	}

	jointName = self->spawnArgs.GetString( "ik_waist" );
	waistJoint = animator->GetJointHandle( jointName );
	if ( waistJoint == INVALID_JOINT ) {
		gameLocal.Error( "idIK_Walk::Init: invalid waist joint '%s'\n", jointName );
	}

	// get the leg bone lengths and rotation matrices
	for ( i = 0; i < numLegs; i++ ) {
		oldAnkleHeights[i] = 0.0f;

		ankleAxis = joints[ ankleJoints[ i ] ].ToMat3();
		ankleOrigin = joints[ ankleJoints[ i ] ].ToVec3();

		kneeAxis = joints[ kneeJoints[ i ] ].ToMat3();
		kneeOrigin = joints[ kneeJoints[ i ] ].ToVec3();

		hipAxis = joints[ hipJoints[ i ] ].ToMat3();
		hipOrigin = joints[ hipJoints[ i ] ].ToVec3();

		// get the IK direction
		if ( dirJoints[i] != INVALID_JOINT ) {
			dirOrigin = joints[ dirJoints[ i ] ].ToVec3();
			dir = dirOrigin - kneeOrigin;
		} else {
			dir.Set( 1.0f, 0.0f, 0.0f );
		}

		hipForward[i] = dir * hipAxis.Transpose();
		kneeForward[i] = dir * kneeAxis.Transpose();

		// conversion from upper leg bone axis to hip joint axis
		upperLegLength[i] = GetBoneAxis( hipOrigin, kneeOrigin, dir, axis );
		upperLegToHipJoint[i] = hipAxis * axis.Transpose();

		// conversion from lower leg bone axis to knee joint axis
		lowerLegLength[i] = GetBoneAxis( kneeOrigin, ankleOrigin, dir, axis );
		lowerLegToKneeJoint[i] = kneeAxis * axis.Transpose();
	}

	smoothing = self->spawnArgs.GetFloat( "ik_smoothing", "0.75" );
	waistSmoothing = self->spawnArgs.GetFloat( "ik_waistSmoothing", "0.75" );
	footShift = self->spawnArgs.GetFloat( "ik_footShift", "0" );
	waistShift = self->spawnArgs.GetFloat( "ik_waistShift", "0" );
	minWaistFloorDist = self->spawnArgs.GetFloat( "ik_minWaistFloorDist", "0" );
	minWaistAnkleDist = self->spawnArgs.GetFloat( "ik_minWaistAnkleDist", "0" );
	footUpTrace = self->spawnArgs.GetFloat( "ik_footUpTrace", "32" );
	footDownTrace = self->spawnArgs.GetFloat( "ik_footDownTrace", "32" );
	tiltWaist = self->spawnArgs.GetBool( "ik_tiltWaist", "0" );
	usePivot = self->spawnArgs.GetBool( "ik_usePivot", "0" );

	// setup a clip model for the feet
	footSize = self->spawnArgs.GetFloat( "ik_footSize", "4" ) * 0.5f;
	if ( footSize > 0.0f ) {
		for ( i = 0; i < 4; i++ ) {
			verts[i] = footWinding[i] * footSize;
		}
		trm.SetupPolygon( verts, 4 );
		footModel = new (TAG_PHYSICS_CLIP) idClipModel( trm );
	}

	initialized = true;

	return true;
}