00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llviewerparceloverlay.h"
00035
00036
00037 #include "llparcel.h"
00038 #include "llgl.h"
00039 #include "llglimmediate.h"
00040 #include "v4color.h"
00041 #include "v2math.h"
00042
00043
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
00067 {
00068
00069
00070
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
00081
00082
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
00092
00093 mOwnership = new U8[ mParcelGridsPerEdge * mParcelGridsPerEdge ];
00094 for (S32 i = 0; i < mParcelGridsPerEdge * mParcelGridsPerEdge; i++)
00095 {
00096 mOwnership[i] = PARCEL_PUBLIC;
00097 }
00098
00099
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
00116
00117
00118
00119 mImageRaw = NULL;
00120 }
00121
00122
00123
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
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 void LLViewerParcelOverlay::updateOverlayTexture()
00198 {
00199 if (mOverlayTextureIdx < 0 && mDirty)
00200 {
00201 mOverlayTextureIdx = 0;
00202 }
00203 if (mOverlayTextureIdx < 0)
00204 {
00205 return;
00206 }
00207
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
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
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
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
00299 S32 size = mParcelGridsPerEdge * mParcelGridsPerEdge;
00300 S32 chunk_size = size / PARCEL_OVERLAY_CHUNKS;
00301
00302 memcpy(mOwnership + chunk*chunk_size, packed_overlay, chunk_size);
00303
00304
00305 setDirty();
00306 }
00307
00308
00309 void LLViewerParcelOverlay::updatePropertyLines()
00310 {
00311 if (!gSavedSettings.getBOOL("ShowPropertyLines"))
00312 return;
00313
00314 S32 row, col;
00315
00316
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
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
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
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
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
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
00489
00490
00491 S32 new_vertex_count = new_vertex_array.count();
00492
00493 if (!(mVertexArray && mColorArray && new_vertex_count == mVertexCount))
00494 {
00495
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
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
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
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
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
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
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
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
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
00722 updateOverlayTexture();
00723 return;
00724 }
00725
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;
00751 LLGLSNoTexture gls_no_texture;
00752 LLGLDepthTest mDepthTest(GL_TRUE);
00753
00754
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
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
00768 pull_toward_camera.mV[VZ] += 0.01f;
00769
00770 glMatrixMode( GL_MODELVIEW );
00771 glPushMatrix();
00772
00773
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
00781
00782 const S32 GRID_STEP = S32( PARCEL_GRID_STEP_METERS );
00783 const S32 vertex_per_edge = 3 + 2 * (GRID_STEP-1) + 3;
00784
00785
00786 LLVector3 camera_region = mRegion->getPosRegionFromGlobal( gAgent.getCameraPositionGlobal() );
00787
00788
00789
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
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
00821 vertex -= cull_plane_point;
00822
00823
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 }