W3DWaterTracks.cpp 44 KB

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