aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs7
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs11
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs12
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs88
-rw-r--r--OpenSim/Region/ClientStack/RegionApplicationBase.cs6
-rw-r--r--OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs20
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs673
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs5
-rw-r--r--OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs26
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs9
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs6
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs3
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs86
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs318
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs187
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs34
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs34
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs49
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs63
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs436
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs241
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs41
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs5
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJ2KDecoder.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs16
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs141
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs30
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs160
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainChannel.cs278
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainCompressor.cs944
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs5
-rw-r--r--OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs2
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs11
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs13
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs5
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs6
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs9
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionConnections.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs19
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs7
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs10
65 files changed, 2744 insertions, 1394 deletions
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 308638c..0dc9306 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -690,7 +690,8 @@ namespace OpenSim
690 clientServer = clientNetworkServers; 690 clientServer = clientNetworkServers;
691 scene.LoadWorldMap(); 691 scene.LoadWorldMap();
692 692
693 scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName); 693 Vector3 regionExtent = new Vector3(regionInfo.RegionSizeX, regionInfo.RegionSizeY, regionInfo.RegionSizeZ);
694 scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName, regionExtent);
694 scene.PhysicsScene.RequestAssetMethod = scene.PhysicsRequestAsset; 695 scene.PhysicsScene.RequestAssetMethod = scene.PhysicsRequestAsset;
695 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); 696 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
696 scene.PhysicsScene.SetWaterLevel((float) regionInfo.RegionSettings.WaterHeight); 697 scene.PhysicsScene.SetWaterLevel((float) regionInfo.RegionSettings.WaterHeight);
@@ -752,10 +753,10 @@ namespace OpenSim
752 753
753 # region Setup methods 754 # region Setup methods
754 755
755 protected override PhysicsScene GetPhysicsScene(string osSceneIdentifier) 756 protected override PhysicsScene GetPhysicsScene(string osSceneIdentifier, Vector3 regionExtent)
756 { 757 {
757 return GetPhysicsScene( 758 return GetPhysicsScene(
758 m_configSettings.PhysicsEngine, m_configSettings.MeshEngineName, Config, osSceneIdentifier); 759 m_configSettings.PhysicsEngine, m_configSettings.MeshEngineName, Config, osSceneIdentifier, regionExtent);
759 } 760 }
760 761
761 /// <summary> 762 /// <summary>
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index a05e88c..f98337d 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -59,6 +59,7 @@ namespace OpenSim.Region.ClientStack.Linden
59 public class EventQueueGetModule : IEventQueue, INonSharedRegionModule 59 public class EventQueueGetModule : IEventQueue, INonSharedRegionModule
60 { 60 {
61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62 private static string LogHeader = "[EVENT QUEUE GET MODULE]";
62 63
63 /// <value> 64 /// <value>
64 /// Debug level. 65 /// Debug level.
@@ -714,7 +715,7 @@ namespace OpenSim.Region.ClientStack.Linden
714 public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY) 715 public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY)
715 { 716 {
716 m_log.DebugFormat("{0} EnableSimulator. handle={1}, avatarID={2}, regionSize={3},{4}>", 717 m_log.DebugFormat("{0} EnableSimulator. handle={1}, avatarID={2}, regionSize={3},{4}>",
717 "[EVENT QUEUE GET MODULE]", handle, avatarID, regionSizeX, regionSizeY); 718 LogHeader, handle, avatarID, regionSizeX, regionSizeY);
718 719
719 OSD item = EventQueueHelper.EnableSimulator(handle, endPoint, regionSizeX, regionSizeY); 720 OSD item = EventQueueHelper.EnableSimulator(handle, endPoint, regionSizeX, regionSizeY);
720 Enqueue(item, avatarID); 721 Enqueue(item, avatarID);
@@ -724,7 +725,7 @@ namespace OpenSim.Region.ClientStack.Linden
724 ulong regionHandle, int regionSizeX, int regionSizeY) 725 ulong regionHandle, int regionSizeX, int regionSizeY)
725 { 726 {
726 m_log.DebugFormat("{0} EstablishAgentCommunication. handle={1}, avatarID={2}, regionSize={3},{4}>", 727 m_log.DebugFormat("{0} EstablishAgentCommunication. handle={1}, avatarID={2}, regionSize={3},{4}>",
727 "[EVENT QUEUE GET MODULE]", regionHandle, avatarID, regionSizeX, regionSizeY); 728 LogHeader, regionHandle, avatarID, regionSizeX, regionSizeY);
728 OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath, regionHandle, regionSizeX, regionSizeY); 729 OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath, regionHandle, regionSizeX, regionSizeY);
729 Enqueue(item, avatarID); 730 Enqueue(item, avatarID);
730 } 731 }
@@ -734,8 +735,8 @@ namespace OpenSim.Region.ClientStack.Linden
734 uint locationID, uint flags, string capsURL, 735 uint locationID, uint flags, string capsURL,
735 UUID avatarID, int regionSizeX, int regionSizeY) 736 UUID avatarID, int regionSizeX, int regionSizeY)
736 { 737 {
737 m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, avatarID={2}, regionSize={3},{4}>", 738 m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, avatarID={2}, regionSize=<{3},{4}>",
738 "[EVENT QUEUE GET MODULE]", regionHandle, avatarID, regionSizeX, regionSizeY); 739 LogHeader, regionHandle, avatarID, regionSizeX, regionSizeY);
739 740
740 OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint, 741 OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint,
741 locationID, flags, capsURL, avatarID, regionSizeX, regionSizeY); 742 locationID, flags, capsURL, avatarID, regionSizeX, regionSizeY);
@@ -747,7 +748,7 @@ namespace OpenSim.Region.ClientStack.Linden
747 string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY) 748 string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY)
748 { 749 {
749 m_log.DebugFormat("{0} CrossRegion. handle={1}, avatarID={2}, regionSize={3},{4}>", 750 m_log.DebugFormat("{0} CrossRegion. handle={1}, avatarID={2}, regionSize={3},{4}>",
750 "[EVENT QUEUE GET MODULE]", handle, avatarID, regionSizeX, regionSizeY); 751 LogHeader, handle, avatarID, regionSizeX, regionSizeY);
751 752
752 OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint, 753 OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint,
753 capsURL, avatarID, sessionID, regionSizeX, regionSizeY); 754 capsURL, avatarID, sessionID, regionSizeX, regionSizeY);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
index ded228d..384af74 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
@@ -77,8 +77,8 @@ namespace OpenSim.Region.ClientStack.Linden
77 llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle))); 77 llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle)));
78 llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes())); 78 llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes()));
79 llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port)); 79 llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port));
80 llsdSimInfo.Add("RegionSizeX", new OSDInteger(regionSizeX)); 80 llsdSimInfo.Add("RegionSizeX", OSD.FromUInteger((uint) regionSizeX));
81 llsdSimInfo.Add("RegionSizeY", new OSDInteger(regionSizeY)); 81 llsdSimInfo.Add("RegionSizeY", OSD.FromUInteger((uint) regionSizeY));
82 82
83 OSDArray arr = new OSDArray(1); 83 OSDArray arr = new OSDArray(1);
84 arr.Add(llsdSimInfo); 84 arr.Add(llsdSimInfo);
@@ -138,8 +138,8 @@ namespace OpenSim.Region.ClientStack.Linden
138 regionDataMap.Add("SeedCapability", OSD.FromString(capsURL)); 138 regionDataMap.Add("SeedCapability", OSD.FromString(capsURL));
139 regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes())); 139 regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes()));
140 regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port)); 140 regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port));
141 regionDataMap.Add("RegionSizeX", new OSDInteger(regionSizeX)); 141 regionDataMap.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX));
142 regionDataMap.Add("RegionSizeY", new OSDInteger(regionSizeY)); 142 regionDataMap.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY));
143 143
144 OSDArray regionDataArr = new OSDArray(1); 144 OSDArray regionDataArr = new OSDArray(1);
145 regionDataArr.Add(regionDataMap); 145 regionDataArr.Add(regionDataMap);
@@ -166,8 +166,8 @@ namespace OpenSim.Region.ClientStack.Linden
166 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes())); 166 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes()));
167 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port)); 167 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port));
168 info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation 168 info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation
169 info.Add("RegionSizeX", new OSDInteger(regionSizeX)); 169 info.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX));
170 info.Add("RegionSizeY", new OSDInteger(regionSizeY)); 170 info.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY));
171 171
172 OSDArray infoArr = new OSDArray(); 172 OSDArray infoArr = new OSDArray();
173 infoArr.Add(info); 173 infoArr.Add(info);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 3a0ddae..6861f5b 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -34,11 +34,13 @@ using System.Text;
34using System.Threading; 34using System.Threading;
35using System.Timers; 35using System.Timers;
36using System.Xml; 36using System.Xml;
37
37using log4net; 38using log4net;
38using OpenMetaverse; 39using OpenMetaverse;
39using OpenMetaverse.Packets; 40using OpenMetaverse.Packets;
40using OpenMetaverse.Messages.Linden; 41using OpenMetaverse.Messages.Linden;
41using OpenMetaverse.StructuredData; 42using OpenMetaverse.StructuredData;
43
42using OpenSim.Framework; 44using OpenSim.Framework;
43using OpenSim.Framework.Client; 45using OpenSim.Framework.Client;
44using OpenSim.Framework.Monitoring; 46using OpenSim.Framework.Monitoring;
@@ -48,7 +50,6 @@ using OpenSim.Services.Interfaces;
48using Timer = System.Timers.Timer; 50using Timer = System.Timers.Timer;
49using AssetLandmark = OpenSim.Framework.AssetLandmark; 51using AssetLandmark = OpenSim.Framework.AssetLandmark;
50using RegionFlags = OpenMetaverse.RegionFlags; 52using RegionFlags = OpenMetaverse.RegionFlags;
51using Nini.Config;
52 53
53using System.IO; 54using System.IO;
54using PermissionMask = OpenSim.Framework.PermissionMask; 55using PermissionMask = OpenSim.Framework.PermissionMask;
@@ -307,6 +308,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
307 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; 308 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
308 309
309 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 310 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
311 private static string LogHeader = "[LLCLIENTVIEW]";
310 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients 312 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
311 313
312 /// <summary> 314 /// <summary>
@@ -447,7 +449,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
447 449
448// ~LLClientView() 450// ~LLClientView()
449// { 451// {
450// m_log.DebugFormat("[LLCLIENTVIEW]: Destructor called for {0}, circuit code {1}", Name, CircuitCode); 452// m_log.DebugFormat("{0} Destructor called for {1}, circuit code {2}", LogHeader, Name, CircuitCode);
451// } 453// }
452 454
453 /// <summary> 455 /// <summary>
@@ -513,9 +515,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
513 // there is some unidentified connection problem, not where we have issues due to deadlock 515 // there is some unidentified connection problem, not where we have issues due to deadlock
514 if (!IsActive && !force) 516 if (!IsActive && !force)
515 { 517 {
516 m_log.DebugFormat( 518 m_log.DebugFormat( "{0} Not attempting to close inactive client {1} in {2} since force flag is not set",
517 "[CLIENT]: Not attempting to close inactive client {0} in {1} since force flag is not set", 519 LogHeader, Name, m_scene.Name);
518 Name, m_scene.Name);
519 520
520 return; 521 return;
521 } 522 }
@@ -1153,7 +1154,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1153 /// <param name="map">heightmap</param> 1154 /// <param name="map">heightmap</param>
1154 public virtual void SendLayerData(float[] map) 1155 public virtual void SendLayerData(float[] map)
1155 { 1156 {
1156 Util.FireAndForget(DoSendLayerData, map); 1157 Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData());
1157 } 1158 }
1158 1159
1159 /// <summary> 1160 /// <summary>
@@ -1162,10 +1163,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1162 /// <param name="o"></param> 1163 /// <param name="o"></param>
1163 private void DoSendLayerData(object o) 1164 private void DoSendLayerData(object o)
1164 { 1165 {
1165 float[] map = LLHeightFieldMoronize((float[])o); 1166 TerrainData map = (TerrainData)o;
1166 1167
1167 try 1168 try
1168 { 1169 {
1170 // Send LayerData in typerwriter pattern
1169 //for (int y = 0; y < 16; y++) 1171 //for (int y = 0; y < 16; y++)
1170 //{ 1172 //{
1171 // for (int x = 0; x < 16; x++) 1173 // for (int x = 0; x < 16; x++)
@@ -1175,7 +1177,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1175 //} 1177 //}
1176 1178
1177 // Send LayerData in a spiral pattern. Fun! 1179 // Send LayerData in a spiral pattern. Fun!
1178 SendLayerTopRight(map, 0, 0, 15, 15); 1180 SendLayerTopRight(map, 0, 0, map.SizeX/Constants.TerrainPatchSize-1, map.SizeY/Constants.TerrainPatchSize-1);
1179 } 1181 }
1180 catch (Exception e) 1182 catch (Exception e)
1181 { 1183 {
@@ -1183,7 +1185,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1183 } 1185 }
1184 } 1186 }
1185 1187
1186 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2) 1188 private void SendLayerTopRight(TerrainData map, int x1, int y1, int x2, int y2)
1187 { 1189 {
1188 // Row 1190 // Row
1189 for (int i = x1; i <= x2; i++) 1191 for (int i = x1; i <= x2; i++)
@@ -1193,11 +1195,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1193 for (int j = y1 + 1; j <= y2; j++) 1195 for (int j = y1 + 1; j <= y2; j++)
1194 SendLayerData(x2, j, map); 1196 SendLayerData(x2, j, map);
1195 1197
1196 if (x2 - x1 > 0) 1198 if (x2 - x1 > 0 && y2 - y1 > 0)
1197 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2); 1199 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1198 } 1200 }
1199 1201
1200 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2) 1202 void SendLayerBottomLeft(TerrainData map, int x1, int y1, int x2, int y2)
1201 { 1203 {
1202 // Row in reverse 1204 // Row in reverse
1203 for (int i = x2; i >= x1; i--) 1205 for (int i = x2; i >= x1; i--)
@@ -1207,7 +1209,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1207 for (int j = y2 - 1; j >= y1; j--) 1209 for (int j = y2 - 1; j >= y1; j--)
1208 SendLayerData(x1, j, map); 1210 SendLayerData(x1, j, map);
1209 1211
1210 if (x2 - x1 > 0) 1212 if (x2 - x1 > 0 && y2 - y1 > 0)
1211 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1); 1213 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1212 } 1214 }
1213 1215
@@ -1229,22 +1231,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1229 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1231 // OutPacket(layerpack, ThrottleOutPacketType.Land);
1230 // } 1232 // }
1231 1233
1234 // Legacy form of invocation that passes around a bare data array.
1235 // Just ignore what was passed and use the real terrain info that is part of the scene.
1236 public void SendLayerData(int px, int py, float[] map)
1237 {
1238 SendLayerData(px, py, m_scene.Heightmap.GetTerrainData());
1239 }
1240
1232 /// <summary> 1241 /// <summary>
1233 /// Sends a specified patch to a client 1242 /// Sends a terrain packet for the point specified.
1243 /// This is a legacy call that has refarbed the terrain into a flat map of floats.
1244 /// We just use the terrain from the region we know about.
1234 /// </summary> 1245 /// </summary>
1235 /// <param name="px">Patch coordinate (x) 0..15</param> 1246 /// <param name="px">Patch coordinate (x) 0..15</param>
1236 /// <param name="py">Patch coordinate (y) 0..15</param> 1247 /// <param name="py">Patch coordinate (y) 0..15</param>
1237 /// <param name="map">heightmap</param> 1248 /// <param name="map">heightmap</param>
1238 public void SendLayerData(int px, int py, float[] map) 1249 public void SendLayerData(int px, int py, TerrainData terrData)
1239 { 1250 {
1240 try 1251 try
1241 { 1252 {
1242 int[] patches = new int[] { py * 16 + px }; 1253 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, px, py);
1243 float[] heightmap = (map.Length == 65536) ?
1244 map :
1245 LLHeightFieldMoronize(map);
1246
1247 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1248 1254
1249 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience. 1255 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience.
1250 // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain. 1256 // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain.
@@ -1262,14 +1268,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1262 if (m_justEditedTerrain) 1268 if (m_justEditedTerrain)
1263 { 1269 {
1264 layerpack.Header.Reliable = false; 1270 layerpack.Header.Reliable = false;
1265 OutPacket(layerpack, 1271 OutPacket(layerpack, ThrottleOutPacketType.Unknown );
1266 ThrottleOutPacketType.Unknown );
1267 } 1272 }
1268 else 1273 else
1269 { 1274 {
1270 layerpack.Header.Reliable = true; 1275 layerpack.Header.Reliable = true;
1271 OutPacket(layerpack, 1276 OutPacket(layerpack, ThrottleOutPacketType.Land);
1272 ThrottleOutPacketType.Land);
1273 } 1277 }
1274 } 1278 }
1275 catch (Exception e) 1279 catch (Exception e)
@@ -1279,38 +1283,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1279 } 1283 }
1280 1284
1281 /// <summary> 1285 /// <summary>
1282 /// Munges heightfield into the LLUDP backed in restricted heightfield.
1283 /// </summary>
1284 /// <param name="map">float array in the base; Constants.RegionSize</param>
1285 /// <returns>float array in the base 256</returns>
1286 internal float[] LLHeightFieldMoronize(float[] map)
1287 {
1288 if (map.Length == 65536)
1289 return map;
1290 else
1291 {
1292 float[] returnmap = new float[65536];
1293
1294 if (map.Length < 65535)
1295 {
1296 // rebase the vector stride to 256
1297 for (int i = 0; i < Constants.RegionSize; i++)
1298 Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, (int)Constants.RegionSize);
1299 }
1300 else
1301 {
1302 for (int i = 0; i < 256; i++)
1303 Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256);
1304 }
1305
1306 //Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536);
1307
1308 return returnmap;
1309 }
1310
1311 }
1312
1313 /// <summary>
1314 /// Send the wind matrix to the client 1286 /// Send the wind matrix to the client
1315 /// </summary> 1287 /// </summary>
1316 /// <param name="windSpeeds">16x16 array of wind speeds</param> 1288 /// <param name="windSpeeds">16x16 array of wind speeds</param>
@@ -2785,8 +2757,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2785 { 2757 {
2786 if (req.AssetInf.Data == null) 2758 if (req.AssetInf.Data == null)
2787 { 2759 {
2788 m_log.ErrorFormat("Cannot send asset {0} ({1}), asset data is null", 2760 m_log.ErrorFormat("{0} Cannot send asset {1} ({2}), asset data is null",
2789 req.AssetInf.ID, req.AssetInf.Metadata.ContentType); 2761 LogHeader, req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
2790 return; 2762 return;
2791 } 2763 }
2792 2764
diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
index 853b72d..1ce166e 100644
--- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs
+++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
@@ -69,7 +69,7 @@ namespace OpenSim.Region.ClientStack
69 /// The name of the OpenSim scene this physics scene is serving. This will be used in log messages. 69 /// The name of the OpenSim scene this physics scene is serving. This will be used in log messages.
70 /// </param> 70 /// </param>
71 /// <returns></returns> 71 /// <returns></returns>
72 protected abstract PhysicsScene GetPhysicsScene(string osSceneIdentifier); 72 protected abstract PhysicsScene GetPhysicsScene(string osSceneIdentifier, Vector3 regionExtent);
73 73
74 protected abstract ClientStackManager CreateClientStackManager(); 74 protected abstract ClientStackManager CreateClientStackManager();
75 protected abstract Scene CreateScene(RegionInfo regionInfo, ISimulationDataService simDataService, IEstateDataService estateDataService, AgentCircuitManager circuitManager); 75 protected abstract Scene CreateScene(RegionInfo regionInfo, ISimulationDataService simDataService, IEstateDataService estateDataService, AgentCircuitManager circuitManager);
@@ -123,13 +123,13 @@ namespace OpenSim.Region.ClientStack
123 /// </param> 123 /// </param>
124 /// <returns></returns> 124 /// <returns></returns>
125 protected PhysicsScene GetPhysicsScene( 125 protected PhysicsScene GetPhysicsScene(
126 string engine, string meshEngine, IConfigSource config, string osSceneIdentifier) 126 string engine, string meshEngine, IConfigSource config, string osSceneIdentifier, Vector3 regionExtent)
127 { 127 {
128 PhysicsPluginManager physicsPluginManager; 128 PhysicsPluginManager physicsPluginManager;
129 physicsPluginManager = new PhysicsPluginManager(); 129 physicsPluginManager = new PhysicsPluginManager();
130 physicsPluginManager.LoadPluginsFromAssemblies("Physics"); 130 physicsPluginManager.LoadPluginsFromAssemblies("Physics");
131 131
132 return physicsPluginManager.GetPhysicsScene(engine, meshEngine, config, osSceneIdentifier); 132 return physicsPluginManager.GetPhysicsScene(engine, meshEngine, config, osSceneIdentifier, regionExtent);
133 } 133 }
134 } 134 }
135} \ No newline at end of file 135} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
index d9b0eff..732781a 100644
--- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing;
30using System.IO; 31using System.IO;
31using System.Reflection; 32using System.Reflection;
32using System.Text; 33using System.Text;
@@ -182,6 +183,25 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
182 return DoJ2KDecode(assetID, j2kData, out layers, out components); 183 return DoJ2KDecode(assetID, j2kData, out layers, out components);
183 } 184 }
184 185
186 public Image DecodeToImage(byte[] j2kData)
187 {
188 if (m_useCSJ2K)
189 return J2kImage.FromBytes(j2kData);
190 else
191 {
192 ManagedImage mimage;
193 Image image;
194 if (OpenJPEG.DecodeToImage(j2kData, out mimage, out image))
195 {
196 mimage = null;
197 return image;
198 }
199 else
200 return null;
201 }
202 }
203
204
185 #endregion IJ2KDecoder 205 #endregion IJ2KDecoder
186 206
187 /// <summary> 207 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 27ace68..10122e6 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -189,8 +189,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
189 string message = c.Message; 189 string message = c.Message;
190 Scene scene = (Scene)c.Scene; 190 Scene scene = (Scene)c.Scene;
191 Vector3 fromPos = c.Position; 191 Vector3 fromPos = c.Position;
192 Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, 192 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0);
193 scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
194 193
195 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; 194 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel;
196 195
@@ -342,8 +341,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
342 { 341 {
343 Vector3 fromRegionPos = fromPos + regionPos; 342 Vector3 fromRegionPos = fromPos + regionPos;
344 Vector3 toRegionPos = presence.AbsolutePosition + 343 Vector3 toRegionPos = presence.AbsolutePosition +
345 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize, 344 new Vector3(presence.Scene.RegionInfo.WorldLocX, presence.Scene.RegionInfo.WorldLocY, 0);
346 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
347 345
348 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos); 346 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
349 347
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
index bfa30e6..7e50cc6 100644
--- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -667,8 +667,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
667 667
668 Vector3 avaPos = p.AbsolutePosition; 668 Vector3 avaPos = p.AbsolutePosition;
669 // Getting the global position for the Avatar 669 // Getting the global position for the Avatar
670 Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.RegionLocX*Constants.RegionSize + avaPos.X, 670 Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.WorldLocX + avaPos.X,
671 remoteClient.Scene.RegionInfo.RegionLocY*Constants.RegionSize + avaPos.Y, 671 remoteClient.Scene.RegionInfo.WorldLocY + avaPos.Y,
672 avaPos.Z); 672 avaPos.Z);
673 673
674 string landOwnerName = string.Empty; 674 string landOwnerName = string.Empty;
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index 6545a99..13cc99a 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -269,9 +269,7 @@ namespace OpenSim.Region.CoreModules.Framework
269 foreach (KeyValuePair<ulong, string> kvp in m_childrenSeeds[agentID]) 269 foreach (KeyValuePair<ulong, string> kvp in m_childrenSeeds[agentID])
270 { 270 {
271 uint x, y; 271 uint x, y;
272 Utils.LongToUInts(kvp.Key, out x, out y); 272 Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
273 x = x / Constants.RegionSize;
274 y = y / Constants.RegionSize;
275 m_log.Info(" >> "+x+", "+y+": "+kvp.Value); 273 m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
276 } 274 }
277 } 275 }
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 5fea0cf..85e8159 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EntityTransferModule")] 51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EntityTransferModule")]
52 public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule 52 public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule
53 { 53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]"; 55 private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]";
56 56
57 public const int DefaultMaxTransferDistance = 4095; 57 public const int DefaultMaxTransferDistance = 4095;
@@ -121,8 +121,53 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
121 /// </summary> 121 /// </summary>
122 private EntityTransferStateMachine m_entityTransferStateMachine; 122 private EntityTransferStateMachine m_entityTransferStateMachine;
123 123
124 private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions = 124 // For performance, we keed a cached of banned regions so we don't keep going
125 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); 125 // to the grid service.
126 private class BannedRegionCache
127 {
128 private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
129 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
130 ExpiringCache<ulong, DateTime> m_idCache;
131 DateTime m_banUntil;
132 public BannedRegionCache()
133 {
134 }
135 // Return 'true' if there is a valid ban entry for this agent in this region
136 public bool IfBanned(ulong pRegionHandle, UUID pAgentID)
137 {
138 bool ret = false;
139 if (m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
140 {
141 if (m_idCache.TryGetValue(pRegionHandle, out m_banUntil))
142 {
143 if (DateTime.Now < m_banUntil)
144 {
145 ret = true;
146 }
147 }
148 }
149 return ret;
150 }
151 // Add this agent in this region as a banned person
152 public void Add(ulong pRegionHandle, UUID pAgentID)
153 {
154 if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
155 {
156 m_idCache = new ExpiringCache<ulong, DateTime>();
157 m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(45));
158 }
159 m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
160 }
161 // Remove the agent from the region's banned list
162 public void Remove(ulong pRegionHandle, UUID pAgentID)
163 {
164 if (m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
165 {
166 m_idCache.Remove(pRegionHandle);
167 }
168 }
169 }
170 private BannedRegionCache m_bannedRegionCache = new BannedRegionCache();
126 171
127 private IEventQueue m_eqModule; 172 private IEventQueue m_eqModule;
128 private IRegionCombinerModule m_regionCombinerModule; 173 private IRegionCombinerModule m_regionCombinerModule;
@@ -337,6 +382,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
337 "[ENTITY TRANSFER MODULE]: Received teleport cancel request from {0} in {1}", client.Name, Scene.Name); 382 "[ENTITY TRANSFER MODULE]: Received teleport cancel request from {0} in {1}", client.Name, Scene.Name);
338 } 383 }
339 384
385 // Attempt to teleport the ScenePresence to the specified position in the specified region (spec'ed by its handle).
340 public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags) 386 public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
341 { 387 {
342 if (sp.Scene.Permissions.IsGridGod(sp.UUID)) 388 if (sp.Scene.Permissions.IsGridGod(sp.UUID))
@@ -434,10 +480,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
434 float posZLimit = 22; 480 float posZLimit = 22;
435 481
436 // TODO: Check other Scene HeightField 482 // TODO: Check other Scene HeightField
437 if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize) 483 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
438 {
439 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
440 }
441 484
442 float newPosZ = posZLimit + localAVHeight; 485 float newPosZ = posZLimit + localAVHeight;
443 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 486 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
@@ -481,7 +524,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
481 Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination) 524 Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination)
482 { 525 {
483 uint x = 0, y = 0; 526 uint x = 0, y = 0;
484 Utils.LongToUInts(regionHandle, out x, out y); 527 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
485 GridRegion reg = Scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y); 528 GridRegion reg = Scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);
486 529
487 if (reg != null) 530 if (reg != null)
@@ -490,9 +533,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
490 533
491 if (finalDestination == null) 534 if (finalDestination == null)
492 { 535 {
493 m_log.WarnFormat( 536 m_log.WarnFormat( "{0} Final destination is having problems. Unable to teleport {1} {2}",
494 "[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport {0} {1}", 537 LogHeader, sp.Name, sp.UUID);
495 sp.Name, sp.UUID);
496 538
497 sp.ControllingClient.SendTeleportFailed("Problem at destination"); 539 sp.ControllingClient.SendTeleportFailed("Problem at destination");
498 return; 540 return;
@@ -533,11 +575,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
533 575
534 // and set the map-tile to '(Offline)' 576 // and set the map-tile to '(Offline)'
535 uint regX, regY; 577 uint regX, regY;
536 Utils.LongToUInts(regionHandle, out regX, out regY); 578 Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY);
537 579
538 MapBlockData block = new MapBlockData(); 580 MapBlockData block = new MapBlockData();
539 block.X = (ushort)(regX / Constants.RegionSize); 581 block.X = (ushort)regX;
540 block.Y = (ushort)(regY / Constants.RegionSize); 582 block.Y = (ushort)regY;
541 block.Access = 254; // == not there 583 block.Access = 254; // == not there
542 584
543 List<MapBlockData> blocks = new List<MapBlockData>(); 585 List<MapBlockData> blocks = new List<MapBlockData>();
@@ -1349,6 +1391,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1349 if (uinfo.HomeRegionID == UUID.Zero) 1391 if (uinfo.HomeRegionID == UUID.Zero)
1350 { 1392 {
1351 // can't find the Home region: Tell viewer and abort 1393 // can't find the Home region: Tell viewer and abort
1394 m_log.ErrorFormat("{0} No grid user info found for {1} {2}. Cannot send home.",
1395 LogHeader, client.Name, client.AgentId);
1352 client.SendTeleportFailed("You don't have a home position set."); 1396 client.SendTeleportFailed("You don't have a home position set.");
1353 return false; 1397 return false;
1354 } 1398 }
@@ -1382,7 +1426,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1382 1426
1383 #region Agent Crossings 1427 #region Agent Crossings
1384 1428
1385 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos) 1429 // Given a position relative to the current region (which has previously been tested to
1430 // see that it is actually outside the current region), find the new region that the
1431 // point is actually in.
1432 // Returns the coordinates and information of the new region or 'null' of it doesn't exist.
1433 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos)
1386 { 1434 {
1387 version = String.Empty; 1435 version = String.Empty;
1388 newpos = pos; 1436 newpos = pos;
@@ -1390,131 +1438,54 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1390// m_log.DebugFormat( 1438// m_log.DebugFormat(
1391// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); 1439// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
1392 1440
1393 uint neighbourx = scene.RegionInfo.RegionLocX; 1441 // Compute world location of the object's position
1394 uint neighboury = scene.RegionInfo.RegionLocY; 1442 double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X;
1395 const float boundaryDistance = 1.7f; 1443 double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y;
1396 Vector3 northCross = new Vector3(0, boundaryDistance, 0);
1397 Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0);
1398 Vector3 eastCross = new Vector3(boundaryDistance, 0, 0);
1399 Vector3 westCross = new Vector3(-1 * boundaryDistance, 0, 0);
1400 1444
1401 // distance into new region to place avatar 1445 // Call the grid service to lookup the region containing the new position.
1402 const float enterDistance = 0.5f; 1446 GridRegion neighbourRegion = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID,
1447 presenceWorldX, presenceWorldY,
1448 Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY));
1403 1449
1404 if (scene.TestBorderCross(pos + westCross, Cardinals.W)) 1450 if (neighbourRegion != null)
1405 { 1451 {
1406 if (scene.TestBorderCross(pos + northCross, Cardinals.N)) 1452 // Compute the entity's position relative to the new region
1407 { 1453 newpos = new Vector3( (float)(presenceWorldX - (double)neighbourRegion.RegionLocX),
1408 Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N); 1454 (float)(presenceWorldY - (double)neighbourRegion.RegionLocY),
1409 neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize); 1455 pos.Z);
1410 }
1411 else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
1412 {
1413 neighboury--;
1414 newpos.Y = Constants.RegionSize - enterDistance;
1415 }
1416
1417 neighbourx--;
1418 newpos.X = Constants.RegionSize - enterDistance;
1419 }
1420 else if (scene.TestBorderCross(pos + eastCross, Cardinals.E))
1421 {
1422 Border b = scene.GetCrossedBorder(pos + eastCross, Cardinals.E);
1423 neighbourx += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
1424 newpos.X = enterDistance;
1425 1456
1426 if (scene.TestBorderCross(pos + southCross, Cardinals.S)) 1457 if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID))
1427 { 1458 {
1428 neighboury--; 1459 neighbourRegion = null;
1429 newpos.Y = Constants.RegionSize - enterDistance;
1430 } 1460 }
1431 else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) 1461 else
1432 { 1462 {
1433 Border c = scene.GetCrossedBorder(pos + northCross, Cardinals.N); 1463 // If not banned, make sure this agent is not in the list.
1434 neighboury += (uint)(int)(c.BorderLine.Z / (int)Constants.RegionSize); 1464 m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
1435 newpos.Y = enterDistance;
1436 } 1465 }
1437 }
1438 else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
1439 {
1440 Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S);
1441 neighboury--;
1442 newpos.Y = Constants.RegionSize - enterDistance;
1443 }
1444 else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
1445 {
1446 Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
1447 neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
1448 newpos.Y = enterDistance;
1449 }
1450
1451 /*
1452
1453 if (pos.X < boundaryDistance) //West
1454 {
1455 neighbourx--;
1456 newpos.X = Constants.RegionSize - enterDistance;
1457 }
1458 else if (pos.X > Constants.RegionSize - boundaryDistance) // East
1459 {
1460 neighbourx++;
1461 newpos.X = enterDistance;
1462 }
1463
1464 if (pos.Y < boundaryDistance) // South
1465 {
1466 neighboury--;
1467 newpos.Y = Constants.RegionSize - enterDistance;
1468 }
1469 else if (pos.Y > Constants.RegionSize - boundaryDistance) // North
1470 {
1471 neighboury++;
1472 newpos.Y = enterDistance;
1473 }
1474 */
1475
1476 xDest = neighbourx;
1477 yDest = neighboury;
1478
1479 int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize);
1480 1466
1481 ulong neighbourHandle = Utils.UIntsToLong((uint)x, (uint)y); 1467 // Check to see if we have access to the target region.
1482 1468 string reason;
1483 ExpiringCache<ulong, DateTime> r; 1469 if (neighbourRegion != null
1484 DateTime banUntil; 1470 && !scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason))
1485
1486 if (m_bannedRegions.TryGetValue(agentID, out r))
1487 {
1488 if (r.TryGetValue(neighbourHandle, out banUntil))
1489 { 1471 {
1490 if (DateTime.Now < banUntil) 1472 // remember banned
1491 return null; 1473 m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
1492 r.Remove(neighbourHandle); 1474 neighbourRegion = null;
1493 } 1475 }
1494 } 1476 }
1495 else
1496 {
1497 r = null;
1498 }
1499
1500 GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
1501 1477
1502 string reason; 1478 if (neighbourRegion == null)
1503 if (!scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason)) 1479 m_log.DebugFormat("{0} GetDestination: region not found. Old region name={1} at <{2},{3}> of size <{4},{5}>. Old pos={6}",
1504 { 1480 LogHeader, scene.RegionInfo.RegionName,
1505 if (r == null) 1481 scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
1506 { 1482 scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY,
1507 r = new ExpiringCache<ulong, DateTime>(); 1483 pos);
1508 r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); 1484 else
1509 1485 m_log.DebugFormat("{0} GetDestination: new region={1} at <{2},{3}> of size <{4},{5}>, newpos=<{6},{7}>",
1510 m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(45)); 1486 LogHeader, neighbourRegion.RegionName,
1511 } 1487 neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY,
1512 else 1488 newpos.X, newpos.Y);
1513 {
1514 r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
1515 }
1516 return null;
1517 }
1518 1489
1519 return neighbourRegion; 1490 return neighbourRegion;
1520 } 1491 }
@@ -1526,7 +1497,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1526 Vector3 newpos; 1497 Vector3 newpos;
1527 string version; 1498 string version;
1528 1499
1529 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, out x, out y, out version, out newpos); 1500 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, out version, out newpos);
1530 if (neighbourRegion == null) 1501 if (neighbourRegion == null)
1531 { 1502 {
1532 agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel"); 1503 agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel");
@@ -1568,7 +1539,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1568 1539
1569 agent.Scene.RequestTeleportLocation( 1540 agent.Scene.RequestTeleportLocation(
1570 agent.ControllingClient, 1541 agent.ControllingClient,
1571 Utils.UIntsToLong(regionX * (uint)Constants.RegionSize, regionY * (uint)Constants.RegionSize), 1542 Util.RegionLocToHandle(regionX, regionY),
1572 position, 1543 position,
1573 agent.Lookat, 1544 agent.Lookat,
1574 (uint)Constants.TeleportFlags.ViaLocation); 1545 (uint)Constants.TeleportFlags.ViaLocation);
@@ -1578,11 +1549,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1578 if (im != null) 1549 if (im != null)
1579 { 1550 {
1580 UUID gotoLocation = Util.BuildFakeParcelID( 1551 UUID gotoLocation = Util.BuildFakeParcelID(
1581 Util.UIntsToLong( 1552 Util.RegionLocToHandle(regionX, regionY),
1582 (regionX *
1583 (uint)Constants.RegionSize),
1584 (regionY *
1585 (uint)Constants.RegionSize)),
1586 (uint)(int)position.X, 1553 (uint)(int)position.X,
1587 (uint)(int)position.Y, 1554 (uint)(int)position.Y,
1588 (uint)(int)position.Z); 1555 (uint)(int)position.Z);
@@ -1635,17 +1602,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1635 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 1602 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
1636 /// </summary> 1603 /// </summary>
1637 public ScenePresence CrossAgentToNewRegionAsync( 1604 public ScenePresence CrossAgentToNewRegionAsync(
1638 ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, 1605 ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
1639 bool isFlying, string version) 1606 bool isFlying, string version)
1640 { 1607 {
1608 m_log.DebugFormat("{0} CrossAgentToNewRegionAsync: new region={1} at <{2},{3}>. newpos={4}",
1609 LogHeader, neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, pos);
1610
1641 if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) 1611 if (!CrossAgentToNewRegionPrep(agent, neighbourRegion))
1642 { 1612 {
1613 m_log.DebugFormat("{0} CrossAgentToNewRegionAsync: prep failed. Resetting transfer state", LogHeader);
1643 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1614 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1644 return agent; 1615 return agent;
1645 } 1616 }
1646 1617
1647 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying)) 1618 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying))
1648 { 1619 {
1620 m_log.DebugFormat("{0} CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader);
1649 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1621 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1650 return agent; 1622 return agent;
1651 } 1623 }
@@ -2038,15 +2010,195 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2038 } 2010 }
2039 } 2011 }
2040 2012
2013 // Computes the difference between two region bases.
2014 // Returns a vector of world coordinates (meters) from base of first region to the second.
2015 // The first region is the home region of the passed scene presence.
2041 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour) 2016 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour)
2042 { 2017 {
2043 int rRegionX = (int)sp.Scene.RegionInfo.RegionLocX; 2018 /*
2044 int rRegionY = (int)sp.Scene.RegionInfo.RegionLocY; 2019 int rRegionX = (int)sp.Scene.RegionInfo.LegacyRegionLocX;
2020 int rRegionY = (int)sp.Scene.RegionInfo.LegacyRegionLocY;
2045 int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize; 2021 int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize;
2046 int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize; 2022 int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize;
2047 int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize; 2023 int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize;
2048 int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize; 2024 int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize;
2049 return new Vector3(shiftx, shifty, 0f); 2025 return new Vector3(shiftx, shifty, 0f);
2026 */
2027 return new Vector3( sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
2028 sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY,
2029 0f);
2030 }
2031
2032 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
2033 {
2034 // Since we don't know how big the regions could be, we have to search a very large area
2035 // to find possible regions.
2036 return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
2037 }
2038
2039 #region NotFoundLocationCache class
2040 // A collection of not found locations to make future lookups 'not found' lookups quick.
2041 // A simple expiring cache that keeps not found locations for some number of seconds.
2042 // A 'not found' location is presumed to be anywhere in the minimum sized region that
2043 // contains that point. A conservitive estimate.
2044 private class NotFoundLocationCache
2045 {
2046 private struct NotFoundLocation
2047 {
2048 public double minX, maxX, minY, maxY;
2049 public DateTime expireTime;
2050 }
2051 private List<NotFoundLocation> m_notFoundLocations = new List<NotFoundLocation>();
2052 public NotFoundLocationCache()
2053 {
2054 }
2055 // Add an area to the lost of 'not found' places. The area is the snapped region
2056 // area around the added point.
2057 public void Add(double pX, double pY)
2058 {
2059 lock (m_notFoundLocations)
2060 {
2061 if (!LockedContains(pX, pY))
2062 {
2063 NotFoundLocation nfl = new NotFoundLocation();
2064 // A not found location is not found for at least a whole region sized area
2065 nfl.minX = pX - (pX % (double)Constants.RegionSize);
2066 nfl.minY = pY - (pY % (double)Constants.RegionSize);
2067 nfl.maxX = nfl.minX + (double)Constants.RegionSize;
2068 nfl.maxY = nfl.minY + (double)Constants.RegionSize;
2069 nfl.expireTime = DateTime.Now + TimeSpan.FromSeconds(30);
2070 m_notFoundLocations.Add(nfl);
2071 }
2072 }
2073
2074 }
2075 // Test to see of this point is in any of the 'not found' areas.
2076 // Return 'true' if the point is found inside the 'not found' areas.
2077 public bool Contains(double pX, double pY)
2078 {
2079 bool ret = false;
2080 lock (m_notFoundLocations)
2081 ret = LockedContains(pX, pY);
2082 return ret;
2083 }
2084 private bool LockedContains(double pX, double pY)
2085 {
2086 bool ret = false;
2087 this.DoExpiration();
2088 foreach (NotFoundLocation nfl in m_notFoundLocations)
2089 {
2090 if (pX >= nfl.minX && pX < nfl.maxX && pY >= nfl.minY && pY < nfl.maxY)
2091 {
2092 ret = true;
2093 break;
2094 }
2095 }
2096 return ret;
2097 }
2098 private void DoExpiration()
2099 {
2100 List<NotFoundLocation> m_toRemove = null;
2101 DateTime now = DateTime.Now;
2102 foreach (NotFoundLocation nfl in m_notFoundLocations)
2103 {
2104 if (nfl.expireTime < now)
2105 {
2106 if (m_toRemove == null)
2107 m_toRemove = new List<NotFoundLocation>();
2108 m_toRemove.Add(nfl);
2109 }
2110 }
2111 if (m_toRemove != null)
2112 {
2113 foreach (NotFoundLocation nfl in m_toRemove)
2114 m_notFoundLocations.Remove(nfl);
2115 m_toRemove.Clear();
2116 }
2117 }
2118 }
2119 #endregion // NotFoundLocationCache class
2120 private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache();
2121
2122 // Given a world position (fractional meter coordinate), get the GridRegion info for
2123 // the region containing that point.
2124 // Someday this should be a method on GridService.
2125 // 'pSizeHint' is the size of the source region but since the destination point can be anywhere
2126 // the size of the target region is unknown thus the search area might have to be very large.
2127 // Return 'null' if no such region exists.
2128 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID,
2129 double px, double py, uint pSizeHint)
2130 {
2131 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py);
2132 GridRegion ret = null;
2133 const double fudge = 2.0;
2134
2135 // One problem with this routine is negative results. That is, this can be called lots of times
2136 // for regions that don't exist. m_notFoundLocationCache remembers 'not found' results so they
2137 // will be quick 'not found's next time.
2138 // NotFoundLocationCache is an expiring cache so it will eventually forget about 'not found' and
2139 // thus re-ask the GridService about the location.
2140 if (m_notFoundLocationCache.Contains(px, py))
2141 {
2142 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py);
2143 return null;
2144 }
2145
2146 // As an optimization, since most regions will be legacy sized regions (256x256), first try to get
2147 // the region at the appropriate legacy region location.
2148 uint possibleX = (uint)Math.Floor(px);
2149 possibleX -= possibleX % Constants.RegionSize;
2150 uint possibleY = (uint)Math.Floor(py);
2151 possibleY -= possibleY % Constants.RegionSize;
2152 ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (int)possibleY);
2153 if (ret != null)
2154 {
2155 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}",
2156 LogHeader, possibleX, possibleY, ret.RegionName);
2157 }
2158
2159 if (ret == null)
2160 {
2161 // If the simple lookup failed, search the larger area for a region that contains this point
2162 double range = (double)pSizeHint + fudge;
2163 while (ret == null && range <= (Constants.MaximumRegionSize + Constants.RegionSize))
2164 {
2165 // Get from the grid service a list of regions that might contain this point.
2166 // The region origin will be in the zero direction so only subtract the range.
2167 List<GridRegion> possibleRegions = pGridService.GetRegionRange(pScopeID,
2168 (int)(px - range), (int)(px),
2169 (int)(py - range), (int)(py));
2170 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}",
2171 LogHeader, possibleRegions.Count, range);
2172 if (possibleRegions != null && possibleRegions.Count > 0)
2173 {
2174 // If we found some regions, check to see if the point is within
2175 foreach (GridRegion gr in possibleRegions)
2176 {
2177 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>",
2178 LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY);
2179 if (px >= (double)gr.RegionLocX && px < (double)(gr.RegionLocX + gr.RegionSizeX)
2180 && py >= (double)gr.RegionLocY && py < (double)(gr.RegionLocY + gr.RegionSizeY))
2181 {
2182 // Found a region that contains the point
2183 ret = gr;
2184 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName);
2185 break;
2186 }
2187 }
2188 }
2189 // Larger search area for next time around if not found
2190 range *= 2;
2191 }
2192 }
2193
2194 if (ret == null)
2195 {
2196 // remember this location was not found so we can quickly not find it next time
2197 m_notFoundLocationCache.Add(px, py);
2198 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found. Remembering loc=<{1},{2}>", LogHeader, px, py);
2199 }
2200
2201 return ret;
2050 } 2202 }
2051 2203
2052 private void InformClientOfNeighbourCompleted(IAsyncResult iar) 2204 private void InformClientOfNeighbourCompleted(IAsyncResult iar)
@@ -2168,16 +2320,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2168 // view to include everything in the megaregion 2320 // view to include everything in the megaregion
2169 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) 2321 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
2170 { 2322 {
2171 int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance; 2323 // The area to check is as big as the current region.
2324 // We presume all adjacent regions are the same size as this region.
2325 uint dd = Math.Max((uint)avatar.DrawDistance,
2326 Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
2172 2327
2173 int startX = (int)pRegionLocX * (int)Constants.RegionSize - dd + (int)(Constants.RegionSize/2); 2328 uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2;
2174 int startY = (int)pRegionLocY * (int)Constants.RegionSize - dd + (int)(Constants.RegionSize/2); 2329 uint startY = Util.RegionToWorldLoc(pRegionLocY) - dd + Constants.RegionSize/2;
2175 2330
2176 int endX = (int)pRegionLocX * (int)Constants.RegionSize + dd + (int)(Constants.RegionSize/2); 2331 uint endX = Util.RegionToWorldLoc(pRegionLocX) + dd + Constants.RegionSize/2;
2177 int endY = (int)pRegionLocY * (int)Constants.RegionSize + dd + (int)(Constants.RegionSize/2); 2332 uint endY = Util.RegionToWorldLoc(pRegionLocY) + dd + Constants.RegionSize/2;
2178 2333
2179 List<GridRegion> neighbours = 2334 List<GridRegion> neighbours =
2180 avatar.Scene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY); 2335 avatar.Scene.GridService.GetRegionRange(m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY);
2181 2336
2182 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; }); 2337 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
2183 return neighbours; 2338 return neighbours;
@@ -2190,10 +2345,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2190 List<GridRegion> neighbours 2345 List<GridRegion> neighbours
2191 = pScene.GridService.GetRegionRange( 2346 = pScene.GridService.GetRegionRange(
2192 m_regionInfo.ScopeID, 2347 m_regionInfo.ScopeID,
2193 (int)swCorner.X * (int)Constants.RegionSize, 2348 (int)Util.RegionToWorldLoc((uint)swCorner.X), (int)Util.RegionToWorldLoc((uint)neCorner.X),
2194 (int)neCorner.X * (int)Constants.RegionSize, 2349 (int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y) );
2195 (int)swCorner.Y * (int)Constants.RegionSize,
2196 (int)neCorner.Y * (int)Constants.RegionSize);
2197 2350
2198 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; }); 2351 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
2199 2352
@@ -2256,10 +2409,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2256 /// Move the given scene object into a new region depending on which region its absolute position has moved 2409 /// Move the given scene object into a new region depending on which region its absolute position has moved
2257 /// into. 2410 /// into.
2258 /// 2411 ///
2259 /// This method locates the new region handle and offsets the prim position for the new region 2412 /// Using the objects new world location, ask the grid service for a the new region and adjust the prim
2413 /// position to be relative to the new region.
2260 /// </summary> 2414 /// </summary>
2261 /// <param name="attemptedPosition">the attempted out of region position of the scene object</param>
2262 /// <param name="grp">the scene object that we're crossing</param> 2415 /// <param name="grp">the scene object that we're crossing</param>
2416 /// <param name="attemptedPosition">the attempted out of region position of the scene object. This position is
2417 /// relative to the region the object currently is in.</param>
2418 /// <param name="silent">if 'true', the deletion of the client from the region is not broadcast to the clients</param>
2263 public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent) 2419 public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent)
2264 { 2420 {
2265 if (grp == null) 2421 if (grp == null)
@@ -2285,208 +2441,49 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2285 return; 2441 return;
2286 } 2442 }
2287 2443
2288 int thisx = (int)scene.RegionInfo.RegionLocX; 2444 // Remember the old group position in case the region lookup fails so position can be restored.
2289 int thisy = (int)scene.RegionInfo.RegionLocY; 2445 Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
2290 Vector3 EastCross = new Vector3(0.1f, 0, 0);
2291 Vector3 WestCross = new Vector3(-0.1f, 0, 0);
2292 Vector3 NorthCross = new Vector3(0, 0.1f, 0);
2293 Vector3 SouthCross = new Vector3(0, -0.1f, 0);
2294
2295
2296 // use this if no borders were crossed!
2297 ulong newRegionHandle
2298 = Util.UIntsToLong((uint)((thisx) * Constants.RegionSize),
2299 (uint)((thisy) * Constants.RegionSize));
2300
2301 Vector3 pos = attemptedPosition;
2302
2303 int changeX = 1;
2304 int changeY = 1;
2305
2306 if (scene.TestBorderCross(attemptedPosition + WestCross, Cardinals.W))
2307 {
2308 if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
2309 {
2310
2311 Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
2312
2313 if (crossedBorderx.BorderLine.Z > 0)
2314 {
2315 pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
2316 changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
2317 }
2318 else
2319 pos.X = ((pos.X + Constants.RegionSize));
2320
2321 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
2322 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
2323
2324 if (crossedBordery.BorderLine.Z > 0)
2325 {
2326 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
2327 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
2328 }
2329 else
2330 pos.Y = ((pos.Y + Constants.RegionSize));
2331
2332
2333
2334 newRegionHandle
2335 = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
2336 (uint)((thisy - changeY) * Constants.RegionSize));
2337 // x - 1
2338 // y - 1
2339 }
2340 else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
2341 {
2342 Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
2343
2344 if (crossedBorderx.BorderLine.Z > 0)
2345 {
2346 pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
2347 changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
2348 }
2349 else
2350 pos.X = ((pos.X + Constants.RegionSize));
2351
2352 2446
2353 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); 2447 // Compute the absolute position of the object.
2354 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize) 2448 double objectWorldLocX = (double)scene.RegionInfo.WorldLocX + attemptedPosition.X;
2449 double objectWorldLocY = (double)scene.RegionInfo.WorldLocY + attemptedPosition.Y;
2355 2450
2356 if (crossedBordery.BorderLine.Z > 0) 2451 // Ask the grid service for the region that contains the passed address
2357 { 2452 GridRegion destination = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID,
2358 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z)); 2453 objectWorldLocX, objectWorldLocY);
2359 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
2360 }
2361 else
2362 pos.Y = ((pos.Y + Constants.RegionSize));
2363 2454
2364 newRegionHandle 2455 Vector3 pos = Vector3.Zero;
2365 = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize), 2456 if (destination != null)
2366 (uint)((thisy + changeY) * Constants.RegionSize));
2367 // x - 1
2368 // y + 1
2369 }
2370 else
2371 {
2372 Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
2373
2374 if (crossedBorderx.BorderLine.Z > 0)
2375 {
2376 pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
2377 changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
2378 }
2379 else
2380 pos.X = ((pos.X + Constants.RegionSize));
2381
2382 newRegionHandle
2383 = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
2384 (uint)(thisy * Constants.RegionSize));
2385 // x - 1
2386 }
2387 }
2388 else if (scene.TestBorderCross(attemptedPosition + EastCross, Cardinals.E))
2389 { 2457 {
2390 if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S)) 2458 // Adjust the object's relative position from the old region (attemptedPosition)
2391 { 2459 // to be relative to the new region (pos).
2392 2460 pos = new Vector3( (float)(objectWorldLocX - (double)destination.RegionLocX),
2393 pos.X = ((pos.X - Constants.RegionSize)); 2461 (float)(objectWorldLocY - (double)destination.RegionLocY),
2394 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S); 2462 attemptedPosition.Z);
2395 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
2396
2397 if (crossedBordery.BorderLine.Z > 0)
2398 {
2399 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
2400 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
2401 }
2402 else
2403 pos.Y = ((pos.Y + Constants.RegionSize));
2404
2405
2406 newRegionHandle
2407 = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
2408 (uint)((thisy - changeY) * Constants.RegionSize));
2409 // x + 1
2410 // y - 1
2411 }
2412 else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
2413 {
2414 pos.X = ((pos.X - Constants.RegionSize));
2415 pos.Y = ((pos.Y - Constants.RegionSize));
2416 newRegionHandle
2417 = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
2418 (uint)((thisy + changeY) * Constants.RegionSize));
2419 // x + 1
2420 // y + 1
2421 }
2422 else
2423 {
2424 pos.X = ((pos.X - Constants.RegionSize));
2425 newRegionHandle
2426 = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
2427 (uint)(thisy * Constants.RegionSize));
2428 // x + 1
2429 }
2430 } 2463 }
2431 else if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
2432 {
2433 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
2434 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
2435
2436 if (crossedBordery.BorderLine.Z > 0)
2437 {
2438 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
2439 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
2440 }
2441 else
2442 pos.Y = ((pos.Y + Constants.RegionSize));
2443 2464
2444 newRegionHandle 2465 if (destination == null || !CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
2445 = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize));
2446 // y - 1
2447 }
2448 else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
2449 { 2466 {
2467 m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}", grp.UUID);
2450 2468
2451 pos.Y = ((pos.Y - Constants.RegionSize)); 2469 // We are going to move the object back to the old position so long as the old position
2452 newRegionHandle 2470 // is in the region
2453 = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize)); 2471 oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 1.0f, (float)(scene.RegionInfo.RegionSizeX - 1));
2454 // y + 1 2472 oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 1.0f, (float)(scene.RegionInfo.RegionSizeY - 1));
2455 } 2473 oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 1.0f, Constants.RegionHeight);
2456 2474
2457 // Offset the positions for the new region across the border 2475 grp.AbsolutePosition = oldGroupPosition;
2458 Vector3 oldGroupPosition = grp.RootPart.GroupPosition; 2476 grp.Velocity = Vector3.Zero;
2477 if (grp.RootPart.PhysActor != null)
2478 grp.RootPart.PhysActor.CrossingFailure();
2459 2479
2460 // If we fail to cross the border, then reset the position of the scene object on that border. 2480 if (grp.RootPart.KeyframeMotion != null)
2461 uint x = 0, y = 0; 2481 grp.RootPart.KeyframeMotion.CrossingFailure();
2462 Utils.LongToUInts(newRegionHandle, out x, out y);
2463 GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
2464 2482
2465 if (destination != null) 2483 grp.ScheduleGroupForFullUpdate();
2466 {
2467 if (CrossPrimGroupIntoNewRegion(destination, pos, grp, silent))
2468 return; // we did it
2469 } 2484 }
2470
2471 // no one or failed lets go back and tell physics to go on
2472 oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 0.5f, (float)Constants.RegionSize - 0.5f);
2473 oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
2474 oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 0.5f, 4096.0f);
2475
2476 grp.AbsolutePosition = oldGroupPosition;
2477 grp.Velocity = Vector3.Zero;
2478
2479 if (grp.RootPart.PhysActor != null)
2480 grp.RootPart.PhysActor.CrossingFailure();
2481
2482 if (grp.RootPart.KeyframeMotion != null)
2483 grp.RootPart.KeyframeMotion.CrossingFailure();
2484
2485 grp.ScheduleGroupForFullUpdate();
2486 } 2485 }
2487 2486
2488
2489
2490 /// <summary> 2487 /// <summary>
2491 /// Move the given scene object into a new region 2488 /// Move the given scene object into a new region
2492 /// </summary> 2489 /// </summary>
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
index fc02916..6a04acf 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
@@ -77,6 +77,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
77 public class EntityTransferStateMachine 77 public class EntityTransferStateMachine
78 { 78 {
79 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 79 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
80 private static readonly string LogHeader = "[ENTITY TRANSFER STATE MACHINE]";
80 81
81 /// <summary> 82 /// <summary>
82 /// If true then on a teleport, the source region waits for a callback from the destination region. If 83 /// If true then on a teleport, the source region waits for a callback from the destination region. If
@@ -100,6 +101,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
100 /// <returns>true if the agent was not already in transit, false if it was</returns> 101 /// <returns>true if the agent was not already in transit, false if it was</returns>
101 internal bool SetInTransit(UUID id) 102 internal bool SetInTransit(UUID id)
102 { 103 {
104 m_log.DebugFormat("{0} SetInTransit. agent={1}, newState=Preparing", LogHeader, id);
103 lock (m_agentsInTransit) 105 lock (m_agentsInTransit)
104 { 106 {
105 if (!m_agentsInTransit.ContainsKey(id)) 107 if (!m_agentsInTransit.ContainsKey(id))
@@ -121,6 +123,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
121 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception> 123 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
122 internal bool UpdateInTransit(UUID id, AgentTransferState newState) 124 internal bool UpdateInTransit(UUID id, AgentTransferState newState)
123 { 125 {
126 m_log.DebugFormat("{0} UpdateInTransit. agent={1}, newState={2}", LogHeader, id, newState);
127
124 bool transitionOkay = false; 128 bool transitionOkay = false;
125 129
126 // We don't want to throw an exception on cancel since this can come it at any time. 130 // We don't want to throw an exception on cancel since this can come it at any time.
@@ -193,6 +197,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
193 } 197 }
194 else if (failIfNotOkay) 198 else if (failIfNotOkay)
195 { 199 {
200 m_log.DebugFormat("{0} UpdateInTransit. Throwing transition failure = {1}", LogHeader, failureMessage);
196 throw new Exception(failureMessage); 201 throw new Exception(failureMessage);
197 } 202 }
198// else 203// else
diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
index d943b20..4e7ad75 100644
--- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
@@ -213,8 +213,8 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
213 if (part != null) 213 if (part != null)
214 { 214 {
215 ObjectRegionName = s.RegionInfo.RegionName; 215 ObjectRegionName = s.RegionInfo.RegionName;
216 uint localX = (s.RegionInfo.RegionLocX * (int)Constants.RegionSize); 216 uint localX = s.RegionInfo.WorldLocX;
217 uint localY = (s.RegionInfo.RegionLocY * (int)Constants.RegionSize); 217 uint localY = s.RegionInfo.WorldLocY;
218 ObjectRegionName = ObjectRegionName + " (" + localX + ", " + localY + ")"; 218 ObjectRegionName = ObjectRegionName + " (" + localX + ", " + localY + ")";
219 return part; 219 return part;
220 } 220 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index 31ef79b..3b38c71 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -48,6 +48,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
48 private static readonly ILog m_log = 48 private static readonly ILog m_log =
49 LogManager.GetLogger( 49 LogManager.GetLogger(
50 MethodBase.GetCurrentMethod().DeclaringType); 50 MethodBase.GetCurrentMethod().DeclaringType);
51 private static string LogHeader = "[LOCAL GRID SERVICE CONNECTOR]";
51 52
52 private IGridService m_GridService; 53 private IGridService m_GridService;
53 private Dictionary<UUID, RegionCache> m_LocalCache = new Dictionary<UUID, RegionCache>(); 54 private Dictionary<UUID, RegionCache> m_LocalCache = new Dictionary<UUID, RegionCache>();
@@ -56,12 +57,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
56 57
57 public LocalGridServicesConnector() 58 public LocalGridServicesConnector()
58 { 59 {
59 m_log.Debug("[LOCAL GRID SERVICE CONNECTOR]: LocalGridServicesConnector no parms."); 60 m_log.DebugFormat("{0} LocalGridServicesConnector no parms.", LogHeader);
60 } 61 }
61 62
62 public LocalGridServicesConnector(IConfigSource source) 63 public LocalGridServicesConnector(IConfigSource source)
63 { 64 {
64 m_log.Debug("[LOCAL GRID SERVICE CONNECTOR]: LocalGridServicesConnector instantiated directly."); 65 m_log.DebugFormat("{0} LocalGridServicesConnector instantiated directly.", LogHeader);
65 InitialiseService(source); 66 InitialiseService(source);
66 } 67 }
67 68
@@ -192,6 +193,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
192 return m_GridService.GetRegionByUUID(scopeID, regionID); 193 return m_GridService.GetRegionByUUID(scopeID, regionID);
193 } 194 }
194 195
196 // Get a region given its base coordinates.
197 // NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST
198 // be the base coordinate of the region.
195 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) 199 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
196 { 200 {
197 GridRegion region = null; 201 GridRegion region = null;
@@ -206,13 +210,25 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
206 region = rcache.GetRegionByPosition(x, y); 210 region = rcache.GetRegionByPosition(x, y);
207 if (region != null) 211 if (region != null)
208 { 212 {
209 return region; 213 // m_log.DebugFormat("{0} GetRegionByPosition. Found region {1} in cache. Pos=<{2},{3}>",
214 // LogHeader, region.RegionName, x, y);
215 break;
210 } 216 }
211 } 217 }
212 } 218 }
213 219
214 // Then try on this sim (may be a lookup in DB if this is using MySql). 220 // Then try on this sim (may be a lookup in DB if this is using MySql).
215 return m_GridService.GetRegionByPosition(scopeID, x, y); 221 if (region == null)
222 {
223 region = m_GridService.GetRegionByPosition(scopeID, x, y);
224 if (region == null)
225 m_log.DebugFormat("{0} GetRegionByPosition. Region not found by grid service. Pos=<{1},{2}>",
226 LogHeader, x, y);
227 else
228 m_log.DebugFormat("{0} GetRegionByPosition. Requested region {1} from grid service. Pos=<{2},{3}>",
229 LogHeader, region.RegionName, x, y);
230 }
231 return region;
216 } 232 }
217 233
218 public GridRegion GetRegionByName(UUID scopeID, string regionName) 234 public GridRegion GetRegionByName(UUID scopeID, string regionName)
@@ -268,7 +284,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
268 caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key); 284 caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key);
269 List<GridRegion> regions = kvp.Value.GetNeighbours(); 285 List<GridRegion> regions = kvp.Value.GetNeighbours();
270 foreach (GridRegion r in regions) 286 foreach (GridRegion r in regions)
271 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, r.RegionLocX / Constants.RegionSize, r.RegionLocY / Constants.RegionSize); 287 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, Util.WorldToRegionLoc((uint)r.RegionLocX), Util.WorldToRegionLoc((uint)r.RegionLocY));
272 } 288 }
273 } 289 }
274 290
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
index 9172536..ae76288 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
@@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
66 return; 66 return;
67 67
68 m_log.DebugFormat("[REGION CACHE]: (on region {0}) Region {1} is up @ {2}-{3}", 68 m_log.DebugFormat("[REGION CACHE]: (on region {0}) Region {1} is up @ {2}-{3}",
69 m_scene.RegionInfo.RegionName, otherRegion.RegionName, otherRegion.RegionLocX / Constants.RegionSize, otherRegion.RegionLocY / Constants.RegionSize); 69 m_scene.RegionInfo.RegionName, otherRegion.RegionName, Util.WorldToRegionLoc((uint)otherRegion.RegionLocX), Util.WorldToRegionLoc((uint)otherRegion.RegionLocY));
70 70
71 m_neighbours[otherRegion.RegionHandle] = otherRegion; 71 m_neighbours[otherRegion.RegionHandle] = otherRegion;
72 } 72 }
@@ -82,11 +82,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
82 return new List<GridRegion>(m_neighbours.Values); 82 return new List<GridRegion>(m_neighbours.Values);
83 } 83 }
84 84
85 // Get a region given its base coordinates (in meters).
86 // NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST
87 // be the base coordinate of the region.
88 // The snapping is technically unnecessary but is harmless because regions are always
89 // multiples of the legacy region size (256).
85 public GridRegion GetRegionByPosition(int x, int y) 90 public GridRegion GetRegionByPosition(int x, int y)
86 { 91 {
87 uint xsnap = (uint)(x / Constants.RegionSize) * Constants.RegionSize; 92 uint xsnap = (uint)(x / Constants.RegionSize) * Constants.RegionSize;
88 uint ysnap = (uint)(y / Constants.RegionSize) * Constants.RegionSize; 93 uint ysnap = (uint)(y / Constants.RegionSize) * Constants.RegionSize;
89 ulong handle = Utils.UIntsToLong(xsnap, ysnap); 94 ulong handle = Util.RegionWorldLocToHandle(xsnap, ysnap);
90 95
91 if (m_neighbours.ContainsKey(handle)) 96 if (m_neighbours.ContainsKey(handle))
92 return m_neighbours[handle]; 97 return m_neighbours[handle];
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
index 6a57d1f..ae5081c 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
@@ -186,10 +186,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
186 return rinfo; 186 return rinfo;
187 } 187 }
188 188
189 // Get a region given its base world coordinates (in meters).
190 // NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST
191 // be the base coordinate of the region.
192 // The coordinates are world coords (meters), NOT region units.
189 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) 193 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
190 { 194 {
191 bool inCache = false; 195 bool inCache = false;
192 GridRegion rinfo = m_RegionInfoCache.Get(scopeID, Util.UIntsToLong((uint)x, (uint)y), out inCache); 196 GridRegion rinfo = m_RegionInfoCache.Get(scopeID, Util.RegionWorldLocToHandle((uint)x, (uint)y), out inCache);
193 if (inCache) 197 if (inCache)
194 return rinfo; 198 return rinfo;
195 199
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
index 4338133..25ae689 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
@@ -34,6 +34,7 @@ using log4net.Config;
34using Nini.Config; 34using Nini.Config;
35using NUnit.Framework; 35using NUnit.Framework;
36using OpenMetaverse; 36using OpenMetaverse;
37
37using OpenSim.Framework; 38using OpenSim.Framework;
38using OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid; 39using OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid;
39using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
@@ -141,7 +142,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
141 Assert.IsNotNull(result, "Retrieved GetRegionByUUID is null"); 142 Assert.IsNotNull(result, "Retrieved GetRegionByUUID is null");
142 Assert.That(result.RegionID, Is.EqualTo(new UUID(1)), "Retrieved region's UUID does not match"); 143 Assert.That(result.RegionID, Is.EqualTo(new UUID(1)), "Retrieved region's UUID does not match");
143 144
144 result = m_LocalConnector.GetRegionByPosition(UUID.Zero, 1000 * (int)Constants.RegionSize, 1000 * (int)Constants.RegionSize); 145 result = m_LocalConnector.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc(1000), (int)Util.RegionToWorldLoc(1000));
145 Assert.IsNotNull(result, "Retrieved GetRegionByPosition is null"); 146 Assert.IsNotNull(result, "Retrieved GetRegionByPosition is null");
146 Assert.That(result.RegionLocX, Is.EqualTo(1000 * (int)Constants.RegionSize), "Retrieved region's position does not match"); 147 Assert.That(result.RegionLocX, Is.EqualTo(1000 * (int)Constants.RegionSize), "Retrieved region's position does not match");
147 148
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
index 26d22b8..4d7538c 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
@@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
57 { 57 {
58 private static readonly ILog m_log = 58 private static readonly ILog m_log =
59 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 59 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60 private static string LogHeader = "[MAP IMAGE SERVICE MODULE]";
60 61
61 private bool m_enabled = false; 62 private bool m_enabled = false;
62 private IMapImageService m_MapService; 63 private IMapImageService m_MapService;
@@ -192,42 +193,85 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
192 ///</summary> 193 ///</summary>
193 private void UploadMapTile(IScene scene) 194 private void UploadMapTile(IScene scene)
194 { 195 {
195 m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: upload maptile for {0}", scene.RegionInfo.RegionName); 196 m_log.DebugFormat("{0} Upload maptile for {1}", LogHeader, scene.RegionInfo.RegionName);
197 string regionName = scene.RegionInfo.RegionName;
196 198
197 // Create a JPG map tile and upload it to the AddMapTile API 199 // Create a JPG map tile and upload it to the AddMapTile API
198 byte[] jpgData = Utils.EmptyBytes;
199 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>(); 200 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>();
200 if (tileGenerator == null) 201 if (tileGenerator == null)
201 { 202 {
202 m_log.Warn("[MAP IMAGE SERVICE MODULE]: Cannot upload PNG map tile without an ImageGenerator"); 203 m_log.WarnFormat("{0} Cannot upload map tile without an ImageGenerator", LogHeader);
203 return; 204 return;
204 } 205 }
205 206 using (Bitmap mapTile = tileGenerator.CreateMapTile())
206 using (Image mapTile = tileGenerator.CreateMapTile())
207 { 207 {
208 // XXX: The MapImageModule will return a null if the user has chosen not to create map tiles and there 208 if (mapTile != null)
209 // is no static map tile. 209 {
210 if (mapTile == null) 210 // mapTile.Save( // DEBUG DEBUG
211 return; 211 // String.Format("maptiles/raw-{0}-{1}-{2}.jpg", regionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY),
212 212 // ImageFormat.Jpeg);
213 using (MemoryStream stream = new MemoryStream()) 213 // If the region/maptile is legacy sized, just upload the one tile like it has always been done
214 if (mapTile.Width == Constants.RegionSize && mapTile.Height == Constants.RegionSize)
215 {
216 ConvertAndUploadMaptile(mapTile,
217 scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
218 scene.RegionInfo.RegionName);
219 }
220 else
221 {
222 // For larger regions (varregion) we must cut the region image into legacy sized
223 // pieces since that is how the maptile system works.
224 // Note the assumption that varregions are always a multiple of legacy size.
225 for (uint xx = 0; xx < mapTile.Width; xx += Constants.RegionSize)
226 {
227 for (uint yy = 0; yy < mapTile.Height; yy += Constants.RegionSize)
228 {
229 // Images are addressed from the upper left corner so have to do funny
230 // math to pick out the sub-tile since regions are numbered from
231 // the lower left.
232 Rectangle rect = new Rectangle(
233 (int)xx,
234 mapTile.Height - (int)yy - (int)Constants.RegionSize,
235 (int)Constants.RegionSize, (int)Constants.RegionSize);
236 using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat))
237 {
238 ConvertAndUploadMaptile(subMapTile,
239 scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize),
240 scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize),
241 regionName);
242 }
243 }
244 }
245 }
246 }
247 else
214 { 248 {
215 mapTile.Save(stream, ImageFormat.Jpeg); 249 m_log.WarnFormat("{0} Tile image generation failed", LogHeader);
216 jpgData = stream.ToArray();
217 } 250 }
218 } 251 }
252 }
219 253
220 if (jpgData == Utils.EmptyBytes) 254 private void ConvertAndUploadMaptile(Image tileImage, uint locX, uint locY, string regionName)
255 {
256 byte[] jpgData = Utils.EmptyBytes;
257
258 using (MemoryStream stream = new MemoryStream())
221 { 259 {
222 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Tile image generation failed"); 260 tileImage.Save(stream, ImageFormat.Jpeg);
223 return; 261 jpgData = stream.ToArray();
224 } 262 }
225 263 if (jpgData != Utils.EmptyBytes)
226 string reason = string.Empty; 264 {
227 if (!m_MapService.AddMapTile((int)scene.RegionInfo.RegionLocX, (int)scene.RegionInfo.RegionLocY, jpgData, out reason)) 265 string reason = string.Empty;
266 if (!m_MapService.AddMapTile((int)locX, (int)locY, jpgData, out reason))
267 {
268 m_log.DebugFormat("{0} Unable to upload tile image for {1} at {2}-{3}: {4}", LogHeader,
269 regionName, locX, locY, reason);
270 }
271 }
272 else
228 { 273 {
229 m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: Unable to upload tile image for {0} at {1}-{2}: {3}", 274 m_log.WarnFormat("{0} Tile image generation failed for region {1}", LogHeader, regionName);
230 scene.RegionInfo.RegionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, reason);
231 } 275 }
232 } 276 }
233 } 277 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
index fd89428..56d9937 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
@@ -132,7 +132,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour
132 if (s.RegionInfo.RegionHandle == regionHandle) 132 if (s.RegionInfo.RegionHandle == regionHandle)
133 { 133 {
134 m_log.DebugFormat("[LOCAL NEIGHBOUR SERVICE CONNECTOR]: HelloNeighbour from region {0} to neighbour {1} at {2}-{3}", 134 m_log.DebugFormat("[LOCAL NEIGHBOUR SERVICE CONNECTOR]: HelloNeighbour from region {0} to neighbour {1} at {2}-{3}",
135 thisRegion.RegionName, s.Name, x / Constants.RegionSize, y / Constants.RegionSize); 135 thisRegion.RegionName, s.Name, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y) );
136 136
137 //m_log.Debug("[NEIGHBOUR CONNECTOR]: Found region to SendHelloNeighbour"); 137 //m_log.Debug("[NEIGHBOUR CONNECTOR]: Found region to SendHelloNeighbour");
138 return s.IncomingHelloNeighbour(thisRegion); 138 return s.IncomingHelloNeighbour(thisRegion);
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index a990898..9f39aa2 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -533,7 +533,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
533 if (isMegaregion) 533 if (isMegaregion)
534 size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID); 534 size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID);
535 else 535 else
536 size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize); 536 size = new Vector2((float)scene.RegionInfo.RegionSizeX, (float)scene.RegionInfo.RegionSizeY);
537 537
538 xtw.WriteElementString("is_megaregion", isMegaregion.ToString()); 538 xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
539 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); 539 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 73c4d6c..99db7ff 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -64,6 +64,7 @@ namespace OpenSim.Region.CoreModules.World.Land
64 public class LandManagementModule : INonSharedRegionModule 64 public class LandManagementModule : INonSharedRegionModule
65 { 65 {
66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
67 private static readonly string LogHeader = "[LAND MANAGEMENT MODULE]";
67 68
68 private static readonly string remoteParcelRequestPath = "0009/"; 69 private static readonly string remoteParcelRequestPath = "0009/";
69 70
@@ -74,15 +75,11 @@ namespace OpenSim.Region.CoreModules.World.Land
74 protected IPrimCountModule m_primCountModule; 75 protected IPrimCountModule m_primCountModule;
75 protected IDialogModule m_Dialog; 76 protected IDialogModule m_Dialog;
76 77
77 // Minimum for parcels to work is 64m even if we don't actually use them.
78 #pragma warning disable 0429
79 private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64;
80 #pragma warning restore 0429
81
82 /// <value> 78 /// <value>
83 /// Local land ids at specified region co-ordinates (region size / 4) 79 /// Local land ids at specified region co-ordinates (region size / 4)
84 /// </value> 80 /// </value>
85 private readonly int[,] m_landIDList = new int[landArrayMax, landArrayMax]; 81 private int[,] m_landIDList;
82 private const int landUnit = 4;
86 83
87 /// <value> 84 /// <value>
88 /// Land objects keyed by local id 85 /// Land objects keyed by local id
@@ -115,6 +112,8 @@ namespace OpenSim.Region.CoreModules.World.Land
115 public void AddRegion(Scene scene) 112 public void AddRegion(Scene scene)
116 { 113 {
117 m_scene = scene; 114 m_scene = scene;
115 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
116
118 m_landIDList.Initialize(); 117 m_landIDList.Initialize();
119 landChannel = new LandChannel(scene, this); 118 landChannel = new LandChannel(scene, this);
120 119
@@ -297,6 +296,7 @@ namespace OpenSim.Region.CoreModules.World.Land
297 { 296 {
298 m_landList.Clear(); 297 m_landList.Clear();
299 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; 298 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
299 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
300 m_landIDList.Initialize(); 300 m_landIDList.Initialize();
301 } 301 }
302 } 302 }
@@ -311,7 +311,8 @@ namespace OpenSim.Region.CoreModules.World.Land
311 "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName); 311 "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName);
312 312
313 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); 313 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
314 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); 314 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0,
315 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY));
315 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 316 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
316 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); 317 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
317 318
@@ -438,8 +439,8 @@ namespace OpenSim.Region.CoreModules.World.Land
438 439
439 public void SendLandUpdate(ScenePresence avatar, bool force) 440 public void SendLandUpdate(ScenePresence avatar, bool force)
440 { 441 {
441 ILandObject over = GetLandObject((int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), 442 ILandObject over = GetLandObject((int)Math.Min(((int)m_scene.RegionInfo.RegionSizeX - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))),
442 (int)Math.Min(((int)Constants.RegionSize - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y)))); 443 (int)Math.Min(((int)m_scene.RegionInfo.RegionSizeY - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y))));
443 444
444 if (over != null) 445 if (over != null)
445 { 446 {
@@ -605,17 +606,29 @@ namespace OpenSim.Region.CoreModules.World.Land
605 new_land.LandData.LocalID = newLandLocalID; 606 new_land.LandData.LocalID = newLandLocalID;
606 607
607 bool[,] landBitmap = new_land.GetLandBitmap(); 608 bool[,] landBitmap = new_land.GetLandBitmap();
608 for (int x = 0; x < landArrayMax; x++) 609 // m_log.DebugFormat("{0} AddLandObject. new_land.bitmapSize=({1},{2}). newLocalID={3}",
610 // LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), newLandLocalID);
611
612 if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1))
609 { 613 {
610 for (int y = 0; y < landArrayMax; y++) 614 // Going to variable sized regions can cause mismatches
615 m_log.ErrorFormat("{0} AddLandObject. Added land bitmap different size than region ID map. bitmapSize=({1},{2}), landIDSize=({3},{4})",
616 LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1) );
617 }
618 else
619 {
620 for (int x = 0; x < landBitmap.GetLength(0); x++)
611 { 621 {
612 if (landBitmap[x, y]) 622 for (int y = 0; y < landBitmap.GetLength(1); y++)
613 { 623 {
614// m_log.DebugFormat( 624 if (landBitmap[x, y])
615// "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}", 625 {
616// new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName); 626 // m_log.DebugFormat(
617 627 // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}",
618 m_landIDList[x, y] = newLandLocalID; 628 // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName);
629
630 m_landIDList[x, y] = newLandLocalID;
631 }
619 } 632 }
620 } 633 }
621 } 634 }
@@ -637,9 +650,9 @@ namespace OpenSim.Region.CoreModules.World.Land
637 ILandObject land; 650 ILandObject land;
638 lock (m_landList) 651 lock (m_landList)
639 { 652 {
640 for (int x = 0; x < 64; x++) 653 for (int x = 0; x < m_landIDList.GetLength(0); x++)
641 { 654 {
642 for (int y = 0; y < 64; y++) 655 for (int y = 0; y < m_landIDList.GetLength(1); y++)
643 { 656 {
644 if (m_landIDList[x, y] == local_id) 657 if (m_landIDList[x, y] == local_id)
645 { 658 {
@@ -691,9 +704,9 @@ namespace OpenSim.Region.CoreModules.World.Land
691 bool[,] landBitmapSlave = slave.GetLandBitmap(); 704 bool[,] landBitmapSlave = slave.GetLandBitmap();
692 lock (m_landList) 705 lock (m_landList)
693 { 706 {
694 for (int x = 0; x < 64; x++) 707 for (int x = 0; x < landBitmapSlave.GetLength(0); x++)
695 { 708 {
696 for (int y = 0; y < 64; y++) 709 for (int y = 0; y < landBitmapSlave.GetLength(1); y++)
697 { 710 {
698 if (landBitmapSlave[x, y]) 711 if (landBitmapSlave[x, y])
699 { 712 {
@@ -727,23 +740,28 @@ namespace OpenSim.Region.CoreModules.World.Land
727 /// <returns>Land object at the point supplied</returns> 740 /// <returns>Land object at the point supplied</returns>
728 public ILandObject GetLandObject(float x_float, float y_float) 741 public ILandObject GetLandObject(float x_float, float y_float)
729 { 742 {
743 return GetLandObject((int)x_float, (int)y_float, true /* returnNullIfLandObjectNotFound */);
744 /*
730 int x; 745 int x;
731 int y; 746 int y;
732 747
733 if (x_float >= Constants.RegionSize || x_float < 0 || y_float >= Constants.RegionSize || y_float < 0) 748 if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0)
734 return null; 749 return null;
735 750
736 try 751 try
737 { 752 {
738 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / 4.0)); 753 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit));
739 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / 4.0)); 754 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit));
740 } 755 }
741 catch (OverflowException) 756 catch (OverflowException)
742 { 757 {
743 return null; 758 return null;
744 } 759 }
745 760
746 if (x >= 64 || y >= 64 || x < 0 || y < 0) 761 if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit)
762 || y >= (m_scene.RegionInfo.RegionSizeY / landUnit)
763 || x < 0
764 || y < 0)
747 { 765 {
748 return null; 766 return null;
749 } 767 }
@@ -759,38 +777,122 @@ namespace OpenSim.Region.CoreModules.World.Land
759// m_log.DebugFormat( 777// m_log.DebugFormat(
760// "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}", 778// "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}",
761// x, y, m_scene.RegionInfo.RegionName); 779// x, y, m_scene.RegionInfo.RegionName);
762 780
763 if (m_landList.ContainsKey(m_landIDList[x, y])) 781 try
764 return m_landList[m_landIDList[x, y]]; 782 {
783 if (m_landList.ContainsKey(m_landIDList[x, y]))
784 return m_landList[m_landIDList[x, y]];
785 }
786 catch (Exception e)
787 {
788 m_log.DebugFormat("{0} GetLandObject exception. x={1}, y={2}, m_landIDList.len=({3},{4})",
789 LogHeader, x, y, m_landIDList.GetLength(0), m_landIDList.GetLength(1));
790 }
765 791
766 return null; 792 return null;
767 } 793 }
794 */
768 } 795 }
769 796
797 // Public entry.
798 // Throws exception if land object is not found
770 public ILandObject GetLandObject(int x, int y) 799 public ILandObject GetLandObject(int x, int y)
771 { 800 {
772 if (x >= Convert.ToInt32(Constants.RegionSize) || y >= Convert.ToInt32(Constants.RegionSize) || x < 0 || y < 0) 801 return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */);
802 }
803
804 // Given a region position, return the parcel land object for that location
805 private ILandObject GetLandObject(int x, int y, bool returnNullIfLandObjectNotFound)
806 {
807 ILandObject ret = null;
808
809 if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0)
773 { 810 {
774 // These exceptions here will cause a lot of complaints from the users specifically because 811 // These exceptions here will cause a lot of complaints from the users specifically because
775 // they happen every time at border crossings 812 // they happen every time at border crossings
776 throw new Exception("Error: Parcel not found at point " + x + ", " + y); 813 if (returnNullIfLandObjectNotFound)
814 return null;
815 else
816 throw new Exception(
817 String.Format("{0} GetLandObject for non-existant position. Region={1}, pos=<{2},{3}",
818 LogHeader, m_scene.RegionInfo.RegionName, x, y)
819 );
777 } 820 }
778 821
779 lock (m_landIDList) 822 lock (m_landIDList)
780 { 823 {
781 try 824 try
782 { 825 {
783 return m_landList[m_landIDList[x / 4, y / 4]]; 826 int landID = m_landIDList[x / landUnit, y / landUnit];
827 if (landID == 0)
828 {
829 // Zero is the uninitialized value saying there is no parcel for this location.
830 // This sometimes happens when terrain is resized.
831 if (m_landList.Count == 1)
832 {
833 int onlyParcelID = 0;
834 ILandObject onlyLandObject = null;
835 foreach (KeyValuePair<int, ILandObject> kvp in m_landList)
836 {
837 onlyParcelID = kvp.Key;
838 onlyLandObject = kvp.Value;
839 break;
840 }
841
842 // There is only one parcel. Grow it to fill all the unallocated spaces.
843 for (int xx = 0; xx < m_landIDList.GetLength(0); xx++)
844 for (int yy = 0; yy < m_landIDList.GetLength(1); yy++)
845 if (m_landIDList[xx, yy] == 0)
846 m_landIDList[xx, yy] = onlyParcelID;
847
848 onlyLandObject.LandBitmap = CreateBitmapForID(onlyParcelID);
849 landID = onlyParcelID;
850 }
851 else
852 {
853 // There are several other parcels so we must create a new one for the unassigned space
854 ILandObject newLand = new LandObject(UUID.Zero, false, m_scene);
855 // Claim all the unclaimed "0" ids
856 newLand.SetLandBitmap(CreateBitmapForID(0));
857 newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
858 newLand.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
859 AddLandObject(newLand);
860 landID = m_lastLandLocalID;
861 }
862 }
863
864 ret = m_landList[landID];
784 } 865 }
785 catch (IndexOutOfRangeException) 866 catch (IndexOutOfRangeException)
786 { 867 {
787// m_log.WarnFormat( 868 m_log.ErrorFormat(
788// "[LAND MANAGEMENT MODULE]: Tried to retrieve land object from out of bounds co-ordinate ({0},{1}) in {2}", 869 "{0} GetLandObject: Tried to retrieve land object from out of bounds co-ordinate ({1},{2}) in {3}. landListSize=({4},{5})",
789// x, y, m_scene.RegionInfo.RegionName); 870 LogHeader, x, y, m_scene.RegionInfo.RegionName, m_landIDList.GetLength(0), m_landIDList.GetLength(1));
790 871 return null;
872 }
873 catch
874 {
875 m_log.ErrorFormat(
876 "{0} GetLandObject: LandID not in landlist. XY=<{1},{2}> in {3}. landID[x,y]={4}",
877 LogHeader, x, y, m_scene.RegionInfo.RegionName, m_landIDList[x/landUnit, y/landUnit]);
791 return null; 878 return null;
792 } 879 }
793 } 880 }
881 return ret;
882 }
883
884 // Create a 'parcel is here' bitmap for the parcel identified by the passed landID
885 private bool[,] CreateBitmapForID(int landID)
886 {
887 bool[,] ret = new bool[m_landIDList.GetLength(0), m_landIDList.GetLength(1)];
888 ret.Initialize();
889
890 for (int xx = 0; xx < m_landIDList.GetLength(0); xx++)
891 for (int yy = 0; yy < m_landIDList.GetLength(0); yy++)
892 if (m_landIDList[xx, yy] == landID)
893 ret[xx, yy] = true;
894
895 return ret;
794 } 896 }
795 897
796 #endregion 898 #endregion
@@ -1053,85 +1155,93 @@ namespace OpenSim.Region.CoreModules.World.Land
1053 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; 1155 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1054 int byteArrayCount = 0; 1156 int byteArrayCount = 0;
1055 int sequenceID = 0; 1157 int sequenceID = 0;
1056 int blockmeters = 4 * (int) Constants.RegionSize/(int)Constants.TerrainPatchSize;
1057
1058 1158
1059 for (int y = 0; y < blockmeters; y++) 1159 // Layer data is in landUnit (4m) chunks
1160 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / landUnit); y++)
1060 { 1161 {
1061 for (int x = 0; x < blockmeters; x++) 1162 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / landUnit); x++)
1062 { 1163 {
1063 byte tempByte = 0; //This represents the byte for the current 4x4 1164 byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * landUnit, y * landUnit), x, y, remote_client);
1165 byteArrayCount++;
1166 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
1167 {
1168 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1169 byteArrayCount = 0;
1170 sequenceID++;
1171 byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1172 }
1064 1173
1065 ILandObject currentParcelBlock = GetLandObject(x * 4, y * 4); 1174 }
1175 }
1176 if (byteArrayCount != 0)
1177 {
1178 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1179 }
1180 }
1066 1181
1067 if (currentParcelBlock != null) 1182 private byte BuildLayerByte(ILandObject currentParcelBlock, int x, int y, IClientAPI remote_client)
1068 { 1183 {
1069 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) 1184 byte tempByte = 0; //This represents the byte for the current 4x4
1070 {
1071 //Owner Flag
1072 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
1073 }
1074 else if (currentParcelBlock.LandData.SalePrice > 0 &&
1075 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1076 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
1077 {
1078 //Sale Flag
1079 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE);
1080 }
1081 else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
1082 {
1083 //Public Flag
1084 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC);
1085 }
1086 else
1087 {
1088 //Other Flag
1089 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER);
1090 }
1091 1185
1092 //Now for border control 1186 if (currentParcelBlock != null)
1187 {
1188 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId)
1189 {
1190 //Owner Flag
1191 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER);
1192 }
1193 else if (currentParcelBlock.LandData.SalePrice > 0 &&
1194 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1195 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
1196 {
1197 //Sale Flag
1198 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE);
1199 }
1200 else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
1201 {
1202 //Public Flag
1203 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC);
1204 }
1205 else
1206 {
1207 //Other Flag
1208 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER);
1209 }
1093 1210
1094 ILandObject westParcel = null; 1211 //Now for border control
1095 ILandObject southParcel = null;
1096 if (x > 0)
1097 {
1098 westParcel = GetLandObject((x - 1) * 4, y * 4);
1099 }
1100 if (y > 0)
1101 {
1102 southParcel = GetLandObject(x * 4, (y - 1) * 4);
1103 }
1104 1212
1105 if (x == 0) 1213 ILandObject westParcel = null;
1106 { 1214 ILandObject southParcel = null;
1107 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); 1215 if (x > 0)
1108 } 1216 {
1109 else if (westParcel != null && westParcel != currentParcelBlock) 1217 westParcel = GetLandObject((x - 1) * landUnit, y * landUnit);
1110 { 1218 }
1111 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST); 1219 if (y > 0)
1112 } 1220 {
1221 southParcel = GetLandObject(x * landUnit, (y - 1) * landUnit);
1222 }
1113 1223
1114 if (y == 0) 1224 if (x == 0)
1115 { 1225 {
1116 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1226 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
1117 } 1227 }
1118 else if (southParcel != null && southParcel != currentParcelBlock) 1228 else if (westParcel != null && westParcel != currentParcelBlock)
1119 { 1229 {
1120 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1230 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
1121 } 1231 }
1122 1232
1123 byteArray[byteArrayCount] = tempByte; 1233 if (y == 0)
1124 byteArrayCount++; 1234 {
1125 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) 1235 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
1126 { 1236 }
1127 remote_client.SendLandParcelOverlay(byteArray, sequenceID); 1237 else if (southParcel != null && southParcel != currentParcelBlock)
1128 byteArrayCount = 0; 1238 {
1129 sequenceID++; 1239 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH);
1130 byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1131 }
1132 }
1133 } 1240 }
1241
1134 } 1242 }
1243
1244 return tempByte;
1135 } 1245 }
1136 1246
1137 public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, 1247 public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id,
@@ -1679,7 +1789,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1679 { 1789 {
1680 // most likely still cached from building the extLandData entry 1790 // most likely still cached from building the extLandData entry
1681 uint x = 0, y = 0; 1791 uint x = 0, y = 0;
1682 Utils.LongToUInts(data.RegionHandle, out x, out y); 1792 Util.RegionHandleToWorldLoc(data.RegionHandle, out x, out y);
1683 info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); 1793 info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
1684 } 1794 }
1685 // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark. 1795 // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark.
@@ -2007,4 +2117,4 @@ namespace OpenSim.Region.CoreModules.World.Land
2007 cdl.AddToStringBuilder(report); 2117 cdl.AddToStringBuilder(report);
2008 } 2118 }
2009 } 2119 }
2010} \ No newline at end of file 2120}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index e54c849..f8f4986 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -45,10 +45,10 @@ namespace OpenSim.Region.CoreModules.World.Land
45 #region Member Variables 45 #region Member Variables
46 46
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 #pragma warning disable 0429 48 private static readonly string LogHeader = "[LAND OBJECT]";
49 private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64; 49
50 #pragma warning restore 0429 50 private bool[,] m_landBitmap;
51 private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax]; 51 private readonly int landUnit = 4;
52 52
53 private int m_lastSeqId = 0; 53 private int m_lastSeqId = 0;
54 54
@@ -93,15 +93,17 @@ namespace OpenSim.Region.CoreModules.World.Land
93 { 93 {
94 get 94 get
95 { 95 {
96 for (int y = 0; y < landArrayMax; y++) 96 for (int y = 0; y < LandBitmap.GetLength(1); y++)
97 { 97 {
98 for (int x = 0; x < landArrayMax; x++) 98 for (int x = 0; x < LandBitmap.GetLength(0); x++)
99 { 99 {
100 if (LandBitmap[x, y]) 100 if (LandBitmap[x, y])
101 return new Vector3(x * 4, y * 4, 0); 101 return new Vector3(x * landUnit, y * landUnit, 0);
102 } 102 }
103 } 103 }
104 104
105 m_log.ErrorFormat("{0} StartPoint. No start point found. bitmapSize=<{1},{2}>",
106 LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
105 return new Vector3(-1, -1, -1); 107 return new Vector3(-1, -1, -1);
106 } 108 }
107 } 109 }
@@ -110,17 +112,19 @@ namespace OpenSim.Region.CoreModules.World.Land
110 { 112 {
111 get 113 get
112 { 114 {
113 for (int y = landArrayMax - 1; y >= 0; y--) 115 for (int y = LandBitmap.GetLength(1) - 1; y >= 0; y--)
114 { 116 {
115 for (int x = landArrayMax - 1; x >= 0; x--) 117 for (int x = LandBitmap.GetLength(0) - 1; x >= 0; x--)
116 { 118 {
117 if (LandBitmap[x, y]) 119 if (LandBitmap[x, y])
118 { 120 {
119 return new Vector3(x * 4 + 4, y * 4 + 4, 0); 121 return new Vector3(x * landUnit + landUnit, y * landUnit + landUnit, 0);
120 } 122 }
121 } 123 }
122 } 124 }
123 125
126 m_log.ErrorFormat("{0} EndPoint. No end point found. bitmapSize=<{1},{2}>",
127 LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
124 return new Vector3(-1, -1, -1); 128 return new Vector3(-1, -1, -1);
125 } 129 }
126 } 130 }
@@ -130,6 +134,8 @@ namespace OpenSim.Region.CoreModules.World.Land
130 public LandObject(UUID owner_id, bool is_group_owned, Scene scene) 134 public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
131 { 135 {
132 m_scene = scene; 136 m_scene = scene;
137 m_landBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
138
133 LandData.OwnerID = owner_id; 139 LandData.OwnerID = owner_id;
134 if (is_group_owned) 140 if (is_group_owned)
135 LandData.GroupID = owner_id; 141 LandData.GroupID = owner_id;
@@ -152,9 +158,9 @@ namespace OpenSim.Region.CoreModules.World.Land
152 /// <returns>Returns true if the piece of land contains the specified point</returns> 158 /// <returns>Returns true if the piece of land contains the specified point</returns>
153 public bool ContainsPoint(int x, int y) 159 public bool ContainsPoint(int x, int y)
154 { 160 {
155 if (x >= 0 && y >= 0 && x < Constants.RegionSize && y < Constants.RegionSize) 161 if (x >= 0 && y >= 0 && x < m_scene.RegionInfo.RegionSizeX && y < m_scene.RegionInfo.RegionSizeY)
156 { 162 {
157 return (LandBitmap[x / 4, y / 4] == true); 163 return (LandBitmap[x / landUnit, y / landUnit] == true);
158 } 164 }
159 else 165 else
160 { 166 {
@@ -194,7 +200,7 @@ namespace OpenSim.Region.CoreModules.World.Land
194 else 200 else
195 { 201 {
196 // Normal Calculations 202 // Normal Calculations
197 int parcelMax = (int)(((float)LandData.Area / 65536.0f) 203 int parcelMax = (int)(((float)LandData.Area / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY))
198 * (float)m_scene.RegionInfo.ObjectCapacity 204 * (float)m_scene.RegionInfo.ObjectCapacity
199 * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 205 * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus);
200 // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL! 206 // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL!
@@ -211,7 +217,7 @@ namespace OpenSim.Region.CoreModules.World.Land
211 else 217 else
212 { 218 {
213 //Normal Calculations 219 //Normal Calculations
214 int simMax = (int)(((float)LandData.SimwideArea / 65536.0f) 220 int simMax = (int)(((float)LandData.SimwideArea / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY))
215 * (float)m_scene.RegionInfo.ObjectCapacity); 221 * (float)m_scene.RegionInfo.ObjectCapacity);
216 return simMax; 222 return simMax;
217 } 223 }
@@ -224,7 +230,12 @@ namespace OpenSim.Region.CoreModules.World.Land
224 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) 230 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
225 { 231 {
226 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); 232 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
227 uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); 233 // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
234 uint regionFlags = (uint)(RegionFlags.PublicAllowed
235 | RegionFlags.AllowDirectTeleport
236 | RegionFlags.AllowParcelChanges
237 | RegionFlags.AllowVoice );
238
228 if (estateModule != null) 239 if (estateModule != null)
229 regionFlags = estateModule.GetRegionFlags(); 240 regionFlags = estateModule.GetRegionFlags();
230 241
@@ -559,8 +570,8 @@ namespace OpenSim.Region.CoreModules.World.Land
559 try 570 try
560 { 571 {
561 over = 572 over =
562 m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)), 573 m_scene.LandChannel.GetLandObject(Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)m_scene.RegionInfo.RegionSizeX - 1)),
563 Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1))); 574 Util.Clamp<int>((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)m_scene.RegionInfo.RegionSizeY - 1)));
564 } 575 }
565 catch (Exception) 576 catch (Exception)
566 { 577 {
@@ -707,15 +718,15 @@ namespace OpenSim.Region.CoreModules.World.Land
707 /// </summary> 718 /// </summary>
708 private void UpdateAABBAndAreaValues() 719 private void UpdateAABBAndAreaValues()
709 { 720 {
710 int min_x = 64; 721 int min_x = 10000;
711 int min_y = 64; 722 int min_y = 10000;
712 int max_x = 0; 723 int max_x = 0;
713 int max_y = 0; 724 int max_y = 0;
714 int tempArea = 0; 725 int tempArea = 0;
715 int x, y; 726 int x, y;
716 for (x = 0; x < 64; x++) 727 for (x = 0; x < LandBitmap.GetLength(0); x++)
717 { 728 {
718 for (y = 0; y < 64; y++) 729 for (y = 0; y < LandBitmap.GetLength(1); y++)
719 { 730 {
720 if (LandBitmap[x, y] == true) 731 if (LandBitmap[x, y] == true)
721 { 732 {
@@ -723,31 +734,31 @@ namespace OpenSim.Region.CoreModules.World.Land
723 if (min_y > y) min_y = y; 734 if (min_y > y) min_y = y;
724 if (max_x < x) max_x = x; 735 if (max_x < x) max_x = x;
725 if (max_y < y) max_y = y; 736 if (max_y < y) max_y = y;
726 tempArea += 16; //16sqm peice of land 737 tempArea += landUnit * landUnit; //16sqm peice of land
727 } 738 }
728 } 739 }
729 } 740 }
730 int tx = min_x * 4; 741 int tx = min_x * landUnit;
731 if (tx > ((int)Constants.RegionSize - 1)) 742 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
732 tx = ((int)Constants.RegionSize - 1); 743 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
733 int ty = min_y * 4; 744 int ty = min_y * landUnit;
734 if (ty > ((int)Constants.RegionSize - 1)) 745 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1))
735 ty = ((int)Constants.RegionSize - 1); 746 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1);
736 747
737 LandData.AABBMin = 748 LandData.AABBMin =
738 new Vector3( 749 new Vector3(
739 (float)(min_x * 4), (float)(min_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 750 (float)(min_x * landUnit), (float)(min_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
740 751
741 tx = max_x * 4; 752 tx = max_x * landUnit;
742 if (tx > ((int)Constants.RegionSize - 1)) 753 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
743 tx = ((int)Constants.RegionSize - 1); 754 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
744 ty = max_y * 4; 755 ty = max_y * landUnit;
745 if (ty > ((int)Constants.RegionSize - 1)) 756 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1))
746 ty = ((int)Constants.RegionSize - 1); 757 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1);
747 758
748 LandData.AABBMax 759 LandData.AABBMax
749 = new Vector3( 760 = new Vector3(
750 (float)(max_x * 4), (float)(max_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 761 (float)(max_x * landUnit), (float)(max_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
751 762
752 LandData.Area = tempArea; 763 LandData.Area = tempArea;
753 } 764 }
@@ -759,20 +770,12 @@ namespace OpenSim.Region.CoreModules.World.Land
759 /// <summary> 770 /// <summary>
760 /// Sets the land's bitmap manually 771 /// Sets the land's bitmap manually
761 /// </summary> 772 /// </summary>
762 /// <param name="bitmap">64x64 block representing where this land is on a map</param> 773 /// <param name="bitmap">block representing where this land is on a map mapped in a 4x4 meter grid</param>
763 public void SetLandBitmap(bool[,] bitmap) 774 public void SetLandBitmap(bool[,] bitmap)
764 { 775 {
765 if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2) 776 LandBitmap = bitmap;
766 { 777 // m_log.DebugFormat("{0} SetLandBitmap. BitmapSize=<{1},{2}>", LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
767 //Throw an exception - The bitmap is not 64x64 778 ForceUpdateLandInfo();
768 //throw new Exception("Error: Invalid Parcel Bitmap");
769 }
770 else
771 {
772 //Valid: Lets set it
773 LandBitmap = bitmap;
774 ForceUpdateLandInfo();
775 }
776 } 779 }
777 780
778 /// <summary> 781 /// <summary>
@@ -786,15 +789,19 @@ namespace OpenSim.Region.CoreModules.World.Land
786 789
787 public bool[,] BasicFullRegionLandBitmap() 790 public bool[,] BasicFullRegionLandBitmap()
788 { 791 {
789 return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize); 792 return GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int) m_scene.RegionInfo.RegionSizeY);
790 } 793 }
791 794
792 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) 795 public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y)
793 { 796 {
794 bool[,] tempBitmap = new bool[64,64]; 797 // Empty bitmap for the whole region
798 bool[,] tempBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
795 tempBitmap.Initialize(); 799 tempBitmap.Initialize();
796 800
801 // Fill the bitmap square area specified by state and end
797 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); 802 tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true);
803 // m_log.DebugFormat("{0} GetSquareLandBitmap. tempBitmapSize=<{1},{2}>",
804 // LogHeader, tempBitmap.GetLength(0), tempBitmap.GetLength(1));
798 return tempBitmap; 805 return tempBitmap;
799 } 806 }
800 807
@@ -811,24 +818,20 @@ namespace OpenSim.Region.CoreModules.World.Land
811 public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y, 818 public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y,
812 bool set_value) 819 bool set_value)
813 { 820 {
814 if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2)
815 {
816 //Throw an exception - The bitmap is not 64x64
817 //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()");
818 }
819
820 int x, y; 821 int x, y;
821 for (y = 0; y < 64; y++) 822 for (y = 0; y < land_bitmap.GetLength(1); y++)
822 { 823 {
823 for (x = 0; x < 64; x++) 824 for (x = 0; x < land_bitmap.GetLength(0); x++)
824 { 825 {
825 if (x >= start_x / 4 && x < end_x / 4 826 if (x >= start_x / landUnit && x < end_x / landUnit
826 && y >= start_y / 4 && y < end_y / 4) 827 && y >= start_y / landUnit && y < end_y / landUnit)
827 { 828 {
828 land_bitmap[x, y] = set_value; 829 land_bitmap[x, y] = set_value;
829 } 830 }
830 } 831 }
831 } 832 }
833 // m_log.DebugFormat("{0} ModifyLandBitmapSquare. startXY=<{1},{2}>, endXY=<{3},{4}>, val={5}, landBitmapSize=<{6},{7}>",
834 // LogHeader, start_x, start_y, end_x, end_y, set_value, land_bitmap.GetLength(0), land_bitmap.GetLength(1));
832 return land_bitmap; 835 return land_bitmap;
833 } 836 }
834 837
@@ -840,21 +843,21 @@ namespace OpenSim.Region.CoreModules.World.Land
840 /// <returns></returns> 843 /// <returns></returns>
841 public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add) 844 public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
842 { 845 {
843 if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2) 846 if (bitmap_base.GetLength(0) != bitmap_add.GetLength(0)
847 || bitmap_base.GetLength(1) != bitmap_add.GetLength(1)
848 || bitmap_add.Rank != 2
849 || bitmap_base.Rank != 2)
844 { 850 {
845 //Throw an exception - The bitmap is not 64x64 851 throw new Exception(
846 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps"); 852 String.Format("{0} MergeLandBitmaps. merging maps not same size. baseSizeXY=<{1},{2}>, addSizeXY=<{3},{4}>",
847 } 853 LogHeader, bitmap_base.GetLength(0), bitmap_base.GetLength(1), bitmap_add.GetLength(0), bitmap_add.GetLength(1))
848 if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2) 854 );
849 {
850 //Throw an exception - The bitmap is not 64x64
851 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps");
852 } 855 }
853 856
854 int x, y; 857 int x, y;
855 for (y = 0; y < 64; y++) 858 for (y = 0; y < bitmap_base.GetLength(1); y++)
856 { 859 {
857 for (x = 0; x < 64; x++) 860 for (x = 0; x < bitmap_add.GetLength(0); x++)
858 { 861 {
859 if (bitmap_add[x, y]) 862 if (bitmap_add[x, y])
860 { 863 {
@@ -871,13 +874,13 @@ namespace OpenSim.Region.CoreModules.World.Land
871 /// <returns></returns> 874 /// <returns></returns>
872 private byte[] ConvertLandBitmapToBytes() 875 private byte[] ConvertLandBitmapToBytes()
873 { 876 {
874 byte[] tempConvertArr = new byte[512]; 877 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
875 byte tempByte = 0; 878 byte tempByte = 0;
876 int x, y, i, byteNum = 0; 879 int byteNum = 0;
877 i = 0; 880 int i = 0;
878 for (y = 0; y < 64; y++) 881 for (int y = 0; y < LandBitmap.GetLength(1); y++)
879 { 882 {
880 for (x = 0; x < 64; x++) 883 for (int x = 0; x < LandBitmap.GetLength(0); x++)
881 { 884 {
882 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); 885 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8));
883 if (i % 8 == 0) 886 if (i % 8 == 0)
@@ -889,30 +892,52 @@ namespace OpenSim.Region.CoreModules.World.Land
889 } 892 }
890 } 893 }
891 } 894 }
895 // m_log.DebugFormat("{0} ConvertLandBitmapToBytes. BitmapSize=<{1},{2}>",
896 // LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
892 return tempConvertArr; 897 return tempConvertArr;
893 } 898 }
894 899
895 private bool[,] ConvertBytesToLandBitmap() 900 private bool[,] ConvertBytesToLandBitmap()
896 { 901 {
897 bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax]; 902 bool[,] tempConvertMap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit];
898 tempConvertMap.Initialize(); 903 tempConvertMap.Initialize();
899 byte tempByte = 0; 904 byte tempByte = 0;
900 int x = 0, y = 0, i = 0, bitNum = 0; 905 // Math.Min overcomes an old bug that might have made it into the database. Only use the bytes that fit into convertMap.
901 for (i = 0; i < 512; i++) 906 int bitmapLen = Math.Min(LandData.Bitmap.Length, tempConvertMap.GetLength(0) * tempConvertMap.GetLength(1) / 8);
907 int xLen = (int)(m_scene.RegionInfo.RegionSizeX / landUnit);
908
909 if (bitmapLen == 512)
910 {
911 // Legacy bitmap being passed in. Use the legacy region size
912 // and only set the lower area of the larger region.
913 xLen = (int)(Constants.RegionSize / landUnit);
914 }
915 // m_log.DebugFormat("{0} ConvertBytesToLandBitmap: bitmapLen={1}, xLen={2}", LogHeader, bitmapLen, xLen);
916
917 int x = 0, y = 0;
918 for (int i = 0; i < bitmapLen; i++)
902 { 919 {
903 tempByte = LandData.Bitmap[i]; 920 tempByte = LandData.Bitmap[i];
904 for (bitNum = 0; bitNum < 8; bitNum++) 921 for (int bitNum = 0; bitNum < 8; bitNum++)
905 { 922 {
906 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1); 923 bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1);
907 tempConvertMap[x, y] = bit; 924 try
925 {
926 tempConvertMap[x, y] = bit;
927 }
928 catch (Exception e)
929 {
930 m_log.DebugFormat("{0} ConvertBytestoLandBitmap: i={1}, x={2}, y={3}", LogHeader, i, x, y);
931 }
908 x++; 932 x++;
909 if (x > 63) 933 if (x >= xLen)
910 { 934 {
911 x = 0; 935 x = 0;
912 y++; 936 y++;
913 } 937 }
914 } 938 }
915 } 939 }
940
916 return tempConvertMap; 941 return tempConvertMap;
917 } 942 }
918 943
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index 40638f8..1007e0b 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -102,7 +102,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
102 102
103 terrainRenderer.Initialise(m_scene, m_config); 103 terrainRenderer.Initialise(m_scene, m_config);
104 104
105 mapbmp = new Bitmap((int)Constants.RegionSize, (int)Constants.RegionSize, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 105 mapbmp = new Bitmap((int)m_scene.Heightmap.Width, (int)m_scene.Heightmap.Height,
106 System.Drawing.Imaging.PixelFormat.Format24bppRgb);
106 //long t = System.Environment.TickCount; 107 //long t = System.Environment.TickCount;
107 //for (int i = 0; i < 10; ++i) { 108 //for (int i = 0; i < 10; ++i) {
108 terrainRenderer.TerrainToBitmap(mapbmp); 109 terrainRenderer.TerrainToBitmap(mapbmp);
@@ -273,7 +274,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
273 private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp) 274 private Bitmap DrawObjectVolume(Scene whichScene, Bitmap mapbmp)
274 { 275 {
275 int tc = 0; 276 int tc = 0;
276 double[,] hm = whichScene.Heightmap.GetDoubles(); 277 ITerrainChannel hm = whichScene.Heightmap;
277 tc = Environment.TickCount; 278 tc = Environment.TickCount;
278 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile"); 279 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile");
279 EntityBase[] objs = whichScene.GetEntities(); 280 EntityBase[] objs = whichScene.GetEntities();
@@ -356,7 +357,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
356 Vector3 pos = part.GetWorldPosition(); 357 Vector3 pos = part.GetWorldPosition();
357 358
358 // skip prim outside of retion 359 // skip prim outside of retion
359 if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f) 360 if (!m_scene.PositionIsInCurrentRegion(pos))
360 continue; 361 continue;
361 362
362 // skip prim in non-finite position 363 // skip prim in non-finite position
@@ -399,9 +400,14 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
399 int mapdrawendY = (int)(pos.Y + scale.Y); 400 int mapdrawendY = (int)(pos.Y + scale.Y);
400 401
401 // If object is beyond the edge of the map, don't draw it to avoid errors 402 // If object is beyond the edge of the map, don't draw it to avoid errors
402 if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1) 403 if (mapdrawstartX < 0
403 || mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0 404 || mapdrawstartX > (hm.Width - 1)
404 || mapdrawendY > ((int)Constants.RegionSize - 1)) 405 || mapdrawendX < 0
406 || mapdrawendX > (hm.Width - 1)
407 || mapdrawstartY < 0
408 || mapdrawstartY > (hm.Height - 1)
409 || mapdrawendY < 0
410 || mapdrawendY > (hm.Height - 1))
405 continue; 411 continue;
406 412
407#region obb face reconstruction part duex 413#region obb face reconstruction part duex
@@ -523,11 +529,11 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
523 for (int i = 0; i < FaceA.Length; i++) 529 for (int i = 0; i < FaceA.Length; i++)
524 { 530 {
525 Point[] working = new Point[5]; 531 Point[] working = new Point[5];
526 working[0] = project(FaceA[i], axPos); 532 working[0] = project(hm, FaceA[i], axPos);
527 working[1] = project(FaceB[i], axPos); 533 working[1] = project(hm, FaceB[i], axPos);
528 working[2] = project(FaceD[i], axPos); 534 working[2] = project(hm, FaceD[i], axPos);
529 working[3] = project(FaceC[i], axPos); 535 working[3] = project(hm, FaceC[i], axPos);
530 working[4] = project(FaceA[i], axPos); 536 working[4] = project(hm, FaceA[i], axPos);
531 537
532 face workingface = new face(); 538 face workingface = new face();
533 workingface.pts = working; 539 workingface.pts = working;
@@ -595,17 +601,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
595 return mapbmp; 601 return mapbmp;
596 } 602 }
597 603
598 private Point project(Vector3 point3d, Vector3 originpos) 604 private Point project(ITerrainChannel hm, Vector3 point3d, Vector3 originpos)
599 { 605 {
600 Point returnpt = new Point(); 606 Point returnpt = new Point();
601 //originpos = point3d; 607 //originpos = point3d;
602 //int d = (int)(256f / 1.5f); 608 //int d = (int)(256f / 1.5f);
603 609
604 //Vector3 topos = new Vector3(0, 0, 0); 610 //Vector3 topos = new Vector3(0, 0, 0);
605 // float z = -point3d.z - topos.z; 611 // float z = -point3d.z - topos.z;
606 612
607 returnpt.X = (int)point3d.X;//(int)((topos.x - point3d.x) / z * d); 613 returnpt.X = (int)point3d.X;//(int)((topos.x - point3d.x) / z * d);
608 returnpt.Y = (int)(((int)Constants.RegionSize - 1) - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d))); 614 returnpt.Y = (int)((hm.Width - 1) - point3d.Y);//(int)(255 - (((topos.y - point3d.y) / z * d)));
609 615
610 return returnpt; 616 return returnpt;
611 } 617 }
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
index 992bff3..9b939c9 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
@@ -31,6 +31,7 @@ using System.Reflection;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
35 36
36namespace OpenSim.Region.CoreModules.World.LegacyMap 37namespace OpenSim.Region.CoreModules.World.LegacyMap
@@ -39,8 +40,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
39 { 40 {
40 private static readonly Color WATER_COLOR = Color.FromArgb(29, 71, 95); 41 private static readonly Color WATER_COLOR = Color.FromArgb(29, 71, 95);
41 42
42 private static readonly ILog m_log = 43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly string LogHeader = "[SHADED MAPTILE RENDERER]";
44 45
45 private Scene m_scene; 46 private Scene m_scene;
46 //private IConfigSource m_config; // not used currently 47 //private IConfigSource m_config; // not used currently
@@ -53,19 +54,26 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
53 54
54 public void TerrainToBitmap(Bitmap mapbmp) 55 public void TerrainToBitmap(Bitmap mapbmp)
55 { 56 {
57 m_log.DebugFormat("{0} Generating Maptile Step 1: Terrain", LogHeader);
56 int tc = Environment.TickCount; 58 int tc = Environment.TickCount;
57 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain");
58 59
59 double[,] hm = m_scene.Heightmap.GetDoubles(); 60 ITerrainChannel hm = m_scene.Heightmap;
61
62 if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height)
63 {
64 m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>",
65 LogHeader, mapbmp.Width, mapbmp.Height, hm.Width, hm.Height);
66 }
67
60 bool ShadowDebugContinue = true; 68 bool ShadowDebugContinue = true;
61 69
62 bool terraincorruptedwarningsaid = false; 70 bool terraincorruptedwarningsaid = false;
63 71
64 float low = 255; 72 float low = 255;
65 float high = 0; 73 float high = 0;
66 for (int x = 0; x < (int)Constants.RegionSize; x++) 74 for (int x = 0; x < hm.Width; x++)
67 { 75 {
68 for (int y = 0; y < (int)Constants.RegionSize; y++) 76 for (int y = 0; y < hm.Height; y++)
69 { 77 {
70 float hmval = (float)hm[x, y]; 78 float hmval = (float)hm[x, y];
71 if (hmval < low) 79 if (hmval < low)
@@ -77,12 +85,12 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
77 85
78 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; 86 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
79 87
80 for (int x = 0; x < (int)Constants.RegionSize; x++) 88 for (int x = 0; x < hm.Width; x++)
81 { 89 {
82 for (int y = 0; y < (int)Constants.RegionSize; y++) 90 for (int y = 0; y < hm.Height; y++)
83 { 91 {
84 // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left 92 // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left
85 int yr = ((int)Constants.RegionSize - 1) - y; 93 int yr = ((int)hm.Height - 1) - y;
86 94
87 float heightvalue = (float)hm[x, y]; 95 float heightvalue = (float)hm[x, y];
88 96
@@ -109,12 +117,12 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
109 // . 117 // .
110 // 118 //
111 // Shade the terrain for shadows 119 // Shade the terrain for shadows
112 if (x < ((int)Constants.RegionSize - 1) && yr < ((int)Constants.RegionSize - 1)) 120 if (x < (hm.Width - 1) && yr < (hm.Height - 1))
113 { 121 {
114 float hfvalue = (float)hm[x, y]; 122 float hfvalue = (float)hm[x, y];
115 float hfvaluecompare = 0f; 123 float hfvaluecompare = 0f;
116 124
117 if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize)) 125 if ((x + 1 < hm.Width) && (y + 1 < hm.Height))
118 { 126 {
119 hfvaluecompare = (float)hm[x + 1, y + 1]; // light from north-east => look at land height there 127 hfvaluecompare = (float)hm[x + 1, y + 1]; // light from north-east => look at land height there
120 } 128 }
@@ -179,7 +187,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
179 187
180 if (ShadowDebugContinue) 188 if (ShadowDebugContinue)
181 { 189 {
182 if ((x - 1 > 0) && (yr + 1 < (int)Constants.RegionSize)) 190 if ((x - 1 > 0) && (yr + 1 < hm.Height))
183 { 191 {
184 color = mapbmp.GetPixel(x - 1, yr + 1); 192 color = mapbmp.GetPixel(x - 1, yr + 1);
185 int r = color.R; 193 int r = color.R;
@@ -233,7 +241,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
233 terraincorruptedwarningsaid = true; 241 terraincorruptedwarningsaid = true;
234 } 242 }
235 Color black = Color.Black; 243 Color black = Color.Black;
236 mapbmp.SetPixel(x, ((int)Constants.RegionSize - y) - 1, black); 244 mapbmp.SetPixel(x, (hm.Width - y) - 1, black);
237 } 245 }
238 } 246 }
239 } 247 }
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
index d13c2ef..413ac64 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
@@ -34,6 +34,8 @@ using Nini.Config;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenMetaverse.Imaging; 35using OpenMetaverse.Imaging;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Region.Framework;
38using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
38 40
39namespace OpenSim.Region.CoreModules.World.LegacyMap 41namespace OpenSim.Region.CoreModules.World.LegacyMap
@@ -122,8 +124,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
122 { 124 {
123 #region Constants 125 #region Constants
124 126
125 private static readonly ILog m_log = 127 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
126 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 128 private static readonly string LogHeader = "[TEXTURED MAPTILE RENDERER]";
127 129
128 // some hardcoded terrain UUIDs that work with SL 1.20 (the four default textures and "Blank"). 130 // some hardcoded terrain UUIDs that work with SL 1.20 (the four default textures and "Blank").
129 // The color-values were choosen because they "look right" (at least to me) ;-) 131 // The color-values were choosen because they "look right" (at least to me) ;-)
@@ -173,7 +175,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
173 private Bitmap fetchTexture(UUID id) 175 private Bitmap fetchTexture(UUID id)
174 { 176 {
175 AssetBase asset = m_scene.AssetService.Get(id.ToString()); 177 AssetBase asset = m_scene.AssetService.Get(id.ToString());
176 m_log.DebugFormat("[TexturedMapTileRenderer]: Fetched texture {0}, found: {1}", id, asset != null); 178 m_log.DebugFormat("{0} Fetched texture {1}, found: {2}", LogHeader, id, asset != null);
177 if (asset == null) return null; 179 if (asset == null) return null;
178 180
179 ManagedImage managedImage; 181 ManagedImage managedImage;
@@ -188,18 +190,15 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
188 } 190 }
189 catch (DllNotFoundException) 191 catch (DllNotFoundException)
190 { 192 {
191 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id); 193 m_log.ErrorFormat("{0} OpenJpeg is not installed correctly on this system. Asset Data is empty for {1}", LogHeader, id);
192
193 } 194 }
194 catch (IndexOutOfRangeException) 195 catch (IndexOutOfRangeException)
195 { 196 {
196 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id); 197 m_log.ErrorFormat("{0} OpenJpeg was unable to encode this. Asset Data is empty for {1}", LogHeader, id);
197
198 } 198 }
199 catch (Exception) 199 catch (Exception)
200 { 200 {
201 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id); 201 m_log.ErrorFormat("{0} OpenJpeg was unable to encode this. Asset Data is empty for {1}", LogHeader, id);
202
203 } 202 }
204 return null; 203 return null;
205 204
@@ -267,8 +266,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
267 266
268 // the heigthfield might have some jumps in values. Rendered land is smooth, though, 267 // the heigthfield might have some jumps in values. Rendered land is smooth, though,
269 // as a slope is rendered at that place. So average 4 neighbour values to emulate that. 268 // as a slope is rendered at that place. So average 4 neighbour values to emulate that.
270 private float getHeight(double[,] hm, int x, int y) { 269 private float getHeight(ITerrainChannel hm, int x, int y) {
271 if (x < ((int)Constants.RegionSize - 1) && y < ((int)Constants.RegionSize - 1)) 270 if (x < (hm.Width - 1) && y < (hm.Height - 1))
272 return (float)(hm[x, y] * .444 + (hm[x + 1, y] + hm[x, y + 1]) * .222 + hm[x + 1, y +1] * .112); 271 return (float)(hm[x, y] * .444 + (hm[x + 1, y] + hm[x, y + 1]) * .222 + hm[x + 1, y +1] * .112);
273 else 272 else
274 return (float)hm[x, y]; 273 return (float)hm[x, y];
@@ -278,7 +277,15 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
278 public void TerrainToBitmap(Bitmap mapbmp) 277 public void TerrainToBitmap(Bitmap mapbmp)
279 { 278 {
280 int tc = Environment.TickCount; 279 int tc = Environment.TickCount;
281 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain"); 280 m_log.DebugFormat("{0} Generating Maptile Step 1: Terrain", LogHeader);
281
282 ITerrainChannel hm = m_scene.Heightmap;
283
284 if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height)
285 {
286 m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>",
287 LogHeader, mapbmp.Width, mapbmp.Height, hm.Width, hm.Height);
288 }
282 289
283 // These textures should be in the AssetCache anyway, as every client conneting to this 290 // These textures should be in the AssetCache anyway, as every client conneting to this
284 // region needs them. Except on start, when the map is recreated (before anyone connected), 291 // region needs them. Except on start, when the map is recreated (before anyone connected),
@@ -306,19 +313,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
306 313
307 float waterHeight = (float)settings.WaterHeight; 314 float waterHeight = (float)settings.WaterHeight;
308 315
309 double[,] hm = m_scene.Heightmap.GetDoubles(); 316 for (int x = 0; x < hm.Width; x++)
310
311 for (int x = 0; x < (int)Constants.RegionSize; x++)
312 { 317 {
313 float columnRatio = x / ((float)Constants.RegionSize - 1); // 0 - 1, for interpolation 318 float columnRatio = x / (hm.Width - 1); // 0 - 1, for interpolation
314 for (int y = 0; y < (int)Constants.RegionSize; y++) 319 for (int y = 0; y < hm.Height; y++)
315 { 320 {
316 float rowRatio = y / ((float)Constants.RegionSize - 1); // 0 - 1, for interpolation 321 float rowRatio = y / (hm.Height - 1); // 0 - 1, for interpolation
317 322
318 // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left 323 // Y flip the cordinates for the bitmap: hf origin is lower left, bm origin is upper left
319 int yr = ((int)Constants.RegionSize - 1) - y; 324 int yr = (hm.Height - 1) - y;
320 325
321 float heightvalue = getHeight(hm, x, y); 326 float heightvalue = getHeight(m_scene.Heightmap, x, y);
322 if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue)) 327 if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue))
323 heightvalue = 0; 328 heightvalue = 0;
324 329
@@ -368,9 +373,9 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
368 } 373 }
369 374
370 // Shade the terrain for shadows 375 // Shade the terrain for shadows
371 if (x < ((int)Constants.RegionSize - 1) && y < ((int)Constants.RegionSize - 1)) 376 if (x < (hm.Width - 1) && y < (hm.Height - 1))
372 { 377 {
373 float hfvaluecompare = getHeight(hm, x + 1, y + 1); // light from north-east => look at land height there 378 float hfvaluecompare = getHeight(m_scene.Heightmap, x + 1, y + 1); // light from north-east => look at land height there
374 if (Single.IsInfinity(hfvaluecompare) || Single.IsNaN(hfvaluecompare)) 379 if (Single.IsInfinity(hfvaluecompare) || Single.IsNaN(hfvaluecompare))
375 hfvaluecompare = 0f; 380 hfvaluecompare = 0f;
376 381
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index 0cb574a..b8d4855 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -151,14 +151,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
151 break; 151 break;
152 152
153 case 2: // Sell a copy 153 case 2: // Sell a copy
154 Vector3 inventoryStoredPosition = new Vector3 154 Vector3 inventoryStoredPosition = new Vector3(
155 (((group.AbsolutePosition.X > (int)Constants.RegionSize) 155 Math.Min(group.AbsolutePosition.X, m_scene.RegionInfo.RegionSizeX - 6),
156 ? 250 156 Math.Min(group.AbsolutePosition.Y, m_scene.RegionInfo.RegionSizeY - 6),
157 : group.AbsolutePosition.X)
158 ,
159 (group.AbsolutePosition.X > (int)Constants.RegionSize)
160 ? 250
161 : group.AbsolutePosition.X,
162 group.AbsolutePosition.Z); 157 group.AbsolutePosition.Z);
163 158
164 Vector3 originalPosition = group.AbsolutePosition; 159 Vector3 originalPosition = group.AbsolutePosition;
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index f8e93e1..45617fc 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -1571,10 +1571,10 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1571 float X = position.X; 1571 float X = position.X;
1572 float Y = position.Y; 1572 float Y = position.Y;
1573 1573
1574 if (X > ((int)Constants.RegionSize - 1)) 1574 if (X > ((int)m_scene.RegionInfo.RegionSizeX - 1))
1575 X = ((int)Constants.RegionSize - 1); 1575 X = ((int)m_scene.RegionInfo.RegionSizeX - 1);
1576 if (Y > ((int)Constants.RegionSize - 1)) 1576 if (Y > ((int)m_scene.RegionInfo.RegionSizeY - 1))
1577 Y = ((int)Constants.RegionSize - 1); 1577 Y = ((int)m_scene.RegionInfo.RegionSizeY - 1);
1578 if (X < 0) 1578 if (X < 0)
1579 X = 0; 1579 X = 0;
1580 if (Y < 0) 1580 if (Y < 0)
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
index 7186dd7..89087b1 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
42 for (y = 0; y < map.Height; y++) 42 for (y = 0; y < map.Height; y++)
43 { 43 {
44 map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 10; 44 map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 10;
45 double spherFac = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2, Constants.RegionSize / 2, 50) * 0.01; 45 double spherFac = TerrainUtil.SphericalFactor(x, y, map.Width / 2, map.Height / 2, 50) * 0.01;
46 if (map[x, y] < spherFac) 46 if (map[x, y] < spherFac)
47 { 47 {
48 map[x, y] = spherFac; 48 map[x, y] = spherFac;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
index d78ade5..d5c77ec 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
67 { 67 {
68 using (Bitmap bitmap = new Bitmap(filename)) 68 using (Bitmap bitmap = new Bitmap(filename))
69 { 69 {
70 ITerrainChannel retval = new TerrainChannel(true); 70 ITerrainChannel retval = new TerrainChannel(w, h);
71 71
72 for (int x = 0; x < retval.Width; x++) 72 for (int x = 0; x < retval.Width; x++)
73 { 73 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
index 630473e..b6c635c 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
45 { 45 {
46 if (fillArea[x, y]) 46 if (fillArea[x, y])
47 { 47 {
48 double noise = TerrainUtil.PerlinNoise2D((double) x / Constants.RegionSize, (double) y / Constants.RegionSize, 8, 1.0); 48 double noise = TerrainUtil.PerlinNoise2D((double) x / map.Width, (double) y / map.Height, 8, 1.0);
49 49
50 map[x, y] += noise * strength; 50 map[x, y] += noise * strength;
51 } 51 }
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
index 989b7d8..e7df3f8 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
53 z *= z; 53 z *= z;
54 z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry)); 54 z -= ((x - rx) * (x - rx)) + ((y - ry) * (y - ry));
55 55
56 double noise = TerrainUtil.PerlinNoise2D(x / (double) Constants.RegionSize, y / (double) Constants.RegionSize, 8, 1.0); 56 double noise = TerrainUtil.PerlinNoise2D(x / (double) map.Width, y / (double) map.Height, 8, 1.0);
57 57
58 if (z > 0.0) 58 if (z > 0.0)
59 map[x, y] += noise * z * duration; 59 map[x, y] += noise * z * duration;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index fd30c46..9766bfe 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -30,10 +30,14 @@ using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Reflection; 31using System.Reflection;
32using System.Net; 32using System.Net;
33
33using log4net; 34using log4net;
34using Nini.Config; 35using Nini.Config;
36
35using OpenMetaverse; 37using OpenMetaverse;
36using Mono.Addins; 38using Mono.Addins;
39
40using OpenSim.Data;
37using OpenSim.Framework; 41using OpenSim.Framework;
38using OpenSim.Region.CoreModules.Framework.InterfaceCommander; 42using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
39using OpenSim.Region.CoreModules.World.Terrain.FileLoaders; 43using OpenSim.Region.CoreModules.World.Terrain.FileLoaders;
@@ -70,6 +74,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
70 #endregion 74 #endregion
71 75
72 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 76 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
77 private static readonly string LogHeader = "[TERRAIN MODULE]";
73 78
74 private readonly Commander m_commander = new Commander("terrain"); 79 private readonly Commander m_commander = new Commander("terrain");
75 80
@@ -130,15 +135,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain
130 { 135 {
131 if (m_scene.Heightmap == null) 136 if (m_scene.Heightmap == null)
132 { 137 {
133 m_channel = new TerrainChannel(m_InitialTerrain); 138 m_channel = new TerrainChannel(m_InitialTerrain, (int)m_scene.RegionInfo.RegionSizeX,
139 (int)m_scene.RegionInfo.RegionSizeY,
140 (int)m_scene.RegionInfo.RegionSizeZ);
134 m_scene.Heightmap = m_channel; 141 m_scene.Heightmap = m_channel;
135 m_revert = new TerrainChannel();
136 UpdateRevertMap(); 142 UpdateRevertMap();
137 } 143 }
138 else 144 else
139 { 145 {
140 m_channel = m_scene.Heightmap; 146 m_channel = m_scene.Heightmap;
141 m_revert = new TerrainChannel();
142 UpdateRevertMap(); 147 UpdateRevertMap();
143 } 148 }
144 149
@@ -230,11 +235,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
230 try 235 try
231 { 236 {
232 ITerrainChannel channel = loader.Value.LoadFile(filename); 237 ITerrainChannel channel = loader.Value.LoadFile(filename);
233 if (channel.Width != Constants.RegionSize || channel.Height != Constants.RegionSize) 238 if (channel.Width != m_scene.RegionInfo.RegionSizeX || channel.Height != m_scene.RegionInfo.RegionSizeY)
234 { 239 {
235 // TerrainChannel expects a RegionSize x RegionSize map, currently 240 // TerrainChannel expects a RegionSize x RegionSize map, currently
236 throw new ArgumentException(String.Format("wrong size, use a file with size {0} x {1}", 241 throw new ArgumentException(String.Format("wrong size, use a file with size {0} x {1}",
237 Constants.RegionSize, Constants.RegionSize)); 242 m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY));
238 } 243 }
239 m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height); 244 m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height);
240 m_scene.Heightmap = channel; 245 m_scene.Heightmap = channel;
@@ -532,6 +537,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
532 /// </summary> 537 /// </summary>
533 public void UpdateRevertMap() 538 public void UpdateRevertMap()
534 { 539 {
540 /*
535 int x; 541 int x;
536 for (x = 0; x < m_channel.Width; x++) 542 for (x = 0; x < m_channel.Width; x++)
537 { 543 {
@@ -541,6 +547,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
541 m_revert[x, y] = m_channel[x, y]; 547 m_revert[x, y] = m_channel[x, y];
542 } 548 }
543 } 549 }
550 */
551 m_revert = m_channel.MakeCopy();
544 } 552 }
545 553
546 /// <summary> 554 /// <summary>
@@ -567,8 +575,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
567 { 575 {
568 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, 576 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
569 fileWidth, fileHeight, 577 fileWidth, fileHeight,
570 (int) Constants.RegionSize, 578 (int) m_scene.RegionInfo.RegionSizeX,
571 (int) Constants.RegionSize); 579 (int) m_scene.RegionInfo.RegionSizeY);
572 m_scene.Heightmap = channel; 580 m_scene.Heightmap = channel;
573 m_channel = channel; 581 m_channel = channel;
574 UpdateRevertMap(); 582 UpdateRevertMap();
@@ -615,8 +623,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
615 { 623 {
616 loader.Value.SaveFile(m_channel, filename, offsetX, offsetY, 624 loader.Value.SaveFile(m_channel, filename, offsetX, offsetY,
617 fileWidth, fileHeight, 625 fileWidth, fileHeight,
618 (int)Constants.RegionSize, 626 (int)m_scene.RegionInfo.RegionSizeX,
619 (int)Constants.RegionSize); 627 (int)m_scene.RegionInfo.RegionSizeY);
620 628
621 MainConsole.Instance.OutputFormat( 629 MainConsole.Instance.OutputFormat(
622 "Saved terrain from ({0},{1}) to ({2},{3}) from {4} to {5}", 630 "Saved terrain from ({0},{1}) to ({2},{3}) from {4} to {5}",
@@ -705,7 +713,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
705 private void CheckForTerrainUpdates(bool respectEstateSettings) 713 private void CheckForTerrainUpdates(bool respectEstateSettings)
706 { 714 {
707 bool shouldTaint = false; 715 bool shouldTaint = false;
708 float[] serialised = m_channel.GetFloatsSerialised(); 716 float[] terrHeights = m_channel.GetFloatsSerialised();
709 int x; 717 int x;
710 for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize) 718 for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize)
711 { 719 {
@@ -714,16 +722,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain
714 { 722 {
715 if (m_channel.Tainted(x, y)) 723 if (m_channel.Tainted(x, y))
716 { 724 {
717 // if we should respect the estate settings then 725 // If we should respect the estate settings then
718 // fixup and height deltas that don't respect them 726 // fixup and height deltas that don't respect them.
727 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
719 if (respectEstateSettings && LimitChannelChanges(x, y)) 728 if (respectEstateSettings && LimitChannelChanges(x, y))
720 { 729 {
721 // this has been vetoed, so update 730 // Terrain heights were modified. Refetch the terrain info.
722 // what we are going to send to the client 731 terrHeights = m_channel.GetFloatsSerialised();
723 serialised = m_channel.GetFloatsSerialised();
724 } 732 }
725 733
726 SendToClients(serialised, x, y); 734 // m_log.DebugFormat("{0} Patch modified. Sending (x,y) = ({1},{2})", LogHeader, x, y);
735 SendToClients(terrHeights, x, y);
727 shouldTaint = true; 736 shouldTaint = true;
728 } 737 }
729 } 738 }
@@ -792,13 +801,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
792 /// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param> 801 /// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param>
793 /// <param name="x">The patch corner to send</param> 802 /// <param name="x">The patch corner to send</param>
794 /// <param name="y">The patch corner to send</param> 803 /// <param name="y">The patch corner to send</param>
795 private void SendToClients(float[] serialised, int x, int y) 804 private void SendToClients(float[] heightMap, int x, int y)
796 { 805 {
797 m_scene.ForEachClient( 806 m_scene.ForEachClient(
798 delegate(IClientAPI controller) 807 delegate(IClientAPI controller)
799 { controller.SendLayerData( 808 { controller.SendLayerData( x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, heightMap); }
800 x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised);
801 }
802 ); 809 );
803 } 810 }
804 811
@@ -984,28 +991,28 @@ namespace OpenSim.Region.CoreModules.World.Terrain
984 991
985 if (direction.ToLower().StartsWith("y")) 992 if (direction.ToLower().StartsWith("y"))
986 { 993 {
987 for (int x = 0; x < Constants.RegionSize; x++) 994 for (int x = 0; x < m_channel.Width; x++)
988 { 995 {
989 for (int y = 0; y < Constants.RegionSize / 2; y++) 996 for (int y = 0; y < m_channel.Height / 2; y++)
990 { 997 {
991 double height = m_channel[x, y]; 998 double height = m_channel[x, y];
992 double flippedHeight = m_channel[x, (int)Constants.RegionSize - 1 - y]; 999 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y];
993 m_channel[x, y] = flippedHeight; 1000 m_channel[x, y] = flippedHeight;
994 m_channel[x, (int)Constants.RegionSize - 1 - y] = height; 1001 m_channel[x, (int)m_channel.Height - 1 - y] = height;
995 1002
996 } 1003 }
997 } 1004 }
998 } 1005 }
999 else if (direction.ToLower().StartsWith("x")) 1006 else if (direction.ToLower().StartsWith("x"))
1000 { 1007 {
1001 for (int y = 0; y < Constants.RegionSize; y++) 1008 for (int y = 0; y < m_channel.Height; y++)
1002 { 1009 {
1003 for (int x = 0; x < Constants.RegionSize / 2; x++) 1010 for (int x = 0; x < m_channel.Width / 2; x++)
1004 { 1011 {
1005 double height = m_channel[x, y]; 1012 double height = m_channel[x, y];
1006 double flippedHeight = m_channel[(int)Constants.RegionSize - 1 - x, y]; 1013 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y];
1007 m_channel[x, y] = flippedHeight; 1014 m_channel[x, y] = flippedHeight;
1008 m_channel[(int)Constants.RegionSize - 1 - x, y] = height; 1015 m_channel[(int)m_channel.Width - 1 - x, y] = height;
1009 1016
1010 } 1017 }
1011 } 1018 }
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
index df5ac92..9534ad3 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -32,6 +32,7 @@ using System.Drawing.Imaging;
32using log4net; 32using log4net;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Services.Interfaces; 36using OpenSim.Services.Interfaces;
36 37
37namespace OpenSim.Region.CoreModules.World.Warp3DMap 38namespace OpenSim.Region.CoreModules.World.Warp3DMap
@@ -66,261 +67,271 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
66 #endregion Constants 67 #endregion Constants
67 68
68 private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); 69 private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
70 private static string LogHeader = "[WARP3D TERRAIN SPLAT]";
69 71
70 /// <summary> 72 /// <summary>
71 /// Builds a composited terrain texture given the region texture 73 /// Builds a composited terrain texture given the region texture
72 /// and heightmap settings 74 /// and heightmap settings
73 /// </summary> 75 /// </summary>
74 /// <param name="heightmap">Terrain heightmap</param> 76 /// <param name="terrain">Terrain heightmap</param>
75 /// <param name="regionInfo">Region information including terrain texture parameters</param> 77 /// <param name="regionInfo">Region information including terrain texture parameters</param>
76 /// <returns>A composited 256x256 RGB texture ready for rendering</returns> 78 /// <returns>A 256x256 square RGB texture ready for rendering</returns>
77 /// <remarks>Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting 79 /// <remarks>Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting
80 /// Note we create a 256x256 dimension texture even if the actual terrain is larger.
78 /// </remarks> 81 /// </remarks>
79 public static Bitmap Splat(float[] heightmap, UUID[] textureIDs, float[] startHeights, float[] heightRanges, Vector3d regionPosition, IAssetService assetService, bool textureTerrain) 82 public static Bitmap Splat(ITerrainChannel terrain,
83 UUID[] textureIDs, float[] startHeights, float[] heightRanges,
84 Vector3d regionPosition, IAssetService assetService, bool textureTerrain)
80 { 85 {
81 Debug.Assert(heightmap.Length == 256 * 256);
82 Debug.Assert(textureIDs.Length == 4); 86 Debug.Assert(textureIDs.Length == 4);
83 Debug.Assert(startHeights.Length == 4); 87 Debug.Assert(startHeights.Length == 4);
84 Debug.Assert(heightRanges.Length == 4); 88 Debug.Assert(heightRanges.Length == 4);
85 89
86 Bitmap[] detailTexture = new Bitmap[4]; 90 Bitmap[] detailTexture = new Bitmap[4];
87 Bitmap output = null;
88 BitmapData outputData = null;
89 91
90 try 92 if (textureTerrain)
91 { 93 {
92 if (textureTerrain) 94 // Swap empty terrain textureIDs with default IDs
95 for (int i = 0; i < textureIDs.Length; i++)
93 { 96 {
94 // Swap empty terrain textureIDs with default IDs 97 if (textureIDs[i] == UUID.Zero)
95 for (int i = 0; i < textureIDs.Length; i++) 98 textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i];
96 { 99 }
97 if (textureIDs[i] == UUID.Zero) 100
98 textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; 101 #region Texture Fetching
99 } 102
100 103 if (assetService != null)
101 #region Texture Fetching 104 {
102 105 for (int i = 0; i < 4; i++)
103 if (assetService != null)
104 { 106 {
105 for (int i = 0; i < 4; i++) 107 AssetBase asset;
108 UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]);
109
110 // Try to fetch a cached copy of the decoded/resized version of this texture
111 asset = assetService.GetCached(cacheID.ToString());
112 if (asset != null)
113 {
114 try
115 {
116 using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data))
117 detailTexture[i] = (Bitmap)Image.FromStream(stream);
118 }
119 catch (Exception ex)
120 {
121 m_log.Warn("Failed to decode cached terrain texture " + cacheID +
122 " (textureID: " + textureIDs[i] + "): " + ex.Message);
123 }
124 }
125
126 if (detailTexture[i] == null)
106 { 127 {
107 AssetBase asset; 128 // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG
108 UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); 129 asset = assetService.Get(textureIDs[i].ToString());
109
110 // Try to fetch a cached copy of the decoded/resized version of this texture
111 asset = assetService.GetCached(cacheID.ToString());
112 if (asset != null) 130 if (asset != null)
113 { 131 {
114// m_log.DebugFormat( 132// m_log.DebugFormat(
115// "[TERRAIN SPLAT]: Got asset service cached terrain texture {0} {1}", i, asset.ID); 133// "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID);
116 134
117 try 135 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); }
118 {
119 using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data))
120 detailTexture[i] = (Bitmap)Image.FromStream(stream);
121 }
122 catch (Exception ex) 136 catch (Exception ex)
123 { 137 {
124 m_log.Warn("Failed to decode cached terrain texture " + cacheID + 138 m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message);
125 " (textureID: " + textureIDs[i] + "): " + ex.Message);
126 } 139 }
127 } 140 }
128
129 if (detailTexture[i] == null)
130 {
131 // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG
132 asset = assetService.Get(textureIDs[i].ToString());
133 if (asset != null)
134 {
135// m_log.DebugFormat(
136// "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID);
137 141
138 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } 142 if (detailTexture[i] != null)
139 catch (Exception ex) 143 {
144 // Make sure this texture is the correct size, otherwise resize
145 if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256)
146 {
147 using (Bitmap origBitmap = detailTexture[i])
140 { 148 {
141 m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); 149 detailTexture[i] = ImageUtils.ResizeImage(origBitmap, 256, 256);
142 } 150 }
143 } 151 }
144 152
145 if (detailTexture[i] != null) 153 // Save the decoded and resized texture to the cache
146 { 154 byte[] data;
147 // Make sure this texture is the correct size, otherwise resize 155 using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
148 if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) 156 {
149 { 157 detailTexture[i].Save(stream, ImageFormat.Png);
150 using (Bitmap origBitmap = detailTexture[i]) 158 data = stream.ToArray();
151 {
152 detailTexture[i] = ImageUtils.ResizeImage(origBitmap, 256, 256);
153 }
154 }
155
156 // Save the decoded and resized texture to the cache
157 byte[] data;
158 using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
159 {
160 detailTexture[i].Save(stream, ImageFormat.Png);
161 data = stream.ToArray();
162 }
163
164 // Cache a PNG copy of this terrain texture
165 AssetBase newAsset = new AssetBase
166 {
167 Data = data,
168 Description = "PNG",
169 Flags = AssetFlags.Collectable,
170 FullID = cacheID,
171 ID = cacheID.ToString(),
172 Local = true,
173 Name = String.Empty,
174 Temporary = true,
175 Type = (sbyte)AssetType.Unknown
176 };
177 newAsset.Metadata.ContentType = "image/png";
178 assetService.Store(newAsset);
179 } 159 }
160
161 // Cache a PNG copy of this terrain texture
162 AssetBase newAsset = new AssetBase
163 {
164 Data = data,
165 Description = "PNG",
166 Flags = AssetFlags.Collectable,
167 FullID = cacheID,
168 ID = cacheID.ToString(),
169 Local = true,
170 Name = String.Empty,
171 Temporary = true,
172 Type = (sbyte)AssetType.Unknown
173 };
174 newAsset.Metadata.ContentType = "image/png";
175 assetService.Store(newAsset);
180 } 176 }
181 } 177 }
182 } 178 }
183
184 #endregion Texture Fetching
185 } 179 }
186 180
187 // Fill in any missing textures with a solid color 181 #endregion Texture Fetching
188 for (int i = 0; i < 4; i++) 182 }
183
184 // Fill in any missing textures with a solid color
185 for (int i = 0; i < 4; i++)
186 {
187 if (detailTexture[i] == null)
189 { 188 {
190 if (detailTexture[i] == null) 189 m_log.DebugFormat("{0} Missing terrain texture for layer {1}. Filling with solid default color",
190 LogHeader, i);
191 // Create a solid color texture for this layer
192 detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
193 using (Graphics gfx = Graphics.FromImage(detailTexture[i]))
191 { 194 {
192// m_log.DebugFormat( 195 using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i]))
193// "[TERRAIN SPLAT]: Generating solid colour for missing texture {0}", i); 196 gfx.FillRectangle(brush, 0, 0, 256, 256);
194
195 // Create a solid color texture for this layer
196 detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
197 using (Graphics gfx = Graphics.FromImage(detailTexture[i]))
198 {
199 using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i]))
200 gfx.FillRectangle(brush, 0, 0, 256, 256);
201 }
202 } 197 }
203 } 198 }
204 199 else
205 #region Layer Map
206
207 float[] layermap = new float[256 * 256];
208
209 for (int y = 0; y < 256; y++)
210 { 200 {
211 for (int x = 0; x < 256; x++) 201 if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256)
212 { 202 {
213 float height = heightmap[y * 256 + x]; 203 detailTexture[i] = ResizeBitmap(detailTexture[i], 256, 256);
214
215 float pctX = (float)x / 255f;
216 float pctY = (float)y / 255f;
217
218 // Use bilinear interpolation between the four corners of start height and
219 // height range to select the current values at this position
220 float startHeight = ImageUtils.Bilinear(
221 startHeights[0],
222 startHeights[2],
223 startHeights[1],
224 startHeights[3],
225 pctX, pctY);
226 startHeight = Utils.Clamp(startHeight, 0f, 255f);
227
228 float heightRange = ImageUtils.Bilinear(
229 heightRanges[0],
230 heightRanges[2],
231 heightRanges[1],
232 heightRanges[3],
233 pctX, pctY);
234 heightRange = Utils.Clamp(heightRange, 0f, 255f);
235
236 // Generate two frequencies of perlin noise based on our global position
237 // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
238 Vector3 vec = new Vector3
239 (
240 ((float)regionPosition.X + x) * 0.20319f,
241 ((float)regionPosition.Y + y) * 0.20319f,
242 height * 0.25f
243 );
244
245 float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f;
246 float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
247 float noise = (lowFreq + highFreq) * 2f;
248
249 // Combine the current height, generated noise, start height, and height range parameters, then scale all of it
250 float layer = ((height + noise - startHeight) / heightRange) * 4f;
251 if (Single.IsNaN(layer)) layer = 0f;
252 layermap[y * 256 + x] = Utils.Clamp(layer, 0f, 3f);
253 } 204 }
254 } 205 }
255 206 }
256 #endregion Layer Map 207
257 208 #region Layer Map
258 #region Texture Compositing 209
259 210 float[,] layermap = new float[256, 256];
260 output = new Bitmap(256, 256, PixelFormat.Format24bppRgb); 211
261 outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); 212 // Scale difference between actual region size and the 256 texture being created
262 213 int xFactor = terrain.Width / 256;
263 unsafe 214 int yFactor = terrain.Height / 256;
215
216 // Create 'layermap' where each value is the fractional layer number to place
217 // at that point. For instance, a value of 1.345 gives the blending of
218 // layer 1 and layer 2 for that point.
219 for (int y = 0; y < 256; y++)
220 {
221 for (int x = 0; x < 256; x++)
264 { 222 {
265 // Get handles to all of the texture data arrays 223 float height = (float)terrain[x * xFactor, y * yFactor];
266 BitmapData[] datas = new BitmapData[] 224
267 { 225 float pctX = (float)x / 255f;
268 detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat), 226 float pctY = (float)y / 255f;
269 detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat), 227
270 detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat), 228 // Use bilinear interpolation between the four corners of start height and
271 detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat) 229 // height range to select the current values at this position
272 }; 230 float startHeight = ImageUtils.Bilinear(
273 231 startHeights[0],
274 int[] comps = new int[] 232 startHeights[2],
275 { 233 startHeights[1],
276 (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, 234 startHeights[3],
277 (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, 235 pctX, pctY);
278 (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, 236 startHeight = Utils.Clamp(startHeight, 0f, 255f);
279 (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3 237
280 }; 238 float heightRange = ImageUtils.Bilinear(
281 239 heightRanges[0],
282 for (int y = 0; y < 256; y++) 240 heightRanges[2],
283 { 241 heightRanges[1],
284 for (int x = 0; x < 256; x++) 242 heightRanges[3],
285 { 243 pctX, pctY);
286 float layer = layermap[y * 256 + x]; 244 heightRange = Utils.Clamp(heightRange, 0f, 255f);
287 245
288 // Select two textures 246 // Generate two frequencies of perlin noise based on our global position
289 int l0 = (int)Math.Floor(layer); 247 // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting
290 int l1 = Math.Min(l0 + 1, 3); 248 Vector3 vec = new Vector3
291 249 (
292 byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0]; 250 ((float)regionPosition.X + (x * xFactor)) * 0.20319f,
293 byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1]; 251 ((float)regionPosition.Y + (y * yFactor)) * 0.20319f,
294 byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3; 252 height * 0.25f
295 253 );
296 float aB = *(ptrA + 0); 254
297 float aG = *(ptrA + 1); 255 float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f;
298 float aR = *(ptrA + 2); 256 float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f;
299 257 float noise = (lowFreq + highFreq) * 2f;
300 float bB = *(ptrB + 0); 258
301 float bG = *(ptrB + 1); 259 // Combine the current height, generated noise, start height, and height range parameters, then scale all of it
302 float bR = *(ptrB + 2); 260 float layer = ((height + noise - startHeight) / heightRange) * 4f;
303 261 if (Single.IsNaN(layer))
304 float layerDiff = layer - l0; 262 layer = 0f;
305 263 layermap[x, y] = Utils.Clamp(layer, 0f, 3f);
306 // Interpolate between the two selected textures
307 *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB));
308 *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG));
309 *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR));
310 }
311 }
312
313 for (int i = 0; i < 4; i++)
314 detailTexture[i].UnlockBits(datas[i]);
315 } 264 }
316 } 265 }
317 finally 266
267 #endregion Layer Map
268
269 #region Texture Compositing
270
271 Bitmap output = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
272 BitmapData outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
273
274 // Unsafe work as we lock down the source textures for quicker access and access the
275 // pixel data directly
276 unsafe
318 { 277 {
319 for (int i = 0; i < 4; i++) 278 // Get handles to all of the texture data arrays
320 if (detailTexture[i] != null) 279 BitmapData[] datas = new BitmapData[]
321 detailTexture[i].Dispose(); 280 {
281 detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat),
282 detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat),
283 detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat),
284 detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat)
285 };
286
287 // Compute size of each pixel data (used to address into the pixel data array)
288 int[] comps = new int[]
289 {
290 (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
291 (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
292 (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3,
293 (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3
294 };
295
296 for (int y = 0; y < 256; y++)
297 {
298 for (int x = 0; x < 256; x++)
299 {
300 float layer = layermap[x, y];
301
302 // Select two textures
303 int l0 = (int)Math.Floor(layer);
304 int l1 = Math.Min(l0 + 1, 3);
305
306 byte* ptrA = (byte*)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0];
307 byte* ptrB = (byte*)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1];
308 byte* ptrO = (byte*)outputData.Scan0 + y * outputData.Stride + x * 3;
309
310 float aB = *(ptrA + 0);
311 float aG = *(ptrA + 1);
312 float aR = *(ptrA + 2);
313
314 float bB = *(ptrB + 0);
315 float bG = *(ptrB + 1);
316 float bR = *(ptrB + 2);
317
318 float layerDiff = layer - l0;
319
320 // Interpolate between the two selected textures
321 *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB));
322 *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG));
323 *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR));
324 }
325 }
326
327 for (int i = 0; i < detailTexture.Length; i++)
328 detailTexture[i].UnlockBits(datas[i]);
322 } 329 }
323 330
331 for (int i = 0; i < detailTexture.Length; i++)
332 if (detailTexture[i] != null)
333 detailTexture[i].Dispose();
334
324 output.UnlockBits(outputData); 335 output.UnlockBits(outputData);
325 336
326 // We generated the texture upside down, so flip it 337 // We generated the texture upside down, so flip it
@@ -331,6 +342,17 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
331 return output; 342 return output;
332 } 343 }
333 344
345 public static Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight)
346 {
347 m_log.DebugFormat("{0} ResizeBitmap. From <{1},{2}> to <{3},{4}>",
348 LogHeader, b.Width, b.Height, nWidth, nHeight);
349 Bitmap result = new Bitmap(nWidth, nHeight);
350 using (Graphics g = Graphics.FromImage(result))
351 g.DrawImage(b, 0, 0, nWidth, nHeight);
352 b.Dispose();
353 return result;
354 }
355
334 public static Bitmap SplatSimple(float[] heightmap) 356 public static Bitmap SplatSimple(float[] heightmap)
335 { 357 {
336 const float BASE_HSV_H = 93f / 360f; 358 const float BASE_HSV_H = 93f / 360f;
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index ed2b06a..f072268 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -31,21 +31,25 @@ using System.Drawing;
31using System.Drawing.Imaging; 31using System.Drawing.Imaging;
32using System.IO; 32using System.IO;
33using System.Reflection; 33using System.Reflection;
34
34using CSJ2K; 35using CSJ2K;
35using Nini.Config; 36using Nini.Config;
36using log4net; 37using log4net;
37using Rednettle.Warp3D; 38using Rednettle.Warp3D;
38using Mono.Addins; 39using Mono.Addins;
39using OpenMetaverse; 40
40using OpenMetaverse.Imaging;
41using OpenMetaverse.Rendering;
42using OpenMetaverse.StructuredData;
43using OpenSim.Framework; 41using OpenSim.Framework;
44using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
46using OpenSim.Region.Physics.Manager; 44using OpenSim.Region.Physics.Manager;
47using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
48 46
47using OpenMetaverse;
48using OpenMetaverse.Assets;
49using OpenMetaverse.Imaging;
50using OpenMetaverse.Rendering;
51using OpenMetaverse.StructuredData;
52
49using WarpRenderer = global::Warp3D.Warp3D; 53using WarpRenderer = global::Warp3D.Warp3D;
50 54
51namespace OpenSim.Region.CoreModules.World.Warp3DMap 55namespace OpenSim.Region.CoreModules.World.Warp3DMap
@@ -57,12 +61,20 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
57 private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216); 61 private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216);
58 62
59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 63 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
64 private static string LogHeader = "[WARP 3D IMAGE MODULE]";
60 65
61 private Scene m_scene; 66 private Scene m_scene;
62 private IRendering m_primMesher; 67 private IRendering m_primMesher;
63 private IConfigSource m_config;
64 private Dictionary<UUID, Color4> m_colors = new Dictionary<UUID, Color4>(); 68 private Dictionary<UUID, Color4> m_colors = new Dictionary<UUID, Color4>();
65 private bool m_useAntiAliasing = false; // TODO: Make this a config option 69
70 private IConfigSource m_config;
71 private bool m_drawPrimVolume = true; // true if should render the prims on the tile
72 private bool m_textureTerrain = true; // true if to create terrain splatting texture
73 private bool m_texturePrims = true; // true if should texture the rendered prims
74 private float m_texturePrimSize = 48f; // size of prim before we consider texturing it
75 private bool m_renderMeshes = false; // true if to render meshes rather than just bounding boxes
76 private bool m_useAntiAliasing = false; // true if to anti-alias the rendered image
77
66 private bool m_Enabled = false; 78 private bool m_Enabled = false;
67 79
68 #region Region Module interface 80 #region Region Module interface
@@ -71,11 +83,27 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
71 { 83 {
72 m_config = source; 84 m_config = source;
73 85
86 string[] configSections = new string[] { "Map", "Startup" };
87
74 if (Util.GetConfigVarFromSections<string>( 88 if (Util.GetConfigVarFromSections<string>(
75 m_config, "MapImageModule", new string[] { "Startup", "Map" }, "MapImageModule") != "Warp3DImageModule") 89 m_config, "MapImageModule", configSections, "MapImageModule") != "Warp3DImageModule")
76 return; 90 return;
77 91
78 m_Enabled = true; 92 m_Enabled = true;
93
94 m_drawPrimVolume
95 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, m_drawPrimVolume);
96 m_textureTerrain
97 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, m_textureTerrain);
98 m_texturePrims
99 = Util.GetConfigVarFromSections<bool>(m_config, "TexturePrims", configSections, m_texturePrims);
100 m_texturePrimSize
101 = Util.GetConfigVarFromSections<float>(m_config, "TexturePrimSize", configSections, m_texturePrimSize);
102 m_renderMeshes
103 = Util.GetConfigVarFromSections<bool>(m_config, "RenderMeshes", configSections, m_renderMeshes);
104 m_useAntiAliasing
105 = Util.GetConfigVarFromSections<bool>(m_config, "UseAntiAliasing", configSections, m_useAntiAliasing);
106
79 } 107 }
80 108
81 public void AddRegion(Scene scene) 109 public void AddRegion(Scene scene)
@@ -127,29 +155,28 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
127 155
128 public Bitmap CreateMapTile() 156 public Bitmap CreateMapTile()
129 { 157 {
130 Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f); 158 // Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f);
131 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, (int)Constants.RegionSize, (int)Constants.RegionSize, (float)Constants.RegionSize, (float)Constants.RegionSize); 159 // Camera above the middle of the region
160 Vector3 camPos = new Vector3(
161 m_scene.RegionInfo.RegionSizeX/2 - 0.5f,
162 m_scene.RegionInfo.RegionSizeY/2 - 0.5f,
163 221.7025033688163f);
164 // Viewport viewing down onto the region
165 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f,
166 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY,
167 (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY );
168 // Fill the viewport and return the image
132 return CreateMapTile(viewport, false); 169 return CreateMapTile(viewport, false);
133 } 170 }
134 171
135 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures) 172 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures)
136 { 173 {
137 Viewport viewport = new Viewport(camPos, camDir, fov, (float)Constants.RegionSize, 0.1f, width, height); 174 Viewport viewport = new Viewport(camPos, camDir, fov, Constants.RegionSize, 0.1f, width, height);
138 return CreateMapTile(viewport, useTextures); 175 return CreateMapTile(viewport, useTextures);
139 } 176 }
140 177
141 public Bitmap CreateMapTile(Viewport viewport, bool useTextures) 178 public Bitmap CreateMapTile(Viewport viewport, bool useTextures)
142 { 179 {
143 bool drawPrimVolume = true;
144 bool textureTerrain = true;
145
146 string[] configSections = new string[] { "Map", "Startup" };
147
148 drawPrimVolume
149 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, drawPrimVolume);
150 textureTerrain
151 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, textureTerrain);
152
153 m_colors.Clear(); 180 m_colors.Clear();
154 181
155 int width = viewport.Width; 182 int width = viewport.Width;
@@ -193,8 +220,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
193 renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40)); 220 renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40));
194 221
195 CreateWater(renderer); 222 CreateWater(renderer);
196 CreateTerrain(renderer, textureTerrain); 223 CreateTerrain(renderer, m_textureTerrain);
197 if (drawPrimVolume) 224 if (m_drawPrimVolume)
198 CreateAllPrims(renderer, useTextures); 225 CreateAllPrims(renderer, useTextures);
199 226
200 renderer.Render(); 227 renderer.Render();
@@ -210,6 +237,16 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
210 // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory 237 // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory
211 // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating 238 // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating
212 // this map tile simply takes a lot of memory. 239 // this map tile simply takes a lot of memory.
240 foreach (var o in renderer.Scene.objectData.Values)
241 {
242 warp_Object obj = (warp_Object)o;
243 obj.vertexData = null;
244 obj.triangleData = null;
245 }
246 renderer.Scene.removeAllObjects();
247 renderer = null;
248 viewport = null;
249 m_colors.Clear();
213 GC.Collect(); 250 GC.Collect();
214 m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()"); 251 m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()");
215 252
@@ -236,61 +273,74 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
236 273
237 #region Rendering Methods 274 #region Rendering Methods
238 275
276 // Add a water plane to the renderer.
239 private void CreateWater(WarpRenderer renderer) 277 private void CreateWater(WarpRenderer renderer)
240 { 278 {
241 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; 279 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
242 280
243 renderer.AddPlane("Water", 256f * 0.5f); 281 renderer.AddPlane("Water", m_scene.RegionInfo.RegionSizeX * 0.5f);
244 renderer.Scene.sceneobject("Water").setPos(127.5f, waterHeight, 127.5f); 282 renderer.Scene.sceneobject("Water").setPos(m_scene.RegionInfo.RegionSizeX/2 - 0.5f,
283 waterHeight,
284 m_scene.RegionInfo.RegionSizeY/2 - 0.5f );
245 285
246 renderer.AddMaterial("WaterColor", ConvertColor(WATER_COLOR)); 286 warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR));
247 renderer.Scene.material("WaterColor").setReflectivity(0); // match water color with standard map module thanks lkalif 287 waterColorMaterial.setReflectivity(0); // match water color with standard map module thanks lkalif
248 renderer.Scene.material("WaterColor").setTransparency((byte)((1f - WATER_COLOR.A) * 255f)); 288 waterColorMaterial.setTransparency((byte)((1f - WATER_COLOR.A) * 255f));
289 renderer.Scene.addMaterial("WaterColor", waterColorMaterial);
249 renderer.SetObjectMaterial("Water", "WaterColor"); 290 renderer.SetObjectMaterial("Water", "WaterColor");
250 } 291 }
251 292
293 // Add a terrain to the renderer.
294 // Note that we create a 'low resolution' 256x256 vertex terrain rather than trying for
295 // full resolution. This saves a lot of memory especially for very large regions.
252 private void CreateTerrain(WarpRenderer renderer, bool textureTerrain) 296 private void CreateTerrain(WarpRenderer renderer, bool textureTerrain)
253 { 297 {
254 ITerrainChannel terrain = m_scene.Heightmap; 298 ITerrainChannel terrain = m_scene.Heightmap;
255 float[] heightmap = terrain.GetFloatsSerialised(); 299
300 // 'diff' is the difference in scale between the real region size and the size of terrain we're buiding
301 float diff = (float)m_scene.RegionInfo.RegionSizeX / 256f;
256 302
257 warp_Object obj = new warp_Object(256 * 256, 255 * 255 * 2); 303 warp_Object obj = new warp_Object(256 * 256, 255 * 255 * 2);
258 304
259 for (int y = 0; y < 256; y++) 305 // Create all the vertices for the terrain
306 for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff)
260 { 307 {
261 for (int x = 0; x < 256; x++) 308 for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff)
262 { 309 {
263 int v = y * 256 + x; 310 warp_Vector pos = ConvertVector(x, y, (float)terrain[(int)x, (int)y]);
264 float height = heightmap[v]; 311 obj.addVertex(new warp_Vertex(pos,
265 312 x / (float)m_scene.RegionInfo.RegionSizeX,
266 warp_Vector pos = ConvertVector(new Vector3(x, y, height)); 313 (((float)m_scene.RegionInfo.RegionSizeY) - y) / m_scene.RegionInfo.RegionSizeY) );
267 obj.addVertex(new warp_Vertex(pos, (float)x / 255f, (float)(255 - y) / 255f));
268 } 314 }
269 } 315 }
270 316
271 for (int y = 0; y < 256; y++) 317 // Now that we have all the vertices, make another pass and create
318 // the normals for each of the surface triangles and
319 // create the list of triangle indices.
320 for (float y = 0; y < m_scene.RegionInfo.RegionSizeY; y += diff)
272 { 321 {
273 for (int x = 0; x < 256; x++) 322 for (float x = 0; x < m_scene.RegionInfo.RegionSizeX; x += diff)
274 { 323 {
275 if (x < 255 && y < 255) 324 float newX = x / diff;
325 float newY = y / diff;
326 if (newX < 255 && newY < 255)
276 { 327 {
277 int v = y * 256 + x; 328 int v = (int)newY * 256 + (int)newX;
278 329
279 // Normal 330 // Normal for a triangle made up of three adjacent vertices
280 Vector3 v1 = new Vector3(x, y, heightmap[y * 256 + x]); 331 Vector3 v1 = new Vector3(newX, newY, (float)terrain[(int)x, (int)y]);
281 Vector3 v2 = new Vector3(x + 1, y, heightmap[y * 256 + x + 1]); 332 Vector3 v2 = new Vector3(newX + 1, newY, (float)terrain[(int)(x + 1), (int)y]);
282 Vector3 v3 = new Vector3(x, y + 1, heightmap[(y + 1) * 256 + x]); 333 Vector3 v3 = new Vector3(newX, newY + 1, (float)terrain[(int)x, ((int)(y + 1))]);
283 warp_Vector norm = ConvertVector(SurfaceNormal(v1, v2, v3)); 334 warp_Vector norm = ConvertVector(SurfaceNormal(v1, v2, v3));
284 norm = norm.reverse(); 335 norm = norm.reverse();
285 obj.vertex(v).n = norm; 336 obj.vertex(v).n = norm;
286 337
287 // Triangle 1 338 // Make two triangles for each of the squares in the grid of vertices
288 obj.addTriangle( 339 obj.addTriangle(
289 v, 340 v,
290 v + 1, 341 v + 1,
291 v + 256); 342 v + 256);
292 343
293 // Triangle 2
294 obj.addTriangle( 344 obj.addTriangle(
295 v + 256 + 1, 345 v + 256 + 1,
296 v + 256, 346 v + 256,
@@ -305,7 +355,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
305 float[] startHeights = new float[4]; 355 float[] startHeights = new float[4];
306 float[] heightRanges = new float[4]; 356 float[] heightRanges = new float[4];
307 357
308 RegionSettings regionInfo = m_scene.RegionInfo.RegionSettings; 358 OpenSim.Framework.RegionSettings regionInfo = m_scene.RegionInfo.RegionSettings;
309 359
310 textureIDs[0] = regionInfo.TerrainTexture1; 360 textureIDs[0] = regionInfo.TerrainTexture1;
311 textureIDs[1] = regionInfo.TerrainTexture2; 361 textureIDs[1] = regionInfo.TerrainTexture2;
@@ -323,16 +373,18 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
323 heightRanges[3] = (float)regionInfo.Elevation2NE; 373 heightRanges[3] = (float)regionInfo.Elevation2NE;
324 374
325 uint globalX, globalY; 375 uint globalX, globalY;
326 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out globalX, out globalY); 376 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out globalX, out globalY);
327 377
328 warp_Texture texture; 378 warp_Texture texture;
329
330 using ( 379 using (
331 Bitmap image 380 Bitmap image
332 = TerrainSplat.Splat( 381 = TerrainSplat.Splat(terrain, textureIDs, startHeights, heightRanges,
333 heightmap, textureIDs, startHeights, heightRanges,
334 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain)) 382 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain))
335 { 383 {
384 image.Save( // DEBUG DEBUG
385 String.Format("maptiles/splat-{0}-{1}-{2}.jpg", m_scene.RegionInfo.RegionName,
386 m_scene.RegionInfo.RegionLocX, m_scene.RegionInfo.RegionLocY),
387 ImageFormat.Jpeg);
336 texture = new warp_Texture(image); 388 texture = new warp_Texture(image);
337 } 389 }
338 390
@@ -368,8 +420,48 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
368 if (prim.Scale.LengthSquared() < MIN_SIZE * MIN_SIZE) 420 if (prim.Scale.LengthSquared() < MIN_SIZE * MIN_SIZE)
369 return; 421 return;
370 422
423 FacetedMesh renderMesh = null;
371 Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset); 424 Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset);
372 FacetedMesh renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium); 425
426 if (m_renderMeshes)
427 {
428 if (omvPrim.Sculpt != null && omvPrim.Sculpt.SculptTexture != UUID.Zero)
429 {
430 // Try fetchinng the asset
431 byte[] sculptAsset = m_scene.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
432 if (sculptAsset != null)
433 {
434 // Is it a mesh?
435 if (omvPrim.Sculpt.Type == SculptType.Mesh)
436 {
437 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
438 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out renderMesh);
439 meshAsset = null;
440 }
441 else // It's sculptie
442 {
443 IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface<IJ2KDecoder>();
444 if (imgDecoder != null)
445 {
446 Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
447 if (sculpt != null)
448 {
449 renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt,
450 DetailLevel.Medium);
451 sculpt.Dispose();
452 }
453 }
454 }
455 }
456 }
457 }
458
459 // If not a mesh or sculptie, try the regular mesher
460 if (renderMesh == null)
461 {
462 renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium);
463 }
464
373 if (renderMesh == null) 465 if (renderMesh == null)
374 return; 466 return;
375 467
@@ -428,7 +520,11 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
428 520
429 Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); 521 Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i);
430 Color4 faceColor = GetFaceColor(teFace); 522 Color4 faceColor = GetFaceColor(teFace);
431 string materialName = GetOrCreateMaterial(renderer, faceColor); 523 string materialName = String.Empty;
524 if (m_texturePrims && prim.Scale.LengthSquared() > m_texturePrimSize*m_texturePrimSize)
525 materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID);
526 else
527 materialName = GetOrCreateMaterial(renderer, faceColor);
432 528
433 faceObj.transform(m); 529 faceObj.transform(m);
434 faceObj.setPos(primPos); 530 faceObj.setPos(primPos);
@@ -517,10 +613,51 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
517 return name; 613 return name;
518 } 614 }
519 615
616 public string GetOrCreateMaterial(WarpRenderer renderer, Color4 faceColor, UUID textureID)
617 {
618 string materialName = "Color-" + faceColor.ToString() + "-Texture-" + textureID.ToString();
619
620 if (renderer.Scene.material(materialName) == null)
621 {
622 renderer.AddMaterial(materialName, ConvertColor(faceColor));
623 if (faceColor.A < 1f)
624 {
625 renderer.Scene.material(materialName).setTransparency((byte) ((1f - faceColor.A)*255f));
626 }
627 warp_Texture texture = GetTexture(textureID);
628 if (texture != null)
629 renderer.Scene.material(materialName).setTexture(texture);
630 }
631
632 return materialName;
633 }
634
635 private warp_Texture GetTexture(UUID id)
636 {
637 warp_Texture ret = null;
638 byte[] asset = m_scene.AssetService.GetData(id.ToString());
639 if (asset != null)
640 {
641 IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface<IJ2KDecoder>();
642 Bitmap img = (Bitmap) imgDecoder.DecodeToImage(asset);
643 if (img != null)
644 {
645 return new warp_Texture(img);
646 }
647 }
648 return ret;
649 }
650
520 #endregion Rendering Methods 651 #endregion Rendering Methods
521 652
522 #region Static Helpers 653 #region Static Helpers
523 654
655 // Note: axis change.
656 private static warp_Vector ConvertVector(float x, float y, float z)
657 {
658 return new warp_Vector(x, z, y);
659 }
660
524 private static warp_Vector ConvertVector(Vector3 vector) 661 private static warp_Vector ConvertVector(Vector3 vector)
525 { 662 {
526 return new warp_Vector(vector.X, vector.Z, vector.Y); 663 return new warp_Vector(vector.X, vector.Z, vector.Y);
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
index 708a9a2..1fb1aba 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
@@ -184,8 +184,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
184 data.Name = info.RegionName; 184 data.Name = info.RegionName;
185 data.RegionFlags = 0; // TODO not used? 185 data.RegionFlags = 0; // TODO not used?
186 data.WaterHeight = 0; // not used 186 data.WaterHeight = 0; // not used
187 data.X = (ushort)(info.RegionLocX / Constants.RegionSize); 187 data.X = (ushort)Util.WorldToRegionLoc((uint)info.RegionLocX);
188 data.Y = (ushort)(info.RegionLocY / Constants.RegionSize); 188 data.Y = (ushort)Util.WorldToRegionLoc((uint)info.RegionLocY);
189 blocks.Add(data); 189 blocks.Add(data);
190 } 190 }
191 } 191 }
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index cdf1467..e925f0d 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -277,11 +277,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
277 { 277 {
278 List<MapBlockData> mapBlocks = new List<MapBlockData>(); ; 278 List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
279 279
280 // Get regions that are within 8 regions of here
280 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 281 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
281 (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, 282 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX - 8),
282 (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, 283 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX + 8),
283 (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, 284 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY - 8),
284 (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); 285 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY + 8) );
285 foreach (GridRegion r in regions) 286 foreach (GridRegion r in regions)
286 { 287 {
287 MapBlockData block = new MapBlockData(); 288 MapBlockData block = new MapBlockData();
@@ -405,7 +406,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
405 } 406 }
406 uint xstart = 0; 407 uint xstart = 0;
407 uint ystart = 0; 408 uint ystart = 0;
408 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out xstart, out ystart); 409 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
409 if (itemtype == 6) // Service 6 right now (MAP_ITEM_AGENTS_LOCATION; green dots) 410 if (itemtype == 6) // Service 6 right now (MAP_ITEM_AGENTS_LOCATION; green dots)
410 { 411 {
411 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) 412 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle)
@@ -803,7 +804,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
803 if (httpserver.Length == 0) 804 if (httpserver.Length == 0)
804 { 805 {
805 uint x = 0, y = 0; 806 uint x = 0, y = 0;
806 Utils.LongToUInts(regionhandle, out x, out y); 807 Util.RegionHandleToWorldLoc(regionhandle, out x, out y);
807 GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); 808 GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
808 809
809 if (mreg != null) 810 if (mreg != null)
@@ -1011,17 +1012,15 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1011 // on an unloaded square. 1012 // on an unloaded square.
1012 // But make sure: Look whether the one we requested is in there 1013 // But make sure: Look whether the one we requested is in there
1013 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 1014 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
1014 minX * (int)Constants.RegionSize, 1015 (int)Util.RegionToWorldLoc((uint)minX), (int)Util.RegionToWorldLoc((uint)maxX),
1015 maxX * (int)Constants.RegionSize, 1016 (int)Util.RegionToWorldLoc((uint)minY), (int)Util.RegionToWorldLoc((uint)maxY) );
1016 minY * (int)Constants.RegionSize,
1017 maxY * (int)Constants.RegionSize);
1018 1017
1019 if (regions != null) 1018 if (regions != null)
1020 { 1019 {
1021 foreach (GridRegion r in regions) 1020 foreach (GridRegion r in regions)
1022 { 1021 {
1023 if ((r.RegionLocX == minX * (int)Constants.RegionSize) && 1022 if (r.RegionLocX == Util.RegionToWorldLoc((uint)minX)
1024 (r.RegionLocY == minY * (int)Constants.RegionSize)) 1023 && r.RegionLocY == Util.RegionToWorldLoc((uint)minY) )
1025 { 1024 {
1026 // found it => add it to response 1025 // found it => add it to response
1027 MapBlockData block = new MapBlockData(); 1026 MapBlockData block = new MapBlockData();
@@ -1055,10 +1054,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1055 { 1054 {
1056 List<MapBlockData> mapBlocks = new List<MapBlockData>(); 1055 List<MapBlockData> mapBlocks = new List<MapBlockData>();
1057 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 1056 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
1058 (minX - 4) * (int)Constants.RegionSize, 1057 (int)Util.RegionToWorldLoc((uint)(minX - 4)), (int)Util.RegionToWorldLoc((uint)(maxX + 4)),
1059 (maxX + 4) * (int)Constants.RegionSize, 1058 (int)Util.RegionToWorldLoc((uint)(minY - 4)), (int)Util.RegionToWorldLoc((uint)(maxY + 4)) );
1060 (minY - 4) * (int)Constants.RegionSize,
1061 (maxY + 4) * (int)Constants.RegionSize);
1062 foreach (GridRegion r in regions) 1059 foreach (GridRegion r in regions)
1063 { 1060 {
1064 MapBlockData block = new MapBlockData(); 1061 MapBlockData block = new MapBlockData();
@@ -1086,8 +1083,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1086 break; 1083 break;
1087 } 1084 }
1088 block.Name = r.RegionName; 1085 block.Name = r.RegionName;
1089 block.X = (ushort)(r.RegionLocX / Constants.RegionSize); 1086 block.X = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocX);
1090 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize); 1087 block.Y = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocY);
1091 } 1088 }
1092 1089
1093 public Hashtable OnHTTPThrottled(Hashtable keysvals) 1090 public Hashtable OnHTTPThrottled(Hashtable keysvals)
@@ -1218,10 +1215,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1218 1215
1219 List<MapBlockData> mapBlocks = new List<MapBlockData>(); 1216 List<MapBlockData> mapBlocks = new List<MapBlockData>();
1220 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 1217 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
1221 (int)(m_scene.RegionInfo.RegionLocX - 9) * (int)Constants.RegionSize, 1218 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX - 9),
1222 (int)(m_scene.RegionInfo.RegionLocX + 9) * (int)Constants.RegionSize, 1219 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX + 9),
1223 (int)(m_scene.RegionInfo.RegionLocY - 9) * (int)Constants.RegionSize, 1220 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY - 9),
1224 (int)(m_scene.RegionInfo.RegionLocY + 9) * (int)Constants.RegionSize); 1221 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY + 9));
1225 List<AssetBase> textures = new List<AssetBase>(); 1222 List<AssetBase> textures = new List<AssetBase>();
1226 List<Image> bitImages = new List<Image>(); 1223 List<Image> bitImages = new List<Image>();
1227 1224
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 214b07a..709d8fc 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -92,12 +92,11 @@ namespace OpenSim.Region.Framework.Interfaces
92 92
93 void EnableChildAgent(ScenePresence agent, GridRegion region); 93 void EnableChildAgent(ScenePresence agent, GridRegion region);
94 94
95 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos); 95 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos);
96 96
97 void Cross(SceneObjectGroup sog, Vector3 position, bool silent); 97 void Cross(SceneObjectGroup sog, Vector3 position, bool silent);
98 98
99 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); 99 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version);
100
101 } 100 }
102 101
103 public interface IUserAgentVerificationModule 102 public interface IUserAgentVerificationModule
diff --git a/OpenSim/Region/Framework/Interfaces/IJ2KDecoder.cs b/OpenSim/Region/Framework/Interfaces/IJ2KDecoder.cs
index 46d03b3..1cbd045 100644
--- a/OpenSim/Region/Framework/Interfaces/IJ2KDecoder.cs
+++ b/OpenSim/Region/Framework/Interfaces/IJ2KDecoder.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -25,6 +25,7 @@
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 System.Drawing;
28using OpenMetaverse; 29using OpenMetaverse;
29using OpenMetaverse.Imaging; 30using OpenMetaverse.Imaging;
30 31
@@ -53,5 +54,12 @@ namespace OpenSim.Region.Framework.Interfaces
53 /// <param name="components">number of components</param> 54 /// <param name="components">number of components</param>
54 /// <returns>true if decode was successful. false otherwise.</returns> 55 /// <returns>true if decode was successful. false otherwise.</returns>
55 bool Decode(UUID assetID, byte[] j2kData, out OpenJPEG.J2KLayerInfo[] layers, out int components); 56 bool Decode(UUID assetID, byte[] j2kData, out OpenJPEG.J2KLayerInfo[] layers, out int components);
57
58 /// <summary>
59 /// Provides a synchronous decode direct to an image object
60 /// </summary>
61 /// <param name="j2kData"></param>
62 /// <returns>decoded image or 'null' of unsuccessful</returns>
63 Image DecodeToImage(byte[] j2kData);
56 } 64 }
57} 65}
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
index 085b5ca..8948f04 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
@@ -68,13 +68,22 @@ namespace OpenSim.Region.Framework.Interfaces
68 /// </summary> 68 /// </summary>
69 /// <param name="ter">HeightField data</param> 69 /// <param name="ter">HeightField data</param>
70 /// <param name="regionID">region UUID</param> 70 /// <param name="regionID">region UUID</param>
71 void StoreTerrain(TerrainData terrain, UUID regionID);
72
73 // Legacy version kept for downward compabibility
71 void StoreTerrain(double[,] terrain, UUID regionID); 74 void StoreTerrain(double[,] terrain, UUID regionID);
72 75
73 /// <summary> 76 /// <summary>
74 /// Load the latest terrain revision from region storage 77 /// Load the latest terrain revision from region storage
75 /// </summary> 78 /// </summary>
76 /// <param name="regionID">the region UUID</param> 79 /// <param name="regionID">the region UUID</param>
80 /// <param name="sizeX">the X dimension of the region being filled</param>
81 /// <param name="sizeY">the Y dimension of the region being filled</param>
82 /// <param name="sizeZ">the Z dimension of the region being filled</param>
77 /// <returns>Heightfield data</returns> 83 /// <returns>Heightfield data</returns>
84 TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
85
86 // Legacy version kept for downward compabibility
78 double[,] LoadTerrain(UUID regionID); 87 double[,] LoadTerrain(UUID regionID);
79 88
80 void StoreLandObject(ILandObject Parcel); 89 void StoreLandObject(ILandObject Parcel);
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index 3787ca0..917b5d1 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -79,13 +79,22 @@ namespace OpenSim.Region.Framework.Interfaces
79 /// </summary> 79 /// </summary>
80 /// <param name="ter">HeightField data</param> 80 /// <param name="ter">HeightField data</param>
81 /// <param name="regionID">region UUID</param> 81 /// <param name="regionID">region UUID</param>
82 void StoreTerrain(TerrainData terrain, UUID regionID);
83
84 // Legacy version kept for downward compabibility
82 void StoreTerrain(double[,] terrain, UUID regionID); 85 void StoreTerrain(double[,] terrain, UUID regionID);
83 86
84 /// <summary> 87 /// <summary>
85 /// Load the latest terrain revision from region storage 88 /// Load the latest terrain revision from region storage
86 /// </summary> 89 /// </summary>
87 /// <param name="regionID">the region UUID</param> 90 /// <param name="regionID">the region UUID</param>
91 /// <param name="pSizeX">the X dimension of the terrain being filled</param>
92 /// <param name="pSizeY">the Y dimension of the terrain being filled</param>
93 /// <param name="pSizeZ">the Z dimension of the terrain being filled</param>
88 /// <returns>Heightfield data</returns> 94 /// <returns>Heightfield data</returns>
95 TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
96
97 // Legacy version kept for downward compabibility
89 double[,] LoadTerrain(UUID regionID); 98 double[,] LoadTerrain(UUID regionID);
90 99
91 void StoreLandObject(ILandObject Parcel); 100 void StoreLandObject(ILandObject Parcel);
@@ -135,4 +144,5 @@ namespace OpenSim.Region.Framework.Interfaces
135 144
136 void Shutdown(); 145 void Shutdown();
137 } 146 }
147
138} 148}
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
index e467701..469bd31 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
@@ -25,13 +25,22 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using OpenSim.Framework;
29
28namespace OpenSim.Region.Framework.Interfaces 30namespace OpenSim.Region.Framework.Interfaces
29{ 31{
30 public interface ITerrainChannel 32 public interface ITerrainChannel
31 { 33 {
32 int Height { get; } 34 int Width { get;} // X dimension
35 int Height { get;} // Y dimension
36 int Altitude { get;} // Z dimension
37
33 double this[int x, int y] { get; set; } 38 double this[int x, int y] { get; set; }
34 int Width { get; } 39
40 float GetHeightAtXYZ(float x, float y, float z);
41
42 // Return the packaged terrain data for passing into lower levels of communication
43 TerrainData GetTerrainData();
35 44
36 /// <summary> 45 /// <summary>
37 /// Squash the entire heightmap into a single dimensioned array 46 /// Squash the entire heightmap into a single dimensioned array
@@ -40,7 +49,10 @@ namespace OpenSim.Region.Framework.Interfaces
40 float[] GetFloatsSerialised(); 49 float[] GetFloatsSerialised();
41 50
42 double[,] GetDoubles(); 51 double[,] GetDoubles();
52
53 // Check if a location has been updated. Clears the taint flag as a side effect.
43 bool Tainted(int x, int y); 54 bool Tainted(int x, int y);
55
44 ITerrainChannel MakeCopy(); 56 ITerrainChannel MakeCopy();
45 string SaveToXmlString(); 57 string SaveToXmlString();
46 void LoadFromXmlString(string data); 58 void LoadFromXmlString(string data);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 9cc5cde..b86f349 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -46,8 +46,8 @@ namespace OpenSim.Region.Framework.Scenes
46{ 46{
47 public partial class Scene 47 public partial class Scene
48 { 48 {
49 private static readonly ILog m_log 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly string LogHeader = "[SCENE INVENTORY]";
51 51
52 /// <summary> 52 /// <summary>
53 /// Allows asynchronous derezzing of objects from the scene into a client's inventory. 53 /// Allows asynchronous derezzing of objects from the scene into a client's inventory.
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index a9fe556..aee621f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1033,7 +1033,7 @@ namespace OpenSim.Region.Framework.Scenes
1033 1033
1034 BordersLocked = true; 1034 BordersLocked = true;
1035 Border northBorder = new Border(); 1035 Border northBorder = new Border();
1036 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<--- 1036 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (float)RegionInfo.RegionSizeY); //<---
1037 northBorder.CrossDirection = Cardinals.N; 1037 northBorder.CrossDirection = Cardinals.N;
1038 NorthBorders.Add(northBorder); 1038 NorthBorders.Add(northBorder);
1039 1039
@@ -1043,7 +1043,7 @@ namespace OpenSim.Region.Framework.Scenes
1043 SouthBorders.Add(southBorder); 1043 SouthBorders.Add(southBorder);
1044 1044
1045 Border eastBorder = new Border(); 1045 Border eastBorder = new Border();
1046 eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<--- 1046 eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (float)RegionInfo.RegionSizeY); //<---
1047 eastBorder.CrossDirection = Cardinals.E; 1047 eastBorder.CrossDirection = Cardinals.E;
1048 EastBorders.Add(eastBorder); 1048 EastBorders.Add(eastBorder);
1049 1049
@@ -1099,8 +1099,9 @@ namespace OpenSim.Region.Framework.Scenes
1099 /// <returns>True after all operations complete, throws exceptions otherwise.</returns> 1099 /// <returns>True after all operations complete, throws exceptions otherwise.</returns>
1100 public override void OtherRegionUp(GridRegion otherRegion) 1100 public override void OtherRegionUp(GridRegion otherRegion)
1101 { 1101 {
1102 uint xcell = (uint)((int)otherRegion.RegionLocX / (int)Constants.RegionSize); 1102 uint xcell = Util.WorldToRegionLoc((uint)otherRegion.RegionLocX);
1103 uint ycell = (uint)((int)otherRegion.RegionLocY / (int)Constants.RegionSize); 1103 uint ycell = Util.WorldToRegionLoc((uint)otherRegion.RegionLocY);
1104
1104 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}", 1105 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}",
1105 // RegionInfo.RegionName, otherRegion.RegionName, xcell, ycell); 1106 // RegionInfo.RegionName, otherRegion.RegionName, xcell, ycell);
1106 1107
@@ -1172,46 +1173,6 @@ namespace OpenSim.Region.Framework.Scenes
1172 return found; 1173 return found;
1173 } 1174 }
1174 1175
1175 /// <summary>
1176 /// Checks whether this region has a neighbour in the given direction.
1177 /// </summary>
1178 /// <param name="car"></param>
1179 /// <param name="fix"></param>
1180 /// <returns>
1181 /// An integer which represents a compass point. N == 1, going clockwise until we reach NW == 8.
1182 /// Returns a positive integer if there is a region in that direction, a negative integer if not.
1183 /// </returns>
1184 public int HaveNeighbor(Cardinals car, ref int[] fix)
1185 {
1186 uint neighbourx = RegionInfo.RegionLocX;
1187 uint neighboury = RegionInfo.RegionLocY;
1188
1189 int dir = (int)car;
1190
1191 if (dir > 1 && dir < 5) //Heading East
1192 neighbourx++;
1193 else if (dir > 5) // Heading West
1194 neighbourx--;
1195
1196 if (dir < 3 || dir == 8) // Heading North
1197 neighboury++;
1198 else if (dir > 3 && dir < 7) // Heading Sout
1199 neighboury--;
1200
1201 int x = (int)(neighbourx * Constants.RegionSize);
1202 int y = (int)(neighboury * Constants.RegionSize);
1203 GridRegion neighbourRegion = GridService.GetRegionByPosition(RegionInfo.ScopeID, x, y);
1204
1205 if (neighbourRegion == null)
1206 {
1207 fix[0] = (int)(RegionInfo.RegionLocX - neighbourx);
1208 fix[1] = (int)(RegionInfo.RegionLocY - neighboury);
1209 return dir * (-1);
1210 }
1211 else
1212 return dir;
1213 }
1214
1215 // Alias IncomingHelloNeighbour OtherRegionUp, for now 1176 // Alias IncomingHelloNeighbour OtherRegionUp, for now
1216 public GridRegion IncomingHelloNeighbour(RegionInfo neighbour) 1177 public GridRegion IncomingHelloNeighbour(RegionInfo neighbour)
1217 { 1178 {
@@ -1894,7 +1855,7 @@ namespace OpenSim.Region.Framework.Scenes
1894 { 1855 {
1895 try 1856 try
1896 { 1857 {
1897 double[,] map = SimulationDataService.LoadTerrain(RegionInfo.RegionID); 1858 TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
1898 if (map == null) 1859 if (map == null)
1899 { 1860 {
1900 // This should be in the Terrain module, but it isn't because 1861 // This should be in the Terrain module, but it isn't because
@@ -1905,7 +1866,7 @@ namespace OpenSim.Region.Framework.Scenes
1905 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 1866 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
1906 1867
1907 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); 1868 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain);
1908 Heightmap = new TerrainChannel(m_InitialTerrain); 1869 Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
1909 1870
1910 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 1871 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
1911 } 1872 }
@@ -2483,6 +2444,23 @@ namespace OpenSim.Region.Framework.Scenes
2483 EntityTransferModule.Cross(grp, attemptedPosition, silent); 2444 EntityTransferModule.Cross(grp, attemptedPosition, silent);
2484 } 2445 }
2485 2446
2447 // Simple test to see if a position is in the current region.
2448 // Resuming the position is relative to the region so anything outside its bounds.
2449 // Return 'true' if position inside region.
2450 public bool PositionIsInCurrentRegion(Vector3 pos)
2451 {
2452 bool ret = true;
2453 int xx = (int)Math.Floor(pos.X);
2454 int yy = (int)Math.Floor(pos.Y);
2455 if (xx < 0
2456 || xx >= RegionInfo.RegionSizeX
2457 || yy < 0
2458 || yy >= RegionInfo.RegionSizeY)
2459 ret = false;
2460 return ret;
2461
2462 }
2463
2486 public Border GetCrossedBorder(Vector3 position, Cardinals gridline) 2464 public Border GetCrossedBorder(Vector3 position, Cardinals gridline)
2487 { 2465 {
2488 if (BordersLocked) 2466 if (BordersLocked)
@@ -3900,6 +3878,7 @@ namespace OpenSim.Region.Framework.Scenes
3900 { 3878 {
3901 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E); 3879 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
3902 acd.startpos.X = crossedBorder.BorderLine.Z - 1; 3880 acd.startpos.X = crossedBorder.BorderLine.Z - 1;
3881 m_log.DebugFormat("{0} NewUserConnection Adjusted border E. startpos={1}", LogHeader, acd.startpos);
3903 } 3882 }
3904 3883
3905 if (TestBorderCross(acd.startpos, Cardinals.N)) 3884 if (TestBorderCross(acd.startpos, Cardinals.N))
@@ -3999,12 +3978,12 @@ namespace OpenSim.Region.Framework.Scenes
3999 { 3978 {
4000 if (posX < 0) 3979 if (posX < 0)
4001 posX = 0; 3980 posX = 0;
4002 else if (posX >= 256) 3981 else if (posX >= (float)RegionInfo.RegionSizeX)
4003 posX = 255.999f; 3982 posX = (float)RegionInfo.RegionSizeX - 0.001f;
4004 if (posY < 0) 3983 if (posY < 0)
4005 posY = 0; 3984 posY = 0;
4006 else if (posY >= 256) 3985 else if (posY >= (float)RegionInfo.RegionSizeY)
4007 posY = 255.999f; 3986 posY = (float)RegionInfo.RegionSizeY - 0.001f;
4008 3987
4009 reason = String.Empty; 3988 reason = String.Empty;
4010 if (Permissions.IsGod(agentID)) 3989 if (Permissions.IsGod(agentID))
@@ -4298,7 +4277,7 @@ namespace OpenSim.Region.Framework.Scenes
4298 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4277 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4299 4278
4300 // TODO: This check should probably be in QueryAccess(). 4279 // TODO: This check should probably be in QueryAccess().
4301 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4280 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2);
4302 if (nearestParcel == null) 4281 if (nearestParcel == null)
4303 { 4282 {
4304 m_log.InfoFormat( 4283 m_log.InfoFormat(
@@ -4593,44 +4572,6 @@ namespace OpenSim.Region.Framework.Scenes
4593 ScenePresence sp = GetScenePresence(remoteClient.AgentId); 4572 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4594 if (sp != null) 4573 if (sp != null)
4595 { 4574 {
4596 uint regionX = RegionInfo.RegionLocX;
4597 uint regionY = RegionInfo.RegionLocY;
4598
4599 Utils.LongToUInts(regionHandle, out regionX, out regionY);
4600
4601 int shiftx = (int) regionX - (int) RegionInfo.RegionLocX * (int)Constants.RegionSize;
4602 int shifty = (int) regionY - (int) RegionInfo.RegionLocY * (int)Constants.RegionSize;
4603
4604 position.X += shiftx;
4605 position.Y += shifty;
4606
4607 bool result = false;
4608
4609 if (TestBorderCross(position,Cardinals.N))
4610 result = true;
4611
4612 if (TestBorderCross(position, Cardinals.S))
4613 result = true;
4614
4615 if (TestBorderCross(position, Cardinals.E))
4616 result = true;
4617
4618 if (TestBorderCross(position, Cardinals.W))
4619 result = true;
4620
4621 // bordercross if position is outside of region
4622
4623 if (!result)
4624 {
4625 regionHandle = RegionInfo.RegionHandle;
4626 }
4627 else
4628 {
4629 // not in this region, undo the shift!
4630 position.X -= shiftx;
4631 position.Y -= shifty;
4632 }
4633
4634 if (EntityTransferModule != null) 4575 if (EntityTransferModule != null)
4635 { 4576 {
4636 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags); 4577 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
@@ -4810,7 +4751,7 @@ namespace OpenSim.Region.Framework.Scenes
4810 else 4751 else
4811 { 4752 {
4812 4753
4813 if (pos.X > 0f && pos.X < Constants.RegionSize && pos.Y > 0f && pos.Y < Constants.RegionSize) 4754 if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY)
4814 { 4755 {
4815 // The only time parcel != null when an object is inside a region is when 4756 // The only time parcel != null when an object is inside a region is when
4816 // there is nothing behind the landchannel. IE, no land plugin loaded. 4757 // there is nothing behind the landchannel. IE, no land plugin loaded.
@@ -5471,7 +5412,7 @@ namespace OpenSim.Region.Framework.Scenes
5471 { 5412 {
5472 Vector3 unitDirection = Vector3.Normalize(direction); 5413 Vector3 unitDirection = Vector3.Normalize(direction);
5473 //Making distance to search go through some sane limit of distance 5414 //Making distance to search go through some sane limit of distance
5474 for (float distance = 0; distance < Constants.RegionSize * 2; distance += .5f) 5415 for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f)
5475 { 5416 {
5476 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance)); 5417 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance));
5477 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) 5418 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y))
@@ -5525,9 +5466,9 @@ namespace OpenSim.Region.Framework.Scenes
5525 int count = 0; 5466 int count = 0;
5526 int avgx = 0; 5467 int avgx = 0;
5527 int avgy = 0; 5468 int avgy = 0;
5528 for (int x = 0; x < Constants.RegionSize; x++) 5469 for (int x = 0; x < RegionInfo.RegionSizeX; x++)
5529 { 5470 {
5530 for (int y = 0; y < Constants.RegionSize; y++) 5471 for (int y = 0; y < RegionInfo.RegionSizeY; y++)
5531 { 5472 {
5532 //Just keep a running average as we check if all the points are inside or not 5473 //Just keep a running average as we check if all the points are inside or not
5533 if (parcel.ContainsPoint(x, y)) 5474 if (parcel.ContainsPoint(x, y))
@@ -5551,31 +5492,33 @@ namespace OpenSim.Region.Framework.Scenes
5551 5492
5552 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) 5493 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar)
5553 { 5494 {
5554 float xdistance = avatar.AbsolutePosition.X < Constants.RegionSize / 2 ? avatar.AbsolutePosition.X : Constants.RegionSize - avatar.AbsolutePosition.X; 5495 float xdistance = avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2
5555 float ydistance = avatar.AbsolutePosition.Y < Constants.RegionSize / 2 ? avatar.AbsolutePosition.Y : Constants.RegionSize - avatar.AbsolutePosition.Y; 5496 ? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X;
5497 float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2
5498 ? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y;
5556 5499
5557 //find out what vertical edge to go to 5500 //find out what vertical edge to go to
5558 if (xdistance < ydistance) 5501 if (xdistance < ydistance)
5559 { 5502 {
5560 if (avatar.AbsolutePosition.X < Constants.RegionSize / 2) 5503 if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2)
5561 { 5504 {
5562 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y); 5505 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y);
5563 } 5506 }
5564 else 5507 else
5565 { 5508 {
5566 return GetPositionAtAvatarHeightOrGroundHeight(avatar, Constants.RegionSize, avatar.AbsolutePosition.Y); 5509 return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y);
5567 } 5510 }
5568 } 5511 }
5569 //find out what horizontal edge to go to 5512 //find out what horizontal edge to go to
5570 else 5513 else
5571 { 5514 {
5572 if (avatar.AbsolutePosition.Y < Constants.RegionSize / 2) 5515 if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2)
5573 { 5516 {
5574 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f); 5517 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f);
5575 } 5518 }
5576 else 5519 else
5577 { 5520 {
5578 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, Constants.RegionSize); 5521 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY);
5579 } 5522 }
5580 } 5523 }
5581 } 5524 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index c86f412..b059ecf 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -42,8 +42,8 @@ namespace OpenSim.Region.Framework.Scenes
42{ 42{
43 public abstract class SceneBase : IScene 43 public abstract class SceneBase : IScene
44 { 44 {
45 protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 protected static readonly string LogHeader = "[SCENE]"; 46 private static readonly string LogHeader = "[SCENE]";
47 47
48 #region Events 48 #region Events
49 49
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 77889fa..c873e40 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -92,7 +92,7 @@ namespace OpenSim.Region.Framework.Scenes
92 { 92 {
93 m_log.DebugFormat( 93 m_log.DebugFormat(
94 "[SCENE COMMUNICATION SERVICE]: Region {0} successfully informed neighbour {1} at {2}-{3} that it is up", 94 "[SCENE COMMUNICATION SERVICE]: Region {0} successfully informed neighbour {1} at {2}-{3} that it is up",
95 m_scene.Name, neighbour.RegionName, x / Constants.RegionSize, y / Constants.RegionSize); 95 m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
96 96
97 m_scene.EventManager.TriggerOnRegionUp(neighbour); 97 m_scene.EventManager.TriggerOnRegionUp(neighbour);
98 } 98 }
@@ -100,7 +100,7 @@ namespace OpenSim.Region.Framework.Scenes
100 { 100 {
101 m_log.WarnFormat( 101 m_log.WarnFormat(
102 "[SCENE COMMUNICATION SERVICE]: Region {0} failed to inform neighbour at {1}-{2} that it is up.", 102 "[SCENE COMMUNICATION SERVICE]: Region {0} failed to inform neighbour at {1}-{2} that it is up.",
103 m_scene.Name, x / Constants.RegionSize, y / Constants.RegionSize); 103 m_scene.Name, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
104 } 104 }
105 } 105 }
106 106
@@ -166,7 +166,7 @@ namespace OpenSim.Region.Framework.Scenes
166 // we only want to send one update to each simulator; the simulator will 166 // we only want to send one update to each simulator; the simulator will
167 // hand it off to the regions where a child agent exists, this does assume 167 // hand it off to the regions where a child agent exists, this does assume
168 // that the region position is cached or performance will degrade 168 // that the region position is cached or performance will degrade
169 Utils.LongToUInts(regionHandle, out x, out y); 169 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
170 GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y); 170 GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
171 if (dest == null) 171 if (dest == null)
172 continue; 172 continue;
@@ -203,7 +203,7 @@ namespace OpenSim.Region.Framework.Scenes
203 203
204 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); 204 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
205 uint x = 0, y = 0; 205 uint x = 0, y = 0;
206 Utils.LongToUInts(regionHandle, out x, out y); 206 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
207 207
208 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 208 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
209 209
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 9bd7632..c6b98ca 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -334,7 +334,7 @@ namespace OpenSim.Region.Framework.Scenes
334 { 334 {
335 get 335 get
336 { 336 {
337 Vector3 minScale = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionSize); 337 Vector3 minScale = new Vector3(Constants.MaximumRegionSize, Constants.MaximumRegionSize, Constants.MaximumRegionSize);
338 Vector3 maxScale = Vector3.Zero; 338 Vector3 maxScale = Vector3.Zero;
339 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 339 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
340 340
@@ -466,8 +466,6 @@ namespace OpenSim.Region.Framework.Scenes
466 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 466 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
467 { 467 {
468 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 468 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
469 uint x = 0;
470 uint y = 0;
471 string version = String.Empty; 469 string version = String.Empty;
472 Vector3 newpos = Vector3.Zero; 470 Vector3 newpos = Vector3.Zero;
473 OpenSim.Services.Interfaces.GridRegion destination = null; 471 OpenSim.Services.Interfaces.GridRegion destination = null;
@@ -487,7 +485,7 @@ namespace OpenSim.Region.Framework.Scenes
487 485
488 // We set the avatar position as being the object 486 // We set the avatar position as being the object
489 // position to get the region to send to 487 // position to get the region to send to
490 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null) 488 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out version, out newpos)) == null)
491 { 489 {
492 canCross = false; 490 canCross = false;
493 break; 491 break;
@@ -522,14 +520,14 @@ namespace OpenSim.Region.Framework.Scenes
522 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 520 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
523 521
524 // Normalize 522 // Normalize
525 if (val.X >= Constants.RegionSize) 523 if (val.X >= m_scene.RegionInfo.RegionSizeX)
526 val.X -= Constants.RegionSize; 524 val.X -= m_scene.RegionInfo.RegionSizeX;
527 if (val.Y >= Constants.RegionSize) 525 if (val.Y >= m_scene.RegionInfo.RegionSizeY)
528 val.Y -= Constants.RegionSize; 526 val.Y -= m_scene.RegionInfo.RegionSizeY;
529 if (val.X < 0) 527 if (val.X < 0)
530 val.X += Constants.RegionSize; 528 val.X += m_scene.RegionInfo.RegionSizeX;
531 if (val.Y < 0) 529 if (val.Y < 0)
532 val.Y += Constants.RegionSize; 530 val.Y += m_scene.RegionInfo.RegionSizeY;
533 531
534 // If it's deleted, crossing was successful 532 // If it's deleted, crossing was successful
535 if (IsDeleted) 533 if (IsDeleted)
@@ -577,9 +575,9 @@ namespace OpenSim.Region.Framework.Scenes
577 } 575 }
578 } 576 }
579 Vector3 oldp = AbsolutePosition; 577 Vector3 oldp = AbsolutePosition;
580 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f); 578 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)m_scene.RegionInfo.RegionSizeX - 0.5f);
581 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f); 579 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)m_scene.RegionInfo.RegionSizeY - 0.5f);
582 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f); 580 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, Constants.RegionHeight);
583 } 581 }
584 } 582 }
585 583
@@ -996,9 +994,9 @@ namespace OpenSim.Region.Framework.Scenes
996 maxX = -256f; 994 maxX = -256f;
997 maxY = -256f; 995 maxY = -256f;
998 maxZ = -256f; 996 maxZ = -256f;
999 minX = 256f; 997 minX = 10000f;
1000 minY = 256f; 998 minY = 10000f;
1001 minZ = 8192f; 999 minZ = 10000f;
1002 1000
1003 SceneObjectPart[] parts = m_parts.GetArray(); 1001 SceneObjectPart[] parts = m_parts.GetArray();
1004 for (int i = 0; i < parts.Length; i++) 1002 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 85a20e9..b4274ba 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -76,6 +76,7 @@ namespace OpenSim.Region.Framework.Scenes
76 public class ScenePresence : EntityBase, IScenePresence 76 public class ScenePresence : EntityBase, IScenePresence
77 { 77 {
78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
79 private static readonly String LogHeader = "[SCENE PRESENCE]";
79 80
80// ~ScenePresence() 81// ~ScenePresence()
81// { 82// {
@@ -759,9 +760,8 @@ namespace OpenSim.Region.Framework.Scenes
759 foreach (ulong handle in seeds.Keys) 760 foreach (ulong handle in seeds.Keys)
760 { 761 {
761 uint x, y; 762 uint x, y;
762 Utils.LongToUInts(handle, out x, out y); 763 Util.RegionHandleToRegionLoc(handle, out x, out y);
763 x = x / Constants.RegionSize; 764
764 y = y / Constants.RegionSize;
765 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY)) 765 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
766 { 766 {
767 old.Add(handle); 767 old.Add(handle);
@@ -783,9 +783,7 @@ namespace OpenSim.Region.Framework.Scenes
783 foreach (KeyValuePair<ulong, string> kvp in KnownRegions) 783 foreach (KeyValuePair<ulong, string> kvp in KnownRegions)
784 { 784 {
785 uint x, y; 785 uint x, y;
786 Utils.LongToUInts(kvp.Key, out x, out y); 786 Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
787 x = x / Constants.RegionSize;
788 y = y / Constants.RegionSize;
789 m_log.Info(" >> "+x+", "+y+": "+kvp.Value); 787 m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
790 } 788 }
791 } 789 }
@@ -1092,6 +1090,10 @@ namespace OpenSim.Region.Framework.Scenes
1092 // before the inventory is processed in MakeRootAgent. This fixes a race condition 1090 // before the inventory is processed in MakeRootAgent. This fixes a race condition
1093 // related to the handling of attachments 1091 // related to the handling of attachments
1094 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance); 1092 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
1093
1094 /* RA 20140111: Commented out these TestBorderCross's.
1095 * Not sure why this code is here. It is not checking all the borders
1096 * and 'in region' sanity checking is done in CheckAndAdjustLandingPoint and below.
1095 if (m_scene.TestBorderCross(pos, Cardinals.E)) 1097 if (m_scene.TestBorderCross(pos, Cardinals.E))
1096 { 1098 {
1097 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 1099 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
@@ -1103,6 +1105,7 @@ namespace OpenSim.Region.Framework.Scenes
1103 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 1105 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
1104 pos.Y = crossedBorder.BorderLine.Z - 1; 1106 pos.Y = crossedBorder.BorderLine.Z - 1;
1105 } 1107 }
1108 */
1106 1109
1107 CheckAndAdjustLandingPoint(ref pos); 1110 CheckAndAdjustLandingPoint(ref pos);
1108 1111
@@ -1123,7 +1126,7 @@ namespace OpenSim.Region.Framework.Scenes
1123 1126
1124 float posZLimit = 0; 1127 float posZLimit = 0;
1125 1128
1126 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 1129 if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY)
1127 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1130 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
1128 1131
1129 float newPosZ = posZLimit + localAVHeight / 2; 1132 float newPosZ = posZLimit + localAVHeight / 2;
@@ -2386,7 +2389,7 @@ namespace OpenSim.Region.Framework.Scenes
2386 if (regionCombinerModule != null) 2389 if (regionCombinerModule != null)
2387 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); 2390 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
2388 else 2391 else
2389 regionSize = new Vector2(Constants.RegionSize); 2392 regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY);
2390 2393
2391 if (pos.X < 0 || pos.X >= regionSize.X 2394 if (pos.X < 0 || pos.X >= regionSize.X
2392 || pos.Y < 0 || pos.Y >= regionSize.Y 2395 || pos.Y < 0 || pos.Y >= regionSize.Y
@@ -2404,8 +2407,8 @@ namespace OpenSim.Region.Framework.Scenes
2404// } 2407// }
2405 2408
2406 // Get terrain height for sub-region in a megaregion if necessary 2409 // Get terrain height for sub-region in a megaregion if necessary
2407 int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X); 2410 int X = (int)((m_scene.RegionInfo.WorldLocX) + pos.X);
2408 int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y); 2411 int Y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y);
2409 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y); 2412 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y);
2410 // If X and Y is NaN, target_region will be null 2413 // If X and Y is NaN, target_region will be null
2411 if (target_region == null) 2414 if (target_region == null)
@@ -2416,7 +2419,7 @@ namespace OpenSim.Region.Framework.Scenes
2416 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene)) 2419 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
2417 targetScene = m_scene; 2420 targetScene = m_scene;
2418 2421
2419 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)]; 2422 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
2420 pos.Z = Math.Max(terrainHeight, pos.Z); 2423 pos.Z = Math.Max(terrainHeight, pos.Z);
2421 2424
2422 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 2425 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -3451,10 +3454,14 @@ namespace OpenSim.Region.Framework.Scenes
3451 if (!IsInTransit) 3454 if (!IsInTransit)
3452 { 3455 {
3453 Vector3 pos2 = AbsolutePosition; 3456 Vector3 pos2 = AbsolutePosition;
3457 Vector3 origPosition = pos2;
3454 Vector3 vel = Velocity; 3458 Vector3 vel = Velocity;
3455 int neighbor = 0; 3459 int neighbor = 0;
3456 int[] fix = new int[2]; 3460 int[] fix = new int[2];
3457 3461
3462 // Compute the avatar position in the next physics tick.
3463 // If the avatar will be crossing, we force the crossing to happen now
3464 // in the hope that this will make the avatar movement smoother when crossing.
3458 float timeStep = 0.1f; 3465 float timeStep = 0.1f;
3459 pos2.X = pos2.X + (vel.X * timeStep); 3466 pos2.X = pos2.X + (vel.X * timeStep);
3460 pos2.Y = pos2.Y + (vel.Y * timeStep); 3467 pos2.Y = pos2.Y + (vel.Y * timeStep);
@@ -3462,111 +3469,44 @@ namespace OpenSim.Region.Framework.Scenes
3462 3469
3463 if (!IsInTransit) 3470 if (!IsInTransit)
3464 { 3471 {
3465// m_log.DebugFormat( 3472 if (!m_scene.PositionIsInCurrentRegion(pos2))
3466// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3467// pos2, Name, Scene.Name);
3468
3469 // Checks if where it's headed exists a region
3470 bool needsTransit = false;
3471 if (m_scene.TestBorderCross(pos2, Cardinals.W))
3472 {
3473 if (m_scene.TestBorderCross(pos2, Cardinals.S))
3474 {
3475 needsTransit = true;
3476 neighbor = m_scene.HaveNeighbor(Cardinals.SW, ref fix);
3477 }
3478 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3479 {
3480 needsTransit = true;
3481 neighbor = m_scene.HaveNeighbor(Cardinals.NW, ref fix);
3482 }
3483 else
3484 {
3485 needsTransit = true;
3486 neighbor = m_scene.HaveNeighbor(Cardinals.W, ref fix);
3487 }
3488 }
3489 else if (m_scene.TestBorderCross(pos2, Cardinals.E))
3490 { 3473 {
3491 if (m_scene.TestBorderCross(pos2, Cardinals.S)) 3474 m_log.DebugFormat("{0} CheckForBorderCrossing: position outside region. {1} in {2} at pos {3}",
3475 LogHeader, Name, Scene.Name, pos2);
3476
3477 // Disconnect from the current region
3478 bool isFlying = Flying;
3479 RemoveFromPhysicalScene();
3480 // pos2 is the forcasted position so make that the 'current' position so the crossing
3481 // code will move us into the newly addressed region.
3482 m_pos = pos2;
3483 if (CrossToNewRegion())
3492 { 3484 {
3493 needsTransit = true; 3485 AddToPhysicalScene(isFlying);
3494 neighbor = m_scene.HaveNeighbor(Cardinals.SE, ref fix);
3495 }
3496 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3497 {
3498 needsTransit = true;
3499 neighbor = m_scene.HaveNeighbor(Cardinals.NE, ref fix);
3500 } 3486 }
3501 else 3487 else
3502 { 3488 {
3503 needsTransit = true; 3489 // Tried to make crossing happen but it failed.
3504 neighbor = m_scene.HaveNeighbor(Cardinals.E, ref fix);
3505 }
3506 }
3507 else if (m_scene.TestBorderCross(pos2, Cardinals.S))
3508 {
3509 needsTransit = true;
3510 neighbor = m_scene.HaveNeighbor(Cardinals.S, ref fix);
3511 }
3512 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3513 {
3514 needsTransit = true;
3515 neighbor = m_scene.HaveNeighbor(Cardinals.N, ref fix);
3516 }
3517
3518 // Makes sure avatar does not end up outside region
3519 if (neighbor <= 0)
3520 {
3521 if (needsTransit)
3522 {
3523 if (m_requestedSitTargetUUID == UUID.Zero)
3524 {
3525 bool isFlying = Flying;
3526 RemoveFromPhysicalScene();
3527
3528 Vector3 pos = AbsolutePosition;
3529 if (AbsolutePosition.X < 0)
3530 pos.X += Velocity.X * 2;
3531 else if (AbsolutePosition.X > Constants.RegionSize)
3532 pos.X -= Velocity.X * 2;
3533 if (AbsolutePosition.Y < 0)
3534 pos.Y += Velocity.Y * 2;
3535 else if (AbsolutePosition.Y > Constants.RegionSize)
3536 pos.Y -= Velocity.Y * 2;
3537 Velocity = Vector3.Zero;
3538 AbsolutePosition = pos;
3539
3540// m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition);
3541
3542 AddToPhysicalScene(isFlying);
3543 }
3544 }
3545 }
3546 else if (neighbor > 0)
3547 {
3548 if (!CrossToNewRegion())
3549 {
3550 if (m_requestedSitTargetUUID == UUID.Zero) 3490 if (m_requestedSitTargetUUID == UUID.Zero)
3551 { 3491 {
3552 bool isFlying = Flying; 3492 m_log.DebugFormat("{0} CheckForBorderCrossing: Crossing failed. Restoring old position.", LogHeader);
3553 RemoveFromPhysicalScene(); 3493 const float borderFudge = 0.1f;
3554 3494
3555 Vector3 pos = AbsolutePosition; 3495 if (origPosition.X < 0)
3556 if (AbsolutePosition.X < 0) 3496 origPosition.X = borderFudge;
3557 pos.X += Velocity.X * 2; 3497 else if (origPosition.X > (float)m_scene.RegionInfo.RegionSizeX)
3558 else if (AbsolutePosition.X > Constants.RegionSize) 3498 origPosition.X = (float)m_scene.RegionInfo.RegionSizeX - borderFudge;
3559 pos.X -= Velocity.X * 2; 3499 if (origPosition.Y < 0)
3560 if (AbsolutePosition.Y < 0) 3500 origPosition.Y = borderFudge;
3561 pos.Y += Velocity.Y * 2; 3501 else if (origPosition.Y > (float)m_scene.RegionInfo.RegionSizeY)
3562 else if (AbsolutePosition.Y > Constants.RegionSize) 3502 origPosition.Y = (float)m_scene.RegionInfo.RegionSizeY - borderFudge;
3563 pos.Y -= Velocity.Y * 2;
3564 Velocity = Vector3.Zero; 3503 Velocity = Vector3.Zero;
3565 AbsolutePosition = pos; 3504 AbsolutePosition = origPosition;
3566 3505
3567 AddToPhysicalScene(isFlying); 3506 AddToPhysicalScene(isFlying);
3568 } 3507 }
3569 } 3508 }
3509
3570 } 3510 }
3571 } 3511 }
3572 else 3512 else
@@ -3608,7 +3548,7 @@ namespace OpenSim.Region.Framework.Scenes
3608 3548
3609 // Put the child agent back at the center 3549 // Put the child agent back at the center
3610 AbsolutePosition 3550 AbsolutePosition
3611 = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70); 3551 = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
3612 3552
3613 Animator.ResetAnimations(); 3553 Animator.ResetAnimations();
3614 } 3554 }
@@ -3635,9 +3575,7 @@ namespace OpenSim.Region.Framework.Scenes
3635 if (handle != Scene.RegionInfo.RegionHandle) 3575 if (handle != Scene.RegionInfo.RegionHandle)
3636 { 3576 {
3637 uint x, y; 3577 uint x, y;
3638 Utils.LongToUInts(handle, out x, out y); 3578 Util.RegionHandleToRegionLoc(handle, out x, out y);
3639 x = x / Constants.RegionSize;
3640 y = y / Constants.RegionSize;
3641 3579
3642// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); 3580// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
3643// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); 3581// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
@@ -3718,8 +3656,9 @@ namespace OpenSim.Region.Framework.Scenes
3718 return; 3656 return;
3719 3657
3720 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); 3658 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
3721 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; 3659 // Find the distance (in meters) between the two regions
3722 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; 3660 uint shiftx = Util.RegionToWorldLoc(rRegionX - tRegionX);
3661 uint shifty = Util.RegionToWorldLoc(rRegionY - tRegionY);
3723 3662
3724 Vector3 offset = new Vector3(shiftx, shifty, 0f); 3663 Vector3 offset = new Vector3(shiftx, shifty, 0f);
3725 3664
@@ -4755,6 +4694,7 @@ namespace OpenSim.Region.Framework.Scenes
4755 } 4694 }
4756 } 4695 }
4757 4696
4697 // Modify landing point based on possible banning, telehubs or parcel restrictions.
4758 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 4698 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
4759 { 4699 {
4760 string reason; 4700 string reason;
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}
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index b3fdd22..c8320d0 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -516,7 +516,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
516 516
517 public Vector3 StartPos 517 public Vector3 StartPos
518 { 518 {
519 get { return new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 50); } 519 get { return new Vector3(m_scene.RegionInfo.RegionSizeX * 0.5f, m_scene.RegionInfo.RegionSizeY * 0.5f, 50f); }
520 set { } 520 set { }
521 } 521 }
522 522
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
index c5cba8e..f5bd44d 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
@@ -52,6 +52,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
52 52
53 // Local constants 53 // Local constants
54 54
55 // This computation is not the real region center if the region is larger than 256.
56 // This computation isn't fixed because there is not a handle back to the region.
55 private static readonly Vector3 CenterOfRegion = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20); 57 private static readonly Vector3 CenterOfRegion = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20);
56 private static readonly char[] CS_SPACE = { ' ' }; 58 private static readonly char[] CS_SPACE = { ' ' };
57 59
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs
index d4fe5e0..5505001 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs
@@ -44,6 +44,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
44 private static readonly ILog m_log = 44 private static readonly ILog m_log =
45 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 // This computation is not the real region center if the region is larger than 256.
48 // This computation isn't fixed because there is not a handle back to the region.
47 private static readonly OpenMetaverse.Vector3 CenterOfRegion = new OpenMetaverse.Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20); 49 private static readonly OpenMetaverse.Vector3 CenterOfRegion = new OpenMetaverse.Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 20);
48 private const int DEBUG_CHANNEL = 2147483647; 50 private const int DEBUG_CHANNEL = 2147483647;
49 51
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
index eb386fe..296ab87 100644
--- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
@@ -170,7 +170,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
170 c.Channel = m_channelNotify; 170 c.Channel = m_channelNotify;
171 c.Message += numScriptsFailed.ToString() + "," + message; 171 c.Message += numScriptsFailed.ToString() + "," + message;
172 c.Type = ChatTypeEnum.Region; 172 c.Type = ChatTypeEnum.Region;
173 c.Position = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 30); 173 if (m_scene != null)
174 c.Position = new Vector3((m_scene.RegionInfo.RegionSizeX * 0.5f), (m_scene.RegionInfo.RegionSizeY * 0.5f), 30);
175 else
176 c.Position = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 30);
174 c.Sender = null; 177 c.Sender = null;
175 c.SenderUUID = UUID.Zero; 178 c.SenderUUID = UUID.Zero;
176 c.Scene = m_scene; 179 c.Scene = m_scene;
diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
index 8144870..e4a3382 100644
--- a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
+++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
@@ -748,8 +748,8 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
748 position.X = s_tree.AbsolutePosition.X + (float)randX; 748 position.X = s_tree.AbsolutePosition.X + (float)randX;
749 position.Y = s_tree.AbsolutePosition.Y + (float)randY; 749 position.Y = s_tree.AbsolutePosition.Y + (float)randY;
750 750
751 if (position.X <= ((int)Constants.RegionSize - 1) && position.X >= 0 && 751 if (position.X <= (m_scene.RegionInfo.RegionSizeX - 1) && position.X >= 0 &&
752 position.Y <= ((int)Constants.RegionSize - 1) && position.Y >= 0 && 752 position.Y <= (m_scene.RegionInfo.RegionSizeY - 1) && position.Y >= 0 &&
753 Util.GetDistanceTo(position, copse.m_seed_point) <= copse.m_range) 753 Util.GetDistanceTo(position, copse.m_seed_point) <= copse.m_range)
754 { 754 {
755 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner; 755 UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
index 17ebed2..aca1ed4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -1311,7 +1311,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1311 /* TODO */ 1311 /* TODO */
1312 ConfigurationParameters[] configparms = new ConfigurationParameters[1]; 1312 ConfigurationParameters[] configparms = new ConfigurationParameters[1];
1313 configparms[0] = parms; 1313 configparms[0] = parms;
1314 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 1314 Vector3 worldExtent = maxPosition;
1315 m_maxCollisions = maxCollisions; 1315 m_maxCollisions = maxCollisions;
1316 m_maxUpdatesPerFrame = maxUpdates; 1316 m_maxUpdatesPerFrame = maxUpdates;
1317 specialCollisionObjects = new Dictionary<uint, GhostObject>(); 1317 specialCollisionObjects = new Dictionary<uint, GhostObject>();
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 15b7090..edec949 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -376,18 +376,19 @@ public class BSPrim : BSPhysObject
376 { 376 {
377 bool ret = false; 377 bool ret = false;
378 378
379 uint wayOutThere = Constants.RegionSize * Constants.RegionSize; 379 int wayOverThere = -1000;
380 int wayOutThere = 10000;
380 // There have been instances of objects getting thrown way out of bounds and crashing 381 // There have been instances of objects getting thrown way out of bounds and crashing
381 // the border crossing code. 382 // the border crossing code.
382 if ( RawPosition.X < -Constants.RegionSize || RawPosition.X > wayOutThere 383 if ( RawPosition.X < wayOverThere || RawPosition.X > wayOutThere
383 || RawPosition.Y < -Constants.RegionSize || RawPosition.Y > wayOutThere 384 || RawPosition.Y < wayOverThere || RawPosition.X > wayOutThere
384 || RawPosition.Z < -Constants.RegionSize || RawPosition.Z > wayOutThere) 385 || RawPosition.Z < wayOverThere || RawPosition.X > wayOutThere)
385 { 386 {
386 RawPosition = new OMV.Vector3(10, 10, 50); 387 RawPosition = new OMV.Vector3(10, 10, 50);
387 ZeroMotion(inTaintTime); 388 ZeroMotion(inTaintTime);
388 ret = true; 389 ret = true;
389 } 390 }
390 if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocity) 391 if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocitySquared)
391 { 392 {
392 RawVelocity = Util.ClampV(RawVelocity, BSParam.MaxLinearVelocity); 393 RawVelocity = Util.ClampV(RawVelocity, BSParam.MaxLinearVelocity);
393 ret = true; 394 ret = true;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index b3dfa41..fe014fc 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -208,8 +208,17 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
208 Name = EngineType + "/" + RegionName; 208 Name = EngineType + "/" + RegionName;
209 } 209 }
210 210
211 // Old version of initialization that assumes legacy sized regions (256x256)
211 public override void Initialise(IMesher meshmerizer, IConfigSource config) 212 public override void Initialise(IMesher meshmerizer, IConfigSource config)
212 { 213 {
214 m_log.ErrorFormat("{0} WARNING WARNING WARNING! BulletSim initialized without region extent specification. Terrain will be messed up.");
215 Vector3 regionExtent = new Vector3( Constants.RegionSize, Constants.RegionSize, Constants.RegionSize);
216 Initialise(meshmerizer, config, regionExtent);
217
218 }
219
220 public override void Initialise(IMesher meshmerizer, IConfigSource config, Vector3 regionExtent)
221 {
213 mesher = meshmerizer; 222 mesher = meshmerizer;
214 _taintOperations = new List<TaintCallbackEntry>(); 223 _taintOperations = new List<TaintCallbackEntry>();
215 _postTaintOperations = new Dictionary<string, TaintCallbackEntry>(); 224 _postTaintOperations = new Dictionary<string, TaintCallbackEntry>();
@@ -250,13 +259,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
250 // a child in a mega-region. 259 // a child in a mega-region.
251 // Bullet actually doesn't care about the extents of the simulated 260 // Bullet actually doesn't care about the extents of the simulated
252 // area. It tracks active objects no matter where they are. 261 // area. It tracks active objects no matter where they are.
253 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 262 Vector3 worldExtent = regionExtent;
254 263
255 World = PE.Initialize(worldExtent, Params, m_maxCollisionsPerFrame, ref m_collisionArray, m_maxUpdatesPerFrame, ref m_updateArray); 264 World = PE.Initialize(worldExtent, Params, m_maxCollisionsPerFrame, ref m_collisionArray, m_maxUpdatesPerFrame, ref m_updateArray);
256 265
257 Constraints = new BSConstraintCollection(World); 266 Constraints = new BSConstraintCollection(World);
258 267
259 TerrainManager = new BSTerrainManager(this); 268 TerrainManager = new BSTerrainManager(this, worldExtent);
260 TerrainManager.CreateInitialGroundPlaneAndTerrain(); 269 TerrainManager.CreateInitialGroundPlaneAndTerrain();
261 270
262 // Put some informational messages into the log file. 271 // Put some informational messages into the log file.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
index 8888d6d..d70b2fb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
@@ -58,7 +58,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
58 { 58 {
59 initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION; 59 initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION;
60 } 60 }
61 m_mapInfo = new BulletHMapInfo(id, initialMap); 61 m_mapInfo = new BulletHMapInfo(id, initialMap, regionSize.X, regionSize.Y);
62 m_mapInfo.minCoords = minTerrainCoords; 62 m_mapInfo.minCoords = minTerrainCoords;
63 m_mapInfo.maxCoords = maxTerrainCoords; 63 m_mapInfo.maxCoords = maxTerrainCoords;
64 m_mapInfo.terrainRegionBase = TerrainBase; 64 m_mapInfo.terrainRegionBase = TerrainBase;
@@ -72,7 +72,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
72 Vector3 minCoords, Vector3 maxCoords) 72 Vector3 minCoords, Vector3 maxCoords)
73 : base(physicsScene, regionBase, id) 73 : base(physicsScene, regionBase, id)
74 { 74 {
75 m_mapInfo = new BulletHMapInfo(id, initialMap); 75 m_mapInfo = new BulletHMapInfo(id, initialMap, maxCoords.X - minCoords.X, maxCoords.Y - minCoords.Y);
76 m_mapInfo.minCoords = minCoords; 76 m_mapInfo.minCoords = minCoords;
77 m_mapInfo.maxCoords = maxCoords; 77 m_mapInfo.maxCoords = maxCoords;
78 m_mapInfo.minZ = minCoords.Z; 78 m_mapInfo.minZ = minCoords.Z;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 441d2d3..3013077 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -111,9 +111,11 @@ public sealed class BSTerrainManager : IDisposable
111 private Vector3 m_worldMax; 111 private Vector3 m_worldMax;
112 private PhysicsScene MegaRegionParentPhysicsScene { get; set; } 112 private PhysicsScene MegaRegionParentPhysicsScene { get; set; }
113 113
114 public BSTerrainManager(BSScene physicsScene) 114 public BSTerrainManager(BSScene physicsScene, Vector3 regionSize)
115 { 115 {
116 m_physicsScene = physicsScene; 116 m_physicsScene = physicsScene;
117 DefaultRegionSize = regionSize;
118
117 m_terrains = new Dictionary<Vector3,BSTerrainPhys>(); 119 m_terrains = new Dictionary<Vector3,BSTerrainPhys>();
118 120
119 // Assume one region of default size 121 // Assume one region of default size
@@ -268,7 +270,7 @@ public sealed class BSTerrainManager : IDisposable
268 { 270 {
269 // There is already a terrain in this spot. Free the old and build the new. 271 // There is already a terrain in this spot. Free the old and build the new.
270 DetailLog("{0},BSTErrainManager.UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}", 272 DetailLog("{0},BSTErrainManager.UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}",
271 BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords); 273 BSScene.DetailLogZero, id, terrainRegionBase, minCoords, maxCoords);
272 274
273 // Remove old terrain from the collection 275 // Remove old terrain from the collection
274 m_terrains.Remove(terrainRegionBase); 276 m_terrains.Remove(terrainRegionBase);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
index 971ff9f..3425d9e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
@@ -165,14 +165,15 @@ public class BulletConstraint
165// than making copies. 165// than making copies.
166public class BulletHMapInfo 166public class BulletHMapInfo
167{ 167{
168 public BulletHMapInfo(uint id, float[] hm) { 168 public BulletHMapInfo(uint id, float[] hm, float pSizeX, float pSizeY) {
169 ID = id; 169 ID = id;
170 heightMap = hm; 170 heightMap = hm;
171 terrainRegionBase = OMV.Vector3.Zero; 171 terrainRegionBase = OMV.Vector3.Zero;
172 minCoords = new OMV.Vector3(100f, 100f, 25f); 172 minCoords = new OMV.Vector3(100f, 100f, 25f);
173 maxCoords = new OMV.Vector3(101f, 101f, 26f); 173 maxCoords = new OMV.Vector3(101f, 101f, 26f);
174 minZ = maxZ = 0f; 174 minZ = maxZ = 0f;
175 sizeX = sizeY = 256f; 175 sizeX = pSizeX;
176 sizeY = pSizeY;
176 } 177 }
177 public uint ID; 178 public uint ID;
178 public float[] heightMap; 179 public float[] heightMap;
diff --git a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs
index 8ccfda5..9b06353 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs
@@ -32,6 +32,7 @@ using System.Reflection;
32using Nini.Config; 32using Nini.Config;
33using log4net; 33using log4net;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenMetaverse;
35 36
36namespace OpenSim.Region.Physics.Manager 37namespace OpenSim.Region.Physics.Manager
37{ 38{
@@ -66,7 +67,8 @@ namespace OpenSim.Region.Physics.Manager
66 /// <param name="meshEngineName"></param> 67 /// <param name="meshEngineName"></param>
67 /// <param name="config"></param> 68 /// <param name="config"></param>
68 /// <returns></returns> 69 /// <returns></returns>
69 public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName, IConfigSource config, string regionName) 70 public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName,
71 IConfigSource config, string regionName, Vector3 regionExtent)
70 { 72 {
71 if (String.IsNullOrEmpty(physEngineName)) 73 if (String.IsNullOrEmpty(physEngineName))
72 { 74 {
@@ -94,7 +96,7 @@ namespace OpenSim.Region.Physics.Manager
94 { 96 {
95 m_log.Info("[PHYSICS]: creating " + physEngineName); 97 m_log.Info("[PHYSICS]: creating " + physEngineName);
96 PhysicsScene result = _PhysPlugins[physEngineName].GetScene(regionName); 98 PhysicsScene result = _PhysPlugins[physEngineName].GetScene(regionName);
97 result.Initialise(meshEngine, config); 99 result.Initialise(meshEngine, config, regionExtent);
98 return result; 100 return result;
99 } 101 }
100 else 102 else
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index c93206d..71ad795 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -126,8 +126,17 @@ namespace OpenSim.Region.Physics.Manager
126 } 126 }
127 } 127 }
128 128
129 // Deprecated. Do not use this for new physics engines.
129 public abstract void Initialise(IMesher meshmerizer, IConfigSource config); 130 public abstract void Initialise(IMesher meshmerizer, IConfigSource config);
130 131
132 // For older physics engines that do not implement non-legacy region sizes.
133 // If the physics engine handles the region extent feature, it overrides this function.
134 public virtual void Initialise(IMesher meshmerizer, IConfigSource config, Vector3 regionExtent)
135 {
136 // If not overridden, call the old initialization entry.
137 Initialise(meshmerizer, config);
138 }
139
131 /// <summary> 140 /// <summary>
132 /// Add an avatar 141 /// Add an avatar
133 /// </summary> 142 /// </summary>
diff --git a/OpenSim/Region/RegionCombinerModule/RegionConnections.cs b/OpenSim/Region/RegionCombinerModule/RegionConnections.cs
index fba51d2..62a3a91 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionConnections.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionConnections.cs
@@ -64,12 +64,12 @@ namespace OpenSim.Region.RegionCombinerModule
64 /// <summary> 64 /// <summary>
65 /// The X meters position of this connection. 65 /// The X meters position of this connection.
66 /// </summary> 66 /// </summary>
67 public uint PosX { get { return X * Constants.RegionSize; } } 67 public uint PosX { get { return Util.RegionToWorldLoc(X); } }
68 68
69 /// <summary> 69 /// <summary>
70 /// The Y meters co-ordinate of this connection. 70 /// The Y meters co-ordinate of this connection.
71 /// </summary> 71 /// </summary>
72 public uint PosY { get { return Y * Constants.RegionSize; } } 72 public uint PosY { get { return Util.RegionToWorldLoc(Y); } }
73 73
74 /// <summary> 74 /// <summary>
75 /// The size of the megaregion in meters. 75 /// The size of the megaregion in meters.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index e54b697..7b56abf 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -2107,7 +2107,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2107 // 2107 //
2108 // This workaround is to prevent silent failure of this function. 2108 // This workaround is to prevent silent failure of this function.
2109 // According to the specification on the SL Wiki, providing a position outside of the 2109 // According to the specification on the SL Wiki, providing a position outside of the
2110 if (pos.x < 0 || pos.x > Constants.RegionSize || pos.y < 0 || pos.y > Constants.RegionSize) 2110 if (pos.x < 0 || pos.x > World.RegionInfo.RegionSizeX || pos.y < 0 || pos.y > World.RegionInfo.RegionSizeY)
2111 { 2111 {
2112 return 0; 2112 return 0;
2113 } 2113 }
@@ -2117,9 +2117,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2117 m_host.ParentGroup.IsAttachment || // return FALSE if attachment 2117 m_host.ParentGroup.IsAttachment || // return FALSE if attachment
2118 ( 2118 (
2119 pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region. 2119 pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region.
2120 pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region. 2120 pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
2121 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. 2121 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
2122 pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region. 2122 pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
2123 pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m 2123 pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
2124 ) 2124 )
2125 ) 2125 )
@@ -4244,10 +4244,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4244 DataserverPlugin.RegisterRequest(m_host.LocalId, 4244 DataserverPlugin.RegisterRequest(m_host.LocalId,
4245 m_item.ItemID, item.AssetID.ToString()); 4245 m_item.ItemID, item.AssetID.ToString());
4246 4246
4247 Vector3 region = new Vector3( 4247 Vector3 region = new Vector3(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
4248 World.RegionInfo.RegionLocX * Constants.RegionSize,
4249 World.RegionInfo.RegionLocY * Constants.RegionSize,
4250 0);
4251 4248
4252 World.AssetService.Get(item.AssetID.ToString(), this, 4249 World.AssetService.Get(item.AssetID.ToString(), this,
4253 delegate(string i, object sender, AssetBase a) 4250 delegate(string i, object sender, AssetBase a)
@@ -4336,7 +4333,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4336 m_host.AddScriptLPS(1); 4333 m_host.AddScriptLPS(1);
4337 UUID agentId = new UUID(); 4334 UUID agentId = new UUID();
4338 4335
4339 ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); 4336 ulong regionHandle = Util.RegionWorldLocToHandle((uint)global_coords.x, (uint)global_coords.y);
4340 4337
4341 if (UUID.TryParse(agent, out agentId)) 4338 if (UUID.TryParse(agent, out agentId))
4342 { 4339 {
@@ -5481,7 +5478,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5481 public LSL_Vector llGetRegionCorner() 5478 public LSL_Vector llGetRegionCorner()
5482 { 5479 {
5483 m_host.AddScriptLPS(1); 5480 m_host.AddScriptLPS(1);
5484 return new LSL_Vector(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0); 5481 return new LSL_Vector(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
5485 } 5482 }
5486 5483
5487 /// <summary> 5484 /// <summary>
@@ -5628,7 +5625,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5628 LSL_Float mag; 5625 LSL_Float mag;
5629 if (dir.x > 0) 5626 if (dir.x > 0)
5630 { 5627 {
5631 mag = (Constants.RegionSize - pos.x) / dir.x; 5628 mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x;
5632 } 5629 }
5633 else 5630 else
5634 { 5631 {
@@ -5639,7 +5636,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5639 5636
5640 edge.y = pos.y + (dir.y * mag); 5637 edge.y = pos.y + (dir.y * mag);
5641 5638
5642 if (edge.y > Constants.RegionSize || edge.y < 0) 5639 if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0)
5643 { 5640 {
5644 // Y goes out of bounds first 5641 // Y goes out of bounds first
5645 edge.y = dir.y / Math.Abs(dir.y); 5642 edge.y = dir.y / Math.Abs(dir.y);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index f4d5562..31ea067 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -450,7 +450,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
450 { 450 {
451 m_host.AddScriptLPS(1); 451 m_host.AddScriptLPS(1);
452 452
453 if (x > ((int)Constants.RegionSize - 1) || x < 0 || y > ((int)Constants.RegionSize - 1) || y < 0) 453 if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0)
454 OSSLError("osSetTerrainHeight: Coordinate out of bounds"); 454 OSSLError("osSetTerrainHeight: Coordinate out of bounds");
455 455
456 if (World.Permissions.CanTerraformLand(m_host.OwnerID, new Vector3(x, y, 0))) 456 if (World.Permissions.CanTerraformLand(m_host.OwnerID, new Vector3(x, y, 0)))
@@ -480,7 +480,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
480 private LSL_Float GetTerrainHeight(int x, int y) 480 private LSL_Float GetTerrainHeight(int x, int y)
481 { 481 {
482 m_host.AddScriptLPS(1); 482 m_host.AddScriptLPS(1);
483 if (x > ((int)Constants.RegionSize - 1) || x < 0 || y > ((int)Constants.RegionSize - 1) || y < 0) 483 if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0)
484 OSSLError("osGetTerrainHeight: Coordinate out of bounds"); 484 OSSLError("osGetTerrainHeight: Coordinate out of bounds");
485 485
486 return World.Heightmap[x, y]; 486 return World.Heightmap[x, y];
@@ -814,7 +814,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
814 private void TeleportAgent(string agent, int regionX, int regionY, 814 private void TeleportAgent(string agent, int regionX, int regionY,
815 LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions) 815 LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions)
816 { 816 {
817 ulong regionHandle = Util.UIntsToLong(((uint)regionX * (uint)Constants.RegionSize), ((uint)regionY * (uint)Constants.RegionSize)); 817 // ulong regionHandle = Util.UIntsToLong(((uint)regionX * (uint)Constants.RegionSize), ((uint)regionY * (uint)Constants.RegionSize));
818 ulong regionHandle = Util.RegionLocToHandle((uint)regionX, (uint)regionY);
818 819
819 m_host.AddScriptLPS(1); 820 m_host.AddScriptLPS(1);
820 UUID agentId = new UUID(); 821 UUID agentId = new UUID();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index c9902e4..d81cddc 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -713,16 +713,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
713 } 713 }
714 private void Save() 714 private void Save()
715 { 715 {
716 /* Remove temporarily until we have a handle to the region size
716 if (Position.x > ((int)Constants.RegionSize - 1)) 717 if (Position.x > ((int)Constants.RegionSize - 1))
717 Position.x = ((int)Constants.RegionSize - 1); 718 Position.x = ((int)Constants.RegionSize - 1);
718 if (Position.x < 0)
719 Position.x = 0;
720 if (Position.y > ((int)Constants.RegionSize - 1)) 719 if (Position.y > ((int)Constants.RegionSize - 1))
721 Position.y = ((int)Constants.RegionSize - 1); 720 Position.y = ((int)Constants.RegionSize - 1);
721 */
722 if (Position.z > Constants.RegionHeight)
723 Position.z = Constants.RegionHeight;
724 if (Position.x < 0)
725 Position.x = 0;
722 if (Position.y < 0) 726 if (Position.y < 0)
723 Position.y = 0; 727 Position.y = 0;
724 if (Position.z > 768)
725 Position.z = 768;
726 if (Position.z < 0) 728 if (Position.z < 0)
727 Position.z = 0; 729 Position.z = 0;
728 prim.OSSL.llSetPos(Position); 730 prim.OSSL.llSetPos(Position);