Exemple #1
0
void TraceLine( trace_t *trace ){
	int i, j;
	traceNode_t     *node;
	traceTriangle_t *tt;
	traceInfo_t     *ti;


	/* setup output (note: this code assumes the input data is completely filled out) */
	trace->passSolid = qfalse;
	trace->opaque = qfalse;
	trace->compileFlags = 0;
	trace->numTestNodes = 0;

	/* early outs */
	if ( !trace->recvShadows || !trace->testOcclusion || trace->distance <= 0.00001f ) {
		return;
	}

	/* trace through nodes */
	TraceLine_r( headNodeNum, trace->origin, trace->end, trace );
	if ( trace->passSolid && !trace->testAll ) {
		trace->opaque = qtrue;
		return;
	}

	/* skip surfaces? */
	if ( noSurfaces ) {
		return;
	}

	/* testall means trace through sky */
	if ( trace->testAll && trace->numTestNodes < MAX_TRACE_TEST_NODES &&
		 trace->compileFlags & C_SKY &&
		 ( trace->numSurfaces == 0 || surfaceInfos[ trace->surfaces[ 0 ] ].childSurfaceNum < 0 ) ) {
		//%	trace->testNodes[ trace->numTestNodes++ ] = skyboxNodeNum;
		TraceLine_r( skyboxNodeNum, trace->origin, trace->end, trace );
	}

	/* walk node list */
	for ( i = 0; i < trace->numTestNodes; i++ )
	{
		/* get node */
		node = &traceNodes[ trace->testNodes[ i ] ];

		/* walk node item list */
		for ( j = 0; j < node->numItems; j++ )
		{
			tt = &traceTriangles[ node->items[ j ] ];
			ti = &traceInfos[ tt->infoNum ];
			if ( TraceTriangle( ti, tt, trace ) ) {
				return;
			}
			//%	if( TraceWinding( &traceWindings[ node->items[ j ] ], trace ) )
			//%		return;
		}
	}
}
Exemple #2
0
static qboolean TraceLine_r(int nodeNum, vec3_t origin, vec3_t end, trace_t * trace)
{
	traceNode_t    *node;
	int             side;
	float           front, back, frac;
	vec3_t          mid;
	qboolean        r;


	/* bogus node number means solid, end tracing unless testing all */
	if(nodeNum < 0)
	{
		VectorCopy(origin, trace->hit);
		trace->passSolid = qtrue;
		return qtrue;
	}

	/* get node */
	node = &traceNodes[nodeNum];

	/* solid? */
	if(node->type == TRACE_LEAF_SOLID)
	{
		VectorCopy(origin, trace->hit);
		trace->passSolid = qtrue;
		return qtrue;
	}

	/* leafnode? */
	if(node->type < 0)
	{
		/* note leaf and return */
		if(node->numItems > 0 && trace->numTestNodes < MAX_TRACE_TEST_NODES)
			trace->testNodes[trace->numTestNodes++] = nodeNum;
		return qfalse;
	}

	/* ydnar 2003-09-07: don't test branches of the bsp with nothing in them when testall is enabled */
	if(trace->testAll && node->numItems == 0)
		return qfalse;

	/* classify beginning and end points */
	switch (node->type)
	{
		case PLANE_X:
			front = origin[0] - node->plane[3];
			back = end[0] - node->plane[3];
			break;

		case PLANE_Y:
			front = origin[1] - node->plane[3];
			back = end[1] - node->plane[3];
			break;

		case PLANE_Z:
			front = origin[2] - node->plane[3];
			back = end[2] - node->plane[3];
			break;

		default:
			front = DotProduct(origin, node->plane) - node->plane[3];
			back = DotProduct(end, node->plane) - node->plane[3];
			break;
	}

	/* entirely in front side? */
	if(front >= -TRACE_ON_EPSILON && back >= -TRACE_ON_EPSILON)
		return TraceLine_r(node->children[0], origin, end, trace);

	/* entirely on back side? */
	if(front < TRACE_ON_EPSILON && back < TRACE_ON_EPSILON)
		return TraceLine_r(node->children[1], origin, end, trace);

	/* select side */
	side = front < 0;

	/* calculate intercept point */
	frac = front / (front - back);
	mid[0] = origin[0] + (end[0] - origin[0]) * frac;
	mid[1] = origin[1] + (end[1] - origin[1]) * frac;
	mid[2] = origin[2] + (end[2] - origin[2]) * frac;

	/* fixme: check inhibit radius, then solid nodes and ignore */

	/* set trace hit here */
	//% VectorCopy( mid, trace->hit );

	/* trace first side */
	r = TraceLine_r(node->children[side], origin, mid, trace);
	if(r)
		return r;

	/* trace other side */
	return TraceLine_r(node->children[!side], mid, end, trace);
}
void TraceLine( const vec3_t start, const vec3_t stop, trace_t *trace, qboolean testAll, traceWork_t *tw ) {
	int				r;
	int				i, j;
	dleaf_t			*leaf;
	float			oldHitFrac;
	surfaceTest_t	*test;
	int				surfaceNum;
	byte			surfaceTested[MAX_MAP_DRAW_SURFS/8];
	;

	if ( numthreads == 1 ) {
		c_totalTrace++;
	}

	// assume all light gets through, unless the ray crosses
	// a translucent surface
	trace->filter[0] = 1.0;
	trace->filter[1] = 1.0;
	trace->filter[2] = 1.0;

	VectorCopy( start, tw->start );
	VectorCopy( stop, tw->end );
	tw->trace = trace;

	tw->numOpenLeafs = 0;

	trace->passSolid = qfalse;
	trace->hitFraction = 1.0;

	r = TraceLine_r( 0, start, stop, tw );

	// if we hit a solid leaf, stop without testing the leaf
	// surfaces.  Note that the plane and endpoint might not
	// be the first solid intersection along the ray.
	if ( r && !testAll ) {
		return;
	}

	if ( noSurfaces ) {
		return;
	}

	memset( surfaceTested, 0, (numDrawSurfaces+7)/8 );
	oldHitFrac = trace->hitFraction;

	for ( i = 0 ; i < tw->numOpenLeafs ; i++ ) {
		leaf = &dleafs[ tw->openLeafNumbers[ i ] ];
		for ( j = 0 ; j < leaf->numLeafSurfaces ; j++ ) {
			surfaceNum = dleafsurfaces[ leaf->firstLeafSurface + j ];

			// make sure we don't test the same ray against a surface more than once
			if ( surfaceTested[ surfaceNum>>3 ] & ( 1 << ( surfaceNum & 7) ) ) {
				continue;
			}
			surfaceTested[ surfaceNum>>3 ] |= ( 1 << ( surfaceNum & 7 ) );

			test = surfaceTest[ surfaceNum ];
			if ( !test ) {
				continue;
			}
			//
			if ( !tw->patchshadows && test->patch ) {
				continue;
			}
			TraceAgainstSurface( tw, test );
		}

		// if the trace is now solid, we can't possibly hit anything closer
		if ( trace->hitFraction < oldHitFrac ) {
			trace->passSolid = qtrue;
			break;
		}
	}
	
	for ( i = 0 ; i < 3 ; i++ ) {
		trace->hit[i] = start[i] + ( stop[i] - start[i] ) * trace->hitFraction;
	}
}
/*
=============
TraceLine_r

Returns qtrue if something is hit and tracing can stop
=============
*/
int TraceLine_r( int node, const vec3_t start, const vec3_t stop, traceWork_t *tw ) {
	tnode_t	*tnode;
	float	front, back;
	vec3_t	mid;
	float	frac;
	int		side;
	int		r;

	if (node & (1<<31)) {
		if (node & ( 1 << 30 ) ) {
			VectorCopy (start, tw->trace->hit);
			tw->trace->passSolid = qtrue;
			return qtrue;
		} else {
			// save the node off for more exact testing
			if ( tw->numOpenLeafs == MAX_MAP_LEAFS ) {
				return qfalse;
			}
			tw->openLeafNumbers[ tw->numOpenLeafs ] = node & ~(3 << 30);
			tw->numOpenLeafs++;
			return qfalse;
		}
	}

	tnode = &tnodes[node];
	switch (tnode->type) {
	case PLANE_X:
		front = start[0] - tnode->dist;
		back = stop[0] - tnode->dist;
		break;
	case PLANE_Y:
		front = start[1] - tnode->dist;
		back = stop[1] - tnode->dist;
		break;
	case PLANE_Z:
		front = start[2] - tnode->dist;
		back = stop[2] - tnode->dist;
		break;
	default:
		front = (start[0]*tnode->normal[0] + start[1]*tnode->normal[1] + start[2]*tnode->normal[2]) - tnode->dist;
		back = (stop[0]*tnode->normal[0] + stop[1]*tnode->normal[1] + stop[2]*tnode->normal[2]) - tnode->dist;
		break;
	}

	if (front >= -TRACE_ON_EPSILON && back >= -TRACE_ON_EPSILON) {
		return TraceLine_r (tnode->children[0], start, stop, tw);
	}
	
	if (front < TRACE_ON_EPSILON && back < TRACE_ON_EPSILON) {
		return TraceLine_r (tnode->children[1], start, stop, tw);
	}

	side = front < 0;
	
	frac = front / (front-back);

	mid[0] = start[0] + (stop[0] - start[0])*frac;
	mid[1] = start[1] + (stop[1] - start[1])*frac;
	mid[2] = start[2] + (stop[2] - start[2])*frac;

	r = TraceLine_r (tnode->children[side], start, mid, tw);

	if (r) {
		return r;
	}

//	trace->planeNum = tnode->planeNum;
	return TraceLine_r (tnode->children[!side], mid, stop, tw);
}