aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llvowater.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llvowater.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llvowater.cpp')
-rw-r--r--linden/indra/newview/llvowater.cpp1047
1 files changed, 1047 insertions, 0 deletions
diff --git a/linden/indra/newview/llvowater.cpp b/linden/indra/newview/llvowater.cpp
new file mode 100644
index 0000000..55a7020
--- /dev/null
+++ b/linden/indra/newview/llvowater.cpp
@@ -0,0 +1,1047 @@
1/**
2 * @file llvowater.cpp
3 * @brief LLVOWater class implementation
4 *
5 * Copyright (c) 2005-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "llvowater.h"
31
32#include "imageids.h"
33#include "llviewercontrol.h"
34
35#include "llagent.h"
36#include "lldrawable.h"
37#include "lldrawpoolwater.h"
38#include "llface.h"
39#include "llsky.h"
40#include "llsurface.h"
41#include "llvosky.h"
42#include "llviewercamera.h"
43#include "llviewerimagelist.h"
44#include "llviewerregion.h"
45#include "llworld.h"
46#include "pipeline.h"
47
48const BOOL gUseRoam = FALSE;
49
50
51///////////////////////////////////
52
53#include "randgauss.h"
54
55template<class T> inline T LERP(T a, T b, F32 factor)
56{
57 return a + (b - a) * factor;
58}
59
60const U32 N_RES_HALF = (N_RES >> 1);
61
62const U32 WIDTH = (N_RES * WAVE_STEP); //128.f //64 // width of wave tile, in meters
63const F32 WAVE_STEP_INV = (1. / WAVE_STEP);
64
65const F32 g = 9.81f; // gravitational constant (m/s^2)
66
67///////////////////////////////////
68
69LLWaterSurface::LLWaterSurface() :
70 mInitialized(FALSE),
71 mWind(9, 0, 0),
72 mA(0.2f),
73 mVisc(0.001f),
74 mShininess(8.0f)
75{}
76
77
78LLWaterGrid *LLVOWater::sGrid = 0;
79
80
81LLVOWater::LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
82: LLViewerObject(id, LL_VO_WATER, regionp)
83{
84 // Terrain must draw during selection passes so it can block objects behind it.
85 mbCanSelect = FALSE;
86 setScale(LLVector3(256.f, 256.f, 0.f)); // Hack for setting scale for bounding boxes/visibility.
87
88 mUseTexture = TRUE;
89}
90
91
92void LLVOWater::markDead()
93{
94 LLViewerObject::markDead();
95}
96
97
98BOOL LLVOWater::isActive() const
99{
100 return FALSE;
101}
102
103
104void LLVOWater::setPixelAreaAndAngle(LLAgent &agent)
105{
106 mAppAngle = 50;
107 mPixelArea = 500*500;
108}
109
110
111// virtual
112void LLVOWater::updateTextures(LLAgent &agent)
113{
114}
115
116// virtual
117void LLVOWater::updateDrawable(BOOL force_damped)
118{
119 // Force an immediate rebuild on any update
120 if (mDrawable.notNull())
121 {
122 gPipeline.updateMoveNormalAsync(mDrawable);
123 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
124 }
125 clearChanged(SHIFTED);
126}
127
128// Never gets called
129BOOL LLVOWater::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
130{
131 if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER)))
132 {
133 return TRUE;
134 }
135 if (mDrawable)
136 {
137 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
138 }
139 return TRUE;
140}
141
142LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline)
143{
144 pipeline->allocDrawable(this);
145 mDrawable->setLit(FALSE);
146 mDrawable->setRenderType(LLPipeline::RENDER_TYPE_WATER);
147
148 LLDrawPoolWater *pool = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
149
150 if (mUseTexture)
151 {
152 mDrawable->setNumFaces(1, pool, mRegionp->getLand().getWaterTexture());
153 }
154 else
155 {
156 mDrawable->setNumFaces(1, pool, gWorldp->getDefaultWaterTexture());
157 }
158
159 return mDrawable;
160}
161
162BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
163{
164 return updateGeometryFlat(drawable);
165}
166
167
168BOOL LLVOWater::updateGeometryFlat(LLDrawable *drawable)
169{
170 LLFace *face;
171
172 if (drawable->getNumFaces() < 1)
173 {
174 drawable->addFace(gPipeline.getPool(LLDrawPool::POOL_WATER), NULL);
175 }
176 face = drawable->getFace(0);
177
178 LLVector2 uvs[4];
179 LLVector3 vtx[4];
180
181 LLStrider<LLVector3> verticesp, normalsp;
182 LLStrider<LLVector2> texCoordsp;
183 U32 *indicesp;
184 S32 index_offset;
185
186 S32 size = 16;
187
188 S32 num_quads = size*size;
189
190 face->setPrimType(LLTriangles);
191 face->setSize(4*num_quads, 6*num_quads);
192 index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
193 if (-1 == index_offset)
194 {
195 return TRUE;
196 }
197
198 LLVector3 position_agent;
199 position_agent = getPositionAgent();
200 face->mCenterAgent = position_agent;
201
202 S32 x, y;
203 F32 step_x = getScale().mV[0] / size;
204 F32 step_y = getScale().mV[1] / size;
205
206 const LLVector3 up(0.f, step_y * 0.5f, 0.f);
207 const LLVector3 right(step_x * 0.5f, 0.f, 0.f);
208 const LLVector3 normal(0.f, 0.f, 1.f);
209
210 F32 size_inv = 1.f / size;
211
212 for (y = 0; y < size; y++)
213 {
214 for (x = 0; x < size; x++)
215 {
216 S32 toffset = index_offset + 4*(y*size + x);
217 position_agent = getPositionAgent() - getScale() * 0.5f;
218 position_agent.mV[VX] += (x + 0.5f) * step_x;
219 position_agent.mV[VY] += (y + 0.5f) * step_y;
220
221 vtx[0] = position_agent - right + up;
222 vtx[1] = position_agent - right - up;
223 vtx[2] = position_agent + right + up;
224 vtx[3] = position_agent + right - up;
225
226 *(verticesp++) = vtx[0];
227 *(verticesp++) = vtx[1];
228 *(verticesp++) = vtx[2];
229 *(verticesp++) = vtx[3];
230
231 uvs[0].setVec(x*size_inv, (y+1)*size_inv);
232 uvs[1].setVec(x*size_inv, y*size_inv);
233 uvs[2].setVec((x+1)*size_inv, (y+1)*size_inv);
234 uvs[3].setVec((x+1)*size_inv, y*size_inv);
235
236 *(texCoordsp) = uvs[0];
237 texCoordsp++;
238 *(texCoordsp) = uvs[1];
239 texCoordsp++;
240 *(texCoordsp) = uvs[2];
241 texCoordsp++;
242 *(texCoordsp) = uvs[3];
243 texCoordsp++;
244
245 *(normalsp++) = normal;
246 *(normalsp++) = normal;
247 *(normalsp++) = normal;
248 *(normalsp++) = normal;
249
250 *indicesp++ = toffset + 0;
251 *indicesp++ = toffset + 1;
252 *indicesp++ = toffset + 2;
253
254 *indicesp++ = toffset + 1;
255 *indicesp++ = toffset + 3;
256 *indicesp++ = toffset + 2;
257 }
258 }
259
260
261 mDrawable->movePartition();
262 LLPipeline::sCompiles++;
263 return TRUE;
264}
265
266
267BOOL LLVOWater::updateGeometryHeightFieldRoam(LLDrawable *drawable)
268{
269 LLVector3 position_agent = getPositionAgent();
270 const LLVector3 region_size = getScale();
271 const LLVector3 region_origin = position_agent - region_size * 0.5f;
272
273 S32 patch_origx = llround(region_origin.mV[VX] - sGrid->mRegionOrigin.mV[VX]) / sGrid->mRegionWidth;
274 S32 patch_origy = llround(region_origin.mV[VY] - sGrid->mRegionOrigin.mV[VY]) / sGrid->mRegionWidth;
275 S32 patch_dimx = llround(region_size.mV[VX]) / sGrid->mRegionWidth;
276 S32 patch_dimy = llround(region_size.mV[VY]) / sGrid->mRegionWidth;
277
278 static S32 res = (S32)sGrid->mPatchRes;
279 if (patch_origx < 0)
280 {
281 patch_dimx -= - patch_origx;
282 if (patch_dimx < 1)
283 {
284 return TRUE;
285 }
286 patch_origx = 0;
287 }
288 if (patch_origy < 0)
289 {
290 patch_dimy -= - patch_origy;
291 if (patch_dimy < 1)
292 {
293 return TRUE;
294 }
295 patch_origy = 0;
296 }
297 if (patch_origx >= res)
298 {
299 return TRUE;
300 }
301 if (patch_origy >= res)
302 {
303 return TRUE;
304 }
305
306 patch_dimx = llmin<U32>(patch_dimx, res - patch_origx);
307 patch_dimy = llmin<U32>(patch_dimy, res - patch_origy);
308
309 U32 num_of_tris = 0;
310 S32 px, py;
311 for (py = patch_origy; py < patch_origy + patch_dimy; py++)
312 {
313 for (px = patch_origx; px < patch_origx + patch_dimx; px++)
314 {
315 const U32 ind = py * sGrid->mPatchRes + px;
316 if (sGrid->mPatches[ind].visible() && sGrid->mTab[px][py] == 0)
317 {
318 num_of_tris += sGrid->mPatches[ind].numTris();
319 sGrid->mTab[px][py] = this;
320 }
321 }
322 }
323
324 if (num_of_tris == 0)
325 {
326 return TRUE;
327 }
328
329 if (drawable->getNumFaces() < 1)
330 {
331 drawable->addFace((LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER),
332 gWorldp->getDefaultWaterTexture());
333 }
334
335 LLFace *face;
336
337 face = drawable->getFace(0);
338 face->mCenterAgent = position_agent;
339
340 LLStrider<LLVector3> verticesp, normalsp;
341 LLStrider<LLVector2> texCoordsp;
342 U32 *indicesp;
343 S32 index_offset;
344
345 const F32 water_height = getRegion()->getWaterHeight();
346
347
348 face->setPrimType(LLTriangles);
349 face->setSize(3 * num_of_tris, 3 * num_of_tris);
350 index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
351 if (-1 == index_offset)
352 {
353 return TRUE;
354 }
355
356 U32 num_of_vtx = 0;
357
358 for (py = patch_origy; py < patch_origy + patch_dimy; py++)
359 {
360 for (px = patch_origx; px < patch_origx + patch_dimx; px++)
361 {
362 for (U8 h = 0; h < 2; h++)
363 {
364 const U32 ind = py * sGrid->mPatchRes + px;
365 if (!sGrid->mPatches[ind].visible() || sGrid->mTab[px][py] != this)
366 continue;
367 LLWaterTri* half = (LLWaterTri*) sGrid->mPatches[ind].half(h);
368 for (const LLWaterTri* tri = (LLWaterTri*) half->getFirstLeaf();
369 tri != NULL;
370 tri = (LLWaterTri*) tri->getNextLeaf())
371 {
372 /////// check for coordinates
373 *(verticesp++) = sGrid->vtx(tri->Lvtx(), water_height);
374 *(verticesp++) = sGrid->vtx(tri->Rvtx(), water_height);
375 *(verticesp++) = sGrid->vtx(tri->Tvtx(), water_height);
376
377 *(normalsp++) = sGrid->norm(tri->Lvtx());
378 *(normalsp++) = sGrid->norm(tri->Rvtx());
379 *(normalsp++) = sGrid->norm(tri->Tvtx());
380
381 *(indicesp++) = index_offset + num_of_vtx + 0;
382 *(indicesp++) = index_offset + num_of_vtx + 1;
383 *(indicesp++) = index_offset + num_of_vtx + 2;
384 num_of_vtx += 3;
385 }
386 }
387 }
388 }
389
390
391 LLPipeline::sCompiles++;
392 return TRUE;
393}
394
395
396
397BOOL LLVOWater::updateGeometryHeightFieldSimple(LLDrawable *drawable)
398{
399 LLVector3 position_agent = getPositionAgent();
400 const LLVector3 region_size = getScale();
401 const LLVector3 region_origin = position_agent - region_size * 0.5f;
402
403 S32 patch_origx = llround(region_origin.mV[VX] - sGrid->mRegionOrigin.mV[VX]) / sGrid->mRegionWidth;
404 S32 patch_origy = llround(region_origin.mV[VY] - sGrid->mRegionOrigin.mV[VY]) / sGrid->mRegionWidth;
405 S32 patch_dimx = llround(region_size.mV[VX]) / sGrid->mRegionWidth;
406 S32 patch_dimy = llround(region_size.mV[VY]) / sGrid->mRegionWidth;
407
408 static S32 res = sGrid->mPatchRes;
409 if (patch_origx < 0)
410 {
411 patch_dimx -= - patch_origx;
412 if (patch_dimx < 1)
413 {
414 return TRUE;
415 }
416 patch_origx = 0;
417 }
418 if (patch_origy < 0)
419 {
420 patch_dimy -= - patch_origy;
421 if (patch_dimy < 1)
422 {
423 return TRUE;
424 }
425 patch_origy = 0;
426 }
427 if (patch_origx >= res)
428 {
429 return TRUE;
430 }
431 if (patch_origy >= res)
432 {
433 return TRUE;
434 }
435
436 patch_dimx = llmin<U32>(patch_dimx, res - patch_origx);
437 patch_dimy = llmin<U32>(patch_dimy, res - patch_origy);
438
439
440 U32 num_of_regions = 0;
441 S32 px, py;
442
443 for (py = patch_origy; py < patch_origy + patch_dimy; py++)
444 {
445 for (px = patch_origx; px < patch_origx + patch_dimx; px++)
446 {
447 // if (sGrid->mTab[px][py] != 0)
448 // bool stop = true;
449 if (sGrid->mPatches[py * sGrid->mPatchRes + px].visible() && sGrid->mTab[px][py] == 0)
450 {
451 num_of_regions++;
452 sGrid->mTab[px][py] = this;
453 }
454 }
455 }
456
457 if (num_of_regions == 0)
458 {
459 return TRUE;
460 }
461
462 if (drawable->getNumFaces() < 1)
463 {
464 drawable->addFace((LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER),
465 gWorldp->getDefaultWaterTexture());
466 }
467
468 LLFace *face;
469
470 face = drawable->getFace(0);
471 face->mCenterAgent = position_agent;
472
473 LLStrider<LLVector3> verticesp, normalsp;
474 LLStrider<LLVector2> texCoordsp;
475 U32 *indicesp;
476 S32 index_offset;
477
478 const F32 water_height = getRegion()->getWaterHeight();
479
480 const U32 steps_in_region = sGrid->mStepsInRegion / sGrid->mResDecrease;
481 const U32 num_quads = steps_in_region * steps_in_region * num_of_regions;
482
483 face->setPrimType(LLTriangles);
484 face->setSize(4*num_quads, 6*num_quads);
485 index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
486 if (-1 == index_offset)
487 {
488 return TRUE;
489 }
490
491 U32 num_of_vtx = 0;
492
493 for (py = patch_origy; py < patch_origy + patch_dimy; py++)
494 {
495 for (px = patch_origx; px < patch_origx + patch_dimx; px++)
496 {
497 if (!sGrid->mPatches[py * sGrid->mPatchRes + px].visible() || sGrid->mTab[px][py] != this)
498 {
499 continue;
500 }
501
502 U32 orig_indx = px * sGrid->mStepsInRegion;
503 U32 orig_indy = py * sGrid->mStepsInRegion;
504
505 for (U32 qy = 0; qy < steps_in_region; qy++)
506 {
507 for (U32 qx = 0; qx < steps_in_region; qx++)
508 {
509 const S32 x0 = orig_indx + qx * sGrid->mResDecrease;
510 const S32 y0 = orig_indy + qy * sGrid->mResDecrease;
511 const S32 x1 = x0 + sGrid->mResDecrease;
512 const S32 y1 = y0 + sGrid->mResDecrease;
513
514 sGrid->setVertex(x0, y1, water_height, *(verticesp));
515 verticesp++;
516 sGrid->setVertex(x0, y0, water_height, *(verticesp));
517 verticesp++;
518 sGrid->setVertex(x1, y1, water_height, *(verticesp));
519 verticesp++;
520 sGrid->setVertex(x1, y0, water_height, *(verticesp));
521 verticesp++;
522 /*
523 *(verticesp++) = sGrid->vtx(x0, y1, water_height);
524 *(verticesp++) = sGrid->vtx(x0, y0, water_height);
525 *(verticesp++) = sGrid->vtx(x1, y1, water_height);
526 *(verticesp++) = sGrid->vtx(x1, y0, water_height);
527 */
528 *(normalsp++) = sGrid->norm(x0, y1);
529 *(normalsp++) = sGrid->norm(x0, y0);
530 *(normalsp++) = sGrid->norm(x1, y1);
531 *(normalsp++) = sGrid->norm(x1, y0);
532
533 const S32 curr_index_offset = index_offset + num_of_vtx;
534
535 *indicesp++ = curr_index_offset + 0;
536 *indicesp++ = curr_index_offset + 1;
537 *indicesp++ = curr_index_offset + 2;
538
539 *indicesp++ = curr_index_offset + 1;
540 *indicesp++ = curr_index_offset + 3;
541 *indicesp++ = curr_index_offset + 2;
542 num_of_vtx += 4;
543 }
544 }
545 }
546 }
547
548
549 LLPipeline::sCompiles++;
550 return TRUE;
551}
552
553void LLVOWater::initClass()
554{
555 sGrid = new LLWaterGrid;
556}
557
558void LLVOWater::cleanupClass()
559{
560 if (sGrid)
561 {
562 sGrid->cleanup();
563 delete sGrid;
564 sGrid = 0;
565 }
566}
567
568
569LLWaterGrid::LLWaterGrid() : mResIncrease(1)//0.5)
570{
571 init();
572}
573
574
575void LLWaterGrid::init()
576{
577 //mRegionOrigin = LLVector3(-2 * mRegionWidth, -2 * mRegionWidth, 0);
578 mRegionWidth = 256;
579 mPatchRes = 5;
580 mMaxGridSize = mPatchRes * mRegionWidth;
581 mMinStep = (U32)(WAVE_STEP * mResIncrease);
582
583 LLWaterTri::sMinStep = mMinStep;
584 LLWaterTri::sQueues = &mRoam;
585
586 setGridDim(mMaxGridSize / mMinStep);
587
588 mVtx = new LLVector3[mGridDim1 * mGridDim1];
589 mNorms = new LLVector3[mGridDim1 * mGridDim1];
590
591 mPatches = new LLWaterPatch[mPatchRes * mPatchRes];
592
593 mStepsInRegion = mRegionWidth / mMinStep;
594 const U32 max_div_level = 2 * (U32)(log((F32)mStepsInRegion) / log(2.0f));
595
596 for (U32 y = 0; y < mPatchRes; y++)
597 {
598 for (U32 x = 0; x < mPatchRes; x++)
599 {
600 LLVector3 patch_center(mRegionWidth * (x + 0.5f), mRegionWidth * (y + 0.5f), 0);
601
602 mPatches[y * mPatchRes + x].set(x * mStepsInRegion, y * mStepsInRegion,
603 mStepsInRegion, mRegionWidth, patch_center, max_div_level);
604 if (x > 0)
605 {
606 mPatches[y * mPatchRes + x].left()->setRight(mPatches[y * mPatchRes + x - 1].right());
607 mPatches[y * mPatchRes + x - 1].right()->setRight(mPatches[y * mPatchRes + x].left());
608 }
609 if (y > 0)
610 {
611 mPatches[y * mPatchRes + x].left()->setLeft(mPatches[(y - 1) * mPatchRes + x].right());
612 mPatches[(y - 1) * mPatchRes + x].right()->setLeft(mPatches[y * mPatchRes + x].left());
613 }
614 }
615 }
616}
617
618void LLWaterGrid::cleanup()
619{
620 delete[] mVtx;
621 mVtx = NULL;
622
623 delete[] mNorms;
624 mNorms = NULL;
625
626 delete[] mPatches;
627 mPatches = NULL;
628}
629
630
631void setVecZ(LLVector3& v)
632{
633 v.mV[VX] = 0;
634 v.mV[VY] = 0;
635 v.mV[VZ] = 1;
636}
637
638void LLWaterGrid::update()
639{
640 static LLViewerRegion* prev_region = gAgent.getRegion();
641 LLViewerRegion* region = gAgent.getRegion();
642
643 mRegionOrigin = region->getOriginAgent();
644 mRegionOrigin.mV[VX] -= 2 * mRegionWidth;
645 mRegionOrigin.mV[VY] -= 2 * mRegionWidth;
646 mRegionOrigin.mV[VZ] = 0;
647
648 const F32 clip_far = gCamera->getFar() - 31;
649 const F32 clip_far2 = clip_far * clip_far;
650
651 const LLVector3 camera_pos = gAgent.getCameraPositionAgent();
652 const LLVector3 look_at = gCamera->getAtAxis();
653
654
655 if (camera_pos.mV[VZ] > 200)
656 {
657 mResDecrease = 4;
658 }
659 else if (camera_pos.mV[VZ] > 100)
660 {
661 mResDecrease = 2;
662 }
663 else
664 {
665 mResDecrease = 1;
666 }
667
668
669 //U32 mResDecrease = res_decrease;
670 U32 res_decrease = 1;
671
672 const F32 res_change = mResIncrease;// * res_decrease ;
673
674 F32 height;
675
676 // Set the grid
677
678 //U32 fractions = 1;
679 U32 fractions_res = res_decrease;
680 if (res_change < 1)
681 {
682 //fractions = llround(1. / res_change);
683 fractions_res = llround(1.f / mResIncrease);
684 }
685
686
687 //const U32 fractions_res = fractions * res_decrease;
688
689 LLVector3 cur_pos;
690 U32 x, y;
691 U32 ind = 0;
692 for (y = 0; y < mGridDim1; y += fractions_res)
693 {
694 const F32 dispy = (F32)(y * mMinStep);//step;
695 for (x = 0; x < mGridDim1; x += fractions_res)
696 {
697 const F32 dispx = (F32)(x * mMinStep);//step;
698 cur_pos = mRegionOrigin;
699 cur_pos.mV[VX] += dispx;
700 cur_pos.mV[VY] += dispy;
701
702 const F32 x_dist = cur_pos.mV[VX] - camera_pos.mV[VX];
703 const F32 y_dist = cur_pos.mV[VY] - camera_pos.mV[VY];
704
705 if (x_dist * look_at.mV[VX] + y_dist * look_at.mV[VY] < 0)
706 {
707 mVtx[ind] = cur_pos;
708 setVecZ(mNorms[ind]);
709 ind++;
710 continue;
711 }
712
713 const F32 dist_to_vtx2 = x_dist * x_dist + y_dist * y_dist;
714 if (dist_to_vtx2 > .81 * clip_far2)
715 {
716 mVtx[ind] = cur_pos;
717 setVecZ(mNorms[ind]);
718 ind++;
719 continue;
720 }
721
722 mWater.getIntegerHeightAndNormal(llround(WAVE_STEP_INV * dispx),
723 llround(WAVE_STEP_INV * dispy), height, mNorms[ind]);
724
725 cur_pos.mV[VZ] += height;
726 mVtx[ind] = cur_pos;
727 ind++;
728 }
729 }
730
731 if (res_change < 1)
732 {
733 U32 fractions = llround(1.f / mResIncrease);
734 for (y = 0; y < mGridDim1; y += fractions_res)
735 {
736 for (x = 0; x < mGridDim; x += fractions_res)
737 {
738 const U32 ind00 = index(x, y);
739 const U32 ind01 = ind00 + fractions_res;
740 for (U32 frx = 1; frx < fractions; frx += res_decrease)
741 {
742 const U32 ind = ind00 + frx;
743 mNorms[ind] = LERP(mNorms[ind00], mNorms[ind01], frx * res_change);
744 mVtx[ind] = LERP( mVtx[ind00], mVtx[ind01], frx * res_change);
745 }
746 }
747 }
748 for (x = 0; x < mGridDim1; x += res_decrease)
749 {
750 for (y = 0; y < mGridDim; y += fractions_res)
751 {
752 const U32 ind00 = index(x, y);
753 const U32 ind10 = ind00 + fractions_res * mGridDim1;//(y + fractions) * quad_resx1 + x;
754 for (U32 fry = 1; fry < fractions; fry += res_decrease)
755 {
756 const U32 ind = ind00 + fry * mGridDim1;//(y + fry) * quad_resx1 + x;
757 mNorms[ind] = LERP(mNorms[ind00], mNorms[ind10], fry * res_change);
758 mVtx[ind] = LERP( mVtx[ind00], mVtx[ind10], fry * res_change);
759 }
760 }
761 }
762 }
763
764 if (gUseRoam)
765 {
766 updateTree(camera_pos, look_at, clip_far, prev_region != region);
767 }
768 else
769 {
770 updateVisibility(camera_pos, look_at, clip_far);
771 }
772
773 prev_region = region;
774
775
776 //mTab[0][0] = 0;
777 for (y = 0; y < mPatchRes; y++)
778 {
779 for (x = 0; x < mPatchRes; x++)
780 mTab[x][y] = 0;
781 }
782
783}
784
785void LLWaterGrid::updateTree(const LLVector3 &camera_pos, const LLVector3 &look_at, F32 clip_far,
786 BOOL restart = FALSE)
787{
788 static S8 recalculate_frame = 0;
789
790 if (restart)
791 {
792 recalculate_frame = 0;
793 }
794
795 if (recalculate_frame == 0)
796 {
797 LLWaterTri::nextRound();
798 setCamPosition(LLWaterTri::sCam, camera_pos);
799 LLWaterTri::sClipFar = clip_far;
800
801
802 const U32 step = (U32)(WAVE_STEP * mResIncrease * mResDecrease);
803 const U32 steps_in_region = mRegionWidth / step;
804 LLWaterTri::sMaxDivLevel = 2 * llround(log((F32)steps_in_region) / log(2.0f));
805
806 for (U32 y = 0; y < mPatchRes; y++)
807 {
808 for (U32 x = 0; x < mPatchRes; x++)
809 {
810 U32 patch_ind = y * mPatchRes + x;
811 mPatches[patch_ind].updateTree(camera_pos, look_at, mRegionOrigin);
812 }
813 }
814
815 mRoam.process();
816
817 // debug
818 /*
819 for (y = 0; y < mPatchRes; y++)
820 {
821 for (U32 x = 0; x < mPatchRes; x++)
822 {
823 //mPatches[y * mPatchRes + x].checkUpToDate();
824 //mPatches[y * mPatchRes + x].checkConsistensy();
825 mPatches[y * mPatchRes + x].checkCount();
826 }
827 }
828 */
829 }
830 ++recalculate_frame;
831 recalculate_frame = recalculate_frame % 2;
832}
833
834void LLWaterGrid::updateVisibility(const LLVector3 &camera_pos, const LLVector3 &look_at, F32 clip_far)
835{
836 for (U32 y = 0; y < mPatchRes; y++)
837 {
838 for (U32 x = 0; x < mPatchRes; x++)
839 {
840 mPatches[y * mPatchRes + x].updateVisibility(camera_pos, look_at, mRegionOrigin);
841 }
842 }
843}
844
845
846void LLVOWater::setUseTexture(const BOOL use_texture)
847{
848 mUseTexture = use_texture;
849}
850
851F32 LLWaterSurface::agentDepth() const
852{
853 const LLViewerRegion* region = gAgent.getRegion();
854 LLVector3 position_agent = region->getOriginAgent();// getPositionAgent();
855 const LLVector3 region_origin = position_agent;
856 const LLVector3 camera_pos = gAgent.getCameraPositionAgent();
857
858 F32 height;
859 LLVector3 normal;
860
861 getHeightAndNormal(WAVE_STEP_INV * camera_pos.mV[VX],
862 WAVE_STEP_INV * camera_pos.mV[VY], height, normal);
863 F32 agent_water_height = gAgent.getRegion()->getWaterHeight();
864 return camera_pos.mV[VZ] - (agent_water_height + height);
865}
866
867////////////////////////////////////////////////
868
869
870void LLWaterSurface::getHeightAndNormal(F32 i, F32 j, F32& wave_height, LLVector3& normal) const
871{
872 S32 i_ind = llfloor(i);
873 S32 j_ind = llfloor(j);
874 F32 i_fr = i - i_ind;
875 F32 j_fr = j - j_ind;
876
877 i_ind = i_ind % N_RES;
878 j_ind = j_ind % N_RES;
879
880 S32 i_ind_next = i_ind + 1;
881 S32 j_ind_next = j_ind + 1;
882 if (i_ind_next == (S32)N_RES) i_ind_next = 0;
883 if (j_ind_next == (S32)N_RES) j_ind_next = 0;
884
885 const F32 i_fr1 = 1 - i_fr;
886 const F32 j_fr1 = 1 - j_fr;
887
888 const F32 hi0 = i_fr1 * height(i_ind, j_ind) + i_fr * height(i_ind_next, j_ind);
889 const F32 hi1 = i_fr1 * height(i_ind, j_ind_next) + i_fr * height(i_ind_next, j_ind_next);
890 wave_height = j_fr1 * hi0 + j_fr * hi1;
891
892 normal = i_fr1 * mNorms[i_ind][j_ind];
893 normal += i_fr * mNorms[i_ind_next][j_ind];
894 LLVector3 vi1 = i_fr1 * mNorms[i_ind][j_ind_next];
895 vi1 += i_fr * mNorms[i_ind_next][j_ind_next];
896 normal *= j_fr1;
897 normal += j_fr * vi1;
898
899 //normal.normVec();
900}
901
902void LLWaterSurface::getIntegerHeightAndNormal(S32 i, S32 j, F32& wave_height, LLVector3& normal) const
903{
904 S32 i_ind = i % N_RES;
905 S32 j_ind = j % N_RES;
906
907 wave_height = height(i_ind, j_ind);
908 normal = mNorms[i_ind][j_ind];
909}
910
911F32 LLWaterSurface::phillips(const LLVector2& k, const LLVector2& wind_n, F32 L, F32 L_small)
912{
913 F32 k2 = k * k;
914 F32 k_dot_wind = k * wind_n;
915 F32 spectrum = mA * (F32) exp(-1 / (L * L * k2)) / (k2 * k2) * (k_dot_wind * k_dot_wind / k2);
916
917 if (k_dot_wind < 0) spectrum *= .25f; // scale down waves that move opposite to the wind
918
919 F32 damp = (F32) exp(- k2 * L_small * L_small);
920
921 return (spectrum * damp);
922}
923
924
925
926void LLWaterSurface::initAmplitudes()
927{
928 U16 i, j;
929 LLVector2 k;
930 F32 sqrtPhillips;
931
932 const LLVector2 wind(mWind.mV);
933
934 LLVector2 wind_n = wind;
935 const F32 wind_vel = wind_n.normVec();
936
937 const F32 L = wind_vel * wind_vel / g; // largest wave arising from constant wind of speed wind_vel
938
939 const F32 L_small = L / 70; // eliminate waves with very small length (L_small << L)
940
941
942 for (i = 0; i <= N_RES; i++)
943 {
944 k.mV[VX] = (- (S32)N_RES_HALF + i) * (F_TWO_PI / WIDTH);
945 for (j = 0; j <= N_RES; j++)
946 {
947 k.mV[VY] = (- (S32)N_RES_HALF + j) * (F_TWO_PI / WIDTH);
948
949 const F32 k_mag = k.magVec();
950 mOmega[i][j] = (F32) sqrt(g * k_mag);
951
952 if (k_mag < F_APPROXIMATELY_ZERO)
953 sqrtPhillips = 0;
954 else
955 sqrtPhillips = (F32) sqrt(phillips(k, wind_n, L, L_small));
956
957 //const F32 r1 = rand() / (F32) RAND_MAX;
958 //const F32 r2 = rand() / (F32) RAND_MAX;
959 const F32 r1 = randGauss(0, 1);
960 const F32 r2 = randGauss(0, 1);
961
962 mHtilda0[i][j].re = sqrtPhillips * r1 * OO_SQRT2;
963 mHtilda0[i][j].im = sqrtPhillips * r2 * OO_SQRT2;
964
965 }
966 }
967
968 mPlan.init(N_RES, N_RES);
969 mInitialized = 1; // initialization complete
970}
971
972void LLWaterSurface::generateWaterHeightField(F64 t)
973{
974 S32 i, j;
975 S32 mi, mj; // -K indices
976 COMPLEX plus, minus;
977
978 if (!mInitialized) initAmplitudes();
979
980 for (i = 0; i < (S32)N_RES_HALF; i++)
981 {
982 mi = N_RES - i;
983 for (j = 0; j < (S32)N_RES ; j++)
984 {
985 mj = N_RES - j;
986
987 const F32 cos_wt = cosf(mOmega[i][j] * t); // = cos(-mOmega[i][j] * t)
988 const F32 sin_wt = sinf(mOmega[i][j] * t); // = -sin(-mOmega[i][j] * t)
989 plus.re = mHtilda0[i][j].re * cos_wt - mHtilda0[i][j].im * sin_wt;
990 plus.im = mHtilda0[i][j].re * sin_wt + mHtilda0[i][j].im * cos_wt;
991 minus.re = mHtilda0[mi][mj].re * cos_wt - mHtilda0[mi][mj].im * sin_wt;
992 minus.im = -mHtilda0[mi][mj].re * sin_wt - mHtilda0[mi][mj].im * cos_wt;
993
994 // now sum the plus and minus waves to get the total wave amplitude h
995 mHtilda[i * N_RES + j].re = plus.re + minus.re;
996 mHtilda[i * N_RES + j].im = plus.im + minus.im;
997 if (mi < (S32)N_RES && mj < (S32)N_RES)
998 {
999 mHtilda[mi * N_RES + mj].re = plus.re + minus.re;
1000 mHtilda[mi * N_RES + mj].im = -plus.im - minus.im;
1001 }
1002 }
1003 }
1004
1005 inverse_fft(mPlan, mHtilda, N_RES, N_RES);
1006
1007 calcNormals();
1008}
1009
1010
1011/*
1012 * Computer normals by taking finite differences.
1013 */
1014
1015void LLWaterSurface::calcNormals()
1016{
1017 LLVector3 n;
1018
1019 for (U32 i = 0; i < N_RES; i++)
1020 {
1021 for (U32 j = 0; j < N_RES; j++)
1022 {
1023 F32 px = heightWrapped(i + 1, j);
1024 F32 mx = heightWrapped(i - 1, j);
1025 F32 py = heightWrapped(i, j + 1);
1026 F32 my = heightWrapped(i, j - 1);
1027 F32 pxpy = heightWrapped(i + 1, j + 1);
1028 F32 pxmy = heightWrapped(i + 1, j - 1);
1029 F32 mxpy = heightWrapped(i - 1, j + 1);
1030 F32 mxmy = heightWrapped(i - 1, j - 1);
1031
1032 n.mV[VX] = -((2 * px + pxpy + pxmy) - (2 * mx + mxpy + mxmy));
1033 n.mV[VY] = -((2 * py + pxpy + mxpy) - (2 * my + pxmy + mxmy));
1034 n.mV[VZ] = 8 * WIDTH / (F32) N_RES;
1035 n.normVec();
1036
1037 mNorms[i][j] = n;
1038 }
1039 }
1040}
1041
1042void LLVOWater::generateNewWaves(F64 time)
1043{
1044 getWaterSurface()->generateWaterHeightField(time);
1045 sGrid->update();
1046}
1047