mirror of
https://github.com/opensim/opensim.git
synced 2026-08-08 10:15:33 +08:00
make main terrain taints also a bitarray
This commit is contained in:
@@ -26,7 +26,7 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Reflection;
|
||||
@@ -73,12 +73,15 @@ namespace OpenSim.Framework
|
||||
|
||||
private float[,] m_heightmap;
|
||||
// Remember subregions of the heightmap that has changed.
|
||||
private bool[,] m_taint;
|
||||
|
||||
private BitArray m_taint;
|
||||
private int m_taintSizeX;
|
||||
private int m_taintStrideForY; // stride when Y is in meters
|
||||
private int m_taintSizeY;
|
||||
|
||||
// legacy CompressionFactor
|
||||
public float CompressionFactor { get; private set; }
|
||||
|
||||
// Terrain always is a square
|
||||
public int SizeX { get; protected set; }
|
||||
public int SizeY { get; protected set; }
|
||||
public int SizeZ { get; protected set; }
|
||||
@@ -104,7 +107,7 @@ namespace OpenSim.Framework
|
||||
if (m_heightmap[x, y] != value)
|
||||
{
|
||||
m_heightmap[x, y] = value;
|
||||
m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true;
|
||||
m_taint[x / Constants.TerrainPatchSize + y * m_taintStrideForY] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,19 +120,17 @@ namespace OpenSim.Framework
|
||||
|
||||
public void ClearTaint()
|
||||
{
|
||||
SetAllTaint(false);
|
||||
m_taint.SetAll(false);
|
||||
}
|
||||
|
||||
public void TaintAllTerrain()
|
||||
{
|
||||
SetAllTaint(true);
|
||||
m_taint.SetAll(true);
|
||||
}
|
||||
|
||||
private void SetAllTaint(bool setting)
|
||||
{
|
||||
for (int ii = 0; ii < m_taint.GetLength(0); ii++)
|
||||
for (int jj = 0; jj < m_taint.GetLength(1); jj++)
|
||||
m_taint[ii, jj] = setting;
|
||||
m_taint.SetAll(setting);
|
||||
}
|
||||
|
||||
public void ClearLand()
|
||||
@@ -147,24 +148,63 @@ namespace OpenSim.Framework
|
||||
// Return 'true' of the patch that contains these region coordinates has been modified.
|
||||
// Note that checking the taint clears it.
|
||||
// There is existing code that relies on this feature.
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool IsTaintedAt(int xx, int yy, bool clearOnTest)
|
||||
{
|
||||
int tx = xx / Constants.TerrainPatchSize;
|
||||
int ty = yy / Constants.TerrainPatchSize;
|
||||
bool ret = m_taint[tx, ty];
|
||||
int indx = xx / Constants.TerrainPatchSize + yy * m_taintStrideForY;
|
||||
bool ret = m_taint[indx];
|
||||
if (ret && clearOnTest)
|
||||
m_taint[tx, ty] = false;
|
||||
m_taint[indx] = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Old form that clears the taint flag when we check it.
|
||||
// ubit: this dangerus naming should be only check without clear
|
||||
// keeping for old modules outthere
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool IsTaintedAt(int xx, int yy)
|
||||
{
|
||||
return IsTaintedAt(xx, yy, true /* clearOnTest */);
|
||||
return m_taint[xx / Constants.TerrainPatchSize + yy * m_taintStrideForY];
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool IsTaintedAtPatch(int xx, int yy, bool clearOnTest)
|
||||
{
|
||||
int indx = xx + yy * m_taintSizeX;
|
||||
bool ret = m_taint[indx];
|
||||
if (ret && clearOnTest)
|
||||
m_taint[indx] = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool IsTaintedAtPatch(int xx, int yy)
|
||||
{
|
||||
return m_taint[xx + yy * m_taintSizeX];
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool IsTaintedAtPatch(int indx, bool clearOnTest)
|
||||
{
|
||||
bool ret = m_taint[indx];
|
||||
if (ret && clearOnTest)
|
||||
m_taint[indx] = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool IsTaintedAtPatchWithClear(int indx)
|
||||
{
|
||||
if(m_taint[indx])
|
||||
{
|
||||
m_taint[indx] = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool IsTaintedAtPatch(int indx)
|
||||
{
|
||||
return m_taint[indx];
|
||||
}
|
||||
// TerrainData.GetDatabaseBlob
|
||||
// The user wants something to store in the database.
|
||||
public bool GetDatabaseBlob(out int DBRevisionCode, out Array blob)
|
||||
@@ -306,6 +346,10 @@ namespace OpenSim.Framework
|
||||
{
|
||||
SizeX = pTerrain.GetLength(0);
|
||||
SizeY = pTerrain.GetLength(1);
|
||||
m_taintSizeX = SizeX / Constants.TerrainPatchSize;
|
||||
m_taintStrideForY = m_taintSizeX / Constants.TerrainPatchSize;
|
||||
m_taintSizeY = SizeY / Constants.TerrainPatchSize;
|
||||
|
||||
SizeZ = (int)Constants.RegionHeight;
|
||||
CompressionFactor = 100.0f;
|
||||
|
||||
@@ -320,8 +364,7 @@ namespace OpenSim.Framework
|
||||
}
|
||||
// m_log.DebugFormat("{0} new by doubles. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
|
||||
|
||||
m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
|
||||
ClearTaint();
|
||||
m_taint = new BitArray(m_taintSizeX * m_taintSizeY, false);
|
||||
}
|
||||
|
||||
// Create underlying structures but don't initialize the heightmap assuming the caller will immediately do that
|
||||
@@ -330,11 +373,14 @@ namespace OpenSim.Framework
|
||||
SizeX = pX;
|
||||
SizeY = pY;
|
||||
SizeZ = pZ;
|
||||
m_taintSizeX = SizeX / Constants.TerrainPatchSize;
|
||||
m_taintStrideForY = m_taintSizeX / Constants.TerrainPatchSize;
|
||||
m_taintSizeY = SizeY / Constants.TerrainPatchSize;
|
||||
CompressionFactor = 100.0f;
|
||||
m_heightmap = new float[SizeX, SizeY];
|
||||
m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
|
||||
m_taint = new BitArray(m_taintSizeX * m_taintSizeY, false);
|
||||
|
||||
// m_log.DebugFormat("{0} new by dimensions. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
|
||||
ClearTaint();
|
||||
ClearLand(0f);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
sendAllcurrentY = 0;
|
||||
}
|
||||
|
||||
public PatchUpdates(TerrainData terrData, ScenePresence pPresence, bool defaultState)
|
||||
{
|
||||
xsize = terrData.SizeX / Constants.TerrainPatchSize;
|
||||
ysize = terrData.SizeY / Constants.TerrainPatchSize;
|
||||
updated = new BitArray(xsize * ysize, true);
|
||||
updateCount = defaultState ? xsize * ysize : 0;
|
||||
Presence = pPresence;
|
||||
sendAll = defaultState;
|
||||
sendAllcurrentX = 0;
|
||||
sendAllcurrentY = 0;
|
||||
}
|
||||
|
||||
// Returns 'true' if there are any patches marked for sending
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool HasUpdates()
|
||||
@@ -140,17 +152,23 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
return updated[patchX + xsize * patchY];
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool GetByPatch(int indx)
|
||||
{
|
||||
return updated[indx];
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool GetByPatchAndClear(int patchX, int patchY)
|
||||
{
|
||||
int indx = patchX + xsize * patchY;
|
||||
bool ret = updated[indx];
|
||||
if(ret)
|
||||
if(updated[indx])
|
||||
{
|
||||
updated[indx] = false;
|
||||
--updateCount;
|
||||
return true;
|
||||
}
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
@@ -162,12 +180,54 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
if (state)
|
||||
{
|
||||
if (!prevState)
|
||||
updateCount++;
|
||||
++updateCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prevState)
|
||||
updateCount--;
|
||||
--updateCount;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void SetTrueByPatch(int patchX, int patchY)
|
||||
{
|
||||
int indx = patchX + xsize * patchY;
|
||||
if (!updated[indx])
|
||||
{
|
||||
updated[indx] = true;
|
||||
++updateCount;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void SetTrueByPatch(int indx)
|
||||
{
|
||||
if (!updated[indx])
|
||||
{
|
||||
updated[indx] = true;
|
||||
++updateCount;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void SetFalseByPatch(int patchX, int patchY)
|
||||
{
|
||||
int indx = patchX + xsize * patchY;
|
||||
if (updated[indx])
|
||||
{
|
||||
updated[indx] = false;
|
||||
--updateCount;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void SetFalseByPatch(int indx)
|
||||
{
|
||||
if (updated[indx])
|
||||
{
|
||||
updated[indx] = false;
|
||||
--updateCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,16 +259,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
);
|
||||
}
|
||||
|
||||
for (int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize)
|
||||
for (int indx = 0; indx < updated.Length; ++indx)
|
||||
{
|
||||
for (int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize)
|
||||
{
|
||||
// Only set tainted. The patch bit may be set if the patch was to be sent later.
|
||||
if (terrData.IsTaintedAt(xx, yy, false))
|
||||
{
|
||||
SetByXY(xx, yy, true);
|
||||
}
|
||||
}
|
||||
if (terrData.IsTaintedAtPatch(indx))
|
||||
SetTrueByPatch(indx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -638,7 +692,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence);
|
||||
m_perClientPatchUpdates.Add(presence.UUID, pups);
|
||||
}
|
||||
pups.SetAll(true);
|
||||
else
|
||||
pups.SetAll(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -896,15 +951,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
// dont overlap execution
|
||||
if(Monitor.TryEnter(TerrainCheckUpdatesLock))
|
||||
{
|
||||
// this needs fixing
|
||||
TerrainData terrData = m_channel.GetTerrainData();
|
||||
|
||||
bool shouldTaint = false;
|
||||
for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
|
||||
|
||||
int sx = terrData.SizeX / Constants.TerrainPatchSize;
|
||||
for (int y = 0, py = 0; y < terrData.SizeY / Constants.TerrainPatchSize; y++, py += sx)
|
||||
{
|
||||
for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
|
||||
for (int x = 0; x < sx; x++)
|
||||
{
|
||||
if (terrData.IsTaintedAt(x, y,true))
|
||||
if (terrData.IsTaintedAtPatchWithClear(x + py))
|
||||
{
|
||||
// Found a patch that was modified. Push this flag into the clients.
|
||||
SendToClients(terrData, x, y);
|
||||
@@ -1010,8 +1065,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
{
|
||||
for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
|
||||
{
|
||||
if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
|
||||
{
|
||||
if (terrData.IsTaintedAt(x, y))
|
||||
{
|
||||
// If we should respect the estate settings then
|
||||
// fixup and height deltas that don't respect them.
|
||||
// Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
|
||||
@@ -1031,8 +1086,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
{
|
||||
for (int y = startX; y <= endY; y += Constants.TerrainPatchSize)
|
||||
{
|
||||
if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
|
||||
{
|
||||
if (terrData.IsTaintedAt(x, y))
|
||||
{
|
||||
// If we should respect the estate settings then
|
||||
// fixup and height deltas that don't respect them.
|
||||
// Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
|
||||
@@ -1088,9 +1143,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
/// Sends a copy of the current terrain to the scenes clients
|
||||
/// </summary>
|
||||
/// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param>
|
||||
/// <param name="x">The patch corner to send</param>
|
||||
/// <param name="y">The patch corner to send</param>
|
||||
private void SendToClients(TerrainData terrData, int x, int y)
|
||||
/// <param name="px">x patch coords</param>
|
||||
/// <param name="py">y patch coords</param>
|
||||
private void SendToClients(TerrainData terrData, int px, int py)
|
||||
{
|
||||
if (m_sendTerrainUpdatesByViewDistance)
|
||||
{
|
||||
@@ -1099,14 +1154,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
{
|
||||
m_scene.ForEachScenePresence(presence =>
|
||||
{
|
||||
PatchUpdates thisClientUpdates;
|
||||
if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
|
||||
if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out PatchUpdates thisClientUpdates))
|
||||
{
|
||||
// There is a ScenePresence without a send patch map. Create one.
|
||||
thisClientUpdates = new PatchUpdates(terrData, presence);
|
||||
// There is a ScenePresence without a send patch map. Create one. should not happen
|
||||
thisClientUpdates = new PatchUpdates(terrData, presence, false);
|
||||
m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
|
||||
}
|
||||
thisClientUpdates.SetByXY(x, y, true);
|
||||
thisClientUpdates.SetTrueByPatch(px, py);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1116,7 +1170,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
// Legacy update sending where the update is sent out as soon as noticed
|
||||
// We know the actual terrain data that is passed is ignored so this passes a dummy heightmap.
|
||||
//float[] heightMap = terrData.GetFloatsSerialized();
|
||||
int[] map = new int[]{ x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize };
|
||||
int[] map = new int[]{px, py};
|
||||
m_scene.ForEachClient(
|
||||
delegate (IClientAPI controller)
|
||||
{
|
||||
@@ -1319,20 +1373,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
|
||||
DrawDistance *= DrawDistance;
|
||||
|
||||
for (int y = startY; y < endY; y++)
|
||||
for (int y = startY, py = startY * limitX; y < endY; y++, py += limitX)
|
||||
{
|
||||
distysq = y - testposY;
|
||||
distysq *= distysq;
|
||||
distlimitsq = DrawDistance - distysq;
|
||||
for (int x = startX; x < endX; x++)
|
||||
{
|
||||
if (pups.GetByPatch(x, y))
|
||||
int indx = x + py;
|
||||
if (pups.GetByPatch(indx))
|
||||
{
|
||||
distxsq = x - testposX;
|
||||
distxsq *= distxsq;
|
||||
if (distxsq < distlimitsq)
|
||||
{
|
||||
pups.SetByPatch(x, y, false);
|
||||
pups.SetFalseByPatch(x + py);
|
||||
ret.Add(new PatchesToSend(x, y, distxsq + distysq));
|
||||
if (npatchs++ > 1024)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user