diff options
Diffstat (limited to 'OpenSim')
36 files changed, 1125 insertions, 507 deletions
diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs index 16a63e0..dff956a 100644 --- a/OpenSim/Framework/Console/ConsoleUtil.cs +++ b/OpenSim/Framework/Console/ConsoleUtil.cs | |||
@@ -97,7 +97,7 @@ namespace OpenSim.Framework.Console | |||
97 | if (!UUID.TryParse(rawUuid, out uuid)) | 97 | if (!UUID.TryParse(rawUuid, out uuid)) |
98 | { | 98 | { |
99 | if (console != null) | 99 | if (console != null) |
100 | console.OutputFormat("{0} is not a valid uuid", rawUuid); | 100 | console.OutputFormat("ERROR: {0} is not a valid uuid", rawUuid); |
101 | 101 | ||
102 | return false; | 102 | return false; |
103 | } | 103 | } |
@@ -110,7 +110,7 @@ namespace OpenSim.Framework.Console | |||
110 | if (!uint.TryParse(rawLocalId, out localId)) | 110 | if (!uint.TryParse(rawLocalId, out localId)) |
111 | { | 111 | { |
112 | if (console != null) | 112 | if (console != null) |
113 | console.OutputFormat("{0} is not a valid local id", localId); | 113 | console.OutputFormat("ERROR: {0} is not a valid local id", localId); |
114 | 114 | ||
115 | return false; | 115 | return false; |
116 | } | 116 | } |
@@ -118,7 +118,7 @@ namespace OpenSim.Framework.Console | |||
118 | if (localId == 0) | 118 | if (localId == 0) |
119 | { | 119 | { |
120 | if (console != null) | 120 | if (console != null) |
121 | console.OutputFormat("{0} is not a valid local id - it must be greater than 0", localId); | 121 | console.OutputFormat("ERROR: {0} is not a valid local id - it must be greater than 0", localId); |
122 | 122 | ||
123 | return false; | 123 | return false; |
124 | } | 124 | } |
@@ -150,10 +150,30 @@ namespace OpenSim.Framework.Console | |||
150 | } | 150 | } |
151 | 151 | ||
152 | if (console != null) | 152 | if (console != null) |
153 | console.OutputFormat("{0} is not a valid UUID or local id", rawId); | 153 | console.OutputFormat("ERROR: {0} is not a valid UUID or local id", rawId); |
154 | 154 | ||
155 | return false; | 155 | return false; |
156 | } | 156 | } |
157 | |||
158 | /// <summary> | ||
159 | /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 | ||
160 | /// </summary> | ||
161 | /// <param name='console'>Can be null if no console is available.</param> | ||
162 | /// <param name='rawConsoleVector'>/param> | ||
163 | /// <param name='vector'></param> | ||
164 | /// <returns></returns> | ||
165 | public static bool TryParseConsoleInt(ICommandConsole console, string rawConsoleInt, out int i) | ||
166 | { | ||
167 | if (!int.TryParse(rawConsoleInt, out i)) | ||
168 | { | ||
169 | if (console != null) | ||
170 | console.OutputFormat("ERROR: {0} is not a valid integer", rawConsoleInt); | ||
171 | |||
172 | return false; | ||
173 | } | ||
174 | |||
175 | return true; | ||
176 | } | ||
157 | 177 | ||
158 | /// <summary> | 178 | /// <summary> |
159 | /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 | 179 | /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 |
diff --git a/OpenSim/Framework/PluginManager.cs b/OpenSim/Framework/PluginManager.cs index 23d5945..00263f5 100644 --- a/OpenSim/Framework/PluginManager.cs +++ b/OpenSim/Framework/PluginManager.cs | |||
@@ -92,6 +92,7 @@ namespace OpenSim.Framework | |||
92 | // Attempt to install the plugin disabled | 92 | // Attempt to install the plugin disabled |
93 | if (Install(ps, pack) == true) | 93 | if (Install(ps, pack) == true) |
94 | { | 94 | { |
95 | MainConsole.Instance.Output("Ignore the following error..."); | ||
95 | PluginRegistry.Update(ps); | 96 | PluginRegistry.Update(ps); |
96 | Addin addin = PluginRegistry.GetAddin(aentry.Addin.Id); | 97 | Addin addin = PluginRegistry.GetAddin(aentry.Addin.Id); |
97 | PluginRegistry.DisableAddin(addin.Id); | 98 | PluginRegistry.DisableAddin(addin.Id); |
@@ -479,6 +480,7 @@ namespace OpenSim.Framework | |||
479 | ConsoleProgressStatus ps = new ConsoleProgressStatus(false); | 480 | ConsoleProgressStatus ps = new ConsoleProgressStatus(false); |
480 | if (!AddinManager.AddinEngine.IsAddinLoaded(addin.Id)) | 481 | if (!AddinManager.AddinEngine.IsAddinLoaded(addin.Id)) |
481 | { | 482 | { |
483 | MainConsole.Instance.Output("Ignore the following error..."); | ||
482 | AddinManager.Registry.Rebuild(ps); | 484 | AddinManager.Registry.Rebuild(ps); |
483 | AddinManager.AddinEngine.LoadAddin(ps, addin.Id); | 485 | AddinManager.AddinEngine.LoadAddin(ps, addin.Id); |
484 | } | 486 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 8e0b72f..c0daba2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |||
@@ -12077,11 +12077,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12077 | if (logPacket) | 12077 | if (logPacket) |
12078 | m_log.DebugFormat( | 12078 | m_log.DebugFormat( |
12079 | "[CLIENT]: PACKET IN from {0} ({1}) in {2} - {3}", | 12079 | "[CLIENT]: PACKET IN from {0} ({1}) in {2} - {3}", |
12080 | Name, SceneAgent.IsChildAgent ? "child" : "root ", m_scene.RegionInfo.RegionName, packet.Type); | 12080 | Name, SceneAgent.IsChildAgent ? "child" : "root ", Scene.Name, packet.Type); |
12081 | } | 12081 | } |
12082 | 12082 | ||
12083 | if (!ProcessPacketMethod(packet)) | 12083 | if (!ProcessPacketMethod(packet)) |
12084 | m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); | 12084 | m_log.WarnFormat( |
12085 | "[CLIENT]: Unhandled packet {0} from {1} ({2}) in {3}. Ignoring.", | ||
12086 | packet.Type, Name, SceneAgent.IsChildAgent ? "child" : "root ", Scene.Name); | ||
12085 | } | 12087 | } |
12086 | 12088 | ||
12087 | private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) | 12089 | private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) |
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index f8ec6de..7871eda 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs | |||
@@ -71,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
71 | 71 | ||
72 | #region Internal functions | 72 | #region Internal functions |
73 | 73 | ||
74 | public AssetMetadata FetchMetadata(string url, UUID assetID) | 74 | private AssetMetadata FetchMetadata(string url, UUID assetID) |
75 | { | 75 | { |
76 | if (!url.EndsWith("/") && !url.EndsWith("=")) | 76 | if (!url.EndsWith("/") && !url.EndsWith("=")) |
77 | url = url + "/"; | 77 | url = url + "/"; |
@@ -86,6 +86,27 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
86 | return meta; | 86 | return meta; |
87 | } | 87 | } |
88 | 88 | ||
89 | private AssetBase FetchAsset(string url, UUID assetID) | ||
90 | { | ||
91 | // Test if it's already here | ||
92 | AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); | ||
93 | if (asset == null) | ||
94 | { | ||
95 | if (!url.EndsWith("/") && !url.EndsWith("=")) | ||
96 | url = url + "/"; | ||
97 | |||
98 | asset = m_scene.AssetService.Get(url + assetID.ToString()); | ||
99 | |||
100 | //if (asset != null) | ||
101 | // m_log.DebugFormat("[HG ASSET MAPPER]: Fetched asset {0} of type {1} from {2} ", assetID, asset.Metadata.Type, url); | ||
102 | //else | ||
103 | // m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetch asset {0} from {1} ", assetID, url); | ||
104 | |||
105 | } | ||
106 | |||
107 | return asset; | ||
108 | } | ||
109 | |||
89 | public bool PostAsset(string url, AssetBase asset) | 110 | public bool PostAsset(string url, AssetBase asset) |
90 | { | 111 | { |
91 | if (asset != null) | 112 | if (asset != null) |
@@ -228,11 +249,22 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
228 | if (meta == null) | 249 | if (meta == null) |
229 | return; | 250 | return; |
230 | 251 | ||
231 | // The act of gathering UUIDs downloads the assets from the remote server | 252 | // The act of gathering UUIDs downloads some assets from the remote server |
253 | // but not all... | ||
232 | Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); | 254 | Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); |
233 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); | 255 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); |
234 | uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); | 256 | uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); |
235 | 257 | m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count); | |
258 | bool success = true; | ||
259 | foreach (UUID uuid in ids.Keys) | ||
260 | if (FetchAsset(userAssetURL, uuid) == null) | ||
261 | success = false; | ||
262 | |||
263 | // maybe all pieces got here... | ||
264 | if (!success) | ||
265 | m_log.DebugFormat("[HG ASSET MAPPER]: Problems getting item {0} from asset server {1}", assetID, userAssetURL); | ||
266 | else | ||
267 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully got item {0} from asset server {1}", assetID, userAssetURL); | ||
236 | } | 268 | } |
237 | 269 | ||
238 | 270 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 86e7004..77e8b00 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs | |||
@@ -181,6 +181,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
181 | 181 | ||
182 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); | 182 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); |
183 | 183 | ||
184 | // searhc the user accounts service | ||
184 | List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); | 185 | List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); |
185 | 186 | ||
186 | List<UserData> users = new List<UserData>(); | 187 | List<UserData> users = new List<UserData>(); |
@@ -196,6 +197,12 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
196 | } | 197 | } |
197 | } | 198 | } |
198 | 199 | ||
200 | // search the local cache | ||
201 | foreach (UserData data in m_UserCache.Values) | ||
202 | if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && | ||
203 | (data.FirstName.StartsWith(query) || data.LastName.StartsWith(query))) | ||
204 | users.Add(data); | ||
205 | |||
199 | AddAdditionalUsers(avatarID, query, users); | 206 | AddAdditionalUsers(avatarID, query, users); |
200 | 207 | ||
201 | AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); | 208 | AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); |
@@ -433,6 +440,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
433 | public void AddUser(UUID uuid, string first, string last, string homeURL) | 440 | public void AddUser(UUID uuid, string first, string last, string homeURL) |
434 | { | 441 | { |
435 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); | 442 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); |
443 | if (homeURL == string.Empty) | ||
444 | return; | ||
445 | |||
436 | AddUser(uuid, homeURL + ";" + first + " " + last); | 446 | AddUser(uuid, homeURL + ";" + first + " " + last); |
437 | } | 447 | } |
438 | 448 | ||
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs index 089fcda..883045a 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs | |||
@@ -76,7 +76,7 @@ namespace OpenSim.Region.CoreModules.World.Sound | |||
76 | 76 | ||
77 | public void RemoveRegion(Scene scene) | 77 | public void RemoveRegion(Scene scene) |
78 | { | 78 | { |
79 | m_scene.EventManager.OnClientLogin -= OnNewClient; | 79 | m_scene.EventManager.OnNewClient -= OnNewClient; |
80 | } | 80 | } |
81 | 81 | ||
82 | public void RegionLoaded(Scene scene) | 82 | public void RegionLoaded(Scene scene) |
@@ -85,7 +85,7 @@ namespace OpenSim.Region.CoreModules.World.Sound | |||
85 | return; | 85 | return; |
86 | 86 | ||
87 | m_scene = scene; | 87 | m_scene = scene; |
88 | m_scene.EventManager.OnClientLogin += OnNewClient; | 88 | m_scene.EventManager.OnNewClient += OnNewClient; |
89 | 89 | ||
90 | m_scene.RegisterModuleInterface<ISoundModule>(this); | 90 | m_scene.RegisterModuleInterface<ISoundModule>(this); |
91 | } | 91 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 9458079..d18571c 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs | |||
@@ -26,9 +26,10 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Threading; | ||
30 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Linq; | ||
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Threading; | ||
32 | using log4net; | 33 | using log4net; |
33 | using OpenMetaverse; | 34 | using OpenMetaverse; |
34 | using OpenSim.Framework; | 35 | using OpenSim.Framework; |
@@ -113,6 +114,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
113 | if (m_scenePresence.IsChildAgent) | 114 | if (m_scenePresence.IsChildAgent) |
114 | return; | 115 | return; |
115 | 116 | ||
117 | // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Removing animation {0} for {1}", animID, m_scenePresence.Name); | ||
118 | |||
116 | if (m_animations.Remove(animID)) | 119 | if (m_animations.Remove(animID)) |
117 | SendAnimPack(); | 120 | SendAnimPack(); |
118 | } | 121 | } |
@@ -519,6 +522,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
519 | if (m_scenePresence.IsChildAgent) | 522 | if (m_scenePresence.IsChildAgent) |
520 | return; | 523 | return; |
521 | 524 | ||
525 | // m_log.DebugFormat( | ||
526 | // "[SCENE PRESENCE ANIMATOR]: Sending anim pack with animations '{0}', sequence '{1}', uuids '{2}'", | ||
527 | // string.Join(",", Array.ConvertAll<UUID, string>(animations, a => a.ToString())), | ||
528 | // string.Join(",", Array.ConvertAll<int, string>(seqs, s => s.ToString())), | ||
529 | // string.Join(",", Array.ConvertAll<UUID, string>(objectIDs, o => o.ToString()))); | ||
530 | |||
522 | m_scenePresence.Scene.ForEachClient( | 531 | m_scenePresence.Scene.ForEachClient( |
523 | delegate(IClientAPI client) | 532 | delegate(IClientAPI client) |
524 | { | 533 | { |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index c9d1205..65c50bf 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | |||
@@ -683,12 +683,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
683 | itemCopy.SalePrice = item.SalePrice; | 683 | itemCopy.SalePrice = item.SalePrice; |
684 | itemCopy.SaleType = item.SaleType; | 684 | itemCopy.SaleType = item.SaleType; |
685 | 685 | ||
686 | if (AddInventoryItem(itemCopy)) | 686 | IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>(); |
687 | { | 687 | if (invAccess != null) |
688 | IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>(); | 688 | invAccess.TransferInventoryAssets(itemCopy, senderId, recipient); |
689 | if (invAccess != null) | 689 | AddInventoryItem(itemCopy); |
690 | Util.FireAndForget(delegate { invAccess.TransferInventoryAssets(itemCopy, senderId, recipient); }); | ||
691 | } | ||
692 | 690 | ||
693 | if (!Permissions.BypassPermissions()) | 691 | if (!Permissions.BypassPermissions()) |
694 | { | 692 | { |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 2191cfa..c746690 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -2895,11 +2895,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2895 | 2895 | ||
2896 | public void PhysicsOutOfBounds(Vector3 pos) | 2896 | public void PhysicsOutOfBounds(Vector3 pos) |
2897 | { | 2897 | { |
2898 | m_log.Error("[PHYSICS]: Physical Object went out of bounds."); | 2898 | // Note: This is only being called on the root prim at this time. |
2899 | |||
2900 | m_log.ErrorFormat( | ||
2901 | "[SCENE OBJECT PART]: Physical object {0}, localID {1} went out of bounds at {2} in {3}. Stopping at {4} and making non-physical.", | ||
2902 | Name, LocalId, pos, ParentGroup.Scene.Name, AbsolutePosition); | ||
2899 | 2903 | ||
2900 | RemFlag(PrimFlags.Physics); | 2904 | RemFlag(PrimFlags.Physics); |
2901 | DoPhysicsPropertyUpdate(false, true); | 2905 | DoPhysicsPropertyUpdate(false, true); |
2902 | //ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); | ||
2903 | } | 2906 | } |
2904 | 2907 | ||
2905 | public void PhysicsRequestingTerseUpdate() | 2908 | public void PhysicsRequestingTerseUpdate() |
@@ -4549,7 +4552,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4549 | if (ParentGroup.RootPart == this) | 4552 | if (ParentGroup.RootPart == this) |
4550 | AngularVelocity = new Vector3(0, 0, 0); | 4553 | AngularVelocity = new Vector3(0, 0, 0); |
4551 | } | 4554 | } |
4552 | else | 4555 | else if (SetVD != wasVD) |
4553 | { | 4556 | { |
4554 | if (ParentGroup.Scene.CollidablePrims) | 4557 | if (ParentGroup.Scene.CollidablePrims) |
4555 | { | 4558 | { |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 7f07d73..1250a11 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -214,8 +214,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
214 | 214 | ||
215 | private Quaternion m_headrotation = Quaternion.Identity; | 215 | private Quaternion m_headrotation = Quaternion.Identity; |
216 | 216 | ||
217 | private string m_nextSitAnimation = String.Empty; | ||
218 | |||
219 | //PauPaw:Proper PID Controler for autopilot************ | 217 | //PauPaw:Proper PID Controler for autopilot************ |
220 | public bool MovingToTarget { get; private set; } | 218 | public bool MovingToTarget { get; private set; } |
221 | public Vector3 MoveToPositionTarget { get; private set; } | 219 | public Vector3 MoveToPositionTarget { get; private set; } |
@@ -2120,25 +2118,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2120 | StandUp(); | 2118 | StandUp(); |
2121 | } | 2119 | } |
2122 | 2120 | ||
2123 | // if (!String.IsNullOrEmpty(sitAnimation)) | ||
2124 | // { | ||
2125 | // m_nextSitAnimation = sitAnimation; | ||
2126 | // } | ||
2127 | // else | ||
2128 | // { | ||
2129 | m_nextSitAnimation = "SIT"; | ||
2130 | // } | ||
2131 | |||
2132 | //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); | ||
2133 | SceneObjectPart part = FindNextAvailableSitTarget(targetID); | 2121 | SceneObjectPart part = FindNextAvailableSitTarget(targetID); |
2134 | 2122 | ||
2135 | if (part != null) | 2123 | if (part != null) |
2136 | { | 2124 | { |
2137 | if (!String.IsNullOrEmpty(part.SitAnimation)) | ||
2138 | { | ||
2139 | m_nextSitAnimation = part.SitAnimation; | ||
2140 | } | ||
2141 | |||
2142 | m_requestedSitTargetID = part.LocalId; | 2125 | m_requestedSitTargetID = part.LocalId; |
2143 | m_requestedSitTargetUUID = targetID; | 2126 | m_requestedSitTargetUUID = targetID; |
2144 | 2127 | ||
@@ -2353,18 +2336,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2353 | 2336 | ||
2354 | public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) | 2337 | public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) |
2355 | { | 2338 | { |
2356 | if (!String.IsNullOrEmpty(m_nextSitAnimation)) | ||
2357 | { | ||
2358 | HandleAgentSit(remoteClient, agentID, m_nextSitAnimation); | ||
2359 | } | ||
2360 | else | ||
2361 | { | ||
2362 | HandleAgentSit(remoteClient, agentID, "SIT"); | ||
2363 | } | ||
2364 | } | ||
2365 | |||
2366 | public void HandleAgentSit(IClientAPI remoteClient, UUID agentID, string sitAnimation) | ||
2367 | { | ||
2368 | SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); | 2339 | SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); |
2369 | 2340 | ||
2370 | if (part != null) | 2341 | if (part != null) |
@@ -2436,7 +2407,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2436 | 2407 | ||
2437 | Velocity = Vector3.Zero; | 2408 | Velocity = Vector3.Zero; |
2438 | RemoveFromPhysicalScene(); | 2409 | RemoveFromPhysicalScene(); |
2439 | 2410 | ||
2411 | String sitAnimation = "SIT"; | ||
2412 | if (!String.IsNullOrEmpty(part.SitAnimation)) | ||
2413 | { | ||
2414 | sitAnimation = part.SitAnimation; | ||
2415 | } | ||
2440 | Animator.TrySetMovementAnimation(sitAnimation); | 2416 | Animator.TrySetMovementAnimation(sitAnimation); |
2441 | SendAvatarDataToAllAgents(); | 2417 | SendAvatarDataToAllAgents(); |
2442 | } | 2418 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs index 093cbd2..8eb3191 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs | |||
@@ -78,6 +78,26 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
78 | } | 78 | } |
79 | 79 | ||
80 | [Test] | 80 | [Test] |
81 | public void TestSetNonPhysicsVolumeDetectSinglePrim() | ||
82 | { | ||
83 | TestHelpers.InMethod(); | ||
84 | |||
85 | m_scene.AddSceneObject(m_so1); | ||
86 | |||
87 | SceneObjectPart rootPart = m_so1.RootPart; | ||
88 | Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); | ||
89 | |||
90 | m_so1.ScriptSetVolumeDetect(true); | ||
91 | |||
92 | // Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags); | ||
93 | Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom)); | ||
94 | |||
95 | m_so1.ScriptSetVolumeDetect(false); | ||
96 | |||
97 | Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); | ||
98 | } | ||
99 | |||
100 | [Test] | ||
81 | public void TestSetPhysicsSinglePrim() | 101 | public void TestSetPhysicsSinglePrim() |
82 | { | 102 | { |
83 | TestHelpers.InMethod(); | 103 | TestHelpers.InMethod(); |
@@ -89,13 +109,32 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
89 | 109 | ||
90 | m_so1.ScriptSetPhysicsStatus(true); | 110 | m_so1.ScriptSetPhysicsStatus(true); |
91 | 111 | ||
92 | // Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags); | ||
93 | Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics)); | 112 | Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics)); |
94 | 113 | ||
95 | m_so1.ScriptSetPhysicsStatus(false); | 114 | m_so1.ScriptSetPhysicsStatus(false); |
96 | 115 | ||
97 | Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); | 116 | Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); |
98 | } | 117 | } |
118 | |||
119 | [Test] | ||
120 | public void TestSetPhysicsVolumeDetectSinglePrim() | ||
121 | { | ||
122 | TestHelpers.InMethod(); | ||
123 | |||
124 | m_scene.AddSceneObject(m_so1); | ||
125 | |||
126 | SceneObjectPart rootPart = m_so1.RootPart; | ||
127 | Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); | ||
128 | |||
129 | m_so1.ScriptSetPhysicsStatus(true); | ||
130 | m_so1.ScriptSetVolumeDetect(true); | ||
131 | |||
132 | Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom | PrimFlags.Physics)); | ||
133 | |||
134 | m_so1.ScriptSetVolumeDetect(false); | ||
135 | |||
136 | Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics)); | ||
137 | } | ||
99 | 138 | ||
100 | [Test] | 139 | [Test] |
101 | public void TestSetPhysicsLinkset() | 140 | public void TestSetPhysicsLinkset() |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 21aa9be..0defb24 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -105,12 +105,12 @@ public sealed class BSCharacter : BSPhysObject | |||
105 | DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", | 105 | DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", |
106 | LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); | 106 | LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); |
107 | 107 | ||
108 | // do actual create at taint time | 108 | // do actual creation in taint time |
109 | PhysicsScene.TaintedObject("BSCharacter.create", delegate() | 109 | PhysicsScene.TaintedObject("BSCharacter.create", delegate() |
110 | { | 110 | { |
111 | DetailLog("{0},BSCharacter.create,taint", LocalID); | 111 | DetailLog("{0},BSCharacter.create,taint", LocalID); |
112 | // New body and shape into PhysBody and PhysShape | 112 | // New body and shape into PhysBody and PhysShape |
113 | PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null); | 113 | PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this); |
114 | 114 | ||
115 | SetPhysicalProperties(); | 115 | SetPhysicalProperties(); |
116 | }); | 116 | }); |
@@ -124,7 +124,9 @@ public sealed class BSCharacter : BSPhysObject | |||
124 | PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() | 124 | PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() |
125 | { | 125 | { |
126 | PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); | 126 | PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); |
127 | PhysBody.Clear(); | ||
127 | PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); | 128 | PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); |
129 | PhysShape.Clear(); | ||
128 | }); | 130 | }); |
129 | } | 131 | } |
130 | 132 | ||
@@ -165,9 +167,8 @@ public sealed class BSCharacter : BSPhysObject | |||
165 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); | 167 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); |
166 | 168 | ||
167 | // Do this after the object has been added to the world | 169 | // Do this after the object has been added to the world |
168 | BulletSimAPI.SetCollisionGroupMask2(PhysBody.ptr, | 170 | PhysBody.collisionType = CollisionType.Avatar; |
169 | (uint)CollisionFilterGroups.AvatarGroup, | 171 | PhysBody.ApplyCollisionMask(); |
170 | (uint)CollisionFilterGroups.AvatarMask); | ||
171 | } | 172 | } |
172 | 173 | ||
173 | public override void RequestPhysicsterseUpdate() | 174 | public override void RequestPhysicsterseUpdate() |
@@ -187,6 +188,11 @@ public sealed class BSCharacter : BSPhysObject | |||
187 | set { | 188 | set { |
188 | // When an avatar's size is set, only the height is changed. | 189 | // When an avatar's size is set, only the height is changed. |
189 | _size = value; | 190 | _size = value; |
191 | // Old versions of ScenePresence passed only the height. If width and/or depth are zero, | ||
192 | // replace with the default values. | ||
193 | if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth; | ||
194 | if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth; | ||
195 | |||
190 | ComputeAvatarScale(_size); | 196 | ComputeAvatarScale(_size); |
191 | ComputeAvatarVolumeAndMass(); | 197 | ComputeAvatarVolumeAndMass(); |
192 | DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", | 198 | DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", |
@@ -194,15 +200,18 @@ public sealed class BSCharacter : BSPhysObject | |||
194 | 200 | ||
195 | PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() | 201 | PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() |
196 | { | 202 | { |
197 | BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); | 203 | if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape) |
198 | UpdatePhysicalMassProperties(RawMass); | 204 | { |
205 | BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); | ||
206 | UpdatePhysicalMassProperties(RawMass); | ||
207 | // Make sure this change appears as a property update event | ||
208 | BulletSimAPI.PushUpdate2(PhysBody.ptr); | ||
209 | } | ||
199 | }); | 210 | }); |
200 | 211 | ||
201 | } | 212 | } |
202 | } | 213 | } |
203 | 214 | ||
204 | public override OMV.Vector3 Scale { get; set; } | ||
205 | |||
206 | public override PrimitiveBaseShape Shape | 215 | public override PrimitiveBaseShape Shape |
207 | { | 216 | { |
208 | set { BaseShape = value; } | 217 | set { BaseShape = value; } |
@@ -236,7 +245,8 @@ public sealed class BSCharacter : BSPhysObject | |||
236 | // Zero some other properties directly into the physics engine | 245 | // Zero some other properties directly into the physics engine |
237 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() | 246 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() |
238 | { | 247 | { |
239 | BulletSimAPI.ClearAllForces2(PhysBody.ptr); | 248 | if (PhysBody.HasPhysicalBody) |
249 | BulletSimAPI.ClearAllForces2(PhysBody.ptr); | ||
240 | }); | 250 | }); |
241 | } | 251 | } |
242 | public override void ZeroAngularMotion(bool inTaintTime) | 252 | public override void ZeroAngularMotion(bool inTaintTime) |
@@ -245,10 +255,13 @@ public sealed class BSCharacter : BSPhysObject | |||
245 | 255 | ||
246 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() | 256 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() |
247 | { | 257 | { |
248 | BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); | 258 | if (PhysBody.HasPhysicalBody) |
249 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); | 259 | { |
250 | // The next also get rid of applied linear force but the linear velocity is untouched. | 260 | BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); |
251 | BulletSimAPI.ClearForces2(PhysBody.ptr); | 261 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); |
262 | // The next also get rid of applied linear force but the linear velocity is untouched. | ||
263 | BulletSimAPI.ClearForces2(PhysBody.ptr); | ||
264 | } | ||
252 | }); | 265 | }); |
253 | } | 266 | } |
254 | 267 | ||
@@ -273,7 +286,8 @@ public sealed class BSCharacter : BSPhysObject | |||
273 | PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() | 286 | PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() |
274 | { | 287 | { |
275 | DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 288 | DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
276 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 289 | if (PhysBody.HasPhysicalBody) |
290 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
277 | }); | 291 | }); |
278 | } | 292 | } |
279 | } | 293 | } |
@@ -332,7 +346,8 @@ public sealed class BSCharacter : BSPhysObject | |||
332 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() | 346 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() |
333 | { | 347 | { |
334 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 348 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
335 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 349 | if (PhysBody.HasPhysicalBody) |
350 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
336 | }); | 351 | }); |
337 | ret = true; | 352 | ret = true; |
338 | } | 353 | } |
@@ -359,7 +374,8 @@ public sealed class BSCharacter : BSPhysObject | |||
359 | PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() | 374 | PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() |
360 | { | 375 | { |
361 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); | 376 | DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); |
362 | BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); | 377 | if (PhysBody.HasPhysicalBody) |
378 | BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); | ||
363 | }); | 379 | }); |
364 | } | 380 | } |
365 | } | 381 | } |
@@ -398,7 +414,8 @@ public sealed class BSCharacter : BSPhysObject | |||
398 | if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) | 414 | if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) |
399 | { | 415 | { |
400 | _currentFriction = PhysicsScene.Params.avatarStandingFriction; | 416 | _currentFriction = PhysicsScene.Params.avatarStandingFriction; |
401 | BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); | 417 | if (PhysBody.HasPhysicalBody) |
418 | BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); | ||
402 | } | 419 | } |
403 | } | 420 | } |
404 | else | 421 | else |
@@ -406,7 +423,8 @@ public sealed class BSCharacter : BSPhysObject | |||
406 | if (_currentFriction != PhysicsScene.Params.avatarFriction) | 423 | if (_currentFriction != PhysicsScene.Params.avatarFriction) |
407 | { | 424 | { |
408 | _currentFriction = PhysicsScene.Params.avatarFriction; | 425 | _currentFriction = PhysicsScene.Params.avatarFriction; |
409 | BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); | 426 | if (PhysBody.HasPhysicalBody) |
427 | BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); | ||
410 | } | 428 | } |
411 | } | 429 | } |
412 | _velocity = value; | 430 | _velocity = value; |
@@ -443,8 +461,11 @@ public sealed class BSCharacter : BSPhysObject | |||
443 | // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); | 461 | // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); |
444 | PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() | 462 | PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() |
445 | { | 463 | { |
446 | // _position = BulletSimAPI.GetPosition2(BSBody.ptr); | 464 | if (PhysBody.HasPhysicalBody) |
447 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 465 | { |
466 | // _position = BulletSimAPI.GetPosition2(BSBody.ptr); | ||
467 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
468 | } | ||
448 | }); | 469 | }); |
449 | } | 470 | } |
450 | } | 471 | } |
@@ -517,10 +538,13 @@ public sealed class BSCharacter : BSPhysObject | |||
517 | _floatOnWater = value; | 538 | _floatOnWater = value; |
518 | PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() | 539 | PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() |
519 | { | 540 | { |
520 | if (_floatOnWater) | 541 | if (PhysBody.HasPhysicalBody) |
521 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | 542 | { |
522 | else | 543 | if (_floatOnWater) |
523 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | 544 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); |
545 | else | ||
546 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); | ||
547 | } | ||
524 | }); | 548 | }); |
525 | } | 549 | } |
526 | } | 550 | } |
@@ -553,7 +577,8 @@ public sealed class BSCharacter : BSPhysObject | |||
553 | DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 577 | DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
554 | // Buoyancy is faked by changing the gravity applied to the object | 578 | // Buoyancy is faked by changing the gravity applied to the object |
555 | float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); | 579 | float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); |
556 | BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); | 580 | if (PhysBody.HasPhysicalBody) |
581 | BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); | ||
557 | } | 582 | } |
558 | } | 583 | } |
559 | 584 | ||
@@ -599,7 +624,8 @@ public sealed class BSCharacter : BSPhysObject | |||
599 | PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() | 624 | PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() |
600 | { | 625 | { |
601 | DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); | 626 | DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); |
602 | BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); | 627 | if (PhysBody.HasPhysicalBody) |
628 | BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); | ||
603 | }); | 629 | }); |
604 | } | 630 | } |
605 | else | 631 | else |
@@ -616,9 +642,6 @@ public sealed class BSCharacter : BSPhysObject | |||
616 | 642 | ||
617 | private void ComputeAvatarScale(OMV.Vector3 size) | 643 | private void ComputeAvatarScale(OMV.Vector3 size) |
618 | { | 644 | { |
619 | // The 'size' given by the simulator is the mid-point of the avatar | ||
620 | // and X and Y are unspecified. | ||
621 | |||
622 | OMV.Vector3 newScale = size; | 645 | OMV.Vector3 newScale = size; |
623 | // newScale.X = PhysicsScene.Params.avatarCapsuleWidth; | 646 | // newScale.X = PhysicsScene.Params.avatarCapsuleWidth; |
624 | // newScale.Y = PhysicsScene.Params.avatarCapsuleDepth; | 647 | // newScale.Y = PhysicsScene.Params.avatarCapsuleDepth; |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index 65fac00..6b1e304 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | |||
@@ -57,7 +57,7 @@ public abstract class BSConstraint : IDisposable | |||
57 | if (m_enabled) | 57 | if (m_enabled) |
58 | { | 58 | { |
59 | m_enabled = false; | 59 | m_enabled = false; |
60 | if (m_constraint.ptr != IntPtr.Zero) | 60 | if (m_constraint.HasPhysicalConstraint) |
61 | { | 61 | { |
62 | bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); | 62 | bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); |
63 | m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", | 63 | m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", |
@@ -65,7 +65,7 @@ public abstract class BSConstraint : IDisposable | |||
65 | m_body1.ID, m_body1.ptr.ToString("X"), | 65 | m_body1.ID, m_body1.ptr.ToString("X"), |
66 | m_body2.ID, m_body2.ptr.ToString("X"), | 66 | m_body2.ID, m_body2.ptr.ToString("X"), |
67 | success); | 67 | success); |
68 | m_constraint.ptr = System.IntPtr.Zero; | 68 | m_constraint.Clear(); |
69 | } | 69 | } |
70 | } | 70 | } |
71 | } | 71 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs index 23ef052..b073555 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs | |||
@@ -65,7 +65,7 @@ public sealed class BSConstraint6Dof : BSConstraint | |||
65 | m_world = world; | 65 | m_world = world; |
66 | m_body1 = obj1; | 66 | m_body1 = obj1; |
67 | m_body2 = obj2; | 67 | m_body2 = obj2; |
68 | if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) | 68 | if (!obj1.HasPhysicalBody || !obj2.HasPhysicalBody) |
69 | { | 69 | { |
70 | world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", | 70 | world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", |
71 | BSScene.DetailLogZero, world.worldID, | 71 | BSScene.DetailLogZero, world.worldID, |
@@ -83,7 +83,7 @@ public sealed class BSConstraint6Dof : BSConstraint | |||
83 | world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", | 83 | world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", |
84 | BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"), | 84 | BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"), |
85 | obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); | 85 | obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); |
86 | if (m_constraint.ptr == IntPtr.Zero) | 86 | if (!m_constraint.HasPhysicalConstraint) |
87 | { | 87 | { |
88 | world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", | 88 | world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", |
89 | LogHeader, obj1.ID, obj2.ID); | 89 | LogHeader, obj1.ID, obj2.ID); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index fa3110c..82e829e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -570,8 +570,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
570 | BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); | 570 | BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); |
571 | BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr); | 571 | BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr); |
572 | 572 | ||
573 | VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}", | 573 | VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}", |
574 | Prim.LocalID, friction, localInertia, angularDamping); | 574 | Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping); |
575 | } | 575 | } |
576 | else | 576 | else |
577 | { | 577 | { |
@@ -818,6 +818,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
818 | + hoverContribution | 818 | + hoverContribution |
819 | + limitMotorUpContribution; | 819 | + limitMotorUpContribution; |
820 | 820 | ||
821 | Vector3 newForce = buoyancyContribution; | ||
822 | |||
821 | // If not changing some axis, reduce out velocity | 823 | // If not changing some axis, reduce out velocity |
822 | if ((m_flags & (VehicleFlag.NO_X)) != 0) | 824 | if ((m_flags & (VehicleFlag.NO_X)) != 0) |
823 | newVelocity.X = 0; | 825 | newVelocity.X = 0; |
@@ -845,7 +847,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
845 | VehicleVelocity = newVelocity; | 847 | VehicleVelocity = newVelocity; |
846 | 848 | ||
847 | // Other linear forces are applied as forces. | 849 | // Other linear forces are applied as forces. |
848 | Vector3 totalDownForce = buoyancyContribution * m_vehicleMass; | 850 | Vector3 totalDownForce = newForce * m_vehicleMass; |
849 | if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f)) | 851 | if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f)) |
850 | { | 852 | { |
851 | VehicleAddForce(totalDownForce); | 853 | VehicleAddForce(totalDownForce); |
@@ -991,8 +993,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
991 | 993 | ||
992 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) | 994 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) |
993 | { | 995 | { |
994 | // If the vehicle is motoring into the sky, get it going back down. | 996 | float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); |
995 | float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition); | 997 | float distanceAboveGround = VehiclePosition.Z - targetHeight; |
996 | // Not colliding if the vehicle is off the ground | 998 | // Not colliding if the vehicle is off the ground |
997 | if (!Prim.IsColliding) | 999 | if (!Prim.IsColliding) |
998 | { | 1000 | { |
@@ -1005,8 +1007,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1005 | // has a decay factor. This says this force should | 1007 | // has a decay factor. This says this force should |
1006 | // be computed with a motor. | 1008 | // be computed with a motor. |
1007 | // TODO: add interaction with banking. | 1009 | // TODO: add interaction with banking. |
1008 | VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},downForce={2}", | 1010 | VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", |
1009 | Prim.LocalID, distanceAboveGround, ret); | 1011 | Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); |
1010 | } | 1012 | } |
1011 | return ret; | 1013 | return ret; |
1012 | } | 1014 | } |
@@ -1055,7 +1057,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1055 | // TODO: Should this be applied as an angular force (torque)? | 1057 | // TODO: Should this be applied as an angular force (torque)? |
1056 | if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f)) | 1058 | if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f)) |
1057 | { | 1059 | { |
1058 | Vector3 scaledCorrection = m_lastAngularCorrection * pTimestep; | 1060 | // DEBUG DEBUG DEBUG: optionally scale the angular velocity. Debugging SL vs ODE turning functions. |
1061 | Vector3 scaledCorrection = m_lastAngularCorrection; | ||
1062 | if (PhysicsScene.VehicleScaleAngularVelocityByTimestep) | ||
1063 | scaledCorrection *= pTimestep; | ||
1059 | VehicleRotationalVelocity = scaledCorrection; | 1064 | VehicleRotationalVelocity = scaledCorrection; |
1060 | 1065 | ||
1061 | VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}", | 1066 | VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}", |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 0df4310..ce0fbe6 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -32,6 +32,14 @@ using OMV = OpenMetaverse; | |||
32 | 32 | ||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | 33 | namespace OpenSim.Region.Physics.BulletSPlugin |
34 | { | 34 | { |
35 | |||
36 | // A BSPrim can get individual information about its linkedness attached | ||
37 | // to it through an instance of a subclass of LinksetInfo. | ||
38 | // Each type of linkset will define the information needed for its type. | ||
39 | public abstract class BSLinksetInfo | ||
40 | { | ||
41 | } | ||
42 | |||
35 | public abstract class BSLinkset | 43 | public abstract class BSLinkset |
36 | { | 44 | { |
37 | // private static string LogHeader = "[BULLETSIM LINKSET]"; | 45 | // private static string LogHeader = "[BULLETSIM LINKSET]"; |
@@ -116,7 +124,7 @@ public abstract class BSLinkset | |||
116 | get { return ComputeLinksetGeometricCenter(); } | 124 | get { return ComputeLinksetGeometricCenter(); } |
117 | } | 125 | } |
118 | 126 | ||
119 | protected void Initialize(BSScene scene, BSPhysObject parent) | 127 | protected BSLinkset(BSScene scene, BSPhysObject parent) |
120 | { | 128 | { |
121 | // A simple linkset of one (no children) | 129 | // A simple linkset of one (no children) |
122 | LinksetID = m_nextLinksetID++; | 130 | LinksetID = m_nextLinksetID++; |
@@ -127,6 +135,7 @@ public abstract class BSLinkset | |||
127 | LinksetRoot = parent; | 135 | LinksetRoot = parent; |
128 | m_children = new HashSet<BSPhysObject>(); | 136 | m_children = new HashSet<BSPhysObject>(); |
129 | m_mass = parent.RawMass; | 137 | m_mass = parent.RawMass; |
138 | Rebuilding = false; | ||
130 | } | 139 | } |
131 | 140 | ||
132 | // Link to a linkset where the child knows the parent. | 141 | // Link to a linkset where the child knows the parent. |
@@ -219,7 +228,7 @@ public abstract class BSLinkset | |||
219 | // I am the root of a linkset and a new child is being added | 228 | // I am the root of a linkset and a new child is being added |
220 | // Called while LinkActivity is locked. | 229 | // Called while LinkActivity is locked. |
221 | protected abstract void AddChildToLinkset(BSPhysObject child); | 230 | protected abstract void AddChildToLinkset(BSPhysObject child); |
222 | 231 | ||
223 | // I am the root of a linkset and one of my children is being removed. | 232 | // I am the root of a linkset and one of my children is being removed. |
224 | // Safe to call even if the child is not really in my linkset. | 233 | // Safe to call even if the child is not really in my linkset. |
225 | protected abstract void RemoveChildFromLinkset(BSPhysObject child); | 234 | protected abstract void RemoveChildFromLinkset(BSPhysObject child); |
@@ -229,6 +238,10 @@ public abstract class BSLinkset | |||
229 | // May be called at runtime or taint-time. | 238 | // May be called at runtime or taint-time. |
230 | public abstract void Refresh(BSPhysObject requestor); | 239 | public abstract void Refresh(BSPhysObject requestor); |
231 | 240 | ||
241 | // Flag denoting the linkset is in the process of being rebuilt. | ||
242 | // Used to know not the schedule a rebuild in the middle of a rebuild. | ||
243 | protected bool Rebuilding { get; set; } | ||
244 | |||
232 | // The object is going dynamic (physical). Do any setup necessary | 245 | // The object is going dynamic (physical). Do any setup necessary |
233 | // for a dynamic linkset. | 246 | // for a dynamic linkset. |
234 | // Only the state of the passed object can be modified. The rest of the linkset | 247 | // Only the state of the passed object can be modified. The rest of the linkset |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 1f7c398..2189468 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs | |||
@@ -32,18 +32,43 @@ using OMV = OpenMetaverse; | |||
32 | 32 | ||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | 33 | namespace OpenSim.Region.Physics.BulletSPlugin |
34 | { | 34 | { |
35 | |||
36 | // When a child is linked, the relationship position of the child to the parent | ||
37 | // is remembered so the child's world position can be recomputed when it is | ||
38 | // removed from the linkset. | ||
39 | sealed class BSLinksetCompoundInfo : BSLinksetInfo | ||
40 | { | ||
41 | public OMV.Vector3 OffsetPos; | ||
42 | public OMV.Quaternion OffsetRot; | ||
43 | public BSLinksetCompoundInfo(OMV.Vector3 p, OMV.Quaternion r) | ||
44 | { | ||
45 | OffsetPos = p; | ||
46 | OffsetRot = r; | ||
47 | } | ||
48 | public override string ToString() | ||
49 | { | ||
50 | StringBuilder buff = new StringBuilder(); | ||
51 | buff.Append("<p="); | ||
52 | buff.Append(OffsetPos.ToString()); | ||
53 | buff.Append(",r="); | ||
54 | buff.Append(OffsetRot.ToString()); | ||
55 | buff.Append(">"); | ||
56 | return buff.ToString(); | ||
57 | } | ||
58 | }; | ||
59 | |||
35 | public sealed class BSLinksetCompound : BSLinkset | 60 | public sealed class BSLinksetCompound : BSLinkset |
36 | { | 61 | { |
37 | private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; | 62 | private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; |
38 | 63 | ||
39 | public BSLinksetCompound(BSScene scene, BSPhysObject parent) | 64 | public BSLinksetCompound(BSScene scene, BSPhysObject parent) : base(scene, parent) |
40 | { | 65 | { |
41 | base.Initialize(scene, parent); | ||
42 | } | 66 | } |
43 | 67 | ||
44 | // For compound implimented linksets, if there are children, use compound shape for the root. | 68 | // For compound implimented linksets, if there are children, use compound shape for the root. |
45 | public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) | 69 | public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) |
46 | { | 70 | { |
71 | // Returning 'unknown' means we don't have a preference. | ||
47 | BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN; | 72 | BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN; |
48 | if (IsRoot(requestor) && HasAnyChildren) | 73 | if (IsRoot(requestor) && HasAnyChildren) |
49 | { | 74 | { |
@@ -55,23 +80,27 @@ public sealed class BSLinksetCompound : BSLinkset | |||
55 | 80 | ||
56 | // When physical properties are changed the linkset needs to recalculate | 81 | // When physical properties are changed the linkset needs to recalculate |
57 | // its internal properties. | 82 | // its internal properties. |
58 | // This is queued in the 'post taint' queue so the | ||
59 | // refresh will happen once after all the other taints are applied. | ||
60 | public override void Refresh(BSPhysObject requestor) | 83 | public override void Refresh(BSPhysObject requestor) |
61 | { | 84 | { |
62 | // External request for Refresh (from BSPrim) doesn't need to do anything | 85 | // External request for Refresh (from BSPrim) doesn't need to do anything |
63 | // InternalRefresh(requestor); | 86 | // InternalRefresh(requestor); |
64 | } | 87 | } |
65 | 88 | ||
89 | // Schedule a refresh to happen after all the other taint processing. | ||
66 | private void InternalRefresh(BSPhysObject requestor) | 90 | private void InternalRefresh(BSPhysObject requestor) |
67 | { | 91 | { |
68 | DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); | 92 | DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1},rebuilding={2}", |
69 | // Queue to happen after all the other taint processing | 93 | LinksetRoot.LocalID, requestor.LocalID, Rebuilding); |
70 | PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() | 94 | // When rebuilding, it is possible to set properties that would normally require a rebuild. |
95 | // If already rebuilding, don't request another rebuild. | ||
96 | if (!Rebuilding) | ||
71 | { | 97 | { |
72 | if (IsRoot(requestor) && HasAnyChildren) | 98 | PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() |
73 | RecomputeLinksetCompound(); | 99 | { |
74 | }); | 100 | if (IsRoot(requestor) && HasAnyChildren) |
101 | RecomputeLinksetCompound(); | ||
102 | }); | ||
103 | } | ||
75 | } | 104 | } |
76 | 105 | ||
77 | // The object is going dynamic (physical). Do any setup necessary | 106 | // The object is going dynamic (physical). Do any setup necessary |
@@ -84,12 +113,24 @@ public sealed class BSLinksetCompound : BSLinkset | |||
84 | { | 113 | { |
85 | bool ret = false; | 114 | bool ret = false; |
86 | DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child)); | 115 | DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child)); |
87 | if (!IsRoot(child)) | 116 | if (IsRoot(child)) |
117 | { | ||
118 | // The root is going dynamic. Make sure mass is properly set. | ||
119 | m_mass = ComputeLinksetMass(); | ||
120 | if (HasAnyChildren) | ||
121 | InternalRefresh(LinksetRoot); | ||
122 | } | ||
123 | else | ||
88 | { | 124 | { |
89 | // The origional prims are removed from the world as the shape of the root compound | 125 | // The origional prims are removed from the world as the shape of the root compound |
90 | // shape takes over. | 126 | // shape takes over. |
91 | BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | 127 | BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); |
92 | BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION); | 128 | BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION); |
129 | // We don't want collisions from the old linkset children. | ||
130 | BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
131 | |||
132 | child.PhysBody.collisionType = CollisionType.LinksetChild; | ||
133 | |||
93 | ret = true; | 134 | ret = true; |
94 | } | 135 | } |
95 | return ret; | 136 | return ret; |
@@ -104,11 +145,19 @@ public sealed class BSLinksetCompound : BSLinkset | |||
104 | { | 145 | { |
105 | bool ret = false; | 146 | bool ret = false; |
106 | DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); | 147 | DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); |
107 | if (!IsRoot(child)) | 148 | if (IsRoot(child)) |
149 | { | ||
150 | if (HasAnyChildren) | ||
151 | InternalRefresh(LinksetRoot); | ||
152 | } | ||
153 | else | ||
108 | { | 154 | { |
109 | // The non-physical children can come back to life. | 155 | // The non-physical children can come back to life. |
110 | BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | 156 | BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); |
111 | // Don't force activation so setting of DISABLE_SIMULATION can stay. | 157 | |
158 | child.PhysBody.collisionType = CollisionType.LinksetChild; | ||
159 | |||
160 | // Don't force activation so setting of DISABLE_SIMULATION can stay if used. | ||
112 | BulletSimAPI.Activate2(child.PhysBody.ptr, false); | 161 | BulletSimAPI.Activate2(child.PhysBody.ptr, false); |
113 | ret = true; | 162 | ret = true; |
114 | } | 163 | } |
@@ -146,20 +195,58 @@ public sealed class BSLinksetCompound : BSLinkset | |||
146 | 195 | ||
147 | if (!IsRoot(child)) | 196 | if (!IsRoot(child)) |
148 | { | 197 | { |
149 | // Cause the current shape to be freed and the new one to be built. | 198 | // Because it is a convenient time, recompute child world position and rotation based on |
150 | InternalRefresh(LinksetRoot); | 199 | // its position in the linkset. |
151 | ret = true; | 200 | RecomputeChildWorldPosition(child, true); |
152 | } | 201 | } |
153 | 202 | ||
203 | // Cannot schedule a refresh/rebuild here because this routine is called when | ||
204 | // the linkset is being rebuilt. | ||
205 | // InternalRefresh(LinksetRoot); | ||
206 | |||
154 | return ret; | 207 | return ret; |
155 | } | 208 | } |
156 | 209 | ||
157 | // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', | 210 | // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', |
158 | // this routine will restore the removed constraints. | 211 | // this routine will restore the removed constraints. |
159 | // Called at taint-time!! | 212 | // Called at taint-time!! |
160 | public override void RestoreBodyDependencies(BSPrim child) | 213 | public override void RestoreBodyDependencies(BSPrim child) |
161 | { | 214 | { |
162 | // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. | 215 | } |
216 | |||
217 | // When the linkset is built, the child shape is added to the compound shape relative to the | ||
218 | // root shape. The linkset then moves around but this does not move the actual child | ||
219 | // prim. The child prim's location must be recomputed based on the location of the root shape. | ||
220 | private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime) | ||
221 | { | ||
222 | BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo; | ||
223 | if (lci != null) | ||
224 | { | ||
225 | if (inTaintTime) | ||
226 | { | ||
227 | OMV.Vector3 oldPos = child.RawPosition; | ||
228 | child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetPos; | ||
229 | child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot; | ||
230 | DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}", | ||
231 | child.LocalID, oldPos, lci, child.RawPosition); | ||
232 | } | ||
233 | else | ||
234 | { | ||
235 | // TaintedObject is not used here so the raw position is set now and not at taint-time. | ||
236 | child.Position = LinksetRoot.RawPosition + lci.OffsetPos; | ||
237 | child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot; | ||
238 | } | ||
239 | } | ||
240 | else | ||
241 | { | ||
242 | // This happens when children have been added to the linkset but the linkset | ||
243 | // has not been constructed yet. So like, at taint time, adding children to a linkset | ||
244 | // and then changing properties of the children (makePhysical, for instance) | ||
245 | // but the post-print action of actually rebuilding the linkset has not yet happened. | ||
246 | // PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}", | ||
247 | // LogHeader, child.LocalID); | ||
248 | DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID); | ||
249 | } | ||
163 | } | 250 | } |
164 | 251 | ||
165 | // ================================================================ | 252 | // ================================================================ |
@@ -181,7 +268,7 @@ public sealed class BSLinksetCompound : BSLinkset | |||
181 | } | 268 | } |
182 | 269 | ||
183 | // Remove the specified child from the linkset. | 270 | // Remove the specified child from the linkset. |
184 | // Safe to call even if the child is not really in my linkset. | 271 | // Safe to call even if the child is not really in the linkset. |
185 | protected override void RemoveChildFromLinkset(BSPhysObject child) | 272 | protected override void RemoveChildFromLinkset(BSPhysObject child) |
186 | { | 273 | { |
187 | if (m_children.Remove(child)) | 274 | if (m_children.Remove(child)) |
@@ -192,6 +279,7 @@ public sealed class BSLinksetCompound : BSLinkset | |||
192 | child.LocalID, child.PhysBody.ptr.ToString("X")); | 279 | child.LocalID, child.PhysBody.ptr.ToString("X")); |
193 | 280 | ||
194 | // Cause the child's body to be rebuilt and thus restored to normal operation | 281 | // Cause the child's body to be rebuilt and thus restored to normal operation |
282 | RecomputeChildWorldPosition(child, false); | ||
195 | child.ForceBodyShapeRebuild(false); | 283 | child.ForceBodyShapeRebuild(false); |
196 | 284 | ||
197 | if (!HasAnyChildren) | 285 | if (!HasAnyChildren) |
@@ -215,59 +303,83 @@ public sealed class BSLinksetCompound : BSLinkset | |||
215 | // Called at taint time!! | 303 | // Called at taint time!! |
216 | private void RecomputeLinksetCompound() | 304 | private void RecomputeLinksetCompound() |
217 | { | 305 | { |
218 | // Cause the root shape to be rebuilt as a compound object with just the root in it | 306 | try |
219 | LinksetRoot.ForceBodyShapeRebuild(true); | ||
220 | |||
221 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", | ||
222 | LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); | ||
223 | |||
224 | // Add a shape for each of the other children in the linkset | ||
225 | ForEachMember(delegate(BSPhysObject cPrim) | ||
226 | { | 307 | { |
227 | if (!IsRoot(cPrim)) | 308 | // Suppress rebuilding while rebuilding |
228 | { | 309 | Rebuilding = true; |
229 | // Each child position and rotation is given relative to the root. | ||
230 | OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); | ||
231 | OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; | ||
232 | OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; | ||
233 | 310 | ||
234 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", | 311 | // Cause the root shape to be rebuilt as a compound object with just the root in it |
235 | LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot); | 312 | LinksetRoot.ForceBodyShapeRebuild(true); |
236 | 313 | ||
237 | if (cPrim.PhysShape.isNativeShape) | 314 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", |
238 | { | 315 | LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); |
239 | // Native shapes are not shared so we need to create a new one. | 316 | |
240 | // A mesh or hull is created because scale is not available on a native shape. | 317 | // Add a shape for each of the other children in the linkset |
241 | // (TODO: Bullet does have a btScaledCollisionShape. Can that be used?) | 318 | ForEachMember(delegate(BSPhysObject cPrim) |
242 | BulletShape saveShape = cPrim.PhysShape; | 319 | { |
243 | cPrim.PhysShape.ptr = IntPtr.Zero; // Don't let the create free the child's shape | 320 | if (!IsRoot(cPrim)) |
244 | PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); | ||
245 | BulletShape newShape = cPrim.PhysShape; | ||
246 | cPrim.PhysShape = saveShape; | ||
247 | BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot); | ||
248 | } | ||
249 | else | ||
250 | { | 321 | { |
251 | // For the shared shapes (meshes and hulls), just use the shape in the child. | 322 | // Compute the displacement of the child from the root of the linkset. |
252 | if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) | 323 | // This info is saved in the child prim so the relationship does not |
324 | // change over time and the new child position can be computed | ||
325 | // when the linkset is being disassembled (the linkset may have moved). | ||
326 | BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo; | ||
327 | if (lci == null) | ||
253 | { | 328 | { |
254 | PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", | 329 | // Each child position and rotation is given relative to the root. |
255 | LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); | 330 | OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); |
331 | OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; | ||
332 | OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; | ||
333 | |||
334 | // Save relative position for recomputing child's world position after moving linkset. | ||
335 | lci = new BSLinksetCompoundInfo(displacementPos, displacementRot); | ||
336 | cPrim.LinksetInfo = lci; | ||
337 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci); | ||
256 | } | 338 | } |
257 | BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); | ||
258 | } | ||
259 | } | ||
260 | 339 | ||
261 | // TODO: need to phantomize the child prims left behind. | 340 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", |
262 | // Maybe just destroy the children bodies and shapes and have them rebuild on unlink. | 341 | LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot); |
263 | // Selection/deselection might cause way too many build/destructions esp. for LARGE linksets. | ||
264 | 342 | ||
265 | return false; // 'false' says to move onto the next child in the list | 343 | if (cPrim.PhysShape.isNativeShape) |
266 | }); | 344 | { |
345 | // A native shape is turning into a hull collision shape because native | ||
346 | // shapes are not shared so we have to hullify it so it will be tracked | ||
347 | // and freed at the correct time. This also solves the scaling problem | ||
348 | // (native shapes scaled but hull/meshes are assumed to not be). | ||
349 | // TODO: decide of the native shape can just be used in the compound shape. | ||
350 | // Use call to CreateGeomNonSpecial(). | ||
351 | BulletShape saveShape = cPrim.PhysShape; | ||
352 | cPrim.PhysShape.Clear(); // Don't let the create free the child's shape | ||
353 | // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null); | ||
354 | PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); | ||
355 | BulletShape newShape = cPrim.PhysShape; | ||
356 | cPrim.PhysShape = saveShape; | ||
357 | BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, lci.OffsetPos, lci.OffsetRot); | ||
358 | } | ||
359 | else | ||
360 | { | ||
361 | // For the shared shapes (meshes and hulls), just use the shape in the child. | ||
362 | // The reference count added here will be decremented when the compound shape | ||
363 | // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced). | ||
364 | if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) | ||
365 | { | ||
366 | PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", | ||
367 | LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); | ||
368 | } | ||
369 | BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, lci.OffsetPos, lci.OffsetRot); | ||
370 | } | ||
371 | } | ||
372 | return false; // 'false' says to move onto the next child in the list | ||
373 | }); | ||
267 | 374 | ||
268 | // With all of the linkset packed into the root prim, it has the mass of everyone. | 375 | // With all of the linkset packed into the root prim, it has the mass of everyone. |
269 | float linksetMass = LinksetMass; | 376 | float linksetMass = LinksetMass; |
270 | LinksetRoot.UpdatePhysicalMassProperties(linksetMass); | 377 | LinksetRoot.UpdatePhysicalMassProperties(linksetMass); |
378 | } | ||
379 | finally | ||
380 | { | ||
381 | Rebuilding = false; | ||
382 | } | ||
271 | 383 | ||
272 | BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr); | 384 | BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr); |
273 | 385 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index c855fda..732c084 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs | |||
@@ -36,9 +36,8 @@ public sealed class BSLinksetConstraints : BSLinkset | |||
36 | { | 36 | { |
37 | // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; | 37 | // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; |
38 | 38 | ||
39 | public BSLinksetConstraints(BSScene scene, BSPhysObject parent) | 39 | public BSLinksetConstraints(BSScene scene, BSPhysObject parent) : base(scene, parent) |
40 | { | 40 | { |
41 | base.Initialize(scene, parent); | ||
42 | } | 41 | } |
43 | 42 | ||
44 | // When physical properties are changed the linkset needs to recalculate | 43 | // When physical properties are changed the linkset needs to recalculate |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs index 390c2f9..c113a43 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs | |||
@@ -50,10 +50,11 @@ public struct MaterialAttributes | |||
50 | Avatar, | 50 | Avatar, |
51 | NumberOfTypes // the count of types in the enum. | 51 | NumberOfTypes // the count of types in the enum. |
52 | } | 52 | } |
53 | |||
53 | // Names must be in the order of the above enum. | 54 | // Names must be in the order of the above enum. |
54 | public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood", | 55 | // These names must coorespond to the lower case field names in the MaterialAttributes |
55 | "Flesh", "Plastic", "Rubber", "Light", "Avatar" }; | 56 | // structure as reflection is used to select the field to put the value in. |
56 | public static string[] MaterialAttribs = { "Density", "Friction", "Restitution"}; | 57 | public static readonly string[] MaterialAttribs = { "Density", "Friction", "Restitution"}; |
57 | 58 | ||
58 | public MaterialAttributes(string t, float d, float f, float r) | 59 | public MaterialAttributes(string t, float d, float f, float r) |
59 | { | 60 | { |
@@ -70,60 +71,74 @@ public struct MaterialAttributes | |||
70 | 71 | ||
71 | public static class BSMaterials | 72 | public static class BSMaterials |
72 | { | 73 | { |
73 | public static MaterialAttributes[] Attributes; | 74 | // Attributes for each material type |
75 | private static readonly MaterialAttributes[] Attributes; | ||
76 | |||
77 | // Map of material name to material type code | ||
78 | public static readonly Dictionary<string, MaterialAttributes.Material> MaterialMap; | ||
74 | 79 | ||
75 | static BSMaterials() | 80 | static BSMaterials() |
76 | { | 81 | { |
77 | // Attribute sets for both the non-physical and physical instances of materials. | 82 | // Attribute sets for both the non-physical and physical instances of materials. |
78 | Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2]; | 83 | Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2]; |
84 | |||
85 | // Map of name to type code. | ||
86 | MaterialMap = new Dictionary<string, MaterialAttributes.Material>(); | ||
87 | MaterialMap.Add("Stone", MaterialAttributes.Material.Stone); | ||
88 | MaterialMap.Add("Metal", MaterialAttributes.Material.Metal); | ||
89 | MaterialMap.Add("Glass", MaterialAttributes.Material.Glass); | ||
90 | MaterialMap.Add("Wood", MaterialAttributes.Material.Wood); | ||
91 | MaterialMap.Add("Flesh", MaterialAttributes.Material.Flesh); | ||
92 | MaterialMap.Add("Plastic", MaterialAttributes.Material.Plastic); | ||
93 | MaterialMap.Add("Rubber", MaterialAttributes.Material.Rubber); | ||
94 | MaterialMap.Add("Light", MaterialAttributes.Material.Light); | ||
95 | MaterialMap.Add("Avatar", MaterialAttributes.Material.Avatar); | ||
79 | } | 96 | } |
80 | 97 | ||
81 | // This is where all the default material attributes are defined. | 98 | // This is where all the default material attributes are defined. |
82 | public static void InitializeFromDefaults(ConfigurationParameters parms) | 99 | public static void InitializeFromDefaults(ConfigurationParameters parms) |
83 | { | 100 | { |
84 | // Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL | 101 | // Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL |
85 | // public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood", | 102 | float dDensity = parms.defaultDensity; |
86 | // "Flesh", "Plastic", "Rubber", "Light", "Avatar" }; | ||
87 | float dFriction = parms.defaultFriction; | 103 | float dFriction = parms.defaultFriction; |
88 | float dRestitution = parms.defaultRestitution; | 104 | float dRestitution = parms.defaultRestitution; |
89 | float dDensity = parms.defaultDensity; | ||
90 | Attributes[(int)MaterialAttributes.Material.Stone] = | 105 | Attributes[(int)MaterialAttributes.Material.Stone] = |
91 | new MaterialAttributes("stone",dDensity, 0.8f, 0.4f); | 106 | new MaterialAttributes("stone",dDensity, 0.8f, 0.4f); |
92 | Attributes[(int)MaterialAttributes.Material.Metal] = | 107 | Attributes[(int)MaterialAttributes.Material.Metal] = |
93 | new MaterialAttributes("metal",dDensity, 0.3f, 0.4f); | 108 | new MaterialAttributes("metal",dDensity, 0.3f, 0.4f); |
94 | Attributes[(int)MaterialAttributes.Material.Glass] = | 109 | Attributes[(int)MaterialAttributes.Material.Glass] = |
95 | new MaterialAttributes("glass",dDensity, 0.2f, 0.7f); | 110 | new MaterialAttributes("glass",dDensity, 0.2f, 0.7f); |
96 | Attributes[(int)MaterialAttributes.Material.Wood] = | 111 | Attributes[(int)MaterialAttributes.Material.Wood] = |
97 | new MaterialAttributes("wood",dDensity, 0.6f, 0.5f); | 112 | new MaterialAttributes("wood",dDensity, 0.6f, 0.5f); |
98 | Attributes[(int)MaterialAttributes.Material.Flesh] = | 113 | Attributes[(int)MaterialAttributes.Material.Flesh] = |
99 | new MaterialAttributes("flesh",dDensity, 0.9f, 0.3f); | 114 | new MaterialAttributes("flesh",dDensity, 0.9f, 0.3f); |
100 | Attributes[(int)MaterialAttributes.Material.Plastic] = | 115 | Attributes[(int)MaterialAttributes.Material.Plastic] = |
101 | new MaterialAttributes("plastic",dDensity, 0.4f, 0.7f); | 116 | new MaterialAttributes("plastic",dDensity, 0.4f, 0.7f); |
102 | Attributes[(int)MaterialAttributes.Material.Rubber] = | 117 | Attributes[(int)MaterialAttributes.Material.Rubber] = |
103 | new MaterialAttributes("rubber",dDensity, 0.9f, 0.9f); | 118 | new MaterialAttributes("rubber",dDensity, 0.9f, 0.9f); |
104 | Attributes[(int)MaterialAttributes.Material.Light] = | 119 | Attributes[(int)MaterialAttributes.Material.Light] = |
105 | new MaterialAttributes("light",dDensity, dFriction, dRestitution); | 120 | new MaterialAttributes("light",dDensity, dFriction, dRestitution); |
106 | Attributes[(int)MaterialAttributes.Material.Avatar] = | 121 | Attributes[(int)MaterialAttributes.Material.Avatar] = |
107 | new MaterialAttributes("avatar",60f, 0.2f, 0f); | 122 | new MaterialAttributes("avatar",60f, 0.2f, 0f); |
108 | 123 | ||
109 | Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] = | 124 | Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] = |
110 | new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f); | 125 | new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f); |
111 | Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] = | 126 | Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] = |
112 | new MaterialAttributes("metalPhysical",dDensity, 0.8f, 0.4f); | 127 | new MaterialAttributes("metalPhysical",dDensity, 0.8f, 0.4f); |
113 | Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] = | 128 | Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] = |
114 | new MaterialAttributes("glassPhysical",dDensity, 0.8f, 0.7f); | 129 | new MaterialAttributes("glassPhysical",dDensity, 0.8f, 0.7f); |
115 | Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] = | 130 | Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] = |
116 | new MaterialAttributes("woodPhysical",dDensity, 0.8f, 0.5f); | 131 | new MaterialAttributes("woodPhysical",dDensity, 0.8f, 0.5f); |
117 | Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] = | 132 | Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] = |
118 | new MaterialAttributes("fleshPhysical",dDensity, 0.8f, 0.3f); | 133 | new MaterialAttributes("fleshPhysical",dDensity, 0.8f, 0.3f); |
119 | Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] = | 134 | Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] = |
120 | new MaterialAttributes("plasticPhysical",dDensity, 0.8f, 0.7f); | 135 | new MaterialAttributes("plasticPhysical",dDensity, 0.8f, 0.7f); |
121 | Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] = | 136 | Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] = |
122 | new MaterialAttributes("rubberPhysical",dDensity, 0.8f, 0.9f); | 137 | new MaterialAttributes("rubberPhysical",dDensity, 0.8f, 0.9f); |
123 | Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] = | 138 | Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] = |
124 | new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution); | 139 | new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution); |
125 | Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] = | 140 | Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] = |
126 | new MaterialAttributes("avatarPhysical",60f, 0.2f, 0f); | 141 | new MaterialAttributes("avatarPhysical",60f, 0.2f, 0f); |
127 | } | 142 | } |
128 | 143 | ||
129 | // Under the [BulletSim] section, one can change the individual material | 144 | // Under the [BulletSim] section, one can change the individual material |
@@ -139,34 +154,34 @@ public static class BSMaterials | |||
139 | // the physical value. | 154 | // the physical value. |
140 | public static void InitializefromParameters(IConfig pConfig) | 155 | public static void InitializefromParameters(IConfig pConfig) |
141 | { | 156 | { |
142 | int matType = 0; | 157 | foreach (KeyValuePair<string, MaterialAttributes.Material> kvp in MaterialMap) |
143 | foreach (string matName in MaterialAttributes.MaterialNames) | ||
144 | { | 158 | { |
159 | string matName = kvp.Key; | ||
145 | foreach (string attribName in MaterialAttributes.MaterialAttribs) | 160 | foreach (string attribName in MaterialAttributes.MaterialAttribs) |
146 | { | 161 | { |
147 | string paramName = matName + attribName; | 162 | string paramName = matName + attribName; |
148 | if (pConfig.Contains(paramName)) | 163 | if (pConfig.Contains(paramName)) |
149 | { | 164 | { |
150 | float paramValue = pConfig.GetFloat(paramName); | 165 | float paramValue = pConfig.GetFloat(paramName); |
151 | SetAttributeValue(matType, attribName, paramValue); | 166 | SetAttributeValue((int)kvp.Value, attribName, paramValue); |
152 | // set the physical value also | 167 | // set the physical value also |
153 | SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); | 168 | SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); |
154 | } | 169 | } |
155 | paramName += "Physical"; | 170 | paramName += "Physical"; |
156 | if (pConfig.Contains(paramName)) | 171 | if (pConfig.Contains(paramName)) |
157 | { | 172 | { |
158 | float paramValue = pConfig.GetFloat(paramName); | 173 | float paramValue = pConfig.GetFloat(paramName); |
159 | SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); | 174 | SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue); |
160 | } | 175 | } |
161 | } | 176 | } |
162 | matType++; | ||
163 | } | 177 | } |
164 | } | 178 | } |
165 | 179 | ||
180 | // Use reflection to set the value in the attribute structure. | ||
166 | private static void SetAttributeValue(int matType, string attribName, float val) | 181 | private static void SetAttributeValue(int matType, string attribName, float val) |
167 | { | 182 | { |
168 | MaterialAttributes thisAttrib = Attributes[matType]; | 183 | MaterialAttributes thisAttrib = Attributes[matType]; |
169 | FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName); | 184 | FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName.ToLower()); |
170 | if (fieldInfo != null) | 185 | if (fieldInfo != null) |
171 | { | 186 | { |
172 | fieldInfo.SetValue(thisAttrib, val); | 187 | fieldInfo.SetValue(thisAttrib, val); |
@@ -174,12 +189,12 @@ public static class BSMaterials | |||
174 | } | 189 | } |
175 | } | 190 | } |
176 | 191 | ||
192 | // Given a material type, return a structure of attributes. | ||
177 | public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical) | 193 | public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical) |
178 | { | 194 | { |
179 | int ind = (int)type; | 195 | int ind = (int)type; |
180 | if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes; | 196 | if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes; |
181 | return Attributes[ind]; | 197 | return Attributes[ind]; |
182 | } | 198 | } |
183 | |||
184 | } | 199 | } |
185 | } | 200 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs index 851d508..cf0a9dc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs | |||
@@ -65,7 +65,7 @@ public abstract class BSMotor | |||
65 | // Can all the incremental stepping be replaced with motor classes? | 65 | // Can all the incremental stepping be replaced with motor classes? |
66 | 66 | ||
67 | // Motor which moves CurrentValue to TargetValue over TimeScale seconds. | 67 | // Motor which moves CurrentValue to TargetValue over TimeScale seconds. |
68 | // The TargetValue is decays in TargetValueDecayTimeScale and | 68 | // The TargetValue decays in TargetValueDecayTimeScale and |
69 | // the CurrentValue will be held back by FrictionTimeScale. | 69 | // the CurrentValue will be held back by FrictionTimeScale. |
70 | // TimeScale and TargetDelayTimeScale may be 'infinite' which means go decay. | 70 | // TimeScale and TargetDelayTimeScale may be 'infinite' which means go decay. |
71 | 71 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index f6a890e..6539b43 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | |||
@@ -60,6 +60,9 @@ public abstract class BSPhysObject : PhysicsActor | |||
60 | Linkset = BSLinkset.Factory(PhysicsScene, this); | 60 | Linkset = BSLinkset.Factory(PhysicsScene, this); |
61 | LastAssetBuildFailed = false; | 61 | LastAssetBuildFailed = false; |
62 | 62 | ||
63 | // Default material type | ||
64 | Material = MaterialAttributes.Material.Wood; | ||
65 | |||
63 | CollisionCollection = new CollisionEventUpdate(); | 66 | CollisionCollection = new CollisionEventUpdate(); |
64 | SubscribedEventsMs = 0; | 67 | SubscribedEventsMs = 0; |
65 | CollidingStep = 0; | 68 | CollidingStep = 0; |
@@ -72,6 +75,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
72 | public string TypeName { get; protected set; } | 75 | public string TypeName { get; protected set; } |
73 | 76 | ||
74 | public BSLinkset Linkset { get; set; } | 77 | public BSLinkset Linkset { get; set; } |
78 | public BSLinksetInfo LinksetInfo { get; set; } | ||
75 | 79 | ||
76 | // Return the object mass without calculating it or having side effects | 80 | // Return the object mass without calculating it or having side effects |
77 | public abstract float RawMass { get; } | 81 | public abstract float RawMass { get; } |
@@ -105,10 +109,17 @@ public abstract class BSPhysObject : PhysicsActor | |||
105 | public EntityProperties CurrentEntityProperties { get; set; } | 109 | public EntityProperties CurrentEntityProperties { get; set; } |
106 | public EntityProperties LastEntityProperties { get; set; } | 110 | public EntityProperties LastEntityProperties { get; set; } |
107 | 111 | ||
108 | public abstract OMV.Vector3 Scale { get; set; } | 112 | public virtual OMV.Vector3 Scale { get; set; } |
109 | public abstract bool IsSolid { get; } | 113 | public abstract bool IsSolid { get; } |
110 | public abstract bool IsStatic { get; } | 114 | public abstract bool IsStatic { get; } |
111 | 115 | ||
116 | // Materialness | ||
117 | public MaterialAttributes.Material Material { get; private set; } | ||
118 | public override void SetMaterial(int material) | ||
119 | { | ||
120 | Material = (MaterialAttributes.Material)material; | ||
121 | } | ||
122 | |||
112 | // Stop all physical motion. | 123 | // Stop all physical motion. |
113 | public abstract void ZeroMotion(bool inTaintTime); | 124 | public abstract void ZeroMotion(bool inTaintTime); |
114 | public abstract void ZeroAngularMotion(bool inTaintTime); | 125 | public abstract void ZeroAngularMotion(bool inTaintTime); |
@@ -128,6 +139,17 @@ public abstract class BSPhysObject : PhysicsActor | |||
128 | public abstract OMV.Quaternion RawOrientation { get; set; } | 139 | public abstract OMV.Quaternion RawOrientation { get; set; } |
129 | public abstract OMV.Quaternion ForceOrientation { get; set; } | 140 | public abstract OMV.Quaternion ForceOrientation { get; set; } |
130 | 141 | ||
142 | // The system is telling us the velocity it wants to move at. | ||
143 | protected OMV.Vector3 m_targetVelocity; | ||
144 | public override OMV.Vector3 TargetVelocity | ||
145 | { | ||
146 | get { return m_targetVelocity; } | ||
147 | set | ||
148 | { | ||
149 | m_targetVelocity = value; | ||
150 | Velocity = value; | ||
151 | } | ||
152 | } | ||
131 | public abstract OMV.Vector3 ForceVelocity { get; set; } | 153 | public abstract OMV.Vector3 ForceVelocity { get; set; } |
132 | 154 | ||
133 | public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } | 155 | public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } |
@@ -243,7 +265,9 @@ public abstract class BSPhysObject : PhysicsActor | |||
243 | SubscribedEventsMs = 0; | 265 | SubscribedEventsMs = 0; |
244 | PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() | 266 | PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() |
245 | { | 267 | { |
246 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | 268 | // Make sure there is a body there because sometimes destruction happens in an un-ideal order. |
269 | if (PhysBody.HasPhysicalBody) | ||
270 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
247 | }); | 271 | }); |
248 | } | 272 | } |
249 | // Return 'true' if the simulator wants collision events | 273 | // Return 'true' if the simulator wants collision events |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 4d203ff..c9c9c2c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -45,7 +45,6 @@ public sealed class BSPrim : BSPhysObject | |||
45 | private static readonly string LogHeader = "[BULLETS PRIM]"; | 45 | private static readonly string LogHeader = "[BULLETS PRIM]"; |
46 | 46 | ||
47 | // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. | 47 | // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. |
48 | // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. | ||
49 | private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user | 48 | private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user |
50 | 49 | ||
51 | private bool _grabbed; | 50 | private bool _grabbed; |
@@ -93,7 +92,7 @@ public sealed class BSPrim : BSPhysObject | |||
93 | _physicsActorType = (int)ActorTypes.Prim; | 92 | _physicsActorType = (int)ActorTypes.Prim; |
94 | _position = pos; | 93 | _position = pos; |
95 | _size = size; | 94 | _size = size; |
96 | Scale = size; // the scale will be set by CreateGeom depending on object type | 95 | Scale = size; // prims are the size the user wants them to be (different for BSCharactes). |
97 | _orientation = rotation; | 96 | _orientation = rotation; |
98 | _buoyancy = 1f; | 97 | _buoyancy = 1f; |
99 | _velocity = OMV.Vector3.Zero; | 98 | _velocity = OMV.Vector3.Zero; |
@@ -108,8 +107,8 @@ public sealed class BSPrim : BSPhysObject | |||
108 | _mass = CalculateMass(); | 107 | _mass = CalculateMass(); |
109 | 108 | ||
110 | // No body or shape yet | 109 | // No body or shape yet |
111 | PhysBody = new BulletBody(LocalID, IntPtr.Zero); | 110 | PhysBody = new BulletBody(LocalID); |
112 | PhysShape = new BulletShape(IntPtr.Zero); | 111 | PhysShape = new BulletShape(); |
113 | 112 | ||
114 | DetailLog("{0},BSPrim.constructor,call", LocalID); | 113 | DetailLog("{0},BSPrim.constructor,call", LocalID); |
115 | // do the actual object creation at taint time | 114 | // do the actual object creation at taint time |
@@ -143,7 +142,9 @@ public sealed class BSPrim : BSPhysObject | |||
143 | DetailLog("{0},BSPrim.Destroy,taint,", LocalID); | 142 | DetailLog("{0},BSPrim.Destroy,taint,", LocalID); |
144 | // If there are physical body and shape, release my use of same. | 143 | // If there are physical body and shape, release my use of same. |
145 | PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); | 144 | PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); |
145 | PhysBody.Clear(); | ||
146 | PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); | 146 | PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); |
147 | PhysShape.Clear(); | ||
147 | }); | 148 | }); |
148 | } | 149 | } |
149 | 150 | ||
@@ -157,12 +158,10 @@ public sealed class BSPrim : BSPhysObject | |||
157 | // We presume the scale and size are the same. If scale must be changed for | 158 | // We presume the scale and size are the same. If scale must be changed for |
158 | // the physical shape, that is done when the geometry is built. | 159 | // the physical shape, that is done when the geometry is built. |
159 | _size = value; | 160 | _size = value; |
161 | Scale = _size; | ||
160 | ForceBodyShapeRebuild(false); | 162 | ForceBodyShapeRebuild(false); |
161 | } | 163 | } |
162 | } | 164 | } |
163 | // Scale is what we set in the physics engine. It is different than 'size' in that | ||
164 | // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>. | ||
165 | public override OMV.Vector3 Scale { get; set; } | ||
166 | 165 | ||
167 | public override PrimitiveBaseShape Shape { | 166 | public override PrimitiveBaseShape Shape { |
168 | set { | 167 | set { |
@@ -189,7 +188,8 @@ public sealed class BSPrim : BSPhysObject | |||
189 | } | 188 | } |
190 | } | 189 | } |
191 | public override bool Selected { | 190 | public override bool Selected { |
192 | set { | 191 | set |
192 | { | ||
193 | if (value != _isSelected) | 193 | if (value != _isSelected) |
194 | { | 194 | { |
195 | _isSelected = value; | 195 | _isSelected = value; |
@@ -247,7 +247,8 @@ public sealed class BSPrim : BSPhysObject | |||
247 | // Zero some other properties in the physics engine | 247 | // Zero some other properties in the physics engine |
248 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() | 248 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() |
249 | { | 249 | { |
250 | BulletSimAPI.ClearAllForces2(PhysBody.ptr); | 250 | if (PhysBody.HasPhysicalBody) |
251 | BulletSimAPI.ClearAllForces2(PhysBody.ptr); | ||
251 | }); | 252 | }); |
252 | } | 253 | } |
253 | public override void ZeroAngularMotion(bool inTaintTime) | 254 | public override void ZeroAngularMotion(bool inTaintTime) |
@@ -257,8 +258,11 @@ public sealed class BSPrim : BSPhysObject | |||
257 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() | 258 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() |
258 | { | 259 | { |
259 | // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); | 260 | // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); |
260 | BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, _rotationalVelocity); | 261 | if (PhysBody.HasPhysicalBody) |
261 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); | 262 | { |
263 | BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, _rotationalVelocity); | ||
264 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); | ||
265 | } | ||
262 | }); | 266 | }); |
263 | } | 267 | } |
264 | 268 | ||
@@ -295,8 +299,11 @@ public sealed class BSPrim : BSPhysObject | |||
295 | PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() | 299 | PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() |
296 | { | 300 | { |
297 | // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 301 | // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
298 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 302 | if (PhysBody.HasPhysicalBody) |
299 | ActivateIfPhysical(false); | 303 | { |
304 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
305 | ActivateIfPhysical(false); | ||
306 | } | ||
300 | }); | 307 | }); |
301 | } | 308 | } |
302 | } | 309 | } |
@@ -322,12 +329,12 @@ public sealed class BSPrim : BSPhysObject | |||
322 | 329 | ||
323 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); | 330 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); |
324 | OMV.Vector3 upForce = OMV.Vector3.Zero; | 331 | OMV.Vector3 upForce = OMV.Vector3.Zero; |
325 | if (Position.Z < terrainHeight) | 332 | if (RawPosition.Z < terrainHeight) |
326 | { | 333 | { |
327 | DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); | 334 | DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); |
328 | float targetHeight = terrainHeight + (Size.Z / 2f); | 335 | float targetHeight = terrainHeight + (Size.Z / 2f); |
329 | // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec. | 336 | // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec. |
330 | upForce.Z = (terrainHeight - Position.Z) * 1f; | 337 | upForce.Z = (terrainHeight - RawPosition.Z) * 1f; |
331 | ret = true; | 338 | ret = true; |
332 | } | 339 | } |
333 | 340 | ||
@@ -335,10 +342,10 @@ public sealed class BSPrim : BSPhysObject | |||
335 | { | 342 | { |
336 | float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); | 343 | float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); |
337 | // TODO: a floating motor so object will bob in the water | 344 | // TODO: a floating motor so object will bob in the water |
338 | if (Math.Abs(Position.Z - waterHeight) > 0.1f) | 345 | if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) |
339 | { | 346 | { |
340 | // Upforce proportional to the distance away from the water. Correct the error in 1 sec. | 347 | // Upforce proportional to the distance away from the water. Correct the error in 1 sec. |
341 | upForce.Z = (waterHeight - Position.Z) * 1f; | 348 | upForce.Z = (waterHeight - RawPosition.Z) * 1f; |
342 | ret = true; | 349 | ret = true; |
343 | } | 350 | } |
344 | } | 351 | } |
@@ -413,7 +420,8 @@ public sealed class BSPrim : BSPhysObject | |||
413 | PhysicsScene.TaintedObject("BSPrim.setForce", delegate() | 420 | PhysicsScene.TaintedObject("BSPrim.setForce", delegate() |
414 | { | 421 | { |
415 | // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); | 422 | // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); |
416 | BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); | 423 | if (PhysBody.HasPhysicalBody) |
424 | BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); | ||
417 | }); | 425 | }); |
418 | } | 426 | } |
419 | } | 427 | } |
@@ -507,7 +515,8 @@ public sealed class BSPrim : BSPhysObject | |||
507 | PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() | 515 | PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() |
508 | { | 516 | { |
509 | // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); | 517 | // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); |
510 | BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); | 518 | if (PhysBody.HasPhysicalBody) |
519 | BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); | ||
511 | }); | 520 | }); |
512 | } | 521 | } |
513 | } | 522 | } |
@@ -556,9 +565,12 @@ public sealed class BSPrim : BSPhysObject | |||
556 | // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? | 565 | // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? |
557 | PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() | 566 | PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() |
558 | { | 567 | { |
559 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); | 568 | if (PhysBody.HasPhysicalBody) |
560 | // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 569 | { |
561 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 570 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); |
571 | // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); | ||
572 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
573 | } | ||
562 | }); | 574 | }); |
563 | } | 575 | } |
564 | } | 576 | } |
@@ -649,14 +661,7 @@ public sealed class BSPrim : BSPhysObject | |||
649 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); | 661 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); |
650 | 662 | ||
651 | // Collision filter can be set only when the object is in the world | 663 | // Collision filter can be set only when the object is in the world |
652 | if (PhysBody.collisionGroup != 0 || PhysBody.collisionMask != 0) | 664 | PhysBody.ApplyCollisionMask(); |
653 | { | ||
654 | if (!BulletSimAPI.SetCollisionGroupMask2(PhysBody.ptr, (uint)PhysBody.collisionGroup, (uint)PhysBody.collisionMask)) | ||
655 | { | ||
656 | PhysicsScene.Logger.ErrorFormat("{0} Failure setting prim collision mask. localID={1}, grp={2:X}, mask={3:X}", | ||
657 | LogHeader, LocalID, PhysBody.collisionGroup, PhysBody.collisionMask); | ||
658 | } | ||
659 | } | ||
660 | 665 | ||
661 | // Recompute any linkset parameters. | 666 | // Recompute any linkset parameters. |
662 | // When going from non-physical to physical, this re-enables the constraints that | 667 | // When going from non-physical to physical, this re-enables the constraints that |
@@ -683,8 +688,9 @@ public sealed class BSPrim : BSPhysObject | |||
683 | ZeroMotion(true); | 688 | ZeroMotion(true); |
684 | 689 | ||
685 | // Set various physical properties so other object interact properly | 690 | // Set various physical properties so other object interact properly |
686 | BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction); | 691 | MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false); |
687 | BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution); | 692 | BulletSimAPI.SetFriction2(PhysBody.ptr, matAttrib.friction); |
693 | BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution); | ||
688 | 694 | ||
689 | // Mass is zero which disables a bunch of physics stuff in Bullet | 695 | // Mass is zero which disables a bunch of physics stuff in Bullet |
690 | UpdatePhysicalMassProperties(0f); | 696 | UpdatePhysicalMassProperties(0f); |
@@ -700,20 +706,21 @@ public sealed class BSPrim : BSPhysObject | |||
700 | // Start it out sleeping and physical actions could wake it up. | 706 | // Start it out sleeping and physical actions could wake it up. |
701 | BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ISLAND_SLEEPING); | 707 | BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ISLAND_SLEEPING); |
702 | 708 | ||
709 | // This collides like a static object | ||
710 | PhysBody.collisionType = CollisionType.Static; | ||
711 | |||
703 | // There can be special things needed for implementing linksets | 712 | // There can be special things needed for implementing linksets |
704 | Linkset.MakeStatic(this); | 713 | Linkset.MakeStatic(this); |
705 | |||
706 | PhysBody.collisionGroup = CollisionFilterGroups.StaticObjectGroup; | ||
707 | PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask; | ||
708 | } | 714 | } |
709 | else | 715 | else |
710 | { | 716 | { |
711 | // Not a Bullet static object | 717 | // Not a Bullet static object |
712 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); | 718 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); |
713 | 719 | ||
714 | // Set various physical properties so internal dynamic properties will get computed correctly as they are set | 720 | // Set various physical properties so other object interact properly |
715 | BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction); | 721 | MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, true); |
716 | BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution); | 722 | BulletSimAPI.SetFriction2(PhysBody.ptr, matAttrib.friction); |
723 | BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution); | ||
717 | 724 | ||
718 | // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 | 725 | // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 |
719 | // Since this can be called multiple times, only zero forces when becoming physical | 726 | // Since this can be called multiple times, only zero forces when becoming physical |
@@ -741,16 +748,15 @@ public sealed class BSPrim : BSPhysObject | |||
741 | BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); | 748 | BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); |
742 | BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); | 749 | BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); |
743 | 750 | ||
744 | // There might be special things needed for implementing linksets. | 751 | // This collides like an object. |
745 | Linkset.MakeDynamic(this); | 752 | PhysBody.collisionType = CollisionType.Dynamic; |
746 | 753 | ||
747 | // Force activation of the object so Bullet will act on it. | 754 | // Force activation of the object so Bullet will act on it. |
748 | // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. | 755 | // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. |
749 | BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG); | 756 | BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG); |
750 | // BulletSimAPI.Activate2(BSBody.ptr, true); | ||
751 | 757 | ||
752 | PhysBody.collisionGroup = CollisionFilterGroups.ObjectGroup; | 758 | // There might be special things needed for implementing linksets. |
753 | PhysBody.collisionMask = CollisionFilterGroups.ObjectMask; | 759 | Linkset.MakeDynamic(this); |
754 | } | 760 | } |
755 | } | 761 | } |
756 | 762 | ||
@@ -777,8 +783,9 @@ public sealed class BSPrim : BSPhysObject | |||
777 | m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); | 783 | m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); |
778 | } | 784 | } |
779 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | 785 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); |
780 | PhysBody.collisionGroup = CollisionFilterGroups.VolumeDetectGroup; | 786 | |
781 | PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; | 787 | // Change collision info from a static object to a ghosty collision object |
788 | PhysBody.collisionType = CollisionType.VolumeDetect; | ||
782 | } | 789 | } |
783 | } | 790 | } |
784 | 791 | ||
@@ -861,7 +868,8 @@ public sealed class BSPrim : BSPhysObject | |||
861 | PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() | 868 | PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() |
862 | { | 869 | { |
863 | DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); | 870 | DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); |
864 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); | 871 | if (PhysBody.HasPhysicalBody) |
872 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); | ||
865 | }); | 873 | }); |
866 | } | 874 | } |
867 | } | 875 | } |
@@ -896,8 +904,11 @@ public sealed class BSPrim : BSPhysObject | |||
896 | _buoyancy = value; | 904 | _buoyancy = value; |
897 | // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 905 | // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
898 | // Buoyancy is faked by changing the gravity applied to the object | 906 | // Buoyancy is faked by changing the gravity applied to the object |
899 | float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); | 907 | if (PhysBody.HasPhysicalBody) |
900 | BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); | 908 | { |
909 | float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); | ||
910 | BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); | ||
911 | } | ||
901 | } | 912 | } |
902 | } | 913 | } |
903 | 914 | ||
@@ -965,7 +976,8 @@ public sealed class BSPrim : BSPhysObject | |||
965 | } | 976 | } |
966 | DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); | 977 | DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); |
967 | if (fSum != OMV.Vector3.Zero) | 978 | if (fSum != OMV.Vector3.Zero) |
968 | BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); | 979 | if (PhysBody.HasPhysicalBody) |
980 | BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); | ||
969 | }); | 981 | }); |
970 | } | 982 | } |
971 | 983 | ||
@@ -976,7 +988,8 @@ public sealed class BSPrim : BSPhysObject | |||
976 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate() | 988 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate() |
977 | { | 989 | { |
978 | DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse); | 990 | DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse); |
979 | BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse); | 991 | if (PhysBody.HasPhysicalBody) |
992 | BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse); | ||
980 | }); | 993 | }); |
981 | } | 994 | } |
982 | 995 | ||
@@ -1012,7 +1025,8 @@ public sealed class BSPrim : BSPhysObject | |||
1012 | DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); | 1025 | DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); |
1013 | if (fSum != OMV.Vector3.Zero) | 1026 | if (fSum != OMV.Vector3.Zero) |
1014 | { | 1027 | { |
1015 | BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); | 1028 | if (PhysBody.HasPhysicalBody) |
1029 | BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); | ||
1016 | _torque = fSum; | 1030 | _torque = fSum; |
1017 | } | 1031 | } |
1018 | }); | 1032 | }); |
@@ -1026,7 +1040,8 @@ public sealed class BSPrim : BSPhysObject | |||
1026 | OMV.Vector3 applyImpulse = impulse; | 1040 | OMV.Vector3 applyImpulse = impulse; |
1027 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() | 1041 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() |
1028 | { | 1042 | { |
1029 | BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); | 1043 | if (PhysBody.HasPhysicalBody) |
1044 | BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); | ||
1030 | }); | 1045 | }); |
1031 | } | 1046 | } |
1032 | 1047 | ||
@@ -1344,7 +1359,6 @@ public sealed class BSPrim : BSPhysObject | |||
1344 | // Create the correct physical representation for this type of object. | 1359 | // Create the correct physical representation for this type of object. |
1345 | // Updates PhysBody and PhysShape with the new information. | 1360 | // Updates PhysBody and PhysShape with the new information. |
1346 | // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. | 1361 | // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. |
1347 | // Returns 'true' if either the body or the shape was changed. | ||
1348 | PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) | 1362 | PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) |
1349 | { | 1363 | { |
1350 | // Called if the current prim body is about to be destroyed. | 1364 | // Called if the current prim body is about to be destroyed. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index f72bd74..cf5bb57 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -188,6 +188,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
188 | private bool m_physicsLoggingDoFlush; | 188 | private bool m_physicsLoggingDoFlush; |
189 | // 'true' of the vehicle code is to log lots of details | 189 | // 'true' of the vehicle code is to log lots of details |
190 | public bool VehicleLoggingEnabled { get; private set; } | 190 | public bool VehicleLoggingEnabled { get; private set; } |
191 | public bool VehiclePhysicalLoggingEnabled { get; private set; } | ||
192 | public bool VehicleScaleAngularVelocityByTimestep { get; private set; } | ||
191 | 193 | ||
192 | #region Construction and Initialization | 194 | #region Construction and Initialization |
193 | public BSScene(string identifier) | 195 | public BSScene(string identifier) |
@@ -297,6 +299,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
297 | m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false); | 299 | m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false); |
298 | // Very detailed logging for vehicle debugging | 300 | // Very detailed logging for vehicle debugging |
299 | VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); | 301 | VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); |
302 | VehiclePhysicalLoggingEnabled = pConfig.GetBoolean("VehiclePhysicalLoggingEnabled", false); | ||
300 | 303 | ||
301 | // Do any replacements in the parameters | 304 | // Do any replacements in the parameters |
302 | m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); | 305 | m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); |
@@ -306,6 +309,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
306 | BSMaterials.InitializeFromDefaults(Params); | 309 | BSMaterials.InitializeFromDefaults(Params); |
307 | if (pConfig != null) | 310 | if (pConfig != null) |
308 | { | 311 | { |
312 | // Let the user add new and interesting material property values. | ||
309 | BSMaterials.InitializefromParameters(pConfig); | 313 | BSMaterials.InitializefromParameters(pConfig); |
310 | } | 314 | } |
311 | } | 315 | } |
@@ -501,7 +505,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
501 | 505 | ||
502 | try | 506 | try |
503 | { | 507 | { |
504 | if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG | 508 | if (VehiclePhysicalLoggingEnabled) DumpVehicles(); // DEBUG |
505 | if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); | 509 | if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); |
506 | 510 | ||
507 | numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, | 511 | numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, |
@@ -510,7 +514,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
510 | if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); | 514 | if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); |
511 | DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", | 515 | DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", |
512 | DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); | 516 | DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); |
513 | if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG | 517 | if (VehiclePhysicalLoggingEnabled) DumpVehicles(); // DEBUG |
514 | } | 518 | } |
515 | catch (Exception e) | 519 | catch (Exception e) |
516 | { | 520 | { |
@@ -1226,6 +1230,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1226 | (s,cf,p,v) => { s.m_params[0].vehicleAngularDamping = cf.GetFloat(p, v); }, | 1230 | (s,cf,p,v) => { s.m_params[0].vehicleAngularDamping = cf.GetFloat(p, v); }, |
1227 | (s) => { return s.m_params[0].vehicleAngularDamping; }, | 1231 | (s) => { return s.m_params[0].vehicleAngularDamping; }, |
1228 | (s,p,l,v) => { s.m_params[0].vehicleAngularDamping = v; } ), | 1232 | (s,p,l,v) => { s.m_params[0].vehicleAngularDamping = v; } ), |
1233 | new ParameterDefn("VehicleScaleAngularVelocityByTimestep", "If true, scale angular turning by timestep", | ||
1234 | ConfigurationParameters.numericFalse, | ||
1235 | (s,cf,p,v) => { s.VehicleScaleAngularVelocityByTimestep = cf.GetBoolean(p, s.BoolNumeric(v)); }, | ||
1236 | (s) => { return s.NumericBool(s.VehicleScaleAngularVelocityByTimestep); }, | ||
1237 | (s,p,l,v) => { s.VehicleScaleAngularVelocityByTimestep = s.BoolNumeric(v); } ), | ||
1229 | 1238 | ||
1230 | new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", | 1239 | new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", |
1231 | 0f, | 1240 | 0f, |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index a77dee9..d6e2fe9 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | |||
@@ -126,6 +126,11 @@ public sealed class BSShapeCollection : IDisposable | |||
126 | return ret; | 126 | return ret; |
127 | } | 127 | } |
128 | 128 | ||
129 | public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim) | ||
130 | { | ||
131 | return GetBodyAndShape(forceRebuild, sim, prim, null, null); | ||
132 | } | ||
133 | |||
129 | // Track another user of a body. | 134 | // Track another user of a body. |
130 | // We presume the caller has allocated the body. | 135 | // We presume the caller has allocated the body. |
131 | // Bodies only have one user so the body is just put into the world if not already there. | 136 | // Bodies only have one user so the body is just put into the world if not already there. |
@@ -149,7 +154,7 @@ public sealed class BSShapeCollection : IDisposable | |||
149 | // Called when releasing use of a BSBody. BSShape is handled separately. | 154 | // Called when releasing use of a BSBody. BSShape is handled separately. |
150 | public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) | 155 | public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) |
151 | { | 156 | { |
152 | if (body.ptr == IntPtr.Zero) | 157 | if (!body.HasPhysicalBody) |
153 | return; | 158 | return; |
154 | 159 | ||
155 | lock (m_collectionActivityLock) | 160 | lock (m_collectionActivityLock) |
@@ -243,12 +248,12 @@ public sealed class BSShapeCollection : IDisposable | |||
243 | // Release the usage of a shape. | 248 | // Release the usage of a shape. |
244 | public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) | 249 | public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) |
245 | { | 250 | { |
246 | if (shape.ptr == IntPtr.Zero) | 251 | if (!shape.HasPhysicalShape) |
247 | return; | 252 | return; |
248 | 253 | ||
249 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() | 254 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() |
250 | { | 255 | { |
251 | if (shape.ptr != IntPtr.Zero) | 256 | if (shape.HasPhysicalShape) |
252 | { | 257 | { |
253 | if (shape.isNativeShape) | 258 | if (shape.isNativeShape) |
254 | { | 259 | { |
@@ -440,7 +445,7 @@ public sealed class BSShapeCollection : IDisposable | |||
440 | } | 445 | } |
441 | 446 | ||
442 | // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. | 447 | // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. |
443 | private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) | 448 | public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) |
444 | { | 449 | { |
445 | bool ret = false; | 450 | bool ret = false; |
446 | bool haveShape = false; | 451 | bool haveShape = false; |
@@ -460,6 +465,11 @@ public sealed class BSShapeCollection : IDisposable | |||
460 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 | 465 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 |
461 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) | 466 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) |
462 | { | 467 | { |
468 | // Get the scale of any existing shape so we can see if the new shape is same native type and same size. | ||
469 | OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero; | ||
470 | if (prim.PhysShape.HasPhysicalShape) | ||
471 | scaleOfExistingShape = BulletSimAPI.GetLocalScaling2(prim.PhysShape.ptr); | ||
472 | |||
463 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}", | 473 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}", |
464 | prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type); | 474 | prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type); |
465 | 475 | ||
@@ -469,7 +479,7 @@ public sealed class BSShapeCollection : IDisposable | |||
469 | { | 479 | { |
470 | haveShape = true; | 480 | haveShape = true; |
471 | if (forceRebuild | 481 | if (forceRebuild |
472 | || prim.Scale != prim.Size | 482 | || prim.Scale != scaleOfExistingShape |
473 | || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE | 483 | || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE |
474 | ) | 484 | ) |
475 | { | 485 | { |
@@ -483,7 +493,7 @@ public sealed class BSShapeCollection : IDisposable | |||
483 | { | 493 | { |
484 | haveShape = true; | 494 | haveShape = true; |
485 | if (forceRebuild | 495 | if (forceRebuild |
486 | || prim.Scale != prim.Size | 496 | || prim.Scale != scaleOfExistingShape |
487 | || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX | 497 | || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX |
488 | ) | 498 | ) |
489 | { | 499 | { |
@@ -542,7 +552,6 @@ public sealed class BSShapeCollection : IDisposable | |||
542 | prim.LocalID, newShape, prim.Scale); | 552 | prim.LocalID, newShape, prim.Scale); |
543 | 553 | ||
544 | // native shapes are scaled by Bullet | 554 | // native shapes are scaled by Bullet |
545 | prim.Scale = prim.Size; | ||
546 | prim.PhysShape = newShape; | 555 | prim.PhysShape = newShape; |
547 | return true; | 556 | return true; |
548 | } | 557 | } |
@@ -555,8 +564,8 @@ public sealed class BSShapeCollection : IDisposable | |||
555 | ShapeData nativeShapeData = new ShapeData(); | 564 | ShapeData nativeShapeData = new ShapeData(); |
556 | nativeShapeData.Type = shapeType; | 565 | nativeShapeData.Type = shapeType; |
557 | nativeShapeData.ID = prim.LocalID; | 566 | nativeShapeData.ID = prim.LocalID; |
558 | nativeShapeData.Scale = prim.Size; | 567 | nativeShapeData.Scale = prim.Scale; |
559 | nativeShapeData.Size = prim.Size; // unneeded, I think. | 568 | nativeShapeData.Size = prim.Scale; // unneeded, I think. |
560 | nativeShapeData.MeshKey = (ulong)shapeKey; | 569 | nativeShapeData.MeshKey = (ulong)shapeKey; |
561 | nativeShapeData.HullKey = (ulong)shapeKey; | 570 | nativeShapeData.HullKey = (ulong)shapeKey; |
562 | 571 | ||
@@ -573,7 +582,7 @@ public sealed class BSShapeCollection : IDisposable | |||
573 | // Native shapes are scaled in Bullet so set the scaling to the size | 582 | // Native shapes are scaled in Bullet so set the scaling to the size |
574 | newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); | 583 | newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); |
575 | } | 584 | } |
576 | if (newShape.ptr == IntPtr.Zero) | 585 | if (!newShape.HasPhysicalShape) |
577 | { | 586 | { |
578 | PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", | 587 | PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", |
579 | LogHeader, prim.LocalID, shapeType); | 588 | LogHeader, prim.LocalID, shapeType); |
@@ -590,7 +599,7 @@ public sealed class BSShapeCollection : IDisposable | |||
590 | // Called at taint-time! | 599 | // Called at taint-time! |
591 | private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | 600 | private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) |
592 | { | 601 | { |
593 | BulletShape newShape = new BulletShape(IntPtr.Zero); | 602 | BulletShape newShape = new BulletShape(); |
594 | 603 | ||
595 | float lod; | 604 | float lod; |
596 | System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); | 605 | System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); |
@@ -611,8 +620,6 @@ public sealed class BSShapeCollection : IDisposable | |||
611 | 620 | ||
612 | ReferenceShape(newShape); | 621 | ReferenceShape(newShape); |
613 | 622 | ||
614 | // meshes are already scaled by the meshmerizer | ||
615 | prim.Scale = new OMV.Vector3(1f, 1f, 1f); | ||
616 | prim.PhysShape = newShape; | 623 | prim.PhysShape = newShape; |
617 | 624 | ||
618 | return true; // 'true' means a new shape has been added to this prim | 625 | return true; // 'true' means a new shape has been added to this prim |
@@ -683,8 +690,6 @@ public sealed class BSShapeCollection : IDisposable | |||
683 | 690 | ||
684 | ReferenceShape(newShape); | 691 | ReferenceShape(newShape); |
685 | 692 | ||
686 | // hulls are already scaled by the meshmerizer | ||
687 | prim.Scale = new OMV.Vector3(1f, 1f, 1f); | ||
688 | prim.PhysShape = newShape; | 693 | prim.PhysShape = newShape; |
689 | return true; // 'true' means a new shape has been added to this prim | 694 | return true; // 'true' means a new shape has been added to this prim |
690 | } | 695 | } |
@@ -793,7 +798,7 @@ public sealed class BSShapeCollection : IDisposable | |||
793 | BulletShape newShape = new BulletShape(hullPtr, BSPhysicsShapeType.SHAPE_HULL); | 798 | BulletShape newShape = new BulletShape(hullPtr, BSPhysicsShapeType.SHAPE_HULL); |
794 | newShape.shapeKey = newHullKey; | 799 | newShape.shapeKey = newHullKey; |
795 | 800 | ||
796 | return newShape; // 'true' means a new shape has been added to this prim | 801 | return newShape; |
797 | } | 802 | } |
798 | 803 | ||
799 | // Callback from convex hull creater with a newly created hull. | 804 | // Callback from convex hull creater with a newly created hull. |
@@ -860,7 +865,7 @@ public sealed class BSShapeCollection : IDisposable | |||
860 | private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) | 865 | private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) |
861 | { | 866 | { |
862 | // If the shape was successfully created, nothing more to do | 867 | // If the shape was successfully created, nothing more to do |
863 | if (newShape.ptr != IntPtr.Zero) | 868 | if (newShape.HasPhysicalShape) |
864 | return newShape; | 869 | return newShape; |
865 | 870 | ||
866 | // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset | 871 | // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset |
@@ -919,7 +924,7 @@ public sealed class BSShapeCollection : IDisposable | |||
919 | bool ret = false; | 924 | bool ret = false; |
920 | 925 | ||
921 | // the mesh, hull or native shape must have already been created in Bullet | 926 | // the mesh, hull or native shape must have already been created in Bullet |
922 | bool mustRebuild = (prim.PhysBody.ptr == IntPtr.Zero); | 927 | bool mustRebuild = !prim.PhysBody.HasPhysicalBody; |
923 | 928 | ||
924 | // If there is an existing body, verify it's of an acceptable type. | 929 | // If there is an existing body, verify it's of an acceptable type. |
925 | // If not a solid object, body is a GhostObject. Otherwise a RigidBody. | 930 | // If not a solid object, body is a GhostObject. Otherwise a RigidBody. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs index 83b9c37..2b120d6 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs | |||
@@ -121,9 +121,8 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys | |||
121 | // redo its bounding box now that it is in the world | 121 | // redo its bounding box now that it is in the world |
122 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); | 122 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); |
123 | 123 | ||
124 | BulletSimAPI.SetCollisionGroupMask2(m_mapInfo.terrainBody.ptr, | 124 | m_mapInfo.terrainBody.collisionType = CollisionType.Terrain; |
125 | (uint)CollisionFilterGroups.TerrainGroup, | 125 | m_mapInfo.terrainBody.ApplyCollisionMask(); |
126 | (uint)CollisionFilterGroups.TerrainMask); | ||
127 | 126 | ||
128 | // Make it so the terrain will not move or be considered for movement. | 127 | // Make it so the terrain will not move or be considered for movement. |
129 | BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); | 128 | BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); |
@@ -136,7 +135,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys | |||
136 | { | 135 | { |
137 | if (m_mapInfo != null) | 136 | if (m_mapInfo != null) |
138 | { | 137 | { |
139 | if (m_mapInfo.terrainBody.ptr != IntPtr.Zero) | 138 | if (m_mapInfo.terrainBody.HasPhysicalBody) |
140 | { | 139 | { |
141 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); | 140 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); |
142 | // Frees both the body and the shape. | 141 | // Frees both the body and the shape. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 83df360..5dbd8ce 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs | |||
@@ -140,8 +140,8 @@ public sealed class BSTerrainManager | |||
140 | // Ground plane does not move | 140 | // Ground plane does not move |
141 | BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); | 141 | BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); |
142 | // Everything collides with the ground plane. | 142 | // Everything collides with the ground plane. |
143 | BulletSimAPI.SetCollisionGroupMask2(m_groundPlane.ptr, | 143 | m_groundPlane.collisionType = CollisionType.Groundplane; |
144 | (uint)CollisionFilterGroups.GroundPlaneGroup, (uint)CollisionFilterGroups.GroundPlaneMask); | 144 | m_groundPlane.ApplyCollisionMask(); |
145 | 145 | ||
146 | // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. | 146 | // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. |
147 | BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); | 147 | BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); |
@@ -151,13 +151,13 @@ public sealed class BSTerrainManager | |||
151 | // Release all the terrain structures we might have allocated | 151 | // Release all the terrain structures we might have allocated |
152 | public void ReleaseGroundPlaneAndTerrain() | 152 | public void ReleaseGroundPlaneAndTerrain() |
153 | { | 153 | { |
154 | if (m_groundPlane.ptr != IntPtr.Zero) | 154 | if (m_groundPlane.HasPhysicalBody) |
155 | { | 155 | { |
156 | if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr)) | 156 | if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr)) |
157 | { | 157 | { |
158 | BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr); | 158 | BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr); |
159 | } | 159 | } |
160 | m_groundPlane.ptr = IntPtr.Zero; | 160 | m_groundPlane.Clear(); |
161 | } | 161 | } |
162 | 162 | ||
163 | ReleaseTerrain(); | 163 | ReleaseTerrain(); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs index 6ce767d..6dc0d92 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs | |||
@@ -94,7 +94,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys | |||
94 | m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, | 94 | m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, |
95 | indicesCount, indices, verticesCount, vertices), | 95 | indicesCount, indices, verticesCount, vertices), |
96 | BSPhysicsShapeType.SHAPE_MESH); | 96 | BSPhysicsShapeType.SHAPE_MESH); |
97 | if (m_terrainShape.ptr == IntPtr.Zero) | 97 | if (!m_terrainShape.HasPhysicalShape) |
98 | { | 98 | { |
99 | // DISASTER!! | 99 | // DISASTER!! |
100 | PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID); | 100 | PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID); |
@@ -107,7 +107,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys | |||
107 | Quaternion rot = Quaternion.Identity; | 107 | Quaternion rot = Quaternion.Identity; |
108 | 108 | ||
109 | m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot)); | 109 | m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot)); |
110 | if (m_terrainBody.ptr == IntPtr.Zero) | 110 | if (!m_terrainBody.HasPhysicalBody) |
111 | { | 111 | { |
112 | // DISASTER!! | 112 | // DISASTER!! |
113 | physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); | 113 | physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); |
@@ -130,9 +130,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys | |||
130 | // Redo its bounding box now that it is in the world | 130 | // Redo its bounding box now that it is in the world |
131 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr); | 131 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr); |
132 | 132 | ||
133 | BulletSimAPI.SetCollisionGroupMask2(m_terrainBody.ptr, | 133 | m_terrainBody.collisionType = CollisionType.Terrain; |
134 | (uint)CollisionFilterGroups.TerrainGroup, | 134 | m_terrainBody.ApplyCollisionMask(); |
135 | (uint)CollisionFilterGroups.TerrainMask); | ||
136 | 135 | ||
137 | // Make it so the terrain will not move or be considered for movement. | 136 | // Make it so the terrain will not move or be considered for movement. |
138 | BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION); | 137 | BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION); |
@@ -140,7 +139,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys | |||
140 | 139 | ||
141 | public override void Dispose() | 140 | public override void Dispose() |
142 | { | 141 | { |
143 | if (m_terrainBody.ptr != IntPtr.Zero) | 142 | if (m_terrainBody.HasPhysicalBody) |
144 | { | 143 | { |
145 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); | 144 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); |
146 | // Frees both the body and the shape. | 145 | // Frees both the body and the shape. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 2671995..962b540 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | |||
@@ -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 | using System; | 27 | using System; |
28 | using System.Collections.Generic; | ||
28 | using System.Runtime.InteropServices; | 29 | using System.Runtime.InteropServices; |
29 | using System.Security; | 30 | using System.Security; |
30 | using System.Text; | 31 | using System.Text; |
@@ -32,93 +33,6 @@ using OpenMetaverse; | |||
32 | 33 | ||
33 | namespace OpenSim.Region.Physics.BulletSPlugin { | 34 | namespace OpenSim.Region.Physics.BulletSPlugin { |
34 | 35 | ||
35 | // Classes to allow some type checking for the API | ||
36 | // These hold pointers to allocated objects in the unmanaged space. | ||
37 | |||
38 | // The physics engine controller class created at initialization | ||
39 | public struct BulletSim | ||
40 | { | ||
41 | public BulletSim(uint worldId, BSScene bss, IntPtr xx) | ||
42 | { | ||
43 | ptr = xx; | ||
44 | worldID = worldId; | ||
45 | physicsScene = bss; | ||
46 | } | ||
47 | public IntPtr ptr; | ||
48 | public uint worldID; | ||
49 | // The scene is only in here so very low level routines have a handle to print debug/error messages | ||
50 | public BSScene physicsScene; | ||
51 | } | ||
52 | |||
53 | // An allocated Bullet btRigidBody | ||
54 | public struct BulletBody | ||
55 | { | ||
56 | public BulletBody(uint id, IntPtr xx) | ||
57 | { | ||
58 | ID = id; | ||
59 | ptr = xx; | ||
60 | collisionGroup = 0; | ||
61 | collisionMask = 0; | ||
62 | } | ||
63 | public IntPtr ptr; | ||
64 | public uint ID; | ||
65 | public CollisionFilterGroups collisionGroup; | ||
66 | public CollisionFilterGroups collisionMask; | ||
67 | public override string ToString() | ||
68 | { | ||
69 | StringBuilder buff = new StringBuilder(); | ||
70 | buff.Append("<id="); | ||
71 | buff.Append(ID.ToString()); | ||
72 | buff.Append(",p="); | ||
73 | buff.Append(ptr.ToString("X")); | ||
74 | if (collisionGroup != 0 || collisionMask != 0) | ||
75 | { | ||
76 | buff.Append(",g="); | ||
77 | buff.Append(collisionGroup.ToString("X")); | ||
78 | buff.Append(",m="); | ||
79 | buff.Append(collisionMask.ToString("X")); | ||
80 | } | ||
81 | buff.Append(">"); | ||
82 | return buff.ToString(); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | public struct BulletShape | ||
87 | { | ||
88 | public BulletShape(IntPtr xx) | ||
89 | { | ||
90 | ptr = xx; | ||
91 | type=BSPhysicsShapeType.SHAPE_UNKNOWN; | ||
92 | shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; | ||
93 | isNativeShape = false; | ||
94 | } | ||
95 | public BulletShape(IntPtr xx, BSPhysicsShapeType typ) | ||
96 | { | ||
97 | ptr = xx; | ||
98 | type = typ; | ||
99 | shapeKey = 0; | ||
100 | isNativeShape = false; | ||
101 | } | ||
102 | public IntPtr ptr; | ||
103 | public BSPhysicsShapeType type; | ||
104 | public System.UInt64 shapeKey; | ||
105 | public bool isNativeShape; | ||
106 | public override string ToString() | ||
107 | { | ||
108 | StringBuilder buff = new StringBuilder(); | ||
109 | buff.Append("<p="); | ||
110 | buff.Append(ptr.ToString("X")); | ||
111 | buff.Append(",s="); | ||
112 | buff.Append(type.ToString()); | ||
113 | buff.Append(",k="); | ||
114 | buff.Append(shapeKey.ToString("X")); | ||
115 | buff.Append(",n="); | ||
116 | buff.Append(isNativeShape.ToString()); | ||
117 | buff.Append(">"); | ||
118 | return buff.ToString(); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | // Constraint type values as defined by Bullet | 36 | // Constraint type values as defined by Bullet |
123 | public enum ConstraintType : int | 37 | public enum ConstraintType : int |
124 | { | 38 | { |
@@ -132,44 +46,6 @@ public enum ConstraintType : int | |||
132 | MAX_CONSTRAINT_TYPE | 46 | MAX_CONSTRAINT_TYPE |
133 | } | 47 | } |
134 | 48 | ||
135 | // An allocated Bullet btConstraint | ||
136 | public struct BulletConstraint | ||
137 | { | ||
138 | public BulletConstraint(IntPtr xx) | ||
139 | { | ||
140 | ptr = xx; | ||
141 | } | ||
142 | public IntPtr ptr; | ||
143 | } | ||
144 | |||
145 | // An allocated HeightMapThing which holds various heightmap info. | ||
146 | // Made a class rather than a struct so there would be only one | ||
147 | // instance of this and C# will pass around pointers rather | ||
148 | // than making copies. | ||
149 | public class BulletHeightMapInfo | ||
150 | { | ||
151 | public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) { | ||
152 | ID = id; | ||
153 | Ptr = xx; | ||
154 | heightMap = hm; | ||
155 | terrainRegionBase = Vector3.Zero; | ||
156 | minCoords = new Vector3(100f, 100f, 25f); | ||
157 | maxCoords = new Vector3(101f, 101f, 26f); | ||
158 | minZ = maxZ = 0f; | ||
159 | sizeX = sizeY = 256f; | ||
160 | } | ||
161 | public uint ID; | ||
162 | public IntPtr Ptr; | ||
163 | public float[] heightMap; | ||
164 | public Vector3 terrainRegionBase; | ||
165 | public Vector3 minCoords; | ||
166 | public Vector3 maxCoords; | ||
167 | public float sizeX, sizeY; | ||
168 | public float minZ, maxZ; | ||
169 | public BulletShape terrainShape; | ||
170 | public BulletBody terrainBody; | ||
171 | } | ||
172 | |||
173 | // =============================================================================== | 49 | // =============================================================================== |
174 | [StructLayout(LayoutKind.Sequential)] | 50 | [StructLayout(LayoutKind.Sequential)] |
175 | public struct ConvexHull | 51 | public struct ConvexHull |
@@ -362,21 +238,15 @@ public enum CollisionFlags : uint | |||
362 | BS_FLOATS_ON_WATER = 1 << 11, | 238 | BS_FLOATS_ON_WATER = 1 << 11, |
363 | BS_VEHICLE_COLLISIONS = 1 << 12, | 239 | BS_VEHICLE_COLLISIONS = 1 << 12, |
364 | BS_NONE = 0, | 240 | BS_NONE = 0, |
365 | BS_ALL = 0xFFFFFFFF, | 241 | BS_ALL = 0xFFFFFFFF |
366 | |||
367 | // These are the collision flags switched depending on physical state. | ||
368 | // The other flags are used for other things and should not be fooled with. | ||
369 | BS_ACTIVE = CF_STATIC_OBJECT | ||
370 | | CF_KINEMATIC_OBJECT | ||
371 | | CF_NO_CONTACT_RESPONSE | ||
372 | }; | 242 | }; |
373 | 243 | ||
374 | // Values for collisions groups and masks | 244 | // Values f collisions groups and masks |
375 | public enum CollisionFilterGroups : uint | 245 | public enum CollisionFilterGroups : uint |
376 | { | 246 | { |
377 | // Don't use the bit definitions!! Define the use in a | 247 | // Don't use the bit definitions!! Define the use in a |
378 | // filter/mask definition below. This way collision interactions | 248 | // filter/mask definition below. This way collision interactions |
379 | // are more easily debugged. | 249 | // are more easily found and debugged. |
380 | BNoneGroup = 0, | 250 | BNoneGroup = 0, |
381 | BDefaultGroup = 1 << 0, | 251 | BDefaultGroup = 1 << 0, |
382 | BStaticGroup = 1 << 1, | 252 | BStaticGroup = 1 << 1, |
@@ -390,24 +260,8 @@ public enum CollisionFilterGroups : uint | |||
390 | BTerrainGroup = 1 << 11, | 260 | BTerrainGroup = 1 << 11, |
391 | BRaycastGroup = 1 << 12, | 261 | BRaycastGroup = 1 << 12, |
392 | BSolidGroup = 1 << 13, | 262 | BSolidGroup = 1 << 13, |
393 | BLinksetGroup = 1 << 14, | 263 | // BLinksetGroup = xx // a linkset proper is either static or dynamic |
394 | 264 | BLinksetChildGroup = 1 << 14, | |
395 | // The collsion filters and masked are defined in one place -- don't want them scattered | ||
396 | AvatarGroup = BCharacterGroup, | ||
397 | AvatarMask = BAllGroup, | ||
398 | ObjectGroup = BSolidGroup, | ||
399 | ObjectMask = BAllGroup, | ||
400 | StaticObjectGroup = BStaticGroup, | ||
401 | StaticObjectMask = AvatarGroup | ObjectGroup, // static things don't interact with much | ||
402 | LinksetGroup = BLinksetGroup, | ||
403 | LinksetMask = BAllGroup & ~BLinksetGroup, // linkset objects don't collide with each other | ||
404 | VolumeDetectGroup = BSensorTrigger, | ||
405 | VolumeDetectMask = ~BSensorTrigger, | ||
406 | TerrainGroup = BTerrainGroup, | ||
407 | TerrainMask = BAllGroup & ~BStaticGroup, // static objects on the ground don't collide | ||
408 | GroundPlaneGroup = BGroundPlaneGroup, | ||
409 | GroundPlaneMask = BAllGroup | ||
410 | |||
411 | }; | 265 | }; |
412 | 266 | ||
413 | // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 | 267 | // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 |
@@ -434,7 +288,7 @@ public enum ConstraintParamAxis : int | |||
434 | 288 | ||
435 | // =============================================================================== | 289 | // =============================================================================== |
436 | static class BulletSimAPI { | 290 | static class BulletSimAPI { |
437 | 291 | // =============================================================================== | |
438 | // Link back to the managed code for outputting log messages | 292 | // Link back to the managed code for outputting log messages |
439 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | 293 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] |
440 | public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); | 294 | public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs new file mode 100755 index 0000000..662177f --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs | |||
@@ -0,0 +1,278 @@ | |||
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 copyrightD | ||
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 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Text; | ||
30 | using OMV = OpenMetaverse; | ||
31 | |||
32 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
33 | { | ||
34 | // Classes to allow some type checking for the API | ||
35 | // These hold pointers to allocated objects in the unmanaged space. | ||
36 | |||
37 | // The physics engine controller class created at initialization | ||
38 | public struct BulletSim | ||
39 | { | ||
40 | public BulletSim(uint worldId, BSScene bss, IntPtr xx) | ||
41 | { | ||
42 | ptr = xx; | ||
43 | worldID = worldId; | ||
44 | physicsScene = bss; | ||
45 | } | ||
46 | public IntPtr ptr; | ||
47 | public uint worldID; | ||
48 | // The scene is only in here so very low level routines have a handle to print debug/error messages | ||
49 | public BSScene physicsScene; | ||
50 | } | ||
51 | |||
52 | // An allocated Bullet btRigidBody | ||
53 | public struct BulletBody | ||
54 | { | ||
55 | public BulletBody(uint id) : this(id, IntPtr.Zero) | ||
56 | { | ||
57 | } | ||
58 | public BulletBody(uint id, IntPtr xx) | ||
59 | { | ||
60 | ID = id; | ||
61 | ptr = xx; | ||
62 | collisionType = CollisionType.Static; | ||
63 | } | ||
64 | public IntPtr ptr; | ||
65 | public uint ID; | ||
66 | public CollisionType collisionType; | ||
67 | |||
68 | public void Clear() | ||
69 | { | ||
70 | ptr = IntPtr.Zero; | ||
71 | } | ||
72 | public bool HasPhysicalBody { get { return ptr != IntPtr.Zero; } } | ||
73 | |||
74 | // Apply the specificed collision mask into the physical world | ||
75 | public void ApplyCollisionMask() | ||
76 | { | ||
77 | // Should assert the body has been added to the physical world. | ||
78 | // (The collision masks are stored in the collision proxy cache which only exists for | ||
79 | // a collision body that is in the world.) | ||
80 | BulletSimAPI.SetCollisionGroupMask2(ptr, | ||
81 | BulletSimData.CollisionTypeMasks[collisionType].group, | ||
82 | BulletSimData.CollisionTypeMasks[collisionType].mask); | ||
83 | } | ||
84 | |||
85 | public override string ToString() | ||
86 | { | ||
87 | StringBuilder buff = new StringBuilder(); | ||
88 | buff.Append("<id="); | ||
89 | buff.Append(ID.ToString()); | ||
90 | buff.Append(",p="); | ||
91 | buff.Append(ptr.ToString("X")); | ||
92 | buff.Append(",c="); | ||
93 | buff.Append(collisionType); | ||
94 | buff.Append(">"); | ||
95 | return buff.ToString(); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | public struct BulletShape | ||
100 | { | ||
101 | public BulletShape(IntPtr xx) : this(xx, BSPhysicsShapeType.SHAPE_UNKNOWN) | ||
102 | { | ||
103 | } | ||
104 | public BulletShape(IntPtr xx, BSPhysicsShapeType typ) | ||
105 | { | ||
106 | ptr = xx; | ||
107 | type = typ; | ||
108 | shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; | ||
109 | isNativeShape = false; | ||
110 | } | ||
111 | public IntPtr ptr; | ||
112 | public BSPhysicsShapeType type; | ||
113 | public System.UInt64 shapeKey; | ||
114 | public bool isNativeShape; | ||
115 | |||
116 | public void Clear() | ||
117 | { | ||
118 | ptr = IntPtr.Zero; | ||
119 | } | ||
120 | public bool HasPhysicalShape { get { return ptr != IntPtr.Zero; } } | ||
121 | |||
122 | public override string ToString() | ||
123 | { | ||
124 | StringBuilder buff = new StringBuilder(); | ||
125 | buff.Append("<p="); | ||
126 | buff.Append(ptr.ToString("X")); | ||
127 | buff.Append(",s="); | ||
128 | buff.Append(type.ToString()); | ||
129 | buff.Append(",k="); | ||
130 | buff.Append(shapeKey.ToString("X")); | ||
131 | buff.Append(",n="); | ||
132 | buff.Append(isNativeShape.ToString()); | ||
133 | buff.Append(">"); | ||
134 | return buff.ToString(); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | // An allocated Bullet btConstraint | ||
139 | public struct BulletConstraint | ||
140 | { | ||
141 | public BulletConstraint(IntPtr xx) | ||
142 | { | ||
143 | ptr = xx; | ||
144 | } | ||
145 | public IntPtr ptr; | ||
146 | |||
147 | public void Clear() | ||
148 | { | ||
149 | ptr = IntPtr.Zero; | ||
150 | } | ||
151 | public bool HasPhysicalConstraint { get { return ptr != IntPtr.Zero; } } | ||
152 | } | ||
153 | |||
154 | // An allocated HeightMapThing which holds various heightmap info. | ||
155 | // Made a class rather than a struct so there would be only one | ||
156 | // instance of this and C# will pass around pointers rather | ||
157 | // than making copies. | ||
158 | public class BulletHeightMapInfo | ||
159 | { | ||
160 | public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) { | ||
161 | ID = id; | ||
162 | Ptr = xx; | ||
163 | heightMap = hm; | ||
164 | terrainRegionBase = OMV.Vector3.Zero; | ||
165 | minCoords = new OMV.Vector3(100f, 100f, 25f); | ||
166 | maxCoords = new OMV.Vector3(101f, 101f, 26f); | ||
167 | minZ = maxZ = 0f; | ||
168 | sizeX = sizeY = 256f; | ||
169 | } | ||
170 | public uint ID; | ||
171 | public IntPtr Ptr; | ||
172 | public float[] heightMap; | ||
173 | public OMV.Vector3 terrainRegionBase; | ||
174 | public OMV.Vector3 minCoords; | ||
175 | public OMV.Vector3 maxCoords; | ||
176 | public float sizeX, sizeY; | ||
177 | public float minZ, maxZ; | ||
178 | public BulletShape terrainShape; | ||
179 | public BulletBody terrainBody; | ||
180 | } | ||
181 | |||
182 | // The general class of collsion object. | ||
183 | public enum CollisionType | ||
184 | { | ||
185 | Avatar, | ||
186 | Groundplane, | ||
187 | Terrain, | ||
188 | Static, | ||
189 | Dynamic, | ||
190 | VolumeDetect, | ||
191 | // Linkset, // A linkset should be either Static or Dynamic | ||
192 | LinksetChild, | ||
193 | Unknown | ||
194 | }; | ||
195 | |||
196 | // Hold specification of group and mask collision flags for a CollisionType | ||
197 | public struct CollisionTypeFilterGroup | ||
198 | { | ||
199 | public CollisionTypeFilterGroup(CollisionType t, uint g, uint m) | ||
200 | { | ||
201 | type = t; | ||
202 | group = g; | ||
203 | mask = m; | ||
204 | } | ||
205 | public CollisionType type; | ||
206 | public uint group; | ||
207 | public uint mask; | ||
208 | }; | ||
209 | |||
210 | /* NOTE: old definitions kept for reference. Delete when things are working. | ||
211 | // The collsion filters and masked are defined in one place -- don't want them scattered | ||
212 | AvatarGroup = BCharacterGroup, | ||
213 | AvatarMask = BAllGroup, | ||
214 | ObjectGroup = BSolidGroup, | ||
215 | ObjectMask = BAllGroup, | ||
216 | StaticObjectGroup = BStaticGroup, | ||
217 | StaticObjectMask = AvatarGroup | ObjectGroup, // static things don't interact with much | ||
218 | LinksetGroup = BLinksetGroup, | ||
219 | LinksetMask = BAllGroup, | ||
220 | LinksetChildGroup = BLinksetChildGroup, | ||
221 | LinksetChildMask = BNoneGroup, // Linkset children disappear from the world | ||
222 | VolumeDetectGroup = BSensorTrigger, | ||
223 | VolumeDetectMask = ~BSensorTrigger, | ||
224 | TerrainGroup = BTerrainGroup, | ||
225 | TerrainMask = BAllGroup & ~BStaticGroup, // static objects on the ground don't collide | ||
226 | GroundPlaneGroup = BGroundPlaneGroup, | ||
227 | GroundPlaneMask = BAllGroup | ||
228 | */ | ||
229 | |||
230 | public static class BulletSimData | ||
231 | { | ||
232 | |||
233 | // Map of collisionTypes to flags for collision groups and masks. | ||
234 | // As mentioned above, don't use the CollisionFilterGroups definitions directly in the code | ||
235 | // but, instead, use references to this dictionary. Finding and debugging | ||
236 | // collision flag problems will be made easier. | ||
237 | public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeMasks | ||
238 | = new Dictionary<CollisionType, CollisionTypeFilterGroup>() | ||
239 | { | ||
240 | { CollisionType.Avatar, | ||
241 | new CollisionTypeFilterGroup(CollisionType.Avatar, | ||
242 | (uint)CollisionFilterGroups.BCharacterGroup, | ||
243 | (uint)CollisionFilterGroups.BAllGroup) | ||
244 | }, | ||
245 | { CollisionType.Groundplane, | ||
246 | new CollisionTypeFilterGroup(CollisionType.Groundplane, | ||
247 | (uint)CollisionFilterGroups.BGroundPlaneGroup, | ||
248 | (uint)CollisionFilterGroups.BAllGroup) | ||
249 | }, | ||
250 | { CollisionType.Terrain, | ||
251 | new CollisionTypeFilterGroup(CollisionType.Terrain, | ||
252 | (uint)CollisionFilterGroups.BTerrainGroup, | ||
253 | (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup)) | ||
254 | }, | ||
255 | { CollisionType.Static, | ||
256 | new CollisionTypeFilterGroup(CollisionType.Static, | ||
257 | (uint)CollisionFilterGroups.BStaticGroup, | ||
258 | (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup)) | ||
259 | }, | ||
260 | { CollisionType.Dynamic, | ||
261 | new CollisionTypeFilterGroup(CollisionType.Dynamic, | ||
262 | (uint)CollisionFilterGroups.BSolidGroup, | ||
263 | (uint)(CollisionFilterGroups.BAllGroup)) | ||
264 | }, | ||
265 | { CollisionType.VolumeDetect, | ||
266 | new CollisionTypeFilterGroup(CollisionType.VolumeDetect, | ||
267 | (uint)CollisionFilterGroups.BSensorTrigger, | ||
268 | (uint)(~CollisionFilterGroups.BSensorTrigger)) | ||
269 | }, | ||
270 | { CollisionType.LinksetChild, | ||
271 | new CollisionTypeFilterGroup(CollisionType.LinksetChild, | ||
272 | (uint)CollisionFilterGroups.BTerrainGroup, | ||
273 | (uint)(CollisionFilterGroups.BNoneGroup)) | ||
274 | }, | ||
275 | }; | ||
276 | |||
277 | } | ||
278 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt index a2161c3..7d6ace8 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt | |||
@@ -11,13 +11,20 @@ CRASHES | |||
11 | 11 | ||
12 | VEHICLES TODO LIST: | 12 | VEHICLES TODO LIST: |
13 | ================================================= | 13 | ================================================= |
14 | Neb car jiggling left and right | 14 | Neb vehicle taking > 25ms of physics time!! |
15 | Happens on terrain and any other mesh object. Flat cubes are much smoother. | ||
16 | Vehicles (Move smoothly) | 15 | Vehicles (Move smoothly) |
17 | Add vehicle collisions so IsColliding is properly reported. | 16 | Add vehicle collisions so IsColliding is properly reported. |
18 | Needed for banking, limitMotorUp, movementLimiting, ... | 17 | Needed for banking, limitMotorUp, movementLimiting, ... |
19 | Some vehicles should not be able to turn if no speed or off ground. | 18 | Some vehicles should not be able to turn if no speed or off ground. |
19 | Neb car jiggling left and right | ||
20 | Happens on terrain and any other mesh object. Flat cubes are much smoother. | ||
21 | This has been reduced but not eliminated. | ||
22 | Light cycle falling over when driving | ||
20 | For limitMotorUp, use raycast down to find if vehicle is in the air. | 23 | For limitMotorUp, use raycast down to find if vehicle is in the air. |
24 | Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE. | ||
25 | Verify that angular motion specified around Z moves in the vehicle coordinates. | ||
26 | Verify llGetVel() is returning a smooth and good value for vehicle movement. | ||
27 | llGetVel() should return the root's velocity if requested in a child prim. | ||
21 | Implement function efficiency for lineaar and angular motion. | 28 | Implement function efficiency for lineaar and angular motion. |
22 | Should vehicle angular/linear movement friction happen after all the components | 29 | Should vehicle angular/linear movement friction happen after all the components |
23 | or does it only apply to the basic movement? | 30 | or does it only apply to the basic movement? |
@@ -30,15 +37,14 @@ Border crossing with linked vehicle causes crash | |||
30 | 37 | ||
31 | BULLETSIM TODO LIST: | 38 | BULLETSIM TODO LIST: |
32 | ================================================= | 39 | ================================================= |
40 | Avatar height off after unsitting (floats off ground) | ||
41 | Editting appearance then moving restores. | ||
42 | Must not be initializing height when recreating capsule after unsit. | ||
33 | Duplicating a physical prim causes old prim to jump away | 43 | Duplicating a physical prim causes old prim to jump away |
34 | Dup a phys prim and the original become unselected and thus interacts w/ selected prim. | 44 | Dup a phys prim and the original become unselected and thus interacts w/ selected prim. |
35 | Disable activity of passive linkset children. | ||
36 | Since the linkset is a compound object, the old prims are left lying | ||
37 | around and need to be phantomized so they don't collide, ... | ||
38 | Scenes with hundred of thousands of static objects take a lot of physics CPU time. | 45 | Scenes with hundred of thousands of static objects take a lot of physics CPU time. |
39 | BSPrim.Force should set a continious force on the prim. The force should be | 46 | BSPrim.Force should set a continious force on the prim. The force should be |
40 | applied each tick. Some limits? | 47 | applied each tick. Some limits? |
41 | Single prim vehicles don't seem to properly vehiclize. | ||
42 | Gun sending shooter flying. | 48 | Gun sending shooter flying. |
43 | Collision margin (gap between physical objects lying on each other) | 49 | Collision margin (gap between physical objects lying on each other) |
44 | Boundry checking (crashes related to crossing boundry) | 50 | Boundry checking (crashes related to crossing boundry) |
@@ -51,14 +57,34 @@ Small physical objects do not interact correctly | |||
51 | The chain will fall apart and pairs will dance around on ground | 57 | The chain will fall apart and pairs will dance around on ground |
52 | Chains of 1x1x.2 will stay connected but will dance. | 58 | Chains of 1x1x.2 will stay connected but will dance. |
53 | Chains above 2x2x.4 are move stable and get stablier as torui get larger. | 59 | Chains above 2x2x.4 are move stable and get stablier as torui get larger. |
54 | Add material type linkage and input all the material property definitions. | ||
55 | Skeleton classes and table are in the sources but are not filled or used. | ||
56 | Add PID motor for avatar movement (slow to stop, ...) | 60 | Add PID motor for avatar movement (slow to stop, ...) |
57 | setForce should set a constant force. Different than AddImpulse. | 61 | setForce should set a constant force. Different than AddImpulse. |
58 | Implement raycast. | 62 | Implement raycast. |
59 | Implement ShapeCollection.Dispose() | 63 | Implement ShapeCollection.Dispose() |
60 | Implement water as a plain so raycasting and collisions can happen with same. | 64 | Implement water as a plain so raycasting and collisions can happen with same. |
65 | Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE | ||
66 | Also osGetPhysicsEngineVerion() maybe. | ||
67 | |||
68 | LINKSETS | ||
69 | ====================================================== | ||
70 | Linksets should allow collisions to individual children | ||
71 | Add LocalID to children shapes in LinksetCompound and create events for individuals | ||
72 | Verify/think through scripts in children of linksets. What do they reference | ||
73 | and return when getting position, velocity, ... | ||
74 | Confirm constraint linksets still work after making all the changes for compound linksets. | ||
75 | Add 'changed' flag or similar to reduce the number of times a linkset is rebuilt. | ||
76 | For compound linksets, add ability to remove or reposition individual child shapes. | ||
77 | Disable activity of passive linkset children. | ||
78 | Since the linkset is a compound object, the old prims are left lying | ||
79 | around and need to be phantomized so they don't collide, ... | ||
80 | Speed up creation of large physical linksets | ||
81 | For instance, sitting in Neb's car (130 prims) takes several seconds to become physical | ||
82 | Eliminate collisions between objects in a linkset. (LinksetConstraint) | ||
83 | Have UserPointer point to struct with localID and linksetID? | ||
84 | Objects in original linkset still collide with each other? | ||
61 | 85 | ||
86 | MORE | ||
87 | ====================================================== | ||
62 | Find/remove avatar collision with ID=0. | 88 | Find/remove avatar collision with ID=0. |
63 | Test avatar walking up stairs. How does compare with SL. | 89 | Test avatar walking up stairs. How does compare with SL. |
64 | Radius of the capsule affects ability to climb edges. | 90 | Radius of the capsule affects ability to climb edges. |
@@ -67,8 +93,6 @@ Debounce avatar contact so legs don't keep folding up when standing. | |||
67 | Implement LSL physics controls. Like STATUS_ROTATE_X. | 93 | Implement LSL physics controls. Like STATUS_ROTATE_X. |
68 | Add border extensions to terrain to help region crossings and objects leaving region. | 94 | Add border extensions to terrain to help region crossings and objects leaving region. |
69 | 95 | ||
70 | Speed up creation of large physical linksets | ||
71 | For instance, sitting in Neb's car (130 prims) takes several seconds to become physical | ||
72 | Performance test with lots of avatars. Can BulletSim support a thousand? | 96 | Performance test with lots of avatars. Can BulletSim support a thousand? |
73 | Optimize collisions in C++: only send up to the object subscribed to collisions. | 97 | Optimize collisions in C++: only send up to the object subscribed to collisions. |
74 | Use collision subscription and remove the collsion(A,B) and collision(B,A) | 98 | Use collision subscription and remove the collsion(A,B) and collision(B,A) |
@@ -79,10 +103,6 @@ Avatar jump | |||
79 | Performance measurement and changes to make quicker. | 103 | Performance measurement and changes to make quicker. |
80 | Implement detailed physics stats (GetStats()). | 104 | Implement detailed physics stats (GetStats()). |
81 | 105 | ||
82 | Eliminate collisions between objects in a linkset. (LinksetConstraint) | ||
83 | Have UserPointer point to struct with localID and linksetID? | ||
84 | Objects in original linkset still collide with each other? | ||
85 | |||
86 | Measure performance improvement from hulls | 106 | Measure performance improvement from hulls |
87 | Test not using ghost objects for volume detect implementation. | 107 | Test not using ghost objects for volume detect implementation. |
88 | Performance of closures and delegates for taint processing | 108 | Performance of closures and delegates for taint processing |
@@ -95,10 +115,16 @@ Physics Arena central pyramid: why is one side permiable? | |||
95 | 115 | ||
96 | INTERNAL IMPROVEMENT/CLEANUP | 116 | INTERNAL IMPROVEMENT/CLEANUP |
97 | ================================================= | 117 | ================================================= |
118 | Consider moving prim/character body and shape destruction in destroy() | ||
119 | to postTimeTime rather than protecting all the potential sets that | ||
120 | might have been queued up. | ||
98 | Remove unused fields from ShapeData (not used in API2) | 121 | Remove unused fields from ShapeData (not used in API2) |
99 | Breakout code for mesh/hull/compound/native into separate BSShape* classes | 122 | Breakout code for mesh/hull/compound/native into separate BSShape* classes |
100 | Standardize access to building and reference code. | 123 | Standardize access to building and reference code. |
101 | The skeleton classes are in the sources but are not complete or linked in. | 124 | The skeleton classes are in the sources but are not complete or linked in. |
125 | Make BSBody and BSShape real classes to centralize creation/changin/destruction | ||
126 | Convert state and parameter calls from BulletSimAPI direct calls to | ||
127 | calls on BSBody and BSShape | ||
102 | Generalize Dynamics and PID with standardized motors. | 128 | Generalize Dynamics and PID with standardized motors. |
103 | Generalize Linkset and vehicles into PropertyManagers | 129 | Generalize Linkset and vehicles into PropertyManagers |
104 | Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies | 130 | Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies |
@@ -110,7 +136,7 @@ Implement linkset by setting position of children when root updated. (LinksetMan | |||
110 | Linkset implementation using manual prim movement. | 136 | Linkset implementation using manual prim movement. |
111 | LinkablePrim class? Would that simplify/centralize the linkset logic? | 137 | LinkablePrim class? Would that simplify/centralize the linkset logic? |
112 | BSScene.UpdateParameterSet() is broken. How to set params on objects? | 138 | BSScene.UpdateParameterSet() is broken. How to set params on objects? |
113 | Remove HeightmapInfo from terrain specification. | 139 | Remove HeightmapInfo from terrain specification |
114 | Since C++ code does not need terrain height, this structure et al are not needed. | 140 | Since C++ code does not need terrain height, this structure et al are not needed. |
115 | Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will | 141 | Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will |
116 | bob at the water level. BSPrim.PositionSanityCheck(). | 142 | bob at the water level. BSPrim.PositionSanityCheck(). |
@@ -142,7 +168,11 @@ Do prim hash codes work for sculpties and meshes? (Resolution: yes) | |||
142 | Linkset implementation using compound shapes. (Resolution: implemented LinksetCompound) | 168 | Linkset implementation using compound shapes. (Resolution: implemented LinksetCompound) |
143 | Compound shapes will need the LocalID in the shapes and collision | 169 | Compound shapes will need the LocalID in the shapes and collision |
144 | processing to get it from there. | 170 | processing to get it from there. |
145 | Light cycle falling over when driving (Resolution: implemented VerticalAttractor) | ||
146 | Light cycle not banking (Resolution: It doesn't. Banking is roll adding yaw.) | 171 | Light cycle not banking (Resolution: It doesn't. Banking is roll adding yaw.) |
147 | Package Bullet source mods for Bullet internal stats output | 172 | Package Bullet source mods for Bullet internal stats output |
148 | (Resolution: move code into WorldData.h rather than relying on patches) \ No newline at end of file | 173 | (Resolution: move code into WorldData.h rather than relying on patches) |
174 | Single prim vehicles don't seem to properly vehiclize. | ||
175 | (Resolution: mass was not getting set properly for single prim linksets) | ||
176 | Add material type linkage and input all the material property definitions. | ||
177 | Skeleton classes and table are in the sources but are not filled or used. | ||
178 | (Resolution: | ||
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 5af6373..be36be3 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs | |||
@@ -333,17 +333,20 @@ namespace OpenSim.Region.Physics.Manager | |||
333 | } | 333 | } |
334 | 334 | ||
335 | /// <summary> | 335 | /// <summary> |
336 | /// Velocity of this actor. | 336 | /// The desired velocity of this actor. |
337 | /// </summary> | 337 | /// </summary> |
338 | /// <remarks> | 338 | /// <remarks> |
339 | /// Setting this provides a target velocity for physics scene updates. | 339 | /// Setting this provides a target velocity for physics scene updates. |
340 | /// Getting this returns the velocity calculated by physics scene updates, using factors such as target velocity, | 340 | /// Getting this returns the last set target. Fetch Velocity to get the current velocity. |
341 | /// time to accelerate and collisions. | ||
342 | /// </remarks> | 341 | /// </remarks> |
342 | protected Vector3 m_targetVelocity; | ||
343 | public virtual Vector3 TargetVelocity | 343 | public virtual Vector3 TargetVelocity |
344 | { | 344 | { |
345 | get { return Velocity; } | 345 | get { return m_targetVelocity; } |
346 | set { Velocity = value; } | 346 | set { |
347 | m_targetVelocity = value; | ||
348 | Velocity = m_targetVelocity; | ||
349 | } | ||
347 | } | 350 | } |
348 | 351 | ||
349 | public abstract Vector3 Velocity { get; set; } | 352 | public abstract Vector3 Velocity { get; set; } |
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs index 0cef550..00a99c3 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs | |||
@@ -59,6 +59,18 @@ namespace OpenSim.Region.ScriptEngine.Interfaces | |||
59 | public interface IScriptInstance | 59 | public interface IScriptInstance |
60 | { | 60 | { |
61 | /// <summary> | 61 | /// <summary> |
62 | /// Debug level for this script instance. | ||
63 | /// </summary> | ||
64 | /// <remarks> | ||
65 | /// Level == 0, no extra data is logged. | ||
66 | /// Level >= 1, state changes are logged. | ||
67 | /// Level >= 2, event firing is logged. | ||
68 | /// <value> | ||
69 | /// The debug level. | ||
70 | /// </value> | ||
71 | int DebugLevel { get; set; } | ||
72 | |||
73 | /// <summary> | ||
62 | /// Is the script currently running? | 74 | /// Is the script currently running? |
63 | /// </summary> | 75 | /// </summary> |
64 | bool Running { get; set; } | 76 | bool Running { get; set; } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 538cb8b..68f701c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | |||
@@ -94,6 +94,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
94 | private UUID m_CurrentStateHash; | 94 | private UUID m_CurrentStateHash; |
95 | private UUID m_RegionID; | 95 | private UUID m_RegionID; |
96 | 96 | ||
97 | public int DebugLevel { get; set; } | ||
98 | |||
97 | public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; } | 99 | public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; } |
98 | 100 | ||
99 | private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>(); | 101 | private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>(); |
@@ -549,9 +551,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
549 | // forcibly abort the work item (this aborts the underlying thread). | 551 | // forcibly abort the work item (this aborts the underlying thread). |
550 | if (!m_InSelfDelete) | 552 | if (!m_InSelfDelete) |
551 | { | 553 | { |
552 | // m_log.ErrorFormat( | 554 | m_log.DebugFormat( |
553 | // "[SCRIPT INSTANCE]: Aborting script {0} {1} in prim {2} {3} {4} {5}", | 555 | "[SCRIPT INSTANCE]: Aborting unstopped script {0} {1} in prim {2}, localID {3}, timeout was {4} ms", |
554 | // ScriptName, ItemID, PrimName, ObjectID, m_InSelfDelete, DateTime.Now.Ticks); | 556 | ScriptName, ItemID, PrimName, LocalID, timeout); |
555 | 557 | ||
556 | workItem.Abort(); | 558 | workItem.Abort(); |
557 | } | 559 | } |
@@ -707,19 +709,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
707 | { | 709 | { |
708 | 710 | ||
709 | // m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this); | 711 | // m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this); |
712 | SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID); | ||
713 | |||
714 | if (DebugLevel >= 2) | ||
715 | m_log.DebugFormat( | ||
716 | "[SCRIPT INSTANCE]: Processing event {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}", | ||
717 | data.EventName, | ||
718 | ScriptName, | ||
719 | part.Name, | ||
720 | part.LocalId, | ||
721 | part.ParentGroup.Name, | ||
722 | part.ParentGroup.UUID, | ||
723 | part.AbsolutePosition, | ||
724 | part.ParentGroup.Scene.Name); | ||
710 | 725 | ||
711 | m_DetectParams = data.DetectParams; | 726 | m_DetectParams = data.DetectParams; |
712 | 727 | ||
713 | if (data.EventName == "state") // Hardcoded state change | 728 | if (data.EventName == "state") // Hardcoded state change |
714 | { | 729 | { |
715 | // m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}", | ||
716 | // PrimName, ScriptName, data.Params[0].ToString()); | ||
717 | State = data.Params[0].ToString(); | 730 | State = data.Params[0].ToString(); |
731 | |||
732 | if (DebugLevel >= 1) | ||
733 | m_log.DebugFormat( | ||
734 | "[SCRIPT INSTANCE]: Changing state to {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}", | ||
735 | State, | ||
736 | ScriptName, | ||
737 | part.Name, | ||
738 | part.LocalId, | ||
739 | part.ParentGroup.Name, | ||
740 | part.ParentGroup.UUID, | ||
741 | part.AbsolutePosition, | ||
742 | part.ParentGroup.Scene.Name); | ||
743 | |||
718 | AsyncCommandManager.RemoveScript(Engine, | 744 | AsyncCommandManager.RemoveScript(Engine, |
719 | LocalID, ItemID); | 745 | LocalID, ItemID); |
720 | 746 | ||
721 | SceneObjectPart part = Engine.World.GetSceneObjectPart( | ||
722 | LocalID); | ||
723 | if (part != null) | 747 | if (part != null) |
724 | { | 748 | { |
725 | part.SetScriptEvents(ItemID, | 749 | part.SetScriptEvents(ItemID, |
@@ -731,8 +755,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
731 | if (Engine.World.PipeEventsForScript(LocalID) || | 755 | if (Engine.World.PipeEventsForScript(LocalID) || |
732 | data.EventName == "control") // Don't freeze avies! | 756 | data.EventName == "control") // Don't freeze avies! |
733 | { | 757 | { |
734 | SceneObjectPart part = Engine.World.GetSceneObjectPart( | ||
735 | LocalID); | ||
736 | // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", | 758 | // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", |
737 | // PrimName, ScriptName, data.EventName, State); | 759 | // PrimName, ScriptName, data.EventName, State); |
738 | 760 | ||
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 05ba890..494e0b6 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | |||
@@ -108,6 +108,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
108 | private IXmlRpcRouter m_XmlRpcRouter; | 108 | private IXmlRpcRouter m_XmlRpcRouter; |
109 | private int m_EventLimit; | 109 | private int m_EventLimit; |
110 | private bool m_KillTimedOutScripts; | 110 | private bool m_KillTimedOutScripts; |
111 | |||
112 | /// <summary> | ||
113 | /// Number of milliseconds we will wait for a script event to complete on script stop before we forcibly abort | ||
114 | /// its thread. | ||
115 | /// </summary> | ||
116 | /// <remarks> | ||
117 | /// It appears that if a script thread is aborted whilst it is holding ReaderWriterLockSlim (possibly the write | ||
118 | /// lock) then the lock is not properly released. This causes mono 2.6, 2.10 and possibly | ||
119 | /// later to crash, sometimes with symptoms such as a leap to 100% script usage and a vm thead dump showing | ||
120 | /// all threads waiting on release of ReaderWriterLockSlim write thread which none of the threads listed | ||
121 | /// actually hold. | ||
122 | /// | ||
123 | /// Pausing for event completion reduces the risk of this happening. However, it may be that aborting threads | ||
124 | /// is not a mono issue per se but rather a risky activity in itself in an AppDomain that is not immediately | ||
125 | /// shutting down. | ||
126 | /// </remarks> | ||
127 | private int m_WaitForEventCompletionOnScriptStop = 1000; | ||
128 | |||
111 | private string m_ScriptEnginesPath = null; | 129 | private string m_ScriptEnginesPath = null; |
112 | 130 | ||
113 | private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>(); | 131 | private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>(); |
@@ -317,6 +335,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
317 | m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30); | 335 | m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30); |
318 | m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false); | 336 | m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false); |
319 | m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000; | 337 | m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000; |
338 | m_WaitForEventCompletionOnScriptStop | ||
339 | = m_ScriptConfig.GetInt("WaitForEventCompletionOnScriptStop", m_WaitForEventCompletionOnScriptStop); | ||
340 | |||
320 | m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines"); | 341 | m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines"); |
321 | 342 | ||
322 | m_Prio = ThreadPriority.BelowNormal; | 343 | m_Prio = ThreadPriority.BelowNormal; |
@@ -372,7 +393,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
372 | 393 | ||
373 | MainConsole.Instance.Commands.AddCommand( | 394 | MainConsole.Instance.Commands.AddCommand( |
374 | "Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information", | 395 | "Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information", |
375 | "Show information on all scripts known to the script engine." | 396 | "Show information on all scripts known to the script engine.\n" |
376 | + "If a <script-item-uuid> is given then only information on that script will be shown.", | 397 | + "If a <script-item-uuid> is given then only information on that script will be shown.", |
377 | HandleShowScripts); | 398 | HandleShowScripts); |
378 | 399 | ||
@@ -391,22 +412,30 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
391 | MainConsole.Instance.Commands.AddCommand( | 412 | MainConsole.Instance.Commands.AddCommand( |
392 | "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts", | 413 | "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts", |
393 | "Resumes all currently suspended scripts.\n" | 414 | "Resumes all currently suspended scripts.\n" |
394 | + "Resumed scripts will process all events accumulated whilst suspended." | 415 | + "Resumed scripts will process all events accumulated whilst suspended.\n" |
395 | + "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.", | 416 | + "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.", |
396 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript)); | 417 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript)); |
397 | 418 | ||
398 | MainConsole.Instance.Commands.AddCommand( | 419 | MainConsole.Instance.Commands.AddCommand( |
399 | "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts", | 420 | "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts", |
400 | "Stops all running scripts." | 421 | "Stops all running scripts.\n" |
401 | + "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.", | 422 | + "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.", |
402 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript)); | 423 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript)); |
403 | 424 | ||
404 | MainConsole.Instance.Commands.AddCommand( | 425 | MainConsole.Instance.Commands.AddCommand( |
405 | "Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts", | 426 | "Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts", |
406 | "Starts all stopped scripts." | 427 | "Starts all stopped scripts.\n" |
407 | + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.", | 428 | + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.", |
408 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); | 429 | (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); |
409 | 430 | ||
431 | MainConsole.Instance.Commands.AddCommand( | ||
432 | "Scripts", false, "debug script log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a script", | ||
433 | "Activates or deactivates extra debug logging for the given script.\n" | ||
434 | + "Level == 0, deactivate extra debug logging.\n" | ||
435 | + "Level >= 1, log state changes.\n" | ||
436 | + "Level >= 2, log event invocations.\n", | ||
437 | HandleDebugScriptLogCommand); | ||
438 | |||
410 | // MainConsole.Instance.Commands.AddCommand( | 439 | // MainConsole.Instance.Commands.AddCommand( |
411 | // "Debug", false, "debug xengine", "debug xengine [<level>]", | 440 | // "Debug", false, "debug xengine", "debug xengine [<level>]", |
412 | // "Turn on detailed xengine debugging.", | 441 | // "Turn on detailed xengine debugging.", |
@@ -415,6 +444,41 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
415 | // HandleDebugLevelCommand); | 444 | // HandleDebugLevelCommand); |
416 | } | 445 | } |
417 | 446 | ||
447 | private void HandleDebugScriptLogCommand(string module, string[] args) | ||
448 | { | ||
449 | if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) | ||
450 | return; | ||
451 | |||
452 | if (args.Length != 5) | ||
453 | { | ||
454 | MainConsole.Instance.Output("Usage: debug script log <item-id> <log-level>"); | ||
455 | return; | ||
456 | } | ||
457 | |||
458 | UUID itemId; | ||
459 | |||
460 | if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, args[3], out itemId)) | ||
461 | return; | ||
462 | |||
463 | int newLevel; | ||
464 | |||
465 | if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out newLevel)) | ||
466 | return; | ||
467 | |||
468 | IScriptInstance si; | ||
469 | |||
470 | lock (m_Scripts) | ||
471 | { | ||
472 | // XXX: We can't give the user feedback on a bad item id because this may apply to a different script | ||
473 | // engine | ||
474 | if (!m_Scripts.TryGetValue(itemId, out si)) | ||
475 | return; | ||
476 | } | ||
477 | |||
478 | si.DebugLevel = newLevel; | ||
479 | MainConsole.Instance.OutputFormat("Set debug level of {0} {1} to {2}", si.ScriptName, si.ItemID, newLevel); | ||
480 | } | ||
481 | |||
418 | /// <summary> | 482 | /// <summary> |
419 | /// Change debug level | 483 | /// Change debug level |
420 | /// </summary> | 484 | /// </summary> |
@@ -486,7 +550,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
486 | 550 | ||
487 | if (!UUID.TryParse(rawItemId, out itemId)) | 551 | if (!UUID.TryParse(rawItemId, out itemId)) |
488 | { | 552 | { |
489 | MainConsole.Instance.OutputFormat("Error - {0} is not a valid UUID", rawItemId); | 553 | MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid UUID", rawItemId); |
490 | return; | 554 | return; |
491 | } | 555 | } |
492 | 556 | ||
@@ -610,6 +674,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
610 | sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued); | 674 | sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued); |
611 | sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed); | 675 | sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed); |
612 | sb.AppendFormat("Item UUID : {0}\n", instance.ItemID); | 676 | sb.AppendFormat("Item UUID : {0}\n", instance.ItemID); |
677 | sb.AppendFormat("Asset UUID : {0}\n", instance.AssetID); | ||
613 | sb.AppendFormat("Containing part name: {0}\n", instance.PrimName); | 678 | sb.AppendFormat("Containing part name: {0}\n", instance.PrimName); |
614 | sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); | 679 | sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); |
615 | sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition); | 680 | sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition); |
@@ -1375,9 +1440,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1375 | lockScriptsForWrite(false); | 1440 | lockScriptsForWrite(false); |
1376 | instance.ClearQueue(); | 1441 | instance.ClearQueue(); |
1377 | 1442 | ||
1378 | // Give the script some time to finish processing its last event. Simply aborting the script thread can | 1443 | instance.Stop(m_WaitForEventCompletionOnScriptStop); |
1379 | // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort. | ||
1380 | instance.Stop(1000); | ||
1381 | 1444 | ||
1382 | // bool objectRemoved = false; | 1445 | // bool objectRemoved = false; |
1383 | 1446 | ||
@@ -1735,16 +1798,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1735 | public void StopScript(UUID itemID) | 1798 | public void StopScript(UUID itemID) |
1736 | { | 1799 | { |
1737 | IScriptInstance instance = GetInstance(itemID); | 1800 | IScriptInstance instance = GetInstance(itemID); |
1801 | |||
1738 | if (instance != null) | 1802 | if (instance != null) |
1739 | { | 1803 | instance.Stop(m_WaitForEventCompletionOnScriptStop); |
1740 | // Give the script some time to finish processing its last event. Simply aborting the script thread can | ||
1741 | // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort. | ||
1742 | instance.Stop(1000); | ||
1743 | } | ||
1744 | else | 1804 | else |
1745 | { | ||
1746 | m_runFlags.AddOrUpdate(itemID, false, 240); | 1805 | m_runFlags.AddOrUpdate(itemID, false, 240); |
1747 | } | ||
1748 | } | 1806 | } |
1749 | 1807 | ||
1750 | public DetectParams GetDetectParams(UUID itemID, int idx) | 1808 | public DetectParams GetDetectParams(UUID itemID, int idx) |
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs index b08233c..64cb577 100644 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs | |||
@@ -94,8 +94,6 @@ namespace OpenSim.Region.UserStatistics | |||
94 | if (!enabled) | 94 | if (!enabled) |
95 | return; | 95 | return; |
96 | 96 | ||
97 | AddEventHandlers(); | ||
98 | |||
99 | if (Util.IsWindows()) | 97 | if (Util.IsWindows()) |
100 | Util.LoadArchSpecificWindowsDll("sqlite3.dll"); | 98 | Util.LoadArchSpecificWindowsDll("sqlite3.dll"); |
101 | 99 | ||
@@ -143,10 +141,14 @@ namespace OpenSim.Region.UserStatistics | |||
143 | lock (m_scenes) | 141 | lock (m_scenes) |
144 | { | 142 | { |
145 | m_scenes.Add(scene); | 143 | m_scenes.Add(scene); |
146 | if (m_simstatsCounters.ContainsKey(scene.RegionInfo.RegionID)) | 144 | updateLogMod = m_scenes.Count * 2; |
147 | m_simstatsCounters.Remove(scene.RegionInfo.RegionID); | ||
148 | 145 | ||
149 | m_simstatsCounters.Add(scene.RegionInfo.RegionID, new USimStatsData(scene.RegionInfo.RegionID)); | 146 | m_simstatsCounters.Add(scene.RegionInfo.RegionID, new USimStatsData(scene.RegionInfo.RegionID)); |
147 | |||
148 | scene.EventManager.OnRegisterCaps += OnRegisterCaps; | ||
149 | scene.EventManager.OnDeregisterCaps += OnDeRegisterCaps; | ||
150 | scene.EventManager.OnClientClosed += OnClientClosed; | ||
151 | scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; | ||
150 | scene.StatsReporter.OnSendStatsResult += ReceiveClassicSimStatsPacket; | 152 | scene.StatsReporter.OnSendStatsResult += ReceiveClassicSimStatsPacket; |
151 | } | 153 | } |
152 | } | 154 | } |
@@ -157,6 +159,15 @@ namespace OpenSim.Region.UserStatistics | |||
157 | 159 | ||
158 | public void RemoveRegion(Scene scene) | 160 | public void RemoveRegion(Scene scene) |
159 | { | 161 | { |
162 | if (!enabled) | ||
163 | return; | ||
164 | |||
165 | lock (m_scenes) | ||
166 | { | ||
167 | m_scenes.Remove(scene); | ||
168 | updateLogMod = m_scenes.Count * 2; | ||
169 | m_simstatsCounters.Remove(scene.RegionInfo.RegionID); | ||
170 | } | ||
160 | } | 171 | } |
161 | 172 | ||
162 | public virtual void Close() | 173 | public virtual void Close() |
@@ -187,9 +198,7 @@ namespace OpenSim.Region.UserStatistics | |||
187 | private void ReceiveClassicSimStatsPacket(SimStats stats) | 198 | private void ReceiveClassicSimStatsPacket(SimStats stats) |
188 | { | 199 | { |
189 | if (!enabled) | 200 | if (!enabled) |
190 | { | ||
191 | return; | 201 | return; |
192 | } | ||
193 | 202 | ||
194 | try | 203 | try |
195 | { | 204 | { |
@@ -198,17 +207,25 @@ namespace OpenSim.Region.UserStatistics | |||
198 | if (concurrencyCounter > 0 || System.Environment.TickCount - lastHit > 30000) | 207 | if (concurrencyCounter > 0 || System.Environment.TickCount - lastHit > 30000) |
199 | return; | 208 | return; |
200 | 209 | ||
201 | if ((updateLogCounter++ % updateLogMod) == 0) | 210 | // We will conduct this under lock so that fields such as updateLogCounter do not potentially get |
211 | // confused if a scene is removed. | ||
212 | // XXX: Possibly the scope of this lock could be reduced though it's not critical. | ||
213 | lock (m_scenes) | ||
202 | { | 214 | { |
203 | m_loglines = readLogLines(10); | 215 | if (updateLogMod != 0 && updateLogCounter++ % updateLogMod == 0) |
204 | if (updateLogCounter > 10000) updateLogCounter = 1; | 216 | { |
205 | } | 217 | m_loglines = readLogLines(10); |
206 | 218 | ||
207 | USimStatsData ss = m_simstatsCounters[stats.RegionUUID]; | 219 | if (updateLogCounter > 10000) |
220 | updateLogCounter = 1; | ||
221 | } | ||
208 | 222 | ||
209 | if ((++ss.StatsCounter % updateStatsMod) == 0) | 223 | USimStatsData ss = m_simstatsCounters[stats.RegionUUID]; |
210 | { | 224 | |
211 | ss.ConsumeSimStats(stats); | 225 | if ((++ss.StatsCounter % updateStatsMod) == 0) |
226 | { | ||
227 | ss.ConsumeSimStats(stats); | ||
228 | } | ||
212 | } | 229 | } |
213 | } | 230 | } |
214 | catch (KeyNotFoundException) | 231 | catch (KeyNotFoundException) |
diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs index 31b0446..3f208bf 100644 --- a/OpenSim/Server/Base/ServerUtils.cs +++ b/OpenSim/Server/Base/ServerUtils.cs | |||
@@ -89,12 +89,39 @@ namespace OpenSim.Server.Base | |||
89 | Config = config; | 89 | Config = config; |
90 | 90 | ||
91 | Registry = new AddinRegistry(registryPath, "."); | 91 | Registry = new AddinRegistry(registryPath, "."); |
92 | suppress_console_output_(true); | ||
92 | AddinManager.Initialize(registryPath); | 93 | AddinManager.Initialize(registryPath); |
94 | suppress_console_output_(false); | ||
93 | AddinManager.Registry.Update(); | 95 | AddinManager.Registry.Update(); |
94 | CommandManager commandmanager = new CommandManager(Registry); | 96 | CommandManager commandmanager = new CommandManager(Registry); |
95 | AddinManager.AddExtensionNodeHandler("/Robust/Connector", OnExtensionChanged); | 97 | AddinManager.AddExtensionNodeHandler("/Robust/Connector", OnExtensionChanged); |
96 | } | 98 | } |
97 | 99 | ||
100 | private static TextWriter prev_console_; | ||
101 | // Temporarily masking the errors reported on start | ||
102 | // This is caused by a non-managed dll in the ./bin dir | ||
103 | // when the registry is initialized. The dll belongs to | ||
104 | // libomv, which has a hard-coded path to "." for pinvoke | ||
105 | // to load the openjpeg dll | ||
106 | // | ||
107 | // Will look for a way to fix, but for now this keeps the | ||
108 | // confusion to a minimum. this was copied from our region | ||
109 | // plugin loader, we have been doing this in there for a long time. | ||
110 | // | ||
111 | public void suppress_console_output_(bool save) | ||
112 | { | ||
113 | if (save) | ||
114 | { | ||
115 | prev_console_ = System.Console.Out; | ||
116 | System.Console.SetOut(new StreamWriter(Stream.Null)); | ||
117 | } | ||
118 | else | ||
119 | { | ||
120 | if (prev_console_ != null) | ||
121 | System.Console.SetOut(prev_console_); | ||
122 | } | ||
123 | } | ||
124 | |||
98 | private void OnExtensionChanged(object s, ExtensionNodeEventArgs args) | 125 | private void OnExtensionChanged(object s, ExtensionNodeEventArgs args) |
99 | { | 126 | { |
100 | IRobustConnector connector = (IRobustConnector)args.ExtensionObject; | 127 | IRobustConnector connector = (IRobustConnector)args.ExtensionObject; |
@@ -112,8 +139,7 @@ namespace OpenSim.Server.Base | |||
112 | if (a.AddinFile.Contains(Registry.DefaultAddinsFolder)) | 139 | if (a.AddinFile.Contains(Registry.DefaultAddinsFolder)) |
113 | { | 140 | { |
114 | m_log.InfoFormat("[SERVER]: Adding {0} from registry", a.Name); | 141 | m_log.InfoFormat("[SERVER]: Adding {0} from registry", a.Name); |
115 | connector.PluginPath = String.Format("{0}/{1}", Registry.DefaultAddinsFolder, a.Name.Replace(',', '.')); | 142 | connector.PluginPath = System.IO.Path.Combine(Registry.DefaultAddinsFolder,a.Name.Replace(',', '.')); } |
116 | } | ||
117 | else | 143 | else |
118 | { | 144 | { |
119 | m_log.InfoFormat("[SERVER]: Adding {0} from ./bin", a.Name); | 145 | m_log.InfoFormat("[SERVER]: Adding {0} from ./bin", a.Name); |
@@ -189,20 +215,30 @@ namespace OpenSim.Server.Base | |||
189 | /// <param name="dllName"></param> | 215 | /// <param name="dllName"></param> |
190 | /// <param name="args">The arguments which control which constructor is invoked on the plugin</param> | 216 | /// <param name="args">The arguments which control which constructor is invoked on the plugin</param> |
191 | /// <returns></returns> | 217 | /// <returns></returns> |
192 | public static T LoadPlugin<T>(string dllName, Object[] args) where T:class | 218 | public static T LoadPlugin<T> (string dllName, Object[] args) where T:class |
193 | { | 219 | { |
194 | // This is good to debug configuration problems | 220 | // This is good to debug configuration problems |
195 | //if (dllName == string.Empty) | 221 | //if (dllName == string.Empty) |
196 | // Util.PrintCallStack(); | 222 | // Util.PrintCallStack(); |
197 | 223 | ||
198 | string[] parts = dllName.Split(new char[] {':'}); | ||
199 | |||
200 | dllName = parts[0]; | ||
201 | |||
202 | string className = String.Empty; | 224 | string className = String.Empty; |
203 | 225 | ||
204 | if (parts.Length > 1) | 226 | // The path for a dynamic plugin will contain ":" on Windows |
205 | className = parts[1]; | 227 | string[] parts = dllName.Split (new char[] {':'}); |
228 | |||
229 | if (parts [0].Length > 1) | ||
230 | { | ||
231 | dllName = parts [0]; | ||
232 | if (parts.Length > 1) | ||
233 | className = parts[1]; | ||
234 | } | ||
235 | else | ||
236 | { | ||
237 | // This is Windows - we must replace the ":" in the path | ||
238 | dllName = String.Format ("{0}:{1}", parts [0], parts [1]); | ||
239 | if (parts.Length > 2) | ||
240 | className = parts[2]; | ||
241 | } | ||
206 | 242 | ||
207 | return LoadPlugin<T>(dllName, className, args); | 243 | return LoadPlugin<T>(dllName, className, args); |
208 | } | 244 | } |