waterPlane.cpp 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "environment/waterPlane.h"
  24. #include "core/util/safeDelete.h"
  25. #include "scene/sceneRenderState.h"
  26. #include "scene/sceneManager.h"
  27. #include "lighting/lightInfo.h"
  28. #include "core/stream/bitStream.h"
  29. #include "math/mathIO.h"
  30. #include "math/mathUtils.h"
  31. #include "console/consoleTypes.h"
  32. #include "gui/3d/guiTSControl.h"
  33. #include "gfx/primBuilder.h"
  34. #include "gfx/gfxTransformSaver.h"
  35. #include "gfx/gfxDebugEvent.h"
  36. #include "gfx/gfxOcclusionQuery.h"
  37. #include "renderInstance/renderPassManager.h"
  38. #include "sim/netConnection.h"
  39. #include "scene/reflectionManager.h"
  40. #include "ts/tsShapeInstance.h"
  41. #include "T3D/gameFunctions.h"
  42. #include "postFx/postEffect.h"
  43. #include "math/util/matrixSet.h"
  44. extern ColorI gCanvasClearColor;
  45. #define BLEND_TEX_SIZE 256
  46. #define V_SHADER_PARAM_OFFSET 50
  47. IMPLEMENT_CO_NETOBJECT_V1(WaterPlane);
  48. ConsoleDocClass( WaterPlane,
  49. "@brief Represents a large body of water stretching to the horizon in all directions.\n\n"
  50. "WaterPlane's position is defined only height, the z element of position, "
  51. "it is infinite in xy and depth. %WaterPlane is designed to represent the "
  52. "ocean on an island scene and viewed from ground level; other uses may not "
  53. "be appropriate and a WaterBlock may be used.\n\n"
  54. "@see WaterObject for inherited functionality.\n\n"
  55. "Limitations:\n\n"
  56. "Because %WaterPlane cannot be projected exactly to the far-clip distance, "
  57. "other objects nearing this distance can have noticible artifacts as they "
  58. "clip through first the %WaterPlane and then the far plane.\n\n"
  59. "To avoid this large objects should be positioned such that they will not line up with "
  60. "the far-clip from vantage points the player is expected to be. In particular, "
  61. "your TerrainBlock should be completely contained by the far-clip distance.\n\n"
  62. "Viewing %WaterPlane from a high altitude with a tight far-clip distance "
  63. "will accentuate this limitation. %WaterPlane is primarily designed to "
  64. "be viewed from ground level.\n\n"
  65. "@ingroup Water"
  66. );
  67. WaterPlane::WaterPlane()
  68. {
  69. mGridElementSize = 1.0f;
  70. mGridSize = 101;
  71. mGridSizeMinusOne = mGridSize - 1;
  72. mNetFlags.set(Ghostable | ScopeAlways);
  73. mVertCount = 0;
  74. mIndxCount = 0;
  75. mPrimCount = 0;
  76. }
  77. WaterPlane::~WaterPlane()
  78. {
  79. }
  80. bool WaterPlane::onAdd()
  81. {
  82. if ( !Parent::onAdd() )
  83. return false;
  84. setGlobalBounds();
  85. resetWorldBox();
  86. addToScene();
  87. mWaterFogData.plane.set( 0, 0, 1, -getPosition().z );
  88. return true;
  89. }
  90. void WaterPlane::onRemove()
  91. {
  92. removeFromScene();
  93. Parent::onRemove();
  94. }
  95. void WaterPlane::initPersistFields()
  96. {
  97. addGroup( "WaterPlane" );
  98. addProtectedField( "gridSize", TypeS32, Offset( mGridSize, WaterPlane ), &protectedSetGridSize, &defaultProtectedGetFn,
  99. "Spacing between vertices in the WaterBlock mesh" );
  100. addProtectedField( "gridElementSize", TypeF32, Offset( mGridElementSize, WaterPlane ), &protectedSetGridElementSize, &defaultProtectedGetFn,
  101. "Duplicate of gridElementSize for backwards compatility");
  102. endGroup( "WaterPlane" );
  103. Parent::initPersistFields();
  104. removeField( "rotation" );
  105. removeField( "scale" );
  106. }
  107. U32 WaterPlane::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
  108. {
  109. U32 retMask = Parent::packUpdate(con, mask, stream);
  110. stream->write( mGridSize );
  111. stream->write( mGridElementSize );
  112. if ( stream->writeFlag( mask & UpdateMask ) )
  113. {
  114. stream->write( getPosition().z );
  115. }
  116. return retMask;
  117. }
  118. void WaterPlane::unpackUpdate(NetConnection* con, BitStream* stream)
  119. {
  120. Parent::unpackUpdate(con, stream);
  121. U32 inGridSize;
  122. stream->read( &inGridSize );
  123. setGridSize( inGridSize );
  124. F32 inGridElementSize;
  125. stream->read( &inGridElementSize );
  126. setGridElementSize( inGridElementSize );
  127. if( stream->readFlag() ) // UpdateMask
  128. {
  129. F32 posZ;
  130. stream->read( &posZ );
  131. Point3F newPos = getPosition();
  132. newPos.z = posZ;
  133. setPosition( newPos );
  134. }
  135. }
  136. void WaterPlane::setupVBIB( SceneRenderState *state )
  137. {
  138. const Frustum &frustum = state->getCullingFrustum();
  139. // Water base-color, assigned as color for all verts.
  140. const GFXVertexColor vertCol(mWaterFogData.color);
  141. // World-Up vector, assigned as normal for all verts.
  142. const Point3F worldUp( 0.0f, 0.0f, 1.0f );
  143. // World-unit size of a grid cell.
  144. const F32 squareSize = mGridElementSize;
  145. // Column/Row count.
  146. // So we don't neet to access class-specific member variables
  147. // in the code below.
  148. const U32 gridSize = mGridSize;
  149. // Number of verts in one column / row
  150. const U32 gridStride = gridSize + 1;
  151. // Grid is filled in this order...
  152. // Ex. Grid with gridSize of 2.
  153. //
  154. // Letters are cells.
  155. // Numbers are verts, enumerated in their order within the vert buffer.
  156. //
  157. // 6 7 8
  158. // (c) (d)
  159. // 3 4 5
  160. // (a) (b)
  161. // 0 1 2
  162. //
  163. // Note...
  164. // Camera would be positioned at vert 4 ( in this particular grid not a constant ).
  165. // Positive Y points UP the diagram ( verts 0, 3, 6 ).
  166. // Positive X points RIGHT across the diagram ( verts 0, 1, 2 ).
  167. // Length of a grid row/column divided by two.
  168. F32 gridSideHalfLen = squareSize * gridSize * 0.5f;
  169. // Position of the first vertex in the grid.
  170. // Relative to the camera this is the "Back Left" corner vert.
  171. const Point3F cornerPosition( -gridSideHalfLen, -gridSideHalfLen, 0.0f );
  172. // Number of verts in the grid centered on the camera.
  173. const U32 gridVertCount = gridStride * gridStride;
  174. // Number of verts surrounding the grid, projected by the frustum.
  175. const U32 borderVertCount = gridSize * 4;
  176. // Number of verts in the front-most row which are raised to the horizon.
  177. const U32 horizonVertCount = gridStride;
  178. // Total number of verts. Calculation explained above.
  179. mVertCount = gridVertCount + borderVertCount + horizonVertCount;
  180. // Fill the vertex buffer...
  181. mVertBuff.set( GFX, mVertCount, GFXBufferTypeStatic );
  182. GFXWaterVertex *vertPtr = mVertBuff.lock();
  183. // Fill verts in the camera centered grid...
  184. // Temorary storage for calculation of vert position.
  185. F32 xVal, yVal;
  186. for ( U32 i = 0; i < gridStride; i++ )
  187. {
  188. yVal = cornerPosition.y + (F32)( i * squareSize );
  189. for ( U32 j = 0; j < gridStride; j++ )
  190. {
  191. xVal = cornerPosition.x + (F32)( j * squareSize );
  192. vertPtr->point.set( xVal, yVal, 0.0f );
  193. vertPtr->color = vertCol;
  194. vertPtr->normal = worldUp;
  195. vertPtr->undulateData.set( xVal, yVal );
  196. vertPtr->horizonFactor.set( 0, 0, 0, 0 );
  197. vertPtr++;
  198. }
  199. }
  200. // Fill in 'border' verts, surrounding the grid, projected by the frustum.
  201. // Ex. Grid with gridSize of 2.
  202. //
  203. // Letters in parenthesis are cells.
  204. // x's are grid-verts ( we have already filled ).
  205. // Numbers are border verts, enumerated in their order within the vert buffer.
  206. //
  207. // Lines connecting verts explained in the code below.
  208. //
  209. // Front
  210. //
  211. // L 0------1 2 R
  212. // e x x x | i
  213. // f (c) (d) | g
  214. // t 7 x x x 3 h
  215. // | (a) (b) t
  216. // | x x x
  217. // 6 5------4
  218. //
  219. // Back
  220. //
  221. // As in previous diagram...
  222. // Camera would be positioned at vert 4 ( in this particular grid not a constant ).
  223. // Positive Y points UP the diagram ( verts 6, 7, 0 ).
  224. // Positive X points RIGHT across the diagram ( verts 0, 1, 2 ).
  225. // Iterator i is looping through the 4 'sides' of the grid.
  226. // Inner loop ( using iterator j ) will fill in a number of verts
  227. // where that count is 'gridSize'.
  228. //
  229. //
  230. // Ex. Given the grid with gridSize of 2 diagramed above,
  231. // Outer loop iterates through: Front, Right, Back, Left
  232. // Inner loop fills 2 verts per iteration of the outer loop: { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }
  233. // Grid-space vectors indexed by 'side'.
  234. // Each vector describes the direction we iterate when
  235. // filling in verts ( mathematically the tangent ).
  236. const Point2F sBorderTangentVec [4] = {
  237. Point2F( 1, 0 ), // Front ( 0 )
  238. Point2F( 0, -1 ), // Right ( 1 )
  239. Point2F( -1, 0 ), // Back ( 2 )
  240. Point2F( 0, 1 ) // Left ( 3 )
  241. };
  242. // Normalized positions indexed by 'side'
  243. // Defines the 'start' position of each side, eg. the position of the first vert.
  244. // See Diagram below.
  245. const Point2F sBorderStartPos [4] = {
  246. Point2F( -1, 1 ), // Front ( 0 )
  247. Point2F( 1, 1 ), // Right ( 1 )
  248. Point2F( 1, -1 ), // Back ( 2 )
  249. Point2F( -1, -1 ) // Left ( 3 )
  250. };
  251. // Diagram of Start vert position per Side.
  252. //
  253. // Labeling convention for verts is 'As' where A is the first letter of
  254. // that side's descriptive name and lower-case s indicates 'start'.
  255. //
  256. //
  257. //
  258. // Front
  259. // (-1,1)
  260. // Fs------o-----Rs(1,1)R
  261. // | | i
  262. // | | g
  263. // o (0,0) o h
  264. // | | t
  265. // | |
  266. // L(-1,-1)Ls------o-----Bs
  267. // e (1,-1)
  268. // f Back
  269. // t
  270. // Calculate the world-space dimension of the border-vert-ring...
  271. // Diagram shows overall layout of the WaterPlane with a gridSize of 1,
  272. // with all 'quads' enumerated.
  273. // center-grid ( 1 ), border ( 2, 3, 4, 5 ), and horizon ( 6 ).
  274. //
  275. //
  276. // x------------x
  277. // \ 6 \ <- horizon quad is really 'above' the front border
  278. // x --------- x not in front of it
  279. // | \ 2 / |
  280. // | x---- x |
  281. // | | | |
  282. // | 5| 1 |3 |
  283. // | x --- x |
  284. // | / 4 \|
  285. // x------------x
  286. // WaterPlane renders relative to the camera rotation around z and xy position.
  287. //
  288. // That is, it rotates around the z-up axis with the camera such that the
  289. // camera is always facing towards the front border unless looking straight
  290. // down or up.
  291. //
  292. // Also note that the horizon verts are pulled straight up from the front
  293. // border verts.
  294. //
  295. // Therefore...
  296. //
  297. // The front border must be as close to the farclip plane as possible
  298. // so distant objects clip through the horizon and farplane at the same time.
  299. //
  300. // The left and right borders must be pulled outward a distance such
  301. // that water extends horizontally across the entire viewable area while
  302. // looking straight forward +y or straight down -z.
  303. //
  304. //
  305. const F32 farDistScale = 0.99f;
  306. //
  307. F32 farDist = frustum.getFarDist() * farDistScale;
  308. //
  309. F32 farWidth = (F32)state->getViewport().extent.x * farDist / state->getWorldToScreenScale().x;
  310. Point2F borderExtents( farWidth * 2.0f, farDist * 2.0f );
  311. Point2F borderHalfExtents( farWidth, farDist );
  312. Point2F borderDir;
  313. Point2F borderStart;
  314. for ( U32 i = 0; i < 4; i++ )
  315. {
  316. borderDir = sBorderTangentVec[i];
  317. borderStart = sBorderStartPos[i];
  318. for ( U32 j = 0; j < gridSize; j++ )
  319. {
  320. F32 frac = (F32)j / (F32)gridSize;
  321. Point2F pos( borderStart * borderHalfExtents );
  322. pos += borderDir * borderExtents * frac;
  323. vertPtr->point.set( pos.x, pos.y, 0.0f );
  324. vertPtr->undulateData.set( pos.x, pos.y );
  325. vertPtr->horizonFactor.set( 0, 0, 0, 0 );
  326. vertPtr->color = vertCol;
  327. vertPtr->normal = worldUp;
  328. vertPtr++;
  329. }
  330. }
  331. // Fill in row of horizion verts.
  332. // Verts are positioned identical to the front border, but will be
  333. // manipulated in z within the shader.
  334. //
  335. // Z position of 50.0f is unimportant unless you want to disable
  336. // shader manipulation and render in wireframe for debugging.
  337. for ( U32 i = 0; i < gridStride; i++ )
  338. {
  339. F32 frac = (F32)i / (F32)gridSize;
  340. Point2F pos( sBorderStartPos[0] * borderHalfExtents );
  341. pos += sBorderTangentVec[0] * borderExtents * frac;
  342. vertPtr->point.set( pos.x, pos.y, 50.0f );
  343. vertPtr->undulateData.set( pos.x, pos.y );
  344. vertPtr->horizonFactor.set( 1, 0, 0, 0 );
  345. vertPtr->color = vertCol;
  346. vertPtr->normal = worldUp;
  347. vertPtr++;
  348. }
  349. mVertBuff.unlock();
  350. // Fill in the PrimitiveBuffer...
  351. // 2 triangles per cell/quad
  352. const U32 gridTriCount = gridSize * gridSize * 2;
  353. // 4 sides, mGridSize quads per side, 2 triangles per quad
  354. const U32 borderTriCount = 4 * gridSize * 2;
  355. // 1 quad per gridSize, 2 triangles per quad
  356. // i.e. an extra row of 'cells' leading the front side of the grid
  357. const U32 horizonTriCount = gridSize * 2;
  358. mPrimCount = gridTriCount + borderTriCount + horizonTriCount;
  359. // 3 indices per triangle.
  360. mIndxCount = mPrimCount * 3;
  361. mPrimBuff.set( GFX, mIndxCount, mPrimCount, GFXBufferTypeStatic );
  362. U16 *idxPtr;
  363. mPrimBuff.lock(&idxPtr);
  364. // Temporaries to hold indices for the corner points of a quad.
  365. U32 p00, p01, p11, p10;
  366. U32 offset = 0;
  367. // Given a single cell of the grid diagramed below,
  368. // quad indice variables are in this orientation.
  369. //
  370. // p01 --- p11
  371. // | |
  372. // | |
  373. // p00 --- p10
  374. //
  375. // Positive Y points UP the diagram ( p00, p01 ).
  376. // Positive X points RIGHT across the diagram ( p00, p10 )
  377. //
  378. // i iterates bottom to top "column-wise"
  379. for ( U32 i = 0; i < mGridSize; i++ )
  380. {
  381. // j iterates left to right "row-wise"
  382. for ( U32 j = 0; j < mGridSize; j++ )
  383. {
  384. // where (j,i) is a particular cell.
  385. p00 = offset;
  386. p10 = offset + 1;
  387. p01 = offset + gridStride;
  388. p11 = offset + 1 + gridStride;
  389. // Top Left Triangle
  390. *idxPtr = p00;
  391. idxPtr++;
  392. *idxPtr = p01;
  393. idxPtr++;
  394. *idxPtr = p11;
  395. idxPtr++;
  396. // Bottom Right Triangle
  397. *idxPtr = p00;
  398. idxPtr++;
  399. *idxPtr = p11;
  400. idxPtr++;
  401. *idxPtr = p10;
  402. idxPtr++;
  403. offset += 1;
  404. }
  405. offset += 1;
  406. }
  407. // Fill border indices...
  408. // Given a grid size of 1,
  409. // the grid / border verts are in the vertex buffer in this order.
  410. //
  411. //
  412. // 4 5
  413. // 2 --- 3
  414. // | |
  415. // | |
  416. // 0 --- 1
  417. // 7 6
  418. //
  419. // Positive Y points UP the diagram ( p00, p01 ).
  420. // Positive X points RIGHT across the diagram ( p00, p10 )
  421. //
  422. // Note we duplicate the first border vert ( 4 ) since it is also the last
  423. // and this makes our loop easier.
  424. const U32 sBorderStartVert [4] = {
  425. gridStride * gridSize, // Index to the Top-Left grid vert.
  426. gridStride * gridSize + gridSize, // Index to the Top-Right grid vert.
  427. gridSize, // Index to the Bottom-Right grid vert.
  428. 0, // Index to the Bottom-Left grid vert.
  429. };
  430. const S32 sBorderStepSize [4] = {
  431. // Step size to the next grid vert along the specified side....
  432. 1, // Top
  433. -(S32)gridStride, // Right
  434. -1, // Bottom
  435. gridStride, // Left
  436. };
  437. const U32 firstBorderVert = gridStride * gridSize + gridStride;
  438. const U32 lastBorderVert = firstBorderVert + ( borderVertCount - 1 );
  439. U32 startBorderVert = firstBorderVert;
  440. U32 startGridVert;
  441. U32 curStepSize;
  442. for ( U32 i = 0; i < 4; i++ )
  443. {
  444. startGridVert = sBorderStartVert[i];
  445. curStepSize = sBorderStepSize[i];
  446. for ( U32 j = 0; j < gridSize; j++ )
  447. {
  448. // Each border cell is 1 quad, 2 triangles.
  449. p00 = startGridVert;
  450. p10 = startGridVert + curStepSize;
  451. p01 = startBorderVert;
  452. p11 = startBorderVert + 1;
  453. if ( p11 > lastBorderVert )
  454. p11 = firstBorderVert;
  455. // Top Left Triangle
  456. *idxPtr = p00;
  457. idxPtr++;
  458. *idxPtr = p01;
  459. idxPtr++;
  460. *idxPtr = p11;
  461. idxPtr++;
  462. // Bottom Right Triangle
  463. *idxPtr = p00;
  464. idxPtr++;
  465. *idxPtr = p11;
  466. idxPtr++;
  467. *idxPtr = p10;
  468. idxPtr++;
  469. startBorderVert++;
  470. startGridVert += curStepSize;
  471. }
  472. }
  473. // Fill in 'horizon' triangles.
  474. U32 curHorizonVert = lastBorderVert + 1;
  475. U32 curBorderVert = firstBorderVert;
  476. for ( U32 i = 0; i < gridSize; i++ )
  477. {
  478. p00 = curBorderVert;
  479. p10 = curBorderVert + 1;
  480. p01 = curHorizonVert;
  481. p11 = curHorizonVert + 1;
  482. // Top Left Triangle
  483. *idxPtr = p00;
  484. idxPtr++;
  485. *idxPtr = p01;
  486. idxPtr++;
  487. *idxPtr = p11;
  488. idxPtr++;
  489. // Bottom Right Triangle
  490. *idxPtr = p00;
  491. idxPtr++;
  492. *idxPtr = p11;
  493. idxPtr++;
  494. *idxPtr = p10;
  495. idxPtr++;
  496. curBorderVert++;
  497. curHorizonVert++;
  498. }
  499. mPrimBuff.unlock();
  500. }
  501. SceneData WaterPlane::setupSceneGraphInfo( SceneRenderState *state )
  502. {
  503. SceneData sgData;
  504. sgData.lights[0] = LIGHTMGR->getSpecialLight( LightManager::slSunLightType );
  505. // fill in water's transform
  506. sgData.objTrans = &getRenderTransform();
  507. // fog
  508. sgData.setFogParams( state->getSceneManager()->getFogData() );
  509. // misc
  510. sgData.backBuffTex = REFLECTMGR->getRefractTex();
  511. sgData.reflectTex = mPlaneReflector.reflectTex;
  512. sgData.wireframe = GFXDevice::getWireframe() || smWireframe;
  513. return sgData;
  514. }
  515. void WaterPlane::setShaderParams( SceneRenderState *state, BaseMatInstance* mat, const WaterMatParams& paramHandles)
  516. {
  517. // Set variables that will be assigned to shader consts within WaterCommon
  518. // before calling Parent::setShaderParams
  519. mUndulateMaxDist = mGridElementSize * mGridSizeMinusOne * 0.5f;
  520. Parent::setShaderParams( state, mat, paramHandles );
  521. // Now set the rest of the shader consts that are either unique to this
  522. // class or that WaterObject leaves to us to handle...
  523. MaterialParameters* matParams = mat->getMaterialParameters();
  524. // set vertex shader constants
  525. //-----------------------------------
  526. matParams->setSafe(paramHandles.mGridElementSizeSC, (F32)mGridElementSize);
  527. //matParams->setSafe( paramHandles.mReflectTexSizeSC, mReflectTexSize );
  528. if ( paramHandles.mModelMatSC->isValid() )
  529. matParams->set(paramHandles.mModelMatSC, getRenderTransform(), GFXSCT_Float4x4);
  530. // set pixel shader constants
  531. //-----------------------------------
  532. ColorF c( mWaterFogData.color );
  533. matParams->setSafe( paramHandles.mBaseColorSC, c );
  534. // By default we need to show a true reflection is fullReflect is enabled and
  535. // we are above water.
  536. F32 reflect = mPlaneReflector.isEnabled() && !isUnderwater( state->getCameraPosition() );
  537. // If we were occluded the last frame a query was fetched ( not necessarily last frame )
  538. // and we weren't updated last frame... we don't have a valid texture to show
  539. // so use the cubemap / fake reflection color this frame.
  540. if ( mPlaneReflector.lastUpdateMs != REFLECTMGR->getLastUpdateMs() && mPlaneReflector.isOccluded() )
  541. reflect = false;
  542. //Point4F reflectParams( getRenderPosition().z, mReflectMinDist, mReflectMaxDist, reflect );
  543. Point4F reflectParams( getRenderPosition().z, 0.0f, 1000.0f, !reflect );
  544. // TODO: This is a hack... why is this broken... check after
  545. // we merge advanced lighting with trunk!
  546. //
  547. reflectParams.z = 0.0f;
  548. matParams->setSafe( paramHandles.mReflectParamsSC, reflectParams );
  549. VectorF reflectNorm( 0, 0, 1 );
  550. matParams->setSafe(paramHandles.mReflectNormalSC, reflectNorm );
  551. }
  552. void WaterPlane::prepRenderImage( SceneRenderState *state )
  553. {
  554. PROFILE_SCOPE(WaterPlane_prepRenderImage);
  555. if( !state->isDiffusePass() )
  556. return;
  557. mBasicLighting = dStricmp( LIGHTMGR->getId(), "BLM" ) == 0;
  558. mUnderwater = isUnderwater( state->getCameraPosition() );
  559. mMatrixSet->setSceneView(GFX->getWorldMatrix());
  560. const Frustum &frustum = state->getCameraFrustum();
  561. if ( mPrimBuff.isNull() ||
  562. mGenerateVB ||
  563. frustum != mFrustum )
  564. {
  565. mFrustum = frustum;
  566. setupVBIB( state );
  567. mGenerateVB = false;
  568. MatrixF proj( true );
  569. MathUtils::getZBiasProjectionMatrix( 0.0001f, mFrustum, &proj );
  570. mMatrixSet->setSceneProjection(proj);
  571. }
  572. _getWaterPlane( state->getCameraPosition(), mWaterPlane, mWaterPos );
  573. mWaterFogData.plane = mWaterPlane;
  574. mPlaneReflector.refplane = mWaterPlane;
  575. updateUnderwaterEffect( state );
  576. ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
  577. ri->renderDelegate.bind( this, &WaterObject::renderObject );
  578. ri->type = RenderPassManager::RIT_Water;
  579. state->getRenderPass()->addInst( ri );
  580. //mRenderUpdateCount++;
  581. }
  582. void WaterPlane::innerRender( SceneRenderState *state )
  583. {
  584. GFXDEBUGEVENT_SCOPE( WaterPlane_innerRender, ColorI( 255, 0, 0 ) );
  585. const Point3F &camPosition = state->getCameraPosition();
  586. Point3F rvec, fvec, uvec, pos;
  587. const MatrixF &objMat = getTransform(); //getRenderTransform();
  588. const MatrixF &camMat = state->getCameraTransform();
  589. MatrixF renderMat( true );
  590. camMat.getColumn( 1, &fvec );
  591. uvec.set( 0, 0, 1 );
  592. rvec = mCross( fvec, uvec );
  593. rvec.normalize();
  594. fvec = mCross( uvec, rvec );
  595. pos = camPosition;
  596. pos.z = objMat.getPosition().z;
  597. renderMat.setColumn( 0, rvec );
  598. renderMat.setColumn( 1, fvec );
  599. renderMat.setColumn( 2, uvec );
  600. renderMat.setColumn( 3, pos );
  601. setRenderTransform( renderMat );
  602. // Setup SceneData
  603. SceneData sgData = setupSceneGraphInfo( state );
  604. // set the material
  605. S32 matIdx = getMaterialIndex( camPosition );
  606. if ( !initMaterial( matIdx ) )
  607. return;
  608. BaseMatInstance *mat = mMatInstances[matIdx];
  609. WaterMatParams matParams = mMatParamHandles[matIdx];
  610. // render the geometry
  611. if ( mat )
  612. {
  613. // setup proj/world transform
  614. mMatrixSet->restoreSceneViewProjection();
  615. mMatrixSet->setWorld(getRenderTransform());
  616. setShaderParams( state, mat, matParams );
  617. while( mat->setupPass( state, sgData ) )
  618. {
  619. mat->setSceneInfo(state, sgData);
  620. mat->setTransforms(*mMatrixSet, state);
  621. setCustomTextures( matIdx, mat->getCurPass(), matParams );
  622. // set vert/prim buffer
  623. GFX->setVertexBuffer( mVertBuff );
  624. GFX->setPrimitiveBuffer( mPrimBuff );
  625. GFX->drawIndexedPrimitive( GFXTriangleList, 0, 0, mVertCount, 0, mPrimCount );
  626. }
  627. }
  628. }
  629. bool WaterPlane::isUnderwater( const Point3F &pnt ) const
  630. {
  631. F32 height = getPosition().z;
  632. F32 diff = pnt.z - height;
  633. return ( diff < 0.1 );
  634. }
  635. F32 WaterPlane::distanceTo( const Point3F& point ) const
  636. {
  637. if( isUnderwater( point ) )
  638. return 0.f;
  639. else
  640. return ( point.z - getPosition().z );
  641. }
  642. bool WaterPlane::buildPolyList( PolyListContext context, AbstractPolyList* polyList, const Box3F& box, const SphereF& )
  643. {
  644. if(context == PLC_Navigation)
  645. {
  646. polyList->setObject( this );
  647. polyList->setTransform( &MatrixF::Identity, Point3F( 1.0f, 1.0f, 1.0f ) );
  648. F32 z = getPosition().z;
  649. Point3F
  650. p0(box.minExtents.x, box.maxExtents.y, z),
  651. p1(box.maxExtents.x, box.maxExtents.y, z),
  652. p2(box.maxExtents.x, box.minExtents.y, z),
  653. p3(box.minExtents.x, box.minExtents.y, z);
  654. // Add vertices to poly list.
  655. U32 v0 = polyList->addPoint(p0);
  656. polyList->addPoint(p1);
  657. polyList->addPoint(p2);
  658. polyList->addPoint(p3);
  659. // Add plane between first three vertices.
  660. polyList->begin(0, 0);
  661. polyList->vertex(v0);
  662. polyList->vertex(v0+1);
  663. polyList->vertex(v0+2);
  664. polyList->plane(v0, v0+1, v0+2);
  665. polyList->end();
  666. // Add plane between last three vertices.
  667. polyList->begin(0, 1);
  668. polyList->vertex(v0+2);
  669. polyList->vertex(v0+3);
  670. polyList->vertex(v0);
  671. polyList->plane(v0+2, v0+3, v0);
  672. polyList->end();
  673. return true;
  674. }
  675. return false;
  676. }
  677. void WaterPlane::inspectPostApply()
  678. {
  679. Parent::inspectPostApply();
  680. setMaskBits( UpdateMask );
  681. }
  682. void WaterPlane::setTransform( const MatrixF &mat )
  683. {
  684. // We only accept the z value from the new transform.
  685. MatrixF newMat( true );
  686. Point3F newPos = getPosition();
  687. newPos.z = mat.getPosition().z;
  688. newMat.setPosition( newPos );
  689. Parent::setTransform( newMat );
  690. // Parent::setTransforms ends up setting our worldBox to something other than
  691. // global, so we have to set it back... but we can't actually call setGlobalBounds
  692. // again because it does extra work adding and removing us from the container.
  693. mGlobalBounds = true;
  694. mObjBox.minExtents.set(-1e10, -1e10, -1e10);
  695. mObjBox.maxExtents.set( 1e10, 1e10, 1e10);
  696. // Keep mWaterPlane up to date.
  697. mWaterFogData.plane.set( 0, 0, 1, -getPosition().z );
  698. }
  699. void WaterPlane::onStaticModified( const char* slotName, const char*newValue )
  700. {
  701. Parent::onStaticModified( slotName, newValue );
  702. if ( dStricmp( slotName, "surfMaterial" ) == 0 )
  703. setMaskBits( MaterialMask );
  704. }
  705. bool WaterPlane::castRay(const Point3F& start, const Point3F& end, RayInfo* info )
  706. {
  707. // Simply look for the hit on the water plane
  708. // and ignore any future issues with waves, etc.
  709. const Point3F norm(0,0,1);
  710. PlaneF plane( Point3F::Zero, norm );
  711. F32 hit = plane.intersect( start, end );
  712. if ( hit < 0.0f || hit > 1.0f )
  713. return false;
  714. info->t = hit;
  715. info->object = this;
  716. info->point = start + ( ( end - start ) * hit );
  717. info->normal = norm;
  718. info->material = mMatInstances[ WaterMat ];
  719. return true;
  720. }
  721. F32 WaterPlane::getWaterCoverage( const Box3F &testBox ) const
  722. {
  723. F32 posZ = getPosition().z;
  724. F32 coverage = 0.0f;
  725. if ( posZ > testBox.minExtents.z )
  726. {
  727. if ( posZ < testBox.maxExtents.z )
  728. coverage = (posZ - testBox.minExtents.z) / (testBox.maxExtents.z - testBox.minExtents.z);
  729. else
  730. coverage = 1.0f;
  731. }
  732. return coverage;
  733. }
  734. F32 WaterPlane::getSurfaceHeight( const Point2F &pos ) const
  735. {
  736. return getPosition().z;
  737. }
  738. void WaterPlane::onReflectionInfoChanged()
  739. {
  740. /*
  741. if ( isClientObject() && GFX->getPixelShaderVersion() >= 1.4 )
  742. {
  743. if ( mFullReflect )
  744. REFLECTMGR->registerObject( this, ReflectDelegate( this, &WaterPlane::updateReflection ), mReflectPriority, mReflectMaxRateMs, mReflectMaxDist );
  745. else
  746. {
  747. REFLECTMGR->unregisterObject( this );
  748. mReflectTex = NULL;
  749. }
  750. }
  751. */
  752. }
  753. void WaterPlane::setGridSize( U32 inSize )
  754. {
  755. if ( inSize == mGridSize )
  756. return;
  757. // GridSize must be an odd number.
  758. //if ( inSize % 2 == 0 )
  759. // inSize++;
  760. // GridSize must be at least 1
  761. inSize = getMax( inSize, (U32)1 );
  762. mGridSize = inSize;
  763. mGridSizeMinusOne = mGridSize - 1;
  764. mGenerateVB = true;
  765. setMaskBits( UpdateMask );
  766. }
  767. void WaterPlane::setGridElementSize( F32 inSize )
  768. {
  769. if ( inSize == mGridElementSize )
  770. return;
  771. // GridElementSize must be greater than 0
  772. inSize = getMax( inSize, 0.0001f );
  773. mGridElementSize = inSize;
  774. mGenerateVB = true;
  775. setMaskBits( UpdateMask );
  776. }
  777. bool WaterPlane::protectedSetGridSize( void *obj, const char *index, const char *data )
  778. {
  779. WaterPlane *object = static_cast<WaterPlane*>(obj);
  780. S32 size = dAtoi( data );
  781. object->setGridSize( size );
  782. // We already set the field.
  783. return false;
  784. }
  785. bool WaterPlane::protectedSetGridElementSize( void *obj, const char *index, const char *data )
  786. {
  787. WaterPlane *object = static_cast<WaterPlane*>(obj);
  788. F32 size = dAtof( data );
  789. object->setGridElementSize( size );
  790. // We already set the field.
  791. return false;
  792. }
  793. void WaterPlane::_getWaterPlane( const Point3F &camPos, PlaneF &outPlane, Point3F &outPos )
  794. {
  795. outPos = getPosition();
  796. outPlane.set( outPos, Point3F(0,0,1) );
  797. }