diff --git a/Core/GameEngineDevice/Include/W3DDevice/GameClient/BaseHeightMap.h b/Core/GameEngineDevice/Include/W3DDevice/GameClient/BaseHeightMap.h index f533fe72e4d..f6a257835f9 100644 --- a/Core/GameEngineDevice/Include/W3DDevice/GameClient/BaseHeightMap.h +++ b/Core/GameEngineDevice/Include/W3DDevice/GameClient/BaseHeightMap.h @@ -152,6 +152,7 @@ class BaseHeightMapRenderObjClass : public RenderObjClass, public DX8_CleanupHoo /// Update the diffuse value from static light info for one vertex. void doTheLight(VERTEX_FORMAT *vb, const Vector3*light, Vector3*normal, RefRenderObjListIterator *pLightsIterator, UnsignedByte alpha); void addScorch(Vector3 location, Real radius, Scorches type); + void addStaticScorch(Vector3 location, Real radius, Scorches type); void addTree(DrawableID id, Coord3D location, Real scale, Real angle, Real randomScaleAmount, const W3DTreeDrawModuleData *data); void removeAllTrees(); @@ -268,6 +269,7 @@ class BaseHeightMapRenderObjClass : public RenderObjClass, public DX8_CleanupHoo #endif W3DBridgeBuffer *m_bridgeBuffer; W3DScorchInterface *m_scorches; + W3DScorchInterface *m_staticScorches; W3DShroud *m_shroud; ///< Class for drawing the shroud over terrain. struct shoreLineTileInfo { Int m_xy; //x,y position of tile diff --git a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h index 0e35dd4eec0..f14908b507c 100644 --- a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h +++ b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h @@ -43,7 +43,7 @@ class W3DScorchInterface class W3DScorch : public W3DScorchInterface { public: - W3DScorch(); + W3DScorch(bool deduplicateScorches); virtual ~W3DScorch() override; virtual void allocateBuffers() override; ///< allocate static buffers for drawing scorch marks. @@ -80,6 +80,7 @@ class W3DScorch : public W3DScorchInterface TScorch m_scorches[MAX_SCORCH_MARKS]; Int m_numScorches; Int m_scorchesInBuffer; ///< how many are in the buffers. If less than numScorches, we need to update + Bool m_deduplicateScorches; }; class W3DScorchDummy : public W3DScorchInterface diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/BaseHeightMap.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/BaseHeightMap.cpp index 25c41156a89..1db76d70f65 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/BaseHeightMap.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/BaseHeightMap.cpp @@ -150,6 +150,7 @@ inline Int IABS(Int x) { if (x>=0) return x; return -x;}; Int BaseHeightMapRenderObjClass::freeMapResources() { m_scorches->freeBuffers(); + m_staticScorches->freeBuffers(); REF_PTR_RELEASE(m_vertexMaterialClass); REF_PTR_RELEASE(m_stageZeroTexture); @@ -171,6 +172,7 @@ void BaseHeightMapRenderObjClass::drawScorches() { ShaderClass::Invalidate(); if (m_map && Is_Hidden() == 0 && !ShaderClass::Is_Backface_Culling_Inverted()) { + m_staticScorches->drawScorches(*m_map); m_scorches->drawScorches(*m_map); } } @@ -214,6 +216,9 @@ BaseHeightMapRenderObjClass::~BaseHeightMapRenderObjClass() delete m_scorches; m_scorches = nullptr; + delete m_staticScorches; + m_staticScorches = nullptr; + delete [] m_shoreLineTilePositions; m_shoreLineTilePositions = nullptr; @@ -271,9 +276,11 @@ BaseHeightMapRenderObjClass::BaseHeightMapRenderObjClass() m_roadBuffer = nullptr; #endif #if DO_SCORCH - m_scorches = NEW W3DScorch; + m_scorches = NEW W3DScorch(true); + m_staticScorches = NEW W3DScorch(false); #else m_scorches = NEW W3DScorchDummy; + m_staticScorches = NEW W3DScorchDummy; #endif m_bridgeBuffer = NEW W3DBridgeBuffer; @@ -1821,6 +1828,7 @@ Int BaseHeightMapRenderObjClass::initHeightData(Int x, Int y, WorldHeightMap *pM scheduleFullUpdate(); m_scorches->invalidateBuffers(); + m_staticScorches->invalidateBuffers(); // If the textures aren't allocated (usually because of a hardware reset) need to allocate. Bool needToAllocate = false; @@ -1837,6 +1845,7 @@ Int BaseHeightMapRenderObjClass::initHeightData(Int x, Int y, WorldHeightMap *pM m_destAlphaTexture=MSGNEW("TextureClass") TextureClass(256,1,WW3D_FORMAT_A8R8G8B8,MIP_LEVELS_1); initDestAlphaLUT(); m_scorches->allocateBuffers(); + m_staticScorches->allocateBuffers(); m_vertexMaterialClass=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE); @@ -1854,6 +1863,7 @@ Int BaseHeightMapRenderObjClass::initHeightData(Int x, Int y, WorldHeightMap *pM void BaseHeightMapRenderObjClass::clearAllScorches() { m_scorches->clearAllScorches(); + m_staticScorches->clearAllScorches(); } //============================================================================= @@ -1866,6 +1876,17 @@ void BaseHeightMapRenderObjClass::addScorch(Vector3 location, Real radius, Scorc m_scorches->addScorch(location, radius, type); } +//============================================================================= +// BaseHeightMapRenderObjClass::addStaticScorch +//============================================================================= +/** TheSuperHackers @feature stephanmeesters 13/08/2026 Adds a permanent scorch mark loaded from the map. Static + * scorch marks are managed separately so adding gameplay scorch marks cannot evict them. */ +//============================================================================= +void BaseHeightMapRenderObjClass::addStaticScorch(Vector3 location, Real radius, Scorches type) +{ + m_staticScorches->addScorch(location, radius, type); +} + //============================================================================= // BaseHeightMapRenderObjClass::getStaticDiffuse //============================================================================= @@ -2157,6 +2178,7 @@ void BaseHeightMapRenderObjClass::staticLightingChanged() // Cause the scorches to get updated with new lighting. m_scorches->invalidateBuffers(); + m_staticScorches->invalidateBuffers(); if (m_roadBuffer) m_roadBuffer->updateLighting(); diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp index 04041b57877..60a0189d2da 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp @@ -26,7 +26,7 @@ #include "W3DDevice/GameClient/WorldHeightMap.h" #include "WW3D2/dx8wrapper.h" -W3DScorch::W3DScorch() +W3DScorch::W3DScorch(bool deduplicateScorches) : m_vertexScorch(nullptr) , m_indexScorch(nullptr) , m_scorchTexture(nullptr) @@ -34,6 +34,7 @@ W3DScorch::W3DScorch() , m_curNumScorchIndices(0) , m_numScorches(0) , m_scorchesInBuffer(0) + , m_deduplicateScorches(deduplicateScorches) {} W3DScorch::~W3DScorch() { freeBuffers(); } @@ -85,16 +86,18 @@ void W3DScorch::addScorch(Vector3 location, Real radius, Scorches type) m_numScorches--; } - Int i; - Real limit = radius / 4; - for (i = 0; i < m_numScorches; i++) + if (m_deduplicateScorches) { - if (abs(location.X - m_scorches[i].location.X) < limit && - abs(location.Y - m_scorches[i].location.Y) < limit && - abs(radius - m_scorches[i].radius) < limit && - m_scorches[i].scorchType == type) + const Real limit = radius / 4; + for (Int i = 0; i < m_numScorches; i++) { - return; // basically a duplicate. + if (abs(location.X - m_scorches[i].location.X) < limit && + abs(location.Y - m_scorches[i].location.Y) < limit && + abs(radius - m_scorches[i].radius) < limit && + m_scorches[i].scorchType == type) + { + return; // basically a duplicate. + } } } diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp index ad5d6386a98..e50d92a7a38 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp @@ -661,7 +661,7 @@ Bool W3DTerrainVisual::load( AsciiString filename ) Vector3 loc(pos->x, pos->y, pos->z); Real radius = d->getReal(TheKey_objectRadius); Scorches type = (Scorches)d->getInt(TheKey_scorchType); - m_terrainRenderObject->addScorch(loc, radius, type); + m_terrainRenderObject->addStaticScorch(loc, radius, type); } pMapObj = pMapObj->getNext(); } diff --git a/Generals/Code/Tools/WorldBuilder/src/wbview3d.cpp b/Generals/Code/Tools/WorldBuilder/src/wbview3d.cpp index 1d824b032f0..ba3fb4530e4 100644 --- a/Generals/Code/Tools/WorldBuilder/src/wbview3d.cpp +++ b/Generals/Code/Tools/WorldBuilder/src/wbview3d.cpp @@ -973,7 +973,7 @@ void WbView3d::updateScorches() Scorches type = (Scorches) pMapObj->getProperties()->getInt(TheKey_scorchType); Vector3 loc(pos->x, pos->y, pos->z); - TheTerrainRenderObject->addScorch(loc, radius, type); + TheTerrainRenderObject->addStaticScorch(loc, radius, type); } } } diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/wbview3d.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/wbview3d.cpp index 5f42dc261fa..a1f39f2fb3f 100644 --- a/GeneralsMD/Code/Tools/WorldBuilder/src/wbview3d.cpp +++ b/GeneralsMD/Code/Tools/WorldBuilder/src/wbview3d.cpp @@ -998,7 +998,7 @@ void WbView3d::updateScorches() Scorches type = (Scorches) pMapObj->getProperties()->getInt(TheKey_scorchType); Vector3 loc(pos->x, pos->y, pos->z); - TheTerrainRenderObject->addScorch(loc, radius, type); + TheTerrainRenderObject->addStaticScorch(loc, radius, type); } } }