aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
authorRobert Adams2014-06-01 19:22:26 -0700
committerRobert Adams2014-06-01 19:23:49 -0700
commit0aa0dad47868d6f64fa19f81b0f5daf35196fc3b (patch)
tree794ba1ab5af3733a109175414e934dcba2a42c50 /OpenSim/Region/ClientStack
parentFixes a permissions bug where a user with group powers to always rez was not ... (diff)
downloadopensim-SC-0aa0dad47868d6f64fa19f81b0f5daf35196fc3b.zip
opensim-SC-0aa0dad47868d6f64fa19f81b0f5daf35196fc3b.tar.gz
opensim-SC-0aa0dad47868d6f64fa19f81b0f5daf35196fc3b.tar.bz2
opensim-SC-0aa0dad47868d6f64fa19f81b0f5daf35196fc3b.tar.xz
Send multiple terrain patches per terrain update packet if terrain
draw distance optimization is enabled. Makes terrain editting a lot snappier.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs124
1 files changed, 100 insertions, 24 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index c28e58d..44386c9 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -1154,6 +1154,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1154 1154
1155 /// <summary> 1155 /// <summary>
1156 /// Send the region heightmap to the client 1156 /// Send the region heightmap to the client
1157 /// This method is only called when not doing intellegent terrain patch sending and
1158 /// is only called when the scene presence is initially created and sends all of the
1159 /// region's patches to the client.
1157 /// </summary> 1160 /// </summary>
1158 /// <param name="map">heightmap</param> 1161 /// <param name="map">heightmap</param>
1159 public virtual void SendLayerData(float[] map) 1162 public virtual void SendLayerData(float[] map)
@@ -1237,9 +1240,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1237 1240
1238 // Legacy form of invocation that passes around a bare data array. 1241 // Legacy form of invocation that passes around a bare data array.
1239 // Just ignore what was passed and use the real terrain info that is part of the scene. 1242 // Just ignore what was passed and use the real terrain info that is part of the scene.
1243 // As a HORRIBLE kludge in an attempt to not change the definition of IClientAPI,
1244 // there is a special form for specifying multiple terrain patches to send.
1245 // The form is to pass 'px' as negative the number of patches to send and to
1246 // pass the float array as pairs of patch X and Y coordinates. So, passing 'px'
1247 // as -2 and map= [3, 5, 8, 4] would mean to send two terrain heightmap patches
1248 // and the patches to send are <3,5> and <8,4>.
1240 public void SendLayerData(int px, int py, float[] map) 1249 public void SendLayerData(int px, int py, float[] map)
1241 { 1250 {
1242 SendLayerData(px, py, m_scene.Heightmap.GetTerrainData()); 1251 if (px >= 0)
1252 {
1253 SendLayerData(px, py, m_scene.Heightmap.GetTerrainData());
1254 }
1255 else
1256 {
1257 int numPatches = -px;
1258 int[] xPatches = new int[numPatches];
1259 int[] yPatches = new int[numPatches];
1260 for (int pp = 0; pp < numPatches; pp++)
1261 {
1262 xPatches[pp] = (int)map[pp * 2];
1263 yPatches[pp] = (int)map[pp * 2 + 1];
1264 }
1265
1266 // DebugSendingPatches("SendLayerData", xPatches, yPatches);
1267
1268 SendLayerData(xPatches, yPatches, m_scene.Heightmap.GetTerrainData());
1269 }
1270 }
1271
1272 private void DebugSendingPatches(string pWho, int[] pX, int[] pY)
1273 {
1274 if (m_log.IsDebugEnabled)
1275 {
1276 int numPatches = pX.Length;
1277 string Xs = "";
1278 string Ys = "";
1279 for (int pp = 0; pp < numPatches; pp++)
1280 {
1281 Xs += String.Format("{0}", (int)pX[pp]) + ",";
1282 Ys += String.Format("{0}", (int)pY[pp]) + ",";
1283 }
1284 m_log.DebugFormat("{0} {1}: numPatches={2}, X={3}, Y={4}", LogHeader, pWho, numPatches, Xs, Ys);
1285 }
1243 } 1286 }
1244 1287
1245 /// <summary> 1288 /// <summary>
@@ -1252,6 +1295,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1252 /// <param name="map">heightmap</param> 1295 /// <param name="map">heightmap</param>
1253 public void SendLayerData(int px, int py, TerrainData terrData) 1296 public void SendLayerData(int px, int py, TerrainData terrData)
1254 { 1297 {
1298 int[] xPatches = new[] { px };
1299 int[] yPatches = new[] { py };
1300 SendLayerData(xPatches, yPatches, terrData);
1301 }
1302
1303 private void SendLayerData(int[] px, int[] py, TerrainData terrData)
1304 {
1255 try 1305 try
1256 { 1306 {
1257 /* test code using the terrain compressor in libOpenMetaverse 1307 /* test code using the terrain compressor in libOpenMetaverse
@@ -1259,31 +1309,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1259 patchInd[0] = px + (py * Constants.TerrainPatchSize); 1309 patchInd[0] = px + (py * Constants.TerrainPatchSize);
1260 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(terrData.GetFloatsSerialized(), patchInd); 1310 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(terrData.GetFloatsSerialized(), patchInd);
1261 */ 1311 */
1262 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, px, py); 1312 // Many, many patches could have been passed to us. Since the patches will be compressed
1263 1313 // into variable sized blocks, we cannot pre-compute how many will fit into one
1264 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience. 1314 // packet. While some fancy packing algorithm is possible, 4 seems to always fit.
1265 // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain. 1315 int PatchesAssumedToFit = 4;
1266 // We also make them unreliable because it's extremely likely that multiple packets will be sent for a terrain patch area 1316 for (int pcnt = 0; pcnt < px.Length; pcnt += PatchesAssumedToFit)
1267 // invalidating previous packets for that area. 1317 {
1268 1318 int remaining = Math.Min(px.Length - pcnt, PatchesAssumedToFit);
1269 // It's possible for an editing user to flood themselves with edited packets but the majority of use cases are such that only a 1319 int[] xPatches = new int[remaining];
1270 // tiny percentage of users will be editing the terrain. Other, non-editing users will see the edits much slower. 1320 int[] yPatches = new int[remaining];
1271 1321 for (int ii = 0; ii < remaining; ii++)
1272 // One last note on this topic, by the time users are going to be editing the terrain, it's extremely likely that the sim will 1322 {
1273 // have rezzed already and therefore this is not likely going to cause any additional issues with lost packets, objects or terrain 1323 xPatches[ii] = px[pcnt + ii];
1274 // patches. 1324 yPatches[ii] = py[pcnt + ii];
1325 }
1326 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, xPatches, yPatches);
1327 // DebugSendingPatches("SendLayerDataInternal", xPatches, yPatches);
1275 1328
1276 // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we only have one cache miss. 1329 SendTheLayerPacket(layerpack);
1277 if (m_justEditedTerrain)
1278 {
1279 layerpack.Header.Reliable = false;
1280 OutPacket(layerpack, ThrottleOutPacketType.Unknown );
1281 }
1282 else
1283 {
1284 layerpack.Header.Reliable = true;
1285 OutPacket(layerpack, ThrottleOutPacketType.Land);
1286 } 1330 }
1331 // LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, px, py);
1332
1287 } 1333 }
1288 catch (Exception e) 1334 catch (Exception e)
1289 { 1335 {
@@ -1291,6 +1337,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1291 } 1337 }
1292 } 1338 }
1293 1339
1340 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a
1341 // sub optimal editing experience. To alleviate this issue, when the user edits the terrain, we
1342 // start skipping the queues until they're done editing the terrain. We also make them
1343 // unreliable because it's extremely likely that multiple packets will be sent for a terrain patch
1344 // area invalidating previous packets for that area.
1345
1346 // It's possible for an editing user to flood themselves with edited packets but the majority
1347 // of use cases are such that only a tiny percentage of users will be editing the terrain.
1348 // Other, non-editing users will see the edits much slower.
1349
1350 // One last note on this topic, by the time users are going to be editing the terrain, it's
1351 // extremely likely that the sim will have rezzed already and therefore this is not likely going
1352 // to cause any additional issues with lost packets, objects or terrain patches.
1353
1354 // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we
1355 // only have one cache miss.
1356 private void SendTheLayerPacket(LayerDataPacket layerpack)
1357 {
1358 if (m_justEditedTerrain)
1359 {
1360 layerpack.Header.Reliable = false;
1361 OutPacket(layerpack, ThrottleOutPacketType.Unknown );
1362 }
1363 else
1364 {
1365 layerpack.Header.Reliable = true;
1366 OutPacket(layerpack, ThrottleOutPacketType.Land);
1367 }
1368 }
1369
1294 /// <summary> 1370 /// <summary>
1295 /// Send the wind matrix to the client 1371 /// Send the wind matrix to the client
1296 /// </summary> 1372 /// </summary>