aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs6
-rw-r--r--OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs40
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEventQueue.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJ2KDecoder.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/INPCModule.cs26
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs28
-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.cs19
-rw-r--r--OpenSim/Region/Framework/Interfaces/ITerrainModule.cs1
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs146
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs1
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs202
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs1152
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainChannel.cs354
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainCompressor.cs942
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs94
23 files changed, 2402 insertions, 719 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs
index 34aca33..d25c930 100644
--- a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs
@@ -35,8 +35,8 @@ namespace OpenSim.Region.Framework.Interfaces
35 35
36 public interface IAvatarFactoryModule 36 public interface IAvatarFactoryModule
37 { 37 {
38 void SetAppearance(IScenePresence sp, AvatarAppearance appearance); 38 void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems);
39 void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams); 39 void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems);
40 40
41 /// <summary> 41 /// <summary>
42 /// Send the appearance of an avatar to others in the scene. 42 /// Send the appearance of an avatar to others in the scene.
@@ -52,6 +52,8 @@ namespace OpenSim.Region.Framework.Interfaces
52 /// <returns>An empty list if this agent has no baked textures (e.g. because it's a child agent)</returns> 52 /// <returns>An empty list if this agent has no baked textures (e.g. because it's a child agent)</returns>
53 Dictionary<BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(UUID agentId); 53 Dictionary<BakeType, Primitive.TextureEntryFace> GetBakedTextureFaces(UUID agentId);
54 54
55
56 WearableCacheItem[] GetCachedItems(UUID agentId);
55 /// <summary> 57 /// <summary>
56 /// Save the baked textures for the given agent permanently in the asset database. 58 /// Save the baked textures for the given agent permanently in the asset database.
57 /// </summary> 59 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
new file mode 100644
index 0000000..b536a49
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
@@ -0,0 +1,40 @@
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
28using System;
29using Nini.Config;
30using OpenSim.Framework;
31using OpenMetaverse;
32
33namespace OpenSim.Services.Interfaces
34{
35 public interface IBakedTextureModule
36 {
37 WearableCacheItem[] Get(UUID id);
38 void Store(UUID id, WearableCacheItem[] data);
39 }
40}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 1c43a25..709d8fc 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -35,6 +35,8 @@ using OpenSim.Region.Framework.Scenes;
35 35
36namespace OpenSim.Region.Framework.Interfaces 36namespace OpenSim.Region.Framework.Interfaces
37{ 37{
38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version);
39
38 public interface IEntityTransferModule 40 public interface IEntityTransferModule
39 { 41 {
40 /// <summary> 42 /// <summary>
@@ -45,13 +47,22 @@ namespace OpenSim.Region.Framework.Interfaces
45 /// The handle of the destination region. If it's the same as the region currently 47 /// The handle of the destination region. If it's the same as the region currently
46 /// occupied by the agent then the teleport will be within that region. 48 /// occupied by the agent then the teleport will be within that region.
47 /// </param> 49 /// </param>
50 /// <param name='agent'></param>
51 /// <param name='regionHandle'></param>
48 /// <param name='position'></param> 52 /// <param name='position'></param>
49 /// <param name='lookAt'></param> 53 /// <param name='lookAt'></param>
50 /// <param name='teleportFlags'></param> 54 /// <param name='teleportFlags'></param>
51 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); 55 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags);
52 56
53 /// <summary> 57 /// <summary>
54 /// Teleport an agent directly to a given region without checking whether the region should be subsituted. 58 /// Teleports the agent for the given client to their home destination.
59 /// </summary>
60 /// <param name='id'></param>
61 /// <param name='client'></param>
62 bool TeleportHome(UUID id, IClientAPI client);
63
64 /// <summary>
65 /// Teleport an agent directly to a given region without checking whether the region should be substituted.
55 /// </summary> 66 /// </summary>
56 /// <remarks> 67 /// <remarks>
57 /// Please use Teleport() instead unless you know exactly what you're doing. 68 /// Please use Teleport() instead unless you know exactly what you're doing.
@@ -63,18 +74,10 @@ namespace OpenSim.Region.Framework.Interfaces
63 /// <param name='position'></param> 74 /// <param name='position'></param>
64 /// <param name='lookAt'></param> 75 /// <param name='lookAt'></param>
65 /// <param name='teleportFlags'></param> 76 /// <param name='teleportFlags'></param>
66 void DoTeleport( 77 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
67 ScenePresence sp, GridRegion reg, GridRegion finalDestination,
68 Vector3 position, Vector3 lookAt, uint teleportFlags); 78 Vector3 position, Vector3 lookAt, uint teleportFlags);
69 79
70 /// <summary> 80 /// <summary>
71 /// Teleports the agent for the given client to their home destination.
72 /// </summary>
73 /// <param name='id'></param>
74 /// <param name='client'></param>
75 bool TeleportHome(UUID id, IClientAPI client);
76
77 /// <summary>
78 /// Show whether the given agent is being teleported. 81 /// Show whether the given agent is being teleported.
79 /// </summary> 82 /// </summary>
80 /// <param name='id'>The agent ID</para></param> 83 /// <param name='id'>The agent ID</para></param>
@@ -89,7 +92,11 @@ namespace OpenSim.Region.Framework.Interfaces
89 92
90 void EnableChildAgent(ScenePresence agent, GridRegion region); 93 void EnableChildAgent(ScenePresence agent, GridRegion region);
91 94
95 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos);
96
92 void Cross(SceneObjectGroup sog, Vector3 position, bool silent); 97 void Cross(SceneObjectGroup sog, Vector3 position, bool silent);
98
99 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version);
93 } 100 }
94 101
95 public interface IUserAgentVerificationModule 102 public interface IUserAgentVerificationModule
diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
index 3780ece..dfc269e 100644
--- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
@@ -39,16 +39,17 @@ namespace OpenSim.Region.Framework.Interfaces
39 39
40 // These are required to decouple Scenes from EventQueueHelper 40 // These are required to decouple Scenes from EventQueueHelper
41 void DisableSimulator(ulong handle, UUID avatarID); 41 void DisableSimulator(ulong handle, UUID avatarID);
42 void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID); 42 void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY);
43 void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, 43 void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint,
44 string capsPath); 44 string capsPath, ulong regionHandle, int regionSizeX, int regionSizeY);
45 void TeleportFinishEvent(ulong regionHandle, byte simAccess, 45 void TeleportFinishEvent(ulong regionHandle, byte simAccess,
46 IPEndPoint regionExternalEndPoint, 46 IPEndPoint regionExternalEndPoint,
47 uint locationID, uint flags, string capsURL, 47 uint locationID, uint flags, string capsURL,
48 UUID agentID); 48 UUID agentID, int regionSizeX, int regionSizeY);
49 void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, 49 void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
50 IPEndPoint newRegionExternalEndPoint, 50 IPEndPoint newRegionExternalEndPoint,
51 string capsURL, UUID avatarID, UUID sessionID); 51 string capsURL, UUID avatarID, UUID sessionID,
52 int regionSizeX, int regionSizeY);
52 void ChatterboxInvitation(UUID sessionID, string sessionName, 53 void ChatterboxInvitation(UUID sessionID, string sessionName,
53 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, 54 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
54 uint timeStamp, bool offline, int parentEstateID, Vector3 position, 55 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
diff --git a/OpenSim/Region/Framework/Interfaces/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/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
index b67312e..1a89721 100644
--- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
@@ -51,10 +51,17 @@ namespace OpenSim.Region.Framework.Interfaces
51 UUID = 5 51 UUID = 5
52 } 52 }
53 53
54 public struct JsonStoreStats
55 {
56 public int StoreCount;
57 }
58
54 public delegate void TakeValueCallback(string s); 59 public delegate void TakeValueCallback(string s);
55 60
56 public interface IJsonStoreModule 61 public interface IJsonStoreModule
57 { 62 {
63 JsonStoreStats GetStoreStats();
64
58 bool AttachObjectStore(UUID objectID); 65 bool AttachObjectStore(UUID objectID);
59 bool CreateStore(string value, ref UUID result); 66 bool CreateStore(string value, ref UUID result);
60 bool DestroyStore(UUID storeID); 67 bool DestroyStore(UUID storeID);
diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
index 9817cf7..d5dcddd 100644
--- a/OpenSim/Region/Framework/Interfaces/INPCModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
@@ -72,6 +72,32 @@ namespace OpenSim.Region.Framework.Interfaces
72 AvatarAppearance appearance); 72 AvatarAppearance appearance);
73 73
74 /// <summary> 74 /// <summary>
75 /// Create an NPC with a user-supplied agentID
76 /// </summary>
77 /// <param name="firstname"></param>
78 /// <param name="lastname"></param>
79 /// <param name="position"></param>
80 /// <param name="agentID"></param>
81 /// The desired agent ID
82 /// <param name="owner"></param>
83 /// <param name="senseAsAgent">
84 /// Make the NPC show up as an agent on LSL sensors. The default is
85 /// that they show up as the NPC type instead, but this is currently
86 /// an OpenSim-only extension.
87 /// </param>
88 /// <param name="scene"></param>
89 /// <param name="appearance">
90 /// The avatar appearance to use for the new NPC.
91 /// </param>
92 /// <returns>
93 /// The UUID of the ScenePresence created. UUID.Zero if there was a
94 /// failure.
95 /// </returns>
96 UUID CreateNPC(string firstname, string lastname,
97 Vector3 position, UUID agentID, UUID owner, bool senseAsAgent, Scene scene,
98 AvatarAppearance appearance);
99
100 /// <summary>
75 /// Check if the agent is an NPC. 101 /// Check if the agent is an NPC.
76 /// </summary> 102 /// </summary>
77 /// <param name="agentID"></param> 103 /// <param name="agentID"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs
index 3fafc47..99bc87d 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs
@@ -29,6 +29,8 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31 31
32using OpenMetaverse;
33
32namespace OpenSim.Region.Framework.Interfaces 34namespace OpenSim.Region.Framework.Interfaces
33{ 35{
34 /// <summary> 36 /// <summary>
@@ -100,16 +102,11 @@ namespace OpenSim.Region.Framework.Interfaces
100 /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. 102 /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event.
101 /// 103 ///
102 /// <param name="loadPath"></param> 104 /// <param name="loadPath"></param>
103 /// <param name="merge">
104 /// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region
105 /// settings in the archive will be ignored.
106 /// </param>
107 /// <param name="skipAssets">
108 /// If true, the archive is loaded without loading any assets contained within it. This is useful if the
109 /// assets are already known to be present in the grid's asset service.
110 /// </param>
111 /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param> 105 /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param>
112 void DearchiveRegion(string loadPath, bool merge, bool skipAssets, Guid requestId); 106 /// <param name="options">
107 /// Dictionary of options.
108 /// </param>
109 void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string,object> options);
113 110
114 /// <summary> 111 /// <summary>
115 /// Dearchive a region from a stream. This replaces the existing scene. 112 /// Dearchive a region from a stream. This replaces the existing scene.
@@ -127,15 +124,10 @@ namespace OpenSim.Region.Framework.Interfaces
127 /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. 124 /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event.
128 /// 125 ///
129 /// <param name="loadStream"></param> 126 /// <param name="loadStream"></param>
130 /// <param name="merge">
131 /// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region
132 /// settings in the archive will be ignored.
133 /// </param>
134 /// <param name="skipAssets">
135 /// If true, the archive is loaded without loading any assets contained within it. This is useful if the
136 /// assets are already known to be present in the grid's asset service.
137 /// </param
138 /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param> 127 /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param>
139 void DearchiveRegion(Stream loadStream, bool merge, bool skipAssets, Guid requestId); 128 /// <param name="options">
129 /// Dictionary of options.
130 /// </param>
131 void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string,object> options);
140 } 132 }
141} 133}
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..f660b8d 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
@@ -25,13 +25,23 @@
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 OpenMetaverse;
30
28namespace OpenSim.Region.Framework.Interfaces 31namespace OpenSim.Region.Framework.Interfaces
29{ 32{
30 public interface ITerrainChannel 33 public interface ITerrainChannel
31 { 34 {
32 int Height { get; } 35 int Width { get;} // X dimension
36 int Height { get;} // Y dimension
37 int Altitude { get;} // Z dimension
38
33 double this[int x, int y] { get; set; } 39 double this[int x, int y] { get; set; }
34 int Width { get; } 40
41 float GetHeightAtXYZ(float x, float y, float z);
42
43 // Return the packaged terrain data for passing into lower levels of communication
44 TerrainData GetTerrainData();
35 45
36 /// <summary> 46 /// <summary>
37 /// Squash the entire heightmap into a single dimensioned array 47 /// Squash the entire heightmap into a single dimensioned array
@@ -40,9 +50,14 @@ namespace OpenSim.Region.Framework.Interfaces
40 float[] GetFloatsSerialised(); 50 float[] GetFloatsSerialised();
41 51
42 double[,] GetDoubles(); 52 double[,] GetDoubles();
53
54 // Check if a location has been updated. Clears the taint flag as a side effect.
43 bool Tainted(int x, int y); 55 bool Tainted(int x, int y);
56
44 ITerrainChannel MakeCopy(); 57 ITerrainChannel MakeCopy();
45 string SaveToXmlString(); 58 string SaveToXmlString();
46 void LoadFromXmlString(string data); 59 void LoadFromXmlString(string data);
60 // Merge some terrain into this channel
61 void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement);
47 } 62 }
48} 63}
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
index 5947afb..a6f5d98 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
@@ -51,6 +51,7 @@ namespace OpenSim.Region.Framework.Interfaces
51 /// </param> 51 /// </param>
52 /// <param name="stream"></param> 52 /// <param name="stream"></param>
53 void LoadFromStream(string filename, Stream stream); 53 void LoadFromStream(string filename, Stream stream);
54 void LoadFromStream(string filename, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement, Stream stream);
54 void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap); 55 void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap);
55 /// <summary> 56 /// <summary>
56 /// Save a terrain to a stream. 57 /// Save a terrain to a stream.
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 59c5b09..2f666c0 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1033,7 +1033,7 @@ namespace OpenSim.Region.Framework.Scenes
1033 1033
1034 BordersLocked = true; 1034 BordersLocked = true;
1035 Border northBorder = new Border(); 1035 Border northBorder = new Border();
1036 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<--- 1036 northBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (float)RegionInfo.RegionSizeY); //<---
1037 northBorder.CrossDirection = Cardinals.N; 1037 northBorder.CrossDirection = Cardinals.N;
1038 NorthBorders.Add(northBorder); 1038 NorthBorders.Add(northBorder);
1039 1039
@@ -1043,7 +1043,7 @@ namespace OpenSim.Region.Framework.Scenes
1043 SouthBorders.Add(southBorder); 1043 SouthBorders.Add(southBorder);
1044 1044
1045 Border eastBorder = new Border(); 1045 Border eastBorder = new Border();
1046 eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (int)Constants.RegionSize); //<--- 1046 eastBorder.BorderLine = new Vector3(float.MinValue, float.MaxValue, (float)RegionInfo.RegionSizeY); //<---
1047 eastBorder.CrossDirection = Cardinals.E; 1047 eastBorder.CrossDirection = Cardinals.E;
1048 EastBorders.Add(eastBorder); 1048 EastBorders.Add(eastBorder);
1049 1049
@@ -1099,8 +1099,9 @@ namespace OpenSim.Region.Framework.Scenes
1099 /// <returns>True after all operations complete, throws exceptions otherwise.</returns> 1099 /// <returns>True after all operations complete, throws exceptions otherwise.</returns>
1100 public override void OtherRegionUp(GridRegion otherRegion) 1100 public override void OtherRegionUp(GridRegion otherRegion)
1101 { 1101 {
1102 uint xcell = (uint)((int)otherRegion.RegionLocX / (int)Constants.RegionSize); 1102 uint xcell = Util.WorldToRegionLoc((uint)otherRegion.RegionLocX);
1103 uint ycell = (uint)((int)otherRegion.RegionLocY / (int)Constants.RegionSize); 1103 uint ycell = Util.WorldToRegionLoc((uint)otherRegion.RegionLocY);
1104
1104 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}", 1105 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}",
1105 // RegionInfo.RegionName, otherRegion.RegionName, xcell, ycell); 1106 // RegionInfo.RegionName, otherRegion.RegionName, xcell, ycell);
1106 1107
@@ -1172,46 +1173,6 @@ namespace OpenSim.Region.Framework.Scenes
1172 return found; 1173 return found;
1173 } 1174 }
1174 1175
1175 /// <summary>
1176 /// Checks whether this region has a neighbour in the given direction.
1177 /// </summary>
1178 /// <param name="car"></param>
1179 /// <param name="fix"></param>
1180 /// <returns>
1181 /// An integer which represents a compass point. N == 1, going clockwise until we reach NW == 8.
1182 /// Returns a positive integer if there is a region in that direction, a negative integer if not.
1183 /// </returns>
1184 public int HaveNeighbor(Cardinals car, ref int[] fix)
1185 {
1186 uint neighbourx = RegionInfo.RegionLocX;
1187 uint neighboury = RegionInfo.RegionLocY;
1188
1189 int dir = (int)car;
1190
1191 if (dir > 1 && dir < 5) //Heading East
1192 neighbourx++;
1193 else if (dir > 5) // Heading West
1194 neighbourx--;
1195
1196 if (dir < 3 || dir == 8) // Heading North
1197 neighboury++;
1198 else if (dir > 3 && dir < 7) // Heading Sout
1199 neighboury--;
1200
1201 int x = (int)(neighbourx * Constants.RegionSize);
1202 int y = (int)(neighboury * Constants.RegionSize);
1203 GridRegion neighbourRegion = GridService.GetRegionByPosition(RegionInfo.ScopeID, x, y);
1204
1205 if (neighbourRegion == null)
1206 {
1207 fix[0] = (int)(RegionInfo.RegionLocX - neighbourx);
1208 fix[1] = (int)(RegionInfo.RegionLocY - neighboury);
1209 return dir * (-1);
1210 }
1211 else
1212 return dir;
1213 }
1214
1215 // Alias IncomingHelloNeighbour OtherRegionUp, for now 1176 // Alias IncomingHelloNeighbour OtherRegionUp, for now
1216 public GridRegion IncomingHelloNeighbour(RegionInfo neighbour) 1177 public GridRegion IncomingHelloNeighbour(RegionInfo neighbour)
1217 { 1178 {
@@ -1894,7 +1855,7 @@ namespace OpenSim.Region.Framework.Scenes
1894 { 1855 {
1895 try 1856 try
1896 { 1857 {
1897 double[,] map = SimulationDataService.LoadTerrain(RegionInfo.RegionID); 1858 TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
1898 if (map == null) 1859 if (map == null)
1899 { 1860 {
1900 // This should be in the Terrain module, but it isn't because 1861 // This should be in the Terrain module, but it isn't because
@@ -1905,7 +1866,7 @@ namespace OpenSim.Region.Framework.Scenes
1905 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 1866 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
1906 1867
1907 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); 1868 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain);
1908 Heightmap = new TerrainChannel(m_InitialTerrain); 1869 Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
1909 1870
1910 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 1871 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
1911 } 1872 }
@@ -1953,6 +1914,11 @@ namespace OpenSim.Region.Framework.Scenes
1953 1914
1954 GridRegion region = new GridRegion(RegionInfo); 1915 GridRegion region = new GridRegion(RegionInfo);
1955 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 1916 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
1917 m_log.DebugFormat("{0} RegisterRegionWithGrid. name={1},id={2},loc=<{3},{4}>,size=<{5},{6}>",
1918 LogHeader, m_regionName,
1919 RegionInfo.RegionID,
1920 RegionInfo.RegionLocX, RegionInfo.RegionLocY,
1921 RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
1956 if (error != String.Empty) 1922 if (error != String.Empty)
1957 throw new Exception(error); 1923 throw new Exception(error);
1958 } 1924 }
@@ -2478,6 +2444,23 @@ namespace OpenSim.Region.Framework.Scenes
2478 EntityTransferModule.Cross(grp, attemptedPosition, silent); 2444 EntityTransferModule.Cross(grp, attemptedPosition, silent);
2479 } 2445 }
2480 2446
2447 // Simple test to see if a position is in the current region.
2448 // Resuming the position is relative to the region so anything outside its bounds.
2449 // Return 'true' if position inside region.
2450 public bool PositionIsInCurrentRegion(Vector3 pos)
2451 {
2452 bool ret = true;
2453 int xx = (int)Math.Floor(pos.X);
2454 int yy = (int)Math.Floor(pos.Y);
2455 if (xx < 0
2456 || xx >= RegionInfo.RegionSizeX
2457 || yy < 0
2458 || yy >= RegionInfo.RegionSizeY)
2459 ret = false;
2460 return ret;
2461
2462 }
2463
2481 public Border GetCrossedBorder(Vector3 position, Cardinals gridline) 2464 public Border GetCrossedBorder(Vector3 position, Cardinals gridline)
2482 { 2465 {
2483 if (BordersLocked) 2466 if (BordersLocked)
@@ -3895,6 +3878,7 @@ namespace OpenSim.Region.Framework.Scenes
3895 { 3878 {
3896 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E); 3879 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
3897 acd.startpos.X = crossedBorder.BorderLine.Z - 1; 3880 acd.startpos.X = crossedBorder.BorderLine.Z - 1;
3881 m_log.DebugFormat("{0} NewUserConnection Adjusted border E. startpos={1}", LogHeader, acd.startpos);
3898 } 3882 }
3899 3883
3900 if (TestBorderCross(acd.startpos, Cardinals.N)) 3884 if (TestBorderCross(acd.startpos, Cardinals.N))
@@ -4014,12 +3998,12 @@ namespace OpenSim.Region.Framework.Scenes
4014 { 3998 {
4015 if (posX < 0) 3999 if (posX < 0)
4016 posX = 0; 4000 posX = 0;
4017 else if (posX >= 256) 4001 else if (posX >= (float)RegionInfo.RegionSizeX)
4018 posX = 255.999f; 4002 posX = (float)RegionInfo.RegionSizeX - 0.001f;
4019 if (posY < 0) 4003 if (posY < 0)
4020 posY = 0; 4004 posY = 0;
4021 else if (posY >= 256) 4005 else if (posY >= (float)RegionInfo.RegionSizeY)
4022 posY = 255.999f; 4006 posY = (float)RegionInfo.RegionSizeY - 0.001f;
4023 4007
4024 reason = String.Empty; 4008 reason = String.Empty;
4025 if (Permissions.IsGod(agentID)) 4009 if (Permissions.IsGod(agentID))
@@ -4313,7 +4297,7 @@ namespace OpenSim.Region.Framework.Scenes
4313 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4297 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4314 4298
4315 // TODO: This check should probably be in QueryAccess(). 4299 // TODO: This check should probably be in QueryAccess().
4316 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4300 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2);
4317 if (nearestParcel == null) 4301 if (nearestParcel == null)
4318 { 4302 {
4319 m_log.InfoFormat( 4303 m_log.InfoFormat(
@@ -4608,44 +4592,6 @@ namespace OpenSim.Region.Framework.Scenes
4608 ScenePresence sp = GetScenePresence(remoteClient.AgentId); 4592 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4609 if (sp != null) 4593 if (sp != null)
4610 { 4594 {
4611 uint regionX = RegionInfo.RegionLocX;
4612 uint regionY = RegionInfo.RegionLocY;
4613
4614 Utils.LongToUInts(regionHandle, out regionX, out regionY);
4615
4616 int shiftx = (int) regionX - (int) RegionInfo.RegionLocX * (int)Constants.RegionSize;
4617 int shifty = (int) regionY - (int) RegionInfo.RegionLocY * (int)Constants.RegionSize;
4618
4619 position.X += shiftx;
4620 position.Y += shifty;
4621
4622 bool result = false;
4623
4624 if (TestBorderCross(position,Cardinals.N))
4625 result = true;
4626
4627 if (TestBorderCross(position, Cardinals.S))
4628 result = true;
4629
4630 if (TestBorderCross(position, Cardinals.E))
4631 result = true;
4632
4633 if (TestBorderCross(position, Cardinals.W))
4634 result = true;
4635
4636 // bordercross if position is outside of region
4637
4638 if (!result)
4639 {
4640 regionHandle = RegionInfo.RegionHandle;
4641 }
4642 else
4643 {
4644 // not in this region, undo the shift!
4645 position.X -= shiftx;
4646 position.Y -= shifty;
4647 }
4648
4649 if (EntityTransferModule != null) 4595 if (EntityTransferModule != null)
4650 { 4596 {
4651 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags); 4597 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
@@ -4825,7 +4771,7 @@ namespace OpenSim.Region.Framework.Scenes
4825 else 4771 else
4826 { 4772 {
4827 4773
4828 if (pos.X > 0f && pos.X < Constants.RegionSize && pos.Y > 0f && pos.Y < Constants.RegionSize) 4774 if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY)
4829 { 4775 {
4830 // The only time parcel != null when an object is inside a region is when 4776 // The only time parcel != null when an object is inside a region is when
4831 // there is nothing behind the landchannel. IE, no land plugin loaded. 4777 // there is nothing behind the landchannel. IE, no land plugin loaded.
@@ -5486,7 +5432,7 @@ namespace OpenSim.Region.Framework.Scenes
5486 { 5432 {
5487 Vector3 unitDirection = Vector3.Normalize(direction); 5433 Vector3 unitDirection = Vector3.Normalize(direction);
5488 //Making distance to search go through some sane limit of distance 5434 //Making distance to search go through some sane limit of distance
5489 for (float distance = 0; distance < Constants.RegionSize * 2; distance += .5f) 5435 for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f)
5490 { 5436 {
5491 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance)); 5437 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance));
5492 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) 5438 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y))
@@ -5540,9 +5486,9 @@ namespace OpenSim.Region.Framework.Scenes
5540 int count = 0; 5486 int count = 0;
5541 int avgx = 0; 5487 int avgx = 0;
5542 int avgy = 0; 5488 int avgy = 0;
5543 for (int x = 0; x < Constants.RegionSize; x++) 5489 for (int x = 0; x < RegionInfo.RegionSizeX; x++)
5544 { 5490 {
5545 for (int y = 0; y < Constants.RegionSize; y++) 5491 for (int y = 0; y < RegionInfo.RegionSizeY; y++)
5546 { 5492 {
5547 //Just keep a running average as we check if all the points are inside or not 5493 //Just keep a running average as we check if all the points are inside or not
5548 if (parcel.ContainsPoint(x, y)) 5494 if (parcel.ContainsPoint(x, y))
@@ -5566,31 +5512,33 @@ namespace OpenSim.Region.Framework.Scenes
5566 5512
5567 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) 5513 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar)
5568 { 5514 {
5569 float xdistance = avatar.AbsolutePosition.X < Constants.RegionSize / 2 ? avatar.AbsolutePosition.X : Constants.RegionSize - avatar.AbsolutePosition.X; 5515 float xdistance = avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2
5570 float ydistance = avatar.AbsolutePosition.Y < Constants.RegionSize / 2 ? avatar.AbsolutePosition.Y : Constants.RegionSize - avatar.AbsolutePosition.Y; 5516 ? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X;
5517 float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2
5518 ? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y;
5571 5519
5572 //find out what vertical edge to go to 5520 //find out what vertical edge to go to
5573 if (xdistance < ydistance) 5521 if (xdistance < ydistance)
5574 { 5522 {
5575 if (avatar.AbsolutePosition.X < Constants.RegionSize / 2) 5523 if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2)
5576 { 5524 {
5577 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y); 5525 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y);
5578 } 5526 }
5579 else 5527 else
5580 { 5528 {
5581 return GetPositionAtAvatarHeightOrGroundHeight(avatar, Constants.RegionSize, avatar.AbsolutePosition.Y); 5529 return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y);
5582 } 5530 }
5583 } 5531 }
5584 //find out what horizontal edge to go to 5532 //find out what horizontal edge to go to
5585 else 5533 else
5586 { 5534 {
5587 if (avatar.AbsolutePosition.Y < Constants.RegionSize / 2) 5535 if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2)
5588 { 5536 {
5589 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f); 5537 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f);
5590 } 5538 }
5591 else 5539 else
5592 { 5540 {
5593 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, Constants.RegionSize); 5541 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY);
5594 } 5542 }
5595 } 5543 }
5596 } 5544 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 4f04706..b059ecf 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -43,6 +43,7 @@ namespace OpenSim.Region.Framework.Scenes
43 public abstract class SceneBase : IScene 43 public abstract class SceneBase : IScene
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 private static readonly string LogHeader = "[SCENE]";
46 47
47 #region Events 48 #region Events
48 49
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 77889fa..c873e40 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -92,7 +92,7 @@ namespace OpenSim.Region.Framework.Scenes
92 { 92 {
93 m_log.DebugFormat( 93 m_log.DebugFormat(
94 "[SCENE COMMUNICATION SERVICE]: Region {0} successfully informed neighbour {1} at {2}-{3} that it is up", 94 "[SCENE COMMUNICATION SERVICE]: Region {0} successfully informed neighbour {1} at {2}-{3} that it is up",
95 m_scene.Name, neighbour.RegionName, x / Constants.RegionSize, y / Constants.RegionSize); 95 m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
96 96
97 m_scene.EventManager.TriggerOnRegionUp(neighbour); 97 m_scene.EventManager.TriggerOnRegionUp(neighbour);
98 } 98 }
@@ -100,7 +100,7 @@ namespace OpenSim.Region.Framework.Scenes
100 { 100 {
101 m_log.WarnFormat( 101 m_log.WarnFormat(
102 "[SCENE COMMUNICATION SERVICE]: Region {0} failed to inform neighbour at {1}-{2} that it is up.", 102 "[SCENE COMMUNICATION SERVICE]: Region {0} failed to inform neighbour at {1}-{2} that it is up.",
103 m_scene.Name, x / Constants.RegionSize, y / Constants.RegionSize); 103 m_scene.Name, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
104 } 104 }
105 } 105 }
106 106
@@ -166,7 +166,7 @@ namespace OpenSim.Region.Framework.Scenes
166 // we only want to send one update to each simulator; the simulator will 166 // we only want to send one update to each simulator; the simulator will
167 // hand it off to the regions where a child agent exists, this does assume 167 // hand it off to the regions where a child agent exists, this does assume
168 // that the region position is cached or performance will degrade 168 // that the region position is cached or performance will degrade
169 Utils.LongToUInts(regionHandle, out x, out y); 169 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
170 GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y); 170 GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
171 if (dest == null) 171 if (dest == null)
172 continue; 172 continue;
@@ -203,7 +203,7 @@ namespace OpenSim.Region.Framework.Scenes
203 203
204 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); 204 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
205 uint x = 0, y = 0; 205 uint x = 0, y = 0;
206 Utils.LongToUInts(regionHandle, out x, out y); 206 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
207 207
208 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 208 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
209 209
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index e31270c..c6b98ca 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -121,6 +121,7 @@ namespace OpenSim.Region.Framework.Scenes
121 private bool m_hasGroupChanged = false; 121 private bool m_hasGroupChanged = false;
122 private long timeFirstChanged; 122 private long timeFirstChanged;
123 private long timeLastChanged; 123 private long timeLastChanged;
124 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
124 125
125 /// <summary> 126 /// <summary>
126 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage 127 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage
@@ -333,7 +334,7 @@ namespace OpenSim.Region.Framework.Scenes
333 { 334 {
334 get 335 get
335 { 336 {
336 Vector3 minScale = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionSize); 337 Vector3 minScale = new Vector3(Constants.MaximumRegionSize, Constants.MaximumRegionSize, Constants.MaximumRegionSize);
337 Vector3 maxScale = Vector3.Zero; 338 Vector3 maxScale = Vector3.Zero;
338 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 339 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
339 340
@@ -431,6 +432,12 @@ namespace OpenSim.Region.Framework.Scenes
431 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); 432 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
432 } 433 }
433 434
435 private struct avtocrossInfo
436 {
437 public ScenePresence av;
438 public uint ParentID;
439 }
440
434 /// <summary> 441 /// <summary>
435 /// The absolute position of this scene object in the scene 442 /// The absolute position of this scene object in the scene
436 /// </summary> 443 /// </summary>
@@ -458,13 +465,122 @@ namespace OpenSim.Region.Framework.Scenes
458 || Scene.TestBorderCross(val, Cardinals.S)) 465 || Scene.TestBorderCross(val, Cardinals.S))
459 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 466 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
460 { 467 {
468 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
469 string version = String.Empty;
470 Vector3 newpos = Vector3.Zero;
471 OpenSim.Services.Interfaces.GridRegion destination = null;
472
461 if (m_rootPart.KeyframeMotion != null) 473 if (m_rootPart.KeyframeMotion != null)
462 m_rootPart.KeyframeMotion.StartCrossingCheck(); 474 m_rootPart.KeyframeMotion.StartCrossingCheck();
463 475
464 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 476 bool canCross = true;
477 foreach (ScenePresence av in m_linkedAvatars)
478 {
479 // We need to cross these agents. First, let's find
480 // out if any of them can't cross for some reason.
481 // We have to deny the crossing entirely if any
482 // of them are banned. Alternatively, we could
483 // unsit banned agents....
484
485
486 // We set the avatar position as being the object
487 // position to get the region to send to
488 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out version, out newpos)) == null)
489 {
490 canCross = false;
491 break;
492 }
493
494 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
495 }
496
497 if (canCross)
498 {
499 // We unparent the SP quietly so that it won't
500 // be made to stand up
501
502 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
503
504 foreach (ScenePresence av in m_linkedAvatars)
505 {
506 avtocrossInfo avinfo = new avtocrossInfo();
507 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
508 if (parentPart != null)
509 av.ParentUUID = parentPart.UUID;
510
511 avinfo.av = av;
512 avinfo.ParentID = av.ParentID;
513 avsToCross.Add(avinfo);
514
515 av.PrevSitOffset = av.OffsetPosition;
516 av.ParentID = 0;
517 }
518
519 // m_linkedAvatars.Clear();
520 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
521
522 // Normalize
523 if (val.X >= m_scene.RegionInfo.RegionSizeX)
524 val.X -= m_scene.RegionInfo.RegionSizeX;
525 if (val.Y >= m_scene.RegionInfo.RegionSizeY)
526 val.Y -= m_scene.RegionInfo.RegionSizeY;
527 if (val.X < 0)
528 val.X += m_scene.RegionInfo.RegionSizeX;
529 if (val.Y < 0)
530 val.Y += m_scene.RegionInfo.RegionSizeY;
531
532 // If it's deleted, crossing was successful
533 if (IsDeleted)
534 {
535 // foreach (ScenePresence av in m_linkedAvatars)
536 foreach (avtocrossInfo avinfo in avsToCross)
537 {
538 ScenePresence av = avinfo.av;
539 if (!av.IsInTransit) // just in case...
540 {
541 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
542
543 av.IsInTransit = true;
544
545 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
546 d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
547 }
548 else
549 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val);
550 }
551 avsToCross.Clear();
552 return;
553 }
554 else // cross failed, put avas back ??
555 {
556 foreach (avtocrossInfo avinfo in avsToCross)
557 {
558 ScenePresence av = avinfo.av;
559 av.ParentUUID = UUID.Zero;
560 av.ParentID = avinfo.ParentID;
561// m_linkedAvatars.Add(av);
562 }
563 }
564 avsToCross.Clear();
565
566 }
567 else
568 {
569 if (m_rootPart.KeyframeMotion != null)
570 m_rootPart.KeyframeMotion.CrossingFailure();
571
572 if (RootPart.PhysActor != null)
573 {
574 RootPart.PhysActor.CrossingFailure();
575 }
576 }
577 Vector3 oldp = AbsolutePosition;
578 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)m_scene.RegionInfo.RegionSizeX - 0.5f);
579 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)m_scene.RegionInfo.RegionSizeY - 0.5f);
580 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, Constants.RegionHeight);
465 } 581 }
466 } 582 }
467 583
468 if (RootPart.GetStatusSandbox()) 584 if (RootPart.GetStatusSandbox())
469 { 585 {
470 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 586 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -498,6 +614,39 @@ namespace OpenSim.Region.Framework.Scenes
498 } 614 }
499 } 615 }
500 616
617 public override Vector3 Velocity
618 {
619 get { return RootPart.Velocity; }
620 set { RootPart.Velocity = value; }
621 }
622
623 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
624 {
625 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
626 ScenePresence agent = icon.EndInvoke(iar);
627
628 //// If the cross was successful, this agent is a child agent
629 if (agent.IsChildAgent)
630 {
631 if (agent.ParentUUID != UUID.Zero)
632 {
633 agent.ParentPart = null;
634// agent.ParentPosition = Vector3.Zero;
635// agent.ParentUUID = UUID.Zero;
636 }
637 }
638
639 agent.ParentUUID = UUID.Zero;
640// agent.Reset();
641// else // Not successful
642// agent.RestoreInCurrentScene();
643
644 // In any case
645 agent.IsInTransit = false;
646
647 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
648 }
649
501 public override uint LocalId 650 public override uint LocalId
502 { 651 {
503 get { return m_rootPart.LocalId; } 652 get { return m_rootPart.LocalId; }
@@ -845,9 +994,9 @@ namespace OpenSim.Region.Framework.Scenes
845 maxX = -256f; 994 maxX = -256f;
846 maxY = -256f; 995 maxY = -256f;
847 maxZ = -256f; 996 maxZ = -256f;
848 minX = 256f; 997 minX = 10000f;
849 minY = 256f; 998 minY = 10000f;
850 minZ = 8192f; 999 minZ = 10000f;
851 1000
852 SceneObjectPart[] parts = m_parts.GetArray(); 1001 SceneObjectPart[] parts = m_parts.GetArray();
853 for (int i = 0; i < parts.Length; i++) 1002 for (int i = 0; i < parts.Length; i++)
@@ -1099,6 +1248,7 @@ namespace OpenSim.Region.Framework.Scenes
1099 } 1248 }
1100 } 1249 }
1101 1250
1251
1102 /// <summary> 1252 /// <summary>
1103 /// 1253 ///
1104 /// </summary> 1254 /// </summary>
@@ -1108,6 +1258,46 @@ namespace OpenSim.Region.Framework.Scenes
1108 part.ParentID = m_rootPart.LocalId; 1258 part.ParentID = m_rootPart.LocalId;
1109 part.ClearUndoState(); 1259 part.ClearUndoState();
1110 } 1260 }
1261 /// <summary>
1262 /// Add the avatar to this linkset (avatar is sat).
1263 /// </summary>
1264 /// <param name="agentID"></param>
1265 public void AddAvatar(UUID agentID)
1266 {
1267 ScenePresence presence;
1268 if (m_scene.TryGetScenePresence(agentID, out presence))
1269 {
1270 if (!m_linkedAvatars.Contains(presence))
1271 {
1272 m_linkedAvatars.Add(presence);
1273 }
1274 }
1275 }
1276
1277 /// <summary>
1278 /// Delete the avatar from this linkset (avatar is unsat).
1279 /// </summary>
1280 /// <param name="agentID"></param>
1281 public void DeleteAvatar(UUID agentID)
1282 {
1283 ScenePresence presence;
1284 if (m_scene.TryGetScenePresence(agentID, out presence))
1285 {
1286 if (m_linkedAvatars.Contains(presence))
1287 {
1288 m_linkedAvatars.Remove(presence);
1289 }
1290 }
1291 }
1292
1293 /// <summary>
1294 /// Returns the list of linked presences (avatars sat on this group)
1295 /// </summary>
1296 /// <param name="agentID"></param>
1297 public List<ScenePresence> GetLinkedAvatars()
1298 {
1299 return m_linkedAvatars;
1300 }
1111 1301
1112 public ushort GetTimeDilation() 1302 public ushort GetTimeDilation()
1113 { 1303 {
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 3290da1..576b8c2 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -65,6 +65,7 @@ namespace OpenSim.Region.Framework.Scenes
65 65
66 struct ScriptControllers 66 struct ScriptControllers
67 { 67 {
68 public UUID objectID;
68 public UUID itemID; 69 public UUID itemID;
69 public ScriptControlled ignoreControls; 70 public ScriptControlled ignoreControls;
70 public ScriptControlled eventControls; 71 public ScriptControlled eventControls;
@@ -75,6 +76,7 @@ namespace OpenSim.Region.Framework.Scenes
75 public class ScenePresence : EntityBase, IScenePresence 76 public class ScenePresence : EntityBase, IScenePresence
76 { 77 {
77 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]";
78 80
79// ~ScenePresence() 81// ~ScenePresence()
80// { 82// {
@@ -130,7 +132,7 @@ namespace OpenSim.Region.Framework.Scenes
130 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 132 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
131 /// issue #1716 133 /// issue #1716
132 /// </summary> 134 /// </summary>
133 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); 135 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f);
134 136
135 /// <summary> 137 /// <summary>
136 /// Movement updates for agents in neighboring regions are sent directly to clients. 138 /// Movement updates for agents in neighboring regions are sent directly to clients.
@@ -152,8 +154,6 @@ namespace OpenSim.Region.Framework.Scenes
152 /// <remarks> 154 /// <remarks>
153 /// TODO: For some reason, we effectively have a list both here and in Appearance. Need to work out if this is 155 /// TODO: For some reason, we effectively have a list both here and in Appearance. Need to work out if this is
154 /// necessary. 156 /// necessary.
155 /// NOTE: To avoid deadlocks, do not lock m_attachments and then perform other tasks under that lock. Take a copy
156 /// of the list and act on that instead.
157 /// </remarks> 157 /// </remarks>
158 private List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>(); 158 private List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
159 159
@@ -172,6 +172,10 @@ namespace OpenSim.Region.Framework.Scenes
172 private Vector3 m_lastPosition; 172 private Vector3 m_lastPosition;
173 private Quaternion m_lastRotation; 173 private Quaternion m_lastRotation;
174 private Vector3 m_lastVelocity; 174 private Vector3 m_lastVelocity;
175 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f);
176
177 private bool m_followCamAuto = false;
178
175 179
176 private Vector3? m_forceToApply; 180 private Vector3? m_forceToApply;
177 private int m_userFlags; 181 private int m_userFlags;
@@ -204,6 +208,7 @@ namespace OpenSim.Region.Framework.Scenes
204// private int m_lastColCount = -1; //KF: Look for Collision chnages 208// private int m_lastColCount = -1; //KF: Look for Collision chnages
205// private int m_updateCount = 0; //KF: Update Anims for a while 209// private int m_updateCount = 0; //KF: Update Anims for a while
206// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 210// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
211 private List<uint> m_lastColliders = new List<uint>();
207 212
208 private TeleportFlags m_teleportFlags; 213 private TeleportFlags m_teleportFlags;
209 public TeleportFlags TeleportFlags 214 public TeleportFlags TeleportFlags
@@ -259,8 +264,6 @@ namespace OpenSim.Region.Framework.Scenes
259 /// </summary> 264 /// </summary>
260 public bool LandAtTarget { get; private set; } 265 public bool LandAtTarget { get; private set; }
261 266
262 private bool m_followCamAuto;
263
264 private int m_movementUpdateCount; 267 private int m_movementUpdateCount;
265 private const int NumMovementsBetweenRayCast = 5; 268 private const int NumMovementsBetweenRayCast = 5;
266 269
@@ -268,6 +271,13 @@ namespace OpenSim.Region.Framework.Scenes
268 //private int m_moveToPositionStateStatus; 271 //private int m_moveToPositionStateStatus;
269 //***************************************************** 272 //*****************************************************
270 273
274 private bool m_collisionEventFlag = false;
275 private object m_collisionEventLock = new Object();
276
277 private int m_movementAnimationUpdateCounter = 0;
278
279 public Vector3 PrevSitOffset { get; set; }
280
271 protected AvatarAppearance m_appearance; 281 protected AvatarAppearance m_appearance;
272 282
273 public AvatarAppearance Appearance 283 public AvatarAppearance Appearance
@@ -407,6 +417,9 @@ namespace OpenSim.Region.Framework.Scenes
407 /// </summary> 417 /// </summary>
408 protected Vector3 m_lastCameraPosition; 418 protected Vector3 m_lastCameraPosition;
409 419
420 private Vector4 m_lastCameraCollisionPlane = new Vector4(0f, 0f, 0f, 1);
421 private bool m_doingCamRayCast = false;
422
410 public Vector3 CameraPosition { get; set; } 423 public Vector3 CameraPosition { get; set; }
411 424
412 public Quaternion CameraRotation 425 public Quaternion CameraRotation
@@ -487,6 +500,10 @@ namespace OpenSim.Region.Framework.Scenes
487 get { return (IClientCore)ControllingClient; } 500 get { return (IClientCore)ControllingClient; }
488 } 501 }
489 502
503 public UUID COF { get; set; }
504
505// public Vector3 ParentPosition { get; set; }
506
490 /// <summary> 507 /// <summary>
491 /// Position of this avatar relative to the region the avatar is in 508 /// Position of this avatar relative to the region the avatar is in
492 /// </summary> 509 /// </summary>
@@ -613,7 +630,24 @@ namespace OpenSim.Region.Framework.Scenes
613// Scene.RegionInfo.RegionName, Name, m_velocity); 630// Scene.RegionInfo.RegionName, Name, m_velocity);
614 } 631 }
615 } 632 }
633/*
634 public override Vector3 AngularVelocity
635 {
636 get
637 {
638 if (PhysicsActor != null)
639 {
640 m_rotationalvelocity = PhysicsActor.RotationalVelocity;
641
642 // m_log.DebugFormat(
643 // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
644 // m_velocity, Name, Scene.RegionInfo.RegionName);
645 }
616 646
647 return m_rotationalvelocity;
648 }
649 }
650*/
617 private Quaternion m_bodyRot = Quaternion.Identity; 651 private Quaternion m_bodyRot = Quaternion.Identity;
618 652
619 /// <summary> 653 /// <summary>
@@ -636,8 +670,16 @@ namespace OpenSim.Region.Framework.Scenes
636 m_bodyRot = value; 670 m_bodyRot = value;
637 671
638 if (PhysicsActor != null) 672 if (PhysicsActor != null)
639 PhysicsActor.Orientation = m_bodyRot; 673 {
640 674 try
675 {
676 PhysicsActor.Orientation = m_bodyRot;
677 }
678 catch (Exception e)
679 {
680 m_log.Error("[SCENE PRESENCE]: Orientation " + e.Message);
681 }
682 }
641// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot); 683// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot);
642 } 684 }
643 } 685 }
@@ -651,12 +693,20 @@ namespace OpenSim.Region.Framework.Scenes
651 } 693 }
652 694
653 public bool IsChildAgent { get; set; } 695 public bool IsChildAgent { get; set; }
696 public bool IsLoggingIn { get; set; }
654 697
655 /// <summary> 698 /// <summary>
656 /// If the avatar is sitting, the local ID of the prim that it's sitting on. If not sitting then zero. 699 /// If the avatar is sitting, the local ID of the prim that it's sitting on. If not sitting then zero.
657 /// </summary> 700 /// </summary>
658 public uint ParentID { get; set; } 701 public uint ParentID { get; set; }
659 702
703 public UUID ParentUUID
704 {
705 get { return m_parentUUID; }
706 set { m_parentUUID = value; }
707 }
708 private UUID m_parentUUID = UUID.Zero;
709
660 /// <summary> 710 /// <summary>
661 /// Are we sitting on an object? 711 /// Are we sitting on an object?
662 /// </summary> 712 /// </summary>
@@ -710,9 +760,8 @@ namespace OpenSim.Region.Framework.Scenes
710 foreach (ulong handle in seeds.Keys) 760 foreach (ulong handle in seeds.Keys)
711 { 761 {
712 uint x, y; 762 uint x, y;
713 Utils.LongToUInts(handle, out x, out y); 763 Util.RegionHandleToRegionLoc(handle, out x, out y);
714 x = x / Constants.RegionSize; 764
715 y = y / Constants.RegionSize;
716 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))
717 { 766 {
718 old.Add(handle); 767 old.Add(handle);
@@ -734,9 +783,7 @@ namespace OpenSim.Region.Framework.Scenes
734 foreach (KeyValuePair<ulong, string> kvp in KnownRegions) 783 foreach (KeyValuePair<ulong, string> kvp in KnownRegions)
735 { 784 {
736 uint x, y; 785 uint x, y;
737 Utils.LongToUInts(kvp.Key, out x, out y); 786 Util.RegionHandleToRegionLoc(kvp.Key, out x, out y);
738 x = x / Constants.RegionSize;
739 y = y / Constants.RegionSize;
740 m_log.Info(" >> "+x+", "+y+": "+kvp.Value); 787 m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
741 } 788 }
742 } 789 }
@@ -814,6 +861,7 @@ namespace OpenSim.Region.Framework.Scenes
814 AttachmentsSyncLock = new Object(); 861 AttachmentsSyncLock = new Object();
815 AllowMovement = true; 862 AllowMovement = true;
816 IsChildAgent = true; 863 IsChildAgent = true;
864 IsLoggingIn = false;
817 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; 865 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault;
818 Animator = new ScenePresenceAnimator(this); 866 Animator = new ScenePresenceAnimator(this);
819 PresenceType = type; 867 PresenceType = type;
@@ -859,6 +907,33 @@ namespace OpenSim.Region.Framework.Scenes
859 m_stateMachine = new ScenePresenceStateMachine(this); 907 m_stateMachine = new ScenePresenceStateMachine(this);
860 } 908 }
861 909
910 private void RegionHeartbeatEnd(Scene scene)
911 {
912 if (IsChildAgent)
913 return;
914
915 m_movementAnimationUpdateCounter ++;
916 if (m_movementAnimationUpdateCounter >= 2)
917 {
918 m_movementAnimationUpdateCounter = 0;
919 if (Animator != null)
920 {
921 // If the parentID == 0 we are not sitting
922 // if !SitGournd then we are not sitting on the ground
923 // Fairly straightforward, now here comes the twist
924 // if ParentUUID is NOT UUID.Zero, we are looking to
925 // be sat on an object that isn't there yet. Should
926 // be treated as if sat.
927 if(ParentID == 0 && !SitGround && ParentUUID == UUID.Zero) // skip it if sitting
928 Animator.UpdateMovementAnimations();
929 }
930 else
931 {
932 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
933 }
934 }
935 }
936
862 public void RegisterToEvents() 937 public void RegisterToEvents()
863 { 938 {
864 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 939 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
@@ -926,17 +1001,46 @@ namespace OpenSim.Region.Framework.Scenes
926 /// </remarks> 1001 /// </remarks>
927 private bool MakeRootAgent(Vector3 pos, bool isFlying) 1002 private bool MakeRootAgent(Vector3 pos, bool isFlying)
928 { 1003 {
929// m_log.InfoFormat(
930// "[SCENE]: Upgrading child to root agent for {0} in {1}",
931// Name, m_scene.RegionInfo.RegionName);
932
933 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
934
935 lock (m_completeMovementLock) 1004 lock (m_completeMovementLock)
936 { 1005 {
937 if (!IsChildAgent) 1006 if (!IsChildAgent)
938 return false; 1007 return false;
939 1008
1009 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1010
1011 // m_log.InfoFormat(
1012 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1013 // Name, m_scene.RegionInfo.RegionName);
1014
1015 if (ParentUUID != UUID.Zero)
1016 {
1017 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
1018 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
1019 if (part == null)
1020 {
1021 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1022 }
1023 else
1024 {
1025 part.ParentGroup.AddAvatar(UUID);
1026 if (part.SitTargetPosition != Vector3.Zero)
1027 part.SitTargetAvatar = UUID;
1028 // ParentPosition = part.GetWorldPosition();
1029 ParentID = part.LocalId;
1030 ParentPart = part;
1031 m_pos = PrevSitOffset;
1032 // pos = ParentPosition;
1033 pos = part.GetWorldPosition();
1034 }
1035 ParentUUID = UUID.Zero;
1036
1037 // Animator.TrySetMovementAnimation("SIT");
1038 }
1039 else
1040 {
1041 IsLoggingIn = false;
1042 }
1043
940 IsChildAgent = false; 1044 IsChildAgent = false;
941 } 1045 }
942 1046
@@ -953,70 +1057,113 @@ namespace OpenSim.Region.Framework.Scenes
953 1057
954 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 1058 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
955 1059
956 // Moved this from SendInitialData to ensure that Appearance is initialized 1060 UUID groupUUID = ControllingClient.ActiveGroupId;
957 // before the inventory is processed in MakeRootAgent. This fixes a race condition 1061 string groupName = string.Empty;
958 // related to the handling of attachments 1062 ulong groupPowers = 0;
959 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
960 1063
961 if (m_scene.TestBorderCross(pos, Cardinals.E)) 1064 // ----------------------------------
1065 // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status
1066 try
962 { 1067 {
963 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 1068 if (groupUUID != UUID.Zero && gm != null)
964 pos.X = crossedBorder.BorderLine.Z - 1; 1069 {
965 } 1070 GroupRecord record = gm.GetGroupRecord(groupUUID);
1071 if (record != null)
1072 groupName = record.GroupName;
1073
1074 GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid);
966 1075
967 if (m_scene.TestBorderCross(pos, Cardinals.N)) 1076 if (groupMembershipData != null)
1077 groupPowers = groupMembershipData.GroupPowers;
1078 }
1079
1080 ControllingClient.SendAgentDataUpdate(
1081 m_uuid, groupUUID, Firstname, Lastname, groupPowers, groupName, Grouptitle);
1082 }
1083 catch (Exception e)
968 { 1084 {
969 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 1085 m_log.Error("[AGENTUPDATE]: Error ", e);
970 pos.Y = crossedBorder.BorderLine.Z - 1;
971 } 1086 }
1087 // ------------------------------------
972 1088
973 CheckAndAdjustLandingPoint(ref pos); 1089 if (ParentID == 0)
974
975 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
976 { 1090 {
977 m_log.WarnFormat( 1091 // Moved this from SendInitialData to ensure that Appearance is initialized
978 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", 1092 // before the inventory is processed in MakeRootAgent. This fixes a race condition
979 pos, Name, UUID); 1093 // related to the handling of attachments
1094 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
980 1095
981 if (pos.X < 0f) pos.X = 0f; 1096 /* RA 20140111: Commented out these TestBorderCross's.
982 if (pos.Y < 0f) pos.Y = 0f; 1097 * Not sure why this code is here. It is not checking all the borders
983 if (pos.Z < 0f) pos.Z = 0f; 1098 * and 'in region' sanity checking is done in CheckAndAdjustLandingPoint and below.
984 } 1099 if (m_scene.TestBorderCross(pos, Cardinals.E))
1100 {
1101 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
1102 pos.X = crossedBorder.BorderLine.Z - 1;
1103 }
985 1104
986 float localAVHeight = 1.56f; 1105 if (m_scene.TestBorderCross(pos, Cardinals.N))
987 if (Appearance.AvatarHeight > 0) 1106 {
988 localAVHeight = Appearance.AvatarHeight; 1107 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
1108 pos.Y = crossedBorder.BorderLine.Z - 1;
1109 }
1110 */
989 1111
990 float posZLimit = 0; 1112 CheckAndAdjustLandingPoint(ref pos);
991 1113
992 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 1114 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
993 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1115 {
994 1116 m_log.WarnFormat(
995 float newPosZ = posZLimit + localAVHeight / 2; 1117 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
996 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 1118 pos, Name, UUID);
997 {
998 pos.Z = newPosZ;
999 }
1000 AbsolutePosition = pos;
1001 1119
1002 AddToPhysicalScene(isFlying); 1120 if (pos.X < 0f) pos.X = 0f;
1121 if (pos.Y < 0f) pos.Y = 0f;
1122 if (pos.Z < 0f) pos.Z = 0f;
1123 }
1003 1124
1004 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a 1125 float localAVHeight = 1.56f;
1005 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it 1126 if (Appearance.AvatarHeight > 0)
1006 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset 1127 localAVHeight = Appearance.AvatarHeight;
1007 // the value to a negative position which does not trigger the border cross.
1008 // This may not be the best location for this.
1009 CheckForBorderCrossing();
1010 1128
1011 if (ForceFly) 1129 float posZLimit = 0;
1012 { 1130
1013 Flying = true; 1131 if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY)
1014 } 1132 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
1015 else if (FlyDisabled) 1133
1016 { 1134 float newPosZ = posZLimit + localAVHeight / 2;
1017 Flying = false; 1135 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
1018 } 1136 {
1137 pos.Z = newPosZ;
1138 }
1139 AbsolutePosition = pos;
1019 1140
1141 if (m_teleportFlags == TeleportFlags.Default)
1142 {
1143 Vector3 vel = Velocity;
1144 AddToPhysicalScene(isFlying);
1145 if (PhysicsActor != null)
1146 PhysicsActor.SetMomentum(vel);
1147 }
1148 else
1149 AddToPhysicalScene(isFlying);
1150
1151 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a
1152 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it
1153 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset
1154 // the value to a negative position which does not trigger the border cross.
1155 // This may not be the best location for this.
1156 CheckForBorderCrossing();
1157
1158 if (ForceFly)
1159 {
1160 Flying = true;
1161 }
1162 else if (FlyDisabled)
1163 {
1164 Flying = false;
1165 }
1166 }
1020 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 1167 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
1021 // avatar to return to the standing position in mid-air. On login it looks like this is being sent 1168 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
1022 // elsewhere anyway 1169 // elsewhere anyway
@@ -1049,6 +1196,11 @@ namespace OpenSim.Region.Framework.Scenes
1049 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are 1196 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1050 // not transporting the required data. 1197 // not transporting the required data.
1051 // 1198 //
1199 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
1200 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1201 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1202 // not transporting the required data.
1203 //
1052 // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of 1204 // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
1053 // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here 1205 // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
1054 // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status. 1206 // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
@@ -1057,6 +1209,9 @@ namespace OpenSim.Region.Framework.Scenes
1057 // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing 1209 // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
1058 // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the 1210 // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
1059 // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine. 1211 // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
1212 //
1213 // One cannot simply iterate over attachments in a fire and forget thread because this would no longer
1214 // be locked, allowing race conditions if other code changes the attachments list.
1060 List<SceneObjectGroup> attachments = GetAttachments(); 1215 List<SceneObjectGroup> attachments = GetAttachments();
1061 1216
1062 if (attachments.Count > 0) 1217 if (attachments.Count > 0)
@@ -1067,12 +1222,15 @@ namespace OpenSim.Region.Framework.Scenes
1067 // Resume scripts 1222 // Resume scripts
1068 foreach (SceneObjectGroup sog in attachments) 1223 foreach (SceneObjectGroup sog in attachments)
1069 { 1224 {
1225 sog.ScheduleGroupForFullUpdate();
1070 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 1226 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1071 sog.ResumeScripts(); 1227 sog.ResumeScripts();
1072 } 1228 }
1073 } 1229 }
1074 } 1230 }
1075 1231
1232 SendAvatarDataToAllAgents();
1233
1076 // send the animations of the other presences to me 1234 // send the animations of the other presences to me
1077 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) 1235 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
1078 { 1236 {
@@ -1083,6 +1241,7 @@ namespace OpenSim.Region.Framework.Scenes
1083 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will 1241 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will
1084 // stall on the border crossing since the existing child agent will still have the last movement 1242 // stall on the border crossing since the existing child agent will still have the last movement
1085 // recorded, which stops the input from being processed. 1243 // recorded, which stops the input from being processed.
1244
1086 MovementFlag = 0; 1245 MovementFlag = 0;
1087 1246
1088 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1247 m_scene.EventManager.TriggerOnMakeRootAgent(this);
@@ -1115,12 +1274,16 @@ namespace OpenSim.Region.Framework.Scenes
1115 /// </remarks> 1274 /// </remarks>
1116 public void MakeChildAgent() 1275 public void MakeChildAgent()
1117 { 1276 {
1277 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1278
1118 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1279 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName);
1119 1280
1120 // Reset these so that teleporting in and walking out isn't seen 1281 // Reset these so that teleporting in and walking out isn't seen
1121 // as teleporting back 1282 // as teleporting back
1122 TeleportFlags = TeleportFlags.Default; 1283 TeleportFlags = TeleportFlags.Default;
1123 1284
1285 MovementFlag = 0;
1286
1124 // It looks like Animator is set to null somewhere, and MakeChild 1287 // It looks like Animator is set to null somewhere, and MakeChild
1125 // is called after that. Probably in aborted teleports. 1288 // is called after that. Probably in aborted teleports.
1126 if (Animator == null) 1289 if (Animator == null)
@@ -1128,6 +1291,7 @@ namespace OpenSim.Region.Framework.Scenes
1128 else 1291 else
1129 Animator.ResetAnimations(); 1292 Animator.ResetAnimations();
1130 1293
1294
1131// m_log.DebugFormat( 1295// m_log.DebugFormat(
1132// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", 1296// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
1133// Name, UUID, m_scene.RegionInfo.RegionName); 1297// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1139,6 +1303,7 @@ namespace OpenSim.Region.Framework.Scenes
1139 IsChildAgent = true; 1303 IsChildAgent = true;
1140 m_scene.SwapRootAgentCount(true); 1304 m_scene.SwapRootAgentCount(true);
1141 RemoveFromPhysicalScene(); 1305 RemoveFromPhysicalScene();
1306 ParentID = 0; // Child agents can't be sitting
1142 1307
1143 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into 1308 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into
1144 1309
@@ -1154,9 +1319,9 @@ namespace OpenSim.Region.Framework.Scenes
1154 { 1319 {
1155// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1320// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
1156 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall; 1321 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall;
1157 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1158 PhysicsActor.UnSubscribeEvents();
1159 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1322 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1323 PhysicsActor.UnSubscribeEvents();
1324 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1160 PhysicsActor = null; 1325 PhysicsActor = null;
1161 } 1326 }
1162// else 1327// else
@@ -1173,7 +1338,7 @@ namespace OpenSim.Region.Framework.Scenes
1173 /// <param name="pos"></param> 1338 /// <param name="pos"></param>
1174 public void Teleport(Vector3 pos) 1339 public void Teleport(Vector3 pos)
1175 { 1340 {
1176 TeleportWithMomentum(pos, null); 1341 TeleportWithMomentum(pos, Vector3.Zero);
1177 } 1342 }
1178 1343
1179 public void TeleportWithMomentum(Vector3 pos, Vector3? v) 1344 public void TeleportWithMomentum(Vector3 pos, Vector3? v)
@@ -1197,6 +1362,41 @@ namespace OpenSim.Region.Framework.Scenes
1197 SendTerseUpdateToAllClients(); 1362 SendTerseUpdateToAllClients();
1198 } 1363 }
1199 1364
1365 public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY)
1366 {
1367 CheckLandingPoint(ref newpos);
1368 AbsolutePosition = newpos;
1369
1370 if (newvel.HasValue)
1371 {
1372 if ((Vector3)newvel == Vector3.Zero)
1373 {
1374 if (PhysicsActor != null)
1375 PhysicsActor.SetMomentum(Vector3.Zero);
1376 m_velocity = Vector3.Zero;
1377 }
1378 else
1379 {
1380 if (PhysicsActor != null)
1381 PhysicsActor.SetMomentum((Vector3)newvel);
1382 m_velocity = (Vector3)newvel;
1383
1384 if (rotateToVelXY)
1385 {
1386 Vector3 lookAt = (Vector3)newvel;
1387 lookAt.Z = 0;
1388 lookAt.Normalize();
1389 ControllingClient.SendLocalTeleport(newpos, lookAt, (uint)TeleportFlags.ViaLocation);
1390 return;
1391 }
1392 }
1393 }
1394
1395 SendTerseUpdateToAllClients();
1396 }
1397
1398
1399
1200 public void StopFlying() 1400 public void StopFlying()
1201 { 1401 {
1202 Vector3 pos = AbsolutePosition; 1402 Vector3 pos = AbsolutePosition;
@@ -1385,6 +1585,14 @@ namespace OpenSim.Region.Framework.Scenes
1385 PhysicsActor.Size = new Vector3(0.45f, 0.6f, height); 1585 PhysicsActor.Size = new Vector3(0.45f, 0.6f, height);
1386 } 1586 }
1387 1587
1588 public void SetSize(Vector3 size, float feetoffset)
1589 {
1590// TODO: Merge the physics bits
1591// if (PhysicsActor != null && !IsChildAgent)
1592// PhysicsActor.setAvatarSize(size, feetoffset);
1593
1594 }
1595
1388 private bool WaitForUpdateAgent(IClientAPI client) 1596 private bool WaitForUpdateAgent(IClientAPI client)
1389 { 1597 {
1390 // Before the source region executes UpdateAgent 1598 // Before the source region executes UpdateAgent
@@ -1444,7 +1652,8 @@ namespace OpenSim.Region.Framework.Scenes
1444 1652
1445 Vector3 look = Velocity; 1653 Vector3 look = Velocity;
1446 1654
1447 if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) 1655 // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
1656 if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1))
1448 { 1657 {
1449 look = new Vector3(0.99f, 0.042f, 0); 1658 look = new Vector3(0.99f, 0.042f, 0);
1450 } 1659 }
@@ -1514,11 +1723,12 @@ namespace OpenSim.Region.Framework.Scenes
1514 { 1723 {
1515 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 1724 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
1516 if (m_agentTransfer != null) 1725 if (m_agentTransfer != null)
1517 Util.FireAndForget(delegate { m_agentTransfer.EnableChildAgents(this); }); 1726 m_agentTransfer.EnableChildAgents(this);
1518 1727
1519 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); 1728 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
1520 if (friendsModule != null) 1729 if (friendsModule != null)
1521 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); 1730 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
1731
1522 } 1732 }
1523 1733
1524 // XXX: If we force an update here, then multiple attachments do appear correctly on a destination region 1734 // XXX: If we force an update here, then multiple attachments do appear correctly on a destination region
@@ -1544,36 +1754,69 @@ namespace OpenSim.Region.Framework.Scenes
1544 /// <param name="collisionPoint"></param> 1754 /// <param name="collisionPoint"></param>
1545 /// <param name="localid"></param> 1755 /// <param name="localid"></param>
1546 /// <param name="distance"></param> 1756 /// <param name="distance"></param>
1757 ///
1758
1759 private void UpdateCameraCollisionPlane(Vector4 plane)
1760 {
1761 if (m_lastCameraCollisionPlane != plane)
1762 {
1763 m_lastCameraCollisionPlane = plane;
1764 ControllingClient.SendCameraConstraint(plane);
1765 }
1766 }
1767
1547 public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal) 1768 public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal)
1548 { 1769 {
1549 const float POSITION_TOLERANCE = 0.02f; 1770 const float POSITION_TOLERANCE = 0.02f;
1550 const float VELOCITY_TOLERANCE = 0.02f;
1551 const float ROTATION_TOLERANCE = 0.02f; 1771 const float ROTATION_TOLERANCE = 0.02f;
1552 1772
1553 if (m_followCamAuto) 1773 m_doingCamRayCast = false;
1774 if (hitYN && localid != LocalId)
1554 { 1775 {
1555 if (hitYN) 1776 SceneObjectGroup group = m_scene.GetGroupByPrim(localid);
1777 bool IsPrim = group != null;
1778 if (IsPrim)
1556 { 1779 {
1557 CameraConstraintActive = true; 1780 SceneObjectPart part = group.GetPart(localid);
1558 //m_log.DebugFormat("[RAYCASTRESULT]: {0}, {1}, {2}, {3}", hitYN, collisionPoint, localid, distance); 1781 if (part != null && !part.VolumeDetectActive)
1559 1782 {
1560 Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint); 1783 CameraConstraintActive = true;
1561 ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint))); 1784 pNormal.X = (float) Math.Round(pNormal.X, 2);
1785 pNormal.Y = (float) Math.Round(pNormal.Y, 2);
1786 pNormal.Z = (float) Math.Round(pNormal.Z, 2);
1787 pNormal.Normalize();
1788 collisionPoint.X = (float) Math.Round(collisionPoint.X, 1);
1789 collisionPoint.Y = (float) Math.Round(collisionPoint.Y, 1);
1790 collisionPoint.Z = (float) Math.Round(collisionPoint.Z, 1);
1791
1792 Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z,
1793 Vector3.Dot(collisionPoint, pNormal));
1794 UpdateCameraCollisionPlane(plane);
1795 }
1562 } 1796 }
1563 else 1797 else
1564 { 1798 {
1565 if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 1799 CameraConstraintActive = true;
1566 !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || 1800 pNormal.X = (float) Math.Round(pNormal.X, 2);
1567 !Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)) 1801 pNormal.Y = (float) Math.Round(pNormal.Y, 2);
1568 { 1802 pNormal.Z = (float) Math.Round(pNormal.Z, 2);
1569 if (CameraConstraintActive) 1803 pNormal.Normalize();
1570 { 1804 collisionPoint.X = (float) Math.Round(collisionPoint.X, 1);
1571 ControllingClient.SendCameraConstraint(new Vector4(0f, 0.5f, 0.9f, -3000f)); 1805 collisionPoint.Y = (float) Math.Round(collisionPoint.Y, 1);
1572 CameraConstraintActive = false; 1806 collisionPoint.Z = (float) Math.Round(collisionPoint.Z, 1);
1573 } 1807
1574 } 1808 Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z,
1809 Vector3.Dot(collisionPoint, pNormal));
1810 UpdateCameraCollisionPlane(plane);
1575 } 1811 }
1576 } 1812 }
1813 else if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
1814 !Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE))
1815 {
1816 Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -9000f); // not right...
1817 UpdateCameraCollisionPlane(plane);
1818 CameraConstraintActive = false;
1819 }
1577 } 1820 }
1578 1821
1579 /// <summary> 1822 /// <summary>
@@ -1647,6 +1890,41 @@ namespace OpenSim.Region.Framework.Scenes
1647 StandUp(); 1890 StandUp();
1648 } 1891 }
1649 1892
1893 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
1894 // this exclude checks may not be complete
1895
1896 if (m_movementUpdateCount % NumMovementsBetweenRayCast == 0 && m_scene.PhysicsScene.SupportsRayCast())
1897 {
1898 if (!m_doingCamRayCast && !m_mouseLook && ParentID == 0)
1899 {
1900 Vector3 posAdjusted = AbsolutePosition;
1901// posAdjusted.Z += 0.5f * Appearance.AvatarSize.Z - 0.5f;
1902 posAdjusted.Z += 1.0f; // viewer current camera focus point
1903 Vector3 tocam = CameraPosition - posAdjusted;
1904 tocam.X = (float)Math.Round(tocam.X, 1);
1905 tocam.Y = (float)Math.Round(tocam.Y, 1);
1906 tocam.Z = (float)Math.Round(tocam.Z, 1);
1907
1908 float distTocamlen = tocam.Length();
1909 if (distTocamlen > 0.3f)
1910 {
1911 tocam *= (1.0f / distTocamlen);
1912 posAdjusted.X = (float)Math.Round(posAdjusted.X, 1);
1913 posAdjusted.Y = (float)Math.Round(posAdjusted.Y, 1);
1914 posAdjusted.Z = (float)Math.Round(posAdjusted.Z, 1);
1915
1916 m_doingCamRayCast = true;
1917 m_scene.PhysicsScene.RaycastWorld(posAdjusted, tocam, distTocamlen + 1.0f, RayCastCameraCallback);
1918 }
1919 }
1920 else if (CameraConstraintActive && (m_mouseLook || ParentID != 0))
1921 {
1922 Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -10000f); // not right...
1923 UpdateCameraCollisionPlane(plane);
1924 CameraConstraintActive = false;
1925 }
1926 }
1927
1650 uint flagsForScripts = (uint)flags; 1928 uint flagsForScripts = (uint)flags;
1651 flags = RemoveIgnoredControls(flags, IgnoredControls); 1929 flags = RemoveIgnoredControls(flags, IgnoredControls);
1652 1930
@@ -2127,7 +2405,7 @@ namespace OpenSim.Region.Framework.Scenes
2127 if (regionCombinerModule != null) 2405 if (regionCombinerModule != null)
2128 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); 2406 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
2129 else 2407 else
2130 regionSize = new Vector2(Constants.RegionSize); 2408 regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY);
2131 2409
2132 if (pos.X < 0 || pos.X >= regionSize.X 2410 if (pos.X < 0 || pos.X >= regionSize.X
2133 || pos.Y < 0 || pos.Y >= regionSize.Y 2411 || pos.Y < 0 || pos.Y >= regionSize.Y
@@ -2145,8 +2423,8 @@ namespace OpenSim.Region.Framework.Scenes
2145// } 2423// }
2146 2424
2147 // Get terrain height for sub-region in a megaregion if necessary 2425 // Get terrain height for sub-region in a megaregion if necessary
2148 int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X); 2426 int X = (int)((m_scene.RegionInfo.WorldLocX) + pos.X);
2149 int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y); 2427 int Y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y);
2150 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y); 2428 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y);
2151 // If X and Y is NaN, target_region will be null 2429 // If X and Y is NaN, target_region will be null
2152 if (target_region == null) 2430 if (target_region == null)
@@ -2157,7 +2435,7 @@ namespace OpenSim.Region.Framework.Scenes
2157 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene)) 2435 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
2158 targetScene = m_scene; 2436 targetScene = m_scene;
2159 2437
2160 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)]; 2438 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
2161 pos.Z = Math.Max(terrainHeight, pos.Z); 2439 pos.Z = Math.Max(terrainHeight, pos.Z);
2162 2440
2163 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 2441 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -2207,7 +2485,8 @@ namespace OpenSim.Region.Framework.Scenes
2207// m_log.DebugFormat("[SCENE PRESENCE]: Resetting move to target for {0}", Name); 2485// m_log.DebugFormat("[SCENE PRESENCE]: Resetting move to target for {0}", Name);
2208 2486
2209 MovingToTarget = false; 2487 MovingToTarget = false;
2210 MoveToPositionTarget = Vector3.Zero; 2488// MoveToPositionTarget = Vector3.Zero;
2489 m_forceToApply = null; // cancel possible last action
2211 2490
2212 // We need to reset the control flag as the ScenePresenceAnimator uses this to determine the correct 2491 // We need to reset the control flag as the ScenePresenceAnimator uses this to determine the correct
2213 // resting animation (e.g. hover or stand). NPCs don't have a client that will quickly reset this flag. 2492 // resting animation (e.g. hover or stand). NPCs don't have a client that will quickly reset this flag.
@@ -2230,6 +2509,9 @@ namespace OpenSim.Region.Framework.Scenes
2230 2509
2231 if (satOnObject) 2510 if (satOnObject)
2232 { 2511 {
2512 PrevSitOffset = m_pos; // Save sit offset
2513 UnRegisterSeatControls(part.ParentGroup.UUID);
2514
2233 TaskInventoryDictionary taskIDict = part.TaskInventory; 2515 TaskInventoryDictionary taskIDict = part.TaskInventory;
2234 if (taskIDict != null) 2516 if (taskIDict != null)
2235 { 2517 {
@@ -2245,6 +2527,7 @@ namespace OpenSim.Region.Framework.Scenes
2245 } 2527 }
2246 } 2528 }
2247 2529
2530 part.ParentGroup.DeleteAvatar(UUID);
2248 Vector3 sitPartWorldPosition = part.GetWorldPosition(); 2531 Vector3 sitPartWorldPosition = part.GetWorldPosition();
2249 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 2532 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2250 2533
@@ -2305,6 +2588,9 @@ namespace OpenSim.Region.Framework.Scenes
2305 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 2588 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2306 } 2589 }
2307 2590
2591 else if (PhysicsActor == null)
2592 AddToPhysicalScene(false);
2593
2308 Animator.TrySetMovementAnimation("STAND"); 2594 Animator.TrySetMovementAnimation("STAND");
2309 TriggerScenePresenceUpdated(); 2595 TriggerScenePresenceUpdated();
2310 } 2596 }
@@ -2353,11 +2639,8 @@ namespace OpenSim.Region.Framework.Scenes
2353 if (part == null) 2639 if (part == null)
2354 return; 2640 return;
2355 2641
2356 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
2357 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
2358
2359 if (PhysicsActor != null) 2642 if (PhysicsActor != null)
2360 m_sitAvatarHeight = PhysicsActor.Size.Z; 2643 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
2361 2644
2362 bool canSit = false; 2645 bool canSit = false;
2363 2646
@@ -2384,33 +2667,32 @@ namespace OpenSim.Region.Framework.Scenes
2384 } 2667 }
2385 else 2668 else
2386 { 2669 {
2670 if (PhysicsSit(part,offset)) // physics engine
2671 return;
2672
2387 Vector3 pos = part.AbsolutePosition + offset; 2673 Vector3 pos = part.AbsolutePosition + offset;
2388 2674
2389 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) 2675 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10)
2390 { 2676 {
2391// m_log.DebugFormat(
2392// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is unset and within 10m",
2393// Name, part.Name, part.LocalId);
2394
2395 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 2677 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
2396 canSit = true; 2678 canSit = true;
2397 } 2679 }
2398// else
2399// {
2400// m_log.DebugFormat(
2401// "[SCENE PRESENCE]: Ignoring sit request of {0} on {1} {2} because sit target is unset and outside 10m",
2402// Name, part.Name, part.LocalId);
2403// }
2404 } 2680 }
2405 2681
2406 if (canSit) 2682 if (canSit)
2407 { 2683 {
2684
2408 if (PhysicsActor != null) 2685 if (PhysicsActor != null)
2409 { 2686 {
2410 // We can remove the physicsActor until they stand up. 2687 // We can remove the physicsActor until they stand up.
2411 RemoveFromPhysicalScene(); 2688 RemoveFromPhysicalScene();
2412 } 2689 }
2413 2690
2691 if (MovingToTarget)
2692 ResetMoveToTarget();
2693
2694 Velocity = Vector3.Zero;
2695
2414 part.AddSittingAvatar(UUID); 2696 part.AddSittingAvatar(UUID);
2415 2697
2416 cameraAtOffset = part.GetCameraAtOffset(); 2698 cameraAtOffset = part.GetCameraAtOffset();
@@ -2454,14 +2736,6 @@ namespace OpenSim.Region.Framework.Scenes
2454 m_requestedSitTargetID = part.LocalId; 2736 m_requestedSitTargetID = part.LocalId;
2455 m_requestedSitTargetUUID = part.UUID; 2737 m_requestedSitTargetUUID = part.UUID;
2456 2738
2457// m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset);
2458
2459 if (m_scene.PhysicsScene.SupportsRayCast())
2460 {
2461 //m_scene.PhysicsScene.RaycastWorld(Vector3.Zero,Vector3.Zero, 0.01f,new RaycastCallback());
2462 //SitRayCastAvatarPosition(part);
2463 //return;
2464 }
2465 } 2739 }
2466 else 2740 else
2467 { 2741 {
@@ -2471,197 +2745,115 @@ namespace OpenSim.Region.Framework.Scenes
2471 SendSitResponse(targetID, offset, Quaternion.Identity); 2745 SendSitResponse(targetID, offset, Quaternion.Identity);
2472 } 2746 }
2473 2747
2474 /* 2748 // returns false if does not suport so older sit can be tried
2475 public void SitRayCastAvatarPosition(SceneObjectPart part) 2749 public bool PhysicsSit(SceneObjectPart part, Vector3 offset)
2476 {
2477 Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
2478 Vector3 StartRayCastPosition = AbsolutePosition;
2479 Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
2480 float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
2481 m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionResponse);
2482 }
2483
2484 public void SitRayCastAvatarPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
2485 { 2750 {
2486 SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); 2751// TODO: Pull in these bits
2487 if (part != null) 2752 return false;
2488 { 2753/*
2489 if (hitYN) 2754 if (part == null || part.ParentGroup.IsAttachment)
2490 {
2491 if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
2492 {
2493 SitRaycastFindEdge(collisionPoint, normal);
2494 m_log.DebugFormat("[SIT]: Raycast Avatar Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
2495 }
2496 else
2497 {
2498 SitRayCastAvatarPositionCameraZ(part);
2499 }
2500 }
2501 else
2502 {
2503 SitRayCastAvatarPositionCameraZ(part);
2504 }
2505 }
2506 else
2507 { 2755 {
2508 ControllingClient.SendAlertMessage("Sit position no longer exists"); 2756 return true;
2509 m_requestedSitTargetUUID = UUID.Zero;
2510 m_requestedSitTargetID = 0;
2511 m_requestedSitOffset = Vector3.Zero;
2512 } 2757 }
2513 2758
2514 } 2759 if ( m_scene.PhysicsScene == null)
2515 2760 return false;
2516 public void SitRayCastAvatarPositionCameraZ(SceneObjectPart part)
2517 {
2518 // Next, try to raycast from the camera Z position
2519 Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
2520 Vector3 StartRayCastPosition = AbsolutePosition; StartRayCastPosition.Z = CameraPosition.Z;
2521 Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
2522 float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
2523 m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionCameraZResponse);
2524 }
2525 2761
2526 public void SitRayCastAvatarPositionCameraZResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) 2762 if (part.PhysActor == null)
2527 {
2528 SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
2529 if (part != null)
2530 { 2763 {
2531 if (hitYN) 2764 // none physcis shape
2532 { 2765 if (part.PhysicsShapeType == (byte)PhysicsShapeType.None)
2533 if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) 2766 ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot.");
2534 {
2535 SitRaycastFindEdge(collisionPoint, normal);
2536 m_log.DebugFormat("[SIT]: Raycast Avatar Position + CameraZ succeeded at point: {0}, normal:{1}", collisionPoint, normal);
2537 }
2538 else
2539 {
2540 SitRayCastCameraPosition(part);
2541 }
2542 }
2543 else 2767 else
2544 { 2768 { // non physical phantom TODO
2545 SitRayCastCameraPosition(part); 2769 ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot.");
2770 return false;
2546 } 2771 }
2547 } 2772 return true;
2548 else
2549 {
2550 ControllingClient.SendAlertMessage("Sit position no longer exists");
2551 m_requestedSitTargetUUID = UUID.Zero;
2552 m_requestedSitTargetID = 0;
2553 m_requestedSitOffset = Vector3.Zero;
2554 } 2773 }
2555 2774
2556 }
2557 2775
2558 public void SitRayCastCameraPosition(SceneObjectPart part) 2776 // not doing autopilot
2559 { 2777 m_requestedSitTargetID = 0;
2560 // Next, try to raycast from the camera position
2561 Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
2562 Vector3 StartRayCastPosition = CameraPosition;
2563 Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
2564 float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
2565 m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastCameraPositionResponse);
2566 }
2567 2778
2568 public void SitRayCastCameraPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) 2779 if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0)
2569 { 2780 return true;
2570 SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
2571 if (part != null)
2572 {
2573 if (hitYN)
2574 {
2575 if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
2576 {
2577 SitRaycastFindEdge(collisionPoint, normal);
2578 m_log.DebugFormat("[SIT]: Raycast Camera Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
2579 }
2580 else
2581 {
2582 SitRayHorizontal(part);
2583 }
2584 }
2585 else
2586 {
2587 SitRayHorizontal(part);
2588 }
2589 }
2590 else
2591 {
2592 ControllingClient.SendAlertMessage("Sit position no longer exists");
2593 m_requestedSitTargetUUID = UUID.Zero;
2594 m_requestedSitTargetID = 0;
2595 m_requestedSitOffset = Vector3.Zero;
2596 }
2597 2781
2782 return false;
2783*/
2598 } 2784 }
2599 2785
2600 public void SitRayHorizontal(SceneObjectPart part) 2786
2787 private bool CanEnterLandPosition(Vector3 testPos)
2601 { 2788 {
2602 // Next, try to raycast from the avatar position to fwd 2789 ILandObject land = m_scene.LandChannel.GetLandObject(testPos.X, testPos.Y);
2603 Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; 2790
2604 Vector3 StartRayCastPosition = CameraPosition; 2791 if (land == null || land.LandData.Name == "NO_LAND")
2605 Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); 2792 return true;
2606 float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); 2793
2607 m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastHorizontalResponse); 2794 return land.CanBeOnThisLand(UUID,testPos.Z);
2608 } 2795 }
2609 2796
2610 public void SitRayCastHorizontalResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) 2797 // status
2798 // < 0 ignore
2799 // 0 bad sit spot
2800 public void PhysicsSitResponse(int status, uint partID, Vector3 offset, Quaternion Orientation)
2611 { 2801 {
2612 SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); 2802 if (status < 0)
2613 if (part != null) 2803 return;
2804
2805 if (status == 0)
2614 { 2806 {
2615 if (hitYN) 2807 ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot.");
2616 { 2808 return;
2617 if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
2618 {
2619 SitRaycastFindEdge(collisionPoint, normal);
2620 m_log.DebugFormat("[SIT]: Raycast Horizontal Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
2621 // Next, try to raycast from the camera position
2622 Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
2623 Vector3 StartRayCastPosition = CameraPosition;
2624 Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
2625 float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
2626 //m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastResponseAvatarPosition);
2627 }
2628 else
2629 {
2630 ControllingClient.SendAlertMessage("Sit position not accessable.");
2631 m_requestedSitTargetUUID = UUID.Zero;
2632 m_requestedSitTargetID = 0;
2633 m_requestedSitOffset = Vector3.Zero;
2634 }
2635 }
2636 else
2637 {
2638 ControllingClient.SendAlertMessage("Sit position not accessable.");
2639 m_requestedSitTargetUUID = UUID.Zero;
2640 m_requestedSitTargetID = 0;
2641 m_requestedSitOffset = Vector3.Zero;
2642 }
2643 } 2809 }
2644 else 2810
2811 SceneObjectPart part = m_scene.GetSceneObjectPart(partID);
2812 if (part == null)
2813 return;
2814
2815 Vector3 targetPos = part.GetWorldPosition() + offset * part.GetWorldRotation();
2816 if(!CanEnterLandPosition(targetPos))
2645 { 2817 {
2646 ControllingClient.SendAlertMessage("Sit position no longer exists"); 2818 ControllingClient.SendAlertMessage(" Sit position on restricted land, try another spot");
2647 m_requestedSitTargetUUID = UUID.Zero; 2819 return;
2648 m_requestedSitTargetID = 0;
2649 m_requestedSitOffset = Vector3.Zero;
2650 } 2820 }
2651 2821
2652 } 2822 RemoveFromPhysicalScene();
2653 2823
2654 private void SitRaycastFindEdge(Vector3 collisionPoint, Vector3 collisionNormal) 2824 if (MovingToTarget)
2655 { 2825 ResetMoveToTarget();
2656 int i = 0; 2826
2657 //throw new NotImplementedException(); 2827 Velocity = Vector3.Zero;
2658 //m_requestedSitTargetUUID = UUID.Zero; 2828
2659 //m_requestedSitTargetID = 0; 2829 part.AddSittingAvatar(UUID);
2660 //m_requestedSitOffset = Vector3.Zero; 2830
2831 Vector3 cameraAtOffset = part.GetCameraAtOffset();
2832 Vector3 cameraEyeOffset = part.GetCameraEyeOffset();
2833 bool forceMouselook = part.GetForceMouselook();
2834
2835 ControllingClient.SendSitResponse(
2836 part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2837
2838 // not using autopilot
2839
2840 Rotation = Orientation;
2841 m_pos = offset;
2842
2843 m_requestedSitTargetID = 0;
2844 part.ParentGroup.AddAvatar(UUID);
2661 2845
2662 SendSitResponse(ControllingClient, m_requestedSitTargetUUID, collisionPoint - m_requestedSitOffset, Quaternion.Identity); 2846 ParentPart = part;
2847 ParentID = part.LocalId;
2848 if(status == 3)
2849 Animator.TrySetMovementAnimation("SIT_GROUND");
2850 else
2851 Animator.TrySetMovementAnimation("SIT");
2852 SendAvatarDataToAllAgents();
2853
2854 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2663 } 2855 }
2664 */ 2856
2665 2857
2666 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 2858 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
2667 { 2859 {
@@ -2681,6 +2873,7 @@ namespace OpenSim.Region.Framework.Scenes
2681 return; 2873 return;
2682 } 2874 }
2683 2875
2876
2684 if (part.SitTargetAvatar == UUID) 2877 if (part.SitTargetAvatar == UUID)
2685 { 2878 {
2686 Vector3 sitTargetPos = part.SitTargetPosition; 2879 Vector3 sitTargetPos = part.SitTargetPosition;
@@ -2695,7 +2888,28 @@ namespace OpenSim.Region.Framework.Scenes
2695 2888
2696 //Quaternion result = (sitTargetOrient * vq) * nq; 2889 //Quaternion result = (sitTargetOrient * vq) * nq;
2697 2890
2698 Vector3 newPos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2891 double x, y, z, m;
2892
2893 Quaternion r = sitTargetOrient;
2894 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2895
2896 if (Math.Abs(1.0 - m) > 0.000001)
2897 {
2898 m = 1.0 / Math.Sqrt(m);
2899 r.X *= (float)m;
2900 r.Y *= (float)m;
2901 r.Z *= (float)m;
2902 r.W *= (float)m;
2903 }
2904
2905 x = 2 * (r.X * r.Z + r.Y * r.W);
2906 y = 2 * (-r.X * r.W + r.Y * r.Z);
2907 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2908
2909 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2910 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2911
2912 Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
2699 Quaternion newRot; 2913 Quaternion newRot;
2700 2914
2701 if (part.IsRoot) 2915 if (part.IsRoot)
@@ -2712,6 +2926,8 @@ namespace OpenSim.Region.Framework.Scenes
2712 2926
2713 m_pos = newPos; 2927 m_pos = newPos;
2714 Rotation = newRot; 2928 Rotation = newRot;
2929
2930// ParentPosition = part.AbsolutePosition;
2715 } 2931 }
2716 else 2932 else
2717 { 2933 {
@@ -2719,11 +2935,14 @@ namespace OpenSim.Region.Framework.Scenes
2719 // being sat upon. 2935 // being sat upon.
2720 m_pos -= part.GroupPosition; 2936 m_pos -= part.GroupPosition;
2721 2937
2938// ParentPosition = part.AbsolutePosition;
2939
2722// m_log.DebugFormat( 2940// m_log.DebugFormat(
2723// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2941// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
2724// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); 2942// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
2725 } 2943 }
2726 2944
2945 part.ParentGroup.AddAvatar(UUID);
2727 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 2946 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2728 ParentID = m_requestedSitTargetID; 2947 ParentID = m_requestedSitTargetID;
2729 m_AngularVelocity = Vector3.Zero; 2948 m_AngularVelocity = Vector3.Zero;
@@ -2834,8 +3053,8 @@ namespace OpenSim.Region.Framework.Scenes
2834 direc.Z *= 2.6f; 3053 direc.Z *= 2.6f;
2835 3054
2836 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 3055 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
2837 Animator.TrySetMovementAnimation("PREJUMP"); 3056// Animator.TrySetMovementAnimation("PREJUMP");
2838 Animator.TrySetMovementAnimation("JUMP"); 3057// Animator.TrySetMovementAnimation("JUMP");
2839 } 3058 }
2840 } 3059 }
2841 } 3060 }
@@ -2844,6 +3063,7 @@ namespace OpenSim.Region.Framework.Scenes
2844 3063
2845 // TODO: Add the force instead of only setting it to support multiple forces per frame? 3064 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2846 m_forceToApply = direc; 3065 m_forceToApply = direc;
3066 Animator.UpdateMovementAnimations();
2847 } 3067 }
2848 3068
2849 #endregion 3069 #endregion
@@ -2861,16 +3081,12 @@ namespace OpenSim.Region.Framework.Scenes
2861 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to 3081 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to
2862 // grab the latest PhysicsActor velocity, whereas m_velocity is often 3082 // grab the latest PhysicsActor velocity, whereas m_velocity is often
2863 // storing a requested force instead of an actual traveling velocity 3083 // storing a requested force instead of an actual traveling velocity
3084 if (Appearance.AvatarSize != m_lastSize && !IsLoggingIn)
3085 SendAvatarDataToAllAgents();
2864 3086
2865 // Throw away duplicate or insignificant updates 3087 if (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
2866 if ( 3088 !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
2867 // If the velocity has become zero, send it no matter what. 3089 !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
2868 (Velocity != m_lastVelocity && Velocity == Vector3.Zero)
2869 // otherwise, if things have changed reasonably, send the update
2870 || (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)
2871 || !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE)
2872 || !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)))
2873
2874 { 3090 {
2875 SendTerseUpdateToAllClients(); 3091 SendTerseUpdateToAllClients();
2876 3092
@@ -3031,8 +3247,8 @@ namespace OpenSim.Region.Framework.Scenes
3031 // appearance goes into the avatar update packet 3247 // appearance goes into the avatar update packet
3032 SendAvatarDataToAllAgents(); 3248 SendAvatarDataToAllAgents();
3033 3249
3034 // This invocation always shows up in the viewer logs as an error. 3250 // This invocation always shows up in the viewer logs as an error. Is it needed?
3035 // SendAppearanceToAgent(this); 3251 SendAppearanceToAgent(this);
3036 3252
3037 // If we are using the the cached appearance then send it out to everyone 3253 // If we are using the the cached appearance then send it out to everyone
3038 if (cachedappearance) 3254 if (cachedappearance)
@@ -3063,6 +3279,8 @@ namespace OpenSim.Region.Framework.Scenes
3063 return; 3279 return;
3064 } 3280 }
3065 3281
3282 m_lastSize = Appearance.AvatarSize;
3283
3066 int count = 0; 3284 int count = 0;
3067 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3285 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3068 { 3286 {
@@ -3170,6 +3388,8 @@ namespace OpenSim.Region.Framework.Scenes
3170 3388
3171 avatar.ControllingClient.SendAppearance( 3389 avatar.ControllingClient.SendAppearance(
3172 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); 3390 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
3391
3392
3173 } 3393 }
3174 3394
3175 #endregion 3395 #endregion
@@ -3243,17 +3463,22 @@ namespace OpenSim.Region.Framework.Scenes
3243 3463
3244 // If we don't have a PhysActor, we can't cross anyway 3464 // If we don't have a PhysActor, we can't cross anyway
3245 // Also don't do this while sat, sitting avatars cross with the 3465 // Also don't do this while sat, sitting avatars cross with the
3246 // object they sit on. 3466 // object they sit on. ParentUUID denoted a pending sit, don't
3247 if (ParentID != 0 || PhysicsActor == null) 3467 // interfere with it.
3468 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
3248 return; 3469 return;
3249 3470
3250 if (!IsInTransit) 3471 if (!IsInTransit)
3251 { 3472 {
3252 Vector3 pos2 = AbsolutePosition; 3473 Vector3 pos2 = AbsolutePosition;
3474 Vector3 origPosition = pos2;
3253 Vector3 vel = Velocity; 3475 Vector3 vel = Velocity;
3254 int neighbor = 0; 3476 int neighbor = 0;
3255 int[] fix = new int[2]; 3477 int[] fix = new int[2];
3256 3478
3479 // Compute the avatar position in the next physics tick.
3480 // If the avatar will be crossing, we force the crossing to happen now
3481 // in the hope that this will make the avatar movement smoother when crossing.
3257 float timeStep = 0.1f; 3482 float timeStep = 0.1f;
3258 pos2.X = pos2.X + (vel.X * timeStep); 3483 pos2.X = pos2.X + (vel.X * timeStep);
3259 pos2.Y = pos2.Y + (vel.Y * timeStep); 3484 pos2.Y = pos2.Y + (vel.Y * timeStep);
@@ -3261,111 +3486,44 @@ namespace OpenSim.Region.Framework.Scenes
3261 3486
3262 if (!IsInTransit) 3487 if (!IsInTransit)
3263 { 3488 {
3264// m_log.DebugFormat( 3489 if (!m_scene.PositionIsInCurrentRegion(pos2))
3265// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3266// pos2, Name, Scene.Name);
3267
3268 // Checks if where it's headed exists a region
3269 bool needsTransit = false;
3270 if (m_scene.TestBorderCross(pos2, Cardinals.W))
3271 { 3490 {
3272 if (m_scene.TestBorderCross(pos2, Cardinals.S)) 3491 m_log.DebugFormat("{0} CheckForBorderCrossing: position outside region. {1} in {2} at pos {3}",
3492 LogHeader, Name, Scene.Name, pos2);
3493
3494 // Disconnect from the current region
3495 bool isFlying = Flying;
3496 RemoveFromPhysicalScene();
3497 // pos2 is the forcasted position so make that the 'current' position so the crossing
3498 // code will move us into the newly addressed region.
3499 m_pos = pos2;
3500 if (CrossToNewRegion())
3273 { 3501 {
3274 needsTransit = true; 3502 AddToPhysicalScene(isFlying);
3275 neighbor = m_scene.HaveNeighbor(Cardinals.SW, ref fix);
3276 }
3277 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3278 {
3279 needsTransit = true;
3280 neighbor = m_scene.HaveNeighbor(Cardinals.NW, ref fix);
3281 } 3503 }
3282 else 3504 else
3283 { 3505 {
3284 needsTransit = true; 3506 // Tried to make crossing happen but it failed.
3285 neighbor = m_scene.HaveNeighbor(Cardinals.W, ref fix);
3286 }
3287 }
3288 else if (m_scene.TestBorderCross(pos2, Cardinals.E))
3289 {
3290 if (m_scene.TestBorderCross(pos2, Cardinals.S))
3291 {
3292 needsTransit = true;
3293 neighbor = m_scene.HaveNeighbor(Cardinals.SE, ref fix);
3294 }
3295 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3296 {
3297 needsTransit = true;
3298 neighbor = m_scene.HaveNeighbor(Cardinals.NE, ref fix);
3299 }
3300 else
3301 {
3302 needsTransit = true;
3303 neighbor = m_scene.HaveNeighbor(Cardinals.E, ref fix);
3304 }
3305 }
3306 else if (m_scene.TestBorderCross(pos2, Cardinals.S))
3307 {
3308 needsTransit = true;
3309 neighbor = m_scene.HaveNeighbor(Cardinals.S, ref fix);
3310 }
3311 else if (m_scene.TestBorderCross(pos2, Cardinals.N))
3312 {
3313 needsTransit = true;
3314 neighbor = m_scene.HaveNeighbor(Cardinals.N, ref fix);
3315 }
3316
3317 // Makes sure avatar does not end up outside region
3318 if (neighbor <= 0)
3319 {
3320 if (needsTransit)
3321 {
3322 if (m_requestedSitTargetUUID == UUID.Zero) 3507 if (m_requestedSitTargetUUID == UUID.Zero)
3323 { 3508 {
3324 bool isFlying = Flying; 3509 m_log.DebugFormat("{0} CheckForBorderCrossing: Crossing failed. Restoring old position.", LogHeader);
3325 RemoveFromPhysicalScene(); 3510 const float borderFudge = 0.1f;
3326 3511
3327 Vector3 pos = AbsolutePosition; 3512 if (origPosition.X < 0)
3328 if (AbsolutePosition.X < 0) 3513 origPosition.X = borderFudge;
3329 pos.X += Velocity.X * 2; 3514 else if (origPosition.X > (float)m_scene.RegionInfo.RegionSizeX)
3330 else if (AbsolutePosition.X > Constants.RegionSize) 3515 origPosition.X = (float)m_scene.RegionInfo.RegionSizeX - borderFudge;
3331 pos.X -= Velocity.X * 2; 3516 if (origPosition.Y < 0)
3332 if (AbsolutePosition.Y < 0) 3517 origPosition.Y = borderFudge;
3333 pos.Y += Velocity.Y * 2; 3518 else if (origPosition.Y > (float)m_scene.RegionInfo.RegionSizeY)
3334 else if (AbsolutePosition.Y > Constants.RegionSize) 3519 origPosition.Y = (float)m_scene.RegionInfo.RegionSizeY - borderFudge;
3335 pos.Y -= Velocity.Y * 2;
3336 Velocity = Vector3.Zero; 3520 Velocity = Vector3.Zero;
3337 AbsolutePosition = pos; 3521 AbsolutePosition = origPosition;
3338
3339// m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition);
3340
3341 AddToPhysicalScene(isFlying);
3342 }
3343 }
3344 }
3345 else if (neighbor > 0)
3346 {
3347 if (!CrossToNewRegion())
3348 {
3349 if (m_requestedSitTargetUUID == UUID.Zero)
3350 {
3351 bool isFlying = Flying;
3352 RemoveFromPhysicalScene();
3353
3354 Vector3 pos = AbsolutePosition;
3355 if (AbsolutePosition.X < 0)
3356 pos.X += Velocity.X * 2;
3357 else if (AbsolutePosition.X > Constants.RegionSize)
3358 pos.X -= Velocity.X * 2;
3359 if (AbsolutePosition.Y < 0)
3360 pos.Y += Velocity.Y * 2;
3361 else if (AbsolutePosition.Y > Constants.RegionSize)
3362 pos.Y -= Velocity.Y * 2;
3363 Velocity = Vector3.Zero;
3364 AbsolutePosition = pos;
3365 3522
3366 AddToPhysicalScene(isFlying); 3523 AddToPhysicalScene(isFlying);
3367 } 3524 }
3368 } 3525 }
3526
3369 } 3527 }
3370 } 3528 }
3371 else 3529 else
@@ -3407,7 +3565,7 @@ namespace OpenSim.Region.Framework.Scenes
3407 3565
3408 // Put the child agent back at the center 3566 // Put the child agent back at the center
3409 AbsolutePosition 3567 AbsolutePosition
3410 = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70); 3568 = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
3411 3569
3412 Animator.ResetAnimations(); 3570 Animator.ResetAnimations();
3413 } 3571 }
@@ -3434,9 +3592,7 @@ namespace OpenSim.Region.Framework.Scenes
3434 if (handle != Scene.RegionInfo.RegionHandle) 3592 if (handle != Scene.RegionInfo.RegionHandle)
3435 { 3593 {
3436 uint x, y; 3594 uint x, y;
3437 Utils.LongToUInts(handle, out x, out y); 3595 Util.RegionHandleToRegionLoc(handle, out x, out y);
3438 x = x / Constants.RegionSize;
3439 y = y / Constants.RegionSize;
3440 3596
3441// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); 3597// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
3442// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); 3598// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
@@ -3517,8 +3673,9 @@ namespace OpenSim.Region.Framework.Scenes
3517 return; 3673 return;
3518 3674
3519 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); 3675 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
3520 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; 3676 // Find the distance (in meters) between the two regions
3521 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; 3677 uint shiftx = Util.RegionToWorldLoc(rRegionX - tRegionX);
3678 uint shifty = Util.RegionToWorldLoc(rRegionY - tRegionY);
3522 3679
3523 Vector3 offset = new Vector3(shiftx, shifty, 0f); 3680 Vector3 offset = new Vector3(shiftx, shifty, 0f);
3524 3681
@@ -3588,6 +3745,9 @@ namespace OpenSim.Region.Framework.Scenes
3588 cAgent.AlwaysRun = SetAlwaysRun; 3745 cAgent.AlwaysRun = SetAlwaysRun;
3589 3746
3590 cAgent.Appearance = new AvatarAppearance(Appearance); 3747 cAgent.Appearance = new AvatarAppearance(Appearance);
3748
3749 cAgent.ParentPart = ParentUUID;
3750 cAgent.SitOffset = PrevSitOffset;
3591 3751
3592 lock (scriptedcontrols) 3752 lock (scriptedcontrols)
3593 { 3753 {
@@ -3596,7 +3756,7 @@ namespace OpenSim.Region.Framework.Scenes
3596 3756
3597 foreach (ScriptControllers c in scriptedcontrols.Values) 3757 foreach (ScriptControllers c in scriptedcontrols.Values)
3598 { 3758 {
3599 controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls); 3759 controls[i++] = new ControllerData(c.objectID, c.itemID, (uint)c.ignoreControls, (uint)c.eventControls);
3600 } 3760 }
3601 cAgent.Controllers = controls; 3761 cAgent.Controllers = controls;
3602 } 3762 }
@@ -3630,6 +3790,8 @@ namespace OpenSim.Region.Framework.Scenes
3630 CameraAtAxis = cAgent.AtAxis; 3790 CameraAtAxis = cAgent.AtAxis;
3631 CameraLeftAxis = cAgent.LeftAxis; 3791 CameraLeftAxis = cAgent.LeftAxis;
3632 CameraUpAxis = cAgent.UpAxis; 3792 CameraUpAxis = cAgent.UpAxis;
3793 ParentUUID = cAgent.ParentPart;
3794 PrevSitOffset = cAgent.SitOffset;
3633 3795
3634 // When we get to the point of re-computing neighbors everytime this 3796 // When we get to the point of re-computing neighbors everytime this
3635 // changes, then start using the agent's drawdistance rather than the 3797 // changes, then start using the agent's drawdistance rather than the
@@ -3667,6 +3829,7 @@ namespace OpenSim.Region.Framework.Scenes
3667 foreach (ControllerData c in cAgent.Controllers) 3829 foreach (ControllerData c in cAgent.Controllers)
3668 { 3830 {
3669 ScriptControllers sc = new ScriptControllers(); 3831 ScriptControllers sc = new ScriptControllers();
3832 sc.objectID = c.ObjectID;
3670 sc.itemID = c.ItemID; 3833 sc.itemID = c.ItemID;
3671 sc.ignoreControls = (ScriptControlled)c.IgnoreControls; 3834 sc.ignoreControls = (ScriptControlled)c.IgnoreControls;
3672 sc.eventControls = (ScriptControlled)c.EventControls; 3835 sc.eventControls = (ScriptControlled)c.EventControls;
@@ -3732,20 +3895,27 @@ namespace OpenSim.Region.Framework.Scenes
3732 } 3895 }
3733 3896
3734 if (Appearance.AvatarHeight == 0) 3897 if (Appearance.AvatarHeight == 0)
3735 Appearance.SetHeight(); 3898// Appearance.SetHeight();
3899 Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f));
3736 3900
3737 PhysicsScene scene = m_scene.PhysicsScene; 3901 PhysicsScene scene = m_scene.PhysicsScene;
3738 3902
3739 Vector3 pVec = AbsolutePosition; 3903 Vector3 pVec = AbsolutePosition;
3740 3904
3905/*
3741 PhysicsActor = scene.AddAvatar( 3906 PhysicsActor = scene.AddAvatar(
3742 LocalId, Firstname + "." + Lastname, pVec, 3907 LocalId, Firstname + "." + Lastname, pVec,
3743 new Vector3(0f, 0f, Appearance.AvatarHeight), isFlying); 3908 new Vector3(0.45f, 0.6f, Appearance.AvatarHeight), isFlying);
3909*/
3910
3911 PhysicsActor = scene.AddAvatar(
3912 LocalId, Firstname + "." + Lastname, pVec,
3913 Appearance.AvatarBoxSize, isFlying);
3744 3914
3745 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3915 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3746 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3916 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
3747 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong 3917 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
3748 PhysicsActor.SubscribeEvents(500); 3918 PhysicsActor.SubscribeEvents(100);
3749 PhysicsActor.LocalID = LocalId; 3919 PhysicsActor.LocalID = LocalId;
3750 } 3920 }
3751 3921
@@ -3759,6 +3929,7 @@ namespace OpenSim.Region.Framework.Scenes
3759 ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true); 3929 ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true);
3760 } 3930 }
3761 3931
3932
3762 /// <summary> 3933 /// <summary>
3763 /// Event called by the physics plugin to tell the avatar about a collision. 3934 /// Event called by the physics plugin to tell the avatar about a collision.
3764 /// </summary> 3935 /// </summary>
@@ -3772,7 +3943,7 @@ namespace OpenSim.Region.Framework.Scenes
3772 /// <param name="e"></param> 3943 /// <param name="e"></param>
3773 public void PhysicsCollisionUpdate(EventArgs e) 3944 public void PhysicsCollisionUpdate(EventArgs e)
3774 { 3945 {
3775 if (IsChildAgent) 3946 if (IsChildAgent || Animator == null)
3776 return; 3947 return;
3777 3948
3778 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3949 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
@@ -3789,7 +3960,6 @@ namespace OpenSim.Region.Framework.Scenes
3789 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3960 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3790 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3961 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3791 3962
3792 CollisionPlane = Vector4.UnitW;
3793 3963
3794// // No collisions at all means we may be flying. Update always 3964// // No collisions at all means we may be flying. Update always
3795// // to make falling work 3965// // to make falling work
@@ -3799,34 +3969,7 @@ namespace OpenSim.Region.Framework.Scenes
3799// m_lastColCount = coldata.Count; 3969// m_lastColCount = coldata.Count;
3800// } 3970// }
3801 3971
3802 if (coldata.Count != 0) 3972 CollisionPlane = Vector4.UnitW;
3803 {
3804 switch (Animator.CurrentMovementAnimation)
3805 {
3806 case "STAND":
3807 case "WALK":
3808 case "RUN":
3809 case "CROUCH":
3810 case "CROUCHWALK":
3811 {
3812 ContactPoint lowest;
3813 lowest.SurfaceNormal = Vector3.Zero;
3814 lowest.Position = Vector3.Zero;
3815 lowest.Position.Z = Single.NaN;
3816
3817 foreach (ContactPoint contact in coldata.Values)
3818 {
3819 if (Single.IsNaN(lowest.Position.Z) || contact.Position.Z < lowest.Position.Z)
3820 {
3821 lowest = contact;
3822 }
3823 }
3824
3825 CollisionPlane = new Vector4(-lowest.SurfaceNormal, -Vector3.Dot(lowest.Position, lowest.SurfaceNormal));
3826 }
3827 break;
3828 }
3829 }
3830 3973
3831 // Gods do not take damage and Invulnerable is set depending on parcel/region flags 3974 // Gods do not take damage and Invulnerable is set depending on parcel/region flags
3832 if (Invulnerable || GodLevel > 0) 3975 if (Invulnerable || GodLevel > 0)
@@ -3925,6 +4068,12 @@ namespace OpenSim.Region.Framework.Scenes
3925 // m_reprioritizationTimer.Dispose(); 4068 // m_reprioritizationTimer.Dispose();
3926 4069
3927 RemoveFromPhysicalScene(); 4070 RemoveFromPhysicalScene();
4071
4072 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
4073
4074// if (Animator != null)
4075// Animator.Close();
4076 Animator = null;
3928 4077
3929 LifecycleState = ScenePresenceState.Removed; 4078 LifecycleState = ScenePresenceState.Removed;
3930 } 4079 }
@@ -4160,10 +4309,18 @@ namespace OpenSim.Region.Framework.Scenes
4160 4309
4161 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID) 4310 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID)
4162 { 4311 {
4312 SceneObjectPart p = m_scene.GetSceneObjectPart(Obj_localID);
4313 if (p == null)
4314 return;
4315
4316 ControllingClient.SendTakeControls(controls, false, false);
4317 ControllingClient.SendTakeControls(controls, true, false);
4318
4163 ScriptControllers obj = new ScriptControllers(); 4319 ScriptControllers obj = new ScriptControllers();
4164 obj.ignoreControls = ScriptControlled.CONTROL_ZERO; 4320 obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
4165 obj.eventControls = ScriptControlled.CONTROL_ZERO; 4321 obj.eventControls = ScriptControlled.CONTROL_ZERO;
4166 4322
4323 obj.objectID = p.ParentGroup.UUID;
4167 obj.itemID = Script_item_UUID; 4324 obj.itemID = Script_item_UUID;
4168 if (pass_on == 0 && accept == 0) 4325 if (pass_on == 0 && accept == 0)
4169 { 4326 {
@@ -4212,6 +4369,21 @@ namespace OpenSim.Region.Framework.Scenes
4212 ControllingClient.SendTakeControls(int.MaxValue, false, false); 4369 ControllingClient.SendTakeControls(int.MaxValue, false, false);
4213 } 4370 }
4214 4371
4372 private void UnRegisterSeatControls(UUID obj)
4373 {
4374 List<UUID> takers = new List<UUID>();
4375
4376 foreach (ScriptControllers c in scriptedcontrols.Values)
4377 {
4378 if (c.objectID == obj)
4379 takers.Add(c.itemID);
4380 }
4381 foreach (UUID t in takers)
4382 {
4383 UnRegisterControlEventsToScript(0, t);
4384 }
4385 }
4386
4215 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) 4387 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID)
4216 { 4388 {
4217 ScriptControllers takecontrols; 4389 ScriptControllers takecontrols;
@@ -4539,8 +4711,15 @@ namespace OpenSim.Region.Framework.Scenes
4539 } 4711 }
4540 } 4712 }
4541 4713
4714 // Modify landing point based on possible banning, telehubs or parcel restrictions.
4542 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 4715 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
4543 { 4716 {
4717 string reason;
4718
4719 // Honor bans
4720 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
4721 return;
4722
4544 SceneObjectGroup telehub = null; 4723 SceneObjectGroup telehub = null;
4545 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 4724 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
4546 { 4725 {
@@ -4580,11 +4759,119 @@ namespace OpenSim.Region.Framework.Scenes
4580 pos = land.LandData.UserLocation; 4759 pos = land.LandData.UserLocation;
4581 } 4760 }
4582 } 4761 }
4583 4762
4584 land.SendLandUpdateToClient(ControllingClient); 4763 land.SendLandUpdateToClient(ControllingClient);
4585 } 4764 }
4586 } 4765 }
4587 4766
4767 private DetectedObject CreateDetObject(SceneObjectPart obj)
4768 {
4769 DetectedObject detobj = new DetectedObject();
4770 detobj.keyUUID = obj.UUID;
4771 detobj.nameStr = obj.Name;
4772 detobj.ownerUUID = obj.OwnerID;
4773 detobj.posVector = obj.AbsolutePosition;
4774 detobj.rotQuat = obj.GetWorldRotation();
4775 detobj.velVector = obj.Velocity;
4776 detobj.colliderType = 0;
4777 detobj.groupUUID = obj.GroupID;
4778
4779 return detobj;
4780 }
4781
4782 private DetectedObject CreateDetObject(ScenePresence av)
4783 {
4784 DetectedObject detobj = new DetectedObject();
4785 detobj.keyUUID = av.UUID;
4786 detobj.nameStr = av.ControllingClient.Name;
4787 detobj.ownerUUID = av.UUID;
4788 detobj.posVector = av.AbsolutePosition;
4789 detobj.rotQuat = av.Rotation;
4790 detobj.velVector = av.Velocity;
4791 detobj.colliderType = 0;
4792 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
4793
4794 return detobj;
4795 }
4796
4797 private DetectedObject CreateDetObjectForGround()
4798 {
4799 DetectedObject detobj = new DetectedObject();
4800 detobj.keyUUID = UUID.Zero;
4801 detobj.nameStr = "";
4802 detobj.ownerUUID = UUID.Zero;
4803 detobj.posVector = AbsolutePosition;
4804 detobj.rotQuat = Quaternion.Identity;
4805 detobj.velVector = Vector3.Zero;
4806 detobj.colliderType = 0;
4807 detobj.groupUUID = UUID.Zero;
4808
4809 return detobj;
4810 }
4811
4812 private ColliderArgs CreateColliderArgs(SceneObjectPart dest, List<uint> colliders)
4813 {
4814 ColliderArgs colliderArgs = new ColliderArgs();
4815 List<DetectedObject> colliding = new List<DetectedObject>();
4816 foreach (uint localId in colliders)
4817 {
4818 if (localId == 0)
4819 continue;
4820
4821 SceneObjectPart obj = m_scene.GetSceneObjectPart(localId);
4822 if (obj != null)
4823 {
4824 if (!dest.CollisionFilteredOut(obj.UUID, obj.Name))
4825 colliding.Add(CreateDetObject(obj));
4826 }
4827 else
4828 {
4829 ScenePresence av = m_scene.GetScenePresence(localId);
4830 if (av != null && (!av.IsChildAgent))
4831 {
4832 if (!dest.CollisionFilteredOut(av.UUID, av.Name))
4833 colliding.Add(CreateDetObject(av));
4834 }
4835 }
4836 }
4837
4838 colliderArgs.Colliders = colliding;
4839
4840 return colliderArgs;
4841 }
4842
4843 private delegate void ScriptCollidingNotification(uint localID, ColliderArgs message);
4844
4845 private void SendCollisionEvent(SceneObjectGroup dest, scriptEvents ev, List<uint> colliders, ScriptCollidingNotification notify)
4846 {
4847 ColliderArgs CollidingMessage;
4848
4849 if (colliders.Count > 0)
4850 {
4851 if ((dest.RootPart.ScriptEvents & ev) != 0)
4852 {
4853 CollidingMessage = CreateColliderArgs(dest.RootPart, colliders);
4854
4855 if (CollidingMessage.Colliders.Count > 0)
4856 notify(dest.RootPart.LocalId, CollidingMessage);
4857 }
4858 }
4859 }
4860
4861 private void SendLandCollisionEvent(SceneObjectGroup dest, scriptEvents ev, ScriptCollidingNotification notify)
4862 {
4863 if ((dest.RootPart.ScriptEvents & ev) != 0)
4864 {
4865 ColliderArgs LandCollidingMessage = new ColliderArgs();
4866 List<DetectedObject> colliding = new List<DetectedObject>();
4867
4868 colliding.Add(CreateDetObjectForGround());
4869 LandCollidingMessage.Colliders = colliding;
4870
4871 notify(dest.RootPart.LocalId, LandCollidingMessage);
4872 }
4873 }
4874
4588 private void TeleportFlagsDebug() { 4875 private void TeleportFlagsDebug() {
4589 4876
4590 // Some temporary debugging help to show all the TeleportFlags we have... 4877 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -4609,6 +4896,5 @@ namespace OpenSim.Region.Framework.Scenes
4609 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 4896 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
4610 4897
4611 } 4898 }
4612
4613 } 4899 }
4614} 4900}
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index c0ca48e..60dc6c9 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
@@ -25,14 +25,21 @@
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 OpenMetaverse;
40
41using log4net;
42
36namespace OpenSim.Region.Framework.Scenes 43namespace OpenSim.Region.Framework.Scenes
37{ 44{
38 /// <summary> 45 /// <summary>
@@ -40,132 +47,146 @@ namespace OpenSim.Region.Framework.Scenes
40 /// </summary> 47 /// </summary>
41 public class TerrainChannel : ITerrainChannel 48 public class TerrainChannel : ITerrainChannel
42 { 49 {
43 private readonly bool[,] taint; 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 private double[,] map; 51 private static string LogHeader = "[TERRAIN CHANNEL]";
45 52
53 protected TerrainData m_terrainData;
54
55 public int Width { get { return m_terrainData.SizeX; } } // X dimension
56 // Unfortunately, for historical reasons, in this module 'Width' is X and 'Height' is Y
57 public int Height { get { return m_terrainData.SizeY; } } // Y dimension
58 public int Altitude { get { return m_terrainData.SizeZ; } } // Y dimension
59
60 // Default, not-often-used builder
46 public TerrainChannel() 61 public TerrainChannel()
47 { 62 {
48 map = new double[Constants.RegionSize, Constants.RegionSize]; 63 m_terrainData = new HeightmapTerrainData((int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
49 taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16]; 64 FlatLand();
50 65 // PinHeadIsland();
51 PinHeadIsland();
52 } 66 }
53 67
54 public TerrainChannel(String type) 68 // Create terrain of given size
69 public TerrainChannel(int pX, int pY)
55 { 70 {
56 map = new double[Constants.RegionSize, Constants.RegionSize]; 71 m_terrainData = new HeightmapTerrainData(pX, pY, (int)Constants.RegionHeight);
57 taint = new bool[Constants.RegionSize / 16, Constants.RegionSize / 16]; 72 }
58 73
74 // Create terrain of specified size and initialize with specified terrain.
75 // TODO: join this with the terrain initializers.
76 public TerrainChannel(String type, int pX, int pY, int pZ)
77 {
78 m_terrainData = new HeightmapTerrainData(pX, pY, pZ);
59 if (type.Equals("flat")) 79 if (type.Equals("flat"))
60 FlatLand(); 80 FlatLand();
61 else 81 else
62 PinHeadIsland(); 82 PinHeadIsland();
63 } 83 }
64 84
65 public TerrainChannel(double[,] import) 85 // Create channel passed a heightmap and expected dimensions of the region.
86 // The heightmap might not fit the passed size so accomodations must be made.
87 public TerrainChannel(double[,] pM, int pSizeX, int pSizeY, int pAltitude)
66 { 88 {
67 map = import; 89 int hmSizeX = pM.GetLength(0);
68 taint = new bool[import.GetLength(0),import.GetLength(1)]; 90 int hmSizeY = pM.GetLength(1);
69 }
70 91
71 public TerrainChannel(bool createMap) 92 m_terrainData = new HeightmapTerrainData(pSizeX, pSizeY, pAltitude);
72 { 93
73 if (createMap) 94 for (int xx = 0; xx < pSizeX; xx++)
74 { 95 for (int yy = 0; yy < pSizeY; yy++)
75 map = new double[Constants.RegionSize,Constants.RegionSize]; 96 if (xx > hmSizeX || yy > hmSizeY)
76 taint = new bool[Constants.RegionSize / 16,Constants.RegionSize / 16]; 97 m_terrainData[xx, yy] = TerrainData.DefaultTerrainHeight;
77 } 98 else
99 m_terrainData[xx, yy] = (float)pM[xx, yy];
78 } 100 }
79 101
80 public TerrainChannel(int w, int h) 102 public TerrainChannel(TerrainData pTerrData)
81 { 103 {
82 map = new double[w,h]; 104 m_terrainData = pTerrData;
83 taint = new bool[w / 16,h / 16];
84 } 105 }
85 106
86 #region ITerrainChannel Members 107 #region ITerrainChannel Members
87 108
88 public int Width 109 // ITerrainChannel.MakeCopy()
110 public ITerrainChannel MakeCopy()
89 { 111 {
90 get { return map.GetLength(0); } 112 return this.Copy();
91 } 113 }
92 114
93 public int Height 115 // ITerrainChannel.GetTerrainData()
116 public TerrainData GetTerrainData()
94 { 117 {
95 get { return map.GetLength(1); } 118 return m_terrainData;
96 } 119 }
97 120
98 public ITerrainChannel MakeCopy() 121 // ITerrainChannel.GetFloatsSerialized()
122 // This one dimensional version is ordered so height = map[y*sizeX+x];
123 // DEPRECATED: don't use this function as it does not retain the dimensions of the terrain
124 // and the caller will probably do the wrong thing if the terrain is not the legacy 256x256.
125 public float[] GetFloatsSerialised()
99 { 126 {
100 TerrainChannel copy = new TerrainChannel(false); 127 int points = Width * Height;
101 copy.map = (double[,]) map.Clone(); 128 float[] heights = new float[points];
102 129
103 return copy; 130 int idx = 0;
131 for (int jj = 0; jj < Height; jj++)
132 for (int ii = 0; ii < Width; ii++)
133 {
134 heights[idx++] = m_terrainData[ii, jj];
135 }
136
137 return heights;
104 } 138 }
105 139
106 public float[] GetFloatsSerialised() 140 // ITerrainChannel.GetDoubles()
141 public double[,] GetDoubles()
107 { 142 {
108 // Move the member variables into local variables, calling 143 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 144
114 int i, j; // map coordinates
115 int idx = 0; // index into serialized array 145 int idx = 0; // index into serialized array
116 for (i = 0; i < h; i++) 146 for (int ii = 0; ii < Width; ii++)
117 { 147 {
118 for (j = 0; j < w; j++) 148 for (int jj = 0; jj < Height; jj++)
119 { 149 {
120 heights[idx++] = (float)map[j, i]; 150 heights[ii, jj] = (double)m_terrainData[ii, jj];
151 idx++;
121 } 152 }
122 } 153 }
123 154
124 return heights; 155 return heights;
125 } 156 }
126 157
127 public double[,] GetDoubles() 158 // ITerrainChannel.this[x,y]
128 {
129 return map;
130 }
131
132 public double this[int x, int y] 159 public double this[int x, int y]
133 { 160 {
134 get { return map[x, y]; } 161 get {
162 if (x < 0 || x >= Width || y < 0 || y >= Height)
163 return 0;
164 return (double)m_terrainData[x, y];
165 }
135 set 166 set
136 { 167 {
137 // Will "fix" terrain hole problems. Although not fantastically.
138 if (Double.IsNaN(value) || Double.IsInfinity(value)) 168 if (Double.IsNaN(value) || Double.IsInfinity(value))
139 return; 169 return;
140 170
141 if (map[x, y] != value) 171 m_terrainData[x, y] = (float)value;
142 {
143 taint[x / 16, y / 16] = true;
144 map[x, y] = value;
145 }
146 } 172 }
147 } 173 }
148 174
149 public bool Tainted(int x, int y) 175 // ITerrainChannel.GetHieghtAtXYZ(x, y, z)
176 public float GetHeightAtXYZ(float x, float y, float z)
150 { 177 {
151 if (taint[x / 16, y / 16]) 178 if (x < 0 || x >= Width || y < 0 || y >= Height)
152 { 179 return 0;
153 taint[x / 16, y / 16] = false; 180 return m_terrainData[(int)x, (int)y];
154 return true;
155 }
156 return false;
157 } 181 }
158 182
159 #endregion 183 // ITerrainChannel.Tainted()
160 184 public bool Tainted(int x, int y)
161 public TerrainChannel Copy()
162 { 185 {
163 TerrainChannel copy = new TerrainChannel(false); 186 return m_terrainData.IsTaintedAt(x, y);
164 copy.map = (double[,]) map.Clone();
165
166 return copy;
167 } 187 }
168 188
189 // ITerrainChannel.SaveToXmlString()
169 public string SaveToXmlString() 190 public string SaveToXmlString()
170 { 191 {
171 XmlWriterSettings settings = new XmlWriterSettings(); 192 XmlWriterSettings settings = new XmlWriterSettings();
@@ -181,13 +202,7 @@ namespace OpenSim.Region.Framework.Scenes
181 } 202 }
182 } 203 }
183 204
184 private void WriteXml(XmlWriter writer) 205 // 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) 206 public void LoadFromXmlString(string data)
192 { 207 {
193 StringReader sr = new StringReader(data); 208 StringReader sr = new StringReader(data);
@@ -199,12 +214,124 @@ namespace OpenSim.Region.Framework.Scenes
199 sr.Close(); 214 sr.Close();
200 } 215 }
201 216
217 // ITerrainChannel.Merge
218 public void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement)
219 {
220 m_log.DebugFormat("{0} Merge. inSize=<{1},{2}>, disp={3}, rot={4}, rotDisp={5}, outSize=<{6},{7}>", LogHeader,
221 newTerrain.Width, newTerrain.Height,
222 displacement, radianRotation, rotationDisplacement,
223 m_terrainData.SizeX, m_terrainData.SizeY);
224 for (int xx = 0; xx < newTerrain.Width; xx++)
225 {
226 for (int yy = 0; yy < newTerrain.Height; yy++)
227 {
228 int dispX = (int)displacement.X;
229 int dispY = (int)displacement.Y;
230 float newHeight = (float)newTerrain[xx, yy] + displacement.Z;
231 if (radianRotation == 0)
232 {
233 // If no rotation, place the new height in the specified location
234 dispX += xx;
235 dispY += yy;
236 if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
237 {
238 m_terrainData[dispX, dispY] = newHeight;
239 }
240 }
241 else
242 {
243 // If rotating, we have to smooth the result because the conversion
244 // to ints will mean heightmap entries will not get changed
245 // First compute the rotation location for the new height.
246 dispX += (int)(rotationDisplacement.X
247 + ((float)xx - rotationDisplacement.X) * Math.Cos(radianRotation)
248 - ((float)yy - rotationDisplacement.Y) * Math.Sin(radianRotation) );
249
250 dispY += (int)(rotationDisplacement.Y
251 + ((float)xx - rotationDisplacement.X) * Math.Sin(radianRotation)
252 + ((float)yy - rotationDisplacement.Y) * Math.Cos(radianRotation) );
253
254 if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
255 {
256 float oldHeight = m_terrainData[dispX, dispY];
257 // Smooth the heights around this location if the old height is far from this one
258 for (int sxx = dispX - 2; sxx < dispX + 2; sxx++)
259 {
260 for (int syy = dispY - 2; syy < dispY + 2; syy++)
261 {
262 if (sxx >= 0 && sxx < m_terrainData.SizeX && syy >= 0 && syy < m_terrainData.SizeY)
263 {
264 if (sxx == dispX && syy == dispY)
265 {
266 // Set height for the exact rotated point
267 m_terrainData[dispX, dispY] = newHeight;
268 }
269 else
270 {
271 if (Math.Abs(m_terrainData[sxx, syy] - newHeight) > 1f)
272 {
273 // If the adjacent height is far off, force it to this height
274 m_terrainData[sxx, syy] = newHeight;
275 }
276 }
277 }
278 }
279 }
280 }
281
282 if (dispX >= 0 && dispX < m_terrainData.SizeX && dispY >= 0 && dispY < m_terrainData.SizeY)
283 {
284 m_terrainData[dispX, dispY] = (float)newTerrain[xx, yy];
285 }
286 }
287 }
288 }
289 }
290
291 #endregion
292
293 public TerrainChannel Copy()
294 {
295 TerrainChannel copy = new TerrainChannel();
296 copy.m_terrainData = m_terrainData.Clone();
297 return copy;
298 }
299
300 private void WriteXml(XmlWriter writer)
301 {
302 if (Width == Constants.RegionSize && Height == Constants.RegionSize)
303 {
304 // Downward compatibility for legacy region terrain maps.
305 // If region is exactly legacy size, return the old format XML.
306 writer.WriteStartElement(String.Empty, "TerrainMap", String.Empty);
307 ToXml(writer);
308 writer.WriteEndElement();
309 }
310 else
311 {
312 // New format XML that includes width and length.
313 writer.WriteStartElement(String.Empty, "TerrainMap2", String.Empty);
314 ToXml2(writer);
315 writer.WriteEndElement();
316 }
317 }
318
202 private void ReadXml(XmlReader reader) 319 private void ReadXml(XmlReader reader)
203 { 320 {
204 reader.ReadStartElement("TerrainMap"); 321 // Check the first element. If legacy element, use the legacy reader.
205 FromXml(reader); 322 if (reader.IsStartElement("TerrainMap"))
323 {
324 reader.ReadStartElement("TerrainMap");
325 FromXml(reader);
326 }
327 else
328 {
329 reader.ReadStartElement("TerrainMap2");
330 FromXml2(reader);
331 }
206 } 332 }
207 333
334 // Write legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
208 private void ToXml(XmlWriter xmlWriter) 335 private void ToXml(XmlWriter xmlWriter)
209 { 336 {
210 float[] mapData = GetFloatsSerialised(); 337 float[] mapData = GetFloatsSerialised();
@@ -218,12 +345,15 @@ namespace OpenSim.Region.Framework.Scenes
218 serializer.Serialize(xmlWriter, buffer); 345 serializer.Serialize(xmlWriter, buffer);
219 } 346 }
220 347
348 // Read legacy terrain map. Presumed to be 256x256 of data encoded as floats in a byte array.
221 private void FromXml(XmlReader xmlReader) 349 private void FromXml(XmlReader xmlReader)
222 { 350 {
223 XmlSerializer serializer = new XmlSerializer(typeof(byte[])); 351 XmlSerializer serializer = new XmlSerializer(typeof(byte[]));
224 byte[] dataArray = (byte[])serializer.Deserialize(xmlReader); 352 byte[] dataArray = (byte[])serializer.Deserialize(xmlReader);
225 int index = 0; 353 int index = 0;
226 354
355 m_terrainData = new HeightmapTerrainData(Height, Width, (int)Constants.RegionHeight);
356
227 for (int y = 0; y < Height; y++) 357 for (int y = 0; y < Height; y++)
228 { 358 {
229 for (int x = 0; x < Width; x++) 359 for (int x = 0; x < Width; x++)
@@ -236,35 +366,63 @@ namespace OpenSim.Region.Framework.Scenes
236 } 366 }
237 } 367 }
238 368
369 private class TerrainChannelXMLPackage
370 {
371 public int Version;
372 public int SizeX;
373 public int SizeY;
374 public int SizeZ;
375 public float CompressionFactor;
376 public short[] Map;
377 public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, short[] pMap)
378 {
379 Version = 1;
380 SizeX = pX;
381 SizeY = pY;
382 SizeZ = pZ;
383 CompressionFactor = pCompressionFactor;
384 Map = pMap;
385 }
386 }
387
388 // New terrain serialization format that includes the width and length.
389 private void ToXml2(XmlWriter xmlWriter)
390 {
391 TerrainChannelXMLPackage package = new TerrainChannelXMLPackage(Width, Height, Altitude, m_terrainData.CompressionFactor,
392 m_terrainData.GetCompressedMap());
393 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
394 serializer.Serialize(xmlWriter, package);
395 }
396
397 // New terrain serialization format that includes the width and length.
398 private void FromXml2(XmlReader xmlReader)
399 {
400 XmlSerializer serializer = new XmlSerializer(typeof(TerrainChannelXMLPackage));
401 TerrainChannelXMLPackage package = (TerrainChannelXMLPackage)serializer.Deserialize(xmlReader);
402 m_terrainData = new HeightmapTerrainData(package.Map, package.CompressionFactor, package.SizeX, package.SizeY, package.SizeZ);
403 }
404
405 // Fill the heightmap with the center bump terrain
239 private void PinHeadIsland() 406 private void PinHeadIsland()
240 { 407 {
241 int x; 408 for (int x = 0; x < Width; x++)
242 for (x = 0; x < Constants.RegionSize; x++)
243 { 409 {
244 int y; 410 for (int y = 0; y < Height; y++)
245 for (y = 0; y < Constants.RegionSize; y++)
246 { 411 {
247 map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10; 412 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; 413 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; 414 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) 415 if (m_terrainData[x, y]< spherFacA)
251 map[x, y] = spherFacA; 416 m_terrainData[x, y]= spherFacA;
252 if (map[x, y] < spherFacB) 417 if (m_terrainData[x, y]< spherFacB)
253 map[x, y] = spherFacB; 418 m_terrainData[x, y] = spherFacB;
254 } 419 }
255 } 420 }
256 } 421 }
257 422
258 private void FlatLand() 423 private void FlatLand()
259 { 424 {
260 int x; 425 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 } 426 }
268
269 } 427 }
270} 428}
diff --git a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
new file mode 100644
index 0000000..bdb748a
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
@@ -0,0 +1,942 @@
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 landPacketType = (byte)TerrainPatch.LayerType.LandExtended;
123 }
124
125 return CreateLandPacket(terrData, xPieces, yPieces, landPacketType);
126 }
127
128 /// <summary>
129 /// Creates a LayerData packet for compressed land data given a full
130 /// simulator heightmap and an array of indices of patches to compress
131 /// </summary>
132 /// <param name="terrData">
133 /// Terrain data that can result in a meter square heightmap.
134 /// </param>
135 /// <param name="x">
136 /// Array of indexes in the grid of patches
137 /// for this simulator.
138 /// If creating a packet for multiple patches, there will be entries in
139 /// both the X and Y arrays for each of the patches.
140 /// For example if patches 1 and 17 are to be sent,
141 /// x[] = {1,1} and y[] = {0,1} which specifies the patches at
142 /// indexes <1,0> and <1,1> (presuming the terrain size is 16x16 patches).
143 /// </param>
144 /// <param name="y">
145 /// Array of indexes in the grid of patches.
146 /// </param>
147 /// <param name="type"></param>
148 /// <param name="pRegionSizeX"></param>
149 /// <param name="pRegionSizeY"></param>
150 /// <returns></returns>
151 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] x, int[] y, byte type)
152 {
153 LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}};
154
155 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
156 {Stride = STRIDE, PatchSize = Constants.TerrainPatchSize};
157
158 byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
159 BitPack bitpack = new BitPack(data, 0);
160 bitpack.PackBits(header.Stride, 16);
161 bitpack.PackBits(header.PatchSize, 8);
162 bitpack.PackBits(type, 8);
163
164 for (int i = 0; i < x.Length; i++)
165 CreatePatchFromHeightmap(bitpack, terrData, x[i], y[i]);
166
167 bitpack.PackBits(END_OF_PATCHES, 8);
168
169 layer.LayerData.Data = new byte[bitpack.BytePos + 1];
170 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
171
172 return layer;
173 }
174
175 // Unused: left for historical reference.
176 public static void CreatePatch(BitPack output, float[] patchData, int x, int y, int pRegionSizeX, int pRegionSizeY)
177 {
178 TerrainPatch.Header header = PrescanPatch(patchData);
179 header.QuantWBits = 136;
180 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize)
181 {
182 header.PatchIDs = (y & 0xFFFF);
183 header.PatchIDs += (x << 16);
184 }
185 else
186 {
187 header.PatchIDs = (y & 0x1F);
188 header.PatchIDs += (x << 5);
189 }
190
191 // NOTE: No idea what prequant and postquant should be or what they do
192
193 int wbits;
194 int[] patch = CompressPatch(patchData, header, 10, out wbits);
195 wbits = EncodePatchHeader(output, header, patch, (uint)pRegionSizeX, (uint)pRegionSizeY, wbits);
196 EncodePatch(output, patch, 0, wbits);
197 }
198
199 /// <summary>
200 /// Add a patch of terrain to a BitPacker
201 /// </summary>
202 /// <param name="output">BitPacker to write the patch to</param>
203 /// <param name="heightmap">
204 /// Heightmap of the simulator. Presumed to be an sizeX*sizeY array.
205 /// </param>
206 /// <param name="patchX">
207 /// X offset of the patch to create.
208 /// </param>
209 /// <param name="patchY">
210 /// Y offset of the patch to create.
211 /// </param>
212 /// <param name="pRegionSizeX"></param>
213 /// <param name="pRegionSizeY"></param>
214 public static void CreatePatchFromHeightmap(BitPack output, TerrainData terrData, int patchX, int patchY)
215 {
216 TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY);
217 header.QuantWBits = 136;
218
219 // If larger than legacy region size, pack patch X and Y info differently.
220 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
221 {
222 header.PatchIDs = (patchY & 0xFFFF);
223 header.PatchIDs += (patchX << 16);
224 }
225 else
226 {
227 header.PatchIDs = (patchY & 0x1F);
228 header.PatchIDs += (patchX << 5);
229 }
230
231 // m_log.DebugFormat("{0} CreatePatchFromHeightmap. patchX={1}, patchY={2}, DCOffset={3}, range={4}",
232 // LogHeader, patchX, patchY, header.DCOffset, header.Range);
233
234 // NOTE: No idea what prequant and postquant should be or what they do
235 int wbits;
236 int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
237 wbits = EncodePatchHeader(output, header, patch, (uint)terrData.SizeX, (uint)terrData.SizeY, wbits);
238 EncodePatch(output, patch, 0, wbits);
239 }
240
241 private static TerrainPatch.Header PrescanPatch(float[] patch)
242 {
243 TerrainPatch.Header header = new TerrainPatch.Header();
244 float zmax = -99999999.0f;
245 float zmin = 99999999.0f;
246
247 for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++)
248 {
249 float val = patch[i];
250 if (val > zmax) zmax = val;
251 if (val < zmin) zmin = val;
252 }
253
254 header.DCOffset = zmin;
255 header.Range = (int) ((zmax - zmin) + 1.0f);
256
257 return header;
258 }
259
260 // Scan the height info we're returning and return a patch packet header for this patch.
261 private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY)
262 {
263 TerrainPatch.Header header = new TerrainPatch.Header();
264 float zmax = -99999999.0f;
265 float zmin = 99999999.0f;
266
267 for (int j = patchY*Constants.TerrainPatchSize; j < (patchY + 1)*Constants.TerrainPatchSize; j++)
268 {
269 for (int i = patchX*Constants.TerrainPatchSize; i < (patchX + 1)*Constants.TerrainPatchSize; i++)
270 {
271 float val = terrData[i, j];
272 if (val > zmax) zmax = val;
273 if (val < zmin) zmin = val;
274 }
275 }
276
277 header.DCOffset = zmin;
278 header.Range = (int)(zmax - zmin + 1.0f);
279
280 return header;
281 }
282
283 public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
284 {
285 TerrainPatch.Header header = new TerrainPatch.Header {QuantWBits = bitpack.UnpackBits(8)};
286
287 // Quantized word bits
288 if (header.QuantWBits == END_OF_PATCHES)
289 return header;
290
291 // DC offset
292 header.DCOffset = bitpack.UnpackFloat();
293
294 // Range
295 header.Range = bitpack.UnpackBits(16);
296
297 // Patch IDs (10 bits)
298 header.PatchIDs = bitpack.UnpackBits(10);
299
300 // Word bits
301 header.WordBits = (uint) ((header.QuantWBits & 0x0f) + 2);
302
303 return header;
304 }
305
306 private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, uint pRegionSizeX,
307 uint pRegionSizeY, int wbits)
308 {
309 /*
310 int temp;
311 int wbits = (header.QuantWBits & 0x0f) + 2;
312 uint maxWbits = (uint)wbits + 5;
313 uint minWbits = ((uint)wbits >> 1);
314 int wbitsMaxValue;
315 */
316 // goal is to determ minimum number of bits to use so all data fits
317 /*
318 wbits = (int)minWbits;
319 wbitsMaxValue = (1 << wbits);
320
321 for (int i = 0; i < patch.Length; i++)
322 {
323 temp = patch[i];
324 if (temp != 0)
325 {
326 // Get the absolute value
327 if (temp < 0) temp *= -1;
328
329 no coments..
330
331 for (int j = (int)maxWbits; j > (int)minWbits; j--)
332 {
333 if ((temp & (1 << j)) != 0)
334 {
335 if (j > wbits) wbits = j;
336 break;
337 }
338 }
339
340 while (temp > wbitsMaxValue)
341 {
342 wbits++;
343 if (wbits == maxWbits)
344 goto Done;
345 wbitsMaxValue = 1 << wbits;
346 }
347 }
348 }
349
350 Done:
351
352 // wbits += 1;
353 */
354 // better check
355 if (wbits > 17)
356 wbits = 16;
357 else if (wbits < 3)
358 wbits = 3;
359
360 header.QuantWBits &= 0xf0;
361
362 header.QuantWBits |= (wbits - 2);
363
364 output.PackBits(header.QuantWBits, 8);
365 output.PackFloat(header.DCOffset);
366 output.PackBits(header.Range, 16);
367 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize)
368 output.PackBits(header.PatchIDs, 32);
369 else
370 output.PackBits(header.PatchIDs, 10);
371
372 return wbits;
373 }
374
375 private static void IDCTColumn16(float[] linein, float[] lineout, int column)
376 {
377 for (int n = 0; n < Constants.TerrainPatchSize; n++)
378 {
379 float total = OO_SQRT2*linein[column];
380
381 for (int u = 1; u < Constants.TerrainPatchSize; u++)
382 {
383 int usize = u*Constants.TerrainPatchSize;
384 total += linein[usize + column]*CosineTable16[usize + n];
385 }
386
387 lineout[Constants.TerrainPatchSize*n + column] = total;
388 }
389 }
390
391 private static void IDCTLine16(float[] linein, float[] lineout, int line)
392 {
393 const float oosob = 2.0f/Constants.TerrainPatchSize;
394 int lineSize = line*Constants.TerrainPatchSize;
395
396 for (int n = 0; n < Constants.TerrainPatchSize; n++)
397 {
398 float total = OO_SQRT2*linein[lineSize];
399
400 for (int u = 1; u < Constants.TerrainPatchSize; u++)
401 {
402 total += linein[lineSize + u]*CosineTable16[u*Constants.TerrainPatchSize + n];
403 }
404
405 lineout[lineSize + n] = total*oosob;
406 }
407 }
408
409/*
410 private static void DCTLine16(float[] linein, float[] lineout, int line)
411 {
412 float total = 0.0f;
413 int lineSize = line * Constants.TerrainPatchSize;
414
415 for (int n = 0; n < Constants.TerrainPatchSize; n++)
416 {
417 total += linein[lineSize + n];
418 }
419
420 lineout[lineSize] = OO_SQRT2 * total;
421
422 int uptr = 0;
423 for (int u = 1; u < Constants.TerrainPatchSize; u++)
424 {
425 total = 0.0f;
426 uptr += Constants.TerrainPatchSize;
427
428 for (int n = 0; n < Constants.TerrainPatchSize; n++)
429 {
430 total += linein[lineSize + n] * CosineTable16[uptr + n];
431 }
432
433 lineout[lineSize + u] = total;
434 }
435 }
436*/
437
438 private static void DCTLine16(float[] linein, float[] lineout, int line)
439 {
440 // outputs transpose data (lines exchanged with coluns )
441 // so to save a bit of cpu when doing coluns
442 float total = 0.0f;
443 int lineSize = line*Constants.TerrainPatchSize;
444
445 for (int n = 0; n < Constants.TerrainPatchSize; n++)
446 {
447 total += linein[lineSize + n];
448 }
449
450 lineout[line] = OO_SQRT2*total;
451
452 for (int u = Constants.TerrainPatchSize;
453 u < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
454 u += Constants.TerrainPatchSize)
455 {
456 total = 0.0f;
457 for (int ptrn = lineSize, ptru = u; ptrn < lineSize + Constants.TerrainPatchSize; ptrn++,ptru++)
458 {
459 total += linein[ptrn]*CosineTable16[ptru];
460 }
461
462 lineout[line + u] = total;
463 }
464 }
465
466
467 /*
468 private static void DCTColumn16(float[] linein, int[] lineout, int column)
469 {
470 float total = 0.0f;
471 // const float oosob = 2.0f / Constants.TerrainPatchSize;
472
473 for (int n = 0; n < Constants.TerrainPatchSize; n++)
474 {
475 total += linein[Constants.TerrainPatchSize * n + column];
476 }
477
478 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
479 lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * QuantizeTable16[column]);
480
481 for (int uptr = Constants.TerrainPatchSize; uptr < Constants.TerrainPatchSize * Constants.TerrainPatchSize; uptr += Constants.TerrainPatchSize)
482 {
483 total = 0.0f;
484
485 for (int n = 0; n < Constants.TerrainPatchSize; n++)
486 {
487 total += linein[Constants.TerrainPatchSize * n + column] * CosineTable16[uptr + n];
488 }
489
490 // lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]);
491 lineout[CopyMatrix16[uptr + column]] = (int)(total * QuantizeTable16[uptr + column]);
492 }
493 }
494 */
495
496 private static void DCTColumn16(float[] linein, int[] lineout, int column)
497 {
498 // input columns are in fact stored in lines now
499
500 float total = 0.0f;
501// const float oosob = 2.0f / Constants.TerrainPatchSize;
502 int inlinesptr = Constants.TerrainPatchSize*column;
503
504 for (int n = 0; n < Constants.TerrainPatchSize; n++)
505 {
506 total += linein[inlinesptr + n];
507 }
508
509 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
510 lineout[CopyMatrix16[column]] = (int) (OO_SQRT2*total*QuantizeTable16[column]);
511
512 for (int uptr = Constants.TerrainPatchSize;
513 uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
514 uptr += Constants.TerrainPatchSize)
515 {
516 total = 0.0f;
517
518 for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++)
519 {
520 total += linein[n]*CosineTable16[ptru];
521 }
522
523// lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]);
524 lineout[CopyMatrix16[uptr + column]] = (int) (total*QuantizeTable16[uptr + column]);
525 }
526 }
527
528 private static int DCTColumn16Wbits(float[] linein, int[] lineout, int column, int wbits, int maxwbits)
529 {
530 // input columns are in fact stored in lines now
531
532 bool dowbits = wbits != maxwbits;
533 int wbitsMaxValue = 1 << wbits;
534
535 float total = 0.0f;
536 // const float oosob = 2.0f / Constants.TerrainPatchSize;
537 int inlinesptr = Constants.TerrainPatchSize*column;
538
539 for (int n = 0; n < Constants.TerrainPatchSize; n++)
540 {
541 total += linein[inlinesptr + n];
542 }
543
544 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
545 int tmp = (int) (OO_SQRT2*total*QuantizeTable16[column]);
546 lineout[CopyMatrix16[column]] = tmp;
547
548 if (dowbits)
549 {
550 if (tmp < 0) tmp *= -1;
551 while (tmp > wbitsMaxValue)
552 {
553 wbits++;
554 wbitsMaxValue = 1 << wbits;
555 if (wbits == maxwbits)
556 {
557 dowbits = false;
558 break;
559 }
560 }
561 }
562
563 for (int uptr = Constants.TerrainPatchSize;
564 uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
565 uptr += Constants.TerrainPatchSize)
566 {
567 total = 0.0f;
568
569 for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++)
570 {
571 total += linein[n]*CosineTable16[ptru];
572 }
573
574 tmp = (int) (total*QuantizeTable16[uptr + column]);
575 lineout[CopyMatrix16[uptr + column]] = tmp;
576
577 if (dowbits)
578 {
579 if (tmp < 0) tmp *= -1;
580 while (tmp > wbitsMaxValue)
581 {
582 wbits++;
583 wbitsMaxValue = 1 << wbits;
584 if (wbits == maxwbits)
585 {
586 dowbits = false;
587 break;
588 }
589 }
590 }
591 }
592 return wbits;
593 }
594
595 public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size)
596 {
597 for (int n = 0; n < size*size; n++)
598 {
599 // ?
600 int temp = bitpack.UnpackBits(1);
601 if (temp != 0)
602 {
603 // Value or EOB
604 temp = bitpack.UnpackBits(1);
605 if (temp != 0)
606 {
607 // Value
608 temp = bitpack.UnpackBits(1);
609 if (temp != 0)
610 {
611 // Negative
612 temp = bitpack.UnpackBits((int) header.WordBits);
613 patches[n] = temp*-1;
614 }
615 else
616 {
617 // Positive
618 temp = bitpack.UnpackBits((int) header.WordBits);
619 patches[n] = temp;
620 }
621 }
622 else
623 {
624 // Set the rest to zero
625 // TODO: This might not be necessary
626 for (int o = n; o < size*size; o++)
627 {
628 patches[o] = 0;
629 }
630 break;
631 }
632 }
633 else
634 {
635 patches[n] = 0;
636 }
637 }
638 }
639
640 private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits)
641 {
642 int maxwbitssize = (1 << wbits) - 1;
643
644 if (postquant > Constants.TerrainPatchSize*Constants.TerrainPatchSize || postquant < 0)
645 {
646 Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
647 return;
648 }
649
650 if (postquant != 0) patch[Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant] = 0;
651
652 for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++)
653 {
654 int temp = patch[i];
655
656 if (temp == 0)
657 {
658 bool eob = true;
659
660 for (int j = i; j < Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant; j++)
661 {
662 if (patch[j] != 0)
663 {
664 eob = false;
665 break;
666 }
667 }
668
669 if (eob)
670 {
671 output.PackBits(ZERO_EOB, 2);
672 return;
673 }
674 output.PackBits(ZERO_CODE, 1);
675 }
676 else
677 {
678 if (temp < 0)
679 {
680 temp *= -1;
681
682 if (temp > maxwbitssize) temp = maxwbitssize;
683
684 output.PackBits(NEGATIVE_VALUE, 3);
685 output.PackBits(temp, wbits);
686 }
687 else
688 {
689 if (temp > maxwbitssize) temp = maxwbitssize;
690
691 output.PackBits(POSITIVE_VALUE, 3);
692 output.PackBits(temp, wbits);
693 }
694 }
695 }
696 }
697
698 public static float[] DecompressPatch(int[] patches, TerrainPatch.Header header, TerrainPatch.GroupHeader group)
699 {
700 float[] block = new float[group.PatchSize*group.PatchSize];
701 float[] output = new float[group.PatchSize*group.PatchSize];
702 int prequant = (header.QuantWBits >> 4) + 2;
703 int quantize = 1 << prequant;
704 float ooq = 1.0f/quantize;
705 float mult = ooq*header.Range;
706 float addval = mult*(1 << (prequant - 1)) + header.DCOffset;
707
708 if (group.PatchSize == Constants.TerrainPatchSize)
709 {
710 for (int n = 0; n < Constants.TerrainPatchSize*Constants.TerrainPatchSize; n++)
711 {
712 block[n] = patches[CopyMatrix16[n]]*DequantizeTable16[n];
713 }
714
715 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
716
717 for (int o = 0; o < Constants.TerrainPatchSize; o++)
718 IDCTColumn16(block, ftemp, o);
719 for (int o = 0; o < Constants.TerrainPatchSize; o++)
720 IDCTLine16(ftemp, block, o);
721 }
722 else
723 {
724 for (int n = 0; n < Constants.TerrainPatchSize*2*Constants.TerrainPatchSize*2; n++)
725 {
726 block[n] = patches[CopyMatrix32[n]]*DequantizeTable32[n];
727 }
728
729 Logger.Log("Implement IDCTPatchLarge", Helpers.LogLevel.Error);
730 }
731
732 for (int j = 0; j < block.Length; j++)
733 {
734 output[j] = block[j]*mult + addval;
735 }
736
737 return output;
738 }
739
740 private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
741 {
742 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
743 int wordsize = (prequant - 2) & 0x0f;
744 float oozrange = 1.0f/header.Range;
745 float range = (1 << prequant);
746 float premult = oozrange*range;
747 float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
748
749 header.QuantWBits = wordsize;
750 header.QuantWBits |= wordsize << 4;
751
752 int k = 0;
753 for (int j = 0; j < Constants.TerrainPatchSize; j++)
754 {
755 for (int i = 0; i < Constants.TerrainPatchSize; i++)
756 block[k++] = patchData[j*Constants.TerrainPatchSize + i]*premult - sub;
757 }
758
759 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
760 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
761
762
763 int maxWbits = prequant + 5;
764 wbits = (prequant >> 1);
765
766 for (int o = 0; o < Constants.TerrainPatchSize; o++)
767 DCTLine16(block, ftemp, o);
768 for (int o = 0; o < Constants.TerrainPatchSize; o++)
769 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
770
771 return itemp;
772 }
773
774 private static int[] CompressPatch(float[,] patchData, TerrainPatch.Header header, int prequant, out int wbits)
775 {
776 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
777 float oozrange = 1.0f/header.Range;
778 float range = (1 << prequant);
779 float premult = oozrange*range;
780 float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
781 int wordsize = (prequant - 2) & 0x0f;
782
783 header.QuantWBits = wordsize;
784 header.QuantWBits |= wordsize << 4;
785
786 int k = 0;
787 for (int j = 0; j < Constants.TerrainPatchSize; j++)
788 {
789 for (int i = 0; i < Constants.TerrainPatchSize; i++)
790 block[k++] = patchData[j, i]*premult - sub;
791 }
792
793 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
794 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
795
796 int maxWbits = prequant + 5;
797 wbits = (prequant >> 1);
798
799 for (int o = 0; o < Constants.TerrainPatchSize; o++)
800 DCTLine16(block, ftemp, o);
801 for (int o = 0; o < Constants.TerrainPatchSize; o++)
802 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
803
804 return itemp;
805 }
806
807 private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
808 int prequant, out int wbits)
809 {
810 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
811 int wordsize = prequant;
812 float oozrange = 1.0f/header.Range;
813 float range = (1 << prequant);
814 float premult = oozrange*range;
815 float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
816
817 header.QuantWBits = wordsize - 2;
818 header.QuantWBits |= (prequant - 2) << 4;
819
820 int k = 0;
821
822 int yPatchLimit = patchY >= (terrData.SizeY / Constants.TerrainPatchSize) ?
823 (terrData.SizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchY;
824 yPatchLimit = (yPatchLimit + 1) * Constants.TerrainPatchSize;
825
826 int xPatchLimit = patchX >= (terrData.SizeX / Constants.TerrainPatchSize) ?
827 (terrData.SizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchX;
828 xPatchLimit = (xPatchLimit + 1) * Constants.TerrainPatchSize;
829
830 for (int yy = patchY * Constants.TerrainPatchSize; yy < yPatchLimit; yy++)
831 {
832 for (int xx = patchX * Constants.TerrainPatchSize; xx < xPatchLimit; xx++)
833 {
834 block[k++] = terrData[xx, yy] * premult - sub;
835 }
836 }
837
838 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
839 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
840
841 int maxWbits = prequant + 5;
842 wbits = (prequant >> 1);
843
844 for (int o = 0; o < Constants.TerrainPatchSize; o++)
845 DCTLine16(block, ftemp, o);
846 for (int o = 0; o < Constants.TerrainPatchSize; o++)
847 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
848
849 return itemp;
850 }
851
852 #region Initialization
853
854 private static void BuildDequantizeTable16()
855 {
856 for (int j = 0; j < Constants.TerrainPatchSize; j++)
857 {
858 for (int i = 0; i < Constants.TerrainPatchSize; i++)
859 {
860 DequantizeTable16[j*Constants.TerrainPatchSize + i] = 1.0f + 2.0f*(i + j);
861 }
862 }
863 }
864
865 private static void BuildQuantizeTable16()
866 {
867 const float oosob = 2.0f/Constants.TerrainPatchSize;
868 for (int j = 0; j < Constants.TerrainPatchSize; j++)
869 {
870 for (int i = 0; i < Constants.TerrainPatchSize; i++)
871 {
872// QuantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f / (1.0f + 2.0f * ((float)i + (float)j));
873 QuantizeTable16[j*Constants.TerrainPatchSize + i] = oosob/(1.0f + 2.0f*(i + (float) j));
874 }
875 }
876 }
877
878 private static void SetupCosines16()
879 {
880 const float hposz = (float) Math.PI*0.5f/Constants.TerrainPatchSize;
881
882 for (int u = 0; u < Constants.TerrainPatchSize; u++)
883 {
884 for (int n = 0; n < Constants.TerrainPatchSize; n++)
885 {
886 CosineTable16[u*Constants.TerrainPatchSize + n] = (float) Math.Cos((2.0f*n + 1.0f)*u*hposz);
887 }
888 }
889 }
890
891 private static void BuildCopyMatrix16()
892 {
893 bool diag = false;
894 bool right = true;
895 int i = 0;
896 int j = 0;
897 int count = 0;
898
899 while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
900 {
901 CopyMatrix16[j*Constants.TerrainPatchSize + i] = count++;
902
903 if (!diag)
904 {
905 if (right)
906 {
907 if (i < Constants.TerrainPatchSize - 1) i++;
908 else j++;
909
910 right = false;
911 diag = true;
912 }
913 else
914 {
915 if (j < Constants.TerrainPatchSize - 1) j++;
916 else i++;
917
918 right = true;
919 diag = true;
920 }
921 }
922 else
923 {
924 if (right)
925 {
926 i++;
927 j--;
928 if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false;
929 }
930 else
931 {
932 i--;
933 j++;
934 if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false;
935 }
936 }
937 }
938 }
939
940 #endregion Initialization
941 }
942}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
index acaeb90..0911f00 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
@@ -111,15 +111,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
111 111
112 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; 112 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
113 113
114 // We need to preserve this here because phys actor is removed by the sit.
115 Vector3 spPhysActorSize = m_sp.PhysicsActor.Size;
114 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); 116 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
115 117
116 // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the
117 // default avatar.
118 // Curiously, Vector3.ToString() will not display the last two places of the float. For example,
119 // printing out npc.AbsolutePosition will give <0, 0, 0.8454993> not <0, 0, 0.845499337>
120 Assert.That( 118 Assert.That(
121 m_sp.AbsolutePosition, 119 m_sp.AbsolutePosition,
122 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, 0.845499337f))); 120 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, spPhysActorSize.Z / 2)));
123 121
124 m_sp.StandUp(); 122 m_sp.StandUp();
125 123
@@ -147,9 +145,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
147 145
148 Assert.That(part.SitTargetAvatar, Is.EqualTo(m_sp.UUID)); 146 Assert.That(part.SitTargetAvatar, Is.EqualTo(m_sp.UUID));
149 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId)); 147 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId));
150 Assert.That( 148// Assert.That(
151 m_sp.AbsolutePosition, 149// m_sp.AbsolutePosition,
152 Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); 150// Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT));
153 Assert.That(m_sp.PhysicsActor, Is.Null); 151 Assert.That(m_sp.PhysicsActor, Is.Null);
154 152
155 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1)); 153 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1));
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index dd27294..1e59e3f 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -62,8 +62,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero); 62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero);
63 m_assetService.Store(corruptAsset); 63 m_assetService.Store(corruptAsset);
64 64
65 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 65 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, AssetType.Object, foundAssetUuids); 66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
67 67
68 // We count the uuid as gathered even if the asset itself is corrupt. 68 // We count the uuid as gathered even if the asset itself is corrupt.
69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -78,9 +78,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
78 TestHelpers.InMethod(); 78 TestHelpers.InMethod();
79 79
80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); 80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666");
81 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 81 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
82 82
83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, AssetType.Object, foundAssetUuids); 83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
84 84
85 // We count the uuid as gathered even if the asset itself is missing. 85 // We count the uuid as gathered even if the asset itself is missing.
86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -103,8 +103,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString()); 103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString());
104 m_assetService.Store(ncAsset); 104 m_assetService.Store(ncAsset);
105 105
106 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 106 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
107 m_uuidGatherer.GatherAssetUuids(ncAssetId, AssetType.Notecard, foundAssetUuids); 107 m_uuidGatherer.GatherAssetUuids(ncAssetId, (sbyte)AssetType.Notecard, foundAssetUuids);
108 108
109 // We count the uuid as gathered even if the asset itself is corrupt. 109 // We count the uuid as gathered even if the asset itself is corrupt.
110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2)); 110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2));
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 3e074b9..fe6cb84 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -38,6 +38,7 @@ using OpenMetaverse.StructuredData;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Region.Framework.Scenes.Serialization; 39using OpenSim.Region.Framework.Scenes.Serialization;
40using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
41using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
41 42
42namespace OpenSim.Region.Framework.Scenes 43namespace OpenSim.Region.Framework.Scenes
43{ 44{
@@ -83,7 +84,7 @@ namespace OpenSim.Region.Framework.Scenes
83 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> 84 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param>
84 /// <param name="assetType">The type of the asset for the uuid given</param> 85 /// <param name="assetType">The type of the asset for the uuid given</param>
85 /// <param name="assetUuids">The assets gathered</param> 86 /// <param name="assetUuids">The assets gathered</param>
86 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 87 public void GatherAssetUuids(UUID assetUuid, sbyte assetType, IDictionary<UUID, sbyte> assetUuids)
87 { 88 {
88 // avoid infinite loops 89 // avoid infinite loops
89 if (assetUuids.ContainsKey(assetUuid)) 90 if (assetUuids.ContainsKey(assetUuid))
@@ -93,23 +94,27 @@ namespace OpenSim.Region.Framework.Scenes
93 { 94 {
94 assetUuids[assetUuid] = assetType; 95 assetUuids[assetUuid] = assetType;
95 96
96 if (AssetType.Bodypart == assetType || AssetType.Clothing == assetType) 97 if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType)
97 { 98 {
98 GetWearableAssetUuids(assetUuid, assetUuids); 99 GetWearableAssetUuids(assetUuid, assetUuids);
99 } 100 }
100 else if (AssetType.Gesture == assetType) 101 else if ((sbyte)AssetType.Gesture == assetType)
101 { 102 {
102 GetGestureAssetUuids(assetUuid, assetUuids); 103 GetGestureAssetUuids(assetUuid, assetUuids);
103 } 104 }
104 else if (AssetType.Notecard == assetType) 105 else if ((sbyte)AssetType.Notecard == assetType)
105 { 106 {
106 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 107 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
107 } 108 }
108 else if (AssetType.LSLText == assetType) 109 else if ((sbyte)AssetType.LSLText == assetType)
109 { 110 {
110 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 111 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
111 } 112 }
112 else if (AssetType.Object == assetType) 113 else if ((sbyte)OpenSimAssetType.Material == assetType)
114 {
115 GetMaterialAssetUuids(assetUuid, assetUuids);
116 }
117 else if ((sbyte)AssetType.Object == assetType)
113 { 118 {
114 GetSceneObjectAssetUuids(assetUuid, assetUuids); 119 GetSceneObjectAssetUuids(assetUuid, assetUuids);
115 } 120 }
@@ -136,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes
136 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset. 141 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset.
137 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown. 142 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown.
138 /// </param> 143 /// </param>
139 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids) 144 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, sbyte> assetUuids)
140 { 145 {
141// m_log.DebugFormat( 146// m_log.DebugFormat(
142// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); 147// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
@@ -156,7 +161,7 @@ namespace OpenSim.Region.Framework.Scenes
156 { 161 {
157 // Get the prim's default texture. This will be used for faces which don't have their own texture 162 // Get the prim's default texture. This will be used for faces which don't have their own texture
158 if (textureEntry.DefaultTexture != null) 163 if (textureEntry.DefaultTexture != null)
159 assetUuids[textureEntry.DefaultTexture.TextureID] = AssetType.Texture; 164 GatherTextureEntryAssets(textureEntry.DefaultTexture, assetUuids);
160 165
161 if (textureEntry.FaceTextures != null) 166 if (textureEntry.FaceTextures != null)
162 { 167 {
@@ -164,20 +169,20 @@ namespace OpenSim.Region.Framework.Scenes
164 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) 169 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
165 { 170 {
166 if (texture != null) 171 if (texture != null)
167 assetUuids[texture.TextureID] = AssetType.Texture; 172 GatherTextureEntryAssets(texture, assetUuids);
168 } 173 }
169 } 174 }
170 } 175 }
171 176
172 // If the prim is a sculpt then preserve this information too 177 // If the prim is a sculpt then preserve this information too
173 if (part.Shape.SculptTexture != UUID.Zero) 178 if (part.Shape.SculptTexture != UUID.Zero)
174 assetUuids[part.Shape.SculptTexture] = AssetType.Texture; 179 assetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture;
175 180
176 if (part.Shape.ProjectionTextureUUID != UUID.Zero) 181 if (part.Shape.ProjectionTextureUUID != UUID.Zero)
177 assetUuids[part.Shape.ProjectionTextureUUID] = AssetType.Texture; 182 assetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture;
178 183
179 if (part.CollisionSound != UUID.Zero) 184 if (part.CollisionSound != UUID.Zero)
180 assetUuids[part.CollisionSound] = AssetType.Sound; 185 assetUuids[part.CollisionSound] = (sbyte)AssetType.Sound;
181 186
182 if (part.ParticleSystem.Length > 0) 187 if (part.ParticleSystem.Length > 0)
183 { 188 {
@@ -185,7 +190,7 @@ namespace OpenSim.Region.Framework.Scenes
185 { 190 {
186 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); 191 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
187 if (ps.Texture != UUID.Zero) 192 if (ps.Texture != UUID.Zero)
188 assetUuids[ps.Texture] = AssetType.Texture; 193 assetUuids[ps.Texture] = (sbyte)AssetType.Texture;
189 } 194 }
190 catch (Exception e) 195 catch (Exception e)
191 { 196 {
@@ -205,7 +210,7 @@ namespace OpenSim.Region.Framework.Scenes
205// tii.Name, tii.Type, part.Name, part.UUID); 210// tii.Name, tii.Type, part.Name, part.UUID);
206 211
207 if (!assetUuids.ContainsKey(tii.AssetID)) 212 if (!assetUuids.ContainsKey(tii.AssetID))
208 GatherAssetUuids(tii.AssetID, (AssetType)tii.Type, assetUuids); 213 GatherAssetUuids(tii.AssetID, (sbyte)tii.Type, assetUuids);
209 } 214 }
210 215
211 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed 216 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
@@ -214,7 +219,9 @@ namespace OpenSim.Region.Framework.Scenes
214 // Scene.EventManager is present. 219 // Scene.EventManager is present.
215// part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids); 220// part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
216 221
217 GatherMaterialsUuids(part, assetUuids); 222
223 // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs
224 GatherMaterialsUuids(part, assetUuids);
218 } 225 }
219 catch (Exception e) 226 catch (Exception e)
220 { 227 {
@@ -225,7 +232,20 @@ namespace OpenSim.Region.Framework.Scenes
225 } 232 }
226 } 233 }
227 } 234 }
228 235
236 /// <summary>
237 /// Gather all the asset uuids found in one face of a Texture Entry.
238 /// </summary>
239 private void GatherTextureEntryAssets(Primitive.TextureEntryFace texture, IDictionary<UUID, sbyte> assetUuids)
240 {
241 assetUuids[texture.TextureID] = (sbyte)AssetType.Texture;
242
243 if (texture.MaterialID != UUID.Zero)
244 {
245 GatherAssetUuids(texture.MaterialID, (sbyte)OpenSimAssetType.Material, assetUuids);
246 }
247 }
248
229// /// <summary> 249// /// <summary>
230// /// The callback made when we request the asset for an object from the asset service. 250// /// The callback made when we request the asset for an object from the asset service.
231// /// </summary> 251// /// </summary>
@@ -241,10 +261,12 @@ namespace OpenSim.Region.Framework.Scenes
241 261
242 /// <summary> 262 /// <summary>
243 /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps 263 /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
264 /// stored in legacy format in part.DynAttrs
244 /// </summary> 265 /// </summary>
245 /// <param name="part"></param> 266 /// <param name="part"></param>
246 /// <param name="assetUuids"></param> 267 /// <param name="assetUuids"></param>
247 public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids) 268 //public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
269 public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, sbyte> assetUuids)
248 { 270 {
249 // scan thru the dynAttrs map of this part for any textures used as materials 271 // scan thru the dynAttrs map of this part for any textures used as materials
250 OSD osdMaterials = null; 272 OSD osdMaterials = null;
@@ -280,7 +302,7 @@ namespace OpenSim.Region.Framework.Scenes
280 UUID normalMapId = mat["NormMap"].AsUUID(); 302 UUID normalMapId = mat["NormMap"].AsUUID();
281 if (normalMapId != UUID.Zero) 303 if (normalMapId != UUID.Zero)
282 { 304 {
283 assetUuids[normalMapId] = AssetType.Texture; 305 assetUuids[normalMapId] = (sbyte)AssetType.Texture;
284 //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString()); 306 //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
285 } 307 }
286 } 308 }
@@ -289,7 +311,7 @@ namespace OpenSim.Region.Framework.Scenes
289 UUID specularMapId = mat["SpecMap"].AsUUID(); 311 UUID specularMapId = mat["SpecMap"].AsUUID();
290 if (specularMapId != UUID.Zero) 312 if (specularMapId != UUID.Zero)
291 { 313 {
292 assetUuids[specularMapId] = AssetType.Texture; 314 assetUuids[specularMapId] = (sbyte)AssetType.Texture;
293 //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString()); 315 //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
294 } 316 }
295 } 317 }
@@ -344,7 +366,7 @@ namespace OpenSim.Region.Framework.Scenes
344 /// </summary> 366 /// </summary>
345 /// <param name="scriptUuid"></param> 367 /// <param name="scriptUuid"></param>
346 /// <param name="assetUuids">Dictionary in which to record the references</param> 368 /// <param name="assetUuids">Dictionary in which to record the references</param>
347 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, AssetType> assetUuids) 369 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, sbyte> assetUuids)
348 { 370 {
349// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); 371// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId);
350 372
@@ -364,7 +386,7 @@ namespace OpenSim.Region.Framework.Scenes
364 386
365 // Embedded asset references (if not false positives) could be for many types of asset, so we will 387 // Embedded asset references (if not false positives) could be for many types of asset, so we will
366 // label these as unknown. 388 // label these as unknown.
367 assetUuids[uuid] = AssetType.Unknown; 389 assetUuids[uuid] = (sbyte)AssetType.Unknown;
368 } 390 }
369 } 391 }
370 } 392 }
@@ -374,7 +396,7 @@ namespace OpenSim.Region.Framework.Scenes
374 /// </summary> 396 /// </summary>
375 /// <param name="wearableAssetUuid"></param> 397 /// <param name="wearableAssetUuid"></param>
376 /// <param name="assetUuids">Dictionary in which to record the references</param> 398 /// <param name="assetUuids">Dictionary in which to record the references</param>
377 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, AssetType> assetUuids) 399 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, sbyte> assetUuids)
378 { 400 {
379 AssetBase assetBase = GetAsset(wearableAssetUuid); 401 AssetBase assetBase = GetAsset(wearableAssetUuid);
380 402
@@ -389,7 +411,7 @@ namespace OpenSim.Region.Framework.Scenes
389 411
390 foreach (UUID uuid in wearableAsset.Textures.Values) 412 foreach (UUID uuid in wearableAsset.Textures.Values)
391 { 413 {
392 assetUuids[uuid] = AssetType.Texture; 414 assetUuids[uuid] = (sbyte)AssetType.Texture;
393 } 415 }
394 } 416 }
395 } 417 }
@@ -401,7 +423,7 @@ namespace OpenSim.Region.Framework.Scenes
401 /// </summary> 423 /// </summary>
402 /// <param name="sceneObject"></param> 424 /// <param name="sceneObject"></param>
403 /// <param name="assetUuids"></param> 425 /// <param name="assetUuids"></param>
404 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, AssetType> assetUuids) 426 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, sbyte> assetUuids)
405 { 427 {
406 AssetBase objectAsset = GetAsset(sceneObjectUuid); 428 AssetBase objectAsset = GetAsset(sceneObjectUuid);
407 429
@@ -430,7 +452,7 @@ namespace OpenSim.Region.Framework.Scenes
430 /// </summary> 452 /// </summary>
431 /// <param name="gestureUuid"></param> 453 /// <param name="gestureUuid"></param>
432 /// <param name="assetUuids"></param> 454 /// <param name="assetUuids"></param>
433 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, AssetType> assetUuids) 455 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, sbyte> assetUuids)
434 { 456 {
435 AssetBase assetBase = GetAsset(gestureUuid); 457 AssetBase assetBase = GetAsset(gestureUuid);
436 if (null == assetBase) 458 if (null == assetBase)
@@ -464,9 +486,29 @@ namespace OpenSim.Region.Framework.Scenes
464 // If it can be parsed as a UUID, it is an asset ID 486 // If it can be parsed as a UUID, it is an asset ID
465 UUID uuid; 487 UUID uuid;
466 if (UUID.TryParse(id, out uuid)) 488 if (UUID.TryParse(id, out uuid))
467 assetUuids[uuid] = AssetType.Animation; 489 assetUuids[uuid] = (sbyte)AssetType.Animation;
468 } 490 }
469 } 491 }
492
493 /// <summary>
494 /// Get the asset uuid's referenced in a material.
495 /// </summary>
496 private void GetMaterialAssetUuids(UUID materialUuid, IDictionary<UUID, sbyte> assetUuids)
497 {
498 AssetBase assetBase = GetAsset(materialUuid);
499 if (null == assetBase)
500 return;
501
502 OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(assetBase.Data);
503
504 UUID normMap = mat["NormMap"].AsUUID();
505 if (normMap != UUID.Zero)
506 assetUuids[normMap] = (sbyte)AssetType.Texture;
507
508 UUID specMap = mat["SpecMap"].AsUUID();
509 if (specMap != UUID.Zero)
510 assetUuids[specMap] = (sbyte)AssetType.Texture;
511 }
470 } 512 }
471 513
472 public class HGUuidGatherer : UuidGatherer 514 public class HGUuidGatherer : UuidGatherer