Skip to main content
gamedev.net
🔒 Locked

Rendering Quake 3 .bsp

Started by patrrr Aug 7, 2007 at 6:58 AM 9 replies 2.6k views
Original Post
patrrr
patrrr
Hello! So I'm trying to render bsp's from Quake 3 but I'm having some problems, I'm hoping someone of you have done this before! First question: I've noticed that there are more leaves than faces. How can this be? I don't have to split the faces and stuff like that, do I? Second question: I can't get it to render properly back-to-front, some faces even dissappear when I move about. This is how I render:

void CBSPNode::Traverse(CVector position)  // position is the position of the camera
{
   float side = this->plane.GetSide(position);

   if (side > 0.0) {  // the camera is in front of the plane
      if (this->back) this->back->Traverse(position);
      if (this->leaf1) this->leaf1->Render();
      if (this->leaf2) this->leaf2->Render();
      if (this->front) this->front->Traverse(position);
   }
   else if (side < 0.0) {
      if (this->front) this->front->Traverse(position);
      if (this->leaf1) this->leaf1->Render();
      if (this->leaf2) this->leaf2->Render();
      if (this->back) this->back->Traverse(position);
   }
   else {
      if (this->back) this->back->Traverse(position);
      if (this->front) this->front->Traverse(position);
   }
}
The bsp tree is exactly like the one in the file. I don't know if my plane.GetSide is correct, could someone verify it?

float side = point.DotProduct(plane.normal) - plane.distance;
And a final question: how do I determine which cluster the camera is currently in? I figure I need to know that to render all the other visible clusters?
Deliverance
Deliverance
From what i see I think you are trying to render back to front a solid leaf BSP tree(a tree that has polygon data in the leaves). You cannot do that easily. You can render a solid node bsp tree(a tree that has one or more polygons in every node)back to front easily. Here's some code that could do just that
void RenderSolidNodeTree(int Node, const CVector3D &Position){	// Is this a leaf?	if (NodeArray[Node].isLeaf)			return;		int Result = ClassifyPoint(PolygonArray[NodeArray[Node].PolygonIndex].Plane, Position);		if (Result == CP_FRONT)	{			RenderSolidNodeTree(NodeArray[Node].Back, Position);		RenderPolygon(&PolygonArray[NodeArray[Node].PolygonIndex]);		RenderSolidNodeTree(NodeArray[Node].Front, Position);	}else	{		RenderSolidNodeTree(NodeArray[Node].Front, Position);										     					// This polygon CANNOT be seen so don't render it		// RenderPolygon(&PolygonArray[NodeArray[Node].PolygonIndex]);					RenderSolidNodeTree(NodeArray[Node].Back, Position);	}  }


From what I know quake uses bsp solid leaf tree's and for rendering it uses potential visibility sets, so you cannot render the solid leaf tree as a solid node tree.
As for the other question, you can find the leaf you are currently in by traversing the bsp tree and stopping in a leaf node, the code would be very similar to the one above, just don't render anything and setup a variable when you end up in a leaf to know in which leaf you're in.
patrrr
patrrr
Thanks for your reply!

So you're telling me that I shouldn't render the tree by traversing it?
Should I simply have a list of clusters and their faces, then use the tree to determine camera cluster? This obviously wouldn't work if I want back-to-front sorting...

I don't fully understand why you can't render a solid-leaf tree the way you render a solid-node, the only difference is where you store the polygon data, right?

And why are you only rendering nodes where the camera is on the front side of the node's plane? What if the player rotates the camera?
Extrarius
Extrarius
Do you have backface culling enabled in your graphics library? That might cause some polygons to be hidden if you defined the vertices in the wrong order (presuming bsp files store a 'correct' order).
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Deliverance
Deliverance
You can write a Z-buferless solution that renders the solid leaf tree but with hardware getting faster and faster I think it could be slower than just using a Z buffer instead.

The way to go and render a bsp tree with pvs sets is very simple:
1.0 Find the leaf you are in
2.0 Draw the pvs set associated with the leaf

Why I'm rendering that way? W, I'm not completely sure about that but the code is working code ripped from my bsp application. :)
patrrr
patrrr
I've disabled culling for debugging, everything is perfect when rendering the faces without the tree.
I still don't know why a face is in multiple leaves, any ideas? Is it because I need to split it? Or is that done by the bsp compiler?

Deliverance: I need transparent faces to be sorted back-to-front to avoid the graphical bugs, and instead of just sorting them based on distance from the center to the camera I figured I should use the tree.
Fingers_
Fingers_
IIRC Quake3 moved away from the idea of splitting faces at leaf boundaries (that was how Quake1 and 2 worked), and only splits faces to fix T-junctions. This significantly reduces the polygon count in areas with a complex BSP tree. When rendering, you just have to keep track of whether a face has already been rendered and not draw it again.

I think the optimal way to render is first rendering solid faces front to back, then transparent faces back to front.
patrrr
patrrr
Fingers: that sounds familiar, I'm now doing that (not rendering the same face twice), and the result is the best I've got until now.

There seems to be some kind of offset or origin to the camera position that I'm missing, because when I move around two transparent objects they render properly most of the time, but going a bit higher or closer makes one of the objects render in the wrong order.

But the biggest problem is that the transparent objects are drawn first, even though they're inside a room. This is pretty weird, I've tried stepping through the list of objects in the sorted order and the first face of the room to be rendered is the one furthest away.



Fingers_
Fingers_
I believe the way Quake3 (and most games) deal with transparent faces is that they're not rendered at the same time as the rest of the world. As you're rendering each vis leaf, every time you encounter a transparent face you add it to a sorted list of transparent polygons. When you're done drawing the leaves (and solid objects like player models), you go through the transparent list in the correct order.

Properly sorting transparent polygons is not as easy as it seems at first. Even games like Quake3 can sometimes render stuff in the wrong order (especially if you have very large panes of glass).
patrrr
patrrr
Yes, that's what I'm going to do when I've got the bsp-traversing correct. It should work shouldn't it? Because it's quite unstable at the moment; moving parallel to a face can make it render before faces that are behind it, etc.
And I'm checking this with really easy maps here, nothing fancy. All plane normals are orthogonal to the world.
benryves
benryves
I'm currently working on the previous two versions of the BSP structure (Quake 1 and Quake 2) and tried disabling the Z buffer and using the BSP tree to sort objects. So far I have found no working solution - in the best cases, it mostly works but there are many errant faces being drawn.

Looking over the BSP specifications I have I get the impression that the BSP tree is not used for ordering faces, and that the faces grouped in the leaves are used for the PVS data, and those in the nodes are used for speeding up collision detections.

I haven't delved deeply into either engine's code at this point. I'd be interested to hear if you make any positive progress. [smile]
[Website] [+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.