aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-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.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs88
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs40
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainChannel.cs270
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainCompressor.cs944
11 files changed, 1223 insertions, 168 deletions
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..cc8a236 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
@@ -25,13 +25,20 @@
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 // Return the packaged terrain data for passing into lower levels of communication
41 TerrainData GetTerrainData();
35 42
36 /// <summary> 43 /// <summary>
37 /// Squash the entire heightmap into a single dimensioned array 44 /// Squash the entire heightmap into a single dimensioned array
@@ -40,7 +47,10 @@ namespace OpenSim.Region.Framework.Interfaces
40 float[] GetFloatsSerialised(); 47 float[] GetFloatsSerialised();
41 48
42 double[,] GetDoubles(); 49 double[,] GetDoubles();
50
51 // Check if a location has been updated. Clears the taint flag as a side effect.
43 bool Tainted(int x, int y); 52 bool Tainted(int x, int y);
53
44 ITerrainChannel MakeCopy(); 54 ITerrainChannel MakeCopy();
45 string SaveToXmlString(); 55 string SaveToXmlString();
46 void LoadFromXmlString(string data); 56 void LoadFromXmlString(string data);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 7772f94..99c7079 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,16 +1099,19 @@ 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 = (uint)((int)otherRegion.RegionLocX / (int)Constants.RegionSize);
1103 uint ycell = (uint)((int)otherRegion.RegionLocY / (int)Constants.RegionSize); 1103 // uint ycell = (uint)((int)otherRegion.RegionLocY / (int)Constants.RegionSize);
1104 uint xcell = Util.WorldToRegionLoc((uint)otherRegion.RegionLocX);
1105 uint ycell = Util.WorldToRegionLoc((uint)otherRegion.RegionLocY);
1106
1104 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}", 1107 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}",
1105 // RegionInfo.RegionName, otherRegion.RegionName, xcell, ycell); 1108 // RegionInfo.RegionName, otherRegion.RegionName, xcell, ycell);
1106 1109
1107 if (RegionInfo.RegionHandle != otherRegion.RegionHandle) 1110 if (RegionInfo.RegionHandle != otherRegion.RegionHandle)
1108 { 1111 {
1109 // If these are cast to INT because long + negative values + abs returns invalid data 1112 // If these are cast to INT because long + negative values + abs returns invalid data
1110 int resultX = Math.Abs((int)xcell - (int)RegionInfo.RegionLocX); 1113 int resultX = Math.Abs((int)xcell - (int)RegionInfo.LegacyRegionLocX);
1111 int resultY = Math.Abs((int)ycell - (int)RegionInfo.RegionLocY); 1114 int resultY = Math.Abs((int)ycell - (int)RegionInfo.LegacyRegionLocY);
1112 if (resultX <= 1 && resultY <= 1) 1115 if (resultX <= 1 && resultY <= 1)
1113 { 1116 {
1114 // Let the grid service module know, so this can be cached 1117 // Let the grid service module know, so this can be cached
@@ -1183,8 +1186,8 @@ namespace OpenSim.Region.Framework.Scenes
1183 /// </returns> 1186 /// </returns>
1184 public int HaveNeighbor(Cardinals car, ref int[] fix) 1187 public int HaveNeighbor(Cardinals car, ref int[] fix)
1185 { 1188 {
1186 uint neighbourx = RegionInfo.RegionLocX; 1189 uint neighbourx = RegionInfo.LegacyRegionLocX;
1187 uint neighboury = RegionInfo.RegionLocY; 1190 uint neighboury = RegionInfo.LegacyRegionLocY;
1188 1191
1189 int dir = (int)car; 1192 int dir = (int)car;
1190 1193
@@ -1198,14 +1201,16 @@ namespace OpenSim.Region.Framework.Scenes
1198 else if (dir > 3 && dir < 7) // Heading Sout 1201 else if (dir > 3 && dir < 7) // Heading Sout
1199 neighboury--; 1202 neighboury--;
1200 1203
1201 int x = (int)(neighbourx * Constants.RegionSize); 1204 // int x = (int)(neighbourx * Constants.RegionSize);
1202 int y = (int)(neighboury * Constants.RegionSize); 1205 // int y = (int)(neighboury * Constants.RegionSize);
1203 GridRegion neighbourRegion = GridService.GetRegionByPosition(RegionInfo.ScopeID, x, y); 1206 uint x = Util.RegionToWorldLoc(neighbourx);
1207 uint y = Util.RegionToWorldLoc(neighboury);
1208 GridRegion neighbourRegion = GridService.GetRegionByPosition(RegionInfo.ScopeID, (int)x, (int)y);
1204 1209
1205 if (neighbourRegion == null) 1210 if (neighbourRegion == null)
1206 { 1211 {
1207 fix[0] = (int)(RegionInfo.RegionLocX - neighbourx); 1212 fix[0] = (int)(RegionInfo.LegacyRegionLocX - neighbourx);
1208 fix[1] = (int)(RegionInfo.RegionLocY - neighboury); 1213 fix[1] = (int)(RegionInfo.LegacyRegionLocY - neighboury);
1209 return dir * (-1); 1214 return dir * (-1);
1210 } 1215 }
1211 else 1216 else
@@ -1894,7 +1899,7 @@ namespace OpenSim.Region.Framework.Scenes
1894 { 1899 {
1895 try 1900 try
1896 { 1901 {
1897 double[,] map = SimulationDataService.LoadTerrain(RegionInfo.RegionID); 1902 TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
1898 if (map == null) 1903 if (map == null)
1899 { 1904 {
1900 // This should be in the Terrain module, but it isn't because 1905 // This should be in the Terrain module, but it isn't because
@@ -1905,7 +1910,7 @@ namespace OpenSim.Region.Framework.Scenes
1905 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 1910 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
1906 1911
1907 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); 1912 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain);
1908 Heightmap = new TerrainChannel(m_InitialTerrain); 1913 Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
1909 1914
1910 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 1915 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
1911 } 1916 }
@@ -3994,12 +3999,12 @@ namespace OpenSim.Region.Framework.Scenes
3994 { 3999 {
3995 if (posX < 0) 4000 if (posX < 0)
3996 posX = 0; 4001 posX = 0;
3997 else if (posX >= 256) 4002 else if (posX >= (float)RegionInfo.RegionSizeX)
3998 posX = 255.999f; 4003 posX = (float)RegionInfo.RegionSizeX - 0.001f;
3999 if (posY < 0) 4004 if (posY < 0)
4000 posY = 0; 4005 posY = 0;
4001 else if (posY >= 256) 4006 else if (posY >= (float)RegionInfo.RegionSizeY)
4002 posY = 255.999f; 4007 posY = (float)RegionInfo.RegionSizeY - 0.001f;
4003 4008
4004 reason = String.Empty; 4009 reason = String.Empty;
4005 if (Permissions.IsGod(agentID)) 4010 if (Permissions.IsGod(agentID))
@@ -4293,7 +4298,7 @@ namespace OpenSim.Region.Framework.Scenes
4293 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4298 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4294 4299
4295 // TODO: This check should probably be in QueryAccess(). 4300 // TODO: This check should probably be in QueryAccess().
4296 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4301 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2);
4297 if (nearestParcel == null) 4302 if (nearestParcel == null)
4298 { 4303 {
4299 m_log.InfoFormat( 4304 m_log.InfoFormat(
@@ -4371,8 +4376,8 @@ namespace OpenSim.Region.Framework.Scenes
4371 { 4376 {
4372 uint rRegionX = (uint)(cAgentData.RegionHandle >> 40); 4377 uint rRegionX = (uint)(cAgentData.RegionHandle >> 40);
4373 uint rRegionY = (((uint)(cAgentData.RegionHandle)) >> 8); 4378 uint rRegionY = (((uint)(cAgentData.RegionHandle)) >> 8);
4374 uint tRegionX = RegionInfo.RegionLocX; 4379 uint tRegionX = RegionInfo.LegacyRegionLocX;
4375 uint tRegionY = RegionInfo.RegionLocY; 4380 uint tRegionY = RegionInfo.LegacyRegionLocY;
4376 //Send Data to ScenePresence 4381 //Send Data to ScenePresence
4377 childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); 4382 childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
4378 // Not Implemented: 4383 // Not Implemented:
@@ -4600,13 +4605,22 @@ namespace OpenSim.Region.Framework.Scenes
4600 ScenePresence sp = GetScenePresence(remoteClient.AgentId); 4605 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4601 if (sp != null) 4606 if (sp != null)
4602 { 4607 {
4603 uint regionX = RegionInfo.RegionLocX; 4608 /*
4604 uint regionY = RegionInfo.RegionLocY; 4609 uint regionX = RegionInfo.LegacyRegionLocX;
4610 uint regionY = RegionInfo.LegacyRegionLocY;
4605 4611
4612 Util.RegionHandleToWorldLoc(regionHandle, out regionX, out regionY);
4606 Utils.LongToUInts(regionHandle, out regionX, out regionY); 4613 Utils.LongToUInts(regionHandle, out regionX, out regionY);
4607 4614
4608 int shiftx = (int) regionX - (int) RegionInfo.RegionLocX * (int)Constants.RegionSize; 4615 int shiftx = (int) regionX - (int) RegionInfo.LegacyRegionLocX * (int)Constants.RegionSize;
4609 int shifty = (int) regionY - (int) RegionInfo.RegionLocY * (int)Constants.RegionSize; 4616 int shifty = (int) regionY - (int) RegionInfo.LegacyRegionLocY * (int)Constants.RegionSize;
4617 */
4618
4619 uint regionX, regionY;
4620 Util.RegionHandleToWorldLoc(regionHandle, out regionX, out regionY);
4621
4622 int shiftx = (int) regionX - (int)RegionInfo.RegionWorldLocX;
4623 int shifty = (int) regionY - (int)RegionInfo.RegionWorldLocY;
4610 4624
4611 position.X += shiftx; 4625 position.X += shiftx;
4612 position.Y += shifty; 4626 position.Y += shifty;
@@ -4817,7 +4831,7 @@ namespace OpenSim.Region.Framework.Scenes
4817 else 4831 else
4818 { 4832 {
4819 4833
4820 if (pos.X > 0f && pos.X < Constants.RegionSize && pos.Y > 0f && pos.Y < Constants.RegionSize) 4834 if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY)
4821 { 4835 {
4822 // The only time parcel != null when an object is inside a region is when 4836 // 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. 4837 // there is nothing behind the landchannel. IE, no land plugin loaded.
@@ -5478,7 +5492,7 @@ namespace OpenSim.Region.Framework.Scenes
5478 { 5492 {
5479 Vector3 unitDirection = Vector3.Normalize(direction); 5493 Vector3 unitDirection = Vector3.Normalize(direction);
5480 //Making distance to search go through some sane limit of distance 5494 //Making distance to search go through some sane limit of distance
5481 for (float distance = 0; distance < Constants.RegionSize * 2; distance += .5f) 5495 for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f)
5482 { 5496 {
5483 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance)); 5497 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance));
5484 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) 5498 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y))
@@ -5532,9 +5546,9 @@ namespace OpenSim.Region.Framework.Scenes
5532 int count = 0; 5546 int count = 0;
5533 int avgx = 0; 5547 int avgx = 0;
5534 int avgy = 0; 5548 int avgy = 0;
5535 for (int x = 0; x < Constants.RegionSize; x++) 5549 for (int x = 0; x < RegionInfo.RegionSizeX; x++)
5536 { 5550 {
5537 for (int y = 0; y < Constants.RegionSize; y++) 5551 for (int y = 0; y < RegionInfo.RegionSizeY; y++)
5538 { 5552 {
5539 //Just keep a running average as we check if all the points are inside or not 5553 //Just keep a running average as we check if all the points are inside or not
5540 if (parcel.ContainsPoint(x, y)) 5554 if (parcel.ContainsPoint(x, y))
@@ -5558,31 +5572,33 @@ namespace OpenSim.Region.Framework.Scenes
5558 5572
5559 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) 5573 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar)
5560 { 5574 {
5561 float xdistance = avatar.AbsolutePosition.X < Constants.RegionSize / 2 ? avatar.AbsolutePosition.X : Constants.RegionSize - avatar.AbsolutePosition.X; 5575 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; 5576 ? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X;
5577 float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2
5578 ? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y;
5563 5579
5564 //find out what vertical edge to go to 5580 //find out what vertical edge to go to
5565 if (xdistance < ydistance) 5581 if (xdistance < ydistance)
5566 { 5582 {
5567 if (avatar.AbsolutePosition.X < Constants.RegionSize / 2) 5583 if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2)
5568 { 5584 {
5569 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y); 5585 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y);
5570 } 5586 }
5571 else 5587 else
5572 { 5588 {
5573 return GetPositionAtAvatarHeightOrGroundHeight(avatar, Constants.RegionSize, avatar.AbsolutePosition.Y); 5589 return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y);
5574 } 5590 }
5575 } 5591 }
5576 //find out what horizontal edge to go to 5592 //find out what horizontal edge to go to
5577 else 5593 else
5578 { 5594 {
5579 if (avatar.AbsolutePosition.Y < Constants.RegionSize / 2) 5595 if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2)
5580 { 5596 {
5581 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f); 5597 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f);
5582 } 5598 }
5583 else 5599 else
5584 { 5600 {
5585 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, Constants.RegionSize); 5601 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY);
5586 } 5602 }
5587 } 5603 }
5588 } 5604 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 77889fa..262b882 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
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index 28f7896..2677989 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -445,8 +445,8 @@ namespace OpenSim.Region.Framework.Scenes
445 { 445 {
446 foreach (Scene mscene in m_localScenes) 446 foreach (Scene mscene in m_localScenes)
447 { 447 {
448 if (mscene.RegionInfo.RegionLocX == locX && 448 if (mscene.RegionInfo.LegacyRegionLocX == locX &&
449 mscene.RegionInfo.RegionLocY == locY) 449 mscene.RegionInfo.LegacyRegionLocY == locY)
450 { 450 {
451 scene = mscene; 451 scene = mscene;
452 return true; 452 return true;
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 4b4e4ba..eed8908 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -842,9 +842,9 @@ namespace OpenSim.Region.Framework.Scenes
842 maxX = -256f; 842 maxX = -256f;
843 maxY = -256f; 843 maxY = -256f;
844 maxZ = -256f; 844 maxZ = -256f;
845 minX = 256f; 845 minX = 10000f;
846 minY = 256f; 846 minY = 10000f;
847 minZ = 8192f; 847 minZ = 10000f;
848 848
849 SceneObjectPart[] parts = m_parts.GetArray(); 849 SceneObjectPart[] parts = m_parts.GetArray();
850 for (int i = 0; i < parts.Length; i++) 850 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 7243db1..2c64c85 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -707,10 +707,9 @@ namespace OpenSim.Region.Framework.Scenes
707 foreach (ulong handle in seeds.Keys) 707 foreach (ulong handle in seeds.Keys)
708 { 708 {
709 uint x, y; 709 uint x, y;
710 Utils.LongToUInts(handle, out x, out y); 710 Util.RegionHandleToRegionLoc(handle, out x, out y);
711 x = x / Constants.RegionSize; 711
712 y = y / Constants.RegionSize; 712 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.LegacyRegionLocX, y, Scene.RegionInfo.LegacyRegionLocY))
713 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
714 { 713 {
715 old.Add(handle); 714 old.Add(handle);
716 } 715 }
@@ -731,9 +730,7 @@ namespace OpenSim.Region.Framework.Scenes
731 foreach (KeyValuePair<ulong, string> kvp in KnownRegions) 730 foreach (KeyValuePair<ulong, string> kvp in KnownRegions)
732 { 731 {
733 uint x, y; 732 uint x, y;
734 Utils.LongToUInts(kvp.Key, out x, out y); 733 Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
735 x = x / Constants.RegionSize;
736 y = y / Constants.RegionSize;
737 m_log.Info(" >> "+x+", "+y+": "+kvp.Value); 734 m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
738 } 735 }
739 } 736 }
@@ -971,7 +968,7 @@ namespace OpenSim.Region.Framework.Scenes
971 968
972 float posZLimit = 0; 969 float posZLimit = 0;
973 970
974 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 971 if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY)
975 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 972 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
976 973
977 float newPosZ = posZLimit + localAVHeight / 2; 974 float newPosZ = posZLimit + localAVHeight / 2;
@@ -2076,7 +2073,7 @@ namespace OpenSim.Region.Framework.Scenes
2076 if (regionCombinerModule != null) 2073 if (regionCombinerModule != null)
2077 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); 2074 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
2078 else 2075 else
2079 regionSize = new Vector2(Constants.RegionSize); 2076 regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY);
2080 2077
2081 if (pos.X < 0 || pos.X >= regionSize.X 2078 if (pos.X < 0 || pos.X >= regionSize.X
2082 || pos.Y < 0 || pos.Y >= regionSize.Y 2079 || pos.Y < 0 || pos.Y >= regionSize.Y
@@ -2094,8 +2091,8 @@ namespace OpenSim.Region.Framework.Scenes
2094// } 2091// }
2095 2092
2096 // Get terrain height for sub-region in a megaregion if necessary 2093 // Get terrain height for sub-region in a megaregion if necessary
2097 int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X); 2094 int X = (int)((m_scene.RegionInfo.RegionWorldLocX) + pos.X);
2098 int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y); 2095 int Y = (int)((m_scene.RegionInfo.RegionWorldLocY) + pos.Y);
2099 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y); 2096 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y);
2100 // If X and Y is NaN, target_region will be null 2097 // If X and Y is NaN, target_region will be null
2101 if (target_region == null) 2098 if (target_region == null)
@@ -2106,7 +2103,7 @@ namespace OpenSim.Region.Framework.Scenes
2106 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene)) 2103 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
2107 targetScene = m_scene; 2104 targetScene = m_scene;
2108 2105
2109 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)]; 2106 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
2110 pos.Z = Math.Max(terrainHeight, pos.Z); 2107 pos.Z = Math.Max(terrainHeight, pos.Z);
2111 2108
2112 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 2109 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -3199,11 +3196,11 @@ namespace OpenSim.Region.Framework.Scenes
3199 Vector3 pos = AbsolutePosition; 3196 Vector3 pos = AbsolutePosition;
3200 if (AbsolutePosition.X < 0) 3197 if (AbsolutePosition.X < 0)
3201 pos.X += Velocity.X * 2; 3198 pos.X += Velocity.X * 2;
3202 else if (AbsolutePosition.X > Constants.RegionSize) 3199 else if (AbsolutePosition.X > m_scene.RegionInfo.RegionSizeX)
3203 pos.X -= Velocity.X * 2; 3200 pos.X -= Velocity.X * 2;
3204 if (AbsolutePosition.Y < 0) 3201 if (AbsolutePosition.Y < 0)
3205 pos.Y += Velocity.Y * 2; 3202 pos.Y += Velocity.Y * 2;
3206 else if (AbsolutePosition.Y > Constants.RegionSize) 3203 else if (AbsolutePosition.Y > m_scene.RegionInfo.RegionSizeY)
3207 pos.Y -= Velocity.Y * 2; 3204 pos.Y -= Velocity.Y * 2;
3208 Velocity = Vector3.Zero; 3205 Velocity = Vector3.Zero;
3209 AbsolutePosition = pos; 3206 AbsolutePosition = pos;
@@ -3226,11 +3223,11 @@ namespace OpenSim.Region.Framework.Scenes
3226 Vector3 pos = AbsolutePosition; 3223 Vector3 pos = AbsolutePosition;
3227 if (AbsolutePosition.X < 0) 3224 if (AbsolutePosition.X < 0)
3228 pos.X += Velocity.X * 2; 3225 pos.X += Velocity.X * 2;
3229 else if (AbsolutePosition.X > Constants.RegionSize) 3226 else if (AbsolutePosition.X > m_scene.RegionInfo.RegionSizeX)
3230 pos.X -= Velocity.X * 2; 3227 pos.X -= Velocity.X * 2;
3231 if (AbsolutePosition.Y < 0) 3228 if (AbsolutePosition.Y < 0)
3232 pos.Y += Velocity.Y * 2; 3229 pos.Y += Velocity.Y * 2;
3233 else if (AbsolutePosition.Y > Constants.RegionSize) 3230 else if (AbsolutePosition.Y > m_scene.RegionInfo.RegionSizeY)
3234 pos.Y -= Velocity.Y * 2; 3231 pos.Y -= Velocity.Y * 2;
3235 Velocity = Vector3.Zero; 3232 Velocity = Vector3.Zero;
3236 AbsolutePosition = pos; 3233 AbsolutePosition = pos;
@@ -3279,7 +3276,7 @@ namespace OpenSim.Region.Framework.Scenes
3279 3276
3280 // Put the child agent back at the center 3277 // Put the child agent back at the center
3281 AbsolutePosition 3278 AbsolutePosition
3282 = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70); 3279 = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
3283 3280
3284 Animator.ResetAnimations(); 3281 Animator.ResetAnimations();
3285 } 3282 }
@@ -3306,9 +3303,7 @@ namespace OpenSim.Region.Framework.Scenes
3306 if (handle != Scene.RegionInfo.RegionHandle) 3303 if (handle != Scene.RegionInfo.RegionHandle)
3307 { 3304 {
3308 uint x, y; 3305 uint x, y;
3309 Utils.LongToUInts(handle, out x, out y); 3306 Util.RegionHandleToRegionLoc(handle, out x, out y);
3310 x = x / Constants.RegionSize;
3311 y = y / Constants.RegionSize;
3312 3307
3313// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); 3308// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
3314// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); 3309// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
@@ -3389,8 +3384,9 @@ namespace OpenSim.Region.Framework.Scenes
3389 return; 3384 return;
3390 3385
3391 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); 3386 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
3392 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; 3387 // Find the distance (in meters) between the two regions
3393 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; 3388 uint shiftx = Util.RegionToWorldLoc(rRegionX - tRegionX);
3389 uint shifty = Util.RegionToWorldLoc(rRegionY - tRegionY);
3394 3390
3395 Vector3 offset = new Vector3(shiftx, shifty, 0f); 3391 Vector3 offset = new Vector3(shiftx, shifty, 0f);
3396 3392
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 95f9caf..67998a0 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -437,7 +437,7 @@ namespace OpenSim.Region.Framework.Scenes
437 437
438 SimStats simStats 438 SimStats simStats
439 = new SimStats( 439 = new SimStats(
440 ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)m_objectCapacity, 440 ReportingRegion.LegacyRegionLocX, ReportingRegion.LegacyRegionLocY, regionFlags, (uint)m_objectCapacity,
441 rb, sb, m_scene.RegionInfo.originRegionID); 441 rb, sb, m_scene.RegionInfo.originRegionID);
442 442
443 handlerSendStatResult = OnSendStatsResult; 443 handlerSendStatResult = OnSendStatsResult;
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index c0ca48e..a5b42ff 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,134 @@ 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 { return (double)m_terrainData[x, y]; }
135 set 160 set
136 { 161 {
137 // Will "fix" terrain hole problems. Although not fantastically.
138 if (Double.IsNaN(value) || Double.IsInfinity(value)) 162 if (Double.IsNaN(value) || Double.IsInfinity(value))
139 return; 163 return;
140 164
141 if (map[x, y] != value) 165 m_terrainData[x, y] = (float)value;
142 {
143 taint[x / 16, y / 16] = true;
144 map[x, y] = value;
145 }
146 } 166 }
147 } 167 }
148 168
169 // ITerrainChannel.Tainted()
149 public bool Tainted(int x, int y) 170 public bool Tainted(int x, int y)
150 { 171 {
151 if (taint[x / 16, y / 16]) 172 return m_terrainData.IsTaintedAt(x, y);
152 {
153 taint[x / 16, y / 16] = false;
154 return true;
155 }
156 return false;
157 }
158
159 #endregion
160
161 public TerrainChannel Copy()
162 {
163 TerrainChannel copy = new TerrainChannel(false);
164 copy.map = (double[,]) map.Clone();
165
166 return copy;
167 } 173 }
168 174
175 // ITerrainChannel.SaveToXmlString()
169 public string SaveToXmlString() 176 public string SaveToXmlString()
170 { 177 {
171 XmlWriterSettings settings = new XmlWriterSettings(); 178 XmlWriterSettings settings = new XmlWriterSettings();
@@ -181,13 +188,7 @@ namespace OpenSim.Region.Framework.Scenes
181 } 188 }
182 } 189 }
183 190
184 private void WriteXml(XmlWriter writer) 191 // 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) 192 public void LoadFromXmlString(string data)
192 { 193 {
193 StringReader sr = new StringReader(data); 194 StringReader sr = new StringReader(data);
@@ -199,12 +200,50 @@ namespace OpenSim.Region.Framework.Scenes
199 sr.Close(); 200 sr.Close();
200 } 201 }
201 202
203 #endregion
204
205 public TerrainChannel Copy()
206 {
207 TerrainChannel copy = new TerrainChannel();
208 copy.m_terrainData = m_terrainData.Clone();
209 return copy;
210 }
211
212 private void WriteXml(XmlWriter writer)
213 {
214 if (Width == Constants.RegionSize && Height == Constants.RegionSize)
215 {
216 // Downward compatibility for legacy region terrain maps.
217 // If region is exactly legacy size, return the old format XML.
218 writer.WriteStartElement(String.Empty, "TerrainMap", String.Empty);
219 ToXml(writer);
220 writer.WriteEndElement();
221 }
222 else
223 {
224 // New format XML that includes width and length.
225 writer.WriteStartElement(String.Empty, "TerrainMap2", String.Empty);
226 ToXml2(writer);
227 writer.WriteEndElement();
228 }
229 }
230
202 private void ReadXml(XmlReader reader) 231 private void ReadXml(XmlReader reader)
203 { 232 {
204 reader.ReadStartElement("TerrainMap"); 233 // Check the first element. If legacy element, use the legacy reader.
205 FromXml(reader); 234 if (reader.IsStartElement("TerrainMap"))
235 {
236 reader.ReadStartElement("TerrainMap");
237 FromXml(reader);
238 }
239 else
240 {
241 reader.ReadStartElement("TerrainMap2");
242 FromXml2(reader);
243 }
206 } 244 }
207 245
246 // Write legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
208 private void ToXml(XmlWriter xmlWriter) 247 private void ToXml(XmlWriter xmlWriter)
209 { 248 {
210 float[] mapData = GetFloatsSerialised(); 249 float[] mapData = GetFloatsSerialised();
@@ -218,12 +257,15 @@ namespace OpenSim.Region.Framework.Scenes
218 serializer.Serialize(xmlWriter, buffer); 257 serializer.Serialize(xmlWriter, buffer);
219 } 258 }
220 259
260 // Read legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
221 private void FromXml(XmlReader xmlReader) 261 private void FromXml(XmlReader xmlReader)
222 { 262 {
223 XmlSerializer serializer = new XmlSerializer(typeof(byte[])); 263 XmlSerializer serializer = new XmlSerializer(typeof(byte[]));
224 byte[] dataArray = (byte[])serializer.Deserialize(xmlReader); 264 byte[] dataArray = (byte[])serializer.Deserialize(xmlReader);
225 int index = 0; 265 int index = 0;
226 266
267 m_terrainData = new HeightmapTerrainData(Height, Width, (int)Constants.RegionHeight);
268
227 for (int y = 0; y < Height; y++) 269 for (int y = 0; y < Height; y++)
228 { 270 {
229 for (int x = 0; x < Width; x++) 271 for (int x = 0; x < Width; x++)
@@ -236,35 +278,63 @@ namespace OpenSim.Region.Framework.Scenes
236 } 278 }
237 } 279 }
238 280
281 private class TerrainChannelXMLPackage
282 {
283 public int Version;
284 public int SizeX;
285 public int SizeY;
286 public int SizeZ;
287 public float CompressionFactor;
288 public short[] Map;
289 public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, short[] pMap)
290 {
291 Version = 1;
292 SizeX = pX;
293 SizeY = pY;
294 SizeZ = pZ;
295 CompressionFactor = pCompressionFactor;
296 Map = pMap;
297 }
298 }
299
300 // New terrain serialization format that includes the width and length.
301 private void ToXml2(XmlWriter xmlWriter)
302 {
303 TerrainChannelXMLPackage package = new TerrainChannelXMLPackage(Width, Height, Altitude, m_terrainData.CompressionFactor,
304 m_terrainData.GetCompressedMap());
305 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
306 serializer.Serialize(xmlWriter, package);
307 }
308
309 // New terrain serialization format that includes the width and length.
310 private void FromXml2(XmlReader xmlReader)
311 {
312 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
313 TerrainChannelXMLPackage package = (TerrainChannelXMLPackage)serializer.Deserialize(xmlReader);
314 m_terrainData = new HeightmapTerrainData(package.Map, package.CompressionFactor, package.SizeX, package.SizeY, package.SizeZ);
315 }
316
317 // Fill the heightmap with the center bump terrain
239 private void PinHeadIsland() 318 private void PinHeadIsland()
240 { 319 {
241 int x; 320 for (int x = 0; x < Width; x++)
242 for (x = 0; x < Constants.RegionSize; x++)
243 { 321 {
244 int y; 322 for (int y = 0; y < Height; y++)
245 for (y = 0; y < Constants.RegionSize; y++)
246 { 323 {
247 map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10; 324 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; 325 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; 326 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) 327 if (m_terrainData[x, y]< spherFacA)
251 map[x, y] = spherFacA; 328 m_terrainData[x, y]= spherFacA;
252 if (map[x, y] < spherFacB) 329 if (m_terrainData[x, y]< spherFacB)
253 map[x, y] = spherFacB; 330 m_terrainData[x, y] = spherFacB;
254 } 331 }
255 } 332 }
256 } 333 }
257 334
258 private void FlatLand() 335 private void FlatLand()
259 { 336 {
260 int x; 337 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 } 338 }
268
269 } 339 }
270} 340}
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}