Skip to content

Commit 96a4f2d

Browse files
committed
Update Repo + New IterateDrawablesInRegion Implementation
1 parent dbdcd89 commit 96a4f2d

11 files changed

Lines changed: 642 additions & 55 deletions

File tree

GeneralsMD/Code/GameEngine/Include/Common/GlobalData.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,10 @@ class GlobalData : public SubsystemInterface
556556
//-allAdvice feature
557557
//Bool m_allAdvice;
558558

559+
Bool m_usePartitionManagerToIterateDrawables;
560+
Bool m_usePartitionManagerToIterateDrawablesOnlySelect;
561+
Bool m_useEfficientDrawableScheme;
562+
559563

560564
// the trailing '\' is included!
561565
const AsciiString &getPath_UserData() const { return m_userDataDir; }

GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ class Drawable : public Thing,
640640

641641
virtual void reactToTransformChange(const Matrix3D* oldMtx, const Coord3D* oldPos, Real oldAngle);
642642
void updateHiddenStatus();
643+
Bool checkDrawModuleNullptr(DrawModule** dm);
643644

644645
private:
645646

GeneralsMD/Code/GameEngine/Include/GameClient/GameClient.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ class GameClient : public SubsystemInterface,
157157
void incrementRenderedObjectCount() { m_renderedObjectCount++; }
158158
virtual void notifyTerrainObjectMoved(Object *obj) = 0;
159159

160+
void informClientNewDrawable(Drawable *draw);
161+
void addDrawableToEfficientList(Drawable *draw);
162+
inline void clearEfficientDrawablesList() { m_drawablesListMarkedForClear = TRUE; }
163+
160164

161165
protected:
162166

@@ -215,6 +219,9 @@ class GameClient : public SubsystemInterface,
215219
typedef std::list< Drawable* > TextBearingDrawableList;
216220
typedef TextBearingDrawableList::iterator TextBearingDrawableListIterator;
217221
TextBearingDrawableList m_textBearingDrawableList; ///< the drawables that have registered here during drawablepostdraw
222+
223+
std::list< Drawable* > m_drawablesList;
224+
Bool m_drawablesListMarkedForClear;
218225
};
219226

220227
//Kris: Try not to use this if possible. In every case I found in the code base, the status was always Drawable::SELECTED.

GeneralsMD/Code/GameEngine/Include/GameLogic/PartitionManager.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@
5959
#include "Common/Snapshot.h"
6060
#include "Common/Geometry.h"
6161
#include "GameClient/Display.h" // for ShroudLevel
62+
#include "GameClient/Drawable.h"
63+
64+
class Drawable;
6265

6366
//-----------------------------------------------------------------------------
6467
// defines
@@ -1534,6 +1537,10 @@ class PartitionManager : public SubsystemInterface, public Snapshot
15341537
// If saveToFog is false, then we are writing STORE_PERMENANT_REVEAL
15351538
void storeFoggedCells(ShroudStatusStoreRestore &outPartitionStore, Bool storeToFog) const;
15361539
void restoreFoggedCells(const ShroudStatusStoreRestore &inPartitionStore, Bool restoreToFog);
1540+
1541+
std::list<Drawable*> getDrawablesInRegion( IRegion2D *region2D );
1542+
std::list<Drawable*> getDrawablesInRegionEfficient();
1543+
inline Bool hasNoOffset() const { return m_radiusVec.empty(); }
15371544
};
15381545

15391546
// -----------------------------------------------------------------------------

GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,10 @@ GlobalData* GlobalData::m_theOriginal = NULL;
494494

495495
{ "PlayStats", INI::parseInt, NULL, offsetof( GlobalData, m_playStats ) },
496496

