- Maintain bounding box (or even a list of bounding boxes)


Rendering:

	- get bounding boxes of graph
	

	render_scene_graph ()
	{
		get bounding box()
		split into front part and back part()
		render_opaque (front part);
		render_opaque (back part);
		render_translucent (back part);
		render_translucent (font part);
	}

	This might work, but assumes that each leaf in the 
	graph is convex and doesn't 'cover' itself. In other 
	words, the polygons drawn by any single node must never
	have to be blended with each other.
		Solution might be to have
	
		cm_state_begin (GL_QUADS)
		cm_state_emit_vertex (x, y, z);
		...;
		cm_end_begin

		where the state would take care of sorting the resulting
		quads, according to render mode. Polygons that
		intersect other polygons are probably hopeless to get
		right.

	Actually, the algorithm below has the problem that it assumes
	that node_class->render will render in back-to-front order (or 	
	the other way around). 

	Probably the only thing to do is to actually sort all the polygons
	(assuming polygons don't intersect):

	maintain a tree of cmstate. Every polygon to be rendered is added
	to an array, with a pointer to the current state. When all polygons
	have been entered, 

		(a) first the array is sorted according to solid/translucent
		    of the polygons

		(b) then the solid polygons are sorted from front to back

		(c) then the translucent polygons are sorted

		(d) Then the array is traversed, and quads are emitted,
		    with state changes and begins/ends according to
		    the state in the state tree.
	
	Note that coplanar polygons must be treated specially: They should
	be drawn in the order they are given, even those with alpha. The
	entire coplanar segment needs to be drawn in its proper place 
	in the sorting order.

	Also, coplanar polygons need to be rendered twice, once with depth
	buffer disabled, and once with color buffer disabled. This is a
	pretty serious performance degradation however. Maybe if we _know_
	that we are doing 2D rendering we could disable depth buffering,
	which will cause the stacker not do the second stage.

	How to compare polygons. Comparing the farthest z coordinate doesn't
	work: Imagine a very long polygon in front of a very short one. The
	long polygon will have a z coordinate deep in the screen, but the
	short one should be rendered first.

	Probably the right way is to

		CompareTriangles (a, b):

		2DPoint ap[3], bp[3];

		compute_screen_projection (a, ap);
		compute_screen_projection (b, bp);

		if (ap intersects bp)
		{
			(x, y) = an intersection point;

			project (x, y) back onto a
			project (x, y) back onto b

			compare depths of those backprojected points.
		}

		This is going to be really slow to do n log n times.
		Although: we could cache the screen projections and
		hope that the bounding boxes of the intersections would
		rarely intersect.

		Note that this is really a partial sort: We don't
		care about the order of polygons whose screen
		projections don't intersect.

	Will we have to turn off depth buffering completely?


	Another algorithm:

		- sort all vertices, and store with them
		  a pointer to the polygon

		- keep list of open triangles

		- move along the vertex list from back to front

		- whenever a polygon is complete and there are no
		  other open polygons, draw it

		- (doesn't work)

	Yet another:

	Compute the projection of all edges into screenspace, then
	compute the intersections of all such edges. Assume non-degenerate
	case where all intersection points are exactly for two edges. 

	For all those intersection points we can compute a layering of
	two polygons. We can even detect inconsistencies (intersecting
	polygons). (So we just do depth buffering for those).

	Bounding boxes:

	For each node, compute guaranteed screen coverage, which is
	a list of (rectangle/depth) pairs. All nodes whose complete
	screen projection is subsumed by rectangle/depth pairs, can
	be culled. The depths in the rectangle/depth pairs are the
	farthest of the vertices in the node. 

	probably call them minimum and maximum screen projections.

	cm_node_render (Node *node, 
			State *state,
			Boxes *boxes)
	{
		klass = CM_NODE_GET_CLASS (node);

		get_bounding_box (node);
		if (box in boxes == OUTSIDE)
			return;
		else
			boxes = insersect (boxes, box);

		if (!state)
			state = state_new ();

		if (state->render_mode == BOTH)
		{
			state_set_render_mode (state, SOLID);
			cm_node_render (node, state, boxes);

			state_set_render_mode (state, TRANSLUCENT);
			cm_node_render (node, state, boxes);
		}
		else
		{
			front_part, back_part = split (boxes, mid_point);

			if (state->render_mode == TRANS)
			{	
				cm_node_render (node, state, back_part);
				cm_node_render (node, state, front_part);
			}
			else if (state->render_mode == SOLID)
			{
				cm_node_render (node, state, front_part);
				cm_node_render (node, state, back_part);
			}
			else
			{
				g_assert_not_reached();
			}
		}
	}

	cm_node_render_translucent ()
	{
		if (state_has_alpha (state))
		{
		}
	}


	node_render (node)
	{
		split

	}

	- render_opaque (node, state, boxes)
		
