llvosurfacepatch.cpp

Go to the documentation of this file.
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         // virtual
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         // Terrain must draw during selection passes so it can block objects behind it.
00108         mbCanSelect = TRUE;
00109         setScale(LLVector3(16.f, 16.f, 16.f)); // Hack for setting scale for bounding boxes/visibility.
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                         // The top side runs over more
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                         // The top side runs over more
00201                         new_base_comp++;
00202                 }
00203                 range = 3;
00204         }
00205 
00206         // Pick the two closest detail textures for this patch...
00207         // Then create the draw pool for it.
00208         // Actually, should get the average composition instead of the center.
00209         mBaseComp = new_base_comp;
00210 
00212         //
00213         // Figure out the strides
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         //mDrawable->updateLightSet();
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         // Render the main patch
00338         //
00339         //
00340 
00341         num_vertices = 0;
00342         num_indices = 0;
00343         // First, figure out how many vertices we need...
00344         getGeomSizesMain(render_stride, num_vertices, num_indices);
00345 
00346         if (num_vertices > 0)
00347         {
00348                 facep->mCenterAgent = mPatchp->getPointAgent(8, 8);
00349 
00350                 // Generate patch points first
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         // Render the north strip
00444         //
00445         //
00446 
00447         // Stride lengths are the same
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                 // Main patch
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                 // North patch
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                         // Generate indices
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                 // North stride is longer (has less vertices)
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                 // Iterate through this patch's points
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                 // Iterate through the north patch's points
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                 // North stride is shorter (more vertices)
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                 // Iterate through this patch's points
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                 // Iterate through the north patch's points
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         // Stride lengths are the same
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                 // Main patch
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                 // East patch
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                         // Generate indices
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                 // East stride is longer (has less vertices)
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                 // Iterate through this patch's points
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                 // Iterate through the east patch's points
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                 // East stride is shorter (more vertices)
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                 // Iterate through this patch's points
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                 // Iterate through the east patch's points
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; //terrain updates its shadows during standard relight
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         // First, figure out how many vertices we need...
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         // Stride lengths are the same
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                 // North stride is longer (has less vertices)
00920                 num_vertices += length + (length/2) + 1;
00921                 num_indices += (length/2)*9 - 3;
00922         }
00923         else
00924         {
00925                 // North stride is shorter (more vertices)
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         // Stride lengths are the same
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                 // East stride is longer (has less vertices)
00946                 num_vertices += length + (length/2) + 1;
00947                 num_indices += (length/2)*9 - 3;
00948         }
00949         else
00950         {
00951                 // East stride is shorter (more vertices)
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         //get vertex buffer striders
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 

Generated on Thu Jul 1 06:09:43 2010 for Second Life Viewer by  doxygen 1.4.7