aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs13
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs101
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs449
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs43
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs111
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs12
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs142
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActors.cs8
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs6
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs127
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs2
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs41
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs21
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs272
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs20
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs12
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs11
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs77
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs220
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs22
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs21
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs3
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs1019
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapes.cs712
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs30
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs60
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs56
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs48
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt18
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs7
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs6
44 files changed, 1986 insertions, 1761 deletions
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index d86eefe..f9e0cf1 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -425,9 +425,6 @@ namespace OpenSim
425 425
426 mscene = scene; 426 mscene = scene;
427 427
428 scene.Start();
429 scene.StartScripts();
430
431 return clientServers; 428 return clientServers;
432 } 429 }
433 430
@@ -751,6 +748,7 @@ namespace OpenSim
751 ShutdownClientServer(whichRegion); 748 ShutdownClientServer(whichRegion);
752 IScene scene; 749 IScene scene;
753 CreateRegion(whichRegion, true, out scene); 750 CreateRegion(whichRegion, true, out scene);
751 scene.Start();
754 } 752 }
755 753
756 # region Setup methods 754 # region Setup methods
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 8752404..a46c24a 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -273,11 +273,22 @@ namespace OpenSim.Region.ClientStack.Linden
273 return string.Empty; 273 return string.Empty;
274 } 274 }
275 275
276 Hashtable caps = m_HostCapsObj.CapsHandlers.GetCapsDetails(true); 276 OSDArray capsRequested = (OSDArray)OSDParser.DeserializeLLSDXml(request);
277 List<string> validCaps = new List<string>();
278
279 foreach (OSD c in capsRequested)
280 validCaps.Add(c.AsString());
281
282 Hashtable caps = m_HostCapsObj.CapsHandlers.GetCapsDetails(true, validCaps);
277 283
278 // Add the external too 284 // Add the external too
279 foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers) 285 foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers)
286 {
287 if (!validCaps.Contains(kvp.Key))
288 continue;
289
280 caps[kvp.Key] = kvp.Value; 290 caps[kvp.Key] = kvp.Value;
291 }
281 292
282 string result = LLSDHelpers.SerialiseLLSDReply(caps); 293 string result = LLSDHelpers.SerialiseLLSDReply(caps);
283 294
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
index 7d9f581..a0e0078 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
@@ -75,6 +75,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
75 [SetUp] 75 [SetUp]
76 public void SetUp() 76 public void SetUp()
77 { 77 {
78 base.SetUp();
79
78 UUID userId = TestHelpers.ParseTail(0x3); 80 UUID userId = TestHelpers.ParseTail(0x3);
79 81
80 J2KDecoderModule j2kdm = new J2KDecoderModule(); 82 J2KDecoderModule j2kdm = new J2KDecoderModule();
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index bcb7f42..1417a19 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -47,10 +47,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
47 47
48 /// <summary> 48 /// <summary>
49 private List<Scene> m_Scenelist = new List<Scene>(); 49 private List<Scene> m_Scenelist = new List<Scene>();
50// private Dictionary<UUID, Scene> m_AgentRegions =
51// new Dictionary<UUID, Scene>();
52 50
53 private IMessageTransferModule m_TransferModule = null; 51 private IMessageTransferModule m_TransferModule;
54 private bool m_Enabled = true; 52 private bool m_Enabled = true;
55 53
56 #region Region Module interface 54 #region Region Module interface
@@ -81,9 +79,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
81// scene.RegisterModuleInterface<IInventoryTransferModule>(this); 79// scene.RegisterModuleInterface<IInventoryTransferModule>(this);
82 80
83 scene.EventManager.OnNewClient += OnNewClient; 81 scene.EventManager.OnNewClient += OnNewClient;
84// scene.EventManager.OnClientClosed += ClientLoggedOut;
85 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; 82 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
86// scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
87 } 83 }
88 84
89 public void RegionLoaded(Scene scene) 85 public void RegionLoaded(Scene scene)
@@ -96,11 +92,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
96 m_log.Error("[INVENTORY TRANSFER]: No Message transfer module found, transfers will be local only"); 92 m_log.Error("[INVENTORY TRANSFER]: No Message transfer module found, transfers will be local only");
97 m_Enabled = false; 93 m_Enabled = false;
98 94
99 m_Scenelist.Clear(); 95// m_Scenelist.Clear();
100 scene.EventManager.OnNewClient -= OnNewClient; 96// scene.EventManager.OnNewClient -= OnNewClient;
101// scene.EventManager.OnClientClosed -= ClientLoggedOut;
102 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 97 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
103// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
104 } 98 }
105 } 99 }
106 } 100 }
@@ -108,9 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
108 public void RemoveRegion(Scene scene) 102 public void RemoveRegion(Scene scene)
109 { 103 {
110 scene.EventManager.OnNewClient -= OnNewClient; 104 scene.EventManager.OnNewClient -= OnNewClient;
111// scene.EventManager.OnClientClosed -= ClientLoggedOut;
112 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 105 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
113// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
114 m_Scenelist.Remove(scene); 106 m_Scenelist.Remove(scene);
115 } 107 }
116 108
@@ -139,11 +131,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
139 // Inventory giving is conducted via instant message 131 // Inventory giving is conducted via instant message
140 client.OnInstantMessage += OnInstantMessage; 132 client.OnInstantMessage += OnInstantMessage;
141 } 133 }
142
143// protected void OnSetRootAgentScene(UUID id, Scene scene)
144// {
145// m_AgentRegions[id] = scene;
146// }
147 134
148 private Scene FindClientScene(UUID agentId) 135 private Scene FindClientScene(UUID agentId)
149 { 136 {
@@ -188,9 +175,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
188 { 175 {
189 UUID folderID = new UUID(im.binaryBucket, 1); 176 UUID folderID = new UUID(im.binaryBucket, 1);
190 177
191 m_log.DebugFormat("[INVENTORY TRANSFER]: Inserting original folder {0} "+ 178 m_log.DebugFormat(
192 "into agent {1}'s inventory", 179 "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory",
193 folderID, new UUID(im.toAgentID)); 180 folderID, new UUID(im.toAgentID));
194 181
195 InventoryFolderBase folderCopy 182 InventoryFolderBase folderCopy
196 = scene.GiveInventoryFolder(receipientID, client.AgentId, folderID, UUID.Zero); 183 = scene.GiveInventoryFolder(receipientID, client.AgentId, folderID, UUID.Zero);
@@ -213,7 +200,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
213 user.ControllingClient.SendBulkUpdateInventory(folderCopy); 200 user.ControllingClient.SendBulkUpdateInventory(folderCopy);
214 201
215 // HACK!! 202 // HACK!!
216 im.imSessionID = folderID.Guid; 203 // Insert the ID of the copied folder into the IM so that we know which item to move to trash if it
204 // is rejected.
205 // XXX: This is probably a misuse of the session ID slot.
206 im.imSessionID = copyID.Guid;
217 } 207 }
218 else 208 else
219 { 209 {
@@ -243,7 +233,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
243 user.ControllingClient.SendBulkUpdateInventory(itemCopy); 233 user.ControllingClient.SendBulkUpdateInventory(itemCopy);
244 234
245 // HACK!! 235 // HACK!!
246 im.imSessionID = itemID.Guid; 236 // Insert the ID of the copied item into the IM so that we know which item to move to trash if it
237 // is rejected.
238 // XXX: This is probably a misuse of the session ID slot.
239 im.imSessionID = copyID.Guid;
247 } 240 }
248 241
249 // Send the IM to the recipient. The item is already 242 // Send the IM to the recipient. The item is already
@@ -403,7 +396,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
403 { 396 {
404 folder = new InventoryFolderBase(inventoryID, client.AgentId); 397 folder = new InventoryFolderBase(inventoryID, client.AgentId);
405 folder = invService.GetFolder(folder); 398 folder = invService.GetFolder(folder);
406 399
407 if (folder != null & trashFolder != null) 400 if (folder != null & trashFolder != null)
408 { 401 {
409 previousParentFolderID = folder.ParentID; 402 previousParentFolderID = folder.ParentID;
@@ -454,70 +447,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
454 } 447 }
455 } 448 }
456 449
457// public bool NeedSceneCacheClear(UUID agentID, Scene scene)
458// {
459// if (!m_AgentRegions.ContainsKey(agentID))
460// {
461// // Since we can get here two ways, we need to scan
462// // the scenes here. This is somewhat more expensive
463// // but helps avoid a nasty bug
464// //
465//
466// foreach (Scene s in m_Scenelist)
467// {
468// ScenePresence presence;
469//
470// if (s.TryGetScenePresence(agentID, out presence))
471// {
472// // If the agent is in this scene, then we
473// // are being called twice in a single
474// // teleport. This is wasteful of cycles
475// // but harmless due to this 2nd level check
476// //
477// // If the agent is found in another scene
478// // then the list wasn't current
479// //
480// // If the agent is totally unknown, then what
481// // are we even doing here??
482// //
483// if (s == scene)
484// {
485// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName);
486// return true;
487// }
488// else
489// {
490// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName);
491// return false;
492// }
493// }
494// }
495// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName);
496// return true;
497// }
498//
499// // The agent is left in current Scene, so we must be
500// // going to another instance
501// //
502// if (m_AgentRegions[agentID] == scene)
503// {
504// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName);
505// m_AgentRegions.Remove(agentID);
506// return true;
507// }
508//
509// // Another region has claimed the agent
510// //
511// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName);
512// return false;
513// }
514//
515// public void ClientLoggedOut(UUID agentID, Scene scene)
516// {
517// if (m_AgentRegions.ContainsKey(agentID))
518// m_AgentRegions.Remove(agentID);
519// }
520
521 /// <summary> 450 /// <summary>
522 /// 451 ///
523 /// </summary> 452 /// </summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
new file mode 100644
index 0000000..162a0c3
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
@@ -0,0 +1,449 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net.Config;
32using Nini.Config;
33using NUnit.Framework;
34using OpenMetaverse;
35using OpenMetaverse.Assets;
36using OpenSim.Framework;
37using OpenSim.Region.CoreModules.Avatar.Inventory.Transfer;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Tests.Common;
42using OpenSim.Tests.Common.Mock;
43
44namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
45{
46 [TestFixture]
47 public class InventoryTransferModuleTests : OpenSimTestCase
48 {
49 protected TestScene m_scene;
50
51 [SetUp]
52 public override void SetUp()
53 {
54 base.SetUp();
55
56 IConfigSource config = new IniConfigSource();
57 config.AddConfig("Messaging");
58 config.Configs["Messaging"].Set("InventoryTransferModule", "InventoryTransferModule");
59
60 m_scene = new SceneHelpers().SetupScene();
61 SceneHelpers.SetupSceneModules(m_scene, config, new InventoryTransferModule());
62 }
63
64 [Test]
65 public void TestAcceptGivenItem()
66 {
67// TestHelpers.EnableLogging();
68
69 UUID initialSessionId = TestHelpers.ParseTail(0x10);
70 UUID itemId = TestHelpers.ParseTail(0x100);
71 UUID assetId = TestHelpers.ParseTail(0x200);
72
73 UserAccount ua1
74 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
75 UserAccount ua2
76 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
77
78 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
79 TestClient giverClient = (TestClient)giverSp.ControllingClient;
80
81 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
82 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
83
84 // Create the object to test give
85 InventoryItemBase originalItem
86 = UserInventoryHelpers.CreateInventoryItem(
87 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
88
89 byte[] giveImBinaryBucket = new byte[17];
90 byte[] itemIdBytes = itemId.GetBytes();
91 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
92
93 GridInstantMessage giveIm
94 = new GridInstantMessage(
95 m_scene,
96 giverSp.UUID,
97 giverSp.Name,
98 receiverSp.UUID,
99 (byte)InstantMessageDialog.InventoryOffered,
100 false,
101 "inventory offered msg",
102 initialSessionId,
103 false,
104 Vector3.Zero,
105 giveImBinaryBucket,
106 true);
107
108 giverClient.HandleImprovedInstantMessage(giveIm);
109
110 // These details might not all be correct.
111 GridInstantMessage acceptIm
112 = new GridInstantMessage(
113 m_scene,
114 receiverSp.UUID,
115 receiverSp.Name,
116 giverSp.UUID,
117 (byte)InstantMessageDialog.InventoryAccepted,
118 false,
119 "inventory accepted msg",
120 initialSessionId,
121 false,
122 Vector3.Zero,
123 null,
124 true);
125
126 receiverClient.HandleImprovedInstantMessage(acceptIm);
127
128 // Test for item remaining in the giver's inventory (here we assume a copy item)
129 // TODO: Test no-copy items.
130 InventoryItemBase originalItemAfterGive
131 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
132
133 Assert.That(originalItemAfterGive, Is.Not.Null);
134 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
135
136 // Test for item successfully making it into the receiver's inventory
137 InventoryItemBase receivedItem
138 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Objects/givenObj");
139
140 Assert.That(receivedItem, Is.Not.Null);
141 Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID));
142
143 // Test that on a delete, item still exists and is accessible for the giver.
144 m_scene.InventoryService.DeleteItems(receiverSp.UUID, new List<UUID>() { receivedItem.ID });
145
146 InventoryItemBase originalItemAfterDelete
147 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
148
149 Assert.That(originalItemAfterDelete, Is.Not.Null);
150
151 // TODO: Test scenario where giver deletes their item first.
152 }
153
154 /// <summary>
155 /// Test user rejection of a given item.
156 /// </summary>
157 /// <remarks>
158 /// A rejected item still ends up in the user's trash folder.
159 /// </remarks>
160 [Test]
161 public void TestRejectGivenItem()
162 {
163// TestHelpers.EnableLogging();
164
165 UUID initialSessionId = TestHelpers.ParseTail(0x10);
166 UUID itemId = TestHelpers.ParseTail(0x100);
167 UUID assetId = TestHelpers.ParseTail(0x200);
168
169 UserAccount ua1
170 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
171 UserAccount ua2
172 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
173
174 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
175 TestClient giverClient = (TestClient)giverSp.ControllingClient;
176
177 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
178 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
179
180 // Create the object to test give
181 InventoryItemBase originalItem
182 = UserInventoryHelpers.CreateInventoryItem(
183 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
184
185 GridInstantMessage receivedIm = null;
186 receiverClient.OnReceivedInstantMessage += im => receivedIm = im;
187
188 byte[] giveImBinaryBucket = new byte[17];
189 byte[] itemIdBytes = itemId.GetBytes();
190 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
191
192 GridInstantMessage giveIm
193 = new GridInstantMessage(
194 m_scene,
195 giverSp.UUID,
196 giverSp.Name,
197 receiverSp.UUID,
198 (byte)InstantMessageDialog.InventoryOffered,
199 false,
200 "inventory offered msg",
201 initialSessionId,
202 false,
203 Vector3.Zero,
204 giveImBinaryBucket,
205 true);
206
207 giverClient.HandleImprovedInstantMessage(giveIm);
208
209 // These details might not all be correct.
210 // Session ID is now the created item ID (!)
211 GridInstantMessage rejectIm
212 = new GridInstantMessage(
213 m_scene,
214 receiverSp.UUID,
215 receiverSp.Name,
216 giverSp.UUID,
217 (byte)InstantMessageDialog.InventoryDeclined,
218 false,
219 "inventory declined msg",
220 new UUID(receivedIm.imSessionID),
221 false,
222 Vector3.Zero,
223 null,
224 true);
225
226 receiverClient.HandleImprovedInstantMessage(rejectIm);
227
228 // Test for item remaining in the giver's inventory (here we assume a copy item)
229 // TODO: Test no-copy items.
230 InventoryItemBase originalItemAfterGive
231 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
232
233 Assert.That(originalItemAfterGive, Is.Not.Null);
234 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
235
236 // Test for item successfully making it into the receiver's inventory
237 InventoryItemBase receivedItem
238 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Trash/givenObj");
239
240 InventoryFolderBase trashFolder
241 = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, AssetType.TrashFolder);
242
243 Assert.That(receivedItem, Is.Not.Null);
244 Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID));
245 Assert.That(receivedItem.Folder, Is.EqualTo(trashFolder.ID));
246
247 // Test that on a delete, item still exists and is accessible for the giver.
248 m_scene.InventoryService.PurgeFolder(trashFolder);
249
250 InventoryItemBase originalItemAfterDelete
251 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
252
253 Assert.That(originalItemAfterDelete, Is.Not.Null);
254 }
255
256 [Test]
257 public void TestAcceptGivenFolder()
258 {
259 TestHelpers.InMethod();
260// TestHelpers.EnableLogging();
261
262 UUID initialSessionId = TestHelpers.ParseTail(0x10);
263 UUID folderId = TestHelpers.ParseTail(0x100);
264
265 UserAccount ua1
266 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
267 UserAccount ua2
268 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
269
270 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
271 TestClient giverClient = (TestClient)giverSp.ControllingClient;
272
273 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
274 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
275
276 InventoryFolderBase originalFolder
277 = UserInventoryHelpers.CreateInventoryFolder(
278 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
279
280 byte[] giveImBinaryBucket = new byte[17];
281 giveImBinaryBucket[0] = (byte)AssetType.Folder;
282 byte[] itemIdBytes = folderId.GetBytes();
283 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
284
285 GridInstantMessage giveIm
286 = new GridInstantMessage(
287 m_scene,
288 giverSp.UUID,
289 giverSp.Name,
290 receiverSp.UUID,
291 (byte)InstantMessageDialog.InventoryOffered,
292 false,
293 "inventory offered msg",
294 initialSessionId,
295 false,
296 Vector3.Zero,
297 giveImBinaryBucket,
298 true);
299
300 giverClient.HandleImprovedInstantMessage(giveIm);
301
302 // These details might not all be correct.
303 GridInstantMessage acceptIm
304 = new GridInstantMessage(
305 m_scene,
306 receiverSp.UUID,
307 receiverSp.Name,
308 giverSp.UUID,
309 (byte)InstantMessageDialog.InventoryAccepted,
310 false,
311 "inventory accepted msg",
312 initialSessionId,
313 false,
314 Vector3.Zero,
315 null,
316 true);
317
318 receiverClient.HandleImprovedInstantMessage(acceptIm);
319
320 // Test for item remaining in the giver's inventory (here we assume a copy item)
321 // TODO: Test no-copy items.
322 InventoryFolderBase originalFolderAfterGive
323 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
324
325 Assert.That(originalFolderAfterGive, Is.Not.Null);
326 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
327
328 // Test for item successfully making it into the receiver's inventory
329 InventoryFolderBase receivedFolder
330 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "f1");
331
332 Assert.That(receivedFolder, Is.Not.Null);
333 Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID));
334
335 // Test that on a delete, item still exists and is accessible for the giver.
336 m_scene.InventoryService.DeleteFolders(receiverSp.UUID, new List<UUID>() { receivedFolder.ID });
337
338 InventoryFolderBase originalFolderAfterDelete
339 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
340
341 Assert.That(originalFolderAfterDelete, Is.Not.Null);
342
343 // TODO: Test scenario where giver deletes their item first.
344 }
345
346 /// <summary>
347 /// Test user rejection of a given item.
348 /// </summary>
349 /// <remarks>
350 /// A rejected item still ends up in the user's trash folder.
351 /// </remarks>
352 [Test]
353 public void TestRejectGivenFolder()
354 {
355 TestHelpers.InMethod();
356// TestHelpers.EnableLogging();
357
358 UUID initialSessionId = TestHelpers.ParseTail(0x10);
359 UUID folderId = TestHelpers.ParseTail(0x100);
360
361 UserAccount ua1
362 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
363 UserAccount ua2
364 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
365
366 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
367 TestClient giverClient = (TestClient)giverSp.ControllingClient;
368
369 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
370 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
371
372 // Create the folder to test give
373 InventoryFolderBase originalFolder
374 = UserInventoryHelpers.CreateInventoryFolder(
375 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
376
377 GridInstantMessage receivedIm = null;
378 receiverClient.OnReceivedInstantMessage += im => receivedIm = im;
379
380 byte[] giveImBinaryBucket = new byte[17];
381 giveImBinaryBucket[0] = (byte)AssetType.Folder;
382 byte[] itemIdBytes = folderId.GetBytes();
383 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
384
385 GridInstantMessage giveIm
386 = new GridInstantMessage(
387 m_scene,
388 giverSp.UUID,
389 giverSp.Name,
390 receiverSp.UUID,
391 (byte)InstantMessageDialog.InventoryOffered,
392 false,
393 "inventory offered msg",
394 initialSessionId,
395 false,
396 Vector3.Zero,
397 giveImBinaryBucket,
398 true);
399
400 giverClient.HandleImprovedInstantMessage(giveIm);
401
402 // These details might not all be correct.
403 // Session ID is now the created item ID (!)
404 GridInstantMessage rejectIm
405 = new GridInstantMessage(
406 m_scene,
407 receiverSp.UUID,
408 receiverSp.Name,
409 giverSp.UUID,
410 (byte)InstantMessageDialog.InventoryDeclined,
411 false,
412 "inventory declined msg",
413 new UUID(receivedIm.imSessionID),
414 false,
415 Vector3.Zero,
416 null,
417 true);
418
419 receiverClient.HandleImprovedInstantMessage(rejectIm);
420
421 // Test for item remaining in the giver's inventory (here we assume a copy item)
422 // TODO: Test no-copy items.
423 InventoryFolderBase originalFolderAfterGive
424 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
425
426 Assert.That(originalFolderAfterGive, Is.Not.Null);
427 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
428
429 // Test for folder successfully making it into the receiver's inventory
430 InventoryFolderBase receivedFolder
431 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "Trash/f1");
432
433 InventoryFolderBase trashFolder
434 = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, AssetType.TrashFolder);
435
436 Assert.That(receivedFolder, Is.Not.Null);
437 Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID));
438 Assert.That(receivedFolder.ParentID, Is.EqualTo(trashFolder.ID));
439
440 // Test that on a delete, item still exists and is accessible for the giver.
441 m_scene.InventoryService.PurgeFolder(trashFolder);
442
443 InventoryFolderBase originalFolderAfterDelete
444 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
445
446 Assert.That(originalFolderAfterDelete, Is.Not.Null);
447 }
448 }
449} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index 8329af0..6ae9448 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -240,7 +240,7 @@ namespace OpenSim.Region.CoreModules.Framework
240 { 240 {
241 caps.AppendFormat("** User {0}:\n", kvp.Key); 241 caps.AppendFormat("** User {0}:\n", kvp.Key);
242 242
243 for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false).GetEnumerator(); kvp2.MoveNext(); ) 243 for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); )
244 { 244 {
245 Uri uri = new Uri(kvp2.Value.ToString()); 245 Uri uri = new Uri(kvp2.Value.ToString());
246 caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery); 246 caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery);
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index e0009bb..e6d6cbf 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -646,11 +646,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
646 } 646 }
647 else 647 else
648 { 648 {
649 if (remoteClient == null || so.OwnerID != remoteClient.AgentId) 649 if (remoteClient == null || so.RootPart.OwnerID != remoteClient.AgentId)
650 { 650 {
651 // Taking copy of another person's item. Take to 651 // Taking copy of another person's item. Take to
652 // Objects folder. 652 // Objects folder.
653 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); 653 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
654 so.FromFolderID = UUID.Zero;
654 } 655 }
655 else 656 else
656 { 657 {
@@ -666,10 +667,16 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
666 // 667 //
667 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) 668 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy)
668 { 669 {
669 if (so.FromFolderID != UUID.Zero && userID == remoteClient.AgentId) 670 if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId)
670 { 671 {
671 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); 672 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID);
672 folder = m_Scene.InventoryService.GetFolder(f); 673 folder = m_Scene.InventoryService.GetFolder(f);
674
675 if(folder.Type == 14 || folder.Type == 16)
676 {
677 // folder.Type = 6;
678 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
679 }
673 } 680 }
674 } 681 }
675 682
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index c0c2ca7..c32820e 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -142,10 +142,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
142 142
143 scene.RegisterModuleInterface<IGridService>(this); 143 scene.RegisterModuleInterface<IGridService>(this);
144 144
145 if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID)) 145 lock (m_LocalCache)
146 m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!"); 146 {
147 else 147 if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID))
148 m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene)); 148 m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
149 else
150 m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene));
151 }
149 } 152 }
150 153
151 public void RemoveRegion(Scene scene) 154 public void RemoveRegion(Scene scene)
@@ -153,8 +156,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
153 if (!m_Enabled) 156 if (!m_Enabled)
154 return; 157 return;
155 158
156 m_LocalCache[scene.RegionInfo.RegionID].Clear(); 159 lock (m_LocalCache)
157 m_LocalCache.Remove(scene.RegionInfo.RegionID); 160 {
161 m_LocalCache[scene.RegionInfo.RegionID].Clear();
162 m_LocalCache.Remove(scene.RegionInfo.RegionID);
163 }
158 } 164 }
159 165
160 public void RegionLoaded(Scene scene) 166 public void RegionLoaded(Scene scene)
@@ -191,12 +197,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
191 197
192 // First see if it's a neighbour, even if it isn't on this sim. 198 // First see if it's a neighbour, even if it isn't on this sim.
193 // Neighbour data is cached in memory, so this is fast 199 // Neighbour data is cached in memory, so this is fast
194 foreach (RegionCache rcache in m_LocalCache.Values) 200
201 lock (m_LocalCache)
195 { 202 {
196 region = rcache.GetRegionByPosition(x, y); 203 foreach (RegionCache rcache in m_LocalCache.Values)
197 if (region != null)
198 { 204 {
199 return region; 205 region = rcache.GetRegionByPosition(x, y);
206 if (region != null)
207 {
208 return region;
209 }
200 } 210 }
201 } 211 }
202 212
@@ -245,12 +255,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
245 { 255 {
246 System.Text.StringBuilder caps = new System.Text.StringBuilder(); 256 System.Text.StringBuilder caps = new System.Text.StringBuilder();
247 257
248 foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache) 258 lock (m_LocalCache)
249 { 259 {
250 caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key); 260 foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache)
251 List<GridRegion> regions = kvp.Value.GetNeighbours(); 261 {
252 foreach (GridRegion r in regions) 262 caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key);
253 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, r.RegionLocX / Constants.RegionSize, r.RegionLocY / Constants.RegionSize); 263 List<GridRegion> regions = kvp.Value.GetNeighbours();
264 foreach (GridRegion r in regions)
265 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, r.RegionLocX / Constants.RegionSize, r.RegionLocY / Constants.RegionSize);
266 }
254 } 267 }
255 268
256 MainConsole.Instance.Output(caps.ToString()); 269 MainConsole.Instance.Output(caps.ToString());
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index ff7e5ed..8fe2d72 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -389,10 +389,12 @@ namespace OpenSim.Region.Framework.Scenes
389 if (value) 389 if (value)
390 { 390 {
391 if (!m_active) 391 if (!m_active)
392 Start(); 392 Start(false);
393 } 393 }
394 else 394 else
395 { 395 {
396 // This appears assymetric with Start() above but is not - setting m_active = false stops the loops
397 // XXX: Possibly this should be in an explicit Stop() method for symmetry.
396 m_active = false; 398 m_active = false;
397 } 399 }
398 } 400 }
@@ -1331,10 +1333,18 @@ namespace OpenSim.Region.Framework.Scenes
1331 } 1333 }
1332 } 1334 }
1333 1335
1336 public override void Start()
1337 {
1338 Start(true);
1339 }
1340
1334 /// <summary> 1341 /// <summary>
1335 /// Start the scene 1342 /// Start the scene
1336 /// </summary> 1343 /// </summary>
1337 public void Start() 1344 /// <param name='startScripts'>
1345 /// Start the scripts within the scene.
1346 /// </param>
1347 public void Start(bool startScripts)
1338 { 1348 {
1339 m_active = true; 1349 m_active = true;
1340 1350
@@ -1353,6 +1363,8 @@ namespace OpenSim.Region.Framework.Scenes
1353 m_heartbeatThread 1363 m_heartbeatThread
1354 = Watchdog.StartThread( 1364 = Watchdog.StartThread(
1355 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); 1365 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false);
1366
1367 StartScripts();
1356 } 1368 }
1357 1369
1358 /// <summary> 1370 /// <summary>
@@ -3699,7 +3711,7 @@ namespace OpenSim.Region.Framework.Scenes
3699 // On login test land permisions 3711 // On login test land permisions
3700 if (vialogin) 3712 if (vialogin)
3701 { 3713 {
3702 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3714 if (land != null && !TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3703 { 3715 {
3704 m_authenticateHandler.RemoveCircuit(agent.circuitcode); 3716 m_authenticateHandler.RemoveCircuit(agent.circuitcode);
3705 return false; 3717 return false;
@@ -3880,20 +3892,37 @@ namespace OpenSim.Region.Framework.Scenes
3880 return true; 3892 return true;
3881 } 3893 }
3882 3894
3883 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3895 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3884 { 3896 {
3885 bool banned = land.IsBannedFromLand(agent.AgentID); 3897 if (posX < 0)
3886 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3898 posX = 0;
3899 else if (posX >= 256)
3900 posX = 255.999f;
3901 if (posY < 0)
3902 posY = 0;
3903 else if (posY >= 256)
3904 posY = 255.999f;
3905
3906 reason = String.Empty;
3907 if (Permissions.IsGod(agentID))
3908 return true;
3909
3910 ILandObject land = LandChannel.GetLandObject(posX, posY);
3911 if (land == null)
3912 return false;
3913
3914 bool banned = land.IsBannedFromLand(agentID);
3915 bool restricted = land.IsRestrictedFromLand(agentID);
3887 3916
3888 if (banned || restricted) 3917 if (banned || restricted)
3889 { 3918 {
3890 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3919 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3891 if (nearestParcel != null) 3920 if (nearestParcel != null)
3892 { 3921 {
3893 //Move agent to nearest allowed 3922 //Move agent to nearest allowed
3894 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3923 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3895 agent.startpos.X = newPosition.X; 3924 posX = newPosition.X;
3896 agent.startpos.Y = newPosition.Y; 3925 posY = newPosition.Y;
3897 } 3926 }
3898 else 3927 else
3899 { 3928 {
@@ -5478,6 +5507,8 @@ namespace OpenSim.Region.Framework.Scenes
5478 /// <returns></returns> 5507 /// <returns></returns>
5479 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5508 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5480 { 5509 {
5510 reason = "You are banned from the region";
5511
5481 if (EntityTransferModule.IsInTransit(agentID)) 5512 if (EntityTransferModule.IsInTransit(agentID))
5482 { 5513 {
5483 reason = "Agent is still in transit from this region"; 5514 reason = "Agent is still in transit from this region";
@@ -5489,6 +5520,12 @@ namespace OpenSim.Region.Framework.Scenes
5489 return false; 5520 return false;
5490 } 5521 }
5491 5522
5523 if (Permissions.IsGod(agentID))
5524 {
5525 reason = String.Empty;
5526 return true;
5527 }
5528
5492 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. 5529 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check.
5493 // However, the long term fix is to make sure root agent count is always accurate. 5530 // However, the long term fix is to make sure root agent count is always accurate.
5494 m_sceneGraph.RecalculateStats(); 5531 m_sceneGraph.RecalculateStats();
@@ -5509,6 +5546,41 @@ namespace OpenSim.Region.Framework.Scenes
5509 } 5546 }
5510 } 5547 }
5511 5548
5549 ScenePresence presence = GetScenePresence(agentID);
5550 IClientAPI client = null;
5551 AgentCircuitData aCircuit = null;
5552
5553 if (presence != null)
5554 {
5555 client = presence.ControllingClient;
5556 if (client != null)
5557 aCircuit = client.RequestClientInfo();
5558 }
5559
5560 // We may be called before there is a presence or a client.
5561 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5562 if (client == null)
5563 {
5564 aCircuit = new AgentCircuitData();
5565 aCircuit.AgentID = agentID;
5566 aCircuit.firstname = String.Empty;
5567 aCircuit.lastname = String.Empty;
5568 }
5569
5570 try
5571 {
5572 if (!AuthorizeUser(aCircuit, out reason))
5573 {
5574 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5575 return false;
5576 }
5577 }
5578 catch (Exception e)
5579 {
5580 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5581 return false;
5582 }
5583
5512 if (position == Vector3.Zero) // Teleport 5584 if (position == Vector3.Zero) // Teleport
5513 { 5585 {
5514 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5586 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5542,6 +5614,27 @@ namespace OpenSim.Region.Framework.Scenes
5542 } 5614 }
5543 } 5615 }
5544 } 5616 }
5617
5618 float posX = 128.0f;
5619 float posY = 128.0f;
5620
5621 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5622 {
5623 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5624 return false;
5625 }
5626 }
5627 else // Walking
5628 {
5629 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5630 if (land == null)
5631 return false;
5632
5633 bool banned = land.IsBannedFromLand(agentID);
5634 bool restricted = land.IsRestrictedFromLand(agentID);
5635
5636 if (banned || restricted)
5637 return false;
5545 } 5638 }
5546 5639
5547 reason = String.Empty; 5640 reason = String.Empty;
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index d3e968e..d2097ea 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -561,6 +561,10 @@ namespace OpenSim.Region.Framework.Scenes
561 get { return false; } 561 get { return false; }
562 } 562 }
563 563
564 public virtual void Start()
565 {
566 }
567
564 public void Restart() 568 public void Restart()
565 { 569 {
566 // This has to be here to fire the event 570 // This has to be here to fire the event
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
index fdf2cb9..231f0f8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
@@ -75,11 +75,11 @@ private sealed class BulletBodyUnman : BulletBody
75private sealed class BulletShapeUnman : BulletShape 75private sealed class BulletShapeUnman : BulletShape
76{ 76{
77 public IntPtr ptr; 77 public IntPtr ptr;
78 public BulletShapeUnman(IntPtr xx, BSPhysicsShapeType typ) 78 public BulletShapeUnman(IntPtr xx, BSPhysicsShapeType typ)
79 : base() 79 : base()
80 { 80 {
81 ptr = xx; 81 ptr = xx;
82 type = typ; 82 shapeType = typ;
83 } 83 }
84 public override bool HasPhysicalShape 84 public override bool HasPhysicalShape
85 { 85 {
@@ -91,7 +91,7 @@ private sealed class BulletShapeUnman : BulletShape
91 } 91 }
92 public override BulletShape Clone() 92 public override BulletShape Clone()
93 { 93 {
94 return new BulletShapeUnman(ptr, type); 94 return new BulletShapeUnman(ptr, shapeType);
95 } 95 }
96 public override bool ReferenceSame(BulletShape other) 96 public override bool ReferenceSame(BulletShape other)
97 { 97 {
@@ -255,7 +255,7 @@ public override BulletShape CreateHullShape(BulletWorld world, int hullCount, fl
255{ 255{
256 BulletWorldUnman worldu = world as BulletWorldUnman; 256 BulletWorldUnman worldu = world as BulletWorldUnman;
257 return new BulletShapeUnman( 257 return new BulletShapeUnman(
258 BSAPICPP.CreateHullShape2(worldu.ptr, hullCount, hulls), 258 BSAPICPP.CreateHullShape2(worldu.ptr, hullCount, hulls),
259 BSPhysicsShapeType.SHAPE_HULL); 259 BSPhysicsShapeType.SHAPE_HULL);
260} 260}
261 261
@@ -375,7 +375,7 @@ public override BulletShape DuplicateCollisionShape(BulletWorld world, BulletSha
375{ 375{
376 BulletWorldUnman worldu = world as BulletWorldUnman; 376 BulletWorldUnman worldu = world as BulletWorldUnman;
377 BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman; 377 BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman;
378 return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.type); 378 return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.shapeType);
379} 379}
380 380
381public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape) 381public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape)
@@ -1503,7 +1503,7 @@ public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
1503public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin); 1503public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
1504 1504
1505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1506public static extern IntPtr CreateTerrainShape2(uint id, Vector3 size, float minHeight, float maxHeight, 1506public static extern IntPtr CreateTerrainShape2(uint id, Vector3 size, float minHeight, float maxHeight,
1507 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, 1507 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap,
1508 float scaleFactor, float collisionMargin); 1508 float scaleFactor, float collisionMargin);
1509 1509
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
index b37265a..59780ae 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -81,11 +81,11 @@ private sealed class BulletBodyXNA : BulletBody
81private sealed class BulletShapeXNA : BulletShape 81private sealed class BulletShapeXNA : BulletShape
82{ 82{
83 public CollisionShape shape; 83 public CollisionShape shape;
84 public BulletShapeXNA(CollisionShape xx, BSPhysicsShapeType typ) 84 public BulletShapeXNA(CollisionShape xx, BSPhysicsShapeType typ)
85 : base() 85 : base()
86 { 86 {
87 shape = xx; 87 shape = xx;
88 type = typ; 88 shapeType = typ;
89 } 89 }
90 public override bool HasPhysicalShape 90 public override bool HasPhysicalShape
91 { 91 {
@@ -97,7 +97,7 @@ private sealed class BulletShapeXNA : BulletShape
97 } 97 }
98 public override BulletShape Clone() 98 public override BulletShape Clone()
99 { 99 {
100 return new BulletShapeXNA(shape, type); 100 return new BulletShapeXNA(shape, shapeType);
101 } 101 }
102 public override bool ReferenceSame(BulletShape other) 102 public override bool ReferenceSame(BulletShape other)
103 { 103 {
@@ -137,8 +137,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
137 internal int LastEntityProperty = 0; 137 internal int LastEntityProperty = 0;
138 138
139 internal EntityProperties[] UpdatedObjects; 139 internal EntityProperties[] UpdatedObjects;
140 internal Dictionary<uint, GhostObject> specialCollisionObjects; 140 internal Dictionary<uint, GhostObject> specialCollisionObjects;
141 141
142 private static int m_collisionsThisFrame; 142 private static int m_collisionsThisFrame;
143 private BSScene PhysicsScene { get; set; } 143 private BSScene PhysicsScene { get; set; }
144 144
@@ -151,7 +151,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
151 } 151 }
152 152
153 /// <summary> 153 /// <summary>
154 /// 154 ///
155 /// </summary> 155 /// </summary>
156 /// <param name="p"></param> 156 /// <param name="p"></param>
157 /// <param name="p_2"></param> 157 /// <param name="p_2"></param>
@@ -174,7 +174,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
174 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 174 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
175 TypedConstraint constraint = (pConstraint as BulletConstraintXNA).constrain; 175 TypedConstraint constraint = (pConstraint as BulletConstraintXNA).constrain;
176 world.AddConstraint(constraint, pDisableCollisionsBetweenLinkedObjects); 176 world.AddConstraint(constraint, pDisableCollisionsBetweenLinkedObjects);
177 177
178 return true; 178 return true;
179 179
180 } 180 }
@@ -300,7 +300,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
300 public override bool GetForceUpdateAllAabbs(BulletWorld pWorld) { 300 public override bool GetForceUpdateAllAabbs(BulletWorld pWorld) {
301 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 301 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
302 return world.GetForceUpdateAllAabbs(); 302 return world.GetForceUpdateAllAabbs();
303 303
304 } 304 }
305 public override void SetForceUpdateAllAabbs(BulletWorld pWorld, bool pForce) 305 public override void SetForceUpdateAllAabbs(BulletWorld pWorld, bool pForce)
306 { 306 {
@@ -404,7 +404,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
404 IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(vquaternion); 404 IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(vquaternion);
405 mat._origin = vposition; 405 mat._origin = vposition;
406 collisionObject.SetWorldTransform(mat); 406 collisionObject.SetWorldTransform(mat);
407 407
408 } 408 }
409 409
410 public override Vector3 GetPosition(BulletBody pCollisionObject) 410 public override Vector3 GetPosition(BulletBody pCollisionObject)
@@ -457,7 +457,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
457 { 457 {
458 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody; 458 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
459 collisionObject.Activate(pforceactivation); 459 collisionObject.Activate(pforceactivation);
460 460
461 } 461 }
462 462
463 public override Quaternion GetOrientation(BulletBody pCollisionObject) 463 public override Quaternion GetOrientation(BulletBody pCollisionObject)
@@ -486,7 +486,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
486 { 486 {
487 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody; 487 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
488 return collisionObject.GetCcdSweptSphereRadius(); 488 return collisionObject.GetCcdSweptSphereRadius();
489 489
490 } 490 }
491 491
492 public override IntPtr GetUserPointer(BulletBody pCollisionObject) 492 public override IntPtr GetUserPointer(BulletBody pCollisionObject)
@@ -559,8 +559,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
559 } 559 }
560 560
561 561
562 public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, 562 public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
563 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, 563 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot,
564 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) 564 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
565 565
566 { 566 {
@@ -604,7 +604,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
604 } 604 }
605 605
606 /// <summary> 606 /// <summary>
607 /// 607 ///
608 /// </summary> 608 /// </summary>
609 /// <param name="pWorld"></param> 609 /// <param name="pWorld"></param>
610 /// <param name="pBody1"></param> 610 /// <param name="pBody1"></param>
@@ -824,7 +824,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
824 { 824 {
825 RigidBody body = (pBody as BulletBodyXNA).rigidBody; 825 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
826 float angularDamping = body.GetAngularDamping(); 826 float angularDamping = body.GetAngularDamping();
827 body.SetDamping(lin_damping, angularDamping); 827 body.SetDamping(lin_damping, angularDamping);
828 } 828 }
829 829
830 public override float GetLinearDamping(BulletBody pBody) 830 public override float GetLinearDamping(BulletBody pBody)
@@ -907,7 +907,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
907 RigidBody bo = co as RigidBody; 907 RigidBody bo = co as RigidBody;
908 if (bo == null) 908 if (bo == null)
909 { 909 {
910 910
911 if (world.IsInWorld(co)) 911 if (world.IsInWorld(co))
912 { 912 {
913 world.RemoveCollisionObject(co); 913 world.RemoveCollisionObject(co);
@@ -915,7 +915,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
915 } 915 }
916 else 916 else
917 { 917 {
918 918
919 if (world.IsInWorld(bo)) 919 if (world.IsInWorld(bo))
920 { 920 {
921 world.RemoveRigidBody(bo); 921 world.RemoveRigidBody(bo);
@@ -947,7 +947,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
947 947
948 // TODO: Turn this from a reference copy to a Value Copy. 948 // TODO: Turn this from a reference copy to a Value Copy.
949 BulletShapeXNA shape2 = new BulletShapeXNA(shape1, BSShapeTypeFromBroadPhaseNativeType(shape1.GetShapeType())); 949 BulletShapeXNA shape2 = new BulletShapeXNA(shape1, BSShapeTypeFromBroadPhaseNativeType(shape1.GetShapeType()));
950 950
951 return shape2; 951 return shape2;
952 } 952 }
953 953
@@ -957,7 +957,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
957 return false; 957 return false;
958 } 958 }
959 //(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation); 959 //(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation);
960 960
961 public override BulletBody CreateBodyFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) 961 public override BulletBody CreateBodyFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
962 { 962 {
963 CollisionWorld world = (pWorld as BulletWorldXNA).world; 963 CollisionWorld world = (pWorld as BulletWorldXNA).world;
@@ -993,11 +993,11 @@ private sealed class BulletConstraintXNA : BulletConstraint
993 m_startWorldTransform = IndexedMatrix.Identity; 993 m_startWorldTransform = IndexedMatrix.Identity;
994 */ 994 */
995 body.SetUserPointer(pLocalID); 995 body.SetUserPointer(pLocalID);
996 996
997 return new BulletBodyXNA(pLocalID, body); 997 return new BulletBodyXNA(pLocalID, body);
998 } 998 }
999 999
1000 1000
1001 public override BulletBody CreateBodyWithDefaultMotionState( BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) 1001 public override BulletBody CreateBodyWithDefaultMotionState( BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
1002 { 1002 {
1003 1003
@@ -1025,7 +1025,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1025 public override Vector3 GetAnisotripicFriction(BulletConstraint pconstrain) 1025 public override Vector3 GetAnisotripicFriction(BulletConstraint pconstrain)
1026 { 1026 {
1027 1027
1028 /* TODO */ 1028 /* TODO */
1029 return Vector3.Zero; 1029 return Vector3.Zero;
1030 } 1030 }
1031 public override Vector3 SetAnisotripicFriction(BulletConstraint pconstrain, Vector3 frict) { /* TODO */ return Vector3.Zero; } 1031 public override Vector3 SetAnisotripicFriction(BulletConstraint pconstrain, Vector3 frict) { /* TODO */ return Vector3.Zero; }
@@ -1035,7 +1035,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1035 { 1035 {
1036 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody; 1036 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
1037 return collisionObject.IsStaticObject(); 1037 return collisionObject.IsStaticObject();
1038 1038
1039 } 1039 }
1040 public override bool IsKinematicObject(BulletBody pCollisionObject) 1040 public override bool IsKinematicObject(BulletBody pCollisionObject)
1041 { 1041 {
@@ -1098,10 +1098,10 @@ private sealed class BulletConstraintXNA : BulletConstraint
1098 return new BulletWorldXNA(1, PhysicsScene, BSAPIXNA.Initialize2(worldExtent, configparms, maxCollisions, ref collisionArray, maxUpdates, ref updateArray, null)); 1098 return new BulletWorldXNA(1, PhysicsScene, BSAPIXNA.Initialize2(worldExtent, configparms, maxCollisions, ref collisionArray, maxUpdates, ref updateArray, null));
1099 } 1099 }
1100 1100
1101 private static DiscreteDynamicsWorld Initialize2(Vector3 worldExtent, 1101 private static DiscreteDynamicsWorld Initialize2(Vector3 worldExtent,
1102 ConfigurationParameters[] o, 1102 ConfigurationParameters[] o,
1103 int mMaxCollisionsPerFrame, ref CollisionDesc[] collisionArray, 1103 int mMaxCollisionsPerFrame, ref CollisionDesc[] collisionArray,
1104 int mMaxUpdatesPerFrame, ref EntityProperties[] updateArray, 1104 int mMaxUpdatesPerFrame, ref EntityProperties[] updateArray,
1105 object mDebugLogCallbackHandle) 1105 object mDebugLogCallbackHandle)
1106 { 1106 {
1107 CollisionWorld.WorldData.ParamData p = new CollisionWorld.WorldData.ParamData(); 1107 CollisionWorld.WorldData.ParamData p = new CollisionWorld.WorldData.ParamData();
@@ -1138,9 +1138,9 @@ private sealed class BulletConstraintXNA : BulletConstraint
1138 p.avatarCapsuleDepth = BSParam.AvatarCapsuleDepth; 1138 p.avatarCapsuleDepth = BSParam.AvatarCapsuleDepth;
1139 p.avatarCapsuleHeight = BSParam.AvatarCapsuleHeight; 1139 p.avatarCapsuleHeight = BSParam.AvatarCapsuleHeight;
1140 p.avatarContactProcessingThreshold = BSParam.AvatarContactProcessingThreshold; 1140 p.avatarContactProcessingThreshold = BSParam.AvatarContactProcessingThreshold;
1141 1141
1142 p.vehicleAngularDamping = BSParam.VehicleAngularDamping; 1142 p.vehicleAngularDamping = BSParam.VehicleAngularDamping;
1143 1143
1144 p.maxPersistantManifoldPoolSize = o[0].maxPersistantManifoldPoolSize; 1144 p.maxPersistantManifoldPoolSize = o[0].maxPersistantManifoldPoolSize;
1145 p.maxCollisionAlgorithmPoolSize = o[0].maxCollisionAlgorithmPoolSize; 1145 p.maxCollisionAlgorithmPoolSize = o[0].maxCollisionAlgorithmPoolSize;
1146 p.shouldDisableContactPoolDynamicAllocation = o[0].shouldDisableContactPoolDynamicAllocation; 1146 p.shouldDisableContactPoolDynamicAllocation = o[0].shouldDisableContactPoolDynamicAllocation;
@@ -1160,7 +1160,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1160 p.linkConstraintSolverIterations = BSParam.LinkConstraintSolverIterations; 1160 p.linkConstraintSolverIterations = BSParam.LinkConstraintSolverIterations;
1161 p.physicsLoggingFrames = o[0].physicsLoggingFrames; 1161 p.physicsLoggingFrames = o[0].physicsLoggingFrames;
1162 DefaultCollisionConstructionInfo ccci = new DefaultCollisionConstructionInfo(); 1162 DefaultCollisionConstructionInfo ccci = new DefaultCollisionConstructionInfo();
1163 1163
1164 DefaultCollisionConfiguration cci = new DefaultCollisionConfiguration(); 1164 DefaultCollisionConfiguration cci = new DefaultCollisionConfiguration();
1165 CollisionDispatcher m_dispatcher = new CollisionDispatcher(cci); 1165 CollisionDispatcher m_dispatcher = new CollisionDispatcher(cci);
1166 1166
@@ -1263,7 +1263,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1263 } 1263 }
1264 } 1264 }
1265 return ret; 1265 return ret;
1266 1266
1267 } 1267 }
1268 1268
1269 public override float GetAngularMotionDisc(BulletShape pShape) 1269 public override float GetAngularMotionDisc(BulletShape pShape)
@@ -1353,10 +1353,10 @@ private sealed class BulletConstraintXNA : BulletConstraint
1353 CollisionShape shape = (pShape as BulletShapeXNA).shape; 1353 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1354 gObj.SetCollisionShape(shape); 1354 gObj.SetCollisionShape(shape);
1355 gObj.SetUserPointer(pLocalID); 1355 gObj.SetUserPointer(pLocalID);
1356 1356
1357 if (specialCollisionObjects.ContainsKey(pLocalID)) 1357 if (specialCollisionObjects.ContainsKey(pLocalID))
1358 specialCollisionObjects[pLocalID] = gObj; 1358 specialCollisionObjects[pLocalID] = gObj;
1359 else 1359 else
1360 specialCollisionObjects.Add(pLocalID, gObj); 1360 specialCollisionObjects.Add(pLocalID, gObj);
1361 1361
1362 // TODO: Add to Special CollisionObjects! 1362 // TODO: Add to Special CollisionObjects!
@@ -1447,8 +1447,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
1447 return new BulletShapeXNA(ret, BSShapeTypeFromBroadPhaseNativeType(ret.GetShapeType())); 1447 return new BulletShapeXNA(ret, BSShapeTypeFromBroadPhaseNativeType(ret.GetShapeType()));
1448 } 1448 }
1449 1449
1450 public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) { 1450 public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) {
1451 1451
1452 if (cShape == null) 1452 if (cShape == null)
1453 return null; 1453 return null;
1454 CompoundShape compoundShape = (cShape as BulletShapeXNA).shape as CompoundShape; 1454 CompoundShape compoundShape = (cShape as BulletShapeXNA).shape as CompoundShape;
@@ -1456,7 +1456,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1456 BulletShape retShape = new BulletShapeXNA(shape, BSShapeTypeFromBroadPhaseNativeType(shape.GetShapeType())); 1456 BulletShape retShape = new BulletShapeXNA(shape, BSShapeTypeFromBroadPhaseNativeType(shape.GetShapeType()));
1457 1457
1458 1458
1459 return retShape; 1459 return retShape;
1460 } 1460 }
1461 1461
1462 public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin) 1462 public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin)
@@ -1598,8 +1598,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
1598 return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE); 1598 return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE);
1599 } 1599 }
1600 1600
1601 public override BulletConstraint Create6DofSpringConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, 1601 public override BulletConstraint Create6DofSpringConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
1602 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, 1602 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot,
1603 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) 1603 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
1604 1604
1605 { 1605 {
@@ -1745,7 +1745,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1745 { 1745 {
1746 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 1746 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1747 CompoundShape compoundshape = new CompoundShape(false); 1747 CompoundShape compoundshape = new CompoundShape(false);
1748 1748
1749 compoundshape.SetMargin(world.WorldSettings.Params.collisionMargin); 1749 compoundshape.SetMargin(world.WorldSettings.Params.collisionMargin);
1750 int ii = 1; 1750 int ii = 1;
1751 1751
@@ -1761,7 +1761,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1761 int ender = ((ii + 4) + (vertexCount*3)); 1761 int ender = ((ii + 4) + (vertexCount*3));
1762 for (int iii = ii + 4; iii < ender; iii+=3) 1762 for (int iii = ii + 4; iii < ender; iii+=3)
1763 { 1763 {
1764 1764
1765 virts.Add(new IndexedVector3(pConvHulls[iii], pConvHulls[iii + 1], pConvHulls[iii +2])); 1765 virts.Add(new IndexedVector3(pConvHulls[iii], pConvHulls[iii + 1], pConvHulls[iii +2]));
1766 } 1766 }
1767 ConvexHullShape convexShape = new ConvexHullShape(virts, vertexCount); 1767 ConvexHullShape convexShape = new ConvexHullShape(virts, vertexCount);
@@ -1769,7 +1769,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1769 compoundshape.AddChildShape(ref childTrans, convexShape); 1769 compoundshape.AddChildShape(ref childTrans, convexShape);
1770 ii += (vertexCount*3 + 4); 1770 ii += (vertexCount*3 + 4);
1771 } 1771 }
1772 1772
1773 return new BulletShapeXNA(compoundshape, BSPhysicsShapeType.SHAPE_HULL); 1773 return new BulletShapeXNA(compoundshape, BSPhysicsShapeType.SHAPE_HULL);
1774 } 1774 }
1775 1775
@@ -1791,13 +1791,13 @@ private sealed class BulletConstraintXNA : BulletConstraint
1791 public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats) 1791 public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
1792 { 1792 {
1793 //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount); 1793 //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount);
1794 1794
1795 for (int iter = 0; iter < pVerticesCount; iter++) 1795 for (int iter = 0; iter < pVerticesCount; iter++)
1796 { 1796 {
1797 if (verticesAsFloats[iter] > 0 && verticesAsFloats[iter] < 0.0001) verticesAsFloats[iter] = 0; 1797 if (verticesAsFloats[iter] > 0 && verticesAsFloats[iter] < 0.0001) verticesAsFloats[iter] = 0;
1798 if (verticesAsFloats[iter] < 0 && verticesAsFloats[iter] > -0.0001) verticesAsFloats[iter] = 0; 1798 if (verticesAsFloats[iter] < 0 && verticesAsFloats[iter] > -0.0001) verticesAsFloats[iter] = 0;
1799 } 1799 }
1800 1800
1801 ObjectArray<int> indicesarr = new ObjectArray<int>(indices); 1801 ObjectArray<int> indicesarr = new ObjectArray<int>(indices);
1802 ObjectArray<float> vertices = new ObjectArray<float>(verticesAsFloats); 1802 ObjectArray<float> vertices = new ObjectArray<float>(verticesAsFloats);
1803 DumpRaw(indicesarr,vertices,pIndicesCount,pVerticesCount); 1803 DumpRaw(indicesarr,vertices,pIndicesCount,pVerticesCount);
@@ -1811,7 +1811,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1811 mesh.m_vertexStride = 3; 1811 mesh.m_vertexStride = 3;
1812 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; 1812 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1813 mesh.m_triangleIndexStride = 3; 1813 mesh.m_triangleIndexStride = 3;
1814 1814
1815 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); 1815 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1816 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); 1816 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1817 BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(tribuilder, true,true); 1817 BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(tribuilder, true,true);
@@ -1822,7 +1822,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1822 } 1822 }
1823 public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount ) 1823 public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount )
1824 { 1824 {
1825 1825
1826 String fileName = "objTest3.raw"; 1826 String fileName = "objTest3.raw";
1827 String completePath = System.IO.Path.Combine(Util.configDir(), fileName); 1827 String completePath = System.IO.Path.Combine(Util.configDir(), fileName);
1828 StreamWriter sw = new StreamWriter(completePath); 1828 StreamWriter sw = new StreamWriter(completePath);
@@ -1848,7 +1848,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1848 string s = vertices[indices[i * 3]].ToString("0.0000"); 1848 string s = vertices[indices[i * 3]].ToString("0.0000");
1849 s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000"); 1849 s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000");
1850 s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000"); 1850 s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000");
1851 1851
1852 sw.Write(s + "\n"); 1852 sw.Write(s + "\n");
1853 } 1853 }
1854 1854
@@ -1870,7 +1870,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1870 mesh.m_vertexStride = 3; 1870 mesh.m_vertexStride = 3;
1871 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; 1871 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1872 mesh.m_triangleIndexStride = 3; 1872 mesh.m_triangleIndexStride = 3;
1873 1873
1874 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); 1874 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1875 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); 1875 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1876 1876
@@ -1901,7 +1901,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1901 sw.Close(); 1901 sw.Close();
1902 } 1902 }
1903 1903
1904 public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap, 1904 public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
1905 float scaleFactor, float collisionMargin) 1905 float scaleFactor, float collisionMargin)
1906 { 1906 {
1907 const int upAxis = 2; 1907 const int upAxis = 2;
@@ -1943,14 +1943,14 @@ private sealed class BulletConstraintXNA : BulletConstraint
1943 /* TODO */ 1943 /* TODO */
1944 updatedEntityCount = 0; 1944 updatedEntityCount = 0;
1945 collidersCount = 0; 1945 collidersCount = 0;
1946 1946
1947 1947
1948 int ret = PhysicsStep2(world,timeStep,maxSubSteps,fixedTimeStep,out updatedEntityCount,out world.physicsScene.m_updateArray, out collidersCount, out world.physicsScene.m_collisionArray); 1948 int ret = PhysicsStep2(world,timeStep,maxSubSteps,fixedTimeStep,out updatedEntityCount,out world.physicsScene.m_updateArray, out collidersCount, out world.physicsScene.m_collisionArray);
1949 1949
1950 return ret; 1950 return ret;
1951 } 1951 }
1952 1952
1953 private int PhysicsStep2(BulletWorld pWorld, float timeStep, int m_maxSubSteps, float m_fixedTimeStep, 1953 private int PhysicsStep2(BulletWorld pWorld, float timeStep, int m_maxSubSteps, float m_fixedTimeStep,
1954 out int updatedEntityCount, out EntityProperties[] updatedEntities, 1954 out int updatedEntityCount, out EntityProperties[] updatedEntities,
1955 out int collidersCount, out CollisionDesc[] colliders) 1955 out int collidersCount, out CollisionDesc[] colliders)
1956 { 1956 {
@@ -1959,24 +1959,24 @@ private sealed class BulletConstraintXNA : BulletConstraint
1959 return epic; 1959 return epic;
1960 } 1960 }
1961 1961
1962 private int PhysicsStepint(BulletWorld pWorld,float timeStep, int m_maxSubSteps, float m_fixedTimeStep, out int updatedEntityCount, 1962 private int PhysicsStepint(BulletWorld pWorld,float timeStep, int m_maxSubSteps, float m_fixedTimeStep, out int updatedEntityCount,
1963 out EntityProperties[] updatedEntities, out int collidersCount, out CollisionDesc[] colliders, int maxCollisions, int maxUpdates) 1963 out EntityProperties[] updatedEntities, out int collidersCount, out CollisionDesc[] colliders, int maxCollisions, int maxUpdates)
1964 { 1964 {
1965 int numSimSteps = 0; 1965 int numSimSteps = 0;
1966 Array.Clear(UpdatedObjects, 0, UpdatedObjects.Length); 1966 Array.Clear(UpdatedObjects, 0, UpdatedObjects.Length);
1967 Array.Clear(UpdatedCollisions, 0, UpdatedCollisions.Length); 1967 Array.Clear(UpdatedCollisions, 0, UpdatedCollisions.Length);
1968 LastEntityProperty=0; 1968 LastEntityProperty=0;
1969 1969
1970 1970
1971 1971
1972 1972
1973 1973
1974 1974
1975 LastCollisionDesc=0; 1975 LastCollisionDesc=0;
1976 1976
1977 updatedEntityCount = 0; 1977 updatedEntityCount = 0;
1978 collidersCount = 0; 1978 collidersCount = 0;
1979 1979
1980 1980
1981 if (pWorld is BulletWorldXNA) 1981 if (pWorld is BulletWorldXNA)
1982 { 1982 {
@@ -2033,7 +2033,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2033 2033
2034 collidersCount = LastCollisionDesc; 2034 collidersCount = LastCollisionDesc;
2035 colliders = UpdatedCollisions; 2035 colliders = UpdatedCollisions;
2036 2036
2037 2037
2038 } 2038 }
2039 else 2039 else
@@ -2041,15 +2041,15 @@ private sealed class BulletConstraintXNA : BulletConstraint
2041 //if (updatedEntities is null) 2041 //if (updatedEntities is null)
2042 //updatedEntities = new List<BulletXNA.EntityProperties>(); 2042 //updatedEntities = new List<BulletXNA.EntityProperties>();
2043 //updatedEntityCount = 0; 2043 //updatedEntityCount = 0;
2044 2044
2045 2045
2046 //collidersCount = 0; 2046 //collidersCount = 0;
2047 2047
2048 updatedEntities = new EntityProperties[0]; 2048 updatedEntities = new EntityProperties[0];
2049 2049
2050 2050
2051 colliders = new CollisionDesc[0]; 2051 colliders = new CollisionDesc[0];
2052 2052
2053 } 2053 }
2054 return numSimSteps; 2054 return numSimSteps;
2055 } 2055 }
@@ -2057,7 +2057,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2057 { 2057 {
2058 IOverlappingPairCache cache = obj.GetOverlappingPairCache(); 2058 IOverlappingPairCache cache = obj.GetOverlappingPairCache();
2059 ObjectArray<BroadphasePair> pairs = cache.GetOverlappingPairArray(); 2059 ObjectArray<BroadphasePair> pairs = cache.GetOverlappingPairArray();
2060 2060
2061 DiscreteDynamicsWorld world = (PhysicsScene.World as BulletWorldXNA).world; 2061 DiscreteDynamicsWorld world = (PhysicsScene.World as BulletWorldXNA).world;
2062 PersistentManifoldArray manifoldArray = new PersistentManifoldArray(); 2062 PersistentManifoldArray manifoldArray = new PersistentManifoldArray();
2063 BroadphasePair collisionPair; 2063 BroadphasePair collisionPair;
@@ -2069,7 +2069,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2069 ManifoldPoint pt; 2069 ManifoldPoint pt;
2070 2070
2071 int numPairs = pairs.Count; 2071 int numPairs = pairs.Count;
2072 2072
2073 for (int i = 0; i < numPairs; i++) 2073 for (int i = 0; i < numPairs; i++)
2074 { 2074 {
2075 manifoldArray.Clear(); 2075 manifoldArray.Clear();
@@ -2078,7 +2078,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2078 collisionPair = world.GetPairCache().FindPair(pairs[i].m_pProxy0, pairs[i].m_pProxy1); 2078 collisionPair = world.GetPairCache().FindPair(pairs[i].m_pProxy0, pairs[i].m_pProxy1);
2079 if (collisionPair == null) 2079 if (collisionPair == null)
2080 continue; 2080 continue;
2081 2081
2082 collisionPair.m_algorithm.GetAllContactManifolds(manifoldArray); 2082 collisionPair.m_algorithm.GetAllContactManifolds(manifoldArray);
2083 for (int j = 0; j < manifoldArray.Count; j++) 2083 for (int j = 0; j < manifoldArray.Count; j++)
2084 { 2084 {
@@ -2101,7 +2101,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2101 } 2101 }
2102 private static void RecordCollision(BSAPIXNA world, CollisionObject objA, CollisionObject objB, IndexedVector3 contact, IndexedVector3 norm, float penetration) 2102 private static void RecordCollision(BSAPIXNA world, CollisionObject objA, CollisionObject objB, IndexedVector3 contact, IndexedVector3 norm, float penetration)
2103 { 2103 {
2104 2104
2105 IndexedVector3 contactNormal = norm; 2105 IndexedVector3 contactNormal = norm;
2106 if ((objA.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0 && 2106 if ((objA.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0 &&
2107 (objB.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0) 2107 (objB.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0)
@@ -2171,11 +2171,11 @@ private sealed class BulletConstraintXNA : BulletConstraint
2171 if (NotMe is BulletBodyXNA && NotMe.HasPhysicalBody) 2171 if (NotMe is BulletBodyXNA && NotMe.HasPhysicalBody)
2172 { 2172 {
2173 CollisionObject AvoidBody = (NotMe as BulletBodyXNA).body; 2173 CollisionObject AvoidBody = (NotMe as BulletBodyXNA).body;
2174 2174
2175 IndexedVector3 rOrigin = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z); 2175 IndexedVector3 rOrigin = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z);
2176 IndexedVector3 rEnd = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z - pRayHeight); 2176 IndexedVector3 rEnd = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z - pRayHeight);
2177 using ( 2177 using (
2178 ClosestNotMeRayResultCallback rayCallback = 2178 ClosestNotMeRayResultCallback rayCallback =
2179 new ClosestNotMeRayResultCallback(rOrigin, rEnd, AvoidBody) 2179 new ClosestNotMeRayResultCallback(rOrigin, rEnd, AvoidBody)
2180 ) 2180 )
2181 { 2181 {
@@ -2191,9 +2191,9 @@ private sealed class BulletConstraintXNA : BulletConstraint
2191 return false; 2191 return false;
2192 } 2192 }
2193} 2193}
2194
2195 2194
2196 2195
2196
2197 2197
2198 public class SimMotionState : DefaultMotionState 2198 public class SimMotionState : DefaultMotionState
2199 { 2199 {
@@ -2286,12 +2286,12 @@ private sealed class BulletConstraintXNA : BulletConstraint
2286 m_lastProperties = m_properties; 2286 m_lastProperties = m_properties;
2287 if (m_world.LastEntityProperty < m_world.UpdatedObjects.Length) 2287 if (m_world.LastEntityProperty < m_world.UpdatedObjects.Length)
2288 m_world.UpdatedObjects[m_world.LastEntityProperty++]=(m_properties); 2288 m_world.UpdatedObjects[m_world.LastEntityProperty++]=(m_properties);
2289 2289
2290 //(*m_updatesThisFrame)[m_properties.ID] = &m_properties; 2290 //(*m_updatesThisFrame)[m_properties.ID] = &m_properties;
2291 } 2291 }
2292 2292
2293 2293
2294 2294
2295 2295
2296 } 2296 }
2297 public override void SetRigidBody(RigidBody body) 2297 public override void SetRigidBody(RigidBody body)
@@ -2314,7 +2314,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2314 (((v1.Z - nEpsilon) < v2.Z) && (v2.Z < (v1.Z + nEpsilon))) && 2314 (((v1.Z - nEpsilon) < v2.Z) && (v2.Z < (v1.Z + nEpsilon))) &&
2315 (((v1.W - nEpsilon) < v2.W) && (v2.W < (v1.W + nEpsilon))); 2315 (((v1.W - nEpsilon) < v2.W) && (v2.W < (v1.W + nEpsilon)));
2316 } 2316 }
2317 2317
2318 } 2318 }
2319} 2319}
2320 2320
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
index bd5ee0b1..4e067b5 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
@@ -87,8 +87,8 @@ public class BSActorAvatarMove : BSActor
87 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 87 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
88 // Register a prestep action to restore physical requirements before the next simulation step. 88 // Register a prestep action to restore physical requirements before the next simulation step.
89 // Called at taint-time. 89 // Called at taint-time.
90 // BSActor.RemoveBodyDependencies() 90 // BSActor.RemoveDependencies()
91 public override void RemoveBodyDependencies() 91 public override void RemoveDependencies()
92 { 92 {
93 // Nothing to do for the hoverer since it is all software at pre-step action time. 93 // Nothing to do for the hoverer since it is all software at pre-step action time.
94 } 94 }
@@ -115,7 +115,7 @@ public class BSActorAvatarMove : BSActor
115 if (m_velocityMotor == null) 115 if (m_velocityMotor == null)
116 { 116 {
117 // Infinite decay and timescale values so motor only changes current to target values. 117 // Infinite decay and timescale values so motor only changes current to target values.
118 m_velocityMotor = new BSVMotor("BSCharacter.Velocity", 118 m_velocityMotor = new BSVMotor("BSCharacter.Velocity",
119 0.2f, // time scale 119 0.2f, // time scale
120 BSMotor.Infinite, // decay time scale 120 BSMotor.Infinite, // decay time scale
121 BSMotor.InfiniteVector, // friction timescale 121 BSMotor.InfiniteVector, // friction timescale
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
index 92ace66..3630ca8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
@@ -87,8 +87,8 @@ public class BSActorHover : BSActor
87 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 87 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
88 // Register a prestep action to restore physical requirements before the next simulation step. 88 // Register a prestep action to restore physical requirements before the next simulation step.
89 // Called at taint-time. 89 // Called at taint-time.
90 // BSActor.RemoveBodyDependencies() 90 // BSActor.RemoveDependencies()
91 public override void RemoveBodyDependencies() 91 public override void RemoveDependencies()
92 { 92 {
93 // Nothing to do for the hoverer since it is all software at pre-step action time. 93 // Nothing to do for the hoverer since it is all software at pre-step action time.
94 } 94 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
index 09ee32b..7801d8e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
@@ -63,7 +63,7 @@ public class BSActorLockAxis : BSActor
63 // BSActor.Refresh() 63 // BSActor.Refresh()
64 public override void Refresh() 64 public override void Refresh()
65 { 65 {
66 m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,lockedAxis={1},enabled={2},pActive={3}", 66 m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,lockedAxis={1},enabled={2},pActive={3}",
67 m_controllingPrim.LocalID, m_controllingPrim.LockedAxis, Enabled, m_controllingPrim.IsPhysicallyActive); 67 m_controllingPrim.LocalID, m_controllingPrim.LockedAxis, Enabled, m_controllingPrim.IsPhysicallyActive);
68 // If all the axis are free, we don't need to exist 68 // If all the axis are free, we don't need to exist
69 if (m_controllingPrim.LockedAxis == m_controllingPrim.LockedAxisFree) 69 if (m_controllingPrim.LockedAxis == m_controllingPrim.LockedAxisFree)
@@ -85,8 +85,8 @@ public class BSActorLockAxis : BSActor
85 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 85 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
86 // Register a prestep action to restore physical requirements before the next simulation step. 86 // Register a prestep action to restore physical requirements before the next simulation step.
87 // Called at taint-time. 87 // Called at taint-time.
88 // BSActor.RemoveBodyDependencies() 88 // BSActor.RemoveDependencies()
89 public override void RemoveBodyDependencies() 89 public override void RemoveDependencies()
90 { 90 {
91 if (LockAxisConstraint != null) 91 if (LockAxisConstraint != null)
92 { 92 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
index 56aacc5..1b598fd 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
@@ -88,8 +88,8 @@ public class BSActorMoveToTarget : BSActor
88 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 88 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
89 // Register a prestep action to restore physical requirements before the next simulation step. 89 // Register a prestep action to restore physical requirements before the next simulation step.
90 // Called at taint-time. 90 // Called at taint-time.
91 // BSActor.RemoveBodyDependencies() 91 // BSActor.RemoveDependencies()
92 public override void RemoveBodyDependencies() 92 public override void RemoveDependencies()
93 { 93 {
94 // Nothing to do for the moveToTarget since it is all software at pre-step action time. 94 // Nothing to do for the moveToTarget since it is all software at pre-step action time.
95 } 95 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
index 3ad138d..c0f40fd 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
@@ -89,8 +89,8 @@ public class BSActorSetForce : BSActor
89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
90 // Register a prestep action to restore physical requirements before the next simulation step. 90 // Register a prestep action to restore physical requirements before the next simulation step.
91 // Called at taint-time. 91 // Called at taint-time.
92 // BSActor.RemoveBodyDependencies() 92 // BSActor.RemoveDependencies()
93 public override void RemoveBodyDependencies() 93 public override void RemoveDependencies()
94 { 94 {
95 // Nothing to do for the hoverer since it is all software at pre-step action time. 95 // Nothing to do for the hoverer since it is all software at pre-step action time.
96 } 96 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
index 7a791ec..b3806e1 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
@@ -89,8 +89,8 @@ public class BSActorSetTorque : BSActor
89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
90 // Register a prestep action to restore physical requirements before the next simulation step. 90 // Register a prestep action to restore physical requirements before the next simulation step.
91 // Called at taint-time. 91 // Called at taint-time.
92 // BSActor.RemoveBodyDependencies() 92 // BSActor.RemoveDependencies()
93 public override void RemoveBodyDependencies() 93 public override void RemoveDependencies()
94 { 94 {
95 // Nothing to do for the hoverer since it is all software at pre-step action time. 95 // Nothing to do for the hoverer since it is all software at pre-step action time.
96 } 96 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
index 12a8817..fff63e4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
@@ -106,9 +106,9 @@ public class BSActorCollection
106 { 106 {
107 ForEachActor(a => a.Refresh()); 107 ForEachActor(a => a.Refresh());
108 } 108 }
109 public void RemoveBodyDependencies() 109 public void RemoveDependencies()
110 { 110 {
111 ForEachActor(a => a.RemoveBodyDependencies()); 111 ForEachActor(a => a.RemoveDependencies());
112 } 112 }
113} 113}
114 114
@@ -117,7 +117,7 @@ public class BSActorCollection
117/// Each physical object can have 'actors' who are pushing the object around. 117/// Each physical object can have 'actors' who are pushing the object around.
118/// This can be used for hover, locking axis, making vehicles, etc. 118/// This can be used for hover, locking axis, making vehicles, etc.
119/// Each physical object can have multiple actors acting on it. 119/// Each physical object can have multiple actors acting on it.
120/// 120///
121/// An actor usually registers itself with physics scene events (pre-step action) 121/// An actor usually registers itself with physics scene events (pre-step action)
122/// and modifies the parameters on the host physical object. 122/// and modifies the parameters on the host physical object.
123/// </summary> 123/// </summary>
@@ -154,7 +154,7 @@ public abstract class BSActor
154 public abstract void Refresh(); 154 public abstract void Refresh();
155 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 155 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
156 // Register a prestep action to restore physical requirements before the next simulation step. 156 // Register a prestep action to restore physical requirements before the next simulation step.
157 public abstract void RemoveBodyDependencies(); 157 public abstract void RemoveDependencies();
158 158
159} 159}
160} 160}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
index bfeec24..3378c93 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
@@ -298,7 +298,7 @@ public abstract class BSAPITemplate
298{ 298{
299// Returns the name of the underlying Bullet engine 299// Returns the name of the underlying Bullet engine
300public abstract string BulletEngineName { get; } 300public abstract string BulletEngineName { get; }
301public abstract string BulletEngineVersion { get; protected set;} 301public abstract string BulletEngineVersion { get; protected set;}
302 302
303// Initialization and simulation 303// Initialization and simulation
304public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms, 304public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
@@ -373,7 +373,7 @@ public abstract void DestroyObject(BulletWorld sim, BulletBody obj);
373// ===================================================================================== 373// =====================================================================================
374public abstract BulletShape CreateGroundPlaneShape(UInt32 id, float height, float collisionMargin); 374public abstract BulletShape CreateGroundPlaneShape(UInt32 id, float height, float collisionMargin);
375 375
376public abstract BulletShape CreateTerrainShape(UInt32 id, Vector3 size, float minHeight, float maxHeight, float[] heightMap, 376public abstract BulletShape CreateTerrainShape(UInt32 id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
377 float scaleFactor, float collisionMargin); 377 float scaleFactor, float collisionMargin);
378 378
379// ===================================================================================== 379// =====================================================================================
@@ -388,7 +388,7 @@ public abstract BulletConstraint Create6DofConstraintToPoint(BulletWorld world,
388 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); 388 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
389 389
390public abstract BulletConstraint Create6DofConstraintFixed(BulletWorld world, BulletBody obj1, 390public abstract BulletConstraint Create6DofConstraintFixed(BulletWorld world, BulletBody obj1,
391 Vector3 frameInBloc, Quaternion frameInBrot, 391 Vector3 frameInBloc, Quaternion frameInBrot,
392 bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies); 392 bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies);
393 393
394public abstract BulletConstraint Create6DofSpringConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2, 394public abstract BulletConstraint Create6DofSpringConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index a0d58d3..542f732 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -95,18 +95,18 @@ public sealed class BSCharacter : BSPhysObject
95 // the avatar seeking to reach the motor's target speed. 95 // the avatar seeking to reach the motor's target speed.
96 // This motor runs as a prestep action for the avatar so it will keep the avatar 96 // This motor runs as a prestep action for the avatar so it will keep the avatar
97 // standing as well as moving. Destruction of the avatar will destroy the pre-step action. 97 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
98 m_moveActor = new BSActorAvatarMove(PhysicsScene, this, AvatarMoveActorName); 98 m_moveActor = new BSActorAvatarMove(PhysScene, this, AvatarMoveActorName);
99 PhysicalActors.Add(AvatarMoveActorName, m_moveActor); 99 PhysicalActors.Add(AvatarMoveActorName, m_moveActor);
100 100
101 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", 101 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
102 LocalID, _size, Scale, Density, _avatarVolume, RawMass); 102 LocalID, _size, Scale, Density, _avatarVolume, RawMass);
103 103
104 // do actual creation in taint time 104 // do actual creation in taint time
105 PhysicsScene.TaintedObject("BSCharacter.create", delegate() 105 PhysScene.TaintedObject("BSCharacter.create", delegate()
106 { 106 {
107 DetailLog("{0},BSCharacter.create,taint", LocalID); 107 DetailLog("{0},BSCharacter.create,taint", LocalID);
108 // New body and shape into PhysBody and PhysShape 108 // New body and shape into PhysBody and PhysShape
109 PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this); 109 PhysScene.Shapes.GetBodyAndShape(true, PhysScene.World, this);
110 110
111 SetPhysicalProperties(); 111 SetPhysicalProperties();
112 }); 112 });
@@ -119,18 +119,18 @@ public sealed class BSCharacter : BSPhysObject
119 base.Destroy(); 119 base.Destroy();
120 120
121 DetailLog("{0},BSCharacter.Destroy", LocalID); 121 DetailLog("{0},BSCharacter.Destroy", LocalID);
122 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() 122 PhysScene.TaintedObject("BSCharacter.destroy", delegate()
123 { 123 {
124 PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */); 124 PhysScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */);
125 PhysBody.Clear(); 125 PhysBody.Clear();
126 PhysicsScene.Shapes.DereferenceShape(PhysShape, null /* bodyCallback */); 126 PhysShape.Dereference(PhysScene);
127 PhysShape.Clear(); 127 PhysShape = new BSShapeNull();
128 }); 128 });
129 } 129 }
130 130
131 private void SetPhysicalProperties() 131 private void SetPhysicalProperties()
132 { 132 {
133 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 133 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
134 134
135 ZeroMotion(true); 135 ZeroMotion(true);
136 ForcePosition = _position; 136 ForcePosition = _position;
@@ -145,35 +145,35 @@ public sealed class BSCharacter : BSPhysObject
145 // Needs to be reset especially when an avatar is recreated after crossing a region boundry. 145 // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
146 Flying = _flying; 146 Flying = _flying;
147 147
148 PhysicsScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution); 148 PhysScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution);
149 PhysicsScene.PE.SetMargin(PhysShape, PhysicsScene.Params.collisionMargin); 149 PhysScene.PE.SetMargin(PhysShape.physShapeInfo, PhysScene.Params.collisionMargin);
150 PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); 150 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
151 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 151 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
152 if (BSParam.CcdMotionThreshold > 0f) 152 if (BSParam.CcdMotionThreshold > 0f)
153 { 153 {
154 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 154 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
155 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 155 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
156 } 156 }
157 157
158 UpdatePhysicalMassProperties(RawMass, false); 158 UpdatePhysicalMassProperties(RawMass, false);
159 159
160 // Make so capsule does not fall over 160 // Make so capsule does not fall over
161 PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero); 161 PhysScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero);
162 162
163 // The avatar mover sets some parameters. 163 // The avatar mover sets some parameters.
164 PhysicalActors.Refresh(); 164 PhysicalActors.Refresh();
165 165
166 PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT); 166 PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT);
167 167
168 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); 168 PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody);
169 169
170 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); 170 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
171 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION); 171 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION);
172 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); 172 PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody);
173 173
174 // Do this after the object has been added to the world 174 // Do this after the object has been added to the world
175 PhysBody.collisionType = CollisionType.Avatar; 175 PhysBody.collisionType = CollisionType.Avatar;
176 PhysBody.ApplyCollisionMask(PhysicsScene); 176 PhysBody.ApplyCollisionMask(PhysScene);
177 } 177 }
178 178
179 179
@@ -203,14 +203,14 @@ public sealed class BSCharacter : BSPhysObject
203 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", 203 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
204 LocalID, _size, Scale, Density, _avatarVolume, RawMass); 204 LocalID, _size, Scale, Density, _avatarVolume, RawMass);
205 205
206 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() 206 PhysScene.TaintedObject("BSCharacter.setSize", delegate()
207 { 207 {
208 if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape) 208 if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape)
209 { 209 {
210 PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); 210 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
211 UpdatePhysicalMassProperties(RawMass, true); 211 UpdatePhysicalMassProperties(RawMass, true);
212 // Make sure this change appears as a property update event 212 // Make sure this change appears as a property update event
213 PhysicsScene.PE.PushUpdate(PhysBody); 213 PhysScene.PE.PushUpdate(PhysBody);
214 } 214 }
215 }); 215 });
216 216
@@ -221,11 +221,6 @@ public sealed class BSCharacter : BSPhysObject
221 { 221 {
222 set { BaseShape = value; } 222 set { BaseShape = value; }
223 } 223 }
224 // I want the physics engine to make an avatar capsule
225 public override BSPhysicsShapeType PreferredPhysicalShape
226 {
227 get {return BSPhysicsShapeType.SHAPE_CAPSULE; }
228 }
229 224
230 public override bool Grabbed { 225 public override bool Grabbed {
231 set { _grabbed = value; } 226 set { _grabbed = value; }
@@ -252,24 +247,24 @@ public sealed class BSCharacter : BSPhysObject
252 _rotationalVelocity = OMV.Vector3.Zero; 247 _rotationalVelocity = OMV.Vector3.Zero;
253 248
254 // Zero some other properties directly into the physics engine 249 // Zero some other properties directly into the physics engine
255 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() 250 PhysScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
256 { 251 {
257 if (PhysBody.HasPhysicalBody) 252 if (PhysBody.HasPhysicalBody)
258 PhysicsScene.PE.ClearAllForces(PhysBody); 253 PhysScene.PE.ClearAllForces(PhysBody);
259 }); 254 });
260 } 255 }
261 public override void ZeroAngularMotion(bool inTaintTime) 256 public override void ZeroAngularMotion(bool inTaintTime)
262 { 257 {
263 _rotationalVelocity = OMV.Vector3.Zero; 258 _rotationalVelocity = OMV.Vector3.Zero;
264 259
265 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() 260 PhysScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
266 { 261 {
267 if (PhysBody.HasPhysicalBody) 262 if (PhysBody.HasPhysicalBody)
268 { 263 {
269 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero); 264 PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero);
270 PhysicsScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero); 265 PhysScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero);
271 // The next also get rid of applied linear force but the linear velocity is untouched. 266 // The next also get rid of applied linear force but the linear velocity is untouched.
272 PhysicsScene.PE.ClearForces(PhysBody); 267 PhysScene.PE.ClearForces(PhysBody);
273 } 268 }
274 }); 269 });
275 } 270 }
@@ -291,7 +286,7 @@ public sealed class BSCharacter : BSPhysObject
291 set { 286 set {
292 _position = value; 287 _position = value;
293 288
294 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() 289 PhysScene.TaintedObject("BSCharacter.setPosition", delegate()
295 { 290 {
296 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 291 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
297 PositionSanityCheck(); 292 PositionSanityCheck();
@@ -301,14 +296,14 @@ public sealed class BSCharacter : BSPhysObject
301 } 296 }
302 public override OMV.Vector3 ForcePosition { 297 public override OMV.Vector3 ForcePosition {
303 get { 298 get {
304 _position = PhysicsScene.PE.GetPosition(PhysBody); 299 _position = PhysScene.PE.GetPosition(PhysBody);
305 return _position; 300 return _position;
306 } 301 }
307 set { 302 set {
308 _position = value; 303 _position = value;
309 if (PhysBody.HasPhysicalBody) 304 if (PhysBody.HasPhysicalBody)
310 { 305 {
311 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 306 PhysScene.PE.SetTranslation(PhysBody, _position, _orientation);
312 } 307 }
313 } 308 }
314 } 309 }
@@ -322,18 +317,18 @@ public sealed class BSCharacter : BSPhysObject
322 bool ret = false; 317 bool ret = false;
323 318
324 // TODO: check for out of bounds 319 // TODO: check for out of bounds
325 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) 320 if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
326 { 321 {
327 // The character is out of the known/simulated area. 322 // The character is out of the known/simulated area.
328 // Force the avatar position to be within known. ScenePresence will use the position 323 // Force the avatar position to be within known. ScenePresence will use the position
329 // plus the velocity to decide if the avatar is moving out of the region. 324 // plus the velocity to decide if the avatar is moving out of the region.
330 RawPosition = PhysicsScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition); 325 RawPosition = PhysScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition);
331 DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition); 326 DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition);
332 return true; 327 return true;
333 } 328 }
334 329
335 // If below the ground, move the avatar up 330 // If below the ground, move the avatar up
336 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); 331 float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
337 if (Position.Z < terrainHeight) 332 if (Position.Z < terrainHeight)
338 { 333 {
339 DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, _position, terrainHeight); 334 DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, _position, terrainHeight);
@@ -342,7 +337,7 @@ public sealed class BSCharacter : BSPhysObject
342 } 337 }
343 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 338 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
344 { 339 {
345 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); 340 float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(_position);
346 if (Position.Z < waterHeight) 341 if (Position.Z < waterHeight)
347 { 342 {
348 _position.Z = waterHeight; 343 _position.Z = waterHeight;
@@ -363,7 +358,7 @@ public sealed class BSCharacter : BSPhysObject
363 { 358 {
364 // The new position value must be pushed into the physics engine but we can't 359 // The new position value must be pushed into the physics engine but we can't
365 // just assign to "Position" because of potential call loops. 360 // just assign to "Position" because of potential call loops.
366 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() 361 PhysScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
367 { 362 {
368 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 363 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
369 ForcePosition = _position; 364 ForcePosition = _position;
@@ -376,13 +371,13 @@ public sealed class BSCharacter : BSPhysObject
376 public override float Mass { get { return _mass; } } 371 public override float Mass { get { return _mass; } }
377 372
378 // used when we only want this prim's mass and not the linkset thing 373 // used when we only want this prim's mass and not the linkset thing
379 public override float RawMass { 374 public override float RawMass {
380 get {return _mass; } 375 get {return _mass; }
381 } 376 }
382 public override void UpdatePhysicalMassProperties(float physMass, bool inWorld) 377 public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
383 { 378 {
384 OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); 379 OMV.Vector3 localInertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
385 PhysicsScene.PE.SetMassProps(PhysBody, physMass, localInertia); 380 PhysScene.PE.SetMassProps(PhysBody, physMass, localInertia);
386 } 381 }
387 382
388 public override OMV.Vector3 Force { 383 public override OMV.Vector3 Force {
@@ -390,11 +385,11 @@ public sealed class BSCharacter : BSPhysObject
390 set { 385 set {
391 RawForce = value; 386 RawForce = value;
392 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 387 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
393 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() 388 PhysScene.TaintedObject("BSCharacter.SetForce", delegate()
394 { 389 {
395 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce); 390 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce);
396 if (PhysBody.HasPhysicalBody) 391 if (PhysBody.HasPhysicalBody)
397 PhysicsScene.PE.SetObjectForce(PhysBody, RawForce); 392 PhysScene.PE.SetObjectForce(PhysBody, RawForce);
398 }); 393 });
399 } 394 }
400 } 395 }
@@ -437,7 +432,7 @@ public sealed class BSCharacter : BSPhysObject
437 set { 432 set {
438 RawVelocity = value; 433 RawVelocity = value;
439 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity); 434 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity);
440 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() 435 PhysScene.TaintedObject("BSCharacter.setVelocity", delegate()
441 { 436 {
442 if (m_moveActor != null) 437 if (m_moveActor != null)
443 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */); 438 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */);
@@ -450,11 +445,11 @@ public sealed class BSCharacter : BSPhysObject
450 public override OMV.Vector3 ForceVelocity { 445 public override OMV.Vector3 ForceVelocity {
451 get { return RawVelocity; } 446 get { return RawVelocity; }
452 set { 447 set {
453 PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); 448 PhysScene.AssertInTaintTime("BSCharacter.ForceVelocity");
454 449
455 RawVelocity = value; 450 RawVelocity = value;
456 PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity); 451 PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
457 PhysicsScene.PE.Activate(PhysBody, true); 452 PhysScene.PE.Activate(PhysBody, true);
458 } 453 }
459 } 454 }
460 public override OMV.Vector3 Torque { 455 public override OMV.Vector3 Torque {
@@ -484,7 +479,7 @@ public sealed class BSCharacter : BSPhysObject
484 if (_orientation != value) 479 if (_orientation != value)
485 { 480 {
486 _orientation = value; 481 _orientation = value;
487 PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() 482 PhysScene.TaintedObject("BSCharacter.setOrientation", delegate()
488 { 483 {
489 ForceOrientation = _orientation; 484 ForceOrientation = _orientation;
490 }); 485 });
@@ -496,7 +491,7 @@ public sealed class BSCharacter : BSPhysObject
496 { 491 {
497 get 492 get
498 { 493 {
499 _orientation = PhysicsScene.PE.GetOrientation(PhysBody); 494 _orientation = PhysScene.PE.GetOrientation(PhysBody);
500 return _orientation; 495 return _orientation;
501 } 496 }
502 set 497 set
@@ -505,7 +500,7 @@ public sealed class BSCharacter : BSPhysObject
505 if (PhysBody.HasPhysicalBody) 500 if (PhysBody.HasPhysicalBody)
506 { 501 {
507 // _position = PhysicsScene.PE.GetPosition(BSBody); 502 // _position = PhysicsScene.PE.GetPosition(BSBody);
508 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 503 PhysScene.PE.SetTranslation(PhysBody, _position, _orientation);
509 } 504 }
510 } 505 }
511 } 506 }
@@ -554,14 +549,14 @@ public sealed class BSCharacter : BSPhysObject
554 public override bool FloatOnWater { 549 public override bool FloatOnWater {
555 set { 550 set {
556 _floatOnWater = value; 551 _floatOnWater = value;
557 PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() 552 PhysScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
558 { 553 {
559 if (PhysBody.HasPhysicalBody) 554 if (PhysBody.HasPhysicalBody)
560 { 555 {
561 if (_floatOnWater) 556 if (_floatOnWater)
562 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 557 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
563 else 558 else
564 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 559 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
565 } 560 }
566 }); 561 });
567 } 562 }
@@ -582,7 +577,7 @@ public sealed class BSCharacter : BSPhysObject
582 public override float Buoyancy { 577 public override float Buoyancy {
583 get { return _buoyancy; } 578 get { return _buoyancy; }
584 set { _buoyancy = value; 579 set { _buoyancy = value;
585 PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() 580 PhysScene.TaintedObject("BSCharacter.setBuoyancy", delegate()
586 { 581 {
587 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 582 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
588 ForceBuoyancy = _buoyancy; 583 ForceBuoyancy = _buoyancy;
@@ -591,8 +586,8 @@ public sealed class BSCharacter : BSPhysObject
591 } 586 }
592 public override float ForceBuoyancy { 587 public override float ForceBuoyancy {
593 get { return _buoyancy; } 588 get { return _buoyancy; }
594 set { 589 set {
595 PhysicsScene.AssertInTaintTime("BSCharacter.ForceBuoyancy"); 590 PhysScene.AssertInTaintTime("BSCharacter.ForceBuoyancy");
596 591
597 _buoyancy = value; 592 _buoyancy = value;
598 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 593 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
@@ -600,7 +595,7 @@ public sealed class BSCharacter : BSPhysObject
600 float grav = BSParam.Gravity * (1f - _buoyancy); 595 float grav = BSParam.Gravity * (1f - _buoyancy);
601 Gravity = new OMV.Vector3(0f, 0f, grav); 596 Gravity = new OMV.Vector3(0f, 0f, grav);
602 if (PhysBody.HasPhysicalBody) 597 if (PhysBody.HasPhysicalBody)
603 PhysicsScene.PE.SetGravity(PhysBody, Gravity); 598 PhysScene.PE.SetGravity(PhysBody, Gravity);
604 } 599 }
605 } 600 }
606 601
@@ -618,7 +613,7 @@ public sealed class BSCharacter : BSPhysObject
618 public override void AddForce(OMV.Vector3 force, bool pushforce) 613 public override void AddForce(OMV.Vector3 force, bool pushforce)
619 { 614 {
620 // Since this force is being applied in only one step, make this a force per second. 615 // Since this force is being applied in only one step, make this a force per second.
621 OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep; 616 OMV.Vector3 addForce = force / PhysScene.LastTimeStep;
622 AddForce(addForce, pushforce, false); 617 AddForce(addForce, pushforce, false);
623 } 618 }
624 private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 619 private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
@@ -627,13 +622,13 @@ public sealed class BSCharacter : BSPhysObject
627 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 622 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
628 // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); 623 // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce);
629 624
630 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate() 625 PhysScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate()
631 { 626 {
632 // Bullet adds this central force to the total force for this tick 627 // Bullet adds this central force to the total force for this tick
633 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce); 628 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce);
634 if (PhysBody.HasPhysicalBody) 629 if (PhysBody.HasPhysicalBody)
635 { 630 {
636 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); 631 PhysScene.PE.ApplyCentralForce(PhysBody, addForce);
637 } 632 }
638 }); 633 });
639 } 634 }
@@ -652,7 +647,7 @@ public sealed class BSCharacter : BSPhysObject
652 private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size) 647 private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size)
653 { 648 {
654 OMV.Vector3 newScale; 649 OMV.Vector3 newScale;
655 650
656 // Bullet's capsule total height is the "passed height + radius * 2"; 651 // Bullet's capsule total height is the "passed height + radius * 2";
657 // The base capsule is 1 diameter and 2 height (passed radius=0.5, passed height = 1) 652 // The base capsule is 1 diameter and 2 height (passed radius=0.5, passed height = 1)
658 // The number we pass in for 'scaling' is the multiplier to get that base 653 // The number we pass in for 'scaling' is the multiplier to get that base
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
index 7714a03..ed89f63 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
@@ -45,7 +45,7 @@ public sealed class BSConstraintHinge : BSConstraint
45 m_body1 = obj1; 45 m_body1 = obj1;
46 m_body2 = obj2; 46 m_body2 = obj2;
47 m_constraint = PhysicsScene.PE.CreateHingeConstraint(world, obj1, obj2, 47 m_constraint = PhysicsScene.PE.CreateHingeConstraint(world, obj1, obj2,
48 pivotInA, pivotInB, axisInA, axisInB, 48 pivotInA, pivotInB, axisInA, axisInB,
49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies); 49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
50 m_enabled = true; 50 m_enabled = true;
51 } 51 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 612c68b..c5bee6d 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -559,9 +559,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
559 break; 559 break;
560 } 560 }
561 561
562 // Update any physical parameters based on this type.
563 Refresh();
564
565 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, 562 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale,
566 m_linearMotorDecayTimescale, m_linearFrictionTimescale, 563 m_linearMotorDecayTimescale, m_linearFrictionTimescale,
567 1f); 564 1f);
@@ -589,6 +586,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
589 { 586 {
590 RegisterForSceneEvents(); 587 RegisterForSceneEvents();
591 } 588 }
589
590 // Update any physical parameters based on this type.
591 Refresh();
592 } 592 }
593 #endregion // Vehicle parameter setting 593 #endregion // Vehicle parameter setting
594 594
@@ -596,6 +596,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
596 public override void Refresh() 596 public override void Refresh()
597 { 597 {
598 // If asking for a refresh, reset the physical parameters before the next simulation step. 598 // If asking for a refresh, reset the physical parameters before the next simulation step.
599 // Called whether active or not since the active state may be updated before the next step.
599 m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate() 600 m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate()
600 { 601 {
601 SetPhysicalParameters(); 602 SetPhysicalParameters();
@@ -625,7 +626,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
625 // Vehicles report collision events so we know when it's on the ground 626 // Vehicles report collision events so we know when it's on the ground
626 m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); 627 m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
627 628
628 ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape, m_vehicleMass); 629 ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass);
629 m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); 630 m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia);
630 m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody); 631 m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody);
631 632
@@ -649,7 +650,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
649 } 650 }
650 651
651 // BSActor.RemoveBodyDependencies 652 // BSActor.RemoveBodyDependencies
652 public override void RemoveBodyDependencies() 653 public override void RemoveDependencies()
653 { 654 {
654 Refresh(); 655 Refresh();
655 } 656 }
@@ -789,7 +790,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
789 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos) 790 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos)
790 { 791 {
791 lastRememberedHeightPos = pos; 792 lastRememberedHeightPos = pos;
792 m_knownTerrainHeight = ControllingPrim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); 793 m_knownTerrainHeight = ControllingPrim.PhysScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
793 m_knownHas |= m_knownChangedTerrainHeight; 794 m_knownHas |= m_knownChangedTerrainHeight;
794 } 795 }
795 return m_knownTerrainHeight; 796 return m_knownTerrainHeight;
@@ -801,7 +802,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
801 { 802 {
802 if ((m_knownHas & m_knownChangedWaterLevel) == 0) 803 if ((m_knownHas & m_knownChangedWaterLevel) == 0)
803 { 804 {
804 m_knownWaterLevel = ControllingPrim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); 805 m_knownWaterLevel = ControllingPrim.PhysScene.TerrainManager.GetWaterLevelAtXYZ(pos);
805 m_knownHas |= m_knownChangedWaterLevel; 806 m_knownHas |= m_knownChangedWaterLevel;
806 } 807 }
807 return (float)m_knownWaterLevel; 808 return (float)m_knownWaterLevel;
@@ -1019,7 +1020,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1019 Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG 1020 Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG
1020 VehicleVelocity /= VehicleVelocity.Length(); 1021 VehicleVelocity /= VehicleVelocity.Length();
1021 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity; 1022 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity;
1022 VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}", 1023 VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}",
1023 ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity); 1024 ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity);
1024 } 1025 }
1025 else if (newVelocityLengthSq < 0.001f) 1026 else if (newVelocityLengthSq < 0.001f)
@@ -1094,7 +1095,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1094 if (VehiclePosition.Z > m_VhoverTargetHeight) 1095 if (VehiclePosition.Z > m_VhoverTargetHeight)
1095 m_VhoverTargetHeight = VehiclePosition.Z; 1096 m_VhoverTargetHeight = VehiclePosition.Z;
1096 } 1097 }
1097 1098
1098 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 1099 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
1099 { 1100 {
1100 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) 1101 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f)
@@ -1188,7 +1189,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1188 // used with conjunction with banking: the strength of the banking will decay when the 1189 // used with conjunction with banking: the strength of the banking will decay when the
1189 // vehicle no longer experiences collisions. The decay timescale is the same as 1190 // vehicle no longer experiences collisions. The decay timescale is the same as
1190 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering 1191 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
1191 // when they are in mid jump. 1192 // when they are in mid jump.
1192 // TODO: this code is wrong. Also, what should it do for boats (height from water)? 1193 // TODO: this code is wrong. Also, what should it do for boats (height from water)?
1193 // This is just using the ground and a general collision check. Should really be using 1194 // This is just using the ground and a general collision check. Should really be using
1194 // a downward raycast to find what is below. 1195 // a downward raycast to find what is below.
@@ -1254,7 +1255,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1254 1255
1255 VehicleAddForce(appliedGravity); 1256 VehicleAddForce(appliedGravity);
1256 1257
1257 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={3}", 1258 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={3}",
1258 ControllingPrim.LocalID, m_VehicleGravity, 1259 ControllingPrim.LocalID, m_VehicleGravity,
1259 ControllingPrim.IsColliding, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity); 1260 ControllingPrim.IsColliding, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity);
1260 } 1261 }
@@ -1330,7 +1331,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1330 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : 1331 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
1331 // This flag prevents linear deflection parallel to world z-axis. This is useful 1332 // This flag prevents linear deflection parallel to world z-axis. This is useful
1332 // for preventing ground vehicles with large linear deflection, like bumper cars, 1333 // for preventing ground vehicles with large linear deflection, like bumper cars,
1333 // from climbing their linear deflection into the sky. 1334 // from climbing their linear deflection into the sky.
1334 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement 1335 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
1335 // TODO: This is here because this is where ODE put it but documentation says it 1336 // TODO: This is here because this is where ODE put it but documentation says it
1336 // is a linear effect. Where should this check go? 1337 // is a linear effect. Where should this check go?
@@ -1463,7 +1464,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1463 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation); 1464 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
1464 1465
1465 VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}", 1466 VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}",
1466 Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV, 1467 Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
1467 m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV); 1468 m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
1468 */ 1469 */
1469 } 1470 }
@@ -1530,13 +1531,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1530 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude 1531 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude
1531 // of the yaw effect will be proportional to the 1532 // of the yaw effect will be proportional to the
1532 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's 1533 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's
1533 // velocity along its preferred axis of motion. 1534 // velocity along its preferred axis of motion.
1534 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any 1535 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any
1535 // positive rotation (by the right-hand rule) about the roll-axis will effect a 1536 // positive rotation (by the right-hand rule) about the roll-axis will effect a
1536 // (negative) torque around the yaw-axis, making it turn to the right--that is the 1537 // (negative) torque around the yaw-axis, making it turn to the right--that is the
1537 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work. 1538 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work.
1538 // Negating the banking coefficient will make it so that the vehicle leans to the 1539 // Negating the banking coefficient will make it so that the vehicle leans to the
1539 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?). 1540 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?).
1540 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making 1541 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making
1541 // banking vehicles do what you want rather than what the laws of physics allow. 1542 // banking vehicles do what you want rather than what the laws of physics allow.
1542 // For example, consider a real motorcycle...it must be moving forward in order for 1543 // For example, consider a real motorcycle...it must be moving forward in order for
@@ -1548,11 +1549,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1548 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the 1549 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the
1549 // banking effect depends only on the vehicle's rotation about its roll-axis compared 1550 // banking effect depends only on the vehicle's rotation about its roll-axis compared
1550 // to "dynamic" where the banking is also proportional to its velocity along its 1551 // to "dynamic" where the banking is also proportional to its velocity along its
1551 // roll-axis. Finding the best value of the "mixture" will probably require trial and error. 1552 // roll-axis. Finding the best value of the "mixture" will probably require trial and error.
1552 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the 1553 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the
1553 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to 1554 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to
1554 // bank quickly then give it a banking timescale of about a second or less, otherwise you can 1555 // bank quickly then give it a banking timescale of about a second or less, otherwise you can
1555 // make a sluggish vehicle by giving it a timescale of several seconds. 1556 // make a sluggish vehicle by giving it a timescale of several seconds.
1556 public void ComputeAngularBanking() 1557 public void ComputeAngularBanking()
1557 { 1558 {
1558 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1559 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
@@ -1581,7 +1582,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1581 1582
1582 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; 1583 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation;
1583 VehicleRotationalVelocity += bankingContributionV; 1584 VehicleRotationalVelocity += bankingContributionV;
1584 1585
1585 1586
1586 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", 1587 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}",
1587 ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); 1588 ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV);
@@ -1637,8 +1638,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1637 // Invoke the detailed logger and output something if it's enabled. 1638 // Invoke the detailed logger and output something if it's enabled.
1638 private void VDetailLog(string msg, params Object[] args) 1639 private void VDetailLog(string msg, params Object[] args)
1639 { 1640 {
1640 if (ControllingPrim.PhysicsScene.VehicleLoggingEnabled) 1641 if (ControllingPrim.PhysScene.VehicleLoggingEnabled)
1641 ControllingPrim.PhysicsScene.DetailLog(msg, args); 1642 ControllingPrim.PhysScene.DetailLog(msg, args);
1642 } 1643 }
1643 } 1644 }
1644} 1645}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 4ece1eb..76c2187 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -80,7 +80,7 @@ public abstract class BSLinkset
80 80
81 public BSPrimLinkable LinksetRoot { get; protected set; } 81 public BSPrimLinkable LinksetRoot { get; protected set; }
82 82
83 public BSScene PhysicsScene { get; private set; } 83 protected BSScene m_physicsScene { get; private set; }
84 84
85 static int m_nextLinksetID = 1; 85 static int m_nextLinksetID = 1;
86 public int LinksetID { get; private set; } 86 public int LinksetID { get; private set; }
@@ -93,13 +93,6 @@ public abstract class BSLinkset
93 // to the physical representation is done via the tainting mechenism. 93 // to the physical representation is done via the tainting mechenism.
94 protected object m_linksetActivityLock = new Object(); 94 protected object m_linksetActivityLock = new Object();
95 95
96 // Some linksets have a preferred physical shape.
97 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
98 public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor)
99 {
100 return BSPhysicsShapeType.SHAPE_UNKNOWN;
101 }
102
103 // We keep the prim's mass in the linkset structure since it could be dependent on other prims 96 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
104 public float LinksetMass { get; protected set; } 97 public float LinksetMass { get; protected set; }
105 98
@@ -122,7 +115,7 @@ public abstract class BSLinkset
122 // We create LOTS of linksets. 115 // We create LOTS of linksets.
123 if (m_nextLinksetID <= 0) 116 if (m_nextLinksetID <= 0)
124 m_nextLinksetID = 1; 117 m_nextLinksetID = 1;
125 PhysicsScene = scene; 118 m_physicsScene = scene;
126 LinksetRoot = parent; 119 LinksetRoot = parent;
127 m_children = new HashSet<BSPrimLinkable>(); 120 m_children = new HashSet<BSPrimLinkable>();
128 LinksetMass = parent.RawMass; 121 LinksetMass = parent.RawMass;
@@ -165,7 +158,7 @@ public abstract class BSLinkset
165 } 158 }
166 159
167 // The child is down to a linkset of just itself 160 // The child is down to a linkset of just itself
168 return BSLinkset.Factory(PhysicsScene, child); 161 return BSLinkset.Factory(m_physicsScene, child);
169 } 162 }
170 163
171 // Return 'true' if the passed object is the root object of this linkset 164 // Return 'true' if the passed object is the root object of this linkset
@@ -221,7 +214,7 @@ public abstract class BSLinkset
221 // I am the root of a linkset and a new child is being added 214 // I am the root of a linkset and a new child is being added
222 // Called while LinkActivity is locked. 215 // Called while LinkActivity is locked.
223 protected abstract void AddChildToLinkset(BSPrimLinkable child); 216 protected abstract void AddChildToLinkset(BSPrimLinkable child);
224 217
225 // I am the root of a linkset and one of my children is being removed. 218 // I am the root of a linkset and one of my children is being removed.
226 // Safe to call even if the child is not really in my linkset. 219 // Safe to call even if the child is not really in my linkset.
227 protected abstract void RemoveChildFromLinkset(BSPrimLinkable child); 220 protected abstract void RemoveChildFromLinkset(BSPrimLinkable child);
@@ -263,7 +256,7 @@ public abstract class BSLinkset
263 // This is called when the root body is changing. 256 // This is called when the root body is changing.
264 // Returns 'true' of something was actually removed and would need restoring 257 // Returns 'true' of something was actually removed and would need restoring
265 // Called at taint-time!! 258 // Called at taint-time!!
266 public abstract bool RemoveBodyDependencies(BSPrimLinkable child); 259 public abstract bool RemoveDependencies(BSPrimLinkable child);
267 260
268 // ================================================================ 261 // ================================================================
269 protected virtual float ComputeLinksetMass() 262 protected virtual float ComputeLinksetMass()
@@ -323,8 +316,8 @@ public abstract class BSLinkset
323 // Invoke the detailed logger and output something if it's enabled. 316 // Invoke the detailed logger and output something if it's enabled.
324 protected void DetailLog(string msg, params Object[] args) 317 protected void DetailLog(string msg, params Object[] args)
325 { 318 {
326 if (PhysicsScene.PhysicsLogging.Enabled) 319 if (m_physicsScene.PhysicsLogging.Enabled)
327 PhysicsScene.DetailLog(msg, args); 320 m_physicsScene.DetailLog(msg, args);
328 } 321 }
329 322
330} 323}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index e05562a..1f16cc8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -35,6 +35,7 @@ using OMV = OpenMetaverse;
35namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37 37
38 /*
38// When a child is linked, the relationship position of the child to the parent 39// When a child is linked, the relationship position of the child to the parent
39// is remembered so the child's world position can be recomputed when it is 40// is remembered so the child's world position can be recomputed when it is
40// removed from the linkset. 41// removed from the linkset.
@@ -88,6 +89,7 @@ sealed class BSLinksetCompoundInfo : BSLinksetInfo
88 return buff.ToString(); 89 return buff.ToString();
89 } 90 }
90}; 91};
92 */
91 93
92public sealed class BSLinksetCompound : BSLinkset 94public sealed class BSLinksetCompound : BSLinkset
93{ 95{
@@ -98,19 +100,6 @@ public sealed class BSLinksetCompound : BSLinkset
98 { 100 {
99 } 101 }
100 102
101 // For compound implimented linksets, if there are children, use compound shape for the root.
102 public override BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor)
103 {
104 // Returning 'unknown' means we don't have a preference.
105 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
106 if (IsRoot(requestor) && HasAnyChildren)
107 {
108 ret = BSPhysicsShapeType.SHAPE_COMPOUND;
109 }
110 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
111 return ret;
112 }
113
114 // When physical properties are changed the linkset needs to recalculate 103 // When physical properties are changed the linkset needs to recalculate
115 // its internal properties. 104 // its internal properties.
116 public override void Refresh(BSPrimLinkable requestor) 105 public override void Refresh(BSPrimLinkable requestor)
@@ -124,14 +113,14 @@ public sealed class BSLinksetCompound : BSLinkset
124 // Schedule a refresh to happen after all the other taint processing. 113 // Schedule a refresh to happen after all the other taint processing.
125 private void ScheduleRebuild(BSPrimLinkable requestor) 114 private void ScheduleRebuild(BSPrimLinkable requestor)
126 { 115 {
127 DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}", 116 DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}",
128 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren)); 117 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren));
129 // When rebuilding, it is possible to set properties that would normally require a rebuild. 118 // When rebuilding, it is possible to set properties that would normally require a rebuild.
130 // If already rebuilding, don't request another rebuild. 119 // If already rebuilding, don't request another rebuild.
131 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding. 120 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding.
132 if (!Rebuilding && HasAnyChildren) 121 if (!Rebuilding && HasAnyChildren)
133 { 122 {
134 PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate() 123 m_physicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate()
135 { 124 {
136 if (HasAnyChildren) 125 if (HasAnyChildren)
137 RecomputeLinksetCompound(); 126 RecomputeLinksetCompound();
@@ -153,26 +142,11 @@ public sealed class BSLinksetCompound : BSLinkset
153 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly. 142 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
154 ScheduleRebuild(LinksetRoot); 143 ScheduleRebuild(LinksetRoot);
155 } 144 }
156 else
157 {
158 // The origional prims are removed from the world as the shape of the root compound
159 // shape takes over.
160 PhysicsScene.PE.AddToCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
161 PhysicsScene.PE.ForceActivationState(child.PhysBody, ActivationState.DISABLE_SIMULATION);
162 // We don't want collisions from the old linkset children.
163 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
164
165 child.PhysBody.collisionType = CollisionType.LinksetChild;
166
167 ret = true;
168 }
169 return ret; 145 return ret;
170 } 146 }
171 147
172 // The object is going static (non-physical). Do any setup necessary for a static linkset. 148 // The object is going static (non-physical). We do not do anything for static linksets.
173 // Return 'true' if any properties updated on the passed object. 149 // Return 'true' if any properties updated on the passed object.
174 // This doesn't normally happen -- OpenSim removes the objects from the physical
175 // world if it is a static linkset.
176 // Called at taint-time! 150 // Called at taint-time!
177 public override bool MakeStatic(BSPrimLinkable child) 151 public override bool MakeStatic(BSPrimLinkable child)
178 { 152 {
@@ -180,19 +154,9 @@ public sealed class BSLinksetCompound : BSLinkset
180 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); 154 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
181 if (IsRoot(child)) 155 if (IsRoot(child))
182 { 156 {
157 // Schedule a rebuild to verify that the root shape is set to the real shape.
183 ScheduleRebuild(LinksetRoot); 158 ScheduleRebuild(LinksetRoot);
184 } 159 }
185 else
186 {
187 // The non-physical children can come back to life.
188 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
189
190 child.PhysBody.collisionType = CollisionType.LinksetChild;
191
192 // Don't force activation so setting of DISABLE_SIMULATION can stay if used.
193 PhysicsScene.PE.Activate(child.PhysBody, false);
194 ret = true;
195 }
196 return ret; 160 return ret;
197 } 161 }
198 162
@@ -200,13 +164,20 @@ public sealed class BSLinksetCompound : BSLinkset
200 // Called at taint-time. 164 // Called at taint-time.
201 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable updated) 165 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable updated)
202 { 166 {
167 if (!LinksetRoot.IsPhysicallyActive)
168 {
169 // No reason to do this physical stuff for static linksets.
170 DetailLog("{0},BSLinksetCompound.UpdateProperties,notPhysical", LinksetRoot.LocalID);
171 return;
172 }
173
203 // The user moving a child around requires the rebuilding of the linkset compound shape 174 // The user moving a child around requires the rebuilding of the linkset compound shape
204 // One problem is this happens when a border is crossed -- the simulator implementation 175 // One problem is this happens when a border is crossed -- the simulator implementation
205 // stores the position into the group which causes the move of the object 176 // stores the position into the group which causes the move of the object
206 // but it also means all the child positions get updated. 177 // but it also means all the child positions get updated.
207 // What would cause an unnecessary rebuild so we make sure the linkset is in a 178 // What would cause an unnecessary rebuild so we make sure the linkset is in a
208 // region before bothering to do a rebuild. 179 // region before bothering to do a rebuild.
209 if (!IsRoot(updated) && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition)) 180 if (!IsRoot(updated) && m_physicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
210 { 181 {
211 // If a child of the linkset is updating only the position or rotation, that can be done 182 // If a child of the linkset is updating only the position or rotation, that can be done
212 // without rebuilding the linkset. 183 // without rebuilding the linkset.
@@ -218,22 +189,22 @@ public sealed class BSLinksetCompound : BSLinkset
218 // and that is caused by us updating the object. 189 // and that is caused by us updating the object.
219 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0) 190 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
220 { 191 {
221 // Find the physical instance of the child 192 // Find the physical instance of the child
222 if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) 193 if (LinksetRoot.PhysShape.HasPhysicalShape && m_physicsScene.PE.IsCompound(LinksetRoot.PhysShape.physShapeInfo))
223 { 194 {
224 // It is possible that the linkset is still under construction and the child is not yet 195 // It is possible that the linkset is still under construction and the child is not yet
225 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will 196 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will
226 // build the whole thing with the new position or rotation. 197 // build the whole thing with the new position or rotation.
227 // The index must be checked because Bullet references the child array but does no validity 198 // The index must be checked because Bullet references the child array but does no validity
228 // checking of the child index passed. 199 // checking of the child index passed.
229 int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape); 200 int numLinksetChildren = m_physicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape.physShapeInfo);
230 if (updated.LinksetChildIndex < numLinksetChildren) 201 if (updated.LinksetChildIndex < numLinksetChildren)
231 { 202 {
232 BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex); 203 BulletShape linksetChildShape = m_physicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex);
233 if (linksetChildShape.HasPhysicalShape) 204 if (linksetChildShape.HasPhysicalShape)
234 { 205 {
235 // Found the child shape within the compound shape 206 // Found the child shape within the compound shape
236 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex, 207 m_physicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex,
237 updated.RawPosition - LinksetRoot.RawPosition, 208 updated.RawPosition - LinksetRoot.RawPosition,
238 updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation), 209 updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation),
239 true /* shouldRecalculateLocalAabb */); 210 true /* shouldRecalculateLocalAabb */);
@@ -275,75 +246,22 @@ public sealed class BSLinksetCompound : BSLinkset
275 } 246 }
276 247
277 // Routine called when rebuilding the body of some member of the linkset. 248 // Routine called when rebuilding the body of some member of the linkset.
278 // Since we don't keep in world relationships, do nothing unless it's a child changing. 249 // If one of the bodies is being changed, the linkset needs rebuilding.
250 // For instance, a linkset is built and then a mesh asset is read in and the mesh is recreated.
279 // Returns 'true' of something was actually removed and would need restoring 251 // Returns 'true' of something was actually removed and would need restoring
280 // Called at taint-time!! 252 // Called at taint-time!!
281 public override bool RemoveBodyDependencies(BSPrimLinkable child) 253 public override bool RemoveDependencies(BSPrimLinkable child)
282 { 254 {
283 bool ret = false; 255 bool ret = false;
284 256
285 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", 257 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
286 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child)); 258 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child));
287 259
288 if (!IsRoot(child)) 260 ScheduleRebuild(child);
289 {
290 // Because it is a convenient time, recompute child world position and rotation based on
291 // its position in the linkset.
292 RecomputeChildWorldPosition(child, true /* inTaintTime */);
293 child.LinksetInfo = null;
294 }
295
296 // Cannot schedule a refresh/rebuild here because this routine is called when
297 // the linkset is being rebuilt.
298 // InternalRefresh(LinksetRoot);
299 261
300 return ret; 262 return ret;
301 } 263 }
302 264
303 // When the linkset is built, the child shape is added to the compound shape relative to the
304 // root shape. The linkset then moves around but this does not move the actual child
305 // prim. The child prim's location must be recomputed based on the location of the root shape.
306 private void RecomputeChildWorldPosition(BSPrimLinkable child, bool inTaintTime)
307 {
308 // For the moment (20130201), disable this computation (converting the child physical addr back to
309 // a region address) until we have a good handle on center-of-mass offsets and what the physics
310 // engine moving a child actually means.
311 // The simulator keeps track of where children should be as the linkset moves. Setting
312 // the pos/rot here does not effect that knowledge as there is no good way for the
313 // physics engine to send the simulator an update for a child.
314
315 /*
316 BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo;
317 if (lci != null)
318 {
319 if (inTaintTime)
320 {
321 OMV.Vector3 oldPos = child.RawPosition;
322 child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetFromRoot;
323 child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
324 DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
325 child.LocalID, oldPos, lci, child.RawPosition);
326 }
327 else
328 {
329 // TaintedObject is not used here so the raw position is set now and not at taint-time.
330 child.Position = LinksetRoot.RawPosition + lci.OffsetFromRoot;
331 child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
332 }
333 }
334 else
335 {
336 // This happens when children have been added to the linkset but the linkset
337 // has not been constructed yet. So like, at taint time, adding children to a linkset
338 // and then changing properties of the children (makePhysical, for instance)
339 // but the post-print action of actually rebuilding the linkset has not yet happened.
340 // PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}",
341 // LogHeader, child.LocalID);
342 DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID);
343 }
344 */
345 }
346
347 // ================================================================ 265 // ================================================================
348 266
349 // Add a new child to the linkset. 267 // Add a new child to the linkset.
@@ -376,7 +294,6 @@ public sealed class BSLinksetCompound : BSLinkset
376 child.LocalID, child.PhysBody.AddrString); 294 child.LocalID, child.PhysBody.AddrString);
377 295
378 // Cause the child's body to be rebuilt and thus restored to normal operation 296 // Cause the child's body to be rebuilt and thus restored to normal operation
379 RecomputeChildWorldPosition(child, false);
380 child.LinksetInfo = null; 297 child.LinksetInfo = null;
381 child.ForceBodyShapeRebuild(false); 298 child.ForceBodyShapeRebuild(false);
382 299
@@ -399,108 +316,105 @@ public sealed class BSLinksetCompound : BSLinkset
399 // Constraint linksets are rebuilt every time. 316 // Constraint linksets are rebuilt every time.
400 // Note that this works for rebuilding just the root after a linkset is taken apart. 317 // Note that this works for rebuilding just the root after a linkset is taken apart.
401 // Called at taint time!! 318 // Called at taint time!!
402 private bool disableCOM = true; // DEBUG DEBUG: disable until we get this debugged 319 private bool UseBulletSimRootOffsetHack = false; // Attempt to have Bullet track the coords of root compound shape
320 private bool disableCOM = true; // For basic linkset debugging, turn off the center-of-mass setting
403 private void RecomputeLinksetCompound() 321 private void RecomputeLinksetCompound()
404 { 322 {
405 try 323 try
406 { 324 {
407 // Suppress rebuilding while rebuilding. (We know rebuilding is on only one thread.)
408 Rebuilding = true; 325 Rebuilding = true;
409 326
410 // Cause the root shape to be rebuilt as a compound object with just the root in it 327 // No matter what is being done, force the root prim's PhysBody and PhysShape to get set
411 LinksetRoot.ForceBodyShapeRebuild(true /* inTaintTime */); 328 // to what they should be as if the root was not in a linkset.
329 // Not that bad since we only get into this routine if there are children in the linkset and
330 // something has been updated/changed.
331 LinksetRoot.ForceBodyShapeRebuild(true);
332
333 // There is no reason to build all this physical stuff for a non-physical linkset.
334 if (!LinksetRoot.IsPhysicallyActive)
335 {
336 // Clean up any old linkset shape and make sure the root shape is set to the root object.
337 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysical", LinksetRoot.LocalID);
338
339 return; // Note the 'finally' clause at the botton which will get executed.
340 }
341
342 // Get a new compound shape to build the linkset shape in.
343 BSShape linksetShape = BSShapeCompound.GetReference(m_physicsScene);
412 344
413 // The center of mass for the linkset is the geometric center of the group. 345 // The center of mass for the linkset is the geometric center of the group.
414 // Compute a displacement for each component so it is relative to the center-of-mass. 346 // Compute a displacement for each component so it is relative to the center-of-mass.
415 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass 347 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
416 OMV.Vector3 centerOfMassW = LinksetRoot.RawPosition; 348 OMV.Vector3 centerOfMassW = ComputeLinksetCenterOfMass();
417 if (!disableCOM) // DEBUG DEBUG
418 {
419 // Compute a center-of-mass in world coordinates.
420 centerOfMassW = ComputeLinksetCenterOfMass();
421 }
422 349
423 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); 350 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
424 351
425 // 'centerDisplacement' is the value to subtract from children to give physical offset position 352 // 'centerDisplacement' is the value to subtract from children to give physical offset position
426 OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation; 353 OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation;
427 LinksetRoot.SetEffectiveCenterOfMassW(centerDisplacement); 354 if (UseBulletSimRootOffsetHack || disableCOM)
428 355 {
429 // This causes the physical position of the root prim to be offset to accomodate for the displacements 356 centerDisplacement = OMV.Vector3.Zero;
430 LinksetRoot.ForcePosition = LinksetRoot.RawPosition; 357 LinksetRoot.ClearDisplacement();
431 358 }
432 // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM 359 else
433 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0 /* childIndex */, 360 {
434 -centerDisplacement, 361 LinksetRoot.SetEffectiveCenterOfMassDisplacement(centerDisplacement);
435 OMV.Quaternion.Identity, // LinksetRoot.RawOrientation, 362 }
436 false /* shouldRecalculateLocalAabb (is done later after linkset built) */); 363 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,rootPos={1},com={2},comDisp={3}",
437 364 LinksetRoot.LocalID, LinksetRoot.RawPosition, centerOfMassW, centerDisplacement);
438 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
439 LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement);
440
441 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
442 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
443 365
444 // Add a shape for each of the other children in the linkset 366 // Add the shapes of all the components of the linkset
445 int memberIndex = 1; 367 int memberIndex = 1;
446 ForEachMember(delegate(BSPrimLinkable cPrim) 368 ForEachMember(delegate(BSPrimLinkable cPrim)
447 { 369 {
448 if (IsRoot(cPrim)) 370 // Root shape is always index zero.
371 cPrim.LinksetChildIndex = IsRoot(cPrim) ? 0 : memberIndex;
372
373 // Get a reference to the shape of the child and add that shape to the linkset compound shape
374 BSShape childShape = cPrim.PhysShape.GetReference(m_physicsScene, cPrim);
375 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
376 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
377 m_physicsScene.PE.AddChildShapeToCompoundShape(linksetShape.physShapeInfo, childShape.physShapeInfo, offsetPos, offsetRot);
378 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addChild,indx={1},cShape={2},offPos={3},offRot={4}",
379 LinksetRoot.LocalID, memberIndex, childShape, offsetPos, offsetRot);
380
381 // Since we are borrowing the shape of the child, disable the origional child body
382 if (!IsRoot(cPrim))
449 { 383 {
450 cPrim.LinksetChildIndex = 0; 384 m_physicsScene.PE.AddToCollisionFlags(cPrim.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
385 m_physicsScene.PE.ForceActivationState(cPrim.PhysBody, ActivationState.DISABLE_SIMULATION);
386 // We don't want collisions from the old linkset children.
387 m_physicsScene.PE.RemoveFromCollisionFlags(cPrim.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
388 cPrim.PhysBody.collisionType = CollisionType.LinksetChild;
451 } 389 }
452 else
453 {
454 cPrim.LinksetChildIndex = memberIndex;
455 390
456 if (cPrim.PhysShape.isNativeShape) 391 memberIndex++;
457 {
458 // A native shape is turned into a hull collision shape because native
459 // shapes are not shared so we have to hullify it so it will be tracked
460 // and freed at the correct time. This also solves the scaling problem
461 // (native shapes scale but hull/meshes are assumed to not be).
462 // TODO: decide of the native shape can just be used in the compound shape.
463 // Use call to CreateGeomNonSpecial().
464 BulletShape saveShape = cPrim.PhysShape;
465 cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
466 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
467 BulletShape newShape = cPrim.PhysShape;
468 cPrim.PhysShape = saveShape;
469
470 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
471 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
472 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
473 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
474 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
475 }
476 else
477 {
478 // For the shared shapes (meshes and hulls), just use the shape in the child.
479 // The reference count added here will be decremented when the compound shape
480 // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced).
481 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
482 {
483 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
484 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
485 }
486 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
487 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
488 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
489 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNonNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
490 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
491 392
492 }
493 memberIndex++;
494 }
495 return false; // 'false' says to move onto the next child in the list 393 return false; // 'false' says to move onto the next child in the list
496 }); 394 });
497 395
396 // Replace the root shape with the built compound shape.
397 // Object removed and added to world to get collision cache rebuilt for new shape.
398 LinksetRoot.PhysShape.Dereference(m_physicsScene);
399 LinksetRoot.PhysShape = linksetShape;
400 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, LinksetRoot.PhysBody);
401 m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, LinksetRoot.PhysBody, linksetShape.physShapeInfo);
402 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, LinksetRoot.PhysBody);
403 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addBody,body={1},shape={2}",
404 LinksetRoot.LocalID, LinksetRoot.PhysBody, linksetShape);
405
498 // With all of the linkset packed into the root prim, it has the mass of everyone. 406 // With all of the linkset packed into the root prim, it has the mass of everyone.
499 LinksetMass = ComputeLinksetMass(); 407 LinksetMass = ComputeLinksetMass();
500 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); 408 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
501 409
502 // Enable the physical position updator to return the position and rotation of the root shape 410 if (UseBulletSimRootOffsetHack)
503 PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE); 411 {
412 // Enable the physical position updator to return the position and rotation of the root shape.
413 // This enables a feature in the C++ code to return the world coordinates of the first shape in the
414 // compound shape. This eleviates the need to offset the returned physical position by the
415 // center-of-mass offset.
416 m_physicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE);
417 }
504 } 418 }
505 finally 419 finally
506 { 420 {
@@ -508,7 +422,7 @@ public sealed class BSLinksetCompound : BSLinkset
508 } 422 }
509 423
510 // See that the Aabb surrounds the new shape 424 // See that the Aabb surrounds the new shape
511 PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); 425 m_physicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape.physShapeInfo);
512 } 426 }
513} 427}
514} \ No newline at end of file 428} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
index 6d252ca..a06a44d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -51,7 +51,7 @@ public sealed class BSLinksetConstraints : BSLinkset
51 if (HasAnyChildren && IsRoot(requestor)) 51 if (HasAnyChildren && IsRoot(requestor))
52 { 52 {
53 // Queue to happen after all the other taint processing 53 // Queue to happen after all the other taint processing
54 PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() 54 m_physicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
55 { 55 {
56 if (HasAnyChildren && IsRoot(requestor)) 56 if (HasAnyChildren && IsRoot(requestor))
57 RecomputeLinksetConstraints(); 57 RecomputeLinksetConstraints();
@@ -93,11 +93,11 @@ public sealed class BSLinksetConstraints : BSLinkset
93 // up to rebuild the constraints before the next simulation step. 93 // up to rebuild the constraints before the next simulation step.
94 // Returns 'true' of something was actually removed and would need restoring 94 // Returns 'true' of something was actually removed and would need restoring
95 // Called at taint-time!! 95 // Called at taint-time!!
96 public override bool RemoveBodyDependencies(BSPrimLinkable child) 96 public override bool RemoveDependencies(BSPrimLinkable child)
97 { 97 {
98 bool ret = false; 98 bool ret = false;
99 99
100 DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", 100 DetailLog("{0},BSLinksetConstraint.RemoveDependencies,removeChildrenForRoot,rID={1},rBody={2}",
101 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString); 101 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString);
102 102
103 lock (m_linksetActivityLock) 103 lock (m_linksetActivityLock)
@@ -142,7 +142,7 @@ public sealed class BSLinksetConstraints : BSLinkset
142 rootx.LocalID, rootx.PhysBody.AddrString, 142 rootx.LocalID, rootx.PhysBody.AddrString,
143 childx.LocalID, childx.PhysBody.AddrString); 143 childx.LocalID, childx.PhysBody.AddrString);
144 144
145 PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() 145 m_physicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate()
146 { 146 {
147 PhysicallyUnlinkAChildFromRoot(rootx, childx); 147 PhysicallyUnlinkAChildFromRoot(rootx, childx);
148 }); 148 });
@@ -187,7 +187,7 @@ public sealed class BSLinksetConstraints : BSLinkset
187 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 187 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
188 188
189 BSConstraint6Dof constrain = new BSConstraint6Dof( 189 BSConstraint6Dof constrain = new BSConstraint6Dof(
190 PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true ); 190 m_physicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true );
191 // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true ); 191 // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true );
192 192
193 /* NOTE: below is an attempt to build constraint with full frame computation, etc. 193 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
@@ -216,7 +216,7 @@ public sealed class BSLinksetConstraints : BSLinkset
216 // ================================================================================== 216 // ==================================================================================
217 */ 217 */
218 218
219 PhysicsScene.Constraints.AddConstraint(constrain); 219 m_physicsScene.Constraints.AddConstraint(constrain);
220 220
221 // zero linear and angular limits makes the objects unable to move in relation to each other 221 // zero linear and angular limits makes the objects unable to move in relation to each other
222 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 222 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
@@ -248,10 +248,10 @@ public sealed class BSLinksetConstraints : BSLinkset
248 childPrim.LocalID, childPrim.PhysBody.AddrString); 248 childPrim.LocalID, childPrim.PhysBody.AddrString);
249 249
250 // Find the constraint for this link and get rid of it from the overall collection and from my list 250 // Find the constraint for this link and get rid of it from the overall collection and from my list
251 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) 251 if (m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody))
252 { 252 {
253 // Make the child refresh its location 253 // Make the child refresh its location
254 PhysicsScene.PE.PushUpdate(childPrim.PhysBody); 254 m_physicsScene.PE.PushUpdate(childPrim.PhysBody);
255 ret = true; 255 ret = true;
256 } 256 }
257 257
@@ -265,7 +265,7 @@ public sealed class BSLinksetConstraints : BSLinkset
265 { 265 {
266 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); 266 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
267 267
268 return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody); 268 return m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody);
269 } 269 }
270 270
271 // Call each of the constraints that make up this linkset and recompute the 271 // Call each of the constraints that make up this linkset and recompute the
@@ -289,7 +289,7 @@ public sealed class BSLinksetConstraints : BSLinkset
289 child.UpdatePhysicalMassProperties(linksetMass, true); 289 child.UpdatePhysicalMassProperties(linksetMass, true);
290 290
291 BSConstraint constrain; 291 BSConstraint constrain;
292 if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) 292 if (!m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain))
293 { 293 {
294 // If constraint doesn't exist yet, create it. 294 // If constraint doesn't exist yet, create it.
295 constrain = BuildConstraint(LinksetRoot, child); 295 constrain = BuildConstraint(LinksetRoot, child);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
index 9501e2d..0128d8d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
@@ -102,7 +102,7 @@ public class BSVMotor : BSMotor
102 return ErrorIsZero(LastError); 102 return ErrorIsZero(LastError);
103 } 103 }
104 public virtual bool ErrorIsZero(Vector3 err) 104 public virtual bool ErrorIsZero(Vector3 err)
105 { 105 {
106 return (err == Vector3.Zero || err.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)); 106 return (err == Vector3.Zero || err.ApproxEquals(Vector3.Zero, ErrorZeroThreshold));
107 } 107 }
108 108
@@ -115,7 +115,7 @@ public class BSVMotor : BSMotor
115 CurrentValue = TargetValue = Vector3.Zero; 115 CurrentValue = TargetValue = Vector3.Zero;
116 ErrorZeroThreshold = 0.001f; 116 ErrorZeroThreshold = 0.001f;
117 } 117 }
118 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) 118 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency)
119 : this(useName) 119 : this(useName)
120 { 120 {
121 TimeScale = timeScale; 121 TimeScale = timeScale;
@@ -237,7 +237,7 @@ public class BSVMotor : BSMotor
237 MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName); 237 MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName);
238 MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},frictTS={4},eff={5},curr={6},tgt={7}", 238 MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},frictTS={4},eff={5},curr={6},tgt={7}",
239 BSScene.DetailLogZero, UseName, 239 BSScene.DetailLogZero, UseName,
240 TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency, 240 TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency,
241 CurrentValue, TargetValue); 241 CurrentValue, TargetValue);
242 242
243 LastError = BSMotor.InfiniteVector; 243 LastError = BSMotor.InfiniteVector;
@@ -248,7 +248,7 @@ public class BSVMotor : BSMotor
248 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep); 248 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep);
249 } 249 }
250 MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName); 250 MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName);
251 251
252 252
253 } 253 }
254 254
@@ -279,7 +279,7 @@ public class BSFMotor : BSMotor
279 return ErrorIsZero(LastError); 279 return ErrorIsZero(LastError);
280 } 280 }
281 public virtual bool ErrorIsZero(float err) 281 public virtual bool ErrorIsZero(float err)
282 { 282 {
283 return (err >= -ErrorZeroThreshold && err <= ErrorZeroThreshold); 283 return (err >= -ErrorZeroThreshold && err <= ErrorZeroThreshold);
284 } 284 }
285 285
@@ -410,7 +410,7 @@ public class BSPIDVMotor : BSVMotor
410 // The factors are vectors for the three dimensions. This is the proportional of each 410 // The factors are vectors for the three dimensions. This is the proportional of each
411 // that is applied. This could be multiplied through the actual factors but it 411 // that is applied. This could be multiplied through the actual factors but it
412 // is sometimes easier to manipulate the factors and their mix separately. 412 // is sometimes easier to manipulate the factors and their mix separately.
413 // to 413 // to
414 public Vector3 FactorMix; 414 public Vector3 FactorMix;
415 415
416 // Arbritrary factor range. 416 // Arbritrary factor range.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 980d405..2ac68e3 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -37,7 +37,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
37{ 37{
38public static class BSParam 38public static class BSParam
39{ 39{
40 private static string LogHeader = "[BULLETSIM PARAMETERS]"; 40 private static string LogHeader = "[BULLETSIM PARAMETERS]";
41 41
42 // Tuning notes: 42 // Tuning notes:
43 // From: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6575 43 // From: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6575
@@ -51,7 +51,7 @@ public static class BSParam
51 // This is separate/independent from the collision margin. The collision margin increases the object a bit 51 // This is separate/independent from the collision margin. The collision margin increases the object a bit
52 // to improve collision detection performance and accuracy. 52 // to improve collision detection performance and accuracy.
53 // =================== 53 // ===================
54 // From: 54 // From:
55 55
56 // Level of Detail values kept as float because that's what the Meshmerizer wants 56 // Level of Detail values kept as float because that's what the Meshmerizer wants
57 public static float MeshLOD { get; private set; } 57 public static float MeshLOD { get; private set; }
@@ -87,6 +87,7 @@ public static class BSParam
87 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects 87 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
88 public static bool ShouldRemoveZeroWidthTriangles { get; private set; } 88 public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
89 public static bool ShouldUseBulletHACD { get; set; } 89 public static bool ShouldUseBulletHACD { get; set; }
90 public static bool ShouldUseSingleConvexHullForPrims { get; set; }
90 91
91 public static float TerrainImplementation { get; private set; } 92 public static float TerrainImplementation { get; private set; }
92 public static int TerrainMeshMagnification { get; private set; } 93 public static int TerrainMeshMagnification { get; private set; }
@@ -342,6 +343,10 @@ public static class BSParam
342 false, 343 false,
343 (s) => { return ShouldUseBulletHACD; }, 344 (s) => { return ShouldUseBulletHACD; },
344 (s,v) => { ShouldUseBulletHACD = v; } ), 345 (s,v) => { ShouldUseBulletHACD = v; } ),
346 new ParameterDefn<bool>("ShouldUseSingleConvexHullForPrims", "If true, use a single convex hull shape for physical prims",
347 true,
348 (s) => { return ShouldUseSingleConvexHullForPrims; },
349 (s,v) => { ShouldUseSingleConvexHullForPrims = v; } ),
345 350
346 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions", 351 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
347 5, 352 5,
@@ -636,7 +641,7 @@ public static class BSParam
636 new ParameterDefn<bool>("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", 641 new ParameterDefn<bool>("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
637 false, 642 false,
638 (s) => { return ShouldDisableContactPoolDynamicAllocation; }, 643 (s) => { return ShouldDisableContactPoolDynamicAllocation; },
639 (s,v) => { ShouldDisableContactPoolDynamicAllocation = v; 644 (s,v) => { ShouldDisableContactPoolDynamicAllocation = v;
640 s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = NumericBool(v); } ), 645 s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = NumericBool(v); } ),
641 new ParameterDefn<bool>("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", 646 new ParameterDefn<bool>("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
642 false, 647 false,
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 309d004..e796804 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -38,7 +38,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
38 * Class to wrap all objects. 38 * Class to wrap all objects.
39 * The rest of BulletSim doesn't need to keep checking for avatars or prims 39 * The rest of BulletSim doesn't need to keep checking for avatars or prims
40 * unless the difference is significant. 40 * unless the difference is significant.
41 * 41 *
42 * Variables in the physicsl objects are in three forms: 42 * Variables in the physicsl objects are in three forms:
43 * VariableName: used by the simulator and performs taint operations, etc 43 * VariableName: used by the simulator and performs taint operations, etc
44 * RawVariableName: direct reference to the BulletSim storage for the variable value 44 * RawVariableName: direct reference to the BulletSim storage for the variable value
@@ -52,7 +52,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce 52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce
53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse 53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse
54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v 54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v
55 * BS.ApplyCentralForce BS.ApplyTorque 55 * BS.ApplyCentralForce BS.ApplyTorque
56 */ 56 */
57 57
58// Flags used to denote which properties updates when making UpdateProperties calls to linksets, etc. 58// Flags used to denote which properties updates when making UpdateProperties calls to linksets, etc.
@@ -72,14 +72,14 @@ public abstract class BSPhysObject : PhysicsActor
72 } 72 }
73 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName) 73 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName)
74 { 74 {
75 PhysicsScene = parentScene; 75 PhysScene = parentScene;
76 LocalID = localID; 76 LocalID = localID;
77 PhysObjectName = name; 77 PhysObjectName = name;
78 Name = name; // PhysicsActor also has the name of the object. Someday consolidate. 78 Name = name; // PhysicsActor also has the name of the object. Someday consolidate.
79 TypeName = typeName; 79 TypeName = typeName;
80 80
81 // The collection of things that push me around 81 // The collection of things that push me around
82 PhysicalActors = new BSActorCollection(PhysicsScene); 82 PhysicalActors = new BSActorCollection(PhysScene);
83 83
84 // Initialize variables kept in base. 84 // Initialize variables kept in base.
85 GravModifier = 1.0f; 85 GravModifier = 1.0f;
@@ -88,7 +88,7 @@ public abstract class BSPhysObject : PhysicsActor
88 88
89 // We don't have any physical representation yet. 89 // We don't have any physical representation yet.
90 PhysBody = new BulletBody(localID); 90 PhysBody = new BulletBody(localID);
91 PhysShape = new BulletShape(); 91 PhysShape = new BSShapeNull();
92 92
93 PrimAssetState = PrimAssetCondition.Unknown; 93 PrimAssetState = PrimAssetCondition.Unknown;
94 94
@@ -97,6 +97,9 @@ public abstract class BSPhysObject : PhysicsActor
97 97
98 CollisionCollection = new CollisionEventUpdate(); 98 CollisionCollection = new CollisionEventUpdate();
99 CollisionsLastReported = CollisionCollection; 99 CollisionsLastReported = CollisionCollection;
100 CollisionsLastTick = new CollisionEventUpdate();
101 CollisionsLastTickStep = -1;
102
100 SubscribedEventsMs = 0; 103 SubscribedEventsMs = 0;
101 CollidingStep = 0; 104 CollidingStep = 0;
102 CollidingGroundStep = 0; 105 CollidingGroundStep = 0;
@@ -112,13 +115,13 @@ public abstract class BSPhysObject : PhysicsActor
112 public virtual void Destroy() 115 public virtual void Destroy()
113 { 116 {
114 PhysicalActors.Enable(false); 117 PhysicalActors.Enable(false);
115 PhysicsScene.TaintedObject("BSPhysObject.Destroy", delegate() 118 PhysScene.TaintedObject("BSPhysObject.Destroy", delegate()
116 { 119 {
117 PhysicalActors.Dispose(); 120 PhysicalActors.Dispose();
118 }); 121 });
119 } 122 }
120 123
121 public BSScene PhysicsScene { get; protected set; } 124 public BSScene PhysScene { get; protected set; }
122 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor 125 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
123 public string PhysObjectName { get; protected set; } 126 public string PhysObjectName { get; protected set; }
124 public string TypeName { get; protected set; } 127 public string TypeName { get; protected set; }
@@ -138,7 +141,7 @@ public abstract class BSPhysObject : PhysicsActor
138 // Reference to the physical body (btCollisionObject) of this object 141 // Reference to the physical body (btCollisionObject) of this object
139 public BulletBody PhysBody; 142 public BulletBody PhysBody;
140 // Reference to the physical shape (btCollisionShape) of this object 143 // Reference to the physical shape (btCollisionShape) of this object
141 public BulletShape PhysShape; 144 public BSShape PhysShape;
142 145
143 // The physical representation of the prim might require an asset fetch. 146 // The physical representation of the prim might require an asset fetch.
144 // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'. 147 // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
@@ -151,13 +154,6 @@ public abstract class BSPhysObject : PhysicsActor
151 // The objects base shape information. Null if not a prim type shape. 154 // The objects base shape information. Null if not a prim type shape.
152 public PrimitiveBaseShape BaseShape { get; protected set; } 155 public PrimitiveBaseShape BaseShape { get; protected set; }
153 156
154 // Some types of objects have preferred physical representations.
155 // Returns SHAPE_UNKNOWN if there is no preference.
156 public virtual BSPhysicsShapeType PreferredPhysicalShape
157 {
158 get { return BSPhysicsShapeType.SHAPE_UNKNOWN; }
159 }
160
161 // When the physical properties are updated, an EntityProperty holds the update values. 157 // When the physical properties are updated, an EntityProperty holds the update values.
162 // Keep the current and last EntityProperties to enable computation of differences 158 // Keep the current and last EntityProperties to enable computation of differences
163 // between the current update and the previous values. 159 // between the current update and the previous values.
@@ -266,7 +262,8 @@ public abstract class BSPhysObject : PhysicsActor
266 262
267 // The user can optionally set the center of mass. The user's setting will override any 263 // The user can optionally set the center of mass. The user's setting will override any
268 // computed center-of-mass (like in linksets). 264 // computed center-of-mass (like in linksets).
269 public OMV.Vector3? UserSetCenterOfMass { get; set; } 265 // Note this is a displacement from the root's coordinates. Zero means use the root prim as center-of-mass.
266 public OMV.Vector3? UserSetCenterOfMassDisplacement { get; set; }
270 267
271 public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free. 268 public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free.
272 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free 269 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free
@@ -277,7 +274,7 @@ public abstract class BSPhysObject : PhysicsActor
277 public void ActivateIfPhysical(bool forceIt) 274 public void ActivateIfPhysical(bool forceIt)
278 { 275 {
279 if (IsPhysical && PhysBody.HasPhysicalBody) 276 if (IsPhysical && PhysBody.HasPhysicalBody)
280 PhysicsScene.PE.Activate(PhysBody, forceIt); 277 PhysScene.PE.Activate(PhysBody, forceIt);
281 } 278 }
282 279
283 // 'actors' act on the physical object to change or constrain its motion. These can range from 280 // 'actors' act on the physical object to change or constrain its motion. These can range from
@@ -340,29 +337,29 @@ public abstract class BSPhysObject : PhysicsActor
340 protected long CollisionAccumulation { get; set; } 337 protected long CollisionAccumulation { get; set; }
341 338
342 public override bool IsColliding { 339 public override bool IsColliding {
343 get { return (CollidingStep == PhysicsScene.SimulationStep); } 340 get { return (CollidingStep == PhysScene.SimulationStep); }
344 set { 341 set {
345 if (value) 342 if (value)
346 CollidingStep = PhysicsScene.SimulationStep; 343 CollidingStep = PhysScene.SimulationStep;
347 else 344 else
348 CollidingStep = 0; 345 CollidingStep = 0;
349 } 346 }
350 } 347 }
351 public override bool CollidingGround { 348 public override bool CollidingGround {
352 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } 349 get { return (CollidingGroundStep == PhysScene.SimulationStep); }
353 set 350 set
354 { 351 {
355 if (value) 352 if (value)
356 CollidingGroundStep = PhysicsScene.SimulationStep; 353 CollidingGroundStep = PhysScene.SimulationStep;
357 else 354 else
358 CollidingGroundStep = 0; 355 CollidingGroundStep = 0;
359 } 356 }
360 } 357 }
361 public override bool CollidingObj { 358 public override bool CollidingObj {
362 get { return (CollidingObjectStep == PhysicsScene.SimulationStep); } 359 get { return (CollidingObjectStep == PhysScene.SimulationStep); }
363 set { 360 set {
364 if (value) 361 if (value)
365 CollidingObjectStep = PhysicsScene.SimulationStep; 362 CollidingObjectStep = PhysScene.SimulationStep;
366 else 363 else
367 CollidingObjectStep = 0; 364 CollidingObjectStep = 0;
368 } 365 }
@@ -387,14 +384,14 @@ public abstract class BSPhysObject : PhysicsActor
387 bool ret = false; 384 bool ret = false;
388 385
389 // The following lines make IsColliding(), CollidingGround() and CollidingObj work 386 // The following lines make IsColliding(), CollidingGround() and CollidingObj work
390 CollidingStep = PhysicsScene.SimulationStep; 387 CollidingStep = PhysScene.SimulationStep;
391 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) 388 if (collidingWith <= PhysScene.TerrainManager.HighestTerrainID)
392 { 389 {
393 CollidingGroundStep = PhysicsScene.SimulationStep; 390 CollidingGroundStep = PhysScene.SimulationStep;
394 } 391 }
395 else 392 else
396 { 393 {
397 CollidingObjectStep = PhysicsScene.SimulationStep; 394 CollidingObjectStep = PhysScene.SimulationStep;
398 } 395 }
399 396
400 CollisionAccumulation++; 397 CollisionAccumulation++;
@@ -404,10 +401,10 @@ public abstract class BSPhysObject : PhysicsActor
404 401
405 // Make a collection of the collisions that happened the last simulation tick. 402 // Make a collection of the collisions that happened the last simulation tick.
406 // This is different than the collection created for sending up to the simulator as it is cleared every tick. 403 // This is different than the collection created for sending up to the simulator as it is cleared every tick.
407 if (CollisionsLastTickStep != PhysicsScene.SimulationStep) 404 if (CollisionsLastTickStep != PhysScene.SimulationStep)
408 { 405 {
409 CollisionsLastTick = new CollisionEventUpdate(); 406 CollisionsLastTick = new CollisionEventUpdate();
410 CollisionsLastTickStep = PhysicsScene.SimulationStep; 407 CollisionsLastTickStep = PhysScene.SimulationStep;
411 } 408 }
412 CollisionsLastTick.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 409 CollisionsLastTick.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
413 410
@@ -434,9 +431,9 @@ public abstract class BSPhysObject : PhysicsActor
434 bool force = (CollisionCollection.Count == 0 && CollisionsLastReported.Count != 0); 431 bool force = (CollisionCollection.Count == 0 && CollisionsLastReported.Count != 0);
435 432
436 // throttle the collisions to the number of milliseconds specified in the subscription 433 // throttle the collisions to the number of milliseconds specified in the subscription
437 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) 434 if (force || (PhysScene.SimulationNowTime >= NextCollisionOkTime))
438 { 435 {
439 NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; 436 NextCollisionOkTime = PhysScene.SimulationNowTime + SubscribedEventsMs;
440 437
441 // We are called if we previously had collisions. If there are no collisions 438 // We are called if we previously had collisions. If there are no collisions
442 // this time, send up one last empty event so OpenSim can sense collision end. 439 // this time, send up one last empty event so OpenSim can sense collision end.
@@ -454,7 +451,7 @@ public abstract class BSPhysObject : PhysicsActor
454 451
455 // The CollisionCollection instance is passed around in the simulator. 452 // The CollisionCollection instance is passed around in the simulator.
456 // Make sure we don't have a handle to that one and that a new one is used for next time. 453 // Make sure we don't have a handle to that one and that a new one is used for next time.
457 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here, 454 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
458 // a race condition is created for the other users of this instance. 455 // a race condition is created for the other users of this instance.
459 CollisionCollection = new CollisionEventUpdate(); 456 CollisionCollection = new CollisionEventUpdate();
460 } 457 }
@@ -471,10 +468,10 @@ public abstract class BSPhysObject : PhysicsActor
471 // make sure first collision happens 468 // make sure first collision happens
472 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); 469 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
473 470
474 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() 471 PhysScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
475 { 472 {
476 if (PhysBody.HasPhysicalBody) 473 if (PhysBody.HasPhysicalBody)
477 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 474 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
478 }); 475 });
479 } 476 }
480 else 477 else
@@ -486,11 +483,11 @@ public abstract class BSPhysObject : PhysicsActor
486 public override void UnSubscribeEvents() { 483 public override void UnSubscribeEvents() {
487 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); 484 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
488 SubscribedEventsMs = 0; 485 SubscribedEventsMs = 0;
489 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 486 PhysScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
490 { 487 {
491 // Make sure there is a body there because sometimes destruction happens in an un-ideal order. 488 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
492 if (PhysBody.HasPhysicalBody) 489 if (PhysBody.HasPhysicalBody)
493 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 490 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
494 }); 491 });
495 } 492 }
496 // Return 'true' if the simulator wants collision events 493 // Return 'true' if the simulator wants collision events
@@ -504,7 +501,7 @@ public abstract class BSPhysObject : PhysicsActor
504 { 501 {
505 // Scale the collision count by the time since the last collision. 502 // Scale the collision count by the time since the last collision.
506 // The "+1" prevents dividing by zero. 503 // The "+1" prevents dividing by zero.
507 long timeAgo = PhysicsScene.SimulationStep - CollidingStep + 1; 504 long timeAgo = PhysScene.SimulationStep - CollidingStep + 1;
508 CollisionScore = CollisionAccumulation / timeAgo; 505 CollisionScore = CollisionAccumulation / timeAgo;
509 } 506 }
510 public override float CollisionScore { get; set; } 507 public override float CollisionScore { get; set; }
@@ -531,8 +528,8 @@ public abstract class BSPhysObject : PhysicsActor
531 // High performance detailed logging routine used by the physical objects. 528 // High performance detailed logging routine used by the physical objects.
532 protected void DetailLog(string msg, params Object[] args) 529 protected void DetailLog(string msg, params Object[] args)
533 { 530 {
534 if (PhysicsScene.PhysicsLogging.Enabled) 531 if (PhysScene.PhysicsLogging.Enabled)
535 PhysicsScene.DetailLog(msg, args); 532 PhysScene.DetailLog(msg, args);
536 } 533 }
537 534
538} 535}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 4bc266b..d3f3475 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -101,21 +101,21 @@ public class BSPrim : BSPhysObject
101 _isVolumeDetect = false; 101 _isVolumeDetect = false;
102 102
103 // We keep a handle to the vehicle actor so we can set vehicle parameters later. 103 // We keep a handle to the vehicle actor so we can set vehicle parameters later.
104 VehicleActor = new BSDynamics(PhysicsScene, this, VehicleActorName); 104 VehicleActor = new BSDynamics(PhysScene, this, VehicleActorName);
105 PhysicalActors.Add(VehicleActorName, VehicleActor); 105 PhysicalActors.Add(VehicleActorName, VehicleActor);
106 106
107 _mass = CalculateMass(); 107 _mass = CalculateMass();
108 108
109 // DetailLog("{0},BSPrim.constructor,call", LocalID); 109 // DetailLog("{0},BSPrim.constructor,call", LocalID);
110 // do the actual object creation at taint time 110 // do the actual object creation at taint time
111 PhysicsScene.TaintedObject("BSPrim.create", delegate() 111 PhysScene.TaintedObject("BSPrim.create", delegate()
112 { 112 {
113 // Make sure the object is being created with some sanity. 113 // Make sure the object is being created with some sanity.
114 ExtremeSanityCheck(true /* inTaintTime */); 114 ExtremeSanityCheck(true /* inTaintTime */);
115 115
116 CreateGeomAndObject(true); 116 CreateGeomAndObject(true);
117 117
118 CurrentCollisionFlags = PhysicsScene.PE.GetCollisionFlags(PhysBody); 118 CurrentCollisionFlags = PhysScene.PE.GetCollisionFlags(PhysBody);
119 }); 119 });
120 } 120 }
121 121
@@ -128,14 +128,14 @@ public class BSPrim : BSPhysObject
128 // Undo any vehicle properties 128 // Undo any vehicle properties
129 this.VehicleType = (int)Vehicle.TYPE_NONE; 129 this.VehicleType = (int)Vehicle.TYPE_NONE;
130 130
131 PhysicsScene.TaintedObject("BSPrim.Destroy", delegate() 131 PhysScene.TaintedObject("BSPrim.Destroy", delegate()
132 { 132 {
133 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 133 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
134 // If there are physical body and shape, release my use of same. 134 // If there are physical body and shape, release my use of same.
135 PhysicsScene.Shapes.DereferenceBody(PhysBody, null); 135 PhysScene.Shapes.DereferenceBody(PhysBody, null);
136 PhysBody.Clear(); 136 PhysBody.Clear();
137 PhysicsScene.Shapes.DereferenceShape(PhysShape, null); 137 PhysShape.Dereference(PhysScene);
138 PhysShape.Clear(); 138 PhysShape = new BSShapeNull();
139 }); 139 });
140 } 140 }
141 141
@@ -161,25 +161,13 @@ public class BSPrim : BSPhysObject
161 ForceBodyShapeRebuild(false); 161 ForceBodyShapeRebuild(false);
162 } 162 }
163 } 163 }
164 // 'unknown' says to choose the best type
165 public override BSPhysicsShapeType PreferredPhysicalShape
166 { get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } }
167
168 public override bool ForceBodyShapeRebuild(bool inTaintTime) 164 public override bool ForceBodyShapeRebuild(bool inTaintTime)
169 { 165 {
170 if (inTaintTime) 166 PhysScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
171 { 167 {
172 _mass = CalculateMass(); // changing the shape changes the mass 168 _mass = CalculateMass(); // changing the shape changes the mass
173 CreateGeomAndObject(true); 169 CreateGeomAndObject(true);
174 } 170 });
175 else
176 {
177 PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate()
178 {
179 _mass = CalculateMass(); // changing the shape changes the mass
180 CreateGeomAndObject(true);
181 });
182 }
183 return true; 171 return true;
184 } 172 }
185 public override bool Grabbed { 173 public override bool Grabbed {
@@ -192,7 +180,7 @@ public class BSPrim : BSPhysObject
192 if (value != _isSelected) 180 if (value != _isSelected)
193 { 181 {
194 _isSelected = value; 182 _isSelected = value;
195 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() 183 PhysScene.TaintedObject("BSPrim.setSelected", delegate()
196 { 184 {
197 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); 185 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
198 SetObjectDynamic(false); 186 SetObjectDynamic(false);
@@ -238,23 +226,23 @@ public class BSPrim : BSPhysObject
238 _rotationalVelocity = OMV.Vector3.Zero; 226 _rotationalVelocity = OMV.Vector3.Zero;
239 227
240 // Zero some other properties in the physics engine 228 // Zero some other properties in the physics engine
241 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 229 PhysScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
242 { 230 {
243 if (PhysBody.HasPhysicalBody) 231 if (PhysBody.HasPhysicalBody)
244 PhysicsScene.PE.ClearAllForces(PhysBody); 232 PhysScene.PE.ClearAllForces(PhysBody);
245 }); 233 });
246 } 234 }
247 public override void ZeroAngularMotion(bool inTaintTime) 235 public override void ZeroAngularMotion(bool inTaintTime)
248 { 236 {
249 _rotationalVelocity = OMV.Vector3.Zero; 237 _rotationalVelocity = OMV.Vector3.Zero;
250 // Zero some other properties in the physics engine 238 // Zero some other properties in the physics engine
251 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 239 PhysScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
252 { 240 {
253 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); 241 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
254 if (PhysBody.HasPhysicalBody) 242 if (PhysBody.HasPhysicalBody)
255 { 243 {
256 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); 244 PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
257 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); 245 PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
258 } 246 }
259 }); 247 });
260 } 248 }
@@ -272,11 +260,11 @@ public class BSPrim : BSPhysObject
272 260
273 EnableActor(LockedAxis != LockedAxisFree, LockedAxisActorName, delegate() 261 EnableActor(LockedAxis != LockedAxisFree, LockedAxisActorName, delegate()
274 { 262 {
275 return new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName); 263 return new BSActorLockAxis(PhysScene, this, LockedAxisActorName);
276 }); 264 });
277 265
278 // Update parameters so the new actor's Refresh() action is called at the right time. 266 // Update parameters so the new actor's Refresh() action is called at the right time.
279 PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate() 267 PhysScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
280 { 268 {
281 UpdatePhysicalParameters(); 269 UpdatePhysicalParameters();
282 }); 270 });
@@ -306,7 +294,7 @@ public class BSPrim : BSPhysObject
306 _position = value; 294 _position = value;
307 PositionSanityCheck(false); 295 PositionSanityCheck(false);
308 296
309 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() 297 PhysScene.TaintedObject("BSPrim.setPosition", delegate()
310 { 298 {
311 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 299 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
312 ForcePosition = _position; 300 ForcePosition = _position;
@@ -316,14 +304,14 @@ public class BSPrim : BSPhysObject
316 304
317 public override OMV.Vector3 ForcePosition { 305 public override OMV.Vector3 ForcePosition {
318 get { 306 get {
319 _position = PhysicsScene.PE.GetPosition(PhysBody); 307 _position = PhysScene.PE.GetPosition(PhysBody);
320 return _position; 308 return _position;
321 } 309 }
322 set { 310 set {
323 _position = value; 311 _position = value;
324 if (PhysBody.HasPhysicalBody) 312 if (PhysBody.HasPhysicalBody)
325 { 313 {
326 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 314 PhysScene.PE.SetTranslation(PhysBody, _position, _orientation);
327 ActivateIfPhysical(false); 315 ActivateIfPhysical(false);
328 } 316 }
329 } 317 }
@@ -340,7 +328,7 @@ public class BSPrim : BSPhysObject
340 if (!IsPhysicallyActive) 328 if (!IsPhysicallyActive)
341 return ret; 329 return ret;
342 330
343 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) 331 if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
344 { 332 {
345 // The physical object is out of the known/simulated area. 333 // The physical object is out of the known/simulated area.
346 // Upper levels of code will handle the transition to other areas so, for 334 // Upper levels of code will handle the transition to other areas so, for
@@ -348,7 +336,7 @@ public class BSPrim : BSPhysObject
348 return ret; 336 return ret;
349 } 337 }
350 338
351 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); 339 float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
352 OMV.Vector3 upForce = OMV.Vector3.Zero; 340 OMV.Vector3 upForce = OMV.Vector3.Zero;
353 float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z)); 341 float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z));
354 if ((RawPosition.Z + approxSize / 2f) < terrainHeight) 342 if ((RawPosition.Z + approxSize / 2f) < terrainHeight)
@@ -369,7 +357,7 @@ public class BSPrim : BSPhysObject
369 357
370 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 358 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
371 { 359 {
372 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); 360 float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(_position);
373 // TODO: a floating motor so object will bob in the water 361 // TODO: a floating motor so object will bob in the water
374 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) 362 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f)
375 { 363 {
@@ -377,7 +365,7 @@ public class BSPrim : BSPhysObject
377 upForce.Z = (waterHeight - RawPosition.Z) * 1f; 365 upForce.Z = (waterHeight - RawPosition.Z) * 1f;
378 366
379 // Apply upforce and overcome gravity. 367 // Apply upforce and overcome gravity.
380 OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity; 368 OMV.Vector3 correctionForce = upForce - PhysScene.DefaultGravity;
381 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce); 369 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce);
382 AddForce(correctionForce, false, inTaintTime); 370 AddForce(correctionForce, false, inTaintTime);
383 ret = true; 371 ret = true;
@@ -432,7 +420,7 @@ public class BSPrim : BSPhysObject
432 get { return _mass; } 420 get { return _mass; }
433 } 421 }
434 // used when we only want this prim's mass and not the linkset thing 422 // used when we only want this prim's mass and not the linkset thing
435 public override float RawMass { 423 public override float RawMass {
436 get { return _mass; } 424 get { return _mass; }
437 } 425 }
438 // Set the physical mass to the passed mass. 426 // Set the physical mass to the passed mass.
@@ -443,10 +431,10 @@ public class BSPrim : BSPhysObject
443 { 431 {
444 if (IsStatic) 432 if (IsStatic)
445 { 433 {
446 PhysicsScene.PE.SetGravity(PhysBody, PhysicsScene.DefaultGravity); 434 PhysScene.PE.SetGravity(PhysBody, PhysScene.DefaultGravity);
447 Inertia = OMV.Vector3.Zero; 435 Inertia = OMV.Vector3.Zero;
448 PhysicsScene.PE.SetMassProps(PhysBody, 0f, Inertia); 436 PhysScene.PE.SetMassProps(PhysBody, 0f, Inertia);
449 PhysicsScene.PE.UpdateInertiaTensor(PhysBody); 437 PhysScene.PE.UpdateInertiaTensor(PhysBody);
450 } 438 }
451 else 439 else
452 { 440 {
@@ -455,16 +443,16 @@ public class BSPrim : BSPhysObject
455 // Changing interesting properties doesn't change proxy and collision cache 443 // Changing interesting properties doesn't change proxy and collision cache
456 // information. The Bullet solution is to re-add the object to the world 444 // information. The Bullet solution is to re-add the object to the world
457 // after parameters are changed. 445 // after parameters are changed.
458 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 446 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
459 } 447 }
460 448
461 // The computation of mass props requires gravity to be set on the object. 449 // The computation of mass props requires gravity to be set on the object.
462 Gravity = ComputeGravity(Buoyancy); 450 Gravity = ComputeGravity(Buoyancy);
463 PhysicsScene.PE.SetGravity(PhysBody, Gravity); 451 PhysScene.PE.SetGravity(PhysBody, Gravity);
464 452
465 Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); 453 Inertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
466 PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia); 454 PhysScene.PE.SetMassProps(PhysBody, physMass, Inertia);
467 PhysicsScene.PE.UpdateInertiaTensor(PhysBody); 455 PhysScene.PE.UpdateInertiaTensor(PhysBody);
468 456
469 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}", 457 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}",
470 LocalID, physMass, Inertia, Gravity, inWorld); 458 LocalID, physMass, Inertia, Gravity, inWorld);
@@ -480,7 +468,7 @@ public class BSPrim : BSPhysObject
480 // Return what gravity should be set to this very moment 468 // Return what gravity should be set to this very moment
481 public OMV.Vector3 ComputeGravity(float buoyancy) 469 public OMV.Vector3 ComputeGravity(float buoyancy)
482 { 470 {
483 OMV.Vector3 ret = PhysicsScene.DefaultGravity; 471 OMV.Vector3 ret = PhysScene.DefaultGravity;
484 472
485 if (!IsStatic) 473 if (!IsStatic)
486 { 474 {
@@ -509,7 +497,7 @@ public class BSPrim : BSPhysObject
509 RawForce = value; 497 RawForce = value;
510 EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate() 498 EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate()
511 { 499 {
512 return new BSActorSetForce(PhysicsScene, this, SetForceActorName); 500 return new BSActorSetForce(PhysScene, this, SetForceActorName);
513 }); 501 });
514 } 502 }
515 } 503 }
@@ -521,9 +509,9 @@ public class BSPrim : BSPhysObject
521 set { 509 set {
522 Vehicle type = (Vehicle)value; 510 Vehicle type = (Vehicle)value;
523 511
524 PhysicsScene.TaintedObject("setVehicleType", delegate() 512 PhysScene.TaintedObject("setVehicleType", delegate()
525 { 513 {
526 // Vehicle code changes the parameters for this vehicle type. 514 ZeroMotion(true /* inTaintTime */);
527 VehicleActor.ProcessTypeChange(type); 515 VehicleActor.ProcessTypeChange(type);
528 ActivateIfPhysical(false); 516 ActivateIfPhysical(false);
529 }); 517 });
@@ -531,7 +519,7 @@ public class BSPrim : BSPhysObject
531 } 519 }
532 public override void VehicleFloatParam(int param, float value) 520 public override void VehicleFloatParam(int param, float value)
533 { 521 {
534 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 522 PhysScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
535 { 523 {
536 VehicleActor.ProcessFloatVehicleParam((Vehicle)param, value); 524 VehicleActor.ProcessFloatVehicleParam((Vehicle)param, value);
537 ActivateIfPhysical(false); 525 ActivateIfPhysical(false);
@@ -539,7 +527,7 @@ public class BSPrim : BSPhysObject
539 } 527 }
540 public override void VehicleVectorParam(int param, OMV.Vector3 value) 528 public override void VehicleVectorParam(int param, OMV.Vector3 value)
541 { 529 {
542 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 530 PhysScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
543 { 531 {
544 VehicleActor.ProcessVectorVehicleParam((Vehicle)param, value); 532 VehicleActor.ProcessVectorVehicleParam((Vehicle)param, value);
545 ActivateIfPhysical(false); 533 ActivateIfPhysical(false);
@@ -547,7 +535,7 @@ public class BSPrim : BSPhysObject
547 } 535 }
548 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 536 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
549 { 537 {
550 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 538 PhysScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
551 { 539 {
552 VehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation); 540 VehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation);
553 ActivateIfPhysical(false); 541 ActivateIfPhysical(false);
@@ -555,7 +543,7 @@ public class BSPrim : BSPhysObject
555 } 543 }
556 public override void VehicleFlags(int param, bool remove) 544 public override void VehicleFlags(int param, bool remove)
557 { 545 {
558 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() 546 PhysScene.TaintedObject("BSPrim.VehicleFlags", delegate()
559 { 547 {
560 VehicleActor.ProcessVehicleFlags(param, remove); 548 VehicleActor.ProcessVehicleFlags(param, remove);
561 }); 549 });
@@ -567,7 +555,7 @@ public class BSPrim : BSPhysObject
567 if (_isVolumeDetect != newValue) 555 if (_isVolumeDetect != newValue)
568 { 556 {
569 _isVolumeDetect = newValue; 557 _isVolumeDetect = newValue;
570 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() 558 PhysScene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
571 { 559 {
572 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); 560 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
573 SetObjectDynamic(true); 561 SetObjectDynamic(true);
@@ -578,7 +566,7 @@ public class BSPrim : BSPhysObject
578 public override void SetMaterial(int material) 566 public override void SetMaterial(int material)
579 { 567 {
580 base.SetMaterial(material); 568 base.SetMaterial(material);
581 PhysicsScene.TaintedObject("BSPrim.SetMaterial", delegate() 569 PhysScene.TaintedObject("BSPrim.SetMaterial", delegate()
582 { 570 {
583 UpdatePhysicalParameters(); 571 UpdatePhysicalParameters();
584 }); 572 });
@@ -591,7 +579,7 @@ public class BSPrim : BSPhysObject
591 if (base.Friction != value) 579 if (base.Friction != value)
592 { 580 {
593 base.Friction = value; 581 base.Friction = value;
594 PhysicsScene.TaintedObject("BSPrim.setFriction", delegate() 582 PhysScene.TaintedObject("BSPrim.setFriction", delegate()
595 { 583 {
596 UpdatePhysicalParameters(); 584 UpdatePhysicalParameters();
597 }); 585 });
@@ -606,7 +594,7 @@ public class BSPrim : BSPhysObject
606 if (base.Restitution != value) 594 if (base.Restitution != value)
607 { 595 {
608 base.Restitution = value; 596 base.Restitution = value;
609 PhysicsScene.TaintedObject("BSPrim.setRestitution", delegate() 597 PhysScene.TaintedObject("BSPrim.setRestitution", delegate()
610 { 598 {
611 UpdatePhysicalParameters(); 599 UpdatePhysicalParameters();
612 }); 600 });
@@ -623,7 +611,7 @@ public class BSPrim : BSPhysObject
623 if (base.Density != value) 611 if (base.Density != value)
624 { 612 {
625 base.Density = value; 613 base.Density = value;
626 PhysicsScene.TaintedObject("BSPrim.setDensity", delegate() 614 PhysScene.TaintedObject("BSPrim.setDensity", delegate()
627 { 615 {
628 UpdatePhysicalParameters(); 616 UpdatePhysicalParameters();
629 }); 617 });
@@ -638,7 +626,7 @@ public class BSPrim : BSPhysObject
638 if (base.GravModifier != value) 626 if (base.GravModifier != value)
639 { 627 {
640 base.GravModifier = value; 628 base.GravModifier = value;
641 PhysicsScene.TaintedObject("BSPrim.setGravityModifier", delegate() 629 PhysScene.TaintedObject("BSPrim.setGravityModifier", delegate()
642 { 630 {
643 UpdatePhysicalParameters(); 631 UpdatePhysicalParameters();
644 }); 632 });
@@ -649,7 +637,7 @@ public class BSPrim : BSPhysObject
649 get { return RawVelocity; } 637 get { return RawVelocity; }
650 set { 638 set {
651 RawVelocity = value; 639 RawVelocity = value;
652 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() 640 PhysScene.TaintedObject("BSPrim.setVelocity", delegate()
653 { 641 {
654 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity); 642 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity);
655 ForceVelocity = RawVelocity; 643 ForceVelocity = RawVelocity;
@@ -659,13 +647,13 @@ public class BSPrim : BSPhysObject
659 public override OMV.Vector3 ForceVelocity { 647 public override OMV.Vector3 ForceVelocity {
660 get { return RawVelocity; } 648 get { return RawVelocity; }
661 set { 649 set {
662 PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity"); 650 PhysScene.AssertInTaintTime("BSPrim.ForceVelocity");
663 651
664 RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity); 652 RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
665 if (PhysBody.HasPhysicalBody) 653 if (PhysBody.HasPhysicalBody)
666 { 654 {
667 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity); 655 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity);
668 PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity); 656 PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
669 ActivateIfPhysical(false); 657 ActivateIfPhysical(false);
670 } 658 }
671 } 659 }
@@ -676,7 +664,7 @@ public class BSPrim : BSPhysObject
676 RawTorque = value; 664 RawTorque = value;
677 EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate() 665 EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate()
678 { 666 {
679 return new BSActorSetTorque(PhysicsScene, this, SetTorqueActorName); 667 return new BSActorSetTorque(PhysScene, this, SetTorqueActorName);
680 }); 668 });
681 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque); 669 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque);
682 } 670 }
@@ -699,7 +687,7 @@ public class BSPrim : BSPhysObject
699 return; 687 return;
700 _orientation = value; 688 _orientation = value;
701 689
702 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() 690 PhysScene.TaintedObject("BSPrim.setOrientation", delegate()
703 { 691 {
704 ForceOrientation = _orientation; 692 ForceOrientation = _orientation;
705 }); 693 });
@@ -710,14 +698,14 @@ public class BSPrim : BSPhysObject
710 { 698 {
711 get 699 get
712 { 700 {
713 _orientation = PhysicsScene.PE.GetOrientation(PhysBody); 701 _orientation = PhysScene.PE.GetOrientation(PhysBody);
714 return _orientation; 702 return _orientation;
715 } 703 }
716 set 704 set
717 { 705 {
718 _orientation = value; 706 _orientation = value;
719 if (PhysBody.HasPhysicalBody) 707 if (PhysBody.HasPhysicalBody)
720 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 708 PhysScene.PE.SetTranslation(PhysBody, _position, _orientation);
721 } 709 }
722 } 710 }
723 public override int PhysicsActorType { 711 public override int PhysicsActorType {
@@ -730,7 +718,7 @@ public class BSPrim : BSPhysObject
730 if (_isPhysical != value) 718 if (_isPhysical != value)
731 { 719 {
732 _isPhysical = value; 720 _isPhysical = value;
733 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() 721 PhysScene.TaintedObject("BSPrim.setIsPhysical", delegate()
734 { 722 {
735 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); 723 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
736 SetObjectDynamic(true); 724 SetObjectDynamic(true);
@@ -779,13 +767,13 @@ public class BSPrim : BSPhysObject
779 if (!PhysBody.HasPhysicalBody) 767 if (!PhysBody.HasPhysicalBody)
780 { 768 {
781 // This would only happen if updates are called for during initialization when the body is not set up yet. 769 // This would only happen if updates are called for during initialization when the body is not set up yet.
782 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID); 770 // DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID);
783 return; 771 return;
784 } 772 }
785 773
786 // Mangling all the physical properties requires the object not be in the physical world. 774 // Mangling all the physical properties requires the object not be in the physical world.
787 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). 775 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
788 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 776 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
789 777
790 // Set up the object physicalness (does gravity and collisions move this object) 778 // Set up the object physicalness (does gravity and collisions move this object)
791 MakeDynamic(IsStatic); 779 MakeDynamic(IsStatic);
@@ -802,10 +790,11 @@ public class BSPrim : BSPhysObject
802 AddObjectToPhysicalWorld(); 790 AddObjectToPhysicalWorld();
803 791
804 // Rebuild its shape 792 // Rebuild its shape
805 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); 793 PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody);
806 794
807 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}", 795 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}",
808 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape); 796 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(),
797 CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
809 } 798 }
810 799
811 // "Making dynamic" means changing to and from static. 800 // "Making dynamic" means changing to and from static.
@@ -818,28 +807,28 @@ public class BSPrim : BSPhysObject
818 if (makeStatic) 807 if (makeStatic)
819 { 808 {
820 // Become a Bullet 'static' object type 809 // Become a Bullet 'static' object type
821 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); 810 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
822 // Stop all movement 811 // Stop all movement
823 ZeroMotion(true); 812 ZeroMotion(true);
824 813
825 // Set various physical properties so other object interact properly 814 // Set various physical properties so other object interact properly
826 PhysicsScene.PE.SetFriction(PhysBody, Friction); 815 PhysScene.PE.SetFriction(PhysBody, Friction);
827 PhysicsScene.PE.SetRestitution(PhysBody, Restitution); 816 PhysScene.PE.SetRestitution(PhysBody, Restitution);
828 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 817 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
829 818
830 // Mass is zero which disables a bunch of physics stuff in Bullet 819 // Mass is zero which disables a bunch of physics stuff in Bullet
831 UpdatePhysicalMassProperties(0f, false); 820 UpdatePhysicalMassProperties(0f, false);
832 // Set collision detection parameters 821 // Set collision detection parameters
833 if (BSParam.CcdMotionThreshold > 0f) 822 if (BSParam.CcdMotionThreshold > 0f)
834 { 823 {
835 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 824 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
836 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 825 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
837 } 826 }
838 827
839 // The activation state is 'disabled' so Bullet will not try to act on it. 828 // The activation state is 'disabled' so Bullet will not try to act on it.
840 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION); 829 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION);
841 // Start it out sleeping and physical actions could wake it up. 830 // Start it out sleeping and physical actions could wake it up.
842 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING); 831 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING);
843 832
844 // This collides like a static object 833 // This collides like a static object
845 PhysBody.collisionType = CollisionType.Static; 834 PhysBody.collisionType = CollisionType.Static;
@@ -847,11 +836,11 @@ public class BSPrim : BSPhysObject
847 else 836 else
848 { 837 {
849 // Not a Bullet static object 838 // Not a Bullet static object
850 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); 839 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
851 840
852 // Set various physical properties so other object interact properly 841 // Set various physical properties so other object interact properly
853 PhysicsScene.PE.SetFriction(PhysBody, Friction); 842 PhysScene.PE.SetFriction(PhysBody, Friction);
854 PhysicsScene.PE.SetRestitution(PhysBody, Restitution); 843 PhysScene.PE.SetRestitution(PhysBody, Restitution);
855 // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution); 844 // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution);
856 845
857 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 846 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
@@ -869,22 +858,22 @@ public class BSPrim : BSPhysObject
869 // Set collision detection parameters 858 // Set collision detection parameters
870 if (BSParam.CcdMotionThreshold > 0f) 859 if (BSParam.CcdMotionThreshold > 0f)
871 { 860 {
872 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 861 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
873 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 862 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
874 } 863 }
875 864
876 // Various values for simulation limits 865 // Various values for simulation limits
877 PhysicsScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping); 866 PhysScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping);
878 PhysicsScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime); 867 PhysScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime);
879 PhysicsScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold); 868 PhysScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold);
880 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 869 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
881 870
882 // This collides like an object. 871 // This collides like an object.
883 PhysBody.collisionType = CollisionType.Dynamic; 872 PhysBody.collisionType = CollisionType.Dynamic;
884 873
885 // Force activation of the object so Bullet will act on it. 874 // Force activation of the object so Bullet will act on it.
886 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. 875 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
887 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); 876 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
888 } 877 }
889 } 878 }
890 879
@@ -894,7 +883,7 @@ public class BSPrim : BSPhysObject
894 // the functions after this one set up the state of a possibly newly created collision body. 883 // the functions after this one set up the state of a possibly newly created collision body.
895 private void MakeSolid(bool makeSolid) 884 private void MakeSolid(bool makeSolid)
896 { 885 {
897 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(PhysBody); 886 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysScene.PE.GetBodyType(PhysBody);
898 if (makeSolid) 887 if (makeSolid)
899 { 888 {
900 // Verify the previous code created the correct shape for this type of thing. 889 // Verify the previous code created the correct shape for this type of thing.
@@ -902,7 +891,7 @@ public class BSPrim : BSPhysObject
902 { 891 {
903 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); 892 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
904 } 893 }
905 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); 894 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
906 } 895 }
907 else 896 else
908 { 897 {
@@ -910,7 +899,7 @@ public class BSPrim : BSPhysObject
910 { 899 {
911 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); 900 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
912 } 901 }
913 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); 902 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
914 903
915 // Change collision info from a static object to a ghosty collision object 904 // Change collision info from a static object to a ghosty collision object
916 PhysBody.collisionType = CollisionType.VolumeDetect; 905 PhysBody.collisionType = CollisionType.VolumeDetect;
@@ -922,11 +911,11 @@ public class BSPrim : BSPhysObject
922 { 911 {
923 if (wantsCollisionEvents) 912 if (wantsCollisionEvents)
924 { 913 {
925 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 914 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
926 } 915 }
927 else 916 else
928 { 917 {
929 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 918 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
930 } 919 }
931 } 920 }
932 921
@@ -937,7 +926,7 @@ public class BSPrim : BSPhysObject
937 { 926 {
938 if (PhysBody.HasPhysicalBody) 927 if (PhysBody.HasPhysicalBody)
939 { 928 {
940 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); 929 PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody);
941 } 930 }
942 else 931 else
943 { 932 {
@@ -972,12 +961,12 @@ public class BSPrim : BSPhysObject
972 public override bool FloatOnWater { 961 public override bool FloatOnWater {
973 set { 962 set {
974 _floatOnWater = value; 963 _floatOnWater = value;
975 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() 964 PhysScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
976 { 965 {
977 if (_floatOnWater) 966 if (_floatOnWater)
978 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 967 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
979 else 968 else
980 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 969 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
981 }); 970 });
982 } 971 }
983 } 972 }
@@ -989,7 +978,7 @@ public class BSPrim : BSPhysObject
989 _rotationalVelocity = value; 978 _rotationalVelocity = value;
990 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity); 979 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity);
991 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 980 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
992 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 981 PhysScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
993 { 982 {
994 ForceRotationalVelocity = _rotationalVelocity; 983 ForceRotationalVelocity = _rotationalVelocity;
995 }); 984 });
@@ -1004,7 +993,7 @@ public class BSPrim : BSPhysObject
1004 if (PhysBody.HasPhysicalBody) 993 if (PhysBody.HasPhysicalBody)
1005 { 994 {
1006 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 995 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
1007 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); 996 PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
1008 // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); 997 // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
1009 ActivateIfPhysical(false); 998 ActivateIfPhysical(false);
1010 } 999 }
@@ -1020,7 +1009,7 @@ public class BSPrim : BSPhysObject
1020 get { return _buoyancy; } 1009 get { return _buoyancy; }
1021 set { 1010 set {
1022 _buoyancy = value; 1011 _buoyancy = value;
1023 PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() 1012 PhysScene.TaintedObject("BSPrim.setBuoyancy", delegate()
1024 { 1013 {
1025 ForceBuoyancy = _buoyancy; 1014 ForceBuoyancy = _buoyancy;
1026 }); 1015 });
@@ -1043,7 +1032,7 @@ public class BSPrim : BSPhysObject
1043 base.MoveToTargetActive = value; 1032 base.MoveToTargetActive = value;
1044 EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate() 1033 EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate()
1045 { 1034 {
1046 return new BSActorMoveToTarget(PhysicsScene, this, MoveToTargetActorName); 1035 return new BSActorMoveToTarget(PhysScene, this, MoveToTargetActorName);
1047 }); 1036 });
1048 } 1037 }
1049 } 1038 }
@@ -1055,7 +1044,7 @@ public class BSPrim : BSPhysObject
1055 base.HoverActive = value; 1044 base.HoverActive = value;
1056 EnableActor(HoverActive, HoverActorName, delegate() 1045 EnableActor(HoverActive, HoverActorName, delegate()
1057 { 1046 {
1058 return new BSActorHover(PhysicsScene, this, HoverActorName); 1047 return new BSActorHover(PhysScene, this, HoverActorName);
1059 }); 1048 });
1060 } 1049 }
1061 } 1050 }
@@ -1065,7 +1054,7 @@ public class BSPrim : BSPhysObject
1065 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 1054 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
1066 1055
1067 // Since this force is being applied in only one step, make this a force per second. 1056 // Since this force is being applied in only one step, make this a force per second.
1068 addForce /= PhysicsScene.LastTimeStep; 1057 addForce /= PhysScene.LastTimeStep;
1069 AddForce(addForce, pushforce, false /* inTaintTime */); 1058 AddForce(addForce, pushforce, false /* inTaintTime */);
1070 } 1059 }
1071 1060
@@ -1080,13 +1069,13 @@ public class BSPrim : BSPhysObject
1080 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); 1069 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
1081 1070
1082 OMV.Vector3 addForce = force; 1071 OMV.Vector3 addForce = force;
1083 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() 1072 PhysScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
1084 { 1073 {
1085 // Bullet adds this central force to the total force for this tick 1074 // Bullet adds this central force to the total force for this tick
1086 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce); 1075 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
1087 if (PhysBody.HasPhysicalBody) 1076 if (PhysBody.HasPhysicalBody)
1088 { 1077 {
1089 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); 1078 PhysScene.PE.ApplyCentralForce(PhysBody, addForce);
1090 ActivateIfPhysical(false); 1079 ActivateIfPhysical(false);
1091 } 1080 }
1092 }); 1081 });
@@ -1108,13 +1097,13 @@ public class BSPrim : BSPhysObject
1108 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude); 1097 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude);
1109 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse); 1098 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse);
1110 1099
1111 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate() 1100 PhysScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate()
1112 { 1101 {
1113 // Bullet adds this impulse immediately to the velocity 1102 // Bullet adds this impulse immediately to the velocity
1114 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse); 1103 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse);
1115 if (PhysBody.HasPhysicalBody) 1104 if (PhysBody.HasPhysicalBody)
1116 { 1105 {
1117 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, addImpulse); 1106 PhysScene.PE.ApplyCentralImpulse(PhysBody, addImpulse);
1118 ActivateIfPhysical(false); 1107 ActivateIfPhysical(false);
1119 } 1108 }
1120 }); 1109 });
@@ -1133,12 +1122,12 @@ public class BSPrim : BSPhysObject
1133 if (force.IsFinite()) 1122 if (force.IsFinite())
1134 { 1123 {
1135 OMV.Vector3 angForce = force; 1124 OMV.Vector3 angForce = force;
1136 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() 1125 PhysScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
1137 { 1126 {
1138 if (PhysBody.HasPhysicalBody) 1127 if (PhysBody.HasPhysicalBody)
1139 { 1128 {
1140 DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce); 1129 DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce);
1141 PhysicsScene.PE.ApplyTorque(PhysBody, angForce); 1130 PhysScene.PE.ApplyTorque(PhysBody, angForce);
1142 ActivateIfPhysical(false); 1131 ActivateIfPhysical(false);
1143 } 1132 }
1144 }); 1133 });
@@ -1157,11 +1146,11 @@ public class BSPrim : BSPhysObject
1157 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) 1146 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1158 { 1147 {
1159 OMV.Vector3 applyImpulse = impulse; 1148 OMV.Vector3 applyImpulse = impulse;
1160 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() 1149 PhysScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
1161 { 1150 {
1162 if (PhysBody.HasPhysicalBody) 1151 if (PhysBody.HasPhysicalBody)
1163 { 1152 {
1164 PhysicsScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse); 1153 PhysScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse);
1165 ActivateIfPhysical(false); 1154 ActivateIfPhysical(false);
1166 } 1155 }
1167 }); 1156 });
@@ -1463,12 +1452,13 @@ public class BSPrim : BSPhysObject
1463 // Create the correct physical representation for this type of object. 1452 // Create the correct physical representation for this type of object.
1464 // Updates base.PhysBody and base.PhysShape with the new information. 1453 // Updates base.PhysBody and base.PhysShape with the new information.
1465 // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary. 1454 // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary.
1466 PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody) 1455 PhysScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysScene.World, this, delegate(BulletBody pBody, BulletShape pShape)
1467 { 1456 {
1468 // Called if the current prim body is about to be destroyed. 1457 // Called if the current prim body is about to be destroyed.
1469 // Remove all the physical dependencies on the old body. 1458 // Remove all the physical dependencies on the old body.
1470 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) 1459 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...)
1471 RemoveBodyDependencies(); 1460 // Note: this virtual function is overloaded by BSPrimLinkable to remove linkset constraints.
1461 RemoveDependencies();
1472 }); 1462 });
1473 1463
1474 // Make sure the properties are set on the new object 1464 // Make sure the properties are set on the new object
@@ -1477,9 +1467,9 @@ public class BSPrim : BSPhysObject
1477 } 1467 }
1478 1468
1479 // Called at taint-time 1469 // Called at taint-time
1480 protected virtual void RemoveBodyDependencies() 1470 protected virtual void RemoveDependencies()
1481 { 1471 {
1482 PhysicalActors.RemoveBodyDependencies(); 1472 PhysicalActors.RemoveDependencies();
1483 } 1473 }
1484 1474
1485 // The physics engine says that properties have updated. Update same and inform 1475 // The physics engine says that properties have updated. Update same and inform
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
index f1c3b5c..f5ee671 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
@@ -78,14 +78,16 @@ public class BSPrimDisplaced : BSPrim
78 // Set this sets and computes the displacement from the passed prim to the center-of-mass. 78 // Set this sets and computes the displacement from the passed prim to the center-of-mass.
79 // A user set value for center-of-mass overrides whatever might be passed in here. 79 // A user set value for center-of-mass overrides whatever might be passed in here.
80 // The displacement is in local coordinates (relative to root prim in linkset oriented coordinates). 80 // The displacement is in local coordinates (relative to root prim in linkset oriented coordinates).
81 public virtual void SetEffectiveCenterOfMassW(Vector3 centerOfMassDisplacement) 81 public virtual void SetEffectiveCenterOfMassDisplacement(Vector3 centerOfMassDisplacement)
82 { 82 {
83 Vector3 comDisp; 83 Vector3 comDisp;
84 if (UserSetCenterOfMass.HasValue) 84 if (UserSetCenterOfMassDisplacement.HasValue)
85 comDisp = (OMV.Vector3)UserSetCenterOfMass; 85 comDisp = (OMV.Vector3)UserSetCenterOfMassDisplacement;
86 else 86 else
87 comDisp = centerOfMassDisplacement; 87 comDisp = centerOfMassDisplacement;
88 88
89 DetailLog("{0},BSPrimDisplaced.SetEffectiveCenterOfMassDisplacement,userSet={1},comDisp={2}",
90 LocalID, UserSetCenterOfMassDisplacement.HasValue, comDisp);
89 if (comDisp == Vector3.Zero) 91 if (comDisp == Vector3.Zero)
90 { 92 {
91 // If there is no diplacement. Things get reset. 93 // If there is no diplacement. Things get reset.
@@ -107,9 +109,15 @@ public class BSPrimDisplaced : BSPrim
107 set 109 set
108 { 110 {
109 if (PositionDisplacement != OMV.Vector3.Zero) 111 if (PositionDisplacement != OMV.Vector3.Zero)
110 base.ForcePosition = value - (PositionDisplacement * RawOrientation); 112 {
113 OMV.Vector3 displacedPos = value - (PositionDisplacement * RawOrientation);
114 DetailLog("{0},BSPrimDisplaced.ForcePosition,val={1},disp={2},newPos={3}", LocalID, value, PositionDisplacement, displacedPos);
115 base.ForcePosition = displacedPos;
116 }
111 else 117 else
118 {
112 base.ForcePosition = value; 119 base.ForcePosition = value;
120 }
113 } 121 }
114 } 122 }
115 123
@@ -118,6 +126,7 @@ public class BSPrimDisplaced : BSPrim
118 get { return base.ForceOrientation; } 126 get { return base.ForceOrientation; }
119 set 127 set
120 { 128 {
129 // TODO:
121 base.ForceOrientation = value; 130 base.ForceOrientation = value;
122 } 131 }
123 } 132 }
@@ -143,7 +152,10 @@ public class BSPrimDisplaced : BSPrim
143 { 152 {
144 // Correct for any rotation around the center-of-mass 153 // Correct for any rotation around the center-of-mass
145 // TODO!!! 154 // TODO!!!
146 entprop.Position = entprop.Position + (PositionDisplacement * entprop.Rotation); 155
156 OMV.Vector3 displacedPos = entprop.Position + (PositionDisplacement * entprop.Rotation);
157 DetailLog("{0},BSPrimDisplaced.ForcePosition,physPos={1},disp={2},newPos={3}", LocalID, entprop.Position, PositionDisplacement, displacedPos);
158 entprop.Position = displacedPos;
147 // entprop.Rotation = something; 159 // entprop.Rotation = something;
148 } 160 }
149 161
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
index 28242d4..235da78 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
@@ -47,9 +47,9 @@ public class BSPrimLinkable : BSPrimDisplaced
47 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 47 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
48 : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical) 48 : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical)
49 { 49 {
50 Linkset = BSLinkset.Factory(PhysicsScene, this); 50 Linkset = BSLinkset.Factory(PhysScene, this);
51 51
52 PhysicsScene.TaintedObject("BSPrimLinksetCompound.Refresh", delegate() 52 PhysScene.TaintedObject("BSPrimLinksetCompound.Refresh", delegate()
53 { 53 {
54 Linkset.Refresh(this); 54 Linkset.Refresh(this);
55 }); 55 });
@@ -61,9 +61,6 @@ public class BSPrimLinkable : BSPrimDisplaced
61 base.Destroy(); 61 base.Destroy();
62 } 62 }
63 63
64 public override BSPhysicsShapeType PreferredPhysicalShape
65 { get { return Linkset.PreferredPhysicalShape(this); } }
66
67 public override void link(Manager.PhysicsActor obj) 64 public override void link(Manager.PhysicsActor obj)
68 { 65 {
69 BSPrimLinkable parent = obj as BSPrimLinkable; 66 BSPrimLinkable parent = obj as BSPrimLinkable;
@@ -102,7 +99,7 @@ public class BSPrimLinkable : BSPrimDisplaced
102 set 99 set
103 { 100 {
104 base.Position = value; 101 base.Position = value;
105 PhysicsScene.TaintedObject("BSPrimLinkset.setPosition", delegate() 102 PhysScene.TaintedObject("BSPrimLinkset.setPosition", delegate()
106 { 103 {
107 Linkset.UpdateProperties(UpdatedProperties.Position, this); 104 Linkset.UpdateProperties(UpdatedProperties.Position, this);
108 }); 105 });
@@ -116,7 +113,7 @@ public class BSPrimLinkable : BSPrimDisplaced
116 set 113 set
117 { 114 {
118 base.Orientation = value; 115 base.Orientation = value;
119 PhysicsScene.TaintedObject("BSPrimLinkset.setOrientation", delegate() 116 PhysScene.TaintedObject("BSPrimLinkset.setOrientation", delegate()
120 { 117 {
121 Linkset.UpdateProperties(UpdatedProperties.Orientation, this); 118 Linkset.UpdateProperties(UpdatedProperties.Orientation, this);
122 }); 119 });
@@ -149,10 +146,10 @@ public class BSPrimLinkable : BSPrimDisplaced
149 } 146 }
150 147
151 // Body is being taken apart. Remove physical dependencies and schedule a rebuild. 148 // Body is being taken apart. Remove physical dependencies and schedule a rebuild.
152 protected override void RemoveBodyDependencies() 149 protected override void RemoveDependencies()
153 { 150 {
154 Linkset.RemoveBodyDependencies(this); 151 Linkset.RemoveDependencies(this);
155 base.RemoveBodyDependencies(); 152 base.RemoveDependencies();
156 } 153 }
157 154
158 public override void UpdateProperties(EntityProperties entprop) 155 public override void UpdateProperties(EntityProperties entprop)
@@ -185,6 +182,10 @@ public class BSPrimLinkable : BSPrimDisplaced
185 { 182 {
186 return false; 183 return false;
187 } 184 }
185
186 // TODO: handle collisions of other objects with with children of linkset.
187 // This is a problem for LinksetCompound since the children are packed into the root.
188
188 return base.Collide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth); 189 return base.Collide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth);
189 } 190 }
190} 191}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 8e05b58..a4a8794 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -316,7 +316,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
316 break; 316 break;
317 case "bulletxna": 317 case "bulletxna":
318 ret = new BSAPIXNA(engineName, this); 318 ret = new BSAPIXNA(engineName, this);
319 // Disable some features that are not implemented in BulletXNA
320 m_log.InfoFormat("{0} Disabling some physics features not implemented by BulletXNA", LogHeader);
319 BSParam.ShouldUseBulletHACD = false; 321 BSParam.ShouldUseBulletHACD = false;
322 BSParam.ShouldUseSingleConvexHullForPrims = false;
320 break; 323 break;
321 } 324 }
322 325
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index bc26460..64aaa15 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -38,38 +38,15 @@ public sealed class BSShapeCollection : IDisposable
38{ 38{
39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; 39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
40 40
41 private BSScene PhysicsScene { get; set; } 41 private BSScene m_physicsScene { get; set; }
42 42
43 private Object m_collectionActivityLock = new Object(); 43 private Object m_collectionActivityLock = new Object();
44 44
45 // Description of a Mesh
46 private struct MeshDesc
47 {
48 public BulletShape shape;
49 public int referenceCount;
50 public DateTime lastReferenced;
51 public UInt64 shapeKey;
52 }
53
54 // Description of a hull.
55 // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations.
56 private struct HullDesc
57 {
58 public BulletShape shape;
59 public int referenceCount;
60 public DateTime lastReferenced;
61 public UInt64 shapeKey;
62 }
63
64 // The sharable set of meshes and hulls. Indexed by their shape hash.
65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
67
68 private bool DDetail = false; 45 private bool DDetail = false;
69 46
70 public BSShapeCollection(BSScene physScene) 47 public BSShapeCollection(BSScene physScene)
71 { 48 {
72 PhysicsScene = physScene; 49 m_physicsScene = physScene;
73 // Set the next to 'true' for very detailed shape update detailed logging (detailed details?) 50 // Set the next to 'true' for very detailed shape update detailed logging (detailed details?)
74 // While detailed debugging is still active, this is better than commenting out all the 51 // While detailed debugging is still active, this is better than commenting out all the
75 // DetailLog statements. When debugging slows down, this and the protected logging 52 // DetailLog statements. When debugging slows down, this and the protected logging
@@ -86,22 +63,18 @@ public sealed class BSShapeCollection : IDisposable
86 // Mostly used for changing bodies out from under Linksets. 63 // Mostly used for changing bodies out from under Linksets.
87 // Useful for other cases where parameters need saving. 64 // Useful for other cases where parameters need saving.
88 // Passing 'null' says no callback. 65 // Passing 'null' says no callback.
89 public delegate void ShapeDestructionCallback(BulletShape shape); 66 public delegate void PhysicalDestructionCallback(BulletBody pBody, BulletShape pShape);
90 public delegate void BodyDestructionCallback(BulletBody body);
91 67
92 // Called to update/change the body and shape for an object. 68 // Called to update/change the body and shape for an object.
93 // First checks the shape and updates that if necessary then makes 69 // The object has some shape and body on it. Here we decide if that is the correct shape
94 // sure the body is of the right type. 70 // for the current state of the object (static/dynamic/...).
71 // If bodyCallback is not null, it is called if either the body or the shape are changed
72 // so dependencies (like constraints) can be removed before the physical object is dereferenced.
95 // Return 'true' if either the body or the shape changed. 73 // Return 'true' if either the body or the shape changed.
96 // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before 74 // Called at taint-time.
97 // the current shape or body is destroyed. This allows the caller to remove any 75 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, PhysicalDestructionCallback bodyCallback)
98 // higher level dependencies on the shape or body. Mostly used for LinkSets to
99 // remove the physical constraints before the body is destroyed.
100 // Called at taint-time!!
101 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim,
102 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
103 { 76 {
104 PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); 77 m_physicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
105 78
106 bool ret = false; 79 bool ret = false;
107 80
@@ -111,12 +84,12 @@ public sealed class BSShapeCollection : IDisposable
111 // Do we have the correct geometry for this type of object? 84 // Do we have the correct geometry for this type of object?
112 // Updates prim.BSShape with information/pointers to shape. 85 // Updates prim.BSShape with information/pointers to shape.
113 // Returns 'true' of BSShape is changed to a new shape. 86 // Returns 'true' of BSShape is changed to a new shape.
114 bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); 87 bool newGeom = CreateGeom(forceRebuild, prim, bodyCallback);
115 // If we had to select a new shape geometry for the object, 88 // If we had to select a new shape geometry for the object,
116 // rebuild the body around it. 89 // rebuild the body around it.
117 // Updates prim.BSBody with information/pointers to requested body 90 // Updates prim.BSBody with information/pointers to requested body
118 // Returns 'true' if BSBody was changed. 91 // Returns 'true' if BSBody was changed.
119 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, bodyCallback); 92 bool newBody = CreateBody((newGeom || forceRebuild), prim, m_physicsScene.World, bodyCallback);
120 ret = newGeom || newBody; 93 ret = newGeom || newBody;
121 } 94 }
122 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", 95 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}",
@@ -127,271 +100,20 @@ public sealed class BSShapeCollection : IDisposable
127 100
128 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim) 101 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
129 { 102 {
130 return GetBodyAndShape(forceRebuild, sim, prim, null, null); 103 return GetBodyAndShape(forceRebuild, sim, prim, null);
131 }
132
133 // Track another user of a body.
134 // We presume the caller has allocated the body.
135 // Bodies only have one user so the body is just put into the world if not already there.
136 private void ReferenceBody(BulletBody body)
137 {
138 lock (m_collectionActivityLock)
139 {
140 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
141 if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
142 {
143 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body);
144 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
145 }
146 }
147 }
148
149 // Release the usage of a body.
150 // Called when releasing use of a BSBody. BSShape is handled separately.
151 // Called in taint time.
152 public void DereferenceBody(BulletBody body, BodyDestructionCallback bodyCallback )
153 {
154 if (!body.HasPhysicalBody)
155 return;
156
157 PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
158
159 lock (m_collectionActivityLock)
160 {
161 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body);
162 // If the caller needs to know the old body is going away, pass the event up.
163 if (bodyCallback != null) bodyCallback(body);
164
165 // Removing an object not in the world is a NOOP
166 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body);
167
168 // Zero any reference to the shape so it is not freed when the body is deleted.
169 PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null);
170 PhysicsScene.PE.DestroyObject(PhysicsScene.World, body);
171 }
172 }
173
174 // Track the datastructures and use count for a shape.
175 // When creating a hull, this is called first to reference the mesh
176 // and then again to reference the hull.
177 // Meshes and hulls for the same shape have the same hash key.
178 // NOTE that native shapes are not added to the mesh list or removed.
179 // Returns 'true' if this is the initial reference to the shape. Otherwise reused.
180 public bool ReferenceShape(BulletShape shape)
181 {
182 bool ret = false;
183 switch (shape.type)
184 {
185 case BSPhysicsShapeType.SHAPE_MESH:
186 MeshDesc meshDesc;
187 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
188 {
189 // There is an existing instance of this mesh.
190 meshDesc.referenceCount++;
191 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
192 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
193 }
194 else
195 {
196 // This is a new reference to a mesh
197 meshDesc.shape = shape.Clone();
198 meshDesc.shapeKey = shape.shapeKey;
199 // We keep a reference to the underlying IMesh data so a hull can be built
200 meshDesc.referenceCount = 1;
201 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
202 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
203 ret = true;
204 }
205 meshDesc.lastReferenced = System.DateTime.Now;
206 Meshes[shape.shapeKey] = meshDesc;
207 break;
208 case BSPhysicsShapeType.SHAPE_HULL:
209 HullDesc hullDesc;
210 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
211 {
212 // There is an existing instance of this hull.
213 hullDesc.referenceCount++;
214 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
215 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
216 }
217 else
218 {
219 // This is a new reference to a hull
220 hullDesc.shape = shape.Clone();
221 hullDesc.shapeKey = shape.shapeKey;
222 hullDesc.referenceCount = 1;
223 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
224 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
225 ret = true;
226
227 }
228 hullDesc.lastReferenced = System.DateTime.Now;
229 Hulls[shape.shapeKey] = hullDesc;
230 break;
231 case BSPhysicsShapeType.SHAPE_UNKNOWN:
232 break;
233 default:
234 // Native shapes are not tracked and they don't go into any list
235 break;
236 }
237 return ret;
238 }
239
240 // Release the usage of a shape.
241 public void DereferenceShape(BulletShape shape, ShapeDestructionCallback shapeCallback)
242 {
243 if (!shape.HasPhysicalShape)
244 return;
245
246 PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceShape");
247
248 if (shape.HasPhysicalShape)
249 {
250 if (shape.isNativeShape)
251 {
252 // Native shapes are not tracked and are released immediately
253 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1}",
254 BSScene.DetailLogZero, shape.AddrString);
255 if (shapeCallback != null) shapeCallback(shape);
256 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
257 }
258 else
259 {
260 switch (shape.type)
261 {
262 case BSPhysicsShapeType.SHAPE_HULL:
263 DereferenceHull(shape, shapeCallback);
264 break;
265 case BSPhysicsShapeType.SHAPE_MESH:
266 DereferenceMesh(shape, shapeCallback);
267 break;
268 case BSPhysicsShapeType.SHAPE_COMPOUND:
269 DereferenceCompound(shape, shapeCallback);
270 break;
271 case BSPhysicsShapeType.SHAPE_UNKNOWN:
272 break;
273 default:
274 break;
275 }
276 }
277 }
278 }
279
280 // Count down the reference count for a mesh shape
281 // Called at taint-time.
282 private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback)
283 {
284 MeshDesc meshDesc;
285 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
286 {
287 meshDesc.referenceCount--;
288 // TODO: release the Bullet storage
289 if (shapeCallback != null) shapeCallback(shape);
290 meshDesc.lastReferenced = System.DateTime.Now;
291 Meshes[shape.shapeKey] = meshDesc;
292 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
293 BSScene.DetailLogZero, shape, meshDesc.referenceCount);
294
295 }
296 }
297
298 // Count down the reference count for a hull shape
299 // Called at taint-time.
300 private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback)
301 {
302 HullDesc hullDesc;
303 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
304 {
305 hullDesc.referenceCount--;
306 // TODO: release the Bullet storage (aging old entries?)
307
308 // Tell upper layers that, if they have dependencies on this shape, this link is going away
309 if (shapeCallback != null) shapeCallback(shape);
310
311 hullDesc.lastReferenced = System.DateTime.Now;
312 Hulls[shape.shapeKey] = hullDesc;
313 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
314 BSScene.DetailLogZero, shape, hullDesc.referenceCount);
315 }
316 }
317
318 // Remove a reference to a compound shape.
319 // Taking a compound shape apart is a little tricky because if you just delete the
320 // physical shape, it will free all the underlying children. We can't do that because
321 // they could be shared. So, this removes each of the children from the compound and
322 // dereferences them separately before destroying the compound collision object itself.
323 // Called at taint-time.
324 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback)
325 {
326 if (!PhysicsScene.PE.IsCompound(shape))
327 {
328 // Failed the sanity check!!
329 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
330 LogHeader, shape.type, shape.AddrString);
331 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
332 BSScene.DetailLogZero, shape.type, shape.AddrString);
333 return;
334 }
335
336 int numChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(shape);
337 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
338
339 for (int ii = numChildren - 1; ii >= 0; ii--)
340 {
341 BulletShape childShape = PhysicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(shape, ii);
342 DereferenceAnonCollisionShape(childShape);
343 }
344 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
345 } 104 }
346 105
347 // Sometimes we have a pointer to a collision shape but don't know what type it is. 106 // If the existing prim's shape is to be replaced, remove the tie to the existing shape
348 // Figure out type and call the correct dereference routine. 107 // before replacing it.
349 // Called at taint-time. 108 private void DereferenceExistingShape(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
350 private void DereferenceAnonCollisionShape(BulletShape shapeInfo)
351 { 109 {
352 MeshDesc meshDesc; 110 if (prim.PhysShape.HasPhysicalShape)
353 HullDesc hullDesc;
354
355 if (TryGetMeshByPtr(shapeInfo, out meshDesc))
356 {
357 shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH;
358 shapeInfo.shapeKey = meshDesc.shapeKey;
359 }
360 else
361 {
362 if (TryGetHullByPtr(shapeInfo, out hullDesc))
363 {
364 shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL;
365 shapeInfo.shapeKey = hullDesc.shapeKey;
366 }
367 else
368 {
369 if (PhysicsScene.PE.IsCompound(shapeInfo))
370 {
371 shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND;
372 }
373 else
374 {
375 if (PhysicsScene.PE.IsNativeShape(shapeInfo))
376 {
377 shapeInfo.isNativeShape = true;
378 shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
379 }
380 }
381 }
382 }
383
384 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
385
386 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
387 {
388 DereferenceShape(shapeInfo, null);
389 }
390 else
391 { 111 {
392 PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", 112 if (shapeCallback != null)
393 LogHeader, PhysicsScene.RegionName, shapeInfo.AddrString); 113 shapeCallback(prim.PhysBody, prim.PhysShape.physShapeInfo);
114 prim.PhysShape.Dereference(m_physicsScene);
394 } 115 }
116 prim.PhysShape = new BSShapeNull();
395 } 117 }
396 118
397 // Create the geometry information in Bullet for later use. 119 // Create the geometry information in Bullet for later use.
@@ -402,60 +124,41 @@ public sealed class BSShapeCollection : IDisposable
402 // Info in prim.BSShape is updated to the new shape. 124 // Info in prim.BSShape is updated to the new shape.
403 // Returns 'true' if the geometry was rebuilt. 125 // Returns 'true' if the geometry was rebuilt.
404 // Called at taint-time! 126 // Called at taint-time!
405 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) 127 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
406 { 128 {
407 bool ret = false; 129 bool ret = false;
408 bool haveShape = false; 130 bool haveShape = false;
131 bool nativeShapePossible = true;
132 PrimitiveBaseShape pbs = prim.BaseShape;
409 133
410 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) 134 // Kludge to create the capsule for the avatar.
135 // TDOD: Remove/redo this when BSShapeAvatar is working!!
136 BSCharacter theChar = prim as BSCharacter;
137 if (theChar != null)
411 { 138 {
412 // an avatar capsule is close to a native shape (it is not shared) 139 DereferenceExistingShape(prim, shapeCallback);
413 GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback); 140 prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
414 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); 141 BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE);
415 ret = true; 142 ret = true;
416 haveShape = true; 143 haveShape = true;
417 } 144 }
418 145
419 // Compound shapes are handled special as they are rebuilt from scratch.
420 // This isn't too great a hardship since most of the child shapes will have already been created.
421 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
422 {
423 ret = GetReferenceToCompoundShape(prim, shapeCallback);
424 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
425 haveShape = true;
426 }
427
428 if (!haveShape)
429 {
430 ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback);
431 }
432
433 return ret;
434 }
435
436 // Create a mesh, hull or native shape.
437 // Return 'true' if the prim's shape was changed.
438 public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
439 {
440 bool ret = false;
441 bool haveShape = false;
442 bool nativeShapePossible = true;
443 PrimitiveBaseShape pbs = prim.BaseShape;
444
445 // If the prim attributes are simple, this could be a simple Bullet native shape 146 // If the prim attributes are simple, this could be a simple Bullet native shape
147 // Native shapes work whether to object is static or physical.
446 if (!haveShape 148 if (!haveShape
447 && nativeShapePossible 149 && nativeShapePossible
448 && pbs != null 150 && pbs != null
449 && !pbs.SculptEntry 151 && PrimHasNoCuts(pbs)
450 && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) ) 152 && ( !pbs.SculptEntry || (pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) )
153 )
451 { 154 {
452 // Get the scale of any existing shape so we can see if the new shape is same native type and same size. 155 // Get the scale of any existing shape so we can see if the new shape is same native type and same size.
453 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero; 156 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
454 if (prim.PhysShape.HasPhysicalShape) 157 if (prim.PhysShape.HasPhysicalShape)
455 scaleOfExistingShape = PhysicsScene.PE.GetLocalScaling(prim.PhysShape); 158 scaleOfExistingShape = m_physicsScene.PE.GetLocalScaling(prim.PhysShape.physShapeInfo);
456 159
457 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}", 160 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}",
458 prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type); 161 prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.physShapeInfo.shapeType);
459 162
460 // It doesn't look like Bullet scales native spheres so make sure the scales are all equal 163 // It doesn't look like Bullet scales native spheres so make sure the scales are all equal
461 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) 164 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
@@ -463,26 +166,30 @@ public sealed class BSShapeCollection : IDisposable
463 { 166 {
464 haveShape = true; 167 haveShape = true;
465 if (forceRebuild 168 if (forceRebuild
466 || prim.Scale != scaleOfExistingShape 169 || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_SPHERE
467 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE 170 )
468 )
469 { 171 {
470 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, 172 DereferenceExistingShape(prim, shapeCallback);
471 FixedShapeKey.KEY_SPHERE, shapeCallback); 173 prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
174 BSPhysicsShapeType.SHAPE_SPHERE, FixedShapeKey.KEY_SPHERE);
175 ret = true;
472 } 176 }
473 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}", 177 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}",
474 prim.LocalID, forceRebuild, ret, prim.PhysShape); 178 prim.LocalID, forceRebuild, ret, prim.PhysShape);
475 } 179 }
180 // If we didn't make a sphere, maybe a box will work.
476 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) 181 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
477 { 182 {
478 haveShape = true; 183 haveShape = true;
479 if (forceRebuild 184 if (forceRebuild
480 || prim.Scale != scaleOfExistingShape 185 || prim.Scale != scaleOfExistingShape
481 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX 186 || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_BOX
482 ) 187 )
483 { 188 {
484 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, 189 DereferenceExistingShape(prim, shapeCallback);
485 FixedShapeKey.KEY_BOX, shapeCallback); 190 prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
191 BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
192 ret = true;
486 } 193 }
487 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}", 194 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}",
488 prim.LocalID, forceRebuild, ret, prim.PhysShape); 195 prim.LocalID, forceRebuild, ret, prim.PhysShape);
@@ -499,7 +206,7 @@ public sealed class BSShapeCollection : IDisposable
499 } 206 }
500 207
501 // return 'true' if this shape description does not include any cutting or twisting. 208 // return 'true' if this shape description does not include any cutting or twisting.
502 private bool PrimHasNoCuts(PrimitiveBaseShape pbs) 209 public static bool PrimHasNoCuts(PrimitiveBaseShape pbs)
503 { 210 {
504 return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 211 return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
505 && pbs.ProfileHollow == 0 212 && pbs.ProfileHollow == 0
@@ -511,7 +218,7 @@ public sealed class BSShapeCollection : IDisposable
511 } 218 }
512 219
513 // return 'true' if the prim's shape was changed. 220 // return 'true' if the prim's shape was changed.
514 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 221 private bool CreateGeomMeshOrHull(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
515 { 222 {
516 223
517 bool ret = false; 224 bool ret = false;
@@ -519,538 +226,110 @@ public sealed class BSShapeCollection : IDisposable
519 // made. Native shapes work in either case. 226 // made. Native shapes work in either case.
520 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) 227 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
521 { 228 {
522 // Update prim.BSShape to reference a hull of this shape. 229 // Use a simple, single mesh convex hull shape if the object is simple enough
523 ret = GetReferenceToHull(prim, shapeCallback); 230 BSShape potentialHull = null;
524 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
525 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
526 }
527 else
528 {
529 ret = GetReferenceToMesh(prim, shapeCallback);
530 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
531 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
532 }
533 return ret;
534 }
535
536 // Creates a native shape and assignes it to prim.BSShape.
537 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape().
538 private bool GetReferenceToNativeShape(BSPhysObject prim,
539 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey,
540 ShapeDestructionCallback shapeCallback)
541 {
542 // release any previous shape
543 DereferenceShape(prim.PhysShape, shapeCallback);
544
545 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
546
547 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
548 if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
549 prim.LocalID, newShape, prim.Scale);
550
551 // native shapes are scaled by Bullet
552 prim.PhysShape = newShape;
553 return true;
554 }
555
556 private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType,
557 FixedShapeKey shapeKey)
558 {
559 BulletShape newShape;
560 // Need to make sure the passed shape information is for the native type.
561 ShapeData nativeShapeData = new ShapeData();
562 nativeShapeData.Type = shapeType;
563 nativeShapeData.ID = prim.LocalID;
564 nativeShapeData.Scale = prim.Scale;
565 nativeShapeData.Size = prim.Scale; // unneeded, I think.
566 nativeShapeData.MeshKey = (ulong)shapeKey;
567 nativeShapeData.HullKey = (ulong)shapeKey;
568
569 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
570 {
571 231
572 newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale); 232 PrimitiveBaseShape pbs = prim.BaseShape;
573 if (DDetail) DetailLog("{0},BSShapeCollection.BuildPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); 233 if (BSParam.ShouldUseSingleConvexHullForPrims
574 } 234 && pbs != null
575 else 235 && !pbs.SculptEntry
576 { 236 && PrimHasNoCuts(pbs)
577 // Native shapes are scaled in Bullet so set the scaling to the size 237 )
578 newShape = PhysicsScene.PE.BuildNativeShape(PhysicsScene.World, nativeShapeData);
579
580 }
581 if (!newShape.HasPhysicalShape)
582 {
583 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
584 LogHeader, prim.LocalID, shapeType);
585 }
586 newShape.shapeKey = (System.UInt64)shapeKey;
587 newShape.isNativeShape = true;
588
589 return newShape;
590 }
591
592 // Builds a mesh shape in the physical world and updates prim.BSShape.
593 // Dereferences previous shape in BSShape and adds a reference for this new shape.
594 // Returns 'true' of a mesh was actually built. Otherwise .
595 // Called at taint-time!
596 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
597 {
598 BulletShape newShape = new BulletShape();
599
600 float lod;
601 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
602
603 // if this new shape is the same as last time, don't recreate the mesh
604 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
605 return false;
606
607 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2},size={3},lod={4}",
608 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
609
610 // Since we're recreating new, get rid of the reference to the previous shape
611 DereferenceShape(prim.PhysShape, shapeCallback);
612
613 newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod);
614 // Take evasive action if the mesh was not constructed.
615 newShape = VerifyMeshCreated(PhysicsScene, newShape, prim);
616
617 ReferenceShape(newShape);
618
619 prim.PhysShape = newShape;
620
621 return true; // 'true' means a new shape has been added to this prim
622 }
623
624 private BulletShape CreatePhysicalMesh(BSPhysObject prim, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
625 {
626 BulletShape newShape = new BulletShape();
627
628 MeshDesc meshDesc;
629 if (Meshes.TryGetValue(newMeshKey, out meshDesc))
630 {
631 // If the mesh has already been built just use it.
632 newShape = meshDesc.shape.Clone();
633 }
634 else
635 {
636 IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
637 false, // say it is not physical so a bounding box is not built
638 false // do not cache the mesh and do not use previously built versions
639 );
640
641 if (meshData != null)
642 { 238 {
643 239 potentialHull = BSShapeConvexHull.GetReference(m_physicsScene, false /* forceRebuild */, prim);
644 int[] indices = meshData.getIndexListAsInt(); 240 }
645 int realIndicesIndex = indices.Length; 241 else
646 float[] verticesAsFloats = meshData.getVertexListAsFloat(); 242 {
647 243 potentialHull = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
648 if (BSParam.ShouldRemoveZeroWidthTriangles)
649 {
650 // Remove degenerate triangles. These are triangles with two of the vertices
651 // are the same. This is complicated by the problem that vertices are not
652 // made unique in sculpties so we have to compare the values in the vertex.
653 realIndicesIndex = 0;
654 for (int tri = 0; tri < indices.Length; tri += 3)
655 {
656 // Compute displacements into vertex array for each vertex of the triangle
657 int v1 = indices[tri + 0] * 3;
658 int v2 = indices[tri + 1] * 3;
659 int v3 = indices[tri + 2] * 3;
660 // Check to see if any two of the vertices are the same
661 if (!( ( verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
662 && verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1]
663 && verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2])
664 || ( verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
665 && verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1]
666 && verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2])
667 || ( verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
668 && verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1]
669 && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) )
670 )
671 {
672 // None of the vertices of the triangles are the same. This is a good triangle;
673 indices[realIndicesIndex + 0] = indices[tri + 0];
674 indices[realIndicesIndex + 1] = indices[tri + 1];
675 indices[realIndicesIndex + 2] = indices[tri + 2];
676 realIndicesIndex += 3;
677 }
678 }
679 }
680 DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}",
681 BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
682
683 if (realIndicesIndex != 0)
684 {
685 newShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World,
686 realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
687 }
688 else
689 {
690 PhysicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}",
691 LogHeader, prim.PhysObjectName, prim.RawPosition, PhysicsScene.Name);
692 }
693 } 244 }
694 }
695 newShape.shapeKey = newMeshKey;
696
697 return newShape;
698 }
699
700 // See that hull shape exists in the physical world and update prim.BSShape.
701 // We could be creating the hull because scale changed or whatever.
702 // Return 'true' if a new hull was built. Otherwise, returning a shared hull instance.
703 private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
704 {
705 BulletShape newShape;
706
707 float lod;
708 System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
709
710 // if the hull hasn't changed, don't rebuild it
711 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
712 return false;
713
714 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
715 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
716
717 // Remove usage of the previous shape.
718 DereferenceShape(prim.PhysShape, shapeCallback);
719
720 newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod);
721 // It might not have been created if we're waiting for an asset.
722 newShape = VerifyMeshCreated(PhysicsScene, newShape, prim);
723
724 ReferenceShape(newShape);
725
726 prim.PhysShape = newShape;
727 return true; // 'true' means a new shape has been added to this prim
728 }
729
730 List<ConvexResult> m_hulls;
731 private BulletShape CreatePhysicalHull(BSPhysObject prim, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
732 {
733
734 BulletShape newShape = new BulletShape();
735 IntPtr hullPtr = IntPtr.Zero;
736 245
737 HullDesc hullDesc; 246 // If the current shape is not what is on the prim at the moment, time to change.
738 if (Hulls.TryGetValue(newHullKey, out hullDesc)) 247 if (!prim.PhysShape.HasPhysicalShape
739 { 248 || potentialHull.ShapeType != prim.PhysShape.ShapeType
740 // If the hull shape already has been created, just use the one shared instance. 249 || potentialHull.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
741 newShape = hullDesc.shape.Clone(); 250 {
251 DereferenceExistingShape(prim, shapeCallback);
252 prim.PhysShape = potentialHull;
253 ret = true;
254 }
255 else
256 {
257 // The current shape on the prim is the correct one. We don't need the potential reference.
258 potentialHull.Dereference(m_physicsScene);
259 }
260 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1}", prim.LocalID, prim.PhysShape);
742 } 261 }
743 else 262 else
744 { 263 {
745 if (BSParam.ShouldUseBulletHACD) 264 // Update prim.BSShape to reference a mesh of this shape.
265 BSShape potentialMesh = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
266 // If the current shape is not what is on the prim at the moment, time to change.
267 if (!prim.PhysShape.HasPhysicalShape
268 || potentialMesh.ShapeType != prim.PhysShape.ShapeType
269 || potentialMesh.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
746 { 270 {
747 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID); 271 DereferenceExistingShape(prim, shapeCallback);
748 MeshDesc meshDesc; 272 prim.PhysShape = potentialMesh;
749 if (!Meshes.TryGetValue(newHullKey, out meshDesc)) 273 ret = true;
750 {
751 // That's odd because the mesh should have been created before the hull
752 // but, since it doesn't exist, create it.
753 newShape = CreatePhysicalMesh(prim, newHullKey, prim.BaseShape, prim.Size, lod);
754 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,noMeshBuiltNew,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
755
756 if (newShape.HasPhysicalShape)
757 {
758 ReferenceShape(newShape);
759 Meshes.TryGetValue(newHullKey, out meshDesc);
760 }
761 }
762 if (meshDesc.shape.HasPhysicalShape)
763 {
764 HACDParams parms;
765 parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
766 parms.minClusters = BSParam.BHullMinClusters;
767 parms.compacityWeight = BSParam.BHullCompacityWeight;
768 parms.volumeWeight = BSParam.BHullVolumeWeight;
769 parms.concavity = BSParam.BHullConcavity;
770 parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
771 parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
772 parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
773 parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
774
775 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
776 newShape = PhysicsScene.PE.BuildHullShapeFromMesh(PhysicsScene.World, meshDesc.shape, parms);
777 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
778 }
779 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
780 } 274 }
781 if (!newShape.HasPhysicalShape) 275 else
782 { 276 {
783 // Build a new hull in the physical world. 277 // We don't need this reference to the mesh that is already being using.
784 // Pass true for physicalness as this prevents the creation of bounding box which is not needed 278 potentialMesh.Dereference(m_physicsScene);
785 IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
786 if (meshData != null)
787 {
788 int[] indices = meshData.getIndexListAsInt();
789 List<OMV.Vector3> vertices = meshData.getVertexList();
790
791 //format conversion from IMesh format to DecompDesc format
792 List<int> convIndices = new List<int>();
793 List<float3> convVertices = new List<float3>();
794 for (int ii = 0; ii < indices.GetLength(0); ii++)
795 {
796 convIndices.Add(indices[ii]);
797 }
798 foreach (OMV.Vector3 vv in vertices)
799 {
800 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
801 }
802
803 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
804 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
805 {
806 // Simple primitive shapes we know are convex so they are better implemented with
807 // fewer hulls.
808 // Check for simple shape (prim without cuts) and reduce split parameter if so.
809 if (PrimHasNoCuts(pbs))
810 {
811 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
812 }
813 }
814
815 // setup and do convex hull conversion
816 m_hulls = new List<ConvexResult>();
817 DecompDesc dcomp = new DecompDesc();
818 dcomp.mIndices = convIndices;
819 dcomp.mVertices = convVertices;
820 dcomp.mDepth = maxDepthSplit;
821 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
822 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
823 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
824 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
825 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
826 // create the hull into the _hulls variable
827 convexBuilder.process(dcomp);
828
829 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
830 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
831
832 // Convert the vertices and indices for passing to unmanaged.
833 // The hull information is passed as a large floating point array.
834 // The format is:
835 // convHulls[0] = number of hulls
836 // convHulls[1] = number of vertices in first hull
837 // convHulls[2] = hull centroid X coordinate
838 // convHulls[3] = hull centroid Y coordinate
839 // convHulls[4] = hull centroid Z coordinate
840 // convHulls[5] = first hull vertex X
841 // convHulls[6] = first hull vertex Y
842 // convHulls[7] = first hull vertex Z
843 // convHulls[8] = second hull vertex X
844 // ...
845 // convHulls[n] = number of vertices in second hull
846 // convHulls[n+1] = second hull centroid X coordinate
847 // ...
848 //
849 // TODO: is is very inefficient. Someday change the convex hull generator to return
850 // data structures that do not need to be converted in order to pass to Bullet.
851 // And maybe put the values directly into pinned memory rather than marshaling.
852 int hullCount = m_hulls.Count;
853 int totalVertices = 1; // include one for the count of the hulls
854 foreach (ConvexResult cr in m_hulls)
855 {
856 totalVertices += 4; // add four for the vertex count and centroid
857 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
858 }
859 float[] convHulls = new float[totalVertices];
860
861 convHulls[0] = (float)hullCount;
862 int jj = 1;
863 foreach (ConvexResult cr in m_hulls)
864 {
865 // copy vertices for index access
866 float3[] verts = new float3[cr.HullVertices.Count];
867 int kk = 0;
868 foreach (float3 ff in cr.HullVertices)
869 {
870 verts[kk++] = ff;
871 }
872
873 // add to the array one hull's worth of data
874 convHulls[jj++] = cr.HullIndices.Count;
875 convHulls[jj++] = 0f; // centroid x,y,z
876 convHulls[jj++] = 0f;
877 convHulls[jj++] = 0f;
878 foreach (int ind in cr.HullIndices)
879 {
880 convHulls[jj++] = verts[ind].x;
881 convHulls[jj++] = verts[ind].y;
882 convHulls[jj++] = verts[ind].z;
883 }
884 }
885 // create the hull data structure in Bullet
886 newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
887 }
888 } 279 }
889 newShape.shapeKey = newHullKey; 280 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1}", prim.LocalID, prim.PhysShape);
890 } 281 }
891 282 return ret;
892 return newShape;
893 }
894
895 // Callback from convex hull creater with a newly created hull.
896 // Just add it to our collection of hulls for this shape.
897 private void HullReturn(ConvexResult result)
898 {
899 m_hulls.Add(result);
900 return;
901 } 283 }
902 284
903 // Compound shapes are always built from scratch. 285 // Track another user of a body.
904 // This shouldn't be to bad since most of the parts will be meshes that had been built previously. 286 // We presume the caller has allocated the body.
905 private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 287 // Bodies only have one user so the body is just put into the world if not already there.
288 private void ReferenceBody(BulletBody body)
906 { 289 {
907 // Remove reference to the old shape 290 lock (m_collectionActivityLock)
908 // Don't need to do this as the shape is freed when the new root shape is created below. 291 {
909 // DereferenceShape(prim.PhysShape, true, shapeCallback); 292 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
910 293 if (!m_physicsScene.PE.IsInWorld(m_physicsScene.World, body))
911 BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false); 294 {
912 295 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, body);
913 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. 296 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
914 CreateGeomMeshOrHull(prim, shapeCallback); 297 }
915 PhysicsScene.PE.AddChildShapeToCompoundShape(cShape, prim.PhysShape, OMV.Vector3.Zero, OMV.Quaternion.Identity); 298 }
916 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
917 prim.LocalID, cShape, prim.PhysShape);
918
919 prim.PhysShape = cShape;
920
921 return true;
922 } 299 }
923 300
924 // Create a hash of all the shape parameters to be used as a key 301 // Release the usage of a body.
925 // for this particular shape. 302 // Called when releasing use of a BSBody. BSShape is handled separately.
926 public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) 303 // Called in taint time.
927 { 304 public void DereferenceBody(BulletBody body, PhysicalDestructionCallback bodyCallback )
928 // level of detail based on size and type of the object
929 float lod = BSParam.MeshLOD;
930
931 // prims with curvy internal cuts need higher lod
932 if (pbs.HollowShape == HollowShape.Circle)
933 lod = BSParam.MeshCircularLOD;
934
935 if (pbs.SculptEntry)
936 lod = BSParam.SculptLOD;
937
938 // Mega prims usually get more detail because one can interact with shape approximations at this size.
939 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
940 if (maxAxis > BSParam.MeshMegaPrimThreshold)
941 lod = BSParam.MeshMegaPrimLOD;
942
943 retLod = lod;
944 return pbs.GetMeshKey(size, lod);
945 }
946 // For those who don't want the LOD
947 public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
948 { 305 {
949 float lod; 306 if (!body.HasPhysicalBody)
950 return ComputeShapeKey(size, pbs, out lod); 307 return;
951 }
952 308
953 // The creation of a mesh or hull can fail if an underlying asset is not available. 309 m_physicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
954 // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
955 // and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
956 // The first case causes the asset to be fetched. The second case requires
957 // us to not loop forever.
958 // Called after creating a physical mesh or hull. If the physical shape was created,
959 // just return.
960 public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim)
961 {
962 // If the shape was successfully created, nothing more to do
963 if (newShape.HasPhysicalShape)
964 return newShape;
965 310
966 // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been 311 lock (m_collectionActivityLock)
967 // fetched but we end up here again, the meshing of the asset must have failed.
968 // Prevent trying to keep fetching the mesh by declaring failure.
969 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
970 {
971 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
972 physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
973 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
974 }
975 else
976 { 312 {
977 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset 313 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body);
978 if (prim.BaseShape.SculptEntry 314 // If the caller needs to know the old body is going away, pass the event up.
979 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed 315 if (bodyCallback != null)
980 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting 316 bodyCallback(body, null);
981 && prim.BaseShape.SculptTexture != OMV.UUID.Zero
982 )
983 {
984 physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
985 // Multiple requestors will know we're waiting for this asset
986 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
987
988 BSPhysObject xprim = prim;
989 Util.FireAndForget(delegate
990 {
991 RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
992 if (assetProvider != null)
993 {
994 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
995 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
996 {
997 bool assetFound = false;
998 string mismatchIDs = String.Empty; // DEBUG DEBUG
999 if (asset != null && yprim.BaseShape.SculptEntry)
1000 {
1001 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
1002 {
1003 yprim.BaseShape.SculptData = asset.Data;
1004 // This will cause the prim to see that the filler shape is not the right
1005 // one and try again to build the object.
1006 // No race condition with the normal shape setting since the rebuild is at taint time.
1007 yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
1008 assetFound = true;
1009 }
1010 else
1011 {
1012 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
1013 }
1014 }
1015 if (assetFound)
1016 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
1017 else
1018 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
1019 physicsScene.DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
1020 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
1021 317
1022 }); 318 // Removing an object not in the world is a NOOP
1023 } 319 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, body);
1024 else
1025 {
1026 xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
1027 physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
1028 LogHeader, physicsScene.Name);
1029 }
1030 });
1031 }
1032 else
1033 {
1034 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
1035 {
1036 physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
1037 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
1038 }
1039 }
1040 }
1041 320
1042 // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object. 321 // Zero any reference to the shape so it is not freed when the body is deleted.
1043 BulletShape fillinShape = physicsScene.Shapes.BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); 322 m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, body, null);
1044 physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
1045 323
1046 return fillinShape; 324 m_physicsScene.PE.DestroyObject(m_physicsScene.World, body);
325 }
1047 } 326 }
1048 327
1049 // Create a body object in Bullet. 328 // Create a body object in Bullet.
1050 // Updates prim.BSBody with the information about the new body if one is created. 329 // Updates prim.BSBody with the information about the new body if one is created.
1051 // Returns 'true' if an object was actually created. 330 // Returns 'true' if an object was actually created.
1052 // Called at taint-time. 331 // Called at taint-time.
1053 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BodyDestructionCallback bodyCallback) 332 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, PhysicalDestructionCallback bodyCallback)
1054 { 333 {
1055 bool ret = false; 334 bool ret = false;
1056 335
@@ -1061,7 +340,7 @@ public sealed class BSShapeCollection : IDisposable
1061 // If not a solid object, body is a GhostObject. Otherwise a RigidBody. 340 // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
1062 if (!mustRebuild) 341 if (!mustRebuild)
1063 { 342 {
1064 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(prim.PhysBody); 343 CollisionObjectTypes bodyType = (CollisionObjectTypes)m_physicsScene.PE.GetBodyType(prim.PhysBody);
1065 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY 344 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY
1066 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) 345 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT)
1067 { 346 {
@@ -1079,12 +358,12 @@ public sealed class BSShapeCollection : IDisposable
1079 BulletBody aBody; 358 BulletBody aBody;
1080 if (prim.IsSolid) 359 if (prim.IsSolid)
1081 { 360 {
1082 aBody = PhysicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); 361 aBody = m_physicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation);
1083 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody); 362 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,rigid,body={1}", prim.LocalID, aBody);
1084 } 363 }
1085 else 364 else
1086 { 365 {
1087 aBody = PhysicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); 366 aBody = m_physicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation);
1088 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody); 367 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody);
1089 } 368 }
1090 369
@@ -1098,46 +377,10 @@ public sealed class BSShapeCollection : IDisposable
1098 return ret; 377 return ret;
1099 } 378 }
1100 379
1101 private bool TryGetMeshByPtr(BulletShape shape, out MeshDesc outDesc)
1102 {
1103 bool ret = false;
1104 MeshDesc foundDesc = new MeshDesc();
1105 foreach (MeshDesc md in Meshes.Values)
1106 {
1107 if (md.shape.ReferenceSame(shape))
1108 {
1109 foundDesc = md;
1110 ret = true;
1111 break;
1112 }
1113
1114 }
1115 outDesc = foundDesc;
1116 return ret;
1117 }
1118
1119 private bool TryGetHullByPtr(BulletShape shape, out HullDesc outDesc)
1120 {
1121 bool ret = false;
1122 HullDesc foundDesc = new HullDesc();
1123 foreach (HullDesc hd in Hulls.Values)
1124 {
1125 if (hd.shape.ReferenceSame(shape))
1126 {
1127 foundDesc = hd;
1128 ret = true;
1129 break;
1130 }
1131
1132 }
1133 outDesc = foundDesc;
1134 return ret;
1135 }
1136
1137 private void DetailLog(string msg, params Object[] args) 380 private void DetailLog(string msg, params Object[] args)
1138 { 381 {
1139 if (PhysicsScene.PhysicsLogging.Enabled) 382 if (m_physicsScene.PhysicsLogging.Enabled)
1140 PhysicsScene.DetailLog(msg, args); 383 m_physicsScene.DetailLog(msg, args);
1141 } 384 }
1142} 385}
1143} 386}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
index dd5ae1a..3e4ee5a 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -31,6 +31,7 @@ using System.Text;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager; 33using OpenSim.Region.Physics.Manager;
34using OpenSim.Region.Physics.ConvexDecompositionDotNet;
34 35
35using OMV = OpenMetaverse; 36using OMV = OpenMetaverse;
36 37
@@ -38,74 +39,39 @@ namespace OpenSim.Region.Physics.BulletSPlugin
38{ 39{
39public abstract class BSShape 40public abstract class BSShape
40{ 41{
42 private static string LogHeader = "[BULLETSIM SHAPE]";
43
41 public int referenceCount { get; set; } 44 public int referenceCount { get; set; }
42 public DateTime lastReferenced { get; set; } 45 public DateTime lastReferenced { get; set; }
43 public BulletShape physShapeInfo { get; set; } 46 public BulletShape physShapeInfo { get; set; }
44 47
45 public BSShape() 48 public BSShape()
46 { 49 {
47 referenceCount = 0; 50 referenceCount = 1;
48 lastReferenced = DateTime.Now; 51 lastReferenced = DateTime.Now;
49 physShapeInfo = new BulletShape(); 52 physShapeInfo = new BulletShape();
50 } 53 }
51 public BSShape(BulletShape pShape) 54 public BSShape(BulletShape pShape)
52 { 55 {
53 referenceCount = 0; 56 referenceCount = 1;
54 lastReferenced = DateTime.Now; 57 lastReferenced = DateTime.Now;
55 physShapeInfo = pShape; 58 physShapeInfo = pShape;
56 } 59 }
57 60
58 // Get a reference to a physical shape. Create if it doesn't exist 61 // Get another reference to this shape.
59 public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 62 public abstract BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim);
60 {
61 BSShape ret = null;
62
63 if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
64 {
65 // an avatar capsule is close to a native shape (it is not shared)
66 ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE,
67 FixedShapeKey.KEY_CAPSULE);
68 physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret);
69 }
70
71 // Compound shapes are handled special as they are rebuilt from scratch.
72 // This isn't too great a hardship since most of the child shapes will have already been created.
73 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
74 {
75 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
76 ret = BSShapeCompound.GetReference(prim);
77 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
78 }
79
80 // Avatars have their own unique shape
81 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_AVATAR)
82 {
83 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
84 ret = BSShapeAvatar.GetReference(prim);
85 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,avatarShape,shape={1}", prim.LocalID, ret);
86 }
87
88 if (ret == null)
89 ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim);
90
91 return ret;
92 }
93 private static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
94 {
95 BSShapeMesh.GetReference(physicsScene, forceRebuild, prim);
96 BSShapeHull.GetReference(physicsScene, forceRebuild, prim);
97 return null;
98 }
99 63
100 // Called when this shape is being used again. 64 // Called when this shape is being used again.
101 public virtual void IncrementReference() 65 // Used internally. External callers should call instance.GetReference() to properly copy/reference
66 // the shape.
67 protected virtual void IncrementReference()
102 { 68 {
103 referenceCount++; 69 referenceCount++;
104 lastReferenced = DateTime.Now; 70 lastReferenced = DateTime.Now;
105 } 71 }
106 72
107 // Called when this shape is being used again. 73 // Called when this shape is being used again.
108 public virtual void DecrementReference() 74 protected virtual void DecrementReference()
109 { 75 {
110 referenceCount--; 76 referenceCount--;
111 lastReferenced = DateTime.Now; 77 lastReferenced = DateTime.Now;
@@ -114,22 +80,178 @@ public abstract class BSShape
114 // Release the use of a physical shape. 80 // Release the use of a physical shape.
115 public abstract void Dereference(BSScene physicsScene); 81 public abstract void Dereference(BSScene physicsScene);
116 82
83 // Return 'true' if there is an allocated physics physical shape under this class instance.
84 public virtual bool HasPhysicalShape
85 {
86 get
87 {
88 if (physShapeInfo != null)
89 return physShapeInfo.HasPhysicalShape;
90 return false;
91 }
92 }
93 public virtual BSPhysicsShapeType ShapeType
94 {
95 get
96 {
97 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
98 if (physShapeInfo != null && physShapeInfo.HasPhysicalShape)
99 ret = physShapeInfo.shapeType;
100 return ret;
101 }
102 }
103
117 // Returns a string for debugging that uniquily identifies the memory used by this instance 104 // Returns a string for debugging that uniquily identifies the memory used by this instance
118 public virtual string AddrString 105 public virtual string AddrString
119 { 106 {
120 get { return "unknown"; } 107 get
108 {
109 if (physShapeInfo != null)
110 return physShapeInfo.AddrString;
111 return "unknown";
112 }
121 } 113 }
122 114
123 public override string ToString() 115 public override string ToString()
124 { 116 {
125 StringBuilder buff = new StringBuilder(); 117 StringBuilder buff = new StringBuilder();
126 buff.Append("<p="); 118 if (physShapeInfo == null)
127 buff.Append(AddrString); 119 {
120 buff.Append(",noPhys");
121 }
122 else
123 {
124 buff.Append(",phy=");
125 buff.Append(physShapeInfo.ToString());
126 }
128 buff.Append(",c="); 127 buff.Append(",c=");
129 buff.Append(referenceCount.ToString()); 128 buff.Append(referenceCount.ToString());
130 buff.Append(">"); 129 buff.Append(">");
131 return buff.ToString(); 130 return buff.ToString();
132 } 131 }
132
133 #region Common shape routines
134 // Create a hash of all the shape parameters to be used as a key for this particular shape.
135 public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
136 {
137 // level of detail based on size and type of the object
138 float lod = BSParam.MeshLOD;
139 if (pbs.SculptEntry)
140 lod = BSParam.SculptLOD;
141
142 // Mega prims usually get more detail because one can interact with shape approximations at this size.
143 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
144 if (maxAxis > BSParam.MeshMegaPrimThreshold)
145 lod = BSParam.MeshMegaPrimLOD;
146
147 retLod = lod;
148 return pbs.GetMeshKey(size, lod);
149 }
150
151 // The creation of a mesh or hull can fail if an underlying asset is not available.
152 // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
153 // and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
154 // The first case causes the asset to be fetched. The second case requires
155 // us to not loop forever.
156 // Called after creating a physical mesh or hull. If the physical shape was created,
157 // just return.
158 public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim)
159 {
160 // If the shape was successfully created, nothing more to do
161 if (newShape.HasPhysicalShape)
162 return newShape;
163
164 // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been
165 // fetched but we end up here again, the meshing of the asset must have failed.
166 // Prevent trying to keep fetching the mesh by declaring failure.
167 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
168 {
169 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
170 physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
171 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
172 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,setFailed,objNam={1},tex={2}",
173 prim.LocalID, prim.PhysObjectName, prim.BaseShape.SculptTexture);
174 }
175 else
176 {
177 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
178 if (prim.BaseShape.SculptEntry
179 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed
180 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting
181 && prim.BaseShape.SculptTexture != OMV.UUID.Zero
182 )
183 {
184 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,fetchAsset,objNam={1},tex={2}",
185 prim.LocalID, prim.PhysObjectName, prim.BaseShape.SculptTexture);
186 // Multiple requestors will know we're waiting for this asset
187 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
188
189 BSPhysObject xprim = prim;
190 Util.FireAndForget(delegate
191 {
192 // physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,inFireAndForget", xprim.LocalID);
193 RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
194 if (assetProvider != null)
195 {
196 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
197 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
198 {
199 // physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,assetProviderCallback", xprim.LocalID);
200 bool assetFound = false;
201 string mismatchIDs = String.Empty; // DEBUG DEBUG
202 if (asset != null && yprim.BaseShape.SculptEntry)
203 {
204 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
205 {
206 yprim.BaseShape.SculptData = asset.Data;
207 // This will cause the prim to see that the filler shape is not the right
208 // one and try again to build the object.
209 // No race condition with the normal shape setting since the rebuild is at taint time.
210 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
211 yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
212 assetFound = true;
213 }
214 else
215 {
216 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
217 }
218 }
219 if (!assetFound)
220 {
221 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
222 }
223 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
224 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
225 });
226 }
227 else
228 {
229 xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
230 physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
231 LogHeader, physicsScene.Name);
232 }
233 });
234 }
235 else
236 {
237 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
238 {
239 physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
240 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
241 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,wasFailed,objNam={1},tex={2}",
242 prim.LocalID, prim.PhysObjectName, prim.BaseShape.SculptTexture);
243 }
244 }
245 }
246
247 // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object.
248 BSShape fillShape = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
249 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,boxTempShape", prim.LocalID);
250
251 return fillShape.physShapeInfo;
252 }
253
254 #endregion // Common shape routines
133} 255}
134 256
135// ============================================================================================================ 257// ============================================================================================================
@@ -139,6 +261,7 @@ public class BSShapeNull : BSShape
139 { 261 {
140 } 262 }
141 public static BSShape GetReference() { return new BSShapeNull(); } 263 public static BSShape GetReference() { return new BSShapeNull(); }
264 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim) { return new BSShapeNull(); }
142 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ } 265 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ }
143} 266}
144 267
@@ -150,24 +273,34 @@ public class BSShapeNative : BSShape
150 { 273 {
151 } 274 }
152 275
153 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, 276 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
154 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) 277 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
155 { 278 {
156 // Native shapes are not shared and are always built anew. 279 // Native shapes are not shared and are always built anew.
157 return new BSShapeNative(CreatePhysicalNativeShape(physicsScene, prim, shapeType, shapeKey)); 280 return new BSShapeNative(CreatePhysicalNativeShape(physicsScene, prim, shapeType, shapeKey));
158 } 281 }
159 282
283 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
284 {
285 // Native shapes are not shared so we return a new shape.
286 return new BSShapeNative(CreatePhysicalNativeShape(pPhysicsScene, pPrim,
287 physShapeInfo.shapeType, (FixedShapeKey)physShapeInfo.shapeKey) );
288 }
289
160 // Make this reference to the physical shape go away since native shapes are not shared. 290 // Make this reference to the physical shape go away since native shapes are not shared.
161 public override void Dereference(BSScene physicsScene) 291 public override void Dereference(BSScene physicsScene)
162 { 292 {
163 // Native shapes are not tracked and are released immediately 293 // Native shapes are not tracked and are released immediately
164 if (physShapeInfo.HasPhysicalShape) 294 lock (physShapeInfo)
165 { 295 {
166 physicsScene.DetailLog("{0},BSShapeNative.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this); 296 if (physShapeInfo.HasPhysicalShape)
167 physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo); 297 {
298 physicsScene.DetailLog("{0},BSShapeNative.Dereference,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
299 physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
300 }
301 physShapeInfo.Clear();
302 // Garbage collection will free up this instance.
168 } 303 }
169 physShapeInfo.Clear();
170 // Garbage collection will free up this instance.
171 } 304 }
172 305
173 private static BulletShape CreatePhysicalNativeShape(BSScene physicsScene, BSPhysObject prim, 306 private static BulletShape CreatePhysicalNativeShape(BSScene physicsScene, BSPhysObject prim,
@@ -197,7 +330,7 @@ public class BSShapeNative : BSShape
197 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", 330 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
198 LogHeader, prim.LocalID, shapeType); 331 LogHeader, prim.LocalID, shapeType);
199 } 332 }
200 newShape.type = shapeType; 333 newShape.shapeType = shapeType;
201 newShape.isNativeShape = true; 334 newShape.isNativeShape = true;
202 newShape.shapeKey = (UInt64)shapeKey; 335 newShape.shapeKey = (UInt64)shapeKey;
203 return newShape; 336 return newShape;
@@ -209,7 +342,7 @@ public class BSShapeNative : BSShape
209public class BSShapeMesh : BSShape 342public class BSShapeMesh : BSShape
210{ 343{
211 private static string LogHeader = "[BULLETSIM SHAPE MESH]"; 344 private static string LogHeader = "[BULLETSIM SHAPE MESH]";
212 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>(); 345 public static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>();
213 346
214 public BSShapeMesh(BulletShape pShape) : base(pShape) 347 public BSShapeMesh(BulletShape pShape) : base(pShape)
215 { 348 {
@@ -217,12 +350,9 @@ public class BSShapeMesh : BSShape
217 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 350 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
218 { 351 {
219 float lod; 352 float lod;
220 System.UInt64 newMeshKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); 353 System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
221 354
222 physicsScene.DetailLog("{0},BSShapeMesh,create,oldKey={1},newKey={2},size={3},lod={4}", 355 BSShapeMesh retMesh = null;
223 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
224
225 BSShapeMesh retMesh;
226 lock (Meshes) 356 lock (Meshes)
227 { 357 {
228 if (Meshes.TryGetValue(newMeshKey, out retMesh)) 358 if (Meshes.TryGetValue(newMeshKey, out retMesh))
@@ -232,39 +362,78 @@ public class BSShapeMesh : BSShape
232 } 362 }
233 else 363 else
234 { 364 {
365 retMesh = new BSShapeMesh(new BulletShape());
235 // An instance of this mesh has not been created. Build and remember same. 366 // An instance of this mesh has not been created. Build and remember same.
236 BulletShape newShape = CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod); 367 BulletShape newShape = retMesh.CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
237 // Take evasive action if the mesh was not constructed.
238 newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
239 368
240 retMesh = new BSShapeMesh(newShape); 369 // Check to see if mesh was created (might require an asset).
370 newShape = VerifyMeshCreated(physicsScene, newShape, prim);
371 if (!newShape.isNativeShape)
372 {
373 // If a mesh was what was created, remember the built shape for later sharing.
374 Meshes.Add(newMeshKey, retMesh);
375 }
241 376
242 Meshes.Add(newMeshKey, retMesh); 377 retMesh.physShapeInfo = newShape;
243 } 378 }
244 } 379 }
380 physicsScene.DetailLog("{0},BSShapeMesh,getReference,mesh={1},size={2},lod={3}", prim.LocalID, retMesh, prim.Size, lod);
245 return retMesh; 381 return retMesh;
246 } 382 }
383 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
384 {
385 // Another reference to this shape is just counted.
386 IncrementReference();
387 return this;
388 }
247 public override void Dereference(BSScene physicsScene) 389 public override void Dereference(BSScene physicsScene)
248 { 390 {
249 lock (Meshes) 391 lock (Meshes)
250 { 392 {
251 this.DecrementReference(); 393 this.DecrementReference();
394 physicsScene.DetailLog("{0},BSShapeMesh.Dereference,shape={1}", BSScene.DetailLogZero, this);
252 // TODO: schedule aging and destruction of unused meshes. 395 // TODO: schedule aging and destruction of unused meshes.
253 } 396 }
254 } 397 }
398 // Loop through all the known meshes and return the description based on the physical address.
399 public static bool TryGetMeshByPtr(BulletShape pShape, out BSShapeMesh outMesh)
400 {
401 bool ret = false;
402 BSShapeMesh foundDesc = null;
403 lock (Meshes)
404 {
405 foreach (BSShapeMesh sm in Meshes.Values)
406 {
407 if (sm.physShapeInfo.ReferenceSame(pShape))
408 {
409 foundDesc = sm;
410 ret = true;
411 break;
412 }
255 413
256 private static BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey, 414 }
415 }
416 outMesh = foundDesc;
417 return ret;
418 }
419 private BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
257 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 420 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
258 { 421 {
259 BulletShape newShape = null; 422 BulletShape newShape = new BulletShape();
260 423
261 IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, 424 IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
262 false, // say it is not physical so a bounding box is not built 425 false, // say it is not physical so a bounding box is not built
263 false // do not cache the mesh and do not use previously built versions 426 false // do not cache the mesh and do not use previously built versions
264 ); 427 );
265 428
266 if (meshData != null) 429 if (meshData != null)
267 { 430 {
431 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
432 {
433 // Release the fetched asset data once it has been used.
434 pbs.SculptData = new byte[0];
435 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
436 }
268 437
269 int[] indices = meshData.getIndexListAsInt(); 438 int[] indices = meshData.getIndexListAsInt();
270 int realIndicesIndex = indices.Length; 439 int realIndicesIndex = indices.Length;
@@ -302,8 +471,8 @@ public class BSShapeMesh : BSShape
302 } 471 }
303 } 472 }
304 } 473 }
305 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}", 474 physicsScene.DetailLog("{0},BSShapeMesh.CreatePhysicalMesh,key={1},origTri={2},realTri={3},numVerts={4}",
306 BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3); 475 BSScene.DetailLogZero, newMeshKey.ToString("X"), indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
307 476
308 if (realIndicesIndex != 0) 477 if (realIndicesIndex != 0)
309 { 478 {
@@ -326,17 +495,239 @@ public class BSShapeMesh : BSShape
326public class BSShapeHull : BSShape 495public class BSShapeHull : BSShape
327{ 496{
328 private static string LogHeader = "[BULLETSIM SHAPE HULL]"; 497 private static string LogHeader = "[BULLETSIM SHAPE HULL]";
329 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>(); 498 public static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
330 499
331 public BSShapeHull(BulletShape pShape) : base(pShape) 500 public BSShapeHull(BulletShape pShape) : base(pShape)
332 { 501 {
333 } 502 }
334 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 503 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
335 { 504 {
336 return new BSShapeNull(); 505 float lod;
506 System.UInt64 newHullKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
507
508 BSShapeHull retHull = null;
509 lock (Hulls)
510 {
511 if (Hulls.TryGetValue(newHullKey, out retHull))
512 {
513 // The mesh has already been created. Return a new reference to same.
514 retHull.IncrementReference();
515 }
516 else
517 {
518 retHull = new BSShapeHull(new BulletShape());
519 // An instance of this mesh has not been created. Build and remember same.
520 BulletShape newShape = retHull.CreatePhysicalHull(physicsScene, prim, newHullKey, prim.BaseShape, prim.Size, lod);
521
522 // Check to see if hull was created (might require an asset).
523 newShape = VerifyMeshCreated(physicsScene, newShape, prim);
524 if (!newShape.isNativeShape)
525 {
526 // If a mesh was what was created, remember the built shape for later sharing.
527 Hulls.Add(newHullKey, retHull);
528 }
529 retHull.physShapeInfo = newShape;
530 }
531 }
532 physicsScene.DetailLog("{0},BSShapeHull,getReference,hull={1},size={2},lod={3}", prim.LocalID, retHull, prim.Size, lod);
533 return retHull;
534 }
535 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
536 {
537 // Another reference to this shape is just counted.
538 IncrementReference();
539 return this;
337 } 540 }
338 public override void Dereference(BSScene physicsScene) 541 public override void Dereference(BSScene physicsScene)
339 { 542 {
543 lock (Hulls)
544 {
545 this.DecrementReference();
546 physicsScene.DetailLog("{0},BSShapeHull.Dereference,shape={1}", BSScene.DetailLogZero, this);
547 // TODO: schedule aging and destruction of unused meshes.
548 }
549 }
550 List<ConvexResult> m_hulls;
551 private BulletShape CreatePhysicalHull(BSScene physicsScene, BSPhysObject prim, System.UInt64 newHullKey,
552 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
553 {
554 BulletShape newShape = new BulletShape();
555 IntPtr hullPtr = IntPtr.Zero;
556
557 if (BSParam.ShouldUseBulletHACD)
558 {
559 // Build the hull shape from an existing mesh shape.
560 // The mesh should have already been created in Bullet.
561 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID);
562 BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim);
563
564 if (meshShape.physShapeInfo.HasPhysicalShape)
565 {
566 HACDParams parms;
567 parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
568 parms.minClusters = BSParam.BHullMinClusters;
569 parms.compacityWeight = BSParam.BHullCompacityWeight;
570 parms.volumeWeight = BSParam.BHullVolumeWeight;
571 parms.concavity = BSParam.BHullConcavity;
572 parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
573 parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
574 parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
575 parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
576
577 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
578 newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
579 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
580
581 // Now done with the mesh shape.
582 meshShape.Dereference(physicsScene);
583 }
584 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
585 }
586 if (!newShape.HasPhysicalShape)
587 {
588 // Build a new hull in the physical world using the C# HACD algorigthm.
589 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
590 IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
591 if (meshData != null)
592 {
593 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
594 {
595 // Release the fetched asset data once it has been used.
596 pbs.SculptData = new byte[0];
597 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
598 }
599
600 int[] indices = meshData.getIndexListAsInt();
601 List<OMV.Vector3> vertices = meshData.getVertexList();
602
603 //format conversion from IMesh format to DecompDesc format
604 List<int> convIndices = new List<int>();
605 List<float3> convVertices = new List<float3>();
606 for (int ii = 0; ii < indices.GetLength(0); ii++)
607 {
608 convIndices.Add(indices[ii]);
609 }
610 foreach (OMV.Vector3 vv in vertices)
611 {
612 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
613 }
614
615 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
616 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
617 {
618 // Simple primitive shapes we know are convex so they are better implemented with
619 // fewer hulls.
620 // Check for simple shape (prim without cuts) and reduce split parameter if so.
621 if (BSShapeCollection.PrimHasNoCuts(pbs))
622 {
623 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
624 }
625 }
626
627 // setup and do convex hull conversion
628 m_hulls = new List<ConvexResult>();
629 DecompDesc dcomp = new DecompDesc();
630 dcomp.mIndices = convIndices;
631 dcomp.mVertices = convVertices;
632 dcomp.mDepth = maxDepthSplit;
633 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
634 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
635 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
636 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
637 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
638 // create the hull into the _hulls variable
639 convexBuilder.process(dcomp);
640
641 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
642 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
643
644 // Convert the vertices and indices for passing to unmanaged.
645 // The hull information is passed as a large floating point array.
646 // The format is:
647 // convHulls[0] = number of hulls
648 // convHulls[1] = number of vertices in first hull
649 // convHulls[2] = hull centroid X coordinate
650 // convHulls[3] = hull centroid Y coordinate
651 // convHulls[4] = hull centroid Z coordinate
652 // convHulls[5] = first hull vertex X
653 // convHulls[6] = first hull vertex Y
654 // convHulls[7] = first hull vertex Z
655 // convHulls[8] = second hull vertex X
656 // ...
657 // convHulls[n] = number of vertices in second hull
658 // convHulls[n+1] = second hull centroid X coordinate
659 // ...
660 //
661 // TODO: is is very inefficient. Someday change the convex hull generator to return
662 // data structures that do not need to be converted in order to pass to Bullet.
663 // And maybe put the values directly into pinned memory rather than marshaling.
664 int hullCount = m_hulls.Count;
665 int totalVertices = 1; // include one for the count of the hulls
666 foreach (ConvexResult cr in m_hulls)
667 {
668 totalVertices += 4; // add four for the vertex count and centroid
669 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
670 }
671 float[] convHulls = new float[totalVertices];
672
673 convHulls[0] = (float)hullCount;
674 int jj = 1;
675 foreach (ConvexResult cr in m_hulls)
676 {
677 // copy vertices for index access
678 float3[] verts = new float3[cr.HullVertices.Count];
679 int kk = 0;
680 foreach (float3 ff in cr.HullVertices)
681 {
682 verts[kk++] = ff;
683 }
684
685 // add to the array one hull's worth of data
686 convHulls[jj++] = cr.HullIndices.Count;
687 convHulls[jj++] = 0f; // centroid x,y,z
688 convHulls[jj++] = 0f;
689 convHulls[jj++] = 0f;
690 foreach (int ind in cr.HullIndices)
691 {
692 convHulls[jj++] = verts[ind].x;
693 convHulls[jj++] = verts[ind].y;
694 convHulls[jj++] = verts[ind].z;
695 }
696 }
697 // create the hull data structure in Bullet
698 newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
699 }
700 newShape.shapeKey = newHullKey;
701 }
702 return newShape;
703 }
704 // Callback from convex hull creater with a newly created hull.
705 // Just add it to our collection of hulls for this shape.
706 private void HullReturn(ConvexResult result)
707 {
708 m_hulls.Add(result);
709 return;
710 }
711 // Loop through all the known hulls and return the description based on the physical address.
712 public static bool TryGetHullByPtr(BulletShape pShape, out BSShapeHull outHull)
713 {
714 bool ret = false;
715 BSShapeHull foundDesc = null;
716 lock (Hulls)
717 {
718 foreach (BSShapeHull sh in Hulls.Values)
719 {
720 if (sh.physShapeInfo.ReferenceSame(pShape))
721 {
722 foundDesc = sh;
723 ret = true;
724 break;
725 }
726
727 }
728 }
729 outHull = foundDesc;
730 return ret;
340 } 731 }
341} 732}
342 733
@@ -344,14 +735,169 @@ public class BSShapeHull : BSShape
344public class BSShapeCompound : BSShape 735public class BSShapeCompound : BSShape
345{ 736{
346 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; 737 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
347 public BSShapeCompound() : base() 738 public BSShapeCompound(BulletShape pShape) : base(pShape)
348 { 739 {
349 } 740 }
350 public static BSShape GetReference(BSPhysObject prim) 741 public static BSShape GetReference(BSScene physicsScene)
351 { 742 {
352 return new BSShapeNull(); 743 // Base compound shapes are not shared so this returns a raw shape.
744 // A built compound shape can be reused in linksets.
745 return new BSShapeCompound(CreatePhysicalCompoundShape(physicsScene));
746 }
747 public override BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
748 {
749 // Calling this reference means we want another handle to an existing compound shape
750 // (usually linksets) so return this copy.
751 IncrementReference();
752 return this;
753 }
754 // Dereferencing a compound shape releases the hold on all the child shapes.
755 public override void Dereference(BSScene physicsScene)
756 {
757 lock (physShapeInfo)
758 {
759 this.DecrementReference();
760 physicsScene.DetailLog("{0},BSShapeCompound.Dereference,shape={1}", BSScene.DetailLogZero, this);
761 if (referenceCount <= 0)
762 {
763 if (!physicsScene.PE.IsCompound(physShapeInfo))
764 {
765 // Failed the sanity check!!
766 physicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
767 LogHeader, physShapeInfo.shapeType, physShapeInfo.AddrString);
768 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
769 BSScene.DetailLogZero, physShapeInfo.shapeType, physShapeInfo.AddrString);
770 return;
771 }
772
773 int numChildren = physicsScene.PE.GetNumberOfCompoundChildren(physShapeInfo);
774 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}",
775 BSScene.DetailLogZero, physShapeInfo, numChildren);
776
777 // Loop through all the children dereferencing each.
778 for (int ii = numChildren - 1; ii >= 0; ii--)
779 {
780 BulletShape childShape = physicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(physShapeInfo, ii);
781 DereferenceAnonCollisionShape(physicsScene, childShape);
782 }
783 physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
784 }
785 }
786 }
787 private static BulletShape CreatePhysicalCompoundShape(BSScene physicsScene)
788 {
789 BulletShape cShape = physicsScene.PE.CreateCompoundShape(physicsScene.World, false);
790 return cShape;
791 }
792 // Sometimes we have a pointer to a collision shape but don't know what type it is.
793 // Figure out type and call the correct dereference routine.
794 // Called at taint-time.
795 private void DereferenceAnonCollisionShape(BSScene physicsScene, BulletShape pShape)
796 {
797 BSShapeMesh meshDesc;
798 if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc))
799 {
800 meshDesc.Dereference(physicsScene);
801 }
802 else
803 {
804 BSShapeHull hullDesc;
805 if (BSShapeHull.TryGetHullByPtr(pShape, out hullDesc))
806 {
807 hullDesc.Dereference(physicsScene);
808 }
809 else
810 {
811 if (physicsScene.PE.IsCompound(pShape))
812 {
813 BSShapeCompound recursiveCompound = new BSShapeCompound(pShape);
814 recursiveCompound.Dereference(physicsScene);
815 }
816 else
817 {
818 if (physicsScene.PE.IsNativeShape(pShape))
819 {
820 BSShapeNative nativeShape = new BSShapeNative(pShape);
821 nativeShape.Dereference(physicsScene);
822 }
823 }
824 }
825 }
826 }
827}
828
829// ============================================================================================================
830public class BSShapeConvexHull : BSShape
831{
832 private static string LogHeader = "[BULLETSIM SHAPE CONVEX HULL]";
833 public static Dictionary<System.UInt64, BSShapeConvexHull> ConvexHulls = new Dictionary<System.UInt64, BSShapeConvexHull>();
834
835 public BSShapeConvexHull(BulletShape pShape) : base(pShape)
836 {
837 }
838 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
839 {
840 float lod;
841 System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
842
843 physicsScene.DetailLog("{0},BSShapeMesh,getReference,newKey={1},size={2},lod={3}",
844 prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);
845
846 BSShapeConvexHull retConvexHull = null;
847 lock (ConvexHulls)
848 {
849 if (ConvexHulls.TryGetValue(newMeshKey, out retConvexHull))
850 {
851 // The mesh has already been created. Return a new reference to same.
852 retConvexHull.IncrementReference();
853 }
854 else
855 {
856 retConvexHull = new BSShapeConvexHull(new BulletShape());
857 BulletShape convexShape = null;
858
859 // Get a handle to a mesh to build the hull from
860 BSShape baseMesh = BSShapeMesh.GetReference(physicsScene, false /* forceRebuild */, prim);
861 if (baseMesh.physShapeInfo.isNativeShape)
862 {
863 // We get here if the mesh was not creatable. Could be waiting for an asset from the disk.
864 // In the short term, we return the native shape and a later ForceBodyShapeRebuild should
865 // get back to this code with a buildable mesh.
866 // TODO: not sure the temp native shape is freed when the mesh is rebuilt. When does this get freed?
867 convexShape = baseMesh.physShapeInfo;
868 }
869 else
870 {
871 convexShape = physicsScene.PE.BuildConvexHullShapeFromMesh(physicsScene.World, baseMesh.physShapeInfo);
872 convexShape.shapeKey = newMeshKey;
873 ConvexHulls.Add(convexShape.shapeKey, retConvexHull);
874 }
875
876 // Done with the base mesh
877 baseMesh.Dereference(physicsScene);
878
879 retConvexHull.physShapeInfo = convexShape;
880 }
881 }
882 return retConvexHull;
883 }
884 public override BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
885 {
886 // Calling this reference means we want another handle to an existing shape
887 // (usually linksets) so return this copy.
888 IncrementReference();
889 return this;
890 }
891 // Dereferencing a compound shape releases the hold on all the child shapes.
892 public override void Dereference(BSScene physicsScene)
893 {
894 lock (ConvexHulls)
895 {
896 this.DecrementReference();
897 physicsScene.DetailLog("{0},BSShapeConvexHull.Dereference,shape={1}", BSScene.DetailLogZero, this);
898 // TODO: schedule aging and destruction of unused meshes.
899 }
353 } 900 }
354 public override void Dereference(BSScene physicsScene) { }
355} 901}
356 902
357// ============================================================================================================ 903// ============================================================================================================
@@ -361,8 +907,12 @@ public class BSShapeAvatar : BSShape
361 public BSShapeAvatar() : base() 907 public BSShapeAvatar() : base()
362 { 908 {
363 } 909 }
364 public static BSShape GetReference(BSPhysObject prim) 910 public static BSShape GetReference(BSPhysObject prim)
365 { 911 {
912 return new BSShapeNull();
913 }
914 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
915 {
366 return new BSShapeNull(); 916 return new BSShapeNull();
367 } 917 }
368 public override void Dereference(BSScene physicsScene) { } 918 public override void Dereference(BSScene physicsScene) { }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
index e4fecc3..c7deb4e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
@@ -68,7 +68,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
68 68
69 // This minCoords and maxCoords passed in give the size of the terrain (min and max Z 69 // This minCoords and maxCoords passed in give the size of the terrain (min and max Z
70 // are the high and low points of the heightmap). 70 // are the high and low points of the heightmap).
71 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, 71 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
72 Vector3 minCoords, Vector3 maxCoords) 72 Vector3 minCoords, Vector3 maxCoords)
73 : base(physicsScene, regionBase, id) 73 : base(physicsScene, regionBase, id)
74 { 74 {
@@ -92,7 +92,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
92 private void BuildHeightmapTerrain() 92 private void BuildHeightmapTerrain()
93 { 93 {
94 // Create the terrain shape from the mapInfo 94 // Create the terrain shape from the mapInfo
95 m_mapInfo.terrainShape = PhysicsScene.PE.CreateTerrainShape( m_mapInfo.ID, 95 m_mapInfo.terrainShape = m_physicsScene.PE.CreateTerrainShape( m_mapInfo.ID,
96 new Vector3(m_mapInfo.sizeX, m_mapInfo.sizeY, 0), m_mapInfo.minZ, m_mapInfo.maxZ, 96 new Vector3(m_mapInfo.sizeX, m_mapInfo.sizeY, 0), m_mapInfo.minZ, m_mapInfo.maxZ,
97 m_mapInfo.heightMap, 1f, BSParam.TerrainCollisionMargin); 97 m_mapInfo.heightMap, 1f, BSParam.TerrainCollisionMargin);
98 98
@@ -103,26 +103,26 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
103 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); 103 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f);
104 centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f); 104 centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f);
105 105
106 m_mapInfo.terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_mapInfo.terrainShape, 106 m_mapInfo.terrainBody = m_physicsScene.PE.CreateBodyWithDefaultMotionState(m_mapInfo.terrainShape,
107 m_mapInfo.ID, centerPos, Quaternion.Identity); 107 m_mapInfo.ID, centerPos, Quaternion.Identity);
108 108
109 // Set current terrain attributes 109 // Set current terrain attributes
110 PhysicsScene.PE.SetFriction(m_mapInfo.terrainBody, BSParam.TerrainFriction); 110 m_physicsScene.PE.SetFriction(m_mapInfo.terrainBody, BSParam.TerrainFriction);
111 PhysicsScene.PE.SetHitFraction(m_mapInfo.terrainBody, BSParam.TerrainHitFraction); 111 m_physicsScene.PE.SetHitFraction(m_mapInfo.terrainBody, BSParam.TerrainHitFraction);
112 PhysicsScene.PE.SetRestitution(m_mapInfo.terrainBody, BSParam.TerrainRestitution); 112 m_physicsScene.PE.SetRestitution(m_mapInfo.terrainBody, BSParam.TerrainRestitution);
113 PhysicsScene.PE.SetCollisionFlags(m_mapInfo.terrainBody, CollisionFlags.CF_STATIC_OBJECT); 113 m_physicsScene.PE.SetCollisionFlags(m_mapInfo.terrainBody, CollisionFlags.CF_STATIC_OBJECT);
114 114
115 // Return the new terrain to the world of physical objects 115 // Return the new terrain to the world of physical objects
116 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_mapInfo.terrainBody); 116 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_mapInfo.terrainBody);
117 117
118 // redo its bounding box now that it is in the world 118 // redo its bounding box now that it is in the world
119 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_mapInfo.terrainBody); 119 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_mapInfo.terrainBody);
120 120
121 m_mapInfo.terrainBody.collisionType = CollisionType.Terrain; 121 m_mapInfo.terrainBody.collisionType = CollisionType.Terrain;
122 m_mapInfo.terrainBody.ApplyCollisionMask(PhysicsScene); 122 m_mapInfo.terrainBody.ApplyCollisionMask(m_physicsScene);
123 123
124 // Make it so the terrain will not move or be considered for movement. 124 // Make it so the terrain will not move or be considered for movement.
125 PhysicsScene.PE.ForceActivationState(m_mapInfo.terrainBody, ActivationState.DISABLE_SIMULATION); 125 m_physicsScene.PE.ForceActivationState(m_mapInfo.terrainBody, ActivationState.DISABLE_SIMULATION);
126 126
127 return; 127 return;
128 } 128 }
@@ -134,9 +134,9 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
134 { 134 {
135 if (m_mapInfo.terrainBody.HasPhysicalBody) 135 if (m_mapInfo.terrainBody.HasPhysicalBody)
136 { 136 {
137 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_mapInfo.terrainBody); 137 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_mapInfo.terrainBody);
138 // Frees both the body and the shape. 138 // Frees both the body and the shape.
139 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_mapInfo.terrainBody); 139 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_mapInfo.terrainBody);
140 } 140 }
141 } 141 }
142 m_mapInfo = null; 142 m_mapInfo = null;
@@ -155,7 +155,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
155 catch 155 catch
156 { 156 {
157 // Sometimes they give us wonky values of X and Y. Give a warning and return something. 157 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
158 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", 158 m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
159 LogHeader, m_mapInfo.terrainRegionBase, pos); 159 LogHeader, m_mapInfo.terrainRegionBase, pos);
160 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; 160 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
161 } 161 }
@@ -165,7 +165,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
165 // The passed position is relative to the base of the region. 165 // The passed position is relative to the base of the region.
166 public override float GetWaterLevelAtXYZ(Vector3 pos) 166 public override float GetWaterLevelAtXYZ(Vector3 pos)
167 { 167 {
168 return PhysicsScene.SimpleWaterLevel; 168 return m_physicsScene.SimpleWaterLevel;
169 } 169 }
170} 170}
171} 171}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 5240ad8..c4807c4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -50,14 +50,14 @@ public abstract class BSTerrainPhys : IDisposable
50 Mesh = 1 50 Mesh = 1
51 } 51 }
52 52
53 public BSScene PhysicsScene { get; private set; } 53 protected BSScene m_physicsScene { get; private set; }
54 // Base of the region in world coordinates. Coordinates inside the region are relative to this. 54 // Base of the region in world coordinates. Coordinates inside the region are relative to this.
55 public Vector3 TerrainBase { get; private set; } 55 public Vector3 TerrainBase { get; private set; }
56 public uint ID { get; private set; } 56 public uint ID { get; private set; }
57 57
58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id) 58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id)
59 { 59 {
60 PhysicsScene = physicsScene; 60 m_physicsScene = physicsScene;
61 TerrainBase = regionBase; 61 TerrainBase = regionBase;
62 ID = id; 62 ID = id;
63 } 63 }
@@ -86,7 +86,7 @@ public sealed class BSTerrainManager : IDisposable
86 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 86 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
87 87
88 // The scene that I am part of 88 // The scene that I am part of
89 private BSScene PhysicsScene { get; set; } 89 private BSScene m_physicsScene { get; set; }
90 90
91 // The ground plane created to keep thing from falling to infinity. 91 // The ground plane created to keep thing from falling to infinity.
92 private BulletBody m_groundPlane; 92 private BulletBody m_groundPlane;
@@ -113,7 +113,7 @@ public sealed class BSTerrainManager : IDisposable
113 113
114 public BSTerrainManager(BSScene physicsScene) 114 public BSTerrainManager(BSScene physicsScene)
115 { 115 {
116 PhysicsScene = physicsScene; 116 m_physicsScene = physicsScene;
117 m_terrains = new Dictionary<Vector3,BSTerrainPhys>(); 117 m_terrains = new Dictionary<Vector3,BSTerrainPhys>();
118 118
119 // Assume one region of default size 119 // Assume one region of default size
@@ -132,21 +132,21 @@ public sealed class BSTerrainManager : IDisposable
132 // safe to call Bullet in real time. We hope no one is moving prims around yet. 132 // safe to call Bullet in real time. We hope no one is moving prims around yet.
133 public void CreateInitialGroundPlaneAndTerrain() 133 public void CreateInitialGroundPlaneAndTerrain()
134 { 134 {
135 DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName); 135 DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, m_physicsScene.RegionName);
136 // The ground plane is here to catch things that are trying to drop to negative infinity 136 // The ground plane is here to catch things that are trying to drop to negative infinity
137 BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin); 137 BulletShape groundPlaneShape = m_physicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin);
138 m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape, 138 m_groundPlane = m_physicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape,
139 BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity); 139 BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity);
140 140
141 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_groundPlane); 141 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_groundPlane);
142 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_groundPlane); 142 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_groundPlane);
143 // Ground plane does not move 143 // Ground plane does not move
144 PhysicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION); 144 m_physicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION);
145 // Everything collides with the ground plane. 145 // Everything collides with the ground plane.
146 m_groundPlane.collisionType = CollisionType.Groundplane; 146 m_groundPlane.collisionType = CollisionType.Groundplane;
147 m_groundPlane.ApplyCollisionMask(PhysicsScene); 147 m_groundPlane.ApplyCollisionMask(m_physicsScene);
148 148
149 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); 149 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(m_physicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
150 lock (m_terrains) 150 lock (m_terrains)
151 { 151 {
152 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. 152 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
@@ -157,12 +157,12 @@ public sealed class BSTerrainManager : IDisposable
157 // Release all the terrain structures we might have allocated 157 // Release all the terrain structures we might have allocated
158 public void ReleaseGroundPlaneAndTerrain() 158 public void ReleaseGroundPlaneAndTerrain()
159 { 159 {
160 DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName); 160 DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, m_physicsScene.RegionName);
161 if (m_groundPlane.HasPhysicalBody) 161 if (m_groundPlane.HasPhysicalBody)
162 { 162 {
163 if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane)) 163 if (m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_groundPlane))
164 { 164 {
165 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_groundPlane); 165 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_groundPlane);
166 } 166 }
167 m_groundPlane.Clear(); 167 m_groundPlane.Clear();
168 } 168 }
@@ -188,7 +188,7 @@ public sealed class BSTerrainManager : IDisposable
188 float[] localHeightMap = heightMap; 188 float[] localHeightMap = heightMap;
189 // If there are multiple requests for changes to the same terrain between ticks, 189 // If there are multiple requests for changes to the same terrain between ticks,
190 // only do that last one. 190 // only do that last one.
191 PhysicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate() 191 m_physicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate()
192 { 192 {
193 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) 193 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null)
194 { 194 {
@@ -219,7 +219,7 @@ public sealed class BSTerrainManager : IDisposable
219 private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) 219 private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
220 { 220 {
221 // Since we are called by another region's thread, the action must be rescheduled onto our processing thread. 221 // Since we are called by another region's thread, the action must be rescheduled onto our processing thread.
222 PhysicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + minCoords.ToString(), id, delegate() 222 m_physicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + minCoords.ToString(), id, delegate()
223 { 223 {
224 UpdateTerrain(id, heightMap, minCoords, maxCoords); 224 UpdateTerrain(id, heightMap, minCoords, maxCoords);
225 }); 225 });
@@ -318,26 +318,26 @@ public sealed class BSTerrainManager : IDisposable
318 // TODO: redo terrain implementation selection to allow other base types than heightMap. 318 // TODO: redo terrain implementation selection to allow other base types than heightMap.
319 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) 319 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
320 { 320 {
321 PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", 321 m_physicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}",
322 LogHeader, PhysicsScene.RegionName, terrainRegionBase, 322 LogHeader, m_physicsScene.RegionName, terrainRegionBase,
323 (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation); 323 (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation);
324 BSTerrainPhys newTerrainPhys = null; 324 BSTerrainPhys newTerrainPhys = null;
325 switch ((int)BSParam.TerrainImplementation) 325 switch ((int)BSParam.TerrainImplementation)
326 { 326 {
327 case (int)BSTerrainPhys.TerrainImplementation.Heightmap: 327 case (int)BSTerrainPhys.TerrainImplementation.Heightmap:
328 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, 328 newTerrainPhys = new BSTerrainHeightmap(m_physicsScene, terrainRegionBase, id,
329 heightMap, minCoords, maxCoords); 329 heightMap, minCoords, maxCoords);
330 break; 330 break;
331 case (int)BSTerrainPhys.TerrainImplementation.Mesh: 331 case (int)BSTerrainPhys.TerrainImplementation.Mesh:
332 newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, 332 newTerrainPhys = new BSTerrainMesh(m_physicsScene, terrainRegionBase, id,
333 heightMap, minCoords, maxCoords); 333 heightMap, minCoords, maxCoords);
334 break; 334 break;
335 default: 335 default:
336 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", 336 m_physicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}",
337 LogHeader, 337 LogHeader,
338 (int)BSParam.TerrainImplementation, 338 (int)BSParam.TerrainImplementation,
339 BSParam.TerrainImplementation, 339 BSParam.TerrainImplementation,
340 PhysicsScene.RegionName, terrainRegionBase); 340 m_physicsScene.RegionName, terrainRegionBase);
341 break; 341 break;
342 } 342 }
343 return newTerrainPhys; 343 return newTerrainPhys;
@@ -429,8 +429,8 @@ public sealed class BSTerrainManager : IDisposable
429 } 429 }
430 else 430 else
431 { 431 {
432 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", 432 m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
433 LogHeader, PhysicsScene.RegionName, tX, tY); 433 LogHeader, m_physicsScene.RegionName, tX, tY);
434 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}", 434 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}",
435 BSScene.DetailLogZero, pos, terrainBaseXYZ); 435 BSScene.DetailLogZero, pos, terrainBaseXYZ);
436 } 436 }
@@ -451,8 +451,8 @@ public sealed class BSTerrainManager : IDisposable
451 } 451 }
452 else 452 else
453 { 453 {
454 PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}", 454 m_physicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}",
455 LogHeader, PhysicsScene.RegionName, pos, terrainBaseXYZ, ret); 455 LogHeader, m_physicsScene.RegionName, pos, terrainBaseXYZ, ret);
456 } 456 }
457 return ret; 457 return ret;
458 } 458 }
@@ -564,7 +564,7 @@ public sealed class BSTerrainManager : IDisposable
564 564
565 private void DetailLog(string msg, params Object[] args) 565 private void DetailLog(string msg, params Object[] args)
566 { 566 {
567 PhysicsScene.PhysicsLogging.Write(msg, args); 567 m_physicsScene.PhysicsLogging.Write(msg, args);
568 } 568 }
569} 569}
570} 570}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
index 2ce1513..e4ca098 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
@@ -51,7 +51,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
51 BulletShape m_terrainShape; 51 BulletShape m_terrainShape;
52 BulletBody m_terrainBody; 52 BulletBody m_terrainBody;
53 53
54 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) 54 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
55 : base(physicsScene, regionBase, id) 55 : base(physicsScene, regionBase, id)
56 { 56 {
57 } 57 }
@@ -62,7 +62,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
62 } 62 }
63 63
64 // Create terrain mesh from a heightmap. 64 // Create terrain mesh from a heightmap.
65 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, 65 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
66 Vector3 minCoords, Vector3 maxCoords) 66 Vector3 minCoords, Vector3 maxCoords)
67 : base(physicsScene, regionBase, id) 67 : base(physicsScene, regionBase, id)
68 { 68 {
@@ -80,7 +80,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
80 if (BSParam.TerrainMeshMagnification == 1) 80 if (BSParam.TerrainMeshMagnification == 1)
81 { 81 {
82 // If a magnification of one, use the old routine that is tried and true. 82 // If a magnification of one, use the old routine that is tried and true.
83 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, 83 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh(m_physicsScene,
84 initialMap, m_sizeX, m_sizeY, // input size 84 initialMap, m_sizeX, m_sizeY, // input size
85 Vector3.Zero, // base for mesh 85 Vector3.Zero, // base for mesh
86 out indicesCount, out indices, out verticesCount, out vertices); 86 out indicesCount, out indices, out verticesCount, out vertices);
@@ -88,7 +88,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
88 else 88 else
89 { 89 {
90 // Other magnifications use the newer routine 90 // Other magnifications use the newer routine
91 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh2(PhysicsScene, 91 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh2(m_physicsScene,
92 initialMap, m_sizeX, m_sizeY, // input size 92 initialMap, m_sizeX, m_sizeY, // input size
93 BSParam.TerrainMeshMagnification, 93 BSParam.TerrainMeshMagnification,
94 physicsScene.TerrainManager.DefaultRegionSize, 94 physicsScene.TerrainManager.DefaultRegionSize,
@@ -98,21 +98,21 @@ public sealed class BSTerrainMesh : BSTerrainPhys
98 if (!meshCreationSuccess) 98 if (!meshCreationSuccess)
99 { 99 {
100 // DISASTER!! 100 // DISASTER!!
101 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap,id={1}", BSScene.DetailLogZero, ID); 101 m_physicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap,id={1}", BSScene.DetailLogZero, ID);
102 PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase); 102 m_physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase);
103 // Something is very messed up and a crash is in our future. 103 // Something is very messed up and a crash is in our future.
104 return; 104 return;
105 } 105 }
106 106
107 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}", 107 m_physicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}",
108 BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length); 108 BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length);
109 109
110 m_terrainShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, indicesCount, indices, verticesCount, vertices); 110 m_terrainShape = m_physicsScene.PE.CreateMeshShape(m_physicsScene.World, indicesCount, indices, verticesCount, vertices);
111 if (!m_terrainShape.HasPhysicalShape) 111 if (!m_terrainShape.HasPhysicalShape)
112 { 112 {
113 // DISASTER!! 113 // DISASTER!!
114 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape,id={1}", BSScene.DetailLogZero, ID); 114 m_physicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape,id={1}", BSScene.DetailLogZero, ID);
115 PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); 115 m_physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
116 // Something is very messed up and a crash is in our future. 116 // Something is very messed up and a crash is in our future.
117 return; 117 return;
118 } 118 }
@@ -120,52 +120,52 @@ public sealed class BSTerrainMesh : BSTerrainPhys
120 Vector3 pos = regionBase; 120 Vector3 pos = regionBase;
121 Quaternion rot = Quaternion.Identity; 121 Quaternion rot = Quaternion.Identity;
122 122
123 m_terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot); 123 m_terrainBody = m_physicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot);
124 if (!m_terrainBody.HasPhysicalBody) 124 if (!m_terrainBody.HasPhysicalBody)
125 { 125 {
126 // DISASTER!! 126 // DISASTER!!
127 PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); 127 m_physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
128 // Something is very messed up and a crash is in our future. 128 // Something is very messed up and a crash is in our future.
129 return; 129 return;
130 } 130 }
131 physicsScene.PE.SetShapeCollisionMargin(m_terrainShape, BSParam.TerrainCollisionMargin); 131 physicsScene.PE.SetShapeCollisionMargin(m_terrainShape, BSParam.TerrainCollisionMargin);
132 132
133 // Set current terrain attributes 133 // Set current terrain attributes
134 PhysicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction); 134 m_physicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction);
135 PhysicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction); 135 m_physicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction);
136 PhysicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution); 136 m_physicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution);
137 PhysicsScene.PE.SetContactProcessingThreshold(m_terrainBody, BSParam.TerrainContactProcessingThreshold); 137 m_physicsScene.PE.SetContactProcessingThreshold(m_terrainBody, BSParam.TerrainContactProcessingThreshold);
138 PhysicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT); 138 m_physicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT);
139 139
140 // Static objects are not very massive. 140 // Static objects are not very massive.
141 PhysicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero); 141 m_physicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero);
142 142
143 // Put the new terrain to the world of physical objects 143 // Put the new terrain to the world of physical objects
144 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_terrainBody); 144 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_terrainBody);
145 145
146 // Redo its bounding box now that it is in the world 146 // Redo its bounding box now that it is in the world
147 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_terrainBody); 147 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_terrainBody);
148 148
149 m_terrainBody.collisionType = CollisionType.Terrain; 149 m_terrainBody.collisionType = CollisionType.Terrain;
150 m_terrainBody.ApplyCollisionMask(PhysicsScene); 150 m_terrainBody.ApplyCollisionMask(m_physicsScene);
151 151
152 if (BSParam.UseSingleSidedMeshes) 152 if (BSParam.UseSingleSidedMeshes)
153 { 153 {
154 PhysicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial,id={1}", BSScene.DetailLogZero, id); 154 m_physicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial,id={1}", BSScene.DetailLogZero, id);
155 PhysicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK); 155 m_physicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
156 } 156 }
157 157
158 // Make it so the terrain will not move or be considered for movement. 158 // Make it so the terrain will not move or be considered for movement.
159 PhysicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION); 159 m_physicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION);
160 } 160 }
161 161
162 public override void Dispose() 162 public override void Dispose()
163 { 163 {
164 if (m_terrainBody.HasPhysicalBody) 164 if (m_terrainBody.HasPhysicalBody)
165 { 165 {
166 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_terrainBody); 166 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_terrainBody);
167 // Frees both the body and the shape. 167 // Frees both the body and the shape.
168 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_terrainBody); 168 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_terrainBody);
169 m_terrainBody.Clear(); 169 m_terrainBody.Clear();
170 m_terrainShape.Clear(); 170 m_terrainShape.Clear();
171 } 171 }
@@ -185,7 +185,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
185 catch 185 catch
186 { 186 {
187 // Sometimes they give us wonky values of X and Y. Give a warning and return something. 187 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
188 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", 188 m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
189 LogHeader, TerrainBase, pos); 189 LogHeader, TerrainBase, pos);
190 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; 190 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
191 } 191 }
@@ -195,7 +195,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
195 // The passed position is relative to the base of the region. 195 // The passed position is relative to the base of the region.
196 public override float GetWaterLevelAtXYZ(Vector3 pos) 196 public override float GetWaterLevelAtXYZ(Vector3 pos)
197 { 197 {
198 return PhysicsScene.SimpleWaterLevel; 198 return m_physicsScene.SimpleWaterLevel;
199 } 199 }
200 200
201 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). 201 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
index 8012d91..d5060e3 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
@@ -104,11 +104,11 @@ public class BulletShape
104{ 104{
105 public BulletShape() 105 public BulletShape()
106 { 106 {
107 type = BSPhysicsShapeType.SHAPE_UNKNOWN; 107 shapeType = BSPhysicsShapeType.SHAPE_UNKNOWN;
108 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; 108 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
109 isNativeShape = false; 109 isNativeShape = false;
110 } 110 }
111 public BSPhysicsShapeType type; 111 public BSPhysicsShapeType shapeType;
112 public System.UInt64 shapeKey; 112 public System.UInt64 shapeKey;
113 public bool isNativeShape; 113 public bool isNativeShape;
114 114
@@ -133,7 +133,7 @@ public class BulletShape
133 buff.Append("<p="); 133 buff.Append("<p=");
134 buff.Append(AddrString); 134 buff.Append(AddrString);
135 buff.Append(",s="); 135 buff.Append(",s=");
136 buff.Append(type.ToString()); 136 buff.Append(shapeType.ToString());
137 buff.Append(",k="); 137 buff.Append(",k=");
138 buff.Append(shapeKey.ToString("X")); 138 buff.Append(shapeKey.ToString("X"));
139 buff.Append(",n="); 139 buff.Append(",n=");
@@ -224,42 +224,42 @@ public static class BulletSimData
224// As mentioned above, don't use the CollisionFilterGroups definitions directly in the code 224// As mentioned above, don't use the CollisionFilterGroups definitions directly in the code
225// but, instead, use references to this dictionary. Finding and debugging 225// but, instead, use references to this dictionary. Finding and debugging
226// collision flag problems will be made easier. 226// collision flag problems will be made easier.
227public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeMasks 227public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeMasks
228 = new Dictionary<CollisionType, CollisionTypeFilterGroup>() 228 = new Dictionary<CollisionType, CollisionTypeFilterGroup>()
229{ 229{
230 { CollisionType.Avatar, 230 { CollisionType.Avatar,
231 new CollisionTypeFilterGroup(CollisionType.Avatar, 231 new CollisionTypeFilterGroup(CollisionType.Avatar,
232 (uint)CollisionFilterGroups.BCharacterGroup, 232 (uint)CollisionFilterGroups.BCharacterGroup,
233 (uint)CollisionFilterGroups.BAllGroup) 233 (uint)CollisionFilterGroups.BAllGroup)
234 }, 234 },
235 { CollisionType.Groundplane, 235 { CollisionType.Groundplane,
236 new CollisionTypeFilterGroup(CollisionType.Groundplane, 236 new CollisionTypeFilterGroup(CollisionType.Groundplane,
237 (uint)CollisionFilterGroups.BGroundPlaneGroup, 237 (uint)CollisionFilterGroups.BGroundPlaneGroup,
238 (uint)CollisionFilterGroups.BAllGroup) 238 (uint)CollisionFilterGroups.BAllGroup)
239 }, 239 },
240 { CollisionType.Terrain, 240 { CollisionType.Terrain,
241 new CollisionTypeFilterGroup(CollisionType.Terrain, 241 new CollisionTypeFilterGroup(CollisionType.Terrain,
242 (uint)CollisionFilterGroups.BTerrainGroup, 242 (uint)CollisionFilterGroups.BTerrainGroup,
243 (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup)) 243 (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup))
244 }, 244 },
245 { CollisionType.Static, 245 { CollisionType.Static,
246 new CollisionTypeFilterGroup(CollisionType.Static, 246 new CollisionTypeFilterGroup(CollisionType.Static,
247 (uint)CollisionFilterGroups.BStaticGroup, 247 (uint)CollisionFilterGroups.BStaticGroup,
248 (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup)) 248 (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
249 }, 249 },
250 { CollisionType.Dynamic, 250 { CollisionType.Dynamic,
251 new CollisionTypeFilterGroup(CollisionType.Dynamic, 251 new CollisionTypeFilterGroup(CollisionType.Dynamic,
252 (uint)CollisionFilterGroups.BSolidGroup, 252 (uint)CollisionFilterGroups.BSolidGroup,
253 (uint)(CollisionFilterGroups.BAllGroup)) 253 (uint)(CollisionFilterGroups.BAllGroup))
254 }, 254 },
255 { CollisionType.VolumeDetect, 255 { CollisionType.VolumeDetect,
256 new CollisionTypeFilterGroup(CollisionType.VolumeDetect, 256 new CollisionTypeFilterGroup(CollisionType.VolumeDetect,
257 (uint)CollisionFilterGroups.BSensorTrigger, 257 (uint)CollisionFilterGroups.BSensorTrigger,
258 (uint)(~CollisionFilterGroups.BSensorTrigger)) 258 (uint)(~CollisionFilterGroups.BSensorTrigger))
259 }, 259 },
260 { CollisionType.LinksetChild, 260 { CollisionType.LinksetChild,
261 new CollisionTypeFilterGroup(CollisionType.LinksetChild, 261 new CollisionTypeFilterGroup(CollisionType.LinksetChild,
262 (uint)CollisionFilterGroups.BLinksetChildGroup, 262 (uint)CollisionFilterGroups.BLinksetChildGroup,
263 (uint)(CollisionFilterGroups.BNoneGroup)) 263 (uint)(CollisionFilterGroups.BNoneGroup))
264 // (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup)) 264 // (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
265 }, 265 },
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index 1284ae7..5792ae6 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -1,3 +1,12 @@
1PROBLEMS TO LOOK INTO
2=================================================
3Nebadon vehicle ride, get up, ride again. Second time vehicle does not act correctly.
4 Have to rez new vehicle and delete the old to fix situation.
5Hitting RESET on Nebadon's vehicle while riding causes vehicle to get into odd
6 position state where it will not settle onto ground properly, etc
7Two of Nebadon vehicles in a sim max the CPU. This is new.
8A sitting, active vehicle bobs up and down a small amount.
9
1CURRENT PRIORITIES 10CURRENT PRIORITIES
2================================================= 11=================================================
3Use the HACD convex hull routine in Bullet rather than the C# version. 12Use the HACD convex hull routine in Bullet rather than the C# version.
@@ -11,6 +20,8 @@ Deleting a linkset while standing on the root will leave the physical shape of t
11Linkset child rotations. 20Linkset child rotations.
12 Nebadon spiral tube has middle sections which are rotated wrong. 21 Nebadon spiral tube has middle sections which are rotated wrong.
13 Select linked spiral tube. Delink and note where the middle section ends up. 22 Select linked spiral tube. Delink and note where the middle section ends up.
23Refarb compound linkset creation to create a pseudo-root for center-of-mass
24 Let children change their shape to physical indendently and just add shapes to compound
14Vehicle angular vertical attraction 25Vehicle angular vertical attraction
15vehicle angular banking 26vehicle angular banking
16Center-of-gravity 27Center-of-gravity
@@ -27,14 +38,13 @@ llLookAt
27Avatars walking up stairs (HALF DONE) 38Avatars walking up stairs (HALF DONE)
28Avatar movement 39Avatar movement
29 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE) 40 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
30 walking up stairs is not calibrated correctly (stairs out of Kepler cabin) 41 walking up stairs is not calibrated correctly (stairs out of Kepler cabin) (DONE)
31 avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution) 42 avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution)
32Vehicle script tuning/debugging 43Vehicle script tuning/debugging
33 Avanti speed script 44 Avanti speed script
34 Weapon shooter script 45 Weapon shooter script
35Move material definitions (friction, ...) into simulator. 46Move material definitions (friction, ...) into simulator.
36Add material densities to the material types. 47Add material densities to the material types.
37Terrain detail: double terrain mesh detail
38One sided meshes? Should terrain be built into a closed shape? 48One sided meshes? Should terrain be built into a closed shape?
39 When meshes get partially wedged into the terrain, they cannot push themselves out. 49 When meshes get partially wedged into the terrain, they cannot push themselves out.
40 It is possible that Bullet processes collisions whether entering or leaving a mesh. 50 It is possible that Bullet processes collisions whether entering or leaving a mesh.
@@ -42,6 +52,9 @@ One sided meshes? Should terrain be built into a closed shape?
42 52
43VEHICLES TODO LIST: 53VEHICLES TODO LIST:
44================================================= 54=================================================
55LINEAR_MOTOR_DIRECTION values should be clamped to reasonable numbers.
56 What are the limits in SL?
57 Same for other velocity settings.
45UBit improvements to remove rubber-banding of avatars sitting on vehicle child prims: 58UBit improvements to remove rubber-banding of avatars sitting on vehicle child prims:
46 https://github.com/UbitUmarov/Ubit-opensim 59 https://github.com/UbitUmarov/Ubit-opensim
47Border crossing with linked vehicle causes crash 60Border crossing with linked vehicle causes crash
@@ -347,4 +360,5 @@ Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
347 DONE 20130120: BulletSim properly applies force in vehicle relative coordinates. 360 DONE 20130120: BulletSim properly applies force in vehicle relative coordinates.
348Nebadon vehicles turning funny in arena (DONE) 361Nebadon vehicles turning funny in arena (DONE)
349Lock axis (DONE 20130401) 362Lock axis (DONE 20130401)
363Terrain detail: double terrain mesh detail (DONE)
350 364
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index 35ae44c..b9a217b 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
51 public interface IScriptWorkItem 51 public interface IScriptWorkItem
52 { 52 {
53 bool Cancel(); 53 bool Cancel();
54 void Abort(); 54 bool Abort();
55 55
56 /// <summary> 56 /// <summary>
57 /// Wait for the work item to complete. 57 /// Wait for the work item to complete.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 1e6db43..887a317 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -564,9 +564,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
564 564
565 public bool Stop(int timeout) 565 public bool Stop(int timeout)
566 { 566 {
567// m_log.DebugFormat( 567 if (DebugLevel >= 1)
568// "[SCRIPT INSTANCE]: Stopping script {0} {1} in {2} {3} with timeout {4} {5} {6}", 568 m_log.DebugFormat(
569// ScriptName, ItemID, PrimName, ObjectID, timeout, m_InSelfDelete, DateTime.Now.Ticks); 569 "[SCRIPT INSTANCE]: Stopping script {0} {1} in {2} {3} with timeout {4} {5} {6}",
570 ScriptName, ItemID, PrimName, ObjectID, timeout, m_InSelfDelete, DateTime.Now.Ticks);
570 571
571 IScriptWorkItem workItem; 572 IScriptWorkItem workItem;
572 573
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 0d9babb..5804aa8 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -483,7 +483,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
483 /// <param name="instance"></param> 483 /// <param name="instance"></param>
484 /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param> 484 /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param>
485 private void HandleScriptsAction<TKey>( 485 private void HandleScriptsAction<TKey>(
486 string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector) 486 string[] cmdparams, Action<IScriptInstance> action, System.Func<IScriptInstance, TKey> keySelector)
487 { 487 {
488 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) 488 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
489 return; 489 return;
@@ -1517,7 +1517,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1517 startInfo.MaxWorkerThreads = maxThreads; 1517 startInfo.MaxWorkerThreads = maxThreads;
1518 startInfo.MinWorkerThreads = minThreads; 1518 startInfo.MinWorkerThreads = minThreads;
1519 startInfo.ThreadPriority = threadPriority;; 1519 startInfo.ThreadPriority = threadPriority;;
1520 startInfo.StackSize = stackSize; 1520 startInfo.MaxStackSize = stackSize;
1521 startInfo.StartSuspended = true; 1521 startInfo.StartSuspended = true;
1522 1522
1523 m_ThreadPool = new SmartThreadPool(startInfo); 1523 m_ThreadPool = new SmartThreadPool(startInfo);
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
index 8dd7677..9d9dee1 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
@@ -52,16 +52,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine
52 return wr.Cancel(); 52 return wr.Cancel();
53 } 53 }
54 54
55 public void Abort() 55 public bool Abort()
56 { 56 {
57 wr.Abort(); 57 return wr.Cancel(true);
58 } 58 }
59 59
60 public bool Wait(int t) 60 public bool Wait(int t)
61 { 61 {
62 // We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the 62 // We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the
63 // TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an 63 // TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an
64 // int (32-bit) we can end up with bad values. This occurs on Windows though curious not on Mono 2.10.8 64 // int (32-bit) we can end up with bad values. This occurs on Windows though curiously not on Mono 2.10.8
65 // (or very likely other versions of Mono at least up until 3.0.3). 65 // (or very likely other versions of Mono at least up until 3.0.3).
66 return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false); 66 return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false);
67 } 67 }