Rigs of Rods 2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
ProjectedGrid.cpp
Go to the documentation of this file.
1/*
2--------------------------------------------------------------------------------
3This source file is part of Hydrax.
4Visit ---
5
6Copyright (C) 2008 Xavier Vergu�n Gonz�lez <xavierverguin@hotmail.com>
7 <xavyiy@gmail.com>
8
9This program is free software; you can redistribute it and/or modify it under
10the terms of the GNU Lesser General Public License as published by the Free Software
11Foundation; either version 2 of the License, or (at your option) any later
12version.
13
14This program is distributed in the hope that it will be useful, but WITHOUT
15ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17
18You should have received a copy of the GNU Lesser General Public License along with
19this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21http://www.gnu.org/copyleft/lesser.txt.
22--------------------------------------------------------------------------------
23
24Based on the Projected Grid concept from Claes Johanson thesis:
25http://graphics.cs.lth.se/theses/projects/projgrid/
26and Ren Cheng Ogre3D implementation:
27http://www.cnblogs.com/ArenAK/archive/2007/11/07/951713.html
28--------------------------------------------------------------------------------
29*/
30
31#include <ProjectedGrid.h>
32
33#define _def_MaxFarClipDistance 99999
34
35namespace Hydrax{namespace Module
36{
38 {
39 if (NormalMode == MaterialManager::NM_VERTEX)
40 {
41 return Mesh::VT_POS_NORM;
42 }
43
44 // NM_RTT
45 return Mesh::VT_POS;
46 }
47
49 {
50 if (NormalMode == MaterialManager::NM_VERTEX)
51 {
52 return "Vertex";
53 }
54
55 return "Rtt";
56 }
57
58 ProjectedGrid::ProjectedGrid(Hydrax *h, Noise::Noise *n, const Ogre::Plane &BasePlane, const MaterialManager::NormalMode& NormalMode)
59 : Module("ProjectedGrid" + _PG_getNormalModeString(NormalMode),
60 n, Mesh::Options(256, Size(0), _PG_getVertexTypeFromNormalMode(NormalMode)), NormalMode)
61 , mHydrax(h)
62 , mVertices(0)
63 , mVerticesChoppyBuffer(0)
64 , mBasePlane(BasePlane)
65 , mNormal(BasePlane.normal)
66 , mPos(Ogre::Vector3(0,0,0))
67 , mProjectingCamera(0)
68 , mTmpRndrngCamera(0)
69 , mRenderingCamera(h->getCamera())
70 {
71 }
72
73 ProjectedGrid::ProjectedGrid(Hydrax *h, Noise::Noise *n, const Ogre::Plane &BasePlane, const MaterialManager::NormalMode& NormalMode, const Options &Options)
74 : Module("ProjectedGrid" + _PG_getNormalModeString(NormalMode),
75 n, Mesh::Options(Options.Complexity, Size(0), _PG_getVertexTypeFromNormalMode(NormalMode)), NormalMode)
76 , mHydrax(h)
77 , mVertices(0)
78 , mVerticesChoppyBuffer(0)
79 , mBasePlane(BasePlane)
80 , mNormal(BasePlane.normal)
81 , mPos(Ogre::Vector3(0,0,0))
82 , mProjectingCamera(0)
83 , mTmpRndrngCamera(0)
84 , mRenderingCamera(h->getCamera())
85 {
87 }
88
90 {
91 remove();
92
93 HydraxLOG(getName() + " destroyed.");
94 }
95
97 {
98 // Size(0) -> Infinite mesh
102
105
106 // Re-create geometry if it's needed
108 {
109 remove();
111 create();
112
114 {
116 {
117 HydraxLOG(mNoise->getName() + " doesn't support GPU Normal map generation.");
118 }
119 }
120
121 Ogre::String MaterialNameTmp = mHydrax->getMesh()->getMaterialName();
122 mHydrax->getMesh()->remove();
124 mHydrax->getMesh()->setMaterialName(MaterialNameTmp);
125 mHydrax->getMesh()->create();
126
127 // Force to recalculate the geometry on next frame
128 mLastPosition = Ogre::Vector3(0,0,0);
129 mLastOrientation = Ogre::Quaternion();
130
131 return;
132 }
133
135 }
136
138 {
139 HydraxLOG("Creating " + getName() + " module.");
140
142
144 {
146
147 Mesh::POS_NORM_VERTEX* Vertices = static_cast<Mesh::POS_NORM_VERTEX*>(mVertices);
148
149 for (int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++)
150 {
151 Vertices[i].nx = 0;
152 Vertices[i].ny = -1;
153 Vertices[i].nz = 0;
154 }
155
157 }
159 {
161 }
162
164
165 mTmpRndrngCamera = new Ogre::Camera("PG_TmpRndrngCamera", NULL);
166 mProjectingCamera = new Ogre::Camera("PG_ProjectingCamera", NULL);
167
168 HydraxLOG(getName() + " created.");
169 }
170
172 {
173 if (!isCreated())
174 {
175 return;
176 }
177
179
180 if (mVertices)
181 {
183 {
184 delete [] static_cast<Mesh::POS_NORM_VERTEX*>(mVertices);
185 mVertices = 0;
186 }
188 {
189 delete [] static_cast<Mesh::POS_VERTEX*>(mVertices);
190 mVertices = 0;
191 }
192 }
193
195 {
196 delete [] mVerticesChoppyBuffer;
197 }
198
200 {
201 delete mTmpRndrngCamera;
202 delete mProjectingCamera;
203 }
204
205 mLastPosition = Ogre::Vector3(0,0,0);
206 mLastOrientation = Ogre::Quaternion();
207 }
208
209 void ProjectedGrid::saveCfg(Ogre::String &Data)
210 {
211 Module::saveCfg(Data);
212
213 Data += CfgFileManager::_getCfgString("PG_ChoopyStrength", mOptions.ChoppyStrength);
214 Data += CfgFileManager::_getCfgString("PG_ChoppyWaves", mOptions.ChoppyWaves);
215 Data += CfgFileManager::_getCfgString("PG_Complexity", mOptions.Complexity);
216 Data += CfgFileManager::_getCfgString("PG_Elevation", mOptions.Elevation);
217 Data += CfgFileManager::_getCfgString("PG_ForceRecalculateGeometry", mOptions.ForceRecalculateGeometry);
218 Data += CfgFileManager::_getCfgString("PG_Smooth", mOptions.Smooth);
219 Data += CfgFileManager::_getCfgString("PG_Strength", mOptions.Strength); Data += "\n";
220 }
221
222 bool ProjectedGrid::loadCfg(Ogre::ConfigFile &CfgFile)
223 {
224 if (!Module::loadCfg(CfgFile))
225 {
226 return false;
227 }
228
229 HydraxLOG("\tReading options...");
231 Options(CfgFileManager::_getIntValue(CfgFile, "PG_Complexity"),
232 CfgFileManager::_getFloatValue(CfgFile, "PG_Strength"),
233 CfgFileManager::_getFloatValue(CfgFile, "PG_Elevation"),
234 CfgFileManager::_getBoolValue(CfgFile, "PG_Smooth"),
235 CfgFileManager::_getBoolValue(CfgFile, "PG_ForceRecalculateGeometry"),
236 CfgFileManager::_getBoolValue(CfgFile, "PG_ChoppyWaves"),
237 CfgFileManager::_getFloatValue(CfgFile, "PG_ChoopyStrength")));
238
239 HydraxLOG("\tOptions readed.");
240
241 return true;
242 }
243
244 void ProjectedGrid::update(const Ogre::Real &timeSinceLastFrame)
245 {
246 if (!isCreated())
247 {
248 return;
249 }
250
251 Module::update(timeSinceLastFrame);
252
253 Ogre::Vector3 RenderingCameraPos = mRenderingCamera->getDerivedPosition();
254
255 if (mLastPosition != RenderingCameraPos ||
256 mLastOrientation != mRenderingCamera->getDerivedOrientation() ||
258 {
259 if (mLastPosition != RenderingCameraPos)
260 {
261 Ogre::Vector3 HydraxPos = Ogre::Vector3(RenderingCameraPos.x,mHydrax->getPosition().y,RenderingCameraPos.z);
262
263 mHydrax->getMesh()->getSceneNode()->setPosition(HydraxPos);
264 mHydrax->getRttManager()->getPlanesSceneNode()->setPosition(HydraxPos);
265
266 // For world-space -> object-space conversion
268 }
269
270 float RenderingFarClipDistance = mRenderingCamera->getFarClipDistance();
271
272 if (RenderingFarClipDistance > _def_MaxFarClipDistance)
273 {
274 mRenderingCamera->setFarClipDistance(_def_MaxFarClipDistance);
275 }
276
278
279 if (mLastMinMax)
280 {
281 _renderGeometry(mRange, mProjectingCamera->getViewMatrix(), RenderingCameraPos);
282
284 }
285
286 mRenderingCamera->setFarClipDistance(RenderingFarClipDistance);
287 }
288 else if (mLastMinMax)
289 {
291 {
292 Mesh::POS_NORM_VERTEX* Vertices = static_cast<Mesh::POS_NORM_VERTEX*>(mVertices);
293
295 {
296 for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++)
297 {
298 Vertices[i] = mVerticesChoppyBuffer[i];
299 Vertices[i].y = -mBasePlane.d + mNoise->getValue(RenderingCameraPos.x + Vertices[i].x, RenderingCameraPos.z + Vertices[i].z)*mOptions.Strength;
300 }
301 }
302 else
303 {
304 for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++)
305 {
306 Vertices[i].y = -mBasePlane.d + mNoise->getValue(RenderingCameraPos.x + Vertices[i].x, RenderingCameraPos.z + Vertices[i].z)*mOptions.Strength;
307 }
308 }
309 }
311 {
312 Mesh::POS_VERTEX* Vertices = static_cast<Mesh::POS_VERTEX*>(mVertices);
313
314 for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++)
315 {
316 Vertices[i].y = -mBasePlane.d + mNoise->getValue(RenderingCameraPos.x + Vertices[i].x, RenderingCameraPos.z + Vertices[i].z)*mOptions.Strength;
317 }
318 }
319
320 // Smooth the heightdata
321 if (mOptions.Smooth)
322 {
324 {
325 Mesh::POS_NORM_VERTEX* Vertices = static_cast<Mesh::POS_NORM_VERTEX*>(mVertices);
326
327 for(int v=1; v<(mOptions.Complexity-1); v++)
328 {
329 for(int u=1; u<(mOptions.Complexity-1); u++)
330 {
331 Vertices[v*mOptions.Complexity + u].y =
332 0.2f *
333 (Vertices[v *mOptions.Complexity + u ].y +
334 Vertices[v *mOptions.Complexity + (u+1)].y +
335 Vertices[v *mOptions.Complexity + (u-1)].y +
336 Vertices[(v+1)*mOptions.Complexity + u ].y +
337 Vertices[(v-1)*mOptions.Complexity + u ].y);
338 }
339 }
340 }
342 {
343 Mesh::POS_VERTEX* Vertices = static_cast<Mesh::POS_VERTEX*>(mVertices);
344
345 for(int v=1; v<(mOptions.Complexity-1); v++)
346 {
347 for(int u=1; u<(mOptions.Complexity-1); u++)
348 {
349 Vertices[v*mOptions.Complexity + u].y =
350 0.2f *
351 (Vertices[v *mOptions.Complexity + u ].y +
352 Vertices[v *mOptions.Complexity + (u+1)].y +
353 Vertices[v *mOptions.Complexity + (u-1)].y +
354 Vertices[(v+1)*mOptions.Complexity + u ].y +
355 Vertices[(v-1)*mOptions.Complexity + u ].y);
356 }
357 }
358 }
359 }
360
362
364
366 }
367
368 mLastPosition = RenderingCameraPos;
369 mLastOrientation = mRenderingCamera->getDerivedOrientation();
370 }
371
372 bool ProjectedGrid::_renderGeometry(const Ogre::Matrix4& m,const Ogre::Matrix4& _viewMat, const Ogre::Vector3& WorldPos)
373 {
374 t_corners0 = _calculeWorldPosition(Ogre::Vector2( 0.0f, 0.0f),m,_viewMat);
375 t_corners1 = _calculeWorldPosition(Ogre::Vector2(+1.0f, 0.0f),m,_viewMat);
376 t_corners2 = _calculeWorldPosition(Ogre::Vector2( 0.0f,+1.0f),m,_viewMat);
377 t_corners3 = _calculeWorldPosition(Ogre::Vector2(+1.0f,+1.0f),m,_viewMat);
378
379 float du = 1.0f/(mOptions.Complexity-1),
380 dv = 1.0f/(mOptions.Complexity-1),
381 u,v = 0.0f,
382 // _1_u = (1.0f-u)
383 _1_u, _1_v = 1.0f,
384 divide;
385
386 Ogre::Vector4 result;
387
388 int i = 0, iv, iu;
389
391 {
392 Mesh::POS_NORM_VERTEX* Vertices = static_cast<Mesh::POS_NORM_VERTEX*>(mVertices);
393
394 for(iv=0; iv<mOptions.Complexity; iv++)
395 {
396 u = 0.0f;
397 _1_u = 1.0f;
398 for(iu=0; iu<mOptions.Complexity; iu++)
399 {
400 result.x = _1_v*(_1_u*t_corners0.x + u*t_corners1.x) + v*(_1_u*t_corners2.x + u*t_corners3.x);
401 result.z = _1_v*(_1_u*t_corners0.z + u*t_corners1.z) + v*(_1_u*t_corners2.z + u*t_corners3.z);
402 result.w = _1_v*(_1_u*t_corners0.w + u*t_corners1.w) + v*(_1_u*t_corners2.w + u*t_corners3.w);
403
404 divide = 1.0f/result.w;
405 result.x *= divide;
406 result.z *= divide;
407
408 Vertices[i].x = result.x;
409 Vertices[i].z = result.z;
410 Vertices[i].y = -mBasePlane.d + mNoise->getValue(WorldPos.x + result.x, WorldPos.z + result.z)*mOptions.Strength;
411
412 i++;
413 u += du;
414 _1_u = 1.0f-u;
415 }
416 v += dv;
417 _1_v = 1.0f-v;
418 }
419
421 {
422 for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++)
423 {
424 mVerticesChoppyBuffer[i] = Vertices[i];
425 }
426 }
427 }
429 {
430 Mesh::POS_VERTEX* Vertices = static_cast<Mesh::POS_VERTEX*>(mVertices);
431
432 for(iv=0; iv<mOptions.Complexity; iv++)
433 {
434 u = 0.0f;
435 _1_u = 1.0f;
436 for(iu=0; iu<mOptions.Complexity; iu++)
437 {
438 result.x = _1_v*(_1_u*t_corners0.x + u*t_corners1.x) + v*(_1_u*t_corners2.x + u*t_corners3.x);
439 result.z = _1_v*(_1_u*t_corners0.z + u*t_corners1.z) + v*(_1_u*t_corners2.z + u*t_corners3.z);
440 result.w = _1_v*(_1_u*t_corners0.w + u*t_corners1.w) + v*(_1_u*t_corners2.w + u*t_corners3.w);
441
442 divide = 1.0f/result.w;
443 result.x *= divide;
444 result.z *= divide;
445
446 Vertices[i].x = result.x;
447 Vertices[i].z = result.z;
448 Vertices[i].y = -mBasePlane.d + mNoise->getValue(WorldPos.x + result.x, WorldPos.z + result.z)*mOptions.Strength;
449
450 i++;
451 u += du;
452 _1_u = 1.0f-u;
453 }
454 v += dv;
455 _1_v = 1.0f-v;
456 }
457 }
458
459 // Smooth the heightdata
460 if (mOptions.Smooth)
461 {
463 {
464 Mesh::POS_NORM_VERTEX* Vertices = static_cast<Mesh::POS_NORM_VERTEX*>(mVertices);
465
466 for(iv=1; iv<(mOptions.Complexity-1); iv++)
467 {
468 for(iu=1; iu<(mOptions.Complexity-1); iu++)
469 {
470 Vertices[iv*mOptions.Complexity + iu].y =
471 0.2f *
472 (Vertices[iv *mOptions.Complexity + iu ].y +
473 Vertices[iv *mOptions.Complexity + (iu+1)].y +
474 Vertices[iv *mOptions.Complexity + (iu-1)].y +
475 Vertices[(iv+1)*mOptions.Complexity + iu ].y +
476 Vertices[(iv-1)*mOptions.Complexity + iu ].y);
477 }
478 }
479 }
481 {
482 Mesh::POS_VERTEX* Vertices = static_cast<Mesh::POS_VERTEX*>(mVertices);
483
484 for(iv=1; iv<(mOptions.Complexity-1); iv++)
485 {
486 for(iu=1; iu<(mOptions.Complexity-1); iu++)
487 {
488 Vertices[iv*mOptions.Complexity + iu].y =
489 0.2f *
490 (Vertices[iv *mOptions.Complexity + iu ].y +
491 Vertices[iv *mOptions.Complexity + (iu+1)].y +
492 Vertices[iv *mOptions.Complexity + (iu-1)].y +
493 Vertices[(iv+1)*mOptions.Complexity + iu ].y +
494 Vertices[(iv-1)*mOptions.Complexity + iu ].y);
495 }
496 }
497 }
498 }
499
501
503
504 return true;
505 }
506
508 {
510 {
511 return;
512 }
513
514 int v, u;
515 Ogre::Vector3 vec1, vec2, normal;
516
517 Mesh::POS_NORM_VERTEX* Vertices = static_cast<Mesh::POS_NORM_VERTEX*>(mVertices);
518
519 for(v=1; v<(mOptions.Complexity-1); v++)
520 {
521 for(u=1; u<(mOptions.Complexity-1); u++)
522 {
523 vec1 = Ogre::Vector3(
524 Vertices[v*mOptions.Complexity + u + 1].x-Vertices[v*mOptions.Complexity + u - 1].x,
525 Vertices[v*mOptions.Complexity + u + 1].y-Vertices[v*mOptions.Complexity + u - 1].y,
526 Vertices[v*mOptions.Complexity + u + 1].z-Vertices[v*mOptions.Complexity + u - 1].z);
527
528 vec2 = Ogre::Vector3(
529 Vertices[(v+1)*mOptions.Complexity + u].x - Vertices[(v-1)*mOptions.Complexity + u].x,
530 Vertices[(v+1)*mOptions.Complexity + u].y - Vertices[(v-1)*mOptions.Complexity + u].y,
531 Vertices[(v+1)*mOptions.Complexity + u].z - Vertices[(v-1)*mOptions.Complexity + u].z);
532
533 normal = vec2.crossProduct(vec1);
534
535 Vertices[v*mOptions.Complexity + u].nx = normal.x;
536 Vertices[v*mOptions.Complexity + u].ny = normal.y;
537 Vertices[v*mOptions.Complexity + u].nz = normal.z;
538 }
539 }
540 }
541
543 {
545 {
546 return;
547 }
548
549 int v, u,
550 Underwater = 1;
551
553 {
554 Underwater = -1;
555 }
556
557 float Dis1, Dis2;//,
558 // Dis1_, Dis2_;
559
560 Ogre::Vector3 CameraDir, Norm;
561 Ogre::Vector2 Dir, Perp, Norm2;
562
563 CameraDir = mRenderingCamera->getDerivedDirection();
564 Dir = Ogre::Vector2(CameraDir.x, CameraDir.z).normalisedCopy();
565 Perp = Dir.perpendicular();
566
567 if (Dir.x < 0 ) Dir.x = -Dir.x;
568 if (Dir.y < 0 ) Dir.y = -Dir.y;
569
570 if (Perp.x < 0 ) Perp.x = -Perp.x;
571 if (Perp.y < 0 ) Perp.y = -Perp.y;
572
573 Mesh::POS_NORM_VERTEX* Vertices = static_cast<Mesh::POS_NORM_VERTEX*>(mVertices);
574
575 for(v=1; v<(mOptions.Complexity-1); v++)
576 {
577 Dis1 = (Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + 1].x,
579 Ogre::Vector2(mVerticesChoppyBuffer[(v+1)*mOptions.Complexity + 1].x,
580 mVerticesChoppyBuffer[(v+1)*mOptions.Complexity + 1].z)).length();
581
582 /*Dis1_ = (Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + 1].x,
583 mVerticesChoppyBuffer[v*mOptions.Complexity + 1].z) -
584 Ogre::Vector2(mVerticesChoppyBuffer[(v-1)*mOptions.Complexity + 1].x,
585 mVerticesChoppyBuffer[(v-1)*mOptions.Complexity + 1].z)).length();
586
587 Dis1 = (Dis1+Dis1_)/2;*/
588
589 for(u=1; u<(mOptions.Complexity-1); u++)
590 {
591 Dis2 = (Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + u].x,
593 Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + u+1].x,
594 mVerticesChoppyBuffer[v*mOptions.Complexity + u+1].z)).length();
595/*
596 Dis2_ = (Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + u].x,
597 mVerticesChoppyBuffer[v*mOptions.Complexity + u].z) -
598 Ogre::Vector2(mVerticesChoppyBuffer[v*mOptions.Complexity + u-1].x,
599 mVerticesChoppyBuffer[v*mOptions.Complexity + u-1].z)).length();
600
601 Dis2 = (Dis2+Dis2_)/2;*/
602
603 Norm = Ogre::Vector3(Vertices[v*mOptions.Complexity + u].nx,
604 Vertices[v*mOptions.Complexity + u].ny,
605 Vertices[v*mOptions.Complexity + u].nz).
606 normalisedCopy();
607
608 Norm2 = Ogre::Vector2(Norm.x, Norm.z) *
609 ( (Dir * Dis1) +
610 (Perp * Dis2)) *
612
613 Vertices[v*mOptions.Complexity + u].x = mVerticesChoppyBuffer[v*mOptions.Complexity + u].x + Norm2.x * Underwater;
614 Vertices[v*mOptions.Complexity + u].z = mVerticesChoppyBuffer[v*mOptions.Complexity + u].z + Norm2.y * Underwater;
615 }
616 }
617 }
618
619 // Check the point of intersection with the plane (0,1,0,0) and return the position in homogenous coordinates
620 Ogre::Vector4 ProjectedGrid::_calculeWorldPosition(const Ogre::Vector2 &uv, const Ogre::Matrix4& m, const Ogre::Matrix4& _viewMat)
621 {
622 Ogre::Vector4 origin(uv.x,uv.y,-1,1);
623 Ogre::Vector4 direction(uv.x,uv.y,1,1);
624
625 origin = m*origin;
626 direction = m*direction;
627
628 Ogre::Vector3 _org(origin.x/origin.w,origin.y/origin.w,origin.z/origin.w);
629 Ogre::Vector3 _dir(direction.x/direction.w,direction.y/direction.w,direction.z/direction.w);
630 _dir -= _org;
631 _dir.normalise();
632
633 Ogre::Ray _ray(_org,_dir);
634 std::pair<bool,Ogre::Real> _result = _ray.intersects(mBasePlane);
635 float l = _result.second;
636 Ogre::Vector3 worldPos = _org + _dir*l;
637 Ogre::Vector4 _tempVec = _viewMat*Ogre::Vector4(worldPos);
638 float _temp = -_tempVec.z/_tempVec.w;
639 Ogre::Vector4 retPos(worldPos);
640 retPos /= _temp;
641
642 return retPos;
643 }
644
645 bool ProjectedGrid::_getMinMax(Ogre::Matrix4 *range)
646 {
648
649 float x_min,y_min,x_max,y_max;
650 Ogre::Vector3 frustum[8],proj_points[24];
651
652 int i,
653 n_points = 0,
654 src, dst;
655
656 int cube[] =
657 {0,1, 0,2, 2,3, 1,3,
658 0,4, 2,6, 3,7, 1,5,
659 4,6, 4,5, 5,7, 6,7};
660
661 Ogre::Vector3 _testLine;
662 Ogre::Real _dist;
663 Ogre::Ray _ray;
664
665 std::pair<bool,Ogre::Real> _result;
666
667 // Set temporal rendering camera parameters
668 mTmpRndrngCamera->setFrustumOffset(mRenderingCamera->getFrustumOffset());
669 mTmpRndrngCamera->setAspectRatio(mRenderingCamera->getAspectRatio());
670 mTmpRndrngCamera->setDirection(mRenderingCamera->getDerivedDirection());
671 mTmpRndrngCamera->setFarClipDistance(mRenderingCamera->getFarClipDistance());
672 mTmpRndrngCamera->setFOVy(mRenderingCamera->getFOVy());
673 mTmpRndrngCamera->setNearClipDistance(mRenderingCamera->getNearClipDistance());
674 mTmpRndrngCamera->setOrientation(mRenderingCamera->getDerivedOrientation());
675 mTmpRndrngCamera->setPosition(0, mRenderingCamera->getDerivedPosition().y - mHydrax->getPosition().y, 0);
676
677 Ogre::Matrix4 invviewproj = (mTmpRndrngCamera->getProjectionMatrixWithRSDepth()*mTmpRndrngCamera->getViewMatrix()).inverse();
678 frustum[0] = invviewproj * Ogre::Vector3(-1,-1,0);
679 frustum[1] = invviewproj * Ogre::Vector3(+1,-1,0);
680 frustum[2] = invviewproj * Ogre::Vector3(-1,+1,0);
681 frustum[3] = invviewproj * Ogre::Vector3(+1,+1,0);
682 frustum[4] = invviewproj * Ogre::Vector3(-1,-1,+1);
683 frustum[5] = invviewproj * Ogre::Vector3(+1,-1,+1);
684 frustum[6] = invviewproj * Ogre::Vector3(-1,+1,+1);
685 frustum[7] = invviewproj * Ogre::Vector3(+1,+1,+1);
686
687 // Check intersections with upper_bound and lower_bound
688 for(i=0; i<12; i++)
689 {
690 src=cube[i*2]; dst=cube[i*2+1];
691 _testLine = frustum[dst]-frustum[src];
692 _dist = _testLine.normalise();
693 _ray = Ogre::Ray(frustum[src], _testLine);
694 _result = Ogre::Math::intersects(_ray,mUpperBoundPlane);
695 if ((_result.first) && (_result.second<_dist+0.00001))
696 {
697 proj_points[n_points++] = frustum[src] + _result.second * _testLine;
698 }
699 _result = Ogre::Math::intersects(_ray,mLowerBoundPlane);
700 if ((_result.first) && (_result.second<_dist+0.00001))
701 {
702 proj_points[n_points++] = frustum[src] + _result.second * _testLine;
703 }
704 }
705
706 // Check if any of the frustums vertices lie between the upper_bound and lower_bound planes
707 for(i=0; i<8; i++)
708 {
709 if(mUpperBoundPlane.getDistance(frustum[i])/mLowerBoundPlane.getDistance(frustum[i]) < 0)
710 {
711 proj_points[n_points++] = frustum[i];
712 }
713 }
714
715 // Set projecting camera parameters
716 mProjectingCamera->setFrustumOffset(mTmpRndrngCamera->getFrustumOffset());
717 mProjectingCamera->setAspectRatio(mTmpRndrngCamera->getAspectRatio());
718 mProjectingCamera->setDirection(mTmpRndrngCamera->getDerivedDirection());
719 mProjectingCamera->setFarClipDistance(mTmpRndrngCamera->getFarClipDistance());
720 mProjectingCamera->setFOVy(mTmpRndrngCamera->getFOVy());
721 mProjectingCamera->setNearClipDistance(mTmpRndrngCamera->getNearClipDistance());
722 mProjectingCamera->setOrientation(mTmpRndrngCamera->getDerivedOrientation());
723 mProjectingCamera->setPosition(mTmpRndrngCamera->getDerivedPosition());
724
725 // Make sure the camera isn't too close to the plane
726 float height_in_plane = mBasePlane.getDistance(mProjectingCamera->getRealPosition());
727
728 bool keep_it_simple = false,
729 underwater = false;
730
731 if (height_in_plane < 0.0f)
732 {
733 underwater = true;
734 }
735
736 if (keep_it_simple)
737 {
738 mProjectingCamera->setDirection(mTmpRndrngCamera->getDerivedDirection());
739 }
740 else
741 {
742 Ogre::Vector3 aimpoint, aimpoint2;
743
744 if (height_in_plane < (mOptions.Strength + mOptions.Elevation))
745 {
746 if (underwater)
747 {
748 mProjectingCamera->setPosition(mProjectingCamera->getRealPosition()+mLowerBoundPlane.normal*(mOptions.Strength + mOptions.Elevation - 2*height_in_plane));
749 }
750 else
751 {
752 mProjectingCamera->setPosition(mProjectingCamera->getRealPosition()+mLowerBoundPlane.normal*(mOptions.Strength + mOptions.Elevation - height_in_plane));
753 }
754 }
755
756 // Aim the projector at the point where the camera view-vector intersects the plane
757 // if the camera is aimed away from the plane, mirror it's view-vector against the plane
758 if (((mBasePlane.normal).dotProduct(mTmpRndrngCamera->getDerivedDirection()) < 0.0f) || ((mBasePlane.normal).dotProduct(mTmpRndrngCamera->getDerivedPosition()) < 0.0f ) )
759 {
760 _ray = Ogre::Ray(mTmpRndrngCamera->getDerivedPosition(), mTmpRndrngCamera->getDerivedDirection());
761 _result = Ogre::Math::intersects(_ray,mBasePlane);
762
763 if(!_result.first)
764 {
765 _result.second = -_result.second;
766 }
767
768 aimpoint = mTmpRndrngCamera->getDerivedPosition() + _result.second * mTmpRndrngCamera->getDerivedDirection();
769 }
770 else
771 {
772 Ogre::Vector3 flipped = mTmpRndrngCamera->getDerivedDirection() - 2*mNormal* (mTmpRndrngCamera->getDerivedDirection()).dotProduct(mNormal);
773 flipped.normalise();
774 _ray = Ogre::Ray( mTmpRndrngCamera->getDerivedPosition(), flipped);
775 _result = Ogre::Math::intersects(_ray,mBasePlane);
776
777 aimpoint = mTmpRndrngCamera->getDerivedPosition() + _result.second * flipped;
778 }
779
780 // Force the point the camera is looking at in a plane, and have the projector look at it
781 // works well against horizon, even when camera is looking upwards
782 // doesn't work straight down/up
783 float af = fabs((mBasePlane.normal).dotProduct(mTmpRndrngCamera->getDerivedDirection()));
784 aimpoint2 = mTmpRndrngCamera->getDerivedPosition() + 10.0*mTmpRndrngCamera->getDerivedDirection();
785 aimpoint2 = aimpoint2 - mNormal* (aimpoint2.dotProduct(mNormal));
786
787 // Fade between aimpoint & aimpoint2 depending on view angle
788 aimpoint = aimpoint*af + aimpoint2*(1.0f-af);
789
790 mProjectingCamera->setDirection(aimpoint-mProjectingCamera->getRealPosition());
791 }
792
793 for(i=0; i<n_points; i++)
794 {
795 // Project the point onto the surface plane
796 proj_points[i] = proj_points[i] - mBasePlane.normal*mBasePlane.getDistance(proj_points[i]);
797 proj_points[i] = mProjectingCamera->getViewMatrix() * proj_points[i];
798 proj_points[i] = mProjectingCamera->getProjectionMatrixWithRSDepth() * proj_points[i];
799 }
800
801 // Get max/min x & y-values to determine how big the "projection window" must be
802 if (n_points > 0)
803 {
804 x_min = proj_points[0].x;
805 x_max = proj_points[0].x;
806 y_min = proj_points[0].y;
807 y_max = proj_points[0].y;
808
809 for(i=1; i<n_points; i++)
810 {
811 if (proj_points[i].x > x_max) x_max = proj_points[i].x;
812 if (proj_points[i].x < x_min) x_min = proj_points[i].x;
813 if (proj_points[i].y > y_max) y_max = proj_points[i].y;
814 if (proj_points[i].y < y_min) y_min = proj_points[i].y;
815 }
816
817 // Build the packing matrix that spreads the grid across the "projection window"
818 Ogre::Matrix4 pack(x_max-x_min, 0, 0, x_min,
819 0, y_max-y_min, 0, y_min,
820 0, 0, 1, 0,
821 0, 0, 0, 1);
822
823 Ogre::Matrix4 invviewproj = (mProjectingCamera->getProjectionMatrixWithRSDepth()*mProjectingCamera->getViewMatrix()).inverse();
824 *range = invviewproj * pack;
825
826 return true;
827 }
828
829 return false;
830 }
831
832 void ProjectedGrid::_setDisplacementAmplitude(const float &Amplitude)
833 {
834 mUpperBoundPlane = Ogre::Plane( mNormal, mPos + Amplitude * mNormal);
835 mLowerBoundPlane = Ogre::Plane( mNormal, mPos - Amplitude * mNormal);
836 }
837
838 float ProjectedGrid::getHeigth(const Ogre::Vector2 &Position)
839 {
840 return mHydrax->getPosition().y + mNoise->getValue(Position.x, Position.y)*mOptions.Strength;
841 }
842}}
float Norm() const
#define HydraxLOG(msg)
Definition Application.h:60
#define _def_MaxFarClipDistance
static Ogre::String _getCfgString(const Ogre::String &Name, const int &Value)
static Ogre::Real _getFloatValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name)
Get float value.
static bool _getBoolValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name)
Get bool value.
static int _getIntValue(Ogre::ConfigFile &CfgFile, const Ogre::String Name)
Get int value.
RttManager * getRttManager()
Get Hydrax::RttManager.
Definition Hydrax.h:333
Mesh * getMesh()
Get Hydrax::Mesh.
Definition Hydrax.h:317
const Ogre::Vector3 & getSunPosition() const
Get sun position.
Definition Hydrax.h:468
const Ogre::Vector3 & getPosition() const
Get water position.
Definition Hydrax.h:413
void setSunPosition(const Ogre::Vector3 &SunPosition)
Set sun position.
Definition Hydrax.cpp:884
void _setStrength(const Ogre::Real &Strength)
Set water strength GPU param.
Definition Hydrax.cpp:764
GPUNormalMapManager * getGPUNormalMapManager()
Get Hydrax::GPUNormalMapManager.
Definition Hydrax.h:365
const bool & _isCurrentFrameUnderwater() const
Is current frame underwater?
Definition Hydrax.h:621
NormalMode
Normal generation mode.
Class wich contains all funtions/variables related to Hydrax water mesh.
Definition Mesh.h:47
const Ogre::String & getMaterialName() const
Get material name.
Definition Mesh.h:269
void create()
Create our water mesh, geometry, entity, etc...
Definition Mesh.cpp:117
void setMaterialName(const Ogre::String &MaterialName)
Set mesh material.
Definition Mesh.cpp:107
void remove()
Remove all resources.
Definition Mesh.cpp:52
VertexType
Mesh vertex type enum.
Definition Mesh.h:84
@ VT_POS_NORM
Definition Mesh.h:86
void setOptions(const Options &Options)
Update options.
Definition Mesh.cpp:78
bool updateGeometry(const int &numVer, void *verArray)
Update geomtry.
Definition Mesh.cpp:281
Ogre::SceneNode * getSceneNode()
Get the Ogre::SceneNode pointer where Hydrax mesh is attached.
Definition Mesh.h:293
Base module class, Override it for create different ways of create water noise.
Definition Module.h:47
virtual void update(const Ogre::Real &timeSinceLastFrame)
Call it each frame.
Definition Module.cpp:94
virtual void remove()
Remove.
Definition Module.cpp:53
const Ogre::String & getName() const
Get module name.
Definition Module.h:99
virtual void create()
Create.
Definition Module.cpp:46
const bool & isCreated() const
Is created() called?
Definition Module.h:107
Noise::Noise * mNoise
Noise generator pointer.
Definition Module.h:156
MaterialManager::NormalMode mNormalMode
Normal map generation mode.
Definition Module.h:160
virtual void saveCfg(Ogre::String &Data)
Save config.
Definition Module.cpp:99
Mesh::Options mMeshOptions
Module mesh options.
Definition Module.h:158
const MaterialManager::NormalMode & getNormalMode() const
Get the normal generation mode.
Definition Module.h:125
virtual bool loadCfg(Ogre::ConfigFile &CfgFile)
Load config.
Definition Module.cpp:105
const Mesh::Options & getMeshOptions() const
Get the mesh options for this module.
Definition Module.h:133
Ogre::Quaternion mLastOrientation
void setOptions(const Options &Options)
Set options.
void * mVertices
Vertex pointer (Mesh::POS_NORM_VERTEX or Mesh::POS_VERTEX)
Ogre::Matrix4 mRange
Range matrix.
Ogre::Vector4 t_corners0
For corners.
Hydrax * mHydrax
Our Hydrax pointer.
void _performChoppyWaves()
Perform choppy waves.
void saveCfg(Ogre::String &Data)
Save config.
Options mOptions
Our projected grid options.
void _calculeNormals()
Calcule current normals.
void update(const Ogre::Real &timeSinceLastFrame)
Call it each frame.
Ogre::Vector3 mLastPosition
Last camera position, orientation.
bool _getMinMax(Ogre::Matrix4 *range)
Get min/max.
void _setDisplacementAmplitude(const float &Amplitude)
Set displacement amplitude.
float getHeigth(const Ogre::Vector2 &Position)
Get the current heigth at a especified world-space point.
Mesh::POS_NORM_VERTEX * mVerticesChoppyBuffer
Use it to store vertex positions when choppy displacement is enabled.
ProjectedGrid(Hydrax *h, Noise::Noise *n, const Ogre::Plane &BasePlane, const MaterialManager::NormalMode &NormalMode)
Constructor.
Ogre::Camera * mProjectingCamera
Cameras.
Ogre::Vector3 mNormal
Normal and position.
Ogre::Plane mBasePlane
Planes.
Ogre::Vector4 _calculeWorldPosition(const Ogre::Vector2 &uv, const Ogre::Matrix4 &m, const Ogre::Matrix4 &_viewMat)
Calcule world position.
bool _renderGeometry(const Ogre::Matrix4 &m, const Ogre::Matrix4 &_viewMat, const Ogre::Vector3 &WorldPos)
Render geometry.
bool loadCfg(Ogre::ConfigFile &CfgFile)
Load config.
Base noise class, Override it for create different ways of create water noise.
Definition Noise.h:43
const Ogre::String & getName() const
Get noise name.
Definition Noise.h:92
virtual bool createGPUNormalMapResources(GPUNormalMapManager *g)
Create GPUNormalMap resources.
Definition Noise.cpp:52
virtual float getValue(const float &x, const float &y)=0
Get the especified x/y noise value.
Ogre::SceneNode * getPlanesSceneNode()
Definition RttManager.h:150
Mesh::VertexType _PG_getVertexTypeFromNormalMode(const MaterialManager::NormalMode &NormalMode)
Ogre::String _PG_getNormalModeString(const MaterialManager::NormalMode &NormalMode)
Size MeshSize
Grid size (X/Z) world space.
Definition Mesh.h:135
float MeshStrength
Water strength.
Definition Mesh.h:137
int MeshComplexity
Mesh complexity.
Definition Mesh.h:133
Vertex struct for position and normals data.
Definition Mesh.h:61
Vertex struct for position data.
Definition Mesh.h:77
Struct wich contains Hydrax projected grid module options.
float ChoppyStrength
Choppy waves strength.
int Complexity
Projected grid complexity (N*N)
bool ForceRecalculateGeometry
Force recalculate mesh geometry each frame.
Struct wich contains an especific width and height value.
Definition Help.h:41