From 01b10cfb8904492d4641064a962fd45514b27817 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Thu, 19 Feb 2026 14:46:19 -0600 Subject: [PATCH] make reflectors optional don't waste memory per object-instance on non reflective objects --- Engine/source/T3D/shapeBase.cpp | 39 +++++++++++++++++++++++---------- Engine/source/T3D/shapeBase.h | 2 +- Engine/source/T3D/tsStatic.cpp | 36 +++++++++++++++++++++--------- Engine/source/T3D/tsStatic.h | 2 +- 4 files changed, 56 insertions(+), 23 deletions(-) diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index 729271fae..96fadaf6e 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -975,6 +975,7 @@ ShapeBase::ShapeBase() mMoveMotion( false ), mShapeBaseMount( NULL ), mShapeInstance( NULL ), + mCubeReflector(NULL), mConvexList( new Convex ), mEnergy( 0.0f ), mRechargeRate( 0.0f ), @@ -1053,6 +1054,12 @@ ShapeBase::~ShapeBase() mShapeInstance = NULL; } + if (mCubeReflector) + { + mCubeReflector->unregisterReflector(); + SAFE_DELETE(mCubeReflector); + } + CollisionTimeout* ptr = mTimeoutList; while (ptr) { CollisionTimeout* cur = ptr; @@ -1173,7 +1180,11 @@ void ShapeBase::onRemove() if ( isClientObject() ) { - mCubeReflector.unregisterReflector(); + if (mCubeReflector) + { + mCubeReflector->unregisterReflector(); + SAFE_DELETE(mCubeReflector); + } } } @@ -1349,11 +1360,17 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload ) mLightPlugin->reset(); if ( isClientObject() ) - { - mCubeReflector.unregisterReflector(); - - if ( mDataBlock->reflectorDesc ) - mCubeReflector.registerReflector( this, mDataBlock->reflectorDesc ); + { + if (mCubeReflector) + { + mCubeReflector->unregisterReflector(); + SAFE_DELETE(mCubeReflector); + } + if (mDataBlock->reflectorDesc) + { + mCubeReflector = new CubeReflector(); + mCubeReflector->registerReflector(this, mDataBlock->reflectorDesc); + } } return true; @@ -2681,7 +2698,7 @@ void ShapeBase::_prepRenderImage( SceneRenderState *state, // If we're currently rendering our own reflection we // don't want to render ourselves into it. - if ( mCubeReflector.isRendering() ) + if (mCubeReflector && mCubeReflector->isRendering()) return; // We force all the shapes to use the highest detail @@ -2785,8 +2802,8 @@ void ShapeBase::prepBatchRender(SceneRenderState* state, S32 mountedImageIndex ) // Set up our TS render state. TSRenderState rdata; rdata.setSceneState( state ); - if ( mCubeReflector.isEnabled() ) - rdata.setCubemap( mCubeReflector.getCubemap() ); + if (mCubeReflector && mCubeReflector->isEnabled()) + rdata.setCubemap( mCubeReflector->getCubemap() ); rdata.setFadeOverride( (1.0f - mCloakLevel) * mFadeVal ); // We might have some forward lit materials @@ -2810,14 +2827,14 @@ void ShapeBase::prepBatchRender(SceneRenderState* state, S32 mountedImageIndex ) mat.scale( mObjScale ); GFX->setWorldMatrix( mat ); - if ( state->isDiffusePass() && mCubeReflector.isEnabled() && mCubeReflector.getOcclusionQuery() ) + if ( state->isDiffusePass() && mCubeReflector && mCubeReflector->isEnabled() && mCubeReflector->getOcclusionQuery() ) { RenderPassManager *pass = state->getRenderPass(); OccluderRenderInst *ri = pass->allocInst(); ri->type = RenderPassManager::RIT_Occluder; - ri->query = mCubeReflector.getOcclusionQuery(); + ri->query = mCubeReflector->getOcclusionQuery(); mObjToWorld.mulP( mObjBox.getCenter(), &ri->position ); ri->scale.set( mObjBox.getExtents() ); ri->orientation = pass->allocUniqueXform( mObjToWorld ); diff --git a/Engine/source/T3D/shapeBase.h b/Engine/source/T3D/shapeBase.h index a8807a026..71967bbe1 100644 --- a/Engine/source/T3D/shapeBase.h +++ b/Engine/source/T3D/shapeBase.h @@ -1207,7 +1207,7 @@ public: static F32 sFullCorrectionDistance; static F32 sCloakSpeed; // Time to cloak, in seconds - CubeReflector mCubeReflector; + CubeReflector* mCubeReflector; /// @name Initialization /// @{ diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 329485b4f..c244d25c3 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -109,7 +109,8 @@ F32 TSStatic::smStaticObjectUnfadeableSize = 75; TSStatic::TSStatic() : cubeDescId(0), - reflectorDesc(NULL) + reflectorDesc(NULL), + mCubeReflector(NULL) { mNetFlags.set(Ghostable | ScopeAlways); @@ -159,6 +160,11 @@ TSStatic::~TSStatic() delete mConvexList; mConvexList = NULL; mShapeAsset.unregisterRefreshNotify(); + if (mCubeReflector) + { + mCubeReflector->unregisterReflector(); + SAFE_DELETE(mCubeReflector); + } } ImplementEnumType(TSMeshType, @@ -361,10 +367,17 @@ bool TSStatic::onAdd() if (isClientObject()) { - mCubeReflector.unregisterReflector(); + if (mCubeReflector) + { + mCubeReflector->unregisterReflector(); + SAFE_DELETE(mCubeReflector); + } if (reflectorDesc) - mCubeReflector.registerReflector(this, reflectorDesc); + { + mCubeReflector = new CubeReflector(); + mCubeReflector->registerReflector(this, reflectorDesc); + } } _updateShouldTick(); @@ -594,8 +607,11 @@ void TSStatic::onRemove() mShapeInstance = NULL; mAmbientThread = NULL; - if (isClientObject()) - mCubeReflector.unregisterReflector(); + if (isClientObject() && mCubeReflector) + { + mCubeReflector->unregisterReflector(); + SAFE_DELETE(mCubeReflector); + } Parent::onRemove(); } @@ -780,7 +796,7 @@ void TSStatic::prepRenderImage(SceneRenderState* state) // If we're currently rendering our own reflection we // don't want to render ourselves into it. - if (mCubeReflector.isRendering()) + if (mCubeReflector && mCubeReflector->isRendering()) return; @@ -800,8 +816,8 @@ void TSStatic::prepRenderImage(SceneRenderState* state) rdata.setFadeOverride(1.0f); rdata.setOriginSort(mUseOriginSort); - if (mCubeReflector.isEnabled()) - rdata.setCubemap(mCubeReflector.getCubemap()); + if (mCubeReflector && mCubeReflector->isEnabled()) + rdata.setCubemap(mCubeReflector->getCubemap()); // Acculumation rdata.setAccuTex(mAccuTex); @@ -830,13 +846,13 @@ void TSStatic::prepRenderImage(SceneRenderState* state) mat.scale(mObjScale); GFX->setWorldMatrix(mat); - if (state->isDiffusePass() && mCubeReflector.isEnabled() && mCubeReflector.getOcclusionQuery()) + if (state->isDiffusePass() && mCubeReflector && mCubeReflector->isEnabled() && mCubeReflector->getOcclusionQuery()) { RenderPassManager* pass = state->getRenderPass(); OccluderRenderInst* ri = pass->allocInst(); ri->type = RenderPassManager::RIT_Occluder; - ri->query = mCubeReflector.getOcclusionQuery(); + ri->query = mCubeReflector->getOcclusionQuery(); mObjToWorld.mulP(mObjBox.getCenter(), &ri->position); ri->scale.set(mObjBox.getExtents()); ri->orientation = pass->allocUniqueXform(mObjToWorld); diff --git a/Engine/source/T3D/tsStatic.h b/Engine/source/T3D/tsStatic.h index 150aa59cf..7ab21ba0a 100644 --- a/Engine/source/T3D/tsStatic.h +++ b/Engine/source/T3D/tsStatic.h @@ -184,7 +184,7 @@ protected: String cubeDescName; U32 cubeDescId; ReflectorDesc* reflectorDesc; - CubeReflector mCubeReflector; + CubeReflector* mCubeReflector; void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override {