aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llworld.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llworld.cpp359
1 files changed, 281 insertions, 78 deletions
diff --git a/linden/indra/newview/llworld.cpp b/linden/indra/newview/llworld.cpp
index 90ab49b..ca8ce2d 100644
--- a/linden/indra/newview/llworld.cpp
+++ b/linden/indra/newview/llworld.cpp
@@ -61,6 +61,12 @@
61#include "llappviewer.h" // for do_disconnect() 61#include "llappviewer.h" // for do_disconnect()
62 62
63#include "hippoLimits.h" 63#include "hippoLimits.h"
64
65#include <deque>
66#include <queue>
67#include <map>
68#include <cstring>
69
64// 70//
65// Globals 71// Globals
66// 72//
@@ -661,7 +667,8 @@ void LLWorld::updateParticles()
661 667
662void LLWorld::updateClouds(const F32 dt) 668void LLWorld::updateClouds(const F32 dt)
663{ 669{
664 if (gSavedSettings.getBOOL("FreezeTime") || 670 static BOOL* sFreezeTime = rebind_llcontrol<BOOL>("FreezeTime", &gSavedSettings, true);
671 if ((*sFreezeTime) ||
665 !gSavedSettings.getBOOL("SkyUseClassicClouds")) 672 !gSavedSettings.getBOOL("SkyUseClassicClouds"))
666 { 673 {
667 // don't move clouds in snapshot mode 674 // don't move clouds in snapshot mode
@@ -810,10 +817,69 @@ F32 LLWorld::getLandFarClip() const
810 817
811void LLWorld::setLandFarClip(const F32 far_clip) 818void LLWorld::setLandFarClip(const F32 far_clip)
812{ 819{
820 static S32 const rwidth = (S32)REGION_WIDTH_U32;
821 S32 const n1 = (llceil(mLandFarClip) - 1) / rwidth;
822 S32 const n2 = (llceil(far_clip) - 1) / rwidth;
823 bool need_water_objects_update = n1 != n2;
824
813 mLandFarClip = far_clip; 825 mLandFarClip = far_clip;
826
827 if (need_water_objects_update)
828 {
829 updateWaterObjects();
830 }
814} 831}
815 832
833// Some region that we're connected to, but not the one we're in, gave us
834// a (possibly) new water height. Update it in our local copy.
835void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_height)
836{
837 for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter)
838 {
839 if ((*iter)->getName() == sim_name)
840 {
841 (*iter)->setWaterHeight(water_height);
842 break;
843 }
844 }
845}
816 846
847// There are three types of water objects:
848// Region water objects: the water in a region.
849// Hole water objects: water in the void but within current draw distance.
850// Edge water objects: the water outside the draw distance, up till the horizon.
851//
852// For example:
853//
854// -----------------------horizon-------------------------
855// | | | |
856// | Edge Water | | |
857// | | | |
858// | | | |
859// | | | |
860// | | | |
861// | | rwidth | |
862// | | <-----> | |
863// -------------------------------------------------------
864// | |Hole |other| | |
865// | |Water|reg. | | |
866// | |-----------------| |
867// | |other|cur. |<--> | |
868// | |reg. | reg.| \__|_ draw distance |
869// | |-----------------| |
870// | | | |<--->| |
871// | | | | \__|_ range |
872// -------------------------------------------------------
873// | |<----width------>|<--horizon ext.->|
874// | | | |
875// | | | |
876// | | | |
877// | | | |
878// | | | |
879// | | | |
880// | | | |
881// -------------------------------------------------------
882//
817void LLWorld::updateWaterObjects() 883void LLWorld::updateWaterObjects()
818{ 884{
819 if (!gAgent.getRegion()) 885 if (!gAgent.getRegion())
@@ -826,128 +892,265 @@ void LLWorld::updateWaterObjects()
826 return; 892 return;
827 } 893 }
828 894
829 // First, determine the min and max "box" of water objects 895 // Region width in meters.
830 S32 min_x = 0; 896 S32 const rwidth = (S32)REGION_WIDTH_U32;
831 S32 min_y = 0; 897
832 S32 max_x = 0; 898 // The distance we might see into the void
833 S32 max_y = 0; 899 // when standing on the edge of a region, in meters.
900 S32 const draw_distance = llceil(mLandFarClip);
901
902 // We can only have "holes" in the water (where there no region) if we
903 // can have existing regions around it. Taking into account that this
904 // code is only executed when we enter a region, and not when we walk
905 // around in it, we (only) need to take into account regions that fall
906 // within the draw_distance.
907 //
908 // Set 'range' to draw_distance, rounded up to the nearest multiple of rwidth.
909 S32 const nsims = (draw_distance + rwidth - 1) / rwidth;
910 S32 const range = nsims * rwidth;
911
912 // Get South-West corner of current region.
913 LLViewerRegion const* regionp = gAgent.getRegion();
834 U32 region_x, region_y; 914 U32 region_x, region_y;
835
836 S32 rwidth = 256;
837
838 // We only want to fill in water for stuff that's near us, say, within 256 or 512m
839 S32 range = LLViewerCamera::getInstance()->getFar() > 256.f ? 512 : 256;
840
841 LLViewerRegion* regionp = gAgent.getRegion();
842 from_region_handle(regionp->getHandle(), &region_x, &region_y); 915 from_region_handle(regionp->getHandle(), &region_x, &region_y);
843 916
844 min_x = (S32)region_x - range; 917 // The min. and max. coordinates of the South-West corners of the Hole water objects.
845 min_y = (S32)region_y - range; 918 S32 const min_x = (S32)region_x - range;
846 max_x = (S32)region_x + range; 919 S32 const min_y = (S32)region_y - range;
847 max_y = (S32)region_y + range; 920 S32 const max_x = (S32)region_x + range;
921 S32 const max_y = (S32)region_y + range;
922
923 // Attempt to determine a sensible water height for all the
924 // Hole Water objects.
925 //
926 // It make little sense to try to guess what the best water
927 // height should be when that isn't completely obvious: if it's
928 // impossible to satisfy every region's water height without
929 // getting a jump in the water height.
930 //
931 // In order to keep the reasoning simple, we assume something
932 // logical as a group of connected regions, where the coastline
933 // is at the outer edge. Anything more complex that would "break"
934 // under such an assumption would probably break anyway (would
935 // depend on terrain editing and existing mega prims, say, if
936 // anything would make sense at all).
937 //
938 // So, what we do is find all connected regions within the
939 // draw distance that border void, and then pick the lowest
940 // water height of those (coast) regions.
941 S32 const n = 2 * nsims + 1;
942 S32 const origin = nsims + nsims * n;
943 std::vector<F32> water_heights(n * n);
944 std::vector<U8> checked(n * n, 0); // index = nx + ny * n + origin;
945 U8 const region_bit = 1;
946 U8 const hole_bit = 2;
947 U8 const bordering_hole_bit = 4;
948 U8 const bordering_edge_bit = 8;
949 // Use the legacy waterheight for the Edge water in the case
950 // that we don't find any Hole water at all.
951 F32 water_height = DEFAULT_WATER_HEIGHT;
952 int max_count = 0;
953 LL_DEBUGS("WaterHeight") << "Current region: " << regionp->getName() << "; water height: " << regionp->getWaterHeight() << " m." << LL_ENDL;
954 std::map<S32, int> water_height_counts;
955 typedef std::queue<std::pair<S32, S32>, std::deque<std::pair<S32, S32> > > nxny_pairs_type;
956 nxny_pairs_type nxny_pairs;
957 nxny_pairs.push(nxny_pairs_type::value_type(0, 0));
958 water_heights[origin] = regionp->getWaterHeight();
959 checked[origin] = region_bit;
960 // For debugging purposes.
961 int number_of_connected_regions = 1;
962 int uninitialized_regions = 0;
963 int bordering_hole = 0;
964 int bordering_edge = 0;
965 while(!nxny_pairs.empty())
966 {
967 S32 const nx = nxny_pairs.front().first;
968 S32 const ny = nxny_pairs.front().second;
969 LL_DEBUGS("WaterHeight") << "nx,ny = " << nx << "," << ny << LL_ENDL;
970 S32 const index = nx + ny * n + origin;
971 nxny_pairs.pop();
972 for (S32 dir = 0; dir < 4; ++dir)
973 {
974 S32 const cnx = nx + gDirAxes[dir][0];
975 S32 const cny = ny + gDirAxes[dir][1];
976 LL_DEBUGS("WaterHeight") << "dir = " << dir << "; cnx,cny = " << cnx << "," << cny << LL_ENDL;
977 S32 const cindex = cnx + cny * n + origin;
978 bool is_hole = false;
979 bool is_edge = false;
980 LLViewerRegion* new_region_found = NULL;
981 if (cnx < -nsims || cnx > nsims ||
982 cny < -nsims || cny > nsims)
983 {
984 LL_DEBUGS("WaterHeight") << " Edge Water!" << LL_ENDL;
985 // Bumped into Edge water object.
986 is_edge = true;
987 }
988 else if (checked[cindex])
989 {
990 LL_DEBUGS("WaterHeight") << " Already checked before!" << LL_ENDL;
991 // Already checked.
992 is_hole = (checked[cindex] & hole_bit);
993 }
994 else
995 {
996 S32 x = (S32)region_x + cnx * rwidth;
997 S32 y = (S32)region_y + cny * rwidth;
998 U64 region_handle = to_region_handle(x, y);
999 new_region_found = getRegionFromHandle(region_handle);
1000 is_hole = !new_region_found;
1001 checked[cindex] = is_hole ? hole_bit : region_bit;
1002 }
1003 if (is_hole)
1004 {
1005 // This was a region that borders at least one 'hole'.
1006 // Count the found coastline.
1007 F32 new_water_height = water_heights[index];
1008 LL_DEBUGS("WaterHeight") << " This is void; counting coastline with water height of " << new_water_height << LL_ENDL;
1009 S32 new_water_height_cm = llround(new_water_height * 100);
1010 int count = (water_height_counts[new_water_height_cm] += 1);
1011 // Just use the lowest water height: this is mainly about the horizon water,
1012 // and whatever we do, we don't want it to be possible to look under the water
1013 // when looking in the distance: it is better to make a step downwards in water
1014 // height when going away from the avie than a step upwards. However, since
1015 // everyone is used to DEFAULT_WATER_HEIGHT, don't allow a single region
1016 // to drag the water level below DEFAULT_WATER_HEIGHT on it's own.
1017 if (bordering_hole == 0 || // First time we get here.
1018 (new_water_height >= DEFAULT_WATER_HEIGHT &&
1019 new_water_height < water_height) ||
1020 (new_water_height < DEFAULT_WATER_HEIGHT &&
1021 count > max_count)
1022 )
1023 {
1024 water_height = new_water_height;
1025 }
1026 if (count > max_count)
1027 {
1028 max_count = count;
1029 }
1030 if (!(checked[index] & bordering_hole_bit))
1031 {
1032 checked[index] |= bordering_hole_bit;
1033 ++bordering_hole;
1034 }
1035 }
1036 else if (is_edge && !(checked[index] & bordering_edge_bit))
1037 {
1038 checked[index] |= bordering_edge_bit;
1039 ++bordering_edge;
1040 }
1041 if (!new_region_found)
1042 {
1043 // Dead end, there is no region here.
1044 continue;
1045 }
1046 // Found a new connected region.
1047 ++number_of_connected_regions;
1048 if (new_region_found->getName().empty())
1049 {
1050 // Uninitialized LLViewerRegion, don't use it's water height.
1051 LL_DEBUGS("WaterHeight") << " Uninitialized region." << LL_ENDL;
1052 ++uninitialized_regions;
1053 continue;
1054 }
1055 nxny_pairs.push(nxny_pairs_type::value_type(cnx, cny));
1056 water_heights[cindex] = new_region_found->getWaterHeight();
1057 LL_DEBUGS("WaterHeight") << " Found a new region (name: " << new_region_found->getName() << "; water height: " << water_heights[cindex] << " m)!" << LL_ENDL;
1058 }
1059 }
1060 llinfos << "Number of connected regions: " << number_of_connected_regions << " (" << uninitialized_regions <<
1061 " uninitialized); number of regions bordering Hole water: " << bordering_hole <<
1062 "; number of regions bordering Edge water: " << bordering_edge << llendl;
1063 llinfos << "Coastline count (height, count): ";
1064 bool first = true;
1065 for (std::map<S32, int>::iterator iter = water_height_counts.begin(); iter != water_height_counts.end(); ++iter)
1066 {
1067 if (!first) llcont << ", ";
1068 llcont << "(" << (iter->first / 100.f) << ", " << iter->second << ")";
1069 first = false;
1070 }
1071 llcont << llendl;
1072 llinfos << "Water height used for Hole and Edge water objects: " << water_height << llendl;
848 1073
849 F32 height = 0.f; 1074 // Update all Region water objects.
850 1075 for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter)
851 for (region_list_t::iterator iter = mRegionList.begin();
852 iter != mRegionList.end(); ++iter)
853 { 1076 {
854 LLViewerRegion* regionp = *iter; 1077 LLViewerRegion* regionp = *iter;
855 LLVOWater* waterp = regionp->getLand().getWaterObj(); 1078 LLVOWater* waterp = regionp->getLand().getWaterObj();
856 height += regionp->getWaterHeight();
857 if (waterp) 1079 if (waterp)
858 { 1080 {
859 gObjectList.updateActive(waterp); 1081 gObjectList.updateActive(waterp);
860 } 1082 }
861 } 1083 }
862 1084
1085 // Clean up all existing Hole water objects.
863 for (std::list<LLVOWater*>::iterator iter = mHoleWaterObjects.begin(); 1086 for (std::list<LLVOWater*>::iterator iter = mHoleWaterObjects.begin();
864 iter != mHoleWaterObjects.end(); ++ iter) 1087 iter != mHoleWaterObjects.end(); ++iter)
865 { 1088 {
866 LLVOWater* waterp = *iter; 1089 LLVOWater* waterp = *iter;
867 gObjectList.killObject(waterp); 1090 gObjectList.killObject(waterp);
868 } 1091 }
869 mHoleWaterObjects.clear(); 1092 mHoleWaterObjects.clear();
870 1093
871 // Now, get a list of the holes 1094 // Let the Edge and Hole water boxes be 1024 meter high so that they
872 S32 x, y; 1095 // are never too small to be drawn (A LL_VO_*_WATER box has water
873 for (x = min_x; x <= max_x; x += rwidth) 1096 // rendered on it's bottom surface only), and put their bottom at
1097 // the current regions water height.
1098 F32 const box_height = 1024;
1099 F32 const water_center_z = water_height + box_height / 2;
1100
1101 // Create new Hole water objects within 'range' where there is no region.
1102 for (S32 x = min_x; x <= max_x; x += rwidth)
874 { 1103 {
875 for (y = min_y; y <= max_y; y += rwidth) 1104 for (S32 y = min_y; y <= max_y; y += rwidth)
876 { 1105 {
877 U64 region_handle = to_region_handle(x, y); 1106 U64 region_handle = to_region_handle(x, y);
878 if (!getRegionFromHandle(region_handle)) 1107 if (!getRegionFromHandle(region_handle))
879 { 1108 {
880 LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion()); 1109 LLVOWater* waterp = (LLVOWater*)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, gAgent.getRegion());
881 waterp->setUseTexture(FALSE); 1110 waterp->setUseTexture(FALSE);
882 waterp->setPositionGlobal(LLVector3d(x + rwidth/2, 1111 waterp->setPositionGlobal(LLVector3d(x + rwidth / 2, y + rwidth / 2, water_center_z));
883 y + rwidth/2, 1112 waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, box_height));
884 256.f+DEFAULT_WATER_HEIGHT));
885 waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f));
886 gPipeline.createObject(waterp); 1113 gPipeline.createObject(waterp);
887 mHoleWaterObjects.push_back(waterp); 1114 mHoleWaterObjects.push_back(waterp);
888 } 1115 }
889 } 1116 }
890 } 1117 }
891 1118
892 // Update edge water objects 1119 // Center of the region.
893 S32 wx, wy; 1120 S32 const center_x = region_x + rwidth / 2;
894 S32 center_x, center_y; 1121 S32 const center_y = region_y + rwidth / 2;
895 wx = (max_x - min_x) + rwidth; 1122 // Width of the area with Hole water objects.
896 wy = (max_y - min_y) + rwidth; 1123 S32 const width = rwidth + 2 * range;
897 center_x = min_x + (wx >> 1); 1124 S32 const horizon_extend = 2048 + 512 - range; // Legacy value.
898 center_y = min_y + (wy >> 1); 1125 // The overlap is needed to get rid of sky pixels being visible between the
899 1126 // Edge and Hole water object at greater distances (due to floating point
900 S32 add_boundary[4] = { 1127 // round off errors).
901 512 - (max_x - region_x), 1128 S32 const edge_hole_overlap = 1; // Twice the actual overlap.
902 512 - (max_y - region_y), 1129
903 512 - (region_x - min_x), 1130 for (S32 dir = 0; dir < 8; ++dir)
904 512 - (region_y - min_y) };
905
906 S32 dir;
907 for (dir = 0; dir < 8; dir++)
908 { 1131 {
909 S32 dim[2] = { 0 }; 1132 // Size of the Edge water objects.
910 switch (gDirAxes[dir][0]) 1133 S32 const dim_x = (gDirAxes[dir][0] == 0) ? width : (horizon_extend + edge_hole_overlap);
911 { 1134 S32 const dim_y = (gDirAxes[dir][1] == 0) ? width : (horizon_extend + edge_hole_overlap);
912 case -1: dim[0] = add_boundary[2]; break; 1135 // And their position.
913 case 0: dim[0] = wx; break; 1136 S32 const water_center_x = center_x + (width + horizon_extend) / 2 * gDirAxes[dir][0];
914 default: dim[0] = add_boundary[0]; break; 1137 S32 const water_center_y = center_y + (width + horizon_extend) / 2 * gDirAxes[dir][1];
915 }
916 switch (gDirAxes[dir][1])
917 {
918 case -1: dim[1] = add_boundary[3]; break;
919 case 0: dim[1] = wy; break;
920 default: dim[1] = add_boundary[1]; break;
921 }
922 1138
923 // Resize and reshape the water objects
924 const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]);
925 const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]);
926
927 LLVOWater* waterp = mEdgeWaterObjects[dir]; 1139 LLVOWater* waterp = mEdgeWaterObjects[dir];
928 if (!waterp || waterp->isDead()) 1140 if (!waterp || waterp->isDead())
929 { 1141 {
930 // The edge water objects can be dead because they're attached to the region that the 1142 // The edge water objects can be dead because they're attached to the region that the
931 // agent was in when they were originally created. 1143 // agent was in when they were originally created.
932 mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, 1144 mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, gAgent.getRegion());
933 gAgent.getRegion());
934 waterp = mEdgeWaterObjects[dir]; 1145 waterp = mEdgeWaterObjects[dir];
935 waterp->setUseTexture(FALSE); 1146 waterp->setUseTexture(FALSE);
936 waterp->setIsEdgePatch(TRUE); 1147 waterp->setIsEdgePatch(TRUE); // Mark that this is edge water and not hole water.
937 gPipeline.createObject(waterp); 1148 gPipeline.createObject(waterp);
938 } 1149 }
939 1150
940 waterp->setRegion(gAgent.getRegion()); 1151 waterp->setRegion(gAgent.getRegion());
941 LLVector3d water_pos(water_center_x, water_center_y, 1152 LLVector3d water_pos(water_center_x, water_center_y, water_center_z);
942 DEFAULT_WATER_HEIGHT+256.f); 1153 LLVector3 water_scale((F32) dim_x, (F32) dim_y, box_height);
943 LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f);
944
945 //stretch out to horizon
946 water_scale.mV[0] += fabsf(2048.f * gDirAxes[dir][0]);
947 water_scale.mV[1] += fabsf(2048.f * gDirAxes[dir][1]);
948
949 water_pos.mdV[0] += 1024.f * gDirAxes[dir][0];
950 water_pos.mdV[1] += 1024.f * gDirAxes[dir][1];
951 1154
952 waterp->setPositionGlobal(water_pos); 1155 waterp->setPositionGlobal(water_pos);
953 waterp->setScale(water_scale); 1156 waterp->setScale(water_scale);