00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llvosurfacepatch.h"
00035
00036 #include "lldrawpoolterrain.h"
00037
00038 #include "lldrawable.h"
00039 #include "llface.h"
00040 #include "llprimitive.h"
00041 #include "llsky.h"
00042 #include "llsurfacepatch.h"
00043 #include "llsurface.h"
00044 #include "llviewerobjectlist.h"
00045 #include "llviewerregion.h"
00046 #include "llvlcomposition.h"
00047 #include "llvovolume.h"
00048 #include "pipeline.h"
00049
00050
00051
00052 class LLVertexBufferTerrain : public LLVertexBuffer
00053 {
00054 public:
00055 LLVertexBufferTerrain() :
00056 LLVertexBuffer(MAP_VERTEX | MAP_NORMAL | MAP_TEXCOORD | MAP_TEXCOORD2 | MAP_COLOR, GL_DYNAMIC_DRAW_ARB)
00057 {
00058 };
00059
00060
00061 void setupVertexBuffer(U32 data_mask) const
00062 {
00063 if (LLDrawPoolTerrain::getDetailMode() == 0)
00064 {
00065 LLVertexBuffer::setupVertexBuffer(data_mask);
00066 }
00067 else if (data_mask & LLVertexBuffer::MAP_TEXCOORD2)
00068 {
00069 U8* base = useVBOs() ? NULL : mMappedData;
00070
00071 glVertexPointer(3,GL_FLOAT, mStride, (void*)(base + 0));
00072 glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL]));
00073 glColorPointer(4, GL_UNSIGNED_BYTE, mStride, (void*)(base + mOffsets[TYPE_COLOR]));
00074
00075 glClientActiveTextureARB(GL_TEXTURE3_ARB);
00076 glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2]));
00077 glClientActiveTextureARB(GL_TEXTURE2_ARB);
00078 glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2]));
00079 glClientActiveTextureARB(GL_TEXTURE1_ARB);
00080 glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2]));
00081 glClientActiveTextureARB(GL_TEXTURE0_ARB);
00082 glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2]));
00083 }
00084 else
00085 {
00086 LLVertexBuffer::setupVertexBuffer(data_mask);
00087 }
00088 llglassertok();
00089 }
00090 };
00091
00092
00093
00094 LLVOSurfacePatch::LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
00095 : LLStaticViewerObject(id, LL_VO_SURFACE_PATCH, regionp),
00096 mDirtiedPatch(FALSE),
00097 mPool(NULL),
00098 mBaseComp(0),
00099 mPatchp(NULL),
00100 mDirtyTexture(FALSE),
00101 mDirtyTerrain(FALSE),
00102 mLastNorthStride(0),
00103 mLastEastStride(0),
00104 mLastStride(0),
00105 mLastLength(0)
00106 {
00107
00108 mbCanSelect = TRUE;
00109 setScale(LLVector3(16.f, 16.f, 16.f));
00110 }
00111
00112
00113 LLVOSurfacePatch::~LLVOSurfacePatch()
00114 {
00115 mPatchp = NULL;
00116 }
00117
00118
00119 void LLVOSurfacePatch::markDead()
00120 {
00121 if (mPatchp)
00122 {
00123 mPatchp->clearVObj();
00124 mPatchp = NULL;
00125 }
00126 LLViewerObject::markDead();
00127 }
00128
00129
00130 BOOL LLVOSurfacePatch::isActive() const
00131 {
00132 return FALSE;
00133 }
00134
00135
00136 void LLVOSurfacePatch::setPixelAreaAndAngle(LLAgent &agent)
00137 {
00138 mAppAngle = 50;
00139 mPixelArea = 500*500;
00140 }
00141
00142
00143 void LLVOSurfacePatch::updateTextures(LLAgent &agent)
00144 {
00145 }
00146
00147
00148 LLFacePool *LLVOSurfacePatch::getPool()
00149 {
00150 mPool = (LLDrawPoolTerrain*) gPipeline.getPool(LLDrawPool::POOL_TERRAIN, mPatchp->getSurface()->getSTexture());
00151
00152 return mPool;
00153 }
00154
00155
00156 LLDrawable *LLVOSurfacePatch::createDrawable(LLPipeline *pipeline)
00157 {
00158 pipeline->allocDrawable(this);
00159
00160 mDrawable->setRenderType(LLPipeline::RENDER_TYPE_TERRAIN);
00161
00162 mBaseComp = llfloor(mPatchp->getMinComposition());
00163 S32 min_comp, max_comp, range;
00164 min_comp = llfloor(mPatchp->getMinComposition());
00165 max_comp = llceil(mPatchp->getMaxComposition());
00166 range = (max_comp - min_comp);
00167 range++;
00168 if (range > 3)
00169 {
00170 if ((mPatchp->getMinComposition() - min_comp) > (max_comp - mPatchp->getMaxComposition()))
00171 {
00172
00173 mBaseComp++;
00174 }
00175 range = 3;
00176 }
00177
00178 LLFacePool *poolp = getPool();
00179
00180 mDrawable->addFace(poolp, NULL);
00181
00182 return mDrawable;
00183 }
00184
00185
00186 BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable)
00187 {
00188 LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TERRAIN);
00189
00190 S32 min_comp, max_comp, range;
00191 min_comp = lltrunc(mPatchp->getMinComposition());
00192 max_comp = lltrunc(ceil(mPatchp->getMaxComposition()));
00193 range = (max_comp - min_comp);
00194 range++;
00195 S32 new_base_comp = lltrunc(mPatchp->getMinComposition());
00196 if (range > 3)
00197 {
00198 if ((mPatchp->getMinComposition() - min_comp) > (max_comp - mPatchp->getMaxComposition()))
00199 {
00200
00201 new_base_comp++;
00202 }
00203 range = 3;
00204 }
00205
00206
00207
00208
00209 mBaseComp = new_base_comp;
00210
00212
00213
00214
00215
00216
00217 U32 patch_width, render_stride, north_stride, east_stride, length;
00218 render_stride = mPatchp->getRenderStride();
00219 patch_width = mPatchp->getSurface()->getGridsPerPatchEdge();
00220
00221 length = patch_width / render_stride;
00222
00223 if (mPatchp->getNeighborPatch(NORTH))
00224 {
00225 north_stride = mPatchp->getNeighborPatch(NORTH)->getRenderStride();
00226 }
00227 else
00228 {
00229 north_stride = render_stride;
00230 }
00231
00232 if (mPatchp->getNeighborPatch(EAST))
00233 {
00234 east_stride = mPatchp->getNeighborPatch(EAST)->getRenderStride();
00235 }
00236 else
00237 {
00238 east_stride = render_stride;
00239 }
00240
00241 mLastLength = length;
00242 mLastStride = render_stride;
00243 mLastNorthStride = north_stride;
00244 mLastEastStride = east_stride;
00245
00246 return TRUE;
00247 }
00248
00249 void LLVOSurfacePatch::updateFaceSize(S32 idx)
00250 {
00251 if (idx != 0)
00252 {
00253 llwarns << "Terrain partition requested invalid face!!!" << llendl;
00254 return;
00255 }
00256
00257 LLFace* facep = mDrawable->getFace(idx);
00258
00259 S32 num_vertices = 0;
00260 S32 num_indices = 0;
00261
00262 if (mLastStride)
00263 {
00264 getGeomSizesMain(mLastStride, num_vertices, num_indices);
00265 getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices, num_indices);
00266 getGeomSizesEast(mLastStride, mLastEastStride, num_vertices, num_indices);
00267 }
00268
00269 facep->setSize(num_vertices, num_indices);
00270 }
00271
00272 BOOL LLVOSurfacePatch::updateLOD()
00273 {
00274
00275 mDrawable->setState(LLDrawable::LIGHTING_BUILT);
00276 return TRUE;
00277 }
00278
00279 void LLVOSurfacePatch::getGeometry(LLStrider<LLVector3> &verticesp,
00280 LLStrider<LLVector3> &normalsp,
00281 LLStrider<LLColor4U> &colorsp,
00282 LLStrider<LLVector2> &texCoords0p,
00283 LLStrider<LLVector2> &texCoords1p,
00284 LLStrider<U32> &indicesp)
00285 {
00286 LLFace* facep = mDrawable->getFace(0);
00287
00288 U32 index_offset = facep->getGeomIndex();
00289
00290 updateMainGeometry(facep,
00291 verticesp,
00292 normalsp,
00293 colorsp,
00294 texCoords0p,
00295 texCoords1p,
00296 indicesp,
00297 index_offset);
00298 updateNorthGeometry(facep,
00299 verticesp,
00300 normalsp,
00301 colorsp,
00302 texCoords0p,
00303 texCoords1p,
00304 indicesp,
00305 index_offset);
00306 updateEastGeometry(facep,
00307 verticesp,
00308 normalsp,
00309 colorsp,
00310 texCoords0p,
00311 texCoords1p,
00312 indicesp,
00313 index_offset);
00314 }
00315
00316 void LLVOSurfacePatch::updateMainGeometry(LLFace *facep,
00317 LLStrider<LLVector3> &verticesp,
00318 LLStrider<LLVector3> &normalsp,
00319 LLStrider<LLColor4U> &colorsp,
00320 LLStrider<LLVector2> &texCoords0p,
00321 LLStrider<LLVector2> &texCoords1p,
00322 LLStrider<U32> &indicesp,
00323 U32 &index_offset)
00324 {
00325 S32 i, j, x, y;
00326
00327 U32 patch_size, render_stride;
00328 S32 num_vertices, num_indices;
00329 U32 index;
00330
00331 render_stride = mLastStride;
00332 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
00333 S32 vert_size = patch_size / render_stride;
00334
00336
00337
00338
00339
00340
00341 num_vertices = 0;
00342 num_indices = 0;
00343
00344 getGeomSizesMain(render_stride, num_vertices, num_indices);
00345
00346 if (num_vertices > 0)
00347 {
00348 facep->mCenterAgent = mPatchp->getPointAgent(8, 8);
00349
00350
00351 for (j = 0; j < vert_size; j++)
00352 {
00353 for (i = 0; i < vert_size; i++)
00354 {
00355 x = i * render_stride;
00356 y = j * render_stride;
00357 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
00358 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
00359 verticesp++;
00360 normalsp++;
00361 colorsp++;
00362 texCoords0p++;
00363 texCoords1p++;
00364 }
00365 }
00366
00367 for (j = 0; j < (vert_size - 1); j++)
00368 {
00369 if (j % 2)
00370 {
00371 for (i = (vert_size - 1); i > 0; i--)
00372 {
00373 index = (i - 1)+ j*vert_size;
00374 *(indicesp++) = index_offset + index;
00375
00376 index = i + (j+1)*vert_size;
00377 *(indicesp++) = index_offset + index;
00378
00379 index = (i - 1) + (j+1)*vert_size;
00380 *(indicesp++) = index_offset + index;
00381
00382 index = (i - 1) + j*vert_size;
00383 *(indicesp++) = index_offset + index;
00384
00385 index = i + j*vert_size;
00386 *(indicesp++) = index_offset + index;
00387
00388 index = i + (j+1)*vert_size;
00389 *(indicesp++) = index_offset + index;
00390 }
00391 }
00392 else
00393 {
00394 for (i = 0; i < (vert_size - 1); i++)
00395 {
00396 index = i + j*vert_size;
00397 *(indicesp++) = index_offset + index;
00398
00399 index = (i + 1) + (j+1)*vert_size;
00400 *(indicesp++) = index_offset + index;
00401
00402 index = i + (j+1)*vert_size;
00403 *(indicesp++) = index_offset + index;
00404
00405 index = i + j*vert_size;
00406 *(indicesp++) = index_offset + index;
00407
00408 index = (i + 1) + j*vert_size;
00409 *(indicesp++) = index_offset + index;
00410
00411 index = (i + 1) + (j + 1)*vert_size;
00412 *(indicesp++) = index_offset + index;
00413 }
00414 }
00415 }
00416 }
00417 index_offset += num_vertices;
00418 }
00419
00420
00421 void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
00422 LLStrider<LLVector3> &verticesp,
00423 LLStrider<LLVector3> &normalsp,
00424 LLStrider<LLColor4U> &colorsp,
00425 LLStrider<LLVector2> &texCoords0p,
00426 LLStrider<LLVector2> &texCoords1p,
00427 LLStrider<U32> &indicesp,
00428 U32 &index_offset)
00429 {
00430 S32 vertex_count = 0;
00431 S32 i, x, y;
00432
00433 S32 num_vertices, num_indices;
00434
00435 U32 render_stride = mLastStride;
00436 S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
00437 S32 length = patch_size / render_stride;
00438 S32 half_length = length / 2;
00439 U32 north_stride = mLastNorthStride;
00440
00442
00443
00444
00445
00446
00447
00448 if (north_stride == render_stride)
00449 {
00450 num_vertices = 2 * length + 1;
00451 num_indices = length * 6 - 3;
00452
00453 facep->mCenterAgent = (mPatchp->getPointAgent(8, 15) + mPatchp->getPointAgent(8, 16))*0.5f;
00454
00455
00456 for (i = 0; i < length; i++)
00457 {
00458 x = i * render_stride;
00459 y = 16 - render_stride;
00460
00461 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
00462 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
00463 verticesp++;
00464 normalsp++;
00465 colorsp++;
00466 texCoords0p++;
00467 texCoords1p++;
00468 vertex_count++;
00469 }
00470
00471
00472 for (i = 0; i <= length; i++)
00473 {
00474 x = i * render_stride;
00475 y = 16;
00476 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
00477 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
00478 verticesp++;
00479 normalsp++;
00480 colorsp++;
00481 texCoords0p++;
00482 texCoords1p++;
00483 vertex_count++;
00484 }
00485
00486
00487 for (i = 0; i < length; i++)
00488 {
00489
00490 *(indicesp++) = index_offset + i;
00491 *(indicesp++) = index_offset + length + i + 1;
00492 *(indicesp++) = index_offset + length + i;
00493
00494 if (i != length - 1)
00495 {
00496 *(indicesp++) = index_offset + i;
00497 *(indicesp++) = index_offset + i + 1;
00498 *(indicesp++) = index_offset + length + i + 1;
00499 }
00500 }
00501 }
00502 else if (north_stride > render_stride)
00503 {
00504
00505 num_vertices = length + length/2 + 1;
00506 num_indices = half_length*9 - 3;
00507
00508 facep->mCenterAgent = (mPatchp->getPointAgent(7, 15) + mPatchp->getPointAgent(8, 16))*0.5f;
00509
00510
00511 for (i = 0; i < length; i++)
00512 {
00513 x = i * render_stride;
00514 y = 16 - render_stride;
00515
00516 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
00517 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
00518 verticesp++;
00519 normalsp++;
00520 colorsp++;
00521 texCoords0p++;
00522 texCoords1p++;
00523 vertex_count++;
00524 }
00525
00526
00527 for (i = 0; i <= length; i+=2)
00528 {
00529 x = i * render_stride;
00530 y = 16;
00531
00532 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
00533 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
00534 verticesp++;
00535 normalsp++;
00536 colorsp++;
00537 texCoords0p++;
00538 texCoords1p++;
00539 vertex_count++;
00540 }
00541
00542
00543 for (i = 0; i < length; i++)
00544 {
00545 if (!(i % 2))
00546 {
00547 *(indicesp++) = index_offset + i;
00548 *(indicesp++) = index_offset + i + 1;
00549 *(indicesp++) = index_offset + length + (i/2);
00550
00551 *(indicesp++) = index_offset + i + 1;
00552 *(indicesp++) = index_offset + length + (i/2) + 1;
00553 *(indicesp++) = index_offset + length + (i/2);
00554 }
00555 else if (i < (length - 1))
00556 {
00557 *(indicesp++) = index_offset + i;
00558 *(indicesp++) = index_offset + i + 1;
00559 *(indicesp++) = index_offset + length + (i/2) + 1;
00560 }
00561 }
00562 }
00563 else
00564 {
00565
00566 length = patch_size / north_stride;
00567 half_length = length / 2;
00568 num_vertices = length + half_length + 1;
00569 num_indices = 9*half_length - 3;
00570
00571 facep->mCenterAgent = (mPatchp->getPointAgent(15, 7) + mPatchp->getPointAgent(16, 8))*0.5f;
00572
00573
00574 for (i = 0; i < length; i+=2)
00575 {
00576 x = i * north_stride;
00577 y = 16 - render_stride;
00578
00579 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
00580 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
00581 verticesp++;
00582 normalsp++;
00583 colorsp++;
00584 texCoords0p++;
00585 texCoords1p++;
00586 vertex_count++;
00587 }
00588
00589
00590 for (i = 0; i <= length; i++)
00591 {
00592 x = i * north_stride;
00593 y = 16;
00594
00595 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
00596 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
00597 verticesp++;
00598 normalsp++;
00599 colorsp++;
00600 texCoords0p++;
00601 texCoords1p++;
00602 vertex_count++;
00603 }
00604
00605 for (i = 0; i < length; i++)
00606 {
00607 if (!(i%2))
00608 {
00609 *(indicesp++) = index_offset + half_length + i;
00610 *(indicesp++) = index_offset + i/2;
00611 *(indicesp++) = index_offset + half_length + i + 1;
00612 }
00613 else if (i < (length - 2))
00614 {
00615 *(indicesp++) = index_offset + half_length + i;
00616 *(indicesp++) = index_offset + i/2;
00617 *(indicesp++) = index_offset + i/2 + 1;
00618
00619 *(indicesp++) = index_offset + half_length + i;
00620 *(indicesp++) = index_offset + i/2 + 1;
00621 *(indicesp++) = index_offset + half_length + i + 1;
00622 }
00623 else
00624 {
00625 *(indicesp++) = index_offset + half_length + i;
00626 *(indicesp++) = index_offset + i/2;
00627 *(indicesp++) = index_offset + half_length + i + 1;
00628 }
00629 }
00630 }
00631 index_offset += num_vertices;
00632 }
00633
00634 void LLVOSurfacePatch::updateEastGeometry(LLFace *facep,
00635 LLStrider<LLVector3> &verticesp,
00636 LLStrider<LLVector3> &normalsp,
00637 LLStrider<LLColor4U> &colorsp,
00638 LLStrider<LLVector2> &texCoords0p,
00639 LLStrider<LLVector2> &texCoords1p,
00640 LLStrider<U32> &indicesp,
00641 U32 &index_offset)
00642 {
00643 S32 i, x, y;
00644
00645 S32 num_vertices, num_indices;
00646
00647 U32 render_stride = mLastStride;
00648 S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
00649 S32 length = patch_size / render_stride;
00650 S32 half_length = length / 2;
00651
00652 U32 east_stride = mLastEastStride;
00653
00654
00655 if (east_stride == render_stride)
00656 {
00657 num_vertices = 2 * length + 1;
00658 num_indices = length * 6 - 3;
00659
00660 facep->mCenterAgent = (mPatchp->getPointAgent(8, 15) + mPatchp->getPointAgent(8, 16))*0.5f;
00661
00662
00663 for (i = 0; i < length; i++)
00664 {
00665 x = 16 - render_stride;
00666 y = i * render_stride;
00667
00668 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
00669 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
00670 verticesp++;
00671 normalsp++;
00672 colorsp++;
00673 texCoords0p++;
00674 texCoords1p++;
00675 }
00676
00677
00678 for (i = 0; i <= length; i++)
00679 {
00680 x = 16;
00681 y = i * render_stride;
00682 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
00683 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
00684 verticesp++;
00685 normalsp++;
00686 colorsp++;
00687 texCoords0p++;
00688 texCoords1p++;
00689 }
00690
00691
00692 for (i = 0; i < length; i++)
00693 {
00694
00695 *(indicesp++) = index_offset + i;
00696 *(indicesp++) = index_offset + length + i;
00697 *(indicesp++) = index_offset + length + i + 1;
00698
00699 if (i != length - 1)
00700 {
00701 *(indicesp++) = index_offset + i;
00702 *(indicesp++) = index_offset + length + i + 1;
00703 *(indicesp++) = index_offset + i + 1;
00704 }
00705 }
00706 }
00707 else if (east_stride > render_stride)
00708 {
00709
00710 num_vertices = length + half_length + 1;
00711 num_indices = half_length*9 - 3;
00712
00713 facep->mCenterAgent = (mPatchp->getPointAgent(7, 15) + mPatchp->getPointAgent(8, 16))*0.5f;
00714
00715
00716 for (i = 0; i < length; i++)
00717 {
00718 x = 16 - render_stride;
00719 y = i * render_stride;
00720
00721 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
00722 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
00723 verticesp++;
00724 normalsp++;
00725 colorsp++;
00726 texCoords0p++;
00727 texCoords1p++;
00728 }
00729
00730 for (i = 0; i <= length; i+=2)
00731 {
00732 x = 16;
00733 y = i * render_stride;
00734
00735 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
00736 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
00737 verticesp++;
00738 normalsp++;
00739 colorsp++;
00740 texCoords0p++;
00741 texCoords1p++;
00742 }
00743
00744 for (i = 0; i < length; i++)
00745 {
00746 if (!(i % 2))
00747 {
00748 *(indicesp++) = index_offset + i;
00749 *(indicesp++) = index_offset + length + (i/2);
00750 *(indicesp++) = index_offset + i + 1;
00751
00752 *(indicesp++) = index_offset + i + 1;
00753 *(indicesp++) = index_offset + length + (i/2);
00754 *(indicesp++) = index_offset + length + (i/2) + 1;
00755 }
00756 else if (i < (length - 1))
00757 {
00758 *(indicesp++) = index_offset + i;
00759 *(indicesp++) = index_offset + length + (i/2) + 1;
00760 *(indicesp++) = index_offset + i + 1;
00761 }
00762 }
00763 }
00764 else
00765 {
00766
00767 length = patch_size / east_stride;
00768 half_length = length / 2;
00769 num_vertices = length + length/2 + 1;
00770 num_indices = 9*(length/2) - 3;
00771
00772 facep->mCenterAgent = (mPatchp->getPointAgent(15, 7) + mPatchp->getPointAgent(16, 8))*0.5f;
00773
00774
00775 for (i = 0; i < length; i+=2)
00776 {
00777 x = 16 - render_stride;
00778 y = i * east_stride;
00779
00780 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
00781 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
00782 verticesp++;
00783 normalsp++;
00784 colorsp++;
00785 texCoords0p++;
00786 texCoords1p++;
00787 }
00788
00789 for (i = 0; i <= length; i++)
00790 {
00791 x = 16;
00792 y = i * east_stride;
00793
00794 mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
00795 calcColor(verticesp.get(), normalsp.get(), colorsp.get());
00796 verticesp++;
00797 normalsp++;
00798 colorsp++;
00799 texCoords0p++;
00800 texCoords1p++;
00801 }
00802
00803 for (i = 0; i < length; i++)
00804 {
00805 if (!(i%2))
00806 {
00807 *(indicesp++) = index_offset + half_length + i;
00808 *(indicesp++) = index_offset + half_length + i + 1;
00809 *(indicesp++) = index_offset + i/2;
00810 }
00811 else if (i < (length - 2))
00812 {
00813 *(indicesp++) = index_offset + half_length + i;
00814 *(indicesp++) = index_offset + i/2 + 1;
00815 *(indicesp++) = index_offset + i/2;
00816
00817 *(indicesp++) = index_offset + half_length + i;
00818 *(indicesp++) = index_offset + half_length + i + 1;
00819 *(indicesp++) = index_offset + i/2 + 1;
00820 }
00821 else
00822 {
00823 *(indicesp++) = index_offset + half_length + i;
00824 *(indicesp++) = index_offset + half_length + i + 1;
00825 *(indicesp++) = index_offset + i/2;
00826 }
00827 }
00828 }
00829 index_offset += num_vertices;
00830 }
00831
00832 void LLVOSurfacePatch::calcColor(const LLVector3* vertex, const LLVector3* normal, LLColor4U* colorp)
00833 {
00834 LLColor4 color(0,0,0,0);
00835 if (gPipeline.getLightingDetail() >= 2)
00836 {
00837 for (LLDrawable::drawable_set_t::iterator iter = mDrawable->mLightSet.begin();
00838 iter != mDrawable->mLightSet.end(); ++iter)
00839 {
00840 LLDrawable* light_drawable = *iter;
00841 LLVOVolume* light = light_drawable->getVOVolume();
00842 if (!light)
00843 {
00844 continue;
00845 }
00846 LLColor4 light_color;
00847 light->calcLightAtPoint(*vertex, *normal, light_color);
00848 color += light_color;
00849 }
00850
00851 color.mV[3] = 1.0f;
00852 }
00853 colorp->setVecScaleClamp(color);
00854 }
00855
00856 BOOL LLVOSurfacePatch::updateShadows(BOOL use_shadow_factor)
00857 {
00858 return FALSE;
00859 }
00860
00861 void LLVOSurfacePatch::setPatch(LLSurfacePatch *patchp)
00862 {
00863 mPatchp = patchp;
00864
00865 dirtyPatch();
00866 };
00867
00868
00869 void LLVOSurfacePatch::dirtyPatch()
00870 {
00871 mDirtiedPatch = TRUE;
00872 dirtyGeom();
00873 mDirtyTerrain = TRUE;
00874 LLVector3 center = mPatchp->getCenterRegion();
00875 LLSurface *surfacep = mPatchp->getSurface();
00876
00877 setPositionRegion(center);
00878
00879 F32 scale_factor = surfacep->getGridsPerPatchEdge() * surfacep->getMetersPerGrid();
00880 setScale(LLVector3(scale_factor, scale_factor, mPatchp->getMaxZ() - mPatchp->getMinZ()));
00881 }
00882
00883 void LLVOSurfacePatch::dirtyGeom()
00884 {
00885 if (mDrawable)
00886 {
00887 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
00888 mDrawable->getFace(0)->mVertexBuffer = NULL;
00889 mDrawable->movePartition();
00890 }
00891 }
00892
00893 void LLVOSurfacePatch::getGeomSizesMain(const S32 stride, S32 &num_vertices, S32 &num_indices)
00894 {
00895 S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
00896
00897
00898 S32 vert_size = patch_size / stride;
00899 if (vert_size >= 2)
00900 {
00901 num_vertices += vert_size * vert_size;
00902 num_indices += 6 * (vert_size - 1)*(vert_size - 1);
00903 }
00904 }
00905
00906 void LLVOSurfacePatch::getGeomSizesNorth(const S32 stride, const S32 north_stride,
00907 S32 &num_vertices, S32 &num_indices)
00908 {
00909 S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
00910 S32 length = patch_size / stride;
00911
00912 if (north_stride == stride)
00913 {
00914 num_vertices += 2 * length + 1;
00915 num_indices += length * 6 - 3;
00916 }
00917 else if (north_stride > stride)
00918 {
00919
00920 num_vertices += length + (length/2) + 1;
00921 num_indices += (length/2)*9 - 3;
00922 }
00923 else
00924 {
00925
00926 length = patch_size / north_stride;
00927 num_vertices += length + (length/2) + 1;
00928 num_indices += 9*(length/2) - 3;
00929 }
00930 }
00931
00932 void LLVOSurfacePatch::getGeomSizesEast(const S32 stride, const S32 east_stride,
00933 S32 &num_vertices, S32 &num_indices)
00934 {
00935 S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
00936 S32 length = patch_size / stride;
00937
00938 if (east_stride == stride)
00939 {
00940 num_vertices += 2 * length + 1;
00941 num_indices += length * 6 - 3;
00942 }
00943 else if (east_stride > stride)
00944 {
00945
00946 num_vertices += length + (length/2) + 1;
00947 num_indices += (length/2)*9 - 3;
00948 }
00949 else
00950 {
00951
00952 length = patch_size / east_stride;
00953 num_vertices += length + (length/2) + 1;
00954 num_indices += 9*(length/2) - 3;
00955 }
00956 }
00957
00958 void LLVOSurfacePatch::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax)
00959 {
00960 LLVector3 posAgent = getPositionAgent();
00961 LLVector3 scale = getScale();
00962 newMin = posAgent-scale*0.5f;
00963 newMax = posAgent+scale*0.5f;
00964 mDrawable->setPositionGroup((newMin+newMax)*0.5f);
00965 }
00966
00967 U32 LLVOSurfacePatch::getPartitionType() const
00968 {
00969 return LLPipeline::PARTITION_TERRAIN;
00970 }
00971
00972 LLTerrainPartition::LLTerrainPartition()
00973 : LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK)
00974 {
00975 mRenderByGroup = FALSE;
00976 mBufferUsage = GL_DYNAMIC_DRAW_ARB;
00977 mDrawableType = LLPipeline::RENDER_TYPE_TERRAIN;
00978 mPartitionType = LLPipeline::PARTITION_TERRAIN;
00979 }
00980
00981 LLVertexBuffer* LLTerrainPartition::createVertexBuffer(U32 type_mask, U32 usage)
00982 {
00983 return new LLVertexBufferTerrain();
00984 }
00985
00986 void LLTerrainPartition::getGeometry(LLSpatialGroup* group)
00987 {
00988 LLVertexBuffer* buffer = group->mVertexBuffer;
00989
00990
00991 LLStrider<LLVector3> vertices;
00992 LLStrider<LLVector3> normals;
00993 LLStrider<LLVector2> texcoords2;
00994 LLStrider<LLVector2> texcoords;
00995 LLStrider<LLColor4U> colors;
00996 LLStrider<U32> indices;
00997
00998 buffer->getVertexStrider(vertices);
00999 buffer->getNormalStrider(normals);
01000 buffer->getTexCoordStrider(texcoords);
01001 buffer->getTexCoord2Strider(texcoords2);
01002 buffer->getColorStrider(colors);
01003 buffer->getIndexStrider(indices);
01004
01005 U32 indices_index = 0;
01006 U32 index_offset = 0;
01007
01008 for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i)
01009 {
01010 LLFace* facep = *i;
01011
01012 facep->setIndicesIndex(indices_index);
01013 facep->setGeomIndex(index_offset);
01014 facep->mVertexBuffer = buffer;
01015
01016 LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject();
01017 patchp->getGeometry(vertices, normals, colors, texcoords, texcoords2, indices);
01018
01019 indices_index += facep->getIndicesCount();
01020 index_offset += facep->getGeomCount();
01021 }
01022
01023 mFaceList.clear();
01024 }
01025