diff options
author | Melanie | 2012-08-16 02:46:48 +0100 |
---|---|---|
committer | Melanie | 2012-08-16 02:46:48 +0100 |
commit | 90ad98370aead53e886832a83a3e8793f361426e (patch) | |
tree | b7076c5fb7ecf75d1ad31f7756543ade8fbf1b49 /OpenSim/Region/Physics/BulletSPlugin | |
parent | Remove AreUpdatesSuspended flag because it does nothing (diff) | |
parent | Do a proper null check to avoid the overloaded operator == trap (diff) | |
download | opensim-SC-90ad98370aead53e886832a83a3e8793f361426e.zip opensim-SC-90ad98370aead53e886832a83a3e8793f361426e.tar.gz opensim-SC-90ad98370aead53e886832a83a3e8793f361426e.tar.bz2 opensim-SC-90ad98370aead53e886832a83a3e8793f361426e.tar.xz |
Merge branch 'master' into careminster
Conflicts:
OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
Diffstat (limited to '')
10 files changed, 430 insertions, 215 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs index 72df6b9..683bc51 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs | |||
@@ -37,7 +37,8 @@ public class BS6DofConstraint : BSConstraint | |||
37 | // Create a btGeneric6DofConstraint | 37 | // Create a btGeneric6DofConstraint |
38 | public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, | 38 | public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, |
39 | Vector3 frame1, Quaternion frame1rot, | 39 | Vector3 frame1, Quaternion frame1rot, |
40 | Vector3 frame2, Quaternion frame2rot ) | 40 | Vector3 frame2, Quaternion frame2rot, |
41 | bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) | ||
41 | { | 42 | { |
42 | m_world = world; | 43 | m_world = world; |
43 | m_body1 = obj1; | 44 | m_body1 = obj1; |
@@ -46,16 +47,45 @@ public class BS6DofConstraint : BSConstraint | |||
46 | BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, | 47 | BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, |
47 | frame1, frame1rot, | 48 | frame1, frame1rot, |
48 | frame2, frame2rot, | 49 | frame2, frame2rot, |
49 | true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/)); | 50 | useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); |
50 | m_enabled = true; | 51 | m_enabled = true; |
51 | } | 52 | } |
52 | 53 | ||
54 | public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, | ||
55 | Vector3 joinPoint, | ||
56 | bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) | ||
57 | { | ||
58 | m_world = world; | ||
59 | m_body1 = obj1; | ||
60 | m_body2 = obj2; | ||
61 | m_constraint = new BulletConstraint( | ||
62 | BulletSimAPI.Create6DofConstraintToPoint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, | ||
63 | joinPoint, | ||
64 | useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); | ||
65 | m_enabled = true; | ||
66 | } | ||
67 | |||
68 | public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) | ||
69 | { | ||
70 | bool ret = false; | ||
71 | if (m_enabled) | ||
72 | { | ||
73 | BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot); | ||
74 | ret = true; | ||
75 | } | ||
76 | return ret; | ||
77 | } | ||
78 | |||
53 | public bool SetCFMAndERP(float cfm, float erp) | 79 | public bool SetCFMAndERP(float cfm, float erp) |
54 | { | 80 | { |
55 | bool ret = true; | 81 | bool ret = false; |
56 | BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); | 82 | if (m_enabled) |
57 | BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); | 83 | { |
58 | BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); | 84 | BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); |
85 | BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); | ||
86 | BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); | ||
87 | ret = true; | ||
88 | } | ||
59 | return ret; | 89 | return ret; |
60 | } | 90 | } |
61 | 91 | ||
@@ -76,5 +106,13 @@ public class BS6DofConstraint : BSConstraint | |||
76 | ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); | 106 | ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); |
77 | return ret; | 107 | return ret; |
78 | } | 108 | } |
109 | |||
110 | public bool SetBreakingImpulseThreshold(float threshold) | ||
111 | { | ||
112 | bool ret = false; | ||
113 | if (m_enabled) | ||
114 | ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold); | ||
115 | return ret; | ||
116 | } | ||
79 | } | 117 | } |
80 | } | 118 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index f164afe..e2f7af9 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -137,7 +137,7 @@ public class BSCharacter : PhysicsActor | |||
137 | // called when this character is being destroyed and the resources should be released | 137 | // called when this character is being destroyed and the resources should be released |
138 | public void Destroy() | 138 | public void Destroy() |
139 | { | 139 | { |
140 | // DetailLog("{0},Destroy", LocalID); | 140 | // DetailLog("{0},BSCharacter.Destroy", LocalID); |
141 | _scene.TaintedObject("BSCharacter.destroy", delegate() | 141 | _scene.TaintedObject("BSCharacter.destroy", delegate() |
142 | { | 142 | { |
143 | BulletSimAPI.DestroyObject(_scene.WorldID, _localID); | 143 | BulletSimAPI.DestroyObject(_scene.WorldID, _localID); |
@@ -209,7 +209,7 @@ public class BSCharacter : PhysicsActor | |||
209 | 209 | ||
210 | _scene.TaintedObject("BSCharacter.setPosition", delegate() | 210 | _scene.TaintedObject("BSCharacter.setPosition", delegate() |
211 | { | 211 | { |
212 | DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 212 | DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
213 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); | 213 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); |
214 | }); | 214 | }); |
215 | } | 215 | } |
@@ -226,7 +226,7 @@ public class BSCharacter : PhysicsActor | |||
226 | float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); | 226 | float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); |
227 | if (_position.Z < terrainHeight) | 227 | if (_position.Z < terrainHeight) |
228 | { | 228 | { |
229 | DetailLog("{0},PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); | 229 | DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); |
230 | _position.Z = terrainHeight + 2.0f; | 230 | _position.Z = terrainHeight + 2.0f; |
231 | ret = true; | 231 | ret = true; |
232 | } | 232 | } |
@@ -368,7 +368,7 @@ public class BSCharacter : PhysicsActor | |||
368 | set { _buoyancy = value; | 368 | set { _buoyancy = value; |
369 | _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() | 369 | _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() |
370 | { | 370 | { |
371 | DetailLog("{0},setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 371 | DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
372 | BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); | 372 | BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); |
373 | }); | 373 | }); |
374 | } | 374 | } |
@@ -415,7 +415,7 @@ public class BSCharacter : PhysicsActor | |||
415 | // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); | 415 | // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); |
416 | _scene.TaintedObject("BSCharacter.AddForce", delegate() | 416 | _scene.TaintedObject("BSCharacter.AddForce", delegate() |
417 | { | 417 | { |
418 | DetailLog("{0},setAddForce,taint,addedForce={1}", LocalID, _force); | 418 | DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); |
419 | BulletSimAPI.AddObjectForce2(Body.Ptr, _force); | 419 | BulletSimAPI.AddObjectForce2(Body.Ptr, _force); |
420 | }); | 420 | }); |
421 | } | 421 | } |
@@ -488,9 +488,11 @@ public class BSCharacter : PhysicsActor | |||
488 | // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. | 488 | // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. |
489 | // base.RequestPhysicsterseUpdate(); | 489 | // base.RequestPhysicsterseUpdate(); |
490 | 490 | ||
491 | /* | ||
491 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | 492 | DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", |
492 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, | 493 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, |
493 | entprop.Acceleration, entprop.RotationalVelocity); | 494 | entprop.Acceleration, entprop.RotationalVelocity); |
495 | */ | ||
494 | } | 496 | } |
495 | 497 | ||
496 | // Called by the scene when a collision with this object is reported | 498 | // Called by the scene when a collision with this object is reported |
@@ -507,6 +509,7 @@ public class BSCharacter : PhysicsActor | |||
507 | { | 509 | { |
508 | _collidingGroundStep = _scene.SimulationStep; | 510 | _collidingGroundStep = _scene.SimulationStep; |
509 | } | 511 | } |
512 | // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); | ||
510 | 513 | ||
511 | // throttle collisions to the rate specified in the subscription | 514 | // throttle collisions to the rate specified in the subscription |
512 | if (_subscribedEventsMs != 0) { | 515 | if (_subscribedEventsMs != 0) { |
@@ -535,7 +538,10 @@ public class BSCharacter : PhysicsActor | |||
535 | if (collisionCollection == null) | 538 | if (collisionCollection == null) |
536 | collisionCollection = new CollisionEventUpdate(); | 539 | collisionCollection = new CollisionEventUpdate(); |
537 | base.SendCollisionUpdate(collisionCollection); | 540 | base.SendCollisionUpdate(collisionCollection); |
538 | collisionCollection.Clear(); | 541 | // If there were any collisions in the collection, make sure we don't use the |
542 | // same instance next time. | ||
543 | if (collisionCollection.Count > 0) | ||
544 | collisionCollection = null; | ||
539 | // End kludge | 545 | // End kludge |
540 | } | 546 | } |
541 | 547 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index da26b72..25084d8 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | |||
@@ -80,10 +80,33 @@ public abstract class BSConstraint : IDisposable | |||
80 | bool ret = false; | 80 | bool ret = false; |
81 | if (m_enabled) | 81 | if (m_enabled) |
82 | { | 82 | { |
83 | // Recompute the internal transforms | ||
83 | BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); | 84 | BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); |
84 | ret = true; | 85 | ret = true; |
85 | } | 86 | } |
86 | return ret; | 87 | return ret; |
87 | } | 88 | } |
89 | |||
90 | // Reset this constraint making sure it has all its internal structures | ||
91 | // recomputed and is enabled and ready to go. | ||
92 | public virtual bool RecomputeConstraintVariables(float mass) | ||
93 | { | ||
94 | bool ret = false; | ||
95 | if (m_enabled) | ||
96 | { | ||
97 | ret = CalculateTransforms(); | ||
98 | if (ret) | ||
99 | { | ||
100 | // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}", | ||
101 | // BSScene.DetailLogZero, Body1.ID, Body2.ID); | ||
102 | BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); | ||
103 | } | ||
104 | else | ||
105 | { | ||
106 | m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID); | ||
107 | } | ||
108 | } | ||
109 | return ret; | ||
110 | } | ||
88 | } | 111 | } |
89 | } | 112 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs index 3df2ddc..22ea367 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs | |||
@@ -56,21 +56,25 @@ public class BSConstraintCollection : IDisposable | |||
56 | 56 | ||
57 | public void Clear() | 57 | public void Clear() |
58 | { | 58 | { |
59 | foreach (BSConstraint cons in m_constraints) | 59 | lock (m_constraints) |
60 | { | 60 | { |
61 | cons.Dispose(); | 61 | foreach (BSConstraint cons in m_constraints) |
62 | { | ||
63 | cons.Dispose(); | ||
64 | } | ||
65 | m_constraints.Clear(); | ||
62 | } | 66 | } |
63 | m_constraints.Clear(); | ||
64 | } | 67 | } |
65 | 68 | ||
66 | public bool AddConstraint(BSConstraint cons) | 69 | public bool AddConstraint(BSConstraint cons) |
67 | { | 70 | { |
68 | // There is only one constraint between any bodies. Remove any old just to make sure. | 71 | lock (m_constraints) |
69 | RemoveAndDestroyConstraint(cons.Body1, cons.Body2); | 72 | { |
70 | 73 | // There is only one constraint between any bodies. Remove any old just to make sure. | |
71 | m_world.scene.DetailLog("{0},BSConstraintCollection.AddConstraint,call,body1={1},body2={2}", BSScene.DetailLogZero, cons.Body1.ID, cons.Body2.ID); | 74 | RemoveAndDestroyConstraint(cons.Body1, cons.Body2); |
72 | 75 | ||
73 | m_constraints.Add(cons); | 76 | m_constraints.Add(cons); |
77 | } | ||
74 | 78 | ||
75 | return true; | 79 | return true; |
76 | } | 80 | } |
@@ -84,16 +88,19 @@ public class BSConstraintCollection : IDisposable | |||
84 | 88 | ||
85 | uint lookingID1 = body1.ID; | 89 | uint lookingID1 = body1.ID; |
86 | uint lookingID2 = body2.ID; | 90 | uint lookingID2 = body2.ID; |
87 | ForEachConstraint(delegate(BSConstraint constrain) | 91 | lock (m_constraints) |
88 | { | 92 | { |
89 | if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) | 93 | foreach (BSConstraint constrain in m_constraints) |
90 | || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1)) | ||
91 | { | 94 | { |
92 | foundConstraint = constrain; | 95 | if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) |
93 | found = true; | 96 | || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1)) |
97 | { | ||
98 | foundConstraint = constrain; | ||
99 | found = true; | ||
100 | break; | ||
101 | } | ||
94 | } | 102 | } |
95 | return found; | 103 | } |
96 | }); | ||
97 | returnConstraint = foundConstraint; | 104 | returnConstraint = foundConstraint; |
98 | return found; | 105 | return found; |
99 | } | 106 | } |
@@ -103,23 +110,33 @@ public class BSConstraintCollection : IDisposable | |||
103 | // Return 'true' if a constraint was found and destroyed. | 110 | // Return 'true' if a constraint was found and destroyed. |
104 | public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) | 111 | public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) |
105 | { | 112 | { |
106 | // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID); | ||
107 | |||
108 | bool ret = false; | 113 | bool ret = false; |
109 | BSConstraint constrain; | 114 | lock (m_constraints) |
115 | { | ||
116 | BSConstraint constrain; | ||
117 | if (this.TryGetConstraint(body1, body2, out constrain)) | ||
118 | { | ||
119 | // remove the constraint from our collection | ||
120 | RemoveAndDestroyConstraint(constrain); | ||
121 | ret = true; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | return ret; | ||
126 | } | ||
110 | 127 | ||
111 | if (this.TryGetConstraint(body1, body2, out constrain)) | 128 | // The constraint MUST exist in the collection |
129 | public bool RemoveAndDestroyConstraint(BSConstraint constrain) | ||
130 | { | ||
131 | lock (m_constraints) | ||
112 | { | 132 | { |
113 | m_world.scene.DetailLog("{0},BSConstraintCollection.RemoveAndDestroyConstraint,taint,body1={1},body2={2}", BSScene.DetailLogZero, body1.ID, body2.ID); | ||
114 | // remove the constraint from our collection | 133 | // remove the constraint from our collection |
115 | m_constraints.Remove(constrain); | 134 | m_constraints.Remove(constrain); |
116 | // tell the engine that all its structures need to be freed | ||
117 | constrain.Dispose(); | ||
118 | // we destroyed something | ||
119 | ret = true; | ||
120 | } | 135 | } |
121 | 136 | // tell the engine that all its structures need to be freed | |
122 | return ret; | 137 | constrain.Dispose(); |
138 | // we destroyed something | ||
139 | return true; | ||
123 | } | 140 | } |
124 | 141 | ||
125 | // Remove all constraints that reference the passed body. | 142 | // Remove all constraints that reference the passed body. |
@@ -130,16 +147,15 @@ public class BSConstraintCollection : IDisposable | |||
130 | 147 | ||
131 | List<BSConstraint> toRemove = new List<BSConstraint>(); | 148 | List<BSConstraint> toRemove = new List<BSConstraint>(); |
132 | uint lookingID = body1.ID; | 149 | uint lookingID = body1.ID; |
133 | ForEachConstraint(delegate(BSConstraint constrain) | 150 | lock (m_constraints) |
134 | { | 151 | { |
135 | if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) | 152 | foreach (BSConstraint constrain in m_constraints) |
136 | { | 153 | { |
137 | toRemove.Add(constrain); | 154 | if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) |
155 | { | ||
156 | toRemove.Add(constrain); | ||
157 | } | ||
138 | } | 158 | } |
139 | return false; | ||
140 | }); | ||
141 | lock (m_constraints) | ||
142 | { | ||
143 | foreach (BSConstraint constrain in toRemove) | 159 | foreach (BSConstraint constrain in toRemove) |
144 | { | 160 | { |
145 | m_constraints.Remove(constrain); | 161 | m_constraints.Remove(constrain); |
@@ -151,28 +167,16 @@ public class BSConstraintCollection : IDisposable | |||
151 | 167 | ||
152 | public bool RecalculateAllConstraints() | 168 | public bool RecalculateAllConstraints() |
153 | { | 169 | { |
154 | ForEachConstraint(delegate(BSConstraint constrain) | 170 | bool ret = false; |
155 | { | ||
156 | constrain.CalculateTransforms(); | ||
157 | return false; | ||
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) | 171 | lock (m_constraints) |
167 | { | 172 | { |
168 | foreach (BSConstraint constrain in m_constraints) | 173 | foreach (BSConstraint constrain in m_constraints) |
169 | { | 174 | { |
170 | if (action(constrain)) | 175 | constrain.CalculateTransforms(); |
171 | break; | 176 | ret = true; |
172 | } | 177 | } |
173 | } | 178 | } |
179 | return ret; | ||
174 | } | 180 | } |
175 | |||
176 | |||
177 | } | 181 | } |
178 | } | 182 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index c197e61..5a9f135 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -613,7 +613,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
613 | MoveAngular(pTimestep); | 613 | MoveAngular(pTimestep); |
614 | LimitRotation(pTimestep); | 614 | LimitRotation(pTimestep); |
615 | 615 | ||
616 | DetailLog("{0},Dynamics,done,pos={1},force={2},velocity={3},angvel={4}", | 616 | DetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", |
617 | m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); | 617 | m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); |
618 | }// end Step | 618 | }// end Step |
619 | 619 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs new file mode 100755 index 0000000..d68048b --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs | |||
@@ -0,0 +1,55 @@ | |||
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 | class BSHingeConstraint : BSConstraint | ||
36 | { | ||
37 | public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, | ||
38 | Vector3 pivotInA, Vector3 pivotInB, | ||
39 | Vector3 axisInA, Vector3 axisInB, | ||
40 | bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) | ||
41 | { | ||
42 | m_world = world; | ||
43 | m_body1 = obj1; | ||
44 | m_body2 = obj2; | ||
45 | m_constraint = new BulletConstraint( | ||
46 | BulletSimAPI.CreateHingeConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, | ||
47 | pivotInA, pivotInB, | ||
48 | axisInA, axisInB, | ||
49 | useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); | ||
50 | m_enabled = true; | ||
51 | } | ||
52 | |||
53 | } | ||
54 | |||
55 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 4a71612..087b9bb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -37,11 +37,12 @@ public class BSLinkset | |||
37 | private static string LogHeader = "[BULLETSIM LINKSET]"; | 37 | private static string LogHeader = "[BULLETSIM LINKSET]"; |
38 | 38 | ||
39 | private BSPrim m_linksetRoot; | 39 | private BSPrim m_linksetRoot; |
40 | public BSPrim Root { get { return m_linksetRoot; } } | 40 | public BSPrim LinksetRoot { get { return m_linksetRoot; } } |
41 | 41 | ||
42 | private BSScene m_scene; | 42 | private BSScene m_physicsScene; |
43 | public BSScene Scene { get { return m_scene; } } | 43 | public BSScene PhysicsScene { get { return m_physicsScene; } } |
44 | 44 | ||
45 | // The children under the root in this linkset | ||
45 | private List<BSPrim> m_children; | 46 | private List<BSPrim> m_children; |
46 | 47 | ||
47 | // We lock the diddling of linkset classes to prevent any badness. | 48 | // We lock the diddling of linkset classes to prevent any badness. |
@@ -73,7 +74,7 @@ public class BSLinkset | |||
73 | public BSLinkset(BSScene scene, BSPrim parent) | 74 | public BSLinkset(BSScene scene, BSPrim parent) |
74 | { | 75 | { |
75 | // A simple linkset of one (no children) | 76 | // A simple linkset of one (no children) |
76 | m_scene = scene; | 77 | m_physicsScene = scene; |
77 | m_linksetRoot = parent; | 78 | m_linksetRoot = parent; |
78 | m_children = new List<BSPrim>(); | 79 | m_children = new List<BSPrim>(); |
79 | m_mass = parent.MassRaw; | 80 | m_mass = parent.MassRaw; |
@@ -91,6 +92,9 @@ public class BSLinkset | |||
91 | return this; | 92 | return this; |
92 | } | 93 | } |
93 | 94 | ||
95 | // Remove a child from a linkset. | ||
96 | // Returns a new linkset for the child which is a linkset of one (just the | ||
97 | // orphened child). | ||
94 | public BSLinkset RemoveMeFromLinkset(BSPrim child) | 98 | public BSLinkset RemoveMeFromLinkset(BSPrim child) |
95 | { | 99 | { |
96 | lock (m_linksetActivityLock) | 100 | lock (m_linksetActivityLock) |
@@ -114,60 +118,9 @@ public class BSLinkset | |||
114 | } | 118 | } |
115 | 119 | ||
116 | // The child is down to a linkset of just itself | 120 | // The child is down to a linkset of just itself |
117 | return new BSLinkset(Scene, child); | 121 | return new BSLinkset(PhysicsScene, child); |
118 | } | 122 | } |
119 | 123 | ||
120 | /* DEPRECATED: this is really bad in that it trys to unlink other prims. | ||
121 | // An existing linkset had one of its members rebuilt or something. | ||
122 | // Go through the linkset and rebuild the pointers to the bodies of the linkset members. | ||
123 | public BSLinkset RefreshLinkset(BSPrim requestor) | ||
124 | { | ||
125 | BSLinkset ret = requestor.Linkset; | ||
126 | |||
127 | lock (m_linksetActivityLock) | ||
128 | { | ||
129 | // The body pointer is refetched in case anything has moved. | ||
130 | System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID); | ||
131 | if (aPtr == System.IntPtr.Zero) | ||
132 | { | ||
133 | // That's odd. We can't find the root of the linkset. | ||
134 | // The linkset is somehow dead. The requestor is now a member of a linkset of one. | ||
135 | DetailLog("{0},RefreshLinkset.RemoveRoot,child={1}", m_linksetRoot.LocalID, m_linksetRoot.LocalID); | ||
136 | ret = RemoveMeFromLinkset(m_linksetRoot); | ||
137 | } | ||
138 | else | ||
139 | { | ||
140 | // Reconstruct the pointer to the body of the linkset root. | ||
141 | DetailLog("{0},RefreshLinkset.RebuildRoot,rootID={1},ptr={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, aPtr); | ||
142 | m_linksetRoot.Body = new BulletBody(m_linksetRoot.LocalID, aPtr); | ||
143 | |||
144 | List<BSPrim> toRemove = new List<BSPrim>(); | ||
145 | foreach (BSPrim bsp in m_children) | ||
146 | { | ||
147 | aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, bsp.LocalID); | ||
148 | if (aPtr == System.IntPtr.Zero) | ||
149 | { | ||
150 | toRemove.Add(bsp); | ||
151 | } | ||
152 | else | ||
153 | { | ||
154 | // Reconstruct the pointer to the body of the linkset root. | ||
155 | DetailLog("{0},RefreshLinkset.RebuildChild,rootID={1},ptr={2}", bsp.LocalID, m_linksetRoot.LocalID, aPtr); | ||
156 | bsp.Body = new BulletBody(bsp.LocalID, aPtr); | ||
157 | } | ||
158 | } | ||
159 | foreach (BSPrim bsp in toRemove) | ||
160 | { | ||
161 | RemoveChildFromOtherLinkset(bsp); | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | |||
166 | return ret; | ||
167 | } | ||
168 | */ | ||
169 | |||
170 | |||
171 | // Return 'true' if the passed object is the root object of this linkset | 124 | // Return 'true' if the passed object is the root object of this linkset |
172 | public bool IsRoot(BSPrim requestor) | 125 | public bool IsRoot(BSPrim requestor) |
173 | { | 126 | { |
@@ -183,12 +136,15 @@ public class BSLinkset | |||
183 | public bool HasChild(BSPrim child) | 136 | public bool HasChild(BSPrim child) |
184 | { | 137 | { |
185 | bool ret = false; | 138 | bool ret = false; |
186 | foreach (BSPrim bp in m_children) | 139 | lock (m_linksetActivityLock) |
187 | { | 140 | { |
188 | if (child.LocalID == bp.LocalID) | 141 | foreach (BSPrim bp in m_children) |
189 | { | 142 | { |
190 | ret = true; | 143 | if (child.LocalID == bp.LocalID) |
191 | break; | 144 | { |
145 | ret = true; | ||
146 | break; | ||
147 | } | ||
192 | } | 148 | } |
193 | } | 149 | } |
194 | return ret; | 150 | return ret; |
@@ -209,13 +165,16 @@ public class BSLinkset | |||
209 | OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; | 165 | OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; |
210 | float totalMass = m_linksetRoot.MassRaw; | 166 | float totalMass = m_linksetRoot.MassRaw; |
211 | 167 | ||
212 | foreach (BSPrim bp in m_children) | 168 | lock (m_linksetActivityLock) |
213 | { | 169 | { |
214 | com += bp.Position * bp.MassRaw; | 170 | foreach (BSPrim bp in m_children) |
215 | totalMass += bp.MassRaw; | 171 | { |
172 | com += bp.Position * bp.MassRaw; | ||
173 | totalMass += bp.MassRaw; | ||
174 | } | ||
175 | if (totalMass != 0f) | ||
176 | com /= totalMass; | ||
216 | } | 177 | } |
217 | if (totalMass != 0f) | ||
218 | com /= totalMass; | ||
219 | 178 | ||
220 | return com; | 179 | return com; |
221 | } | 180 | } |
@@ -224,29 +183,84 @@ public class BSLinkset | |||
224 | { | 183 | { |
225 | OMV.Vector3 com = m_linksetRoot.Position; | 184 | OMV.Vector3 com = m_linksetRoot.Position; |
226 | 185 | ||
227 | foreach (BSPrim bp in m_children) | 186 | lock (m_linksetActivityLock) |
228 | { | 187 | { |
229 | com += bp.Position * bp.MassRaw; | 188 | foreach (BSPrim bp in m_children) |
189 | { | ||
190 | com += bp.Position * bp.MassRaw; | ||
191 | } | ||
192 | com /= (m_children.Count + 1); | ||
230 | } | 193 | } |
231 | com /= (m_children.Count + 1); | ||
232 | 194 | ||
233 | return com; | 195 | return com; |
234 | } | 196 | } |
235 | 197 | ||
198 | // When physical properties are changed the linkset needs to recalculate | ||
199 | // its internal properties. | ||
200 | public void Refresh(BSPrim requestor) | ||
201 | { | ||
202 | // If there are no children, there aren't any constraints to recompute | ||
203 | if (!HasAnyChildren) | ||
204 | return; | ||
205 | |||
206 | // Only the root does the recomputation | ||
207 | if (IsRoot(requestor)) | ||
208 | { | ||
209 | PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() | ||
210 | { | ||
211 | RecomputeLinksetConstraintVariables(); | ||
212 | }); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | // Call each of the constraints that make up this linkset and recompute the | ||
217 | // various transforms and variables. Used when objects are added or removed | ||
218 | // from a linkset to make sure the constraints know about the new mass and | ||
219 | // geometry. | ||
220 | // Must only be called at taint time!! | ||
221 | private bool RecomputeLinksetConstraintVariables() | ||
222 | { | ||
223 | float linksetMass = LinksetMass; | ||
224 | lock (m_linksetActivityLock) | ||
225 | { | ||
226 | foreach (BSPrim child in m_children) | ||
227 | { | ||
228 | BSConstraint constrain; | ||
229 | if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain)) | ||
230 | { | ||
231 | // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", | ||
232 | // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); | ||
233 | constrain.RecomputeConstraintVariables(linksetMass); | ||
234 | } | ||
235 | else | ||
236 | { | ||
237 | // Non-fatal error that can happen when children are being added to the linkset but | ||
238 | // their constraints have not been created yet. | ||
239 | // Caused by the fact that m_children is built at run time but building constraints | ||
240 | // happens at taint time. | ||
241 | // m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}", | ||
242 | // m_linksetRoot.Body.ID, child.Body.ID); | ||
243 | } | ||
244 | } | ||
245 | } | ||
246 | return false; | ||
247 | } | ||
248 | |||
236 | // I am the root of a linkset and a new child is being added | 249 | // I am the root of a linkset and a new child is being added |
237 | // Called while LinkActivity is locked. | 250 | // Called while LinkActivity is locked. |
238 | public void AddChildToLinkset(BSPrim child) | 251 | private void AddChildToLinkset(BSPrim child) |
239 | { | 252 | { |
240 | if (!HasChild(child)) | 253 | if (!HasChild(child)) |
241 | { | 254 | { |
242 | m_children.Add(child); | 255 | m_children.Add(child); |
243 | 256 | ||
244 | BSPrim root = Root; // capture the root as of now | 257 | BSPrim rootx = LinksetRoot; // capture the root as of now |
245 | m_scene.TaintedObject("AddChildToLinkset", delegate() | 258 | BSPrim childx = child; |
259 | m_physicsScene.TaintedObject("AddChildToLinkset", delegate() | ||
246 | { | 260 | { |
247 | DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); | 261 | // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); |
248 | DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); | 262 | // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); |
249 | PhysicallyLinkAChildToRoot(root, child); // build the physical binding between me and the child | 263 | PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child |
250 | }); | 264 | }); |
251 | } | 265 | } |
252 | return; | 266 | return; |
@@ -257,31 +271,34 @@ public class BSLinkset | |||
257 | // it's still connected to the linkset. | 271 | // it's still connected to the linkset. |
258 | // Normal OpenSimulator operation will never do this because other SceneObjectPart information | 272 | // Normal OpenSimulator operation will never do this because other SceneObjectPart information |
259 | // has to be updated also (like pointer to prim's parent). | 273 | // has to be updated also (like pointer to prim's parent). |
260 | public void RemoveChildFromOtherLinkset(BSPrim pchild) | 274 | private void RemoveChildFromOtherLinkset(BSPrim pchild) |
261 | { | 275 | { |
262 | pchild.Linkset = new BSLinkset(m_scene, pchild); | 276 | pchild.Linkset = new BSLinkset(m_physicsScene, pchild); |
263 | RemoveChildFromLinkset(pchild); | 277 | RemoveChildFromLinkset(pchild); |
264 | } | 278 | } |
265 | 279 | ||
266 | // I am the root of a linkset and one of my children is being removed. | 280 | // I am the root of a linkset and one of my children is being removed. |
267 | // Safe to call even if the child is not really in my linkset. | 281 | // Safe to call even if the child is not really in my linkset. |
268 | public void RemoveChildFromLinkset(BSPrim child) | 282 | private void RemoveChildFromLinkset(BSPrim child) |
269 | { | 283 | { |
270 | if (m_children.Remove(child)) | 284 | if (m_children.Remove(child)) |
271 | { | 285 | { |
272 | BSPrim root = Root; // capture the root as of now | 286 | BSPrim rootx = LinksetRoot; // capture the root as of now |
273 | m_scene.TaintedObject("RemoveChildFromLinkset", delegate() | 287 | BSPrim childx = child; |
288 | m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() | ||
274 | { | 289 | { |
275 | DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); | 290 | // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); |
276 | DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); | 291 | // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); |
277 | 292 | ||
278 | PhysicallyUnlinkAChildFromRoot(root, child); | 293 | PhysicallyUnlinkAChildFromRoot(rootx, childx); |
279 | }); | 294 | }); |
295 | |||
296 | RecomputeLinksetConstraintVariables(); | ||
280 | } | 297 | } |
281 | else | 298 | else |
282 | { | 299 | { |
283 | // This will happen if we remove the root of the linkset first. Non-fatal occurance. | 300 | // This will happen if we remove the root of the linkset first. Non-fatal occurance. |
284 | // m_scene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); | 301 | // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); |
285 | } | 302 | } |
286 | return; | 303 | return; |
287 | } | 304 | } |
@@ -293,37 +310,72 @@ public class BSLinkset | |||
293 | // Zero motion for children so they don't interpolate | 310 | // Zero motion for children so they don't interpolate |
294 | childPrim.ZeroMotion(); | 311 | childPrim.ZeroMotion(); |
295 | 312 | ||
313 | // Relative position normalized to the root prim | ||
314 | // Essentually a vector pointing from center of rootPrim to center of childPrim | ||
315 | OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; | ||
316 | |||
317 | // real world coordinate of midpoint between the two objects | ||
318 | OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); | ||
319 | |||
320 | // create a constraint that allows no freedom of movement between the two objects | ||
321 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | ||
322 | // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); | ||
323 | DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}", | ||
324 | rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint); | ||
325 | BS6DofConstraint constrain = new BS6DofConstraint( | ||
326 | m_physicsScene.World, rootPrim.Body, childPrim.Body, | ||
327 | midPoint, | ||
328 | true, | ||
329 | true | ||
330 | ); | ||
331 | /* NOTE: attempt to build constraint with full frame computation, etc. | ||
332 | * Using the midpoint is easier since it lets the Bullet code use the transforms | ||
333 | * of the objects. | ||
334 | * Code left here as an example. | ||
335 | // ================================================================================== | ||
296 | // relative position normalized to the root prim | 336 | // relative position normalized to the root prim |
297 | OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); | 337 | OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); |
298 | OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; | 338 | OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; |
299 | 339 | ||
300 | // relative rotation of the child to the parent | 340 | // relative rotation of the child to the parent |
301 | OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; | 341 | OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; |
342 | OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); | ||
302 | 343 | ||
303 | // create a constraint that allows no freedom of movement between the two objects | 344 | // create a constraint that allows no freedom of movement between the two objects |
304 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | 345 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 |
305 | // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); | 346 | // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); |
306 | DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); | 347 | DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); |
307 | BS6DofConstraint constrain = new BS6DofConstraint( | 348 | BS6DofConstraint constrain = new BS6DofConstraint( |
308 | m_scene.World, rootPrim.Body, childPrim.Body, | 349 | PhysicsScene.World, rootPrim.Body, childPrim.Body, |
309 | childRelativePosition, | ||
310 | childRelativeRotation, | ||
311 | OMV.Vector3.Zero, | 350 | OMV.Vector3.Zero, |
312 | -childRelativeRotation | 351 | OMV.Quaternion.Inverse(rootPrim.Orientation), |
352 | OMV.Vector3.Zero, | ||
353 | OMV.Quaternion.Inverse(childPrim.Orientation), | ||
354 | // A point half way between the parent and child | ||
355 | // childRelativePosition/2, | ||
356 | // childRelativeRotation, | ||
357 | // childRelativePosition/2, | ||
358 | // inverseChildRelativeRotation, | ||
359 | true, | ||
360 | true | ||
313 | ); | 361 | ); |
314 | m_scene.Constraints.AddConstraint(constrain); | 362 | // ================================================================================== |
363 | */ | ||
364 | |||
365 | m_physicsScene.Constraints.AddConstraint(constrain); | ||
315 | 366 | ||
316 | // zero linear and angular limits makes the objects unable to move in relation to each other | 367 | // zero linear and angular limits makes the objects unable to move in relation to each other |
317 | constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); | 368 | constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); |
318 | constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); | 369 | constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); |
319 | 370 | ||
320 | // tweek the constraint to increase stability | 371 | // tweek the constraint to increase stability |
321 | constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset)); | 372 | constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); |
322 | constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor), | 373 | constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), |
323 | m_scene.Params.linkConstraintTransMotorMaxVel, | 374 | PhysicsScene.Params.linkConstraintTransMotorMaxVel, |
324 | m_scene.Params.linkConstraintTransMotorMaxForce); | 375 | PhysicsScene.Params.linkConstraintTransMotorMaxForce); |
325 | constrain.SetCFMAndERP(m_scene.Params.linkConstraintCFM, m_scene.Params.linkConstraintERP); | 376 | constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); |
326 | 377 | ||
378 | RecomputeLinksetConstraintVariables(); | ||
327 | } | 379 | } |
328 | 380 | ||
329 | // Remove linkage between myself and a particular child | 381 | // Remove linkage between myself and a particular child |
@@ -334,7 +386,9 @@ public class BSLinkset | |||
334 | // LogHeader, rootPrim.LocalID, childPrim.LocalID); | 386 | // LogHeader, rootPrim.LocalID, childPrim.LocalID); |
335 | DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); | 387 | DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); |
336 | 388 | ||
337 | m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body); | 389 | // Find the constraint for this link and get rid of it from the overall collection and from my list |
390 | m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body); | ||
391 | |||
338 | // Make the child refresh its location | 392 | // Make the child refresh its location |
339 | BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); | 393 | BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); |
340 | } | 394 | } |
@@ -346,20 +400,20 @@ public class BSLinkset | |||
346 | // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); | 400 | // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); |
347 | DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); | 401 | DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); |
348 | 402 | ||
349 | m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); | 403 | m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); |
350 | } | 404 | } |
351 | 405 | ||
352 | // Invoke the detailed logger and output something if it's enabled. | 406 | // Invoke the detailed logger and output something if it's enabled. |
353 | private void DebugLog(string msg, params Object[] args) | 407 | private void DebugLog(string msg, params Object[] args) |
354 | { | 408 | { |
355 | if (m_scene.ShouldDebugLog) | 409 | if (m_physicsScene.ShouldDebugLog) |
356 | m_scene.Logger.DebugFormat(msg, args); | 410 | m_physicsScene.Logger.DebugFormat(msg, args); |
357 | } | 411 | } |
358 | 412 | ||
359 | // Invoke the detailed logger and output something if it's enabled. | 413 | // Invoke the detailed logger and output something if it's enabled. |
360 | private void DetailLog(string msg, params Object[] args) | 414 | private void DetailLog(string msg, params Object[] args) |
361 | { | 415 | { |
362 | m_scene.PhysicsLogging.Write(msg, args); | 416 | m_physicsScene.PhysicsLogging.Write(msg, args); |
363 | } | 417 | } |
364 | 418 | ||
365 | } | 419 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 05cc822..9c20004 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -163,13 +163,13 @@ public sealed class BSPrim : PhysicsActor | |||
163 | // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); | 163 | // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); |
164 | 164 | ||
165 | // Undo any links between me and any other object | 165 | // Undo any links between me and any other object |
166 | BSPrim parentBefore = _linkset.Root; | 166 | BSPrim parentBefore = _linkset.LinksetRoot; |
167 | int childrenBefore = _linkset.NumberOfChildren; | 167 | int childrenBefore = _linkset.NumberOfChildren; |
168 | 168 | ||
169 | _linkset = _linkset.RemoveMeFromLinkset(this); | 169 | _linkset = _linkset.RemoveMeFromLinkset(this); |
170 | 170 | ||
171 | DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", | 171 | DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", |
172 | LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren); | 172 | LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); |
173 | 173 | ||
174 | // Undo any vehicle properties | 174 | // Undo any vehicle properties |
175 | this.VehicleType = (int)Vehicle.TYPE_NONE; | 175 | this.VehicleType = (int)Vehicle.TYPE_NONE; |
@@ -233,13 +233,13 @@ public sealed class BSPrim : PhysicsActor | |||
233 | if (parent != null) | 233 | if (parent != null) |
234 | { | 234 | { |
235 | DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); | 235 | DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); |
236 | BSPrim parentBefore = _linkset.Root; | 236 | BSPrim parentBefore = _linkset.LinksetRoot; |
237 | int childrenBefore = _linkset.NumberOfChildren; | 237 | int childrenBefore = _linkset.NumberOfChildren; |
238 | 238 | ||
239 | _linkset = parent.Linkset.AddMeToLinkset(this); | 239 | _linkset = parent.Linkset.AddMeToLinkset(this); |
240 | 240 | ||
241 | DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", | 241 | DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", |
242 | LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren); | 242 | LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); |
243 | } | 243 | } |
244 | return; | 244 | return; |
245 | } | 245 | } |
@@ -249,15 +249,15 @@ public sealed class BSPrim : PhysicsActor | |||
249 | // TODO: decide if this parent checking needs to happen at taint time | 249 | // TODO: decide if this parent checking needs to happen at taint time |
250 | // Race condition here: if link() and delink() in same simulation tick, the delink will not happen | 250 | // Race condition here: if link() and delink() in same simulation tick, the delink will not happen |
251 | DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, | 251 | DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, |
252 | _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString()); | 252 | _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString()); |
253 | 253 | ||
254 | BSPrim parentBefore = _linkset.Root; | 254 | BSPrim parentBefore = _linkset.LinksetRoot; |
255 | int childrenBefore = _linkset.NumberOfChildren; | 255 | int childrenBefore = _linkset.NumberOfChildren; |
256 | 256 | ||
257 | _linkset = _linkset.RemoveMeFromLinkset(this); | 257 | _linkset = _linkset.RemoveMeFromLinkset(this); |
258 | 258 | ||
259 | DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", | 259 | DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", |
260 | LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren); | 260 | LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); |
261 | return; | 261 | return; |
262 | } | 262 | } |
263 | 263 | ||
@@ -280,7 +280,7 @@ public sealed class BSPrim : PhysicsActor | |||
280 | 280 | ||
281 | public override void LockAngularMotion(OMV.Vector3 axis) | 281 | public override void LockAngularMotion(OMV.Vector3 axis) |
282 | { | 282 | { |
283 | DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); | 283 | // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); |
284 | return; | 284 | return; |
285 | } | 285 | } |
286 | 286 | ||
@@ -299,7 +299,7 @@ public sealed class BSPrim : PhysicsActor | |||
299 | // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? | 299 | // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? |
300 | _scene.TaintedObject("BSPrim.setPosition", delegate() | 300 | _scene.TaintedObject("BSPrim.setPosition", delegate() |
301 | { | 301 | { |
302 | DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 302 | // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
303 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); | 303 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); |
304 | }); | 304 | }); |
305 | } | 305 | } |
@@ -336,7 +336,7 @@ public sealed class BSPrim : PhysicsActor | |||
336 | _force = value; | 336 | _force = value; |
337 | _scene.TaintedObject("BSPrim.setForce", delegate() | 337 | _scene.TaintedObject("BSPrim.setForce", delegate() |
338 | { | 338 | { |
339 | DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); | 339 | // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); |
340 | // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); | 340 | // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); |
341 | BulletSimAPI.SetObjectForce2(Body.Ptr, _force); | 341 | BulletSimAPI.SetObjectForce2(Body.Ptr, _force); |
342 | }); | 342 | }); |
@@ -414,7 +414,7 @@ public sealed class BSPrim : PhysicsActor | |||
414 | _velocity = value; | 414 | _velocity = value; |
415 | _scene.TaintedObject("BSPrim.setVelocity", delegate() | 415 | _scene.TaintedObject("BSPrim.setVelocity", delegate() |
416 | { | 416 | { |
417 | DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); | 417 | // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); |
418 | BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); | 418 | BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); |
419 | }); | 419 | }); |
420 | } | 420 | } |
@@ -422,7 +422,7 @@ public sealed class BSPrim : PhysicsActor | |||
422 | public override OMV.Vector3 Torque { | 422 | public override OMV.Vector3 Torque { |
423 | get { return _torque; } | 423 | get { return _torque; } |
424 | set { _torque = value; | 424 | set { _torque = value; |
425 | DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); | 425 | // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); |
426 | } | 426 | } |
427 | } | 427 | } |
428 | public override float CollisionScore { | 428 | public override float CollisionScore { |
@@ -449,7 +449,7 @@ public sealed class BSPrim : PhysicsActor | |||
449 | _scene.TaintedObject("BSPrim.setOrientation", delegate() | 449 | _scene.TaintedObject("BSPrim.setOrientation", delegate() |
450 | { | 450 | { |
451 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); | 451 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); |
452 | DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 452 | // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
453 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); | 453 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); |
454 | }); | 454 | }); |
455 | } | 455 | } |
@@ -497,8 +497,11 @@ public sealed class BSPrim : PhysicsActor | |||
497 | 497 | ||
498 | BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); | 498 | BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); |
499 | 499 | ||
500 | // recompute any linkset parameters | ||
501 | _linkset.Refresh(this); | ||
502 | |||
500 | CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); | 503 | CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); |
501 | DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); | 504 | // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); |
502 | } | 505 | } |
503 | 506 | ||
504 | // prims don't fly | 507 | // prims don't fly |
@@ -555,7 +558,7 @@ public sealed class BSPrim : PhysicsActor | |||
555 | // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); | 558 | // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); |
556 | _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() | 559 | _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() |
557 | { | 560 | { |
558 | DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); | 561 | // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); |
559 | BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); | 562 | BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); |
560 | }); | 563 | }); |
561 | } | 564 | } |
@@ -572,7 +575,7 @@ public sealed class BSPrim : PhysicsActor | |||
572 | _buoyancy = value; | 575 | _buoyancy = value; |
573 | _scene.TaintedObject("BSPrim.setBuoyancy", delegate() | 576 | _scene.TaintedObject("BSPrim.setBuoyancy", delegate() |
574 | { | 577 | { |
575 | DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 578 | // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
576 | BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); | 579 | BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); |
577 | }); | 580 | }); |
578 | } | 581 | } |
@@ -635,17 +638,17 @@ public sealed class BSPrim : PhysicsActor | |||
635 | } | 638 | } |
636 | m_accumulatedForces.Clear(); | 639 | m_accumulatedForces.Clear(); |
637 | } | 640 | } |
638 | DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); | 641 | // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); |
639 | BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); | 642 | BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); |
640 | }); | 643 | }); |
641 | } | 644 | } |
642 | 645 | ||
643 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { | 646 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { |
644 | DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); | 647 | // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); |
645 | // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); | 648 | // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); |
646 | } | 649 | } |
647 | public override void SetMomentum(OMV.Vector3 momentum) { | 650 | public override void SetMomentum(OMV.Vector3 momentum) { |
648 | DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); | 651 | // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); |
649 | } | 652 | } |
650 | public override void SubscribeEvents(int ms) { | 653 | public override void SubscribeEvents(int ms) { |
651 | _subscribedEventsMs = ms; | 654 | _subscribedEventsMs = ms; |
@@ -989,7 +992,7 @@ public sealed class BSPrim : PhysicsActor | |||
989 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); | 992 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); |
990 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) | 993 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) |
991 | { | 994 | { |
992 | DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); | 995 | // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); |
993 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; | 996 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; |
994 | // Bullet native objects are scaled by the Bullet engine so pass the size in | 997 | // Bullet native objects are scaled by the Bullet engine so pass the size in |
995 | _scale = _size; | 998 | _scale = _size; |
@@ -1003,7 +1006,7 @@ public sealed class BSPrim : PhysicsActor | |||
1003 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); | 1006 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); |
1004 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) | 1007 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) |
1005 | { | 1008 | { |
1006 | DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); | 1009 | // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); |
1007 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; | 1010 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; |
1008 | _scale = _size; | 1011 | _scale = _size; |
1009 | // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? | 1012 | // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? |
@@ -1046,12 +1049,12 @@ public sealed class BSPrim : PhysicsActor | |||
1046 | // if this new shape is the same as last time, don't recreate the mesh | 1049 | // if this new shape is the same as last time, don't recreate the mesh |
1047 | if (_meshKey == newMeshKey) return; | 1050 | if (_meshKey == newMeshKey) return; |
1048 | 1051 | ||
1049 | DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); | 1052 | // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); |
1050 | // Since we're recreating new, get rid of any previously generated shape | 1053 | // Since we're recreating new, get rid of any previously generated shape |
1051 | if (_meshKey != 0) | 1054 | if (_meshKey != 0) |
1052 | { | 1055 | { |
1053 | // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); | 1056 | // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); |
1054 | DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); | 1057 | // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); |
1055 | BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); | 1058 | BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); |
1056 | _mesh = null; | 1059 | _mesh = null; |
1057 | _meshKey = 0; | 1060 | _meshKey = 0; |
@@ -1081,7 +1084,7 @@ public sealed class BSPrim : PhysicsActor | |||
1081 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; | 1084 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; |
1082 | // meshes are already scaled by the meshmerizer | 1085 | // meshes are already scaled by the meshmerizer |
1083 | _scale = new OMV.Vector3(1f, 1f, 1f); | 1086 | _scale = new OMV.Vector3(1f, 1f, 1f); |
1084 | DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); | 1087 | // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); |
1085 | return; | 1088 | return; |
1086 | } | 1089 | } |
1087 | 1090 | ||
@@ -1095,28 +1098,21 @@ public sealed class BSPrim : PhysicsActor | |||
1095 | // if the hull hasn't changed, don't rebuild it | 1098 | // if the hull hasn't changed, don't rebuild it |
1096 | if (newHullKey == _hullKey) return; | 1099 | if (newHullKey == _hullKey) return; |
1097 | 1100 | ||
1098 | DetailLog("{0},BSPrim.CreateGeomHull,create,key={1}", LocalID, _meshKey); | 1101 | // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); |
1099 | 1102 | ||
1100 | // Since we're recreating new, get rid of any previously generated shape | 1103 | // Since we're recreating new, get rid of any previously generated shape |
1101 | if (_hullKey != 0) | 1104 | if (_hullKey != 0) |
1102 | { | 1105 | { |
1103 | // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); | 1106 | // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); |
1104 | DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey); | 1107 | // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey); |
1105 | BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); | 1108 | BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); |
1106 | _hullKey = 0; | 1109 | _hullKey = 0; |
1107 | _hulls.Clear(); | ||
1108 | DetailLog("{0},BSPrim.CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey); | ||
1109 | BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); | ||
1110 | _mesh = null; // the mesh cannot match either | ||
1111 | _meshKey = 0; | ||
1112 | } | 1110 | } |
1113 | 1111 | ||
1114 | _hullKey = newHullKey; | 1112 | _hullKey = newHullKey; |
1115 | if (_meshKey != _hullKey) | 1113 | |
1116 | { | 1114 | // Make sure the underlying mesh exists and is correct |
1117 | // if the underlying mesh has changed, rebuild it | 1115 | CreateGeomMesh(); |
1118 | CreateGeomMesh(); | ||
1119 | } | ||
1120 | 1116 | ||
1121 | int[] indices = _mesh.getIndexListAsInt(); | 1117 | int[] indices = _mesh.getIndexListAsInt(); |
1122 | List<OMV.Vector3> vertices = _mesh.getVertexList(); | 1118 | List<OMV.Vector3> vertices = _mesh.getVertexList(); |
@@ -1142,7 +1138,7 @@ public sealed class BSPrim : PhysicsActor | |||
1142 | // create the hull into the _hulls variable | 1138 | // create the hull into the _hulls variable |
1143 | convexBuilder.process(dcomp); | 1139 | convexBuilder.process(dcomp); |
1144 | 1140 | ||
1145 | // Convert the vertices and indices for passing to unmanaged | 1141 | // Convert the vertices and indices for passing to unmanaged. |
1146 | // The hull information is passed as a large floating point array. | 1142 | // The hull information is passed as a large floating point array. |
1147 | // The format is: | 1143 | // The format is: |
1148 | // convHulls[0] = number of hulls | 1144 | // convHulls[0] = number of hulls |
@@ -1202,7 +1198,7 @@ public sealed class BSPrim : PhysicsActor | |||
1202 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; | 1198 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; |
1203 | // meshes are already scaled by the meshmerizer | 1199 | // meshes are already scaled by the meshmerizer |
1204 | _scale = new OMV.Vector3(1f, 1f, 1f); | 1200 | _scale = new OMV.Vector3(1f, 1f, 1f); |
1205 | DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); | 1201 | // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); |
1206 | return; | 1202 | return; |
1207 | } | 1203 | } |
1208 | 1204 | ||
@@ -1340,11 +1336,12 @@ public sealed class BSPrim : PhysicsActor | |||
1340 | 1336 | ||
1341 | // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", | 1337 | // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", |
1342 | // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); | 1338 | // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); |
1343 | DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | 1339 | // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", |
1344 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); | 1340 | // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); |
1345 | 1341 | ||
1346 | base.RequestPhysicsterseUpdate(); | 1342 | base.RequestPhysicsterseUpdate(); |
1347 | } | 1343 | } |
1344 | /* | ||
1348 | else | 1345 | else |
1349 | { | 1346 | { |
1350 | // For debugging, we also report the movement of children | 1347 | // For debugging, we also report the movement of children |
@@ -1352,10 +1349,11 @@ public sealed class BSPrim : PhysicsActor | |||
1352 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, | 1349 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, |
1353 | entprop.Acceleration, entprop.RotationalVelocity); | 1350 | entprop.Acceleration, entprop.RotationalVelocity); |
1354 | } | 1351 | } |
1352 | */ | ||
1355 | } | 1353 | } |
1356 | 1354 | ||
1357 | // I've collided with something | 1355 | // I've collided with something |
1358 | CollisionEventUpdate collisionCollection = null; | 1356 | CollisionEventUpdate collisionCollection; |
1359 | public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) | 1357 | public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) |
1360 | { | 1358 | { |
1361 | // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); | 1359 | // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); |
@@ -1367,6 +1365,8 @@ public sealed class BSPrim : PhysicsActor | |||
1367 | _collidingGroundStep = _scene.SimulationStep; | 1365 | _collidingGroundStep = _scene.SimulationStep; |
1368 | } | 1366 | } |
1369 | 1367 | ||
1368 | // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); | ||
1369 | |||
1370 | // if someone is subscribed to collision events.... | 1370 | // if someone is subscribed to collision events.... |
1371 | if (_subscribedEventsMs != 0) { | 1371 | if (_subscribedEventsMs != 0) { |
1372 | // throttle the collisions to the number of milliseconds specified in the subscription | 1372 | // throttle the collisions to the number of milliseconds specified in the subscription |
@@ -1387,7 +1387,9 @@ public sealed class BSPrim : PhysicsActor | |||
1387 | if (collisionCollection != null && collisionCollection.Count > 0) | 1387 | if (collisionCollection != null && collisionCollection.Count > 0) |
1388 | { | 1388 | { |
1389 | base.SendCollisionUpdate(collisionCollection); | 1389 | base.SendCollisionUpdate(collisionCollection); |
1390 | collisionCollection.Clear(); | 1390 | // The collisionCollection structure is passed around in the simulator. |
1391 | // Make sure we don't have a handle to that one and that a new one is used next time. | ||
1392 | collisionCollection = null; | ||
1391 | } | 1393 | } |
1392 | } | 1394 | } |
1393 | 1395 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index beaea1f..a31c578 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -362,7 +362,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
362 | BSPrim bsprim = prim as BSPrim; | 362 | BSPrim bsprim = prim as BSPrim; |
363 | if (bsprim != null) | 363 | if (bsprim != null) |
364 | { | 364 | { |
365 | DetailLog("{0},RemovePrim,call", bsprim.LocalID); | 365 | // DetailLog("{0},RemovePrim,call", bsprim.LocalID); |
366 | // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); | 366 | // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); |
367 | try | 367 | try |
368 | { | 368 | { |
@@ -388,7 +388,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
388 | 388 | ||
389 | if (!m_initialized) return null; | 389 | if (!m_initialized) return null; |
390 | 390 | ||
391 | DetailLog("{0},AddPrimShape,call", localID); | 391 | // DetailLog("{0},AddPrimShape,call", localID); |
392 | 392 | ||
393 | BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); | 393 | BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); |
394 | lock (m_prims) m_prims.Add(localID, prim); | 394 | lock (m_prims) m_prims.Add(localID, prim); |
@@ -413,7 +413,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
413 | // prevent simulation until we've been initialized | 413 | // prevent simulation until we've been initialized |
414 | if (!m_initialized) return 10.0f; | 414 | if (!m_initialized) return 10.0f; |
415 | 415 | ||
416 | long simulateStartTime = Util.EnvironmentTickCount(); | 416 | int simulateStartTime = Util.EnvironmentTickCount(); |
417 | 417 | ||
418 | // update the prim states while we know the physics engine is not busy | 418 | // update the prim states while we know the physics engine is not busy |
419 | ProcessTaints(); | 419 | ProcessTaints(); |
@@ -429,12 +429,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
429 | { | 429 | { |
430 | numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, | 430 | numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, |
431 | out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); | 431 | out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); |
432 | DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); | 432 | // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); |
433 | } | 433 | } |
434 | catch (Exception e) | 434 | catch (Exception e) |
435 | { | 435 | { |
436 | m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); | 436 | m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); |
437 | DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); | 437 | // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); |
438 | // updatedEntityCount = 0; | 438 | // updatedEntityCount = 0; |
439 | collidersCount = 0; | 439 | collidersCount = 0; |
440 | } | 440 | } |
@@ -511,8 +511,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
511 | // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); | 511 | // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); |
512 | // return (timeStep * (float)simulateTotalTime); | 512 | // return (timeStep * (float)simulateTotalTime); |
513 | 513 | ||
514 | // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. | 514 | // TODO: FIX THIS: fps calculation possibly wrong. |
515 | return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; | 515 | // This calculation says 1/timeStep is the ideal frame rate. Any time added to |
516 | // that by the physics simulation gives a slower frame rate. | ||
517 | long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime); | ||
518 | if (totalSimulationTime >= timeStep) | ||
519 | return 0; | ||
520 | return 1f / (timeStep + totalSimulationTime); | ||
516 | } | 521 | } |
517 | 522 | ||
518 | // Something has collided | 523 | // Something has collided |
@@ -590,12 +595,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
590 | // make sure no stepping happens while we're deleting stuff | 595 | // make sure no stepping happens while we're deleting stuff |
591 | m_initialized = false; | 596 | m_initialized = false; |
592 | 597 | ||
593 | if (m_constraintCollection != null) | ||
594 | { | ||
595 | m_constraintCollection.Dispose(); | ||
596 | m_constraintCollection = null; | ||
597 | } | ||
598 | |||
599 | foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) | 598 | foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) |
600 | { | 599 | { |
601 | kvp.Value.Destroy(); | 600 | kvp.Value.Destroy(); |
@@ -608,6 +607,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
608 | } | 607 | } |
609 | m_prims.Clear(); | 608 | m_prims.Clear(); |
610 | 609 | ||
610 | // Now that the prims are all cleaned up, there should be no constraints left | ||
611 | if (m_constraintCollection != null) | ||
612 | { | ||
613 | m_constraintCollection.Dispose(); | ||
614 | m_constraintCollection = null; | ||
615 | } | ||
616 | |||
611 | // Anything left in the unmanaged code should be cleaned out | 617 | // Anything left in the unmanaged code should be cleaned out |
612 | BulletSimAPI.Shutdown(WorldID); | 618 | BulletSimAPI.Shutdown(WorldID); |
613 | 619 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 6800b96..504bd3c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | |||
@@ -416,6 +416,27 @@ public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, Int | |||
416 | bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); | 416 | bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); |
417 | 417 | ||
418 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 418 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
419 | public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr obj1, IntPtr obj2, | ||
420 | Vector3 joinPoint, | ||
421 | bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); | ||
422 | |||
423 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
424 | public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, | ||
425 | Vector3 pivotinA, Vector3 pivotinB, | ||
426 | Vector3 axisInA, Vector3 axisInB, | ||
427 | bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); | ||
428 | |||
429 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
430 | public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse); | ||
431 | |||
432 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
433 | public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations); | ||
434 | |||
435 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
436 | public static extern bool SetFrames2(IntPtr constrain, | ||
437 | Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot); | ||
438 | |||
439 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
419 | public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); | 440 | public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); |
420 | 441 | ||
421 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 442 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
@@ -428,6 +449,9 @@ public static extern bool UseFrameOffset2(IntPtr constrain, float enable); | |||
428 | public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce); | 449 | public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce); |
429 | 450 | ||
430 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 451 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
452 | public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold); | ||
453 | |||
454 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
431 | public static extern bool CalculateTransforms2(IntPtr constrain); | 455 | public static extern bool CalculateTransforms2(IntPtr constrain); |
432 | 456 | ||
433 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 457 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
@@ -518,6 +542,9 @@ public static extern bool SetGravity2(IntPtr obj, Vector3 val); | |||
518 | public static extern IntPtr ClearForces2(IntPtr obj); | 542 | public static extern IntPtr ClearForces2(IntPtr obj); |
519 | 543 | ||
520 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 544 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
545 | public static extern IntPtr ClearAllForces2(IntPtr obj); | ||
546 | |||
547 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
521 | public static extern bool SetMargin2(IntPtr obj, float val); | 548 | public static extern bool SetMargin2(IntPtr obj, float val); |
522 | 549 | ||
523 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 550 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |