From 512d14736ca4e108a1afec7403db90e7cf83ab34 Mon Sep 17 00:00:00 2001 From: Garux Date: Thu, 21 Oct 2021 04:48:54 +0300 Subject: [PATCH] * region build: widen temp box to handle small volumes, light entities at the edge and flat primitives * region build: pull temporal respawn to the box instead of error --- radiant/brushmanip.cpp | 8 +-- radiant/map.cpp | 127 ++++++++++++++++++----------------------- radiant/qe3.cpp | 19 ------ 3 files changed, 61 insertions(+), 93 deletions(-) diff --git a/radiant/brushmanip.cpp b/radiant/brushmanip.cpp index 44dcdda9..b181faca 100644 --- a/radiant/brushmanip.cpp +++ b/radiant/brushmanip.cpp @@ -473,12 +473,12 @@ void Brush_ConstructPrefab( Brush& brush, EBrushPrefab type, const AABB& bounds, void ConstructRegionBrushes( scene::Node* brushes[6], const Vector3& region_mins, const Vector3& region_maxs ){ { // set mins - Vector3 mins( region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32 ); + const Vector3 mins( region_mins - Vector3( 32 ) ); // vary maxs for ( std::size_t i = 0; i < 3; i++ ) { - Vector3 maxs( region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32 ); + Vector3 maxs( region_maxs + Vector3( 32 ) ); maxs[i] = region_mins[i]; Brush_ConstructCuboid( *Node_getBrush( *brushes[i] ), aabb_for_minmax( mins, maxs ), texdef_name_default(), TextureProjection() ); } @@ -486,12 +486,12 @@ void ConstructRegionBrushes( scene::Node* brushes[6], const Vector3& region_mins { // set maxs - Vector3 maxs( region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32 ); + const Vector3 maxs( region_maxs + Vector3( 32 ) ); // vary mins for ( std::size_t i = 0; i < 3; i++ ) { - Vector3 mins( region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32 ); + Vector3 mins( region_mins - Vector3( 32 ) ); mins[i] = region_maxs[i]; Brush_ConstructCuboid( *Node_getBrush( *brushes[i + 3] ), aabb_for_minmax( mins, maxs ), texdef_name_default(), TextureProjection() ); } diff --git a/radiant/map.cpp b/radiant/map.cpp index b7e29c3b..cc26ece8 100644 --- a/radiant/map.cpp +++ b/radiant/map.cpp @@ -390,10 +390,6 @@ void Map_SetWorldspawn( Map& map, scene::Node* node ){ } -void AddRegionBrushes( void ); -void RemoveRegionBrushes( void ); - - /* ================ Map_Free @@ -1338,16 +1334,6 @@ void Map_Traverse_Region( scene::Node& root, const scene::Traversable::Walker& w } } -bool Map_SaveRegion( const char *filename ){ - AddRegionBrushes(); - - bool success = MapResource_saveFile( MapFormat_forFile( filename ), GlobalSceneGraph().root(), Map_Traverse_Region, filename ); - - RemoveRegionBrushes(); - - return success; -} - void Map_RenameAbsolute( const char* absolute ){ Resource* resource = GlobalReferenceCache().capture( absolute ); @@ -1419,33 +1405,6 @@ void Map_New(){ GridStatus_changed(); } -extern void ConstructRegionBrushes( scene::Node * brushes[6], const Vector3 ®ion_mins, const Vector3 ®ion_maxs ); - -void ConstructRegionStartpoint( scene::Node* startpoint, const Vector3& region_mins, const Vector3& region_maxs ){ - /*! - \todo we need to make sure that the player start IS inside the region and bail out if it's not - the compiler will refuse to compile a map with a player_start somewhere in empty space.. - for now, let's just print an error - */ - - Vector3 vOrig( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ) ); - - for ( int i = 0 ; i < 3 ; i++ ) - { - if ( vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i] ) { - globalErrorStream() << "Camera is NOT in the region, it's likely that the region won't compile correctly\n"; - break; - } - } - - // write the info_playerstart - char sTmp[1024]; - sprintf( sTmp, "%d %d %d", (int)vOrig[0], (int)vOrig[1], (int)vOrig[2] ); - Node_getEntity( *startpoint )->setKeyValue( "origin", sTmp ); - sprintf( sTmp, "%d", (int)Camera_getAngles( *g_pParentWnd->GetCamWnd() )[CAMERA_YAW] ); - Node_getEntity( *startpoint )->setKeyValue( "angle", sTmp ); -} - /* =========================================================== @@ -1461,13 +1420,10 @@ ToggleItem g_region_item( g_region_caller ); Vector3 g_region_mins; Vector3 g_region_maxs; void Region_defaultMinMax(){ - g_region_maxs[0] = g_region_maxs[1] = g_region_maxs[2] = GetMaxGridCoord(); - g_region_mins[0] = g_region_mins[1] = g_region_mins[2] = -GetMaxGridCoord(); + g_region_maxs = Vector3( GetMaxGridCoord() ); + g_region_mins = -g_region_maxs; } -scene::Node* region_sides[6]; -scene::Node* region_startpoint = 0; - /* =========== AddRegionBrushes @@ -1477,30 +1433,61 @@ scene::Node* region_startpoint = 0; with the new implementation we should be able to append them in a temporary manner to the data we pass to the map module =========== */ -void AddRegionBrushes( void ){ - int i; +extern void ConstructRegionBrushes( scene::Node * brushes[6], const Vector3 ®ion_mins, const Vector3 ®ion_maxs ); - for ( i = 0; i < 6; i++ ) - { - region_sides[i] = &GlobalBrushCreator().createBrush(); - Node_getTraversable( Map_FindOrInsertWorldspawn( g_map ) )->insert( NodeSmartReference( *region_sides[i] ) ); +class ScopeRegionBrushes +{ + scene::Node* m_brushes[6]; + scene::Node* m_startpoint; + + void ConstructRegionStartpoint( const Vector3& vOrig ){ + // write the info_playerstart + char sTmp[1024]; + sprintf( sTmp, "%d %d %d", (int)vOrig[0], (int)vOrig[1], (int)vOrig[2] ); + Node_getEntity( *m_startpoint )->setKeyValue( "origin", sTmp ); + sprintf( sTmp, "%d", (int)Camera_getAngles( *g_pParentWnd->GetCamWnd() )[CAMERA_YAW] ); + Node_getEntity( *m_startpoint )->setKeyValue( "angle", sTmp ); } +public: + ScopeRegionBrushes(){ + for ( auto&& brush : m_brushes ) + { + brush = &GlobalBrushCreator().createBrush(); + Node_getTraversable( Map_FindOrInsertWorldspawn( g_map ) )->insert( NodeSmartReference( *brush ) ); + } - region_startpoint = &GlobalEntityCreator().createEntity( GlobalEntityClassManager().findOrInsert( "info_player_start", false ) ); + m_startpoint = &GlobalEntityCreator().createEntity( GlobalEntityClassManager().findOrInsert( "info_player_start", false ) ); - ConstructRegionBrushes( region_sides, g_region_mins, g_region_maxs ); - ConstructRegionStartpoint( region_startpoint, g_region_mins, g_region_maxs ); + /* adjust temp box: space may be too small, also help with lights and flat primitives */ + const Vector3 min( g_region_mins - Vector3( 256, 256, 8 ) ), max( g_region_maxs + Vector3( 256, 256, 512 ) ); + Vector3 spawn( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ) ); + /* pull spawn point to the box, if needed */ + for( size_t i = 0; i < 3; ++i ) + { + spawn[i] = std::max( spawn[i], min[i] + 64 ); + spawn[i] = std::min( spawn[i], max[i] - 64 ); + } - Node_getTraversable( GlobalSceneGraph().root() )->insert( NodeSmartReference( *region_startpoint ) ); + ConstructRegionBrushes( m_brushes, min, max ); + ConstructRegionStartpoint( spawn ); + + Node_getTraversable( GlobalSceneGraph().root() )->insert( NodeSmartReference( *m_startpoint ) ); + } + ~ScopeRegionBrushes(){ + for ( auto&& brush : m_brushes ) + { + Node_getTraversable( *Map_GetWorldspawn( g_map ) )->erase( *brush ); + } + Node_getTraversable( GlobalSceneGraph().root() )->erase( *m_startpoint ); + } + ScopeRegionBrushes( ScopeRegionBrushes&& ) noexcept = delete; +}; + +bool Map_SaveRegion( const char *filename ){ + ScopeRegionBrushes tmp; + return MapResource_saveFile( MapFormat_forFile( filename ), GlobalSceneGraph().root(), Map_Traverse_Region, filename ); } -void RemoveRegionBrushes( void ){ - for ( std::size_t i = 0; i < 6; i++ ) - { - Node_getTraversable( *Map_GetWorldspawn( g_map ) )->erase( *region_sides[i] ); - } - Node_getTraversable( GlobalSceneGraph().root() )->erase( *region_startpoint ); -} inline void exclude_node( scene::Node& node, bool exclude ){ exclude @@ -2340,8 +2327,8 @@ void map_autocaulk_selected(){ const Vector3 spawn( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ) ); Vector3 mins, maxs; Select_GetBounds( mins, maxs ); - mins -= Vector3( 1024, 1024, 1024 ); - maxs += Vector3( 1024, 1024, 1024 ); + mins -= Vector3( 1024 ); + maxs += Vector3( 1024 ); if( !aabb_intersects_point( aabb_for_minmax( mins, maxs ), spawn ) ){ globalErrorStream() << "map_autocaulk_selected(): camera must be near selection!\n"; @@ -2433,11 +2420,11 @@ void map_autocaulk_selected(){ StringOutputStream str( 256 ); str << AppPath_get() << "q3map2." << RADIANT_EXECUTABLE << " -game quake3" - << " -fs_basepath \"" << EnginePath_get() - << "\" -fs_homepath \"" << g_qeglobals.m_userEnginePath - << "\" -fs_game " << gamename_get() - << " -autocaulk -fulldetail" - << " \"" << filename.c_str() << "\""; + << " -fs_basepath " << makeQuoted( EnginePath_get() ) + << " -fs_homepath " << makeQuoted( g_qeglobals.m_userEnginePath ) + << " -fs_game " << gamename_get() + << " -autocaulk -fulldetail " + << makeQuoted( filename.c_str() ); // run Q_Exec( NULL, str.c_str(), NULL, false, true ); } diff --git a/radiant/qe3.cpp b/radiant/qe3.cpp index dcaed496..b7569dce 100644 --- a/radiant/qe3.cpp +++ b/radiant/qe3.cpp @@ -230,27 +230,8 @@ public: } }; -bool Region_cameraValid(){ - Vector3 vOrig( vector3_snapped( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ) ) ); - - for ( int i = 0 ; i < 3 ; i++ ) - { - if ( vOrig[i] > g_region_maxs[i] || vOrig[i] < g_region_mins[i] ) { - return false; - } - } - return true; -} - void RunBSP( const char* name ){ - // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503 - // make sure we don't attempt to region compile a map with the camera outside the region - if ( g_region_active && !Region_cameraValid() ) { - globalErrorStream() << "The camera must be in the region to start a region compile.\n"; - return; - } - if( !g_region_active ) SaveMap();