Esempio n. 1
0
File: bsp.c Progetto: otty/cake3
/*
============
ProcessWorldModel
============
*/
void ProcessWorldModel(void)
{
	int             s;
	entity_t       *e;
	tree_t         *tree;
	bspFace_t      *faces;
	qboolean        leaked;
	xmlNodePtr      polyline, leaknode;
	char            level[2];
	const char     *value;

	e = &entities[0];
	e->firstDrawSurf = 0;		//numMapDrawSurfs;

	// sets integer blockSize from worldspawn "_blocksize" key if it exists
	value = ValueForKey(e, "_blocksize");
	if(value[0] == '\0')
		value = ValueForKey(e, "blocksize");
	if(value[0] == '\0')
		value = ValueForKey(e, "chopsize");	// sof2
	if(value[0] != '\0')
	{
		// scan 3 numbers
		s = sscanf(value, "%d %d %d", &blockSize[0], &blockSize[1], &blockSize[2]);

		// handle legacy case
		if(s == 1)
		{
			blockSize[1] = blockSize[0];
			blockSize[2] = blockSize[0];
		}
	}
	Sys_Printf("block size = { %d %d %d }\n", blockSize[0], blockSize[1], blockSize[2]);

	BeginModel(e);

	// check for patches with adjacent edges that need to LOD together
	PatchMapDrawSurfs(e);

	// build an initial bsp tree using all of the sides
	// of all of the structural brushes
	faces = MakeStructuralBspFaceList(entities[0].brushes);
	tree = FaceBSP(faces);
	MakeTreePortals(tree);
	FilterStructuralBrushesIntoTree(e, tree);

	if(drawFlag)
	{
		// draw unoptimized portals in new window
		drawTree = tree;
		Draw_Scene(DrawTree);
	}

	// see if the bsp is completely enclosed
	if(FloodEntities(tree))
	{
		// rebuild a better bsp tree using only the
		// sides that are visible from the inside
		FillOutside(tree->headnode);

		// chop the sides to the convex hull of
		// their visible fragments, giving us the smallest
		// polygons 
		ClipSidesIntoTree(e, tree);

		faces = MakeVisibleBspFaceList(entities[0].brushes);
		FreeTree(tree);
		tree = FaceBSP(faces);
		MakeTreePortals(tree);
		FilterStructuralBrushesIntoTree(e, tree);
		leaked = qfalse;
	}
	else
	{
		Sys_FPrintf(SYS_NOXML, "**********************\n");
		Sys_FPrintf(SYS_NOXML, "******* leaked *******\n");
		Sys_FPrintf(SYS_NOXML, "**********************\n");

		polyline = LeakFile(tree);
		leaknode = xmlNewNode(NULL, "message");
		xmlNodeSetContent(leaknode, "MAP LEAKED\n");
		xmlAddChild(leaknode, polyline);
		level[0] = (int)'0' + SYS_ERR;
		level[1] = 0;
		xmlSetProp(leaknode, "level", (char *)&level);
		xml_SendNode(leaknode);

		if(leaktest)
		{
			Sys_Printf("--- MAP LEAKED, ABORTING LEAKTEST ---\n");
			exit(0);
		}
		leaked = qtrue;

		// chop the sides to the convex hull of
		// their visible fragments, giving us the smallest
		// polygons 
		ClipSidesIntoTree(e, tree);
	}

	// save out information for visibility processing
	NumberClusters(tree);

	if(!leaked)
	{
		WritePortalFile(tree);
	}

	if(glview)
	{
		// dump the portals for debugging
		WriteGLView(tree, source);
	}

	FloodAreas(tree);

	if(drawFlag)
	{
		// draw optimized portals in new window
		drawTree = tree;
		Draw_Scene(DrawTree);
	}

	// add references to the detail brushes
	FilterDetailBrushesIntoTree(e, tree);

	// create drawsurfs for triangle models
	AddTriangleModels();

	// drawsurfs that cross fog boundaries will need to
	// be split along the bound
	if(!nofog)
	{
		FogDrawSurfs();			// may fragment drawsurfs
	}

	// subdivide each drawsurf as required by shader tesselation
	if(!nosubdivide)
	{
		SubdivideDrawSurfs(e, tree);
	}

	// merge together all common shaders on the same plane and remove 
	// all colinear points, so extra tjunctions won't be generated
	if(!nomerge)
	{
		MergeSides(e, tree);	// !@# testing
	}

	// add in any vertexes required to fix tjunctions
	if(!notjunc)
	{
		FixTJunctions(e);
	}

	// allocate lightmaps for faces and patches
	AllocateLightmaps(e);

	// add references to the final drawsurfs in the apropriate clusters
	FilterDrawsurfsIntoTree(e, tree);

	EndModel(e, tree->headnode);

	FreeTree(tree);
}
Esempio n. 2
0
void BuildFaceTree_r(node_t * node, face_t * list)
{
	face_t         *split;
	face_t         *next;
	int             side;
	plane_t        *plane;
	face_t         *newFace;
	face_t         *childLists[2];
	winding_t      *frontWinding, *backWinding;
	int             i;
	int             splitPlaneNum, compileFlags;
	qboolean        isstruct = qfalse;
	int             splits, front, back;


	/* count faces left */
	i = CountFaceList(list);

#if defined(DEBUG_SPLITS)
	Sys_FPrintf(SYS_VRB, "faces left = %d\n", i);
#endif

	/* select the best split plane */
	SelectSplitPlaneNum(node, list, &splitPlaneNum, &compileFlags);

	/* if we don't have any more faces, this is a leaf */
	if(splitPlaneNum == -1)
	{
		node->planenum = PLANENUM_LEAF;
		node->has_structural_children = qfalse;
		c_faceLeafs++;
		return;
	}

	/* partition the list */
	node->planenum = splitPlaneNum;
	node->compileFlags = compileFlags;
	node->has_structural_children = !(compileFlags & C_DETAIL) && !node->opaque;
	plane = &mapplanes[splitPlaneNum];
	childLists[0] = NULL;
	childLists[1] = NULL;

	splits = front = back = 0;

	for(split = list; split; split = next)
	{
		/* set next */
		next = split->next;

		/* don't split by identical plane */
		if(split->planenum == node->planenum)
		{
			FreeBspFace(split);
			continue;
		}

		if(!(split->compileFlags & C_DETAIL))
			isstruct = 1;

		/* determine which side the face falls on */
		side = WindingOnPlaneSide(split->w, plane->normal, plane->dist);

		/* switch on side */
		if(side == SIDE_CROSS)
		{
			splits++;

			ClipWindingEpsilon(split->w, plane->normal, plane->dist, CLIP_EPSILON * 2, &frontWinding, &backWinding);
			if(frontWinding)
			{
				newFace = AllocBspFace();
				newFace->w = frontWinding;
				newFace->next = childLists[0];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->compileFlags = split->compileFlags;
				childLists[0] = newFace;

				front++;
			}
			if(backWinding)
			{
				newFace = AllocBspFace();
				newFace->w = backWinding;
				newFace->next = childLists[1];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->compileFlags = split->compileFlags;
				childLists[1] = newFace;

				back++;
			}
			FreeBspFace(split);
		}
		else if(side == SIDE_FRONT)
		{
			split->next = childLists[0];
			childLists[0] = split;

			front++;
		}
		else if(side == SIDE_BACK)
		{
			split->next = childLists[1];
			childLists[1] = split;

			back++;
		}
	}


	// recursively process children
	for(i = 0; i < 2; i++)
	{
		node->children[i] = AllocNode();
		node->children[i]->parent = node;
		VectorCopy(node->mins, node->children[i]->mins);
		VectorCopy(node->maxs, node->children[i]->maxs);

		c_faceNodes++;
	}

	for(i = 0; i < 3; i++)
	{
		if(plane->normal[i] == 1)
		{
			node->children[0]->mins[i] = plane->dist;
			node->children[1]->maxs[i] = plane->dist;
			break;
		}
	}

#if 1
	if(drawBSP && drawTree)
	{
		drawChildLists[0] = childLists[0];
		drawChildLists[1] = childLists[1];
		drawSplitNode = node;
		Draw_Scene(DrawAll);
	}
#endif

#if defined(DEBUG_SPLITS)
	if((node->compileFlags & C_DETAIL) && isstruct)
		Sys_FPrintf(SYS_ERR, "I am detail, my child is structural, this is a wtf1\n", node->has_structural_children);
#endif

	for(i = 0; i < 2; i++)
	{
		BuildFaceTree_r(node->children[i], childLists[i]);
		node->has_structural_children |= node->children[i]->has_structural_children;
	}

#if defined(DEBUG_SPLITS)
	if((node->compileFlags & C_DETAIL) && !(node->children[0]->compileFlags & C_DETAIL) &&
	   node->children[0]->planenum != PLANENUM_LEAF)
		Sys_FPrintf(SYS_ERR, "I am detail, my child is structural\n", node->has_structural_children);
	if((node->compileFlags & C_DETAIL) && isstruct)
		Sys_FPrintf(SYS_ERR, "I am detail, my child is structural, this is a wtf2\n", node->has_structural_children);
#endif
}