497+
{ "UsePartitionManagerToIterateDrawables", INI::parseBool, NULL, offsetof(GlobalData, m_usePartitionManagerToIterateDrawables) },
498+
{ "UsePartitionManagerToIterateDrawablesOnlySelect", INI::parseBool, NULL, offsetof(GlobalData, m_usePartitionManagerToIterateDrawablesOnlySelect) },
499+
{ "UseEfficientIterateDrawablesScheme", INI::parseBool, NULL, offsetof(GlobalData, m_useEfficientDrawableScheme) },
500+
497501
#if defined(RTS_DEBUG)
498502
{ "DisableCameraFade", INI::parseBool, NULL, offsetof( GlobalData, m_disableCameraFade ) },
499503
{ "DisableScriptedInputDisabling", INI::parseBool, NULL, offsetof( GlobalData, m_disableScriptedInputDisabling ) },
@@ -1029,6 +1033,10 @@ GlobalData::GlobalData()
10291033

10301034
m_keyboardCameraRotateSpeed = 0.1f;
10311035

1036+
m_usePartitionManagerToIterateDrawables = FALSE;
1037+
m_usePartitionManagerToIterateDrawablesOnlySelect = FALSE;
1038+
m_useEfficientDrawableScheme = FALSE;
1039+
10321040
// Set user data directory based on registry settings instead of INI parameters. This allows us to
10331041
// localize the leaf name.
10341042
char temp[_MAX_PATH + 1];

GeneralsMD/Code/GameEngine/Source/Common/Thing/Thing.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "Common/Team.h"
4646
#include "Lib/trig.h"
4747
#include "GameLogic/TerrainLogic.h"
48+
#include "GameClient/GameClient.h"
4849

4950

5051
static constexpr const Real InitialThingPosX = 0.0f;
@@ -169,6 +170,8 @@ void Thing::setPositionZ( Real z )
169170
setTransformMatrix(&mtx);
170171
}
171172
DEBUG_ASSERTCRASH(!(_isnan(getPosition()->x) || _isnan(getPosition()->y) || _isnan(getPosition()->z)), ("Drawable/Object position NAN! '%s'", m_template->getName().str() ));
173+
if(TheGameClient && TheGlobalData->m_useEfficientDrawableScheme && AsObject(this) && AsObject(this)->getDrawable())
174+
TheGameClient->informClientNewDrawable(AsObject(this)->getDrawable());
172175
}
173176

174177
//=============================================================================
@@ -198,6 +201,8 @@ void Thing::setPosition( const Coord3D *pos )
198201
setTransformMatrix(&mtx);
199202
}
200203
DEBUG_ASSERTCRASH(!(_isnan(getPosition()->x) || _isnan(getPosition()->y) || _isnan(getPosition()->z)), ("Drawable/Object position NAN! '%s'", m_template->getName().str() ));
204+
if(TheGameClient && TheGlobalData->m_useEfficientDrawableScheme && AsObject(this) && AsObject(this)->getDrawable())
205+
TheGameClient->informClientNewDrawable(AsObject(this)->getDrawable());
201206
}
202207

203208
//=============================================================================

GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2653,7 +2653,7 @@ void Drawable::draw()
26532653
applyPhysicsXform(&transformMtx);
26542654
}
26552655

