aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llsurface.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/llsurface.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 '')
-rw-r--r--linden/indra/newview/llsurface.cpp1356
1 files changed, 1356 insertions, 0 deletions
diff --git a/linden/indra/newview/llsurface.cpp b/linden/indra/newview/llsurface.cpp
new file mode 100644
index 0000000..c1b22c9
--- /dev/null
+++ b/linden/indra/newview/llsurface.cpp
@@ -0,0 +1,1356 @@
1/**
2 * @file llsurface.cpp
3 * @brief Implementation of LLSurface class
4 *
5 * Copyright (c) 2000-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 "llsurface.h"
31
32#include "llviewerimagelist.h"
33#include "llpatchvertexarray.h"
34#include "patch_dct.h"
35#include "patch_code.h"
36#include "bitpack.h"
37#include "llviewerobjectlist.h"
38#include "llregionhandle.h"
39#include "llagent.h"
40#include "viewer.h"
41#include "llworld.h"
42#include "llviewercontrol.h"
43#include "llviewerimage.h"
44#include "llsurfacepatch.h"
45#include "llvosurfacepatch.h"
46#include "llvowater.h"
47#include "pipeline.h"
48#include "llviewerregion.h"
49#include "llvlcomposition.h"
50#include "noise.h"
51#include "llviewercamera.h"
52#include "llglheaders.h"
53#include "lldrawpool.h"
54#include "lldrawable.h"
55
56extern LLPipeline gPipeline;
57
58LLColor4U MAX_WATER_COLOR(0, 48, 96, 240);
59
60
61S32 LLSurface::sTextureSize = 256;
62S32 LLSurface::sTexelsUpdated = 0;
63F32 LLSurface::sTextureUpdateTime = 0.f;
64LLStat LLSurface::sTexelsUpdatedPerSecStat;
65
66extern void bad_network_handler();
67
68// ---------------- LLSurface:: Public Members ---------------
69
70LLSurface::LLSurface(U32 type, LLViewerRegion *regionp) :
71 mGridsPerEdge(0),
72 mOOGridsPerEdge(0.f),
73 mPatchesPerEdge(0),
74 mType(type),
75 mOriginGlobal(0.0, 0.0, 0.0),
76 mSTexturep(NULL),
77 mWaterTexturep(NULL),
78 mGridsPerPatchEdge(0),
79 mMetersPerGrid(1.0f),
80 mMetersPerEdge(1.0f),
81 mRegionp(regionp)
82{
83 // Surface data
84 mSurfaceZ = NULL;
85 mNorm = NULL;
86
87 // Patch data
88 mPatchList = NULL;
89
90 // One of each for each camera
91 mVisiblePatchCount = 0;
92
93 mHasZData = FALSE;
94 // "uninitialized" min/max z
95 mMinZ = 10000.f;
96 mMaxZ = -10000.f;
97
98 mWaterObjp = NULL;
99
100 // In here temporarily.
101 mSurfacePatchUpdateCount = 0;
102
103 for (S32 i = 0; i < 8; i++)
104 {
105 mNeighbors[i] = NULL;
106 }
107}
108
109
110LLSurface::~LLSurface()
111{
112 delete [] mSurfaceZ;
113 mSurfaceZ = NULL;
114
115 delete [] mNorm;
116
117 mGridsPerEdge = 0;
118 mGridsPerPatchEdge = 0;
119 mPatchesPerEdge = 0;
120 mNumberOfPatches = 0;
121 destroyPatchData();
122
123 LLDrawPool *poolp = gPipeline.findPool(LLDrawPool::POOL_TERRAIN, mSTexturep);
124 if (!poolp)
125 {
126 llwarns << "No pool for terrain on destruction!" << llendl;
127 }
128 else if (poolp->mReferences.empty())
129 {
130 gPipeline.removePool(poolp);
131 // Don't enable this until we blitz the draw pool for it as well. -- djs
132 if (mSTexturep)
133 {
134 gImageList.deleteImage(mSTexturep);
135 mSTexturep = NULL;
136 }
137 if (mWaterTexturep)
138 {
139 gImageList.deleteImage(mWaterTexturep);
140 mWaterTexturep = NULL;
141 }
142 }
143 else
144 {
145 llerrs << "Terrain pool not empty!" << llendl;
146 }
147}
148
149void LLSurface::initClasses()
150{
151}
152
153void LLSurface::setRegion(LLViewerRegion *regionp)
154{
155 mRegionp = regionp;
156}
157
158// Assumes that arguments are powers of 2, and that
159// grids_per_edge / grids_per_patch_edge = power of 2
160void LLSurface::create(const S32 grids_per_edge,
161 const S32 grids_per_patch_edge,
162 const LLVector3d &origin_global,
163 const F32 width)
164{
165 // Initialize various constants for the surface
166 mGridsPerEdge = grids_per_edge + 1; // Add 1 for the east and north buffer
167 mOOGridsPerEdge = 1.f / mGridsPerEdge;
168 mGridsPerPatchEdge = grids_per_patch_edge;
169 mPatchesPerEdge = (mGridsPerEdge - 1) / mGridsPerPatchEdge;
170 mNumberOfPatches = mPatchesPerEdge * mPatchesPerEdge;
171 mMetersPerGrid = width / ((F32)(mGridsPerEdge - 1));
172 mMetersPerEdge = mMetersPerGrid * (mGridsPerEdge - 1);
173
174 mOriginGlobal.setVec(origin_global);
175
176 mPVArray.create(mGridsPerEdge, mGridsPerPatchEdge, gWorldPointer->getRegionScale());
177
178 S32 number_of_grids = mGridsPerEdge * mGridsPerEdge;
179
180 /////////////////////////////////////
181 //
182 // Initialize data arrays for surface
183 ///
184 mSurfaceZ = new F32[number_of_grids];
185 mNorm = new LLVector3[number_of_grids];
186
187 // Reset the surface to be a flat square grid
188 for(S32 i=0; i < number_of_grids; i++)
189 {
190 // Surface is flat and zero
191 // Normals all point up
192 mSurfaceZ[i] = 0.0f;
193 mNorm[i].setVec(0.f, 0.f, 1.f);
194 }
195
196
197 mVisiblePatchCount = 0;
198
199
200 ///////////////////////
201 //
202 // Initialize textures
203 //
204
205 initTextures();
206
207 // Has to be done after texture initialization
208 createPatchData();
209}
210
211LLViewerImage* LLSurface::getSTexture()
212{
213 if (mSTexturep.notNull() && !mSTexturep->getHasGLTexture())
214 {
215 createSTexture();
216 }
217 return mSTexturep;
218}
219
220LLViewerImage* LLSurface::getWaterTexture()
221{
222 if (mWaterTexturep.notNull() && !mWaterTexturep->getHasGLTexture())
223 {
224 createWaterTexture();
225 }
226 return mWaterTexturep;
227}
228
229void LLSurface::createSTexture()
230{
231 if (!mSTexturep)
232 {
233 // Fill with dummy gray data.
234 LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize, sTextureSize, 3);
235 U8 *default_texture = raw->getData();
236 for (S32 i = 0; i < sTextureSize; i++)
237 {
238 for (S32 j = 0; j < sTextureSize; j++)
239 {
240 *(default_texture + (i*sTextureSize + j)*3) = 128;
241 *(default_texture + (i*sTextureSize + j)*3 + 1) = 128;
242 *(default_texture + (i*sTextureSize + j)*3 + 2) = 128;
243 }
244 }
245
246 mSTexturep = new LLViewerImage(raw, FALSE);
247 mSTexturep->dontDiscard();
248 mSTexturep->bind();
249 mSTexturep->setClamp(TRUE, TRUE);
250 gImageList.addImage(mSTexturep);
251 }
252}
253
254void LLSurface::createWaterTexture()
255{
256 if (!mWaterTexturep)
257 {
258 // Create the water texture
259 LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize/2, sTextureSize/2, 4);
260 U8 *default_texture = raw->getData();
261 for (S32 i = 0; i < sTextureSize/2; i++)
262 {
263 for (S32 j = 0; j < sTextureSize/2; j++)
264 {
265 *(default_texture + (i*sTextureSize/2 + j)*4) = MAX_WATER_COLOR.mV[0];
266 *(default_texture + (i*sTextureSize/2 + j)*4 + 1) = MAX_WATER_COLOR.mV[1];
267 *(default_texture + (i*sTextureSize/2 + j)*4 + 2) = MAX_WATER_COLOR.mV[2];
268 *(default_texture + (i*sTextureSize/2 + j)*4 + 3) = MAX_WATER_COLOR.mV[3];
269 }
270 }
271 mWaterTexturep = new LLViewerImage(raw, FALSE);
272 mWaterTexturep->dontDiscard();
273 mWaterTexturep->bind();
274 mWaterTexturep->setClamp(TRUE, TRUE);
275 gImageList.addImage(mWaterTexturep);
276 }
277}
278
279void LLSurface::initTextures()
280{
281 ///////////////////////
282 //
283 // Main surface texture
284 //
285 createSTexture();
286
287 ///////////////////////
288 //
289 // Water texture
290 //
291 if (gSavedSettings.getBOOL("RenderWater") )
292 {
293 createWaterTexture();
294 mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp);
295 gPipeline.addObject(mWaterObjp);
296 LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle());
297 water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT);
298 mWaterObjp->setPositionGlobal(water_pos_global);
299 }
300}
301
302
303void LLSurface::setOriginGlobal(const LLVector3d &origin_global)
304{
305 LLVector3d new_origin_global;
306 mOriginGlobal = origin_global;
307 LLSurfacePatch *patchp;
308 S32 i, j;
309 // Need to update the southwest corners of the patches
310 for (j=0; j<mPatchesPerEdge; j++)
311 {
312 for (i=0; i<mPatchesPerEdge; i++)
313 {
314 patchp = getPatch(i, j);
315
316 new_origin_global = patchp->getOriginGlobal();
317
318 new_origin_global.mdV[0] = mOriginGlobal.mdV[0] + i * mMetersPerGrid * mGridsPerPatchEdge;
319 new_origin_global.mdV[1] = mOriginGlobal.mdV[1] + j * mMetersPerGrid * mGridsPerPatchEdge;
320 patchp->setOriginGlobal(new_origin_global);
321 }
322 }
323
324 // Hack!
325 if (mWaterObjp.notNull() && mWaterObjp->mDrawable.notNull())
326 {
327 const F64 x = origin_global.mdV[VX] + 128.0;
328 const F64 y = origin_global.mdV[VY] + 128.0;
329 const F64 z = mWaterObjp->getPositionGlobal().mdV[VZ];
330
331 LLVector3d water_origin_global(x, y, z);
332
333 mWaterObjp->setPositionGlobal(water_origin_global);
334 gPipeline.markMoved(mWaterObjp->mDrawable);
335 }
336}
337
338
339void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
340{
341 S32 i;
342 LLSurfacePatch *patchp, *neighbor_patchp;
343
344 if (gNoRender)
345 {
346 return;
347 }
348
349 mNeighbors[direction] = neighborp;
350 neighborp->mNeighbors[gDirOpposite[direction]] = this;
351
352 // Connect patches
353 if (NORTHEAST == direction)
354 {
355 patchp = getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1);
356 neighbor_patchp = neighborp->getPatch(0, 0);
357
358 patchp->connectNeighbor(neighbor_patchp, direction);
359 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
360
361 patchp->updateNorthEdge(); // Only update one of north or east.
362 patchp->dirtyZ();
363 }
364 else if (NORTHWEST == direction)
365 {
366 patchp = getPatch(0, mPatchesPerEdge - 1);
367 neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, 0);
368
369 patchp->connectNeighbor(neighbor_patchp, direction);
370 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
371 }
372 else if (SOUTHWEST == direction)
373 {
374 patchp = getPatch(0, 0);
375 neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1);
376
377 patchp->connectNeighbor(neighbor_patchp, direction);
378 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
379
380 neighbor_patchp->updateNorthEdge(); // Only update one of north or east.
381 neighbor_patchp->dirtyZ();
382 }
383 else if (SOUTHEAST == direction)
384 {
385 patchp = getPatch(mPatchesPerEdge - 1, 0);
386 neighbor_patchp = neighborp->getPatch(0, mPatchesPerEdge - 1);
387
388 patchp->connectNeighbor(neighbor_patchp, direction);
389 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
390 }
391 else if (EAST == direction)
392 {
393 // Do east/west connections, first
394 for (i = 0; i < (S32)mPatchesPerEdge; i++)
395 {
396 patchp = getPatch(mPatchesPerEdge - 1, i);
397 neighbor_patchp = neighborp->getPatch(0, i);
398
399 patchp->connectNeighbor(neighbor_patchp, direction);
400 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
401
402 patchp->updateEastEdge();
403 patchp->dirtyZ();
404 }
405
406 // Now do northeast/southwest connections
407 for (i = 0; i < (S32)mPatchesPerEdge - 1; i++)
408 {
409 patchp = getPatch(mPatchesPerEdge - 1, i);
410 neighbor_patchp = neighborp->getPatch(0, i+1);
411
412 patchp->connectNeighbor(neighbor_patchp, NORTHEAST);
413 neighbor_patchp->connectNeighbor(patchp, SOUTHWEST);
414 }
415 // Now do southeast/northwest connections
416 for (i = 1; i < (S32)mPatchesPerEdge; i++)
417 {
418 patchp = getPatch(mPatchesPerEdge - 1, i);
419 neighbor_patchp = neighborp->getPatch(0, i-1);
420
421 patchp->connectNeighbor(neighbor_patchp, SOUTHEAST);
422 neighbor_patchp->connectNeighbor(patchp, NORTHWEST);
423 }
424 }
425 else if (NORTH == direction)
426 {
427 // Do north/south connections, first
428 for (i = 0; i < (S32)mPatchesPerEdge; i++)
429 {
430 patchp = getPatch(i, mPatchesPerEdge - 1);
431 neighbor_patchp = neighborp->getPatch(i, 0);
432
433 patchp->connectNeighbor(neighbor_patchp, direction);
434 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
435
436 patchp->updateNorthEdge();
437 patchp->dirtyZ();
438 }
439
440 // Do northeast/southwest connections
441 for (i = 0; i < (S32)mPatchesPerEdge - 1; i++)
442 {
443 patchp = getPatch(i, mPatchesPerEdge - 1);
444 neighbor_patchp = neighborp->getPatch(i+1, 0);
445
446 patchp->connectNeighbor(neighbor_patchp, NORTHEAST);
447 neighbor_patchp->connectNeighbor(patchp, SOUTHWEST);
448 }
449 // Do southeast/northwest connections
450 for (i = 1; i < (S32)mPatchesPerEdge; i++)
451 {
452 patchp = getPatch(i, mPatchesPerEdge - 1);
453 neighbor_patchp = neighborp->getPatch(i-1, 0);
454
455 patchp->connectNeighbor(neighbor_patchp, NORTHWEST);
456 neighbor_patchp->connectNeighbor(patchp, SOUTHEAST);
457 }
458 }
459 else if (WEST == direction)
460 {
461 // Do east/west connections, first
462 for (i = 0; i < mPatchesPerEdge; i++)
463 {
464 patchp = getPatch(0, i);
465 neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i);
466
467 patchp->connectNeighbor(neighbor_patchp, direction);
468 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
469
470 neighbor_patchp->updateEastEdge();
471 neighbor_patchp->dirtyZ();
472 }
473
474 // Now do northeast/southwest connections
475 for (i = 1; i < mPatchesPerEdge; i++)
476 {
477 patchp = getPatch(0, i);
478 neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i - 1);
479
480 patchp->connectNeighbor(neighbor_patchp, SOUTHWEST);
481 neighbor_patchp->connectNeighbor(patchp, NORTHEAST);
482 }
483
484 // Now do northwest/southeast connections
485 for (i = 0; i < mPatchesPerEdge - 1; i++)
486 {
487 patchp = getPatch(0, i);
488 neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i + 1);
489
490 patchp->connectNeighbor(neighbor_patchp, NORTHWEST);
491 neighbor_patchp->connectNeighbor(patchp, SOUTHEAST);
492 }
493 }
494 else if (SOUTH == direction)
495 {
496 // Do north/south connections, first
497 for (i = 0; i < mPatchesPerEdge; i++)
498 {
499 patchp = getPatch(i, 0);
500 neighbor_patchp = neighborp->getPatch(i, mPatchesPerEdge - 1);
501
502 patchp->connectNeighbor(neighbor_patchp, direction);
503 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
504
505 neighbor_patchp->updateNorthEdge();
506 neighbor_patchp->dirtyZ();
507 }
508
509 // Now do northeast/southwest connections
510 for (i = 1; i < mPatchesPerEdge; i++)
511 {
512 patchp = getPatch(i, 0);
513 neighbor_patchp = neighborp->getPatch(i - 1, mPatchesPerEdge - 1);
514
515 patchp->connectNeighbor(neighbor_patchp, SOUTHWEST);
516 neighbor_patchp->connectNeighbor(patchp, NORTHEAST);
517 }
518 // Now do northeast/southwest connections
519 for (i = 0; i < mPatchesPerEdge - 1; i++)
520 {
521 patchp = getPatch(i, 0);
522 neighbor_patchp = neighborp->getPatch(i + 1, mPatchesPerEdge - 1);
523
524 patchp->connectNeighbor(neighbor_patchp, SOUTHEAST);
525 neighbor_patchp->connectNeighbor(patchp, NORTHWEST);
526 }
527 }
528}
529
530void LLSurface::disconnectNeighbor(LLSurface *surfacep)
531{
532 S32 i;
533 for (i = 0; i < 8; i++)
534 {
535 if (surfacep == mNeighbors[i])
536 {
537 mNeighbors[i] = NULL;
538 }
539 }
540
541 // Iterate through surface patches, removing any connectivity to removed surface.
542 for (i = 0; i < mNumberOfPatches; i++)
543 {
544 (mPatchList + i)->disconnectNeighbor(surfacep);
545 }
546}
547
548
549void LLSurface::disconnectAllNeighbors()
550{
551 S32 i;
552 for (i = 0; i < 8; i++)
553 {
554 if (mNeighbors[i])
555 {
556 mNeighbors[i]->disconnectNeighbor(this);
557 mNeighbors[i] = NULL;
558 }
559 }
560}
561
562
563
564const LLVector3d &LLSurface::getOriginGlobal() const
565{
566 return mOriginGlobal;
567}
568
569LLVector3 LLSurface::getOriginAgent() const
570{
571 return gAgent.getPosAgentFromGlobal(mOriginGlobal);
572}
573
574F32 LLSurface::getMetersPerGrid() const
575{
576 return mMetersPerGrid;
577}
578
579S32 LLSurface::getGridsPerEdge() const
580{
581 return mGridsPerEdge;
582}
583
584S32 LLSurface::getPatchesPerEdge() const
585{
586 return mPatchesPerEdge;
587}
588
589S32 LLSurface::getGridsPerPatchEdge() const
590{
591 return mGridsPerPatchEdge;
592}
593
594void LLSurface::moveZ(const S32 x, const S32 y, const F32 delta)
595{
596 llassert(x >= 0);
597 llassert(y >= 0);
598 llassert(x < mGridsPerEdge);
599 llassert(y < mGridsPerEdge);
600 mSurfaceZ[x + y*mGridsPerEdge] += delta;
601}
602
603
604void LLSurface::updatePatchVisibilities(LLAgent &agent)
605{
606 LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(gAgent.getCameraPositionGlobal());
607
608 LLSurfacePatch *patchp;
609
610 mVisiblePatchCount = 0;
611 for (S32 i=0; i<mNumberOfPatches; i++)
612 {
613 patchp = mPatchList + i;
614
615 patchp->updateVisibility();
616 if (patchp->getVisible())
617 {
618 mVisiblePatchCount++;
619 patchp->updateCameraDistanceRegion(pos_region);
620 }
621 }
622}
623
624
625
626BOOL LLSurface::idleUpdate()
627{
628 if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TERRAIN))
629 {
630 return TRUE;
631 }
632
633 // Perform idle time update of non-critical stuff.
634 // In this case, texture and normal updates.
635 LLTimer update_timer;
636 LLSurfacePatch *patchp = NULL;
637
638 // If the Z height data has changed, we need to rebuild our
639 // property line vertex arrays.
640 if (mDirtyPatchList.count() > 0)
641 {
642 getRegion()->dirtyHeights();
643 }
644
645 S32 i = 0;
646 while (i < mDirtyPatchList.count())
647 {
648 patchp = mDirtyPatchList[i];
649 patchp->updateNormals();
650 patchp->updateVerticalStats();
651
652 if ((update_timer.getElapsedTimeF32() < 0.05f) && patchp->updateTexture())
653 {
654 patchp->clearDirty();
655 mDirtyPatchList.remove(i);
656 }
657 else
658 {
659 i++;
660 }
661 }
662 return TRUE;
663}
664
665// TODO -- move this to LLViewerRegion class
666void LLSurface::renderSurfaceBounds()
667{
668 // Shows the edge of the surface, so that visibility across regions can be seen
669 LLVector3 origin_agent = getOriginAgent();
670
671 glPushMatrix();
672 LLGLSNoTexture no_texture;
673
674 F32 region_width_meters = gWorldPointer->getRegionWidthInMeters();
675 glTranslatef(origin_agent.mV[VX] + (region_width_meters * 0.005f),
676 origin_agent.mV[VY] + (region_width_meters * 0.005f), 0.f);
677
678 glColor4ub(0, 128, 0, 64);
679
680 F32 length = region_width_meters * 0.995f;
681 F32 height = length/8.0f;
682
683 glBegin(GL_QUADS);
684 glVertex3f(length, 0, 0);
685 glVertex3f(0,0, 0);
686 glVertex3f(0,0, height);
687 glVertex3f(length,0, height);
688
689 glVertex3f(length,0, height);
690 glVertex3f(0,0, height);
691 glVertex3f(0,0, 0);
692 glVertex3f(length, 0, 0);
693 glEnd();
694
695 glTranslatef(length, 0, 0);
696 glRotated(90, 0, 0, 1);
697 glBegin(GL_QUADS);
698 glVertex3f(length, 0, 0);
699 glVertex3f(0,0, 0);
700 glVertex3f(0,0, height);
701 glVertex3f(length,0, height);
702
703 glVertex3f(length,0, height);
704 glVertex3f(0,0, height);
705 glVertex3f(0,0, 0);
706 glVertex3f(length, 0, 0);
707
708 glEnd();
709 glTranslatef(length, 0, 0);
710 glRotated(90, 0, 0, 1);
711 glBegin(GL_QUADS);
712 glVertex3f(length, 0, 0);
713 glVertex3f(0,0, 0);
714 glVertex3f(0,0, height);
715 glVertex3f(length,0, height);
716
717 glVertex3f(length,0, height);
718 glVertex3f(0,0, height);
719 glVertex3f(0,0, 0);
720 glVertex3f(length, 0, 0);
721 glEnd();
722 glTranslatef(length, 0, 0);
723 glRotated(90, 0, 0, 1);
724 glBegin(GL_QUADS);
725 glVertex3f(length, 0, 0);
726 glVertex3f(0,0, 0);
727 glVertex3f(0,0, height);
728 glVertex3f(length,0, height);
729
730 glVertex3f(length,0, height);
731 glVertex3f(0,0, height);
732 glVertex3f(0,0, 0);
733 glVertex3f(length, 0, 0);
734 glEnd();
735 glTranslatef(length, 0, 0);
736 glRotated(90, 0, 0, 1);
737
738 glPopMatrix();
739}
740
741
742void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL b_large_patch)
743{
744
745 LLPatchHeader ph;
746 S32 j, i;
747 S32 patch[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
748 LLSurfacePatch *patchp;
749
750 init_patch_decompressor(gopp->patch_size);
751 gopp->stride = mGridsPerEdge;
752 set_group_of_patch_header(gopp);
753
754 while (1)
755 {
756 decode_patch_header(bitpack, &ph);
757 if (ph.quant_wbits == END_OF_PATCHES)
758 {
759 break;
760 }
761
762 i = ph.patchids >> 5;
763 j = ph.patchids & 0x1F;
764
765 if ((i >= mPatchesPerEdge) || (j >= mPatchesPerEdge))
766 {
767 llwarns << "Received invalid terrain packet - patch header patch ID incorrect!"
768 << " patches per edge " << mPatchesPerEdge
769 << " i " << i
770 << " j " << j
771 << " dc_offset " << ph.dc_offset
772 << " range " << (S32)ph.range
773 << " quant_wbits " << (S32)ph.quant_wbits
774 << " patchids " << (S32)ph.patchids
775 << llendl;
776 bad_network_handler();
777 return;
778 }
779
780 patchp = &mPatchList[j*mPatchesPerEdge + i];
781
782
783 decode_patch(bitpack, patch);
784 decompress_patch(patchp->getDataZ(), patch, &ph);
785
786 // Update edges for neighbors. Need to guarantee that this gets done before we generate vertical stats.
787 patchp->updateNorthEdge();
788 patchp->updateEastEdge();
789 if (patchp->getNeighborPatch(WEST))
790 {
791 patchp->getNeighborPatch(WEST)->updateEastEdge();
792 }
793 if (patchp->getNeighborPatch(SOUTHWEST))
794 {
795 patchp->getNeighborPatch(SOUTHWEST)->updateEastEdge();
796 patchp->getNeighborPatch(SOUTHWEST)->updateNorthEdge();
797 }
798 if (patchp->getNeighborPatch(SOUTH))
799 {
800 patchp->getNeighborPatch(SOUTH)->updateNorthEdge();
801 }
802
803 // Dirty patch statistics, and flag that the patch has data.
804 patchp->dirtyZ();
805 patchp->setHasReceivedData();
806 }
807}
808
809
810// Retrurns TRUE if "position" is within the bounds of surface.
811// "position" is region-local
812BOOL LLSurface::containsPosition(const LLVector3 &position)
813{
814 if (position.mV[VX] < 0.0f || position.mV[VX] > mMetersPerEdge ||
815 position.mV[VY] < 0.0f || position.mV[VY] > mMetersPerEdge)
816 {
817 return FALSE;
818 }
819 return TRUE;
820}
821
822
823F32 LLSurface::resolveHeightRegion(const F32 x, const F32 y) const
824{
825 F32 height = 0.0f;
826 F32 oometerspergrid = 1.f/mMetersPerGrid;
827
828 // Check to see if v is actually above surface
829 // We use (mGridsPerEdge-1) below rather than (mGridsPerEdge)
830 // becuase of the east and north buffers
831
832 if (x >= 0.f &&
833 x <= mMetersPerEdge &&
834 y >= 0.f &&
835 y <= mMetersPerEdge)
836 {
837 const S32 left = llfloor(x * oometerspergrid);
838 const S32 bottom = llfloor(y * oometerspergrid);
839
840 // Don't walk off the edge of the array!
841 const S32 right = ( left+1 < (S32)mGridsPerEdge-1 ? left+1 : left );
842 const S32 top = ( bottom+1 < (S32)mGridsPerEdge-1 ? bottom+1 : bottom );
843
844 // Figure out if v is in first or second triangle of the square
845 // and calculate the slopes accordingly
846 // | |
847 // -(i,j+1)---(i+1,j+1)--
848 // | 1 / | ^
849 // | / 2 | |
850 // | / | j
851 // --(i,j)----(i+1,j)--
852 // | |
853 //
854 // i ->
855 // where N = mGridsPerEdge
856
857 const F32 left_bottom = getZ( left, bottom );
858 const F32 right_bottom = getZ( right, bottom );
859 const F32 left_top = getZ( left, top );
860 const F32 right_top = getZ( right, top );
861
862 // dx and dy are incremental steps from (mSurface + k)
863 F32 dx = x - left * mMetersPerGrid;
864 F32 dy = y - bottom * mMetersPerGrid;
865
866 if (dy > dx)
867 {
868 // triangle 1
869 dy *= left_top - left_bottom;
870 dx *= right_top - left_top;
871 }
872 else
873 {
874 // triangle 2
875 dx *= right_bottom - left_bottom;
876 dy *= right_top - right_bottom;
877 }
878 height = left_bottom + (dx + dy) * oometerspergrid;
879 }
880 return height;
881}
882
883
884F32 LLSurface::resolveHeightGlobal(const LLVector3d& v) const
885{
886 if (!mRegionp)
887 {
888 return 0.f;
889 }
890
891 LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(v);
892
893 return resolveHeightRegion(pos_region);
894}
895
896
897LLVector3 LLSurface::resolveNormalGlobal(const LLVector3d& pos_global) const
898{
899 if (!mSurfaceZ)
900 {
901 // Hmm. Uninitialized surface!
902 return LLVector3::z_axis;
903 }
904 //
905 // Returns the vector normal to a surface at location specified by vector v
906 //
907 F32 oometerspergrid = 1.f/mMetersPerGrid;
908 LLVector3 normal;
909 F32 dzx, dzy;
910
911 if (pos_global.mdV[VX] >= mOriginGlobal.mdV[VX] &&
912 pos_global.mdV[VX] < mOriginGlobal.mdV[VX] + mMetersPerEdge &&
913 pos_global.mdV[VY] >= mOriginGlobal.mdV[VY] &&
914 pos_global.mdV[VY] < mOriginGlobal.mdV[VY] + mMetersPerEdge)
915 {
916 U32 i, j, k;
917 F32 dx, dy;
918 i = (U32) ((pos_global.mdV[VX] - mOriginGlobal.mdV[VX]) * oometerspergrid);
919 j = (U32) ((pos_global.mdV[VY] - mOriginGlobal.mdV[VY]) * oometerspergrid );
920 k = i + j*mGridsPerEdge;
921
922 // Figure out if v is in first or second triangle of the square
923 // and calculate the slopes accordingly
924 // | |
925 // -(k+N)---(k+1+N)--
926 // | 1 / | ^
927 // | / 2 | |
928 // | / | j
929 // --(k)----(k+1)--
930 // | |
931 //
932 // i ->
933 // where N = mGridsPerEdge
934
935 // dx and dy are incremental steps from (mSurface + k)
936 dx = (F32)(pos_global.mdV[VX] - i*mMetersPerGrid - mOriginGlobal.mdV[VX]);
937 dy = (F32)(pos_global.mdV[VY] - j*mMetersPerGrid - mOriginGlobal.mdV[VY]);
938 if (dy > dx)
939 { // triangle 1
940 dzx = *(mSurfaceZ + k + 1 + mGridsPerEdge) - *(mSurfaceZ + k + mGridsPerEdge);
941 dzy = *(mSurfaceZ + k) - *(mSurfaceZ + k + mGridsPerEdge);
942 normal.setVec(-dzx,dzy,1);
943 }
944 else
945 { // triangle 2
946 dzx = *(mSurfaceZ + k) - *(mSurfaceZ + k + 1);
947 dzy = *(mSurfaceZ + k + 1 + mGridsPerEdge) - *(mSurfaceZ + k + 1);
948 normal.setVec(dzx,-dzy,1);
949 }
950 }
951 normal.normVec();
952 return normal;
953
954
955}
956
957LLSurfacePatch *LLSurface::resolvePatchRegion(const F32 x, const F32 y) const
958{
959// x and y should be region-local coordinates.
960// If x and y are outside of the surface, then the returned
961// index will be for the nearest boundary patch.
962//
963// 12 | 13| 14| 15
964// | | |
965// +---+---+---+---+
966// | 12| 13| 14| 15|
967// ----+---+---+---+---+-----
968// 8 | 8 | 9 | 10| 11| 11
969// ----+---+---+---+---+-----
970// 4 | 4 | 5 | 6 | 7 | 7
971// ----+---+---+---+---+-----
972// | 0 | 1 | 2 | 3 |
973// +---+---+---+---+
974// | | |
975// 0 | 1 | 2 | 3
976//
977
978// When x and y are not region-local do the following first
979
980 S32 i, j;
981 if (x < 0.0f)
982 {
983 i = 0;
984 }
985 else if (x >= mMetersPerEdge)
986 {
987 i = mPatchesPerEdge - 1;
988 }
989 else
990 {
991 i = (U32) (x / (mMetersPerGrid * mGridsPerPatchEdge));
992 }
993
994 if (y < 0.0f)
995 {
996 j = 0;
997 }
998 else if (y >= mMetersPerEdge)
999 {
1000 j = mPatchesPerEdge - 1;
1001 }
1002 else
1003 {
1004 j = (U32) (y / (mMetersPerGrid * mGridsPerPatchEdge));
1005 }
1006
1007 // *NOTE: Super paranoia code follows.
1008 S32 index = i + j * mPatchesPerEdge;
1009 if((index < 0) || (index >= mNumberOfPatches))
1010 {
1011 if(0 == mNumberOfPatches)
1012 {
1013 llwarns << "No patches for current region!" << llendl;
1014 return NULL;
1015 }
1016 S32 old_index = index;
1017 index = llclamp(old_index, 0, (mNumberOfPatches - 1));
1018 llwarns << "Clamping out of range patch index " << old_index
1019 << " to " << index << llendl;
1020 }
1021 return &(mPatchList[index]);
1022}
1023
1024
1025LLSurfacePatch *LLSurface::resolvePatchRegion(const LLVector3 &pos_region) const
1026{
1027 return resolvePatchRegion(pos_region.mV[VX], pos_region.mV[VY]);
1028}
1029
1030
1031LLSurfacePatch *LLSurface::resolvePatchGlobal(const LLVector3d &pos_global) const
1032{
1033 LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(pos_global);
1034 return resolvePatchRegion(pos_region);
1035}
1036
1037
1038std::ostream& operator<<(std::ostream &s, const LLSurface &S)
1039{
1040 s << "{ \n";
1041 s << " mGridsPerEdge = " << S.mGridsPerEdge - 1 << " + 1\n";
1042 s << " mGridsPerPatchEdge = " << S.mGridsPerPatchEdge << "\n";
1043 s << " mPatchesPerEdge = " << S.mPatchesPerEdge << "\n";
1044 s << " mOriginGlobal = " << S.mOriginGlobal << "\n";
1045 s << " mMetersPerGrid = " << S.mMetersPerGrid << "\n";
1046 s << " mVisiblePatchCount = " << S.mVisiblePatchCount << "\n";
1047 s << "}";
1048 return s;
1049}
1050
1051
1052// ---------------- LLSurface:: Protected ----------------
1053
1054void LLSurface::createPatchData()
1055{
1056 // Assumes mGridsPerEdge, mGridsPerPatchEdge, and mPatchesPerEdge have been properly set
1057 // TODO -- check for create() called when surface is not empty
1058 S32 i, j;
1059 LLSurfacePatch *patchp;
1060
1061 // Allocate memory
1062 mPatchList = new LLSurfacePatch[mNumberOfPatches];
1063
1064 // One of each for each camera
1065 mVisiblePatchCount = mNumberOfPatches;
1066
1067 for (j=0; j<mPatchesPerEdge; j++)
1068 {
1069 for (i=0; i<mPatchesPerEdge; i++)
1070 {
1071 patchp = getPatch(i, j);
1072 patchp->setSurface(this);
1073 }
1074 }
1075
1076 for (j=0; j<mPatchesPerEdge; j++)
1077 {
1078 for (i=0; i<mPatchesPerEdge; i++)
1079 {
1080 patchp = getPatch(i, j);
1081 patchp->mHasReceivedData = FALSE;
1082 patchp->mSTexUpdate = TRUE;
1083
1084 S32 data_offset = i * mGridsPerPatchEdge + j * mGridsPerPatchEdge * mGridsPerEdge;
1085
1086 patchp->setDataZ(mSurfaceZ + data_offset);
1087 patchp->setDataNorm(mNorm + data_offset);
1088
1089
1090 // We make each patch point to its neighbors so we can do resolution checking
1091 // when butting up different resolutions. Patches that don't have neighbors
1092 // somewhere will point to NULL on that side.
1093 if (i < mPatchesPerEdge-1)
1094 {
1095 patchp->setNeighborPatch(EAST,getPatch(i+1, j));
1096 }
1097 else
1098 {
1099 patchp->setNeighborPatch(EAST, NULL);
1100 }
1101
1102 if (j < mPatchesPerEdge-1)
1103 {
1104 patchp->setNeighborPatch(NORTH, getPatch(i, j+1));
1105 }
1106 else
1107 {
1108 patchp->setNeighborPatch(NORTH, NULL);
1109 }
1110
1111 if (i > 0)
1112 {
1113 patchp->setNeighborPatch(WEST, getPatch(i - 1, j));
1114 }
1115 else
1116 {
1117 patchp->setNeighborPatch(WEST, NULL);
1118 }
1119
1120 if (j > 0)
1121 {
1122 patchp->setNeighborPatch(SOUTH, getPatch(i, j-1));
1123 }
1124 else
1125 {
1126 patchp->setNeighborPatch(SOUTH, NULL);
1127 }
1128
1129 if (i < (mPatchesPerEdge-1) && j < (mPatchesPerEdge-1))
1130 {
1131 patchp->setNeighborPatch(NORTHEAST, getPatch(i + 1, j + 1));
1132 }
1133 else
1134 {
1135 patchp->setNeighborPatch(NORTHEAST, NULL);
1136 }
1137
1138 if (i > 0 && j < (mPatchesPerEdge-1))
1139 {
1140 patchp->setNeighborPatch(NORTHWEST, getPatch(i - 1, j + 1));
1141 }
1142 else
1143 {
1144 patchp->setNeighborPatch(NORTHWEST, NULL);
1145 }
1146
1147 if (i > 0 && j > 0)
1148 {
1149 patchp->setNeighborPatch(SOUTHWEST, getPatch(i - 1, j - 1));
1150 }
1151 else
1152 {
1153 patchp->setNeighborPatch(SOUTHWEST, NULL);
1154 }
1155
1156 if (i < (mPatchesPerEdge-1) && j > 0)
1157 {
1158 patchp->setNeighborPatch(SOUTHEAST, getPatch(i + 1, j - 1));
1159 }
1160 else
1161 {
1162 patchp->setNeighborPatch(SOUTHEAST, NULL);
1163 }
1164
1165 LLVector3d origin_global;
1166 origin_global.mdV[0] = mOriginGlobal.mdV[0] + i * mMetersPerGrid * mGridsPerPatchEdge;
1167 origin_global.mdV[1] = mOriginGlobal.mdV[0] + j * mMetersPerGrid * mGridsPerPatchEdge;
1168 origin_global.mdV[2] = 0.f;
1169 patchp->setOriginGlobal(origin_global);
1170 }
1171 }
1172}
1173
1174
1175void LLSurface::destroyPatchData()
1176{
1177 // Delete all of the cached patch data for these patches.
1178
1179 delete [] mPatchList;
1180 mPatchList = NULL;
1181 mVisiblePatchCount = 0;
1182}
1183
1184
1185void LLSurface::setTextureSize(const S32 texture_size)
1186{
1187 sTextureSize = texture_size;
1188}
1189
1190
1191U32 LLSurface::getRenderLevel(const U32 render_stride) const
1192{
1193 return mPVArray.mRenderLevelp[render_stride];
1194}
1195
1196
1197U32 LLSurface::getRenderStride(const U32 render_level) const
1198{
1199 return mPVArray.mRenderStridep[render_level];
1200}
1201
1202
1203LLSurfacePatch *LLSurface::getPatch(const S32 x, const S32 y) const
1204{
1205 if ((x < 0) || (x >= mPatchesPerEdge))
1206 {
1207 llerrs << "Asking for patch out of bounds" << llendl;
1208 return NULL;
1209 }
1210 if ((y < 0) || (y >= mPatchesPerEdge))
1211 {
1212 llerrs << "Asking for patch out of bounds" << llendl;
1213 return NULL;
1214 }
1215
1216 return mPatchList + x + y*mPatchesPerEdge;
1217}
1218
1219
1220void LLSurface::dirtyAllPatches()
1221{
1222 S32 i;
1223 for (i = 0; i < mNumberOfPatches; i++)
1224 {
1225 mPatchList[i].dirtyZ();
1226 }
1227}
1228
1229void LLSurface::dirtySurfacePatch(LLSurfacePatch *patchp)
1230{
1231 // Put surface patch on dirty surface patch list
1232 if (-1 == mDirtyPatchList.find(patchp))
1233 {
1234 mDirtyPatchList.put(patchp);
1235 }
1236}
1237
1238
1239void LLSurface::setWaterHeight(F32 height)
1240{
1241 if (!mWaterObjp.isNull())
1242 {
1243 LLVector3 water_pos_region = mWaterObjp->getPositionRegion();
1244 water_pos_region.mV[VZ] = height;
1245 mWaterObjp->setPositionRegion(water_pos_region);
1246 }
1247 else
1248 {
1249 llwarns << "LLSurface::setWaterHeight with no water object!" << llendl;
1250 }
1251}
1252
1253F32 LLSurface::getWaterHeight() const
1254{
1255 if (!mWaterObjp.isNull())
1256 {
1257 // we have a water object, the usual case
1258 return mWaterObjp->getPositionRegion().mV[VZ];
1259 }
1260 else
1261 {
1262 return DEFAULT_WATER_HEIGHT;
1263 }
1264}
1265
1266
1267BOOL LLSurface::generateWaterTexture(const F32 x, const F32 y,
1268 const F32 width, const F32 height)
1269{
1270 if (!getWaterTexture())
1271 {
1272 return FALSE;
1273 }
1274
1275 S32 tex_width = mWaterTexturep->getWidth();
1276 S32 tex_height = mWaterTexturep->getHeight();
1277 S32 tex_comps = mWaterTexturep->getComponents();
1278 S32 tex_stride = tex_width * tex_comps;
1279 LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps);
1280 U8 *rawp = raw->getData();
1281
1282 F32 scale = 256.f * getMetersPerGrid() / (F32)tex_width;
1283 F32 scale_inv = 1.f / scale;
1284
1285 S32 x_begin, y_begin, x_end, y_end;
1286
1287 x_begin = llround(x * scale_inv);
1288 y_begin = llround(y * scale_inv);
1289 x_end = llround((x + width) * scale_inv);
1290 y_end = llround((y + width) * scale_inv);
1291
1292 if (x_end > tex_width)
1293 {
1294 x_end = tex_width;
1295 }
1296 if (y_end > tex_width)
1297 {
1298 y_end = tex_width;
1299 }
1300
1301 LLVector3d origin_global = from_region_handle(getRegion()->getHandle());
1302
1303 // OK, for now, just have the composition value equal the height at the point.
1304 LLVector3 location;
1305 LLColor4U coloru;
1306
1307 const F32 WATER_HEIGHT = getWaterHeight();
1308
1309 S32 i, j, offset;
1310 for (j = y_begin; j < y_end; j++)
1311 {
1312 for (i = x_begin; i < x_end; i++)
1313 {
1314 //F32 nv[2];
1315 //nv[0] = i/256.f;
1316 //nv[1] = j/256.f;
1317 // const S32 modulation = noise2(nv)*40;
1318 offset = j*tex_stride + i*tex_comps;
1319 location.mV[VX] = i*scale;
1320 location.mV[VY] = j*scale;
1321
1322 // Sample multiple points
1323 const F32 height = resolveHeightRegion(location);
1324
1325 if (height > WATER_HEIGHT)
1326 {
1327 // Above water...
1328 coloru = MAX_WATER_COLOR;
1329 coloru.mV[3] = ABOVE_WATERLINE_ALPHA;
1330 *(rawp + offset++) = coloru.mV[0];
1331 *(rawp + offset++) = coloru.mV[1];
1332 *(rawp + offset++) = coloru.mV[2];
1333 *(rawp + offset++) = coloru.mV[3];
1334 }
1335 else
1336 {
1337 // Want non-linear curve for transparency gradient
1338 coloru = MAX_WATER_COLOR;
1339 const F32 frac = 1.f - 2.f/(2.f - (height - WATER_HEIGHT));
1340 S32 alpha = 64 + llround((255-64)*frac);
1341
1342 alpha = llmin(llround((F32)MAX_WATER_COLOR.mV[3]), alpha);
1343 alpha = llmax(64, alpha);
1344
1345 coloru.mV[3] = alpha;
1346 *(rawp + offset++) = coloru.mV[0];
1347 *(rawp + offset++) = coloru.mV[1];
1348 *(rawp + offset++) = coloru.mV[2];
1349 *(rawp + offset++) = coloru.mV[3];
1350 }
1351 }
1352 }
1353
1354 mWaterTexturep->setSubImage(raw, x_begin, y_begin, x_end - x_begin, y_end - y_begin);
1355 return TRUE;
1356}