Beispiel #1
0
/*
=================
R_BoxSurfaces_r

=================
*/
void R_BoxSurfaces_r(mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **list, int *listbmodel, int listsize, int *listlength, vec3_t dir) {

	int			s, c;
	int *mark;

	// do the tail recursion in a loop
	while ( !node->isLeaf ) {
		s = BoxOnPlaneSide( mins, maxs, node->plane );
		if (s == 1) {
			node = node->children[0];
		} else if (s == 2) {
			node = node->children[1];
		} else {
			R_BoxSurfaces_r(node->children[0], mins, maxs, list, listbmodel, listsize, listlength, dir);
			node = node->children[1];
		}
	}

	// add the individual surfaces
	mark = tr.world->marksurfaces + node->firstmarksurface;
	c = node->nummarksurfaces;
	while (c--) {
		//
		if (*listlength >= listsize) break;
		//
		R_AddSurfaceToList( 0, *mark, mins, maxs, list, listbmodel, listsize, listlength, dir );

		mark++;
	}
}
Beispiel #2
0
void R_BoxSurfaces_r(mnode_t *node, vector3 *mins, vector3 *maxs, surfaceType_t **list, int listsize, int *listlength, vector3 *dir) {

	int			s, c;
	msurface_t	*surf, **mark;

	// do the tail recursion in a loop
	while ( node->contents == -1 ) {
		s = BoxOnPlaneSide( mins, maxs, node->plane );
		if (s == 1) {
			node = node->children[0];
		} else if (s == 2) {
			node = node->children[1];
		} else {
			R_BoxSurfaces_r(node->children[0], mins, maxs, list, listsize, listlength, dir);
			node = node->children[1];
		}
	}

	// add the individual surfaces
	mark = node->firstmarksurface;
	c = node->nummarksurfaces;
	while (c--) {
		//
		if (*listlength >= listsize) break;
		//
		surf = *mark;

		//QtZ: optimization from UrT, this surface has already been checked
		if (surf->viewCount == tr.viewCount)
			continue;

		// check if the surface has NOIMPACT or NOMARKS set
		if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) )
			|| ( surf->shader->contentFlags & CONTENTS_FOG ) ) {
			surf->viewCount = tr.viewCount;
		}
		// extra check for surfaces to avoid list overflows
		else if (*(surf->data) == SF_FACE) {
			// the face plane should go through the box
			s = BoxOnPlaneSide( mins, maxs, &(( srfSurfaceFace_t * ) surf->data)->plane );
			if (s == 1 || s == 2) {
				surf->viewCount = tr.viewCount;
			} else if (DotProduct(&(( srfSurfaceFace_t * ) surf->data)->plane.normal, dir) > -0.5f) {
			// don't add faces that make sharp angles with the projection direction
				surf->viewCount = tr.viewCount;
			}
		}
		else if (*(surfaceType_t *) (surf->data) != SF_GRID &&
			 *(surfaceType_t *) (surf->data) != SF_TRIANGLES)
			surf->viewCount = tr.viewCount;
		// check the viewCount because the surface may have
		// already been added if it spans multiple leafs
		if (surf->viewCount != tr.viewCount) {
			surf->viewCount = tr.viewCount;
			list[*listlength] = (surfaceType_t *) surf->data;
			(*listlength)++;
		}
		mark++;
	}
}
Beispiel #3
0
static void R_BoxSurfaces_r( mbrush46_node_t* node, vec3_t mins, vec3_t maxs,
	idWorldSurface** list, int listsize, int* listlength, vec3_t dir ) {
	// RF, if this node hasn't been rendered recently, ignore it
	if ( GGameType & ( GAME_WolfSP | GAME_WolfMP | GAME_ET ) &&
		 node->visframe < tr.visCount - 2 ) {	// allow us to be a few frames behind
		return;
	}

	// do the tail recursion in a loop
	while ( node->contents == -1 ) {
		int s = BoxOnPlaneSide( mins, maxs, node->plane );
		if ( s == 1 ) {
			node = node->children[ 0 ];
		} else if ( s == 2 ) {
			node = node->children[ 1 ];
		} else {
			R_BoxSurfaces_r( node->children[ 0 ], mins, maxs, list, listsize, listlength, dir );
			node = node->children[ 1 ];
		}
	}

	// Ridah, don't mark alpha surfaces
	if ( GGameType & ( GAME_WolfSP | GAME_WolfMP | GAME_ET ) &&
		 node->contents & BSP46CONTENTS_TRANSLUCENT ) {
		return;
	}

	// add the individual surfaces
	idWorldSurface** mark = node->firstmarksurface;
	int c = node->nummarksurfaces;
	while ( c-- ) {
		if ( *listlength >= listsize ) {
			break;
		}
		idWorldSurface* surf = *mark;
		if ( !surf->CheckAddMarks( mins, maxs, dir ) ) {
			surf->viewCount = tr.viewCount;
		}
		// check the viewCount because the surface may have
		// already been added if it spans multiple leafs
		if ( surf->viewCount != tr.viewCount ) {
			surf->viewCount = tr.viewCount;
			list[ *listlength ] = surf;
			( *listlength )++;
		}
		mark++;
	}
}
Beispiel #4
0
/*
=================
R_MarkFragments

=================
*/
int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
				   int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ) {
	int				numsurfaces, numPlanes;
	int				i, j, k, m, n;
	surfaceType_t	*surfaces[64];
	vec3_t			mins, maxs;
	int				returnedFragments;
	int				returnedPoints;
	vec3_t			normals[MAX_VERTS_ON_POLY+2];
	float			dists[MAX_VERTS_ON_POLY+2];
	vec3_t			clipPoints[2][MAX_VERTS_ON_POLY];
	int				numClipPoints;
	float			*v;
	srfSurfaceFace_t *surf;
	srfGridMesh_t	*cv;
	drawVert_t		*dv;
	vec3_t			normal;
	vec3_t			projectionDir;
	vec3_t			v1, v2;
	int				*indexes;

	//increment view count for double check prevention
	tr.viewCount++;

	//
	VectorNormalize2( projection, projectionDir );
	// find all the brushes that are to be considered
	ClearBounds( mins, maxs );
	for ( i = 0 ; i < numPoints ; i++ ) {
		vec3_t	temp;

		AddPointToBounds( points[i], mins, maxs );
		VectorAdd( points[i], projection, temp );
		AddPointToBounds( temp, mins, maxs );
		// make sure we get all the leafs (also the one(s) in front of the hit surface)
		VectorMA( points[i], -20, projectionDir, temp );
		AddPointToBounds( temp, mins, maxs );
	}

	if (numPoints > MAX_VERTS_ON_POLY) numPoints = MAX_VERTS_ON_POLY;
	// create the bounding planes for the to be projected polygon
	for ( i = 0 ; i < numPoints ; i++ ) {
		VectorSubtract(points[(i+1)%numPoints], points[i], v1);
		VectorAdd(points[i], projection, v2);
		VectorSubtract(points[i], v2, v2);
		CrossProduct(v1, v2, normals[i]);
		VectorNormalizeFast(normals[i]);
		dists[i] = DotProduct(normals[i], points[i]);
	}
	// add near and far clipping planes for projection
	VectorCopy(projectionDir, normals[numPoints]);
	dists[numPoints] = DotProduct(normals[numPoints], points[0]) - 32;
	VectorCopy(projectionDir, normals[numPoints+1]);
	VectorInverse(normals[numPoints+1]);
	dists[numPoints+1] = DotProduct(normals[numPoints+1], points[0]) - 20;
	numPlanes = numPoints + 2;

	numsurfaces = 0;
	R_BoxSurfaces_r(tr.world->nodes, mins, maxs, surfaces, 64, &numsurfaces, projectionDir);
	//assert(numsurfaces <= 64);
	//assert(numsurfaces != 64);

	returnedPoints = 0;
	returnedFragments = 0;

	for ( i = 0 ; i < numsurfaces ; i++ ) {

		if (*surfaces[i] == SF_GRID) {

			cv = (srfGridMesh_t *) surfaces[i];
			for ( m = 0 ; m < cv->height - 1 ; m++ ) {
				for ( n = 0 ; n < cv->width - 1 ; n++ ) {
					// We triangulate the grid and chop all triangles within
					// the bounding planes of the to be projected polygon.
					// LOD is not taken into account, not such a big deal though.
					//
					// It's probably much nicer to chop the grid itself and deal
					// with this grid as a normal SF_GRID surface so LOD will
					// be applied. However the LOD of that chopped grid must
					// be synced with the LOD of the original curve.
					// One way to do this; the chopped grid shares vertices with
					// the original curve. When LOD is applied to the original
					// curve the unused vertices are flagged. Now the chopped curve
					// should skip the flagged vertices. This still leaves the
					// problems with the vertices at the chopped grid edges.
					//
					// To avoid issues when LOD applied to "hollow curves" (like
					// the ones around many jump pads) we now just add a 2 unit
					// offset to the triangle vertices.
					// The offset is added in the vertex normal vector direction
					// so all triangles will still fit together.
					// The 2 unit offset should avoid pretty much all LOD problems.

					numClipPoints = 3;

					dv = cv->verts + m * cv->width + n;

					VectorCopy(dv[0].xyz, clipPoints[0][0]);
					VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0]);
					VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
					VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
					VectorCopy(dv[1].xyz, clipPoints[0][2]);
					VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2]);
					// check the normal of this triangle
					VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
					VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
					CrossProduct(v1, v2, normal);
					VectorNormalizeFast(normal);
					if (DotProduct(normal, projectionDir) < -0.1) {
						// add the fragments of this triangle
						R_AddMarkFragments(numClipPoints, clipPoints,
										   numPlanes, normals, dists,
										   maxPoints, pointBuffer,
										   maxFragments, fragmentBuffer,
										   &returnedPoints, &returnedFragments, mins, maxs);

						if ( returnedFragments == maxFragments ) {
							return returnedFragments;	// not enough space for more fragments
						}
					}

					VectorCopy(dv[1].xyz, clipPoints[0][0]);
					VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0]);
					VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
					VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
					VectorCopy(dv[cv->width+1].xyz, clipPoints[0][2]);
					VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[cv->width+1].normal, clipPoints[0][2]);
					// check the normal of this triangle
					VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
					VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
					CrossProduct(v1, v2, normal);
					VectorNormalizeFast(normal);
					if (DotProduct(normal, projectionDir) < -0.05) {
						// add the fragments of this triangle
						R_AddMarkFragments(numClipPoints, clipPoints,
										   numPlanes, normals, dists,
										   maxPoints, pointBuffer,
										   maxFragments, fragmentBuffer,
										   &returnedPoints, &returnedFragments, mins, maxs);

						if ( returnedFragments == maxFragments ) {
							return returnedFragments;	// not enough space for more fragments
						}
					}
				}
			}
		}
		else if (*surfaces[i] == SF_FACE) {

			surf = ( srfSurfaceFace_t * ) surfaces[i];
			// check the normal of this face
			if (DotProduct(surf->plane.normal, projectionDir) > -0.5) {
				continue;
			}

			/*
			VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
			VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
			CrossProduct(v1, v2, normal);
			VectorNormalize(normal);
			if (DotProduct(normal, projectionDir) > -0.5) continue;
			*/
			indexes = (int *)( (byte *)surf + surf->ofsIndices );
			for ( k = 0 ; k < surf->numIndices ; k += 3 ) {
				for ( j = 0 ; j < 3 ; j++ ) {
					v = surf->points[0] + VERTEXSIZE * indexes[k+j];;
					VectorMA( v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j] );
				}
				// add the fragments of this face
				R_AddMarkFragments( 3 , clipPoints,
								   numPlanes, normals, dists,
								   maxPoints, pointBuffer,
								   maxFragments, fragmentBuffer,
								   &returnedPoints, &returnedFragments, mins, maxs);
				if ( returnedFragments == maxFragments ) {
					return returnedFragments;	// not enough space for more fragments
				}
			}
			continue;
		}
		else {
			// ignore all other world surfaces
			// might be cool to also project polygons on a triangle soup
			// however this will probably create huge amounts of extra polys
			// even more than the projection onto curves
			continue;
		}
	}
	return returnedFragments;
}
Beispiel #5
0
/*
=================
R_MarkFragments

=================
*/
int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
				   int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ) {
	int				numsurfaces, numPlanes;
	int				i, j, k, m, n;
	surfaceType_t	*surfaces[64];
	int				surfacesBmodel[64];
	int				lastBmodel;
	vec3_t			mins, maxs;
	int				returnedFragments;
	int				returnedPoints;
	vec3_t			normals[MAX_VERTS_ON_POLY+2], localNormals[MAX_VERTS_ON_POLY+2];
	float			dists[MAX_VERTS_ON_POLY+2], localDists[MAX_VERTS_ON_POLY+2];
	vec3_t			clipPoints[2][MAX_VERTS_ON_POLY];
	int				numClipPoints;
	float			*v;
	srfBspSurface_t	*cv;
	glIndex_t		*tri;
	srfVert_t		*dv;
	vec3_t			normal;
	vec3_t			projectionDir, localProjectionDir;
	vec3_t			v1, v2;

	if (numPoints <= 0) {
		return 0;
	}

	//increment view count for double check prevention
	tr.viewCount++;

	//
	VectorNormalize2( projection, projectionDir );
	// find all the brushes that are to be considered
	ClearBounds( mins, maxs );
	for ( i = 0 ; i < numPoints ; i++ ) {
		vec3_t	temp;

		AddPointToBounds( points[i], mins, maxs );
		VectorAdd( points[i], projection, temp );
		AddPointToBounds( temp, mins, maxs );
		// make sure we get all the leafs (also the one(s) in front of the hit surface)
		VectorMA( points[i], -20, projectionDir, temp );
		AddPointToBounds( temp, mins, maxs );
	}

	if (numPoints > MAX_VERTS_ON_POLY) numPoints = MAX_VERTS_ON_POLY;
	// create the bounding planes for the to be projected polygon
	for ( i = 0 ; i < numPoints ; i++ ) {
		VectorSubtract(points[(i+1)%numPoints], points[i], v1);
		VectorAdd(points[i], projection, v2);
		VectorSubtract(points[i], v2, v2);
		CrossProduct(v1, v2, normals[i]);
		VectorNormalizeFast(normals[i]);
		dists[i] = DotProduct(normals[i], points[i]);
	}
	// add near and far clipping planes for projection
	VectorCopy(projectionDir, normals[numPoints]);
	dists[numPoints] = DotProduct(normals[numPoints], points[0]) - 32;
	VectorCopy(projectionDir, normals[numPoints+1]);
	VectorInverse(normals[numPoints+1]);
	dists[numPoints+1] = DotProduct(normals[numPoints+1], points[0]) - 20;
	numPlanes = numPoints + 2;

	numsurfaces = 0;
	R_BoxSurfaces_r(tr.world->nodes, mins, maxs, surfaces, surfacesBmodel, 64, &numsurfaces, projectionDir);
	//assert(numsurfaces <= 64);
	//assert(numsurfaces != 64);

	// add bmodel surfaces
	for ( j = 1; j < tr.world->numBModels; j++ ) {
		vec3_t localProjection, bmodelOrigin, bmodelAxis[3];

		R_TransformMarkProjection( j, projection, localProjection, 0, NULL, NULL, NULL, NULL );
		R_GetBmodelInfo( j, NULL, bmodelOrigin, bmodelAxis );

		VectorNormalize2( localProjection, localProjectionDir );
		// find all the brushes that are to be considered
		ClearBounds( mins, maxs );
		for ( i = 0 ; i < numPoints ; i++ ) {
			vec3_t	temp;
			vec3_t	delta;
			vec3_t	localPoint;

			// convert point to bmodel local space
			VectorSubtract( points[i], bmodelOrigin, delta );
			localPoint[0] = DotProduct( delta, bmodelAxis[0] );
			localPoint[1] = DotProduct( delta, bmodelAxis[1] );
			localPoint[2] = DotProduct( delta, bmodelAxis[2] );

			AddPointToBounds( localPoint, mins, maxs );
			VectorAdd( localPoint, localProjection, temp );
			AddPointToBounds( temp, mins, maxs );
			// make sure we get all the leafs (also the one(s) in front of the hit surface)
			VectorMA( localPoint, -20, localProjectionDir, temp );
			AddPointToBounds( temp, mins, maxs );
		}

		R_BmodelSurfaces( j, mins, maxs, surfaces, surfacesBmodel, 64, &numsurfaces, localProjectionDir);
	}

	returnedPoints = 0;
	returnedFragments = 0;
	lastBmodel = -1;

	for ( i = 0 ; i < numsurfaces ; i++ ) {
		if (i == 0 || surfacesBmodel[i] != lastBmodel) {
			R_TransformMarkProjection( surfacesBmodel[i], projectionDir, localProjectionDir, numPlanes, normals, dists, localNormals, localDists );
			lastBmodel = surfacesBmodel[i];

			// don't use projectionDir, normals, or dists beyond this point !!!
			// mins and maxs are not setup, so they are not valid !!!
		}

		if (*surfaces[i] == SF_GRID) {

			cv = (srfBspSurface_t *) surfaces[i];
			for ( m = 0 ; m < cv->height - 1 ; m++ ) {
				for ( n = 0 ; n < cv->width - 1 ; n++ ) {
					// We triangulate the grid and chop all triangles within
					// the bounding planes of the to be projected polygon.
					// LOD is not taken into account, not such a big deal though.
					//
					// It's probably much nicer to chop the grid itself and deal
					// with this grid as a normal SF_GRID surface so LOD will
					// be applied. However the LOD of that chopped grid must
					// be synced with the LOD of the original curve.
					// One way to do this; the chopped grid shares vertices with
					// the original curve. When LOD is applied to the original
					// curve the unused vertices are flagged. Now the chopped curve
					// should skip the flagged vertices. This still leaves the
					// problems with the vertices at the chopped grid edges.
					//
					// To avoid issues when LOD applied to "hollow curves" (like
					// the ones around many jump pads) we now just add a 2 unit
					// offset to the triangle vertices.
					// The offset is added in the vertex normal vector direction
					// so all triangles will still fit together.
					// The 2 unit offset should avoid pretty much all LOD problems.

					numClipPoints = 3;

					dv = cv->verts + m * cv->width + n;

					VectorCopy(dv[0].xyz, clipPoints[0][0]);
					VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0]);
					VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
					VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
					VectorCopy(dv[1].xyz, clipPoints[0][2]);
					VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2]);
					// check the normal of this triangle
					VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
					VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
					CrossProduct(v1, v2, normal);
					VectorNormalizeFast(normal);
					if (DotProduct(normal, localProjectionDir) < -0.1) {
						// add the fragments of this triangle
						R_AddMarkFragments(numClipPoints, clipPoints,
										   numPlanes, localNormals, localDists,
										   maxPoints, pointBuffer,
										   maxFragments, fragmentBuffer,
										   &returnedPoints, &returnedFragments, mins, maxs, lastBmodel, localProjectionDir);

						if ( returnedFragments == maxFragments ) {
							return returnedFragments;	// not enough space for more fragments
						}
					}

					VectorCopy(dv[1].xyz, clipPoints[0][0]);
					VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0]);
					VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
					VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
					VectorCopy(dv[cv->width+1].xyz, clipPoints[0][2]);
					VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[cv->width+1].normal, clipPoints[0][2]);
					// check the normal of this triangle
					VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
					VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
					CrossProduct(v1, v2, normal);
					VectorNormalizeFast(normal);
					if (DotProduct(normal, localProjectionDir) < -0.05) {
						// add the fragments of this triangle
						R_AddMarkFragments(numClipPoints, clipPoints,
										   numPlanes, localNormals, localDists,
										   maxPoints, pointBuffer,
										   maxFragments, fragmentBuffer,
										   &returnedPoints, &returnedFragments, mins, maxs, lastBmodel, localProjectionDir);

						if ( returnedFragments == maxFragments ) {
							return returnedFragments;	// not enough space for more fragments
						}
					}
				}
			}
		}
		else if (*surfaces[i] == SF_FACE) {

			srfBspSurface_t *surf = ( srfBspSurface_t * ) surfaces[i];

			// check the normal of this face
			if (DotProduct(surf->cullPlane.normal, localProjectionDir) > -0.5) {
				continue;
			}

			for(k = 0, tri = surf->indexes; k < surf->numIndexes; k += 3, tri += 3)
			{
				for(j = 0; j < 3; j++)
				{
					v = surf->verts[tri[j]].xyz;
					VectorMA(v, MARKER_OFFSET, surf->cullPlane.normal, clipPoints[0][j]);
				}

				// add the fragments of this face
				R_AddMarkFragments( 3 , clipPoints,
								   numPlanes, localNormals, localDists,
								   maxPoints, pointBuffer,
								   maxFragments, fragmentBuffer,
								   &returnedPoints, &returnedFragments, mins, maxs, lastBmodel, localProjectionDir);
				if ( returnedFragments == maxFragments ) {
					return returnedFragments;	// not enough space for more fragments
				}
			}
		}
		else if(*surfaces[i] == SF_TRIANGLES && r_marksOnTriangleMeshes->integer) {

			srfBspSurface_t *surf = (srfBspSurface_t *) surfaces[i];

			for(k = 0, tri = surf->indexes; k < surf->numIndexes; k += 3, tri += 3)
			{
				for(j = 0; j < 3; j++)
				{
					v = surf->verts[tri[j]].xyz;
					VectorMA(v, MARKER_OFFSET, surf->verts[tri[j]].normal, clipPoints[0][j]);
				}

				// add the fragments of this face
				R_AddMarkFragments(3, clipPoints,
								   numPlanes, localNormals, localDists,
								   maxPoints, pointBuffer,
								   maxFragments, fragmentBuffer, &returnedPoints, &returnedFragments, mins, maxs, lastBmodel, localProjectionDir);
				if(returnedFragments == maxFragments)
				{
					return returnedFragments;	// not enough space for more fragments
				}
			}
		}
	}
	return returnedFragments;
}
Beispiel #6
0
/*
=================
R_MarkFragments

=================
*/
int R_MarkFragments(int orientation, const vec3_t *points, const vec3_t projection,
                    int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer)
{
	int           numsurfaces, numPlanes;
	int           i, j, k, m, n;
	surfaceType_t *surfaces[4096];
	vec3_t        mins, maxs;
	int           returnedFragments;
	int           returnedPoints;
	vec3_t        normals[MAX_VERTS_ON_POLY + 2];
	float         dists[MAX_VERTS_ON_POLY + 2];
	vec3_t        clipPoints[2][MAX_VERTS_ON_POLY];
	int           numClipPoints;
	float         *v;
	srfGridMesh_t *cv;
	srfTriangle_t *tri;
	srfVert_t     *dv;
	vec3_t        normal;
	vec3_t        projectionDir;
	vec3_t        v1, v2;
	float         radius;
	vec3_t        center;   // center of original mark
	//vec3_t			bestCenter;	// center point projected onto the closest surface
	float texCoordScale;
	//float			dot;
	int      numPoints  = 4;        // Ridah, we were only ever passing in 4, so I made this local and used the parameter for the orientation
	qboolean oldMapping = qfalse;

	if (numPoints <= 0)
	{
		return 0;
	}

	//increment view count for double check prevention
	tr.viewCount++;

	// RF, negative maxFragments means we want original mapping
	if (maxFragments < 0)
	{
		maxFragments = -maxFragments;
		//return R_OldMarkFragments( numPoints, points, projection, maxPoints, pointBuffer, maxFragments, fragmentBuffer );
		oldMapping = qtrue;
	}

	VectorClear(center);
	for (i = 0 ; i < numPoints ; i++)
	{
		VectorAdd(points[i], center, center);
	}
	VectorScale(center, 1.0 / numPoints, center);
	//
	radius   = VectorNormalize2(projection, projectionDir) / 2.0;
	bestdist = 0;
	VectorNegate(projectionDir, bestnormal);
	// find all the brushes that are to be considered
	ClearBounds(mins, maxs);
	for (i = 0 ; i < numPoints ; i++)
	{
		vec3_t temp;

		AddPointToBounds(points[i], mins, maxs);
		VectorMA(points[i], 1 * (1 + oldMapping * radius * 4), projection, temp);
		AddPointToBounds(temp, mins, maxs);
		// make sure we get all the leafs (also the one(s) in front of the hit surface)
		VectorMA(points[i], -20 * (1.0 + (float)oldMapping * (radius / 20.0) * 4), projectionDir, temp);
		AddPointToBounds(temp, mins, maxs);
	}

	if (numPoints > MAX_VERTS_ON_POLY)
	{
		numPoints = MAX_VERTS_ON_POLY;
	}
	// create the bounding planes for the to be projected polygon
	for (i = 0 ; i < numPoints ; i++)
	{
		VectorSubtract(points[(i + 1) % numPoints], points[i], v1);
		VectorAdd(points[i], projection, v2);
		VectorSubtract(points[i], v2, v2);
		CrossProduct(v1, v2, normals[i]);
		VectorNormalize(normals[i]);
		dists[i] = DotProduct(normals[i], points[i]);
	}
	// add near and far clipping planes for projection
	VectorCopy(projectionDir, normals[numPoints]);
	dists[numPoints] = DotProduct(normals[numPoints], points[0]) - radius * (1 + oldMapping * 10);
	VectorCopy(projectionDir, normals[numPoints + 1]);
	VectorInverse(normals[numPoints + 1]);
	dists[numPoints + 1] = DotProduct(normals[numPoints + 1], points[0]) - radius * (1 + oldMapping * 10);
	numPlanes            = numPoints + 2;

	numsurfaces = 0;
	R_BoxSurfaces_r(tr.world->nodes, mins, maxs, surfaces, 4096, &numsurfaces, projectionDir);
	//assert(numsurfaces <= 64);
	//assert(numsurfaces != 64);

	texCoordScale = 0.5 * 1.0 / radius;

	returnedPoints    = 0;
	returnedFragments = 0;

	// find the closest surface to center the decal there, and wrap around other surfaces
	if (!oldMapping)
	{
/*
        for ( i = 0 ; i < numsurfaces ; i++ ) {
            if (*surfaces[i] == SF_FACE) {
                surf = ( srfSurfaceFace_t * ) surfaces[i];
                // Ridah, check if this is the closest surface
                dot = DotProduct( center, surf->plane.normal );
                dot -= surf->plane.dist;
                if (!bestdist) {
                    if (dot < 0)
                        bestdist = fabs(dot) + 1000;	// avoid this surface, since the point is behind it
                    else
                        bestdist = dot;
                    VectorCopy( surf->plane.normal, bestnormal );
                    VectorMA( center, -dot, surf->plane.normal, bestCenter );
                } else if (dot >= 0 && dot < bestdist) {
                    bestdist = dot;
                    VectorCopy( surf->plane.normal, bestnormal );
                    VectorMA( center, -dot, surf->plane.normal, bestCenter );
                }
            }
        }
        // bestCenter is now the real center
        VectorCopy( bestCenter, center );
Com_Printf("bestnormal: %1.1f %1.1f %1.1f \n", bestnormal[0], bestnormal[1], bestnormal[2] );
*/
		VectorNegate(bestnormal, bestnormal);
	}

	for (i = 0 ; i < numsurfaces ; i++)
	{

		if (*surfaces[i] == SF_GRID)
		{

			cv = (srfGridMesh_t *) surfaces[i];
			for (m = 0 ; m < cv->height - 1 ; m++)
			{
				for (n = 0 ; n < cv->width - 1 ; n++)
				{
					// We triangulate the grid and chop all triangles within
					// the bounding planes of the to be projected polygon.
					// LOD is not taken into account, not such a big deal though.
					//
					// It's probably much nicer to chop the grid itself and deal
					// with this grid as a normal SF_GRID surface so LOD will
					// be applied. However the LOD of that chopped grid must
					// be synced with the LOD of the original curve.
					// One way to do this; the chopped grid shares vertices with
					// the original curve. When LOD is applied to the original
					// curve the unused vertices are flagged. Now the chopped curve
					// should skip the flagged vertices. This still leaves the
					// problems with the vertices at the chopped grid edges.
					//
					// To avoid issues when LOD applied to "hollow curves" (like
					// the ones around many jump pads) we now just add a 2 unit
					// offset to the triangle vertices.
					// The offset is added in the vertex normal vector direction
					// so all triangles will still fit together.
					// The 2 unit offset should avoid pretty much all LOD problems.

					numClipPoints = 3;

					dv = cv->verts + m * cv->width + n;

					VectorCopy(dv[0].xyz, clipPoints[0][0]);
					VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0]);
					VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
					VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
					VectorCopy(dv[1].xyz, clipPoints[0][2]);
					VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2]);
					// check the normal of this triangle
					VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
					VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
					CrossProduct(v1, v2, normal);
					VectorNormalize(normal);
					if (DotProduct(normal, projectionDir) < -0.1)
					{
						// add the fragments of this triangle
						R_AddMarkFragments(numClipPoints, clipPoints,
						                   numPlanes, normals, dists,
						                   maxPoints, pointBuffer,
						                   maxFragments, fragmentBuffer,
						                   &returnedPoints, &returnedFragments, mins, maxs);

						if (returnedFragments == maxFragments)
						{
							return returnedFragments;   // not enough space for more fragments
						}
					}

					VectorCopy(dv[1].xyz, clipPoints[0][0]);
					VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0]);
					VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
					VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
					VectorCopy(dv[cv->width + 1].xyz, clipPoints[0][2]);
					VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[cv->width + 1].normal, clipPoints[0][2]);
					// check the normal of this triangle
					VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
					VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
					CrossProduct(v1, v2, normal);
					VectorNormalize(normal);
					if (DotProduct(normal, projectionDir) < -0.05)
					{
						// add the fragments of this triangle
						R_AddMarkFragments(numClipPoints, clipPoints,
						                   numPlanes, normals, dists,
						                   maxPoints, pointBuffer,
						                   maxFragments, fragmentBuffer,
						                   &returnedPoints, &returnedFragments, mins, maxs);

						if (returnedFragments == maxFragments)
						{
							return returnedFragments;   // not enough space for more fragments
						}
					}
				}
			}
		}
		else if (*surfaces[i] == SF_FACE)
		{
			extern float VectorDistance(vec3_t v1, vec3_t v2);
			vec3_t axis[3];
			float  texCoordScale, dot;
			vec3_t originalPoints[4];
			vec3_t newCenter, delta;
			int    oldNumPoints;
			float  epsilon = 0.5;
			// duplicated so we don't mess with the original clips for the curved surfaces
			vec3_t lnormals[MAX_VERTS_ON_POLY + 2];
			float  ldists[MAX_VERTS_ON_POLY + 2];
			vec3_t lmins, lmaxs;

			srfSurfaceFace_t *surf = ( srfSurfaceFace_t * ) surfaces[i];

			if (!oldMapping)
			{

				// Ridah, create a new clip box such that this decal surface is mapped onto
				// the current surface without distortion. To find the center of the new clip box,
				// we project the center of the original impact center out along the projection vector,
				// onto the current surface

				// find the center of the new decal
				dot  = DotProduct(center, surf->plane.normal);
				dot -= surf->plane.dist;
				// check the normal of this face
				if (dot < -epsilon && DotProduct(surf->plane.normal, projectionDir) >= 0.01)
				{
					continue;
				}
				else if (fabs(dot) > radius)
				{
					continue;
				}
				// if the impact point is behind the surface, subtract the projection, otherwise add it
				VectorMA(center, -dot, bestnormal, newCenter);

				// recalc dot from the offset position
				dot  = DotProduct(newCenter, surf->plane.normal);
				dot -= surf->plane.dist;
				VectorMA(newCenter, -dot, surf->plane.normal, newCenter);

				VectorMA(newCenter, MARKER_OFFSET, surf->plane.normal, newCenter);

				// create the texture axis
				VectorNormalize2(surf->plane.normal, axis[0]);
				PerpendicularVector(axis[1], axis[0]);
				RotatePointAroundVector(axis[2], axis[0], axis[1], (float)orientation);
				CrossProduct(axis[0], axis[2], axis[1]);

				texCoordScale = 0.5 * 1.0 / radius;

				// create the full polygon
				for (j = 0 ; j < 3 ; j++)
				{
					originalPoints[0][j] = newCenter[j] - radius * axis[1][j] - radius * axis[2][j];
					originalPoints[1][j] = newCenter[j] + radius * axis[1][j] - radius * axis[2][j];
					originalPoints[2][j] = newCenter[j] + radius * axis[1][j] + radius * axis[2][j];
					originalPoints[3][j] = newCenter[j] - radius * axis[1][j] + radius * axis[2][j];
				}

				ClearBounds(lmins, lmaxs);

				// create the bounding planes for the to be projected polygon
				for (j = 0 ; j < 4 ; j++)
				{
					AddPointToBounds(originalPoints[j], lmins, lmaxs);

					VectorSubtract(originalPoints[(j + 1) % numPoints], originalPoints[j], v1);
					VectorSubtract(originalPoints[j], surf->plane.normal, v2);
					VectorSubtract(originalPoints[j], v2, v2);
					CrossProduct(v1, v2, lnormals[j]);
					VectorNormalize(lnormals[j]);
					ldists[j] = DotProduct(lnormals[j], originalPoints[j]);
				}
				numPlanes = numPoints;

				// done.

				for (k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++)
				{
					for (j = 0; j < 3; j++)
					{
						v = surf->verts[tri->indexes[j]].xyz;
						VectorMA(v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j]);
					}

					oldNumPoints = returnedPoints;

					// add the fragments of this face
					R_AddMarkFragments(3, clipPoints,
					                   numPlanes, lnormals, ldists,
					                   maxPoints, pointBuffer,
					                   maxFragments, fragmentBuffer,
					                   &returnedPoints, &returnedFragments, lmins, lmaxs);

					if (oldNumPoints != returnedPoints)
					{
						// flag this surface as already having computed ST's
						fragmentBuffer[returnedFragments - 1].numPoints *= -1;

						// Ridah, calculate ST's
						for (j = 0 ; j < (returnedPoints - oldNumPoints) ; j++)
						{
							VectorSubtract((float *)pointBuffer + 5 * (oldNumPoints + j), newCenter, delta);
							*((float *)pointBuffer + 5 * (oldNumPoints + j) + 3) = 0.5 + DotProduct(delta, axis[1]) * texCoordScale;
							*((float *)pointBuffer + 5 * (oldNumPoints + j) + 4) = 0.5 + DotProduct(delta, axis[2]) * texCoordScale;
						}
					}

					if (returnedFragments == maxFragments)
					{
						return returnedFragments;   // not enough space for more fragments
					}
				}

			}
			else        // old mapping
			{   // check the normal of this face
				//if (DotProduct(surf->plane.normal, projectionDir) > 0.0) {
				//	continue;
				//}

				for (k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++)
				{
					for (j = 0; j < 3; j++)
					{
						v = surf->verts[tri->indexes[j]].xyz;
						VectorMA(v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j]);
					}
					// add the fragments of this face
					R_AddMarkFragments(3, clipPoints,
					                   numPlanes, normals, dists,
					                   maxPoints, pointBuffer,
					                   maxFragments, fragmentBuffer,
					                   &returnedPoints, &returnedFragments, mins, maxs);
					if (returnedFragments == maxFragments)
					{
						return returnedFragments;   // not enough space for more fragments
					}
				}

			}

		}
		else if (*surfaces[i] == SF_TRIANGLES && r_marksOnTriangleMeshes->integer)
		{

			srfTriangles_t *surf = (srfTriangles_t *) surfaces[i];

			for (k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++)
			{
				for (j = 0; j < 3; j++)
				{
					v = surf->verts[tri->indexes[j]].xyz;
					VectorMA(v, MARKER_OFFSET, surf->verts[tri->indexes[j]].normal, clipPoints[0][j]);
				}

				// add the fragments of this face
				R_AddMarkFragments(3, clipPoints,
				                   numPlanes, normals, dists,
				                   maxPoints, pointBuffer,
				                   maxFragments, fragmentBuffer, &returnedPoints, &returnedFragments, mins, maxs);
				if (returnedFragments == maxFragments)
				{
					return returnedFragments;   // not enough space for more fragments
				}
			}
		}
	}
	return returnedFragments;
}
Beispiel #7
0
/*
=================
R_BoxSurfaces_r

=================
*/
void R_BoxSurfaces_r(mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **list, int listsize, int *listlength, vec3_t dir)
{

	int        s, c;
	msurface_t *surf;
	int        *mark;

	// do the tail recursion in a loop
	while (node->contents == -1)
	{
		s = BoxOnPlaneSide(mins, maxs, node->plane);
		if (s == 1)
		{
			node = node->children[0];
		}
		else if (s == 2)
		{
			node = node->children[1];
		}
		else
		{
			R_BoxSurfaces_r(node->children[0], mins, maxs, list, listsize, listlength, dir);
			node = node->children[1];
		}
	}

	// Ridah, don't mark alpha surfaces
	if (node->contents & CONTENTS_TRANSLUCENT)
	{
		return;
	}

	// add the individual surfaces
	mark = tr.world->marksurfaces + node->firstmarksurface;
	c    = node->nummarksurfaces;
	while (c--)
	{
		int *surfViewCount;
		//
		if (*listlength >= listsize)
		{
			break;
		}
		//
		surfViewCount = &tr.world->surfacesViewCount[*mark];
		surf          = tr.world->surfaces + *mark;
		// check if the surface has NOIMPACT or NOMARKS set
		if ((surf->shader->surfaceFlags & (SURF_NOIMPACT | SURF_NOMARKS))
		    || (surf->shader->contentFlags & CONTENTS_FOG))
		{
			*surfViewCount = tr.viewCount;
		}
		// extra check for surfaces to avoid list overflows
		else if (*(surf->data) == SF_FACE)
		{
			// the face plane should go through the box
			s = BoxOnPlaneSide(mins, maxs, &surf->cullinfo.plane);
			if (s == 1 || s == 2)
			{
				*surfViewCount = tr.viewCount;
			}
			else if (DotProduct(surf->cullinfo.plane.normal, dir) > -0.5)
			{
				// don't add faces that make sharp angles with the projection direction
				*surfViewCount = tr.viewCount;
			}
		}
		else if (*(surf->data) != SF_GRID &&
		         *(surf->data) != SF_TRIANGLES)
		{
			*surfViewCount = tr.viewCount;
		}
		// check the viewCount because the surface may have
		// already been added if it spans multiple leafs
		if (*surfViewCount != tr.viewCount)
		{
			*surfViewCount    = tr.viewCount;
			list[*listlength] = surf->data;
			(*listlength)++;
		}
		mark++;
	}
}
Beispiel #8
0
/*
=================
R_BoxSurfaces_r

=================
*/
void R_BoxSurfaces_r( mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **list, int listsize, int *listlength, vec3_t dir ) {

	int s, c;
	msurface_t  *surf, **mark;

	// RF, if this node hasn't been rendered recently, ignore it
	if ( node->visframe < tr.visCount - 2 ) { // allow us to be a few frames behind
		return;
	}

	// do the tail recursion in a loop
	while ( node->contents == -1 ) {
		s = BoxOnPlaneSide( mins, maxs, node->plane );
		if ( s == 1 ) {
			node = node->children[0];
		} else if ( s == 2 ) {
			node = node->children[1];
		} else {
			R_BoxSurfaces_r( node->children[0], mins, maxs, list, listsize, listlength, dir );
			node = node->children[1];
		}
	}

	// Ridah, don't mark alpha surfaces
	if ( node->contents & CONTENTS_TRANSLUCENT ) {
		return;
	}

	// add the individual surfaces
	mark = node->firstmarksurface;
	c = node->nummarksurfaces;
	while ( c-- ) {
		//
		if ( *listlength >= listsize ) {
			break;
		}
		//
		surf = *mark;
		// check if the surface has NOIMPACT or NOMARKS set
		if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) )
			 || ( surf->shader->contentFlags & CONTENTS_FOG ) ) {
			surf->viewCount = tr.viewCount;
		}
		// extra check for surfaces to avoid list overflows
		else if ( *( surf->data ) == SF_FACE ) {

#if defined RTCW_ET
			if ( ( ( srfSurfaceFace_t * ) surf->data )->plane.type != PLANE_NON_PLANAR ) {
#endif // RTCW_XX

			// the face plane should go through the box
			s = BoxOnPlaneSide( mins, maxs, &( ( srfSurfaceFace_t * ) surf->data )->plane );
			if ( s == 1 || s == 2 ) {
				surf->viewCount = tr.viewCount;
			} else if ( DotProduct( ( ( srfSurfaceFace_t * ) surf->data )->plane.normal, dir ) < -0.5 )         {
				// don't add faces that make sharp angles with the projection direction
				surf->viewCount = tr.viewCount;
			}

#if !defined RTCW_ET
		} else if ( *( surfaceType_t * )( surf->data ) != SF_GRID )        {
#else
			}
		} else if ( *( surfaceType_t * )( surf->data ) != SF_GRID && *( surfaceType_t * )( surf->data ) != SF_TRIANGLES ) {
#endif // RTCW_XX

			surf->viewCount = tr.viewCount;
		}
		// check the viewCount because the surface may have
		// already been added if it spans multiple leafs
		if ( surf->viewCount != tr.viewCount ) {
			surf->viewCount = tr.viewCount;
			list[*listlength] = (surfaceType_t *) surf->data;
			( *listlength )++;
		}
		mark++;
	}
}
Beispiel #9
0
/*
=================
R_BoxSurfaces_r

=================
*/
void R_BoxSurfaces_r(mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **list, int listsize, int *listlength, vec3_t dir) {

	int			s, c;
	msurface_t	*surf, **mark;

	// do the tail recursion in a loop
	while ( node->contents == -1 ) {
		s = BoxOnPlaneSide( mins, maxs, node->plane );
		if (s == 1) {
			node = node->children[0];
		} else if (s == 2) {
			node = node->children[1];
		} else {
			R_BoxSurfaces_r(node->children[0], mins, maxs, list, listsize, listlength, dir);
			node = node->children[1];
		}
	}

	// add the individual surfaces
	mark = node->firstmarksurface;
	c = node->nummarksurfaces;
	while (c--) {
		//
		if (*listlength >= listsize) break;
		//
		surf = *mark;
		//ri.Printf(PRINT_ALL, "^3surf: %s\n", surf->shader->name);
		// check if the surface has NOIMPACT or NOMARKS set
		if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) )
			 ||  ( surf->shader->contentFlags & CONTENTS_FOG ) ) {
			if (r_ignoreNoMarks->integer == 0) {
				surf->viewCount = tr.viewCount;
			} else if (r_ignoreNoMarks->integer == 1) {
				if (surf->shader->contentFlags & (CONTENTS_FOG | CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA)) {
					surf->viewCount = tr.viewCount;
				}
			} else {  // r_ignoreNoMarks->integer >= 2
				// allow marks liquids, etc..
			}
		}
		// extra check for surfaces to avoid list overflows
		else if (*(surf->data) == SF_FACE) {
			// the face plane should go through the box
			s = BoxOnPlaneSide( mins, maxs, &(( srfSurfaceFace_t * ) surf->data)->plane );
			if (s == 1 || s == 2) {
				surf->viewCount = tr.viewCount;
			} else if (DotProduct((( srfSurfaceFace_t * ) surf->data)->plane.normal, dir) > -0.5) {
				// don't add faces that make sharp angles with the projection direction
				//ri.Printf(PRINT_ALL, "^3sharp angle '%s'\n", surf->shader->name);
				surf->viewCount = tr.viewCount;
			} else {
				//ri.Printf(PRINT_ALL, "^3surf: %s\n", surf->shader->name);
			}
		}
		else if (*(surfaceType_t *) (surf->data) != SF_GRID &&
				 *(surfaceType_t *) (surf->data) != SF_TRIANGLES) {
			surf->viewCount = tr.viewCount;
		}

		// check the viewCount because the surface may have
		// already been added if it spans multiple leafs
		if (surf->viewCount != tr.viewCount) {
			surf->viewCount = tr.viewCount;
			mxsurf[*listlength] = surf;
			list[*listlength] = (surfaceType_t *) surf->data;
			(*listlength)++;
			//ri.Printf(PRINT_ALL, "^3surf: %s\n", surf->shader->name);
		}
		mark++;
	}
}
Beispiel #10
0
int R_MarkFragmentsWolf( int orientation, const vec3_t* points, const vec3_t projection,
	int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t* fragmentBuffer ) {
	int numPlanes;
	int i;
	vec3_t mins, maxs;
	int returnedFragments;
	int returnedPoints;
	vec3_t normals[ MAX_VERTS_ON_POLY + 2 ];
	float dists[ MAX_VERTS_ON_POLY + 2 ];
	vec3_t projectionDir;
	vec3_t v1, v2;
	float radius;
	vec3_t center;			// center of original mark
	int numPoints = 4;				// Ridah, we were only ever passing in 4, so I made this local and used the parameter for the orientation
	qboolean oldMapping = false;

	//increment view count for double check prevention
	tr.viewCount++;

	// RF, negative maxFragments means we want original mapping
	if ( maxFragments < 0 ) {
		maxFragments = -maxFragments;
		oldMapping = true;
	}

	VectorClear( center );
	for ( i = 0; i < numPoints; i++ ) {
		VectorAdd( points[ i ], center, center );
	}
	VectorScale( center, 1.0 / numPoints, center );
	//
	radius = VectorNormalize2( projection, projectionDir ) / 2.0;
	vec3_t bestnormal;
	VectorNegate( projectionDir, bestnormal );
	// find all the brushes that are to be considered
	ClearBounds( mins, maxs );
	for ( i = 0; i < numPoints; i++ ) {
		vec3_t temp;

		AddPointToBounds( points[ i ], mins, maxs );
		VectorMA( points[ i ], 1 * ( 1 + oldMapping * radius * 4 ), projection, temp );
		AddPointToBounds( temp, mins, maxs );
		// make sure we get all the leafs (also the one(s) in front of the hit surface)
		VectorMA( points[ i ], -20 * ( 1.0 + ( float )oldMapping * ( radius / 20.0 ) * 4 ), projectionDir, temp );
		AddPointToBounds( temp, mins, maxs );
	}

	if ( numPoints > MAX_VERTS_ON_POLY ) {
		numPoints = MAX_VERTS_ON_POLY;
	}
	// create the bounding planes for the to be projected polygon
	for ( i = 0; i < numPoints; i++ ) {
		VectorSubtract( points[ ( i + 1 ) % numPoints ], points[ i ], v1 );
		VectorAdd( points[ i ], projection, v2 );
		VectorSubtract( points[ i ], v2, v2 );
		CrossProduct( v1, v2, normals[ i ] );
		VectorNormalize( normals[ i ] );
		dists[ i ] = DotProduct( normals[ i ], points[ i ] );
	}
	// add near and far clipping planes for projection
	VectorCopy( projectionDir, normals[ numPoints ] );
	dists[ numPoints ] = DotProduct( normals[ numPoints ], points[ 0 ] ) - radius * ( 1 + oldMapping * 10 );
	VectorCopy( projectionDir, normals[ numPoints + 1 ] );
	VectorInverse( normals[ numPoints + 1 ] );
	dists[ numPoints + 1 ] = DotProduct( normals[ numPoints + 1 ], points[ 0 ] ) - radius * ( 1 + oldMapping * 10 );
	numPlanes = numPoints + 2;

	int numsurfaces = 0;
	idWorldSurface* surfaces[ 4096 ];
	R_BoxSurfaces_r( tr.world->nodes, mins, maxs, surfaces, 4096, &numsurfaces, projectionDir );

	returnedPoints = 0;
	returnedFragments = 0;

	// find the closest surface to center the decal there, and wrap around other surfaces
	if ( !oldMapping ) {
		VectorNegate( bestnormal, bestnormal );
	}

	for ( i = 0; i < numsurfaces; i++ ) {
		surfaces[ i ]->MarkFragmentsWolf( projectionDir,
				numPlanes, normals, dists,
				maxPoints, pointBuffer,
				maxFragments, fragmentBuffer,
				&returnedPoints, &returnedFragments, mins, maxs,
				oldMapping, center, radius, bestnormal, orientation, numPoints );
		if ( returnedFragments == maxFragments ) {
			break;	// not enough space for more fragments
		}
	}
	return returnedFragments;
}
Beispiel #11
0
int R_MarkFragments( int numPoints, const vec3_t* points, const vec3_t projection,
	int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t* fragmentBuffer ) {
	//increment view count for double check prevention
	tr.viewCount++;

	vec3_t projectionDir;
	VectorNormalize2( projection, projectionDir );

	// find all the brushes that are to be considered
	vec3_t mins, maxs;
	ClearBounds( mins, maxs );
	for ( int i = 0; i < numPoints; i++ ) {
		AddPointToBounds( points[ i ], mins, maxs );
		vec3_t temp;
		VectorAdd( points[ i ], projection, temp );
		AddPointToBounds( temp, mins, maxs );
		// make sure we get all the leafs (also the one(s) in front of the hit surface)
		VectorMA( points[ i ], -20, projectionDir, temp );
		AddPointToBounds( temp, mins, maxs );
	}

	if ( numPoints > MAX_VERTS_ON_POLY ) {
		numPoints = MAX_VERTS_ON_POLY;
	}
	// create the bounding planes for the to be projected polygon
	vec3_t normals[ MAX_VERTS_ON_POLY + 2 ];
	float dists[ MAX_VERTS_ON_POLY + 2 ];
	for ( int i = 0; i < numPoints; i++ ) {
		vec3_t v1, v2;
		VectorSubtract( points[ ( i + 1 ) % numPoints ], points[ i ], v1 );
		VectorAdd( points[ i ], projection, v2 );
		VectorSubtract( points[ i ], v2, v2 );
		CrossProduct( v1, v2, normals[ i ] );
		VectorNormalizeFast( normals[ i ] );
		dists[ i ] = DotProduct( normals[ i ], points[ i ] );
	}

	// add near and far clipping planes for projection
	VectorCopy( projectionDir, normals[ numPoints ] );
	dists[ numPoints ] = DotProduct( normals[ numPoints ], points[ 0 ] ) - 32;
	VectorCopy( projectionDir, normals[ numPoints + 1 ] );
	VectorInverse( normals[ numPoints + 1 ] );
	dists[ numPoints + 1 ] = DotProduct( normals[ numPoints + 1 ], points[ 0 ] ) - 20;
	int numPlanes = numPoints + 2;

	int numsurfaces = 0;
	idWorldSurface* surfaces[ 64 ];
	R_BoxSurfaces_r( tr.world->nodes, mins, maxs, surfaces, 64, &numsurfaces, projectionDir );
	//assert(numsurfaces <= 64);
	//assert(numsurfaces != 64);

	int returnedPoints = 0;
	int returnedFragments = 0;

	for ( int i = 0; i < numsurfaces; i++ ) {
		surfaces[ i ]->MarkFragments( projectionDir,
				numPlanes, normals, dists,
				maxPoints, pointBuffer,
				maxFragments, fragmentBuffer,
				&returnedPoints, &returnedFragments, mins, maxs );
		if ( returnedFragments == maxFragments ) {
			break;	// not enough space for more fragments
		}
	}
	return returnedFragments;
}
Beispiel #12
0
/*
=================
R_BoxSurfaces_r

=================
*/
void R_BoxSurfaces_r(mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **list, int listsize, int *listlength, vec3_t dir) {

	int			s, c;
	msurface_t	*surf, **mark;

	// do the tail recursion in a loop
	while ( node->contents == -1 ) {
#ifdef _XBOX
		s = BoxOnPlaneSide( mins, maxs, tr.world->planes + node->planeNum );
#else
		s = BoxOnPlaneSide( mins, maxs, node->plane );
#endif
		if (s == 1) {
			node = node->children[0];
		} else if (s == 2) {
			node = node->children[1];
		} else {
			R_BoxSurfaces_r(node->children[0], mins, maxs, list, listsize, listlength, dir);
			node = node->children[1];
		}
	}

	// add the individual surfaces
#ifdef _XBOX
	mleaf_s *leaf = (mleaf_s*)node;
	mark = tr.world->marksurfaces + leaf->firstMarkSurfNum;
	c = leaf->nummarksurfaces;
#else
	mark = node->firstmarksurface;
	c = node->nummarksurfaces;
#endif
	while (c--) {
		//
		if (*listlength >= listsize) break;
		//
		surf = *mark;
		// check if the surface has NOIMPACT or NOMARKS set
		if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) )
			|| ( surf->shader->contentFlags & CONTENTS_FOG ) ) {
			surf->viewCount = tr.viewCount;
		}
		// extra check for surfaces to avoid list overflows
		else if (*(surf->data) == SF_FACE) {
			// the face plane should go through the box
			s = BoxOnPlaneSide( mins, maxs, &(( srfSurfaceFace_t * ) surf->data)->plane );
			if (s == 1 || s == 2) {
				surf->viewCount = tr.viewCount;
			} else if (DotProduct((( srfSurfaceFace_t * ) surf->data)->plane.normal, dir) > -0.5) {
			// don't add faces that make sharp angles with the projection direction
				surf->viewCount = tr.viewCount;
			}
		}
		else if (*(surfaceType_t *) (surf->data) != SF_GRID) surf->viewCount = tr.viewCount;
		// check the viewCount because the surface may have
		// already been added if it spans multiple leafs
		if (surf->viewCount != tr.viewCount) {
			surf->viewCount = tr.viewCount;
			list[*listlength] = (surfaceType_t *) surf->data;
			(*listlength)++;
		}
		mark++;
	}
}