diff --git a/Core/GameEngine/Include/Common/STLTypedefs.h b/Core/GameEngine/Include/Common/STLTypedefs.h index 68a195c45a8..7276a459c3f 100644 --- a/Core/GameEngine/Include/Common/STLTypedefs.h +++ b/Core/GameEngine/Include/Common/STLTypedefs.h @@ -94,11 +94,6 @@ typedef std::vector::iterator ObjectIDVectorIterator; typedef std::vector VecCoord3D; typedef VecCoord3D::iterator VecCoord3DIt; -// Used for cursor->3D position request caching in the heightmap -typedef std::pair PosRequest; -typedef std::vector VecPosRequests; -typedef std::vector::iterator VecPosRequestsIt; - // Used to cache off names of objects for faster lookup typedef std::pair NamedRequest; typedef std::vector VecNamedRequests; diff --git a/Core/GameEngine/Include/GameClient/View.h b/Core/GameEngine/Include/GameClient/View.h index ccc33949f64..d60010da63c 100644 --- a/Core/GameEngine/Include/GameClient/View.h +++ b/Core/GameEngine/Include/GameClient/View.h @@ -137,6 +137,8 @@ class View : public Snapshot virtual void getOrigin( Int *x, Int *y) { *x=m_originX; *y=m_originY;} ///< Return location of top-left view corner on display virtual void forceRedraw() = 0; + virtual void onHeightMapChanged() {} + virtual void onBridgeChanged() {} virtual void lookAt( const Coord3D *o ); ///< Center the view on the given coordinate virtual void initHeightForMap() {}; ///< Init the camera height for the map at the current position. diff --git a/Core/GameEngineDevice/Include/W3DDevice/GameClient/BaseHeightMap.h b/Core/GameEngineDevice/Include/W3DDevice/GameClient/BaseHeightMap.h index 119acd38e3f..6feed84e471 100644 --- a/Core/GameEngineDevice/Include/W3DDevice/GameClient/BaseHeightMap.h +++ b/Core/GameEngineDevice/Include/W3DDevice/GameClient/BaseHeightMap.h @@ -229,6 +229,8 @@ class BaseHeightMapRenderObjClass : public RenderObjClass, public DX8_CleanupHoo virtual int updateBlock(Int x0, Int y0, Int x1, Int y1, WorldHeightMap *pMap, RefRenderObjListIterator *pLightsIterator) = 0; protected: + void scheduleFullUpdate(); + // snapshot methods virtual void crc( Xfer *xfer ) override; virtual void xfer( Xfer *xfer ) override; diff --git a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DView.h b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DView.h index 6bbe42054ad..87178aed370 100644 --- a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DView.h +++ b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DView.h @@ -167,6 +167,8 @@ class W3DView : public View, public SubsystemInterface virtual void scrollBy( const Coord2D *delta ) override; ///< Shift the view by the given delta virtual void forceRedraw() override; + virtual void onHeightMapChanged() override { m_lastScreenToTerrainValid = false; } + virtual void onBridgeChanged() override { m_lastScreenToTerrainValid = false; } virtual Bool isDoingScriptedCamera() override; virtual void stopDoingScriptedCamera() override; @@ -277,8 +279,10 @@ class W3DView : public View, public SubsystemInterface Bool m_freezeTimeForCameraMovement; Int m_timeMultiplier; ///< Time speedup multiplier. - Bool m_cameraHasMovedSinceRequest; ///< If true, throw out all saved locations - VecPosRequests m_locationRequests; ///< These are cached. New requests are added here + // TheSuperHackers @performance Cache only the latest screen-to-terrain result. + Bool m_lastScreenToTerrainValid; + ICoord2D m_lastScreenToTerrainScreen; + Coord3D m_lastScreenToTerrainWorld; Coord3D m_previousLookAtPosition; Coord2D m_scrollAmount; ///< scroll speed diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/BaseHeightMap.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/BaseHeightMap.cpp index 4cb1514c396..397d5eee749 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/BaseHeightMap.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/BaseHeightMap.cpp @@ -312,6 +312,14 @@ BaseHeightMapRenderObjClass::BaseHeightMapRenderObjClass() DX8Wrapper::SetCleanupHook(this); } +void BaseHeightMapRenderObjClass::scheduleFullUpdate() +{ + m_needFullUpdate = true; + if (TheTacticalView) { + TheTacticalView->onHeightMapChanged(); + } +} + void BaseHeightMapRenderObjClass::setTextureLOD(Int lod) { if (m_treeBuffer) @@ -454,7 +462,7 @@ void BaseHeightMapRenderObjClass::ReAcquireResources() { this->initHeightData(m_x,m_y,m_map, nullptr); // Tell lights to update next time through. - m_needFullUpdate = true; + scheduleFullUpdate(); } if (m_treeBuffer) { @@ -1823,7 +1831,7 @@ Int BaseHeightMapRenderObjClass::initHeightData(Int x, Int y, WorldHeightMap *pM } Set_Force_Visible(TRUE); //terrain is always visible. - m_needFullUpdate = true; + scheduleFullUpdate(); m_scorchesInBuffer = 0; m_curNumScorchVertices=0; @@ -2352,7 +2360,7 @@ void BaseHeightMapRenderObjClass::removeTerrainBibDrawable(DrawableID id) void BaseHeightMapRenderObjClass::staticLightingChanged() { // Cause the terrain to get updated with new lighting. - m_needFullUpdate = true; + scheduleFullUpdate(); // Cause the scorches to get updated with new lighting. m_scorchesInBuffer = 0; // If we just allocated the buffers, we got no scorches in the buffer. diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/HeightMap.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/HeightMap.cpp index 4987a8071c1..eddcf160ffa 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/HeightMap.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/HeightMap.cpp @@ -1200,7 +1200,7 @@ void HeightMapRenderObjClass::setTerrainDrawSize(Int width, Int height) //delete m_shroud; //m_shroud = nullptr; initHeightData(m_map->getDrawWidth(), m_map->getDrawHeight(), m_map, nullptr, FALSE); - m_needFullUpdate = true; + scheduleFullUpdate(); } @@ -1267,7 +1267,7 @@ Int HeightMapRenderObjClass::initHeightData(Int x, Int y, WorldHeightMap *pMap, m_originX = 0; m_originY = 0; - m_needFullUpdate = true; + scheduleFullUpdate(); // If the size changed, we need to allocate. Bool needToAllocate = (x != m_x || y != m_y); diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp index 963cd2b8183..ad5d6386a98 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp @@ -42,6 +42,7 @@ #include "GameClient/Drawable.h" #include "GameClient/ClientRandomValue.h" +#include "GameClient/View.h" #include "GameLogic/Object.h" #include "GameLogic/GameLogic.h" @@ -494,6 +495,10 @@ void W3DTerrainVisual::updateSeismicSimulations() } + if (TheTacticalView) { + TheTacticalView->onHeightMapChanged(); + } + } } diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp index 376a5297ed3..e65724084c5 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp @@ -99,7 +99,6 @@ // 30 fps Real TheW3DFrameLengthInMsec = MSEC_PER_LOGICFRAME_REAL; // default is 33msec/frame == 30fps. but we may change it depending on sys config. -static const Int MAX_REQUEST_CACHE_SIZE = 40; // Any size larger than 10, or examine code below for changes. jkmcd. static const Real DRAWABLE_OVERSCAN = 75.0f; ///< 3D world coords of how much to overscan in the 3D screen region constexpr const Real NearZ = MAP_XY_FACTOR; ///< Set the near to MAP_XY_FACTOR. Improves z buffer resolution. @@ -174,9 +173,7 @@ W3DView::W3DView() m_shakeIntensity = 0.0f; m_FXPitch = 1.0f; m_freezeTimeForCameraMovement = false; - m_cameraHasMovedSinceRequest = true; - m_locationRequests.clear(); - m_locationRequests.reserve(MAX_REQUEST_CACHE_SIZE + 10); // This prevents the vector from ever re-allocating + m_lastScreenToTerrainValid = false; //Enhancements from CNC3 WST 4/15/2003. JSC Integrated 5/20/03. m_scriptedState = 0; @@ -220,6 +217,7 @@ void W3DView::setHeight(Int height) // showing or hiding the control bar will change the viewable area. m_cameraAreaConstraintsValid = false; m_recalcCamera = true; + m_lastScreenToTerrainValid = false; } //------------------------------------------------------------------------------------------------- @@ -242,6 +240,7 @@ void W3DView::setWidth(Int width) m_cameraAreaConstraintsValid = false; m_recalcCamera = true; + m_lastScreenToTerrainValid = false; } //------------------------------------------------------------------------------------------------- @@ -829,7 +828,7 @@ void W3DView::updateCameraClipPlanes(const Matrix3D &transform) //------------------------------------------------------------------------------------------------- void W3DView::setCameraTransform(const Matrix3D &transform) { - m_cameraHasMovedSinceRequest = true; + m_lastScreenToTerrainValid = false; #if defined(RTS_DEBUG) m_3DCamera->Set_View_Plane( m_FOV, -1 ); @@ -1467,6 +1466,7 @@ void W3DView::update() Matrix3D camXForm; camXForm.Look_At(camtran,objPos,0); m_3DCamera->Set_Transform(camXForm); + m_lastScreenToTerrainValid = false; } } } @@ -1683,8 +1683,7 @@ void W3DView::update() } #ifdef DO_SEISMIC_SIMULATIONS - // Give the terrain a chance to refresh animating (Seismic) regions, if any. - TheTerrainVisual->updateSeismicSimulations(); + TheTerrainVisual->updateSeismicSimulations(); #endif Region3D axisAlignedRegion; @@ -2539,22 +2538,11 @@ Bool W3DView::screenToTerrain( const ICoord2D *screen, Coord3D *world ) if( screen == nullptr || world == nullptr || TheTerrainRenderObject == nullptr ) return false; - if (m_cameraHasMovedSinceRequest) { - m_locationRequests.clear(); - m_cameraHasMovedSinceRequest = false; - } - - if (m_locationRequests.size() > MAX_REQUEST_CACHE_SIZE) { - m_locationRequests.erase(m_locationRequests.begin(), m_locationRequests.begin() + 10); - } - - // We insert them at the end for speed (no copies needed), but using the principle of locality, we should - // start searching where we most recently inserted - for (int i = m_locationRequests.size() - 1; i >= 0; --i) { - if (m_locationRequests[i].first.x == screen->x && m_locationRequests[i].first.y == screen->y) { - (*world) = m_locationRequests[i].second; - return true; - } + if (m_lastScreenToTerrainValid && + m_lastScreenToTerrainScreen.x == screen->x && m_lastScreenToTerrainScreen.y == screen->y) + { + *world = m_lastScreenToTerrainWorld; + return true; } Vector3 rayStart,rayEnd; @@ -2591,10 +2579,9 @@ Bool W3DView::screenToTerrain( const ICoord2D *screen, Coord3D *world ) world->y = intersection.Y; world->z = intersection.Z; - PosRequest req; - req.first = (*screen); - req.second = (*world); - m_locationRequests.push_back(req); // Insert this request at the end, requires no extra copies + m_lastScreenToTerrainScreen = *screen; + m_lastScreenToTerrainWorld = *world; + m_lastScreenToTerrainValid = true; return true; } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp b/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp index d5eff4130f6..00386047267 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp @@ -40,6 +40,7 @@ #include "Common/Xfer.h" #include "GameClient/TerrainVisual.h" +#include "GameClient/View.h" #include "GameLogic/AI.h" #include "GameLogic/AIPathfind.h" @@ -1535,6 +1536,9 @@ void TerrainLogic::addBridgeToLogic(BridgeInfo *pInfo, Dict *props, AsciiString PathfindLayerEnum layer = TheAI->pathfinder()->addBridge(pBridge); pBridge->setLayer(layer); + if (TheTacticalView) { + TheTacticalView->onBridgeChanged(); + } } //------------------------------------------------------------------------------------------------- @@ -1542,13 +1546,15 @@ void TerrainLogic::addBridgeToLogic(BridgeInfo *pInfo, Dict *props, AsciiString //------------------------------------------------------------------------------------------------- void TerrainLogic::addLandmarkBridgeToLogic(Object *bridgeObj) { - Bridge *pBridge = newInstance(Bridge)(bridgeObj); pBridge->setNext(m_bridgeListHead); m_bridgeListHead = pBridge; PathfindLayerEnum layer = TheAI->pathfinder()->addBridge(pBridge); pBridge->setLayer(layer); + if (TheTacticalView) { + TheTacticalView->onBridgeChanged(); + } } //------------------------------------------------------------------------------------------------- @@ -1863,6 +1869,9 @@ void TerrainLogic::updateBridgeDamageStates() pBridge = pBridge->getNext(); } m_bridgeDamageStatesChanged = true; + if (TheTacticalView) { + TheTacticalView->onBridgeChanged(); + } } //------------------------------------------------------------------------------------------------- @@ -1980,6 +1989,8 @@ Drawable *TerrainLogic::pickBridge(const Vector3 &from, const Vector3 &to, Vecto //------------------------------------------------------------------------------------------------- void TerrainLogic::deleteBridges() { + Bool bridgesChanged = m_bridgeListHead != nullptr; + Bridge *pNext = nullptr; Bridge *pBridge; // Traverse all waypoints. @@ -1989,6 +2000,10 @@ void TerrainLogic::deleteBridges() deleteInstance(pBridge); } m_bridgeListHead = nullptr; + + if (bridgesChanged && TheTacticalView) { + TheTacticalView->onBridgeChanged(); + } } //------------------------------------------------------------------------------------------------- @@ -2044,6 +2059,9 @@ void TerrainLogic::deleteBridge( Bridge *bridge ) // delete the bridge in question deleteInstance(bridge); + if (TheTacticalView) { + TheTacticalView->onBridgeChanged(); + } } //------------------------------------------------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp index db2aa8d2200..5a3d16f86ae 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp @@ -40,6 +40,7 @@ #include "Common/Xfer.h" #include "GameClient/TerrainVisual.h" +#include "GameClient/View.h" #include "GameLogic/AI.h" #include "GameLogic/AIPathfind.h" @@ -1535,6 +1536,9 @@ void TerrainLogic::addBridgeToLogic(BridgeInfo *pInfo, Dict *props, AsciiString PathfindLayerEnum layer = TheAI->pathfinder()->addBridge(pBridge); pBridge->setLayer(layer); + if (TheTacticalView) { + TheTacticalView->onBridgeChanged(); + } } //------------------------------------------------------------------------------------------------- @@ -1542,13 +1546,15 @@ void TerrainLogic::addBridgeToLogic(BridgeInfo *pInfo, Dict *props, AsciiString //------------------------------------------------------------------------------------------------- void TerrainLogic::addLandmarkBridgeToLogic(Object *bridgeObj) { - Bridge *pBridge = newInstance(Bridge)(bridgeObj); pBridge->setNext(m_bridgeListHead); m_bridgeListHead = pBridge; PathfindLayerEnum layer = TheAI->pathfinder()->addBridge(pBridge); pBridge->setLayer(layer); + if (TheTacticalView) { + TheTacticalView->onBridgeChanged(); + } } //------------------------------------------------------------------------------------------------- @@ -1863,6 +1869,9 @@ void TerrainLogic::updateBridgeDamageStates() pBridge = pBridge->getNext(); } m_bridgeDamageStatesChanged = true; + if (TheTacticalView) { + TheTacticalView->onBridgeChanged(); + } } //------------------------------------------------------------------------------------------------- @@ -1980,6 +1989,8 @@ Drawable *TerrainLogic::pickBridge(const Vector3 &from, const Vector3 &to, Vecto //------------------------------------------------------------------------------------------------- void TerrainLogic::deleteBridges() { + Bool bridgesChanged = m_bridgeListHead != nullptr; + Bridge *pNext = nullptr; Bridge *pBridge; // Traverse all waypoints. @@ -1989,6 +2000,10 @@ void TerrainLogic::deleteBridges() deleteInstance(pBridge); } m_bridgeListHead = nullptr; + + if (bridgesChanged && TheTacticalView) { + TheTacticalView->onBridgeChanged(); + } } //------------------------------------------------------------------------------------------------- @@ -2044,6 +2059,9 @@ void TerrainLogic::deleteBridge( Bridge *bridge ) // delete the bridge in question deleteInstance(bridge); + if (TheTacticalView) { + TheTacticalView->onBridgeChanged(); + } } //-------------------------------------------------------------------------------------------------