disabling terrain patch sending by view distance for legacy sized regions.

The problem seems to be that people expect adjacent legacy sized regions
to just display like they always have. Limiting displayed terrain is
complicated by the camera position not being updated in child regions.
fsassets
Robert Adams 2015-06-06 07:09:20 -07:00
parent 0c5facbd75
commit 81ef7b586e
1 changed files with 49 additions and 25 deletions

View File

@ -107,11 +107,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private bool[,] updated; // for each patch, whether it needs to be sent to this client
private int updateCount; // number of patches that need to be sent
public ScenePresence Presence; // a reference to the client to send to
public TerrainData Terrain; // reference to the underlying terrain
public PatchUpdates(TerrainData terrData, ScenePresence pPresence)
{
updated = new bool[terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize];
updateCount = 0;
Presence = pPresence;
Terrain = terrData;
// Initially, send all patches to the client
SetAll(true);
}
@ -519,6 +521,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
// ITerrainModule.PushTerrain()
public void PushTerrain(IClientAPI pClient)
{
// If view distance based, set the modified patch bits and the frame event will send the updates
if (m_sendTerrainUpdatesByViewDistance)
{
ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
@ -533,6 +536,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence);
m_perClientPatchUpdates.Add(presence.UUID, pups);
}
// By setting all to modified, the next update tick will send the patches
pups.SetAll(true);
}
}
@ -543,7 +547,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
pClient.SendLayerData(new float[10]);
}
}
#region Plugin Loading Methods
private void LoadPlugins()
@ -991,16 +994,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain
else
{
// Legacy update sending where the update is sent out as soon as noticed
// We know the actual terrain data passed is ignored. This kludge saves changing IClientAPI.
// We know the actual terrain data that is passed is ignored so this passes a dummy heightmap.
//float[] heightMap = terrData.GetFloatsSerialized();
float[] heightMap = new float[10];
m_scene.ForEachClient(
delegate(IClientAPI controller)
{
controller.SendLayerData(x / Constants.TerrainPatchSize,
{
controller.SendLayerData(x / Constants.TerrainPatchSize,
y / Constants.TerrainPatchSize,
heightMap);
}
}
);
}
}
@ -1026,6 +1029,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
// Called each frame time to see if there are any patches to send to any of the
// ScenePresences.
// We know this is only called if we are doing view distance patch sending so some
// tests are not made.
// Loop through all the per-client info and send any patches necessary.
private void CheckSendingPatchesToClients()
{
@ -1043,7 +1048,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
// LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName);
// Sort the patches to send by the distance from the presence
toSend.Sort();
/*
/* old way that sent individual patches
foreach (PatchesToSend pts in toSend)
{
pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
@ -1051,6 +1056,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
}
*/
// new way that sends all patches to the protocol so they can be sent in one block
int[] xPieces = new int[toSend.Count];
int[] yPieces = new int[toSend.Count];
float[] patchPieces = new float[toSend.Count * 2];
@ -1067,6 +1073,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
}
}
// Compute a list of modified patches that are within our view distance.
private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups)
{
List<PatchesToSend> ret = new List<PatchesToSend>();
@ -1075,43 +1082,60 @@ namespace OpenSim.Region.CoreModules.World.Terrain
if (presence == null)
return ret;
// Compute the area of patches within our draw distance
int startX = (((int)(presence.AbsolutePosition.X - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2;
startX = Math.Max(startX, 0);
startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize);
int startY = (((int)(presence.AbsolutePosition.Y - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2;
startY = Math.Max(startY, 0);
startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize);
int endX = (((int)(presence.AbsolutePosition.X + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2;
endX = Math.Max(endX, 0);
endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize);
int endY = (((int)(presence.AbsolutePosition.Y + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2;
endY = Math.Max(endY, 0);
endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize);
// m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, start=<{4},{5}>, end=<{6},{7}>",
Vector3 presencePos = presence.AbsolutePosition;
// Before this distance check, the whole region just showed up. Adding the distance
// check causes different things to happen for the current and adjacent regions.
// So, to keep legacy views, if the region is legacy sized, don't do distance check.
bool isLegacySizedRegion = pups.Terrain.SizeX == Constants.RegionSize && pups.Terrain.SizeY == Constants.RegionSize;
bool shouldCheckViewDistance = m_sendTerrainUpdatesByViewDistance && !isLegacySizedRegion;
int startX = 0;
int endX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize;
int startY = 0;
int endY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize;
// The following only reduces the size of area scanned for updates. Only significant for very large varregions.
if (shouldCheckViewDistance)
{
// Compute the area of patches within our draw distance
startX = (((int)(presencePos.X - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2;
startX = Math.Max(startX, 0);
startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize);
startY = (((int)(presencePos.Y - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2;
startY = Math.Max(startY, 0);
startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize);
endX = (((int)(presencePos.X + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2;
endX = Math.Max(endX, 0);
endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize);
endY = (((int)(presencePos.Y + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2;
endY = Math.Max(endY, 0);
endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize);
}
// m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, cpos={4}, isChild={5}, start=<{6},{7}>, end=<{8},{9}>",
// LogHeader, m_scene.RegionInfo.RegionName,
// presence.DrawDistance, presence.AbsolutePosition,
// presence.DrawDistance, presencePos, presence.CameraPosition,
// isLegacySizeChildRegion,
// startX, startY, endX, endY);
for(int x = startX; x < endX; x++)
{
for(int y = startY; y < endY; y++)
{
//Need to make sure we don't send the same ones over and over
Vector3 presencePos = presence.AbsolutePosition;
Vector3 patchPos = new Vector3(x * Constants.TerrainPatchSize, y * Constants.TerrainPatchSize, presencePos.Z);
if (pups.GetByPatch(x, y))
{
//Check which has less distance, camera or avatar position, both have to be done.
//Its not a radius, its a diameter and we add 50 so that it doesn't look like it cuts off
if (Util.DistanceLessThan(presencePos, patchPos, presence.DrawDistance + 50)
if (!shouldCheckViewDistance
|| Util.DistanceLessThan(presencePos, patchPos, presence.DrawDistance + 50)
|| Util.DistanceLessThan(presence.CameraPosition, patchPos, presence.DrawDistance + 50))
{
//They can see it, send it to them
pups.SetByPatch(x, y, false);
float dist = Vector3.DistanceSquared(presencePos, patchPos);
ret.Add(new PatchesToSend(x, y, dist));
//Wait and send them all at once
// pups.client.SendLayerData(x, y, null);
}
}
}