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

Generated on Fri May 16 08:34:16 2008 for SecondLife by  doxygen 1.5.5