/* * ProcessSubModel */ static void ProcessSubModel(void){ entity_t *e; int start, end; tree_t *tree; bsp_brush_t *list; vec3_t mins, maxs; e = &entities[entity_num]; start = e->first_brush; end = start + e->num_brushes; mins[0] = mins[1] = mins[2] = -MAX_WORLD_WIDTH; maxs[0] = maxs[1] = maxs[2] = MAX_WORLD_WIDTH; list = MakeBspBrushList(start, end, mins, maxs); if(!nocsg) list = ChopBrushes(list); tree = BrushBSP(list, mins, maxs); MakeTreePortals(tree); MarkVisibleSides(tree, start, end); MakeFaces(tree->head_node); FixTjuncs(tree->head_node); WriteBSP(tree->head_node); FreeTree(tree); }
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== tree_t *ProcessWorldBrushes( int brush_start, int brush_end ) { bspbrush_t *brushes; tree_t *tree; node_t *node; vec3_t mins, maxs; //take the whole world mins[0] = map_mins[0] - 8; mins[1] = map_mins[1] - 8; mins[2] = map_mins[2] - 8; maxs[0] = map_maxs[0] + 8; maxs[1] = map_maxs[1] + 8; maxs[2] = map_maxs[2] + 8; //reset the brush bsp ResetBrushBSP(); // the makelist and chopbrushes could be cached between the passes... //create a list with brushes that are within the given mins/maxs //some brushes will be cut and only the part that falls within the //mins/maxs will be in the bush list brushes = MakeBspBrushList( brush_start, brush_end, mins, maxs ); // if ( !brushes ) { node = AllocNode(); node->planenum = PLANENUM_LEAF; node->contents = CONTENTS_SOLID; tree = Tree_Alloc(); tree->headnode = node; VectorCopy( mins, tree->mins ); VectorCopy( maxs, tree->maxs ); } //end if else { //Carves any intersecting solid brushes into the minimum number //of non-intersecting brushes. if ( !nocsg ) { brushes = ChopBrushes( brushes ); /* if (create_aas) { brushes = MergeBrushes(brushes); } //end if*/ } //end if //if the conversion is cancelled if ( cancelconversion ) { FreeBrushList( brushes ); return NULL; } //end if //create the actual bsp tree tree = BrushBSP( brushes, mins, maxs ); } //end else //return the tree return tree; } //end of the function ProcessWorldBrushes
/* ============ ProcessSubModel ============ */ void ProcessSubModel( ) { entity_t *e; int start, end; tree_t *tree; bspbrush_t *list; Vector mins, maxs; e = &entities[entity_num]; start = e->firstbrush; end = start + e->numbrushes; mins[0] = mins[1] = mins[2] = MIN_COORD_INTEGER; maxs[0] = maxs[1] = maxs[2] = MAX_COORD_INTEGER; list = MakeBspBrushList (start, end, mins, maxs, FULL_DETAIL); if (!nocsg) list = ChopBrushes (list); tree = BrushBSP (list, mins, maxs); // This would wind up crashing the engine because we'd have a negative leaf index in dmodel_t::headnode. if ( tree->headnode->planenum == PLANENUM_LEAF ) { const char *pClassName = ValueForKey( e, "classname" ); const char *pTargetName = ValueForKey( e, "targetname" ); Error( "bmodel %d has no head node (class '%s', targetname '%s')", entity_num, pClassName, pTargetName ); } MakeTreePortals (tree); #if DEBUG_BRUSHMODEL if ( entity_num == DEBUG_BRUSHMODEL ) WriteGLView( tree, "tree_all" ); #endif MarkVisibleSides (tree, start, end, FULL_DETAIL); MakeFaces (tree->headnode); FixTjuncs( tree->headnode, NULL ); WriteBSP( tree->headnode, NULL ); #if DEBUG_BRUSHMODEL if ( entity_num == DEBUG_BRUSHMODEL ) { WriteGLView( tree, "tree_vis" ); WriteGLViewFaces( tree, "tree_faces" ); } #endif FreeTree (tree); }
//----------------------------------------------------------------------------- // Purpose: Build faces for the detail brushes and merge them into the BSP // Input : *worldtree - // brush_start - // brush_end - //----------------------------------------------------------------------------- face_t *MergeDetailTree( tree_t *worldtree, int brush_start, int brush_end ) { int start; bspbrush_t *detailbrushes = NULL; tree_t *detailtree = NULL; face_t *pFaces = NULL; face_t *pLeafFaceList = NULL; // Grab the list of detail brushes detailbrushes = MakeBspBrushList (brush_start, brush_end, map_mins, map_maxs, ONLY_DETAIL ); if (detailbrushes) { start = Plat_FloatTime(); Msg("Chop Details..."); // if there are detail brushes, chop them against each other if (!nocsg) detailbrushes = ChopBrushes (detailbrushes); Msg("done (%d)\n", (int)(Plat_FloatTime() - start) ); // Now mark the visible sides so we can eliminate all detail brush sides // that are covered by other detail brush sides // NOTE: This still leaves detail brush sides that are covered by the world. (these are removed in the merge operation) Msg("Find Visible Detail Sides..."); pFaces = ComputeVisibleBrushSides( detailbrushes ); TryMergeFaceList( &pFaces ); SubdivideFaceList( &pFaces ); Msg("done (%d)\n", (int)(Plat_FloatTime() - start) ); start = Plat_FloatTime(); Msg("Merging details..."); // Merge the detail solids and faces into the world tree // Merge all of the faces into the world tree pLeafFaceList = FilterFacesIntoTree( worldtree, pFaces ); FilterBrushesIntoTree( worldtree, detailbrushes ); FreeFaceList( pFaces ); FreeBrushList(detailbrushes); Msg("done (%d)\n", (int)(Plat_FloatTime() - start) ); } return pLeafFaceList; }
static void ProcessBlock_Thread(int blocknum){ int xblock, yblock; vec3_t mins, maxs; bsp_brush_t *brushes; tree_t *tree; node_t *node; yblock = block_yl + blocknum / (block_xh - block_xl + 1); xblock = block_xl + blocknum % (block_xh - block_xl + 1); Com_Verbose("############### block %2i,%2i ###############\n", xblock, yblock); mins[0] = xblock * 1024; mins[1] = yblock * 1024; mins[2] = -MAX_WORLD_WIDTH; maxs[0] = (xblock + 1) * 1024; maxs[1] = (yblock + 1) * 1024; maxs[2] = MAX_WORLD_WIDTH; ThreadLock(); // the makelist and chopbrushes could be cached between the passes... brushes = MakeBspBrushList(brush_start, brush_end, mins, maxs); if(!brushes){ node = AllocNode(); node->plane_num = PLANENUM_LEAF; node->contents = CONTENTS_SOLID; block_nodes[xblock + 5][yblock + 5] = node; ThreadUnlock(); return; } if(!nocsg) brushes = ChopBrushes(brushes); tree = BrushBSP(brushes, mins, maxs); ThreadUnlock(); block_nodes[xblock + 5][yblock + 5] = tree->head_node; }
//----------------------------------------------------------------------------- // Clips all occluder brushes against each other //----------------------------------------------------------------------------- static tree_t *ClipOccluderBrushes( ) { // Create a list of all occluder brushes in the level CUtlVector< mapbrush_t * > mapBrushes( 1024, 1024 ); for ( entity_num=0; entity_num < g_MainMap->num_entities; ++entity_num ) { if (!IsFuncOccluder(entity_num)) continue; entity_t *e = &entities[entity_num]; int end = e->firstbrush + e->numbrushes; int i; for ( i = e->firstbrush; i < end; ++i ) { mapBrushes.AddToTail( &g_MainMap->mapbrushes[i] ); } } int nBrushCount = mapBrushes.Count(); if ( nBrushCount == 0 ) return NULL; Vector mins, maxs; mins[0] = mins[1] = mins[2] = MIN_COORD_INTEGER; maxs[0] = maxs[1] = maxs[2] = MAX_COORD_INTEGER; bspbrush_t *list = MakeBspBrushList( mapBrushes.Base(), nBrushCount, mins, maxs ); if (!nocsg) list = ChopBrushes (list); tree_t *tree = BrushBSP (list, mins, maxs); MakeTreePortals (tree); MarkVisibleSides (tree, mapBrushes.Base(), nBrushCount); MakeFaces( tree->headnode ); // NOTE: This will output the occluder face vertices + planes FixTjuncs( tree->headnode, NULL ); return tree; }
/** * @sa ProcessModels */ static void ProcessSubModel (int entityNum) { const entity_t* e; int start, end; tree_t* tree; bspbrush_t* list; AABB aabb; BeginModel(entityNum); e = &entities[entityNum]; #if 0 Com_Printf("Processing entity: %i into model %i (%s:%s)\n", entityNum, curTile->nummodels, e->epairs->key, e->epairs->value); #endif start = e->firstbrush; end = start + e->numbrushes; aabb.reset(); aabb.expand(MAX_WORLD_WIDTH); /* every level (-1) */ list = MakeBspBrushList(start, end, -1, aabb); if (!config.nocsg) list = ChopBrushes(list); tree = BuildTree(list, aabb.mins, aabb.maxs); assert(tree); assert(tree->headnode); if (tree->headnode->planenum == PLANENUM_LEAF) Sys_Error("No head node bmodel of %s (%i)\n", ValueForKey(e, "classname"), entityNum); MakeTreePortals(tree); MarkVisibleSides(tree, start, end); MakeFaces(tree->headnode); FixTjuncs(tree->headnode); curTile->models[curTile->nummodels].headnode = WriteBSP(tree->headnode); FreeTree(tree); EndModel(); }
void ProcessBlock_Thread (int threadnum, int blocknum) { int xblock, yblock; Vector mins, maxs; bspbrush_t *brushes; tree_t *tree; node_t *node; yblock = block_yl + blocknum / (block_xh-block_xl+1); xblock = block_xl + blocknum % (block_xh-block_xl+1); qprintf ("############### block %2i,%2i ###############\n", xblock, yblock); mins[0] = xblock*BLOCKS_SIZE; mins[1] = yblock*BLOCKS_SIZE; mins[2] = MIN_COORD_INTEGER; maxs[0] = (xblock+1)*BLOCKS_SIZE; maxs[1] = (yblock+1)*BLOCKS_SIZE; maxs[2] = MAX_COORD_INTEGER; // the makelist and chopbrushes could be cached between the passes... brushes = MakeBspBrushList (brush_start, brush_end, mins, maxs, NO_DETAIL); if (!brushes) { node = AllocNode (); node->planenum = PLANENUM_LEAF; node->contents = CONTENTS_SOLID; block_nodes[xblock+BLOCKX_OFFSET][yblock+BLOCKY_OFFSET] = node; return; } FixupAreaportalWaterBrushes( brushes ); if (!nocsg) brushes = ChopBrushes (brushes); tree = BrushBSP (brushes, mins, maxs); block_nodes[xblock+BLOCKX_OFFSET][yblock+BLOCKY_OFFSET] = tree->headnode; }
/** * @sa ProcessLevel * @return The node num */ static int32_t ConstructLevelNodes_r (const int levelnum, const vec3_t cmins, const vec3_t cmaxs, int entityNum) { bspbrush_t *list; tree_t *tree; vec3_t diff, bmins, bmaxs; int32_t nn[3]; node_t *node; /* calculate bounds, stop if no brushes are available */ if (!MapBrushesBounds(brush_start, brush_end, levelnum, cmins, cmaxs, bmins, bmaxs)) return LEAFNODE; Verb_Printf(VERB_DUMP, "ConstructLevelNodes_r: lv=%i (%f %f %f) (%f %f %f)\n", levelnum, cmins[0], cmins[1], cmins[2], cmaxs[0], cmaxs[1], cmaxs[2]); VectorSubtract(bmaxs, bmins, diff); /* Com_Printf("(%i): %i %i: (%i %i) (%i %i) -> (%i %i) (%i %i)\n", levelnum, (int)diff[0], (int)diff[1], (int)cmins[0], (int)cmins[1], (int)cmaxs[0], (int)cmaxs[1], (int)bmins[0], (int)bmins[1], (int)bmaxs[0], (int)bmaxs[1]); */ if (diff[0] > SPLIT_BRUSH_SIZE || diff[1] > SPLIT_BRUSH_SIZE) { /* continue subdivision */ /* split the remaining hull at the middle of the longer axis */ vec3_t nmins, nmaxs; int n; if (diff[1] > diff[0]) n = 1; else n = 0; VectorCopy(bmins, nmins); VectorCopy(bmaxs, nmaxs); nmaxs[n] -= diff[n] / 2; /* Com_Printf(" (%i %i) (%i %i)\n", (int)nmins[0], (int)nmins[1], (int)nmaxs[0], (int)nmaxs[1]); */ nn[0] = ConstructLevelNodes_r(levelnum, nmins, nmaxs, entityNum); nmins[n] += diff[n] / 2; nmaxs[n] += diff[n] / 2; /* Com_Printf(" (%i %i) (%i %i)\n", (int)nmins[0], (int)nmins[1], (int)nmaxs[0], (int)nmaxs[1]); */ nn[1] = ConstructLevelNodes_r(levelnum, nmins, nmaxs, entityNum); } else { /* no children */ nn[0] = LEAFNODE; nn[1] = LEAFNODE; } /* add v_epsilon to avoid clipping errors */ VectorSubtract(bmins, v_epsilon, bmins); VectorAdd(bmaxs, v_epsilon, bmaxs); /* Call BeginModel only to initialize brush pointers */ BeginModel(entityNum); list = MakeBspBrushList(brush_start, brush_end, levelnum, bmins, bmaxs); if (!list) { nn[2] = LEAFNODE; return BuildNodeChildren(nn); } if (!config.nocsg) list = ChopBrushes(list); /* begin model creation now */ tree = BuildTree(list, bmins, bmaxs); MakeTreePortals(tree); MarkVisibleSides(tree, brush_start, brush_end); MakeFaces(tree->headnode); FixTjuncs(tree->headnode); if (!config.noprune) PruneNodes(tree->headnode); /* correct bounds */ node = tree->headnode; VectorAdd(bmins, v_epsilon, node->mins); VectorSubtract(bmaxs, v_epsilon, node->maxs); /* finish model */ nn[2] = WriteBSP(tree->headnode); FreeTree(tree); /* Store created nodes */ return BuildNodeChildren(nn); }