Getting Surface Flags in qrad3?

Discuss the construction of maps and the tools to create maps for 3D games.
Post Reply
jitspoe
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Getting Surface Flags in qrad3?

Post by jitspoe »

So I'm basically rewriting the sun light feature in qrad3, and I need to do a trace that will return true if it hits sky. I'm running into a bit of an issue, though. For some reason, I can't seem to get to the brushes with the trace.

Original trace:

Code: Select all

int TestLine_r (int node, vec3_t set_start, vec3_t stop)
{
	tnode_t	*tnode;
	float	front, back;
	vec3_t	mid, start;
	float	frac;
	int		side;
	int		r;

	start[0] = set_start[0];
	start[1] = set_start[1];
	start[2] = set_start[2];

re_test:

	if (node & (1<<31))
	{
		return node & ~(1<<31);	// leaf node
	}

	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 >= -ON_EPSILON && back >= -ON_EPSILON)
	{
		node = tnode->children[0];

		goto re_test;

		//		return TestLine_r (tnode->children[0], start, stop);
	}

	if (front < ON_EPSILON && back < ON_EPSILON)
	{
		node = tnode->children[1];

		goto re_test;

		//		return TestLine_r (tnode->children[1], start, stop);
	}

	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 = TestLine_r (tnode->children[side], start, mid);

	if (r)
		return r;

	node = tnode->children[!side];

	start[0] = mid[0];
	start[1] = mid[1];
	start[2] = mid[2];

	goto re_test;

	//    return TestLine_r (tnode->children[!side], mid, stop);
}
My modified version, which tries to collide against the actual brushes (Using CM_TraceToLeaf/CM_ClipBoxToBrush from the engine code as reference):

Code: Select all

// jit - mostly copied from TestLine_r.
static int TraceToSky_r (vec3_t scale, int node, const vec3_t start_in, const vec3_t stop)
{
	tnode_t	*tnode;
	float	front, back;
	vec3_t	mid, start;
	float	frac;
	int		side;
	int		r;

	start[0] = start_in[0];
	start[1] = start_in[1];
	start[2] = start_in[2];

re_test:

	// Nodes < 0 (highest bit set) are leaf nodes.
	if (node & (1<<31))
	{
		int leafnum = node & ~(1<<31);	// leaf node

		if (leafnum)
		{
			int			k;
			int			brushnum;
			dleaf_t		*leaf;
			dbrush_t	*b;
			int			brushtestret;

			//leaf = &map_leafs[leafnum];
			leaf = dleafs + leafnum;

			// trace line against all brushes in the leaf
			for (k = 0; k < leaf->numleafbrushes; ++k)
			{
				//brushnum = map_leafbrushes[leaf->firstleafbrush + k];
				brushnum = dleafbrushes[leaf->firstleafbrush + k];
				//b = &map_brushes[brushnum];
				b = dbrushes + brushnum;

				//if (b->checkcount == checkcount)
				//	continue;	// already checked this brush in another leaf

				//b->checkcount = checkcount;

				//if (!(b->contents & trace_contents))
				//	continue;

				brushtestret = TraceToSkyBrushTest(scale, start, stop, b);

				if (brushtestret != 0)
					return brushtestret;
			}
		}

		return 0;
	}

	// todo: seems the conditional checks here would probably be slower than just doing the math -- test that theory.
	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 >= -ON_EPSILON && back >= -ON_EPSILON)
	{
		node = tnode->children[0];

		goto re_test;

		//		return TestLine_r (tnode->children[0], start, stop);
	}

	if (front < ON_EPSILON && back < ON_EPSILON)
	{
		node = tnode->children[1];

		goto re_test;

		//		return TestLine_r (tnode->children[1], start, stop);
	}

	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 = TraceToSky_r(scale, tnode->children[side], start, mid);

	if (r)
		return r;

	node = tnode->children[!side];

	start[0] = mid[0];
	start[1] = mid[1];
	start[2] = mid[2];

	goto re_test;
}
(Pardon the sloppy WIP code).

Problem I'm running into is that leaf->numleafbrushes is always 0. I never actually get into that loop where it checks against all the brushes.

Most leaf nodes are either 0x80000000 or 0x80000001.

There ARE leaves that have brushes, but I never seem to be hitting them. I'm not sure what I'm doing wrong. Probably something stupid. Any ideas?
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Getting Surface Flags in qrad3?

Post by Spike »

TestLine returns contents values, not leaf numbers.
MakeTnode stores the leaf's contents into the tnode's parent, so you'll need to either modify the tnodes or just directly use the dnodes+dplanes
that's why your code deals with bits instead of using the if(node<0)leafnum=(-1-node); conversion that is native to the bsp format.
jitspoe
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Re: Getting Surface Flags in qrad3?

Post by jitspoe »

Ah-HAH! I see it.

Code: Select all

		if (node->children[i] < 0)
		{
			t->children[i] = (dleafs[-node->children[i] - 1].contents & CONTENTS_SOLID) | (1<<31);
		}
		else
		{
			t->children[i] = tnode_p - tnodes;
			MakeTnode (node->children[i]);
		}
Thanks a bunch!
Post Reply