aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs115
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs178
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs66
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs647
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs48
5 files changed, 778 insertions, 276 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
new file mode 100755
index 0000000..fbb9e21
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -0,0 +1,115 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public class BSConstraint : IDisposable
36{
37 private BulletSim m_world;
38 private BulletBody m_body1;
39 private BulletBody m_body2;
40 private BulletConstraint m_constraint;
41 private bool m_enabled = false;
42
43 public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
44 Vector3 frame1, Quaternion frame1rot,
45 Vector3 frame2, Quaternion frame2rot
46 )
47 {
48 m_world = world;
49 m_body1 = obj1;
50 m_body2 = obj2;
51 m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
52 frame1, frame1rot,
53 frame2, frame2rot));
54 m_enabled = true;
55 }
56
57 public void Dispose()
58 {
59 if (m_enabled)
60 {
61 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
62 BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
63 m_enabled = false;
64 }
65 }
66
67 public BulletBody Body1 { get { return m_body1; } }
68 public BulletBody Body2 { get { return m_body2; } }
69
70 public bool SetLinearLimits(Vector3 low, Vector3 high)
71 {
72 bool ret = false;
73 if (m_enabled)
74 ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high);
75 return ret;
76 }
77
78 public bool SetAngularLimits(Vector3 low, Vector3 high)
79 {
80 bool ret = false;
81 if (m_enabled)
82 ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high);
83 return ret;
84 }
85
86 public bool UseFrameOffset(bool useOffset)
87 {
88 bool ret = false;
89 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
90 if (m_enabled)
91 ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
92 return ret;
93 }
94
95 public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
96 {
97 bool ret = false;
98 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
99 if (m_enabled)
100 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
101 return ret;
102 }
103
104 public bool CalculateTransforms()
105 {
106 bool ret = false;
107 if (m_enabled)
108 {
109 BulletSimAPI.CalculateTransforms2(m_constraint.Ptr);
110 ret = true;
111 }
112 return ret;
113 }
114}
115}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
new file mode 100755
index 0000000..a2650fb
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
@@ -0,0 +1,178 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using log4net;
31using OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35
36public class BSConstraintCollection : IDisposable
37{
38 // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
39 // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]";
40
41 delegate bool ConstraintAction(BSConstraint constrain);
42
43 private List<BSConstraint> m_constraints;
44 private BulletSim m_world;
45
46 public BSConstraintCollection(BulletSim world)
47 {
48 m_world = world;
49 m_constraints = new List<BSConstraint>();
50 }
51
52 public void Dispose()
53 {
54 this.Clear();
55 }
56
57 public void Clear()
58 {
59 foreach (BSConstraint cons in m_constraints)
60 {
61 cons.Dispose();
62 }
63 m_constraints.Clear();
64 }
65
66 public BSConstraint CreateConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
67 Vector3 frame1, Quaternion frame1rot,
68 Vector3 frame2, Quaternion frame2rot)
69 {
70 BSConstraint constrain = new BSConstraint(world, obj1, obj2, frame1, frame1rot, frame2, frame2rot);
71
72 this.AddConstraint(constrain);
73 return constrain;
74 }
75
76 public bool AddConstraint(BSConstraint cons)
77 {
78 // There is only one constraint between any bodies. Remove any old just to make sure.
79 RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
80
81 m_constraints.Add(cons);
82
83 return true;
84 }
85
86 // Get the constraint between two bodies. There can be only one the way we're using them.
87 public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint)
88 {
89 bool found = false;
90 BSConstraint foundConstraint = null;
91
92 uint lookingID1 = body1.ID;
93 uint lookingID2 = body2.ID;
94 ForEachConstraint(delegate(BSConstraint constrain)
95 {
96 if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
97 || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
98 {
99 foundConstraint = constrain;
100 found = true;
101 }
102 return found;
103 });
104 returnConstraint = foundConstraint;
105 return found;
106 }
107
108 public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2)
109 {
110 // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID);
111
112 bool ret = false;
113 BSConstraint constrain;
114
115 if (this.TryGetConstraint(body1, body2, out constrain))
116 {
117 // remove the constraint from our collection
118 m_constraints.Remove(constrain);
119 // tell the engine that all its structures need to be freed
120 constrain.Dispose();
121 // we destroyed something
122 ret = true;
123 }
124
125 return ret;
126 }
127
128 public bool RemoveAndDestroyConstraint(BulletBody body1)
129 {
130 // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID);
131
132 List<BSConstraint> toRemove = new List<BSConstraint>();
133 uint lookingID = body1.ID;
134 ForEachConstraint(delegate(BSConstraint constrain)
135 {
136 if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
137 {
138 toRemove.Add(constrain);
139 }
140 return false;
141 });
142 lock (m_constraints)
143 {
144 foreach (BSConstraint constrain in toRemove)
145 {
146 m_constraints.Remove(constrain);
147 constrain.Dispose();
148 }
149 }
150 return (toRemove.Count > 0);
151 }
152
153 public bool RecalculateAllConstraints()
154 {
155 foreach (BSConstraint constrain in m_constraints)
156 {
157 constrain.CalculateTransforms();
158 }
159 return true;
160 }
161
162 // Lock the constraint list and loop through it.
163 // The constraint action returns 'true' if it wants the loop aborted.
164 private void ForEachConstraint(ConstraintAction action)
165 {
166 lock (m_constraints)
167 {
168 foreach (BSConstraint constrain in m_constraints)
169 {
170 if (action(constrain))
171 break;
172 }
173 }
174 }
175
176
177}
178}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index a19d6d7..3be28e3 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -97,6 +97,9 @@ public sealed class BSPrim : PhysicsActor
97 long _collidingStep; 97 long _collidingStep;
98 long _collidingGroundStep; 98 long _collidingGroundStep;
99 99
100 private BulletBody m_body;
101 public BulletBody Body { get { return m_body; } }
102
100 private BSDynamics _vehicle; 103 private BSDynamics _vehicle;
101 104
102 private OMV.Vector3 _PIDTarget; 105 private OMV.Vector3 _PIDTarget;
@@ -138,6 +141,11 @@ public sealed class BSPrim : PhysicsActor
138 _scene.TaintedObject(delegate() 141 _scene.TaintedObject(delegate()
139 { 142 {
140 RecreateGeomAndObject(); 143 RecreateGeomAndObject();
144
145 // Get the pointer to the physical body for this object.
146 // At the moment, we're still letting BulletSim manage the creation and destruction
147 // of the object. Someday we'll move that into the C# code.
148 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
141 }); 149 });
142 } 150 }
143 151
@@ -161,7 +169,7 @@ public sealed class BSPrim : PhysicsActor
161 _parentPrim = null; 169 _parentPrim = null;
162 } 170 }
163 171
164 // make sure there are no possible children depending on me 172 // make sure there are no other prims linked to me
165 UnlinkAllChildren(); 173 UnlinkAllChildren();
166 174
167 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 175 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
@@ -333,11 +341,10 @@ public sealed class BSPrim : PhysicsActor
333 _rotationalVelocity = OMV.Vector3.Zero; 341 _rotationalVelocity = OMV.Vector3.Zero;
334 342
335 // Zero some other properties directly into the physics engine 343 // Zero some other properties directly into the physics engine
336 IntPtr obj = BulletSimAPI.GetBodyHandleWorldID2(_scene.WorldID, LocalID); 344 BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero);
337 BulletSimAPI.SetVelocity2(obj, OMV.Vector3.Zero); 345 BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero);
338 BulletSimAPI.SetAngularVelocity2(obj, OMV.Vector3.Zero); 346 BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
339 BulletSimAPI.SetInterpolation2(obj, OMV.Vector3.Zero, OMV.Vector3.Zero); 347 BulletSimAPI.ClearForces2(Body.Ptr);
340 BulletSimAPI.ClearForces2(obj);
341 } 348 }
342 349
343 public override void LockAngularMotion(OMV.Vector3 axis) 350 public override void LockAngularMotion(OMV.Vector3 axis)
@@ -383,7 +390,8 @@ public sealed class BSPrim : PhysicsActor
383 _scene.TaintedObject(delegate() 390 _scene.TaintedObject(delegate()
384 { 391 {
385 DetailLog("{0},SetForce,taint,force={1}", LocalID, _force); 392 DetailLog("{0},SetForce,taint,force={1}", LocalID, _force);
386 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 393 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
394 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
387 }); 395 });
388 } 396 }
389 } 397 }
@@ -407,8 +415,7 @@ public sealed class BSPrim : PhysicsActor
407 _scene.TaintedObject(delegate() 415 _scene.TaintedObject(delegate()
408 { 416 {
409 // Tell the physics engine to clear state 417 // Tell the physics engine to clear state
410 IntPtr obj = BulletSimAPI.GetBodyHandleWorldID2(_scene.WorldID, LocalID); 418 BulletSimAPI.ClearForces2(this.Body.Ptr);
411 BulletSimAPI.ClearForces2(obj);
412 }); 419 });
413 420
414 // make it so the scene will call us each tick to do vehicle things 421 // make it so the scene will call us each tick to do vehicle things
@@ -420,7 +427,6 @@ public sealed class BSPrim : PhysicsActor
420 } 427 }
421 public override void VehicleFloatParam(int param, float value) 428 public override void VehicleFloatParam(int param, float value)
422 { 429 {
423 m_log.DebugFormat("{0} VehicleFloatParam. {1} <= {2}", LogHeader, param, value);
424 _scene.TaintedObject(delegate() 430 _scene.TaintedObject(delegate()
425 { 431 {
426 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 432 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
@@ -428,7 +434,6 @@ public sealed class BSPrim : PhysicsActor
428 } 434 }
429 public override void VehicleVectorParam(int param, OMV.Vector3 value) 435 public override void VehicleVectorParam(int param, OMV.Vector3 value)
430 { 436 {
431 m_log.DebugFormat("{0} VehicleVectorParam. {1} <= {2}", LogHeader, param, value);
432 _scene.TaintedObject(delegate() 437 _scene.TaintedObject(delegate()
433 { 438 {
434 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 439 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
@@ -436,7 +441,6 @@ public sealed class BSPrim : PhysicsActor
436 } 441 }
437 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 442 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
438 { 443 {
439 m_log.DebugFormat("{0} VehicleRotationParam. {1} <= {2}", LogHeader, param, rotation);
440 _scene.TaintedObject(delegate() 444 _scene.TaintedObject(delegate()
441 { 445 {
442 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 446 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
@@ -444,7 +448,6 @@ public sealed class BSPrim : PhysicsActor
444 } 448 }
445 public override void VehicleFlags(int param, bool remove) 449 public override void VehicleFlags(int param, bool remove)
446 { 450 {
447 m_log.DebugFormat("{0} VehicleFlags. {1}. Remove={2}", LogHeader, param, remove);
448 _scene.TaintedObject(delegate() 451 _scene.TaintedObject(delegate()
449 { 452 {
450 _vehicle.ProcessVehicleFlags(param, remove); 453 _vehicle.ProcessVehicleFlags(param, remove);
@@ -1292,11 +1295,10 @@ public sealed class BSPrim : PhysicsActor
1292 // relative to each other. 1295 // relative to each other.
1293 void CreateLinkset() 1296 void CreateLinkset()
1294 { 1297 {
1295 DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1); 1298 // DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
1296 1299
1297 // remove any constraints that might be in place 1300 // remove any constraints that might be in place
1298 DebugLog("{0}: CreateLinkset: RemoveConstraints between me and any children", LogHeader, LocalID); 1301 UnlinkAllChildren();
1299 BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
1300 1302
1301 // create constraints between the root prim and each of the children 1303 // create constraints between the root prim and each of the children
1302 foreach (BSPrim prim in _childrenPrims) 1304 foreach (BSPrim prim in _childrenPrims)
@@ -1321,15 +1323,25 @@ public sealed class BSPrim : PhysicsActor
1321 1323
1322 // create a constraint that allows no freedom of movement between the two objects 1324 // create a constraint that allows no freedom of movement between the two objects
1323 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 1325 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
1324 DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); 1326 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
1325 DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID); 1327 DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID);
1326 BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, childPrim.LocalID, 1328 BSConstraint constrain = _scene.Constraints.CreateConstraint(
1327 childRelativePosition, 1329 _scene.World, this.Body, childPrim.Body,
1328 childRelativeRotation, 1330 childRelativePosition,
1329 OMV.Vector3.Zero, 1331 childRelativeRotation,
1330 OMV.Quaternion.Identity, 1332 OMV.Vector3.Zero,
1331 OMV.Vector3.Zero, OMV.Vector3.Zero, 1333 OMV.Quaternion.Identity);
1332 OMV.Vector3.Zero, OMV.Vector3.Zero); 1334 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
1335 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
1336
1337 // tweek the constraint to increase stability
1338 constrain.UseFrameOffset(_scene.BoolNumeric(_scene.Params.linkConstraintUseFrameOffset));
1339 if (_scene.BoolNumeric(_scene.Params.linkConstraintEnableTransMotor))
1340 {
1341 constrain.TranslationalLimitMotor(true,
1342 _scene.Params.linkConstraintTransMotorMaxVel,
1343 _scene.Params.linkConstraintTransMotorMaxForce);
1344 }
1333 } 1345 }
1334 1346
1335 // Remove linkage between myself and a particular child 1347 // Remove linkage between myself and a particular child
@@ -1339,7 +1351,8 @@ public sealed class BSPrim : PhysicsActor
1339 DebugLog("{0}: UnlinkAChildFromMe: RemoveConstraint between root prim {1} and child prim {2}", 1351 DebugLog("{0}: UnlinkAChildFromMe: RemoveConstraint between root prim {1} and child prim {2}",
1340 LogHeader, LocalID, childPrim.LocalID); 1352 LogHeader, LocalID, childPrim.LocalID);
1341 DetailLog("{0},UnlinkAChildFromMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID); 1353 DetailLog("{0},UnlinkAChildFromMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID);
1342 BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID); 1354 // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID);
1355 _scene.Constraints.RemoveAndDestroyConstraint(this.Body, childPrim.Body);
1343 } 1356 }
1344 1357
1345 // Remove linkage between myself and any possible children I might have 1358 // Remove linkage between myself and any possible children I might have
@@ -1348,7 +1361,8 @@ public sealed class BSPrim : PhysicsActor
1348 { 1361 {
1349 DebugLog("{0}: UnlinkAllChildren:", LogHeader); 1362 DebugLog("{0}: UnlinkAllChildren:", LogHeader);
1350 DetailLog("{0},UnlinkAllChildren,taint", LocalID); 1363 DetailLog("{0},UnlinkAllChildren,taint", LocalID);
1351 BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); 1364 _scene.Constraints.RemoveAndDestroyConstraint(this.Body);
1365 // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
1352 } 1366 }
1353 1367
1354 #endregion // Linkset creation and destruction 1368 #endregion // Linkset creation and destruction
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 7cc3fe3..a1587a8 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -103,6 +103,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
103 get { return m_sculptLOD; } 103 get { return m_sculptLOD; }
104 } 104 }
105 105
106 private BulletSim m_worldSim;
107 public BulletSim World
108 {
109 get { return m_worldSim; }
110 }
111 private BSConstraintCollection m_constraintCollection;
112 public BSConstraintCollection Constraints
113 {
114 get { return m_constraintCollection; }
115 }
116
106 private int m_maxSubSteps; 117 private int m_maxSubSteps;
107 private float m_fixedTimeStep; 118 private float m_fixedTimeStep;
108 private long m_simulationStep = 0; 119 private long m_simulationStep = 0;
@@ -229,6 +240,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
229 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), 240 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
230 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); 241 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
231 242
243 // Initialization to support the transition to a new API which puts most of the logic
244 // into the C# code so it is easier to modify and add to.
245 m_worldSim = new BulletSim(m_worldID, BulletSimAPI.GetSimHandle2(m_worldID));
246 m_constraintCollection = new BSConstraintCollection(World);
247
232 m_initialized = true; 248 m_initialized = true;
233 } 249 }
234 250
@@ -237,116 +253,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
237 private void GetInitialParameterValues(IConfigSource config) 253 private void GetInitialParameterValues(IConfigSource config)
238 { 254 {
239 ConfigurationParameters parms = new ConfigurationParameters(); 255 ConfigurationParameters parms = new ConfigurationParameters();
256 m_params[0] = parms;
240 257
241 _meshSculptedPrim = true; // mesh sculpted prims 258 SetParameterDefaultValues();
242 _forceSimplePrimMeshing = false; // use complex meshing if called for
243
244 m_meshLOD = 8f;
245 m_sculptLOD = 32f;
246
247 shouldDebugLog = false;
248 m_detailedStatsStep = 0; // disabled
249
250 m_maxSubSteps = 10;
251 m_fixedTimeStep = 1f / 60f;
252 m_maxCollisionsPerFrame = 2048;
253 m_maxUpdatesPerFrame = 2048;
254 m_maximumObjectMass = 10000.01f;
255
256 PID_D = 2200f;
257 PID_P = 900f;
258
259 parms.defaultFriction = 0.5f;
260 parms.defaultDensity = 10.000006836f; // Aluminum g/cm3
261 parms.defaultRestitution = 0f;
262 parms.collisionMargin = 0.0f;
263 parms.gravity = -9.80665f;
264
265 parms.linearDamping = 0.0f;
266 parms.angularDamping = 0.0f;
267 parms.deactivationTime = 0.2f;
268 parms.linearSleepingThreshold = 0.8f;
269 parms.angularSleepingThreshold = 1.0f;
270 parms.ccdMotionThreshold = 0.0f; // set to zero to disable
271 parms.ccdSweptSphereRadius = 0.0f;
272 parms.contactProcessingThreshold = 0.1f;
273
274 parms.terrainFriction = 0.5f;
275 parms.terrainHitFraction = 0.8f;
276 parms.terrainRestitution = 0f;
277 parms.avatarFriction = 0.5f;
278 parms.avatarRestitution = 0.0f;
279 parms.avatarDensity = 60f;
280 parms.avatarCapsuleRadius = 0.37f;
281 parms.avatarCapsuleHeight = 1.5f; // 2.140599f
282 parms.avatarContactProcessingThreshold = 0.1f;
283
284 parms.maxPersistantManifoldPoolSize = 0f;
285 parms.shouldDisableContactPoolDynamicAllocation = ConfigurationParameters.numericTrue;
286 parms.shouldForceUpdateAllAabbs = ConfigurationParameters.numericFalse;
287 parms.shouldRandomizeSolverOrder = ConfigurationParameters.numericFalse;
288 parms.shouldSplitSimulationIslands = ConfigurationParameters.numericFalse;
289 parms.shouldEnableFrictionCaching = ConfigurationParameters.numericFalse;
290 parms.numberOfSolverIterations = 0f; // means use default
291 259
292 if (config != null) 260 if (config != null)
293 { 261 {
294 // If there are specifications in the ini file, use those values 262 // If there are specifications in the ini file, use those values
295 // WHEN ADDING OR UPDATING THIS SECTION, BE SURE TO UPDATE OpenSimDefaults.ini
296 // ALSO REMEMBER TO UPDATE THE RUNTIME SETTING OF THE PARAMETERS.
297 IConfig pConfig = config.Configs["BulletSim"]; 263 IConfig pConfig = config.Configs["BulletSim"];
298 if (pConfig != null) 264 if (pConfig != null)
299 { 265 {
300 _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); 266 SetParameterConfigurationValues(pConfig);
301 _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing);
302
303 shouldDebugLog = pConfig.GetBoolean("ShouldDebugLog", shouldDebugLog);
304 m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep);
305
306 m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD);
307 m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD);
308
309 m_maxSubSteps = pConfig.GetInt("MaxSubSteps", m_maxSubSteps);
310 m_fixedTimeStep = pConfig.GetFloat("FixedTimeStep", m_fixedTimeStep);
311 m_maxCollisionsPerFrame = pConfig.GetInt("MaxCollisionsPerFrame", m_maxCollisionsPerFrame);
312 m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame);
313 m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass);
314
315 PID_D = pConfig.GetFloat("PIDDerivative", PID_D);
316 PID_P = pConfig.GetFloat("PIDProportional", PID_P);
317
318 parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction);
319 parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity);
320 parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution);
321 parms.collisionMargin = pConfig.GetFloat("CollisionMargin", parms.collisionMargin);
322 parms.gravity = pConfig.GetFloat("Gravity", parms.gravity);
323
324 parms.linearDamping = pConfig.GetFloat("LinearDamping", parms.linearDamping);
325 parms.angularDamping = pConfig.GetFloat("AngularDamping", parms.angularDamping);
326 parms.deactivationTime = pConfig.GetFloat("DeactivationTime", parms.deactivationTime);
327 parms.linearSleepingThreshold = pConfig.GetFloat("LinearSleepingThreshold", parms.linearSleepingThreshold);
328 parms.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", parms.angularSleepingThreshold);
329 parms.ccdMotionThreshold = pConfig.GetFloat("CcdMotionThreshold", parms.ccdMotionThreshold);
330 parms.ccdSweptSphereRadius = pConfig.GetFloat("CcdSweptSphereRadius", parms.ccdSweptSphereRadius);
331 parms.contactProcessingThreshold = pConfig.GetFloat("ContactProcessingThreshold", parms.contactProcessingThreshold);
332
333 parms.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction);
334 parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction);
335 parms.terrainRestitution = pConfig.GetFloat("TerrainRestitution", parms.terrainRestitution);
336 parms.avatarFriction = pConfig.GetFloat("AvatarFriction", parms.avatarFriction);
337 parms.avatarRestitution = pConfig.GetFloat("AvatarRestitution", parms.avatarRestitution);
338 parms.avatarDensity = pConfig.GetFloat("AvatarDensity", parms.avatarDensity);
339 parms.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", parms.avatarCapsuleRadius);
340 parms.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", parms.avatarCapsuleHeight);
341 parms.avatarContactProcessingThreshold = pConfig.GetFloat("AvatarContactProcessingThreshold", parms.avatarContactProcessingThreshold);
342
343 parms.maxPersistantManifoldPoolSize = pConfig.GetFloat("MaxPersistantManifoldPoolSize", parms.maxPersistantManifoldPoolSize);
344 parms.shouldDisableContactPoolDynamicAllocation = ParamBoolean(pConfig, "ShouldDisableContactPoolDynamicAllocation", parms.shouldDisableContactPoolDynamicAllocation);
345 parms.shouldForceUpdateAllAabbs = ParamBoolean(pConfig, "ShouldForceUpdateAllAabbs", parms.shouldForceUpdateAllAabbs);
346 parms.shouldRandomizeSolverOrder = ParamBoolean(pConfig, "ShouldRandomizeSolverOrder", parms.shouldRandomizeSolverOrder);
347 parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands);
348 parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching);
349 parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations);
350 267
351 // Very detailed logging for physics debugging 268 // Very detailed logging for physics debugging
352 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 269 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
@@ -357,7 +274,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
357 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); 274 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
358 } 275 }
359 } 276 }
360 m_params[0] = parms;
361 } 277 }
362 278
363 // A helper function that handles a true/false parameter and returns the proper float number encoding 279 // A helper function that handles a true/false parameter and returns the proper float number encoding
@@ -634,6 +550,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
634 // make sure no stepping happens while we're deleting stuff 550 // make sure no stepping happens while we're deleting stuff
635 m_initialized = false; 551 m_initialized = false;
636 552
553 if (m_constraintCollection != null)
554 {
555 m_constraintCollection.Dispose();
556 m_constraintCollection = null;
557 }
558
637 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 559 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
638 { 560 {
639 kvp.Value.Destroy(); 561 kvp.Value.Destroy();
@@ -776,10 +698,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
776 } 698 }
777 699
778 // The calls to the PhysicsActors can't directly call into the physics engine 700 // The calls to the PhysicsActors can't directly call into the physics engine
779 // because it might be busy. We we delay changes to a known time. 701 // because it might be busy. We delay changes to a known time.
780 // We rely on C#'s closure to save and restore the context for the delegate. 702 // We rely on C#'s closure to save and restore the context for the delegate.
781 public void TaintedObject(TaintCallback callback) 703 public void TaintedObject(TaintCallback callback)
782 { 704 {
705 if (!m_initialized) return;
706
783 lock (_taintLock) 707 lock (_taintLock)
784 _taintedObjects.Add(callback); 708 _taintedObjects.Add(callback);
785 return; 709 return;
@@ -853,61 +777,371 @@ public class BSScene : PhysicsScene, IPhysicsParameters
853 } 777 }
854 #endregion Vehicles 778 #endregion Vehicles
855 779
856 #region Runtime settable parameters 780 #region Parameters
857 public static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[] 781
782 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
783 delegate float ParamGet(BSScene scene);
784 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
785
786 private struct ParameterDefn
858 { 787 {
859 new PhysParameterEntry("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)"), 788 public string name;
860 new PhysParameterEntry("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)"), 789 public string desc;
861 new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"), 790 public float defaultValue;
862 new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"), 791 public ParamUser userParam;
863 new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"), 792 public ParamGet getter;
864 new PhysParameterEntry("DetailedStats", "Frames between outputting detailed phys stats. Zero is off"), 793 public ParamSet setter;
865 794 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
866 new PhysParameterEntry("DefaultFriction", "Friction factor used on new objects"), 795 {
867 new PhysParameterEntry("DefaultDensity", "Density for new objects" ), 796 name = n;
868 new PhysParameterEntry("DefaultRestitution", "Bouncyness of an object" ), 797 desc = d;
869 // new PhysParameterEntry("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!!)" ), 798 defaultValue = v;
870 new PhysParameterEntry("Gravity", "Vertical force of gravity (negative means down)" ), 799 userParam = u;
871 800 getter = g;
872 new PhysParameterEntry("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)" ), 801 setter = s;
873 new PhysParameterEntry("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)" ), 802 }
874 new PhysParameterEntry("DeactivationTime", "Seconds before considering an object potentially static" ), 803 }
875 new PhysParameterEntry("LinearSleepingThreshold", "Seconds to measure linear movement before considering static" ), 804
876 new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ), 805 // List of all of the externally visible parameters.
877 new PhysParameterEntry("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ), 806 // For each parameter, this table maps a text name to getter and setters.
878 new PhysParameterEntry("CcdSweptSphereRadius", "Continuious collision detection test radius" ), 807 // A ParameterDefn() takes the following parameters:
879 new PhysParameterEntry("ContactProcessingThreshold", "Distance between contacts before doing collision check" ), 808 // -- the text name of the parameter. This is used for console input and ini file.
880 // Can only change the following at initialization time. Change the INI file and reboot. 809 // -- a short text description of the parameter. This shows up in the console listing.
881 new PhysParameterEntry("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)"), 810 // -- a delegate for fetching the parameter from the ini file.
882 new PhysParameterEntry("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count"), 811 // Should handle fetching the right type from the ini file and converting it.
883 new PhysParameterEntry("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step"), 812 // -- a delegate for getting the value as a float
884 new PhysParameterEntry("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction"), 813 // -- a delegate for setting the value from a float
885 new PhysParameterEntry("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands"), 814 //
886 new PhysParameterEntry("ShouldEnableFrictionCaching", "Enable friction computation caching"), 815 // To add a new variable, it is best to find an existing definition and copy it.
887 new PhysParameterEntry("NumberOfSolverIterations", "Number of internal iterations (0 means default)"), 816 private ParameterDefn[] ParameterDefinitions =
888 817 {
889 new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), 818 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
890 new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), 819 ConfigurationParameters.numericTrue,
891 820 (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
892 new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), 821 (s) => { return s.NumericBool(s._meshSculptedPrim); },
893 new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), 822 (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ),
894 823 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
895 new PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ), 824 ConfigurationParameters.numericFalse,
896 new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ), 825 (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
897 new PhysParameterEntry("TerrainRestitution", "Bouncyness" ), 826 (s) => { return s.NumericBool(s._forceSimplePrimMeshing); },
898 new PhysParameterEntry("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation." ), 827 (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ),
899 new PhysParameterEntry("AvatarDensity", "Density of an avatar. Changed on avatar recreation." ), 828
900 new PhysParameterEntry("AvatarRestitution", "Bouncyness. Changed on avatar recreation." ), 829 new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
901 new PhysParameterEntry("AvatarCapsuleRadius", "Radius of space around an avatar" ), 830 8f,
902 new PhysParameterEntry("AvatarCapsuleHeight", "Default height of space around avatar" ), 831 (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); },
903 new PhysParameterEntry("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions") 832 (s) => { return (float)s.m_meshLOD; },
833 (s,p,l,v) => { s.m_meshLOD = (int)v; } ),
834 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
835 32,
836 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); },
837 (s) => { return (float)s.m_sculptLOD; },
838 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ),
839
840 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
841 10f,
842 (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
843 (s) => { return (float)s.m_maxSubSteps; },
844 (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
845 new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
846 1f / 60f,
847 (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
848 (s) => { return (float)s.m_fixedTimeStep; },
849 (s,p,l,v) => { s.m_fixedTimeStep = v; } ),
850 new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
851 2048f,
852 (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
853 (s) => { return (float)s.m_maxCollisionsPerFrame; },
854 (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
855 new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
856 8000f,
857 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
858 (s) => { return (float)s.m_maxUpdatesPerFrame; },
859 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
860 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
861 10000.01f,
862 (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); },
863 (s) => { return (float)s.m_maximumObjectMass; },
864 (s,p,l,v) => { s.m_maximumObjectMass = v; } ),
865
866 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
867 2200f,
868 (s,cf,p,v) => { s.PID_D = cf.GetFloat(p, v); },
869 (s) => { return (float)s.PID_D; },
870 (s,p,l,v) => { s.PID_D = v; } ),
871 new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
872 900f,
873 (s,cf,p,v) => { s.PID_P = cf.GetFloat(p, v); },
874 (s) => { return (float)s.PID_P; },
875 (s,p,l,v) => { s.PID_P = v; } ),
876
877 new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
878 0.5f,
879 (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); },
880 (s) => { return s.m_params[0].defaultFriction; },
881 (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ),
882 new ParameterDefn("DefaultDensity", "Density for new objects" ,
883 10.000006836f, // Aluminum g/cm3
884 (s,cf,p,v) => { s.m_params[0].defaultDensity = cf.GetFloat(p, v); },
885 (s) => { return s.m_params[0].defaultDensity; },
886 (s,p,l,v) => { s.m_params[0].defaultDensity = v; } ),
887 new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
888 0f,
889 (s,cf,p,v) => { s.m_params[0].defaultRestitution = cf.GetFloat(p, v); },
890 (s) => { return s.m_params[0].defaultRestitution; },
891 (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ),
892 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
893 0f,
894 (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); },
895 (s) => { return s.m_params[0].collisionMargin; },
896 (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ),
897 new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
898 -9.80665f,
899 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); },
900 (s) => { return s.m_params[0].gravity; },
901 (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ),
902
903
904 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
905 0f,
906 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
907 (s) => { return s.m_params[0].linearDamping; },
908 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ),
909 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
910 0f,
911 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
912 (s) => { return s.m_params[0].angularDamping; },
913 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ),
914 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
915 0.2f,
916 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
917 (s) => { return s.m_params[0].deactivationTime; },
918 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ),
919 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
920 0.8f,
921 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
922 (s) => { return s.m_params[0].linearSleepingThreshold; },
923 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
924 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
925 1.0f,
926 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
927 (s) => { return s.m_params[0].angularSleepingThreshold; },
928 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
929 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
930 0f, // set to zero to disable
931 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
932 (s) => { return s.m_params[0].ccdMotionThreshold; },
933 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
934 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
935 0f,
936 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
937 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
938 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
939 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
940 0.1f,
941 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
942 (s) => { return s.m_params[0].contactProcessingThreshold; },
943 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
944
945 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
946 0.5f,
947 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
948 (s) => { return s.m_params[0].terrainFriction; },
949 (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ),
950 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
951 0.8f,
952 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); },
953 (s) => { return s.m_params[0].terrainHitFraction; },
954 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ),
955 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
956 0f,
957 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
958 (s) => { return s.m_params[0].terrainRestitution; },
959 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
960 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
961 0.5f,
962 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
963 (s) => { return s.m_params[0].avatarFriction; },
964 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ),
965 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
966 60f,
967 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
968 (s) => { return s.m_params[0].avatarDensity; },
969 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ),
970 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
971 0f,
972 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
973 (s) => { return s.m_params[0].avatarRestitution; },
974 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ),
975 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
976 0.37f,
977 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
978 (s) => { return s.m_params[0].avatarCapsuleRadius; },
979 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
980 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
981 1.5f,
982 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
983 (s) => { return s.m_params[0].avatarCapsuleHeight; },
984 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
985 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
986 0.1f,
987 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
988 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
989 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
990
991
992 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)",
993 0f, // zero to disable
994 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
995 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
996 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
997 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
998 ConfigurationParameters.numericTrue,
999 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1000 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; },
1001 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
1002 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
1003 ConfigurationParameters.numericFalse,
1004 (s,cf,p,v) => { s.m_params[0].shouldForceUpdateAllAabbs = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1005 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
1006 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
1007 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
1008 ConfigurationParameters.numericFalse,
1009 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1010 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
1011 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
1012 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
1013 ConfigurationParameters.numericFalse,
1014 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1015 (s) => { return s.m_params[0].shouldSplitSimulationIslands; },
1016 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ),
1017 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
1018 ConfigurationParameters.numericFalse,
1019 (s,cf,p,v) => { s.m_params[0].shouldEnableFrictionCaching = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1020 (s) => { return s.m_params[0].shouldEnableFrictionCaching; },
1021 (s,p,l,v) => { s.m_params[0].shouldEnableFrictionCaching = v; } ),
1022 new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
1023 0f, // zero says use Bullet default
1024 (s,cf,p,v) => { s.m_params[0].numberOfSolverIterations = cf.GetFloat(p, v); },
1025 (s) => { return s.m_params[0].numberOfSolverIterations; },
1026 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ),
1027
1028 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
1029 ConfigurationParameters.numericTrue,
1030 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1031 (s) => { return s.m_params[0].linkConstraintUseFrameOffset; },
1032 (s,p,l,v) => { s.m_params[0].linkConstraintUseFrameOffset = v; } ),
1033 new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
1034 ConfigurationParameters.numericTrue,
1035 (s,cf,p,v) => { s.m_params[0].linkConstraintEnableTransMotor = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1036 (s) => { return s.m_params[0].linkConstraintEnableTransMotor; },
1037 (s,p,l,v) => { s.m_params[0].linkConstraintEnableTransMotor = v; } ),
1038 new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
1039 5.0f,
1040 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
1041 (s) => { return s.m_params[0].linkConstraintTransMotorMaxVel; },
1042 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = v; } ),
1043 new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
1044 0.1f,
1045 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1046 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1047 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1048
1049 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)",
1050 0f,
1051 (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); },
1052 (s) => { return (float)s.m_detailedStatsStep; },
1053 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
1054 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
1055 ConfigurationParameters.numericFalse,
1056 (s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
1057 (s) => { return s.NumericBool(s.shouldDebugLog); },
1058 (s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(v); } ),
904 1059
905 }; 1060 };
906 1061
1062 // Convert a boolean to our numeric true and false values
1063 public float NumericBool(bool b)
1064 {
1065 return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse);
1066 }
1067
1068 // Convert numeric true and false values to a boolean
1069 public bool BoolNumeric(float b)
1070 {
1071 return (b == ConfigurationParameters.numericTrue ? true : false);
1072 }
1073
1074 // Search through the parameter definitions and return the matching
1075 // ParameterDefn structure.
1076 // Case does not matter as names are compared after converting to lower case.
1077 // Returns 'false' if the parameter is not found.
1078 private bool TryGetParameter(string paramName, out ParameterDefn defn)
1079 {
1080 bool ret = false;
1081 ParameterDefn foundDefn = new ParameterDefn();
1082 string pName = paramName.ToLower();
1083
1084 foreach (ParameterDefn parm in ParameterDefinitions)
1085 {
1086 if (pName == parm.name.ToLower())
1087 {
1088 foundDefn = parm;
1089 ret = true;
1090 break;
1091 }
1092 }
1093 defn = foundDefn;
1094 return ret;
1095 }
1096
1097 // Pass through the settable parameters and set the default values
1098 private void SetParameterDefaultValues()
1099 {
1100 foreach (ParameterDefn parm in ParameterDefinitions)
1101 {
1102 parm.setter(this, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue);
1103 }
1104 }
1105
1106 // Get user set values out of the ini file.
1107 private void SetParameterConfigurationValues(IConfig cfg)
1108 {
1109 foreach (ParameterDefn parm in ParameterDefinitions)
1110 {
1111 parm.userParam(this, cfg, parm.name, parm.defaultValue);
1112 }
1113 }
1114
1115 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
1116
1117 private void BuildParameterTable()
1118 {
1119 if (SettableParameters.Length < ParameterDefinitions.Length)
1120 {
1121
1122 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
1123 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
1124 {
1125 ParameterDefn pd = ParameterDefinitions[ii];
1126 entries.Add(new PhysParameterEntry(pd.name, pd.desc));
1127 }
1128
1129 // make the list in alphabetical order for estetic reasons
1130 entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2)
1131 {
1132 return ppe1.name.CompareTo(ppe2.name);
1133 });
1134
1135 SettableParameters = entries.ToArray();
1136 }
1137 }
1138
1139
907 #region IPhysicsParameters 1140 #region IPhysicsParameters
908 // Get the list of parameters this physics engine supports 1141 // Get the list of parameters this physics engine supports
909 public PhysParameterEntry[] GetParameterList() 1142 public PhysParameterEntry[] GetParameterList()
910 { 1143 {
1144 BuildParameterTable();
911 return SettableParameters; 1145 return SettableParameters;
912 } 1146 }
913 1147
@@ -919,63 +1153,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
919 // value activated ('terrainFriction' for instance). 1153 // value activated ('terrainFriction' for instance).
920 public bool SetPhysicsParameter(string parm, float val, uint localID) 1154 public bool SetPhysicsParameter(string parm, float val, uint localID)
921 { 1155 {
922 bool ret = true; 1156 bool ret = false;
923 string lparm = parm.ToLower(); 1157 ParameterDefn theParam;
924 switch (lparm) 1158 if (TryGetParameter(parm, out theParam))
925 { 1159 {
926 case "detailedstats": m_detailedStatsStep = (int)val; break; 1160 theParam.setter(this, parm, localID, val);
927 1161 ret = true;
928 case "meshlod": m_meshLOD = (int)val; break;
929 case "sculptlod": m_sculptLOD = (int)val; break;
930 case "maxsubstep": m_maxSubSteps = (int)val; break;
931 case "fixedtimestep": m_fixedTimeStep = val; break;
932 case "maxobjectmass": m_maximumObjectMass = val; break;
933
934 case "defaultfriction": m_params[0].defaultFriction = val; break;
935 case "defaultdensity": m_params[0].defaultDensity = val; break;
936 case "defaultrestitution": m_params[0].defaultRestitution = val; break;
937 case "collisionmargin": m_params[0].collisionMargin = val; break;
938 case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, localID, val); break;
939
940 case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break;
941 case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break;
942 case "deactivationtime": UpdateParameterPrims(ref m_params[0].deactivationTime, lparm, localID, val); break;
943 case "linearsleepingthreshold": UpdateParameterPrims(ref m_params[0].linearSleepingThreshold, lparm, localID, val); break;
944 case "angularsleepingthreshold": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break;
945 case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break;
946 case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break;
947 case "contactprocessingthreshold": UpdateParameterPrims(ref m_params[0].contactProcessingThreshold, lparm, localID, val); break;
948 // the following are used only at initialization time so setting them makes no sense
949 // case "maxPersistantmanifoldpoolSize": m_params[0].maxPersistantManifoldPoolSize = val; break;
950 // case "shoulddisablecontactpooldynamicallocation": m_params[0].shouldDisableContactPoolDynamicAllocation = val; break;
951 // case "shouldforceupdateallaabbs": m_params[0].shouldForceUpdateAllAabbs = val; break;
952 // case "shouldrandomizesolverorder": m_params[0].shouldRandomizeSolverOrder = val; break;
953 // case "shouldsplitsimulationislands": m_params[0].shouldSplitSimulationIslands = val; break;
954 // case "shouldenablefrictioncaching": m_params[0].shouldEnableFrictionCaching = val; break;
955 // case "numberofsolveriterations": m_params[0].numberOfSolverIterations = val; break;
956
957 case "friction": TaintedUpdateParameter(lparm, localID, val); break;
958 case "restitution": TaintedUpdateParameter(lparm, localID, val); break;
959
960 // set a terrain physical feature and cause terrain to be recalculated
961 case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break;
962 case "terrainhitfraction": m_params[0].terrainHitFraction = val; TaintedUpdateParameter("terrain", 0, val); break;
963 case "terrainrestitution": m_params[0].terrainRestitution = val; TaintedUpdateParameter("terrain", 0, val); break;
964 // set an avatar physical feature and cause avatar(s) to be recalculated
965 case "avatarfriction": UpdateParameterAvatars(ref m_params[0].avatarFriction, "avatar", localID, val); break;
966 case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break;
967 case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break;
968 case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break;
969 case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break;
970 case "avatarcontactprocessingthreshold": UpdateParameterAvatars(ref m_params[0].avatarContactProcessingThreshold, "avatar", localID, val); break;
971
972 default: ret = false; break;
973 } 1162 }
974 return ret; 1163 return ret;
975 } 1164 }
976 1165
977 // check to see if we are updating a parameter for a particular or all of the prims 1166 // check to see if we are updating a parameter for a particular or all of the prims
978 private void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) 1167 protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val)
979 { 1168 {
980 List<uint> operateOn; 1169 List<uint> operateOn;
981 lock (m_prims) operateOn = new List<uint>(m_prims.Keys); 1170 lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
@@ -983,7 +1172,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
983 } 1172 }
984 1173
985 // check to see if we are updating a parameter for a particular or all of the avatars 1174 // check to see if we are updating a parameter for a particular or all of the avatars
986 private void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val) 1175 protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
987 { 1176 {
988 List<uint> operateOn; 1177 List<uint> operateOn;
989 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys); 1178 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys);
@@ -994,7 +1183,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
994 // If the local ID is APPLY_TO_NONE, just change the default value 1183 // If the local ID is APPLY_TO_NONE, just change the default value
995 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs 1184 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
996 // If the localID is a specific object, apply the parameter change to only that object 1185 // If the localID is a specific object, apply the parameter change to only that object
997 private void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val) 1186 protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val)
998 { 1187 {
999 switch (localID) 1188 switch (localID)
1000 { 1189 {
@@ -1021,7 +1210,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1021 } 1210 }
1022 1211
1023 // schedule the actual updating of the paramter to when the phys engine is not busy 1212 // schedule the actual updating of the paramter to when the phys engine is not busy
1024 private void TaintedUpdateParameter(string parm, uint localID, float val) 1213 protected void TaintedUpdateParameter(string parm, uint localID, float val)
1025 { 1214 {
1026 uint xlocalID = localID; 1215 uint xlocalID = localID;
1027 string xparm = parm.ToLower(); 1216 string xparm = parm.ToLower();
@@ -1036,50 +1225,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1036 public bool GetPhysicsParameter(string parm, out float value) 1225 public bool GetPhysicsParameter(string parm, out float value)
1037 { 1226 {
1038 float val = 0f; 1227 float val = 0f;
1039 bool ret = true; 1228 bool ret = false;
1040 switch (parm.ToLower()) 1229 ParameterDefn theParam;
1230 if (TryGetParameter(parm, out theParam))
1041 { 1231 {
1042 case "detailedstats": val = (int)m_detailedStatsStep; break; 1232 val = theParam.getter(this);
1043 case "meshlod": val = (float)m_meshLOD; break; 1233 ret = true;
1044 case "sculptlod": val = (float)m_sculptLOD; break;
1045 case "maxsubstep": val = (float)m_maxSubSteps; break;
1046 case "fixedtimestep": val = m_fixedTimeStep; break;
1047 case "maxobjectmass": val = m_maximumObjectMass; break;
1048
1049 case "defaultfriction": val = m_params[0].defaultFriction; break;
1050 case "defaultdensity": val = m_params[0].defaultDensity; break;
1051 case "defaultrestitution": val = m_params[0].defaultRestitution; break;
1052 case "collisionmargin": val = m_params[0].collisionMargin; break;
1053 case "gravity": val = m_params[0].gravity; break;
1054
1055 case "lineardamping": val = m_params[0].linearDamping; break;
1056 case "angulardamping": val = m_params[0].angularDamping; break;
1057 case "deactivationtime": val = m_params[0].deactivationTime; break;
1058 case "linearsleepingthreshold": val = m_params[0].linearSleepingThreshold; break;
1059 case "angularsleepingthreshold": val = m_params[0].angularDamping; break;
1060 case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break;
1061 case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break;
1062 case "contactprocessingthreshold": val = m_params[0].contactProcessingThreshold; break;
1063 case "maxPersistantmanifoldpoolSize": val = m_params[0].maxPersistantManifoldPoolSize; break;
1064 case "shoulddisablecontactpooldynamicallocation": val = m_params[0].shouldDisableContactPoolDynamicAllocation; break;
1065 case "shouldforceupdateallaabbs": val = m_params[0].shouldForceUpdateAllAabbs; break;
1066 case "shouldrandomizesolverorder": val = m_params[0].shouldRandomizeSolverOrder; break;
1067 case "shouldsplitsimulationislands": val = m_params[0].shouldSplitSimulationIslands; break;
1068 case "shouldenablefrictioncaching": val = m_params[0].shouldEnableFrictionCaching; break;
1069 case "numberofsolveriterations": val = m_params[0].numberOfSolverIterations; break;
1070
1071 case "terrainfriction": val = m_params[0].terrainFriction; break;
1072 case "terrainhitfraction": val = m_params[0].terrainHitFraction; break;
1073 case "terrainrestitution": val = m_params[0].terrainRestitution; break;
1074
1075 case "avatarfriction": val = m_params[0].avatarFriction; break;
1076 case "avatardensity": val = m_params[0].avatarDensity; break;
1077 case "avatarrestitution": val = m_params[0].avatarRestitution; break;
1078 case "avatarcapsuleradius": val = m_params[0].avatarCapsuleRadius; break;
1079 case "avatarcapsuleheight": val = m_params[0].avatarCapsuleHeight; break;
1080 case "avatarcontactprocessingthreshold": val = m_params[0].avatarContactProcessingThreshold; break;
1081 default: ret = false; break;
1082
1083 } 1234 }
1084 value = val; 1235 value = val;
1085 return ret; 1236 return ret;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 54a8cfd..89fd9b7 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -32,6 +32,28 @@ using OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin { 33namespace OpenSim.Region.Physics.BulletSPlugin {
34 34
35// Classes to allow some type checking for the API
36public struct BulletSim
37{
38 public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; }
39 public IntPtr Ptr;
40 public uint ID;
41}
42
43public struct BulletBody
44{
45 public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
46 public IntPtr Ptr;
47 public uint ID;
48}
49
50public struct BulletConstraint
51{
52 public BulletConstraint(IntPtr xx) { Ptr = xx; }
53 public IntPtr Ptr;
54}
55
56// ===============================================================================
35[StructLayout(LayoutKind.Sequential)] 57[StructLayout(LayoutKind.Sequential)]
36public struct ConvexHull 58public struct ConvexHull
37{ 59{
@@ -142,6 +164,11 @@ public struct ConfigurationParameters
142 public float shouldEnableFrictionCaching; 164 public float shouldEnableFrictionCaching;
143 public float numberOfSolverIterations; 165 public float numberOfSolverIterations;
144 166
167 public float linkConstraintUseFrameOffset;
168 public float linkConstraintEnableTransMotor;
169 public float linkConstraintTransMotorMaxVel;
170 public float linkConstraintTransMotorMaxForce;
171
145 public const float numericTrue = 1f; 172 public const float numericTrue = 1f;
146 public const float numericFalse = 0f; 173 public const float numericFalse = 0f;
147} 174}
@@ -162,6 +189,7 @@ public enum CollisionFlags : uint
162 PHYSICAL_OBJECT = 1 << 12, 189 PHYSICAL_OBJECT = 1 << 12,
163}; 190};
164 191
192// ===============================================================================
165static class BulletSimAPI { 193static class BulletSimAPI {
166 194
167[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 195[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -214,6 +242,7 @@ public static extern bool CreateObject(uint worldID, ShapeData shapeData);
214[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 242[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
215public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); 243public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas);
216 244
245/* Remove old functionality
217[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 246[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
218public static extern void AddConstraint(uint worldID, uint id1, uint id2, 247public static extern void AddConstraint(uint worldID, uint id1, uint id2,
219 Vector3 frame1, Quaternion frame1rot, 248 Vector3 frame1, Quaternion frame1rot,
@@ -225,6 +254,7 @@ public static extern bool RemoveConstraintByID(uint worldID, uint id1);
225 254
226[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 255[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
227public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); 256public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2);
257 */
228 258
229[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 259[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
230public static extern Vector3 GetObjectPosition(uint WorldID, uint id); 260public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
@@ -350,8 +380,22 @@ public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData);
350[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 380[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
351public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2, 381public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2,
352 Vector3 frame1loc, Quaternion frame1rot, 382 Vector3 frame1loc, Quaternion frame1rot,
353 Vector3 frame2loc, Quaternion frame2rot, 383 Vector3 frame2loc, Quaternion frame2rot);
354 Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular); 384
385[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
386public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
387
388[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
389public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
390
391[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
392public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
393
394[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
395public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
396
397[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
398public static extern bool CalculateTransforms2(IntPtr constrain);
355 399
356[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 400[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
357public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); 401public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain);