aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs5
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEventQueue.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs16
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs146
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs1
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs30
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs154
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainChannel.cs278
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainCompressor.cs944
13 files changed, 1276 insertions, 338 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 1949a90..966916a 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -72,12 +72,11 @@ namespace OpenSim.Region.Framework.Interfaces
72 72
73 void EnableChildAgent(ScenePresence agent, GridRegion region); 73 void EnableChildAgent(ScenePresence agent, GridRegion region);
74 74
75 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos); 75 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos);
76 76
77 void Cross(SceneObjectGroup sog, Vector3 position, bool silent); 77 void Cross(SceneObjectGroup sog, Vector3 position, bool silent);
78 78
79 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); 79 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version);
80
81 } 80 }
82 81
83 public interface IUserAgentVerificationModule 82 public interface IUserAgentVerificationModule
diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
index 3780ece..dfc269e 100644
--- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
@@ -39,16 +39,17 @@ namespace OpenSim.Region.Framework.Interfaces
39 39
40 // These are required to decouple Scenes from EventQueueHelper 40 // These are required to decouple Scenes from EventQueueHelper
41 void DisableSimulator(ulong handle, UUID avatarID); 41 void DisableSimulator(ulong handle, UUID avatarID);
42 void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID); 42 void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY);
43 void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, 43 void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint,
44 string capsPath); 44 string capsPath, ulong regionHandle, int regionSizeX, int regionSizeY);
45 void TeleportFinishEvent(ulong regionHandle, byte simAccess, 45 void TeleportFinishEvent(ulong regionHandle, byte simAccess,
46 IPEndPoint regionExternalEndPoint, 46 IPEndPoint regionExternalEndPoint,
47 uint locationID, uint flags, string capsURL, 47 uint locationID, uint flags, string capsURL,
48 UUID agentID); 48 UUID agentID, int regionSizeX, int regionSizeY);
49 void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, 49 void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
50 IPEndPoint newRegionExternalEndPoint, 50 IPEndPoint newRegionExternalEndPoint,
51 string capsURL, UUID avatarID, UUID sessionID); 51 string capsURL, UUID avatarID, UUID sessionID,
52 int regionSizeX, int regionSizeY);
52 void ChatterboxInvitation(UUID sessionID, string sessionName, 53 void ChatterboxInvitation(UUID sessionID, string sessionName,
53 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, 54 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
54 uint timeStamp, bool offline, int parentEstateID, Vector3 position, 55 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
index 085b5ca..8948f04 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
@@ -68,13 +68,22 @@ namespace OpenSim.Region.Framework.Interfaces
68 /// </summary> 68 /// </summary>
69 /// <param name="ter">HeightField data</param> 69 /// <param name="ter">HeightField data</param>
70 /// <param name="regionID">region UUID</param> 70 /// <param name="regionID">region UUID</param>
71 void StoreTerrain(TerrainData terrain, UUID regionID);
72
73 // Legacy version kept for downward compabibility
71 void StoreTerrain(double[,] terrain, UUID regionID); 74 void StoreTerrain(double[,] terrain, UUID regionID);
72 75
73 /// <summary> 76 /// <summary>
74 /// Load the latest terrain revision from region storage 77 /// Load the latest terrain revision from region storage
75 /// </summary> 78 /// </summary>
76 /// <param name="regionID">the region UUID</param> 79 /// <param name="regionID">the region UUID</param>
80 /// <param name="sizeX">the X dimension of the region being filled</param>
81 /// <param name="sizeY">the Y dimension of the region being filled</param>
82 /// <param name="sizeZ">the Z dimension of the region being filled</param>
77 /// <returns>Heightfield data</returns> 83 /// <returns>Heightfield data</returns>
84 TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
85
86 // Legacy version kept for downward compabibility
78 double[,] LoadTerrain(UUID regionID); 87 double[,] LoadTerrain(UUID regionID);
79 88
80 void StoreLandObject(ILandObject Parcel); 89 void StoreLandObject(ILandObject Parcel);
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index 3787ca0..917b5d1 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -79,13 +79,22 @@ namespace OpenSim.Region.Framework.Interfaces
79 /// </summary> 79 /// </summary>
80 /// <param name="ter">HeightField data</param> 80 /// <param name="ter">HeightField data</param>
81 /// <param name="regionID">region UUID</param> 81 /// <param name="regionID">region UUID</param>
82 void StoreTerrain(TerrainData terrain, UUID regionID);
83
84 // Legacy version kept for downward compabibility
82 void StoreTerrain(double[,] terrain, UUID regionID); 85 void StoreTerrain(double[,] terrain, UUID regionID);
83 86
84 /// <summary> 87 /// <summary>
85 /// Load the latest terrain revision from region storage 88 /// Load the latest terrain revision from region storage
86 /// </summary> 89 /// </summary>
87 /// <param name="regionID">the region UUID</param> 90 /// <param name="regionID">the region UUID</param>
91 /// <param name="pSizeX">the X dimension of the terrain being filled</param>
92 /// <param name="pSizeY">the Y dimension of the terrain being filled</param>
93 /// <param name="pSizeZ">the Z dimension of the terrain being filled</param>
88 /// <returns>Heightfield data</returns> 94 /// <returns>Heightfield data</returns>
95 TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
96
97 // Legacy version kept for downward compabibility
89 double[,] LoadTerrain(UUID regionID); 98 double[,] LoadTerrain(UUID regionID);
90 99
91 void StoreLandObject(ILandObject Parcel); 100 void StoreLandObject(ILandObject Parcel);
@@ -135,4 +144,5 @@ namespace OpenSim.Region.Framework.Interfaces
135 144
136 void Shutdown(); 145 void Shutdown();
137 } 146 }
147
138} 148}
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
index e467701..469bd31 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
@@ -25,13 +25,22 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using OpenSim.Framework;
29
28namespace OpenSim.Region.Framework.Interfaces 30namespace OpenSim.Region.Framework.Interfaces
29{ 31{
30 public interface ITerrainChannel 32 public interface ITerrainChannel
31 { 33 {
32 int Height { get; } 34 int Width { get;} // X dimension
35 int Height { get;} // Y dimension
36 int Altitude { get;} // Z dimension
37
33 double this[int x, int y] { get; set; } 38 double this[int x, int y] { get; set; }
34 int Width { get; } 39
40 float GetHeightAtXYZ(float x, float y, float z);
41
42 // Return the packaged terrain data for passing into lower levels of communication
43 TerrainData GetTerrainData();
35 44
36 /// <summary> 45 /// <summary>
37 /// Squash the entire heightmap into a single dimensioned array 46 /// Squash the entire heightmap into a single dimensioned array
@@ -40,7 +49,10 @@ namespace OpenSim.Region.Framework.Interfaces
40 float[] GetFloatsSerialised(); 49 float[] GetFloatsSerialised();
41 50
42 double[,] GetDoubles(); 51 double[,] GetDoubles();
52
53 // Check if a location has been updated. Clears the taint flag as a side effect.
43 bool Tainted(int x, int y); 54 bool Tainted(int x, int y);
55
44 ITerrainChannel MakeCopy(); 56 ITerrainChannel MakeCopy();
45 string SaveToXmlString(); 57 string SaveToXmlString();
46 void LoadFromXmlString(string data); 58 void LoadFromXmlString(string data);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 65536db..9ae8612 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -46,8 +46,8 @@ namespace OpenSim.Region.Framework.Scenes
46{ 46{
47 public partial class Scene 47 public partial class Scene
48 { 48 {
49 private static readonly ILog m_log 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly string LogHeader = "[SCENE INVENTORY]";
51 51
52 /// <summary> 52 /// <summary>
53 /// Allows asynchronous derezzing of objects from the scene into a client's inventory. 53 /// Allows asynchronous derezzing of objects from the scene into a client's inventory.
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 7772f94..d8a4ed1 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1033,7 +1033,7 @@ namespace OpenSim.Region.Framework.Scenes
1033 1033
1034 BordersLocked = true; 1034 BordersLocked = true;
1035 Border northBorder = new Border(); 1035 Border northBorder = new Border();
1036 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<--- 1036 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (float)RegionInfo.RegionSizeY); //<---
1037 northBorder.CrossDirection = Cardinals.N; 1037 northBorder.CrossDirection = Cardinals.N;
1038 NorthBorders.Add(northBorder); 1038 NorthBorders.Add(northBorder);
1039 1039
@@ -1043,7 +1043,7 @@ namespace OpenSim.Region.Framework.Scenes
1043 SouthBorders.Add(southBorder); 1043 SouthBorders.Add(southBorder);
1044 1044
1045 Border eastBorder = new Border(); 1045 Border eastBorder = new Border();
1046 eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<--- 1046 eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (float)RegionInfo.RegionSizeY); //<---
1047 eastBorder.CrossDirection = Cardinals.E; 1047 eastBorder.CrossDirection = Cardinals.E;
1048 EastBorders.Add(eastBorder); 1048 EastBorders.Add(eastBorder);
1049 1049
@@ -1099,8 +1099,9 @@ namespace OpenSim.Region.Framework.Scenes
1099 /// <returns>True after all operations complete, throws exceptions otherwise.</returns> 1099 /// <returns>True after all operations complete, throws exceptions otherwise.</returns>
1100 public override void OtherRegionUp(GridRegion otherRegion) 1100 public override void OtherRegionUp(GridRegion otherRegion)
1101 { 1101 {
1102 uint xcell = (uint)((int)otherRegion.RegionLocX / (int)Constants.RegionSize); 1102 uint xcell = Util.WorldToRegionLoc((uint)otherRegion.RegionLocX);
1103 uint ycell = (uint)((int)otherRegion.RegionLocY / (int)Constants.RegionSize); 1103 uint ycell = Util.WorldToRegionLoc((uint)otherRegion.RegionLocY);
1104
1104 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}", 1105 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}",
1105 // RegionInfo.RegionName, otherRegion.RegionName, xcell, ycell); 1106 // RegionInfo.RegionName, otherRegion.RegionName, xcell, ycell);
1106 1107
@@ -1172,46 +1173,6 @@ namespace OpenSim.Region.Framework.Scenes
1172 return found; 1173 return found;
1173 } 1174 }
1174 1175
1175 /// <summary>
1176 /// Checks whether this region has a neighbour in the given direction.
1177 /// </summary>
1178 /// <param name="car"></param>
1179 /// <param name="fix"></param>
1180 /// <returns>
1181 /// An integer which represents a compass point. N == 1, going clockwise until we reach NW == 8.
1182 /// Returns a positive integer if there is a region in that direction, a negative integer if not.
1183 /// </returns>
1184 public int HaveNeighbor(Cardinals car, ref int[] fix)
1185 {
1186 uint neighbourx = RegionInfo.RegionLocX;
1187 uint neighboury = RegionInfo.RegionLocY;
1188
1189 int dir = (int)car;
1190
1191 if (dir > 1 && dir < 5) //Heading East
1192 neighbourx++;
1193 else if (dir > 5) // Heading West
1194 neighbourx--;
1195
1196 if (dir < 3 || dir == 8) // Heading North
1197 neighboury++;
1198 else if (dir > 3 && dir < 7) // Heading Sout
1199 neighboury--;
1200
1201 int x = (int)(neighbourx * Constants.RegionSize);
1202 int y = (int)(neighboury * Constants.RegionSize);
1203 GridRegion neighbourRegion = GridService.GetRegionByPosition(RegionInfo.ScopeID, x, y);
1204
1205 if (neighbourRegion == null)
1206 {
1207 fix[0] = (int)(RegionInfo.RegionLocX - neighbourx);
1208 fix[1] = (int)(RegionInfo.RegionLocY - neighboury);
1209 return dir * (-1);
1210 }
1211 else
1212 return dir;
1213 }
1214
1215 // Alias IncomingHelloNeighbour OtherRegionUp, for now 1176 // Alias IncomingHelloNeighbour OtherRegionUp, for now
1216 public GridRegion IncomingHelloNeighbour(RegionInfo neighbour) 1177 public GridRegion IncomingHelloNeighbour(RegionInfo neighbour)
1217 { 1178 {
@@ -1894,7 +1855,7 @@ namespace OpenSim.Region.Framework.Scenes
1894 { 1855 {
1895 try 1856 try
1896 { 1857 {
1897 double[,] map = SimulationDataService.LoadTerrain(RegionInfo.RegionID); 1858 TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
1898 if (map == null) 1859 if (map == null)
1899 { 1860 {
1900 // This should be in the Terrain module, but it isn't because 1861 // This should be in the Terrain module, but it isn't because
@@ -1905,7 +1866,7 @@ namespace OpenSim.Region.Framework.Scenes
1905 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 1866 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
1906 1867
1907 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); 1868 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain);
1908 Heightmap = new TerrainChannel(m_InitialTerrain); 1869 Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
1909 1870
1910 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 1871 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
1911 } 1872 }
@@ -1953,6 +1914,11 @@ namespace OpenSim.Region.Framework.Scenes
1953 1914
1954 GridRegion region = new GridRegion(RegionInfo); 1915 GridRegion region = new GridRegion(RegionInfo);
1955 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 1916 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
1917 m_log.DebugFormat("{0} RegisterRegionWithGrid. name={1},id={2},loc=<{3},{4}>,size=<{5},{6}>",
1918 LogHeader, m_regionName,
1919 RegionInfo.RegionID,
1920 RegionInfo.RegionLocX, RegionInfo.RegionLocY,
1921 RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
1956 if (error != String.Empty) 1922 if (error != String.Empty)
1957 throw new Exception(error); 1923 throw new Exception(error);
1958 } 1924 }
@@ -2478,6 +2444,23 @@ namespace OpenSim.Region.Framework.Scenes
2478 EntityTransferModule.Cross(grp, attemptedPosition, silent); 2444 EntityTransferModule.Cross(grp, attemptedPosition, silent);
2479 } 2445 }
2480 2446
2447 // Simple test to see if a position is in the current region.
2448 // Resuming the position is relative to the region so anything outside its bounds.
2449 // Return 'true' if position inside region.
2450 public bool PositionIsInCurrentRegion(Vector3 pos)
2451 {
2452 bool ret = true;
2453 int xx = (int)Math.Floor(pos.X);
2454 int yy = (int)Math.Floor(pos.Y);
2455 if (xx < 0
2456 || xx >= RegionInfo.RegionSizeX
2457 || yy < 0
2458 || yy >= RegionInfo.RegionSizeY)
2459 ret = false;
2460 return ret;
2461
2462 }
2463
2481 public Border GetCrossedBorder(Vector3 position, Cardinals gridline) 2464 public Border GetCrossedBorder(Vector3 position, Cardinals gridline)
2482 { 2465 {
2483 if (BordersLocked) 2466 if (BordersLocked)
@@ -3895,6 +3878,7 @@ namespace OpenSim.Region.Framework.Scenes
3895 { 3878 {
3896 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E); 3879 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
3897 acd.startpos.X = crossedBorder.BorderLine.Z - 1; 3880 acd.startpos.X = crossedBorder.BorderLine.Z - 1;
3881 m_log.DebugFormat("{0} NewUserConnection Adjusted border E. startpos={1}", LogHeader, acd.startpos);
3898 } 3882 }
3899 3883
3900 if (TestBorderCross(acd.startpos, Cardinals.N)) 3884 if (TestBorderCross(acd.startpos, Cardinals.N))
@@ -3994,12 +3978,12 @@ namespace OpenSim.Region.Framework.Scenes
3994 { 3978 {
3995 if (posX < 0) 3979 if (posX < 0)
3996 posX = 0; 3980 posX = 0;
3997 else if (posX >= 256) 3981 else if (posX >= (float)RegionInfo.RegionSizeX)
3998 posX = 255.999f; 3982 posX = (float)RegionInfo.RegionSizeX - 0.001f;
3999 if (posY < 0) 3983 if (posY < 0)
4000 posY = 0; 3984 posY = 0;
4001 else if (posY >= 256) 3985 else if (posY >= (float)RegionInfo.RegionSizeY)
4002 posY = 255.999f; 3986 posY = (float)RegionInfo.RegionSizeY - 0.001f;
4003 3987
4004 reason = String.Empty; 3988 reason = String.Empty;
4005 if (Permissions.IsGod(agentID)) 3989 if (Permissions.IsGod(agentID))
@@ -4293,7 +4277,7 @@ namespace OpenSim.Region.Framework.Scenes
4293 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4277 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4294 4278
4295 // TODO: This check should probably be in QueryAccess(). 4279 // TODO: This check should probably be in QueryAccess().
4296 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4280 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2);
4297 if (nearestParcel == null) 4281 if (nearestParcel == null)
4298 { 4282 {
4299 m_log.InfoFormat( 4283 m_log.InfoFormat(
@@ -4600,44 +4584,6 @@ namespace OpenSim.Region.Framework.Scenes
4600 ScenePresence sp = GetScenePresence(remoteClient.AgentId); 4584 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4601 if (sp != null) 4585 if (sp != null)
4602 { 4586 {
4603 uint regionX = RegionInfo.RegionLocX;
4604 uint regionY = RegionInfo.RegionLocY;
4605
4606 Utils.LongToUInts(regionHandle, out regionX, out regionY);
4607
4608 int shiftx = (int) regionX - (int) RegionInfo.RegionLocX * (int)Constants.RegionSize;
4609 int shifty = (int) regionY - (int) RegionInfo.RegionLocY * (int)Constants.RegionSize;
4610
4611 position.X += shiftx;
4612 position.Y += shifty;
4613
4614 bool result = false;
4615
4616 if (TestBorderCross(position,Cardinals.N))
4617 result = true;
4618
4619 if (TestBorderCross(position, Cardinals.S))
4620 result = true;
4621
4622 if (TestBorderCross(position, Cardinals.E))
4623 result = true;
4624
4625 if (TestBorderCross(position, Cardinals.W))
4626 result = true;
4627
4628 // bordercross if position is outside of region
4629
4630 if (!result)
4631 {
4632 regionHandle = RegionInfo.RegionHandle;
4633 }
4634 else
4635 {
4636 // not in this region, undo the shift!
4637 position.X -= shiftx;
4638 position.Y -= shifty;
4639 }
4640
4641 if (EntityTransferModule != null) 4587 if (EntityTransferModule != null)
4642 { 4588 {
4643 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags); 4589 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
@@ -4817,7 +4763,7 @@ namespace OpenSim.Region.Framework.Scenes
4817 else 4763 else
4818 { 4764 {
4819 4765
4820 if (pos.X > 0f && pos.X < Constants.RegionSize && pos.Y > 0f && pos.Y < Constants.RegionSize) 4766 if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY)
4821 { 4767 {
4822 // The only time parcel != null when an object is inside a region is when 4768 // The only time parcel != null when an object is inside a region is when
4823 // there is nothing behind the landchannel. IE, no land plugin loaded. 4769 // there is nothing behind the landchannel. IE, no land plugin loaded.
@@ -5478,7 +5424,7 @@ namespace OpenSim.Region.Framework.Scenes
5478 { 5424 {
5479 Vector3 unitDirection = Vector3.Normalize(direction); 5425 Vector3 unitDirection = Vector3.Normalize(direction);
5480 //Making distance to search go through some sane limit of distance 5426 //Making distance to search go through some sane limit of distance
5481 for (float distance = 0; distance < Constants.RegionSize * 2; distance += .5f) 5427 for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f)
5482 { 5428 {
5483 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance)); 5429 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance));
5484 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) 5430 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y))
@@ -5532,9 +5478,9 @@ namespace OpenSim.Region.Framework.Scenes
5532 int count = 0; 5478 int count = 0;
5533 int avgx = 0; 5479 int avgx = 0;
5534 int avgy = 0; 5480 int avgy = 0;
5535 for (int x = 0; x < Constants.RegionSize; x++) 5481 for (int x = 0; x < RegionInfo.RegionSizeX; x++)
5536 { 5482 {
5537 for (int y = 0; y < Constants.RegionSize; y++) 5483 for (int y = 0; y < RegionInfo.RegionSizeY; y++)
5538 { 5484 {
5539 //Just keep a running average as we check if all the points are inside or not 5485 //Just keep a running average as we check if all the points are inside or not
5540 if (parcel.ContainsPoint(x, y)) 5486 if (parcel.ContainsPoint(x, y))
@@ -5558,31 +5504,33 @@ namespace OpenSim.Region.Framework.Scenes
5558 5504
5559 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) 5505 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar)
5560 { 5506 {
5561 float xdistance = avatar.AbsolutePosition.X < Constants.RegionSize / 2 ? avatar.AbsolutePosition.X : Constants.RegionSize - avatar.AbsolutePosition.X; 5507 float xdistance = avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2
5562 float ydistance = avatar.AbsolutePosition.Y < Constants.RegionSize / 2 ? avatar.AbsolutePosition.Y : Constants.RegionSize - avatar.AbsolutePosition.Y; 5508 ? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X;
5509 float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2
5510 ? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y;
5563 5511
5564 //find out what vertical edge to go to 5512 //find out what vertical edge to go to
5565 if (xdistance < ydistance) 5513 if (xdistance < ydistance)
5566 { 5514 {
5567 if (avatar.AbsolutePosition.X < Constants.RegionSize / 2) 5515 if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2)
5568 { 5516 {
5569 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y); 5517 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y);
5570 } 5518 }
5571 else 5519 else
5572 { 5520 {
5573 return GetPositionAtAvatarHeightOrGroundHeight(avatar, Constants.RegionSize, avatar.AbsolutePosition.Y); 5521 return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y);
5574 } 5522 }
5575 } 5523 }
5576 //find out what horizontal edge to go to 5524 //find out what horizontal edge to go to
5577 else 5525 else
5578 { 5526 {
5579 if (avatar.AbsolutePosition.Y < Constants.RegionSize / 2) 5527 if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2)
5580 { 5528 {
5581 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f); 5529 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f);
5582 } 5530 }
5583 else 5531 else
5584 { 5532 {
5585 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, Constants.RegionSize); 5533 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY);
5586 } 5534 }
5587 } 5535 }
5588 } 5536 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 4f04706..b059ecf 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -43,6 +43,7 @@ namespace OpenSim.Region.Framework.Scenes
43 public abstract class SceneBase : IScene 43 public abstract class SceneBase : IScene
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 private static readonly string LogHeader = "[SCENE]";
46 47
47 #region Events 48 #region Events
48 49
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 77889fa..c873e40 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -92,7 +92,7 @@ namespace OpenSim.Region.Framework.Scenes
92 { 92 {
93 m_log.DebugFormat( 93 m_log.DebugFormat(
94 "[SCENE COMMUNICATION SERVICE]: Region {0} successfully informed neighbour {1} at {2}-{3} that it is up", 94 "[SCENE COMMUNICATION SERVICE]: Region {0} successfully informed neighbour {1} at {2}-{3} that it is up",
95 m_scene.Name, neighbour.RegionName, x / Constants.RegionSize, y / Constants.RegionSize); 95 m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
96 96
97 m_scene.EventManager.TriggerOnRegionUp(neighbour); 97 m_scene.EventManager.TriggerOnRegionUp(neighbour);
98 } 98 }
@@ -100,7 +100,7 @@ namespace OpenSim.Region.Framework.Scenes
100 { 100 {
101 m_log.WarnFormat( 101 m_log.WarnFormat(
102 "[SCENE COMMUNICATION SERVICE]: Region {0} failed to inform neighbour at {1}-{2} that it is up.", 102 "[SCENE COMMUNICATION SERVICE]: Region {0} failed to inform neighbour at {1}-{2} that it is up.",
103 m_scene.Name, x / Constants.RegionSize, y / Constants.RegionSize); 103 m_scene.Name, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
104 } 104 }
105 } 105 }
106 106
@@ -166,7 +166,7 @@ namespace OpenSim.Region.Framework.Scenes
166 // we only want to send one update to each simulator; the simulator will 166 // we only want to send one update to each simulator; the simulator will
167 // hand it off to the regions where a child agent exists, this does assume 167 // hand it off to the regions where a child agent exists, this does assume
168 // that the region position is cached or performance will degrade 168 // that the region position is cached or performance will degrade
169 Utils.LongToUInts(regionHandle, out x, out y); 169 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
170 GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y); 170 GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
171 if (dest == null) 171 if (dest == null)
172 continue; 172 continue;
@@ -203,7 +203,7 @@ namespace OpenSim.Region.Framework.Scenes
203 203
204 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); 204 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
205 uint x = 0, y = 0; 205 uint x = 0, y = 0;
206 Utils.LongToUInts(regionHandle, out x, out y); 206 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
207 207
208 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 208 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
209 209
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index a2e4417..44c476c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -331,7 +331,7 @@ namespace OpenSim.Region.Framework.Scenes
331 { 331 {
332 get 332 get
333 { 333 {
334 Vector3 minScale = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionSize); 334 Vector3 minScale = new Vector3(Constants.MaximumRegionSize, Constants.MaximumRegionSize, Constants.MaximumRegionSize);
335 Vector3 maxScale = Vector3.Zero; 335 Vector3 maxScale = Vector3.Zero;
336 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 336 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
337 337
@@ -463,8 +463,6 @@ namespace OpenSim.Region.Framework.Scenes
463 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 463 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
464 { 464 {
465 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 465 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
466 uint x = 0;
467 uint y = 0;
468 string version = String.Empty; 466 string version = String.Empty;
469 Vector3 newpos = Vector3.Zero; 467 Vector3 newpos = Vector3.Zero;
470 OpenSim.Services.Interfaces.GridRegion destination = null; 468 OpenSim.Services.Interfaces.GridRegion destination = null;
@@ -484,7 +482,7 @@ namespace OpenSim.Region.Framework.Scenes
484 482
485 // We set the avatar position as being the object 483 // We set the avatar position as being the object
486 // position to get the region to send to 484 // position to get the region to send to
487 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null) 485 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out version, out newpos)) == null)
488 { 486 {
489 canCross = false; 487 canCross = false;
490 break; 488 break;
@@ -519,14 +517,14 @@ namespace OpenSim.Region.Framework.Scenes
519 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 517 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
520 518
521 // Normalize 519 // Normalize
522 if (val.X >= Constants.RegionSize) 520 if (val.X >= m_scene.RegionInfo.RegionSizeX)
523 val.X -= Constants.RegionSize; 521 val.X -= m_scene.RegionInfo.RegionSizeX;
524 if (val.Y >= Constants.RegionSize) 522 if (val.Y >= m_scene.RegionInfo.RegionSizeY)
525 val.Y -= Constants.RegionSize; 523 val.Y -= m_scene.RegionInfo.RegionSizeY;
526 if (val.X < 0) 524 if (val.X < 0)
527 val.X += Constants.RegionSize; 525 val.X += m_scene.RegionInfo.RegionSizeX;
528 if (val.Y < 0) 526 if (val.Y < 0)
529 val.Y += Constants.RegionSize; 527 val.Y += m_scene.RegionInfo.RegionSizeY;
530 528
531 // If it's deleted, crossing was successful 529 // If it's deleted, crossing was successful
532 if (IsDeleted) 530 if (IsDeleted)
@@ -574,9 +572,9 @@ namespace OpenSim.Region.Framework.Scenes
574 } 572 }
575 } 573 }
576 Vector3 oldp = AbsolutePosition; 574 Vector3 oldp = AbsolutePosition;
577 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f); 575 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)m_scene.RegionInfo.RegionSizeX - 0.5f);
578 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f); 576 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)m_scene.RegionInfo.RegionSizeY - 0.5f);
579 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f); 577 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, Constants.RegionHeight);
580 } 578 }
581 } 579 }
582 580
@@ -993,9 +991,9 @@ namespace OpenSim.Region.Framework.Scenes
993 maxX = -256f; 991 maxX = -256f;
994 maxY = -256f; 992 maxY = -256f;
995 maxZ = -256f; 993 maxZ = -256f;
996 minX = 256f; 994 minX = 10000f;
997 minY = 256f; 995 minY = 10000f;
998 minZ = 8192f; 996 minZ = 10000f;
999 997
1000 SceneObjectPart[] parts = m_parts.GetArray(); 998 SceneObjectPart[] parts = m_parts.GetArray();
1001 for (int i = 0; i < parts.Length; i++) 999 for (int i = 0; i < parts.Length; i++)
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cf98ef2..a98baea 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -76,6 +76,7 @@ namespace OpenSim.Region.Framework.Scenes
76 public class ScenePresence : EntityBase, IScenePresence 76 public class ScenePresence : EntityBase, IScenePresence
77 { 77 {
78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
79 private static readonly String LogHeader = "[SCENE PRESENCE]";
79 80
80// ~ScenePresence() 81// ~ScenePresence()
81// { 82// {
@@ -749,9 +750,8 @@ namespace OpenSim.Region.Framework.Scenes
749 foreach (ulong handle in seeds.Keys) 750 foreach (ulong handle in seeds.Keys)
750 { 751 {
751 uint x, y; 752 uint x, y;
752 Utils.LongToUInts(handle, out x, out y); 753 Util.RegionHandleToRegionLoc(handle, out x, out y);
753 x = x / Constants.RegionSize; 754
754 y = y / Constants.RegionSize;
755 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY)) 755 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
756 { 756 {
757 old.Add(handle); 757 old.Add(handle);
@@ -773,9 +773,7 @@ namespace OpenSim.Region.Framework.Scenes
773 foreach (KeyValuePair<ulong, string> kvp in KnownRegions) 773 foreach (KeyValuePair<ulong, string> kvp in KnownRegions)
774 { 774 {
775 uint x, y; 775 uint x, y;
776 Utils.LongToUInts(kvp.Key, out x, out y); 776 Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
777 x = x / Constants.RegionSize;
778 y = y / Constants.RegionSize;
779 m_log.Info(" >> "+x+", "+y+": "+kvp.Value); 777 m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
780 } 778 }
781 } 779 }
@@ -1109,7 +1107,7 @@ namespace OpenSim.Region.Framework.Scenes
1109 1107
1110 float posZLimit = 0; 1108 float posZLimit = 0;
1111 1109
1112 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 1110 if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY)
1113 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1111 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
1114 1112
1115 float newPosZ = posZLimit + localAVHeight / 2; 1113 float newPosZ = posZLimit + localAVHeight / 2;
@@ -2362,7 +2360,7 @@ namespace OpenSim.Region.Framework.Scenes
2362 if (regionCombinerModule != null) 2360 if (regionCombinerModule != null)
2363 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); 2361 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
2364 else 2362 else
2365 regionSize = new Vector2(Constants.RegionSize); 2363 regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY);
2366 2364
2367 if (pos.X < 0 || pos.X >= regionSize.X 2365 if (pos.X < 0 || pos.X >= regionSize.X
2368 || pos.Y < 0 || pos.Y >= regionSize.Y 2366 || pos.Y < 0 || pos.Y >= regionSize.Y
@@ -2380,8 +2378,8 @@ namespace OpenSim.Region.Framework.Scenes
2380// } 2378// }
2381 2379
2382 // Get terrain height for sub-region in a megaregion if necessary 2380 // Get terrain height for sub-region in a megaregion if necessary
2383 int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X); 2381 int X = (int)((m_scene.RegionInfo.WorldLocX) + pos.X);
2384 int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y); 2382 int Y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y);
2385 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y); 2383 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y);
2386 // If X and Y is NaN, target_region will be null 2384 // If X and Y is NaN, target_region will be null
2387 if (target_region == null) 2385 if (target_region == null)
@@ -2392,7 +2390,7 @@ namespace OpenSim.Region.Framework.Scenes
2392 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene)) 2390 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
2393 targetScene = m_scene; 2391 targetScene = m_scene;
2394 2392
2395 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)]; 2393 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
2396 pos.Z = Math.Max(terrainHeight, pos.Z); 2394 pos.Z = Math.Max(terrainHeight, pos.Z);
2397 2395
2398 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 2396 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -3427,10 +3425,14 @@ namespace OpenSim.Region.Framework.Scenes
3427 if (!IsInTransit) 3425 if (!IsInTransit)
3428 { 3426 {
3429 Vector3 pos2 = AbsolutePosition; 3427 Vector3 pos2 = AbsolutePosition;
3428 Vector3 origPosition = pos2;
3430 Vector3 vel = Velocity; 3429 Vector3 vel = Velocity;
3431 int neighbor = 0; 3430 int neighbor = 0;
3432 int[] fix = new int[2]; 3431 int[] fix = new int[2];
3433 3432
3433 // Compute the avatar position in the next physics tick.
3434 // If the avatar will be crossing, we force the crossing to happen now
3435 // in the hope that this will make the avatar movement smoother when crossing.
3434 float timeStep = 0.1f; 3436 float timeStep = 0.1f;
3435 pos2.X = pos2.X + (vel.X * timeStep); 3437 pos2.X = pos2.X + (vel.X * timeStep);
3436 pos2.Y = pos2.Y + (vel.Y * timeStep); 3438 pos2.Y = pos2.Y + (vel.Y * timeStep);
@@ -3438,111 +3440,44 @@ namespace OpenSim.Region.Framework.Scenes
3438 3440
3439 if (!IsInTransit) 3441 if (!IsInTransit)
3440 { 3442 {
3441// m_log.DebugFormat( 3443 if (!m_scene.PositionIsInCurrentRegion(pos2))
3442// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3443// pos2, Name, Scene.Name);
3444
3445 // Checks if where it's headed exists a region
3446 bool needsTransit = false;
3447 if (m_scene.TestBorderCross(pos2, Cardinals.W))
3448 { 3444 {
3449 if (m_scene.TestBorderCross(pos2, Cardinals.S)) 3445 m_log.DebugFormat("{0} CheckForBorderCrossing: position outside region. {1} in {2} at pos {3}",
3450 { 3446 LogHeader, Name, Scene.Name, pos2);
3451 needsTransit = true; 3447
3452 neighbor = m_scene.HaveNeighbor(Cardinals.SW, ref fix); 3448 // Disconnect from the current region
3453 } 3449 bool isFlying = Flying;
3454 else if (m_scene.TestBorderCross(pos2, Cardinals.N)) 3450 RemoveFromPhysicalScene();
3451 // pos2 is the forcasted position so make that the 'current' position so the crossing
3452 // code will move us into the newly addressed region.
3453 m_pos = pos2;
3454 if (CrossToNewRegion())
3455 { 3455 {
3456 needsTransit = true; 3456 AddToPhysicalScene(isFlying);
3457 neighbor = m_scene.HaveNeighbor(Cardinals.NW, ref fix);
3458 } 3457 }
3459 else 3458 else
3460 { 3459 {
3461 needsTransit = true; 3460 // Tried to make crossing happen but it failed.
3462 neighbor = m_scene.HaveNeighbor(Cardinals.W, ref fix);
3463 }
3464 }
3465 else if (m_scene.TestBorderCross(pos2, Cardinals.E))
3466 {
3467 if (m_scene.TestBorderCross(pos2, Cardinals.S))
3468 {
3469 needsTransit = true;
3470 neighbor = m_scene.HaveNeighbor(Cardinals.SE, ref fix);
3471 }
3472 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3473 {
3474 needsTransit = true;
3475 neighbor = m_scene.HaveNeighbor(Cardinals.NE, ref fix);
3476 }
3477 else
3478 {
3479 needsTransit = true;
3480 neighbor = m_scene.HaveNeighbor(Cardinals.E, ref fix);
3481 }
3482 }
3483 else if (m_scene.TestBorderCross(pos2, Cardinals.S))
3484 {
3485 needsTransit = true;
3486 neighbor = m_scene.HaveNeighbor(Cardinals.S, ref fix);
3487 }
3488 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3489 {
3490 needsTransit = true;
3491 neighbor = m_scene.HaveNeighbor(Cardinals.N, ref fix);
3492 }
3493
3494 // Makes sure avatar does not end up outside region
3495 if (neighbor <= 0)
3496 {
3497 if (needsTransit)
3498 {
3499 if (m_requestedSitTargetUUID == UUID.Zero)
3500 {
3501 bool isFlying = Flying;
3502 RemoveFromPhysicalScene();
3503
3504 Vector3 pos = AbsolutePosition;
3505 if (AbsolutePosition.X < 0)
3506 pos.X += Velocity.X * 2;
3507 else if (AbsolutePosition.X > Constants.RegionSize)
3508 pos.X -= Velocity.X * 2;
3509 if (AbsolutePosition.Y < 0)
3510 pos.Y += Velocity.Y * 2;
3511 else if (AbsolutePosition.Y > Constants.RegionSize)
3512 pos.Y -= Velocity.Y * 2;
3513 Velocity = Vector3.Zero;
3514 AbsolutePosition = pos;
3515
3516// m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition);
3517
3518 AddToPhysicalScene(isFlying);
3519 }
3520 }
3521 }
3522 else if (neighbor > 0)
3523 {
3524 if (!CrossToNewRegion())
3525 {
3526 if (m_requestedSitTargetUUID == UUID.Zero) 3461 if (m_requestedSitTargetUUID == UUID.Zero)
3527 { 3462 {
3528 bool isFlying = Flying; 3463 m_log.DebugFormat("{0} CheckForBorderCrossing: Crossing failed. Restoring old position.", LogHeader);
3529 RemoveFromPhysicalScene(); 3464 const float borderFudge = 0.1f;
3530 3465
3531 Vector3 pos = AbsolutePosition; 3466 if (origPosition.X < 0)
3532 if (AbsolutePosition.X < 0) 3467 origPosition.X = borderFudge;
3533 pos.X += Velocity.X * 2; 3468 else if (origPosition.X > (float)m_scene.RegionInfo.RegionSizeX)
3534 else if (AbsolutePosition.X > Constants.RegionSize) 3469 origPosition.X = (float)m_scene.RegionInfo.RegionSizeX - borderFudge;
3535 pos.X -= Velocity.X * 2; 3470 if (origPosition.Y < 0)
3536 if (AbsolutePosition.Y < 0) 3471 origPosition.Y = borderFudge;
3537 pos.Y += Velocity.Y * 2; 3472 else if (origPosition.Y > (float)m_scene.RegionInfo.RegionSizeY)
3538 else if (AbsolutePosition.Y > Constants.RegionSize) 3473 origPosition.Y = (float)m_scene.RegionInfo.RegionSizeY - borderFudge;
3539 pos.Y -= Velocity.Y * 2;
3540 Velocity = Vector3.Zero; 3474 Velocity = Vector3.Zero;
3541 AbsolutePosition = pos; 3475 AbsolutePosition = origPosition;
3542 3476
3543 AddToPhysicalScene(isFlying); 3477 AddToPhysicalScene(isFlying);
3544 } 3478 }
3545 } 3479 }
3480
3546 } 3481 }
3547 } 3482 }
3548 else 3483 else
@@ -3584,7 +3519,7 @@ namespace OpenSim.Region.Framework.Scenes
3584 3519
3585 // Put the child agent back at the center 3520 // Put the child agent back at the center
3586 AbsolutePosition 3521 AbsolutePosition
3587 = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70); 3522 = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
3588 3523
3589 Animator.ResetAnimations(); 3524 Animator.ResetAnimations();
3590 } 3525 }
@@ -3611,9 +3546,7 @@ namespace OpenSim.Region.Framework.Scenes
3611 if (handle != Scene.RegionInfo.RegionHandle) 3546 if (handle != Scene.RegionInfo.RegionHandle)
3612 { 3547 {
3613 uint x, y; 3548 uint x, y;
3614 Utils.LongToUInts(handle, out x, out y); 3549 Util.RegionHandleToRegionLoc(handle, out x, out y);
3615 x = x / Constants.RegionSize;
3616 y = y / Constants.RegionSize;
3617 3550
3618// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); 3551// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
3619// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); 3552// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
@@ -3694,8 +3627,9 @@ namespace OpenSim.Region.Framework.Scenes
3694 return; 3627 return;
3695 3628
3696 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); 3629 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
3697 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; 3630 // Find the distance (in meters) between the two regions
3698 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; 3631 uint shiftx = Util.RegionToWorldLoc(rRegionX - tRegionX);
3632 uint shifty = Util.RegionToWorldLoc(rRegionY - tRegionY);
3699 3633
3700 Vector3 offset = new Vector3(shiftx, shifty, 0f); 3634 Vector3 offset = new Vector3(shiftx, shifty, 0f);
3701 3635
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index c0ca48e..b4b1823 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
@@ -25,14 +25,19 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using OpenSim.Framework;
29using OpenSim.Region.Framework.Interfaces;
30using System; 28using System;
29using System.IO;
31using System.Text; 30using System.Text;
31using System.Reflection;
32using System.Xml; 32using System.Xml;
33using System.IO;
34using System.Xml.Serialization; 33using System.Xml.Serialization;
35 34
35using OpenSim.Data;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38
39using log4net;
40
36namespace OpenSim.Region.Framework.Scenes 41namespace OpenSim.Region.Framework.Scenes
37{ 42{
38 /// <summary> 43 /// <summary>
@@ -40,132 +45,146 @@ namespace OpenSim.Region.Framework.Scenes
40 /// </summary> 45 /// </summary>
41 public class TerrainChannel : ITerrainChannel 46 public class TerrainChannel : ITerrainChannel
42 { 47 {
43 private readonly bool[,] taint; 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 private double[,] map; 49 private static string LogHeader = "[TERRAIN CHANNEL]";
50
51 protected TerrainData m_terrainData;
45 52
53 public int Width { get { return m_terrainData.SizeX; } } // X dimension
54 // Unfortunately, for historical reasons, in this module 'Width' is X and 'Height' is Y
55 public int Height { get { return m_terrainData.SizeY; } } // Y dimension
56 public int Altitude { get { return m_terrainData.SizeZ; } } // Y dimension
57
58 // Default, not-often-used builder
46 public TerrainChannel() 59 public TerrainChannel()
47 { 60 {
48 map = new double[Constants.RegionSize, Constants.RegionSize]; 61 m_terrainData = new HeightmapTerrainData((int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
49 taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16]; 62 FlatLand();
50 63 // PinHeadIsland();
51 PinHeadIsland();
52 } 64 }
53 65
54 public TerrainChannel(String type) 66 // Create terrain of given size
67 public TerrainChannel(int pX, int pY)
55 { 68 {
56 map = new double[Constants.RegionSize, Constants.RegionSize]; 69 m_terrainData = new HeightmapTerrainData(pX, pY, (int)Constants.RegionHeight);
57 taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16]; 70 }
58 71
72 // Create terrain of specified size and initialize with specified terrain.
73 // TODO: join this with the terrain initializers.
74 public TerrainChannel(String type, int pX, int pY, int pZ)
75 {
76 m_terrainData = new HeightmapTerrainData(pX, pY, pZ);
59 if (type.Equals("flat")) 77 if (type.Equals("flat"))
60 FlatLand(); 78 FlatLand();
61 else 79 else
62 PinHeadIsland(); 80 PinHeadIsland();
63 } 81 }
64 82
65 public TerrainChannel(double[,] import) 83 // Create channel passed a heightmap and expected dimensions of the region.
84 // The heightmap might not fit the passed size so accomodations must be made.
85 public TerrainChannel(double[,] pM, int pSizeX, int pSizeY, int pAltitude)
66 { 86 {
67 map = import; 87 int hmSizeX = pM.GetLength(0);
68 taint = new bool[import.GetLength(0),import.GetLength(1)]; 88 int hmSizeY = pM.GetLength(1);
69 }
70 89
71 public TerrainChannel(bool createMap) 90 m_terrainData = new HeightmapTerrainData(pSizeX, pSizeY, pAltitude);
72 { 91
73 if (createMap) 92 for (int xx = 0; xx < pSizeX; xx++)
74 { 93 for (int yy = 0; yy < pSizeY; yy++)
75 map = new double[Constants.RegionSize,Constants.RegionSize]; 94 if (xx > hmSizeX || yy > hmSizeY)
76 taint = new bool[Constants.RegionSize / 16,Constants.RegionSize / 16]; 95 m_terrainData[xx, yy] = TerrainData.DefaultTerrainHeight;
77 } 96 else
97 m_terrainData[xx, yy] = (float)pM[xx, yy];
78 } 98 }
79 99
80 public TerrainChannel(int w, int h) 100 public TerrainChannel(TerrainData pTerrData)
81 { 101 {
82 map = new double[w,h]; 102 m_terrainData = pTerrData;
83 taint = new bool[w / 16,h / 16];
84 } 103 }
85 104
86 #region ITerrainChannel Members 105 #region ITerrainChannel Members
87 106
88 public int Width 107 // ITerrainChannel.MakeCopy()
108 public ITerrainChannel MakeCopy()
89 { 109 {
90 get { return map.GetLength(0); } 110 return this.Copy();
91 } 111 }
92 112
93 public int Height 113 // ITerrainChannel.GetTerrainData()
114 public TerrainData GetTerrainData()
94 { 115 {
95 get { return map.GetLength(1); } 116 return m_terrainData;
96 } 117 }
97 118
98 public ITerrainChannel MakeCopy() 119 // ITerrainChannel.GetFloatsSerialized()
120 // This one dimensional version is ordered so height = map[y*sizeX+x];
121 // DEPRECATED: don't use this function as it does not retain the dimensions of the terrain
122 // and the caller will probably do the wrong thing if the terrain is not the legacy 256x256.
123 public float[] GetFloatsSerialised()
99 { 124 {
100 TerrainChannel copy = new TerrainChannel(false); 125 int points = Width * Height;
101 copy.map = (double[,]) map.Clone(); 126 float[] heights = new float[points];
102 127
103 return copy; 128 int idx = 0;
129 for (int jj = 0; jj < Height; jj++)
130 for (int ii = 0; ii < Width; ii++)
131 {
132 heights[idx++] = m_terrainData[ii, jj];
133 }
134
135 return heights;
104 } 136 }
105 137
106 public float[] GetFloatsSerialised() 138 // ITerrainChannel.GetDoubles()
139 public double[,] GetDoubles()
107 { 140 {
108 // Move the member variables into local variables, calling 141 double[,] heights = new double[Width, Height];
109 // member variables 256*256 times gets expensive
110 int w = Width;
111 int h = Height;
112 float[] heights = new float[w * h];
113 142
114 int i, j; // map coordinates
115 int idx = 0; // index into serialized array 143 int idx = 0; // index into serialized array
116 for (i = 0; i < h; i++) 144 for (int ii = 0; ii < Width; ii++)
117 { 145 {
118 for (j = 0; j < w; j++) 146 for (int jj = 0; jj < Height; jj++)
119 { 147 {
120 heights[idx++] = (float)map[j, i]; 148 heights[ii, jj] = (double)m_terrainData[ii, jj];
149 idx++;
121 } 150 }
122 } 151 }
123 152
124 return heights; 153 return heights;
125 } 154 }
126 155
127 public double[,] GetDoubles() 156 // ITerrainChannel.this[x,y]
128 {
129 return map;
130 }
131
132 public double this[int x, int y] 157 public double this[int x, int y]
133 { 158 {
134 get { return map[x, y]; } 159 get {
160 if (x < 0 || x >= Width || y < 0 || y >= Height)
161 return 0;
162 return (double)m_terrainData[x, y];
163 }
135 set 164 set
136 { 165 {
137 // Will "fix" terrain hole problems. Although not fantastically.
138 if (Double.IsNaN(value) || Double.IsInfinity(value)) 166 if (Double.IsNaN(value) || Double.IsInfinity(value))
139 return; 167 return;
140 168
141 if (map[x, y] != value) 169 m_terrainData[x, y] = (float)value;
142 {
143 taint[x / 16, y / 16] = true;
144 map[x, y] = value;
145 }
146 } 170 }
147 } 171 }
148 172
149 public bool Tainted(int x, int y) 173 // ITerrainChannel.GetHieghtAtXYZ(x, y, z)
174 public float GetHeightAtXYZ(float x, float y, float z)
150 { 175 {
151 if (taint[x / 16, y / 16]) 176 if (x < 0 || x >= Width || y < 0 || y >= Height)
152 { 177 return 0;
153 taint[x / 16, y / 16] = false; 178 return m_terrainData[(int)x, (int)y];
154 return true;
155 }
156 return false;
157 } 179 }
158 180
159 #endregion 181 // ITerrainChannel.Tainted()
160 182 public bool Tainted(int x, int y)
161 public TerrainChannel Copy()
162 { 183 {
163 TerrainChannel copy = new TerrainChannel(false); 184 return m_terrainData.IsTaintedAt(x, y);
164 copy.map = (double[,]) map.Clone();
165
166 return copy;
167 } 185 }
168 186
187 // ITerrainChannel.SaveToXmlString()
169 public string SaveToXmlString() 188 public string SaveToXmlString()
170 { 189 {
171 XmlWriterSettings settings = new XmlWriterSettings(); 190 XmlWriterSettings settings = new XmlWriterSettings();
@@ -181,13 +200,7 @@ namespace OpenSim.Region.Framework.Scenes
181 } 200 }
182 } 201 }
183 202
184 private void WriteXml(XmlWriter writer) 203 // ITerrainChannel.LoadFromXmlString()
185 {
186 writer.WriteStartElement(String.Empty, "TerrainMap", String.Empty);
187 ToXml(writer);
188 writer.WriteEndElement();
189 }
190
191 public void LoadFromXmlString(string data) 204 public void LoadFromXmlString(string data)
192 { 205 {
193 StringReader sr = new StringReader(data); 206 StringReader sr = new StringReader(data);
@@ -199,12 +212,50 @@ namespace OpenSim.Region.Framework.Scenes
199 sr.Close(); 212 sr.Close();
200 } 213 }
201 214
215 #endregion
216
217 public TerrainChannel Copy()
218 {
219 TerrainChannel copy = new TerrainChannel();
220 copy.m_terrainData = m_terrainData.Clone();
221 return copy;
222 }
223
224 private void WriteXml(XmlWriter writer)
225 {
226 if (Width == Constants.RegionSize && Height == Constants.RegionSize)
227 {
228 // Downward compatibility for legacy region terrain maps.
229 // If region is exactly legacy size, return the old format XML.
230 writer.WriteStartElement(String.Empty, "TerrainMap", String.Empty);
231 ToXml(writer);
232 writer.WriteEndElement();
233 }
234 else
235 {
236 // New format XML that includes width and length.
237 writer.WriteStartElement(String.Empty, "TerrainMap2", String.Empty);
238 ToXml2(writer);
239 writer.WriteEndElement();
240 }
241 }
242
202 private void ReadXml(XmlReader reader) 243 private void ReadXml(XmlReader reader)
203 { 244 {
204 reader.ReadStartElement("TerrainMap"); 245 // Check the first element. If legacy element, use the legacy reader.
205 FromXml(reader); 246 if (reader.IsStartElement("TerrainMap"))
247 {
248 reader.ReadStartElement("TerrainMap");
249 FromXml(reader);
250 }
251 else
252 {
253 reader.ReadStartElement("TerrainMap2");
254 FromXml2(reader);
255 }
206 } 256 }
207 257
258 // Write legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
208 private void ToXml(XmlWriter xmlWriter) 259 private void ToXml(XmlWriter xmlWriter)
209 { 260 {
210 float[] mapData = GetFloatsSerialised(); 261 float[] mapData = GetFloatsSerialised();
@@ -218,12 +269,15 @@ namespace OpenSim.Region.Framework.Scenes
218 serializer.Serialize(xmlWriter, buffer); 269 serializer.Serialize(xmlWriter, buffer);
219 } 270 }
220 271
272 // Read legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
221 private void FromXml(XmlReader xmlReader) 273 private void FromXml(XmlReader xmlReader)
222 { 274 {
223 XmlSerializer serializer = new XmlSerializer(typeof(byte[])); 275 XmlSerializer serializer = new XmlSerializer(typeof(byte[]));
224 byte[] dataArray = (byte[])serializer.Deserialize(xmlReader); 276 byte[] dataArray = (byte[])serializer.Deserialize(xmlReader);
225 int index = 0; 277 int index = 0;
226 278
279 m_terrainData = new HeightmapTerrainData(Height, Width, (int)Constants.RegionHeight);
280
227 for (int y = 0; y < Height; y++) 281 for (int y = 0; y < Height; y++)
228 { 282 {
229 for (int x = 0; x < Width; x++) 283 for (int x = 0; x < Width; x++)
@@ -236,35 +290,63 @@ namespace OpenSim.Region.Framework.Scenes
236 } 290 }
237 } 291 }
238 292
293 private class TerrainChannelXMLPackage
294 {
295 public int Version;
296 public int SizeX;
297 public int SizeY;
298 public int SizeZ;
299 public float CompressionFactor;
300 public short[] Map;
301 public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, short[] pMap)
302 {
303 Version = 1;
304 SizeX = pX;
305 SizeY = pY;
306 SizeZ = pZ;
307 CompressionFactor = pCompressionFactor;
308 Map = pMap;
309 }
310 }
311
312 // New terrain serialization format that includes the width and length.
313 private void ToXml2(XmlWriter xmlWriter)
314 {
315 TerrainChannelXMLPackage package = new TerrainChannelXMLPackage(Width, Height, Altitude, m_terrainData.CompressionFactor,
316 m_terrainData.GetCompressedMap());
317 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
318 serializer.Serialize(xmlWriter, package);
319 }
320
321 // New terrain serialization format that includes the width and length.
322 private void FromXml2(XmlReader xmlReader)
323 {
324 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
325 TerrainChannelXMLPackage package = (TerrainChannelXMLPackage)serializer.Deserialize(xmlReader);
326 m_terrainData = new HeightmapTerrainData(package.Map, package.CompressionFactor, package.SizeX, package.SizeY, package.SizeZ);
327 }
328
329 // Fill the heightmap with the center bump terrain
239 private void PinHeadIsland() 330 private void PinHeadIsland()
240 { 331 {
241 int x; 332 for (int x = 0; x < Width; x++)
242 for (x = 0; x < Constants.RegionSize; x++)
243 { 333 {
244 int y; 334 for (int y = 0; y < Height; y++)
245 for (y = 0; y < Constants.RegionSize; y++)
246 { 335 {
247 map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10; 336 m_terrainData[x, y] = (float)TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10;
248 double spherFacA = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 50) * 0.01; 337 float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 50) * 0.01d);
249 double spherFacB = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2.0, Constants.RegionSize / 2.0, 100) * 0.001; 338 float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 100) * 0.001d);
250 if (map[x, y] < spherFacA) 339 if (m_terrainData[x, y]< spherFacA)
251 map[x, y] = spherFacA; 340 m_terrainData[x, y]= spherFacA;
252 if (map[x, y] < spherFacB) 341 if (m_terrainData[x, y]< spherFacB)
253 map[x, y] = spherFacB; 342 m_terrainData[x, y] = spherFacB;
254 } 343 }
255 } 344 }
256 } 345 }
257 346
258 private void FlatLand() 347 private void FlatLand()
259 { 348 {
260 int x; 349 m_terrainData.ClearLand();
261 for (x = 0; x < Constants.RegionSize; x++)
262 {
263 int y;
264 for (y = 0; y < Constants.RegionSize; y++)
265 map[x, y] = 21;
266 }
267 } 350 }
268
269 } 351 }
270} 352}
diff --git a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
new file mode 100644
index 0000000..ced62e2
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
@@ -0,0 +1,944 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/* Freely adapted from the Aurora version of the terrain compressor.
29 * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
30 */
31
32using System;
33using System.Reflection;
34
35using log4net;
36
37using OpenSim.Framework;
38using OpenSim.Region.Framework;
39using OpenSim.Region.Framework.Scenes;
40
41using OpenMetaverse;
42using OpenMetaverse.Packets;
43
44namespace OpenSim.Region.ClientStack.LindenUDP
45{
46 public static class OpenSimTerrainCompressor
47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 private static string LogHeader = "[TERRAIN COMPRESSOR]";
50
51 public const int END_OF_PATCHES = 97;
52
53 private const float OO_SQRT2 = 0.7071067811865475244008443621049f;
54 private const int STRIDE = 264;
55
56 private const int ZERO_CODE = 0x0;
57 private const int ZERO_EOB = 0x2;
58 private const int POSITIVE_VALUE = 0x6;
59 private const int NEGATIVE_VALUE = 0x7;
60
61 private static readonly float[] DequantizeTable16 =
62 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
63
64 private static readonly float[] DequantizeTable32 =
65 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
66
67 private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
68 //private static readonly float[] CosineTable32 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
69 private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
70 private static readonly int[] CopyMatrix32 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
71
72 private static readonly float[] QuantizeTable16 =
73 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
74
75 static OpenSimTerrainCompressor()
76 {
77 // Initialize the decompression tables
78 BuildDequantizeTable16();
79 SetupCosines16();
80 BuildCopyMatrix16();
81 BuildQuantizeTable16();
82 }
83
84 // Unused: left for historical reference.
85 public static LayerDataPacket CreateLayerDataPacket(TerrainPatch[] patches, byte type, int pRegionSizeX,
86 int pRegionSizeY)
87 {
88 LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}};
89
90 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
91 {Stride = STRIDE, PatchSize = Constants.TerrainPatchSize};
92
93 // Should be enough to fit even the most poorly packed data
94 byte[] data = new byte[patches.Length*Constants.TerrainPatchSize*Constants.TerrainPatchSize*2];
95 BitPack bitpack = new BitPack(data, 0);
96 bitpack.PackBits(header.Stride, 16);
97 bitpack.PackBits(header.PatchSize, 8);
98 bitpack.PackBits(type, 8);
99
100 foreach (TerrainPatch t in patches)
101 CreatePatch(bitpack, t.Data, t.X, t.Y, pRegionSizeX, pRegionSizeY);
102
103 bitpack.PackBits(END_OF_PATCHES, 8);
104
105 layer.LayerData.Data = new byte[bitpack.BytePos + 1];
106 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
107
108 return layer;
109 }
110
111 // Create a land packet for a single patch.
112 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int patchX, int patchY)
113 {
114 int[] xPieces = new int[1];
115 int[] yPieces = new int[1];
116 xPieces[0] = patchX; // patch X dimension
117 yPieces[0] = patchY;
118
119 byte landPacketType = (byte)TerrainPatch.LayerType.Land;
120 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
121 {
122 // libOMV does not have a packet type defined for the extended parcel format.
123 // We just happen to know the extended parcel format code is one more than the usual code.
124 landPacketType++;
125 }
126
127 return CreateLandPacket(terrData, xPieces, yPieces, landPacketType);
128 }
129
130 /// <summary>
131 /// Creates a LayerData packet for compressed land data given a full
132 /// simulator heightmap and an array of indices of patches to compress
133 /// </summary>
134 /// <param name="terrData">
135 /// Terrain data that can result in a meter square heightmap.
136 /// </param>
137 /// <param name="x">
138 /// Array of indexes in the grid of patches
139 /// for this simulator.
140 /// If creating a packet for multiple patches, there will be entries in
141 /// both the X and Y arrays for each of the patches.
142 /// For example if patches 1 and 17 are to be sent,
143 /// x[] = {1,1} and y[] = {0,1} which specifies the patches at
144 /// indexes <1,0> and <1,1> (presuming the terrain size is 16x16 patches).
145 /// </param>
146 /// <param name="y">
147 /// Array of indexes in the grid of patches.
148 /// </param>
149 /// <param name="type"></param>
150 /// <param name="pRegionSizeX"></param>
151 /// <param name="pRegionSizeY"></param>
152 /// <returns></returns>
153 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] x, int[] y, byte type)
154 {
155 LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}};
156
157 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
158 {Stride = STRIDE, PatchSize = Constants.TerrainPatchSize};
159
160 byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
161 BitPack bitpack = new BitPack(data, 0);
162 bitpack.PackBits(header.Stride, 16);
163 bitpack.PackBits(header.PatchSize, 8);
164 bitpack.PackBits(type, 8);
165
166 for (int i = 0; i < x.Length; i++)
167 CreatePatchFromHeightmap(bitpack, terrData, x[i], y[i]);
168
169 bitpack.PackBits(END_OF_PATCHES, 8);
170
171 layer.LayerData.Data = new byte[bitpack.BytePos + 1];
172 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
173
174 return layer;
175 }
176
177 // Unused: left for historical reference.
178 public static void CreatePatch(BitPack output, float[] patchData, int x, int y, int pRegionSizeX, int pRegionSizeY)
179 {
180 TerrainPatch.Header header = PrescanPatch(patchData);
181 header.QuantWBits = 136;
182 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize)
183 {
184 header.PatchIDs = (y & 0xFFFF);
185 header.PatchIDs += (x << 16);
186 }
187 else
188 {
189 header.PatchIDs = (y & 0x1F);
190 header.PatchIDs += (x << 5);
191 }
192
193 // NOTE: No idea what prequant and postquant should be or what they do
194
195 int wbits;
196 int[] patch = CompressPatch(patchData, header, 10, out wbits);
197 wbits = EncodePatchHeader(output, header, patch, (uint)pRegionSizeX, (uint)pRegionSizeY, wbits);
198 EncodePatch(output, patch, 0, wbits);
199 }
200
201 /// <summary>
202 /// Add a patch of terrain to a BitPacker
203 /// </summary>
204 /// <param name="output">BitPacker to write the patch to</param>
205 /// <param name="heightmap">
206 /// Heightmap of the simulator. Presumed to be an sizeX*sizeY array.
207 /// </param>
208 /// <param name="patchX">
209 /// X offset of the patch to create.
210 /// </param>
211 /// <param name="patchY">
212 /// Y offset of the patch to create.
213 /// </param>
214 /// <param name="pRegionSizeX"></param>
215 /// <param name="pRegionSizeY"></param>
216 public static void CreatePatchFromHeightmap(BitPack output, TerrainData terrData, int patchX, int patchY)
217 {
218 TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY);
219 header.QuantWBits = 136;
220
221 // If larger than legacy region size, pack patch X and Y info differently.
222 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
223 {
224 header.PatchIDs = (patchY & 0xFFFF);
225 header.PatchIDs += (patchX << 16);
226 }
227 else
228 {
229 header.PatchIDs = (patchY & 0x1F);
230 header.PatchIDs += (patchX << 5);
231 }
232
233 // m_log.DebugFormat("{0} CreatePatchFromHeightmap. patchX={1}, patchY={2}, DCOffset={3}, range={4}",
234 // LogHeader, patchX, patchY, header.DCOffset, header.Range);
235
236 // NOTE: No idea what prequant and postquant should be or what they do
237 int wbits;
238 int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
239 wbits = EncodePatchHeader(output, header, patch, (uint)terrData.SizeX, (uint)terrData.SizeY, wbits);
240 EncodePatch(output, patch, 0, wbits);
241 }
242
243 private static TerrainPatch.Header PrescanPatch(float[] patch)
244 {
245 TerrainPatch.Header header = new TerrainPatch.Header();
246 float zmax = -99999999.0f;
247 float zmin = 99999999.0f;
248
249 for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++)
250 {
251 float val = patch[i];
252 if (val > zmax) zmax = val;
253 if (val < zmin) zmin = val;
254 }
255
256 header.DCOffset = zmin;
257 header.Range = (int) ((zmax - zmin) + 1.0f);
258
259 return header;
260 }
261
262 // Scan the height info we're returning and return a patch packet header for this patch.
263 private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY)
264 {
265 TerrainPatch.Header header = new TerrainPatch.Header();
266 float zmax = -99999999.0f;
267 float zmin = 99999999.0f;
268
269 for (int j = patchY*Constants.TerrainPatchSize; j < (patchY + 1)*Constants.TerrainPatchSize; j++)
270 {
271 for (int i = patchX*Constants.TerrainPatchSize; i < (patchX + 1)*Constants.TerrainPatchSize; i++)
272 {
273 float val = terrData[i, j];
274 if (val > zmax) zmax = val;
275 if (val < zmin) zmin = val;
276 }
277 }
278
279 header.DCOffset = zmin;
280 header.Range = (int)(zmax - zmin + 1.0f);
281
282 return header;
283 }
284
285 public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
286 {
287 TerrainPatch.Header header = new TerrainPatch.Header {QuantWBits = bitpack.UnpackBits(8)};
288
289 // Quantized word bits
290 if (header.QuantWBits == END_OF_PATCHES)
291 return header;
292
293 // DC offset
294 header.DCOffset = bitpack.UnpackFloat();
295
296 // Range
297 header.Range = bitpack.UnpackBits(16);
298
299 // Patch IDs (10 bits)
300 header.PatchIDs = bitpack.UnpackBits(10);
301
302 // Word bits
303 header.WordBits = (uint) ((header.QuantWBits & 0x0f) + 2);
304
305 return header;
306 }
307
308 private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, uint pRegionSizeX,
309 uint pRegionSizeY, int wbits)
310 {
311 /*
312 int temp;
313 int wbits = (header.QuantWBits & 0x0f) + 2;
314 uint maxWbits = (uint)wbits + 5;
315 uint minWbits = ((uint)wbits >> 1);
316 int wbitsMaxValue;
317 */
318 // goal is to determ minimum number of bits to use so all data fits
319 /*
320 wbits = (int)minWbits;
321 wbitsMaxValue = (1 << wbits);
322
323 for (int i = 0; i < patch.Length; i++)
324 {
325 temp = patch[i];
326 if (temp != 0)
327 {
328 // Get the absolute value
329 if (temp < 0) temp *= -1;
330
331 no coments..
332
333 for (int j = (int)maxWbits; j > (int)minWbits; j--)
334 {
335 if ((temp & (1 << j)) != 0)
336 {
337 if (j > wbits) wbits = j;
338 break;
339 }
340 }
341
342 while (temp > wbitsMaxValue)
343 {
344 wbits++;
345 if (wbits == maxWbits)
346 goto Done;
347 wbitsMaxValue = 1 << wbits;
348 }
349 }
350 }
351
352 Done:
353
354 // wbits += 1;
355 */
356 // better check
357 if (wbits > 17)
358 wbits = 16;
359 else if (wbits < 3)
360 wbits = 3;
361
362 header.QuantWBits &= 0xf0;
363
364 header.QuantWBits |= (wbits - 2);
365
366 output.PackBits(header.QuantWBits, 8);
367 output.PackFloat(header.DCOffset);
368 output.PackBits(header.Range, 16);
369 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize)
370 output.PackBits(header.PatchIDs, 32);
371 else
372 output.PackBits(header.PatchIDs, 10);
373
374 return wbits;
375 }
376
377 private static void IDCTColumn16(float[] linein, float[] lineout, int column)
378 {
379 for (int n = 0; n < Constants.TerrainPatchSize; n++)
380 {
381 float total = OO_SQRT2*linein[column];
382
383 for (int u = 1; u < Constants.TerrainPatchSize; u++)
384 {
385 int usize = u*Constants.TerrainPatchSize;
386 total += linein[usize + column]*CosineTable16[usize + n];
387 }
388
389 lineout[Constants.TerrainPatchSize*n + column] = total;
390 }
391 }
392
393 private static void IDCTLine16(float[] linein, float[] lineout, int line)
394 {
395 const float oosob = 2.0f/Constants.TerrainPatchSize;
396 int lineSize = line*Constants.TerrainPatchSize;
397
398 for (int n = 0; n < Constants.TerrainPatchSize; n++)
399 {
400 float total = OO_SQRT2*linein[lineSize];
401
402 for (int u = 1; u < Constants.TerrainPatchSize; u++)
403 {
404 total += linein[lineSize + u]*CosineTable16[u*Constants.TerrainPatchSize + n];
405 }
406
407 lineout[lineSize + n] = total*oosob;
408 }
409 }
410
411/*
412 private static void DCTLine16(float[] linein, float[] lineout, int line)
413 {
414 float total = 0.0f;
415 int lineSize = line * Constants.TerrainPatchSize;
416
417 for (int n = 0; n < Constants.TerrainPatchSize; n++)
418 {
419 total += linein[lineSize + n];
420 }
421
422 lineout[lineSize] = OO_SQRT2 * total;
423
424 int uptr = 0;
425 for (int u = 1; u < Constants.TerrainPatchSize; u++)
426 {
427 total = 0.0f;
428 uptr += Constants.TerrainPatchSize;
429
430 for (int n = 0; n < Constants.TerrainPatchSize; n++)
431 {
432 total += linein[lineSize + n] * CosineTable16[uptr + n];
433 }
434
435 lineout[lineSize + u] = total;
436 }
437 }
438*/
439
440 private static void DCTLine16(float[] linein, float[] lineout, int line)
441 {
442 // outputs transpose data (lines exchanged with coluns )
443 // so to save a bit of cpu when doing coluns
444 float total = 0.0f;
445 int lineSize = line*Constants.TerrainPatchSize;
446
447 for (int n = 0; n < Constants.TerrainPatchSize; n++)
448 {
449 total += linein[lineSize + n];
450 }
451
452 lineout[line] = OO_SQRT2*total;
453
454 for (int u = Constants.TerrainPatchSize;
455 u < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
456 u += Constants.TerrainPatchSize)
457 {
458 total = 0.0f;
459 for (int ptrn = lineSize, ptru = u; ptrn < lineSize + Constants.TerrainPatchSize; ptrn++,ptru++)
460 {
461 total += linein[ptrn]*CosineTable16[ptru];
462 }
463
464 lineout[line + u] = total;
465 }
466 }
467
468
469 /*
470 private static void DCTColumn16(float[] linein, int[] lineout, int column)
471 {
472 float total = 0.0f;
473 // const float oosob = 2.0f / Constants.TerrainPatchSize;
474
475 for (int n = 0; n < Constants.TerrainPatchSize; n++)
476 {
477 total += linein[Constants.TerrainPatchSize * n + column];
478 }
479
480 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
481 lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * QuantizeTable16[column]);
482
483 for (int uptr = Constants.TerrainPatchSize; uptr < Constants.TerrainPatchSize * Constants.TerrainPatchSize; uptr += Constants.TerrainPatchSize)
484 {
485 total = 0.0f;
486
487 for (int n = 0; n < Constants.TerrainPatchSize; n++)
488 {
489 total += linein[Constants.TerrainPatchSize * n + column] * CosineTable16[uptr + n];
490 }
491
492 // lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]);
493 lineout[CopyMatrix16[uptr + column]] = (int)(total * QuantizeTable16[uptr + column]);
494 }
495 }
496 */
497
498 private static void DCTColumn16(float[] linein, int[] lineout, int column)
499 {
500 // input columns are in fact stored in lines now
501
502 float total = 0.0f;
503// const float oosob = 2.0f / Constants.TerrainPatchSize;
504 int inlinesptr = Constants.TerrainPatchSize*column;
505
506 for (int n = 0; n < Constants.TerrainPatchSize; n++)
507 {
508 total += linein[inlinesptr + n];
509 }
510
511 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
512 lineout[CopyMatrix16[column]] = (int) (OO_SQRT2*total*QuantizeTable16[column]);
513
514 for (int uptr = Constants.TerrainPatchSize;
515 uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
516 uptr += Constants.TerrainPatchSize)
517 {
518 total = 0.0f;
519
520 for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++)
521 {
522 total += linein[n]*CosineTable16[ptru];
523 }
524
525// lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]);
526 lineout[CopyMatrix16[uptr + column]] = (int) (total*QuantizeTable16[uptr + column]);
527 }
528 }
529
530 private static int DCTColumn16Wbits(float[] linein, int[] lineout, int column, int wbits, int maxwbits)
531 {
532 // input columns are in fact stored in lines now
533
534 bool dowbits = wbits != maxwbits;
535 int wbitsMaxValue = 1 << wbits;
536
537 float total = 0.0f;
538 // const float oosob = 2.0f / Constants.TerrainPatchSize;
539 int inlinesptr = Constants.TerrainPatchSize*column;
540
541 for (int n = 0; n < Constants.TerrainPatchSize; n++)
542 {
543 total += linein[inlinesptr + n];
544 }
545
546 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
547 int tmp = (int) (OO_SQRT2*total*QuantizeTable16[column]);
548 lineout[CopyMatrix16[column]] = tmp;
549
550 if (dowbits)
551 {
552 if (tmp < 0) tmp *= -1;
553 while (tmp > wbitsMaxValue)
554 {
555 wbits++;
556 wbitsMaxValue = 1 << wbits;
557 if (wbits == maxwbits)
558 {
559 dowbits = false;
560 break;
561 }
562 }
563 }
564
565 for (int uptr = Constants.TerrainPatchSize;
566 uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
567 uptr += Constants.TerrainPatchSize)
568 {
569 total = 0.0f;
570
571 for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++)
572 {
573 total += linein[n]*CosineTable16[ptru];
574 }
575
576 tmp = (int) (total*QuantizeTable16[uptr + column]);
577 lineout[CopyMatrix16[uptr + column]] = tmp;
578
579 if (dowbits)
580 {
581 if (tmp < 0) tmp *= -1;
582 while (tmp > wbitsMaxValue)
583 {
584 wbits++;
585 wbitsMaxValue = 1 << wbits;
586 if (wbits == maxwbits)
587 {
588 dowbits = false;
589 break;
590 }
591 }
592 }
593 }
594 return wbits;
595 }
596
597 public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size)
598 {
599 for (int n = 0; n < size*size; n++)
600 {
601 // ?
602 int temp = bitpack.UnpackBits(1);
603 if (temp != 0)
604 {
605 // Value or EOB
606 temp = bitpack.UnpackBits(1);
607 if (temp != 0)
608 {
609 // Value
610 temp = bitpack.UnpackBits(1);
611 if (temp != 0)
612 {
613 // Negative
614 temp = bitpack.UnpackBits((int) header.WordBits);
615 patches[n] = temp*-1;
616 }
617 else
618 {
619 // Positive
620 temp = bitpack.UnpackBits((int) header.WordBits);
621 patches[n] = temp;
622 }
623 }
624 else
625 {
626 // Set the rest to zero
627 // TODO: This might not be necessary
628 for (int o = n; o < size*size; o++)
629 {
630 patches[o] = 0;
631 }
632 break;
633 }
634 }
635 else
636 {
637 patches[n] = 0;
638 }
639 }
640 }
641
642 private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits)
643 {
644 int maxwbitssize = (1 << wbits) - 1;
645
646 if (postquant > Constants.TerrainPatchSize*Constants.TerrainPatchSize || postquant < 0)
647 {
648 Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
649 return;
650 }
651
652 if (postquant != 0) patch[Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant] = 0;
653
654 for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++)
655 {
656 int temp = patch[i];
657
658 if (temp == 0)
659 {
660 bool eob = true;
661
662 for (int j = i; j < Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant; j++)
663 {
664 if (patch[j] != 0)
665 {
666 eob = false;
667 break;
668 }
669 }
670
671 if (eob)
672 {
673 output.PackBits(ZERO_EOB, 2);
674 return;
675 }
676 output.PackBits(ZERO_CODE, 1);
677 }
678 else
679 {
680 if (temp < 0)
681 {
682 temp *= -1;
683
684 if (temp > maxwbitssize) temp = maxwbitssize;
685
686 output.PackBits(NEGATIVE_VALUE, 3);
687 output.PackBits(temp, wbits);
688 }
689 else
690 {
691 if (temp > maxwbitssize) temp = maxwbitssize;
692
693 output.PackBits(POSITIVE_VALUE, 3);
694 output.PackBits(temp, wbits);
695 }
696 }
697 }
698 }
699
700 public static float[] DecompressPatch(int[] patches, TerrainPatch.Header header, TerrainPatch.GroupHeader group)
701 {
702 float[] block = new float[group.PatchSize*group.PatchSize];
703 float[] output = new float[group.PatchSize*group.PatchSize];
704 int prequant = (header.QuantWBits >> 4) + 2;
705 int quantize = 1 << prequant;
706 float ooq = 1.0f/quantize;
707 float mult = ooq*header.Range;
708 float addval = mult*(1 << (prequant - 1)) + header.DCOffset;
709
710 if (group.PatchSize == Constants.TerrainPatchSize)
711 {
712 for (int n = 0; n < Constants.TerrainPatchSize*Constants.TerrainPatchSize; n++)
713 {
714 block[n] = patches[CopyMatrix16[n]]*DequantizeTable16[n];
715 }
716
717 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
718
719 for (int o = 0; o < Constants.TerrainPatchSize; o++)
720 IDCTColumn16(block, ftemp, o);
721 for (int o = 0; o < Constants.TerrainPatchSize; o++)
722 IDCTLine16(ftemp, block, o);
723 }
724 else
725 {
726 for (int n = 0; n < Constants.TerrainPatchSize*2*Constants.TerrainPatchSize*2; n++)
727 {
728 block[n] = patches[CopyMatrix32[n]]*DequantizeTable32[n];
729 }
730
731 Logger.Log("Implement IDCTPatchLarge", Helpers.LogLevel.Error);
732 }
733
734 for (int j = 0; j < block.Length; j++)
735 {
736 output[j] = block[j]*mult + addval;
737 }
738
739 return output;
740 }
741
742 private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
743 {
744 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
745 int wordsize = (prequant - 2) & 0x0f;
746 float oozrange = 1.0f/header.Range;
747 float range = (1 << prequant);
748 float premult = oozrange*range;
749 float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
750
751 header.QuantWBits = wordsize;
752 header.QuantWBits |= wordsize << 4;
753
754 int k = 0;
755 for (int j = 0; j < Constants.TerrainPatchSize; j++)
756 {
757 for (int i = 0; i < Constants.TerrainPatchSize; i++)
758 block[k++] = patchData[j*Constants.TerrainPatchSize + i]*premult - sub;
759 }
760
761 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
762 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
763
764
765 int maxWbits = prequant + 5;
766 wbits = (prequant >> 1);
767
768 for (int o = 0; o < Constants.TerrainPatchSize; o++)
769 DCTLine16(block, ftemp, o);
770 for (int o = 0; o < Constants.TerrainPatchSize; o++)
771 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
772
773 return itemp;
774 }
775
776 private static int[] CompressPatch(float[,] patchData, TerrainPatch.Header header, int prequant, out int wbits)
777 {
778 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
779 float oozrange = 1.0f/header.Range;
780 float range = (1 << prequant);
781 float premult = oozrange*range;
782 float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
783 int wordsize = (prequant - 2) & 0x0f;
784
785 header.QuantWBits = wordsize;
786 header.QuantWBits |= wordsize << 4;
787
788 int k = 0;
789 for (int j = 0; j < Constants.TerrainPatchSize; j++)
790 {
791 for (int i = 0; i < Constants.TerrainPatchSize; i++)
792 block[k++] = patchData[j, i]*premult - sub;
793 }
794
795 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
796 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
797
798 int maxWbits = prequant + 5;
799 wbits = (prequant >> 1);
800
801 for (int o = 0; o < Constants.TerrainPatchSize; o++)
802 DCTLine16(block, ftemp, o);
803 for (int o = 0; o < Constants.TerrainPatchSize; o++)
804 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
805
806 return itemp;
807 }
808
809 private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
810 int prequant, out int wbits)
811 {
812 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
813 int wordsize = prequant;
814 float oozrange = 1.0f/header.Range;
815 float range = (1 << prequant);
816 float premult = oozrange*range;
817 float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
818
819 header.QuantWBits = wordsize - 2;
820 header.QuantWBits |= (prequant - 2) << 4;
821
822 int k = 0;
823
824 int yPatchLimit = patchY >= (terrData.SizeY / Constants.TerrainPatchSize) ?
825 (terrData.SizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchY;
826 yPatchLimit = (yPatchLimit + 1) * Constants.TerrainPatchSize;
827
828 int xPatchLimit = patchX >= (terrData.SizeX / Constants.TerrainPatchSize) ?
829 (terrData.SizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchX;
830 xPatchLimit = (xPatchLimit + 1) * Constants.TerrainPatchSize;
831
832 for (int yy = patchY * Constants.TerrainPatchSize; yy < yPatchLimit; yy++)
833 {
834 for (int xx = patchX * Constants.TerrainPatchSize; xx < xPatchLimit; xx++)
835 {
836 block[k++] = terrData[xx, yy] * premult - sub;
837 }
838 }
839
840 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
841 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
842
843 int maxWbits = prequant + 5;
844 wbits = (prequant >> 1);
845
846 for (int o = 0; o < Constants.TerrainPatchSize; o++)
847 DCTLine16(block, ftemp, o);
848 for (int o = 0; o < Constants.TerrainPatchSize; o++)
849 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
850
851 return itemp;
852 }
853
854 #region Initialization
855
856 private static void BuildDequantizeTable16()
857 {
858 for (int j = 0; j < Constants.TerrainPatchSize; j++)
859 {
860 for (int i = 0; i < Constants.TerrainPatchSize; i++)
861 {
862 DequantizeTable16[j*Constants.TerrainPatchSize + i] = 1.0f + 2.0f*(i + j);
863 }
864 }
865 }
866
867 private static void BuildQuantizeTable16()
868 {
869 const float oosob = 2.0f/Constants.TerrainPatchSize;
870 for (int j = 0; j < Constants.TerrainPatchSize; j++)
871 {
872 for (int i = 0; i < Constants.TerrainPatchSize; i++)
873 {
874// QuantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f / (1.0f + 2.0f * ((float)i + (float)j));
875 QuantizeTable16[j*Constants.TerrainPatchSize + i] = oosob/(1.0f + 2.0f*(i + (float) j));
876 }
877 }
878 }
879
880 private static void SetupCosines16()
881 {
882 const float hposz = (float) Math.PI*0.5f/Constants.TerrainPatchSize;
883
884 for (int u = 0; u < Constants.TerrainPatchSize; u++)
885 {
886 for (int n = 0; n < Constants.TerrainPatchSize; n++)
887 {
888 CosineTable16[u*Constants.TerrainPatchSize + n] = (float) Math.Cos((2.0f*n + 1.0f)*u*hposz);
889 }
890 }
891 }
892
893 private static void BuildCopyMatrix16()
894 {
895 bool diag = false;
896 bool right = true;
897 int i = 0;
898 int j = 0;
899 int count = 0;
900
901 while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
902 {
903 CopyMatrix16[j*Constants.TerrainPatchSize + i] = count++;
904
905 if (!diag)
906 {
907 if (right)
908 {
909 if (i < Constants.TerrainPatchSize - 1) i++;
910 else j++;
911
912 right = false;
913 diag = true;
914 }
915 else
916 {
917 if (j < Constants.TerrainPatchSize - 1) j++;
918 else i++;
919
920 right = true;
921 diag = true;
922 }
923 }
924 else
925 {
926 if (right)
927 {
928 i++;
929 j--;
930 if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false;
931 }
932 else
933 {
934 i--;
935 j++;
936 if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false;
937 }
938 }
939 }
940 }
941
942 #endregion Initialization
943 }
944}