2656-
for (DrawModule** dm = getDrawModules(); *dm; ++dm)
2656+
for (DrawModule** dm = getDrawModules(); checkDrawModuleNullptr(dm) && *dm; ++dm)
26572657
{
26582658
(*dm)->doDrawModule(&transformMtx);
26592659
}
@@ -3983,7 +3983,7 @@ DrawModule** Drawable::getDrawModules()
39833983
}
39843984
else
39853985
{
3986-
for (DrawModule** dm2 = dm; *dm2; ++dm2)
3986+
for (DrawModule** dm2 = dm; checkDrawModuleNullptr(dm2) && *dm2; ++dm2)
39873987
{
39883988
ObjectDrawInterface* di = (*dm2)->getObjectDrawInterface();
39893989
if (di)
@@ -3998,6 +3998,20 @@ DrawModule** Drawable::getDrawModules()
39983998
return dm;
39993999
}
40004000

4001+
Bool Drawable::checkDrawModuleNullptr(DrawModule** dm)
4002+
{
4003+
if(!TheGlobalData->m_useEfficientDrawableScheme)
4004+
return TRUE;
4005+
4006+
if(dm == nullptr)
4007+
{
4008+
//TheGameClient->removeDrawableFromEfficientList(this);
4009+
//TheGameClient->clearEfficientDrawablesList();
4010+
return FALSE;
4011+
}
4012+
return TRUE;
4013+
}
4014+
40014015
//-------------------------------------------------------------------------------------------------
40024016
DrawModule const** Drawable::getDrawModules() const
40034017
{

GeneralsMD/Code/GameEngine/Source/GameClient/GameClient.cpp

Lines changed: 118 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
#include "GameLogic/GameLogic.h"
8383
#include "GameLogic/GhostObject.h"
8484
#include "GameLogic/Object.h"
85+
#include "GameLogic/PartitionManager.h"
8586
#include "GameLogic/ScriptEngine.h" // For TheScriptEngine - jkmcd
8687

8788
#define DRAWABLE_HASH_SIZE 8192
@@ -111,6 +112,9 @@ GameClient::GameClient()
111112

112113
m_nextDrawableID = (DrawableID)1;
113114
TheDrawGroupInfo = new DrawGroupInfo;
115+
116+
m_drawablesList.clear();
117+
m_drawablesListMarkedForClear = FALSE;
114118
}
115119

116120
//std::vector<std::string> preloadTextureNamesGlobalHack;
@@ -130,6 +134,10 @@ GameClient::~GameClient()
130134
// clear any drawable TOC we might have
131135
m_drawableTOC.clear();
132136

137+
m_drawablesList.clear();
138+
139+
m_drawablesListMarkedForClear = FALSE;
140+
133141
//DEBUG_LOG(("Preloaded texture files ------------------------------------------"));
134142
//for (Int oog=0; oog<preloadTextureNamesGlobalHack2.size(); ++oog)
135143
//{
@@ -477,6 +485,9 @@ void GameClient::reset( void )
477485
// TheSuperHackers @fix Mauller 13/04/2025 Reset the drawable id so it does not keep growing over the lifetime of the game.
478486
m_nextDrawableID = (DrawableID)1;
479487

488+
m_drawablesList.clear();
489+
m_drawablesListMarkedForClear = FALSE;
490+
480491
}
481492

