aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llvowater.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:50 -0500
committerJacek Antonelli2008-08-15 23:44:50 -0500
commit89fe5dab825a62a0e3fd8d248cbc91c65eb2a426 (patch)
treebcff14b7888d04a2fec799c59369f6095224bd08 /linden/indra/newview/llvowater.cpp
parentSecond Life viewer sources 1.13.3.2 (diff)
downloadmeta-impy-89fe5dab825a62a0e3fd8d248cbc91c65eb2a426.zip
meta-impy-89fe5dab825a62a0e3fd8d248cbc91c65eb2a426.tar.gz
meta-impy-89fe5dab825a62a0e3fd8d248cbc91c65eb2a426.tar.bz2
meta-impy-89fe5dab825a62a0e3fd8d248cbc91c65eb2a426.tar.xz
Second Life viewer sources 1.14.0.0
Diffstat (limited to 'linden/indra/newview/llvowater.cpp')
-rw-r--r--linden/indra/newview/llvowater.cpp830
1 files changed, 36 insertions, 794 deletions
diff --git a/linden/indra/newview/llvowater.cpp b/linden/indra/newview/llvowater.cpp
index 55a7020..a57aa8b 100644
--- a/linden/indra/newview/llvowater.cpp
+++ b/linden/indra/newview/llvowater.cpp
@@ -64,22 +64,8 @@ const F32 WAVE_STEP_INV = (1. / WAVE_STEP);
64 64
65const F32 g = 9.81f; // gravitational constant (m/s^2) 65const F32 g = 9.81f; // gravitational constant (m/s^2)
66 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) 67LLVOWater::LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
82: LLViewerObject(id, LL_VO_WATER, regionp) 68: LLStaticViewerObject(id, LL_VO_WATER, regionp)
83{ 69{
84 // Terrain must draw during selection passes so it can block objects behind it. 70 // Terrain must draw during selection passes so it can block objects behind it.
85 mbCanSelect = FALSE; 71 mbCanSelect = FALSE;
@@ -113,18 +99,6 @@ void LLVOWater::updateTextures(LLAgent &agent)
113{ 99{
114} 100}
115 101
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 102// Never gets called
129BOOL LLVOWater::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) 103BOOL LLVOWater::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
130{ 104{
@@ -161,17 +135,13 @@ LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline)
161 135
162BOOL LLVOWater::updateGeometry(LLDrawable *drawable) 136BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
163{ 137{
164 return updateGeometryFlat(drawable); 138 LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WATER);
165}
166
167
168BOOL LLVOWater::updateGeometryFlat(LLDrawable *drawable)
169{
170 LLFace *face; 139 LLFace *face;
171 140
172 if (drawable->getNumFaces() < 1) 141 if (drawable->getNumFaces() < 1)
173 { 142 {
174 drawable->addFace(gPipeline.getPool(LLDrawPool::POOL_WATER), NULL); 143 LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
144 drawable->addFace(poolp, NULL);
175 } 145 }
176 face = drawable->getFace(0); 146 face = drawable->getFace(0);
177 147
@@ -180,15 +150,26 @@ BOOL LLVOWater::updateGeometryFlat(LLDrawable *drawable)
180 150
181 LLStrider<LLVector3> verticesp, normalsp; 151 LLStrider<LLVector3> verticesp, normalsp;
182 LLStrider<LLVector2> texCoordsp; 152 LLStrider<LLVector2> texCoordsp;
183 U32 *indicesp; 153 LLStrider<U32> indicesp;
184 S32 index_offset; 154 S32 index_offset;
185 155
186 S32 size = 16; 156 S32 size = 16;
187 157
188 S32 num_quads = size*size; 158 if (face->mVertexBuffer.isNull())
189 159 {
190 face->setPrimType(LLTriangles); 160 S32 num_quads = size*size;
191 face->setSize(4*num_quads, 6*num_quads); 161 face->setSize(4*num_quads, 6*num_quads);
162
163 face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
164 face->mVertexBuffer->allocateBuffer(4*num_quads, 6*num_quads, TRUE);
165 face->setIndicesIndex(0);
166 face->setGeomIndex(0);
167 }
168 else
169 {
170 face->mVertexBuffer->resizeBuffer(face->getGeomCount(), face->getIndicesCount());
171 }
172
192 index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); 173 index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
193 if (-1 == index_offset) 174 if (-1 == index_offset)
194 { 175 {
@@ -198,6 +179,7 @@ BOOL LLVOWater::updateGeometryFlat(LLDrawable *drawable)
198 LLVector3 position_agent; 179 LLVector3 position_agent;
199 position_agent = getPositionAgent(); 180 position_agent = getPositionAgent();
200 face->mCenterAgent = position_agent; 181 face->mCenterAgent = position_agent;
182 face->mCenterLocal = position_agent;
201 183
202 S32 x, y; 184 S32 x, y;
203 F32 step_x = getScale().mV[0] / size; 185 F32 step_x = getScale().mV[0] / size;
@@ -256,378 +238,20 @@ BOOL LLVOWater::updateGeometryFlat(LLDrawable *drawable)
256 *indicesp++ = toffset + 2; 238 *indicesp++ = toffset + 2;
257 } 239 }
258 } 240 }
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 241
348 face->setPrimType(LLTriangles); 242 mDrawable->movePartition();
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++; 243 LLPipeline::sCompiles++;
550 return TRUE; 244 return TRUE;
551} 245}
552 246
553void LLVOWater::initClass() 247void LLVOWater::initClass()
554{ 248{
555 sGrid = new LLWaterGrid;
556} 249}
557 250
558void LLVOWater::cleanupClass() 251void LLVOWater::cleanupClass()
559{ 252{
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} 253}
573 254
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) 255void setVecZ(LLVector3& v)
632{ 256{
633 v.mV[VX] = 0; 257 v.mV[VX] = 0;
@@ -635,413 +259,31 @@ void setVecZ(LLVector3& v)
635 v.mV[VZ] = 1; 259 v.mV[VZ] = 1;
636} 260}
637 261
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) 262void LLVOWater::setUseTexture(const BOOL use_texture)
847{ 263{
848 mUseTexture = use_texture; 264 mUseTexture = use_texture;
849} 265}
850 266
851F32 LLWaterSurface::agentDepth() const 267void LLVOWater::updateSpatialExtents(LLVector3 &newMin, LLVector3& newMax)
852{ 268{
853 const LLViewerRegion* region = gAgent.getRegion(); 269 LLVector3 pos = getPositionAgent();
854 LLVector3 position_agent = region->getOriginAgent();// getPositionAgent(); 270 LLVector3 scale = getScale();
855 const LLVector3 region_origin = position_agent;
856 const LLVector3 camera_pos = gAgent.getCameraPositionAgent();
857 271
858 F32 height; 272 newMin = pos - scale * 0.5f;
859 LLVector3 normal; 273 newMax = pos + scale * 0.5f;
860 274
861 getHeightAndNormal(WAVE_STEP_INV * camera_pos.mV[VX], 275 mDrawable->setPositionGroup((newMin + newMax) * 0.5f);
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} 276}
866 277
867//////////////////////////////////////////////// 278U32 LLVOWater::getPartitionType() const
868 279{
869 280 return LLPipeline::PARTITION_WATER;
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} 281}
910 282
911F32 LLWaterSurface::phillips(const LLVector2& k, const LLVector2& wind_n, F32 L, F32 L_small) 283LLWaterPartition::LLWaterPartition()
284: LLSpatialPartition(0)
912{ 285{
913 F32 k2 = k * k; 286 mRenderByGroup = FALSE;
914 F32 k_dot_wind = k * wind_n; 287 mDrawableType = LLPipeline::RENDER_TYPE_WATER;
915 F32 spectrum = mA * (F32) exp(-1 / (L * L * k2)) / (k2 * k2) * (k_dot_wind * k_dot_wind / k2); 288 mPartitionType = LLPipeline::PARTITION_WATER;
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} 289}
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