llviewerparceloverlay.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llviewerparceloverlay.h"
00035 
00036 // indra includes
00037 #include "llparcel.h"
00038 #include "llgl.h"
00039 #include "v4color.h"
00040 #include "v2math.h"
00041 
00042 // newview includes
00043 #include "llviewerimage.h"
00044 #include "llviewercontrol.h"
00045 #include "llsurface.h"
00046 #include "llviewerregion.h"
00047 #include "llagent.h"
00048 #include "llviewercamera.h"
00049 #include "llviewerimagelist.h"
00050 #include "llglheaders.h"
00051 
00052 const U8  OVERLAY_IMG_COMPONENTS = 4;
00053 
00054 LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_width_meters)
00055 :       mRegion( region ),
00056         mParcelGridsPerEdge( S32( region_width_meters / PARCEL_GRID_STEP_METERS ) ),
00057         mDirty( FALSE ),
00058         mTimeSinceLastUpdate(),
00059         mOverlayTextureIdx(-1),
00060         mLineImageID( gViewerArt.getString("propertyline.tga") ),
00061         mVertexCount(0),
00062         mVertexArray(NULL),
00063         mColorArray(NULL)
00064 //      mTexCoordArray(NULL),
00065 {
00066         // Create a texture to hold color information.
00067         // 4 components
00068         // Use mipmaps = FALSE, clamped, NEAREST filter, for sharp edges
00069         mTexture = new LLImageGL(FALSE);
00070         mImageRaw = new LLImageRaw(mParcelGridsPerEdge, mParcelGridsPerEdge, OVERLAY_IMG_COMPONENTS);
00071         mTexture->createGLTexture(0, mImageRaw);
00072         glActiveTextureARB(GL_TEXTURE0_ARB);
00073         mTexture->bind(0);
00074         mTexture->setClamp(TRUE, TRUE);
00075         mTexture->setMipFilterNearest(TRUE);
00076 
00077         //
00078         // Initialize the GL texture with empty data.
00079         //
00080         // Create the base texture.
00081         U8 *raw = mImageRaw->getData();
00082         const S32 COUNT = mParcelGridsPerEdge * mParcelGridsPerEdge * OVERLAY_IMG_COMPONENTS;
00083         for (S32 i = 0; i < COUNT; i++)
00084         {
00085                 raw[i] = 0;
00086         }
00087         mTexture->setSubImage(mImageRaw, 0, 0, mParcelGridsPerEdge, mParcelGridsPerEdge);
00088 
00089         // Create storage for ownership information from simulator
00090         // and initialize it.
00091         mOwnership = new U8[ mParcelGridsPerEdge * mParcelGridsPerEdge ];
00092         for (S32 i = 0; i < mParcelGridsPerEdge * mParcelGridsPerEdge; i++)
00093         {
00094                 mOwnership[i] = PARCEL_PUBLIC;
00095         }
00096 
00097         // Make sure the texture matches the ownership information.
00098         updateOverlayTexture();
00099 }
00100 
00101 
00102 LLViewerParcelOverlay::~LLViewerParcelOverlay()
00103 {
00104         delete[] mOwnership;
00105         mOwnership = NULL;
00106 
00107         delete[] mVertexArray;
00108         mVertexArray = NULL;
00109 
00110         delete[] mColorArray;
00111         mColorArray = NULL;
00112 
00113 // JC No textures.
00114 //      delete mTexCoordArray;
00115 //      mTexCoordArray = NULL;
00116 
00117         mImageRaw = NULL;
00118 }
00119 
00120 //---------------------------------------------------------------------------
00121 // ACCESSORS
00122 //---------------------------------------------------------------------------
00123 BOOL LLViewerParcelOverlay::isOwned(const LLVector3& pos) const
00124 {
00125         S32 row =    S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS);
00126         S32 column = S32(pos.mV[VX] / PARCEL_GRID_STEP_METERS);
00127         return (PARCEL_PUBLIC != ownership(row, column));
00128 }
00129 
00130 BOOL LLViewerParcelOverlay::isOwnedSelf(const LLVector3& pos) const
00131 {
00132         S32 row =    S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS);
00133         S32 column = S32(pos.mV[VX] / PARCEL_GRID_STEP_METERS);
00134         return (PARCEL_SELF == ownership(row, column));
00135 }
00136 
00137 BOOL LLViewerParcelOverlay::isOwnedGroup(const LLVector3& pos) const
00138 {
00139         S32 row =    S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS);
00140         S32 column = S32(pos.mV[VX] / PARCEL_GRID_STEP_METERS);
00141         return (PARCEL_GROUP == ownership(row, column));
00142 }
00143 
00144 BOOL LLViewerParcelOverlay::isOwnedOther(const LLVector3& pos) const
00145 {
00146         S32 row =    S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS);
00147         S32 column = S32(pos.mV[VX] / PARCEL_GRID_STEP_METERS);
00148         U8 overlay = ownership(row, column);
00149         return (PARCEL_OWNED == overlay || PARCEL_FOR_SALE == overlay);
00150 }
00151 
00152 BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const
00153 {
00154         S32 row =    S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS);
00155         S32 column = S32(pos.mV[VX] / PARCEL_GRID_STEP_METERS);
00156         return PARCEL_SOUND_LOCAL & mOwnership[row * mParcelGridsPerEdge + column];
00157 }
00158 
00159 U8 LLViewerParcelOverlay::ownership( const LLVector3& pos) const
00160 {
00161         S32 row =    S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS);
00162         S32 column = S32(pos.mV[VX] / PARCEL_GRID_STEP_METERS);
00163         return ownership(row, column);
00164 }
00165 
00166 F32 LLViewerParcelOverlay::getOwnedRatio() const
00167 {
00168         S32     size = mParcelGridsPerEdge * mParcelGridsPerEdge;
00169         S32 total = 0;
00170 
00171         for (S32 i = 0; i < size; i++)
00172         {
00173                 if ((mOwnership[i] & PARCEL_COLOR_MASK) != PARCEL_PUBLIC)
00174                 {
00175                         total++;
00176                 }
00177         }
00178 
00179         return (F32)total / (F32)size;
00180 
00181 }
00182 
00183 //---------------------------------------------------------------------------
00184 // MANIPULATORS
00185 //---------------------------------------------------------------------------
00186 
00187 // Color tables for owned land
00188 // Available = index 0
00189 // Other     = index 1
00190 // Group     = index 2
00191 // Self      = index 3
00192 
00193 // Make sure the texture colors match the ownership data.
00194 // Note: Assumes that the ownership array and 
00195 void LLViewerParcelOverlay::updateOverlayTexture()
00196 {
00197         if (mOverlayTextureIdx < 0 && mDirty)
00198         {
00199                 mOverlayTextureIdx = 0;
00200         }
00201         if (mOverlayTextureIdx < 0)
00202         {
00203                 return;
00204         }
00205         // Can do this because gColors are actually stored as LLColor4U
00206         const LLColor4U avail = gColors.getColor4U("PropertyColorAvail");
00207         const LLColor4U owned = gColors.getColor4U("PropertyColorOther");
00208         const LLColor4U group = gColors.getColor4U("PropertyColorGroup");
00209         const LLColor4U self  = gColors.getColor4U("PropertyColorSelf");
00210         const LLColor4U for_sale  = gColors.getColor4U("PropertyColorForSale");
00211         const LLColor4U auction  = gColors.getColor4U("PropertyColorAuction");
00212 
00213         // Create the base texture.
00214         U8 *raw = mImageRaw->getData();
00215         const S32 COUNT = mParcelGridsPerEdge * mParcelGridsPerEdge;
00216         S32 max = mOverlayTextureIdx + mParcelGridsPerEdge;
00217         if (max > COUNT) max = COUNT;
00218         S32 pixel_index = mOverlayTextureIdx*OVERLAY_IMG_COMPONENTS;
00219         S32 i;
00220         for (i = mOverlayTextureIdx; i < max; i++)
00221         {
00222                 U8 ownership = mOwnership[i];
00223 
00224                 U8 r,g,b,a;
00225 
00226                 // Color stored in low three bits
00227                 switch( ownership & 0x7 )
00228                 {
00229                 case PARCEL_PUBLIC:
00230                         r = avail.mV[VRED];
00231                         g = avail.mV[VGREEN];
00232                         b = avail.mV[VBLUE];
00233                         a = avail.mV[VALPHA];
00234                         break;
00235                 case PARCEL_OWNED:
00236                         r = owned.mV[VRED];
00237                         g = owned.mV[VGREEN];
00238                         b = owned.mV[VBLUE];
00239                         a = owned.mV[VALPHA];
00240                         break;
00241                 case PARCEL_GROUP:
00242                         r = group.mV[VRED];
00243                         g = group.mV[VGREEN];
00244                         b = group.mV[VBLUE];
00245                         a = group.mV[VALPHA];
00246                         break;
00247                 case PARCEL_SELF:
00248                         r = self.mV[VRED];
00249                         g = self.mV[VGREEN];
00250                         b = self.mV[VBLUE];
00251                         a = self.mV[VALPHA];
00252                         break;
00253                 case PARCEL_FOR_SALE:
00254                         r = for_sale.mV[VRED];
00255                         g = for_sale.mV[VGREEN];
00256                         b = for_sale.mV[VBLUE];
00257                         a = for_sale.mV[VALPHA];
00258                         break;
00259                 case PARCEL_AUCTION:
00260                         r = auction.mV[VRED];
00261                         g = auction.mV[VGREEN];
00262                         b = auction.mV[VBLUE];
00263                         a = auction.mV[VALPHA];
00264                         break;
00265                 default:
00266                         r = self.mV[VRED];
00267                         g = self.mV[VGREEN];
00268                         b = self.mV[VBLUE];
00269                         a = self.mV[VALPHA];
00270                         break;
00271                 }
00272 
00273                 raw[pixel_index + 0] = r;
00274                 raw[pixel_index + 1] = g;
00275                 raw[pixel_index + 2] = b;
00276                 raw[pixel_index + 3] = a;
00277 
00278                 pixel_index += OVERLAY_IMG_COMPONENTS;
00279         }
00280         
00281         // Copy data into GL texture from raw data
00282         if (i >= COUNT)
00283         {
00284                 mTexture->setSubImage(mImageRaw, 0, 0, mParcelGridsPerEdge, mParcelGridsPerEdge);
00285                 mOverlayTextureIdx = -1;
00286         }
00287         else
00288         {
00289                 mOverlayTextureIdx = i;
00290         }
00291 }
00292 
00293 
00294 void LLViewerParcelOverlay::uncompressLandOverlay(S32 chunk, U8 *packed_overlay)
00295 {
00296         // Unpack the message data into the ownership array
00297         S32     size    = mParcelGridsPerEdge * mParcelGridsPerEdge;
00298         S32 chunk_size = size / PARCEL_OVERLAY_CHUNKS;
00299 
00300         memcpy(mOwnership + chunk*chunk_size, packed_overlay, chunk_size);              /*Flawfinder: ignore*/
00301 
00302         // Force property lines and overlay texture to update
00303         setDirty();
00304 }
00305 
00306 
00307 void LLViewerParcelOverlay::updatePropertyLines()
00308 {
00309         if (!gSavedSettings.getBOOL("ShowPropertyLines"))
00310                 return;
00311         
00312         S32 row, col;
00313 
00314         // Can do this because gColors are actually stored as LLColor4U
00315         const LLColor4U self_coloru  = gColors.getColor4U("PropertyColorSelf");
00316         const LLColor4U other_coloru = gColors.getColor4U("PropertyColorOther");
00317         const LLColor4U group_coloru = gColors.getColor4U("PropertyColorGroup");
00318         const LLColor4U for_sale_coloru = gColors.getColor4U("PropertyColorForSale");
00319         const LLColor4U auction_coloru = gColors.getColor4U("PropertyColorAuction");
00320 
00321         // Build into dynamic arrays, then copy into static arrays.
00322         LLDynamicArray<LLVector3, 256> new_vertex_array;
00323         LLDynamicArray<LLColor4U, 256> new_color_array;
00324         LLDynamicArray<LLVector2, 256> new_coord_array;
00325 
00326         U8 overlay = 0;
00327         BOOL add_edge = FALSE;
00328         const F32 GRID_STEP = PARCEL_GRID_STEP_METERS;
00329         const S32 GRIDS_PER_EDGE = mParcelGridsPerEdge;
00330 
00331         for (row = 0; row < GRIDS_PER_EDGE; row++)
00332         {
00333                 for (col = 0; col < GRIDS_PER_EDGE; col++)
00334                 {
00335                         overlay = mOwnership[row*GRIDS_PER_EDGE+col];
00336 
00337                         F32 left = col*GRID_STEP;
00338                         F32 right = left+GRID_STEP;
00339 
00340                         F32 bottom = row*GRID_STEP;
00341                         F32 top = bottom+GRID_STEP;
00342 
00343                         // West edge
00344                         if (overlay & PARCEL_WEST_LINE)
00345                         {
00346                                 switch(overlay & PARCEL_COLOR_MASK)
00347                                 {
00348                                 case PARCEL_SELF:
00349                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00350                                                 left, bottom, WEST, self_coloru);
00351                                         break;
00352                                 case PARCEL_GROUP:
00353                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00354                                                 left, bottom, WEST, group_coloru);
00355                                         break;
00356                                 case PARCEL_OWNED:
00357                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00358                                                 left, bottom, WEST, other_coloru);
00359                                         break;
00360                                 case PARCEL_FOR_SALE:
00361                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00362                                                 left, bottom, WEST, for_sale_coloru);
00363                                         break;
00364                                 case PARCEL_AUCTION:
00365                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00366                                                 left, bottom, WEST, auction_coloru);
00367                                         break;
00368                                 default:
00369                                         break;
00370                                 }
00371                         }
00372 
00373                         // East edge
00374                         if (col < GRIDS_PER_EDGE-1)
00375                         {
00376                                 U8 east_overlay = mOwnership[row*GRIDS_PER_EDGE+col+1];
00377                                 add_edge = east_overlay & PARCEL_WEST_LINE;
00378                         }
00379                         else
00380                         {
00381                                 add_edge = TRUE;
00382                         }
00383 
00384                         if (add_edge)
00385                         {
00386                                 switch(overlay & PARCEL_COLOR_MASK)
00387                                 {
00388                                 case PARCEL_SELF:
00389                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00390                                                 right, bottom, EAST, self_coloru);
00391                                         break;
00392                                 case PARCEL_GROUP:
00393                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00394                                                 right, bottom, EAST, group_coloru);
00395                                         break;
00396                                 case PARCEL_OWNED:
00397                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00398                                                 right, bottom, EAST, other_coloru);
00399                                         break;
00400                                 case PARCEL_FOR_SALE:
00401                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00402                                                 right, bottom, EAST, for_sale_coloru);
00403                                         break;
00404                                 case PARCEL_AUCTION:
00405                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00406                                                 right, bottom, EAST, auction_coloru);
00407                                         break;
00408                                 default:
00409                                         break;
00410                                 }
00411                         }
00412 
00413                         // South edge
00414                         if (overlay & PARCEL_SOUTH_LINE)
00415                         {
00416                                 switch(overlay & PARCEL_COLOR_MASK)
00417                                 {
00418                                 case PARCEL_SELF:
00419                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00420                                                 left, bottom, SOUTH, self_coloru);
00421                                         break;
00422                                 case PARCEL_GROUP:
00423                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00424                                                 left, bottom, SOUTH, group_coloru);
00425                                         break;
00426                                 case PARCEL_OWNED:
00427                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00428                                                 left, bottom, SOUTH, other_coloru);
00429                                         break;
00430                                 case PARCEL_FOR_SALE:
00431                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00432                                                 left, bottom, SOUTH, for_sale_coloru);
00433                                         break;
00434                                 case PARCEL_AUCTION:
00435                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00436                                                 left, bottom, SOUTH, auction_coloru);
00437                                         break;
00438                                 default:
00439                                         break;
00440                                 }
00441                         }
00442 
00443 
00444                         // North edge
00445                         if (row < GRIDS_PER_EDGE-1)
00446                         {
00447                                 U8 north_overlay = mOwnership[(row+1)*GRIDS_PER_EDGE+col];
00448                                 add_edge = north_overlay & PARCEL_SOUTH_LINE;
00449                         }
00450                         else
00451                         {
00452                                 add_edge = TRUE;
00453                         }
00454 
00455                         if (add_edge)
00456                         {
00457                                 switch(overlay & PARCEL_COLOR_MASK)
00458                                 {
00459                                 case PARCEL_SELF:
00460                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00461                                                 left, top, NORTH, self_coloru);
00462                                         break;
00463                                 case PARCEL_GROUP:
00464                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00465                                                 left, top, NORTH, group_coloru);
00466                                         break;
00467                                 case PARCEL_OWNED:
00468                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00469                                                 left, top, NORTH, other_coloru);
00470                                         break;
00471                                 case PARCEL_FOR_SALE:
00472                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00473                                                 left, top, NORTH, for_sale_coloru);
00474                                         break;
00475                                 case PARCEL_AUCTION:
00476                                         addPropertyLine(new_vertex_array, new_color_array, new_coord_array,
00477                                                 left, top, NORTH, auction_coloru);
00478                                         break;
00479                                 default:
00480                                         break;
00481                                 }
00482                         }
00483                 }
00484         }
00485 
00486         // Now copy into static arrays for faster rendering.
00487         // Attempt to recycle old arrays if possible to avoid memory
00488         // shuffling.
00489         S32 new_vertex_count = new_vertex_array.count();
00490         
00491         if (!(mVertexArray && mColorArray && new_vertex_count == mVertexCount))
00492         {
00493                 // ...need new arrays
00494                 delete[] mVertexArray;
00495                 mVertexArray = NULL;
00496                 delete[] mColorArray;
00497                 mColorArray = NULL;
00498 
00499                 mVertexCount = new_vertex_count;
00500 
00501                 if (new_vertex_count > 0)
00502                 {
00503                         mVertexArray   = new F32[3 * mVertexCount];
00504                         mColorArray    = new U8 [4 * mVertexCount];
00505                 }
00506         }
00507 
00508         // Copy the new data into the arrays
00509         S32 i;
00510         F32* vertex = mVertexArray;
00511         for (i = 0; i < mVertexCount; i++)
00512         {
00513                 const LLVector3& point = new_vertex_array.get(i);
00514                 *vertex = point.mV[VX];
00515                 vertex++;
00516                 *vertex = point.mV[VY];
00517                 vertex++;
00518                 *vertex = point.mV[VZ];
00519                 vertex++;
00520         }
00521 
00522         U8* colorp = mColorArray;
00523         for (i = 0; i < mVertexCount; i++)
00524         {
00525                 const LLColor4U& color = new_color_array.get(i);
00526                 *colorp = color.mV[VRED];
00527                 colorp++;
00528                 *colorp = color.mV[VGREEN];
00529                 colorp++;
00530                 *colorp = color.mV[VBLUE];
00531                 colorp++;
00532                 *colorp = color.mV[VALPHA];
00533                 colorp++;
00534         }
00535         
00536         // Everything's clean now
00537         mDirty = FALSE;
00538 }
00539 
00540 
00541 void LLViewerParcelOverlay::addPropertyLine(
00542                                 LLDynamicArray<LLVector3, 256>& vertex_array,
00543                                 LLDynamicArray<LLColor4U, 256>& color_array,
00544                                 LLDynamicArray<LLVector2, 256>& coord_array,
00545                                 const F32 start_x, const F32 start_y, 
00546                                 const U32 edge,
00547                                 const LLColor4U& color)
00548 {
00549         LLColor4U underwater( color );
00550         underwater.mV[VALPHA] /= 2;
00551 
00552         LLSurface& land = mRegion->getLand();
00553 
00554         F32 dx;
00555         F32 dy;
00556         F32 tick_dx;
00557         F32 tick_dy;
00558         //const F32 LINE_WIDTH = 0.125f;
00559         const F32 LINE_WIDTH = 0.0625f;
00560 
00561         switch(edge)
00562         {
00563         case WEST:
00564                 dx = 0.f;
00565                 dy = 1.f;
00566                 tick_dx = LINE_WIDTH;
00567                 tick_dy = 0.f;
00568                 break;
00569 
00570         case EAST:
00571                 dx = 0.f;
00572                 dy = 1.f;
00573                 tick_dx = -LINE_WIDTH;
00574                 tick_dy = 0.f;
00575                 break;
00576 
00577         case NORTH:
00578                 dx = 1.f;
00579                 dy = 0.f;
00580                 tick_dx = 0.f;
00581                 tick_dy = -LINE_WIDTH;
00582                 break;
00583 
00584         case SOUTH:
00585                 dx = 1.f;
00586                 dy = 0.f;
00587                 tick_dx = 0.f;
00588                 tick_dy = LINE_WIDTH;
00589                 break;
00590 
00591         default:
00592                 llerrs << "Invalid edge in addPropertyLine" << llendl;
00593                 return;
00594         }
00595 
00596         F32 outside_x = start_x;
00597         F32 outside_y = start_y;
00598         F32 outside_z = 0.f;
00599         F32 inside_x  = start_x + tick_dx;
00600         F32 inside_y  = start_y + tick_dy;
00601         F32 inside_z  = 0.f;
00602 
00603         // First part, only one vertex
00604         outside_z = land.resolveHeightRegion( outside_x, outside_y );
00605 
00606         if (outside_z > 20.f) color_array.put( color );
00607         else color_array.put( underwater );
00608 
00609         vertex_array.put( LLVector3(outside_x, outside_y, outside_z) );
00610         coord_array.put(  LLVector2(outside_x - start_x, 0.f) );
00611 
00612         inside_x += dx * LINE_WIDTH;
00613         inside_y += dy * LINE_WIDTH;
00614 
00615         outside_x += dx * LINE_WIDTH;
00616         outside_y += dy * LINE_WIDTH;
00617 
00618         // Then the "actual edge"
00619         inside_z = land.resolveHeightRegion( inside_x, inside_y );
00620         outside_z = land.resolveHeightRegion( outside_x, outside_y );
00621 
00622         if (inside_z > 20.f) color_array.put( color );
00623         else color_array.put( underwater );
00624 
00625         if (outside_z > 20.f) color_array.put( color );
00626         else color_array.put( underwater );
00627 
00628         vertex_array.put( LLVector3(inside_x, inside_y, inside_z) );
00629         vertex_array.put( LLVector3(outside_x, outside_y, outside_z) );
00630 
00631         coord_array.put(  LLVector2(outside_x - start_x, 1.f) );
00632         coord_array.put(  LLVector2(outside_x - start_x, 0.f) );
00633 
00634         inside_x += dx * (dx - LINE_WIDTH);
00635         inside_y += dy * (dy - LINE_WIDTH);
00636 
00637         outside_x += dx * (dx - LINE_WIDTH);
00638         outside_y += dy * (dy - LINE_WIDTH);
00639 
00640         // Middle part, full width
00641         S32 i;
00642         const S32 GRID_STEP = S32( PARCEL_GRID_STEP_METERS );
00643         for (i = 1; i < GRID_STEP; i++)
00644         {
00645                 inside_z = land.resolveHeightRegion( inside_x, inside_y );
00646                 outside_z = land.resolveHeightRegion( outside_x, outside_y );
00647 
00648                 if (inside_z > 20.f) color_array.put( color );
00649                 else color_array.put( underwater );
00650 
00651                 if (outside_z > 20.f) color_array.put( color );
00652                 else color_array.put( underwater );
00653 
00654                 vertex_array.put( LLVector3(inside_x, inside_y, inside_z) );
00655                 vertex_array.put( LLVector3(outside_x, outside_y, outside_z) );
00656 
00657                 coord_array.put(  LLVector2(outside_x - start_x, 1.f) );
00658                 coord_array.put(  LLVector2(outside_x - start_x, 0.f) );
00659 
00660                 inside_x += dx;
00661                 inside_y += dy;
00662 
00663                 outside_x += dx;
00664                 outside_y += dy;
00665         }
00666 
00667         // Extra buffer for edge
00668         inside_x -= dx * LINE_WIDTH;
00669         inside_y -= dy * LINE_WIDTH;
00670 
00671         outside_x -= dx * LINE_WIDTH;
00672         outside_y -= dy * LINE_WIDTH;
00673 
00674         inside_z = land.resolveHeightRegion( inside_x, inside_y );
00675         outside_z = land.resolveHeightRegion( outside_x, outside_y );
00676 
00677         if (inside_z > 20.f) color_array.put( color );
00678         else color_array.put( underwater );
00679 
00680         if (outside_z > 20.f) color_array.put( color );
00681         else color_array.put( underwater );
00682 
00683         vertex_array.put( LLVector3(inside_x, inside_y, inside_z) );
00684         vertex_array.put( LLVector3(outside_x, outside_y, outside_z) );
00685 
00686         coord_array.put(  LLVector2(outside_x - start_x, 1.f) );
00687         coord_array.put(  LLVector2(outside_x - start_x, 0.f) );
00688 
00689         inside_x += dx * LINE_WIDTH;
00690         inside_y += dy * LINE_WIDTH;
00691 
00692         outside_x += dx * LINE_WIDTH;
00693         outside_y += dy * LINE_WIDTH;
00694 
00695         // Last edge is not drawn to the edge
00696         outside_z = land.resolveHeightRegion( outside_x, outside_y );
00697 
00698         if (outside_z > 20.f) color_array.put( color );
00699         else color_array.put( underwater );
00700 
00701         vertex_array.put( LLVector3(outside_x, outside_y, outside_z) );
00702         coord_array.put(  LLVector2(outside_x - start_x, 0.f) );
00703 }
00704 
00705 
00706 void LLViewerParcelOverlay::setDirty()
00707 {
00708         mDirty = TRUE;
00709 }
00710 
00711 void LLViewerParcelOverlay::idleUpdate(bool force_update)
00712 {
00713         if (gGLManager.mIsDisabled)
00714         {
00715                 return;
00716         }
00717         if (mOverlayTextureIdx >= 0 && (!(mDirty && force_update)))
00718         {
00719                 // We are in the middle of updating the overlay texture
00720                 updateOverlayTexture();
00721                 return;
00722         }
00723         // Only if we're dirty and it's been a while since the last update.
00724         if (mDirty)
00725         {
00726                 if (force_update || mTimeSinceLastUpdate.getElapsedTimeF32() > 4.0f)
00727                 {
00728                         updateOverlayTexture();
00729                         updatePropertyLines();
00730                         mTimeSinceLastUpdate.reset();
00731                 }
00732         }
00733 }
00734 
00735 S32 LLViewerParcelOverlay::renderPropertyLines  () 
00736 {
00737         if (!gSavedSettings.getBOOL("ShowPropertyLines"))
00738         {
00739                 return 0;
00740         }
00741         if (!mVertexArray || !mColorArray)
00742         {
00743                 return 0;
00744         }
00745 
00746         LLSurface& land = mRegion->getLand();
00747 
00748         LLGLSUIDefault gls_ui; // called from pipeline
00749         LLGLSNoTexture gls_no_texture;
00750         LLGLDepthTest mDepthTest(GL_TRUE);
00751 
00752         // JC - This doesn't work.
00753         //gGLSUITextureDepth.set();
00754         //LLViewerImage* image = gImageList.getImage( mLineImageID );
00755         //image->bindTexture();
00756 
00757         // Find camera height off the ground (not from zero)
00758         F32 ground_height_at_camera = land.resolveHeightGlobal( gAgent.getCameraPositionGlobal() );
00759         F32 camera_z = gCamera->getOrigin().mV[VZ];
00760         F32 camera_height = camera_z - ground_height_at_camera;
00761 
00762         camera_height = llclamp(camera_height, 0.f, 100.f);
00763 
00764         // Pull lines toward camera by 1 cm per meter off the ground.
00765         const LLVector3& CAMERA_AT = gCamera->getAtAxis();
00766         F32 pull_toward_camera_scale = 0.01f * camera_height;
00767         LLVector3 pull_toward_camera = CAMERA_AT;
00768         pull_toward_camera *= -pull_toward_camera_scale;
00769 
00770         // Always fudge a little vertically.
00771         pull_toward_camera.mV[VZ] += 0.01f;
00772 
00773         glMatrixMode( GL_MODELVIEW );
00774         glPushMatrix();
00775 
00776         // Move to appropriate region coords
00777         LLVector3 origin = mRegion->getOriginAgent();
00778         glTranslatef( origin.mV[VX], origin.mV[VY], origin.mV[VZ] );
00779 
00780         glTranslatef(pull_toward_camera.mV[VX], pull_toward_camera.mV[VY],
00781                 pull_toward_camera.mV[VZ]);
00782 
00783         // Include +1 because vertices are fenceposts.
00784         // *2 because it's a quad strip
00785         const S32 GRID_STEP = S32( PARCEL_GRID_STEP_METERS );
00786         const S32 vertex_per_edge = 3 + 2 * (GRID_STEP-1) + 3;
00787 
00788         // Stomp the camera into two dimensions
00789         LLVector3 camera_region = mRegion->getPosRegionFromGlobal( gAgent.getCameraPositionGlobal() );
00790 
00791         // Set up a cull plane 2 * PARCEL_GRID_STEP_METERS behind
00792         // the camera.  The cull plane normal is the camera's at axis.
00793         LLVector3 cull_plane_point = gCamera->getAtAxis();
00794         cull_plane_point *= -2.f * PARCEL_GRID_STEP_METERS;
00795         cull_plane_point += camera_region;
00796 
00797         LLVector3 vertex;
00798 
00799         const S32 BYTES_PER_COLOR = 4;
00800         const S32 FLOATS_PER_VERTEX = 3;
00801         //const S32 FLOATS_PER_TEX_COORD = 2;
00802         S32 i, j;
00803         S32 drawn = 0;
00804         F32* vertexp;
00805         U8* colorp;
00806 
00807         const F32 PROPERTY_LINE_CLIP_DIST = 256.f;
00808 
00809         for (i = 0; i < mVertexCount; i += vertex_per_edge)
00810         {
00811                 colorp  = mColorArray  + BYTES_PER_COLOR   * i;
00812                 vertexp = mVertexArray + FLOATS_PER_VERTEX * i;
00813 
00814                 vertex.mV[VX] = *(vertexp);
00815                 vertex.mV[VY] = *(vertexp+1);
00816                 vertex.mV[VZ] = *(vertexp+2);
00817 
00818                 if (dist_vec_squared2D(vertex, camera_region) > PROPERTY_LINE_CLIP_DIST*PROPERTY_LINE_CLIP_DIST)
00819                 {
00820                         continue;
00821                 }
00822 
00823                 // Destroy vertex, transform to plane-local.
00824                 vertex -= cull_plane_point;
00825 
00826                 // negative dot product means it is in back of the plane
00827                 if ( vertex * CAMERA_AT < 0.f )
00828                 {
00829                         continue;
00830                 }
00831 
00832                 glBegin(GL_TRIANGLE_STRIP);
00833 
00834                 for (j = 0; j < vertex_per_edge; j++)
00835                 {
00836                         // JC - This doesn't work
00837                         //glTexCoord2fv(mTexCoordArray + FLOATS_PER_TEX_COORD*offset);
00838                         glColor4ubv(colorp);
00839                         glVertex3fv(vertexp);
00840 
00841                         colorp  += BYTES_PER_COLOR;
00842                         vertexp += FLOATS_PER_VERTEX;                   
00843                 }
00844 
00845                 drawn += vertex_per_edge;
00846 
00847                 glEnd();
00848         }
00849 
00850         glPopMatrix();
00851 
00852         return drawn;
00853 }

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