aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llvosurfacepatch.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/llvosurfacepatch.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/llvosurfacepatch.cpp')
-rw-r--r--linden/indra/newview/llvosurfacepatch.cpp943
1 files changed, 943 insertions, 0 deletions
diff --git a/linden/indra/newview/llvosurfacepatch.cpp b/linden/indra/newview/llvosurfacepatch.cpp
new file mode 100644
index 0000000..d49d78c
--- /dev/null
+++ b/linden/indra/newview/llvosurfacepatch.cpp
@@ -0,0 +1,943 @@
1/**
2 * @file llvosurfacepatch.cpp
3 * @brief Viewer-object derived "surface patch", which is a piece of terrain
4 *
5 * Copyright (c) 2001-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 "llvosurfacepatch.h"
31
32#include "lldrawable.h"
33#include "llface.h"
34#include "llprimitive.h"
35#include "llsky.h"
36#include "llsurfacepatch.h"
37#include "llsurface.h"
38#include "llviewerobjectlist.h"
39#include "llviewerregion.h"
40#include "llvlcomposition.h"
41#include "llvovolume.h"
42#include "pipeline.h"
43
44LLVOSurfacePatch::LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
45: LLViewerObject(id, LL_VO_SURFACE_PATCH, regionp)
46{
47 // Terrain must draw during selection passes so it can block objects behind it.
48 mbCanSelect = TRUE;
49
50 mBaseComp = 0;
51 setScale(LLVector3(16.f, 16.f, 16.f)); // Hack for setting scale for bounding boxes/visibility.
52 mPool = NULL;
53 mDirtiedPatch = FALSE;
54 mLastStride = 0;
55 mLastNorthStride = 0;
56 mLastEastStride = 0;
57 mLastLength = 0;
58
59 mDirtyTerrain = TRUE;
60}
61
62
63LLVOSurfacePatch::~LLVOSurfacePatch()
64{
65 mPatchp = NULL;
66}
67
68
69void LLVOSurfacePatch::markDead()
70{
71 if (mPatchp)
72 {
73 mPatchp->clearVObj();
74 mPatchp = NULL;
75 }
76 LLViewerObject::markDead();
77}
78
79
80BOOL LLVOSurfacePatch::isActive() const
81{
82 return FALSE;
83}
84
85
86void LLVOSurfacePatch::setPixelAreaAndAngle(LLAgent &agent)
87{
88 mAppAngle = 50;
89 mPixelArea = 500*500;
90}
91
92
93void LLVOSurfacePatch::updateTextures(LLAgent &agent)
94{
95}
96
97
98LLDrawPool *LLVOSurfacePatch::getPool()
99{
100 mPool = gPipeline.getPool(LLDrawPool::POOL_TERRAIN, mPatchp->getSurface()->getSTexture());
101
102 return mPool;
103}
104
105
106LLDrawable *LLVOSurfacePatch::createDrawable(LLPipeline *pipeline)
107{
108 pipeline->allocDrawable(this);
109
110 mDrawable->setRenderType(LLPipeline::RENDER_TYPE_TERRAIN);
111
112 mBaseComp = llfloor(mPatchp->getMinComposition());
113 S32 min_comp, max_comp, range;
114 min_comp = llfloor(mPatchp->getMinComposition());
115 max_comp = llceil(mPatchp->getMaxComposition());
116 range = (max_comp - min_comp);
117 range++;
118 if (range > 3)
119 {
120 if ((mPatchp->getMinComposition() - min_comp) > (max_comp - mPatchp->getMaxComposition()))
121 {
122 // The top side runs over more
123 mBaseComp++;
124 }
125 range = 3;
126 }
127
128 LLDrawPool *poolp = getPool();
129
130 mDrawable->addFace(poolp, NULL);
131 return mDrawable;
132}
133
134
135BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable)
136{
137 S32 min_comp, max_comp, range;
138 min_comp = lltrunc(mPatchp->getMinComposition());
139 max_comp = lltrunc(ceil(mPatchp->getMaxComposition()));
140 range = (max_comp - min_comp);
141 range++;
142 S32 new_base_comp = lltrunc(mPatchp->getMinComposition());
143 if (range > 3)
144 {
145 if ((mPatchp->getMinComposition() - min_comp) > (max_comp - mPatchp->getMaxComposition()))
146 {
147 // The top side runs over more
148 new_base_comp++;
149 }
150 range = 3;
151 }
152
153 // Pick the two closest detail textures for this patch...
154 // Then create the draw pool for it.
155 // Actually, should get the average composition instead of the center.
156 mBaseComp = new_base_comp;
157
158 //////////////////////////
159 //
160 // Figure out the strides
161 //
162 //
163
164 U32 patch_width, render_stride, north_stride, east_stride, length;
165 render_stride = mPatchp->getRenderStride();
166 patch_width = mPatchp->getSurface()->getGridsPerPatchEdge();
167
168 length = patch_width / render_stride;
169
170 if (mPatchp->getNeighborPatch(NORTH))
171 {
172 north_stride = mPatchp->getNeighborPatch(NORTH)->getRenderStride();
173 }
174 else
175 {
176 north_stride = render_stride;
177 }
178
179 if (mPatchp->getNeighborPatch(EAST))
180 {
181 east_stride = mPatchp->getNeighborPatch(EAST)->getRenderStride();
182 }
183 else
184 {
185 east_stride = render_stride;
186 }
187
188 S32 num_vertices = 0;
189 S32 num_indices = 0;
190 S32 new_north_offset = 0;
191 S32 new_east_offset = 0;
192
193 getGeomSizesMain(render_stride, num_vertices, num_indices);
194 new_north_offset = num_vertices;
195 getGeomSizesNorth(render_stride, north_stride, num_vertices, num_indices);
196 new_east_offset = num_vertices;
197 getGeomSizesEast(render_stride, east_stride, num_vertices, num_indices);
198 S32 new_num_vertices = num_vertices;
199 S32 new_num_indices = num_indices;
200
201 LLFace *facep = NULL;
202
203 // Update the allocated face
204 LLStrider<LLVector3> verticesp;
205 LLStrider<LLVector3> normalsp;
206 LLStrider<LLVector2> texCoords0p;
207 LLStrider<LLVector2> texCoords1p;
208 LLStrider<LLColor4U> colorsp;
209 U32* indicesp = NULL;
210 S32 index_offset;
211
212 facep = mDrawable->getFace(0);
213
214 facep->setSize(new_num_vertices, new_num_indices);
215 facep->setPrimType(LLTriangles);
216
217 index_offset = facep->getGeometryTerrain(
218 verticesp,
219 normalsp,
220 colorsp,
221 texCoords0p,
222 texCoords1p,
223 indicesp);
224 if (-1 == index_offset)
225 {
226 return TRUE;
227 }
228
229 mDrawable->updateLightSet();
230
231 updateMainGeometry(facep,
232 verticesp,
233 normalsp,
234 colorsp,
235 texCoords0p,
236 texCoords1p,
237 indicesp,
238 index_offset);
239 updateNorthGeometry(facep,
240 verticesp,
241 normalsp,
242 colorsp,
243 texCoords0p,
244 texCoords1p,
245 indicesp,
246 index_offset);
247 updateEastGeometry(facep,
248 verticesp,
249 normalsp,
250 colorsp,
251 texCoords0p,
252 texCoords1p,
253 indicesp,
254 index_offset);
255
256 if (mLastLength != 0)
257 {
258 // lazy, should cache the geom sizes so we know the offsets.
259 num_vertices = 0;
260 num_indices = 0;
261
262 }
263
264 mLastLength = length;
265 mLastStride = render_stride;
266 mLastNorthStride = north_stride;
267 mLastEastStride = east_stride;
268
269 mDrawable->setState(LLDrawable::LIGHTING_BUILT);
270
271 LLPipeline::sCompiles++;
272 return TRUE;
273}
274
275void LLVOSurfacePatch::updateMainGeometry(LLFace *facep,
276 LLStrider<LLVector3> &verticesp,
277 LLStrider<LLVector3> &normalsp,
278 LLStrider<LLColor4U> &colorsp,
279 LLStrider<LLVector2> &texCoords0p,
280 LLStrider<LLVector2> &texCoords1p,
281 U32* &indicesp,
282 S32 &index_offset)
283{
284 S32 i, j, x, y;
285
286 U32 patch_size, render_stride;
287 S32 num_vertices, num_indices;
288 U32 index;
289
290 render_stride = mPatchp->getRenderStride();
291 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
292 S32 vert_size = patch_size / render_stride;
293
294 ///////////////////////////
295 //
296 // Render the main patch
297 //
298 //
299
300 num_vertices = 0;
301 num_indices = 0;
302 // First, figure out how many vertices we need...
303 getGeomSizesMain(render_stride, num_vertices, num_indices);
304
305 if (num_vertices > 0)
306 {
307 facep->mCenterAgent = mPatchp->getPointAgent(8, 8);
308
309 // Generate patch points first
310 for (j = 0; j < vert_size; j++)
311 {
312 for (i = 0; i < vert_size; i++)
313 {
314 x = i * render_stride;
315 y = j * render_stride;
316 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
317 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
318 verticesp++;
319 normalsp++;
320 colorsp++;
321 texCoords0p++;
322 texCoords1p++;
323 }
324 }
325
326 for (j = 0; j < (vert_size - 1); j++)
327 {
328 if (j % 2)
329 {
330 for (i = (vert_size - 1); i > 0; i--)
331 {
332 index = (i - 1)+ j*vert_size;
333 *(indicesp++) = index_offset + index;
334
335 index = i + (j+1)*vert_size;
336 *(indicesp++) = index_offset + index;
337
338 index = (i - 1) + (j+1)*vert_size;
339 *(indicesp++) = index_offset + index;
340
341 index = (i - 1) + j*vert_size;
342 *(indicesp++) = index_offset + index;
343
344 index = i + j*vert_size;
345 *(indicesp++) = index_offset + index;
346
347 index = i + (j+1)*vert_size;
348 *(indicesp++) = index_offset + index;
349 }
350 }
351 else
352 {
353 for (i = 0; i < (vert_size - 1); i++)
354 {
355 index = i + j*vert_size;
356 *(indicesp++) = index_offset + index;
357
358 index = (i + 1) + (j+1)*vert_size;
359 *(indicesp++) = index_offset + index;
360
361 index = i + (j+1)*vert_size;
362 *(indicesp++) = index_offset + index;
363
364 index = i + j*vert_size;
365 *(indicesp++) = index_offset + index;
366
367 index = (i + 1) + j*vert_size;
368 *(indicesp++) = index_offset + index;
369
370 index = (i + 1) + (j + 1)*vert_size;
371 *(indicesp++) = index_offset + index;
372 }
373 }
374 }
375 }
376 index_offset += num_vertices;
377}
378
379
380void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
381 LLStrider<LLVector3> &verticesp,
382 LLStrider<LLVector3> &normalsp,
383 LLStrider<LLColor4U> &colorsp,
384 LLStrider<LLVector2> &texCoords0p,
385 LLStrider<LLVector2> &texCoords1p,
386 U32* &indicesp,
387 S32 &index_offset)
388{
389 S32 vertex_count = 0;
390 S32 i, x, y;
391
392 S32 num_vertices, num_indices;
393
394 U32 render_stride = mPatchp->getRenderStride();
395 S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
396 S32 length = patch_size / render_stride;
397 S32 half_length = length / 2;
398
399 U32 north_stride;
400 if (mPatchp->getNeighborPatch(NORTH))
401 {
402 north_stride = mPatchp->getNeighborPatch(NORTH)->getRenderStride();
403 }
404 else
405 {
406 north_stride = render_stride;
407 }
408
409 ///////////////////////////
410 //
411 // Render the north strip
412 //
413 //
414
415 // Stride lengths are the same
416 if (north_stride == render_stride)
417 {
418 num_vertices = 2 * length + 1;
419 num_indices = length * 6 - 3;
420
421 facep->mCenterAgent = (mPatchp->getPointAgent(8, 15) + mPatchp->getPointAgent(8, 16))*0.5f;
422
423 // Main patch
424 for (i = 0; i < length; i++)
425 {
426 x = i * render_stride;
427 y = 16 - render_stride;
428
429 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
430 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
431 verticesp++;
432 normalsp++;
433 colorsp++;
434 texCoords0p++;
435 texCoords1p++;
436 vertex_count++;
437 }
438
439 // North patch
440 for (i = 0; i <= length; i++)
441 {
442 x = i * render_stride;
443 y = 16;
444 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
445 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
446 verticesp++;
447 normalsp++;
448 colorsp++;
449 texCoords0p++;
450 texCoords1p++;
451 vertex_count++;
452 }
453
454
455 for (i = 0; i < length; i++)
456 {
457 // Generate indices
458 *(indicesp++) = index_offset + i;
459 *(indicesp++) = index_offset + length + i + 1;
460 *(indicesp++) = index_offset + length + i;
461
462 if (i != length - 1)
463 {
464 *(indicesp++) = index_offset + i;
465 *(indicesp++) = index_offset + i + 1;
466 *(indicesp++) = index_offset + length + i + 1;
467 }
468 }
469 }
470 else if (north_stride > render_stride)
471 {
472 // North stride is longer (has less vertices)
473 num_vertices = length + length/2 + 1;
474 num_indices = half_length*9 - 3;
475
476 facep->mCenterAgent = (mPatchp->getPointAgent(7, 15) + mPatchp->getPointAgent(8, 16))*0.5f;
477
478 // Iterate through this patch's points
479 for (i = 0; i < length; i++)
480 {
481 x = i * render_stride;
482 y = 16 - render_stride;
483
484 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
485 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
486 verticesp++;
487 normalsp++;
488 colorsp++;
489 texCoords0p++;
490 texCoords1p++;
491 vertex_count++;
492 }
493
494 // Iterate through the north patch's points
495 for (i = 0; i <= length; i+=2)
496 {
497 x = i * render_stride;
498 y = 16;
499
500 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
501 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
502 verticesp++;
503 normalsp++;
504 colorsp++;
505 texCoords0p++;
506 texCoords1p++;
507 vertex_count++;
508 }
509
510
511 for (i = 0; i < length; i++)
512 {
513 if (!(i % 2))
514 {
515 *(indicesp++) = index_offset + i;
516 *(indicesp++) = index_offset + i + 1;
517 *(indicesp++) = index_offset + length + (i/2);
518
519 *(indicesp++) = index_offset + i + 1;
520 *(indicesp++) = index_offset + length + (i/2) + 1;
521 *(indicesp++) = index_offset + length + (i/2);
522 }
523 else if (i < (length - 1))
524 {
525 *(indicesp++) = index_offset + i;
526 *(indicesp++) = index_offset + i + 1;
527 *(indicesp++) = index_offset + length + (i/2) + 1;
528 }
529 }
530 }
531 else
532 {
533 // North stride is shorter (more vertices)
534 length = patch_size / north_stride;
535 half_length = length / 2;
536 num_vertices = length + half_length + 1;
537 num_indices = 9*half_length - 3;
538
539 facep->mCenterAgent = (mPatchp->getPointAgent(15, 7) + mPatchp->getPointAgent(16, 8))*0.5f;
540
541 // Iterate through this patch's points
542 for (i = 0; i < length; i+=2)
543 {
544 x = i * north_stride;
545 y = 16 - render_stride;
546
547 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
548 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
549 verticesp++;
550 normalsp++;
551 colorsp++;
552 texCoords0p++;
553 texCoords1p++;
554 vertex_count++;
555 }
556
557 // Iterate through the north patch's points
558 for (i = 0; i <= length; i++)
559 {
560 x = i * north_stride;
561 y = 16;
562
563 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
564 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
565 verticesp++;
566 normalsp++;
567 colorsp++;
568 texCoords0p++;
569 texCoords1p++;
570 vertex_count++;
571 }
572
573 for (i = 0; i < length; i++)
574 {
575 if (!(i%2))
576 {
577 *(indicesp++) = index_offset + half_length + i;
578 *(indicesp++) = index_offset + i/2;
579 *(indicesp++) = index_offset + half_length + i + 1;
580 }
581 else if (i < (length - 2))
582 {
583 *(indicesp++) = index_offset + half_length + i;
584 *(indicesp++) = index_offset + i/2;
585 *(indicesp++) = index_offset + i/2 + 1;
586
587 *(indicesp++) = index_offset + half_length + i;
588 *(indicesp++) = index_offset + i/2 + 1;
589 *(indicesp++) = index_offset + half_length + i + 1;
590 }
591 else
592 {
593 *(indicesp++) = index_offset + half_length + i;
594 *(indicesp++) = index_offset + i/2;
595 *(indicesp++) = index_offset + half_length + i + 1;
596 }
597 }
598 }
599 index_offset += num_vertices;
600}
601
602void LLVOSurfacePatch::updateEastGeometry(LLFace *facep,
603 LLStrider<LLVector3> &verticesp,
604 LLStrider<LLVector3> &normalsp,
605 LLStrider<LLColor4U> &colorsp,
606 LLStrider<LLVector2> &texCoords0p,
607 LLStrider<LLVector2> &texCoords1p,
608 U32* &indicesp,
609 S32 &index_offset)
610{
611 S32 i, x, y;
612
613 S32 num_vertices, num_indices;
614
615 U32 render_stride = mPatchp->getRenderStride();
616 S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
617 S32 length = patch_size / render_stride;
618 S32 half_length = length / 2;
619
620 U32 east_stride;
621 if (mPatchp->getNeighborPatch(EAST))
622 {
623 east_stride = mPatchp->getNeighborPatch(EAST)->getRenderStride();
624 }
625 else
626 {
627 east_stride = render_stride;
628 }
629
630 // Stride lengths are the same
631 if (east_stride == render_stride)
632 {
633 num_vertices = 2 * length + 1;
634 num_indices = length * 6 - 3;
635
636 facep->mCenterAgent = (mPatchp->getPointAgent(8, 15) + mPatchp->getPointAgent(8, 16))*0.5f;
637
638 // Main patch
639 for (i = 0; i < length; i++)
640 {
641 x = 16 - render_stride;
642 y = i * render_stride;
643
644 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
645 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
646 verticesp++;
647 normalsp++;
648 colorsp++;
649 texCoords0p++;
650 texCoords1p++;
651 }
652
653 // East patch
654 for (i = 0; i <= length; i++)
655 {
656 x = 16;
657 y = i * render_stride;
658 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
659 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
660 verticesp++;
661 normalsp++;
662 colorsp++;
663 texCoords0p++;
664 texCoords1p++;
665 }
666
667
668 for (i = 0; i < length; i++)
669 {
670 // Generate indices
671 *(indicesp++) = index_offset + i;
672 *(indicesp++) = index_offset + length + i;
673 *(indicesp++) = index_offset + length + i + 1;
674
675 if (i != length - 1)
676 {
677 *(indicesp++) = index_offset + i;
678 *(indicesp++) = index_offset + length + i + 1;
679 *(indicesp++) = index_offset + i + 1;
680 }
681 }
682 }
683 else if (east_stride > render_stride)
684 {
685 // East stride is longer (has less vertices)
686 num_vertices = length + half_length + 1;
687 num_indices = half_length*9 - 3;
688
689 facep->mCenterAgent = (mPatchp->getPointAgent(7, 15) + mPatchp->getPointAgent(8, 16))*0.5f;
690
691 // Iterate through this patch's points
692 for (i = 0; i < length; i++)
693 {
694 x = 16 - render_stride;
695 y = i * render_stride;
696
697 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
698 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
699 verticesp++;
700 normalsp++;
701 colorsp++;
702 texCoords0p++;
703 texCoords1p++;
704 }
705 // Iterate through the east patch's points
706 for (i = 0; i <= length; i+=2)
707 {
708 x = 16;
709 y = i * render_stride;
710
711 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
712 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
713 verticesp++;
714 normalsp++;
715 colorsp++;
716 texCoords0p++;
717 texCoords1p++;
718 }
719
720 for (i = 0; i < length; i++)
721 {
722 if (!(i % 2))
723 {
724 *(indicesp++) = index_offset + i;
725 *(indicesp++) = index_offset + length + (i/2);
726 *(indicesp++) = index_offset + i + 1;
727
728 *(indicesp++) = index_offset + i + 1;
729 *(indicesp++) = index_offset + length + (i/2);
730 *(indicesp++) = index_offset + length + (i/2) + 1;
731 }
732 else if (i < (length - 1))
733 {
734 *(indicesp++) = index_offset + i;
735 *(indicesp++) = index_offset + length + (i/2) + 1;
736 *(indicesp++) = index_offset + i + 1;
737 }
738 }
739 }
740 else
741 {
742 // East stride is shorter (more vertices)
743 length = patch_size / east_stride;
744 half_length = length / 2;
745 num_vertices = length + length/2 + 1;
746 num_indices = 9*(length/2) - 3;
747
748 facep->mCenterAgent = (mPatchp->getPointAgent(15, 7) + mPatchp->getPointAgent(16, 8))*0.5f;
749
750 // Iterate through this patch's points
751 for (i = 0; i < length; i+=2)
752 {
753 x = 16 - render_stride;
754 y = i * east_stride;
755
756 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
757 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
758 verticesp++;
759 normalsp++;
760 colorsp++;
761 texCoords0p++;
762 texCoords1p++;
763 }
764 // Iterate through the east patch's points
765 for (i = 0; i <= length; i++)
766 {
767 x = 16;
768 y = i * east_stride;
769
770 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
771 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
772 verticesp++;
773 normalsp++;
774 colorsp++;
775 texCoords0p++;
776 texCoords1p++;
777 }
778
779 for (i = 0; i < length; i++)
780 {
781 if (!(i%2))
782 {
783 *(indicesp++) = index_offset + half_length + i;
784 *(indicesp++) = index_offset + half_length + i + 1;
785 *(indicesp++) = index_offset + i/2;
786 }
787 else if (i < (length - 2))
788 {
789 *(indicesp++) = index_offset + half_length + i;
790 *(indicesp++) = index_offset + i/2 + 1;
791 *(indicesp++) = index_offset + i/2;
792
793 *(indicesp++) = index_offset + half_length + i;
794 *(indicesp++) = index_offset + half_length + i + 1;
795 *(indicesp++) = index_offset + i/2 + 1;
796 }
797 else
798 {
799 *(indicesp++) = index_offset + half_length + i;
800 *(indicesp++) = index_offset + half_length + i + 1;
801 *(indicesp++) = index_offset + i/2;
802 }
803 }
804 }
805 index_offset += num_vertices;
806}
807
808void LLVOSurfacePatch::calcColor(const LLVector3* vertex, const LLVector3* normal, LLColor4U* colorp)
809{
810 LLColor4 color(0,0,0,0);
811 if (gPipeline.getLightingDetail() >= 2)
812 {
813 for (LLDrawable::drawable_set_t::iterator iter = mDrawable->mLightSet.begin();
814 iter != mDrawable->mLightSet.end(); ++iter)
815 {
816 LLDrawable* light_drawable = *iter;
817 LLVOVolume* light = light_drawable->getVOVolume();
818 if (!light)
819 {
820 continue;
821 }
822 LLColor4 light_color;
823 light->calcLightAtPoint(*vertex, *normal, light_color);
824 color += light_color;
825 }
826
827 color.mV[3] = 1.0f;
828 }
829 colorp->setVecScaleClamp(color);
830}
831
832BOOL LLVOSurfacePatch::updateShadows(BOOL use_shadow_factor)
833{
834 return FALSE; //terrain updates its shadows during standard relight
835}
836
837void LLVOSurfacePatch::setPatch(LLSurfacePatch *patchp)
838{
839 mPatchp = patchp;
840
841 dirtyPatch();
842};
843
844
845void LLVOSurfacePatch::dirtyPatch()
846{
847 if (mDrawable)
848 {
849 gPipeline.markMoved(mDrawable);
850 }
851 mDirtiedPatch = TRUE;
852 dirtyGeom();
853 mDirtyTerrain = TRUE;
854 LLVector3 center = mPatchp->getCenterRegion();
855 LLSurface *surfacep = mPatchp->getSurface();
856
857 setPositionRegion(center);
858
859 F32 scale_factor = surfacep->getGridsPerPatchEdge() * surfacep->getMetersPerGrid();
860 setScale(LLVector3(scale_factor, scale_factor, mPatchp->getMaxZ() - mPatchp->getMinZ()));
861}
862
863void LLVOSurfacePatch::dirtyGeom()
864{
865 if (mDrawable)
866 {
867 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
868 }
869}
870
871void LLVOSurfacePatch::getGeomSizesMain(const S32 stride, S32 &num_vertices, S32 &num_indices)
872{
873 S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
874
875 // First, figure out how many vertices we need...
876 S32 vert_size = patch_size / stride;
877 if (vert_size >= 2)
878 {
879 num_vertices += vert_size * vert_size;
880 num_indices += 6 * (vert_size - 1)*(vert_size - 1);
881 }
882}
883
884void LLVOSurfacePatch::getGeomSizesNorth(const S32 stride, const S32 north_stride,
885 S32 &num_vertices, S32 &num_indices)
886{
887 S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
888 S32 length = patch_size / stride;
889 // Stride lengths are the same
890 if (north_stride == stride)
891 {
892 num_vertices += 2 * length + 1;
893 num_indices += length * 6 - 3;
894 }
895 else if (north_stride > stride)
896 {
897 // North stride is longer (has less vertices)
898 num_vertices += length + (length/2) + 1;
899 num_indices += (length/2)*9 - 3;
900 }
901 else
902 {
903 // North stride is shorter (more vertices)
904 length = patch_size / north_stride;
905 num_vertices += length + (length/2) + 1;
906 num_indices += 9*(length/2) - 3;
907 }
908}
909
910void LLVOSurfacePatch::getGeomSizesEast(const S32 stride, const S32 east_stride,
911 S32 &num_vertices, S32 &num_indices)
912{
913 S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
914 S32 length = patch_size / stride;
915 // Stride lengths are the same
916 if (east_stride == stride)
917 {
918 num_vertices += 2 * length + 1;
919 num_indices += length * 6 - 3;
920 }
921 else if (east_stride > stride)
922 {
923 // East stride is longer (has less vertices)
924 num_vertices += length + (length/2) + 1;
925 num_indices += (length/2)*9 - 3;
926 }
927 else
928 {
929 // East stride is shorter (more vertices)
930 length = patch_size / east_stride;
931 num_vertices += length + (length/2) + 1;
932 num_indices += 9*(length/2) - 3;
933 }
934}
935
936void LLVOSurfacePatch::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax)
937{
938 LLVector3 posAgent = getPositionAgent();
939 LLVector3 scale = getScale();
940 newMin = posAgent-scale;
941 newMax = posAgent+scale;
942 mDrawable->setPositionGroup((newMin+newMax)*0.5f);
943}