aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs118
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs176
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs79
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs108
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs55
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs302
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs232
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs124
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs104
10 files changed, 845 insertions, 455 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
new file mode 100755
index 0000000..683bc51
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
@@ -0,0 +1,118 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public class BS6DofConstraint : BSConstraint
36{
37 // Create a btGeneric6DofConstraint
38 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
39 Vector3 frame1, Quaternion frame1rot,
40 Vector3 frame2, Quaternion frame2rot,
41 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
42 {
43 m_world = world;
44 m_body1 = obj1;
45 m_body2 = obj2;
46 m_constraint = new BulletConstraint(
47 BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
48 frame1, frame1rot,
49 frame2, frame2rot,
50 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
51 m_enabled = true;
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
79 public bool SetCFMAndERP(float cfm, float erp)
80 {
81 bool ret = false;
82 if (m_enabled)
83 {
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 }
89 return ret;
90 }
91
92 public bool UseFrameOffset(bool useOffset)
93 {
94 bool ret = false;
95 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
96 if (m_enabled)
97 ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
98 return ret;
99 }
100
101 public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
102 {
103 bool ret = false;
104 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
105 if (m_enabled)
106 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
107 return ret;
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 }
117}
118}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 09e1f0c..e2f7af9 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -40,6 +40,7 @@ public class BSCharacter : PhysicsActor
40 private static readonly string LogHeader = "[BULLETS CHAR]"; 40 private static readonly string LogHeader = "[BULLETS CHAR]";
41 41
42 private BSScene _scene; 42 private BSScene _scene;
43 public BSScene Scene { get { return _scene; } }
43 private String _avName; 44 private String _avName;
44 // private bool _stopped; 45 // private bool _stopped;
45 private Vector3 _size; 46 private Vector3 _size;
@@ -73,6 +74,12 @@ public class BSCharacter : PhysicsActor
73 private bool _kinematic; 74 private bool _kinematic;
74 private float _buoyancy; 75 private float _buoyancy;
75 76
77 private BulletBody m_body;
78 public BulletBody Body {
79 get { return m_body; }
80 set { m_body = value; }
81 }
82
76 private int _subscribedEventsMs = 0; 83 private int _subscribedEventsMs = 0;
77 private int _nextCollisionOkTime = 0; 84 private int _nextCollisionOkTime = 0;
78 85
@@ -95,7 +102,9 @@ public class BSCharacter : PhysicsActor
95 _orientation = Quaternion.Identity; 102 _orientation = Quaternion.Identity;
96 _velocity = Vector3.Zero; 103 _velocity = Vector3.Zero;
97 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 104 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
98 _scale = new Vector3(1f, 1f, 1f); 105 // The dimensions of the avatar capsule are kept in the scale.
106 // Physics creates a unit capsule which is scaled by the physics engine.
107 _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z);
99 _density = _scene.Params.avatarDensity; 108 _density = _scene.Params.avatarDensity;
100 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale 109 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
101 110
@@ -113,9 +122,13 @@ public class BSCharacter : PhysicsActor
113 shapeData.Restitution = _scene.Params.avatarRestitution; 122 shapeData.Restitution = _scene.Params.avatarRestitution;
114 123
115 // do actual create at taint time 124 // do actual create at taint time
116 _scene.TaintedObject(delegate() 125 _scene.TaintedObject("BSCharacter.create", delegate()
117 { 126 {
118 BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); 127 BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData);
128
129 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
130 // avatars get all collisions no matter what
131 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
119 }); 132 });
120 133
121 return; 134 return;
@@ -124,7 +137,8 @@ public class BSCharacter : PhysicsActor
124 // 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
125 public void Destroy() 138 public void Destroy()
126 { 139 {
127 _scene.TaintedObject(delegate() 140 // DetailLog("{0},BSCharacter.Destroy", LocalID);
141 _scene.TaintedObject("BSCharacter.destroy", delegate()
128 { 142 {
129 BulletSimAPI.DestroyObject(_scene.WorldID, _localID); 143 BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
130 }); 144 });
@@ -138,9 +152,28 @@ public class BSCharacter : PhysicsActor
138 public override bool Stopped { 152 public override bool Stopped {
139 get { return false; } 153 get { return false; }
140 } 154 }
141 public override Vector3 Size { 155 public override Vector3 Size {
142 get { return _size; } 156 get
143 set { _size = value; 157 {
158 // Avatar capsule size is kept in the scale parameter.
159 return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z);
160 }
161
162 set {
163 // When an avatar's size is set, only the height is changed
164 // and that really only depends on the radius.
165 _size = value;
166 _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y);
167
168 // TODO: something has to be done with the avatar's vertical position
169
170 ComputeAvatarVolumeAndMass();
171
172 _scene.TaintedObject("BSCharacter.setSize", delegate()
173 {
174 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true);
175 });
176
144 } 177 }
145 } 178 }
146 public override PrimitiveBaseShape Shape { 179 public override PrimitiveBaseShape Shape {
@@ -172,12 +205,37 @@ public class BSCharacter : PhysicsActor
172 } 205 }
173 set { 206 set {
174 _position = value; 207 _position = value;
175 _scene.TaintedObject(delegate() 208 PositionSanityCheck();
209
210 _scene.TaintedObject("BSCharacter.setPosition", delegate()
176 { 211 {
212 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
177 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 213 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
178 }); 214 });
179 } 215 }
180 } 216 }
217
218 // Check that the current position is sane and, if not, modify the position to make it so.
219 // Check for being below terrain and being out of bounds.
220 // Returns 'true' of the position was made sane by some action.
221 private bool PositionSanityCheck()
222 {
223 bool ret = false;
224
225 // If below the ground, move the avatar up
226 float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position);
227 if (_position.Z < terrainHeight)
228 {
229 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation);
230 _position.Z = terrainHeight + 2.0f;
231 ret = true;
232 }
233
234 // TODO: check for out of bounds
235
236 return ret;
237 }
238
181 public override float Mass { 239 public override float Mass {
182 get { 240 get {
183 return _mass; 241 return _mass;
@@ -188,9 +246,10 @@ public class BSCharacter : PhysicsActor
188 set { 246 set {
189 _force = value; 247 _force = value;
190 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 248 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
191 _scene.TaintedObject(delegate() 249 Scene.TaintedObject("BSCharacter.SetForce", delegate()
192 { 250 {
193 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 251 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
252 BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force);
194 }); 253 });
195 } 254 }
196 } 255 }
@@ -214,8 +273,9 @@ public class BSCharacter : PhysicsActor
214 set { 273 set {
215 _velocity = value; 274 _velocity = value;
216 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 275 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
217 _scene.TaintedObject(delegate() 276 _scene.TaintedObject("BSCharacter.setVelocity", delegate()
218 { 277 {
278 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
219 BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); 279 BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity);
220 }); 280 });
221 } 281 }
@@ -239,7 +299,7 @@ public class BSCharacter : PhysicsActor
239 set { 299 set {
240 _orientation = value; 300 _orientation = value;
241 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); 301 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
242 _scene.TaintedObject(delegate() 302 _scene.TaintedObject("BSCharacter.setOrientation", delegate()
243 { 303 {
244 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 304 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
245 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 305 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
@@ -259,9 +319,12 @@ public class BSCharacter : PhysicsActor
259 public override bool Flying { 319 public override bool Flying {
260 get { return _flying; } 320 get { return _flying; }
261 set { 321 set {
262 _flying = value; 322 if (_flying != value)
263 // simulate flying by changing the effect of gravity 323 {
264 this.Buoyancy = ComputeBuoyancyFromFlying(_flying); 324 _flying = value;
325 // simulate flying by changing the effect of gravity
326 this.Buoyancy = ComputeBuoyancyFromFlying(_flying);
327 }
265 } 328 }
266 } 329 }
267 private float ComputeBuoyancyFromFlying(bool ifFlying) { 330 private float ComputeBuoyancyFromFlying(bool ifFlying) {
@@ -303,8 +366,9 @@ public class BSCharacter : PhysicsActor
303 public override float Buoyancy { 366 public override float Buoyancy {
304 get { return _buoyancy; } 367 get { return _buoyancy; }
305 set { _buoyancy = value; 368 set { _buoyancy = value;
306 _scene.TaintedObject(delegate() 369 _scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
307 { 370 {
371 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
308 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); 372 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
309 }); 373 });
310 } 374 }
@@ -349,9 +413,10 @@ public class BSCharacter : PhysicsActor
349 _force.Y += force.Y; 413 _force.Y += force.Y;
350 _force.Z += force.Z; 414 _force.Z += force.Z;
351 // 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);
352 _scene.TaintedObject(delegate() 416 _scene.TaintedObject("BSCharacter.AddForce", delegate()
353 { 417 {
354 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 418 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
419 BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
355 }); 420 });
356 } 421 }
357 else 422 else
@@ -369,11 +434,25 @@ public class BSCharacter : PhysicsActor
369 // Turn on collision events at a rate no faster than one every the given milliseconds 434 // Turn on collision events at a rate no faster than one every the given milliseconds
370 public override void SubscribeEvents(int ms) { 435 public override void SubscribeEvents(int ms) {
371 _subscribedEventsMs = ms; 436 _subscribedEventsMs = ms;
372 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen 437 if (ms > 0)
438 {
439 // make sure first collision happens
440 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
441
442 Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate()
443 {
444 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
445 });
446 }
373 } 447 }
374 // Stop collision events 448 // Stop collision events
375 public override void UnSubscribeEvents() { 449 public override void UnSubscribeEvents() {
376 _subscribedEventsMs = 0; 450 _subscribedEventsMs = 0;
451 // Avatars get all their collision events
452 // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate()
453 // {
454 // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
455 // });
377 } 456 }
378 // Return 'true' if someone has subscribed to events 457 // Return 'true' if someone has subscribed to events
379 public override bool SubscribedEvents() { 458 public override bool SubscribedEvents() {
@@ -385,9 +464,15 @@ public class BSCharacter : PhysicsActor
385 { 464 {
386 _avatarVolume = (float)( 465 _avatarVolume = (float)(
387 Math.PI 466 Math.PI
388 * _scene.Params.avatarCapsuleRadius * _scale.X 467 * _scale.X
389 * _scene.Params.avatarCapsuleRadius * _scale.Y 468 * _scale.Y // the area of capsule cylinder
390 * _scene.Params.avatarCapsuleHeight * _scale.Z); 469 * _scale.Z // times height of capsule cylinder
470 + 1.33333333f
471 * Math.PI
472 * _scale.X
473 * Math.Min(_scale.X, _scale.Y)
474 * _scale.Y // plus the volume of the capsule end caps
475 );
391 _mass = _density * _avatarVolume; 476 _mass = _density * _avatarVolume;
392 } 477 }
393 478
@@ -395,43 +480,19 @@ public class BSCharacter : PhysicsActor
395 // the world that things have changed. 480 // the world that things have changed.
396 public void UpdateProperties(EntityProperties entprop) 481 public void UpdateProperties(EntityProperties entprop)
397 { 482 {
398 /*
399 bool changed = false;
400 // we assign to the local variables so the normal set action does not happen
401 if (_position != entprop.Position) {
402 _position = entprop.Position;
403 changed = true;
404 }
405 if (_orientation != entprop.Rotation) {
406 _orientation = entprop.Rotation;
407 changed = true;
408 }
409 if (_velocity != entprop.Velocity) {
410 _velocity = entprop.Velocity;
411 changed = true;
412 }
413 if (_acceleration != entprop.Acceleration) {
414 _acceleration = entprop.Acceleration;
415 changed = true;
416 }
417 if (_rotationalVelocity != entprop.RotationalVelocity) {
418 _rotationalVelocity = entprop.RotationalVelocity;
419 changed = true;
420 }
421 if (changed) {
422 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
423 // Avatar movement is not done by generating this event. There is code in the heartbeat
424 // loop that updates avatars.
425 // base.RequestPhysicsterseUpdate();
426 }
427 */
428 _position = entprop.Position; 483 _position = entprop.Position;
429 _orientation = entprop.Rotation; 484 _orientation = entprop.Rotation;
430 _velocity = entprop.Velocity; 485 _velocity = entprop.Velocity;
431 _acceleration = entprop.Acceleration; 486 _acceleration = entprop.Acceleration;
432 _rotationalVelocity = entprop.RotationalVelocity; 487 _rotationalVelocity = entprop.RotationalVelocity;
433 // Avatars don't report theirr 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.
434 // base.RequestPhysicsterseUpdate(); 489 // base.RequestPhysicsterseUpdate();
490
491 /*
492 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
493 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
494 entprop.Acceleration, entprop.RotationalVelocity);
495 */
435 } 496 }
436 497
437 // 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
@@ -448,6 +509,7 @@ public class BSCharacter : PhysicsActor
448 { 509 {
449 _collidingGroundStep = _scene.SimulationStep; 510 _collidingGroundStep = _scene.SimulationStep;
450 } 511 }
512 // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
451 513
452 // throttle collisions to the rate specified in the subscription 514 // throttle collisions to the rate specified in the subscription
453 if (_subscribedEventsMs != 0) { 515 if (_subscribedEventsMs != 0) {
@@ -476,9 +538,17 @@ public class BSCharacter : PhysicsActor
476 if (collisionCollection == null) 538 if (collisionCollection == null)
477 collisionCollection = new CollisionEventUpdate(); 539 collisionCollection = new CollisionEventUpdate();
478 base.SendCollisionUpdate(collisionCollection); 540 base.SendCollisionUpdate(collisionCollection);
479 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;
480 // End kludge 545 // End kludge
481 } 546 }
482 547
548 // Invoke the detailed logger and output something if it's enabled.
549 private void DetailLog(string msg, params Object[] args)
550 {
551 Scene.PhysicsLogging.Write(msg, args);
552 }
483} 553}
484} 554}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index ea3093a..25084d8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -32,35 +32,26 @@ using OpenMetaverse;
32namespace OpenSim.Region.Physics.BulletSPlugin 32namespace OpenSim.Region.Physics.BulletSPlugin
33{ 33{
34 34
35public class BSConstraint : IDisposable 35public abstract class BSConstraint : IDisposable
36{ 36{
37 private BulletSim m_world; 37 protected BulletSim m_world;
38 private BulletBody m_body1; 38 protected BulletBody m_body1;
39 private BulletBody m_body2; 39 protected BulletBody m_body2;
40 private BulletConstraint m_constraint; 40 protected BulletConstraint m_constraint;
41 private bool m_enabled = false; 41 protected bool m_enabled = false;
42 42
43 public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, 43 public BSConstraint()
44 Vector3 frame1, Quaternion frame1rot,
45 Vector3 frame2, Quaternion frame2rot
46 )
47 { 44 {
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 true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/));
55 m_enabled = true;
56 } 45 }
57 46
58 public void Dispose() 47 public virtual void Dispose()
59 { 48 {
60 if (m_enabled) 49 if (m_enabled)
61 { 50 {
62 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); 51 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
63 BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); 52 bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
53 m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success);
54 m_constraint.Ptr = System.IntPtr.Zero;
64 m_enabled = false; 55 m_enabled = false;
65 } 56 }
66 } 57 }
@@ -68,7 +59,7 @@ public class BSConstraint : IDisposable
68 public BulletBody Body1 { get { return m_body1; } } 59 public BulletBody Body1 { get { return m_body1; } }
69 public BulletBody Body2 { get { return m_body2; } } 60 public BulletBody Body2 { get { return m_body2; } }
70 61
71 public bool SetLinearLimits(Vector3 low, Vector3 high) 62 public virtual bool SetLinearLimits(Vector3 low, Vector3 high)
72 { 63 {
73 bool ret = false; 64 bool ret = false;
74 if (m_enabled) 65 if (m_enabled)
@@ -76,7 +67,7 @@ public class BSConstraint : IDisposable
76 return ret; 67 return ret;
77 } 68 }
78 69
79 public bool SetAngularLimits(Vector3 low, Vector3 high) 70 public virtual bool SetAngularLimits(Vector3 low, Vector3 high)
80 { 71 {
81 bool ret = false; 72 bool ret = false;
82 if (m_enabled) 73 if (m_enabled)
@@ -84,40 +75,36 @@ public class BSConstraint : IDisposable
84 return ret; 75 return ret;
85 } 76 }
86 77
87 public bool SetCFMAndERP(float cfm, float erp) 78 public virtual bool CalculateTransforms()
88 {
89 bool ret = true;
90 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
91 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
92 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
93 return ret;
94 }
95
96 public bool UseFrameOffset(bool useOffset)
97 {
98 bool ret = false;
99 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
100 if (m_enabled)
101 ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
102 return ret;
103 }
104
105 public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
106 { 79 {
107 bool ret = false; 80 bool ret = false;
108 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
109 if (m_enabled) 81 if (m_enabled)
110 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); 82 {
83 // Recompute the internal transforms
84 BulletSimAPI.CalculateTransforms2(m_constraint.Ptr);
85 ret = true;
86 }
111 return ret; 87 return ret;
112 } 88 }
113 89
114 public bool CalculateTransforms() 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)
115 { 93 {
116 bool ret = false; 94 bool ret = false;
117 if (m_enabled) 95 if (m_enabled)
118 { 96 {
119 BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); 97 ret = CalculateTransforms();
120 ret = true; 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 }
121 } 108 }
122 return ret; 109 return ret;
123 } 110 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
index c88e645..22ea367 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
@@ -56,29 +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 }
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 } 67 }
75 68
76 public bool AddConstraint(BSConstraint cons) 69 public bool AddConstraint(BSConstraint cons)
77 { 70 {
78 // There is only one constraint between any bodies. Remove any old just to make sure. 71 lock (m_constraints)
79 RemoveAndDestroyConstraint(cons.Body1, cons.Body2); 72 {
73 // There is only one constraint between any bodies. Remove any old just to make sure.
74 RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
80 75
81 m_constraints.Add(cons); 76 m_constraints.Add(cons);
77 }
82 78
83 return true; 79 return true;
84 } 80 }
@@ -92,16 +88,19 @@ public class BSConstraintCollection : IDisposable
92 88
93 uint lookingID1 = body1.ID; 89 uint lookingID1 = body1.ID;
94 uint lookingID2 = body2.ID; 90 uint lookingID2 = body2.ID;
95 ForEachConstraint(delegate(BSConstraint constrain) 91 lock (m_constraints)
96 { 92 {
97 if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) 93 foreach (BSConstraint constrain in m_constraints)
98 || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
99 { 94 {
100 foundConstraint = constrain; 95 if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
101 found = true; 96 || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
97 {
98 foundConstraint = constrain;
99 found = true;
100 break;
101 }
102 } 102 }
103 return found; 103 }
104 });
105 returnConstraint = foundConstraint; 104 returnConstraint = foundConstraint;
106 return found; 105 return found;
107 } 106 }
@@ -111,22 +110,33 @@ public class BSConstraintCollection : IDisposable
111 // Return 'true' if a constraint was found and destroyed. 110 // Return 'true' if a constraint was found and destroyed.
112 public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) 111 public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2)
113 { 112 {
114 // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID);
115
116 bool ret = false; 113 bool ret = false;
117 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 }
118 124
119 if (this.TryGetConstraint(body1, body2, out constrain)) 125 return ret;
126 }
127
128 // The constraint MUST exist in the collection
129 public bool RemoveAndDestroyConstraint(BSConstraint constrain)
130 {
131 lock (m_constraints)
120 { 132 {
121 // remove the constraint from our collection 133 // remove the constraint from our collection
122 m_constraints.Remove(constrain); 134 m_constraints.Remove(constrain);
123 // tell the engine that all its structures need to be freed
124 constrain.Dispose();
125 // we destroyed something
126 ret = true;
127 } 135 }
128 136 // tell the engine that all its structures need to be freed
129 return ret; 137 constrain.Dispose();
138 // we destroyed something
139 return true;
130 } 140 }
131 141
132 // Remove all constraints that reference the passed body. 142 // Remove all constraints that reference the passed body.
@@ -137,16 +147,15 @@ public class BSConstraintCollection : IDisposable
137 147
138 List<BSConstraint> toRemove = new List<BSConstraint>(); 148 List<BSConstraint> toRemove = new List<BSConstraint>();
139 uint lookingID = body1.ID; 149 uint lookingID = body1.ID;
140 ForEachConstraint(delegate(BSConstraint constrain) 150 lock (m_constraints)
141 { 151 {
142 if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) 152 foreach (BSConstraint constrain in m_constraints)
143 { 153 {
144 toRemove.Add(constrain); 154 if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
155 {
156 toRemove.Add(constrain);
157 }
145 } 158 }
146 return false;
147 });
148 lock (m_constraints)
149 {
150 foreach (BSConstraint constrain in toRemove) 159 foreach (BSConstraint constrain in toRemove)
151 { 160 {
152 m_constraints.Remove(constrain); 161 m_constraints.Remove(constrain);
@@ -158,27 +167,16 @@ public class BSConstraintCollection : IDisposable
158 167
159 public bool RecalculateAllConstraints() 168 public bool RecalculateAllConstraints()
160 { 169 {
161 foreach (BSConstraint constrain in m_constraints) 170 bool ret = false;
162 {
163 constrain.CalculateTransforms();
164 }
165 return true;
166 }
167
168 // Lock the constraint list and loop through it.
169 // The constraint action returns 'true' if it wants the loop aborted.
170 private void ForEachConstraint(ConstraintAction action)
171 {
172 lock (m_constraints) 171 lock (m_constraints)
173 { 172 {
174 foreach (BSConstraint constrain in m_constraints) 173 foreach (BSConstraint constrain in m_constraints)
175 { 174 {
176 if (action(constrain)) 175 constrain.CalculateTransforms();
177 break; 176 ret = true;
178 } 177 }
179 } 178 }
179 return ret;
180 } 180 }
181
182
183} 181}
184} 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 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35class 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 6f8430c..087b9bb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -37,10 +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 PhysicsScene { get { return m_physicsScene; } }
43 44
45 // The children under the root in this linkset
44 private List<BSPrim> m_children; 46 private List<BSPrim> m_children;
45 47
46 // We lock the diddling of linkset classes to prevent any badness. 48 // We lock the diddling of linkset classes to prevent any badness.
@@ -72,7 +74,7 @@ public class BSLinkset
72 public BSLinkset(BSScene scene, BSPrim parent) 74 public BSLinkset(BSScene scene, BSPrim parent)
73 { 75 {
74 // A simple linkset of one (no children) 76 // A simple linkset of one (no children)
75 m_scene = scene; 77 m_physicsScene = scene;
76 m_linksetRoot = parent; 78 m_linksetRoot = parent;
77 m_children = new List<BSPrim>(); 79 m_children = new List<BSPrim>();
78 m_mass = parent.MassRaw; 80 m_mass = parent.MassRaw;
@@ -80,16 +82,19 @@ public class BSLinkset
80 82
81 // Link to a linkset where the child knows the parent. 83 // Link to a linkset where the child knows the parent.
82 // Parent changing should not happen so do some sanity checking. 84 // Parent changing should not happen so do some sanity checking.
83 // We return the parent's linkset so the child can track it's membership. 85 // We return the parent's linkset so the child can track its membership.
84 public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent) 86 public BSLinkset AddMeToLinkset(BSPrim child)
85 { 87 {
86 lock (m_linksetActivityLock) 88 lock (m_linksetActivityLock)
87 { 89 {
88 parent.Linkset.AddChildToLinkset(child); 90 AddChildToLinkset(child);
89 } 91 }
90 return parent.Linkset; 92 return this;
91 } 93 }
92 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).
93 public BSLinkset RemoveMeFromLinkset(BSPrim child) 98 public BSLinkset RemoveMeFromLinkset(BSPrim child)
94 { 99 {
95 lock (m_linksetActivityLock) 100 lock (m_linksetActivityLock)
@@ -101,7 +106,7 @@ public class BSLinkset
101 { 106 {
102 // Note that we don't do a foreach because the remove routine 107 // Note that we don't do a foreach because the remove routine
103 // takes it out of the list. 108 // takes it out of the list.
104 RemoveChildFromLinkset(m_children[0]); 109 RemoveChildFromOtherLinkset(m_children[0]);
105 } 110 }
106 m_children.Clear(); // just to make sure 111 m_children.Clear(); // just to make sure
107 } 112 }
@@ -113,63 +118,17 @@ public class BSLinkset
113 } 118 }
114 119
115 // The child is down to a linkset of just itself 120 // The child is down to a linkset of just itself
116 return new BSLinkset(m_scene, child); 121 return new BSLinkset(PhysicsScene, child);
117 } 122 }
118 123
119 // An existing linkset had one of its members rebuilt or something.
120 // Go through the linkset and rebuild the pointers to the bodies of the linkset members.
121 public BSLinkset RefreshLinkset(BSPrim requestor)
122 {
123 BSLinkset ret = requestor.Linkset;
124
125 lock (m_linksetActivityLock)
126 {
127 System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID);
128 if (aPtr == System.IntPtr.Zero)
129 {
130 // That's odd. We can't find the root of the linkset.
131 // The linkset is somehow dead. The requestor is now a member of a linkset of one.
132 DetailLog("{0},RefreshLinkset.RemoveRoot,child={1}", m_linksetRoot.LocalID, m_linksetRoot.LocalID);
133 ret = RemoveMeFromLinkset(m_linksetRoot);
134 }
135 else
136 {
137 // Reconstruct the pointer to the body of the linkset root.
138 DetailLog("{0},RefreshLinkset.RebuildRoot,rootID={1},ptr={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, aPtr);
139 m_linksetRoot.Body = new BulletBody(m_linksetRoot.LocalID, aPtr);
140
141 List<BSPrim> toRemove = new List<BSPrim>();
142 foreach (BSPrim bsp in m_children)
143 {
144 aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, bsp.LocalID);
145 if (aPtr == System.IntPtr.Zero)
146 {
147 toRemove.Add(bsp);
148 }
149 else
150 {
151 // Reconstruct the pointer to the body of the linkset root.
152 DetailLog("{0},RefreshLinkset.RebuildChild,rootID={1},ptr={2}", bsp.LocalID, m_linksetRoot.LocalID, aPtr);
153 bsp.Body = new BulletBody(bsp.LocalID, aPtr);
154 }
155 }
156 foreach (BSPrim bsp in toRemove)
157 {
158 RemoveChildFromLinkset(bsp);
159 }
160 }
161 }
162
163 return ret;
164 }
165
166
167 // 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
168 public bool IsRoot(BSPrim requestor) 125 public bool IsRoot(BSPrim requestor)
169 { 126 {
170 return (requestor.LocalID == m_linksetRoot.LocalID); 127 return (requestor.LocalID == m_linksetRoot.LocalID);
171 } 128 }
172 129
130 public int NumberOfChildren { get { return m_children.Count; } }
131
173 // Return 'true' if this linkset has any children (more than the root member) 132 // Return 'true' if this linkset has any children (more than the root member)
174 public bool HasAnyChildren { get { return (m_children.Count > 0); } } 133 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
175 134
@@ -177,12 +136,15 @@ public class BSLinkset
177 public bool HasChild(BSPrim child) 136 public bool HasChild(BSPrim child)
178 { 137 {
179 bool ret = false; 138 bool ret = false;
180 foreach (BSPrim bp in m_children) 139 lock (m_linksetActivityLock)
181 { 140 {
182 if (child.LocalID == bp.LocalID) 141 foreach (BSPrim bp in m_children)
183 { 142 {
184 ret = true; 143 if (child.LocalID == bp.LocalID)
185 break; 144 {
145 ret = true;
146 break;
147 }
186 } 148 }
187 } 149 }
188 return ret; 150 return ret;
@@ -203,12 +165,16 @@ public class BSLinkset
203 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; 165 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw;
204 float totalMass = m_linksetRoot.MassRaw; 166 float totalMass = m_linksetRoot.MassRaw;
205 167
206 foreach (BSPrim bp in m_children) 168 lock (m_linksetActivityLock)
207 { 169 {
208 com += bp.Position * bp.MassRaw; 170 foreach (BSPrim bp in m_children)
209 totalMass += bp.MassRaw; 171 {
172 com += bp.Position * bp.MassRaw;
173 totalMass += bp.MassRaw;
174 }
175 if (totalMass != 0f)
176 com /= totalMass;
210 } 177 }
211 com /= totalMass;
212 178
213 return com; 179 return com;
214 } 180 }
@@ -217,135 +183,237 @@ public class BSLinkset
217 { 183 {
218 OMV.Vector3 com = m_linksetRoot.Position; 184 OMV.Vector3 com = m_linksetRoot.Position;
219 185
220 foreach (BSPrim bp in m_children) 186 lock (m_linksetActivityLock)
221 { 187 {
222 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);
223 } 193 }
224 com /= m_children.Count + 1;
225 194
226 return com; 195 return com;
227 } 196 }
228 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
229 // 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
230 public void AddChildToLinkset(BSPrim pchild) 250 // Called while LinkActivity is locked.
251 private void AddChildToLinkset(BSPrim child)
231 { 252 {
232 BSPrim child = pchild;
233 if (!HasChild(child)) 253 if (!HasChild(child))
234 { 254 {
235 m_children.Add(child); 255 m_children.Add(child);
236 256
237 m_scene.TaintedObject(delegate() 257 BSPrim rootx = LinksetRoot; // capture the root as of now
258 BSPrim childx = child;
259 m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
238 { 260 {
239 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);
240 DetailLog("{0},AddChildToLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); 262 // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
241 PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child 263 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child
242 }); 264 });
243 } 265 }
244 return; 266 return;
245 } 267 }
246 268
269 // Forcefully removing a child from a linkset.
270 // This is not being called by the child so we have to make sure the child doesn't think
271 // it's still connected to the linkset.
272 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
273 // has to be updated also (like pointer to prim's parent).
274 private void RemoveChildFromOtherLinkset(BSPrim pchild)
275 {
276 pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
277 RemoveChildFromLinkset(pchild);
278 }
279
247 // 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.
248 // 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.
249 public void RemoveChildFromLinkset(BSPrim pchild) 282 private void RemoveChildFromLinkset(BSPrim child)
250 { 283 {
251 BSPrim child = pchild;
252
253 if (m_children.Remove(child)) 284 if (m_children.Remove(child))
254 { 285 {
255 m_scene.TaintedObject(delegate() 286 BSPrim rootx = LinksetRoot; // capture the root as of now
287 BSPrim childx = child;
288 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
256 { 289 {
257 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); 290 // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
258 DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); 291 // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
259 292
260 if (m_children.Count == 0) 293 PhysicallyUnlinkAChildFromRoot(rootx, childx);
261 {
262 // if the linkset is empty, make sure all linkages have been removed
263 PhysicallyUnlinkAllChildrenFromRoot();
264 }
265 else
266 {
267 PhysicallyUnlinkAChildFromRoot(pchild);
268 }
269 }); 294 });
295
296 RecomputeLinksetConstraintVariables();
270 } 297 }
271 else 298 else
272 { 299 {
273 // 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.
274 // 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);
275 } 302 }
276 return; 303 return;
277 } 304 }
278 305
279 // Create a constraint between me (root of linkset) and the passed prim (the child). 306 // Create a constraint between me (root of linkset) and the passed prim (the child).
280 // Called at taint time! 307 // Called at taint time!
281 private void PhysicallyLinkAChildToRoot(BSPrim childPrim) 308 private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim)
282 { 309 {
283 // Zero motion for children so they don't interpolate 310 // Zero motion for children so they don't interpolate
284 childPrim.ZeroMotion(); 311 childPrim.ZeroMotion();
285 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 // ==================================================================================
286 // relative position normalized to the root prim 336 // relative position normalized to the root prim
287 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation); 337 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
288 OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation; 338 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
289 339
290 // relative rotation of the child to the parent 340 // relative rotation of the child to the parent
291 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; 341 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
342 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
292 343
293 // 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
294 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 345 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
295 // 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);
296 DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); 347 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
297 BSConstraint constrain = m_scene.Constraints.CreateConstraint( 348 BS6DofConstraint constrain = new BS6DofConstraint(
298 m_scene.World, m_linksetRoot.Body, childPrim.Body, 349 PhysicsScene.World, rootPrim.Body, childPrim.Body,
299 // childRelativePosition,
300 // childRelativeRotation,
301 OMV.Vector3.Zero, 350 OMV.Vector3.Zero,
302 OMV.Quaternion.Identity, 351 OMV.Quaternion.Inverse(rootPrim.Orientation),
303 OMV.Vector3.Zero, 352 OMV.Vector3.Zero,
304 OMV.Quaternion.Identity 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
305 ); 361 );
362 // ==================================================================================
363 */
364
365 m_physicsScene.Constraints.AddConstraint(constrain);
366
367 // zero linear and angular limits makes the objects unable to move in relation to each other
306 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 368 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
307 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 369 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
308 370
309 // tweek the constraint to increase stability 371 // tweek the constraint to increase stability
310 constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset)); 372 constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset));
311 constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor), 373 constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor),
312 m_scene.Params.linkConstraintTransMotorMaxVel, 374 PhysicsScene.Params.linkConstraintTransMotorMaxVel,
313 m_scene.Params.linkConstraintTransMotorMaxForce); 375 PhysicsScene.Params.linkConstraintTransMotorMaxForce);
314 constrain.SetCFMAndERP(m_scene.Params.linkConstraintCFM, m_scene.Params.linkConstraintERP); 376 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
315 377
378 RecomputeLinksetConstraintVariables();
316 } 379 }
317 380
318 // Remove linkage between myself and a particular child 381 // Remove linkage between myself and a particular child
319 // Called at taint time! 382 // Called at taint time!
320 private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim) 383 private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim)
321 { 384 {
322 DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", 385 // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
323 LogHeader, m_linksetRoot.LocalID, childPrim.LocalID); 386 // LogHeader, rootPrim.LocalID, childPrim.LocalID);
324 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); 387 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
325 // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID); 388
326 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.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
392 // Make the child refresh its location
393 BulletSimAPI.PushUpdate2(childPrim.Body.Ptr);
327 } 394 }
328 395
329 // Remove linkage between myself and any possible children I might have 396 // Remove linkage between myself and any possible children I might have
330 // Called at taint time! 397 // Called at taint time!
331 private void PhysicallyUnlinkAllChildrenFromRoot() 398 private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim)
332 { 399 {
333 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); 400 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
334 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID); 401 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
335 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body); 402
336 // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); 403 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body);
337 } 404 }
338 405
339 // Invoke the detailed logger and output something if it's enabled. 406 // Invoke the detailed logger and output something if it's enabled.
340 private void DebugLog(string msg, params Object[] args) 407 private void DebugLog(string msg, params Object[] args)
341 { 408 {
342 m_scene.Logger.DebugFormat(msg, args); 409 if (m_physicsScene.ShouldDebugLog)
410 m_physicsScene.Logger.DebugFormat(msg, args);
343 } 411 }
344 412
345 // Invoke the detailed logger and output something if it's enabled. 413 // Invoke the detailed logger and output something if it's enabled.
346 private void DetailLog(string msg, params Object[] args) 414 private void DetailLog(string msg, params Object[] args)
347 { 415 {
348 m_scene.PhysicsLogging.Write(msg, args); 416 m_physicsScene.PhysicsLogging.Write(msg, args);
349 } 417 }
350 418
351} 419}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index ebfd85b..9c20004 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -42,7 +42,7 @@ public sealed class BSPrim : PhysicsActor
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 private static readonly string LogHeader = "[BULLETS PRIM]"; 43 private static readonly string LogHeader = "[BULLETS PRIM]";
44 44
45 private void DebugLog(string mm, params Object[] xx) { if (_scene.shouldDebugLog) m_log.DebugFormat(mm, xx); } 45 private void DebugLog(string mm, params Object[] xx) { if (_scene.ShouldDebugLog) m_log.DebugFormat(mm, xx); }
46 46
47 private IMesh _mesh; 47 private IMesh _mesh;
48 private PrimitiveBaseShape _pbs; 48 private PrimitiveBaseShape _pbs;
@@ -138,14 +138,15 @@ public sealed class BSPrim : PhysicsActor
138 _isPhysical = pisPhysical; 138 _isPhysical = pisPhysical;
139 _isVolumeDetect = false; 139 _isVolumeDetect = false;
140 _subscribedEventsMs = 0; 140 _subscribedEventsMs = 0;
141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material
143 _restitution = _scene.Params.defaultRestitution; 143 _restitution = _scene.Params.defaultRestitution;
144 _linkset = new BSLinkset(_scene, this); // a linkset of one 144 _linkset = new BSLinkset(_scene, this); // a linkset of one
145 _vehicle = new BSDynamics(this); // add vehicleness 145 _vehicle = new BSDynamics(this); // add vehicleness
146 _mass = CalculateMass(); 146 _mass = CalculateMass();
147 // do the actual object creation at taint time 147 // do the actual object creation at taint time
148 _scene.TaintedObject(delegate() 148 DetailLog("{0},BSPrim.constructor,call", LocalID);
149 _scene.TaintedObject("BSPrim.create", delegate()
149 { 150 {
150 RecreateGeomAndObject(); 151 RecreateGeomAndObject();
151 152
@@ -160,17 +161,22 @@ public sealed class BSPrim : PhysicsActor
160 public void Destroy() 161 public void Destroy()
161 { 162 {
162 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 163 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
163 // DetailLog("{0},Destroy", LocalID); 164
165 // Undo any links between me and any other object
166 BSPrim parentBefore = _linkset.LinksetRoot;
167 int childrenBefore = _linkset.NumberOfChildren;
168
169 _linkset = _linkset.RemoveMeFromLinkset(this);
170
171 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
172 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
164 173
165 // Undo any vehicle properties 174 // Undo any vehicle properties
166 _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); 175 this.VehicleType = (int)Vehicle.TYPE_NONE;
167 _scene.RemoveVehiclePrim(this); // just to make sure
168 176
169 _scene.TaintedObject(delegate() 177 _scene.TaintedObject("BSPrim.destroy", delegate()
170 { 178 {
171 // Undo any links between me and any other object 179 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
172 _linkset = _linkset.RemoveMeFromLinkset(this);
173
174 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 180 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
175 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); 181 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
176 }); 182 });
@@ -183,11 +189,11 @@ public sealed class BSPrim : PhysicsActor
183 get { return _size; } 189 get { return _size; }
184 set { 190 set {
185 _size = value; 191 _size = value;
186 _scene.TaintedObject(delegate() 192 _scene.TaintedObject("BSPrim.setSize", delegate()
187 { 193 {
188 _mass = CalculateMass(); // changing size changes the mass 194 _mass = CalculateMass(); // changing size changes the mass
189 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); 195 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
190 DetailLog("{0}: setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); 196 // DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical);
191 RecreateGeomAndObject(); 197 RecreateGeomAndObject();
192 }); 198 });
193 } 199 }
@@ -195,7 +201,7 @@ public sealed class BSPrim : PhysicsActor
195 public override PrimitiveBaseShape Shape { 201 public override PrimitiveBaseShape Shape {
196 set { 202 set {
197 _pbs = value; 203 _pbs = value;
198 _scene.TaintedObject(delegate() 204 _scene.TaintedObject("BSPrim.setShape", delegate()
199 { 205 {
200 _mass = CalculateMass(); // changing the shape changes the mass 206 _mass = CalculateMass(); // changing the shape changes the mass
201 RecreateGeomAndObject(); 207 RecreateGeomAndObject();
@@ -213,7 +219,7 @@ public sealed class BSPrim : PhysicsActor
213 public override bool Selected { 219 public override bool Selected {
214 set { 220 set {
215 _isSelected = value; 221 _isSelected = value;
216 _scene.TaintedObject(delegate() 222 _scene.TaintedObject("BSPrim.setSelected", delegate()
217 { 223 {
218 SetObjectDynamic(); 224 SetObjectDynamic();
219 }); 225 });
@@ -224,10 +230,17 @@ public sealed class BSPrim : PhysicsActor
224 // link me to the specified parent 230 // link me to the specified parent
225 public override void link(PhysicsActor obj) { 231 public override void link(PhysicsActor obj) {
226 BSPrim parent = obj as BSPrim; 232 BSPrim parent = obj as BSPrim;
227 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); 233 if (parent != null)
228 DetailLog("{0},link,parent={1}", LocalID, obj.LocalID); 234 {
235 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID);
236 BSPrim parentBefore = _linkset.LinksetRoot;
237 int childrenBefore = _linkset.NumberOfChildren;
229 238
230 _linkset = _linkset.AddMeToLinkset(this, parent); 239 _linkset = parent.Linkset.AddMeToLinkset(this);
240
241 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
242 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
243 }
231 return; 244 return;
232 } 245 }
233 246
@@ -236,10 +249,15 @@ public sealed class BSPrim : PhysicsActor
236 // 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
237 // 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
238 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, 251 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
239 _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString()); 252 _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString());
240 DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString()); 253
254 BSPrim parentBefore = _linkset.LinksetRoot;
255 int childrenBefore = _linkset.NumberOfChildren;
256
257 _linkset = _linkset.RemoveMeFromLinkset(this);
241 258
242 _linkset.RemoveMeFromLinkset(this); 259 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
260 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
243 return; 261 return;
244 } 262 }
245 263
@@ -262,7 +280,7 @@ public sealed class BSPrim : PhysicsActor
262 280
263 public override void LockAngularMotion(OMV.Vector3 axis) 281 public override void LockAngularMotion(OMV.Vector3 axis)
264 { 282 {
265 DetailLog("{0},LockAngularMotion,call,axis={1}", LocalID, axis); 283 // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
266 return; 284 return;
267 } 285 }
268 286
@@ -279,9 +297,9 @@ public sealed class BSPrim : PhysicsActor
279 set { 297 set {
280 _position = value; 298 _position = value;
281 // 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?
282 _scene.TaintedObject(delegate() 300 _scene.TaintedObject("BSPrim.setPosition", delegate()
283 { 301 {
284 DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 302 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
285 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 303 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
286 }); 304 });
287 } 305 }
@@ -316,9 +334,9 @@ public sealed class BSPrim : PhysicsActor
316 get { return _force; } 334 get { return _force; }
317 set { 335 set {
318 _force = value; 336 _force = value;
319 _scene.TaintedObject(delegate() 337 _scene.TaintedObject("BSPrim.setForce", delegate()
320 { 338 {
321 DetailLog("{0},SetForce,taint,force={1}", LocalID, _force); 339 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
322 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 340 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
323 BulletSimAPI.SetObjectForce2(Body.Ptr, _force); 341 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
324 }); 342 });
@@ -331,53 +349,41 @@ public sealed class BSPrim : PhysicsActor
331 } 349 }
332 set { 350 set {
333 Vehicle type = (Vehicle)value; 351 Vehicle type = (Vehicle)value;
334 _scene.TaintedObject(delegate() 352 BSPrim vehiclePrim = this;
353 _scene.TaintedObject("setVehicleType", delegate()
335 { 354 {
336 DetailLog("{0},SetVehicleType,taint,type={1}", LocalID, type); 355 // Done at taint time so we're sure the physics engine is not using the variables
356 // Vehicle code changes the parameters for this vehicle type.
337 _vehicle.ProcessTypeChange(type); 357 _vehicle.ProcessTypeChange(type);
338 if (type == Vehicle.TYPE_NONE) 358 // Tell the scene about the vehicle so it will get processing each frame.
339 { 359 _scene.VehicleInSceneTypeChanged(this, type);
340 _scene.RemoveVehiclePrim(this);
341 }
342 else
343 {
344 _scene.TaintedObject(delegate()
345 {
346 // Tell the physics engine to clear state
347 BulletSimAPI.ClearForces2(this.Body.Ptr);
348 });
349
350 // make it so the scene will call us each tick to do vehicle things
351 _scene.AddVehiclePrim(this);
352 }
353 return;
354 }); 360 });
355 } 361 }
356 } 362 }
357 public override void VehicleFloatParam(int param, float value) 363 public override void VehicleFloatParam(int param, float value)
358 { 364 {
359 _scene.TaintedObject(delegate() 365 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
360 { 366 {
361 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 367 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
362 }); 368 });
363 } 369 }
364 public override void VehicleVectorParam(int param, OMV.Vector3 value) 370 public override void VehicleVectorParam(int param, OMV.Vector3 value)
365 { 371 {
366 _scene.TaintedObject(delegate() 372 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
367 { 373 {
368 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 374 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
369 }); 375 });
370 } 376 }
371 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 377 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
372 { 378 {
373 _scene.TaintedObject(delegate() 379 _scene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
374 { 380 {
375 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 381 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
376 }); 382 });
377 } 383 }
378 public override void VehicleFlags(int param, bool remove) 384 public override void VehicleFlags(int param, bool remove)
379 { 385 {
380 _scene.TaintedObject(delegate() 386 _scene.TaintedObject("BSPrim.VehicleFlags", delegate()
381 { 387 {
382 _vehicle.ProcessVehicleFlags(param, remove); 388 _vehicle.ProcessVehicleFlags(param, remove);
383 }); 389 });
@@ -395,7 +401,7 @@ public sealed class BSPrim : PhysicsActor
395 public override void SetVolumeDetect(int param) { 401 public override void SetVolumeDetect(int param) {
396 bool newValue = (param != 0); 402 bool newValue = (param != 0);
397 _isVolumeDetect = newValue; 403 _isVolumeDetect = newValue;
398 _scene.TaintedObject(delegate() 404 _scene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
399 { 405 {
400 SetObjectDynamic(); 406 SetObjectDynamic();
401 }); 407 });
@@ -406,9 +412,9 @@ public sealed class BSPrim : PhysicsActor
406 get { return _velocity; } 412 get { return _velocity; }
407 set { 413 set {
408 _velocity = value; 414 _velocity = value;
409 _scene.TaintedObject(delegate() 415 _scene.TaintedObject("BSPrim.setVelocity", delegate()
410 { 416 {
411 DetailLog("{0},SetVelocity,taint,vel={1}", LocalID, _velocity); 417 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
412 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 418 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
413 }); 419 });
414 } 420 }
@@ -416,7 +422,7 @@ public sealed class BSPrim : PhysicsActor
416 public override OMV.Vector3 Torque { 422 public override OMV.Vector3 Torque {
417 get { return _torque; } 423 get { return _torque; }
418 set { _torque = value; 424 set { _torque = value;
419 DetailLog("{0},SetTorque,call,torque={1}", LocalID, _torque); 425 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
420 } 426 }
421 } 427 }
422 public override float CollisionScore { 428 public override float CollisionScore {
@@ -440,10 +446,10 @@ public sealed class BSPrim : PhysicsActor
440 set { 446 set {
441 _orientation = value; 447 _orientation = value;
442 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? 448 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
443 _scene.TaintedObject(delegate() 449 _scene.TaintedObject("BSPrim.setOrientation", delegate()
444 { 450 {
445 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 451 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
446 DetailLog("{0},SetOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 452 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
447 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 453 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
448 }); 454 });
449 } 455 }
@@ -457,7 +463,7 @@ public sealed class BSPrim : PhysicsActor
457 get { return _isPhysical; } 463 get { return _isPhysical; }
458 set { 464 set {
459 _isPhysical = value; 465 _isPhysical = value;
460 _scene.TaintedObject(delegate() 466 _scene.TaintedObject("BSPrim.setIsPhysical", delegate()
461 { 467 {
462 SetObjectDynamic(); 468 SetObjectDynamic();
463 }); 469 });
@@ -478,7 +484,6 @@ public sealed class BSPrim : PhysicsActor
478 484
479 // Make gravity work if the object is physical and not selected 485 // Make gravity work if the object is physical and not selected
480 // No locking here because only called when it is safe 486 // No locking here because only called when it is safe
481 // Only called at taint time so it is save to call into Bullet.
482 private void SetObjectDynamic() 487 private void SetObjectDynamic()
483 { 488 {
484 // RA: remove this for the moment. 489 // RA: remove this for the moment.
@@ -487,13 +492,16 @@ public sealed class BSPrim : PhysicsActor
487 // Maybe a VerifyCorrectPhysicalShape() routine? 492 // Maybe a VerifyCorrectPhysicalShape() routine?
488 // RecreateGeomAndObject(); 493 // RecreateGeomAndObject();
489 494
490 float mass = _mass; 495 // Bullet wants static objects to have a mass of zero
491 // Bullet wants static objects have a mass of zero 496 float mass = IsStatic ? 0f : _mass;
492 if (IsStatic)
493 mass = 0f;
494 497
495 DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, mass);
496 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); 498 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
499
500 // recompute any linkset parameters
501 _linkset.Refresh(this);
502
503 CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr);
504 // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf);
497 } 505 }
498 506
499 // prims don't fly 507 // prims don't fly
@@ -548,9 +556,9 @@ public sealed class BSPrim : PhysicsActor
548 set { 556 set {
549 _rotationalVelocity = value; 557 _rotationalVelocity = value;
550 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 558 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
551 _scene.TaintedObject(delegate() 559 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
552 { 560 {
553 DetailLog("{0},SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 561 // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
554 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 562 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
555 }); 563 });
556 } 564 }
@@ -565,9 +573,9 @@ public sealed class BSPrim : PhysicsActor
565 get { return _buoyancy; } 573 get { return _buoyancy; }
566 set { 574 set {
567 _buoyancy = value; 575 _buoyancy = value;
568 _scene.TaintedObject(delegate() 576 _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
569 { 577 {
570 DetailLog("{0},SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 578 // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
571 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 579 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
572 }); 580 });
573 } 581 }
@@ -607,6 +615,7 @@ public sealed class BSPrim : PhysicsActor
607 615
608 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); 616 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
609 public override void AddForce(OMV.Vector3 force, bool pushforce) { 617 public override void AddForce(OMV.Vector3 force, bool pushforce) {
618 // for an object, doesn't matter if force is a pushforce or not
610 if (force.IsFinite()) 619 if (force.IsFinite())
611 { 620 {
612 // _force += force; 621 // _force += force;
@@ -618,40 +627,48 @@ public sealed class BSPrim : PhysicsActor
618 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 627 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
619 return; 628 return;
620 } 629 }
621 _scene.TaintedObject(delegate() 630 _scene.TaintedObject("BSPrim.AddForce", delegate()
622 { 631 {
632 OMV.Vector3 fSum = OMV.Vector3.Zero;
623 lock (m_accumulatedForces) 633 lock (m_accumulatedForces)
624 { 634 {
625 if (m_accumulatedForces.Count > 0) 635 foreach (OMV.Vector3 v in m_accumulatedForces)
626 { 636 {
627 OMV.Vector3 fSum = OMV.Vector3.Zero; 637 fSum += v;
628 foreach (OMV.Vector3 v in m_accumulatedForces)
629 {
630 fSum += v;
631 }
632 m_accumulatedForces.Clear();
633
634 DetailLog("{0},SetObjectForce,taint,force={1}", LocalID, fSum);
635 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, fSum);
636 } 638 }
639 m_accumulatedForces.Clear();
637 } 640 }
641 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force);
642 BulletSimAPI.AddObjectForce2(Body.Ptr, fSum);
638 }); 643 });
639 } 644 }
640 645
641 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 646 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
642 DetailLog("{0},AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); 647 // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
643 // 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);
644 } 649 }
645 public override void SetMomentum(OMV.Vector3 momentum) { 650 public override void SetMomentum(OMV.Vector3 momentum) {
646 DetailLog("{0},SetMomentum,call,mom={1}", LocalID, momentum); 651 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
647 } 652 }
648 public override void SubscribeEvents(int ms) { 653 public override void SubscribeEvents(int ms) {
649 _subscribedEventsMs = ms; 654 _subscribedEventsMs = ms;
650 // make sure first collision happens 655 if (ms > 0)
651 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; 656 {
657 // make sure first collision happens
658 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
659
660 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
661 {
662 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
663 });
664 }
652 } 665 }
653 public override void UnSubscribeEvents() { 666 public override void UnSubscribeEvents() {
654 _subscribedEventsMs = 0; 667 _subscribedEventsMs = 0;
668 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
669 {
670 BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
671 });
655 } 672 }
656 public override bool SubscribedEvents() { 673 public override bool SubscribedEvents() {
657 return (_subscribedEventsMs > 0); 674 return (_subscribedEventsMs > 0);
@@ -970,26 +987,26 @@ public sealed class BSPrim : PhysicsActor
970 { 987 {
971 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 988 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
972 { 989 {
973 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 990 // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
974 { 991 // {
975 // 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);
976 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) 993 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
977 { 994 {
978 DetailLog("{0},CreateGeom,sphere", LocalID); 995 // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
979 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 996 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
980 // 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
981 _scale = _size; 998 _scale = _size;
982 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 999 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
983 ret = true; 1000 ret = true;
984 } 1001 }
985 } 1002 // }
986 } 1003 }
987 else 1004 else
988 { 1005 {
989 // 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);
990 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) 1007 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
991 { 1008 {
992 DetailLog("{0},CreateGeom,box", LocalID); 1009 // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
993 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 1010 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
994 _scale = _size; 1011 _scale = _size;
995 // 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?
@@ -1032,12 +1049,12 @@ public sealed class BSPrim : PhysicsActor
1032 // 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
1033 if (_meshKey == newMeshKey) return; 1050 if (_meshKey == newMeshKey) return;
1034 1051
1035 DetailLog("{0},CreateGeomMesh,create,key={1}", LocalID, _meshKey); 1052 // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1036 // 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
1037 if (_meshKey != 0) 1054 if (_meshKey != 0)
1038 { 1055 {
1039 // 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);
1040 DetailLog("{0},CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); 1057 // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
1041 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1058 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1042 _mesh = null; 1059 _mesh = null;
1043 _meshKey = 0; 1060 _meshKey = 0;
@@ -1067,7 +1084,7 @@ public sealed class BSPrim : PhysicsActor
1067 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1084 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1068 // meshes are already scaled by the meshmerizer 1085 // meshes are already scaled by the meshmerizer
1069 _scale = new OMV.Vector3(1f, 1f, 1f); 1086 _scale = new OMV.Vector3(1f, 1f, 1f);
1070 DetailLog("{0},CreateGeomMesh,done", LocalID); 1087 // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID);
1071 return; 1088 return;
1072 } 1089 }
1073 1090
@@ -1081,28 +1098,21 @@ public sealed class BSPrim : PhysicsActor
1081 // if the hull hasn't changed, don't rebuild it 1098 // if the hull hasn't changed, don't rebuild it
1082 if (newHullKey == _hullKey) return; 1099 if (newHullKey == _hullKey) return;
1083 1100
1084 DetailLog("{0},CreateGeomHull,create,key={1}", LocalID, _meshKey); 1101 // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey);
1085 1102
1086 // 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
1087 if (_hullKey != 0) 1104 if (_hullKey != 0)
1088 { 1105 {
1089 // 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);
1090 DetailLog("{0},CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey); 1107 // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey);
1091 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1108 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1092 _hullKey = 0; 1109 _hullKey = 0;
1093 _hulls.Clear();
1094 DetailLog("{0},CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey);
1095 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1096 _mesh = null; // the mesh cannot match either
1097 _meshKey = 0;
1098 } 1110 }
1099 1111
1100 _hullKey = newHullKey; 1112 _hullKey = newHullKey;
1101 if (_meshKey != _hullKey) 1113
1102 { 1114 // Make sure the underlying mesh exists and is correct
1103 // if the underlying mesh has changed, rebuild it 1115 CreateGeomMesh();
1104 CreateGeomMesh();
1105 }
1106 1116
1107 int[] indices = _mesh.getIndexListAsInt(); 1117 int[] indices = _mesh.getIndexListAsInt();
1108 List<OMV.Vector3> vertices = _mesh.getVertexList(); 1118 List<OMV.Vector3> vertices = _mesh.getVertexList();
@@ -1128,7 +1138,7 @@ public sealed class BSPrim : PhysicsActor
1128 // create the hull into the _hulls variable 1138 // create the hull into the _hulls variable
1129 convexBuilder.process(dcomp); 1139 convexBuilder.process(dcomp);
1130 1140
1131 // Convert the vertices and indices for passing to unmanaged 1141 // Convert the vertices and indices for passing to unmanaged.
1132 // The hull information is passed as a large floating point array. 1142 // The hull information is passed as a large floating point array.
1133 // The format is: 1143 // The format is:
1134 // convHulls[0] = number of hulls 1144 // convHulls[0] = number of hulls
@@ -1188,7 +1198,7 @@ public sealed class BSPrim : PhysicsActor
1188 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1198 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1189 // meshes are already scaled by the meshmerizer 1199 // meshes are already scaled by the meshmerizer
1190 _scale = new OMV.Vector3(1f, 1f, 1f); 1200 _scale = new OMV.Vector3(1f, 1f, 1f);
1191 DetailLog("{0},CreateGeomHull,done", LocalID); 1201 // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1192 return; 1202 return;
1193 } 1203 }
1194 1204
@@ -1214,7 +1224,7 @@ public sealed class BSPrim : PhysicsActor
1214 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); 1224 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1215 1225
1216 // the CreateObject() may have recreated the rigid body. Make sure we have the latest. 1226 // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
1217 m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID); 1227 Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
1218 1228
1219 return ret; 1229 return ret;
1220 } 1230 }
@@ -1326,8 +1336,8 @@ public sealed class BSPrim : PhysicsActor
1326 1336
1327 // 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}",
1328 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1338 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1329 DetailLog("{0},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}",
1330 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1340 // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1331 1341
1332 base.RequestPhysicsterseUpdate(); 1342 base.RequestPhysicsterseUpdate();
1333 } 1343 }
@@ -1335,7 +1345,7 @@ public sealed class BSPrim : PhysicsActor
1335 else 1345 else
1336 { 1346 {
1337 // For debugging, we also report the movement of children 1347 // For debugging, we also report the movement of children
1338 DetailLog("{0},UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1348 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1339 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1349 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1340 entprop.Acceleration, entprop.RotationalVelocity); 1350 entprop.Acceleration, entprop.RotationalVelocity);
1341 } 1351 }
@@ -1343,7 +1353,7 @@ public sealed class BSPrim : PhysicsActor
1343 } 1353 }
1344 1354
1345 // I've collided with something 1355 // I've collided with something
1346 CollisionEventUpdate collisionCollection = null; 1356 CollisionEventUpdate collisionCollection;
1347 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)
1348 { 1358 {
1349 // 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);
@@ -1355,6 +1365,8 @@ public sealed class BSPrim : PhysicsActor
1355 _collidingGroundStep = _scene.SimulationStep; 1365 _collidingGroundStep = _scene.SimulationStep;
1356 } 1366 }
1357 1367
1368 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
1369
1358 // if someone is subscribed to collision events.... 1370 // if someone is subscribed to collision events....
1359 if (_subscribedEventsMs != 0) { 1371 if (_subscribedEventsMs != 0) {
1360 // 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
@@ -1375,7 +1387,9 @@ public sealed class BSPrim : PhysicsActor
1375 if (collisionCollection != null && collisionCollection.Count > 0) 1387 if (collisionCollection != null && collisionCollection.Count > 0)
1376 { 1388 {
1377 base.SendCollisionUpdate(collisionCollection); 1389 base.SendCollisionUpdate(collisionCollection);
1378 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;
1379 } 1393 }
1380 } 1394 }
1381 1395
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 011033c..a31c578 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -73,7 +73,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
74 private static readonly string LogHeader = "[BULLETS SCENE]"; 74 private static readonly string LogHeader = "[BULLETS SCENE]";
75 75
76 public void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); } 76 public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); }
77 77
78 public string BulletSimVersion = "?"; 78 public string BulletSimVersion = "?";
79 79
@@ -162,14 +162,24 @@ public class BSScene : PhysicsScene, IPhysicsParameters
162 } 162 }
163 163
164 public delegate void TaintCallback(); 164 public delegate void TaintCallback();
165 private List<TaintCallback> _taintedObjects; 165 private struct TaintCallbackEntry
166 {
167 public String ident;
168 public TaintCallback callback;
169 public TaintCallbackEntry(string i, TaintCallback c)
170 {
171 ident = i;
172 callback = c;
173 }
174 }
175 private List<TaintCallbackEntry> _taintedObjects;
166 private Object _taintLock = new Object(); 176 private Object _taintLock = new Object();
167 177
168 // A pointer to an instance if this structure is passed to the C++ code 178 // A pointer to an instance if this structure is passed to the C++ code
169 ConfigurationParameters[] m_params; 179 ConfigurationParameters[] m_params;
170 GCHandle m_paramsHandle; 180 GCHandle m_paramsHandle;
171 181
172 public bool shouldDebugLog { get; private set; } 182 public bool ShouldDebugLog { get; private set; }
173 183
174 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; 184 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
175 185
@@ -232,7 +242,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
232 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); 242 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
233 } 243 }
234 244
235 _taintedObjects = new List<TaintCallback>(); 245 _taintedObjects = new List<TaintCallbackEntry>();
236 246
237 mesher = meshmerizer; 247 mesher = meshmerizer;
238 // The bounding box for the simulated world 248 // The bounding box for the simulated world
@@ -245,7 +255,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
245 255
246 // Initialization to support the transition to a new API which puts most of the logic 256 // Initialization to support the transition to a new API which puts most of the logic
247 // into the C# code so it is easier to modify and add to. 257 // into the C# code so it is easier to modify and add to.
248 m_worldSim = new BulletSim(m_worldID, BulletSimAPI.GetSimHandle2(m_worldID)); 258 m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID));
249 m_constraintCollection = new BSConstraintCollection(World); 259 m_constraintCollection = new BSConstraintCollection(World);
250 260
251 m_initialized = true; 261 m_initialized = true;
@@ -352,7 +362,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
352 BSPrim bsprim = prim as BSPrim; 362 BSPrim bsprim = prim as BSPrim;
353 if (bsprim != null) 363 if (bsprim != null)
354 { 364 {
355 m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); 365 // DetailLog("{0},RemovePrim,call", bsprim.LocalID);
366 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
356 try 367 try
357 { 368 {
358 lock (m_prims) m_prims.Remove(bsprim.LocalID); 369 lock (m_prims) m_prims.Remove(bsprim.LocalID);
@@ -377,6 +388,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
377 388
378 if (!m_initialized) return null; 389 if (!m_initialized) return null;
379 390
391 // DetailLog("{0},AddPrimShape,call", localID);
392
380 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);
381 lock (m_prims) m_prims.Add(localID, prim); 394 lock (m_prims) m_prims.Add(localID, prim);
382 return prim; 395 return prim;
@@ -400,7 +413,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
400 // prevent simulation until we've been initialized 413 // prevent simulation until we've been initialized
401 if (!m_initialized) return 10.0f; 414 if (!m_initialized) return 10.0f;
402 415
403 long simulateStartTime = Util.EnvironmentTickCount(); 416 int simulateStartTime = Util.EnvironmentTickCount();
404 417
405 // 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
406 ProcessTaints(); 419 ProcessTaints();
@@ -416,12 +429,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
416 { 429 {
417 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, 430 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
418 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 431 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
419 DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", "0000000000", numSubSteps, updatedEntityCount, collidersCount); 432 // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
420 } 433 }
421 catch (Exception e) 434 catch (Exception e)
422 { 435 {
423 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);
424 DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", "0000000000", numSubSteps, updatedEntityCount, collidersCount); 437 // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
425 // updatedEntityCount = 0; 438 // updatedEntityCount = 0;
426 collidersCount = 0; 439 collidersCount = 0;
427 } 440 }
@@ -498,8 +511,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
498 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); 511 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
499 // return (timeStep * (float)simulateTotalTime); 512 // return (timeStep * (float)simulateTotalTime);
500 513
501 // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. 514 // TODO: FIX THIS: fps calculation possibly wrong.
502 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);
503 } 521 }
504 522
505 // Something has collided 523 // Something has collided
@@ -535,7 +553,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
535 553
536 public override void SetTerrain(float[] heightMap) { 554 public override void SetTerrain(float[] heightMap) {
537 m_heightMap = heightMap; 555 m_heightMap = heightMap;
538 this.TaintedObject(delegate() 556 this.TaintedObject("BSScene.SetTerrain", delegate()
539 { 557 {
540 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap); 558 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
541 }); 559 });
@@ -577,12 +595,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
577 // make sure no stepping happens while we're deleting stuff 595 // make sure no stepping happens while we're deleting stuff
578 m_initialized = false; 596 m_initialized = false;
579 597
580 if (m_constraintCollection != null)
581 {
582 m_constraintCollection.Dispose();
583 m_constraintCollection = null;
584 }
585
586 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 598 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
587 { 599 {
588 kvp.Value.Destroy(); 600 kvp.Value.Destroy();
@@ -595,6 +607,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
595 } 607 }
596 m_prims.Clear(); 608 m_prims.Clear();
597 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
598 // Anything left in the unmanaged code should be cleaned out 617 // Anything left in the unmanaged code should be cleaned out
599 BulletSimAPI.Shutdown(WorldID); 618 BulletSimAPI.Shutdown(WorldID);
600 619
@@ -727,12 +746,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
727 // Calls to the PhysicsActors can't directly call into the physics engine 746 // Calls to the PhysicsActors can't directly call into the physics engine
728 // because it might be busy. We delay changes to a known time. 747 // because it might be busy. We delay changes to a known time.
729 // We rely on C#'s closure to save and restore the context for the delegate. 748 // We rely on C#'s closure to save and restore the context for the delegate.
730 public void TaintedObject(TaintCallback callback) 749 public void TaintedObject(String ident, TaintCallback callback)
731 { 750 {
732 if (!m_initialized) return; 751 if (!m_initialized) return;
733 752
734 lock (_taintLock) 753 lock (_taintLock)
735 _taintedObjects.Add(callback); 754 _taintedObjects.Add(new TaintCallbackEntry(ident, callback));
736 return; 755 return;
737 } 756 }
738 757
@@ -744,22 +763,22 @@ public class BSScene : PhysicsScene, IPhysicsParameters
744 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process 763 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process
745 { 764 {
746 // swizzle a new list into the list location so we can process what's there 765 // swizzle a new list into the list location so we can process what's there
747 List<TaintCallback> oldList; 766 List<TaintCallbackEntry> oldList;
748 lock (_taintLock) 767 lock (_taintLock)
749 { 768 {
750 oldList = _taintedObjects; 769 oldList = _taintedObjects;
751 _taintedObjects = new List<TaintCallback>(); 770 _taintedObjects = new List<TaintCallbackEntry>();
752 } 771 }
753 772
754 foreach (TaintCallback callback in oldList) 773 foreach (TaintCallbackEntry tcbe in oldList)
755 { 774 {
756 try 775 try
757 { 776 {
758 callback(); 777 tcbe.callback();
759 } 778 }
760 catch (Exception e) 779 catch (Exception e)
761 { 780 {
762 m_log.ErrorFormat("{0}: ProcessTaints: Exception: {1}", LogHeader, e); 781 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
763 } 782 }
764 } 783 }
765 oldList.Clear(); 784 oldList.Clear();
@@ -767,6 +786,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters
767 } 786 }
768 787
769 #region Vehicles 788 #region Vehicles
789
790 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
791 {
792 if (newType == Vehicle.TYPE_NONE)
793 {
794 RemoveVehiclePrim(vehic);
795 }
796 else
797 {
798 // make it so the scene will call us each tick to do vehicle things
799 AddVehiclePrim(vehic);
800 }
801 }
802
770 // Make so the scene will call this prim for vehicle actions each tick. 803 // Make so the scene will call this prim for vehicle actions each tick.
771 // Safe to call if prim is already in the vehicle list. 804 // Safe to call if prim is already in the vehicle list.
772 public void AddVehiclePrim(BSPrim vehicle) 805 public void AddVehiclePrim(BSPrim vehicle)
@@ -812,12 +845,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
812 845
813 private struct ParameterDefn 846 private struct ParameterDefn
814 { 847 {
815 public string name; 848 public string name; // string name of the parameter
816 public string desc; 849 public string desc; // a short description of what the parameter means
817 public float defaultValue; 850 public float defaultValue; // default value if not specified anywhere else
818 public ParamUser userParam; 851 public ParamUser userParam; // get the value from the configuration file
819 public ParamGet getter; 852 public ParamGet getter; // return the current value stored for this parameter
820 public ParamSet setter; 853 public ParamSet setter; // set the current value for this parameter
821 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) 854 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
822 { 855 {
823 name = n; 856 name = n;
@@ -834,7 +867,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
834 // To add a new externally referencable/settable parameter, add the paramter storage 867 // To add a new externally referencable/settable parameter, add the paramter storage
835 // location somewhere in the program and make an entry in this table with the 868 // location somewhere in the program and make an entry in this table with the
836 // getters and setters. 869 // getters and setters.
837 // To add a new variable, it is easiest to find an existing definition and copy it. 870 // It is easiest to find an existing definition and copy it.
838 // Parameter values are floats. Booleans are converted to a floating value. 871 // Parameter values are floats. Booleans are converted to a floating value.
839 // 872 //
840 // A ParameterDefn() takes the following parameters: 873 // A ParameterDefn() takes the following parameters:
@@ -870,7 +903,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
870 (s) => { return (float)s.m_meshLOD; }, 903 (s) => { return (float)s.m_meshLOD; },
871 (s,p,l,v) => { s.m_meshLOD = (int)v; } ), 904 (s,p,l,v) => { s.m_meshLOD = (int)v; } ),
872 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", 905 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
873 32, 906 32f,
874 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, 907 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); },
875 (s) => { return (float)s.m_sculptLOD; }, 908 (s) => { return (float)s.m_sculptLOD; },
876 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), 909 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ),
@@ -1027,14 +1060,19 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1027 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), 1060 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1028 1061
1029 1062
1030 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)", 1063 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
1031 0f, // zero to disable 1064 0f, // zero to disable
1032 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, 1065 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
1033 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, 1066 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
1034 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), 1067 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1068 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
1069 0f, // zero to disable
1070 (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
1071 (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
1072 (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
1035 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", 1073 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
1036 ConfigurationParameters.numericTrue, 1074 ConfigurationParameters.numericFalse,
1037 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1075 (s,cf,p,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1038 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; }, 1076 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; },
1039 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ), 1077 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
1040 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", 1078 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
@@ -1101,9 +1139,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1101 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), 1139 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
1102 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements", 1140 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
1103 ConfigurationParameters.numericFalse, 1141 ConfigurationParameters.numericFalse,
1104 (s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); }, 1142 (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
1105 (s) => { return s.NumericBool(s.shouldDebugLog); }, 1143 (s) => { return s.NumericBool(s.ShouldDebugLog); },
1106 (s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(v); } ), 1144 (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ),
1107 1145
1108 }; 1146 };
1109 1147
@@ -1243,7 +1281,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1243 List<uint> objectIDs = lIDs; 1281 List<uint> objectIDs = lIDs;
1244 string xparm = parm.ToLower(); 1282 string xparm = parm.ToLower();
1245 float xval = val; 1283 float xval = val;
1246 TaintedObject(delegate() { 1284 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1247 foreach (uint lID in objectIDs) 1285 foreach (uint lID in objectIDs)
1248 { 1286 {
1249 BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval); 1287 BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval);
@@ -1263,7 +1301,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1263 uint xlocalID = localID; 1301 uint xlocalID = localID;
1264 string xparm = parm.ToLower(); 1302 string xparm = parm.ToLower();
1265 float xval = val; 1303 float xval = val;
1266 TaintedObject(delegate() { 1304 TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
1267 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); 1305 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval);
1268 }); 1306 });
1269 } 1307 }
@@ -1289,10 +1327,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1289 #endregion Runtime settable parameters 1327 #endregion Runtime settable parameters
1290 1328
1291 // Invoke the detailed logger and output something if it's enabled. 1329 // Invoke the detailed logger and output something if it's enabled.
1292 private void DetailLog(string msg, params Object[] args) 1330 public void DetailLog(string msg, params Object[] args)
1293 { 1331 {
1294 PhysicsLogging.Write(msg, args); 1332 PhysicsLogging.Write(msg, args);
1295 } 1333 }
1334 // used to fill in the LocalID when there isn't one
1335 public const string DetailLogZero = "0000000000";
1296 1336
1297} 1337}
1298} 1338}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 0ffbc94..504bd3c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -35,9 +35,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin {
35// Classes to allow some type checking for the API 35// Classes to allow some type checking for the API
36public struct BulletSim 36public struct BulletSim
37{ 37{
38 public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; } 38 public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; }
39 public IntPtr Ptr;
40 public uint ID; 39 public uint ID;
40 // The scene is only in here so very low level routines have a handle to print debug/error messages
41 public BSScene scene;
42 public IntPtr Ptr;
41} 43}
42 44
43public struct BulletBody 45public struct BulletBody
@@ -158,6 +160,7 @@ public struct ConfigurationParameters
158 public float avatarContactProcessingThreshold; 160 public float avatarContactProcessingThreshold;
159 161
160 public float maxPersistantManifoldPoolSize; 162 public float maxPersistantManifoldPoolSize;
163 public float maxCollisionAlgorithmPoolSize;
161 public float shouldDisableContactPoolDynamicAllocation; 164 public float shouldDisableContactPoolDynamicAllocation;
162 public float shouldForceUpdateAllAabbs; 165 public float shouldForceUpdateAllAabbs;
163 public float shouldRandomizeSolverOrder; 166 public float shouldRandomizeSolverOrder;
@@ -179,17 +182,18 @@ public struct ConfigurationParameters
179// Values used by Bullet and BulletSim to control collisions 182// Values used by Bullet and BulletSim to control collisions
180public enum CollisionFlags : uint 183public enum CollisionFlags : uint
181{ 184{
182 STATIC_OBJECT = 1 << 0, 185 CF_STATIC_OBJECT = 1 << 0,
183 KINEMATIC_OBJECT = 1 << 1, 186 CF_KINEMATIC_OBJECT = 1 << 1,
184 NO_CONTACT_RESPONSE = 1 << 2, 187 CF_NO_CONTACT_RESPONSE = 1 << 2,
185 CUSTOM_MATERIAL_CALLBACK = 1 << 3, 188 CF_CUSTOM_MATERIAL_CALLBACK = 1 << 3,
186 CHARACTER_OBJECT = 1 << 4, 189 CF_CHARACTER_OBJECT = 1 << 4,
187 DISABLE_VISUALIZE_OBJECT = 1 << 5, 190 CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
188 DISABLE_SPU_COLLISION_PROCESS = 1 << 6, 191 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
189 // Following used by BulletSim to control collisions 192 // Following used by BulletSim to control collisions
190 VOLUME_DETECT_OBJECT = 1 << 10, 193 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
191 PHANTOM_OBJECT = 1 << 11, 194 BS_VOLUME_DETECT_OBJECT = 1 << 11,
192 PHYSICAL_OBJECT = 1 << 12, 195 BS_PHANTOM_OBJECT = 1 << 12,
196 BS_PHYSICAL_OBJECT = 1 << 13,
193}; 197};
194 198
195// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 199// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
@@ -361,7 +365,7 @@ public static extern IntPtr GetSimHandle2(uint worldID);
361public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id); 365public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
362 366
363[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 367[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
364public static extern IntPtr GetBodyHandle2(IntPtr sim, uint id); 368public static extern IntPtr GetBodyHandle2(IntPtr world, uint id);
365 369
366// =============================================================================== 370// ===============================================================================
367[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 371[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -370,45 +374,69 @@ public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
370 int maxUpdates, IntPtr updateArray); 374 int maxUpdates, IntPtr updateArray);
371 375
372[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 376[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
373public static extern bool UpdateParameter2(IntPtr sim, uint localID, String parm, float value); 377public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
374 378
375[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 379[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
376public static extern void SetHeightmap2(IntPtr sim, float[] heightmap); 380public static extern void SetHeightmap2(IntPtr world, float[] heightmap);
377 381
378[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 382[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
379public static extern void Shutdown2(IntPtr sim); 383public static extern void Shutdown2(IntPtr sim);
380 384
381[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 385[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
382public static extern int PhysicsStep2(IntPtr sim, float timeStep, int maxSubSteps, float fixedTimeStep, 386public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep,
383 out int updatedEntityCount, 387 out int updatedEntityCount,
384 out IntPtr updatedEntitiesPtr, 388 out IntPtr updatedEntitiesPtr,
385 out int collidersCount, 389 out int collidersCount,
386 out IntPtr collidersPtr); 390 out IntPtr collidersPtr);
387 391
392[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
393public static extern bool PushUpdate2(IntPtr obj);
394
388/* 395/*
389[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 396[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
390public static extern IntPtr CreateMesh2(IntPtr sim, int indicesCount, int* indices, int verticesCount, float* vertices ); 397public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices );
391 398
392[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 399[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
393public static extern bool BuildHull2(IntPtr sim, IntPtr mesh); 400public static extern bool BuildHull2(IntPtr world, IntPtr mesh);
394 401
395[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 402[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
396public static extern bool ReleaseHull2(IntPtr sim, IntPtr mesh); 403public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh);
397 404
398[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 405[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
399public static extern bool DestroyMesh2(IntPtr sim, IntPtr mesh); 406public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh);
400 407
401[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 408[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
402public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData); 409public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData);
403*/ 410*/
404 411
405[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 412[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
406public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2, 413public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
407 Vector3 frame1loc, Quaternion frame1rot, 414 Vector3 frame1loc, Quaternion frame1rot,
408 Vector3 frame2loc, Quaternion frame2rot, 415 Vector3 frame2loc, Quaternion frame2rot,
409 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); 416 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
410 417
411[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 418[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
419public 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]
424public 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]
430public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse);
431
432[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
433public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations);
434
435[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
436public static extern bool SetFrames2(IntPtr constrain,
437 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
438
439[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
412public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); 440public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
413 441
414[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 442[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -421,13 +449,22 @@ public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
421public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce); 449public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
422 450
423[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 451[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
452public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold);
453
454[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
424public static extern bool CalculateTransforms2(IntPtr constrain); 455public static extern bool CalculateTransforms2(IntPtr constrain);
425 456
426[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 457[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
427public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis); 458public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
428 459
429[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 460[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
430public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); 461public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
462
463[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
464public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj);
465
466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
467public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
431 468
432[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
433public static extern Vector3 GetPosition2(IntPtr obj); 470public static extern Vector3 GetPosition2(IntPtr obj);
@@ -448,6 +485,9 @@ public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocit
448public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); 485public static extern bool SetObjectForce2(IntPtr obj, Vector3 force);
449 486
450[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
488public static extern bool AddObjectForce2(IntPtr obj, Vector3 force);
489
490[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
451public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); 491public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val);
452 492
453[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -478,13 +518,16 @@ public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val);
478public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); 518public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang);
479 519
480[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 520[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
481public static extern IntPtr SetCollisionFlags2(IntPtr obj, uint flags); 521public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
482 522
483[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 523[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
484public static extern IntPtr AddToCollisionFlags2(IntPtr obj, uint flags); 524public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
485 525
486[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 526[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
487public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, uint flags); 527public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
528
529[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
530public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
488 531
489[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 532[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
490public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); 533public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
@@ -499,16 +542,13 @@ public static extern bool SetGravity2(IntPtr obj, Vector3 val);
499public static extern IntPtr ClearForces2(IntPtr obj); 542public static extern IntPtr ClearForces2(IntPtr obj);
500 543
501[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 544[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
502public static extern bool SetMargin2(IntPtr obj, float val); 545public static extern IntPtr ClearAllForces2(IntPtr obj);
503
504[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
505public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
506 546
507[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 547[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
508public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj); 548public static extern bool SetMargin2(IntPtr obj, float val);
509 549
510[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 550[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
511public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj); 551public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
512 552
513[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 553[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
514public static extern bool DestroyObject2(IntPtr world, uint id); 554public static extern bool DestroyObject2(IntPtr world, uint id);