W3DWaterTracks.cpp 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328
  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: W3DWaterTracks.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: W3DWaterTracks.cpp
  36. //
  37. // Created: Mark Wilczynski, July 2001
  38. //
  39. // Desc: Draw waves and splash marks on water surface. System allows for
  40. // some simple animation : dynamic uv coordinates, scaling, scrolling,
  41. // and alpha.
  42. //-----------------------------------------------------------------------------
  43. #include "W3DDevice/GameClient/heightmap.h"
  44. #include "W3DDevice/GameClient/W3DWaterTracks.h"
  45. #include "W3DDevice/GameClient/W3DShaderManager.h"
  46. #include "W3DDevice/GameClient/W3DShroud.h"
  47. #include "GameClient/InGameUI.h"
  48. #include "GameClient/Water.h"
  49. #include "GameLogic/TerrainLogic.h"
  50. #include "common/GlobalData.h"
  51. #include "common/UnicodeString.h"
  52. #include "Common/File.h"
  53. #include "Common/FileSystem.h"
  54. #include "texture.h"
  55. #include "colmath.h"
  56. #include "coltest.h"
  57. #include "rinfo.h"
  58. #include "camera.h"
  59. #include "assetmgr.h"
  60. #include "WW3D2/DX8Wrapper.h"
  61. //#pragma optimize("", off)
  62. //#define ALLOW_WATER_TRACK_EDIT
  63. //number of vertex pages allocated - allows double buffering of vertex updates.
  64. //while one is being rendered, another is being updated. Improves HW parallelism.
  65. #define WATER_VB_PAGES 1000
  66. #define WATER_STRIP_X 2 //vertex resolution of each strip
  67. #define WATER_STRIP_Y 2
  68. #define SYNC_WAVES //all the waves are in sync - movement resets at same time.
  69. //#define DEFAULT_FINAL_WAVE_WIDTH 28.0f
  70. //#define DEFAULT_FINAL_WAVE_HEIGHT 18.0f
  71. //#define DEFAULT_SECOND_WAVE_TIME_OFFSET 6267 //should always be half of totalMs
  72. WaterTracksRenderSystem *TheWaterTracksRenderSystem=NULL; ///< singleton for track drawing system.
  73. static Bool pauseWaves=FALSE;
  74. enum waveType
  75. {
  76. WaveTypeFirst,
  77. WaveTypePond=WaveTypeFirst,
  78. WaveTypeOcean,
  79. WaveTypeCloseOcean, //same as above but appears much closer to beach.
  80. WaveTypeCloseOceanDouble, //same as above but waves much sloser together.
  81. WaveTypeRadial,
  82. WaveTypeLast = WaveTypeRadial,
  83. WaveTypeStationary,
  84. WaveTypeMax,
  85. };
  86. struct waveInfo
  87. {
  88. Real m_finalWidth; //final width of of wave when it reaches beach.
  89. Real m_finalHeight; //final height of wave after it stretched out on beach.
  90. Real m_waveDistance; //distance away from beach where wave starts.
  91. Real m_initialVelocity;
  92. Int m_fadeMs; //time to fade out wave after it stops on shore.
  93. Real m_initialWidthFraction; //fraction of m_finalWidth when wave first appears.
  94. Real m_initialHeightWidthFraction; //fraction of initial width to use as the initial height.
  95. Int m_timeToCompress; //time for back of wave to continue moving forward after front starts retreating.
  96. Int m_secondWaveTimeOffset; //time for second wave to start. Should always be half of first wave's TotalMs.
  97. char *m_textureName; //name of texture to use on wave.
  98. char *m_waveTypeName; //name of this wave type.
  99. };
  100. waveInfo waveTypeInfo[WaveTypeMax]=
  101. {
  102. {28.0f, 18.0f, 25.0f, 0.018f, 900, 0.01f, 0.18f, 1500, 0,"wave256.tga","Pond"}, //pond
  103. {55.0f, 36.0f, 80.0f, 0.015f, 2000, 0.5f, 0.18f, 1000, 6267,"wave256.tga","Ocean"}, //ocean
  104. {55.0f, 36.0f, 80.0f, 0.015f, 2000, 0.05f, 0.18f, 1000, 6267,"wave256.tga","Close Ocean"},
  105. {55.0f, 36.0f, 80.0f, 0.015f, 4000, 0.01f, 0.18f, 2000, 6267,"wave256.tga","Close Ocean Double"},
  106. {55.0f, 27.0f, 80.0f, 0.015f, 2000, 0.01f, 8.0f, 2000, 5367,"wave256.tga","Radial"},
  107. };
  108. //=============================================================================
  109. // WaterTracksObj::~WaterTracksObj
  110. //=============================================================================
  111. /** Destructor. Releases w3d assets. */
  112. //=============================================================================
  113. WaterTracksObj::~WaterTracksObj(void)
  114. {
  115. freeWaterTracksResources();
  116. }
  117. //=============================================================================
  118. // WaterTracksObj::WaterTracksObj
  119. //=============================================================================
  120. /** Constructor. Just nulls out some variables. */
  121. //=============================================================================
  122. WaterTracksObj::WaterTracksObj(void)
  123. {
  124. m_stageZeroTexture=NULL;
  125. m_bound=false;
  126. m_initTimeOffset=0;
  127. }
  128. //=============================================================================
  129. // WaterTracksObj::Get_Obj_Space_Bounding_Sphere
  130. //=============================================================================
  131. /** WW3D method that returns object bounding sphere used in frustum culling*/
  132. //=============================================================================
  133. void WaterTracksObj::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
  134. { /// @todo: Add code to cull track marks to screen by constantly updating bounding volumes
  135. sphere=m_boundingSphere;
  136. }
  137. //=============================================================================
  138. // WaterTracksObj::Get_Obj_Space_Bounding_Box
  139. //=============================================================================
  140. /** WW3D method that returns object bounding box used in collision detection*/
  141. //=============================================================================
  142. void WaterTracksObj::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
  143. {
  144. box=m_boundingBox;
  145. }
  146. //=============================================================================
  147. // WaterTracksObj::freeWaterTracksResources
  148. //=============================================================================
  149. /** Free any W3D resources associated with this object */
  150. //=============================================================================
  151. Int WaterTracksObj::freeWaterTracksResources(void)
  152. {
  153. REF_PTR_RELEASE(m_stageZeroTexture);
  154. return 0;
  155. }
  156. //=============================================================================
  157. // WaterTracksObj::init
  158. //=============================================================================
  159. /** Setup size settings and allocate W3D texture
  160. * The width/length define the size of the polygon quad which will contain
  161. * the specified texture.
  162. */
  163. //=============================================================================
  164. void WaterTracksObj::init( Real width, Real length, Vector2 &start, Vector2 &end, Char *texturename, Int waveTimeOffset)
  165. {
  166. freeWaterTracksResources(); //free old resources used by this track
  167. //save original settings used to create this wave
  168. m_initStartPos = start;
  169. m_initEndPos = end;
  170. m_initTimeOffset = waveTimeOffset;
  171. m_boundingSphere.Init(Vector3(0,0,0),400);
  172. m_boundingBox.Center.Set(0.0f, 0.0f, 0.0f);
  173. m_boundingBox.Extent.Set(400.0f, 400.0f, 1.0f);
  174. m_x=WATER_STRIP_X;
  175. m_y=WATER_STRIP_Y;
  176. m_elapsedMs=m_initTimeOffset;
  177. m_startPos=start;
  178. m_perpDir=m_waveDir=end-start;
  179. m_perpDir.Rotate(-1.57079632679f); //get vector perpendicular to wave motion.
  180. m_perpDir.Normalize();
  181. m_waveDir=m_perpDir;
  182. m_waveDir.Rotate(PI/2); //get vector along wave travel direction.
  183. //move back by width of wave so start point turns into maximum reach of wave.
  184. //m_startPos -= m_waveDir*m_width;
  185. //move back initial tip off of wave a couple units off the final position
  186. //to give it some room to travel. Travel vector is stored in m_waveDir.
  187. m_waveDistance = waveTypeInfo[m_type].m_waveDistance; //total distance traveled by wave front
  188. m_waveDir *= m_waveDistance;
  189. m_startPos -= m_waveDir; //move start point down away from shoreline
  190. m_initialVelocity=waveTypeInfo[m_type].m_initialVelocity; //velocity per ms
  191. m_totalMs = m_waveDistance/m_initialVelocity; //amount of time for wave to travel complete distance
  192. m_fadeMs = waveTypeInfo[m_type].m_fadeMs; //time for wave to fade out after it stops on beach
  193. m_waveInitialWidth=length * waveTypeInfo[m_type].m_initialWidthFraction;///<width of wave segment when it first appears
  194. m_waveInitialHeight=m_waveInitialWidth * waveTypeInfo[m_type].m_initialHeightWidthFraction; ///<height of wave segment when it first appears
  195. m_waveFinalWidth=length; ///<width of wave segment at full size
  196. m_waveFinalHeight=width; ///<final height of unstretched wave
  197. //get total time for front to complete its cycle
  198. m_timeToReachBeach=(m_waveDistance - m_waveFinalHeight)/m_initialVelocity;
  199. m_frontSlowDownAcc= -(m_initialVelocity*m_initialVelocity)/(2*m_waveFinalHeight); //deceleration of wave after it hits land
  200. m_timeToStop = -m_initialVelocity/m_frontSlowDownAcc;
  201. m_timeToRetreat = sqrt(fabs(2.0f*m_waveFinalHeight/m_frontSlowDownAcc));
  202. m_totalMs = m_timeToReachBeach + m_timeToStop + m_timeToRetreat; //total time that wave front is on screen
  203. m_backSlowDownAcc = (2.0f*m_waveInitialHeight/(m_timeToStop*m_timeToStop));//((m_waveInitialHeight - m_velocity*m_timeToStop)*2.0f)/(m_timeToStop*m_timeToStop);
  204. m_timeToCompress = waveTypeInfo[m_type].m_timeToCompress; //time for back of wave to continue moving forward after front starts retreating.
  205. if (m_type == WaveTypeStationary)
  206. { //this is a stationary wave slightly behind starting point
  207. m_timeToRetreat = 1000; //time to fade out.
  208. m_totalMs = m_timeToReachBeach + m_timeToStop+m_fadeMs+m_timeToRetreat; //trigger when other wave stops.
  209. m_startPos = start;
  210. m_fadeMs = 1000; //time for wave to fade out after it stops on beach
  211. }
  212. m_stageZeroTexture=WW3DAssetManager::Get_Instance()->Get_Texture(texturename);
  213. }
  214. //=============================================================================
  215. // WaterTracksObj::init
  216. //=============================================================================
  217. /** Setup size settings and allocate W3D texture
  218. * Alternate version of init where:
  219. * (start, end) define a vector perpendicular to wave travel. The length of this
  220. * vector is used as the length of the wave segment. The line between start-end
  221. * defines the maximum distance the wave will reach.
  222. */
  223. //=============================================================================
  224. void WaterTracksObj::init( Real width, Vector2 &start, Vector2 &end, Char *texturename)
  225. {
  226. freeWaterTracksResources(); //free old resources used by this track
  227. m_boundingSphere.Init(Vector3(0,0,0),400);
  228. m_boundingBox.Center.Set(0.0f, 0.0f, 0.0f);
  229. m_boundingBox.Extent.Set(400.0f, 400.0f, 1.0f);
  230. m_perpDir=end-start;
  231. m_startPos=start + m_perpDir*0.5f; //move start point to middle
  232. Real length=m_perpDir.Length();
  233. m_perpDir *= 1.0f/length; //normalize it.
  234. m_waveDir=m_perpDir;
  235. m_waveDir.Rotate(PI/2); //get vector along wave travel direction.
  236. m_startPos -= m_waveDir*width; //move back by width of wave
  237. m_waveDir *= 1.3f*MAP_XY_FACTOR; //travel 4 units
  238. m_startPos -= m_waveDir; //move start point down away from shoreline
  239. m_x=WATER_STRIP_X;
  240. m_y=WATER_STRIP_Y;
  241. m_elapsedMs=0;
  242. m_initialVelocity=0.001f*MAP_XY_FACTOR; //velocity per ms
  243. m_totalMs=m_waveDir.Length()/m_initialVelocity;
  244. m_fadeMs = 3000; //time for wave to fade out after it stops on beach
  245. m_stageZeroTexture=WW3DAssetManager::Get_Instance()->Get_Texture(texturename);
  246. }
  247. //=============================================================================
  248. // WaterTracksObj::update
  249. //=============================================================================
  250. /** Update state of object - advance animations and other states.
  251. */
  252. //=============================================================================
  253. Int WaterTracksObj::update(Int msElapsed)
  254. {
  255. #ifdef ALLOW_WATER_TRACK_EDIT
  256. // if (pauseWaves)
  257. // m_elapsedMs = m_timeToReachBeach+m_timeToStop;
  258. // else
  259. #endif
  260. //nothing to do here...most of the work is done on render.
  261. m_elapsedMs += msElapsed; //advance time for this update
  262. ///@todo: Should check in here if we are done with this object are return FALSE to free it.
  263. // return FALSE;
  264. return TRUE; //assume we had an update
  265. }
  266. #define waveInitialV = 0.01f
  267. #define waveAcceleration = -0.01f
  268. //=============================================================================
  269. // WaterTracksObj::render
  270. //=============================================================================
  271. /** Draws the object in it's current state.
  272. */
  273. //=============================================================================
  274. Int WaterTracksObj::render(DX8VertexBufferClass *vertexBuffer, Int batchStart)
  275. {
  276. VertexFormatXYZDUV1 *vb;
  277. Vector2 waveTailOrigin,waveFrontOrigin;
  278. Real ooWaveDirLen=1.0f/m_waveDir.Length(); //one over length
  279. Real waterHeight;
  280. Real waveAlpha;
  281. Real widthFrac;
  282. Real heightFrac;
  283. if (batchStart < (WATER_VB_PAGES*WATER_STRIP_X*WATER_STRIP_Y-m_x*m_y))
  284. { //we have room in current VB, append new verts
  285. if(vertexBuffer->Get_DX8_Vertex_Buffer()->Lock(batchStart*vertexBuffer->FVF_Info().Get_FVF_Size(),m_x*m_y*vertexBuffer->FVF_Info().Get_FVF_Size(),(unsigned char**)&vb,D3DLOCK_NOOVERWRITE) != D3D_OK)
  286. return batchStart;
  287. }
  288. else
  289. { //ran out of room in last VB, request a substitute VB.
  290. if(vertexBuffer->Get_DX8_Vertex_Buffer()->Lock(0,m_x*m_y*vertexBuffer->FVF_Info().Get_FVF_Size(),(unsigned char**)&vb,D3DLOCK_DISCARD) != D3D_OK)
  291. return batchStart;
  292. batchStart=0; //reset start of page to first vertex
  293. }
  294. //Adjust wave position in a non-linear way so that it slows down as it hits the target. Using 1/4 sine wave
  295. //seems to work okay since it maxes out at 1.0 at our final position.
  296. //Real timeFrac=(Real)m_elapsedMs/(Real)m_totalMs;//sinf(0.5f*3.14159f*(Real)m_elapsedMs/(Real)m_totalMs);
  297. //Real displacement=m_elapsedMs*waveInitialV+0.5*waveAcceleration*m_elapsed*m_elapsed;
  298. heightFrac=1.0f;
  299. widthFrac = 1.0f;
  300. if (m_type == WaveTypeStationary)
  301. { //stationary wave
  302. waveFrontOrigin = m_startPos;
  303. waveFrontOrigin -= m_perpDir*m_waveFinalWidth*0.5f; //offset to left edge of wave
  304. waveTailOrigin = waveFrontOrigin - m_waveFinalHeight * ooWaveDirLen*m_waveDir;
  305. waveAlpha = 0.0f;
  306. if (m_elapsedMs >= m_totalMs)
  307. m_elapsedMs = 0; //done with effect*/
  308. if (m_elapsedMs > (m_timeToReachBeach + m_timeToStop -1000 + m_fadeMs))
  309. { //fading out
  310. waveAlpha = m_elapsedMs-(m_timeToReachBeach + m_timeToStop - 1000 +m_fadeMs);//(m_totalMs-m_timeToRetreat -m_fadeMs - m_elapsedMs)/m_fadeMs;
  311. waveAlpha = waveAlpha / m_timeToRetreat;
  312. waveAlpha = 1.0f - waveAlpha;
  313. if (waveAlpha < 0.0f)
  314. waveAlpha = 0.0f;
  315. }
  316. else
  317. if (m_elapsedMs > (m_timeToReachBeach + m_timeToStop - 1000))
  318. { //start fading up
  319. waveAlpha = m_elapsedMs-(m_timeToReachBeach + m_timeToStop - 1000);//(m_totalMs-m_timeToRetreat -m_fadeMs - m_elapsedMs)/m_fadeMs;
  320. waveAlpha = waveAlpha / m_fadeMs;
  321. if (waveAlpha > 1.0f)
  322. waveAlpha = 1.0f;
  323. }
  324. }
  325. else
  326. { //moving wave
  327. //get coordinate of top left of wave strip
  328. if (m_elapsedMs < m_timeToReachBeach)
  329. { //wave has not reached beach yet so position only depends on velocity
  330. waveAlpha = m_elapsedMs / m_timeToReachBeach;
  331. widthFrac = waveAlpha;
  332. widthFrac=(m_waveInitialWidth + widthFrac* (m_waveFinalWidth-m_waveInitialWidth))/m_waveFinalWidth;
  333. waveFrontOrigin = m_startPos + m_initialVelocity*m_elapsedMs*ooWaveDirLen*m_waveDir;
  334. waveFrontOrigin -= m_perpDir*m_waveFinalWidth*0.5f*widthFrac; //offset to left edge of wave
  335. //Tail of wave will be behind the front by fixed amount.
  336. waveTailOrigin = waveFrontOrigin - m_waveInitialHeight * ooWaveDirLen*m_waveDir;
  337. }
  338. else //wave has reached beach and is decelerating
  339. if (m_elapsedMs < m_totalMs)
  340. { waveAlpha = 1.0f;
  341. widthFrac = 1.0f;
  342. //Get position of wave when it hit the beach
  343. waveFrontOrigin = m_startPos + m_initialVelocity*m_timeToReachBeach*ooWaveDirLen*m_waveDir;
  344. waveTailOrigin = waveFrontOrigin; //store position for calculating tail position
  345. //Add movement after it hit the beach
  346. Real elapsedMs=m_elapsedMs - m_timeToReachBeach;
  347. waveFrontOrigin += (m_initialVelocity*elapsedMs+0.5f*m_frontSlowDownAcc*elapsedMs*elapsedMs)*ooWaveDirLen*m_waveDir;
  348. waveFrontOrigin -= m_perpDir*m_waveFinalWidth*0.5f*widthFrac; //offset to left edge of wave
  349. Real timeSinceBacktrack = m_elapsedMs - m_timeToReachBeach - m_timeToStop;
  350. if (timeSinceBacktrack < 0)
  351. timeSinceBacktrack = 0;
  352. waveAlpha = timeSinceBacktrack/m_fadeMs;
  353. if (waveAlpha > 1.0f)
  354. waveAlpha = 1.0f;
  355. waveAlpha = 1.0f - waveAlpha;
  356. //Get position of tail when front hits the beach.
  357. waveTailOrigin -= m_waveInitialHeight * ooWaveDirLen*m_waveDir;
  358. if (m_elapsedMs > (m_timeToReachBeach+m_timeToStop+m_timeToCompress))
  359. { elapsedMs=elapsedMs; ///@todo: bug?
  360. waveTailOrigin += (0.5f*m_backSlowDownAcc*(m_timeToStop+m_timeToCompress)*(m_timeToStop+m_timeToCompress))*ooWaveDirLen*m_waveDir;
  361. //get time since wave should have stopped moving forward
  362. Real newElapsed = m_elapsedMs - (m_timeToReachBeach+m_timeToStop+m_timeToCompress);
  363. waveTailOrigin += (0.5f*m_frontSlowDownAcc*newElapsed*newElapsed)*ooWaveDirLen*m_waveDir;
  364. }
  365. else
  366. // if (m_elapsedMs < (m_totalMs-m_timeToRetreat))
  367. //find position of tail including slowdown after it hit the beach
  368. // waveTailOrigin += (m_initialVelocity*elapsedMs+0.5f*m_backSlowDownAcc*elapsedMs*elapsedMs)*ooWaveDirLen*m_waveDir;
  369. waveTailOrigin += (0.5f*m_backSlowDownAcc*elapsedMs*elapsedMs)*ooWaveDirLen*m_waveDir;
  370. waveTailOrigin -= m_perpDir*m_waveFinalWidth*0.5f*widthFrac; //offset to left edge of wave
  371. }
  372. else
  373. { m_elapsedMs = 0;
  374. waveAlpha = m_elapsedMs / m_timeToReachBeach;
  375. widthFrac = waveAlpha;
  376. widthFrac=(m_waveInitialWidth + widthFrac* (m_waveFinalWidth-m_waveInitialWidth))/m_waveFinalWidth;
  377. waveFrontOrigin = m_startPos + m_initialVelocity*m_elapsedMs*ooWaveDirLen*m_waveDir;
  378. waveFrontOrigin -= m_perpDir*m_waveFinalWidth*0.5f*widthFrac; //offset to left edge of wave
  379. //Tail of wave will be behind the front by fixed amount.
  380. waveTailOrigin = waveFrontOrigin - m_waveInitialHeight * ooWaveDirLen*m_waveDir;
  381. }
  382. }
  383. //First insert tail of wave:
  384. Vector2 testPoint(waveTailOrigin);
  385. TheTerrainLogic->isUnderwater(testPoint.X,testPoint.Y,&waterHeight);
  386. vb->x= testPoint.X;
  387. vb->y= testPoint.Y;
  388. vb->z=waterHeight+1.5f;
  389. vb->diffuse=(REAL_TO_INT(waveAlpha*255.0f)<<24) |0xffffff;
  390. if (m_flipU)
  391. vb->u1=1;
  392. else
  393. vb->u1=0;
  394. vb->v1=0;
  395. vb++;
  396. testPoint.Set(waveTailOrigin + m_perpDir*m_waveFinalWidth*widthFrac);
  397. vb->x= testPoint.X;
  398. vb->y= testPoint.Y;
  399. vb->z=waterHeight+1.5f;
  400. vb->diffuse=(REAL_TO_INT(waveAlpha*255.0f)<<24) |0xffffff;
  401. if (m_flipU)
  402. vb->u1=0.0f;
  403. else
  404. vb->u1=1.0f;
  405. vb->v1=0;
  406. vb++;
  407. //insert front of wave
  408. testPoint.Set(waveFrontOrigin);
  409. vb->x= testPoint.X;
  410. vb->y= testPoint.Y;
  411. vb->z=waterHeight+1.5f;
  412. vb->diffuse=(REAL_TO_INT(waveAlpha*255.0f)<<24) |0xffffff;
  413. if (m_flipU)
  414. vb->u1=1;
  415. else
  416. vb->u1=0;
  417. vb->v1=1.0f;
  418. vb++;
  419. testPoint.Set(waveFrontOrigin + m_perpDir*m_waveFinalWidth*widthFrac);
  420. vb->x= testPoint.X;
  421. vb->y= testPoint.Y;
  422. vb->z=waterHeight+1.5f;
  423. vb->diffuse=(REAL_TO_INT(waveAlpha*255.0f)<<24) |0xffffff;
  424. if (m_flipU)
  425. vb->u1=0;
  426. else
  427. vb->u1=1.0f;
  428. vb->v1=1.0f;
  429. vb++;
  430. vertexBuffer->Get_DX8_Vertex_Buffer()->Unlock();
  431. Int idxCount=(m_y-1)*(m_x*2+2) - 2; //index count
  432. DX8Wrapper::Set_Index_Buffer(TheWaterTracksRenderSystem->m_indexBuffer,batchStart);
  433. DX8Wrapper::Draw_Strip(0,idxCount-2,0,m_x*m_y); //there are always n-2 primitives for n index strip.
  434. return batchStart+m_x*m_y; //return new offset into unused area of vertex buffer
  435. }
  436. //=============================================================================
  437. //WaterTracksRenderSystem::bindTrack
  438. //=============================================================================
  439. /** Grab a track from the free store. If no free tracks exist, return NULL.
  440. As long as a track is bound to an object (like a tank) it is ready to accept
  441. updates with additional edges. Once it is unbound, it will expire and return
  442. to the free store once all tracks have faded out.
  443. */
  444. //=============================================================================
  445. WaterTracksObj *WaterTracksRenderSystem::bindTrack(waveType type)
  446. {
  447. WaterTracksObj *mod,*nextmod,*prevmod;
  448. mod = m_freeModules;
  449. if( mod )
  450. {
  451. // take module off the free list
  452. if( mod->m_nextSystem )
  453. mod->m_nextSystem->m_prevSystem = mod->m_prevSystem;
  454. if( mod->m_prevSystem )
  455. mod->m_prevSystem->m_nextSystem = mod->m_nextSystem;
  456. else
  457. m_freeModules = mod->m_nextSystem;
  458. mod->m_type=type;
  459. // put module on the used list (sorted next to similar types)
  460. nextmod=NULL,prevmod=NULL;
  461. for( nextmod = m_usedModules; nextmod; prevmod=nextmod,nextmod = nextmod->m_nextSystem )
  462. {
  463. if (nextmod->m_type==type)
  464. { //found start of other shadows using same texture, insert new shadow here.
  465. mod->m_nextSystem=nextmod;
  466. mod->m_prevSystem=prevmod;
  467. nextmod->m_prevSystem=mod;
  468. if (prevmod)
  469. { prevmod->m_nextSystem=mod;
  470. }
  471. else
  472. m_usedModules=mod;
  473. break;
  474. }
  475. }
  476. if (nextmod==NULL)
  477. { //shadow with new texture. Add to top of list.
  478. mod->m_nextSystem = m_usedModules;
  479. if (m_usedModules)
  480. m_usedModules->m_prevSystem=mod;
  481. m_usedModules = mod;
  482. }
  483. mod->m_bound=true;
  484. } // end if
  485. #ifdef SYNC_WAVES
  486. nextmod=m_usedModules;
  487. while(nextmod)
  488. {
  489. nextmod->m_elapsedMs=nextmod->m_initTimeOffset;
  490. nextmod=nextmod->m_nextSystem;
  491. } // end while
  492. #endif
  493. return mod;
  494. } //end bindTrack
  495. //=============================================================================
  496. //WaterTracksRenderSystem::unbindTrack
  497. //=============================================================================
  498. /** Called when an object (i.e Tank) will not lay down any more tracks and
  499. doesn't need this object anymore. The track-laying object will be returned
  500. to pool of available tracks as soon as any remaining track edges have faded out.
  501. */
  502. //=============================================================================
  503. void WaterTracksRenderSystem::unbindTrack( WaterTracksObj *mod )
  504. {
  505. //this object should return to free store as soon as there is nothing
  506. //left to render.
  507. mod->m_bound=false;
  508. releaseTrack(mod);
  509. }
  510. //=============================================================================
  511. //WaterTracksRenderSystem::releaseTrack
  512. //=============================================================================
  513. /** Returns a track laying object to free store to be used again later.
  514. */
  515. void WaterTracksRenderSystem::releaseTrack( WaterTracksObj *mod )
  516. {
  517. if (mod==NULL)
  518. return;
  519. assert(mod->m_bound == false);
  520. // remove module from used list
  521. if( mod->m_nextSystem )
  522. mod->m_nextSystem->m_prevSystem = mod->m_prevSystem;
  523. if( mod->m_prevSystem )
  524. mod->m_prevSystem->m_nextSystem = mod->m_nextSystem;
  525. else
  526. m_usedModules = mod->m_nextSystem;
  527. // add module to free list
  528. mod->m_prevSystem = NULL;
  529. mod->m_nextSystem = m_freeModules;
  530. if( m_freeModules )
  531. m_freeModules->m_prevSystem = mod;
  532. m_freeModules = mod;
  533. mod->freeWaterTracksResources();
  534. }
  535. //=============================================================================
  536. // WaterTracksRenderSystem::WaterTracksRenderSystem
  537. //=============================================================================
  538. /** Constructor. Just nulls out some variables. */
  539. //=============================================================================
  540. WaterTracksRenderSystem::WaterTracksRenderSystem()
  541. {
  542. m_usedModules = NULL;
  543. m_freeModules = NULL;
  544. m_indexBuffer = NULL;
  545. m_vertexMaterialClass = NULL;
  546. m_vertexBuffer = NULL;
  547. m_stripSizeX=WATER_STRIP_X;
  548. m_stripSizeY=WATER_STRIP_Y;
  549. m_batchStart=0;
  550. TheWaterTracksRenderSystem = this; //only allow one instance of this object.
  551. }
  552. //=============================================================================
  553. // WaterTracksRenderSystem::~WaterTracksRenderSystem
  554. //=============================================================================
  555. /** Destructor. Free all pre-allocated track laying render objects*/
  556. //=============================================================================
  557. WaterTracksRenderSystem::~WaterTracksRenderSystem( void )
  558. {
  559. // free all data
  560. shutdown();
  561. m_vertexMaterialClass=NULL;
  562. }
  563. //=============================================================================
  564. // WaterTracksRenderSystem::ReAcquireResources
  565. //=============================================================================
  566. /** (Re)allocates all W3D assets after a reset.. */
  567. //=============================================================================
  568. void WaterTracksRenderSystem::ReAcquireResources(void)
  569. {
  570. Int i,j,k;
  571. // const Int numModules=16; ///@todo: Get a value out of gdf
  572. // just for paranoia's sake.
  573. REF_PTR_RELEASE(m_indexBuffer);
  574. REF_PTR_RELEASE(m_vertexBuffer);
  575. //Will need m_y-1 strips, each of length m_x*2.
  576. //Will also need 2 extra indices to connect each strip to next one (except last strip)
  577. //Total index buffer size = (m_y-1)*(m_x*2+2) - 2 (drop the extra 2 indices from last strip)
  578. Int idxCount=(m_stripSizeY-1)*(m_stripSizeX*2+2) - 2;
  579. m_indexBuffer=NEW_REF(DX8IndexBufferClass,(idxCount));
  580. // Fill up the IB
  581. {
  582. DX8IndexBufferClass::WriteLockClass lockIdxBuffer(m_indexBuffer);
  583. UnsignedShort *ib=lockIdxBuffer.Get_Index_Array();
  584. for (i=0,j=0,k=0; i<idxCount; j++)
  585. {
  586. for (;k<(m_stripSizeX*(j+1)); k++,i+=2)
  587. {
  588. ib[i]=(UnsignedShort) k+m_stripSizeX;
  589. ib[i+1]=(UnsignedShort) k;
  590. }
  591. //Generate 4 degenerate triangle to connect current strip to next strip/row of map
  592. //To do this, we just repeat the last index of first strip and first index of new strip.
  593. //Any triangles with repeated vertices will be skipped during rendering.
  594. if (i<idxCount) //check if there is at least 1 more strip to go
  595. {
  596. ib[i]=k-1;
  597. ib[i+1]=k+m_stripSizeX;
  598. i+=2;
  599. }
  600. }
  601. }
  602. m_vertexBuffer=NEW_REF(DX8VertexBufferClass,(DX8_FVF_XYZDUV1,m_stripSizeX*m_stripSizeY*WATER_VB_PAGES,DX8VertexBufferClass::USAGE_DYNAMIC));
  603. m_batchStart=0;
  604. }
  605. //=============================================================================
  606. // WaterTracksRenderSystem::ReleaseResources
  607. //=============================================================================
  608. /** (Re)allocates all W3D assets after a reset.. */
  609. //=============================================================================
  610. void WaterTracksRenderSystem::ReleaseResources(void)
  611. {
  612. REF_PTR_RELEASE(m_indexBuffer);
  613. REF_PTR_RELEASE(m_vertexBuffer);
  614. // Note - it is ok to not release the material, as it is a w3d object that
  615. // has no dx8 resources. jba.
  616. }
  617. //=============================================================================
  618. // WaterTracksRenderSystem::init
  619. //=============================================================================
  620. /** initialize the system, allocate all the render objects we will need */
  621. //=============================================================================
  622. void WaterTracksRenderSystem::init(void)
  623. {
  624. const Int numModules=2000; ///@todo: Get a value out of gdf
  625. Int i;
  626. WaterTracksObj *mod;
  627. m_stripSizeX=WATER_STRIP_X; ///@todo: grab these out of gdf or define
  628. m_stripSizeY=WATER_STRIP_Y;
  629. m_level=TheGlobalData->m_waterPositionZ;
  630. ReAcquireResources();
  631. //go with a preset material for now.
  632. m_vertexMaterialClass=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
  633. //use a multi-texture shader:
  634. m_shaderClass = ShaderClass::_PresetAlphaShader;
  635. m_shaderClass.Set_Cull_Mode(ShaderClass::CULL_MODE_DISABLE); //water should be visible from both sides
  636. // we cannot initialize a system that is already initialized
  637. if( m_freeModules || m_usedModules )
  638. {
  639. // system already online!
  640. assert( 0 );
  641. return;
  642. } // end if
  643. // allocate our modules for this system
  644. for( i = 0; i < numModules; i++ )
  645. {
  646. mod = NEW WaterTracksObj;
  647. if( mod == NULL )
  648. {
  649. // unable to allocate modules needed
  650. assert( 0 );
  651. return;
  652. } // end if
  653. mod->m_prevSystem = NULL;
  654. mod->m_nextSystem = m_freeModules;
  655. if( m_freeModules )
  656. m_freeModules->m_prevSystem = mod;
  657. m_freeModules = mod;
  658. } // end for i
  659. } // end init
  660. void WaterTracksRenderSystem::reset(void)
  661. {
  662. WaterTracksObj *nextMod,*mod;
  663. //release unbound tracks that may still be fading out
  664. mod=m_usedModules;
  665. while(mod)
  666. {
  667. nextMod=mod->m_nextSystem;
  668. mod->m_bound=false;
  669. releaseTrack(mod);
  670. mod = nextMod;
  671. } // end while
  672. // free all attached things and used modules
  673. assert( m_usedModules == NULL );
  674. }
  675. //=============================================================================
  676. // WaterTracksRenderSystem::shutdown
  677. //=============================================================================
  678. /** Shutdown and free all memory for this system */
  679. //=============================================================================
  680. void WaterTracksRenderSystem::shutdown( void )
  681. {
  682. WaterTracksObj *nextMod,*mod;
  683. //release unbound tracks that may still be fading out
  684. mod=m_usedModules;
  685. while(mod)
  686. {
  687. nextMod=mod->m_nextSystem;
  688. if (!mod->m_bound)
  689. releaseTrack(mod);
  690. mod = nextMod;
  691. } // end while
  692. // free all attached things and used modules
  693. assert( m_usedModules == NULL );
  694. // free all module storage
  695. while( m_freeModules )
  696. {
  697. nextMod = m_freeModules->m_nextSystem;
  698. delete m_freeModules;
  699. m_freeModules = nextMod;
  700. } // end while
  701. REF_PTR_RELEASE(m_indexBuffer);
  702. REF_PTR_RELEASE(m_vertexMaterialClass);
  703. REF_PTR_RELEASE(m_vertexBuffer);
  704. } // end shutdown
  705. //=============================================================================
  706. // WaterTracksRenderSystem::update
  707. //=============================================================================
  708. /** Update the state of all active track marks - fade, expire, etc. */
  709. //=============================================================================
  710. void WaterTracksRenderSystem::update()
  711. {
  712. static Int iLastTime=timeGetTime();
  713. WaterTracksObj *mod=m_usedModules,*nextMod;
  714. Int timeDiff = timeGetTime()-iLastTime;
  715. iLastTime += timeDiff;
  716. //Lock framerate to 30 fps
  717. timeDiff = 1.0f/30.0f*1000.0f;
  718. //first update all the tracks
  719. while( mod )
  720. {
  721. nextMod = mod->m_nextSystem;
  722. if (!mod->m_bound || (!mod->update(timeDiff) && !mod->m_bound))
  723. { //object is not longer updating and is unbound so ok to release it.
  724. releaseTrack(mod);
  725. }
  726. mod = nextMod;
  727. } // end while
  728. }
  729. void TestWaterUpdate(void);
  730. void setFPMode( void );
  731. //=============================================================================
  732. // WaterTracksRenderSystem::flush
  733. //=============================================================================
  734. /** Draw all active track marks for this frame */
  735. //=============================================================================
  736. void WaterTracksRenderSystem::flush(RenderInfoClass & rinfo)
  737. {
  738. /** @todo: Optimize system by drawing tracks as triangle strips and use dynamic vertex buffer access.
  739. May also try rendering all tracks with one call to W3D/D3D by grouping them by texture.
  740. Try improving the fit to vertical surfaces like cliffs.
  741. */
  742. Int diffuseLight;
  743. if (!TheGlobalData->m_showSoftWaterEdge || TheWaterTransparency->m_transparentWaterDepth ==0 )
  744. return;
  745. if (TheGlobalData->m_usingWaterTrackEditor)
  746. TestWaterUpdate();
  747. update(); //update positions of all the tracks
  748. rinfo.Camera.Apply();
  749. if (!m_usedModules || ShaderClass::Is_Backface_Culling_Inverted())
  750. return; //don't render track marks in reflections.
  751. //According to Nvidia there's a D3D bug that happens if you don't start with a
  752. //new dynamic VB each frame - so we force a DISCARD by overflowing the counter.
  753. m_batchStart = 0xffff;
  754. // adjust shading for time of day.
  755. Real shadeR, shadeG, shadeB;
  756. shadeR = TheGlobalData->m_terrainAmbient[0].red;
  757. shadeG = TheGlobalData->m_terrainAmbient[0].green;
  758. shadeB = TheGlobalData->m_terrainAmbient[0].blue;
  759. shadeR += TheGlobalData->m_terrainDiffuse[0].red/2;
  760. shadeG += TheGlobalData->m_terrainDiffuse[0].green/2;
  761. shadeB += TheGlobalData->m_terrainDiffuse[0].blue/2;
  762. shadeR*=255.0f;
  763. shadeG*=255.0f;
  764. shadeB*=255.0f;
  765. diffuseLight=REAL_TO_INT(shadeB) | (REAL_TO_INT(shadeG) << 8) | (REAL_TO_INT(shadeR) << 16);
  766. Matrix3D tm(1); ///set to identity
  767. DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); //position the water surface
  768. DX8Wrapper::Set_Material(m_vertexMaterialClass);
  769. DX8Wrapper::Set_Shader(m_shaderClass);
  770. DX8Wrapper::Set_Vertex_Buffer(m_vertexBuffer);
  771. DX8Wrapper::Set_DX8_Render_State(D3DRS_ZBIAS,8);
  772. //Force apply of render states so we can override them.
  773. DX8Wrapper::Apply_Render_State_Changes();
  774. if (TheTerrainRenderObject->getShroud())
  775. {
  776. W3DShaderManager::setTexture(0,TheTerrainRenderObject->getShroud()->getShroudTexture());
  777. W3DShaderManager::setShader(W3DShaderManager::ST_SHROUD_TEXTURE, 1);
  778. //modulate with shroud texture
  779. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE ); //stage 1 texture
  780. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_CURRENT ); //previous stage texture
  781. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
  782. DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
  783. //Shroud shader uses z-compare of EQUAL which wouldn't work on water because it doesn't
  784. //write to the zbuffer. Change to LESSEQUAL.
  785. DX8Wrapper::Set_DX8_Render_State(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
  786. }
  787. Int LastTextureType=-1;
  788. WaterTracksObj *mod=m_usedModules;
  789. while( mod )
  790. {
  791. if (LastTextureType != mod->m_type)
  792. DX8Wrapper::Set_Texture(0,mod->m_stageZeroTexture);
  793. Int vertsRendered=mod->render(m_vertexBuffer,m_batchStart);
  794. m_batchStart = vertsRendered; //advance past vertices already in buffer
  795. mod = mod->m_nextSystem;
  796. } //while (mod)
  797. DX8Wrapper::Set_DX8_Render_State(D3DRS_ZBIAS,0);
  798. if (TheTerrainRenderObject->getShroud())
  799. { //we used the shroud shader, so reset it.
  800. DX8Wrapper::Set_DX8_Render_State(D3DRS_ZFUNC, D3DCMP_EQUAL);
  801. W3DShaderManager::resetShader(W3DShaderManager::ST_SHROUD_TEXTURE);
  802. }
  803. }
  804. WaterTracksObj *WaterTracksRenderSystem::findTrack(Vector2 &start, Vector2 &end, waveType type)
  805. {
  806. WaterTracksObj *mod=m_usedModules;
  807. while( mod )
  808. {
  809. if (mod->m_initEndPos == end &&
  810. mod->m_initStartPos == start &&
  811. mod->m_type == type)
  812. return mod;
  813. mod = mod->m_nextSystem;
  814. } //while (mod)
  815. return NULL;
  816. }
  817. void WaterTracksRenderSystem::saveTracks(void)
  818. {
  819. if (!TheTerrainLogic)
  820. return;
  821. AsciiString fileName=TheTerrainLogic->getSourceFilename();
  822. char path[256];
  823. strcpy(path,fileName.str());
  824. Int len=strlen(path);
  825. strcpy(path+len-4,".wak");
  826. WaterTracksObj *umod;
  827. Int trackCount=0;
  828. FILE *fp=fopen(path,"wb");
  829. if (fp)
  830. {
  831. umod=m_usedModules;
  832. while(umod)
  833. { if (umod->m_initTimeOffset == 0)
  834. { //only save the primary wave front, second layer is added automatically.
  835. fwrite(&umod->m_initStartPos,sizeof(umod->m_startPos),1,fp);
  836. fwrite(&umod->m_initEndPos,sizeof(umod->m_perpDir),1,fp);
  837. fwrite(&umod->m_type,sizeof(umod->m_type),1,fp);
  838. // fwrite(&umod->m_initTimeOffset,sizeof(umod->m_initTimeOffset),1,fp);
  839. trackCount++;
  840. }
  841. umod=umod->m_nextSystem;
  842. } // end while
  843. fwrite(&trackCount,sizeof(trackCount),1,fp);
  844. fclose(fp);
  845. }
  846. }
  847. void WaterTracksRenderSystem::loadTracks(void)
  848. {
  849. if (!TheTerrainLogic)
  850. return;
  851. AsciiString fileName=TheTerrainLogic->getSourceFilename();
  852. char path[256];
  853. strcpy(path,fileName.str());
  854. Int len=strlen(path);
  855. strcpy(path+len-4,".wak");
  856. File *file = TheFileSystem->openFile(path, File::READ | File::BINARY);
  857. WaterTracksObj *umod;
  858. Int trackCount=0;
  859. Int flipU=0;
  860. Vector2 startPos,endPos;
  861. waveType wtype;
  862. if (file)
  863. {
  864. file->seek(-4,File::END);
  865. file->read(&trackCount,sizeof(trackCount));
  866. file->seek(0, File::START);
  867. for (Int i=0; i<trackCount; i++)
  868. {
  869. tryagain:
  870. file->read(&startPos,sizeof(startPos));
  871. file->read(&endPos,sizeof(endPos));
  872. file->read(&wtype,sizeof(wtype));
  873. //Check if this track already exists.
  874. if (findTrack(startPos,endPos,wtype))
  875. { i++;
  876. goto tryagain;
  877. }
  878. umod=TheWaterTracksRenderSystem->bindTrack(wtype);
  879. if (umod)
  880. { //umod->init(1.5f*MAP_XY_FACTOR,Vector2(0,0),Vector2(1,1),"wave256.tga");
  881. flipU ^= 1; //toggle flip state
  882. umod->init(waveTypeInfo[wtype].m_finalHeight,waveTypeInfo[wtype].m_finalWidth,startPos,endPos,waveTypeInfo[wtype].m_textureName,0);
  883. umod->m_flipU=flipU;
  884. if (waveTypeInfo[wtype].m_secondWaveTimeOffset) //check if we need a second wave to follow
  885. {
  886. umod=TheWaterTracksRenderSystem->bindTrack(wtype);
  887. if (umod)
  888. {
  889. umod->init(waveTypeInfo[wtype].m_finalHeight,waveTypeInfo[wtype].m_finalWidth,startPos,endPos,waveTypeInfo[wtype].m_textureName,waveTypeInfo[wtype].m_secondWaveTimeOffset);
  890. umod->m_flipU = !flipU;
  891. }
  892. }
  893. }
  894. }
  895. file->close();
  896. }
  897. #if 0 //Obsolete code used before there was another editor to place waves.
  898. //Look for all waypoints that start with "waveStart_"
  899. for (Waypoint *way = TheTerrainLogic->getFirstWaypoint(); way; way = way->getNext())
  900. {
  901. if (way->getName().startsWith("waveStart_") && way->getNumLinks() == 1)
  902. {
  903. Waypoint *nextWay = way->getLink(0);
  904. Coord3D startPos = *way->getLocation();
  905. Coord3D endPos = *nextWay->getLocation();
  906. //initialize surface layer (1)
  907. WaterTracksObj *umod=TheWaterTracksRenderSystem->bindTrack(1);
  908. if (umod)
  909. {
  910. umod->init(DEFAULT_FINAL_WAVE_HEIGHT,DEFAULT_FINAL_WAVE_WIDTH,Vector2(startPos.x,startPos.y),Vector2(endPos.x,endPos.y),"wave1.tga",0);
  911. }
  912. /*
  913. //initialize foam layer (0)
  914. umod=TheWaterTracksRenderSystem->bindTrack(0);
  915. if (umod)
  916. {
  917. umod->init(2.5f*MAP_XY_FACTOR,5.0f*MAP_XY_FACTOR,Vector2(startPos.x,startPos.y),Vector2(endPos.x,endPos.y),"wave2.tga");
  918. // umod->m_fadeMs += 1500; //take extra 500 ms to fade out wave.
  919. // umod->m_retreatFrac = 1.0f; //don't move wave back after it hits final position.
  920. }*/
  921. }
  922. }
  923. #endif
  924. }
  925. /**@todo: this is a quick hack for adding/removing/testing breaking waves inside the client.
  926. Will need to move this code to an external editor at some pont. */
  927. #include "GameClient/Display.h"
  928. extern HWND ApplicationHWnd;
  929. //TODO: Fix editor so it actually draws the wave segment instead of line while editing
  930. //Could freeze all the water while editing? Or keep setting elapsed time on current segment.
  931. //Have to make it so seamless merge of segments at final position.
  932. static void TestWaterUpdate(void)
  933. {
  934. static Int doInit=1;
  935. static WaterTracksObj *track=NULL,*track2=NULL;
  936. static Int trackEditMode=0;
  937. static waveType currentWaveType = WaveTypeOcean;
  938. POINT screenPoint;
  939. POINT endPoint;
  940. static POINT mouseAnchor;
  941. static Int haveStart=0;
  942. static Int haveEnd=0;
  943. static Coord3D terrainPointStart,terrainPointEnd;
  944. //flags to tell me when the user lets go of a key
  945. static Int trackEditModeReset=1;
  946. static Int addPointReset=1;
  947. static Int deleteTrackReset=1;
  948. static Int saveTracksReset=1;
  949. static Int loadTracksReset=1;
  950. static Int changeTypeReset=1;
  951. pauseWaves=FALSE;
  952. if (doInit)
  953. { //create the system
  954. doInit=0;
  955. // TheWaterTracksRenderSystem = NEW (WaterTracksRenderSystem);
  956. // TheWaterTracksRenderSystem->init();
  957. //create a dummy track
  958. // track=TheWaterTracksRenderObjClassSystem->bindTrack(0);
  959. // track->init(1.5f,8.0f,Vector2(147.0f,67.0f),Vector2(146.9f,68.6f),"wave2.tga");
  960. // track=TheWaterTracksRenderObjClassSystem->bindTrack(0);
  961. // track->init(1.5f,8.0f,Vector2(139.0f,66.0f),Vector2(138.8f,67.6f),"wave2.tga");
  962. }
  963. if (GetAsyncKeyState(VK_F5) & 0x8001) //check if F5 pressed since last call
  964. {
  965. if (trackEditModeReset)
  966. {
  967. if (trackEditMode)
  968. {
  969. UnicodeString string;
  970. string.format(L"Leaving Water Track Edit Mode");
  971. TheInGameUI->message(string);
  972. }
  973. else
  974. {
  975. UnicodeString string;
  976. string.format(L"Entering Water Track Edit Mode");
  977. TheInGameUI->message(string);
  978. string.format(L"Wave Type: %hs",waveTypeInfo[currentWaveType].m_waveTypeName);
  979. TheInGameUI->message(string);
  980. }
  981. trackEditMode ^= 1; //toggle editor on/off
  982. if (trackEditMode == 0)
  983. { //editor was turned off, save changes
  984. haveStart=0;
  985. haveEnd=0;
  986. }
  987. trackEditModeReset=0;
  988. }
  989. }
  990. else
  991. trackEditModeReset=1;
  992. if (trackEditMode)
  993. { //we are in wave edit mode
  994. if (GetCursorPos(&screenPoint)) //read mouse position
  995. {
  996. ScreenToClient( ApplicationHWnd, &screenPoint);
  997. if (GetAsyncKeyState(VK_F6) & 0x8001)
  998. {
  999. if (addPointReset)
  1000. {
  1001. if (!haveStart)
  1002. { mouseAnchor=screenPoint;
  1003. TheTacticalView->screenToTerrain( (ICoord2D *)&screenPoint, &terrainPointStart);
  1004. haveStart=1;
  1005. UnicodeString string;
  1006. string.format(L"Added Start");
  1007. TheInGameUI->message(string);
  1008. }
  1009. else
  1010. {
  1011. endPoint=screenPoint;
  1012. TheTacticalView->screenToTerrain( (ICoord2D *)&screenPoint, &terrainPointEnd);
  1013. haveEnd=1;
  1014. //Have enough info to add a wave now
  1015. track=TheWaterTracksRenderSystem->bindTrack(currentWaveType);
  1016. if (track)
  1017. {// track->init(1.5f*MAP_XY_FACTOR,Vector2(terrainPointStart.x,terrainPointStart.y),Vector2(terrainPointEnd.x,terrainPointEnd.y),"wave256.tga");
  1018. //Generate valid input for the 2 points
  1019. Vector2 startPoint(terrainPointStart.x,terrainPointStart.y);
  1020. Vector2 endPoint(terrainPointEnd.x,terrainPointEnd.y);
  1021. Vector2 midPoint = endPoint - startPoint;
  1022. Vector2 m_perpDir = midPoint;
  1023. m_perpDir.Rotate(1.57079632679f); //get vector perpendicular to wave motion.
  1024. m_perpDir.Normalize();
  1025. midPoint = startPoint + (midPoint)*0.5f;
  1026. Vector2 dirMidPoint = midPoint + m_perpDir;
  1027. track->init(waveTypeInfo[currentWaveType].m_finalHeight,waveTypeInfo[currentWaveType].m_finalWidth,Vector2(midPoint.X,midPoint.Y),Vector2(dirMidPoint.X,dirMidPoint.Y),waveTypeInfo[currentWaveType].m_textureName,0);
  1028. if (waveTypeInfo[currentWaveType].m_secondWaveTimeOffset)
  1029. {
  1030. //Add a second track slightly behind this one
  1031. track2=TheWaterTracksRenderSystem->bindTrack(currentWaveType);
  1032. if (track2)
  1033. {
  1034. track2->init(waveTypeInfo[currentWaveType].m_finalHeight,waveTypeInfo[currentWaveType].m_finalWidth,Vector2(midPoint.X,midPoint.Y),Vector2(dirMidPoint.X,dirMidPoint.Y),waveTypeInfo[currentWaveType].m_textureName,waveTypeInfo[currentWaveType].m_secondWaveTimeOffset);
  1035. }
  1036. }
  1037. UnicodeString string;
  1038. string.format(L"Added End");
  1039. TheInGameUI->message(string);
  1040. }
  1041. haveStart=0; //reset for next segment
  1042. haveEnd=0;
  1043. }
  1044. addPointReset=0;
  1045. }
  1046. }
  1047. else
  1048. addPointReset=1;
  1049. if (GetAsyncKeyState(VK_DELETE) & 0x8001)
  1050. { //delete last segment added
  1051. if (deleteTrackReset && track)
  1052. { deleteTrackReset=0;
  1053. TheWaterTracksRenderSystem->unbindTrack(track);
  1054. if (track2)
  1055. TheWaterTracksRenderSystem->unbindTrack(track2);
  1056. haveStart=0; //reset for next segment
  1057. haveEnd=0;
  1058. track=NULL;
  1059. track2=NULL;
  1060. }
  1061. }
  1062. else
  1063. deleteTrackReset=1;
  1064. if (GetAsyncKeyState(VK_INSERT) & 0x8001)
  1065. { //change current wave type
  1066. if (changeTypeReset)
  1067. { changeTypeReset=0;
  1068. currentWaveType = (waveType)((Int)currentWaveType + 1);
  1069. if (currentWaveType > WaveTypeLast)
  1070. currentWaveType = WaveTypeFirst;
  1071. UnicodeString string;
  1072. string.format(L"Wave Type: %hs",waveTypeInfo[currentWaveType].m_waveTypeName);
  1073. TheInGameUI->message(string);
  1074. }
  1075. }
  1076. else
  1077. changeTypeReset=1;
  1078. if (GetAsyncKeyState(VK_F7) & 0x8001)
  1079. { //save all segments added
  1080. if (saveTracksReset)
  1081. { saveTracksReset=0;
  1082. TheWaterTracksRenderSystem->saveTracks();
  1083. haveStart=0; //reset for next segment
  1084. haveEnd=0;
  1085. track=NULL;
  1086. track2=NULL;
  1087. UnicodeString string;
  1088. string.format(L"Saved Tracks");
  1089. TheInGameUI->message(string);
  1090. }
  1091. }
  1092. else
  1093. saveTracksReset=1;
  1094. if (GetAsyncKeyState(VK_F8) & 0x8001)
  1095. { //load tracks for map
  1096. if (loadTracksReset)
  1097. { loadTracksReset=0;
  1098. TheWaterTracksRenderSystem->reset();
  1099. TheWaterTracksRenderSystem->loadTracks();
  1100. haveStart=0; //reset for next segment
  1101. haveEnd=0;
  1102. track=NULL;
  1103. track2=NULL;
  1104. UnicodeString string;
  1105. string.format(L"Loaded Tracks");
  1106. TheInGameUI->message(string);
  1107. }
  1108. }
  1109. else
  1110. saveTracksReset=1;
  1111. };
  1112. if (haveStart && !haveEnd)
  1113. { //draw a guide line
  1114. // View *tacticalView = TheDisplay->getFirstView();
  1115. // tacticalView->worldToScreen( &m_moveHint[i].pos, &pos );
  1116. TheTacticalView->screenToTerrain( (ICoord2D *)&screenPoint, &terrainPointEnd);
  1117. //Check if point is within correct distance of start
  1118. Real xdiff=terrainPointEnd.x - terrainPointStart.x;
  1119. Real ydiff=terrainPointEnd.y - terrainPointStart.y;
  1120. if (sqrt (xdiff * xdiff + ydiff * ydiff) <= waveTypeInfo[currentWaveType].m_finalWidth)
  1121. { TheDisplay->drawLine(mouseAnchor.x, mouseAnchor.y, screenPoint.x, screenPoint.y,1,0xffccccff);
  1122. DX8Wrapper::Invalidate_Cached_Render_States();
  1123. ShaderClass::Invalidate();
  1124. }
  1125. pauseWaves=TRUE;
  1126. // char buffer[64];
  1127. // sprintf(buffer,"\n%d,%d,%d,%d",mouseAnchor.x, mouseAnchor.y, screenPoint.x, screenPoint.y);
  1128. // OutputDebugString (buffer);
  1129. }
  1130. }
  1131. }