482493
/** -----------------------------------------------------------------------------------------------
@@ -784,21 +795,119 @@ void GameClient::updateHeadless()
784795
*/
785796
void GameClient::iterateDrawablesInRegion( Region3D *region, GameClientFuncPtr userFunc, void *userData )
786797
{
787-
Drawable *draw, *nextDrawable;
798+
if(m_drawablesListMarkedForClear)
799+
{
800+
m_drawablesList.clear();
801+
m_drawablesListMarkedForClear = FALSE;
802+
}
803+
804+
if(region != NULL && TheGlobalData->m_useEfficientDrawableScheme && !m_drawablesList.empty())
805+
{
806+
//IamInnocent - Attempted to use an Efficient Implementation of PartitionManager code to use WorldCell for Finding Drawables - 7/10/2025
807+
for( std::list< Drawable* >::iterator it = m_drawablesList.begin(); it != m_drawablesList.end();)
808+
{
809+
Coord3D pos = *(*it)->getPosition();
810+
if( pos.x >= region->lo.x && pos.x <= region->hi.x &&
811+
pos.y >= region->lo.y && pos.y <= region->hi.y &&
812+
pos.z >= region->lo.z && pos.z <= region->hi.z )
813+
{
814+
(*userFunc)( (*it), userData );
815+
}
816+
else
817+
{
818+
it = m_drawablesList.erase(it);
819+
continue;
820+
}
821+
++it;
822+
}
788823

789-
for( draw = m_drawableList; draw; draw=nextDrawable )
824+
std::list< Drawable* > newDrawables = ThePartitionManager->getDrawablesInRegionEfficient();
825+
826+
if(!newDrawables.empty())
827+
{
828+
for( std::list< Drawable* >::const_iterator it_new = newDrawables.begin(); it_new != newDrawables.end(); ++it_new )
829+
{
830+
Coord3D pos_new = *(*it_new)->getPosition();
831+
if( pos_new.x >= region->lo.x && pos_new.x <= region->hi.x &&
832+
pos_new.y >= region->lo.y && pos_new.y <= region->hi.y &&
833+
pos_new.z >= region->lo.z && pos_new.z <= region->hi.z )
834+
{
835+
addDrawableToEfficientList(*it_new);
836+
(*userFunc)( (*it_new), userData );
837+
}
838+
}
839+
}
840+
}
841+
else if(region == NULL || ThePartitionManager->hasNoOffset() ||
842+
( !TheGlobalData->m_usePartitionManagerToIterateDrawables || TheGlobalData->m_usePartitionManagerToIterateDrawablesOnlySelect ) )
790843
{
791-
nextDrawable = draw->getNextDrawable();
844+
Drawable *draw, *nextDrawable;
792845

793-
Coord3D pos = *draw->getPosition();
794-
if( region == NULL ||
795-
(pos.x >= region->lo.x && pos.x <= region->hi.x &&
796-
pos.y >= region->lo.y && pos.y <= region->hi.y &&
797-
pos.z >= region->lo.z && pos.z <= region->hi.z) )
846+
for( draw = m_drawableList; draw; draw=nextDrawable )
798847
{
799-
(*userFunc)( draw, userData );
848+
nextDrawable = draw->getNextDrawable();
849+
850+
Coord3D pos = *draw->getPosition();
851+
if( region == NULL ||
852+
(pos.x >= region->lo.x && pos.x <= region->hi.x &&
853+
pos.y >= region->lo.y && pos.y <= region->hi.y &&
854+
pos.z >= region->lo.z && pos.z <= region->hi.z) )
855+
{
856+
if(TheGlobalData->m_useEfficientDrawableScheme)
857+
addDrawableToEfficientList(draw);
858+
(*userFunc)( draw, userData );
859+
}
800860
}
801861
}
862+
else
863+
{
864+
//IamInnocent - Attempted to use PartitionManager code to use WorldCell for Finding Drawables - 6/10/2025
865+
std::list< Drawable* > drawables = ThePartitionManager->getDrawablesInRegion( NULL );
866+
867+
for( std::list< Drawable* >::iterator it = drawables.begin(); it != drawables.end(); ++it )
868+
{
869+
Coord3D pos = *(*it)->getPosition();
870+
if( pos.x >= region->lo.x && pos.x <= region->hi.x &&
871+
pos.y >= region->lo.y && pos.y <= region->hi.y &&
872+
pos.z >= region->lo.z && pos.z <= region->hi.z )
873+
{
874+
if(TheGlobalData->m_useEfficientDrawableScheme)
875+
addDrawableToEfficientList(*it);
876+
(*userFunc)( (*it), userData );
877+
}
878+
}
879+
}
880+
}
881+
882+
883+
/** -----------------------------------------------------------------------------------------------
884+
* Inform the Client to add this Unit to the Efficient Drawable Lisst
885+
*/
886+
void GameClient::informClientNewDrawable(Drawable *draw)
887+
{
888+
// sanity
889+
if( draw == NULL )
890+
return;
891+
892+
// Efficient drawing scheme is not on
893+
// Checked on the Thing.cpp
894+
//if(!TheGlobalData->m_useEfficientDrawableScheme)
895+
// return;
896+
897+
// Only inform New Drawable if the drawables are checked at least once.
898+
if(m_drawablesList.empty())
899+
return;
900+
901+
addDrawableToEfficientList(draw);
902+
}
903+
904+
void GameClient::addDrawableToEfficientList(Drawable *draw)
905+
{
906+
std::list< Drawable* >::iterator it = std::find(m_drawablesList.begin(), m_drawablesList.end(), draw);
907+
if (it == m_drawablesList.end())
908+
{
909+
m_drawablesList.push_back( draw );
910+
}
802911
}
803912

804913
/**Helper function to update fake GLA structures to become visible to certain players.

0 commit comments

Comments
 (0)