/* ============ 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); }
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 }