waterPlane.cpp 29 KB

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