00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llviewerparceloverlay.h"
00035
00036
00037 #include "llparcel.h"
00038 #include "llgl.h"
00039 #include "v4color.h"
00040 #include "v2math.h"
00041
00042
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
00065 {
00066
00067
00068
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
00079
00080
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
00090
00091 mOwnership = new U8[ mParcelGridsPerEdge * mParcelGridsPerEdge ];
00092 for (S32 i = 0; i < mParcelGridsPerEdge * mParcelGridsPerEdge; i++)
00093 {
00094 mOwnership[i] = PARCEL_PUBLIC;
00095 }
00096
00097
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
00114
00115
00116
00117 mImageRaw = NULL;
00118 }
00119
00120
00121
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
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 void LLViewerParcelOverlay::updateOverlayTexture()
00196 {
00197 if (mOverlayTextureIdx < 0 && mDirty)
00198 {
00199 mOverlayTextureIdx = 0;
00200 }
00201 if (mOverlayTextureIdx < 0)
00202 {
00203 return;
00204 }
00205
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
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
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
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
00297 S32 size = mParcelGridsPerEdge * mParcelGridsPerEdge;
00298 S32 chunk_size = size / PARCEL_OVERLAY_CHUNKS;
00299
00300 memcpy(mOwnership + chunk*chunk_size, packed_overlay, chunk_size);
00301
00302
00303 setDirty();
00304 }
00305
00306
00307 void LLViewerParcelOverlay::updatePropertyLines()
00308 {
00309 if (!gSavedSettings.getBOOL("ShowPropertyLines"))
00310 return;
00311
00312 S32 row, col;
00313
00314
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
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
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
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
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
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
00487
00488
00489 S32 new_vertex_count = new_vertex_array.count();
00490
00491 if (!(mVertexArray && mColorArray && new_vertex_count == mVertexCount))
00492 {
00493
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
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
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
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
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
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
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
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
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
00720 updateOverlayTexture();
00721 return;
00722 }
00723
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;
00749 LLGLSNoTexture gls_no_texture;
00750 LLGLDepthTest mDepthTest(GL_TRUE);
00751
00752
00753
00754
00755
00756
00757
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
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
00771 pull_toward_camera.mV[VZ] += 0.01f;
00772
00773 glMatrixMode( GL_MODELVIEW );
00774 glPushMatrix();
00775
00776
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
00784
00785 const S32 GRID_STEP = S32( PARCEL_GRID_STEP_METERS );
00786 const S32 vertex_per_edge = 3 + 2 * (GRID_STEP-1) + 3;
00787
00788
00789 LLVector3 camera_region = mRegion->getPosRegionFromGlobal( gAgent.getCameraPositionGlobal() );
00790
00791
00792
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
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
00824 vertex -= cull_plane_point;
00825
00826
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
00837
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 }