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.cs80
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs168
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs64
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs18
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs114
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs206
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs100
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs77
8 files changed, 501 insertions, 326 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
new file mode 100755
index 0000000..72df6b9
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
@@ -0,0 +1,80 @@
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 {
42 m_world = world;
43 m_body1 = obj1;
44 m_body2 = obj2;
45 m_constraint = new BulletConstraint(
46 BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
47 frame1, frame1rot,
48 frame2, frame2rot,
49 true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/));
50 m_enabled = true;
51 }
52
53 public bool SetCFMAndERP(float cfm, float erp)
54 {
55 bool ret = true;
56 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
57 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
58 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
59 return ret;
60 }
61
62 public bool UseFrameOffset(bool useOffset)
63 {
64 bool ret = false;
65 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
66 if (m_enabled)
67 ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
68 return ret;
69 }
70
71 public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
72 {
73 bool ret = false;
74 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
75 if (m_enabled)
76 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
77 return ret;
78 }
79}
80}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 09e1f0c..f164afe 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},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},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},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},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},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,17 @@ 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 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
492 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
493 entprop.Acceleration, entprop.RotationalVelocity);
435 } 494 }
436 495
437 // Called by the scene when a collision with this object is reported 496 // Called by the scene when a collision with this object is reported
@@ -480,5 +539,10 @@ public class BSCharacter : PhysicsActor
480 // End kludge 539 // End kludge
481 } 540 }
482 541
542 // Invoke the detailed logger and output something if it's enabled.
543 private void DetailLog(string msg, params Object[] args)
544 {
545 Scene.PhysicsLogging.Write(msg, args);
546 }
483} 547}
484} 548}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index ea3093a..da26b72 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,34 +75,7 @@ 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 {
107 bool ret = false;
108 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
109 if (m_enabled)
110 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
111 return ret;
112 }
113
114 public bool CalculateTransforms()
115 { 79 {
116 bool ret = false; 80 bool ret = false;
117 if (m_enabled) 81 if (m_enabled)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
index c88e645..3df2ddc 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
@@ -63,21 +63,13 @@ public class BSConstraintCollection : IDisposable
63 m_constraints.Clear(); 63 m_constraints.Clear();
64 } 64 }
65 65
66 public BSConstraint CreateConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
67 Vector3 frame1, Quaternion frame1rot,
68 Vector3 frame2, Quaternion frame2rot)
69 {
70 BSConstraint constrain = new BSConstraint(world, obj1, obj2, frame1, frame1rot, frame2, frame2rot);
71
72 this.AddConstraint(constrain);
73 return constrain;
74 }
75
76 public bool AddConstraint(BSConstraint cons) 66 public bool AddConstraint(BSConstraint cons)
77 { 67 {
78 // There is only one constraint between any bodies. Remove any old just to make sure. 68 // There is only one constraint between any bodies. Remove any old just to make sure.
79 RemoveAndDestroyConstraint(cons.Body1, cons.Body2); 69 RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
80 70
71 m_world.scene.DetailLog("{0},BSConstraintCollection.AddConstraint,call,body1={1},body2={2}", BSScene.DetailLogZero, cons.Body1.ID, cons.Body2.ID);
72
81 m_constraints.Add(cons); 73 m_constraints.Add(cons);
82 74
83 return true; 75 return true;
@@ -118,6 +110,7 @@ public class BSConstraintCollection : IDisposable
118 110
119 if (this.TryGetConstraint(body1, body2, out constrain)) 111 if (this.TryGetConstraint(body1, body2, out constrain))
120 { 112 {
113 m_world.scene.DetailLog("{0},BSConstraintCollection.RemoveAndDestroyConstraint,taint,body1={1},body2={2}", BSScene.DetailLogZero, body1.ID, body2.ID);
121 // remove the constraint from our collection 114 // remove the constraint from our collection
122 m_constraints.Remove(constrain); 115 m_constraints.Remove(constrain);
123 // tell the engine that all its structures need to be freed 116 // tell the engine that all its structures need to be freed
@@ -158,10 +151,11 @@ public class BSConstraintCollection : IDisposable
158 151
159 public bool RecalculateAllConstraints() 152 public bool RecalculateAllConstraints()
160 { 153 {
161 foreach (BSConstraint constrain in m_constraints) 154 ForEachConstraint(delegate(BSConstraint constrain)
162 { 155 {
163 constrain.CalculateTransforms(); 156 constrain.CalculateTransforms();
164 } 157 return false;
158 });
165 return true; 159 return true;
166 } 160 }
167 161
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 6f8430c..4a71612 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -40,6 +40,7 @@ public class BSLinkset
40 public BSPrim Root { get { return m_linksetRoot; } } 40 public BSPrim Root { get { return m_linksetRoot; } }
41 41
42 private BSScene m_scene; 42 private BSScene m_scene;
43 public BSScene Scene { get { return m_scene; } }
43 44
44 private List<BSPrim> m_children; 45 private List<BSPrim> m_children;
45 46
@@ -80,14 +81,14 @@ public class BSLinkset
80 81
81 // Link to a linkset where the child knows the parent. 82 // Link to a linkset where the child knows the parent.
82 // Parent changing should not happen so do some sanity checking. 83 // 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. 84 // We return the parent's linkset so the child can track its membership.
84 public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent) 85 public BSLinkset AddMeToLinkset(BSPrim child)
85 { 86 {
86 lock (m_linksetActivityLock) 87 lock (m_linksetActivityLock)
87 { 88 {
88 parent.Linkset.AddChildToLinkset(child); 89 AddChildToLinkset(child);
89 } 90 }
90 return parent.Linkset; 91 return this;
91 } 92 }
92 93
93 public BSLinkset RemoveMeFromLinkset(BSPrim child) 94 public BSLinkset RemoveMeFromLinkset(BSPrim child)
@@ -101,7 +102,7 @@ public class BSLinkset
101 { 102 {
102 // Note that we don't do a foreach because the remove routine 103 // Note that we don't do a foreach because the remove routine
103 // takes it out of the list. 104 // takes it out of the list.
104 RemoveChildFromLinkset(m_children[0]); 105 RemoveChildFromOtherLinkset(m_children[0]);
105 } 106 }
106 m_children.Clear(); // just to make sure 107 m_children.Clear(); // just to make sure
107 } 108 }
@@ -113,9 +114,10 @@ public class BSLinkset
113 } 114 }
114 115
115 // The child is down to a linkset of just itself 116 // The child is down to a linkset of just itself
116 return new BSLinkset(m_scene, child); 117 return new BSLinkset(Scene, child);
117 } 118 }
118 119
120 /* DEPRECATED: this is really bad in that it trys to unlink other prims.
119 // An existing linkset had one of its members rebuilt or something. 121 // 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. 122 // Go through the linkset and rebuild the pointers to the bodies of the linkset members.
121 public BSLinkset RefreshLinkset(BSPrim requestor) 123 public BSLinkset RefreshLinkset(BSPrim requestor)
@@ -124,6 +126,7 @@ public class BSLinkset
124 126
125 lock (m_linksetActivityLock) 127 lock (m_linksetActivityLock)
126 { 128 {
129 // The body pointer is refetched in case anything has moved.
127 System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID); 130 System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID);
128 if (aPtr == System.IntPtr.Zero) 131 if (aPtr == System.IntPtr.Zero)
129 { 132 {
@@ -155,13 +158,14 @@ public class BSLinkset
155 } 158 }
156 foreach (BSPrim bsp in toRemove) 159 foreach (BSPrim bsp in toRemove)
157 { 160 {
158 RemoveChildFromLinkset(bsp); 161 RemoveChildFromOtherLinkset(bsp);
159 } 162 }
160 } 163 }
161 } 164 }
162 165
163 return ret; 166 return ret;
164 } 167 }
168 */
165 169
166 170
167 // Return 'true' if the passed object is the root object of this linkset 171 // Return 'true' if the passed object is the root object of this linkset
@@ -170,6 +174,8 @@ public class BSLinkset
170 return (requestor.LocalID == m_linksetRoot.LocalID); 174 return (requestor.LocalID == m_linksetRoot.LocalID);
171 } 175 }
172 176
177 public int NumberOfChildren { get { return m_children.Count; } }
178
173 // Return 'true' if this linkset has any children (more than the root member) 179 // Return 'true' if this linkset has any children (more than the root member)
174 public bool HasAnyChildren { get { return (m_children.Count > 0); } } 180 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
175 181
@@ -208,7 +214,8 @@ public class BSLinkset
208 com += bp.Position * bp.MassRaw; 214 com += bp.Position * bp.MassRaw;
209 totalMass += bp.MassRaw; 215 totalMass += bp.MassRaw;
210 } 216 }
211 com /= totalMass; 217 if (totalMass != 0f)
218 com /= totalMass;
212 219
213 return com; 220 return com;
214 } 221 }
@@ -221,51 +228,54 @@ public class BSLinkset
221 { 228 {
222 com += bp.Position * bp.MassRaw; 229 com += bp.Position * bp.MassRaw;
223 } 230 }
224 com /= m_children.Count + 1; 231 com /= (m_children.Count + 1);
225 232
226 return com; 233 return com;
227 } 234 }
228 235
229 // I am the root of a linkset and a new child is being added 236 // I am the root of a linkset and a new child is being added
230 public void AddChildToLinkset(BSPrim pchild) 237 // Called while LinkActivity is locked.
238 public void AddChildToLinkset(BSPrim child)
231 { 239 {
232 BSPrim child = pchild;
233 if (!HasChild(child)) 240 if (!HasChild(child))
234 { 241 {
235 m_children.Add(child); 242 m_children.Add(child);
236 243
237 m_scene.TaintedObject(delegate() 244 BSPrim root = Root; // capture the root as of now
245 m_scene.TaintedObject("AddChildToLinkset", delegate()
238 { 246 {
239 DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); 247 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); 248 DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
241 PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child 249 PhysicallyLinkAChildToRoot(root, child); // build the physical binding between me and the child
242 }); 250 });
243 } 251 }
244 return; 252 return;
245 } 253 }
246 254
255 // Forcefully removing a child from a linkset.
256 // This is not being called by the child so we have to make sure the child doesn't think
257 // it's still connected to the linkset.
258 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
259 // has to be updated also (like pointer to prim's parent).
260 public void RemoveChildFromOtherLinkset(BSPrim pchild)
261 {
262 pchild.Linkset = new BSLinkset(m_scene, pchild);
263 RemoveChildFromLinkset(pchild);
264 }
265
247 // I am the root of a linkset and one of my children is being removed. 266 // 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. 267 // Safe to call even if the child is not really in my linkset.
249 public void RemoveChildFromLinkset(BSPrim pchild) 268 public void RemoveChildFromLinkset(BSPrim child)
250 { 269 {
251 BSPrim child = pchild;
252
253 if (m_children.Remove(child)) 270 if (m_children.Remove(child))
254 { 271 {
255 m_scene.TaintedObject(delegate() 272 BSPrim root = Root; // capture the root as of now
273 m_scene.TaintedObject("RemoveChildFromLinkset", delegate()
256 { 274 {
257 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); 275 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
258 DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); 276 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
259 277
260 if (m_children.Count == 0) 278 PhysicallyUnlinkAChildFromRoot(root, child);
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 }); 279 });
270 } 280 }
271 else 281 else
@@ -278,14 +288,14 @@ public class BSLinkset
278 288
279 // Create a constraint between me (root of linkset) and the passed prim (the child). 289 // Create a constraint between me (root of linkset) and the passed prim (the child).
280 // Called at taint time! 290 // Called at taint time!
281 private void PhysicallyLinkAChildToRoot(BSPrim childPrim) 291 private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim)
282 { 292 {
283 // Zero motion for children so they don't interpolate 293 // Zero motion for children so they don't interpolate
284 childPrim.ZeroMotion(); 294 childPrim.ZeroMotion();
285 295
286 // relative position normalized to the root prim 296 // relative position normalized to the root prim
287 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation); 297 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
288 OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation; 298 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
289 299
290 // relative rotation of the child to the parent 300 // relative rotation of the child to the parent
291 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; 301 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
@@ -293,16 +303,17 @@ public class BSLinkset
293 // create a constraint that allows no freedom of movement between the two objects 303 // create a constraint that allows no freedom of movement between the two objects
294 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 304 // 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); 305 // 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); 306 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
297 BSConstraint constrain = m_scene.Constraints.CreateConstraint( 307 BS6DofConstraint constrain = new BS6DofConstraint(
298 m_scene.World, m_linksetRoot.Body, childPrim.Body, 308 m_scene.World, rootPrim.Body, childPrim.Body,
299 // childRelativePosition, 309 childRelativePosition,
300 // childRelativeRotation, 310 childRelativeRotation,
301 OMV.Vector3.Zero,
302 OMV.Quaternion.Identity,
303 OMV.Vector3.Zero, 311 OMV.Vector3.Zero,
304 OMV.Quaternion.Identity 312 -childRelativeRotation
305 ); 313 );
314 m_scene.Constraints.AddConstraint(constrain);
315
316 // 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); 317 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
307 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 318 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
308 319
@@ -317,29 +328,32 @@ public class BSLinkset
317 328
318 // Remove linkage between myself and a particular child 329 // Remove linkage between myself and a particular child
319 // Called at taint time! 330 // Called at taint time!
320 private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim) 331 private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim)
321 { 332 {
322 DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", 333 // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
323 LogHeader, m_linksetRoot.LocalID, childPrim.LocalID); 334 // LogHeader, rootPrim.LocalID, childPrim.LocalID);
324 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); 335 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
325 // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID); 336
326 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body, childPrim.Body); 337 m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body);
338 // Make the child refresh its location
339 BulletSimAPI.PushUpdate2(childPrim.Body.Ptr);
327 } 340 }
328 341
329 // Remove linkage between myself and any possible children I might have 342 // Remove linkage between myself and any possible children I might have
330 // Called at taint time! 343 // Called at taint time!
331 private void PhysicallyUnlinkAllChildrenFromRoot() 344 private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim)
332 { 345 {
333 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); 346 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
334 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID); 347 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
335 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body); 348
336 // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); 349 m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body);
337 } 350 }
338 351
339 // Invoke the detailed logger and output something if it's enabled. 352 // Invoke the detailed logger and output something if it's enabled.
340 private void DebugLog(string msg, params Object[] args) 353 private void DebugLog(string msg, params Object[] args)
341 { 354 {
342 m_scene.Logger.DebugFormat(msg, args); 355 if (m_scene.ShouldDebugLog)
356 m_scene.Logger.DebugFormat(msg, args);
343 } 357 }
344 358
345 // Invoke the detailed logger and output something if it's enabled. 359 // Invoke the detailed logger and output something if it's enabled.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index ebfd85b..05cc822 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.Root;
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.Root.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.Root;
237 int childrenBefore = _linkset.NumberOfChildren;
238
239 _linkset = parent.Linkset.AddMeToLinkset(this);
229 240
230 _linkset = _linkset.AddMeToLinkset(this, parent); 241 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
242 LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren);
243 }
231 return; 244 return;
232 } 245 }
233 246
@@ -237,9 +250,14 @@ public sealed class BSPrim : PhysicsActor
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.Root._avName+"/"+_linkset.Root.LocalID.ToString());
240 DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString());
241 253
242 _linkset.RemoveMeFromLinkset(this); 254 BSPrim parentBefore = _linkset.Root;
255 int childrenBefore = _linkset.NumberOfChildren;
256
257 _linkset = _linkset.RemoveMeFromLinkset(this);
258
259 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
260 LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.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,13 @@ 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 CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr);
501 DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf);
497 } 502 }
498 503
499 // prims don't fly 504 // prims don't fly
@@ -548,9 +553,9 @@ public sealed class BSPrim : PhysicsActor
548 set { 553 set {
549 _rotationalVelocity = value; 554 _rotationalVelocity = value;
550 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 555 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
551 _scene.TaintedObject(delegate() 556 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
552 { 557 {
553 DetailLog("{0},SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 558 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
554 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 559 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
555 }); 560 });
556 } 561 }
@@ -565,9 +570,9 @@ public sealed class BSPrim : PhysicsActor
565 get { return _buoyancy; } 570 get { return _buoyancy; }
566 set { 571 set {
567 _buoyancy = value; 572 _buoyancy = value;
568 _scene.TaintedObject(delegate() 573 _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
569 { 574 {
570 DetailLog("{0},SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 575 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
571 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 576 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
572 }); 577 });
573 } 578 }
@@ -607,6 +612,7 @@ public sealed class BSPrim : PhysicsActor
607 612
608 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); 613 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
609 public override void AddForce(OMV.Vector3 force, bool pushforce) { 614 public override void AddForce(OMV.Vector3 force, bool pushforce) {
615 // for an object, doesn't matter if force is a pushforce or not
610 if (force.IsFinite()) 616 if (force.IsFinite())
611 { 617 {
612 // _force += force; 618 // _force += force;
@@ -618,40 +624,48 @@ public sealed class BSPrim : PhysicsActor
618 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 624 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
619 return; 625 return;
620 } 626 }
621 _scene.TaintedObject(delegate() 627 _scene.TaintedObject("BSPrim.AddForce", delegate()
622 { 628 {
629 OMV.Vector3 fSum = OMV.Vector3.Zero;
623 lock (m_accumulatedForces) 630 lock (m_accumulatedForces)
624 { 631 {
625 if (m_accumulatedForces.Count > 0) 632 foreach (OMV.Vector3 v in m_accumulatedForces)
626 { 633 {
627 OMV.Vector3 fSum = OMV.Vector3.Zero; 634 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 } 635 }
636 m_accumulatedForces.Clear();
637 } 637 }
638 DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force);
639 BulletSimAPI.AddObjectForce2(Body.Ptr, fSum);
638 }); 640 });
639 } 641 }
640 642
641 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 643 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
642 DetailLog("{0},AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); 644 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); 645 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
644 } 646 }
645 public override void SetMomentum(OMV.Vector3 momentum) { 647 public override void SetMomentum(OMV.Vector3 momentum) {
646 DetailLog("{0},SetMomentum,call,mom={1}", LocalID, momentum); 648 DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
647 } 649 }
648 public override void SubscribeEvents(int ms) { 650 public override void SubscribeEvents(int ms) {
649 _subscribedEventsMs = ms; 651 _subscribedEventsMs = ms;
650 // make sure first collision happens 652 if (ms > 0)
651 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; 653 {
654 // make sure first collision happens
655 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
656
657 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
658 {
659 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
660 });
661 }
652 } 662 }
653 public override void UnSubscribeEvents() { 663 public override void UnSubscribeEvents() {
654 _subscribedEventsMs = 0; 664 _subscribedEventsMs = 0;
665 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
666 {
667 BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
668 });
655 } 669 }
656 public override bool SubscribedEvents() { 670 public override bool SubscribedEvents() {
657 return (_subscribedEventsMs > 0); 671 return (_subscribedEventsMs > 0);
@@ -970,26 +984,26 @@ public sealed class BSPrim : PhysicsActor
970 { 984 {
971 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 985 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
972 { 986 {
973 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 987 // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
974 { 988 // {
975 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 989 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
976 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) 990 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
977 { 991 {
978 DetailLog("{0},CreateGeom,sphere", LocalID); 992 DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
979 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 993 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
980 // Bullet native objects are scaled by the Bullet engine so pass the size in 994 // Bullet native objects are scaled by the Bullet engine so pass the size in
981 _scale = _size; 995 _scale = _size;
982 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 996 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
983 ret = true; 997 ret = true;
984 } 998 }
985 } 999 // }
986 } 1000 }
987 else 1001 else
988 { 1002 {
989 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); 1003 // 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)) 1004 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
991 { 1005 {
992 DetailLog("{0},CreateGeom,box", LocalID); 1006 DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
993 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 1007 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
994 _scale = _size; 1008 _scale = _size;
995 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1009 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
@@ -1032,12 +1046,12 @@ public sealed class BSPrim : PhysicsActor
1032 // if this new shape is the same as last time, don't recreate the mesh 1046 // if this new shape is the same as last time, don't recreate the mesh
1033 if (_meshKey == newMeshKey) return; 1047 if (_meshKey == newMeshKey) return;
1034 1048
1035 DetailLog("{0},CreateGeomMesh,create,key={1}", LocalID, _meshKey); 1049 DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1036 // Since we're recreating new, get rid of any previously generated shape 1050 // Since we're recreating new, get rid of any previously generated shape
1037 if (_meshKey != 0) 1051 if (_meshKey != 0)
1038 { 1052 {
1039 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); 1053 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1040 DetailLog("{0},CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); 1054 DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
1041 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1055 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1042 _mesh = null; 1056 _mesh = null;
1043 _meshKey = 0; 1057 _meshKey = 0;
@@ -1067,7 +1081,7 @@ public sealed class BSPrim : PhysicsActor
1067 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1081 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1068 // meshes are already scaled by the meshmerizer 1082 // meshes are already scaled by the meshmerizer
1069 _scale = new OMV.Vector3(1f, 1f, 1f); 1083 _scale = new OMV.Vector3(1f, 1f, 1f);
1070 DetailLog("{0},CreateGeomMesh,done", LocalID); 1084 DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID);
1071 return; 1085 return;
1072 } 1086 }
1073 1087
@@ -1081,17 +1095,17 @@ public sealed class BSPrim : PhysicsActor
1081 // if the hull hasn't changed, don't rebuild it 1095 // if the hull hasn't changed, don't rebuild it
1082 if (newHullKey == _hullKey) return; 1096 if (newHullKey == _hullKey) return;
1083 1097
1084 DetailLog("{0},CreateGeomHull,create,key={1}", LocalID, _meshKey); 1098 DetailLog("{0},BSPrim.CreateGeomHull,create,key={1}", LocalID, _meshKey);
1085 1099
1086 // Since we're recreating new, get rid of any previously generated shape 1100 // Since we're recreating new, get rid of any previously generated shape
1087 if (_hullKey != 0) 1101 if (_hullKey != 0)
1088 { 1102 {
1089 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); 1103 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1090 DetailLog("{0},CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey); 1104 DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey);
1091 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1105 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1092 _hullKey = 0; 1106 _hullKey = 0;
1093 _hulls.Clear(); 1107 _hulls.Clear();
1094 DetailLog("{0},CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey); 1108 DetailLog("{0},BSPrim.CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey);
1095 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1109 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1096 _mesh = null; // the mesh cannot match either 1110 _mesh = null; // the mesh cannot match either
1097 _meshKey = 0; 1111 _meshKey = 0;
@@ -1188,7 +1202,7 @@ public sealed class BSPrim : PhysicsActor
1188 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1202 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1189 // meshes are already scaled by the meshmerizer 1203 // meshes are already scaled by the meshmerizer
1190 _scale = new OMV.Vector3(1f, 1f, 1f); 1204 _scale = new OMV.Vector3(1f, 1f, 1f);
1191 DetailLog("{0},CreateGeomHull,done", LocalID); 1205 DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1192 return; 1206 return;
1193 } 1207 }
1194 1208
@@ -1214,7 +1228,7 @@ public sealed class BSPrim : PhysicsActor
1214 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); 1228 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1215 1229
1216 // the CreateObject() may have recreated the rigid body. Make sure we have the latest. 1230 // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
1217 m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID); 1231 Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
1218 1232
1219 return ret; 1233 return ret;
1220 } 1234 }
@@ -1326,20 +1340,18 @@ public sealed class BSPrim : PhysicsActor
1326 1340
1327 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", 1341 // 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); 1342 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1329 DetailLog("{0},UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1343 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1330 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1344 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1331 1345
1332 base.RequestPhysicsterseUpdate(); 1346 base.RequestPhysicsterseUpdate();
1333 } 1347 }
1334 /*
1335 else 1348 else
1336 { 1349 {
1337 // For debugging, we also report the movement of children 1350 // For debugging, we also report the movement of children
1338 DetailLog("{0},UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1351 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1339 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1352 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1340 entprop.Acceleration, entprop.RotationalVelocity); 1353 entprop.Acceleration, entprop.RotationalVelocity);
1341 } 1354 }
1342 */
1343 } 1355 }
1344 1356
1345 // I've collided with something 1357 // I've collided with something
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 011033c..beaea1f 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;
@@ -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 }
@@ -535,7 +548,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
535 548
536 public override void SetTerrain(float[] heightMap) { 549 public override void SetTerrain(float[] heightMap) {
537 m_heightMap = heightMap; 550 m_heightMap = heightMap;
538 this.TaintedObject(delegate() 551 this.TaintedObject("BSScene.SetTerrain", delegate()
539 { 552 {
540 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap); 553 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
541 }); 554 });
@@ -727,12 +740,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
727 // Calls to the PhysicsActors can't directly call into the physics engine 740 // 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. 741 // 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. 742 // We rely on C#'s closure to save and restore the context for the delegate.
730 public void TaintedObject(TaintCallback callback) 743 public void TaintedObject(String ident, TaintCallback callback)
731 { 744 {
732 if (!m_initialized) return; 745 if (!m_initialized) return;
733 746
734 lock (_taintLock) 747 lock (_taintLock)
735 _taintedObjects.Add(callback); 748 _taintedObjects.Add(new TaintCallbackEntry(ident, callback));
736 return; 749 return;
737 } 750 }
738 751
@@ -744,22 +757,22 @@ public class BSScene : PhysicsScene, IPhysicsParameters
744 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process 757 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process
745 { 758 {
746 // swizzle a new list into the list location so we can process what's there 759 // swizzle a new list into the list location so we can process what's there
747 List<TaintCallback> oldList; 760 List<TaintCallbackEntry> oldList;
748 lock (_taintLock) 761 lock (_taintLock)
749 { 762 {
750 oldList = _taintedObjects; 763 oldList = _taintedObjects;
751 _taintedObjects = new List<TaintCallback>(); 764 _taintedObjects = new List<TaintCallbackEntry>();
752 } 765 }
753 766
754 foreach (TaintCallback callback in oldList) 767 foreach (TaintCallbackEntry tcbe in oldList)
755 { 768 {
756 try 769 try
757 { 770 {
758 callback(); 771 tcbe.callback();
759 } 772 }
760 catch (Exception e) 773 catch (Exception e)
761 { 774 {
762 m_log.ErrorFormat("{0}: ProcessTaints: Exception: {1}", LogHeader, e); 775 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
763 } 776 }
764 } 777 }
765 oldList.Clear(); 778 oldList.Clear();
@@ -767,6 +780,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters
767 } 780 }
768 781
769 #region Vehicles 782 #region Vehicles
783
784 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
785 {
786 if (newType == Vehicle.TYPE_NONE)
787 {
788 RemoveVehiclePrim(vehic);
789 }
790 else
791 {
792 // make it so the scene will call us each tick to do vehicle things
793 AddVehiclePrim(vehic);
794 }
795 }
796
770 // Make so the scene will call this prim for vehicle actions each tick. 797 // 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. 798 // Safe to call if prim is already in the vehicle list.
772 public void AddVehiclePrim(BSPrim vehicle) 799 public void AddVehiclePrim(BSPrim vehicle)
@@ -812,12 +839,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
812 839
813 private struct ParameterDefn 840 private struct ParameterDefn
814 { 841 {
815 public string name; 842 public string name; // string name of the parameter
816 public string desc; 843 public string desc; // a short description of what the parameter means
817 public float defaultValue; 844 public float defaultValue; // default value if not specified anywhere else
818 public ParamUser userParam; 845 public ParamUser userParam; // get the value from the configuration file
819 public ParamGet getter; 846 public ParamGet getter; // return the current value stored for this parameter
820 public ParamSet setter; 847 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) 848 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
822 { 849 {
823 name = n; 850 name = n;
@@ -834,7 +861,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
834 // To add a new externally referencable/settable parameter, add the paramter storage 861 // 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 862 // location somewhere in the program and make an entry in this table with the
836 // getters and setters. 863 // getters and setters.
837 // To add a new variable, it is easiest to find an existing definition and copy it. 864 // It is easiest to find an existing definition and copy it.
838 // Parameter values are floats. Booleans are converted to a floating value. 865 // Parameter values are floats. Booleans are converted to a floating value.
839 // 866 //
840 // A ParameterDefn() takes the following parameters: 867 // A ParameterDefn() takes the following parameters:
@@ -870,7 +897,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
870 (s) => { return (float)s.m_meshLOD; }, 897 (s) => { return (float)s.m_meshLOD; },
871 (s,p,l,v) => { s.m_meshLOD = (int)v; } ), 898 (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)", 899 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
873 32, 900 32f,
874 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, 901 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); },
875 (s) => { return (float)s.m_sculptLOD; }, 902 (s) => { return (float)s.m_sculptLOD; },
876 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), 903 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ),
@@ -1027,14 +1054,19 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1027 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), 1054 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1028 1055
1029 1056
1030 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)", 1057 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
1031 0f, // zero to disable 1058 0f, // zero to disable
1032 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, 1059 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
1033 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, 1060 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
1034 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), 1061 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1062 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
1063 0f, // zero to disable
1064 (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
1065 (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
1066 (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
1035 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", 1067 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
1036 ConfigurationParameters.numericTrue, 1068 ConfigurationParameters.numericFalse,
1037 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1069 (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; }, 1070 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; },
1039 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ), 1071 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
1040 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", 1072 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
@@ -1101,9 +1133,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1101 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), 1133 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
1102 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements", 1134 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
1103 ConfigurationParameters.numericFalse, 1135 ConfigurationParameters.numericFalse,
1104 (s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); }, 1136 (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
1105 (s) => { return s.NumericBool(s.shouldDebugLog); }, 1137 (s) => { return s.NumericBool(s.ShouldDebugLog); },
1106 (s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(v); } ), 1138 (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ),
1107 1139
1108 }; 1140 };
1109 1141
@@ -1243,7 +1275,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1243 List<uint> objectIDs = lIDs; 1275 List<uint> objectIDs = lIDs;
1244 string xparm = parm.ToLower(); 1276 string xparm = parm.ToLower();
1245 float xval = val; 1277 float xval = val;
1246 TaintedObject(delegate() { 1278 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1247 foreach (uint lID in objectIDs) 1279 foreach (uint lID in objectIDs)
1248 { 1280 {
1249 BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval); 1281 BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval);
@@ -1263,7 +1295,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1263 uint xlocalID = localID; 1295 uint xlocalID = localID;
1264 string xparm = parm.ToLower(); 1296 string xparm = parm.ToLower();
1265 float xval = val; 1297 float xval = val;
1266 TaintedObject(delegate() { 1298 TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
1267 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); 1299 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval);
1268 }); 1300 });
1269 } 1301 }
@@ -1289,10 +1321,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1289 #endregion Runtime settable parameters 1321 #endregion Runtime settable parameters
1290 1322
1291 // Invoke the detailed logger and output something if it's enabled. 1323 // Invoke the detailed logger and output something if it's enabled.
1292 private void DetailLog(string msg, params Object[] args) 1324 public void DetailLog(string msg, params Object[] args)
1293 { 1325 {
1294 PhysicsLogging.Write(msg, args); 1326 PhysicsLogging.Write(msg, args);
1295 } 1327 }
1328 // used to fill in the LocalID when there isn't one
1329 public const string DetailLogZero = "0000000000";
1296 1330
1297} 1331}
1298} 1332}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 0ffbc94..6800b96 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,40 +374,43 @@ 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);
@@ -427,7 +434,13 @@ public static extern bool CalculateTransforms2(IntPtr constrain);
427public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis); 434public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
428 435
429[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 436[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
430public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); 437public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
438
439[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
440public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj);
441
442[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
443public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
431 444
432[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 445[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
433public static extern Vector3 GetPosition2(IntPtr obj); 446public static extern Vector3 GetPosition2(IntPtr obj);
@@ -448,6 +461,9 @@ public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocit
448public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); 461public static extern bool SetObjectForce2(IntPtr obj, Vector3 force);
449 462
450[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 463[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
464public static extern bool AddObjectForce2(IntPtr obj, Vector3 force);
465
466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
451public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); 467public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val);
452 468
453[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -478,13 +494,16 @@ public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val);
478public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); 494public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang);
479 495
480[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
481public static extern IntPtr SetCollisionFlags2(IntPtr obj, uint flags); 497public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
498
499[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
500public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
482 501
483[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 502[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
484public static extern IntPtr AddToCollisionFlags2(IntPtr obj, uint flags); 503public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
485 504
486[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
487public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, uint flags); 506public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
488 507
489[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 508[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
490public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); 509public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
@@ -505,12 +524,6 @@ public static extern bool SetMargin2(IntPtr obj, float val);
505public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); 524public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
506 525
507[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 526[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
508public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
509
510[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
511public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
512
513[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
514public static extern bool DestroyObject2(IntPtr world, uint id); 527public static extern bool DestroyObject2(IntPtr world, uint id);
515 528
516[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 529[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]