diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llvosurfacepatch.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 943 |
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 | |||
44 | LLVOSurfacePatch::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 | |||
63 | LLVOSurfacePatch::~LLVOSurfacePatch() | ||
64 | { | ||
65 | mPatchp = NULL; | ||
66 | } | ||
67 | |||
68 | |||
69 | void LLVOSurfacePatch::markDead() | ||
70 | { | ||
71 | if (mPatchp) | ||
72 | { | ||
73 | mPatchp->clearVObj(); | ||
74 | mPatchp = NULL; | ||
75 | } | ||
76 | LLViewerObject::markDead(); | ||
77 | } | ||
78 | |||
79 | |||
80 | BOOL LLVOSurfacePatch::isActive() const | ||
81 | { | ||
82 | return FALSE; | ||
83 | } | ||
84 | |||
85 | |||
86 | void LLVOSurfacePatch::setPixelAreaAndAngle(LLAgent &agent) | ||
87 | { | ||
88 | mAppAngle = 50; | ||
89 | mPixelArea = 500*500; | ||
90 | } | ||
91 | |||
92 | |||
93 | void LLVOSurfacePatch::updateTextures(LLAgent &agent) | ||
94 | { | ||
95 | } | ||
96 | |||
97 | |||
98 | LLDrawPool *LLVOSurfacePatch::getPool() | ||
99 | { | ||
100 | mPool = gPipeline.getPool(LLDrawPool::POOL_TERRAIN, mPatchp->getSurface()->getSTexture()); | ||
101 | |||
102 | return mPool; | ||
103 | } | ||
104 | |||
105 | |||
106 | LLDrawable *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 | |||
135 | BOOL 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 | |||
275 | void 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 | |||
380 | void 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 | |||
602 | void 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 | |||
808 | void 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 | |||
832 | BOOL LLVOSurfacePatch::updateShadows(BOOL use_shadow_factor) | ||
833 | { | ||
834 | return FALSE; //terrain updates its shadows during standard relight | ||
835 | } | ||
836 | |||
837 | void LLVOSurfacePatch::setPatch(LLSurfacePatch *patchp) | ||
838 | { | ||
839 | mPatchp = patchp; | ||
840 | |||
841 | dirtyPatch(); | ||
842 | }; | ||
843 | |||
844 | |||
845 | void 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 | |||
863 | void LLVOSurfacePatch::dirtyGeom() | ||
864 | { | ||
865 | if (mDrawable) | ||
866 | { | ||
867 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); | ||
868 | } | ||
869 | } | ||
870 | |||
871 | void 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 | |||
884 | void 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 | |||
910 | void 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 | |||
936 | void 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 | } | ||