aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs238
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs10
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs42
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs138
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs232
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs60
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs57
7 files changed, 361 insertions, 416 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 526dbad..57d5726 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -28,7 +28,7 @@ using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using log4net; 30using log4net;
31using OpenMetaverse; 31using OMV = OpenMetaverse;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager; 33using OpenSim.Region.Physics.Manager;
34 34
@@ -39,25 +39,24 @@ public class BSCharacter : BSPhysObject
39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 private static readonly string LogHeader = "[BULLETS CHAR]"; 40 private static readonly string LogHeader = "[BULLETS CHAR]";
41 41
42 public BSScene Scene { get; private set; }
43 private String _avName; 42 private String _avName;
44 // private bool _stopped; 43 // private bool _stopped;
45 private Vector3 _size; 44 private OMV.Vector3 _size;
46 private Vector3 _scale; 45 private OMV.Vector3 _scale;
47 private PrimitiveBaseShape _pbs; 46 private PrimitiveBaseShape _pbs;
48 private uint _localID = 0; 47 private uint _localID = 0;
49 private bool _grabbed; 48 private bool _grabbed;
50 private bool _selected; 49 private bool _selected;
51 private Vector3 _position; 50 private OMV.Vector3 _position;
52 private float _mass; 51 private float _mass;
53 public float _density; 52 public float _density;
54 public float _avatarVolume; 53 public float _avatarVolume;
55 private Vector3 _force; 54 private OMV.Vector3 _force;
56 private Vector3 _velocity; 55 private OMV.Vector3 _velocity;
57 private Vector3 _torque; 56 private OMV.Vector3 _torque;
58 private float _collisionScore; 57 private float _collisionScore;
59 private Vector3 _acceleration; 58 private OMV.Vector3 _acceleration;
60 private Quaternion _orientation; 59 private OMV.Quaternion _orientation;
61 private int _physicsActorType; 60 private int _physicsActorType;
62 private bool _isPhysical; 61 private bool _isPhysical;
63 private bool _flying; 62 private bool _flying;
@@ -69,18 +68,14 @@ public class BSCharacter : BSPhysObject
69 private long _collidingGroundStep; 68 private long _collidingGroundStep;
70 private bool _collidingObj; 69 private bool _collidingObj;
71 private bool _floatOnWater; 70 private bool _floatOnWater;
72 private Vector3 _rotationalVelocity; 71 private OMV.Vector3 _rotationalVelocity;
73 private bool _kinematic; 72 private bool _kinematic;
74 private float _buoyancy; 73 private float _buoyancy;
75 74
76 public override BulletBody BSBody { get; set; }
77 public override BulletShape BSShape { get; set; }
78 public override BSLinkset Linkset { get; set; }
79
80 private int _subscribedEventsMs = 0; 75 private int _subscribedEventsMs = 0;
81 private int _nextCollisionOkTime = 0; 76 private int _nextCollisionOkTime = 0;
82 77
83 private Vector3 _PIDTarget; 78 private OMV.Vector3 _PIDTarget;
84 private bool _usePID; 79 private bool _usePID;
85 private float _PIDTau; 80 private float _PIDTau;
86 private bool _useHoverPID; 81 private bool _useHoverPID;
@@ -88,26 +83,24 @@ public class BSCharacter : BSPhysObject
88 private PIDHoverType _PIDHoverType; 83 private PIDHoverType _PIDHoverType;
89 private float _PIDHoverTao; 84 private float _PIDHoverTao;
90 85
91 public BSCharacter(uint localID, String avName, BSScene parent_scene, Vector3 pos, Vector3 size, bool isFlying) 86 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
92 { 87 {
88 base.BaseInitialize(parent_scene);
93 _localID = localID; 89 _localID = localID;
94 _avName = avName; 90 _avName = avName;
95 Scene = parent_scene;
96 _physicsActorType = (int)ActorTypes.Agent; 91 _physicsActorType = (int)ActorTypes.Agent;
97 _position = pos; 92 _position = pos;
98 _size = size; 93 _size = size;
99 _flying = isFlying; 94 _flying = isFlying;
100 _orientation = Quaternion.Identity; 95 _orientation = OMV.Quaternion.Identity;
101 _velocity = Vector3.Zero; 96 _velocity = OMV.Vector3.Zero;
102 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 97 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
103 // The dimensions of the avatar capsule are kept in the scale. 98 // The dimensions of the avatar capsule are kept in the scale.
104 // Physics creates a unit capsule which is scaled by the physics engine. 99 // Physics creates a unit capsule which is scaled by the physics engine.
105 _scale = new Vector3(Scene.Params.avatarCapsuleRadius, Scene.Params.avatarCapsuleRadius, size.Z); 100 _scale = new OMV.Vector3(PhysicsScene.Params.avatarCapsuleRadius, PhysicsScene.Params.avatarCapsuleRadius, size.Z);
106 _density = Scene.Params.avatarDensity; 101 _density = PhysicsScene.Params.avatarDensity;
107 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale 102 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
108 103
109 Linkset = new BSLinkset(Scene, this);
110
111 ShapeData shapeData = new ShapeData(); 104 ShapeData shapeData = new ShapeData();
112 shapeData.ID = _localID; 105 shapeData.ID = _localID;
113 shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; 106 shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
@@ -118,19 +111,19 @@ public class BSCharacter : BSPhysObject
118 shapeData.Mass = _mass; 111 shapeData.Mass = _mass;
119 shapeData.Buoyancy = _buoyancy; 112 shapeData.Buoyancy = _buoyancy;
120 shapeData.Static = ShapeData.numericFalse; 113 shapeData.Static = ShapeData.numericFalse;
121 shapeData.Friction = Scene.Params.avatarFriction; 114 shapeData.Friction = PhysicsScene.Params.avatarFriction;
122 shapeData.Restitution = Scene.Params.avatarRestitution; 115 shapeData.Restitution = PhysicsScene.Params.avatarRestitution;
123 116
124 // do actual create at taint time 117 // do actual create at taint time
125 Scene.TaintedObject("BSCharacter.create", delegate() 118 PhysicsScene.TaintedObject("BSCharacter.create", delegate()
126 { 119 {
127 DetailLog("{0},BSCharacter.create", _localID); 120 DetailLog("{0},BSCharacter.create", _localID);
128 BulletSimAPI.CreateObject(Scene.WorldID, shapeData); 121 BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData);
129 122
130 // Set the buoyancy for flying. This will be refactored when all the settings happen in C# 123 // Set the buoyancy for flying. This will be refactored when all the settings happen in C#
131 BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); 124 BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy);
132 125
133 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID)); 126 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID));
134 }); 127 });
135 128
136 return; 129 return;
@@ -140,9 +133,9 @@ public class BSCharacter : BSPhysObject
140 public override void Destroy() 133 public override void Destroy()
141 { 134 {
142 DetailLog("{0},BSCharacter.Destroy", LocalID); 135 DetailLog("{0},BSCharacter.Destroy", LocalID);
143 Scene.TaintedObject("BSCharacter.destroy", delegate() 136 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
144 { 137 {
145 BulletSimAPI.DestroyObject(Scene.WorldID, _localID); 138 BulletSimAPI.DestroyObject(PhysicsScene.WorldID, _localID);
146 }); 139 });
147 } 140 }
148 141
@@ -154,11 +147,11 @@ public class BSCharacter : BSPhysObject
154 public override bool Stopped { 147 public override bool Stopped {
155 get { return false; } 148 get { return false; }
156 } 149 }
157 public override Vector3 Size { 150 public override OMV.Vector3 Size {
158 get 151 get
159 { 152 {
160 // Avatar capsule size is kept in the scale parameter. 153 // Avatar capsule size is kept in the scale parameter.
161 return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); 154 return new OMV.Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z);
162 } 155 }
163 156
164 set { 157 set {
@@ -171,9 +164,9 @@ public class BSCharacter : BSPhysObject
171 164
172 ComputeAvatarVolumeAndMass(); 165 ComputeAvatarVolumeAndMass();
173 166
174 Scene.TaintedObject("BSCharacter.setSize", delegate() 167 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
175 { 168 {
176 BulletSimAPI.SetObjectScaleMass(Scene.WorldID, LocalID, _scale, _mass, true); 169 BulletSimAPI.SetObjectScaleMass(PhysicsScene.WorldID, LocalID, _scale, _mass, true);
177 }); 170 });
178 171
179 } 172 }
@@ -198,9 +191,27 @@ public class BSCharacter : BSPhysObject
198 public override void CrossingFailure() { return; } 191 public override void CrossingFailure() { return; }
199 public override void link(PhysicsActor obj) { return; } 192 public override void link(PhysicsActor obj) { return; }
200 public override void delink() { return; } 193 public override void delink() { return; }
201 public override void LockAngularMotion(Vector3 axis) { return; }
202 194
203 public override Vector3 Position { 195 // Set motion values to zero.
196 // Do it to the properties so the values get set in the physics engine.
197 // Push the setting of the values to the viewer.
198 // Called at taint time!
199 public override void ZeroMotion()
200 {
201 _velocity = OMV.Vector3.Zero;
202 _acceleration = OMV.Vector3.Zero;
203 _rotationalVelocity = OMV.Vector3.Zero;
204
205 // Zero some other properties directly into the physics engine
206 BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
207 BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
208 BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
209 BulletSimAPI.ClearForces2(BSBody.Ptr);
210 }
211
212 public override void LockAngularMotion(OMV.Vector3 axis) { return; }
213
214 public override OMV.Vector3 Position {
204 get { 215 get {
205 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); 216 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
206 return _position; 217 return _position;
@@ -209,10 +220,10 @@ public class BSCharacter : BSPhysObject
209 _position = value; 220 _position = value;
210 PositionSanityCheck(); 221 PositionSanityCheck();
211 222
212 Scene.TaintedObject("BSCharacter.setPosition", delegate() 223 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
213 { 224 {
214 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 225 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
215 BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation); 226 BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, _localID, _position, _orientation);
216 }); 227 });
217 } 228 }
218 } 229 }
@@ -225,7 +236,7 @@ public class BSCharacter : BSPhysObject
225 bool ret = false; 236 bool ret = false;
226 237
227 // If below the ground, move the avatar up 238 // If below the ground, move the avatar up
228 float terrainHeight = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); 239 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
229 if (Position.Z < terrainHeight) 240 if (Position.Z < terrainHeight)
230 { 241 {
231 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); 242 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
@@ -247,10 +258,10 @@ public class BSCharacter : BSPhysObject
247 { 258 {
248 // The new position value must be pushed into the physics engine but we can't 259 // The new position value must be pushed into the physics engine but we can't
249 // just assign to "Position" because of potential call loops. 260 // just assign to "Position" because of potential call loops.
250 Scene.TaintedObject("BSCharacter.PositionSanityCheck", delegate() 261 PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", delegate()
251 { 262 {
252 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 263 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
253 BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation); 264 BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, _localID, _position, _orientation);
254 }); 265 });
255 ret = true; 266 ret = true;
256 } 267 }
@@ -266,15 +277,15 @@ public class BSCharacter : BSPhysObject
266 // used when we only want this prim's mass and not the linkset thing 277 // used when we only want this prim's mass and not the linkset thing
267 public override float MassRaw { get {return _mass; } } 278 public override float MassRaw { get {return _mass; } }
268 279
269 public override Vector3 Force { 280 public override OMV.Vector3 Force {
270 get { return _force; } 281 get { return _force; }
271 set { 282 set {
272 _force = value; 283 _force = value;
273 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 284 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
274 Scene.TaintedObject("BSCharacter.SetForce", delegate() 285 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
275 { 286 {
276 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); 287 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
277 BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force); 288 BulletSimAPI.SetObjectForce(PhysicsScene.WorldID, LocalID, _force);
278 }); 289 });
279 } 290 }
280 } 291 }
@@ -284,28 +295,28 @@ public class BSCharacter : BSPhysObject
284 set { return; } 295 set { return; }
285 } 296 }
286 public override void VehicleFloatParam(int param, float value) { } 297 public override void VehicleFloatParam(int param, float value) { }
287 public override void VehicleVectorParam(int param, Vector3 value) {} 298 public override void VehicleVectorParam(int param, OMV.Vector3 value) {}
288 public override void VehicleRotationParam(int param, Quaternion rotation) { } 299 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { }
289 public override void VehicleFlags(int param, bool remove) { } 300 public override void VehicleFlags(int param, bool remove) { }
290 301
291 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 302 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
292 public override void SetVolumeDetect(int param) { return; } 303 public override void SetVolumeDetect(int param) { return; }
293 304
294 public override Vector3 GeometricCenter { get { return Vector3.Zero; } } 305 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
295 public override Vector3 CenterOfMass { get { return Vector3.Zero; } } 306 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
296 public override Vector3 Velocity { 307 public override OMV.Vector3 Velocity {
297 get { return _velocity; } 308 get { return _velocity; }
298 set { 309 set {
299 _velocity = value; 310 _velocity = value;
300 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 311 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
301 Scene.TaintedObject("BSCharacter.setVelocity", delegate() 312 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
302 { 313 {
303 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); 314 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
304 BulletSimAPI.SetObjectVelocity(Scene.WorldID, _localID, _velocity); 315 BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, _localID, _velocity);
305 }); 316 });
306 } 317 }
307 } 318 }
308 public override Vector3 Torque { 319 public override OMV.Vector3 Torque {
309 get { return _torque; } 320 get { return _torque; }
310 set { _torque = value; 321 set { _torque = value;
311 } 322 }
@@ -315,19 +326,19 @@ public class BSCharacter : BSPhysObject
315 set { _collisionScore = value; 326 set { _collisionScore = value;
316 } 327 }
317 } 328 }
318 public override Vector3 Acceleration { 329 public override OMV.Vector3 Acceleration {
319 get { return _acceleration; } 330 get { return _acceleration; }
320 set { _acceleration = value; } 331 set { _acceleration = value; }
321 } 332 }
322 public override Quaternion Orientation { 333 public override OMV.Quaternion Orientation {
323 get { return _orientation; } 334 get { return _orientation; }
324 set { 335 set {
325 _orientation = value; 336 _orientation = value;
326 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); 337 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
327 Scene.TaintedObject("BSCharacter.setOrientation", delegate() 338 PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate()
328 { 339 {
329 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); 340 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
330 BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation); 341 BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, _localID, _position, _orientation);
331 }); 342 });
332 } 343 }
333 } 344 }
@@ -364,11 +375,11 @@ public class BSCharacter : BSPhysObject
364 set { _throttleUpdates = value; } 375 set { _throttleUpdates = value; }
365 } 376 }
366 public override bool IsColliding { 377 public override bool IsColliding {
367 get { return (_collidingStep == Scene.SimulationStep); } 378 get { return (_collidingStep == PhysicsScene.SimulationStep); }
368 set { _isColliding = value; } 379 set { _isColliding = value; }
369 } 380 }
370 public override bool CollidingGround { 381 public override bool CollidingGround {
371 get { return (_collidingGroundStep == Scene.SimulationStep); } 382 get { return (_collidingGroundStep == PhysicsScene.SimulationStep); }
372 set { _collidingGround = value; } 383 set { _collidingGround = value; }
373 } 384 }
374 public override bool CollidingObj { 385 public override bool CollidingObj {
@@ -378,7 +389,7 @@ public class BSCharacter : BSPhysObject
378 public override bool FloatOnWater { 389 public override bool FloatOnWater {
379 set { _floatOnWater = value; } 390 set { _floatOnWater = value; }
380 } 391 }
381 public override Vector3 RotationalVelocity { 392 public override OMV.Vector3 RotationalVelocity {
382 get { return _rotationalVelocity; } 393 get { return _rotationalVelocity; }
383 set { _rotationalVelocity = value; } 394 set { _rotationalVelocity = value; }
384 } 395 }
@@ -390,16 +401,16 @@ public class BSCharacter : BSPhysObject
390 public override float Buoyancy { 401 public override float Buoyancy {
391 get { return _buoyancy; } 402 get { return _buoyancy; }
392 set { _buoyancy = value; 403 set { _buoyancy = value;
393 Scene.TaintedObject("BSCharacter.setBuoyancy", delegate() 404 PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate()
394 { 405 {
395 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 406 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
396 BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); 407 BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy);
397 }); 408 });
398 } 409 }
399 } 410 }
400 411
401 // Used for MoveTo 412 // Used for MoveTo
402 public override Vector3 PIDTarget { 413 public override OMV.Vector3 PIDTarget {
403 set { _PIDTarget = value; } 414 set { _PIDTarget = value; }
404 } 415 }
405 public override bool PIDActive { 416 public override bool PIDActive {
@@ -425,19 +436,19 @@ public class BSCharacter : BSPhysObject
425 } 436 }
426 437
427 // For RotLookAt 438 // For RotLookAt
428 public override Quaternion APIDTarget { set { return; } } 439 public override OMV.Quaternion APIDTarget { set { return; } }
429 public override bool APIDActive { set { return; } } 440 public override bool APIDActive { set { return; } }
430 public override float APIDStrength { set { return; } } 441 public override float APIDStrength { set { return; } }
431 public override float APIDDamping { set { return; } } 442 public override float APIDDamping { set { return; } }
432 443
433 public override void AddForce(Vector3 force, bool pushforce) { 444 public override void AddForce(OMV.Vector3 force, bool pushforce) {
434 if (force.IsFinite()) 445 if (force.IsFinite())
435 { 446 {
436 _force.X += force.X; 447 _force.X += force.X;
437 _force.Y += force.Y; 448 _force.Y += force.Y;
438 _force.Z += force.Z; 449 _force.Z += force.Z;
439 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); 450 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
440 Scene.TaintedObject("BSCharacter.AddForce", delegate() 451 PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate()
441 { 452 {
442 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); 453 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
443 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); 454 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force);
@@ -450,42 +461,9 @@ public class BSCharacter : BSPhysObject
450 //m_lastUpdateSent = false; 461 //m_lastUpdateSent = false;
451 } 462 }
452 463
453 public override void AddAngularForce(Vector3 force, bool pushforce) { 464 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
454 }
455 public override void SetMomentum(Vector3 momentum) {
456 }
457
458 // Turn on collision events at a rate no faster than one every the given milliseconds
459 public override void SubscribeEvents(int ms) {
460 _subscribedEventsMs = ms;
461 if (ms > 0)
462 {
463 // make sure first collision happens
464 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
465
466 Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate()
467 {
468 BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
469 });
470 }
471 } 465 }
472 466 public override void SetMomentum(OMV.Vector3 momentum) {
473 public override void ZeroMotion()
474 {
475 return;
476 }
477
478 // Stop collision events
479 public override void UnSubscribeEvents() {
480 _subscribedEventsMs = 0;
481 Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate()
482 {
483 BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
484 });
485 }
486 // Return 'true' if someone has subscribed to events
487 public override bool SubscribedEvents() {
488 return (_subscribedEventsMs > 0);
489 } 467 }
490 468
491 // set _avatarVolume and _mass based on capsule size, _density and _scale 469 // set _avatarVolume and _mass based on capsule size, _density and _scale
@@ -520,67 +498,15 @@ public class BSCharacter : BSPhysObject
520 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. 498 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
521 PositionSanityCheck2(); 499 PositionSanityCheck2();
522 500
523 float heightHere = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug 501 float heightHere = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug
524 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}", 502 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}",
525 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere); 503 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere);
526 } 504 }
527 505
528 // Called by the scene when a collision with this object is reported
529 // The collision, if it should be reported to the character, is placed in a collection
530 // that will later be sent to the simulator when SendCollisions() is called.
531 CollisionEventUpdate collisionCollection = null;
532 public override bool Collide(uint collidingWith, BSPhysObject collidee, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
533 {
534 bool ret = false;
535
536 // The following makes IsColliding() and IsCollidingGround() work
537 _collidingStep = Scene.SimulationStep;
538 if (collidingWith <= Scene.TerrainManager.HighestTerrainID)
539 {
540 _collidingGroundStep = Scene.SimulationStep;
541 }
542 // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
543
544 // throttle collisions to the rate specified in the subscription
545 if (SubscribedEvents()) {
546 int nowTime = Scene.SimulationNowTime;
547 if (nowTime >= _nextCollisionOkTime) {
548 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
549
550 if (collisionCollection == null)
551 collisionCollection = new CollisionEventUpdate();
552 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
553 ret = true;
554 }
555 }
556 return ret;
557 }
558
559 public override void SendCollisions()
560 {
561 /*
562 if (collisionCollection != null && collisionCollection.Count > 0)
563 {
564 base.SendCollisionUpdate(collisionCollection);
565 collisionCollection = null;
566 }
567 */
568 // Kludge to make a collision call even if there are no collisions.
569 // This causes the avatar animation to get updated.
570 if (collisionCollection == null)
571 collisionCollection = new CollisionEventUpdate();
572 base.SendCollisionUpdate(collisionCollection);
573 // If there were any collisions in the collection, make sure we don't use the
574 // same instance next time.
575 if (collisionCollection.Count > 0)
576 collisionCollection = null;
577 // End kludge
578 }
579
580 // Invoke the detailed logger and output something if it's enabled. 506 // Invoke the detailed logger and output something if it's enabled.
581 private void DetailLog(string msg, params Object[] args) 507 private void DetailLog(string msg, params Object[] args)
582 { 508 {
583 Scene.PhysicsLogging.Write(msg, args); 509 PhysicsScene.PhysicsLogging.Write(msg, args);
584 } 510 }
585} 511}
586} 512}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 61006f0..2da2331 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -539,7 +539,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
539 // add Gravity and Buoyancy 539 // add Gravity and Buoyancy
540 // There is some gravity, make a gravity force vector that is applied after object velocity. 540 // There is some gravity, make a gravity force vector that is applied after object velocity.
541 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 541 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
542 Vector3 grav = m_prim.Scene.DefaultGravity * (m_prim.Mass * (1f - m_VehicleBuoyancy)); 542 Vector3 grav = m_prim.PhysicsScene.DefaultGravity * (m_prim.Mass * (1f - m_VehicleBuoyancy));
543 543
544 /* 544 /*
545 * RA: Not sure why one would do this 545 * RA: Not sure why one would do this
@@ -552,7 +552,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
552// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); 552// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
553 553
554 // If below the terrain, move us above the ground a little. 554 // If below the terrain, move us above the ground a little.
555 float terrainHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos); 555 float terrainHeight = m_prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
556 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. 556 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
557 // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. 557 // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
558 // Vector3 rotatedSize = m_prim.Size * m_prim.Orientation; 558 // Vector3 rotatedSize = m_prim.Size * m_prim.Orientation;
@@ -570,7 +570,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
570 // We should hover, get the target height 570 // We should hover, get the target height
571 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) 571 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
572 { 572 {
573 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight; 573 m_VhoverTargetHeight = m_prim.PhysicsScene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight;
574 } 574 }
575 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) 575 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
576 { 576 {
@@ -849,8 +849,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
849 // Invoke the detailed logger and output something if it's enabled. 849 // Invoke the detailed logger and output something if it's enabled.
850 private void VDetailLog(string msg, params Object[] args) 850 private void VDetailLog(string msg, params Object[] args)
851 { 851 {
852 if (m_prim.Scene.VehicleLoggingEnabled) 852 if (m_prim.PhysicsScene.VehicleLoggingEnabled)
853 m_prim.Scene.PhysicsLogging.Write(msg, args); 853 m_prim.PhysicsScene.PhysicsLogging.Write(msg, args);
854 } 854 }
855 } 855 }
856} 856}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 7e784eb..005a758 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -36,11 +36,9 @@ public class BSLinkset
36{ 36{
37 private static string LogHeader = "[BULLETSIM LINKSET]"; 37 private static string LogHeader = "[BULLETSIM LINKSET]";
38 38
39 private BSPhysObject m_linksetRoot; 39 public BSPhysObject LinksetRoot { get; protected set; }
40 public BSPhysObject LinksetRoot { get { return m_linksetRoot; } }
41 40
42 private BSScene m_physicsScene; 41 public BSScene PhysicsScene { get; private set; }
43 public BSScene PhysicsScene { get { return m_physicsScene; } }
44 42
45 static int m_nextLinksetID = 1; 43 static int m_nextLinksetID = 1;
46 public int LinksetID { get; private set; } 44 public int LinksetID { get; private set; }
@@ -81,8 +79,8 @@ public class BSLinkset
81 // We create LOTS of linksets. 79 // We create LOTS of linksets.
82 if (m_nextLinksetID < 0) 80 if (m_nextLinksetID < 0)
83 m_nextLinksetID = 1; 81 m_nextLinksetID = 1;
84 m_physicsScene = scene; 82 PhysicsScene = scene;
85 m_linksetRoot = parent; 83 LinksetRoot = parent;
86 m_children = new List<BSPhysObject>(); 84 m_children = new List<BSPhysObject>();
87 m_mass = parent.MassRaw; 85 m_mass = parent.MassRaw;
88 } 86 }
@@ -131,7 +129,7 @@ public class BSLinkset
131 // Return 'true' if the passed object is the root object of this linkset 129 // Return 'true' if the passed object is the root object of this linkset
132 public bool IsRoot(BSPhysObject requestor) 130 public bool IsRoot(BSPhysObject requestor)
133 { 131 {
134 return (requestor.LocalID == m_linksetRoot.LocalID); 132 return (requestor.LocalID == LinksetRoot.LocalID);
135 } 133 }
136 134
137 public int NumberOfChildren { get { return m_children.Count; } } 135 public int NumberOfChildren { get { return m_children.Count; } }
@@ -159,7 +157,7 @@ public class BSLinkset
159 157
160 private float ComputeLinksetMass() 158 private float ComputeLinksetMass()
161 { 159 {
162 float mass = m_linksetRoot.MassRaw; 160 float mass = LinksetRoot.MassRaw;
163 foreach (BSPhysObject bp in m_children) 161 foreach (BSPhysObject bp in m_children)
164 { 162 {
165 mass += bp.MassRaw; 163 mass += bp.MassRaw;
@@ -169,8 +167,8 @@ public class BSLinkset
169 167
170 private OMV.Vector3 ComputeLinksetCenterOfMass() 168 private OMV.Vector3 ComputeLinksetCenterOfMass()
171 { 169 {
172 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; 170 OMV.Vector3 com = LinksetRoot.Position * LinksetRoot.MassRaw;
173 float totalMass = m_linksetRoot.MassRaw; 171 float totalMass = LinksetRoot.MassRaw;
174 172
175 lock (m_linksetActivityLock) 173 lock (m_linksetActivityLock)
176 { 174 {
@@ -188,7 +186,7 @@ public class BSLinkset
188 186
189 private OMV.Vector3 ComputeLinksetGeometricCenter() 187 private OMV.Vector3 ComputeLinksetGeometricCenter()
190 { 188 {
191 OMV.Vector3 com = m_linksetRoot.Position; 189 OMV.Vector3 com = LinksetRoot.Position;
192 190
193 lock (m_linksetActivityLock) 191 lock (m_linksetActivityLock)
194 { 192 {
@@ -256,7 +254,7 @@ public class BSLinkset
256 foreach (BSPhysObject child in m_children) 254 foreach (BSPhysObject child in m_children)
257 { 255 {
258 BSConstraint constrain; 256 BSConstraint constrain;
259 if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) 257 if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain))
260 { 258 {
261 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", 259 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
262 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); 260 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
@@ -306,9 +304,9 @@ public class BSLinkset
306 304
307 BSPhysObject rootx = LinksetRoot; // capture the root as of now 305 BSPhysObject rootx = LinksetRoot; // capture the root as of now
308 BSPhysObject childx = child; 306 BSPhysObject childx = child;
309 m_physicsScene.TaintedObject("AddChildToLinkset", delegate() 307 PhysicsScene.TaintedObject("AddChildToLinkset", delegate()
310 { 308 {
311 DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); 309 DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID);
312 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child 310 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child
313 }); 311 });
314 } 312 }
@@ -322,7 +320,7 @@ public class BSLinkset
322 // has to be updated also (like pointer to prim's parent). 320 // has to be updated also (like pointer to prim's parent).
323 private void RemoveChildFromOtherLinkset(BSPhysObject pchild) 321 private void RemoveChildFromOtherLinkset(BSPhysObject pchild)
324 { 322 {
325 pchild.Linkset = new BSLinkset(m_physicsScene, pchild); 323 pchild.Linkset = new BSLinkset(PhysicsScene, pchild);
326 RemoveChildFromLinkset(pchild); 324 RemoveChildFromLinkset(pchild);
327 } 325 }
328 326
@@ -334,9 +332,9 @@ public class BSLinkset
334 { 332 {
335 BSPhysObject rootx = LinksetRoot; // capture the root as of now 333 BSPhysObject rootx = LinksetRoot; // capture the root as of now
336 BSPhysObject childx = child; 334 BSPhysObject childx = child;
337 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() 335 PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
338 { 336 {
339 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); 337 DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID);
340 338
341 PhysicallyUnlinkAChildFromRoot(rootx, childx); 339 PhysicallyUnlinkAChildFromRoot(rootx, childx);
342 RecomputeLinksetConstraintVariables(); 340 RecomputeLinksetConstraintVariables();
@@ -370,7 +368,7 @@ public class BSLinkset
370 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}", 368 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}",
371 rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint); 369 rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint);
372 BS6DofConstraint constrain = new BS6DofConstraint( 370 BS6DofConstraint constrain = new BS6DofConstraint(
373 m_physicsScene.World, rootPrim.BSBody, childPrim.BSBody, 371 PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody,
374 midPoint, 372 midPoint,
375 true, 373 true,
376 true 374 true
@@ -408,7 +406,7 @@ public class BSLinkset
408 // ================================================================================== 406 // ==================================================================================
409 */ 407 */
410 408
411 m_physicsScene.Constraints.AddConstraint(constrain); 409 PhysicsScene.Constraints.AddConstraint(constrain);
412 410
413 // zero linear and angular limits makes the objects unable to move in relation to each other 411 // zero linear and angular limits makes the objects unable to move in relation to each other
414 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 412 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
@@ -435,7 +433,7 @@ public class BSLinkset
435 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); 433 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
436 434
437 // Find the constraint for this link and get rid of it from the overall collection and from my list 435 // Find the constraint for this link and get rid of it from the overall collection and from my list
438 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody); 436 PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody);
439 437
440 // Make the child refresh its location 438 // Make the child refresh its location
441 BulletSimAPI.PushUpdate2(childPrim.BSBody.Ptr); 439 BulletSimAPI.PushUpdate2(childPrim.BSBody.Ptr);
@@ -447,13 +445,13 @@ public class BSLinkset
447 { 445 {
448 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); 446 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
449 447
450 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); 448 PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody);
451 } 449 }
452 450
453 // Invoke the detailed logger and output something if it's enabled. 451 // Invoke the detailed logger and output something if it's enabled.
454 private void DetailLog(string msg, params Object[] args) 452 private void DetailLog(string msg, params Object[] args)
455 { 453 {
456 m_physicsScene.PhysicsLogging.Write(msg, args); 454 PhysicsScene.PhysicsLogging.Write(msg, args);
457 } 455 }
458 456
459} 457}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 3fe71e1..242aa80 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -39,26 +39,150 @@ namespace OpenSim.Region.Physics.BulletSPlugin
39// unless the difference is significant. 39// unless the difference is significant.
40public abstract class BSPhysObject : PhysicsActor 40public abstract class BSPhysObject : PhysicsActor
41{ 41{
42 public abstract BSLinkset Linkset { get; set; } 42 protected void BaseInitialize(BSScene parentScene)
43 {
44 PhysicsScene = parentScene;
45 Linkset = new BSLinkset(PhysicsScene, this);
43 46
44 public abstract bool Collide(uint collidingWith, BSPhysObject collidee, 47 CollisionCollection = new CollisionEventUpdate();
45 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth); 48 SubscribedEventsMs = 0;
46 public abstract void SendCollisions(); 49 CollidingStep = 0;
50 CollidingGroundStep = 0;
51 }
47 52
48 // Return the object mass without calculating it or side effects 53 public BSScene PhysicsScene { get; protected set; }
54
55 public BSLinkset Linkset { get; set; }
56
57 // Return the object mass without calculating it or having side effects
49 public abstract float MassRaw { get; } 58 public abstract float MassRaw { get; }
50 59
51 // Reference to the physical body (btCollisionObject) of this object 60 // Reference to the physical body (btCollisionObject) of this object
52 public abstract BulletBody BSBody { get; set; } 61 public BulletBody BSBody { get; protected set; }
53 // Reference to the physical shape (btCollisionShape) of this object 62 // Reference to the physical shape (btCollisionShape) of this object
54 public abstract BulletShape BSShape { get; set; } 63 public BulletShape BSShape { get; protected set; }
55 64
65 // Stop all physical motion.
56 public abstract void ZeroMotion(); 66 public abstract void ZeroMotion();
57 67
68 // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured.
58 public virtual void StepVehicle(float timeStep) { } 69 public virtual void StepVehicle(float timeStep) { }
59 70
71 // Update the physical location and motion of the object. Called with data from Bullet.
60 public abstract void UpdateProperties(EntityProperties entprop); 72 public abstract void UpdateProperties(EntityProperties entprop);
61 73
74 // Tell the object to clean up.
62 public abstract void Destroy(); 75 public abstract void Destroy();
76
77 #region Collisions
78
79 // Requested number of milliseconds between collision events. Zero means disabled.
80 protected int SubscribedEventsMs { get; set; }
81 // Given subscription, the time that a collision may be passed up
82 protected int NextCollisionOkTime { get; set; }
83 // The simulation step that last had a collision
84 protected long CollidingStep { get; set; }
85 // The simulation step that last had a collision with the ground
86 protected long CollidingGroundStep { get; set; }
87 // The collision flags we think are set in Bullet
88 protected CollisionFlags CurrentCollisionFlags { get; set; }
89
90 // The collisions that have been collected this tick
91 protected CollisionEventUpdate CollisionCollection;
92
93 // The simulation step is telling this object about a collision.
94 // Return 'true' if a collision was processed and should be sent up.
95 // Called at taint time from within the Step() function
96 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
97 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
98 {
99 bool ret = false;
100
101 // The following lines make IsColliding() and IsCollidingGround() work
102 CollidingStep = PhysicsScene.SimulationStep;
103 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID)
104 {
105 CollidingGroundStep = PhysicsScene.SimulationStep;
106 }
107
108 // prims in the same linkset cannot collide with each other
109 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
110 {
111 return ret;
112 }
113
114 PhysicsScene.PhysicsLogging.Write("{0},BSPhysObject.Collison,call,with={1}", LocalID, collidingWith);
115
116 // if someone has subscribed for collision events....
117 if (SubscribedEvents()) {
118 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
119 PhysicsScene.PhysicsLogging.Write("{0},BSPhysObject.Collison.AddCollider,call,with={1},point={2},normal={3},depth={4},next={5}",
120 LocalID, collidingWith, contactPoint, contactNormal, pentrationDepth, NextCollisionOkTime.ToString("yyyyMMddHHmmssfff"));
121 ret = true;
122 }
123 return ret;
124 }
125
126 // Routine to send the collected collisions into the simulator.
127 // Also handles removal of this from the collection of objects with collisions if
128 // there are no collisions from this object. Mechanism is create one last
129 // collision event to make collision_end work.
130 public virtual void SendCollisions()
131 {
132 // throttle the collisions to the number of milliseconds specified in the subscription
133 int nowTime = PhysicsScene.SimulationNowTime;
134 if (nowTime >= NextCollisionOkTime)
135 {
136 NextCollisionOkTime = nowTime + SubscribedEventsMs;
137
138 // We are called if we previously had collisions. If there are no collisions
139 // this time, send up one last empty event so OpenSim can sense collision end.
140 if (CollisionCollection.Count == 0)
141 PhysicsScene.ObjectsWithNoMoreCollisions.Add(this);
142
143 base.SendCollisionUpdate(CollisionCollection);
144
145 // The collisionCollection structure is passed around in the simulator.
146 // Make sure we don't have a handle to that one and that a new one is used next time.
147 CollisionCollection = new CollisionEventUpdate();
148 }
149 }
150
151 // Subscribe for collision events.
152 // Parameter is the millisecond rate the caller wishes collision events to occur.
153 public override void SubscribeEvents(int ms) {
154 SubscribedEventsMs = ms;
155 if (ms > 0)
156 {
157 // make sure first collision happens
158 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
159 PhysicsScene.PhysicsLogging.Write("{0},SubscribeEvents,call,ms={1},nextOKTime={2}",
160 LocalID, SubscribedEventsMs, NextCollisionOkTime.ToString("yyyyMMddHHmmssfff"));
161
162 PhysicsScene.TaintedObject("BSPhysObject.SubscribeEvents", delegate()
163 {
164 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
165 });
166 }
167 else
168 {
169 // Subscribing for zero or less is the same as unsubscribing
170 UnSubscribeEvents();
171 }
172 }
173 public override void UnSubscribeEvents() {
174 SubscribedEventsMs = 0;
175 PhysicsScene.PhysicsLogging.Write("{0},UnSubscribeEvents,call", LocalID);
176 PhysicsScene.TaintedObject("BSPhysObject.UnSubscribeEvents", delegate()
177 {
178 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
179 });
180 }
181 // Return 'true' if the simulator wants collision events
182 public override bool SubscribedEvents() {
183 return (SubscribedEventsMs > 0);
184 }
185
186 #endregion // Collisions
63} 187}
64} 188}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 26a581f..29f27e8 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -49,8 +49,6 @@ public sealed class BSPrim : BSPhysObject
49 private ulong _hullKey; 49 private ulong _hullKey;
50 private List<ConvexResult> _hulls; 50 private List<ConvexResult> _hulls;
51 51
52 private BSScene _scene;
53 public BSScene Scene { get { return _scene; } }
54 private String _avName; 52 private String _avName;
55 private uint _localID = 0; 53 private uint _localID = 0;
56 54
@@ -87,18 +85,6 @@ public sealed class BSPrim : BSPhysObject
87 private bool _kinematic; 85 private bool _kinematic;
88 private float _buoyancy; 86 private float _buoyancy;
89 87
90 // Membership in a linkset is controlled by this class.
91 public override BSLinkset Linkset { get; set; }
92
93 private int _subscribedEventsMs = 0;
94 private int _nextCollisionOkTime = 0;
95 long _collidingStep;
96 long _collidingGroundStep;
97 CollisionFlags m_currentCollisionFlags = 0;
98
99 public override BulletBody BSBody { get; set; }
100 public override BulletShape BSShape { get; set; }
101
102 private BSDynamics _vehicle; 88 private BSDynamics _vehicle;
103 89
104 private OMV.Vector3 _PIDTarget; 90 private OMV.Vector3 _PIDTarget;
@@ -113,10 +99,10 @@ public sealed class BSPrim : BSPhysObject
113 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 99 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
114 { 100 {
115 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 101 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
102 base.BaseInitialize(parent_scene);
116 _localID = localID; 103 _localID = localID;
117 _avName = primName; 104 _avName = primName;
118 _physicsActorType = (int)ActorTypes.Prim; 105 _physicsActorType = (int)ActorTypes.Prim;
119 _scene = parent_scene;
120 _position = pos; 106 _position = pos;
121 _size = size; 107 _size = size;
122 _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type 108 _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type
@@ -129,25 +115,23 @@ public sealed class BSPrim : BSPhysObject
129 _pbs = pbs; 115 _pbs = pbs;
130 _isPhysical = pisPhysical; 116 _isPhysical = pisPhysical;
131 _isVolumeDetect = false; 117 _isVolumeDetect = false;
132 _subscribedEventsMs = 0; 118 _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material
133 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 119 _density = PhysicsScene.Params.defaultDensity; // TODO: compute based on object material
134 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 120 _restitution = PhysicsScene.Params.defaultRestitution;
135 _restitution = _scene.Params.defaultRestitution; 121 _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness
136 Linkset = new BSLinkset(Scene, this); // a linkset of one
137 _vehicle = new BSDynamics(Scene, this); // add vehicleness
138 _mass = CalculateMass(); 122 _mass = CalculateMass();
139 DetailLog("{0},BSPrim.constructor,call", LocalID); 123 DetailLog("{0},BSPrim.constructor,call", LocalID);
140 // do the actual object creation at taint time 124 // do the actual object creation at taint time
141 _scene.TaintedObject("BSPrim.create", delegate() 125 PhysicsScene.TaintedObject("BSPrim.create", delegate()
142 { 126 {
143 CreateGeomAndObject(true); 127 CreateGeomAndObject(true);
144 128
145 // Get the pointer to the physical body for this object. 129 // Get the pointer to the physical body for this object.
146 // At the moment, we're still letting BulletSim manage the creation and destruction 130 // At the moment, we're still letting BulletSim manage the creation and destruction
147 // of the object. Someday we'll move that into the C# code. 131 // of the object. Someday we'll move that into the C# code.
148 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); 132 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID));
149 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); 133 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
150 m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr); 134 CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr);
151 }); 135 });
152 } 136 }
153 137
@@ -168,11 +152,11 @@ public sealed class BSPrim : BSPhysObject
168 // Undo any vehicle properties 152 // Undo any vehicle properties
169 this.VehicleType = (int)Vehicle.TYPE_NONE; 153 this.VehicleType = (int)Vehicle.TYPE_NONE;
170 154
171 _scene.TaintedObject("BSPrim.destroy", delegate() 155 PhysicsScene.TaintedObject("BSPrim.destroy", delegate()
172 { 156 {
173 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 157 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
174 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 158 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
175 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); 159 BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID);
176 }); 160 });
177 } 161 }
178 162
@@ -183,7 +167,7 @@ public sealed class BSPrim : BSPhysObject
183 get { return _size; } 167 get { return _size; }
184 set { 168 set {
185 _size = value; 169 _size = value;
186 _scene.TaintedObject("BSPrim.setSize", delegate() 170 PhysicsScene.TaintedObject("BSPrim.setSize", delegate()
187 { 171 {
188 _mass = CalculateMass(); // changing size changes the mass 172 _mass = CalculateMass(); // changing size changes the mass
189 // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct 173 // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct
@@ -196,7 +180,7 @@ public sealed class BSPrim : BSPhysObject
196 public override PrimitiveBaseShape Shape { 180 public override PrimitiveBaseShape Shape {
197 set { 181 set {
198 _pbs = value; 182 _pbs = value;
199 _scene.TaintedObject("BSPrim.setShape", delegate() 183 PhysicsScene.TaintedObject("BSPrim.setShape", delegate()
200 { 184 {
201 _mass = CalculateMass(); // changing the shape changes the mass 185 _mass = CalculateMass(); // changing the shape changes the mass
202 CreateGeomAndObject(false); 186 CreateGeomAndObject(false);
@@ -214,7 +198,7 @@ public sealed class BSPrim : BSPhysObject
214 public override bool Selected { 198 public override bool Selected {
215 set { 199 set {
216 _isSelected = value; 200 _isSelected = value;
217 _scene.TaintedObject("BSPrim.setSelected", delegate() 201 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate()
218 { 202 {
219 SetObjectDynamic(); 203 SetObjectDynamic();
220 }); 204 });
@@ -283,13 +267,13 @@ public sealed class BSPrim : BSPhysObject
283 _position = BulletSimAPI.GetPosition2(BSBody.Ptr); 267 _position = BulletSimAPI.GetPosition2(BSBody.Ptr);
284 268
285 // don't do the GetObjectPosition for root elements because this function is called a zillion times 269 // don't do the GetObjectPosition for root elements because this function is called a zillion times
286 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 270 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
287 return _position; 271 return _position;
288 } 272 }
289 set { 273 set {
290 _position = value; 274 _position = value;
291 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 275 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
292 _scene.TaintedObject("BSPrim.setPosition", delegate() 276 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
293 { 277 {
294 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 278 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
295 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation); 279 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation);
@@ -327,7 +311,7 @@ public sealed class BSPrim : BSPhysObject
327 get { return _force; } 311 get { return _force; }
328 set { 312 set {
329 _force = value; 313 _force = value;
330 _scene.TaintedObject("BSPrim.setForce", delegate() 314 PhysicsScene.TaintedObject("BSPrim.setForce", delegate()
331 { 315 {
332 DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 316 DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
333 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); 317 BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force);
@@ -342,40 +326,40 @@ public sealed class BSPrim : BSPhysObject
342 set { 326 set {
343 Vehicle type = (Vehicle)value; 327 Vehicle type = (Vehicle)value;
344 BSPrim vehiclePrim = this; 328 BSPrim vehiclePrim = this;
345 _scene.TaintedObject("setVehicleType", delegate() 329 PhysicsScene.TaintedObject("setVehicleType", delegate()
346 { 330 {
347 // Done at taint time so we're sure the physics engine is not using the variables 331 // Done at taint time so we're sure the physics engine is not using the variables
348 // Vehicle code changes the parameters for this vehicle type. 332 // Vehicle code changes the parameters for this vehicle type.
349 _vehicle.ProcessTypeChange(type); 333 _vehicle.ProcessTypeChange(type);
350 // Tell the scene about the vehicle so it will get processing each frame. 334 // Tell the scene about the vehicle so it will get processing each frame.
351 _scene.VehicleInSceneTypeChanged(this, type); 335 PhysicsScene.VehicleInSceneTypeChanged(this, type);
352 }); 336 });
353 } 337 }
354 } 338 }
355 public override void VehicleFloatParam(int param, float value) 339 public override void VehicleFloatParam(int param, float value)
356 { 340 {
357 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 341 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
358 { 342 {
359 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); 343 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
360 }); 344 });
361 } 345 }
362 public override void VehicleVectorParam(int param, OMV.Vector3 value) 346 public override void VehicleVectorParam(int param, OMV.Vector3 value)
363 { 347 {
364 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 348 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
365 { 349 {
366 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); 350 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
367 }); 351 });
368 } 352 }
369 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 353 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
370 { 354 {
371 _scene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 355 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
372 { 356 {
373 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 357 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
374 }); 358 });
375 } 359 }
376 public override void VehicleFlags(int param, bool remove) 360 public override void VehicleFlags(int param, bool remove)
377 { 361 {
378 _scene.TaintedObject("BSPrim.VehicleFlags", delegate() 362 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate()
379 { 363 {
380 _vehicle.ProcessVehicleFlags(param, remove); 364 _vehicle.ProcessVehicleFlags(param, remove);
381 }); 365 });
@@ -393,8 +377,9 @@ public sealed class BSPrim : BSPhysObject
393 public override void SetVolumeDetect(int param) { 377 public override void SetVolumeDetect(int param) {
394 bool newValue = (param != 0); 378 bool newValue = (param != 0);
395 _isVolumeDetect = newValue; 379 _isVolumeDetect = newValue;
396 _scene.TaintedObject("BSPrim.SetVolumeDetect", delegate() 380 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
397 { 381 {
382 DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
398 SetObjectDynamic(); 383 SetObjectDynamic();
399 }); 384 });
400 return; 385 return;
@@ -404,7 +389,7 @@ public sealed class BSPrim : BSPhysObject
404 get { return _velocity; } 389 get { return _velocity; }
405 set { 390 set {
406 _velocity = value; 391 _velocity = value;
407 _scene.TaintedObject("BSPrim.setVelocity", delegate() 392 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
408 { 393 {
409 DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 394 DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
410 BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, _velocity); 395 BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, _velocity);
@@ -438,9 +423,9 @@ public sealed class BSPrim : BSPhysObject
438 set { 423 set {
439 _orientation = value; 424 _orientation = value;
440 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? 425 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
441 _scene.TaintedObject("BSPrim.setOrientation", delegate() 426 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
442 { 427 {
443 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 428 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
444 DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 429 DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
445 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation); 430 BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation);
446 }); 431 });
@@ -454,8 +439,9 @@ public sealed class BSPrim : BSPhysObject
454 get { return _isPhysical; } 439 get { return _isPhysical; }
455 set { 440 set {
456 _isPhysical = value; 441 _isPhysical = value;
457 _scene.TaintedObject("BSPrim.setIsPhysical", delegate() 442 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate()
458 { 443 {
444 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
459 SetObjectDynamic(); 445 SetObjectDynamic();
460 }); 446 });
461 } 447 }
@@ -493,9 +479,9 @@ public sealed class BSPrim : BSPhysObject
493 // Bullet wants static objects to have a mass of zero 479 // Bullet wants static objects to have a mass of zero
494 float mass = IsStatic ? 0f : _mass; 480 float mass = IsStatic ? 0f : _mass;
495 481
496 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); 482 BulletSimAPI.SetObjectProperties(Scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
497 */ 483 */
498 BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr); 484 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr);
499 485
500 // Set up the object physicalness (does gravity and collisions move this object) 486 // Set up the object physicalness (does gravity and collisions move this object)
501 MakeDynamic(IsStatic); 487 MakeDynamic(IsStatic);
@@ -506,15 +492,15 @@ public sealed class BSPrim : BSPhysObject
506 // Arrange for collisions events if the simulator wants them 492 // Arrange for collisions events if the simulator wants them
507 EnableCollisions(SubscribedEvents()); 493 EnableCollisions(SubscribedEvents());
508 494
509 BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr); 495 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, BSBody.Ptr);
510 496
511 // Recompute any linkset parameters. 497 // Recompute any linkset parameters.
512 // When going from non-physical to physical, this re-enables the constraints that 498 // When going from non-physical to physical, this re-enables the constraints that
513 // had been automatically disabled when the mass was set to zero. 499 // had been automatically disabled when the mass was set to zero.
514 Linkset.Refresh(this); 500 Linkset.Refresh(this);
515 501
516 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,static={1},solid={2},mass={3}, cf={4}", 502 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,static={1},solid={2},mass={3},collide={4},cf={5}",
517 LocalID, IsStatic, IsSolid, _mass, m_currentCollisionFlags); 503 LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags);
518 } 504 }
519 505
520 // "Making dynamic" means changing to and from static. 506 // "Making dynamic" means changing to and from static.
@@ -527,7 +513,7 @@ public sealed class BSPrim : BSPhysObject
527 if (makeStatic) 513 if (makeStatic)
528 { 514 {
529 // Become a Bullet 'static' object type 515 // Become a Bullet 'static' object type
530 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); 516 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
531 // Stop all movement 517 // Stop all movement
532 BulletSimAPI.ClearAllForces2(BSBody.Ptr); 518 BulletSimAPI.ClearAllForces2(BSBody.Ptr);
533 // Center of mass is at the center of the object 519 // Center of mass is at the center of the object
@@ -539,16 +525,17 @@ public sealed class BSPrim : BSPhysObject
539 // There can be special things needed for implementing linksets 525 // There can be special things needed for implementing linksets
540 Linkset.MakeStatic(this); 526 Linkset.MakeStatic(this);
541 // The activation state is 'sleeping' so Bullet will not try to act on it 527 // The activation state is 'sleeping' so Bullet will not try to act on it
542 BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING); 528 // BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING);
529 BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.DISABLE_SIMULATION);
543 } 530 }
544 else 531 else
545 { 532 {
546 // Not a Bullet static object 533 // Not a Bullet static object
547 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); 534 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
548 535
549 // Set various physical properties so internal things will get computed correctly as they are set 536 // Set various physical properties so internal dynamic properties will get computed correctly as they are set
550 BulletSimAPI.SetFriction2(BSBody.Ptr, Scene.Params.defaultFriction); 537 BulletSimAPI.SetFriction2(BSBody.Ptr, PhysicsScene.Params.defaultFriction);
551 BulletSimAPI.SetRestitution2(BSBody.Ptr, Scene.Params.defaultRestitution); 538 BulletSimAPI.SetRestitution2(BSBody.Ptr, PhysicsScene.Params.defaultRestitution);
552 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 539 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
553 BulletSimAPI.SetInterpolationLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero); 540 BulletSimAPI.SetInterpolationLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
554 BulletSimAPI.SetInterpolationAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero); 541 BulletSimAPI.SetInterpolationAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
@@ -562,10 +549,10 @@ public sealed class BSPrim : BSPhysObject
562 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); 549 BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
563 550
564 // Various values for simulation limits 551 // Various values for simulation limits
565 BulletSimAPI.SetDamping2(BSBody.Ptr, Scene.Params.linearDamping, Scene.Params.angularDamping); 552 BulletSimAPI.SetDamping2(BSBody.Ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping);
566 BulletSimAPI.SetDeactivationTime2(BSBody.Ptr, Scene.Params.deactivationTime); 553 BulletSimAPI.SetDeactivationTime2(BSBody.Ptr, PhysicsScene.Params.deactivationTime);
567 BulletSimAPI.SetSleepingThresholds2(BSBody.Ptr, Scene.Params.linearSleepingThreshold, Scene.Params.angularSleepingThreshold); 554 BulletSimAPI.SetSleepingThresholds2(BSBody.Ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
568 BulletSimAPI.SetContactProcessingThreshold2(BSBody.Ptr, Scene.Params.contactProcessingThreshold); 555 BulletSimAPI.SetContactProcessingThreshold2(BSBody.Ptr, PhysicsScene.Params.contactProcessingThreshold);
569 556
570 // There can be special things needed for implementing linksets 557 // There can be special things needed for implementing linksets
571 Linkset.MakeDynamic(this); 558 Linkset.MakeDynamic(this);
@@ -581,11 +568,11 @@ public sealed class BSPrim : BSPhysObject
581 if (makeSolid) 568 if (makeSolid)
582 { 569 {
583 // Easy in Bullet -- just remove the object flag that controls collision response 570 // Easy in Bullet -- just remove the object flag that controls collision response
584 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 571 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
585 } 572 }
586 else 573 else
587 { 574 {
588 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 575 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
589 } 576 }
590 } 577 }
591 578
@@ -594,11 +581,11 @@ public sealed class BSPrim : BSPhysObject
594 { 581 {
595 if (wantsCollisionEvents) 582 if (wantsCollisionEvents)
596 { 583 {
597 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 584 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
598 } 585 }
599 else 586 else
600 { 587 {
601 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 588 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
602 } 589 }
603 } 590 }
604 591
@@ -618,11 +605,11 @@ public sealed class BSPrim : BSPhysObject
618 set { _throttleUpdates = value; } 605 set { _throttleUpdates = value; }
619 } 606 }
620 public override bool IsColliding { 607 public override bool IsColliding {
621 get { return (_collidingStep == _scene.SimulationStep); } 608 get { return (CollidingStep == PhysicsScene.SimulationStep); }
622 set { _isColliding = value; } 609 set { _isColliding = value; }
623 } 610 }
624 public override bool CollidingGround { 611 public override bool CollidingGround {
625 get { return (_collidingGroundStep == _scene.SimulationStep); } 612 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
626 set { _collidingGround = value; } 613 set { _collidingGround = value; }
627 } 614 }
628 public override bool CollidingObj { 615 public override bool CollidingObj {
@@ -656,7 +643,7 @@ public sealed class BSPrim : BSPhysObject
656 set { 643 set {
657 _rotationalVelocity = value; 644 _rotationalVelocity = value;
658 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 645 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
659 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 646 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
660 { 647 {
661 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 648 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
662 BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity); 649 BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity);
@@ -673,13 +660,13 @@ public sealed class BSPrim : BSPhysObject
673 get { return _buoyancy; } 660 get { return _buoyancy; }
674 set { 661 set {
675 _buoyancy = value; 662 _buoyancy = value;
676 _scene.TaintedObject("BSPrim.setBuoyancy", delegate() 663 PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate()
677 { 664 {
678 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 665 DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
679 // Buoyancy is faked by changing the gravity applied to the object 666 // Buoyancy is faked by changing the gravity applied to the object
680 float grav = Scene.Params.gravity * (1f - _buoyancy); 667 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
681 BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav)); 668 BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav));
682 // BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 669 // BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, _localID, _buoyancy);
683 }); 670 });
684 } 671 }
685 } 672 }
@@ -730,7 +717,7 @@ public sealed class BSPrim : BSPhysObject
730 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 717 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
731 return; 718 return;
732 } 719 }
733 _scene.TaintedObject("BSPrim.AddForce", delegate() 720 PhysicsScene.TaintedObject("BSPrim.AddForce", delegate()
734 { 721 {
735 OMV.Vector3 fSum = OMV.Vector3.Zero; 722 OMV.Vector3 fSum = OMV.Vector3.Zero;
736 lock (m_accumulatedForces) 723 lock (m_accumulatedForces)
@@ -754,30 +741,6 @@ public sealed class BSPrim : BSPhysObject
754 public override void SetMomentum(OMV.Vector3 momentum) { 741 public override void SetMomentum(OMV.Vector3 momentum) {
755 DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); 742 DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
756 } 743 }
757 public override void SubscribeEvents(int ms) {
758 _subscribedEventsMs = ms;
759 if (ms > 0)
760 {
761 // make sure first collision happens
762 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
763
764 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
765 {
766 m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
767 });
768 }
769 }
770 public override void UnSubscribeEvents() {
771 _subscribedEventsMs = 0;
772 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
773 {
774 m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
775 });
776 }
777 public override bool SubscribedEvents() {
778 return (_subscribedEventsMs > 0);
779 }
780
781 #region Mass Calculation 744 #region Mass Calculation
782 745
783 private float CalculateMass() 746 private float CalculateMass()
@@ -1071,8 +1034,8 @@ public sealed class BSPrim : BSPhysObject
1071 if (returnMass <= 0) 1034 if (returnMass <= 0)
1072 returnMass = 0.0001f; 1035 returnMass = 0.0001f;
1073 1036
1074 if (returnMass > _scene.MaximumObjectMass) 1037 if (returnMass > PhysicsScene.MaximumObjectMass)
1075 returnMass = _scene.MaximumObjectMass; 1038 returnMass = PhysicsScene.MaximumObjectMass;
1076 1039
1077 return returnMass; 1040 return returnMass;
1078 }// end CalculateMass 1041 }// end CalculateMass
@@ -1090,7 +1053,7 @@ public sealed class BSPrim : BSPhysObject
1090 bool haveShape = false; 1053 bool haveShape = false;
1091 1054
1092 // If the prim attributes are simple, this could be a simple Bullet native shape 1055 // If the prim attributes are simple, this could be a simple Bullet native shape
1093 if ((_pbs.SculptEntry && !Scene.ShouldMeshSculptedPrim) 1056 if ((_pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim)
1094 || (_pbs.ProfileBegin == 0 && _pbs.ProfileEnd == 0 1057 || (_pbs.ProfileBegin == 0 && _pbs.ProfileEnd == 0
1095 && _pbs.ProfileHollow == 0 1058 && _pbs.ProfileHollow == 0
1096 && _pbs.PathTwist == 0 && _pbs.PathTwistBegin == 0 1059 && _pbs.PathTwist == 0 && _pbs.PathTwistBegin == 0
@@ -1156,12 +1119,12 @@ public sealed class BSPrim : BSPhysObject
1156 private bool CreateGeomMesh() 1119 private bool CreateGeomMesh()
1157 { 1120 {
1158 // level of detail based on size and type of the object 1121 // level of detail based on size and type of the object
1159 float lod = _scene.MeshLOD; 1122 float lod = PhysicsScene.MeshLOD;
1160 if (_pbs.SculptEntry) 1123 if (_pbs.SculptEntry)
1161 lod = _scene.SculptLOD; 1124 lod = PhysicsScene.SculptLOD;
1162 float maxAxis = Math.Max(_size.X, Math.Max(_size.Y, _size.Z)); 1125 float maxAxis = Math.Max(_size.X, Math.Max(_size.Y, _size.Z));
1163 if (maxAxis > _scene.MeshMegaPrimThreshold) 1126 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
1164 lod = _scene.MeshMegaPrimLOD; 1127 lod = PhysicsScene.MeshMegaPrimLOD;
1165 1128
1166 ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod); 1129 ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod);
1167 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); 1130 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey);
@@ -1175,14 +1138,14 @@ public sealed class BSPrim : BSPhysObject
1175 { 1138 {
1176 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); 1139 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1177 DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); 1140 DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
1178 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1141 BulletSimAPI.DestroyMesh(PhysicsScene.WorldID, _meshKey);
1179 _mesh = null; 1142 _mesh = null;
1180 _meshKey = 0; 1143 _meshKey = 0;
1181 } 1144 }
1182 1145
1183 _meshKey = newMeshKey; 1146 _meshKey = newMeshKey;
1184 // always pass false for physicalness as this creates some sort of bounding box which we don't need 1147 // always pass false for physicalness as this creates some sort of bounding box which we don't need
1185 _mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, lod, false); 1148 _mesh = PhysicsScene.mesher.CreateMesh(_avName, _pbs, _size, lod, false);
1186 1149
1187 int[] indices = _mesh.getIndexListAsInt(); 1150 int[] indices = _mesh.getIndexListAsInt();
1188 List<OMV.Vector3> vertices = _mesh.getVertexList(); 1151 List<OMV.Vector3> vertices = _mesh.getVertexList();
@@ -1198,7 +1161,7 @@ public sealed class BSPrim : BSPhysObject
1198 1161
1199 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", 1162 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
1200 // LogHeader, _localID, _meshKey, indices.Length, vertices.Count); 1163 // LogHeader, _localID, _meshKey, indices.Length, vertices.Count);
1201 BulletSimAPI.CreateMesh(_scene.WorldID, _meshKey, indices.GetLength(0), indices, 1164 BulletSimAPI.CreateMesh(PhysicsScene.WorldID, _meshKey, indices.GetLength(0), indices,
1202 vertices.Count, verticesAsFloats); 1165 vertices.Count, verticesAsFloats);
1203 1166
1204 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1167 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
@@ -1211,7 +1174,7 @@ public sealed class BSPrim : BSPhysObject
1211 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). 1174 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
1212 private bool CreateGeomHull() 1175 private bool CreateGeomHull()
1213 { 1176 {
1214 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; 1177 float lod = _pbs.SculptEntry ? PhysicsScene.SculptLOD : PhysicsScene.MeshLOD;
1215 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); 1178 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod);
1216 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); 1179 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey);
1217 1180
@@ -1225,7 +1188,7 @@ public sealed class BSPrim : BSPhysObject
1225 { 1188 {
1226 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); 1189 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1227 DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey); 1190 DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey);
1228 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1191 BulletSimAPI.DestroyHull(PhysicsScene.WorldID, _hullKey);
1229 _hullKey = 0; 1192 _hullKey = 0;
1230 } 1193 }
1231 1194
@@ -1314,7 +1277,7 @@ public sealed class BSPrim : BSPhysObject
1314 1277
1315 // create the hull definition in Bullet 1278 // create the hull definition in Bullet
1316 // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount); 1279 // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount);
1317 BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls); 1280 BulletSimAPI.CreateHull(PhysicsScene.WorldID, _hullKey, hullCount, convHulls);
1318 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1281 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1319 // meshes are already scaled by the meshmerizer 1282 // meshes are already scaled by the meshmerizer
1320 _scale = new OMV.Vector3(1f, 1f, 1f); 1283 _scale = new OMV.Vector3(1f, 1f, 1f);
@@ -1354,10 +1317,10 @@ public sealed class BSPrim : BSPhysObject
1354 ShapeData shape; 1317 ShapeData shape;
1355 FillShapeInfo(out shape); 1318 FillShapeInfo(out shape);
1356 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); 1319 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1357 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); 1320 bool ret = BulletSimAPI.CreateObject(PhysicsScene.WorldID, shape);
1358 1321
1359 // the CreateObject() may have recreated the rigid body. Make sure we have the latest address. 1322 // the CreateObject() may have recreated the rigid body. Make sure we have the latest address.
1360 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); 1323 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.Ptr, LocalID));
1361 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); 1324 BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
1362 1325
1363 return ret; 1326 return ret;
@@ -1490,61 +1453,10 @@ public sealed class BSPrim : BSPhysObject
1490 } 1453 }
1491 */ 1454 */
1492 } 1455 }
1493
1494 // I've collided with something
1495 // Called at taint time from within the Step() function
1496 CollisionEventUpdate collisionCollection;
1497 public override bool Collide(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
1498 {
1499 bool ret = false;
1500
1501 // The following lines make IsColliding() and IsCollidingGround() work
1502 _collidingStep = Scene.SimulationStep;
1503 if (collidingWith <= Scene.TerrainManager.HighestTerrainID)
1504 {
1505 _collidingGroundStep = Scene.SimulationStep;
1506 }
1507
1508 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
1509
1510 // prims in the same linkset cannot collide with each other
1511 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
1512 {
1513 return ret;
1514 }
1515
1516 // if someone has subscribed for collision events....
1517 if (SubscribedEvents()) {
1518 // throttle the collisions to the number of milliseconds specified in the subscription
1519 int nowTime = Scene.SimulationNowTime;
1520 if (nowTime >= _nextCollisionOkTime) {
1521 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
1522
1523 if (collisionCollection == null)
1524 collisionCollection = new CollisionEventUpdate();
1525 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
1526 ret = true;
1527 }
1528 }
1529 return ret;
1530 }
1531
1532 // The scene is telling us it's time to pass our collected collisions into the simulator
1533 public override void SendCollisions()
1534 {
1535 if (collisionCollection != null && collisionCollection.Count > 0)
1536 {
1537 base.SendCollisionUpdate(collisionCollection);
1538 // The collisionCollection structure is passed around in the simulator.
1539 // Make sure we don't have a handle to that one and that a new one is used next time.
1540 collisionCollection = null;
1541 }
1542 }
1543
1544 // Invoke the detailed logger and output something if it's enabled. 1456 // Invoke the detailed logger and output something if it's enabled.
1545 private void DetailLog(string msg, params Object[] args) 1457 private void DetailLog(string msg, params Object[] args)
1546 { 1458 {
1547 Scene.PhysicsLogging.Write(msg, args); 1459 PhysicsScene.PhysicsLogging.Write(msg, args);
1548 } 1460 }
1549} 1461}
1550} 1462}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 52997dd..dabced5 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -75,10 +75,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
75 75
76 public Dictionary<uint, BSPhysObject> PhysObjects = new Dictionary<uint, BSPhysObject>(); 76 public Dictionary<uint, BSPhysObject> PhysObjects = new Dictionary<uint, BSPhysObject>();
77 77
78 private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>(); 78 public HashSet<BSPhysObject> ObjectsWithCollisions = new HashSet<BSPhysObject>();
79 // Following is a kludge and can be removed when avatar animation updating is 79 public HashSet<BSPhysObject> ObjectsWithNoMoreCollisions = new HashSet<BSPhysObject>();
80 // moved to a better place. 80 // Keep track of all the avatars so we can send them a collision event
81 private HashSet<BSPhysObject> m_avatarsWithCollisions = new HashSet<BSPhysObject>(); 81 // every tick so OpenSim will update its animation.
82 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>();
82 83
83 // List of all the objects that have vehicle properties and should be called 84 // List of all the objects that have vehicle properties and should be called
84 // to update each physics step. 85 // to update each physics step.
@@ -379,7 +380,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
379 // TODO: Remove kludge someday. 380 // TODO: Remove kludge someday.
380 // We must generate a collision for avatars whether they collide or not. 381 // We must generate a collision for avatars whether they collide or not.
381 // This is required by OpenSim to update avatar animations, etc. 382 // This is required by OpenSim to update avatar animations, etc.
382 lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Add(actor); 383 lock (m_avatars) m_avatars.Add(actor);
383 384
384 return actor; 385 return actor;
385 } 386 }
@@ -397,7 +398,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
397 { 398 {
398 lock (PhysObjects) PhysObjects.Remove(actor.LocalID); 399 lock (PhysObjects) PhysObjects.Remove(actor.LocalID);
399 // Remove kludge someday 400 // Remove kludge someday
400 lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Remove(bsactor); 401 lock (m_avatars) m_avatars.Remove(bsactor);
401 } 402 }
402 catch (Exception e) 403 catch (Exception e)
403 { 404 {
@@ -464,6 +465,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
464 int collidersCount = 0; 465 int collidersCount = 0;
465 IntPtr collidersPtr; 466 IntPtr collidersPtr;
466 467
468 int beforeTime = 0;
469 int simTime = 0;
470
467 // prevent simulation until we've been initialized 471 // prevent simulation until we've been initialized
468 if (!m_initialized) return 5.0f; 472 if (!m_initialized) return 5.0f;
469 473
@@ -481,10 +485,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters
481 int numSubSteps = 0; 485 int numSubSteps = 0;
482 try 486 try
483 { 487 {
488 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
489
484 numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep, 490 numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
485 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 491 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
486 DetailLog("{0},Simulate,call, nTaints= {1}, substeps={2}, updates={3}, colliders={4}", 492
487 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); 493 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
494 DetailLog("{0},Simulate,call, nTaints={1}, simTime={2}, substeps={3}, updates={4}, colliders={5}",
495 DetailLogZero, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
488 } 496 }
489 catch (Exception e) 497 catch (Exception e)
490 { 498 {
@@ -502,12 +510,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
502 // Get a value for 'now' so all the collision and update routines don't have to get their own 510 // Get a value for 'now' so all the collision and update routines don't have to get their own
503 SimulationNowTime = Util.EnvironmentTickCount(); 511 SimulationNowTime = Util.EnvironmentTickCount();
504 512
505 // This is a kludge to get avatar movement updates.
506 // ODE sends collisions for avatars even if there are have been no collisions. This updates
507 // avatar animations and stuff.
508 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
509 m_objectsWithCollisions = new HashSet<BSPhysObject>(m_avatarsWithCollisions);
510
511 // If there were collisions, process them by sending the event to the prim. 513 // If there were collisions, process them by sending the event to the prim.
512 // Collisions must be processed before updates. 514 // Collisions must be processed before updates.
513 if (collidersCount > 0) 515 if (collidersCount > 0)
@@ -523,11 +525,31 @@ public class BSScene : PhysicsScene, IPhysicsParameters
523 } 525 }
524 } 526 }
525 527
528 // This is a kludge to get avatar movement updates.
529 // ODE sends collisions for avatars even if there are have been no collisions. This updates
530 // avatar animations and stuff.
531 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
532 foreach (BSPhysObject bsp in m_avatars)
533 bsp.SendCollisions();
534
526 // The above SendCollision's batch up the collisions on the objects. 535 // The above SendCollision's batch up the collisions on the objects.
527 // Now push the collisions into the simulator. 536 // Now push the collisions into the simulator.
528 foreach (BSPhysObject bsp in m_objectsWithCollisions) 537 // If the object is done colliding, it will add itself to the ObjectsWithNoMoreCollisions list.
529 bsp.SendCollisions(); 538 if (ObjectsWithCollisions.Count > 0)
530 m_objectsWithCollisions.Clear(); 539 {
540 foreach (BSPhysObject bsp in ObjectsWithCollisions)
541 if (!m_avatars.Contains(bsp)) // don't call avatars twice
542 bsp.SendCollisions();
543 }
544
545 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
546 // This can't be done by SendCollisions because it is inside an iteration of ObjectWithCollisions.
547 if (ObjectsWithNoMoreCollisions.Count > 0)
548 {
549 foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
550 ObjectsWithCollisions.Remove(po);
551 ObjectsWithNoMoreCollisions.Clear();
552 }
531 553
532 // If any of the objects had updated properties, tell the object it has been changed by the physics engine 554 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
533 if (updatedEntityCount > 0) 555 if (updatedEntityCount > 0)
@@ -555,7 +577,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
555 // The physics engine returns the number of milliseconds it simulated this call. 577 // The physics engine returns the number of milliseconds it simulated this call.
556 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. 578 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
557 // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS. 579 // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS.
558 return numSubSteps * m_fixedTimeStep; 580 return numSubSteps * m_fixedTimeStep * 1000;
559 } 581 }
560 582
561 // Something has collided 583 // Something has collided
@@ -583,7 +605,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
583 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) 605 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
584 { 606 {
585 // If a collision was posted, remember to send it to the simulator 607 // If a collision was posted, remember to send it to the simulator
586 m_objectsWithCollisions.Add(collider); 608 ObjectsWithCollisions.Add(collider);
587 } 609 }
588 610
589 return; 611 return;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 9221cdb..4d2d962 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -249,7 +249,16 @@ public enum CollisionFlags : uint
249 BS_PHYSICAL_OBJECT = 1 << 13, 249 BS_PHYSICAL_OBJECT = 1 << 13,
250 BS_TERRAIN_OBJECT = 1 << 14, 250 BS_TERRAIN_OBJECT = 1 << 14,
251 BS_NONE = 0, 251 BS_NONE = 0,
252 BS_ALL = 0xFFFFFFFF 252 BS_ALL = 0xFFFFFFFF,
253
254 // These are the collision flags switched depending on physical state.
255 // The other flags are used for other things and should not be fooled with.
256 BS_ACTIVE = CF_STATIC_OBJECT
257 | CF_KINEMATIC_OBJECT
258 | CF_NO_CONTACT_RESPONSE
259 | BS_VOLUME_DETECT_OBJECT
260 | BS_PHANTOM_OBJECT
261 | BS_PHYSICAL_OBJECT,
253}; 262};
254 263
255// Values for collisions groups and masks 264// Values for collisions groups and masks
@@ -270,52 +279,6 @@ public enum CollisionFilterGroups : uint
270 SolidFilter = 1 << 13, 279 SolidFilter = 1 << 13,
271}; 280};
272 281
273 // For each type, we first clear and then set the collision flags
274public enum ClearCollisionFlag : uint
275{
276 Terrain = CollisionFlags.BS_ALL,
277 Phantom = CollisionFlags.BS_ALL,
278 VolumeDetect = CollisionFlags.BS_ALL,
279 PhysicalObject = CollisionFlags.BS_ALL,
280 StaticObject = CollisionFlags.BS_ALL
281}
282
283public enum SetCollisionFlag : uint
284{
285 Terrain = CollisionFlags.CF_STATIC_OBJECT
286 | CollisionFlags.BS_TERRAIN_OBJECT,
287 Phantom = CollisionFlags.CF_STATIC_OBJECT
288 | CollisionFlags.BS_PHANTOM_OBJECT
289 | CollisionFlags.CF_NO_CONTACT_RESPONSE,
290 VolumeDetect = CollisionFlags.CF_STATIC_OBJECT
291 | CollisionFlags.BS_VOLUME_DETECT_OBJECT
292 | CollisionFlags.CF_NO_CONTACT_RESPONSE,
293 PhysicalObject = CollisionFlags.BS_PHYSICAL_OBJECT,
294 StaticObject = CollisionFlags.CF_STATIC_OBJECT,
295}
296
297// Collision filters used for different types of objects
298public enum SetCollisionFilter : uint
299{
300 Terrain = CollisionFilterGroups.AllFilter,
301 Phantom = CollisionFilterGroups.GroundPlaneFilter
302 | CollisionFilterGroups.TerrainFilter,
303 VolumeDetect = CollisionFilterGroups.AllFilter,
304 PhysicalObject = CollisionFilterGroups.AllFilter,
305 StaticObject = CollisionFilterGroups.AllFilter,
306}
307
308// Collision masks used for different types of objects
309public enum SetCollisionMask : uint
310{
311 Terrain = CollisionFilterGroups.AllFilter,
312 Phantom = CollisionFilterGroups.GroundPlaneFilter
313 | CollisionFilterGroups.TerrainFilter,
314 VolumeDetect = CollisionFilterGroups.AllFilter,
315 PhysicalObject = CollisionFilterGroups.AllFilter,
316 StaticObject = CollisionFilterGroups.AllFilter
317}
318
319// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 282// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
320// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. 283// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2.
321public enum ConstraintParams : int 284public enum ConstraintParams : int