aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs2
-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.cs89
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs86
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainChannel.cs278
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainCompressor.cs944
10 files changed, 1288 insertions, 164 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 1949a90..3fa3706 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -72,7 +72,7 @@ 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
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.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 7772f94..3a5aa0f 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,11 @@ 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
@@ -1198,9 +1201,11 @@ 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 {
@@ -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 }
@@ -2478,6 +2483,23 @@ namespace OpenSim.Region.Framework.Scenes
2478 EntityTransferModule.Cross(grp, attemptedPosition, silent); 2483 EntityTransferModule.Cross(grp, attemptedPosition, silent);
2479 } 2484 }
2480 2485
2486 // Simple test to see if a position is in the current region.
2487 // Resuming the position is relative to the region so anything outside its bounds.
2488 // Return 'true' if position inside region.
2489 public bool PositionIsInCurrentRegion(Vector3 pos)
2490 {
2491 bool ret = true;
2492 int xx = (int)Math.Floor(pos.X);
2493 int yy = (int)Math.Floor(pos.Y);
2494 if (xx < 0
2495 || xx > RegionInfo.RegionSizeX
2496 || yy < 0
2497 || yy > RegionInfo.RegionSizeY)
2498 ret = false;
2499 return ret;
2500
2501 }
2502
2481 public Border GetCrossedBorder(Vector3 position, Cardinals gridline) 2503 public Border GetCrossedBorder(Vector3 position, Cardinals gridline)
2482 { 2504 {
2483 if (BordersLocked) 2505 if (BordersLocked)
@@ -3994,12 +4016,12 @@ namespace OpenSim.Region.Framework.Scenes
3994 { 4016 {
3995 if (posX < 0) 4017 if (posX < 0)
3996 posX = 0; 4018 posX = 0;
3997 else if (posX >= 256) 4019 else if (posX >= (float)RegionInfo.RegionSizeX)
3998 posX = 255.999f; 4020 posX = (float)RegionInfo.RegionSizeX - 0.001f;
3999 if (posY < 0) 4021 if (posY < 0)
4000 posY = 0; 4022 posY = 0;
4001 else if (posY >= 256) 4023 else if (posY >= (float)RegionInfo.RegionSizeY)
4002 posY = 255.999f; 4024 posY = (float)RegionInfo.RegionSizeY - 0.001f;
4003 4025
4004 reason = String.Empty; 4026 reason = String.Empty;
4005 if (Permissions.IsGod(agentID)) 4027 if (Permissions.IsGod(agentID))
@@ -4293,7 +4315,7 @@ namespace OpenSim.Region.Framework.Scenes
4293 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4315 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4294 4316
4295 // TODO: This check should probably be in QueryAccess(). 4317 // TODO: This check should probably be in QueryAccess().
4296 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4318 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2);
4297 if (nearestParcel == null) 4319 if (nearestParcel == null)
4298 { 4320 {
4299 m_log.InfoFormat( 4321 m_log.InfoFormat(
@@ -4600,13 +4622,22 @@ namespace OpenSim.Region.Framework.Scenes
4600 ScenePresence sp = GetScenePresence(remoteClient.AgentId); 4622 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4601 if (sp != null) 4623 if (sp != null)
4602 { 4624 {
4603 uint regionX = RegionInfo.RegionLocX; 4625 /*
4604 uint regionY = RegionInfo.RegionLocY; 4626 uint regionX = RegionInfo.LegacyRegionLocX;
4627 uint regionY = RegionInfo.LegacyRegionLocY;
4605 4628
4629 Util.RegionHandleToWorldLoc(regionHandle, out regionX, out regionY);
4606 Utils.LongToUInts(regionHandle, out regionX, out regionY); 4630 Utils.LongToUInts(regionHandle, out regionX, out regionY);
4607 4631
4608 int shiftx = (int) regionX - (int) RegionInfo.RegionLocX * (int)Constants.RegionSize; 4632 int shiftx = (int) regionX - (int) RegionInfo.LegacyRegionLocX * (int)Constants.RegionSize;
4609 int shifty = (int) regionY - (int) RegionInfo.RegionLocY * (int)Constants.RegionSize; 4633 int shifty = (int) regionY - (int) RegionInfo.LegacyRegionLocY * (int)Constants.RegionSize;
4634 */
4635
4636 uint regionX, regionY;
4637 Util.RegionHandleToWorldLoc(regionHandle, out regionX, out regionY);
4638
4639 int shiftx = (int) regionX - (int)RegionInfo.WorldLocX;
4640 int shifty = (int) regionY - (int)RegionInfo.WorldLocY;
4610 4641
4611 position.X += shiftx; 4642 position.X += shiftx;
4612 position.Y += shifty; 4643 position.Y += shifty;
@@ -4817,7 +4848,7 @@ namespace OpenSim.Region.Framework.Scenes
4817 else 4848 else
4818 { 4849 {
4819 4850
4820 if (pos.X > 0f && pos.X < Constants.RegionSize && pos.Y > 0f && pos.Y < Constants.RegionSize) 4851 if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY)
4821 { 4852 {
4822 // The only time parcel != null when an object is inside a region is when 4853 // 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. 4854 // there is nothing behind the landchannel. IE, no land plugin loaded.
@@ -5478,7 +5509,7 @@ namespace OpenSim.Region.Framework.Scenes
5478 { 5509 {
5479 Vector3 unitDirection = Vector3.Normalize(direction); 5510 Vector3 unitDirection = Vector3.Normalize(direction);
5480 //Making distance to search go through some sane limit of distance 5511 //Making distance to search go through some sane limit of distance
5481 for (float distance = 0; distance < Constants.RegionSize * 2; distance += .5f) 5512 for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f)
5482 { 5513 {
5483 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance)); 5514 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance));
5484 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) 5515 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y))
@@ -5532,9 +5563,9 @@ namespace OpenSim.Region.Framework.Scenes
5532 int count = 0; 5563 int count = 0;
5533 int avgx = 0; 5564 int avgx = 0;
5534 int avgy = 0; 5565 int avgy = 0;
5535 for (int x = 0; x < Constants.RegionSize; x++) 5566 for (int x = 0; x < RegionInfo.RegionSizeX; x++)
5536 { 5567 {
5537 for (int y = 0; y < Constants.RegionSize; y++) 5568 for (int y = 0; y < RegionInfo.RegionSizeY; y++)
5538 { 5569 {
5539 //Just keep a running average as we check if all the points are inside or not 5570 //Just keep a running average as we check if all the points are inside or not
5540 if (parcel.ContainsPoint(x, y)) 5571 if (parcel.ContainsPoint(x, y))
@@ -5558,31 +5589,33 @@ namespace OpenSim.Region.Framework.Scenes
5558 5589
5559 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) 5590 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar)
5560 { 5591 {
5561 float xdistance = avatar.AbsolutePosition.X < Constants.RegionSize / 2 ? avatar.AbsolutePosition.X : Constants.RegionSize - avatar.AbsolutePosition.X; 5592 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; 5593 ? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X;
5594 float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2
5595 ? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y;
5563 5596
5564 //find out what vertical edge to go to 5597 //find out what vertical edge to go to
5565 if (xdistance < ydistance) 5598 if (xdistance < ydistance)
5566 { 5599 {
5567 if (avatar.AbsolutePosition.X < Constants.RegionSize / 2) 5600 if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2)
5568 { 5601 {
5569 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y); 5602 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y);
5570 } 5603 }
5571 else 5604 else
5572 { 5605 {
5573 return GetPositionAtAvatarHeightOrGroundHeight(avatar, Constants.RegionSize, avatar.AbsolutePosition.Y); 5606 return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y);
5574 } 5607 }
5575 } 5608 }
5576 //find out what horizontal edge to go to 5609 //find out what horizontal edge to go to
5577 else 5610 else
5578 { 5611 {
5579 if (avatar.AbsolutePosition.Y < Constants.RegionSize / 2) 5612 if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2)
5580 { 5613 {
5581 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f); 5614 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f);
5582 } 5615 }
5583 else 5616 else
5584 { 5617 {
5585 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, Constants.RegionSize); 5618 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY);
5586 } 5619 }
5587 } 5620 }
5588 } 5621 }
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..d4cbf7d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -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;
@@ -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..0cd8b21 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -749,9 +749,8 @@ namespace OpenSim.Region.Framework.Scenes
749 foreach (ulong handle in seeds.Keys) 749 foreach (ulong handle in seeds.Keys)
750 { 750 {
751 uint x, y; 751 uint x, y;
752 Utils.LongToUInts(handle, out x, out y); 752 Util.RegionHandleToRegionLoc(handle, out x, out y);
753 x = x / Constants.RegionSize; 753
754 y = y / Constants.RegionSize;
755 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY)) 754 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
756 { 755 {
757 old.Add(handle); 756 old.Add(handle);
@@ -773,9 +772,7 @@ namespace OpenSim.Region.Framework.Scenes
773 foreach (KeyValuePair<ulong, string> kvp in KnownRegions) 772 foreach (KeyValuePair<ulong, string> kvp in KnownRegions)
774 { 773 {
775 uint x, y; 774 uint x, y;
776 Utils.LongToUInts(kvp.Key, out x, out y); 775 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); 776 m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
780 } 777 }
781 } 778 }
@@ -1109,7 +1106,7 @@ namespace OpenSim.Region.Framework.Scenes
1109 1106
1110 float posZLimit = 0; 1107 float posZLimit = 0;
1111 1108
1112 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 1109 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]; 1110 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
1114 1111
1115 float newPosZ = posZLimit + localAVHeight / 2; 1112 float newPosZ = posZLimit + localAVHeight / 2;
@@ -2362,7 +2359,7 @@ namespace OpenSim.Region.Framework.Scenes
2362 if (regionCombinerModule != null) 2359 if (regionCombinerModule != null)
2363 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); 2360 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
2364 else 2361 else
2365 regionSize = new Vector2(Constants.RegionSize); 2362 regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY);
2366 2363
2367 if (pos.X < 0 || pos.X >= regionSize.X 2364 if (pos.X < 0 || pos.X >= regionSize.X
2368 || pos.Y < 0 || pos.Y >= regionSize.Y 2365 || pos.Y < 0 || pos.Y >= regionSize.Y
@@ -2380,8 +2377,8 @@ namespace OpenSim.Region.Framework.Scenes
2380// } 2377// }
2381 2378
2382 // Get terrain height for sub-region in a megaregion if necessary 2379 // Get terrain height for sub-region in a megaregion if necessary
2383 int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X); 2380 int X = (int)((m_scene.RegionInfo.WorldLocX) + pos.X);
2384 int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y); 2381 int Y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y);
2385 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y); 2382 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 2383 // If X and Y is NaN, target_region will be null
2387 if (target_region == null) 2384 if (target_region == null)
@@ -2392,7 +2389,7 @@ namespace OpenSim.Region.Framework.Scenes
2392 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene)) 2389 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
2393 targetScene = m_scene; 2390 targetScene = m_scene;
2394 2391
2395 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)]; 2392 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
2396 pos.Z = Math.Max(terrainHeight, pos.Z); 2393 pos.Z = Math.Max(terrainHeight, pos.Z);
2397 2394
2398 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 2395 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -3431,6 +3428,9 @@ namespace OpenSim.Region.Framework.Scenes
3431 int neighbor = 0; 3428 int neighbor = 0;
3432 int[] fix = new int[2]; 3429 int[] fix = new int[2];
3433 3430
3431 // Compute the avatar position in the next physics tick.
3432 // If the avatar will be crossing, we force the crossing to happen now
3433 // in the hope that this will make the avatar movement smoother when crossing.
3434 float timeStep = 0.1f; 3434 float timeStep = 0.1f;
3435 pos2.X = pos2.X + (vel.X * timeStep); 3435 pos2.X = pos2.X + (vel.X * timeStep);
3436 pos2.Y = pos2.Y + (vel.Y * timeStep); 3436 pos2.Y = pos2.Y + (vel.Y * timeStep);
@@ -3438,12 +3438,48 @@ namespace OpenSim.Region.Framework.Scenes
3438 3438
3439 if (!IsInTransit) 3439 if (!IsInTransit)
3440 { 3440 {
3441// m_log.DebugFormat( 3441 m_log.DebugFormat(
3442// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}", 3442 "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3443// pos2, Name, Scene.Name); 3443 pos2, Name, Scene.Name);
3444
3445 if (!m_scene.PositionIsInCurrentRegion(pos2))
3446 {
3447 // Disconnect from the current region
3448 bool isFlying = Flying;
3449 RemoveFromPhysicalScene();
3450 // pos2 is the forcasted position so make that the 'current' position so the crossing
3451 // code will move us into the newly addressed region.
3452 m_pos = pos2;
3453 if (CrossToNewRegion())
3454 {
3455 AddToPhysicalScene(isFlying);
3456 }
3457 else
3458 {
3459 // Tried to make crossing happen but it failed.
3460 if (m_requestedSitTargetUUID == UUID.Zero)
3461 {
3462
3463 Vector3 pos = AbsolutePosition;
3464 if (AbsolutePosition.X < 0)
3465 pos.X += Velocity.X * 2;
3466 else if (AbsolutePosition.X > m_scene.RegionInfo.RegionSizeX)
3467 pos.X -= Velocity.X * 2;
3468 if (AbsolutePosition.Y < 0)
3469 pos.Y += Velocity.Y * 2;
3470 else if (AbsolutePosition.Y > m_scene.RegionInfo.RegionSizeY)
3471 pos.Y -= Velocity.Y * 2;
3472 Velocity = Vector3.Zero;
3473 AbsolutePosition = pos;
3474
3475 AddToPhysicalScene(isFlying);
3476 }
3477 }
3478
3479 }
3444 3480
3481 /*
3445 // Checks if where it's headed exists a region 3482 // Checks if where it's headed exists a region
3446 bool needsTransit = false;
3447 if (m_scene.TestBorderCross(pos2, Cardinals.W)) 3483 if (m_scene.TestBorderCross(pos2, Cardinals.W))
3448 { 3484 {
3449 if (m_scene.TestBorderCross(pos2, Cardinals.S)) 3485 if (m_scene.TestBorderCross(pos2, Cardinals.S))
@@ -3504,11 +3540,11 @@ namespace OpenSim.Region.Framework.Scenes
3504 Vector3 pos = AbsolutePosition; 3540 Vector3 pos = AbsolutePosition;
3505 if (AbsolutePosition.X < 0) 3541 if (AbsolutePosition.X < 0)
3506 pos.X += Velocity.X * 2; 3542 pos.X += Velocity.X * 2;
3507 else if (AbsolutePosition.X > Constants.RegionSize) 3543 else if (AbsolutePosition.X > m_scene.RegionInfo.RegionSizeX)
3508 pos.X -= Velocity.X * 2; 3544 pos.X -= Velocity.X * 2;
3509 if (AbsolutePosition.Y < 0) 3545 if (AbsolutePosition.Y < 0)
3510 pos.Y += Velocity.Y * 2; 3546 pos.Y += Velocity.Y * 2;
3511 else if (AbsolutePosition.Y > Constants.RegionSize) 3547 else if (AbsolutePosition.Y > m_scene.RegionInfo.RegionSizeY)
3512 pos.Y -= Velocity.Y * 2; 3548 pos.Y -= Velocity.Y * 2;
3513 Velocity = Vector3.Zero; 3549 Velocity = Vector3.Zero;
3514 AbsolutePosition = pos; 3550 AbsolutePosition = pos;
@@ -3531,11 +3567,11 @@ namespace OpenSim.Region.Framework.Scenes
3531 Vector3 pos = AbsolutePosition; 3567 Vector3 pos = AbsolutePosition;
3532 if (AbsolutePosition.X < 0) 3568 if (AbsolutePosition.X < 0)
3533 pos.X += Velocity.X * 2; 3569 pos.X += Velocity.X * 2;
3534 else if (AbsolutePosition.X > Constants.RegionSize) 3570 else if (AbsolutePosition.X > m_scene.RegionInfo.RegionSizeX)
3535 pos.X -= Velocity.X * 2; 3571 pos.X -= Velocity.X * 2;
3536 if (AbsolutePosition.Y < 0) 3572 if (AbsolutePosition.Y < 0)
3537 pos.Y += Velocity.Y * 2; 3573 pos.Y += Velocity.Y * 2;
3538 else if (AbsolutePosition.Y > Constants.RegionSize) 3574 else if (AbsolutePosition.Y > m_scene.RegionInfo.RegionSizeY)
3539 pos.Y -= Velocity.Y * 2; 3575 pos.Y -= Velocity.Y * 2;
3540 Velocity = Vector3.Zero; 3576 Velocity = Vector3.Zero;
3541 AbsolutePosition = pos; 3577 AbsolutePosition = pos;
@@ -3544,6 +3580,7 @@ namespace OpenSim.Region.Framework.Scenes
3544 } 3580 }
3545 } 3581 }
3546 } 3582 }
3583 */
3547 } 3584 }
3548 else 3585 else
3549 { 3586 {
@@ -3584,7 +3621,7 @@ namespace OpenSim.Region.Framework.Scenes
3584 3621
3585 // Put the child agent back at the center 3622 // Put the child agent back at the center
3586 AbsolutePosition 3623 AbsolutePosition
3587 = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70); 3624 = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
3588 3625
3589 Animator.ResetAnimations(); 3626 Animator.ResetAnimations();
3590 } 3627 }
@@ -3611,9 +3648,7 @@ namespace OpenSim.Region.Framework.Scenes
3611 if (handle != Scene.RegionInfo.RegionHandle) 3648 if (handle != Scene.RegionInfo.RegionHandle)
3612 { 3649 {
3613 uint x, y; 3650 uint x, y;
3614 Utils.LongToUInts(handle, out x, out y); 3651 Util.RegionHandleToRegionLoc(handle, out x, out y);
3615 x = x / Constants.RegionSize;
3616 y = y / Constants.RegionSize;
3617 3652
3618// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); 3653// 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))); 3654// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
@@ -3694,8 +3729,9 @@ namespace OpenSim.Region.Framework.Scenes
3694 return; 3729 return;
3695 3730
3696 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); 3731 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
3697 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; 3732 // Find the distance (in meters) between the two regions
3698 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; 3733 uint shiftx = Util.RegionToWorldLoc(rRegionX - tRegionX);
3734 uint shifty = Util.RegionToWorldLoc(rRegionY - tRegionY);
3699 3735
3700 Vector3 offset = new Vector3(shiftx, shifty, 0f); 3736 Vector3 offset = new Vector3(shiftx, shifty, 0f);
3701 3737
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}