W3DBridgeBuffer.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210
  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: W3DBridgeBuffer.cpp ////////////////////////////////////////////////
  24. //-----------------------------------------------------------------------------
  25. //
  26. // Westwood Studios Pacific.
  27. //
  28. // Confidential Information
  29. // Copyright (C) 2001 - All Rights Reserved
  30. //
  31. //-----------------------------------------------------------------------------
  32. //
  33. // Project: RTS3
  34. //
  35. // File name: W3DBridgeBuffer.cpp
  36. //
  37. // Created: John Ahlquist, May 2001
  38. //
  39. // Desc: Draw buffer to handle all the bridges in a scene.
  40. //
  41. //-----------------------------------------------------------------------------
  42. //-----------------------------------------------------------------------------
  43. // Includes
  44. //-----------------------------------------------------------------------------
  45. #include "W3DDevice/GameClient/W3DBridgeBuffer.h"
  46. #include <stdio.h>
  47. #include <string.h>
  48. #include "W3DDevice/GameClient/W3DAssetManager.h"
  49. #include <texture.h>
  50. #include "common/GlobalData.h"
  51. #include "common/RandomValue.h"
  52. #include "Common/ThingFactory.h"
  53. #include "Common/ThingTemplate.h"
  54. #include "GameClient/TerrainRoads.h"
  55. #include "GameLogic/Damage.h"
  56. #include "GameLogic/Module/BodyModule.h"
  57. #include "W3DDevice/GameLogic/W3DTerrainLogic.h"
  58. #include "W3DDevice/GameClient/TerrainTex.h"
  59. #include "W3DDevice/GameClient/HeightMap.h"
  60. #include "W3DDevice/GameClient/W3DDynamicLight.h"
  61. #include "W3DDevice/GameClient/Module/W3DModelDraw.h"
  62. #include "W3DDevice/GameClient/W3DShaderManager.h"
  63. #include "W3DDevice/GameClient/W3DShroud.h"
  64. #include "WW3D2/Camera.h"
  65. #include "WW3D2/DX8Wrapper.h"
  66. #include "WW3D2/DX8Renderer.h"
  67. #include "WW3D2/Mesh.h"
  68. #include "WW3D2/MeshMdl.h"
  69. #include "WW3D2/Scene.h"
  70. #ifdef _INTERNAL
  71. // for occasional debugging...
  72. //#pragma optimize("", off)
  73. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  74. #endif
  75. //-----------------------------------------------------------------------------
  76. // Private Data
  77. //-----------------------------------------------------------------------------
  78. // A W3D shader that does alpha, texturing, tests zbuffer, doesn't update zbuffer.
  79. #define SC_ALPHA_DETAIL ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_SRC_ALPHA, \
  80. ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
  81. ShaderClass::ALPHATEST_ENABLE, ShaderClass::CULL_MODE_DISABLE, \
  82. ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
  83. static ShaderClass detailAlphaShader(SC_ALPHA_DETAIL);
  84. #define SC_ALPHA_MIRROR ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_ENABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_ONE, \
  85. ShaderClass::DSTBLEND_ZERO, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
  86. ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, \
  87. ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
  88. static ShaderClass detailShader(SC_ALPHA_MIRROR);
  89. #define NO_USE_BRIDGE_NORMALS
  90. //-----------------------------------------------------------------------------
  91. // Private Classes
  92. //-----------------------------------------------------------------------------
  93. //=============================================================================
  94. // W3DBridge constructor.
  95. //=============================================================================
  96. /** Initializes pointers & values. */
  97. //=============================================================================
  98. W3DBridge::W3DBridge() :
  99. m_bridgeTexture(NULL),
  100. m_leftMesh(NULL),
  101. m_sectionMesh(NULL),
  102. m_rightMesh(NULL),
  103. m_visible(false),
  104. m_curDamageState(BODY_PRISTINE),
  105. m_scale(1.0)
  106. {
  107. }
  108. //=============================================================================
  109. // W3DBridge destructor.
  110. //=============================================================================
  111. /** Frees objects. */
  112. //=============================================================================
  113. W3DBridge::~W3DBridge(void)
  114. {
  115. clearBridge();
  116. }
  117. //=============================================================================
  118. // W3DBridge::renderBridge
  119. //=============================================================================
  120. /** Renders the bride. It is assumed that the shared vertex and index buffers
  121. are already set. */
  122. //=============================================================================
  123. void W3DBridge::renderBridge(Bool wireframe)
  124. {
  125. if (m_visible && m_numPolygons && m_numVertex) {
  126. if (!wireframe) DX8Wrapper::Set_Texture(0,m_bridgeTexture);
  127. // Draw all the bridges.
  128. DX8Wrapper::Draw_Triangles( m_firstIndex, m_numPolygons, m_firstVertex, m_numVertex);
  129. }
  130. }
  131. //=============================================================================
  132. // W3DBridge::clearBridge
  133. //=============================================================================
  134. /** Frees all bridge objects (meshes & texture). */
  135. //=============================================================================
  136. void W3DBridge::clearBridge(void)
  137. {
  138. m_visible = false;
  139. REF_PTR_RELEASE(m_bridgeTexture);
  140. REF_PTR_RELEASE(m_leftMesh);
  141. REF_PTR_RELEASE(m_sectionMesh);
  142. REF_PTR_RELEASE(m_rightMesh);
  143. }
  144. //=============================================================================
  145. // W3DBridge::cullBridge
  146. //=============================================================================
  147. /** Culls bridge to camera. */
  148. //=============================================================================
  149. Bool W3DBridge::cullBridge(CameraClass * camera)
  150. {
  151. ///@todo - cull bridges.
  152. Bool wasVisible = m_visible;
  153. m_visible = true;
  154. return(wasVisible != m_visible);
  155. }
  156. #define BRIDGE_FLOAT_AMT (0.25f)
  157. //=============================================================================
  158. // W3DBridge::init
  159. //=============================================================================
  160. /** Inits a bridges location & type so it can be load'ed. */
  161. //=============================================================================
  162. void W3DBridge::init(Vector3 fromLoc, Vector3 toLoc, AsciiString bridgeTemplateName)
  163. {
  164. m_start = fromLoc;
  165. m_end = toLoc;
  166. m_templateName = bridgeTemplateName;
  167. m_enabled = true;
  168. }
  169. //=============================================================================
  170. // W3DBridge::init
  171. //=============================================================================
  172. /** Loads a bridge model(if not already loaded) and gets meshes for use at
  173. specified location. */
  174. //=============================================================================
  175. Bool W3DBridge::load(enum BodyDamageType curDamageState)
  176. {
  177. REF_PTR_RELEASE(m_bridgeTexture);
  178. REF_PTR_RELEASE(m_leftMesh);
  179. REF_PTR_RELEASE(m_sectionMesh);
  180. REF_PTR_RELEASE(m_rightMesh);
  181. Real scale, width, length;
  182. char textureFile[_MAX_PATH] = "No Texture";
  183. char modelName[_MAX_PATH] = "BRIDGESECTIONAL";
  184. /// @todo, should these be defaults in INI??? CBD
  185. scale = 0.7f;
  186. width = 34;
  187. length = 170;
  188. // try to find bridge in INI
  189. TerrainRoadType *bridge = TheTerrainRoads->findBridge( m_templateName );
  190. if (!bridge) return false;
  191. scale = bridge->getBridgeScale();
  192. switch (curDamageState) {
  193. default: return false;
  194. case BODY_PRISTINE:
  195. strcpy( textureFile, bridge->getTexture().str() );
  196. strcpy( modelName, bridge->getBridgeModel().str() );
  197. break;
  198. case BODY_DAMAGED:
  199. strcpy( textureFile, bridge->getTextureDamaged().str() );
  200. strcpy( modelName, bridge->getBridgeModelNameDamaged().str() );
  201. break;
  202. case BODY_REALLYDAMAGED:
  203. strcpy( textureFile, bridge->getTextureReallyDamaged().str() );
  204. strcpy( modelName, bridge->getBridgeModelNameReallyDamaged().str() );
  205. break;
  206. case BODY_RUBBLE:
  207. strcpy( textureFile, bridge->getTextureBroken().str() );
  208. strcpy( modelName, bridge->getBridgeModelNameBroken().str() );
  209. break;
  210. }
  211. WW3DAssetManager *pMgr = W3DAssetManager::Get_Instance();
  212. char left[_MAX_PATH];
  213. char section[_MAX_PATH];
  214. char right[_MAX_PATH];
  215. strcpy(left, modelName);
  216. strcat(left, ".BRIDGE_LEFT");
  217. strcpy(section, modelName);
  218. strcat(section, ".BRIDGE_SPAN");
  219. strcpy(right, modelName);
  220. strcat(right, ".BRIDGE_RIGHT");
  221. m_bridgeTexture = pMgr->Get_Texture(textureFile, MIP_LEVELS_3);
  222. m_leftMtx.Make_Identity();
  223. m_rightMtx.Make_Identity();
  224. m_sectionMtx.Make_Identity();
  225. RenderObjClass *pObj = pMgr->Create_Render_Obj(modelName );
  226. if (!pObj) return false;
  227. Int i;
  228. for (i=0; i<pObj->Get_Num_Sub_Objects(); i++) {
  229. RenderObjClass *pSub = pObj->Get_Sub_Object(i);
  230. Matrix3D mtx = pSub->Get_Transform();
  231. if (0==strnicmp(left, pSub->Get_Name(), strlen(left))) {
  232. m_leftMtx = mtx;
  233. strcpy(left, pSub->Get_Name());
  234. }
  235. if (0==strnicmp(section, pSub->Get_Name(), strlen(section))) {
  236. m_sectionMtx = mtx;
  237. strcpy(section, pSub->Get_Name());
  238. }
  239. if (0==strnicmp(right, pSub->Get_Name(), strlen(right))) {
  240. m_rightMtx = mtx;
  241. strcpy(right, pSub->Get_Name());
  242. }
  243. REF_PTR_RELEASE(pSub);
  244. //DEBUG_LOG(("Sub obj name %s\n", pSub->Get_Name()));
  245. }
  246. REF_PTR_RELEASE(pObj);
  247. m_leftMesh = (MeshClass*)pMgr->Create_Render_Obj(left );
  248. m_sectionMesh = (MeshClass*)pMgr->Create_Render_Obj(section);
  249. m_rightMesh = (MeshClass*)pMgr->Create_Render_Obj(right);
  250. m_scale = scale;
  251. if (m_leftMesh == NULL) {
  252. clearBridge();
  253. return(false);
  254. }
  255. m_bridgeType = SECTIONAL_BRIDGE;
  256. if (m_rightMesh == NULL || m_sectionMesh == NULL) {
  257. m_bridgeType = FIXED_BRIDGE;
  258. }
  259. Int numVertex = m_leftMesh->Peek_Model()->Get_Vertex_Count();
  260. Vector3 *pVert = m_leftMesh->Peek_Model()->Get_Vertex_Array();
  261. m_leftMinX = FLT_MAX;
  262. m_leftMaxX = -FLT_MAX;
  263. m_minY = FLT_MAX;
  264. m_maxY = -FLT_MAX;
  265. for (i=0; i<numVertex; i++) {
  266. Vector3 vert;
  267. Matrix3D::Transform_Vector(m_leftMtx, pVert[i], &vert);
  268. if (m_leftMinX > vert.X) m_leftMinX = vert.X;
  269. if (m_minY > vert.Y) m_minY = vert.Y;
  270. if (vert.X > m_leftMaxX) m_leftMaxX = vert.X;
  271. if (vert.Y > m_maxY) m_maxY = vert.Y; // Note - we assume all sections are the same width, so we only do maxY for first section.
  272. }
  273. if (m_bridgeType == SECTIONAL_BRIDGE) {
  274. numVertex = m_sectionMesh->Peek_Model()->Get_Vertex_Count();
  275. pVert = m_sectionMesh->Peek_Model()->Get_Vertex_Array();
  276. m_sectionMinX = FLT_MAX;
  277. m_sectionMaxX = -FLT_MAX;
  278. for (i=0; i<numVertex; i++) {
  279. Vector3 vert;
  280. Matrix3D::Transform_Vector(m_sectionMtx, pVert[i], &vert);
  281. if (m_sectionMinX > vert.X) m_sectionMinX = vert.X;
  282. if (vert.X > m_sectionMaxX) m_sectionMaxX = vert.X;
  283. }
  284. numVertex = m_rightMesh->Peek_Model()->Get_Vertex_Count();
  285. pVert = m_rightMesh->Peek_Model()->Get_Vertex_Array();
  286. m_rightMinX = FLT_MAX;
  287. m_rightMaxX = -FLT_MAX;
  288. for (i=0; i<numVertex; i++) {
  289. Vector3 vert;
  290. Matrix3D::Transform_Vector(m_rightMtx, pVert[i], &vert);
  291. if (m_rightMinX > vert.X) m_rightMinX = vert.X;
  292. if (vert.X > m_rightMaxX) m_rightMaxX = vert.X;
  293. }
  294. } else {
  295. m_sectionMinX = m_leftMaxX;
  296. m_sectionMaxX = m_leftMaxX;
  297. m_rightMinX = m_leftMaxX;
  298. m_rightMaxX = m_leftMaxX;
  299. }
  300. length = m_rightMaxX - m_leftMinX;
  301. if (length < 1) length = 1;
  302. m_length = length;
  303. if (m_bridgeType == SECTIONAL_BRIDGE) {
  304. Real allowableError = 0.05f*length;
  305. // make sure the sections align.
  306. if (m_leftMaxX>m_sectionMinX+allowableError) {
  307. m_bridgeType = FIXED_BRIDGE;
  308. }
  309. if (m_rightMinX<m_sectionMaxX-allowableError) {
  310. m_bridgeType = FIXED_BRIDGE;
  311. }
  312. }
  313. return(true);
  314. }
  315. //=============================================================================
  316. // W3DBridge::getBridgeInfo
  317. //=============================================================================
  318. /** Gets the location info for the bridge. */
  319. //=============================================================================
  320. void W3DBridge::getBridgeInfo(BridgeInfo *pInfo)
  321. {
  322. pInfo->from.x = m_start.X;
  323. pInfo->from.y = m_start.Y;
  324. pInfo->from.z = m_start.Z;
  325. pInfo->to.x = m_end.X;
  326. pInfo->to.y = m_end.Y;
  327. pInfo->to.z = m_end.Z;
  328. pInfo->bridgeWidth = (m_maxY - m_minY) *m_scale;
  329. Vector3 vec = m_end-m_start;
  330. Vector3 vecNormal(-vec.Y, vec.X, 0);
  331. vecNormal.Normalize();
  332. // From left = from + vecNormal*maxY*scale
  333. pInfo->fromLeft.x = m_start.X + vecNormal.X * m_maxY * m_scale;
  334. pInfo->fromLeft.y = m_start.Y + vecNormal.Y * m_maxY * m_scale;
  335. pInfo->fromLeft.z = m_start.Z + vecNormal.Z * m_maxY * m_scale;
  336. // From right = from + vecNormal*minY*scale
  337. pInfo->fromRight.x = m_start.X + vecNormal.X * m_minY * m_scale;
  338. pInfo->fromRight.y = m_start.Y + vecNormal.Y * m_minY * m_scale;
  339. pInfo->fromRight.z = m_start.Z + vecNormal.Z * m_minY * m_scale;
  340. // to left = to + vecNormal*maxY*scale
  341. pInfo->toLeft.x = m_end.X + vecNormal.X * m_maxY * m_scale;
  342. pInfo->toLeft.y = m_end.Y + vecNormal.Y * m_maxY * m_scale;
  343. pInfo->toLeft.z = m_end.Z + vecNormal.Z * m_maxY * m_scale;
  344. // to right = to + vecNormal*minY*scale
  345. pInfo->toRight.x = m_end.X + vecNormal.X * m_minY * m_scale;
  346. pInfo->toRight.y = m_end.Y + vecNormal.Y * m_minY * m_scale;
  347. pInfo->toRight.z = m_end.Z + vecNormal.Z * m_minY * m_scale;
  348. }
  349. //=============================================================================
  350. // W3DBridge::getModelVertices
  351. //=============================================================================
  352. /** Gets the vertex values for a section of a bridge. */
  353. //=============================================================================
  354. Int W3DBridge::getModelVertices(VertexFormatXYZNDUV1 *destination_vb, Int curVertex, Real xOffset,
  355. Vector3 &vec, Vector3 &vecNormal, Vector3 &vecZ, Vector3 &offset,
  356. const Matrix3D &mtx,
  357. MeshClass *pMesh, RefRenderObjListIterator *pLightsIterator)
  358. {
  359. if (pMesh == NULL)
  360. return(0);
  361. Int i;
  362. Int numVertex = pMesh->Peek_Model()->Get_Vertex_Count();
  363. Vector3 *pVert = pMesh->Peek_Model()->Get_Vertex_Array();
  364. const Vector3 *pNormal = pMesh->Peek_Model()->Get_Vertex_Normal_Array();
  365. // If we happen to have too many bridges, stop.
  366. if (curVertex+numVertex+2>= W3DBridgeBuffer::MAX_BRIDGE_VERTEX) {
  367. return(0);
  368. }
  369. Vector3 lightRay[MAX_GLOBAL_LIGHTS];
  370. const Coord3D *lightPos;
  371. for (Int lightIndex=0; lightIndex < TheGlobalData->m_numGlobalLights; lightIndex++)
  372. {
  373. lightPos=&TheGlobalData->m_terrainLightPos[lightIndex];
  374. lightRay[lightIndex].Set(-lightPos->x,-lightPos->y, -lightPos->z);
  375. // __asm {int 3}; //see if it really needs normalization!!
  376. lightRay[lightIndex].Normalize();
  377. }
  378. const Vector2*uvs=pMesh->Peek_Model()->Get_UV_Array_By_Index(0);
  379. VertexFormatXYZNDUV1 *curVb = destination_vb+curVertex;
  380. for (i=0; i<numVertex; i++) {
  381. Vector3 vLoc;
  382. Vector3 vertex;
  383. Matrix3D::Transform_Vector(mtx, pVert[i], &vertex);
  384. vLoc = (vertex.X+xOffset) * vec + vertex.Y*vecNormal + vertex.Z*vecZ;
  385. vLoc.X += m_start.X;
  386. vLoc.Y += m_start.Y;
  387. vLoc.Z += m_start.Z;
  388. curVb->x = vLoc.X;
  389. curVb->y = vLoc.Y;
  390. curVb->z = vLoc.Z;
  391. VERTEX_FORMAT vb;
  392. vb.x = vLoc.X;
  393. vb.y = vLoc.Y;
  394. vb.z = vLoc.Z;
  395. Vector3 normal;
  396. Matrix3D::Rotate_Vector(mtx, pNormal[i], &normal);
  397. #ifdef USE_BRIDGE_NORMALS
  398. curVb->nx = normal.X;
  399. curVb->ny = normal.Y;
  400. curVb->nz = normal.Z;
  401. curVb->diffuse = 0xFF000000;
  402. #else
  403. normal = (normal.X) * vec + normal.Y*vecNormal + normal.Z*vecZ;
  404. normal.Normalize();
  405. TheTerrainRenderObject->doTheLight(&vb, lightRay, &normal, NULL, 1.0f);
  406. curVb->nx = 0; //will these to keep AGP write buffer happy.
  407. curVb->ny = 0;
  408. curVb->nz = 1;
  409. curVb->diffuse = vb.diffuse | 0xFF000000;
  410. #endif
  411. curVb->u1 = uvs[i].U;
  412. curVb->v1 = uvs[i].V;
  413. curVb++;
  414. }
  415. return(numVertex);
  416. }
  417. //=============================================================================
  418. // W3DBridge::getModelVerticesFixed
  419. //=============================================================================
  420. /** Gets the vertex values for a section of a fixed bridge. */
  421. //=============================================================================
  422. Int W3DBridge::getModelVerticesFixed(VertexFormatXYZNDUV1 *destination_vb, Int curVertex,
  423. const Matrix3D &mtx, MeshClass *pMesh, RefRenderObjListIterator *pLightsIterator)
  424. {
  425. if (pMesh == NULL)
  426. return(0);
  427. Vector3 vec = m_end - m_start;
  428. if (vec.Length2() < 1.0f) {
  429. vec.Normalize();
  430. }
  431. Vector3 vecNormal(-vec.Y, vec.X, 0);
  432. vecNormal.Normalize();
  433. Real deltaZ = m_end.Z - m_start.Z;
  434. deltaZ /= vec.Length();
  435. Real deltaX = sqrt(1.0 - deltaZ*deltaZ);
  436. Vector3 vecZ(-deltaZ, 0, deltaX);
  437. vec /= m_length;
  438. vecNormal *= m_scale;
  439. vecZ *= m_scale;
  440. Real xOffset = -m_leftMinX;
  441. return(getModelVertices(destination_vb, curVertex, xOffset, vec, vecNormal, vecZ, m_start, mtx, pMesh, pLightsIterator));
  442. }
  443. //=============================================================================
  444. // W3DBridge::getIndicesNVertices
  445. //=============================================================================
  446. /** Gets the index values and vertex values for a bridge. */
  447. //=============================================================================
  448. void W3DBridge::getIndicesNVertices(UnsignedShort *destination_ib, VertexFormatXYZNDUV1 *destination_vb,
  449. Int *curIndexP, Int *curVertexP, RefRenderObjListIterator *pLightsIterator)
  450. {
  451. Int numI;
  452. Int numV;
  453. m_firstVertex = *curVertexP;
  454. m_firstIndex = *curIndexP;
  455. m_numVertex = 0;
  456. m_numPolygons = 0;
  457. if (m_sectionMesh == NULL) {
  458. numV = getModelVerticesFixed(destination_vb, *curVertexP, m_leftMtx, m_leftMesh, pLightsIterator);
  459. if (!numV)
  460. { //not enough room for vertices
  461. DEBUG_ASSERTCRASH( numV, ("W3DBridge::GetIndicesNVertices(). Vertex overflow.\n") );
  462. return;
  463. }
  464. numI = getModelIndices( destination_ib, *curIndexP, *curVertexP, m_leftMesh);
  465. if (!numI)
  466. { //not enough room for indices
  467. DEBUG_ASSERTCRASH( numI, ("W3DBridge::GetIndicesNVertices(). Index overflow.\n") );
  468. return;
  469. }
  470. *curIndexP += numI;
  471. *curVertexP += numV;
  472. m_numVertex += numV;
  473. m_numPolygons += numI/3;
  474. return;
  475. }
  476. Vector3 vec = m_end - m_start;
  477. if (vec.Length2() < 1.0f) {
  478. vec.Normalize();
  479. }
  480. Vector3 vecNormal(-vec.Y, vec.X, 0);
  481. vecNormal.Normalize();
  482. vecNormal *= m_scale;
  483. // Rotate along the y axis to get the appropriate Z height adjustment.
  484. Real deltaZ = m_end.Z - m_start.Z;
  485. Real desiredLength = vec.Length();
  486. deltaZ /= desiredLength;
  487. Real deltaX = sqrt(1.0 - deltaZ*deltaZ);
  488. Vector3 vecZ(-deltaZ, 0, deltaX);
  489. vecZ *= m_scale;
  490. Real spanLength = m_rightMinX - m_leftMaxX;
  491. Int numSpans = 1;
  492. if (m_bridgeType != FIXED_BRIDGE) {
  493. Real spannable = desiredLength - (m_length-spanLength);
  494. numSpans = REAL_TO_INT_FLOOR( (spannable + spanLength/2)/spanLength);
  495. if (numSpans<0) numSpans = 0;
  496. }
  497. Real bridgeLength = m_length + (numSpans-1)*spanLength;
  498. Real xOffset = -m_leftMinX;
  499. // Draw the left end.
  500. vec /= bridgeLength;
  501. numV = getModelVertices(destination_vb, *curVertexP, xOffset, vec, vecNormal, vecZ, m_start,
  502. m_leftMtx, m_leftMesh, pLightsIterator);
  503. if (!numV)
  504. { //not enough room for vertices
  505. DEBUG_ASSERTCRASH( numV, ("W3DBridge::GetIndicesNVertices(). Vertex overflow.\n") );
  506. return;
  507. }
  508. numI = getModelIndices( destination_ib, *curIndexP, *curVertexP, m_leftMesh);
  509. if (!numI)
  510. { //not enough room for indices
  511. DEBUG_ASSERTCRASH( numI, ("W3DBridge::GetIndicesNVertices(). Index overflow.\n") );
  512. return;
  513. }
  514. *curIndexP += numI;
  515. *curVertexP += numV;
  516. m_numVertex += numV;
  517. m_numPolygons += numI/3;
  518. Int i;
  519. // draw the spans.
  520. for (i=0; i<numSpans; i++) {
  521. numV = getModelVertices(destination_vb, *curVertexP, xOffset+i*spanLength, vec, vecNormal, vecZ, m_start,
  522. m_sectionMtx, m_sectionMesh, pLightsIterator);
  523. if (!numV)
  524. { //not enough room for vertices
  525. DEBUG_ASSERTCRASH( numV, ("W3DBridge::GetIndicesNVertices(). Vertex overflow.\n") );
  526. return;
  527. }
  528. numI = getModelIndices( destination_ib, *curIndexP, *curVertexP, m_sectionMesh);
  529. if (!numI)
  530. { //not enough room for indices
  531. DEBUG_ASSERTCRASH( numI, ("W3DBridge::GetIndicesNVertices(). Index overflow.\n") );
  532. return;
  533. }
  534. *curIndexP += numI;
  535. *curVertexP += numV;
  536. m_numVertex += numV;
  537. m_numPolygons += numI/3;
  538. }
  539. // Draw the right end.
  540. numV = getModelVertices(destination_vb, *curVertexP, xOffset+(numSpans-1)*spanLength, vec, vecNormal, vecZ, m_start,
  541. m_rightMtx, m_rightMesh, pLightsIterator);
  542. if (!numV)
  543. { //not enough room for vertices
  544. DEBUG_ASSERTCRASH( numV, ("W3DBridge::GetIndicesNVertices(). Vertex overflow.\n") );
  545. return;
  546. }
  547. numI = getModelIndices( destination_ib, *curIndexP, *curVertexP, m_rightMesh);
  548. if (!numI)
  549. { //not enough room for indices
  550. DEBUG_ASSERTCRASH( numI, ("W3DBridge::GetIndicesNVertices(). Index overflow.\n") );
  551. return;
  552. }
  553. *curIndexP += numI;
  554. *curVertexP += numV;
  555. m_numVertex += numV;
  556. m_numPolygons += numI/3;
  557. return;
  558. }
  559. //=============================================================================
  560. // W3DBridge::getModelIndices
  561. //=============================================================================
  562. /** Gets the index values for a particular mesh section of the bridge. */
  563. //=============================================================================
  564. Int W3DBridge::getModelIndices(UnsignedShort *destination_ib, Int curIndex, Int vertexOffset, MeshClass *pMesh)
  565. {
  566. if (pMesh == NULL)
  567. return(0);
  568. Int numPoly = pMesh->Peek_Model()->Get_Polygon_Count();
  569. const TriIndex *pPoly =pMesh->Peek_Model()->Get_Polygon_Array();
  570. if (curIndex+3*numPoly+6 >= W3DBridgeBuffer::MAX_BRIDGE_INDEX) {
  571. return(0);
  572. }
  573. UnsignedShort *curIb = destination_ib+curIndex;
  574. Int i;
  575. for (i=0; i<numPoly; i++) {
  576. *curIb++ = vertexOffset + pPoly[i].I;
  577. *curIb++ = vertexOffset + pPoly[i].J;
  578. *curIb++ = vertexOffset + pPoly[i].K;
  579. }
  580. return(numPoly*3);
  581. }
  582. //-----------------------------------------------------------------------------
  583. // Private Functions
  584. //-----------------------------------------------------------------------------
  585. ///@todo - Sort bridges by texture for better performance.
  586. //=============================================================================
  587. // W3DBridgeBuffer::cull
  588. //=============================================================================
  589. /** Culls the bridges, marking the visible flag. If a bridge changes visibility, it sets
  590. m_anythingChanged */
  591. //=============================================================================
  592. void W3DBridgeBuffer::cull(CameraClass * camera)
  593. {
  594. Int curBridge;
  595. m_anythingChanged = m_updateVis;
  596. for (curBridge=0; curBridge<m_numBridges; curBridge++) {
  597. if (m_bridges[curBridge].cullBridge(camera)) {
  598. m_anythingChanged = true;
  599. }
  600. }
  601. }
  602. //=============================================================================
  603. // W3DBridgeBuffer::loadBridgesInVertexAndIndexBuffers
  604. //=============================================================================
  605. /** Loads the bridges into the vertex buffer for drawing. */
  606. //=============================================================================
  607. void W3DBridgeBuffer::loadBridgesInVertexAndIndexBuffers(RefRenderObjListIterator *pLightsIterator)
  608. {
  609. if (!m_indexBridge || !m_vertexBridge || !m_initialized) {
  610. return;
  611. }
  612. m_curNumBridgeVertices = 0;
  613. m_curNumBridgeIndices = 0;
  614. VertexFormatXYZNDUV1 *vb;
  615. UnsignedShort *ib;
  616. // Lock the buffers.
  617. DX8IndexBufferClass::WriteLockClass lockIdxBuffer(m_indexBridge, D3DLOCK_DISCARD);
  618. DX8VertexBufferClass::WriteLockClass lockVtxBuffer(m_vertexBridge, D3DLOCK_DISCARD);
  619. vb=(VertexFormatXYZNDUV1*)lockVtxBuffer.Get_Vertex_Array();
  620. ib = lockIdxBuffer.Get_Index_Array();
  621. // UnsignedShort *curIb = ib;
  622. // VertexFormatXYZNDUV1 *curVb = vb;
  623. Int curBridge;
  624. try {
  625. for (curBridge=0; curBridge<m_numBridges; curBridge++) {
  626. m_bridges[curBridge].getIndicesNVertices(ib, vb, &m_curNumBridgeIndices,
  627. &m_curNumBridgeVertices, pLightsIterator);
  628. }
  629. IndexBufferExceptionFunc();
  630. } catch(...) {
  631. IndexBufferExceptionFunc();
  632. }
  633. }
  634. //-----------------------------------------------------------------------------
  635. // Public Functions
  636. //-----------------------------------------------------------------------------
  637. //=============================================================================
  638. // W3DBridgeBuffer::~W3DBridgeBuffer
  639. //=============================================================================
  640. /** Destructor. Releases w3d assets. */
  641. //=============================================================================
  642. W3DBridgeBuffer::~W3DBridgeBuffer(void)
  643. {
  644. freeBridgeBuffers();
  645. }
  646. //=============================================================================
  647. // W3DBridgeBuffer::W3DBridgeBuffer
  648. //=============================================================================
  649. /** Constructor. Sets m_initialized to true if it finds the w3d models it needs
  650. for the bridges. */
  651. //=============================================================================
  652. W3DBridgeBuffer::W3DBridgeBuffer(void)
  653. {
  654. m_initialized = false;
  655. m_vertexMaterial = NULL;
  656. m_vertexBridge = NULL;
  657. m_indexBridge = NULL;
  658. m_bridgeTexture = NULL;
  659. m_curNumBridgeVertices=0;
  660. m_curNumBridgeIndices=0;
  661. clearAllBridges();
  662. allocateBridgeBuffers();
  663. m_initialized = true;
  664. }
  665. //=============================================================================
  666. // W3DBridgeBuffer::freeBridgeBuffers
  667. //=============================================================================
  668. /** Frees the index and vertex buffers. */
  669. //=============================================================================
  670. void W3DBridgeBuffer::freeBridgeBuffers(void)
  671. {
  672. REF_PTR_RELEASE(m_vertexBridge);
  673. REF_PTR_RELEASE(m_indexBridge);
  674. REF_PTR_RELEASE(m_vertexMaterial);
  675. }
  676. //=============================================================================
  677. // W3DBridgeBuffer::allocateBridgeBuffers
  678. //=============================================================================
  679. /** Allocates the index and vertex buffers. */
  680. //=============================================================================
  681. void W3DBridgeBuffer::allocateBridgeBuffers(void)
  682. {
  683. m_vertexBridge=NEW_REF(DX8VertexBufferClass,(DX8_FVF_XYZNDUV1,MAX_BRIDGE_VERTEX+4,DX8VertexBufferClass::USAGE_DYNAMIC));
  684. m_indexBridge=NEW_REF(DX8IndexBufferClass,(MAX_BRIDGE_INDEX+4, DX8IndexBufferClass::USAGE_DYNAMIC));
  685. m_vertexMaterial=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
  686. #ifdef USE_BRIDGE_NORMALS
  687. m_vertexMaterial= NEW VertexMaterialClass();
  688. m_vertexMaterial->Set_Shininess(0.0);
  689. m_vertexMaterial->Set_Ambient(1,1,1);
  690. m_vertexMaterial->Set_Diffuse(1,1,1);
  691. m_vertexMaterial->Set_Specular(0,0,0);
  692. m_vertexMaterial->Set_Emissive(0,0,0);
  693. m_vertexMaterial->Set_Opacity(1);
  694. m_vertexMaterial->Set_Lighting(true);
  695. m_vertexMaterial->Set_Diffuse_Color_Source(VertexMaterialClass::COLOR1);
  696. #endif
  697. m_curNumBridgeVertices=0;
  698. m_curNumBridgeIndices=0;
  699. }
  700. //=============================================================================
  701. // W3DBridgeBuffer::clearAllBridges
  702. //=============================================================================
  703. /** Removes all bridges. */
  704. //=============================================================================
  705. void W3DBridgeBuffer::clearAllBridges(void)
  706. {
  707. Int curBridge;
  708. for (curBridge=0; curBridge<m_numBridges; curBridge++) {
  709. m_bridges[curBridge].clearBridge();
  710. }
  711. m_curNumBridgeIndices = 0;
  712. m_numBridges=0;
  713. }
  714. //=============================================================================
  715. // W3DBridgeBuffer::loadBridges
  716. //=============================================================================
  717. /** loadBridges. When loaded, tell the terrain logic where the bridge is. */
  718. //=============================================================================
  719. void W3DBridgeBuffer::loadBridges(W3DTerrainLogic *pTerrainLogic, Bool saveGame)
  720. {
  721. clearAllBridges();
  722. MapObject *pMapObj;
  723. MapObject *pMapObj2;
  724. for (pMapObj = MapObject::getFirstMapObject(); pMapObj; pMapObj = pMapObj->getNext()) {
  725. if (pMapObj->getFlag(FLAG_BRIDGE_POINT1)) {
  726. pMapObj2 = pMapObj->getNext();
  727. if ( !pMapObj2 || !pMapObj2->getFlag(FLAG_BRIDGE_POINT2)) {
  728. DEBUG_LOG(("Missing second bridge point. Ignoring first.\n"));
  729. }
  730. if (pMapObj2==NULL) break;
  731. if (!pMapObj2->getFlag(FLAG_BRIDGE_POINT2)) continue;
  732. Vector3 from, to;
  733. from.Set(pMapObj->getLocation()->x, pMapObj->getLocation()->y, 0);
  734. from.Z = TheTerrainRenderObject->getHeightMapHeight(from.X, from.Y, NULL) + BRIDGE_FLOAT_AMT;
  735. to.Set(pMapObj2->getLocation()->x, pMapObj2->getLocation()->y, 0);
  736. to.Z = TheTerrainRenderObject->getHeightMapHeight(to.X, to.Y, NULL) + BRIDGE_FLOAT_AMT;
  737. addBridge(from, to, pMapObj->getName(), pTerrainLogic, pMapObj->getProperties());
  738. pMapObj = pMapObj2;
  739. }
  740. }
  741. if (pTerrainLogic) {
  742. pTerrainLogic->updateBridgeDamageStates();
  743. }
  744. }
  745. //=============================================================================
  746. //=============================================================================
  747. static RenderObjClass* createTower( SimpleSceneClass *scene,
  748. W3DAssetManager *assetManager,
  749. MapObject *mapObject,
  750. BridgeTowerType type,
  751. BridgeInfo *bridgeInfo )
  752. {
  753. RenderObjClass* tower = NULL;
  754. // sanity
  755. if( scene == NULL ||
  756. assetManager == NULL ||
  757. mapObject == NULL ||
  758. bridgeInfo == NULL ||
  759. type < 0 || type >= BRIDGE_MAX_TOWERS )
  760. return NULL;
  761. // get template for this bridge
  762. DEBUG_ASSERTCRASH( TheTerrainRoads, ("createTower: TheTerrainRoads is NULL\n") );
  763. TerrainRoadType *bridgeTemplate = TheTerrainRoads->findBridge( mapObject->getName() );
  764. if( bridgeTemplate == NULL )
  765. return NULL;
  766. // given the type of tower (corner position) find the appropriate spot to put the tower
  767. Coord3D towerPos;
  768. switch( type )
  769. {
  770. case BRIDGE_TOWER_FROM_LEFT: towerPos = bridgeInfo->fromLeft; break;
  771. case BRIDGE_TOWER_FROM_RIGHT: towerPos = bridgeInfo->fromRight; break;
  772. case BRIDGE_TOWER_TO_LEFT: towerPos = bridgeInfo->toLeft; break;
  773. case BRIDGE_TOWER_TO_RIGHT: towerPos = bridgeInfo->toRight; break;
  774. default: return NULL;
  775. } // end switch
  776. // set the Z position to that of the terrain
  777. towerPos.z = TheTerrainRenderObject->getHeightMapHeight( towerPos.x, towerPos.y, NULL);
  778. // find the thing template for the tower we want to construct
  779. AsciiString towerTemplateName = bridgeTemplate->getTowerObjectName( type );
  780. DEBUG_ASSERTCRASH( TheThingFactory, ("createTower: TheThingFactory is NULL\n") );
  781. const ThingTemplate *towerTemplate = TheThingFactory->findTemplate( towerTemplateName );
  782. if( towerTemplate == NULL )
  783. return NULL;
  784. // find the name of the render object to show
  785. const ModuleInfo& mi = towerTemplate->getDrawModuleInfo( );
  786. if( mi.getCount() <= 0 )
  787. return NULL;
  788. const ModuleData* mdd = mi.getNthData(0);
  789. const W3DModelDrawModuleData* md = mdd ? mdd->getAsW3DModelDrawModuleData() : NULL;
  790. if( md == NULL )
  791. return NULL;
  792. ModelConditionFlags state;
  793. state.clear();
  794. AsciiString modelName = md->getBestModelNameForWB( state );
  795. // create the render object
  796. Int playerColor = 0xFFFFFF;
  797. tower = assetManager->Create_Render_Obj( modelName.str(), 1.0f, playerColor );
  798. // tie the render object into the map object
  799. mapObject->setBridgeRenderObject( type, tower );
  800. // set the position of the tower render object to the position in the world
  801. Matrix3D transform;
  802. transform.Make_Identity();
  803. transform.Set_X_Translation( towerPos.x );
  804. transform.Set_Y_Translation( towerPos.y );
  805. transform.Set_Z_Translation( towerPos.z );
  806. tower->Set_Transform( transform );
  807. // set the angle for the tower
  808. /// @todo --> write me
  809. // add tower render object to the scene
  810. scene->Add_Render_Object( tower );
  811. // return the render object of the tower created
  812. return tower;
  813. }
  814. //=============================================================================
  815. //=============================================================================
  816. static void updateTowerPos( RenderObjClass* tower,
  817. BridgeTowerType type,
  818. BridgeInfo* bridgeInfo )
  819. {
  820. // sanity
  821. if( tower == NULL || type < 0 || type >= BRIDGE_MAX_TOWERS || bridgeInfo == NULL )
  822. return;
  823. //
  824. // compute the angle of the bridge ... we consider the angle of the bridge to be
  825. // from 'from' to 'to' in the bridge info ... and so does the game
  826. //
  827. Coord2D v;
  828. v.x = bridgeInfo->toLeft.x - bridgeInfo->fromLeft.x;
  829. v.y = bridgeInfo->toLeft.y - bridgeInfo->fromLeft.y;
  830. Real angle = v.toAngle();
  831. //
  832. // given the type of tower (corner position) find the appropriate spot to put the tower
  833. // NOTE that we're also adjusting the angle for the from side to point the
  834. // opposite way the "bridge is pointing"
  835. //
  836. Coord3D towerPos;
  837. switch( type )
  838. {
  839. case BRIDGE_TOWER_FROM_LEFT: towerPos = bridgeInfo->fromLeft; angle += PI; break;
  840. case BRIDGE_TOWER_FROM_RIGHT: towerPos = bridgeInfo->fromRight; angle += PI; break;
  841. case BRIDGE_TOWER_TO_LEFT: towerPos = bridgeInfo->toLeft; break;
  842. case BRIDGE_TOWER_TO_RIGHT: towerPos = bridgeInfo->toRight; break;
  843. default: return;
  844. } // end switch
  845. // set the position of the tower render object to the position in the world
  846. Matrix3D transform;
  847. transform.Make_Identity();
  848. transform.Set_X_Translation( towerPos.x );
  849. transform.Set_Y_Translation( towerPos.y );
  850. transform.Set_Z_Translation( towerPos.z );
  851. transform.Rotate_Z( angle );
  852. tower->Set_Transform( transform );
  853. // set the angle for the tower
  854. // tower->setAngle( angle );
  855. }
  856. //=============================================================================
  857. // W3DBridgeBuffer::worldBuilderUpdateBridgeTowers
  858. //=============================================================================
  859. /** loadBridges. When loaded, tell the terrain logic where the bridge is. */
  860. //=============================================================================
  861. void W3DBridgeBuffer::worldBuilderUpdateBridgeTowers( W3DAssetManager *assetManager,
  862. SimpleSceneClass *scene )
  863. {
  864. MapObject *pMapObj;
  865. MapObject *pMapObj2;
  866. for( pMapObj = MapObject::getFirstMapObject(); pMapObj; pMapObj = pMapObj->getNext() )
  867. {
  868. if( pMapObj->getFlag( FLAG_BRIDGE_POINT1 ) )
  869. {
  870. pMapObj2 = pMapObj->getNext();
  871. if( !pMapObj2 || !pMapObj2->getFlag( FLAG_BRIDGE_POINT2 ) )
  872. DEBUG_LOG(("Missing second bridge point. Ignoring first.\n"));
  873. if( pMapObj2 == NULL )
  874. break;
  875. if( !pMapObj2->getFlag( FLAG_BRIDGE_POINT2 ) )
  876. continue;
  877. //
  878. // now that we've got the two map objects that are bridge point 1 and 2, get the
  879. // bridge info that has been stored
  880. //
  881. for( Int i = 0; i < m_numBridges; ++i )
  882. {
  883. //
  884. // find the bridge with the matching name and position ... note we're just matching
  885. // (x,y) here cause name and location (without the additional complication of Z) is
  886. // really all we have to match bridges.
  887. /// @todo integrate the editor with the game ... will never happen tho ...
  888. //
  889. if( m_bridges[ i ].getTemplateName() == pMapObj->getName() &&
  890. m_bridges[ i ].getStart()->X == pMapObj->getLocation()->x &&
  891. m_bridges[ i ].getStart()->Y == pMapObj->getLocation()->y &&
  892. m_bridges[ i ].getEnd()->X == pMapObj2->getLocation()->x &&
  893. m_bridges[ i ].getEnd()->Y == pMapObj2->getLocation()->y )
  894. {
  895. RenderObjClass *towerRenderObj;
  896. // get the bridge info
  897. BridgeInfo bridgeInfo;
  898. m_bridges[ i ].getBridgeInfo( &bridgeInfo );
  899. // go through all bridge tower render objects
  900. Bool created;
  901. for( Int j = 0; j < BRIDGE_MAX_TOWERS; ++j )
  902. {
  903. // create render object if needed
  904. created = FALSE;
  905. towerRenderObj = pMapObj->getBridgeRenderObject( (BridgeTowerType)j );
  906. if( towerRenderObj == NULL )
  907. {
  908. towerRenderObj = createTower( scene, assetManager, pMapObj, (BridgeTowerType)j, &bridgeInfo );
  909. created = TRUE;
  910. } // end if
  911. // sanity
  912. DEBUG_ASSERTCRASH( towerRenderObj != NULL, ("worldBuilderUpdateBridgeTowers: unable to create tower for bridge '%s'\n",
  913. m_bridges[ i ].getTemplateName().str()) );
  914. // update the position of the towers
  915. updateTowerPos( towerRenderObj, (BridgeTowerType)j, &bridgeInfo );
  916. // release the initial ref count of 1 for a newly created tower
  917. if( created )
  918. REF_PTR_RELEASE( towerRenderObj );
  919. } // end for j
  920. } // end if
  921. } // end for i
  922. // skip the 2nd map object representing the second half of the bridgef
  923. pMapObj = pMapObj2;
  924. }
  925. }
  926. }
  927. //=============================================================================
  928. // W3DBridgeBuffer::addBridge
  929. //=============================================================================
  930. /** Adds a bridge. Name is the GDF object name. */
  931. //=============================================================================
  932. void W3DBridgeBuffer::addBridge(Vector3 fromLoc, Vector3 toLoc, AsciiString name, W3DTerrainLogic *pTerrainLogic, Dict *props)
  933. {
  934. if (m_numBridges >= MAX_BRIDGES) {
  935. return;
  936. }
  937. if (!m_initialized) {
  938. return;
  939. }
  940. m_bridges[m_numBridges].init(fromLoc, toLoc, name);
  941. if (m_bridges[m_numBridges].load(BODY_PRISTINE)) {
  942. W3DBridge *pBridge = m_bridges+m_numBridges;
  943. if (pTerrainLogic) {
  944. BridgeInfo info;
  945. pBridge->getBridgeInfo(&info);
  946. info.bridgeIndex = m_numBridges;
  947. pTerrainLogic->addBridgeToLogic(&info, props, name);
  948. }
  949. m_numBridges++;
  950. }
  951. }
  952. //=============================================================================
  953. // W3DBridgeBuffer::updateCenter
  954. //=============================================================================
  955. /** Updates the drawing buffer, based on the camera position. */
  956. //=============================================================================
  957. void W3DBridgeBuffer::updateCenter(CameraClass *camera, RefRenderObjListIterator *pLightsIterator)
  958. {
  959. cull(camera);
  960. if (m_anythingChanged || m_curNumBridgeIndices == 0) {
  961. loadBridgesInVertexAndIndexBuffers(pLightsIterator);
  962. }
  963. m_updateVis = false;
  964. }
  965. //=============================================================================
  966. // W3DBridgeBuffer::drawBridges
  967. //=============================================================================
  968. /** Draws the bridges. */
  969. //=============================================================================
  970. void W3DBridgeBuffer::drawBridges(CameraClass * camera, Bool wireframe, TextureClass *cloudTexture)
  971. {
  972. Int curBridge;
  973. if (TheTerrainLogic) {
  974. for (curBridge=0; curBridge<m_numBridges; curBridge++) {
  975. m_bridges[curBridge].setEnabled(false);
  976. }
  977. /* Check for any changed damage states. */
  978. Bool changed = false;
  979. for (Bridge *bridge = TheTerrainLogic->getFirstBridge(); bridge; bridge = bridge->getNext()) {
  980. BridgeInfo info;
  981. bridge->getBridgeInfo(&info);
  982. if (info.bridgeIndex<0 || info.bridgeIndex>=m_numBridges) {
  983. continue;
  984. }
  985. m_bridges[info.bridgeIndex].setEnabled(true);
  986. if (m_bridges[info.bridgeIndex].getDamageState() != info.curDamageState) {
  987. changed = true;
  988. enum BodyDamageType curState = m_bridges[info.bridgeIndex].getDamageState();
  989. m_bridges[info.bridgeIndex].setDamageState(info.curDamageState);
  990. if (!m_bridges[info.bridgeIndex].load(info.curDamageState)) {
  991. // put the old model back.
  992. m_bridges[info.bridgeIndex].load(curState);
  993. m_bridges[info.bridgeIndex].setDamageState(info.curDamageState);
  994. }
  995. }
  996. }
  997. if (changed) {
  998. loadBridgesInVertexAndIndexBuffers(NULL);
  999. }
  1000. } else {
  1001. // In wb, all are enabled.
  1002. for (curBridge=0; curBridge<m_numBridges; curBridge++) {
  1003. m_bridges[curBridge].setEnabled(true);
  1004. }
  1005. }
  1006. if (m_curNumBridgeIndices == 0) {
  1007. return;
  1008. }
  1009. DX8Wrapper::Set_Material(m_vertexMaterial);
  1010. // Setup the vertex buffer, shader & texture.
  1011. DX8Wrapper::Set_Index_Buffer(m_indexBridge,0);
  1012. DX8Wrapper::Set_Vertex_Buffer(m_vertexBridge);
  1013. DX8Wrapper::Set_Shader(detailAlphaShader);
  1014. #ifdef _DEBUG
  1015. //DX8Wrapper::Set_Shader(detailShader); // shows alpha clipping.
  1016. #endif
  1017. DX8Wrapper::Apply_Render_State_Changes();
  1018. if (!wireframe && cloudTexture)
  1019. { //Force a cloud texture projection into stage 1
  1020. W3DShaderManager::setTexture(1,cloudTexture);
  1021. W3DShaderManager::setShader(W3DShaderManager::ST_CLOUD_TEXTURE,1);
  1022. }
  1023. for (curBridge=0; curBridge<m_numBridges; curBridge++) {
  1024. if (m_bridges[curBridge].isEnabled() && m_bridges[curBridge].isVisible()) {
  1025. m_bridges[curBridge].renderBridge(wireframe);
  1026. }
  1027. }
  1028. if (!wireframe && cloudTexture)
  1029. //Force a cloud texture projection into stage 1
  1030. W3DShaderManager::resetShader(W3DShaderManager::ST_CLOUD_TEXTURE);
  1031. //Render shroud pass over all the bridges
  1032. if (!wireframe && TheTerrainRenderObject->getShroud())
  1033. {
  1034. //Reset to a known shader.
  1035. DX8Wrapper::Invalidate_Cached_Render_States();
  1036. DX8Wrapper::Set_Shader(ShaderClass::_PresetOpaqueShader);
  1037. DX8Wrapper::Set_Material(m_vertexMaterial);
  1038. DX8Wrapper::Set_Index_Buffer(m_indexBridge,0);
  1039. DX8Wrapper::Set_Vertex_Buffer(m_vertexBridge);
  1040. DX8Wrapper::Apply_Render_State_Changes();
  1041. //Apply custom shroud projection shader.
  1042. W3DShaderManager::setTexture(0,TheTerrainRenderObject->getShroud()->getShroudTexture());
  1043. W3DShaderManager::setShader(W3DShaderManager::ST_SHROUD_TEXTURE, 0);
  1044. for (curBridge=0; curBridge<m_numBridges; curBridge++) {
  1045. if (m_bridges[curBridge].isEnabled() && m_bridges[curBridge].isVisible()) {
  1046. //Pretend we're in wireframe so function doesn't reset the shroud texture.
  1047. m_bridges[curBridge].renderBridge(TRUE);
  1048. }
  1049. }
  1050. W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
  1051. }
  1052. }