/* ============ BlockTree ============ */ node_t *BlockTree (int xl, int yl, int xh, int yh) { node_t *node; vec3_t normal; float dist; int mid; if (xl == xh && yl == yh) { node = block_nodes[xl+5][yl+5]; if (!node) { // return an empty leaf node = AllocNode (); node->planenum = PLANENUM_LEAF; node->contents = 0; //CONTENTS_SOLID; return node; } return node; } // create a seperator along the largest axis node = AllocNode (); if (xh - xl > yh - yl) { // split x axis mid = xl + (xh-xl)/2 + 1; normal[0] = 1; normal[1] = 0; normal[2] = 0; dist = mid*1024; node->planenum = FindFloatPlane (normal, dist); node->children[0] = BlockTree ( mid, yl, xh, yh); node->children[1] = BlockTree ( xl, yl, mid-1, yh); } else { mid = yl + (yh-yl)/2 + 1; normal[0] = 0; normal[1] = 1; normal[2] = 0; dist = mid*1024; node->planenum = FindFloatPlane (normal, dist); node->children[0] = BlockTree ( xl, mid, xh, yh); node->children[1] = BlockTree ( xl, yl, xh, mid-1); } return node; }
/* * ProcessWorldModel */ static void ProcessWorldModel(void){ entity_t *e; tree_t *tree; boolean_t leaked; boolean_t optimize; e = &entities[entity_num]; brush_start = e->first_brush; brush_end = brush_start + e->num_brushes; leaked = false; // perform per-block operations if(block_xh * 1024 > map_maxs[0]) block_xh = floor(map_maxs[0] / 1024.0); if((block_xl + 1) * 1024 < map_mins[0]) block_xl = floor(map_mins[0] / 1024.0); if(block_yh * 1024 > map_maxs[1]) block_yh = floor(map_maxs[1] / 1024.0); if((block_yl + 1) * 1024 < map_mins[1]) block_yl = floor(map_mins[1] / 1024.0); if(block_xl < -4) block_xl = -4; if(block_yl < -4) block_yl = -4; if(block_xh > 3) block_xh = 3; if(block_yh > 3) block_yh = 3; for(optimize = false; optimize <= true; optimize++){ Com_Verbose("--------------------------------------------\n"); RunThreadsOn((block_xh - block_xl + 1) * (block_yh - block_yl + 1), !verbose, ProcessBlock_Thread); // build the division tree // oversizing the blocks guarantees that all the boundaries // will also get nodes. Com_Verbose("--------------------------------------------\n"); tree = AllocTree(); tree->head_node = BlockTree(block_xl - 1, block_yl - 1, block_xh + 1, block_yh + 1); tree->mins[0] = (block_xl) * 1024; tree->mins[1] = (block_yl) * 1024; tree->mins[2] = map_mins[2] - 8; tree->maxs[0] = (block_xh + 1) * 1024; tree->maxs[1] = (block_yh + 1) * 1024; tree->maxs[2] = map_maxs[2] + 8; // perform the global operations MakeTreePortals(tree); if(FloodEntities(tree)) FillOutside(tree->head_node); else { leaked = true; LeakFile(tree); if(leaktest){ Com_Error(ERR_FATAL, "--- MAP LEAKED, ABORTING LEAKTEST ---\n"); } Com_Verbose("**** leaked ****\n"); } MarkVisibleSides(tree, brush_start, brush_end); if(noopt || leaked) break; if(!optimize){ FreeTree(tree); } } FloodAreas(tree); MakeFaces(tree->head_node); FixTjuncs(tree->head_node); if(!noprune) PruneNodes(tree->head_node); WriteBSP(tree->head_node); if(!leaked) WritePortalFile(tree); FreeTree(tree); }
/* ============ ProcessWorldModel ============ */ void ProcessWorldModel (void) { entity_t *e; tree_t *tree; qboolean leaked; qboolean optimize; e = &entities[entity_num]; brush_start = e->firstbrush; brush_end = brush_start + e->numbrushes; leaked = false; // // perform per-block operations // if (block_xh * 1024 > map_maxs[0]) block_xh = floor(map_maxs[0]/1024.0); if ( (block_xl+1) * 1024 < map_mins[0]) block_xl = floor(map_mins[0]/1024.0); if (block_yh * 1024 > map_maxs[1]) block_yh = floor(map_maxs[1]/1024.0); if ( (block_yl+1) * 1024 < map_mins[1]) block_yl = floor(map_mins[1]/1024.0); if (block_xl <-4) block_xl = -4; if (block_yl <-4) block_yl = -4; if (block_xh > 3) block_xh = 3; if (block_yh > 3) block_yh = 3; for (optimize = false ; optimize <= true ; optimize++) { qprintf ("--------------------------------------------\n"); RunThreadsOnIndividual ((block_xh-block_xl+1)*(block_yh-block_yl+1), !verbose, ProcessBlock_Thread); // // build the division tree // oversizing the blocks guarantees that all the boundaries // will also get nodes. // qprintf ("--------------------------------------------\n"); tree = AllocTree (); tree->headnode = BlockTree (block_xl-1, block_yl-1, block_xh+1, block_yh+1); tree->mins[0] = (block_xl)*1024; tree->mins[1] = (block_yl)*1024; tree->mins[2] = map_mins[2] - 8; tree->maxs[0] = (block_xh+1)*1024; tree->maxs[1] = (block_yh+1)*1024; tree->maxs[2] = map_maxs[2] + 8; // // perform the global operations // MakeTreePortals (tree); if (FloodEntities (tree)) FillOutside (tree->headnode); else { printf ("**** leaked ****\n"); leaked = true; LeakFile (tree); if (leaktest) { printf ("--- MAP LEAKED ---\n"); exit (0); } } MarkVisibleSides (tree, brush_start, brush_end); if (noopt || leaked) break; if (!optimize) { FreeTree (tree); } } FloodAreas (tree); if (glview) WriteGLView (tree, source); MakeFaces (tree->headnode); FixTjuncs (tree->headnode); if (!noprune) PruneNodes (tree->headnode); WriteBSP (tree->headnode); if (!leaked) WritePortalFile (tree); FreeTree (tree); }
void ProcessWorldModel (void) { entity_t *e; tree_t *tree = NULL; qboolean leaked; int optimize; int start; e = &entities[entity_num]; brush_start = e->firstbrush; brush_end = brush_start + e->numbrushes; leaked = false; // // perform per-block operations // if (block_xh * BLOCKS_SIZE > g_MainMap->map_maxs[0]) { block_xh = floor(g_MainMap->map_maxs[0]/BLOCKS_SIZE); } if ( (block_xl+1) * BLOCKS_SIZE < g_MainMap->map_mins[0]) { block_xl = floor(g_MainMap->map_mins[0]/BLOCKS_SIZE); } if (block_yh * BLOCKS_SIZE > g_MainMap->map_maxs[1]) { block_yh = floor(g_MainMap->map_maxs[1]/BLOCKS_SIZE); } if ( (block_yl+1) * BLOCKS_SIZE < g_MainMap->map_mins[1]) { block_yl = floor(g_MainMap->map_mins[1]/BLOCKS_SIZE); } // HLTOOLS: updated to +/- MAX_COORD_INTEGER ( new world size limits / worldsize.h ) if (block_xl < BLOCKS_MIN) { block_xl = BLOCKS_MIN; } if (block_yl < BLOCKS_MIN) { block_yl = BLOCKS_MIN; } if (block_xh > BLOCKS_MAX) { block_xh = BLOCKS_MAX; } if (block_yh > BLOCKS_MAX) { block_yh = BLOCKS_MAX; } for (optimize = 0 ; optimize <= 1 ; optimize++) { qprintf ("--------------------------------------------\n"); RunThreadsOnIndividual ((block_xh-block_xl+1)*(block_yh-block_yl+1), !verbose, ProcessBlock_Thread); // // build the division tree // oversizing the blocks guarantees that all the boundaries // will also get nodes. // qprintf ("--------------------------------------------\n"); tree = AllocTree (); tree->headnode = BlockTree (block_xl-1, block_yl-1, block_xh+1, block_yh+1); tree->mins[0] = (block_xl)*BLOCKS_SIZE; tree->mins[1] = (block_yl)*BLOCKS_SIZE; tree->mins[2] = g_MainMap->map_mins[2] - 8; tree->maxs[0] = (block_xh+1)*BLOCKS_SIZE; tree->maxs[1] = (block_yh+1)*BLOCKS_SIZE; tree->maxs[2] = g_MainMap->map_maxs[2] + 8; // // perform the global operations // // make the portals/faces by traversing down to each empty leaf MakeTreePortals (tree); if (FloodEntities (tree)) { // turns everthing outside into solid FillOutside (tree->headnode); } else { Warning( ("**** leaked ****\n") ); leaked = true; LeakFile (tree); if (leaktest) { Warning( ("--- MAP LEAKED ---\n") ); exit (0); } } // mark the brush sides that actually turned into faces MarkVisibleSides (tree, brush_start, brush_end, NO_DETAIL); if (noopt || leaked) break; if (!optimize) { // If we are optimizing, free the tree. Next time we will construct it again, but // we'll use the information in MarkVisibleSides() so we'll only split with planes that // actually contribute renderable geometry FreeTree (tree); } } FloodAreas (tree); RemoveAreaPortalBrushes_R( tree->headnode ); start = Plat_FloatTime(); Msg("Building Faces..."); // this turns portals with one solid side into faces // it also subdivides each face if necessary to fit max lightmap dimensions MakeFaces (tree->headnode); Msg("done (%d)\n", (int)(Plat_FloatTime() - start) ); if (glview) { WriteGLView (tree, source); } AssignOccluderAreas( tree ); Compute3DSkyboxAreas( tree->headnode, g_SkyAreas ); face_t *pLeafFaceList = NULL; if ( !nodetail ) { pLeafFaceList = MergeDetailTree( tree, brush_start, brush_end ); } start = Plat_FloatTime(); Msg("FixTjuncs...\n"); // This unifies the vertex list for all edges (splits collinear edges to remove t-junctions) // It also welds the list of vertices out of each winding/portal and rounds nearly integer verts to integer pLeafFaceList = FixTjuncs (tree->headnode, pLeafFaceList); // this merges all of the solid nodes that have separating planes if (!noprune) { Msg("PruneNodes...\n"); PruneNodes (tree->headnode); } // Msg( "SplitSubdividedFaces...\n" ); // SplitSubdividedFaces( tree->headnode ); Msg("WriteBSP...\n"); WriteBSP (tree->headnode, pLeafFaceList); Msg("done (%d)\n", (int)(Plat_FloatTime() - start) ); if (!leaked) { WritePortalFile (tree); } FreeTree( tree ); FreeLeafFaces( pLeafFaceList ); }