W3DTerrainLogic.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: W3DTerrainLogic.cpp //////////////////////////////////////////////////////////////////////
  24. // W3D implementation details for logical terrain
  25. // Author: Colin Day, April 2001
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #include "Common/GameMemory.h"
  28. #include "W3DDevice/GameClient/HeightMap.h"
  29. #include "W3DDevice/GameLogic/W3DTerrainLogic.h"
  30. #include "W3DDevice/GameClient/WorldHeightMap.h"
  31. #include "Common/PerfTimer.h"
  32. #include "Common/MapReaderWriterInfo.h"
  33. #include "Common/GlobalData.h"
  34. #include "Common/Xfer.h"
  35. #include "GameClient/GameClient.h"
  36. #include "GameClient/MapUtil.h"
  37. #include "GameLogic/AI.h"
  38. #include "GameLogic/AIPathfind.h"
  39. #ifdef _INTERNAL
  40. // for occasional debugging...
  41. //#pragma optimize("", off)
  42. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  43. #endif
  44. //-------------------------------------------------------------------------------------------------
  45. //-------------------------------------------------------------------------------------------------
  46. W3DTerrainLogic::W3DTerrainLogic():
  47. m_mapMinZ(0),
  48. m_mapMaxZ(1)
  49. {
  50. m_mapData = NULL;
  51. } // end W3DTerrainLogic
  52. //-------------------------------------------------------------------------------------------------
  53. //-------------------------------------------------------------------------------------------------
  54. W3DTerrainLogic::~W3DTerrainLogic()
  55. {
  56. // free terrain data
  57. } // end W3DTerrainLogic
  58. //-------------------------------------------------------------------------------------------------
  59. /** Device DEPENDENT implementation init details for logical terrain */
  60. //-------------------------------------------------------------------------------------------------
  61. void W3DTerrainLogic::init( void )
  62. {
  63. // enhancing functionality
  64. TerrainLogic::init();
  65. m_mapDX = 0;
  66. m_mapDY = 0;
  67. m_mapMinZ = 0;
  68. m_mapMaxZ = 1;
  69. } // end init
  70. //-------------------------------------------------------------------------------------------------
  71. /** Reset */
  72. //-------------------------------------------------------------------------------------------------
  73. void W3DTerrainLogic::reset( void )
  74. {
  75. TerrainLogic::reset();
  76. m_mapDX = 0;
  77. m_mapDY = 0;
  78. m_mapMinZ = 0;
  79. m_mapMaxZ = 1;
  80. WorldHeightMap::freeListOfMapObjects();
  81. } // end reset
  82. //-------------------------------------------------------------------------------------------------
  83. /** newMap */
  84. //-------------------------------------------------------------------------------------------------
  85. void W3DTerrainLogic::newMap( Bool saveGame )
  86. {
  87. TheTerrainRenderObject->loadRoadsAndBridges( this, saveGame );
  88. TerrainLogic::newMap( saveGame );
  89. } // end update
  90. //-------------------------------------------------------------------------------------------------
  91. /** Update */
  92. //-------------------------------------------------------------------------------------------------
  93. void W3DTerrainLogic::update( void )
  94. {
  95. TerrainLogic::update();
  96. } // end update
  97. //-------------------------------------------------------------------------------------------------
  98. /** Device DEPENDENT implementation for load details of logical terrain.
  99. Note - if query is true, we are */
  100. //-------------------------------------------------------------------------------------------------
  101. Bool W3DTerrainLogic::loadMap( AsciiString filename , Bool query )
  102. {
  103. if(!TheMapCache)
  104. return FALSE;
  105. WorldHeightMap *terrainHeightMap; ///< holds raw heightmap data samples
  106. char tempBuf[_MAX_PATH];
  107. char filenameBuf[_MAX_PATH];
  108. int length = 0;
  109. strcpy(tempBuf, filename.str());
  110. length = strlen( tempBuf );
  111. if( length >= 4 )
  112. {
  113. memset( filenameBuf, '\0', _MAX_PATH);
  114. strncpy( filenameBuf, tempBuf, length - 4);
  115. }
  116. // const char *fname = filename.reverseFind('\\');
  117. // if (fname)
  118. // filename = fname+1;
  119. CachedFileInputStream fileStrm;
  120. if ( !fileStrm.open(filename) )
  121. {
  122. return FALSE;
  123. }
  124. ChunkInputStream *pStrm = &fileStrm;
  125. // allocate new height map data to read from file
  126. // this will be a dummy object only containing logical map data
  127. terrainHeightMap = NEW WorldHeightMap(pStrm, true);
  128. if (terrainHeightMap)
  129. { //copy loaded data
  130. // Get the whole map, because we don't know which boundary is active yet
  131. m_mapDX=terrainHeightMap->getXExtent();
  132. m_mapDY=terrainHeightMap->getYExtent();
  133. // now, get all the boudnaries, and set the current active boundary to boundary 0.
  134. m_boundaries = terrainHeightMap->getAllBoundaries();
  135. m_activeBoundary = 0;
  136. Int i, j, minHt, maxHt;
  137. minHt = terrainHeightMap->getMaxHeightValue();
  138. maxHt = 0;
  139. for (j=0; j<m_mapDY; j++) {
  140. for (i=0; i<m_mapDX; i++) {
  141. Short cur = terrainHeightMap->getHeight(i,j);
  142. if (cur<minHt) minHt = cur;
  143. if (maxHt<cur) maxHt = cur;
  144. }
  145. }
  146. m_mapMinZ = minHt * MAP_HEIGHT_SCALE;
  147. m_mapMaxZ = maxHt * MAP_HEIGHT_SCALE;
  148. //release temporary object used for loading height values
  149. REF_PTR_RELEASE(terrainHeightMap);
  150. }
  151. else
  152. return FALSE; //could not create heightmap object. File not found?
  153. // Note - It is very important that this get called AFTER the map is read in. jba.
  154. // enhancing functionality
  155. if( TerrainLogic::loadMap( filename, query ) == false )
  156. return FALSE;
  157. // Map file now contains lighting & time of day info.
  158. if( TheWritableGlobalData->setTimeOfDay( TheGlobalData->m_timeOfDay ) )
  159. TheGameClient->setTimeOfDay( TheGlobalData->m_timeOfDay );
  160. return TRUE; // success
  161. } // end load
  162. //-------------------------------------------------------------------------------------------------
  163. /** Get the 3D extent of the terrain in world coordinates */
  164. //-------------------------------------------------------------------------------------------------
  165. void W3DTerrainLogic::getExtent( Region3D *extent ) const
  166. {
  167. extent->lo.x = 0.0f;
  168. extent->lo.y = 0.0f;
  169. // Note - m_boundaries are stored in height map grids wide, so we have to
  170. // multiply by the grid width.
  171. if (m_boundaries.size() > 0) {
  172. extent->hi.x = m_boundaries[m_activeBoundary].x*MAP_XY_FACTOR;
  173. extent->hi.y = m_boundaries[m_activeBoundary].y*MAP_XY_FACTOR;
  174. } else {
  175. extent->hi.x = 0.0f;
  176. extent->hi.y = 0.0f;
  177. }
  178. // Note - m_mapMin and Max Z are already in real coord space.
  179. extent->lo.z = m_mapMinZ;
  180. extent->hi.z = m_mapMaxZ;
  181. }
  182. //-------------------------------------------------------------------------------------------------
  183. /** Get the 3D largest bounds defined in the map. */
  184. //-------------------------------------------------------------------------------------------------
  185. void W3DTerrainLogic::getMaximumPathfindExtent( Region3D *extent ) const
  186. {
  187. extent->lo.x = 0.0f;
  188. extent->lo.y = 0.0f;
  189. extent->hi.x = 0.0f;
  190. extent->hi.y = 0.0f;
  191. // Note - m_boundaries are stored in height map grids wide, so we have to
  192. // multiply by the grid width.
  193. Int i;
  194. for (i=0; i<m_boundaries.size(); i++) {
  195. if (extent->hi.x < m_boundaries[i].x*MAP_XY_FACTOR) {
  196. extent->hi.x = m_boundaries[i].x*MAP_XY_FACTOR;
  197. }
  198. if (extent->hi.y < m_boundaries[i].y*MAP_XY_FACTOR) {
  199. extent->hi.y = m_boundaries[i].y*MAP_XY_FACTOR;
  200. }
  201. }
  202. // Note - m_mapMin and Max Z are already in real coord space.
  203. extent->lo.z = m_mapMinZ;
  204. extent->hi.z = m_mapMaxZ;
  205. }
  206. //-------------------------------------------------------------------------------------------------
  207. //-------------------------------------------------------------------------------------------------
  208. void W3DTerrainLogic::getExtentIncludingBorder( Region3D *extent ) const
  209. {
  210. extent->lo.x = 0.0f;
  211. extent->lo.y = 0.0f;
  212. Real border = TheTerrainRenderObject->getMap()->getBorderSizeInline() * MAP_XY_FACTOR;
  213. extent->lo.x -= border;
  214. extent->lo.y -= border;
  215. extent->hi.x = (m_mapDX * MAP_XY_FACTOR)-border;
  216. extent->hi.y = (m_mapDY * MAP_XY_FACTOR)-border;
  217. }
  218. //-------------------------------------------------------------------------------------------------
  219. Bool W3DTerrainLogic::isClearLineOfSight(const Coord3D& pos, const Coord3D& posOther) const
  220. {
  221. if (TheTerrainRenderObject)
  222. {
  223. return TheTerrainRenderObject->isClearLineOfSight(pos, posOther);
  224. }
  225. else
  226. {
  227. return false;
  228. }
  229. }
  230. //-------------------------------------------------------------------------------------------------
  231. /** W3D specific get height function for logical terrain */
  232. //-------------------------------------------------------------------------------------------------
  233. Real W3DTerrainLogic::getGroundHeight( Real x, Real y, Coord3D* normal ) const
  234. {
  235. #define USE_THE_TERRAIN_OBJECT
  236. #ifdef USE_THE_TERRAIN_OBJECT
  237. if (TheTerrainRenderObject)
  238. {
  239. return TheTerrainRenderObject->getHeightMapHeight(x,y,normal);
  240. }
  241. else
  242. {
  243. if (normal)
  244. {
  245. //return a default normal pointing up
  246. normal->x=0.0f;
  247. normal->y=0.0f;
  248. normal->z=1.0f;
  249. }
  250. return 0;
  251. }
  252. #endif
  253. } // end getHight
  254. //-------------------------------------------------------------------------------------------------
  255. /** Get the height considering the layer. */
  256. //-------------------------------------------------------------------------------------------------
  257. Real W3DTerrainLogic::getLayerHeight( Real x, Real y, PathfindLayerEnum layer, Coord3D* normal, Bool clip ) const
  258. {
  259. #ifdef USE_THE_TERRAIN_OBJECT
  260. if (!TheTerrainRenderObject)
  261. {
  262. if (normal)
  263. {
  264. //return a default normal pointing up
  265. normal->x=0.0f;
  266. normal->y=0.0f;
  267. normal->z=1.0f;
  268. }
  269. return 0;
  270. }
  271. Real height = TheTerrainRenderObject->getHeightMapHeight(x,y,normal);
  272. if (layer != LAYER_GROUND)
  273. {
  274. Coord3D loc;
  275. loc.x = x;
  276. loc.y = y;
  277. loc.z = height;
  278. if (layer == LAYER_WALL)
  279. {
  280. if (!clip || TheAI->pathfinder()->isPointOnWall(&loc))
  281. {
  282. return TheAI->pathfinder()->getWallHeight();
  283. }
  284. else
  285. {
  286. return height;
  287. }
  288. }
  289. Bridge* pBridge;
  290. if ((pBridge = findBridgeLayerAt(&loc, layer, clip)) != 0)
  291. {
  292. Real bridgeHeight = pBridge->getBridgeHeight(&loc, normal);
  293. if (bridgeHeight > height)
  294. {
  295. return bridgeHeight; // Don't return bridge height if it's in the ground.
  296. }
  297. }
  298. }
  299. return height;
  300. #endif
  301. } // end getLayerHeight
  302. //-------------------------------------------------------------------------------------------------
  303. /** W3D isCliffCell for terrain logic */
  304. //-------------------------------------------------------------------------------------------------
  305. Bool W3DTerrainLogic::isCliffCell( Real x, Real y) const
  306. {
  307. return TheTerrainRenderObject->isCliffCell(x,y);
  308. } // end isCliffCell
  309. // ------------------------------------------------------------------------------------------------
  310. /** CRC */
  311. // ------------------------------------------------------------------------------------------------
  312. void W3DTerrainLogic::crc( Xfer *xfer )
  313. {
  314. // extend base class
  315. TerrainLogic::crc( xfer );
  316. } // end crc
  317. // ------------------------------------------------------------------------------------------------
  318. /** Xfer
  319. * Version Info:
  320. * 1: Initial version */
  321. // ------------------------------------------------------------------------------------------------
  322. void W3DTerrainLogic::xfer( Xfer *xfer )
  323. {
  324. // version
  325. XferVersion currentVersion = 1;
  326. XferVersion version = currentVersion;
  327. xfer->xferVersion( &version, currentVersion );
  328. // extend base class
  329. TerrainLogic::xfer( xfer );
  330. } // end xfer
  331. // ------------------------------------------------------------------------------------------------
  332. /** Load post process */
  333. // ------------------------------------------------------------------------------------------------
  334. void W3DTerrainLogic::loadPostProcess( void )
  335. {
  336. // extend base class
  337. TerrainLogic::loadPostProcess();
  338. } // end loadPostProcess