Merge remote branch 'origin/unimap2'

This commit is contained in:
Siana Gearz
2011-03-16 01:40:29 +01:00
10 changed files with 988 additions and 401 deletions

View File

@@ -494,6 +494,7 @@ set(viewer_SOURCE_FILES
llwlparamset.cpp llwlparamset.cpp
llworld.cpp llworld.cpp
llworldmap.cpp llworldmap.cpp
llworldmipmap.cpp
llmapresponders.cpp llmapresponders.cpp
llworldmapview.cpp llworldmapview.cpp
llxmlrpctransaction.cpp llxmlrpctransaction.cpp
@@ -968,6 +969,7 @@ set(viewer_HEADER_FILES
llwlparamset.h llwlparamset.h
llworld.h llworld.h
llworldmap.h llworldmap.h
llworldmipmap.h
llmapresponders.h llmapresponders.h
llworldmapview.h llworldmapview.h
llxmlrpctransaction.h llxmlrpctransaction.h

View File

@@ -167,7 +167,6 @@ LLFloaterWorldMap::LLFloaterWorldMap()
{ {
LLCallbackMap::map_t factory_map; LLCallbackMap::map_t factory_map;
factory_map["objects_mapview"] = LLCallbackMap(createWorldMapView, NULL); factory_map["objects_mapview"] = LLCallbackMap(createWorldMapView, NULL);
factory_map["terrain_mapview"] = LLCallbackMap(createWorldMapView, NULL);
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_world_map.xml", &factory_map); LLUICtrlFactory::getInstance()->buildFloater(this, "floater_world_map.xml", &factory_map);
} }
@@ -179,23 +178,6 @@ void* LLFloaterWorldMap::createWorldMapView(void* data)
BOOL LLFloaterWorldMap::postBuild() BOOL LLFloaterWorldMap::postBuild()
{ {
mTabs = getChild<LLTabContainer>("maptab");
if (!mTabs) return FALSE;
LLPanel *panel;
panel = mTabs->getChild<LLPanel>("objects_mapview");
if (panel)
{
mTabs->setTabChangeCallback(panel, onCommitBackground);
mTabs->setTabUserData(panel, this);
}
panel = mTabs->getChild<LLPanel>("terrain_mapview");
if (panel)
{
mTabs->setTabChangeCallback(panel, onCommitBackground);
mTabs->setTabUserData(panel, this);
}
// The following callback syncs the worlmap tabs with the images. // The following callback syncs the worlmap tabs with the images.
// Commented out since it was crashing when LLWorldMap became a singleton. // Commented out since it was crashing when LLWorldMap became a singleton.
@@ -204,6 +186,8 @@ BOOL LLFloaterWorldMap::postBuild()
// //
//onCommitBackground((void*)this, false); //onCommitBackground((void*)this, false);
mPanel = getChild<LLPanel>("objects_mapview");
childSetCommitCallback("friend combo", onAvatarComboCommit, this); childSetCommitCallback("friend combo", onAvatarComboCommit, this);
LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo"); LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo");
@@ -263,7 +247,7 @@ BOOL LLFloaterWorldMap::postBuild()
LLFloaterWorldMap::~LLFloaterWorldMap() LLFloaterWorldMap::~LLFloaterWorldMap()
{ {
// All cleaned up by LLView destructor // All cleaned up by LLView destructor
mTabs = NULL; mPanel = NULL;
// Inventory deletes all observers on shutdown // Inventory deletes all observers on shutdown
mInventory = NULL; mInventory = NULL;
@@ -296,7 +280,7 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target)
gFloaterWorldMap->open(); /* Flawfinder: ignore */ gFloaterWorldMap->open(); /* Flawfinder: ignore */
LLWorldMapView* map_panel; LLWorldMapView* map_panel;
map_panel = (LLWorldMapView*)gFloaterWorldMap->mTabs->getCurrentPanel(); map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel;
map_panel->clearLastClick(); map_panel->clearLastClick();
if (!was_visible) if (!was_visible)
@@ -314,9 +298,8 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target)
// Reload any maps that may have changed // Reload any maps that may have changed
LLWorldMap::getInstance()->clearSimFlags(); LLWorldMap::getInstance()->clearSimFlags();
const S32 panel_num = gFloaterWorldMap->mTabs->getCurrentPanelIndex();
const bool request_from_sim = true; const bool request_from_sim = true;
LLWorldMap::getInstance()->setCurrentLayer(panel_num, request_from_sim); LLWorldMap::getInstance()->setCurrentLayer(0, request_from_sim);
// We may already have a bounding box for the regions of the world, // We may already have a bounding box for the regions of the world,
// so use that to adjust the view. // so use that to adjust the view.
@@ -1033,9 +1016,7 @@ void LLFloaterWorldMap::adjustZoomSliderBounds()
world_height_regions++; world_height_regions++;
// Find how much space we have to display the world // Find how much space we have to display the world
LLWorldMapView* map_panel; LLRect view_rect = mPanel->getRect();
map_panel = (LLWorldMapView*)mTabs->getCurrentPanel();
LLRect view_rect = map_panel->getRect();
// View size in pixels // View size in pixels
S32 view_width = view_rect.getWidth(); S32 view_width = view_rect.getWidth();
@@ -1084,7 +1065,7 @@ void LLFloaterWorldMap::onPanBtn( void* userdata )
} }
LLWorldMapView* map_panel; LLWorldMapView* map_panel;
map_panel = (LLWorldMapView*)gFloaterWorldMap->mTabs->getCurrentPanel(); map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel;
map_panel->translatePan( pan_x, pan_y ); map_panel->translatePan( pan_x, pan_y );
} }
@@ -1566,17 +1547,6 @@ void LLFloaterWorldMap::flyToAvatar()
} }
} }
// static
void LLFloaterWorldMap::onCommitBackground(void* userdata, bool from_click)
{
LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata;
// Find my index
S32 index = self->mTabs->getCurrentPanelIndex();
LLWorldMap::getInstance()->setCurrentLayer(index);
}
void LLFloaterWorldMap::updateSims(bool found_null_sim) void LLFloaterWorldMap::updateSims(bool found_null_sim)
{ {
if (mCompletingRegionName == "") if (mCompletingRegionName == "")

View File

@@ -123,8 +123,6 @@ protected:
static void onAvatarComboPrearrange( LLUICtrl* ctrl, void* data ); static void onAvatarComboPrearrange( LLUICtrl* ctrl, void* data );
static void onAvatarComboCommit( LLUICtrl* ctrl, void* data ); static void onAvatarComboCommit( LLUICtrl* ctrl, void* data );
static void onCommitBackground(void* data, bool from_click);
static void onComboTextEntry( LLLineEditor* ctrl, void* data ); static void onComboTextEntry( LLLineEditor* ctrl, void* data );
static void onSearchTextEntry( LLLineEditor* ctrl, void* data ); static void onSearchTextEntry( LLLineEditor* ctrl, void* data );
@@ -162,7 +160,7 @@ protected:
void cacheLandmarkPosition(); void cacheLandmarkPosition();
protected: protected:
LLTabContainer* mTabs; LLPanel* mPanel; // Panel displaying the map
// Sets sMapScale, in pixels per region // Sets sMapScale, in pixels per region
F32 mCurZoomVal; F32 mCurZoomVal;

View File

@@ -203,6 +203,8 @@ void LLWorldMap::eraseItems()
void LLWorldMap::clearImageRefs() void LLWorldMap::clearImageRefs()
{ {
mWorldMipmap.reset();
for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it) for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
{ {
LLSimInfo* info = (*it).second; LLSimInfo* info = (*it).second;
@@ -231,6 +233,12 @@ void LLWorldMap::clearSimFlags()
} }
} }
void LLWorldMap::equalizeBoostLevels()
{
mWorldMipmap.equalizeBoostLevels();
return;
}
LLSimInfo* LLWorldMap::simInfoFromPosGlobal(const LLVector3d& pos_global) LLSimInfo* LLWorldMap::simInfoFromPosGlobal(const LLVector3d& pos_global)
{ {
U64 handle = to_region_handle(pos_global); U64 handle = to_region_handle(pos_global);
@@ -294,6 +302,7 @@ bool LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global, std::string
void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer) void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer)
{ {
//TODO: we only have 1 layer -SG
mCurrentMap = layer; mCurrentMap = layer;
if (!mMapLoaded[layer] || request_layer) if (!mMapLoaded[layer] || request_layer)
{ {
@@ -1070,3 +1079,19 @@ void LLWorldMap::updateTelehubCoverage()
mTelehubCoverageMap[index] *= mNeighborMap[index]; mTelehubCoverageMap[index] *= mNeighborMap[index];
}*/ }*/
} }
// Drop priority of all images being fetched by the map
void LLWorldMap::dropImagePriorities()
{
// Drop the download of tiles priority to nil
mWorldMipmap.dropBoostLevels();
// Same for the "land for sale" tiles per region
for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
{
LLSimInfo* info = it->second;
if (!info->mOverlayImage.isNull())
{
info->mOverlayImage->setBoostLevel(0);
}
}
}

View File

@@ -41,6 +41,7 @@
#include "v3dmath.h" #include "v3dmath.h"
#include "llframetimer.h" #include "llframetimer.h"
#include "llmapimagetype.h" #include "llmapimagetype.h"
#include "llworldmipmap.h"
#include "lluuid.h" #include "lluuid.h"
#include "llmemory.h" #include "llmemory.h"
#include "llviewerimage.h" #include "llviewerimage.h"
@@ -134,6 +135,9 @@ public:
// Causes a re-request of the sim info without erasing extisting info // Causes a re-request of the sim info without erasing extisting info
void clearSimFlags(); void clearSimFlags();
// Drops the priority of the images being fetched
void dropImagePriorities();
// Returns simulator information, or NULL if out of range // Returns simulator information, or NULL if out of range
LLSimInfo* simInfoFromHandle(const U64 handle); LLSimInfo* simInfoFromHandle(const U64 handle);
@@ -183,6 +187,13 @@ public:
// Bounds of the world, in meters // Bounds of the world, in meters
U32 getWorldWidth() const; U32 getWorldWidth() const;
U32 getWorldHeight() const; U32 getWorldHeight() const;
// World Mipmap delegation: currently used when drawing the mipmap
void equalizeBoostLevels();
LLPointer<LLViewerImage> getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load = true) {
return mWorldMipmap.getObjectsTile(grid_x, grid_y, level, load);
}
public: public:
// Map from region-handle to simulator info // Map from region-handle to simulator info
typedef std::map<U64, LLSimInfo*> sim_info_map_t; typedef std::map<U64, LLSimInfo*> sim_info_map_t;
@@ -224,6 +235,9 @@ public:
S32 mNeighborMapHeight; S32 mNeighborMapHeight;
private: private:
LLWorldMipmap mWorldMipmap;
LLTimer mRequestTimer; LLTimer mRequestTimer;
// search for named region for url processing // search for named region for url processing

