aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin
diff options
context:
space:
mode:
authorRobert Adams2012-09-18 08:39:52 -0700
committerRobert Adams2012-09-27 22:01:11 -0700
commitee7cda261cbbc9dcd558c35eabc070cc0bf45644 (patch)
treef30f9c9baf15ef6988983e53bf3141749eab75f9 /OpenSim/Region/Physics/BulletSPlugin
parentComment out unused RestPlugins text in OpenSimDefaults.ini (diff)
downloadopensim-SC_OLD-ee7cda261cbbc9dcd558c35eabc070cc0bf45644.zip
opensim-SC_OLD-ee7cda261cbbc9dcd558c35eabc070cc0bf45644.tar.gz
opensim-SC_OLD-ee7cda261cbbc9dcd558c35eabc070cc0bf45644.tar.bz2
opensim-SC_OLD-ee7cda261cbbc9dcd558c35eabc070cc0bf45644.tar.xz
BulletSim: move a bunch of common logic out of BSPrim and BSCharacter
and into the parent class BSPhysObject. Rework collision logic to enable extra collision after done colliding. Rename 'Scene' to 'PhysicsScene' to differentiate it from the simulator 'Scene'.
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin')
-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