aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs614
1 files changed, 317 insertions, 297 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 130f1ca..a4ab702 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -42,6 +42,8 @@ public sealed class BSPrim : PhysicsActor
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 private static readonly string LogHeader = "[BULLETS PRIM]"; 43 private static readonly string LogHeader = "[BULLETS PRIM]";
44 44
45 private void DebugLog(string mm, params Object[] xx) { if (_scene.shouldDebugLog) m_log.DebugFormat(mm, xx); }
46
45 private IMesh _mesh; 47 private IMesh _mesh;
46 private PrimitiveBaseShape _pbs; 48 private PrimitiveBaseShape _pbs;
47 private ShapeData.PhysicsShapeType _shapeType; 49 private ShapeData.PhysicsShapeType _shapeType;
@@ -50,6 +52,7 @@ public sealed class BSPrim : PhysicsActor
50 private List<ConvexResult> _hulls; 52 private List<ConvexResult> _hulls;
51 53
52 private BSScene _scene; 54 private BSScene _scene;
55 public BSScene Scene { get { return _scene; } }
53 private String _avName; 56 private String _avName;
54 private uint _localID = 0; 57 private uint _localID = 0;
55 58
@@ -63,7 +66,7 @@ public sealed class BSPrim : PhysicsActor
63 private bool _isSelected; 66 private bool _isSelected;
64 private bool _isVolumeDetect; 67 private bool _isVolumeDetect;
65 private OMV.Vector3 _position; 68 private OMV.Vector3 _position;
66 private float _mass; 69 private float _mass; // the mass of this object
67 private float _density; 70 private float _density;
68 private OMV.Vector3 _force; 71 private OMV.Vector3 _force;
69 private OMV.Vector3 _velocity; 72 private OMV.Vector3 _velocity;
@@ -86,14 +89,25 @@ public sealed class BSPrim : PhysicsActor
86 private bool _kinematic; 89 private bool _kinematic;
87 private float _buoyancy; 90 private float _buoyancy;
88 91
89 private List<BSPrim> _childrenPrims; 92 // Membership in a linkset is controlled by this class.
90 private BSPrim _parentPrim; 93 private BSLinkset _linkset;
94 public BSLinkset Linkset
95 {
96 get { return _linkset; }
97 set { _linkset = value; }
98 }
91 99
92 private int _subscribedEventsMs = 0; 100 private int _subscribedEventsMs = 0;
93 private int _nextCollisionOkTime = 0; 101 private int _nextCollisionOkTime = 0;
94 long _collidingStep; 102 long _collidingStep;
95 long _collidingGroundStep; 103 long _collidingGroundStep;
96 104
105 private BulletBody m_body;
106 public BulletBody Body {
107 get { return m_body; }
108 set { m_body = value; }
109 }
110
97 private BSDynamics _vehicle; 111 private BSDynamics _vehicle;
98 112
99 private OMV.Vector3 _PIDTarget; 113 private OMV.Vector3 _PIDTarget;
@@ -127,17 +141,18 @@ public sealed class BSPrim : PhysicsActor
127 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
128 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material
129 _restitution = _scene.Params.defaultRestitution; 143 _restitution = _scene.Params.defaultRestitution;
130 _parentPrim = null; // not a child or a parent 144 _linkset = new BSLinkset(_scene, this); // a linkset of one
131 _vehicle = new BSDynamics(this); // add vehicleness 145 _vehicle = new BSDynamics(this); // add vehicleness
132 _childrenPrims = new List<BSPrim>(); 146 _mass = CalculateMass();
133 if (_isPhysical)
134 _mass = CalculateMass();
135 else
136 _mass = 0f;
137 // do the actual object creation at taint time 147 // do the actual object creation at taint time
138 _scene.TaintedObject(delegate() 148 _scene.TaintedObject(delegate()
139 { 149 {
140 RecreateGeomAndObject(); 150 RecreateGeomAndObject();
151
152 // Get the pointer to the physical body for this object.
153 // At the moment, we're still letting BulletSim manage the creation and destruction
154 // of the object. Someday we'll move that into the C# code.
155 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
141 }); 156 });
142 } 157 }
143 158
@@ -145,13 +160,19 @@ public sealed class BSPrim : PhysicsActor
145 public void Destroy() 160 public void Destroy()
146 { 161 {
147 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 162 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
163 // DetailLog("{0},Destroy", LocalID);
164
148 // Undo any vehicle properties 165 // Undo any vehicle properties
149 _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); 166 _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE);
150 _scene.RemoveVehiclePrim(this); // just to make sure 167 _scene.RemoveVehiclePrim(this); // just to make sure
168
151 _scene.TaintedObject(delegate() 169 _scene.TaintedObject(delegate()
152 { 170 {
171 // Undo any links between me and any other object
172 _linkset = _linkset.RemoveMeFromLinkset(this);
173
153 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 174 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
154 BulletSimAPI.DestroyObject(_scene.WorldID, _localID); 175 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
155 }); 176 });
156 } 177 }
157 178
@@ -164,8 +185,9 @@ public sealed class BSPrim : PhysicsActor
164 _size = value; 185 _size = value;
165 _scene.TaintedObject(delegate() 186 _scene.TaintedObject(delegate()
166 { 187 {
167 if (_isPhysical) _mass = CalculateMass(); // changing size changes the mass 188 _mass = CalculateMass(); // changing size changes the mass
168 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, _mass, _isPhysical); 189 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
190 DetailLog("{0}: setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical);
169 RecreateGeomAndObject(); 191 RecreateGeomAndObject();
170 }); 192 });
171 } 193 }
@@ -175,7 +197,7 @@ public sealed class BSPrim : PhysicsActor
175 _pbs = value; 197 _pbs = value;
176 _scene.TaintedObject(delegate() 198 _scene.TaintedObject(delegate()
177 { 199 {
178 if (_isPhysical) _mass = CalculateMass(); // changing the shape changes the mass 200 _mass = CalculateMass(); // changing the shape changes the mass
179 RecreateGeomAndObject(); 201 RecreateGeomAndObject();
180 }); 202 });
181 } 203 }
@@ -202,33 +224,10 @@ public sealed class BSPrim : PhysicsActor
202 // link me to the specified parent 224 // link me to the specified parent
203 public override void link(PhysicsActor obj) { 225 public override void link(PhysicsActor obj) {
204 BSPrim parent = obj as BSPrim; 226 BSPrim parent = obj as BSPrim;
205 // m_log.DebugFormat("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); 227 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID);
206 // TODO: decide if this parent checking needs to happen at taint time 228 DetailLog("{0},link,parent={1}", LocalID, obj.LocalID);
207 if (_parentPrim == null) 229
208 { 230 _linkset = _linkset.AddMeToLinkset(this, parent);
209 if (parent != null)
210 {
211 // I don't have a parent so I am joining a linkset
212 parent.AddChildToLinkset(this);
213 }
214 }
215 else
216 {
217 // I already have a parent, is parenting changing?
218 if (parent != _parentPrim)
219 {
220 if (parent == null)
221 {
222 // we are being removed from a linkset
223 _parentPrim.RemoveChildFromLinkset(this);
224 }
225 else
226 {
227 // asking to reparent a prim should not happen
228 m_log.ErrorFormat("{0}: Reparenting a prim. ", LogHeader);
229 }
230 }
231 }
232 return; 231 return;
233 } 232 }
234 233
@@ -236,101 +235,92 @@ public sealed class BSPrim : PhysicsActor
236 public override void delink() { 235 public override void delink() {
237 // TODO: decide if this parent checking needs to happen at taint time 236 // TODO: decide if this parent checking needs to happen at taint time
238 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 237 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
239 // m_log.DebugFormat("{0}: delink {1}/{2}", LogHeader, _avName, _localID); 238 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
240 if (_parentPrim != null) 239 _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString());
241 { 240 DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString());
242 _parentPrim.RemoveChildFromLinkset(this);
243 }
244 return;
245 }
246
247 // I am the root of a linkset and a new child is being added
248 public void AddChildToLinkset(BSPrim pchild)
249 {
250 BSPrim child = pchild;
251 _scene.TaintedObject(delegate()
252 {
253 if (!_childrenPrims.Contains(child))
254 {
255 _childrenPrims.Add(child);
256 child.ParentPrim = this; // the child has gained a parent
257 RecreateGeomAndObject(); // rebuild my shape with the new child added
258 }
259 });
260 return;
261 }
262
263 // I am the root of a linkset and one of my children is being removed.
264 // Safe to call even if the child is not really in my linkset.
265 public void RemoveChildFromLinkset(BSPrim pchild)
266 {
267 BSPrim child = pchild;
268 _scene.TaintedObject(delegate()
269 {
270 if (_childrenPrims.Contains(child))
271 {
272 BulletSimAPI.RemoveConstraint(_scene.WorldID, child.LocalID, this.LocalID);
273 _childrenPrims.Remove(child);
274 child.ParentPrim = null; // the child has lost its parent
275 RecreateGeomAndObject(); // rebuild my shape with the child removed
276 }
277 else
278 {
279 m_log.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset");
280 }
281 });
282 return;
283 }
284
285 public BSPrim ParentPrim
286 {
287 set { _parentPrim = value; }
288 }
289 241
290 // return true if we are the root of a linkset (there are children to manage) 242 _linkset.RemoveMeFromLinkset(this);
291 public bool IsRootOfLinkset 243 return;
292 {
293 get { return (_parentPrim == null && _childrenPrims.Count != 0); }
294 } 244 }
295 245
296 // Set motion values to zero. 246 // Set motion values to zero.
297 // Do it to the properties so the values get set in the physics engine. 247 // Do it to the properties so the values get set in the physics engine.
298 // Push the setting of the values to the viewer. 248 // Push the setting of the values to the viewer.
299 private void ZeroMotion() 249 // Called at taint time!
250 public void ZeroMotion()
300 { 251 {
301 Velocity = OMV.Vector3.Zero; 252 _velocity = OMV.Vector3.Zero;
302 _acceleration = OMV.Vector3.Zero; 253 _acceleration = OMV.Vector3.Zero;
303 RotationalVelocity = OMV.Vector3.Zero; 254 _rotationalVelocity = OMV.Vector3.Zero;
304 base.RequestPhysicsterseUpdate(); 255
256 // Zero some other properties directly into the physics engine
257 BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero);
258 BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero);
259 BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
260 BulletSimAPI.ClearForces2(Body.Ptr);
305 } 261 }
306 262
307 public override void LockAngularMotion(OMV.Vector3 axis) { return; } 263 public override void LockAngularMotion(OMV.Vector3 axis)
264 {
265 DetailLog("{0},LockAngularMotion,call,axis={1}", LocalID, axis);
266 return;
267 }
308 268
309 public override OMV.Vector3 Position { 269 public override OMV.Vector3 Position {
310 get { 270 get {
311 // don't do the following GetObjectPosition because this function is called a zillion times 271 if (!_linkset.IsRoot(this))
272 // child prims move around based on their parent. Need to get the latest location
273 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
274
275 // don't do the GetObjectPosition for root elements because this function is called a zillion times
312 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 276 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
313 return _position; 277 return _position;
314 } 278 }
315 set { 279 set {
316 _position = value; 280 _position = value;
281 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
317 _scene.TaintedObject(delegate() 282 _scene.TaintedObject(delegate()
318 { 283 {
284 DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
319 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 285 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
320 // m_log.DebugFormat("{0}: setPosition: id={1}, position={2}", LogHeader, _localID, _position);
321 }); 286 });
322 } 287 }
323 } 288 }
324 public override float Mass { 289
325 get { return _mass; } 290 // Return the effective mass of the object.
291 // If there are multiple items in the linkset, add them together for the root
292 public override float Mass
293 {
294 get
295 {
296 return _linkset.LinksetMass;
297 }
298 }
299
300 // used when we only want this prim's mass and not the linkset thing
301 public float MassRaw { get { return _mass; } }
302
303 // Is this used?
304 public override OMV.Vector3 CenterOfMass
305 {
306 get { return _linkset.CenterOfMass; }
307 }
308
309 // Is this used?
310 public override OMV.Vector3 GeometricCenter
311 {
312 get { return _linkset.GeometricCenter; }
326 } 313 }
314
327 public override OMV.Vector3 Force { 315 public override OMV.Vector3 Force {
328 get { return _force; } 316 get { return _force; }
329 set { 317 set {
330 _force = value; 318 _force = value;
331 _scene.TaintedObject(delegate() 319 _scene.TaintedObject(delegate()
332 { 320 {
333 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 321 DetailLog("{0},SetForce,taint,force={1}", LocalID, _force);
322 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
323 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
334 }); 324 });
335 } 325 }
336 } 326 }
@@ -341,15 +331,22 @@ public sealed class BSPrim : PhysicsActor
341 } 331 }
342 set { 332 set {
343 Vehicle type = (Vehicle)value; 333 Vehicle type = (Vehicle)value;
344 _vehicle.ProcessTypeChange(type);
345 _scene.TaintedObject(delegate() 334 _scene.TaintedObject(delegate()
346 { 335 {
336 DetailLog("{0},SetVehicleType,taint,type={1}", LocalID, type);
337 _vehicle.ProcessTypeChange(type);
347 if (type == Vehicle.TYPE_NONE) 338 if (type == Vehicle.TYPE_NONE)
348 { 339 {
349 _scene.RemoveVehiclePrim(this); 340 _scene.RemoveVehiclePrim(this);
350 } 341 }
351 else 342 else
352 { 343 {
344 _scene.TaintedObject(delegate()
345 {
346 // Tell the physics engine to clear state
347 BulletSimAPI.ClearForces2(this.Body.Ptr);
348 });
349
353 // make it so the scene will call us each tick to do vehicle things 350 // make it so the scene will call us each tick to do vehicle things
354 _scene.AddVehiclePrim(this); 351 _scene.AddVehiclePrim(this);
355 } 352 }
@@ -359,47 +356,59 @@ public sealed class BSPrim : PhysicsActor
359 } 356 }
360 public override void VehicleFloatParam(int param, float value) 357 public override void VehicleFloatParam(int param, float value)
361 { 358 {
362 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); 359 _scene.TaintedObject(delegate()
360 {
361 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
362 });
363 } 363 }
364 public override void VehicleVectorParam(int param, OMV.Vector3 value) 364 public override void VehicleVectorParam(int param, OMV.Vector3 value)
365 { 365 {
366 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); 366 _scene.TaintedObject(delegate()
367 {
368 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
369 });
367 } 370 }
368 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 371 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
369 { 372 {
370 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 373 _scene.TaintedObject(delegate()
374 {
375 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
376 });
371 } 377 }
372 public override void VehicleFlags(int param, bool remove) 378 public override void VehicleFlags(int param, bool remove)
373 { 379 {
374 _vehicle.ProcessVehicleFlags(param, remove); 380 _scene.TaintedObject(delegate()
381 {
382 _vehicle.ProcessVehicleFlags(param, remove);
383 });
375 } 384 }
376 // Called each simulation step to advance vehicle characteristics 385
386 // Called each simulation step to advance vehicle characteristics.
387 // Called from Scene when doing simulation step so we're in taint processing time.
377 public void StepVehicle(float timeStep) 388 public void StepVehicle(float timeStep)
378 { 389 {
379 _vehicle.Step(timeStep, _scene); 390 if (IsPhysical)
391 _vehicle.Step(timeStep);
380 } 392 }
381 393
382 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 394 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
383 public override void SetVolumeDetect(int param) { 395 public override void SetVolumeDetect(int param) {
384 bool newValue = (param != 0); 396 bool newValue = (param != 0);
385 if (_isVolumeDetect != newValue) 397 _isVolumeDetect = newValue;
398 _scene.TaintedObject(delegate()
386 { 399 {
387 _isVolumeDetect = newValue; 400 SetObjectDynamic();
388 _scene.TaintedObject(delegate() 401 });
389 {
390 SetObjectDynamic();
391 });
392 }
393 return; 402 return;
394 } 403 }
395 404
396 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
397 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
398 public override OMV.Vector3 Velocity { 405 public override OMV.Vector3 Velocity {
399 get { return _velocity; } 406 get { return _velocity; }
400 set { _velocity = value; 407 set {
408 _velocity = value;
401 _scene.TaintedObject(delegate() 409 _scene.TaintedObject(delegate()
402 { 410 {
411 DetailLog("{0},SetVelocity,taint,vel={1}", LocalID, _velocity);
403 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 412 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
404 }); 413 });
405 } 414 }
@@ -407,6 +416,7 @@ public sealed class BSPrim : PhysicsActor
407 public override OMV.Vector3 Torque { 416 public override OMV.Vector3 Torque {
408 get { return _torque; } 417 get { return _torque; }
409 set { _torque = value; 418 set { _torque = value;
419 DetailLog("{0},SetTorque,call,torque={1}", LocalID, _torque);
410 } 420 }
411 } 421 }
412 public override float CollisionScore { 422 public override float CollisionScore {
@@ -419,13 +429,21 @@ public sealed class BSPrim : PhysicsActor
419 set { _acceleration = value; } 429 set { _acceleration = value; }
420 } 430 }
421 public override OMV.Quaternion Orientation { 431 public override OMV.Quaternion Orientation {
422 get { return _orientation; } 432 get {
433 if (!_linkset.IsRoot(this))
434 {
435 // Children move around because tied to parent. Get a fresh value.
436 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
437 }
438 return _orientation;
439 }
423 set { 440 set {
424 _orientation = value; 441 _orientation = value;
425 // m_log.DebugFormat("{0}: set orientation: id={1}, ori={2}", LogHeader, LocalID, _orientation); 442 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
426 _scene.TaintedObject(delegate() 443 _scene.TaintedObject(delegate()
427 { 444 {
428 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 445 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
446 DetailLog("{0},SetOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
429 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 447 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
430 }); 448 });
431 } 449 }
@@ -458,25 +476,24 @@ public sealed class BSPrim : PhysicsActor
458 get { return !IsPhantom && !_isVolumeDetect; } 476 get { return !IsPhantom && !_isVolumeDetect; }
459 } 477 }
460 478
461 // make gravity work if the object is physical and not selected 479 // Make gravity work if the object is physical and not selected
462 // no locking here because only called when it is safe 480 // No locking here because only called when it is safe
481 // Only called at taint time so it is save to call into Bullet.
463 private void SetObjectDynamic() 482 private void SetObjectDynamic()
464 { 483 {
465 // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); 484 // RA: remove this for the moment.
466 // non-physical things work best with a mass of zero 485 // The problem is that dynamic objects are hulls so if we are becoming physical
467 if (IsStatic) 486 // the shape has to be checked and possibly built.
468 { 487 // Maybe a VerifyCorrectPhysicalShape() routine?
469 _mass = 0f; 488 // RecreateGeomAndObject();
470 }
471 else
472 {
473 _mass = CalculateMass();
474 // If it's dynamic, make sure the hull has been created for it
475 // This shouldn't do much work if the object had previously been built
476 RecreateGeomAndObject();
477 489
478 } 490 float mass = _mass;
479 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), _mass); 491 // Bullet wants static objects have a mass of zero
492 if (IsStatic)
493 mass = 0f;
494
495 DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, mass);
496 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
480 } 497 }
481 498
482 // prims don't fly 499 // prims don't fly
@@ -516,11 +533,24 @@ public sealed class BSPrim : PhysicsActor
516 set { _floatOnWater = value; } 533 set { _floatOnWater = value; }
517 } 534 }
518 public override OMV.Vector3 RotationalVelocity { 535 public override OMV.Vector3 RotationalVelocity {
519 get { return _rotationalVelocity; } 536 get {
520 set { _rotationalVelocity = value; 537 /*
538 OMV.Vector3 pv = OMV.Vector3.Zero;
539 // if close to zero, report zero
540 // This is copied from ODE but I'm not sure why it returns zero but doesn't
541 // zero the property in the physics engine.
542 if (_rotationalVelocity.ApproxEquals(pv, 0.2f))
543 return pv;
544 */
545
546 return _rotationalVelocity;
547 }
548 set {
549 _rotationalVelocity = value;
521 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 550 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
522 _scene.TaintedObject(delegate() 551 _scene.TaintedObject(delegate()
523 { 552 {
553 DetailLog("{0},SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
524 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 554 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
525 }); 555 });
526 } 556 }
@@ -533,11 +563,13 @@ public sealed class BSPrim : PhysicsActor
533 } 563 }
534 public override float Buoyancy { 564 public override float Buoyancy {
535 get { return _buoyancy; } 565 get { return _buoyancy; }
536 set { _buoyancy = value; 566 set {
537 _scene.TaintedObject(delegate() 567 _buoyancy = value;
538 { 568 _scene.TaintedObject(delegate()
539 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 569 {
540 }); 570 DetailLog("{0},SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
571 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
572 });
541 } 573 }
542 } 574 }
543 575
@@ -573,27 +605,45 @@ public sealed class BSPrim : PhysicsActor
573 public override float APIDStrength { set { return; } } 605 public override float APIDStrength { set { return; } }
574 public override float APIDDamping { set { return; } } 606 public override float APIDDamping { set { return; } }
575 607
608 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
576 public override void AddForce(OMV.Vector3 force, bool pushforce) { 609 public override void AddForce(OMV.Vector3 force, bool pushforce) {
577 if (force.IsFinite()) 610 if (force.IsFinite())
578 { 611 {
579 _force.X += force.X; 612 // _force += force;
580 _force.Y += force.Y; 613 lock (m_accumulatedForces)
581 _force.Z += force.Z; 614 m_accumulatedForces.Add(new OMV.Vector3(force));
582 } 615 }
583 else 616 else
584 { 617 {
585 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 618 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
619 return;
586 } 620 }
587 _scene.TaintedObject(delegate() 621 _scene.TaintedObject(delegate()
588 { 622 {
589 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 623 lock (m_accumulatedForces)
624 {
625 if (m_accumulatedForces.Count > 0)
626 {
627 OMV.Vector3 fSum = OMV.Vector3.Zero;
628 foreach (OMV.Vector3 v in m_accumulatedForces)
629 {
630 fSum += v;
631 }
632 m_accumulatedForces.Clear();
633
634 DetailLog("{0},SetObjectForce,taint,force={1}", LocalID, fSum);
635 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, fSum);
636 }
637 }
590 }); 638 });
591 } 639 }
592 640
593 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 641 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
642 DetailLog("{0},AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
594 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 643 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
595 } 644 }
596 public override void SetMomentum(OMV.Vector3 momentum) { 645 public override void SetMomentum(OMV.Vector3 momentum) {
646 DetailLog("{0},SetMomentum,call,mom={1}", LocalID, momentum);
597 } 647 }
598 public override void SubscribeEvents(int ms) { 648 public override void SubscribeEvents(int ms) {
599 _subscribedEventsMs = ms; 649 _subscribedEventsMs = ms;
@@ -885,6 +935,9 @@ public sealed class BSPrim : PhysicsActor
885 935
886 returnMass = _density * volume; 936 returnMass = _density * volume;
887 937
938 /*
939 * This change means each object keeps its own mass and the Mass property
940 * will return the sum if we're part of a linkset.
888 if (IsRootOfLinkset) 941 if (IsRootOfLinkset)
889 { 942 {
890 foreach (BSPrim prim in _childrenPrims) 943 foreach (BSPrim prim in _childrenPrims)
@@ -892,6 +945,7 @@ public sealed class BSPrim : PhysicsActor
892 returnMass += prim.CalculateMass(); 945 returnMass += prim.CalculateMass();
893 } 946 }
894 } 947 }
948 */
895 949
896 if (returnMass <= 0) 950 if (returnMass <= 0)
897 returnMass = 0.0001f; 951 returnMass = 0.0001f;
@@ -907,9 +961,11 @@ public sealed class BSPrim : PhysicsActor
907 // The objects needs a hull if it's physical otherwise a mesh is enough 961 // The objects needs a hull if it's physical otherwise a mesh is enough
908 // No locking here because this is done when we know physics is not simulating 962 // No locking here because this is done when we know physics is not simulating
909 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used 963 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used
910 private void CreateGeom(bool forceRebuild) 964 // Returns 'true' if the geometry was rebuilt
965 private bool CreateGeom(bool forceRebuild)
911 { 966 {
912 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. 967 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
968 bool ret = false;
913 if (!_scene.NeedsMeshing(_pbs)) 969 if (!_scene.NeedsMeshing(_pbs))
914 { 970 {
915 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 971 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
@@ -917,16 +973,28 @@ public sealed class BSPrim : PhysicsActor
917 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 973 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
918 { 974 {
919 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 975 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
920 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 976 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
921 // Bullet native objects are scaled by the Bullet engine so pass the size in 977 {
922 _scale = _size; 978 DetailLog("{0},CreateGeom,sphere", LocalID);
979 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
980 // Bullet native objects are scaled by the Bullet engine so pass the size in
981 _scale = _size;
982 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
983 ret = true;
984 }
923 } 985 }
924 } 986 }
925 else 987 else
926 { 988 {
927 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size); 989 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
928 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 990 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
929 _scale = _size; 991 {
992 DetailLog("{0},CreateGeom,box", LocalID);
993 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
994 _scale = _size;
995 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
996 ret = true;
997 }
930 } 998 }
931 } 999 }
932 else 1000 else
@@ -938,6 +1006,7 @@ public sealed class BSPrim : PhysicsActor
938 // physical objects require a hull for interaction. 1006 // physical objects require a hull for interaction.
939 // This will create the mesh if it doesn't already exist 1007 // This will create the mesh if it doesn't already exist
940 CreateGeomHull(); 1008 CreateGeomHull();
1009 ret = true;
941 } 1010 }
942 } 1011 }
943 else 1012 else
@@ -946,9 +1015,11 @@ public sealed class BSPrim : PhysicsActor
946 { 1015 {
947 // Static (non-physical) objects only need a mesh for bumping into 1016 // Static (non-physical) objects only need a mesh for bumping into
948 CreateGeomMesh(); 1017 CreateGeomMesh();
1018 ret = true;
949 } 1019 }
950 } 1020 }
951 } 1021 }
1022 return ret;
952 } 1023 }
953 1024
954 // No locking here because this is done when we know physics is not simulating 1025 // No locking here because this is done when we know physics is not simulating
@@ -961,10 +1032,12 @@ public sealed class BSPrim : PhysicsActor
961 // if this new shape is the same as last time, don't recreate the mesh 1032 // if this new shape is the same as last time, don't recreate the mesh
962 if (_meshKey == newMeshKey) return; 1033 if (_meshKey == newMeshKey) return;
963 1034
1035 DetailLog("{0},CreateGeomMesh,create,key={1}", LocalID, _meshKey);
964 // Since we're recreating new, get rid of any previously generated shape 1036 // Since we're recreating new, get rid of any previously generated shape
965 if (_meshKey != 0) 1037 if (_meshKey != 0)
966 { 1038 {
967 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); 1039 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1040 DetailLog("{0},CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
968 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1041 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
969 _mesh = null; 1042 _mesh = null;
970 _meshKey = 0; 1043 _meshKey = 0;
@@ -981,7 +1054,6 @@ public sealed class BSPrim : PhysicsActor
981 int vi = 0; 1054 int vi = 0;
982 foreach (OMV.Vector3 vv in vertices) 1055 foreach (OMV.Vector3 vv in vertices)
983 { 1056 {
984 // m_log.DebugFormat("{0}: {1}: <{2:0.00}, {3:0.00}, {4:0.00}>", LogHeader, vi / 3, vv.X, vv.Y, vv.Z);
985 verticesAsFloats[vi++] = vv.X; 1057 verticesAsFloats[vi++] = vv.X;
986 verticesAsFloats[vi++] = vv.Y; 1058 verticesAsFloats[vi++] = vv.Y;
987 verticesAsFloats[vi++] = vv.Z; 1059 verticesAsFloats[vi++] = vv.Z;
@@ -995,6 +1067,7 @@ public sealed class BSPrim : PhysicsActor
995 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1067 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
996 // meshes are already scaled by the meshmerizer 1068 // meshes are already scaled by the meshmerizer
997 _scale = new OMV.Vector3(1f, 1f, 1f); 1069 _scale = new OMV.Vector3(1f, 1f, 1f);
1070 DetailLog("{0},CreateGeomMesh,done", LocalID);
998 return; 1071 return;
999 } 1072 }
1000 1073
@@ -1008,13 +1081,17 @@ public sealed class BSPrim : PhysicsActor
1008 // if the hull hasn't changed, don't rebuild it 1081 // if the hull hasn't changed, don't rebuild it
1009 if (newHullKey == _hullKey) return; 1082 if (newHullKey == _hullKey) return;
1010 1083
1084 DetailLog("{0},CreateGeomHull,create,key={1}", LocalID, _meshKey);
1085
1011 // Since we're recreating new, get rid of any previously generated shape 1086 // Since we're recreating new, get rid of any previously generated shape
1012 if (_hullKey != 0) 1087 if (_hullKey != 0)
1013 { 1088 {
1014 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); 1089 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1090 DetailLog("{0},CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey);
1015 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1091 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1016 _hullKey = 0; 1092 _hullKey = 0;
1017 _hulls.Clear(); 1093 _hulls.Clear();
1094 DetailLog("{0},CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey);
1018 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1095 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1019 _mesh = null; // the mesh cannot match either 1096 _mesh = null; // the mesh cannot match either
1020 _meshKey = 0; 1097 _meshKey = 0;
@@ -1111,6 +1188,7 @@ public sealed class BSPrim : PhysicsActor
1111 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1188 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1112 // meshes are already scaled by the meshmerizer 1189 // meshes are already scaled by the meshmerizer
1113 _scale = new OMV.Vector3(1f, 1f, 1f); 1190 _scale = new OMV.Vector3(1f, 1f, 1f);
1191 DetailLog("{0},CreateGeomHull,done", LocalID);
1114 return; 1192 return;
1115 } 1193 }
1116 1194
@@ -1124,47 +1202,21 @@ public sealed class BSPrim : PhysicsActor
1124 1202
1125 // Create an object in Bullet if it has not already been created 1203 // Create an object in Bullet if it has not already been created
1126 // No locking here because this is done when the physics engine is not simulating 1204 // No locking here because this is done when the physics engine is not simulating
1127 private void CreateObject() 1205 // Returns 'true' if an object was actually created.
1206 private bool CreateObject()
1128 { 1207 {
1129 if (IsRootOfLinkset) 1208 // this routine is called when objects are rebuilt.
1130 {
1131 // Create a linkset around this object
1132 // CreateLinksetWithCompoundHull();
1133 CreateLinksetWithConstraints();
1134 }
1135 else
1136 {
1137 // simple object
1138 // the mesh or hull must have already been created in Bullet
1139 ShapeData shape;
1140 FillShapeInfo(out shape);
1141 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1142 BulletSimAPI.CreateObject(_scene.WorldID, shape);
1143 }
1144 }
1145 1209
1146 // Create a linkset by creating a compound hull at the root prim that consists of all 1210 // the mesh or hull must have already been created in Bullet
1147 // the children. 1211 ShapeData shape;
1148 // NOTE: This does not allow proper collisions with the children prims so it is not a workable solution 1212 FillShapeInfo(out shape);
1149 void CreateLinksetWithCompoundHull() 1213 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1150 { 1214 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1151 // If I am the root prim of a linkset, replace my physical shape with all the 1215
1152 // pieces of the children. 1216 // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
1153 // All of the children should have called CreateGeom so they have a hull 1217 m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID);
1154 // in the physics engine already. Here we pull together all of those hulls 1218
1155 // into one shape. 1219 return ret;
1156 int totalPrimsInLinkset = _childrenPrims.Count + 1;
1157 // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, totalPrimsInLinkset);
1158 ShapeData[] shapes = new ShapeData[totalPrimsInLinkset];
1159 FillShapeInfo(out shapes[0]);
1160 int ii = 1;
1161 foreach (BSPrim prim in _childrenPrims)
1162 {
1163 // m_log.DebugFormat("{0}: CreateLinkset: adding prim {1}", LogHeader, prim.LocalID);
1164 prim.FillShapeInfo(out shapes[ii]);
1165 ii++;
1166 }
1167 BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes);
1168 } 1220 }
1169 1221
1170 // Copy prim's info into the BulletSim shape description structure 1222 // Copy prim's info into the BulletSim shape description structure
@@ -1186,44 +1238,6 @@ public sealed class BSPrim : PhysicsActor
1186 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1238 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1187 } 1239 }
1188 1240
1189 // Create the linkset by putting constraints between the objects of the set so they cannot move
1190 // relative to each other.
1191 // TODO: make this more effeicient: a large linkset gets rebuilt over and over and prims are added
1192 void CreateLinksetWithConstraints()
1193 {
1194 // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
1195
1196 // remove any constraints that might be in place
1197 foreach (BSPrim prim in _childrenPrims)
1198 {
1199 // m_log.DebugFormat("{0}: CreateLinkset: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
1200 BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID);
1201 }
1202 // create constraints between the root prim and each of the children
1203 foreach (BSPrim prim in _childrenPrims)
1204 {
1205 // m_log.DebugFormat("{0}: CreateLinkset: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
1206
1207 // Zero motion for children so they don't interpolate
1208 prim.ZeroMotion();
1209
1210 // relative position normalized to the root prim
1211 OMV.Vector3 childRelativePosition = (prim._position - this._position) * OMV.Quaternion.Inverse(this._orientation);
1212
1213 // relative rotation of the child to the parent
1214 OMV.Quaternion relativeRotation = OMV.Quaternion.Inverse(prim._orientation) * this._orientation;
1215
1216 // this is a constraint that allows no freedom of movement between the two objects
1217 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
1218 BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID,
1219 childRelativePosition,
1220 relativeRotation,
1221 OMV.Vector3.Zero,
1222 OMV.Quaternion.Identity,
1223 OMV.Vector3.Zero, OMV.Vector3.Zero,
1224 OMV.Vector3.Zero, OMV.Vector3.Zero);
1225 }
1226 }
1227 1241
1228 // Rebuild the geometry and object. 1242 // Rebuild the geometry and object.
1229 // This is called when the shape changes so we need to recreate the mesh/hull. 1243 // This is called when the shape changes so we need to recreate the mesh/hull.
@@ -1231,8 +1245,8 @@ public sealed class BSPrim : PhysicsActor
1231 private void RecreateGeomAndObject() 1245 private void RecreateGeomAndObject()
1232 { 1246 {
1233 // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); 1247 // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID);
1234 CreateGeom(true); 1248 if (CreateGeom(true))
1235 CreateObject(); 1249 CreateObject();
1236 return; 1250 return;
1237 } 1251 }
1238 1252
@@ -1252,78 +1266,78 @@ public sealed class BSPrim : PhysicsActor
1252 const float POSITION_TOLERANCE = 0.05f; 1266 const float POSITION_TOLERANCE = 0.05f;
1253 const float ACCELERATION_TOLERANCE = 0.01f; 1267 const float ACCELERATION_TOLERANCE = 0.01f;
1254 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; 1268 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1255 const bool SHOULD_DAMP_UPDATES = false;
1256 1269
1257 public void UpdateProperties(EntityProperties entprop) 1270 public void UpdateProperties(EntityProperties entprop)
1258 { 1271 {
1272 /*
1259 UpdatedProperties changed = 0; 1273 UpdatedProperties changed = 0;
1260 if (SHOULD_DAMP_UPDATES) 1274 // assign to the local variables so the normal set action does not happen
1275 // if (_position != entprop.Position)
1276 if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
1261 { 1277 {
1262 // assign to the local variables so the normal set action does not happen 1278 _position = entprop.Position;
1263 // if (_position != entprop.Position) 1279 changed |= UpdatedProperties.Position;
1264 if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
1265 {
1266 _position = entprop.Position;
1267 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, pos = {2}", LogHeader, LocalID, _position);
1268 changed |= UpdatedProperties.Position;
1269 }
1270 // if (_orientation != entprop.Rotation)
1271 if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
1272 {
1273 _orientation = entprop.Rotation;
1274 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, rot = {2}", LogHeader, LocalID, _orientation);
1275 changed |= UpdatedProperties.Rotation;
1276 }
1277 // if (_velocity != entprop.Velocity)
1278 if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
1279 {
1280 _velocity = entprop.Velocity;
1281 // m_log.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity);
1282 changed |= UpdatedProperties.Velocity;
1283 }
1284 // if (_acceleration != entprop.Acceleration)
1285 if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
1286 {
1287 _acceleration = entprop.Acceleration;
1288 // m_log.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration);
1289 changed |= UpdatedProperties.Acceleration;
1290 }
1291 // if (_rotationalVelocity != entprop.RotationalVelocity)
1292 if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
1293 {
1294 _rotationalVelocity = entprop.RotationalVelocity;
1295 // m_log.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity);
1296 changed |= UpdatedProperties.RotationalVel;
1297 }
1298 if (changed != 0)
1299 {
1300 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
1301 // Only update the position of single objects and linkset roots
1302 if (this._parentPrim == null)
1303 {
1304 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
1305 base.RequestPhysicsterseUpdate();
1306 }
1307 }
1308 } 1280 }
1309 else 1281 // if (_orientation != entprop.Rotation)
1282 if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
1310 { 1283 {
1311 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. 1284 _orientation = entprop.Rotation;
1312 1285 changed |= UpdatedProperties.Rotation;
1313 // Only updates only for individual prims and for the root object of a linkset. 1286 }
1287 // if (_velocity != entprop.Velocity)
1288 if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
1289 {
1290 _velocity = entprop.Velocity;
1291 changed |= UpdatedProperties.Velocity;
1292 }
1293 // if (_acceleration != entprop.Acceleration)
1294 if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
1295 {
1296 _acceleration = entprop.Acceleration;
1297 changed |= UpdatedProperties.Acceleration;
1298 }
1299 // if (_rotationalVelocity != entprop.RotationalVelocity)
1300 if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
1301 {
1302 _rotationalVelocity = entprop.RotationalVelocity;
1303 changed |= UpdatedProperties.RotationalVel;
1304 }
1305 if (changed != 0)
1306 {
1307 // Only update the position of single objects and linkset roots
1314 if (this._parentPrim == null) 1308 if (this._parentPrim == null)
1315 { 1309 {
1316 // Assign to the local variables so the normal set action does not happen
1317 _position = entprop.Position;
1318 _orientation = entprop.Rotation;
1319 _velocity = entprop.Velocity;
1320 _acceleration = entprop.Acceleration;
1321 _rotationalVelocity = entprop.RotationalVelocity;
1322 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
1323 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1324 base.RequestPhysicsterseUpdate(); 1310 base.RequestPhysicsterseUpdate();
1325 } 1311 }
1326 } 1312 }
1313 */
1314
1315 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1316
1317 // Updates only for individual prims and for the root object of a linkset.
1318 if (_linkset.IsRoot(this))
1319 {
1320 // Assign to the local variables so the normal set action does not happen
1321 _position = entprop.Position;
1322 _orientation = entprop.Rotation;
1323 _velocity = entprop.Velocity;
1324 _acceleration = entprop.Acceleration;
1325 _rotationalVelocity = entprop.RotationalVelocity;
1326
1327 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
1328 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1329 DetailLog("{0},UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1330 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1331
1332 base.RequestPhysicsterseUpdate();
1333 }
1334 else
1335 {
1336 // For debugging, we can also report the movement of children
1337 DetailLog("{0},UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1338 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1339 entprop.Acceleration, entprop.RotationalVelocity);
1340 }
1327 } 1341 }
1328 1342
1329 // I've collided with something 1343 // I've collided with something
@@ -1362,5 +1376,11 @@ public sealed class BSPrim : PhysicsActor
1362 collisionCollection.Clear(); 1376 collisionCollection.Clear();
1363 } 1377 }
1364 } 1378 }
1379
1380 // Invoke the detailed logger and output something if it's enabled.
1381 private void DetailLog(string msg, params Object[] args)
1382 {
1383 Scene.PhysicsLogging.Write(msg, args);
1384 }
1365} 1385}
1366} 1386}