View File

@@ -61,16 +61,27 @@
#include "llviewerregion.h" #include "llviewerregion.h"
#include "llviewerwindow.h" #include "llviewerwindow.h"
#include "llworldmap.h" #include "llworldmap.h"
#include "llworldmipmap.h"
#include "lltexturefetch.h" #include "lltexturefetch.h"
#include "llappviewer.h" // Only for constants! #include "llappviewer.h" // Only for constants!
#include "lltrans.h" #include "lltrans.h"
#include "llglheaders.h" #include "llglheaders.h"
#include "hippogridmanager.h"
// [RLVa:KB] // [RLVa:KB]
#include "rlvhandler.h" #include "rlvhandler.h"
// [/RLVa:KB] // [/RLVa:KB]
// Basically a C++ implementation of the OCEAN_COLOR defined in mapstitcher.py
// Please ensure consistency between those 2 files (TODO: would be better to get that color from an asset source...)
// # Constants
// OCEAN_COLOR = "#1D475F"
const F32 OCEAN_RED = (F32)(0x1D)/255.f;
const F32 OCEAN_GREEN = (F32)(0x47)/255.f;
const F32 OCEAN_BLUE = (F32)(0x5F)/255.f;
const F32 GODLY_TELEPORT_HEIGHT = 200.f; const F32 GODLY_TELEPORT_HEIGHT = 200.f;
const S32 SCROLL_HINT_WIDTH = 65; const S32 SCROLL_HINT_WIDTH = 65;
const F32 BIG_DOT_RADIUS = 5.f; const F32 BIG_DOT_RADIUS = 5.f;
@@ -106,14 +117,15 @@ F32 LLWorldMapView::sTargetPanY = 0.f;
S32 LLWorldMapView::sTrackingArrowX = 0; S32 LLWorldMapView::sTrackingArrowX = 0;
S32 LLWorldMapView::sTrackingArrowY = 0; S32 LLWorldMapView::sTrackingArrowY = 0;
F32 LLWorldMapView::sPixelsPerMeter = 1.f; F32 LLWorldMapView::sPixelsPerMeter = 1.f;
bool LLWorldMapView::sVisibleTilesLoaded = false;
F32 LLWorldMapView::sMapScale = 128.f; F32 LLWorldMapView::sMapScale = 128.f;
F32 CONE_SIZE = 0.6f; F32 CONE_SIZE = 0.6f;
std::map<std::string,std::string> LLWorldMapView::sStringsMap; std::map<std::string,std::string> LLWorldMapView::sStringsMap;
#define SIM_NULL_MAP_SCALE 1 // width in pixels, where we start drawing "null" sims #define SIM_NULL_MAP_SCALE 4 // width in pixels, where we start drawing "null" sims
#define SIM_MAP_AGENT_SCALE 2 // width in pixels, where we start drawing agents #define SIM_MAP_AGENT_SCALE 8 // width in pixels, where we start drawing agents
#define SIM_MAP_SCALE 1 // width in pixels, where we start drawing sim tiles #define SIM_MAP_SCALE 4 // width in pixels, where we start drawing sim tiles
// Updates for agent locations. // Updates for agent locations.
#define AGENTS_UPDATE_TIME 60.0 // in seconds #define AGENTS_UPDATE_TIME 60.0 // in seconds
@@ -174,7 +186,7 @@ void LLWorldMapView::cleanupClass()
LLWorldMapView::LLWorldMapView(const std::string& name, const LLRect& rect ) LLWorldMapView::LLWorldMapView(const std::string& name, const LLRect& rect )
: LLPanel(name, rect, BORDER_NO), : LLPanel(name, rect, BORDER_NO),
mBackgroundColor( LLColor4( 4.f/255.f, 4.f/255.f, 75.f/255.f, 1.f ) ), mBackgroundColor( LLColor4( OCEAN_RED, OCEAN_GREEN, OCEAN_BLUE, 1.f ) ),
mItemPicked(FALSE), mItemPicked(FALSE),
mPanning( FALSE ), mPanning( FALSE ),
mMouseDownPanX( 0 ), mMouseDownPanX( 0 ),
@@ -261,6 +273,7 @@ void LLWorldMapView::setScale( F32 scale )
sTargetPanY = sPanY; sTargetPanY = sPanY;
sPixelsPerMeter = sMapScale / REGION_WIDTH_METERS; sPixelsPerMeter = sMapScale / REGION_WIDTH_METERS;
sVisibleTilesLoaded = false;
} }
} }
@@ -272,6 +285,7 @@ void LLWorldMapView::translatePan( S32 delta_x, S32 delta_y )
sPanY += delta_y; sPanY += delta_y;
sTargetPanX = sPanX; sTargetPanX = sPanX;
sTargetPanY = sPanY; sTargetPanY = sPanY;
sVisibleTilesLoaded = false;
} }
@@ -285,6 +299,7 @@ void LLWorldMapView::setPan( S32 x, S32 y, BOOL snap )
sPanX = sTargetPanX; sPanX = sTargetPanX;
sPanY = sTargetPanY; sPanY = sTargetPanY;
} }
sVisibleTilesLoaded = false;
} }
@@ -313,8 +328,6 @@ void LLWorldMapView::draw()
const S32 width = getRect().getWidth(); const S32 width = getRect().getWidth();
const S32 height = getRect().getHeight(); const S32 height = getRect().getHeight();
const F32 half_width = F32(width) / 2.0f;
const F32 half_height = F32(height) / 2.0f;
LLVector3d camera_global = gAgent.getCameraPositionGlobal(); LLVector3d camera_global = gAgent.getCameraPositionGlobal();
LLLocalClipRect clip(getLocalRect()); LLLocalClipRect clip(getLocalRect());
@@ -337,224 +350,44 @@ void LLWorldMapView::draw()
gGL.setColorMask(true, true); gGL.setColorMask(true, true);
gGL.setSceneBlendType(LLRender::BT_ALPHA); gGL.setSceneBlendType(LLRender::BT_ALPHA);
F32 layer_alpha = 1.f; if(gHippoGridManager->getConnectedGrid()->isSecondLife())
drawMipmap(width, height);
else
drawTiles(width, height);
// Draw one image per layer LLFontGL* font = LLFontGL::getFontSansSerifSmall();
for (U32 layer_idx=0; layer_idx<LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap].size(); ++layer_idx) const F32 half_width = F32(width) / 2.0f;
{ const F32 half_height = F32(height) / 2.0f;
if (!LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx].LayerDefined)
{
continue;
}
LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx];
LLViewerImage *current_image = layer->LayerImage;
if (current_image->isMissingAsset())
{
continue; // better to draw nothing than the missing asset image
}
LLVector3d origin_global((F64)layer->LayerExtents.mLeft * REGION_WIDTH_METERS, (F64)layer->LayerExtents.mBottom * REGION_WIDTH_METERS, 0.f);
// Find x and y position relative to camera's center.
LLVector3d rel_region_pos = origin_global - camera_global;
F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * sMapScale;
F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale;
F32 pix_width = sMapScale*(layer->LayerExtents.getWidth() + 1);
F32 pix_height = sMapScale*(layer->LayerExtents.getHeight() + 1);
// When the view isn't panned, 0,0 = center of rectangle
F32 bottom = sPanY + half_height + relative_y;
F32 left = sPanX + half_width + relative_x;
F32 top = bottom + pix_height;
F32 right = left + pix_width;
F32 pixel_area = pix_width*pix_height;
// discard layers that are outside the rectangle
// and discard small layers
if (top < 0.f ||
bottom > height ||
right < 0.f ||
left > width ||
(pixel_area < 4*4))
{
current_image->setBoostLevel(0);
continue;
}
current_image->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP_VISIBLE);
current_image->setKnownDrawSize(llround(pix_width * LLUI::sGLScaleFactor.mV[VX]), llround(pix_height * LLUI::sGLScaleFactor.mV[VY]));
if (!current_image->getHasGLTexture())
{
continue; // better to draw nothing than the default image
}
// LLTextureView::addDebugImage(current_image);
// Draw using the texture. If we don't clamp we get artifact at
// the edge.
gGL.getTexUnit(0)->bind(current_image);
// Draw map image into RGB
//gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gGL.flush();
gGL.setColorMask(true, false);
gGL.color4f(1.f, 1.f, 1.f, layer_alpha);
gGL.begin(LLRender::QUADS);
gGL.texCoord2f(0.0f, 1.0f);
gGL.vertex3f(left, top, -1.0f);
gGL.texCoord2f(0.0f, 0.0f);
gGL.vertex3f(left, bottom, -1.0f);
gGL.texCoord2f(1.0f, 0.0f);
gGL.vertex3f(right, bottom, -1.0f);
gGL.texCoord2f(1.0f, 1.0f);
gGL.vertex3f(right, top, -1.0f);
gGL.end();
// draw an alpha of 1 where the sims are visible
gGL.flush();
gGL.setColorMask(false, true);
gGL.color4f(1.f, 1.f, 1.f, 1.f);
gGL.begin(LLRender::QUADS);
gGL.texCoord2f(0.0f, 1.0f);
gGL.vertex2f(left, top);
gGL.texCoord2f(0.0f, 0.0f);
gGL.vertex2f(left, bottom);
gGL.texCoord2f(1.0f, 0.0f);
gGL.vertex2f(right, bottom);
gGL.texCoord2f(1.0f, 1.0f);
gGL.vertex2f(right, top);
gGL.end();
}
gGL.flush();
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
gGL.setColorMask(true, true);
// there used to be an #if 1 here, but it was uncommented; perhaps marking a block of code?
F32 sim_alpha = 1.f;
// Draw one image per region, centered on the camera position.
const S32 MAX_SIMULTANEOUS_TEX = 100;
const S32 MAX_REQUEST_PER_TICK = 5;
const S32 MIN_REQUEST_PER_TICK = 1;
S32 textures_requested_this_tick = 0;
bool use_web_map_tiles = LLWorldMap::useWebMapTiles();
// Draw the region name in the lower left corner
for (LLWorldMap::sim_info_map_t::iterator it = LLWorldMap::getInstance()->mSimInfoMap.begin(); for (LLWorldMap::sim_info_map_t::iterator it = LLWorldMap::getInstance()->mSimInfoMap.begin();
it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it) it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it)
{ {
U64 handle = (*it).first; U64 handle = it->first;
LLSimInfo* info = (*it).second; LLSimInfo* info = (*it).second;
LLViewerImage* simimage = info->mCurrentImage;
LLViewerImage* overlayimage = info->mOverlayImage;
if (sMapScale < SIM_MAP_SCALE)
{
if (simimage != NULL) simimage->setBoostLevel(0);
if (overlayimage != NULL) overlayimage->setBoostLevel(0);
continue;
}
LLVector3d origin_global = from_region_handle(handle); LLVector3d origin_global = from_region_handle(handle);
LLVector3d camera_global = gAgent.getCameraPositionGlobal();
// Find x and y position relative to camera's center. // Find x and y position relative to camera's center.
LLVector3d rel_region_pos = origin_global - camera_global; LLVector3d rel_region_pos = origin_global - camera_global;
F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * sMapScale; F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * sMapScale;
F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale; F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale;
// When the view isn't panned, 0,0 = center of rectangle
F32 bottom = sPanY + half_height + relative_y; F32 bottom = sPanY + half_height + relative_y;
F32 left = sPanX + half_width + relative_x; F32 left = sPanX + half_width + relative_x;
F32 top = bottom + sMapScale ; F32 top = bottom + sMapScale ;
F32 right = left + sMapScale ; F32 right = left + sMapScale ;
// Switch to world map texture (if available for this region) if either: // disregard regions that are outside the rectangle
// 1. Tiles are zoomed out small enough, or
// 2. Sim's texture has not been loaded yet
F32 map_scale_cutoff = SIM_MAP_SCALE;
if ((info->mRegionFlags & REGION_FLAGS_NULL_LAYER) > 0)
{
map_scale_cutoff = SIM_NULL_MAP_SCALE;
}
info->mShowAgentLocations = (sMapScale >= SIM_MAP_AGENT_SCALE);
bool sim_visible =
(sMapScale >= map_scale_cutoff) &&
(simimage != NULL) &&
(simimage->getHasGLTexture());
if (sim_visible)
{
// Fade in
if (info->mAlpha < 0.0f)
info->mAlpha = 1.f; // don't fade initially
else
info->mAlpha = lerp(info->mAlpha, 1.f, LLCriticalDamp::getInterpolant(0.15f));
}
else
{
// Fade out
if (info->mAlpha < 0.0f)
info->mAlpha = 0.f; // don't fade initially
else
info->mAlpha = lerp(info->mAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f));
}
// discard regions that are outside the rectangle
// and discard small regions
if (top < 0.f || if (top < 0.f ||
bottom > height || bottom > height ||
right < 0.f || right < 0.f ||
left > width ) left > width )
{ {
if (simimage != NULL) simimage->setBoostLevel(0);
if (overlayimage != NULL) overlayimage->setBoostLevel(0);
continue; continue;
} }
if (info->mCurrentImage.isNull()) info->mShowAgentLocations = (sMapScale >= SIM_MAP_AGENT_SCALE);
{
if ((textures_requested_this_tick < MIN_REQUEST_PER_TICK) ||
((LLAppViewer::getTextureFetch()->getNumRequests() < MAX_SIMULTANEOUS_TEX) &&
(textures_requested_this_tick < MAX_REQUEST_PER_TICK)))
{
textures_requested_this_tick++;
if (use_web_map_tiles)
{
LLVector3d region_pos = info->getGlobalOrigin();
info->mCurrentImage = LLWorldMap::loadObjectsTile((U32)(region_pos.mdV[VX] / REGION_WIDTH_UNITS), (U32)(region_pos.mdV[VY] / REGION_WIDTH_UNITS));
}
else
{
info->mCurrentImage = gImageList.getImage(info->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE);
}
info->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP);
simimage = info->mCurrentImage;
gGL.getTexUnit(0)->bind(simimage);
}
}
if (info->mOverlayImage.isNull() && info->mMapImageID[2].notNull())
{
if ((textures_requested_this_tick < MIN_REQUEST_PER_TICK) ||
((LLAppViewer::getTextureFetch()->getNumRequests() < MAX_SIMULTANEOUS_TEX) &&
(textures_requested_this_tick < MAX_REQUEST_PER_TICK)))
{
textures_requested_this_tick++;
info->mOverlayImage = gImageList.getImage(info->mMapImageID[2], MIPMAP_TRUE, FALSE);
info->mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP);
overlayimage = info->mOverlayImage;
gGL.getTexUnit(0)->bind(overlayimage);
}
}
mVisibleRegions.push_back(handle); mVisibleRegions.push_back(handle);
// See if the agents need updating // See if the agents need updating
if (current_time - info->mAgentsUpdateTime > AGENTS_UPDATE_TIME) if (current_time - info->mAgentsUpdateTime > AGENTS_UPDATE_TIME)
@@ -563,125 +396,6 @@ void LLWorldMapView::draw()
info->mAgentsUpdateTime = current_time; info->mAgentsUpdateTime = current_time;
} }
// Bias the priority escalation for images nearer
LLVector3d center_global = origin_global;
center_global.mdV[VX] += 128.0;
center_global.mdV[VY] += 128.0;
S32 draw_size = llround(sMapScale);
if (simimage != NULL)
{
simimage->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP);
simimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY]));
}
if (overlayimage != NULL)
{
overlayimage->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP);
overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY]));
}
// LLTextureView::addDebugImage(simimage);
if (sim_visible && info->mAlpha > 0.001f)
{
// Draw using the texture. If we don't clamp we get artifact at
// the edge.
LLGLSUIDefault gls_ui;
if (simimage != NULL)
gGL.getTexUnit(0)->bind(simimage);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
F32 alpha = sim_alpha * info->mAlpha;
gGL.color4f(1.f, 1.0f, 1.0f, alpha);
gGL.begin(LLRender::QUADS);
gGL.texCoord2f(0.f, 1.f);
gGL.vertex3f(left, top, 0.f);
gGL.texCoord2f(0.f, 0.f);
gGL.vertex3f(left, bottom, 0.f);
gGL.texCoord2f(1.f, 0.f);
gGL.vertex3f(right, bottom, 0.f);
gGL.texCoord2f(1.f, 1.f);
gGL.vertex3f(right, top, 0.f);
gGL.end();
if (gSavedSettings.getBOOL("MapShowLandForSale") && overlayimage && overlayimage->getHasGLTexture())
{
gGL.getTexUnit(0)->bind(overlayimage);
gGL.color4f(1.f, 1.f, 1.f, alpha);
gGL.begin(LLRender::QUADS);
gGL.texCoord2f(0.f, 1.f);
gGL.vertex3f(left, top, -0.5f);
gGL.texCoord2f(0.f, 0.f);
gGL.vertex3f(left, bottom, -0.5f);
gGL.texCoord2f(1.f, 0.f);
gGL.vertex3f(right, bottom, -0.5f);
gGL.texCoord2f(1.f, 1.f);
gGL.vertex3f(right, top, -0.5f);
gGL.end();
}
if ((info->mRegionFlags & REGION_FLAGS_NULL_LAYER) == 0)
{
// draw an alpha of 1 where the sims are visible (except NULL sims)
gGL.flush();
gGL.setSceneBlendType(LLRender::BT_REPLACE);
gGL.setColorMask(false, true);
gGL.color4f(1.f, 1.f, 1.f, 1.f);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.begin(LLRender::QUADS);
gGL.vertex2f(left, top);
gGL.vertex2f(left, bottom);
gGL.vertex2f(right, bottom);
gGL.vertex2f(right, top);
gGL.end();
gGL.flush();
gGL.setColorMask(true, true);
}
}
if (info->mAccess == SIM_ACCESS_DOWN)
{
// Draw a transparent red square over down sims
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_SOURCE_ALPHA);
gGL.color4f(0.2f, 0.0f, 0.0f, 0.4f);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.begin(LLRender::QUADS);
gGL.vertex2f(left, top);
gGL.vertex2f(left, bottom);
gGL.vertex2f(right, bottom);
gGL.vertex2f(right, top);
gGL.end();
}
// As part of the AO project, we no longer want to draw access indicators;
// it's too complicated to get all the rules straight and will only
// cause confusion.
/**********************
// If this is mature, and you are not, draw a line across it
if (info->mAccess != SIM_ACCESS_DOWN
&& info->mAccess > SIM_ACCESS_PG
&& gAgent.isTeen())
{
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color3f(1.f, 0.f, 0.f);
gGL.begin(LLRender::LINES);
gGL.vertex2f(left, top);
gGL.vertex2f(right, bottom);
gGL.vertex2f(left, bottom);
gGL.vertex2f(right, top);
gGL.end();
}
**********************/
// Draw the region name in the lower left corner
LLFontGL* font = LLFontGL::getFontSansSerifSmall();
std::string mesg; std::string mesg;
if (sMapScale < sThresholdA) if (sMapScale < sThresholdA)
{ {
@@ -709,6 +423,25 @@ void LLWorldMapView::draw()
else else
{ {
mesg = info->mName; mesg = info->mName;
U8 access = info->mAccess;
switch(access)
{
case SIM_ACCESS_MIN:
mesg += " (Min)";
break;
case SIM_ACCESS_PG:
mesg += " (PG)";
break;
case SIM_ACCESS_MATURE:
mesg += " (Mature)";
break;
case SIM_ACCESS_ADULT:
mesg += " (Adult)";
break;
default:
mesg += llformat(" (Access=%d)",access);
break;
}
} }
} }
@@ -725,7 +458,7 @@ void LLWorldMapView::draw()
// If map texture is still loading, // If map texture is still loading,
// display "Loading" placeholder text. // display "Loading" placeholder text.
if ((simimage != NULL) && /*if ((simimage != NULL) &&
simimage->getDiscardLevel() != 1 && simimage->getDiscardLevel() != 1 &&
simimage->getDiscardLevel() != 0) simimage->getDiscardLevel() != 0)
{ {
@@ -737,13 +470,12 @@ void LLWorldMapView::draw()
LLFontGL::LEFT, LLFontGL::LEFT,
LLFontGL::BASELINE, LLFontGL::BASELINE,
LLFontGL::DROP_SHADOW); LLFontGL::DROP_SHADOW);
}*/
} }
} }
}
// #endif used to be here
// there used to be an #if 1 here, but it was uncommented; perhaps marking a block of code?
// Draw background rectangle // Draw background rectangle
LLGLSUIDefault gls_ui; LLGLSUIDefault gls_ui;
{ {
@@ -899,6 +631,344 @@ void LLWorldMapView::setVisible(BOOL visible)
} }
} }
void LLWorldMapView::drawTiles(S32 width, S32 height) {
const F32 half_width = F32(width) / 2.0f;
const F32 half_height = F32(height) / 2.0f;
F32 layer_alpha = 1.f;
LLVector3d camera_global = gAgent.getCameraPositionGlobal();
// Draw one image per layer
for (U32 layer_idx=0; layer_idx<LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap].size(); ++layer_idx)
{
if (!LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx].LayerDefined)
{
continue;
}
LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx];
LLViewerImage *current_image = layer->LayerImage;
if (current_image->isMissingAsset())
{
continue; // better to draw nothing than the missing asset image
}
LLVector3d origin_global((F64)layer->LayerExtents.mLeft * REGION_WIDTH_METERS, (F64)layer->LayerExtents.mBottom * REGION_WIDTH_METERS, 0.f);
// Find x and y position relative to camera's center.
LLVector3d rel_region_pos = origin_global - camera_global;
F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * sMapScale;
F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale;
F32 pix_width = sMapScale*(layer->LayerExtents.getWidth() + 1);
F32 pix_height = sMapScale*(layer->LayerExtents.getHeight() + 1);
// When the view isn't panned, 0,0 = center of rectangle
F32 bottom = sPanY + half_height + relative_y;
F32 left = sPanX + half_width + relative_x;
F32 top = bottom + pix_height;
F32 right = left + pix_width;
F32 pixel_area = pix_width*pix_height;
// discard layers that are outside the rectangle
// and discard small layers
if (top < 0.f ||
bottom > height ||
right < 0.f ||
left > width ||
(pixel_area < 4*4))
{
current_image->setBoostLevel(0);
continue;
}
current_image->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP_VISIBLE);
current_image->setKnownDrawSize(llround(pix_width * LLUI::sGLScaleFactor.mV[VX]), llround(pix_height * LLUI::sGLScaleFactor.mV[VY]));
if (!current_image->getHasGLTexture())
{
continue; // better to draw nothing than the default image
}
// LLTextureView::addDebugImage(current_image);
// Draw using the texture. If we don't clamp we get artifact at
// the edge.
gGL.getTexUnit(0)->bind(current_image);
// Draw map image into RGB
//gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gGL.flush();
gGL.setColorMask(true, false);
gGL.color4f(1.f, 1.f, 1.f, layer_alpha);
gGL.begin(LLRender::QUADS);
gGL.texCoord2f(0.0f, 1.0f);
gGL.vertex3f(left, top, -1.0f);
gGL.texCoord2f(0.0f, 0.0f);
gGL.vertex3f(left, bottom, -1.0f);
gGL.texCoord2f(1.0f, 0.0f);
gGL.vertex3f(right, bottom, -1.0f);
gGL.texCoord2f(1.0f, 1.0f);
gGL.vertex3f(right, top, -1.0f);
gGL.end();
// draw an alpha of 1 where the sims are visible
gGL.flush();
gGL.setColorMask(false, true);
gGL.color4f(1.f, 1.f, 1.f, 1.f);
gGL.begin(LLRender::QUADS);
gGL.texCoord2f(0.0f, 1.0f);
gGL.vertex2f(left, top);
gGL.texCoord2f(0.0f, 0.0f);
gGL.vertex2f(left, bottom);
gGL.texCoord2f(1.0f, 0.0f);
gGL.vertex2f(right, bottom);
gGL.texCoord2f(1.0f, 1.0f);
gGL.vertex2f(right, top);
gGL.end();
}
gGL.flush();
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
gGL.setColorMask(true, true);
F32 sim_alpha = 1.f;
// Draw one image per region, centered on the camera position.
const S32 MAX_SIMULTANEOUS_TEX = 100;
const S32 MAX_REQUEST_PER_TICK = 5;
const S32 MIN_REQUEST_PER_TICK = 1;
S32 textures_requested_this_tick = 0;
bool use_web_map_tiles = LLWorldMap::useWebMapTiles();
for (LLWorldMap::sim_info_map_t::iterator it = LLWorldMap::getInstance()->mSimInfoMap.begin();
it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it)
{
U64 handle = (*it).first;
LLSimInfo* info = (*it).second;
LLViewerImage* simimage = info->mCurrentImage;
LLViewerImage* overlayimage = info->mOverlayImage;
if (sMapScale < SIM_MAP_SCALE)
{
if (simimage != NULL) simimage->setBoostLevel(0);
if (overlayimage != NULL) overlayimage->setBoostLevel(0);
continue;
}
LLVector3d origin_global = from_region_handle(handle);
LLVector3d camera_global = gAgent.getCameraPositionGlobal();
// Find x and y position relative to camera's center.
LLVector3d rel_region_pos = origin_global - camera_global;
F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * sMapScale;
F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale;
// When the view isn't panned, 0,0 = center of rectangle
F32 bottom = sPanY + half_height + relative_y;
F32 left = sPanX + half_width + relative_x;
F32 top = bottom + sMapScale ;
F32 right = left + sMapScale ;
// Switch to world map texture (if available for this region) if either:
// 1. Tiles are zoomed out small enough, or
// 2. Sim's texture has not been loaded yet
F32 map_scale_cutoff = SIM_MAP_SCALE;
if ((info->mRegionFlags & REGION_FLAGS_NULL_LAYER) > 0)
{
map_scale_cutoff = SIM_NULL_MAP_SCALE;
}
bool sim_visible =
(sMapScale >= map_scale_cutoff) &&
(simimage != NULL) &&
(simimage->getHasGLTexture());
if (sim_visible)
{
// Fade in
if (info->mAlpha < 0.0f)
info->mAlpha = 1.f; // don't fade initially
else
info->mAlpha = lerp(info->mAlpha, 1.f, LLCriticalDamp::getInterpolant(0.15f));
}
else
{
// Fade out
if (info->mAlpha < 0.0f)
info->mAlpha = 0.f; // don't fade initially
else
info->mAlpha = lerp(info->mAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f));
}
// discard regions that are outside the rectangle
// and discard small regions
if (top < 0.f ||
bottom > height ||
right < 0.f ||
left > width )
{
if (simimage != NULL) simimage->setBoostLevel(0);
if (overlayimage != NULL) overlayimage->setBoostLevel(0);
continue;
}
if (info->mCurrentImage.isNull())
{
if ((textures_requested_this_tick < MIN_REQUEST_PER_TICK) ||
((LLAppViewer::getTextureFetch()->getNumRequests() < MAX_SIMULTANEOUS_TEX) &&
(textures_requested_this_tick < MAX_REQUEST_PER_TICK)))
{
textures_requested_this_tick++;
if (use_web_map_tiles)
{
LLVector3d region_pos = info->getGlobalOrigin();
info->mCurrentImage = LLWorldMap::loadObjectsTile((U32)(region_pos.mdV[VX] / REGION_WIDTH_UNITS), (U32)(region_pos.mdV[VY] / REGION_WIDTH_UNITS));
}
else
{
info->mCurrentImage = gImageList.getImage(info->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE);
}
info->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP);
simimage = info->mCurrentImage;
gGL.getTexUnit(0)->bind(simimage);
}
}
if (info->mOverlayImage.isNull() && info->mMapImageID[2].notNull())
{
if ((textures_requested_this_tick < MIN_REQUEST_PER_TICK) ||
((LLAppViewer::getTextureFetch()->getNumRequests() < MAX_SIMULTANEOUS_TEX) &&
(textures_requested_this_tick < MAX_REQUEST_PER_TICK)))
{
textures_requested_this_tick++;
info->mOverlayImage = gImageList.getImage(info->mMapImageID[2], MIPMAP_TRUE, FALSE);
info->mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP);
overlayimage = info->mOverlayImage;
gGL.getTexUnit(0)->bind(overlayimage);
}
}
// Bias the priority escalation for images nearer
LLVector3d center_global = origin_global;
center_global.mdV[VX] += 128.0;
center_global.mdV[VY] += 128.0;
S32 draw_size = llround(sMapScale);
if (simimage != NULL)
{
simimage->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP);
simimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY]));
}
if (overlayimage != NULL)
{
overlayimage->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP);
overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY]));
}
// LLTextureView::addDebugImage(simimage);
if (sim_visible && info->mAlpha > 0.001f)
{
// Draw using the texture. If we don't clamp we get artifact at
// the edge.
LLGLSUIDefault gls_ui;
if (simimage != NULL)
gGL.getTexUnit(0)->bind(simimage);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
F32 alpha = sim_alpha * info->mAlpha;
gGL.color4f(1.f, 1.0f, 1.0f, alpha);
gGL.begin(LLRender::QUADS);
gGL.texCoord2f(0.f, 1.f);
gGL.vertex3f(left, top, 0.f);
gGL.texCoord2f(0.f, 0.f);
gGL.vertex3f(left, bottom, 0.f);
gGL.texCoord2f(1.f, 0.f);
gGL.vertex3f(right, bottom, 0.f);
gGL.texCoord2f(1.f, 1.f);
gGL.vertex3f(right, top, 0.f);
gGL.end();
if (gSavedSettings.getBOOL("MapShowLandForSale") && overlayimage && overlayimage->getHasGLTexture())
{
gGL.getTexUnit(0)->bind(overlayimage);
gGL.color4f(1.f, 1.f, 1.f, alpha);
gGL.begin(LLRender::QUADS);
gGL.texCoord2f(0.f, 1.f);
gGL.vertex3f(left, top, -0.5f);
gGL.texCoord2f(0.f, 0.f);
gGL.vertex3f(left, bottom, -0.5f);
gGL.texCoord2f(1.f, 0.f);
gGL.vertex3f(right, bottom, -0.5f);
gGL.texCoord2f(1.f, 1.f);
gGL.vertex3f(right, top, -0.5f);
gGL.end();
}
if ((info->mRegionFlags & REGION_FLAGS_NULL_LAYER) == 0)
{
// draw an alpha of 1 where the sims are visible (except NULL sims)
gGL.flush();
gGL.setSceneBlendType(LLRender::BT_REPLACE);
gGL.setColorMask(false, true);
gGL.color4f(1.f, 1.f, 1.f, 1.f);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.begin(LLRender::QUADS);
gGL.vertex2f(left, top);
gGL.vertex2f(left, bottom);
gGL.vertex2f(right, bottom);
gGL.vertex2f(right, top);
gGL.end();
gGL.flush();
gGL.setColorMask(true, true);
}
}
if (info->mAccess == SIM_ACCESS_DOWN)
{
// Draw a transparent red square over down sims
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_SOURCE_ALPHA);
gGL.color4f(0.2f, 0.0f, 0.0f, 0.4f);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.begin(LLRender::QUADS);
gGL.vertex2f(left, top);
gGL.vertex2f(left, bottom);
gGL.vertex2f(right, bottom);
gGL.vertex2f(right, top);
gGL.end();
}
// As part of the AO project, we no longer want to draw access indicators;
// it's too complicated to get all the rules straight and will only
// cause confusion.
/**********************
// If this is mature, and you are not, draw a line across it
if (info->mAccess != SIM_ACCESS_DOWN
&& info->mAccess > SIM_ACCESS_PG
&& gAgent.isTeen())
{
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color3f(1.f, 0.f, 0.f);
gGL.begin(LLRender::LINES);
gGL.vertex2f(left, top);
gGL.vertex2f(right, bottom);
gGL.vertex2f(left, bottom);
gGL.vertex2f(right, top);
gGL.end();
}
**********************/
}
}
void LLWorldMapView::drawGenericItems(const LLWorldMap::item_info_list_t& items, LLUIImagePtr image) void LLWorldMapView::drawGenericItems(const LLWorldMap::item_info_list_t& items, LLUIImagePtr image)
{ {
LLWorldMap::item_info_list_t::const_iterator e; LLWorldMap::item_info_list_t::const_iterator e;
@@ -936,6 +1006,9 @@ void LLWorldMapView::drawImageStack(const LLVector3d& global_pos, LLUIImagePtr i
void LLWorldMapView::drawAgents() void LLWorldMapView::drawAgents()
{ {
if(sMapScale < SIM_MAP_AGENT_SCALE)
return;
F32 agents_scale = (sMapScale * 0.9f) / 256.f; F32 agents_scale = (sMapScale * 0.9f) / 256.f;
LLColor4 avatar_color = gColors.getColor( "MapAvatar" ); LLColor4 avatar_color = gColors.getColor( "MapAvatar" );
@@ -1097,6 +1170,138 @@ void LLWorldMapView::drawFrustum()
gGL.popMatrix(); gGL.popMatrix();
} }
void LLWorldMapView::drawMipmap(S32 width, S32 height)
{
// Compute the level of the mipmap to use for the current scale level
S32 level = LLWorldMipmap::scaleToLevel(sMapScale);
// Set the tile boost level so that unused tiles get to 0
LLWorldMap::getInstance()->equalizeBoostLevels();
// Render whatever we already have loaded if we haven't the current level
// complete and use it as a background (scaled up or scaled down)
if (!sVisibleTilesLoaded)
{
// Note: the (load = false) parameter avoids missing tiles to be fetched (i.e. we render what we have, no more)
// Check all the lower res levels and render them in reverse order (worse to best)
// We need to traverse all the levels as the user can zoom in very fast
for (S32 l = LLWorldMipmap::MAP_LEVELS; l > level; l--)
{
drawMipmapLevel(width, height, l, false);
}
// Skip the current level, as we'll do it anyway here under...
// Just go one level down in res as it can really get too much stuff
// when zooming out and too small to see anyway...
if (level > 1)
{
drawMipmapLevel(width, height, level - 1, false);
}
}
else
{
//LL_INFOS("World Map") << "Render complete, don't draw background..." << LL_ENDL;
}
// Render the current level
sVisibleTilesLoaded = drawMipmapLevel(width, height, level);
return;
}
// Return true if all the tiles required to render that level have been fetched or are truly missing
bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load)
{
// Check input level
llassert (level > 0);
if (level <= 0)
return false;
// Count tiles hit and completed
S32 completed_tiles = 0;
S32 total_tiles = 0;
// Size in meters (global) of each tile of that level
S32 tile_width = LLWorldMipmap::MAP_TILE_SIZE * (1 << (level - 1));
// Dimension of the screen in meter at that scale
LLVector3d pos_SW = viewPosToGlobal(0, 0);
LLVector3d pos_NE = viewPosToGlobal(width, height);
// Add external band of tiles on the outskirt so to hit the partially displayed tiles right and top
pos_NE[VX] += tile_width;
pos_NE[VY] += tile_width;
// Iterate through the tiles on screen: we just need to ask for one tile every tile_width meters
U32 grid_x, grid_y;
for (F64 index_y = pos_SW[VY]; index_y < pos_NE[VY]; index_y += tile_width)
{
for (F64 index_x = pos_SW[VX]; index_x < pos_NE[VX]; index_x += tile_width)
{
// Compute the world coordinates of the current point
LLVector3d pos_global(index_x, index_y, pos_SW[VZ]);
// Convert to the mipmap level coordinates for that point (i.e. which tile to we hit)
LLWorldMipmap::globalToMipmap(pos_global[VX], pos_global[VY], level, &grid_x, &grid_y);
// Get the tile. Note: NULL means that the image does not exist (so it's considered "complete" as far as fetching is concerned)
LLPointer<LLViewerImage> simimage = LLWorldMap::getInstance()->getObjectsTile(grid_x, grid_y, level, load);
if (simimage)
{
// Check the texture state
if (simimage->getHasGLTexture())
{
// Increment the number of completly fetched tiles
completed_tiles++;
// Convert those coordinates (SW corner of the mipmap tile) into world (meters) coordinates
pos_global[VX] = grid_x * REGION_WIDTH_METERS;
pos_global[VY] = grid_y * REGION_WIDTH_METERS;
// Now to screen coordinates for SW corner of that tile
LLVector3 pos_screen = globalPosToView (pos_global);
F32 left = pos_screen[VX];
F32 bottom = pos_screen[VY];
// Compute the NE corner coordinates of the tile now
pos_global[VX] += tile_width;
pos_global[VY] += tile_width;
pos_screen = globalPosToView (pos_global);
F32 right = pos_screen[VX];
F32 top = pos_screen[VY];
// Draw the tile
LLGLSUIDefault gls_ui;
gGL.getTexUnit(0)->bind(simimage.get());
simimage->setAddressMode(LLTexUnit::TAM_CLAMP);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
gGL.color4f(1.f, 1.0f, 1.0f, 1.0f);
gGL.begin(LLRender::QUADS);
gGL.texCoord2f(0.f, 1.f);
gGL.vertex3f(left, top, 0.f);
gGL.texCoord2f(0.f, 0.f);
gGL.vertex3f(left, bottom, 0.f);
gGL.texCoord2f(1.f, 0.f);
gGL.vertex3f(right, bottom, 0.f);
gGL.texCoord2f(1.f, 1.f);
gGL.vertex3f(right, top, 0.f);
gGL.end();
#if DEBUG_DRAW_TILE
drawTileOutline(level, top, left, bottom, right);
#endif // DEBUG_DRAW_TILE
}
//else
//{
// Waiting for a tile -> the level is not complete
// LL_INFOS("World Map") << "Unfetched tile. level = " << level << LL_ENDL;
//}
}
else
{
// Unexistent tiles are counted as "completed"
completed_tiles++;
}
// Increment the number of tiles in that level / screen
total_tiles++;
}
}
return (completed_tiles == total_tiles);
}
LLVector3 LLWorldMapView::globalPosToView( const LLVector3d& global_pos ) LLVector3 LLWorldMapView::globalPosToView( const LLVector3d& global_pos )
{ {

View File

@@ -87,6 +87,7 @@ public:
LLVector3d viewPosToGlobal(S32 x,S32 y); LLVector3d viewPosToGlobal(S32 x,S32 y);
virtual void draw(); virtual void draw();
void drawTiles(S32 width, S32 height);
void drawGenericItems(const LLWorldMap::item_info_list_t& items, LLUIImagePtr image); void drawGenericItems(const LLWorldMap::item_info_list_t& items, LLUIImagePtr image);
void drawGenericItem(const LLItemInfo& item, LLUIImagePtr image); void drawGenericItem(const LLItemInfo& item, LLUIImagePtr image);
void drawImage(const LLVector3d& global_pos, LLUIImagePtr image, const LLColor4& color = LLColor4::white); void drawImage(const LLVector3d& global_pos, LLUIImagePtr image, const LLColor4& color = LLColor4::white);
@@ -94,6 +95,8 @@ public:
void drawAgents(); void drawAgents();
void drawEvents(); void drawEvents();
void drawFrustum(); void drawFrustum();
void drawMipmap(S32 width, S32 height);
bool drawMipmapLevel(S32 width, S32 height, S32 level, bool load = true);
static void cleanupTextures(); static void cleanupTextures();
@@ -173,6 +176,7 @@ public:
static F32 sTargetPanY; // in pixels static F32 sTargetPanY; // in pixels
static S32 sTrackingArrowX; static S32 sTrackingArrowX;
static S32 sTrackingArrowY; static S32 sTrackingArrowY;
static bool sVisibleTilesLoaded;
// Are we mid-pan from a user drag? // Are we mid-pan from a user drag?
BOOL mPanning; BOOL mPanning;

View File

@@ -0,0 +1,274 @@
/**
* @file llworldmipmap.cpp
* @brief Data storage for the S3 mipmap of the entire world.
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llworldmipmap.h"
#include "llviewercontrol.h"
#include "llviewerimagelist.h"
#include "math.h" // log()
// Turn this on to output tile stats in the standard output
#define DEBUG_TILES_STAT 0
LLWorldMipmap::LLWorldMipmap() :
mCurrentLevel(0)
{
}
LLWorldMipmap::~LLWorldMipmap()
{
reset();
}
// Delete all sublevel maps and clean them
void LLWorldMipmap::reset()
{
for (int level = 0; level < MAP_LEVELS; level++)
{
mWorldObjectsMipMap[level].clear();
}
}
// This method should be called before each use of the mipmap (typically, before each draw), so that to let
// the boost level of unused tiles to drop to 0 (BOOST_NONE).
// Tiles that are accessed have had their boost level pushed to BOOST_MAP_VISIBLE so we can identify them.
// The result of this strategy is that if a tile is not used during 2 consecutive loops, its boost level drops to 0.
void LLWorldMipmap::equalizeBoostLevels()
{
#if DEBUG_TILES_STAT
S32 nb_missing = 0;
S32 nb_tiles = 0;
S32 nb_visible = 0;
#endif // DEBUG_TILES_STAT
// For each level
for (S32 level = 0; level < MAP_LEVELS; level++)
{
sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level];
// For each tile
for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++)
{
LLPointer<LLViewerImage> img = iter->second;
S32 current_boost_level = img->getBoostLevel();
if (current_boost_level == LLViewerImageBoostLevel::BOOST_MAP_VISIBLE)
{
// If level was BOOST_MAP_VISIBLE, the tile has been used in the last draw so keep it high
img->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP);
}
else
{
// If level was BOOST_MAP only (or anything else...), the tile wasn't used in the last draw
// so we drop its boost level to BOOST_NONE.
img->setBoostLevel(LLViewerImageBoostLevel::BOOST_NONE);
}
#if DEBUG_TILES_STAT
// Increment some stats if compile option on
nb_tiles++;
if (current_boost_level == LLViewerImageBoostLevel::BOOST_MAP_VISIBLE)
{
nb_visible++;
}
if (img->isMissingAsset())
{
nb_missing++;
}
#endif // DEBUG_TILES_STAT
}
}
#if DEBUG_TILES_STAT
LL_INFOS("World Map") << "LLWorldMipmap tile stats : total requested = " << nb_tiles << ", visible = " << nb_visible << ", missing = " << nb_missing << LL_ENDL;
#endif // DEBUG_TILES_STAT
}
// This method should be used when the mipmap is not actively used for a while, e.g., the map UI is hidden
void LLWorldMipmap::dropBoostLevels()
{
// For each level
for (S32 level = 0; level < MAP_LEVELS; level++)
{
sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level];
// For each tile
for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++)
{
LLPointer<LLViewerImage> img = iter->second;
img->setBoostLevel(LLViewerImageBoostLevel::BOOST_NONE);
}
}
}
LLPointer<LLViewerImage> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load)
{
// Check the input data
llassert(level <= MAP_LEVELS);
llassert(level >= 1);
// If the *loading* level changed, cleared the new level from "missed" tiles
// so that we get a chance to reload them
if (load && (level != mCurrentLevel))
{
cleanMissedTilesFromLevel(level);
mCurrentLevel = level;
}
// Build the region handle
U64 handle = convertGridToHandle(grid_x, grid_y);
// Check if the image is around already
sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level-1];
sublevel_tiles_t::iterator found = level_mipmap.find(handle);
// If not there and load on, go load it
if (found == level_mipmap.end())
{
if (load)
{
// Load it
LLPointer<LLViewerImage> img = loadObjectsTile(grid_x, grid_y, level);
// Insert the image in the map
level_mipmap.insert(sublevel_tiles_t::value_type( handle, img ));
// Find the element again in the map (it's there now...)
found = level_mipmap.find(handle);
}
else
{
// Return with NULL if not found and we're not trying to load
return NULL;
}
}
// Get the image pointer and check if this asset is missing
LLPointer<LLViewerImage> img = found->second;
if (img->isMissingAsset())
{
// Return NULL if asset missing
return NULL;
}
else
{
// Boost the tile level so to mark it's in use *if* load on
if (load)
{
img->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP_VISIBLE);
}
return img;
}
}
LLPointer<LLViewerImage> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 grid_y, S32 level)
{
// Get the grid coordinates
std::string imageurl = gSavedSettings.getString("MapServerURL") + llformat("map-%d-%d-%d-objects.jpg", level, grid_x, grid_y);
// DO NOT COMMIT!! DEBUG ONLY!!!
// Use a local jpeg for every tile to test map speed without S3 access
//imageurl = "file://C:\\Develop\\mapserver-distribute-3\\indra\\build-vc80\\mapserver\\relwithdebinfo\\regions\\00995\\01001\\region-995-1001-prims.jpg";
// END DEBUG
//LL_INFOS("World Map") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL;
LLPointer<LLViewerImage> img = gImageList.getImageFromUrl(imageurl);
img->setBoostLevel(LLViewerImageBoostLevel::BOOST_MAP);
// Return the smart pointer
return img;
}
// This method is used to clean up a level from tiles marked as "missing".
// The idea is to allow tiles that have been improperly marked missing to be reloaded when retraversing the level again.
// When zooming in and out rapidly, some tiles are never properly loaded and, eventually marked missing.
// This creates "blue" areas in a subresolution that never got a chance to reload if we don't clean up the level.
void LLWorldMipmap::cleanMissedTilesFromLevel(S32 level)
{
// Check the input data
llassert(level <= MAP_LEVELS);
llassert(level >= 0);
// This happens when the object is first initialized
if (level == 0)
{
return;
}
// Iterate through the subresolution level and suppress the tiles that are marked as missing
// Note: erasing in a map while iterating through it is bug prone. Using a postfix increment is mandatory here.
sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level-1];
sublevel_tiles_t::iterator it = level_mipmap.begin();
while (it != level_mipmap.end())
{
LLPointer<LLViewerImage> img = it->second;
if (img->isMissingAsset())
{
level_mipmap.erase(it++);
}
else
{
++it;
}
}
return;
}
// static methods
// Compute the level in the world mipmap (between 1 and MAP_LEVELS, as in the URL) given the scale (size of a sim in screen pixels)
S32 LLWorldMipmap::scaleToLevel(F32 scale)
{
// If scale really small, picks up the higest level there is (lowest resolution)
if (scale <= F32_MIN)
return MAP_LEVELS;
// Compute the power of two resolution level knowing the base level
S32 level = llfloor((log(REGION_WIDTH_METERS/scale)/log(2.0f)) + 1.0f);
// Check bounds and return the value
if (level > MAP_LEVELS)
return MAP_LEVELS;
else if (level < 1)
return 1;
else
return level;
}
// Convert world coordinates to mipmap grid coordinates at a given level (between 1 and MAP_LEVELS)
void LLWorldMipmap::globalToMipmap(F64 global_x, F64 global_y, S32 level, U32* grid_x, U32* grid_y)
{
// Check the input data
llassert(level <= MAP_LEVELS);
llassert(level >= 1);
// Convert world coordinates into grid coordinates
*grid_x = lltrunc(global_x/REGION_WIDTH_METERS);
*grid_y = lltrunc(global_y/REGION_WIDTH_METERS);
// Compute the valid grid coordinates at that level of the mipmap
S32 regions_in_tile = 1 << (level - 1);
*grid_x = *grid_x - (*grid_x % regions_in_tile);
*grid_y = *grid_y - (*grid_y % regions_in_tile);
}

View File

@@ -0,0 +1,100 @@
/**
* @file llworldmipmap.h
* @brief Data storage for the S3 mipmap of the entire world.
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLWORLDMIPMAP_H
#define LL_LLWORLDMIPMAP_H
#include <map>
#include "llmemory.h" // LLPointer
#include "indra_constants.h" // REGION_WIDTH_UNITS
#include "llregionhandle.h" // to_region_handle()
class LLViewerImage;
// LLWorldMipmap : Mipmap handling of all the tiles used to render the world at any resolution.
// This class provides a clean structured access to the hierarchy of tiles stored in the
// Amazon S3 repository and abstracts its directory/file structure.
// The interface of this class though still assumes that the caller knows the general level/tiles
// structure (at least, that it exists...) but doesn't requite the caller to know the details of it.
// IOW, you need to know that rendering levels exists as well as grid coordinates for regions,
// but you can ignore where those tiles are located, how to get them, etc...
// The class API gives you back LLPointer<LLViewerImage> per tile.
// See llworldmipmapview.cpp for the implementation of a class who knows how to render an LLWorldMipmap.
// Implementation notes:
// - On the S3 servers, the tiles are rendered in 2 flavors: Objects and Terrain.
// - For the moment, LLWorldMipmap implements access only to the Objects tiles.
class LLWorldMipmap
{
public:
// Parameters of the mipmap
static const S32 MAP_LEVELS = 8; // Number of subresolution levels computed by the mapserver
static const S32 MAP_TILE_SIZE = 256; // Width in pixels of the tiles computed by the mapserver
LLWorldMipmap();
~LLWorldMipmap();
// Clear up the maps and release all image handles
void reset();
// Manage the boost levels between loops (typically draw() loops)
void equalizeBoostLevels();
// Drop the boost levels to none (used when hiding the map)
void dropBoostLevels();
// Get the tile smart pointer, does the loading if necessary
LLPointer<LLViewerImage> getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load = true);
// Helper functions: those are here as they depend solely on the topology of the mipmap though they don't access it
// Convert sim scale (given in sim width in display pixels) into a mipmap level
static S32 scaleToLevel(F32 scale);
// Convert world coordinates to mipmap grid coordinates at a given level
static void globalToMipmap(F64 global_x, F64 global_y, S32 level, U32* grid_x, U32* grid_y);
private:
// Get a handle (key) from grid coordinates
U64 convertGridToHandle(U32 grid_x, U32 grid_y) { return to_region_handle(grid_x * REGION_WIDTH_UNITS, grid_y * REGION_WIDTH_UNITS); }
// Load the relevant tile from S3
LLPointer<LLViewerImage> loadObjectsTile(U32 grid_x, U32 grid_y, S32 level);
// Clear a level from its "missing" tiles
void cleanMissedTilesFromLevel(S32 level);
// The mipmap is organized by resolution level (MAP_LEVELS of them). Each resolution level is an std::map
// using a region_handle as a key and storing a smart pointer to the image as a value.
typedef std::map<U64, LLPointer<LLViewerImage> > sublevel_tiles_t;
sublevel_tiles_t mWorldObjectsMipMap[MAP_LEVELS];
// sublevel_tiles_t mWorldTerrainMipMap[MAP_LEVELS];
S32 mCurrentLevel; // The level last accessed by a getObjectsTile()
};
#endif // LL_LLWORLDMIPMAP_H

View File

@@ -2,13 +2,8 @@
<floater can_close="true" can_drag_on_left="false" can_minimize="true" can_resize="true" <floater can_close="true" can_drag_on_left="false" can_minimize="true" can_resize="true"
height="711" min_height="520" min_width="410" name="worldmap" height="711" min_height="520" min_width="410" name="worldmap"
rect_control="FloaterWorldMapRect2" title="World Map" width="1243"> rect_control="FloaterWorldMapRect2" title="World Map" width="1243">
<tab_container bottom="-701" follows="left|top|right|bottom" height="681" left="15" <panel bottom="-701" follows="left|top|right|bottom" height="681"
mouse_opaque="false" name="maptab" tab_position="top" width="995"> left="15" mouse_opaque="true" name="objects_mapview" width="995" />
<panel bottom="-680" follows="left|top|right|bottom" height="664" label="Objects"
left="1" mouse_opaque="true" name="objects_mapview" width="993" />
<panel bottom="-680" follows="left|top|right|bottom" height="664" label="Terrain"
left="1" mouse_opaque="true" name="terrain_mapview" width="993" />
</tab_container>
<icon bottom="-50" color="1, 1, 1, 1" follows="top|right" height="16" <icon bottom="-50" color="1, 1, 1, 1" follows="top|right" height="16"
image_name="map_avatar_16.tga" left="1013" mouse_opaque="true" name="self" image_name="map_avatar_16.tga" left="1013" mouse_opaque="true" name="self"
width="16" /> width="16" />