diff options
author | Justin Clark-Casey (justincc) | 2012-07-26 23:46:54 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-07-26 23:46:54 +0100 |
commit | 0aaf52fca43d0fed461b228dfad4b5d3f42da2b7 (patch) | |
tree | 847a357593e5aa532c397d3886366e4c4922958f /OpenSim/Region | |
parent | When copying items, copy the item description field instead of the asset desc... (diff) | |
parent | BulletSim: update BulletSim DLLs and SOs (diff) | |
download | opensim-SC-0aaf52fca43d0fed461b228dfad4b5d3f42da2b7.zip opensim-SC-0aaf52fca43d0fed461b228dfad4b5d3f42da2b7.tar.gz opensim-SC-0aaf52fca43d0fed461b228dfad4b5d3f42da2b7.tar.bz2 opensim-SC-0aaf52fca43d0fed461b228dfad4b5d3f42da2b7.tar.xz |
Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
Diffstat (limited to 'OpenSim/Region')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | 115 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs | 178 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 66 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 647 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 48 |
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 | */ | ||
27 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Text; | ||
30 | using OpenMetaverse; | ||
31 | |||
32 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
33 | { | ||
34 | |||
35 | public 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 | */ | ||
27 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Text; | ||
30 | using log4net; | ||
31 | using OpenMetaverse; | ||
32 | |||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
34 | { | ||
35 | |||
36 | public 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 | ||
33 | namespace OpenSim.Region.Physics.BulletSPlugin { | 33 | namespace OpenSim.Region.Physics.BulletSPlugin { |
34 | 34 | ||
35 | // Classes to allow some type checking for the API | ||
36 | public struct BulletSim | ||
37 | { | ||
38 | public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; } | ||
39 | public IntPtr Ptr; | ||
40 | public uint ID; | ||
41 | } | ||
42 | |||
43 | public struct BulletBody | ||
44 | { | ||
45 | public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; } | ||
46 | public IntPtr Ptr; | ||
47 | public uint ID; | ||
48 | } | ||
49 | |||
50 | public 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)] |
36 | public struct ConvexHull | 58 | public 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 | // =============================================================================== | ||
165 | static class BulletSimAPI { | 193 | static 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] |
215 | public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); | 243 | public 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] |
218 | public static extern void AddConstraint(uint worldID, uint id1, uint id2, | 247 | public 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] |
227 | public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); | 256 | public 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] |
230 | public static extern Vector3 GetObjectPosition(uint WorldID, uint id); | 260 | public 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] |
351 | public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2, | 381 | public 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] | ||
386 | public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); | ||
387 | |||
388 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
389 | public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi); | ||
390 | |||
391 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
392 | public static extern bool UseFrameOffset2(IntPtr constrain, float enable); | ||
393 | |||
394 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
395 | public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce); | ||
396 | |||
397 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
398 | public static extern bool CalculateTransforms2(IntPtr constrain); | ||
355 | 399 | ||
356 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 400 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
357 | public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); | 401 | public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); |