Ejemplo n.º 1
0
void G2API_CollisionDetect(CollisionRecord_t *collRecMap, CGhoul2Info_v &ghoul2, const vec3_t angles, const vec3_t position,
										  int frameNumber, int entNum, vec3_t rayStart, vec3_t rayEnd, vec3_t scale, CMiniHeap *G2VertSpace, int traceFlags, int useLod)
{

	if ((int)&ghoul2)
	{
		vec3_t	transRayStart, transRayEnd;

		// make sure we have transformed the whole skeletons for each model
		G2_ConstructGhoulSkeleton(ghoul2, frameNumber, NULL, true, angles, position, scale, false);

		// pre generate the world matrix - used to transform the incoming ray
		G2_GenerateWorldMatrix(angles, position);

		// now having done that, time to build the model
		G2_TransformModel(ghoul2, frameNumber, scale, G2VertSpace, useLod);

		// model is built. Lets check to see if any triangles are actually hit.
		// first up, translate the ray to model space
		TransformAndTranslatePoint(rayStart, transRayStart, &worldMatrixInv);
		TransformAndTranslatePoint(rayEnd, transRayEnd, &worldMatrixInv);

		// now walk each model and check the ray against each poly - sigh, this is SO expensive. I wish there was a better way to do this.
		G2_TraceModels(ghoul2, transRayStart, transRayEnd, collRecMap, entNum, traceFlags, useLod);

		// now sort the resulting array of collision records so they are distance ordered
		qsort( collRecMap, MAX_G2_COLLISIONS, 
			sizeof( CCollisionRecord ), QsortDistance );

	}
}
Ejemplo n.º 2
0
void G2API_AddSkinGore(CGhoul2Info_v &ghoul2,SSkinGoreData &gore)
{
	if (VectorLength(gore.rayDirection)<.1f)
	{
		assert(0); // can't add gore without a shot direction
		return;
	}

	// make sure we have transformed the whole skeletons for each model
	G2_ConstructGhoulSkeleton(ghoul2, gore.currentTime, NULL, true, gore.angles, gore.position, gore.scale, false);

	// pre generate the world matrix - used to transform the incoming ray
	G2_GenerateWorldMatrix(gore.angles, gore.position);

	// first up, translate the ray to model space
	vec3_t	transRayDirection, transHitLocation;
	TransformAndTranslatePoint(gore.hitLocation, transHitLocation, &worldMatrixInv);
	TransformPoint(gore.rayDirection, transRayDirection, &worldMatrixInv);

	int lod;
	ResetGoreTag();
	for (lod=0;lod<4;lod++)
	{
		// now having done that, time to build the model
		// FIXME: where does G2VertSpaceServer come from?
//		G2_TransformModel(ghoul2, gore.currentTime, gore.scale,G2VertSpaceServer, lod,true);

		// now walk each model and compute new texture coordinates
		G2_TraceModels(ghoul2, transHitLocation, transRayDirection, 0, gore.entNum, 0, lod);
	}
}
Ejemplo n.º 3
0
void G2API_CollisionDetect(CollisionRecord_t *collRecMap, g2handle_t g2h, const vec3_t angles, const vec3_t position, int frameNumber, int entNum, const vec3_t rayStart, const vec3_t rayEnd, const vec3_t scale, CMiniHeap *G2VertSpace, int traceFlags, int useLod, float fRadius)
{

	CGhoul2Info_v *ghoul2 = G2API_GetGhoul2Model(g2h);

	if (ghoul2)
	{
		vec3_t	transRayStart, transRayEnd;

		// make sure we have transformed the whole skeletons for each model
		G2_ConstructGhoulSkeleton(*ghoul2, frameNumber, NULL, true, angles, position, scale, false);

		// pre generate the world matrix - used to transform the incoming ray
		G2_GenerateWorldMatrix(angles, position);

#ifdef G2_COLLISION_ENABLED
		G2VertSpace->ResetHeap();
#endif

		// now having done that, time to build the model
		G2_TransformModel(*ghoul2, frameNumber, scale, G2VertSpace, useLod);

		// model is built. Lets check to see if any triangles are actually hit.
		// first up, translate the ray to model space
		TransformAndTranslatePoint(rayStart, transRayStart, &worldMatrixInv);
		TransformAndTranslatePoint(rayEnd, transRayEnd, &worldMatrixInv);

		// now walk each model and check the ray against each poly - sigh, this is SO expensive. I wish there was a better way to do this.
		G2_TraceModels(*ghoul2, transRayStart, transRayEnd, collRecMap, entNum, traceFlags, useLod, fRadius);
#ifdef G2_COLLISION_ENABLED
		int i;
		for ( i = 0; i < MAX_G2_COLLISIONS && collRecMap[i].mEntityNum != -1; i ++ );

		// now sort the resulting array of collision records so they are distance ordered
		qsort( collRecMap, i,
			sizeof( CCollisionRecord ), QsortDistance );

#else
		// now sort the resulting array of collision records so they are distance ordered
		qsort( collRecMap, MAX_G2_COLLISIONS,
			sizeof( CCollisionRecord ), QsortDistance );
#endif

	}
}
Ejemplo n.º 4
0
// now we're at poly level, check each model space transformed poly against the model world transfomed ray
static bool G2_RadiusTracePolys(
								const mdxmSurface_t *surface, 
								CTraceSurface &TS
								)
{
	int	i,j;
	vec3_t basis1;
	vec3_t basis2;
	vec3_t taxis;
	vec3_t saxis;

	basis2[0]=0.0f;
	basis2[1]=0.0f;
	basis2[2]=1.0f;

	vec3_t v3RayDir;
	VectorSubtract(TS.rayEnd, TS.rayStart, v3RayDir);

	CrossProduct(v3RayDir,basis2,basis1);

	if (DotProduct(basis1,basis1)<.1f)
	{
		basis2[0]=0.0f;
		basis2[1]=1.0f;
		basis2[2]=0.0f;
		CrossProduct(v3RayDir,basis2,basis1);
	}

	CrossProduct(v3RayDir,basis1,basis2);
	// Give me a shot direction not a bunch of zeros :) -Gil
//	assert(DotProduct(basis1,basis1)>.0001f);
//	assert(DotProduct(basis2,basis2)>.0001f);

	VectorNormalize(basis1);
	VectorNormalize(basis2);

	const float c=cosf(0);//theta
	const float s=sinf(0);//theta

	VectorScale(basis1, 0.5f * c / TS.m_fRadius,taxis);
	VectorMA(taxis,     0.5f * s / TS.m_fRadius,basis2,taxis);

	VectorScale(basis1,-0.5f * s /TS.m_fRadius,saxis);
	VectorMA(    saxis, 0.5f * c /TS.m_fRadius,basis2,saxis);

	const float * const verts = (float *)TS.TransformedVertsArray[surface->thisSurfaceIndex];
	const int numVerts = surface->numVerts;
	
	int flags=63;
	//rayDir/=lengthSquared(raydir);
	const float f = VectorLengthSquared(v3RayDir); 
	v3RayDir[0]/=f;
	v3RayDir[1]/=f;
	v3RayDir[2]/=f;

	for ( j = 0; j < numVerts; j++ ) 
	{
		const int pos=j*5;
		vec3_t delta;
		delta[0]=verts[pos+0]-TS.rayStart[0];
		delta[1]=verts[pos+1]-TS.rayStart[1];
		delta[2]=verts[pos+2]-TS.rayStart[2];
		const float s=DotProduct(delta,saxis)+0.5f;
		const float t=DotProduct(delta,taxis)+0.5f;
		const float u=DotProduct(delta,v3RayDir);
		int vflags=0;

		if (s>0)
		{
			vflags|=1;
		}
		if (s<1)
		{
			vflags|=2;
		}
		if (t>0)
		{
			vflags|=4;
		}
		if (t<1)
		{
			vflags|=8;
		}
		if (u>0)
		{
			vflags|=16;
		}
		if (u<1)
		{
			vflags|=32;
		}

		vflags=(~vflags);
		flags&=vflags;
		GoreVerts[j].flags=vflags;
	}

	if (flags)
	{
		return false; // completely off the gore splotch  (so presumably hit nothing? -Ste)
	}
	const int numTris = surface->numTriangles;
	const mdxmTriangle_t * const tris = (mdxmTriangle_t *) ((byte *)surface + surface->ofsTriangles);

	for ( j = 0; j < numTris; j++ ) 
	{
		assert(tris[j].indexes[0]>=0&&tris[j].indexes[0]<numVerts);
		assert(tris[j].indexes[1]>=0&&tris[j].indexes[1]<numVerts);
		assert(tris[j].indexes[2]>=0&&tris[j].indexes[2]<numVerts);
		flags=63&
			GoreVerts[tris[j].indexes[0]].flags&
			GoreVerts[tris[j].indexes[1]].flags&
			GoreVerts[tris[j].indexes[2]].flags;
		if (flags)
		{
			continue;
		}
		else
		{
			// we hit a triangle, so init a collision record...
			//
			for (i=0; i<MAX_G2_COLLISIONS;i++)
			{
				if (TS.collRecMap[i].mEntityNum == -1)
				{
					CCollisionRecord  	&newCol = TS.collRecMap[i];
					
					newCol.mPolyIndex = j;
					newCol.mEntityNum = TS.entNum;
					newCol.mSurfaceIndex = surface->thisSurfaceIndex;
					newCol.mModelIndex = TS.modelIndex;
//					if (face>0)
//					{
						newCol.mFlags = G2_FRONTFACE;
//					}
//					else
//					{
//						newCol.mFlags = G2_BACKFACE;
//					}

					//get normal from triangle				
					const float *A = &verts[(tris[j].indexes[0] * 5)];
					const float *B = &verts[(tris[j].indexes[1] * 5)];
					const float *C = &verts[(tris[j].indexes[2] * 5)];
					vec3_t normal;
					vec3_t edgeAC, edgeBA;

					VectorSubtract(C, A, edgeAC);
					VectorSubtract(B, A, edgeBA);
					CrossProduct(edgeBA, edgeAC, normal);

					// transform normal (but don't translate) into world angles
					TransformPoint(normal, newCol.mCollisionNormal, &worldMatrix);
					VectorNormalize(newCol.mCollisionNormal);

					newCol.mMaterial = newCol.mLocation = 0;
					// exit now if we should
					if (TS.eG2TraceType == G2_RETURNONHIT)
					{
						TS.hitOne = true;
						return true;
					}

					//i don't know the hitPoint, but let's just assume it's the first vert for now...
					const float *hitPoint = A;
					vec3_t			  distVect;

					VectorSubtract(hitPoint, TS.rayStart, distVect);
					newCol.mDistance = VectorLength(distVect);

					// put the hit point back into world space
					TransformAndTranslatePoint(hitPoint, newCol.mCollisionPosition, &worldMatrix);
					newCol.mBarycentricI = newCol.mBarycentricJ = 0.0f;

					break;
				}
			}
			if (i==MAX_G2_COLLISIONS)
			{
				//assert(i!=MAX_G2_COLLISIONS);		// run out of collision record space - happens OFTEN
				TS.hitOne = true;	//force stop recursion
				return true;	// return true to avoid wasting further time, but no hit will result without a record
			}
		}
	}

	return false;
}
Ejemplo n.º 5
0
// now we're at poly level, check each model space transformed poly against the model world transfomed ray
static bool G2_TracePolys(const mdxmSurface_t *surface, const mdxmSurfHierarchy_t *surfInfo, CTraceSurface &TS)
{
	int				i, j, numTris;
	
	// whip through and actually transform each vertex
	const mdxmTriangle_t *tris = (mdxmTriangle_t *) ((byte *)surface + surface->ofsTriangles);
	const float *verts = (float *)TS.TransformedVertsArray[surface->thisSurfaceIndex];
	numTris = surface->numTriangles;
	for ( j = 0; j < numTris; j++ ) 
	{
		float			face;
		vec3_t	hitPoint, normal;
		// determine actual coords for this triangle
		const float *point1 = &verts[(tris[j].indexes[0] * 5)];
		const float *point2 = &verts[(tris[j].indexes[1] * 5)];
		const float *point3 = &verts[(tris[j].indexes[2] * 5)];
		// did we hit it?
		if (G2_SegmentTriangleTest(TS.rayStart, TS.rayEnd, point1, point2, point3, qtrue, qtrue, hitPoint, normal, &face))
		{	// find space in the collision records for this record
			for (i=0; i<MAX_G2_COLLISIONS;i++)
			{
				if (TS.collRecMap[i].mEntityNum == -1)
				{
					CCollisionRecord  	&newCol = TS.collRecMap[i];
					vec3_t			  	distVect;
					float				x_pos = 0, y_pos = 0;
					
					newCol.mPolyIndex = j;
					newCol.mEntityNum = TS.entNum;
					newCol.mSurfaceIndex = surface->thisSurfaceIndex;
					newCol.mModelIndex = TS.modelIndex;
					if (face>0)
					{
						newCol.mFlags = G2_FRONTFACE;
					}
					else
					{
						newCol.mFlags = G2_BACKFACE;
					}

					VectorSubtract(hitPoint, TS.rayStart, distVect);
					newCol.mDistance = VectorLength(distVect);

					// put the hit point back into world space
					TransformAndTranslatePoint(hitPoint, newCol.mCollisionPosition, &worldMatrix);

					// transform normal (but don't translate) into world angles
					TransformPoint(normal, newCol.mCollisionNormal, &worldMatrix);
					VectorNormalize(newCol.mCollisionNormal);

					newCol.mMaterial = newCol.mLocation = 0;

					// Determine our location within the texture, and barycentric coordinates
					G2_BuildHitPointST(point1, point1[3], point1[4],
									   point2, point2[3], point2[4],
									   point3, point3[3], point3[4],
									   hitPoint, &x_pos, &y_pos,newCol.mBarycentricI,newCol.mBarycentricJ); 
									
/*
					const shader_t		*shader = 0;
					// now, we know what surface this hit belongs to, we need to go get the shader handle so we can get the correct hit location and hit material info
					if ( cust_shader ) 
					{
						shader = cust_shader;
					} 
					else if ( skin ) 
					{
						int		j;
							
						// match the surface name to something in the skin file
						shader = tr.defaultShader;
						for ( j = 0 ; j < skin->numSurfaces ; j++ )
						{
							// the names have both been lowercased
							if ( !strcmp( skin->surfaces[j]->name, surfInfo->name ) ) 
							{
								shader = skin->surfaces[j]->shader;
								break;
							}
						}
					} 
					else 
					{
						shader = R_GetShaderByHandle( surfInfo->shaderIndex );
					}

					// do we even care to decide what the hit or location area's are? If we don't have them in the shader there is little point
					if ((shader->hitLocation) || (shader->hitMaterial))
					{
 						// ok, we have a floating point position. - determine location in data we need to look at
						if (shader->hitLocation)
						{
							newCol.mLocation = *(hitMatReg[shader->hitLocation].loc +
												((int)(y_pos * hitMatReg[shader->hitLocation].height) * hitMatReg[shader->hitLocation].width) +
												((int)(x_pos * hitMatReg[shader->hitLocation].width)));
							Com_Printf("G2_TracePolys hit location: %d\n", newCol.mLocation); 
						}

						if (shader->hitMaterial)
						{
							newCol.mMaterial = *(hitMatReg[shader->hitMaterial].loc +
												((int)(y_pos * hitMatReg[shader->hitMaterial].height) * hitMatReg[shader->hitMaterial].width) +
												((int)(x_pos * hitMatReg[shader->hitMaterial].width)));
						}
					}
*/
					// exit now if we should
					if (TS.eG2TraceType == G2_RETURNONHIT)
					{
						TS.hitOne = true;
						return true;
					}

					break;
				}
			}
			if (i==MAX_G2_COLLISIONS)
			{
				assert(i!=MAX_G2_COLLISIONS);		// run out of collision record space - will probalbly never happen
				TS.hitOne = true;	//force stop recursion
				return true;	// return true to avoid wasting further time, but no hit will result without a record
			}
		}
	}
	return false;
}