aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs588
1 files changed, 296 insertions, 292 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 130f1ca..7590d93 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,22 @@ 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 { get { return m_body; } }
107
97 private BSDynamics _vehicle; 108 private BSDynamics _vehicle;
98 109
99 private OMV.Vector3 _PIDTarget; 110 private OMV.Vector3 _PIDTarget;
@@ -127,17 +138,18 @@ public sealed class BSPrim : PhysicsActor
127 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 138 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
128 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 139 _density = _scene.Params.defaultDensity; // TODO: compute based on object material
129 _restitution = _scene.Params.defaultRestitution; 140 _restitution = _scene.Params.defaultRestitution;
130 _parentPrim = null; // not a child or a parent 141 _linkset = new BSLinkset(_scene, this); // a linkset of one
131 _vehicle = new BSDynamics(this); // add vehicleness 142 _vehicle = new BSDynamics(this); // add vehicleness
132 _childrenPrims = new List<BSPrim>(); 143 _mass = CalculateMass();
133 if (_isPhysical)
134 _mass = CalculateMass();
135 else
136 _mass = 0f;
137 // do the actual object creation at taint time 144 // do the actual object creation at taint time
138 _scene.TaintedObject(delegate() 145 _scene.TaintedObject(delegate()
139 { 146 {
140 RecreateGeomAndObject(); 147 RecreateGeomAndObject();
148
149 // Get the pointer to the physical body for this object.
150 // At the moment, we're still letting BulletSim manage the creation and destruction
151 // of the object. Someday we'll move that into the C# code.
152 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
141 }); 153 });
142 } 154 }
143 155
@@ -145,13 +157,19 @@ public sealed class BSPrim : PhysicsActor
145 public void Destroy() 157 public void Destroy()
146 { 158 {
147 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 159 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
160 // DetailLog("{0},Destroy", LocalID);
161
148 // Undo any vehicle properties 162 // Undo any vehicle properties
149 _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); 163 _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE);
150 _scene.RemoveVehiclePrim(this); // just to make sure 164 _scene.RemoveVehiclePrim(this); // just to make sure
165
151 _scene.TaintedObject(delegate() 166 _scene.TaintedObject(delegate()
152 { 167 {
168 // Undo any links between me and any other object
169 _linkset = _linkset.RemoveMeFromLinkset(this);
170
153 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 171 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
154 BulletSimAPI.DestroyObject(_scene.WorldID, _localID); 172 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
155 }); 173 });
156 } 174 }
157 175
@@ -164,8 +182,8 @@ public sealed class BSPrim : PhysicsActor
164 _size = value; 182 _size = value;
165 _scene.TaintedObject(delegate() 183 _scene.TaintedObject(delegate()
166 { 184 {
167 if (_isPhysical) _mass = CalculateMass(); // changing size changes the mass 185 _mass = CalculateMass(); // changing size changes the mass
168 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, _mass, _isPhysical); 186 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
169 RecreateGeomAndObject(); 187 RecreateGeomAndObject();
170 }); 188 });
171 } 189 }
@@ -175,7 +193,7 @@ public sealed class BSPrim : PhysicsActor
175 _pbs = value; 193 _pbs = value;
176 _scene.TaintedObject(delegate() 194 _scene.TaintedObject(delegate()
177 { 195 {
178 if (_isPhysical) _mass = CalculateMass(); // changing the shape changes the mass 196 _mass = CalculateMass(); // changing the shape changes the mass
179 RecreateGeomAndObject(); 197 RecreateGeomAndObject();
180 }); 198 });
181 } 199 }
@@ -202,33 +220,10 @@ public sealed class BSPrim : PhysicsActor
202 // link me to the specified parent 220 // link me to the specified parent
203 public override void link(PhysicsActor obj) { 221 public override void link(PhysicsActor obj) {
204 BSPrim parent = obj as BSPrim; 222 BSPrim parent = obj as BSPrim;
205 // m_log.DebugFormat("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); 223 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 224 DetailLog("{0},link,parent={1}", LocalID, obj.LocalID);
207 if (_parentPrim == null) 225
208 { 226 _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; 227 return;
233 } 228 }
234 229
@@ -236,101 +231,92 @@ public sealed class BSPrim : PhysicsActor
236 public override void delink() { 231 public override void delink() {
237 // TODO: decide if this parent checking needs to happen at taint time 232 // 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 233 // 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); 234 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
240 if (_parentPrim != null) 235 _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString());
241 { 236 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 237
290 // return true if we are the root of a linkset (there are children to manage) 238 _linkset.RemoveMeFromLinkset(this);
291 public bool IsRootOfLinkset 239 return;
292 {
293 get { return (_parentPrim == null && _childrenPrims.Count != 0); }
294 } 240 }
295 241
296 // Set motion values to zero. 242 // Set motion values to zero.
297 // Do it to the properties so the values get set in the physics engine. 243 // Do it to the properties so the values get set in the physics engine.
298 // Push the setting of the values to the viewer. 244 // Push the setting of the values to the viewer.
299 private void ZeroMotion() 245 // Called at taint time!
246 public void ZeroMotion()
300 { 247 {
301 Velocity = OMV.Vector3.Zero; 248 _velocity = OMV.Vector3.Zero;
302 _acceleration = OMV.Vector3.Zero; 249 _acceleration = OMV.Vector3.Zero;
303 RotationalVelocity = OMV.Vector3.Zero; 250 _rotationalVelocity = OMV.Vector3.Zero;
304 base.RequestPhysicsterseUpdate(); 251
252 // Zero some other properties directly into the physics engine
253 BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero);
254 BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero);
255 BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
256 BulletSimAPI.ClearForces2(Body.Ptr);
305 } 257 }
306 258
307 public override void LockAngularMotion(OMV.Vector3 axis) { return; } 259 public override void LockAngularMotion(OMV.Vector3 axis)
260 {
261 DetailLog("{0},LockAngularMotion,call,axis={1}", LocalID, axis);
262 return;
263 }
308 264
309 public override OMV.Vector3 Position { 265 public override OMV.Vector3 Position {
310 get { 266 get {
311 // don't do the following GetObjectPosition because this function is called a zillion times 267 if (!_linkset.IsRoot(this))
268 // child prims move around based on their parent. Need to get the latest location
269 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
270
271 // don't do the GetObjectPosition for root elements because this function is called a zillion times
312 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 272 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
313 return _position; 273 return _position;
314 } 274 }
315 set { 275 set {
316 _position = value; 276 _position = value;
277 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
317 _scene.TaintedObject(delegate() 278 _scene.TaintedObject(delegate()
318 { 279 {
280 DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
319 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 281 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
320 // m_log.DebugFormat("{0}: setPosition: id={1}, position={2}", LogHeader, _localID, _position);
321 }); 282 });
322 } 283 }
323 } 284 }
324 public override float Mass { 285
325 get { return _mass; } 286 // Return the effective mass of the object.
287 // If there are multiple items in the linkset, add them together for the root
288 public override float Mass
289 {
290 get
291 {
292 return _linkset.LinksetMass;
293 }
294 }
295
296 // used when we only want this prim's mass and not the linkset thing
297 public float MassRaw { get { return _mass; } }
298
299 // Is this used?
300 public override OMV.Vector3 CenterOfMass
301 {
302 get { return _linkset.CenterOfMass; }
326 } 303 }
304
305 // Is this used?
306 public override OMV.Vector3 GeometricCenter
307 {
308 get { return _linkset.GeometricCenter; }
309 }
310
327 public override OMV.Vector3 Force { 311 public override OMV.Vector3 Force {
328 get { return _force; } 312 get { return _force; }
329 set { 313 set {
330 _force = value; 314 _force = value;
331 _scene.TaintedObject(delegate() 315 _scene.TaintedObject(delegate()
332 { 316 {
333 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 317 DetailLog("{0},SetForce,taint,force={1}", LocalID, _force);
318 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
319 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
334 }); 320 });
335 } 321 }
336 } 322 }
@@ -341,15 +327,22 @@ public sealed class BSPrim : PhysicsActor
341 } 327 }
342 set { 328 set {
343 Vehicle type = (Vehicle)value; 329 Vehicle type = (Vehicle)value;
344 _vehicle.ProcessTypeChange(type);
345 _scene.TaintedObject(delegate() 330 _scene.TaintedObject(delegate()
346 { 331 {
332 DetailLog("{0},SetVehicleType,taint,type={1}", LocalID, type);
333 _vehicle.ProcessTypeChange(type);
347 if (type == Vehicle.TYPE_NONE) 334 if (type == Vehicle.TYPE_NONE)
348 { 335 {
349 _scene.RemoveVehiclePrim(this); 336 _scene.RemoveVehiclePrim(this);
350 } 337 }
351 else 338 else
352 { 339 {
340 _scene.TaintedObject(delegate()
341 {
342 // Tell the physics engine to clear state
343 BulletSimAPI.ClearForces2(this.Body.Ptr);
344 });
345
353 // make it so the scene will call us each tick to do vehicle things 346 // make it so the scene will call us each tick to do vehicle things
354 _scene.AddVehiclePrim(this); 347 _scene.AddVehiclePrim(this);
355 } 348 }
@@ -359,47 +352,59 @@ public sealed class BSPrim : PhysicsActor
359 } 352 }
360 public override void VehicleFloatParam(int param, float value) 353 public override void VehicleFloatParam(int param, float value)
361 { 354 {
362 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); 355 _scene.TaintedObject(delegate()
356 {
357 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
358 });
363 } 359 }
364 public override void VehicleVectorParam(int param, OMV.Vector3 value) 360 public override void VehicleVectorParam(int param, OMV.Vector3 value)
365 { 361 {
366 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); 362 _scene.TaintedObject(delegate()
363 {
364 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
365 });
367 } 366 }
368 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 367 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
369 { 368 {
370 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 369 _scene.TaintedObject(delegate()
370 {
371 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
372 });
371 } 373 }
372 public override void VehicleFlags(int param, bool remove) 374 public override void VehicleFlags(int param, bool remove)
373 { 375 {
374 _vehicle.ProcessVehicleFlags(param, remove); 376 _scene.TaintedObject(delegate()
377 {
378 _vehicle.ProcessVehicleFlags(param, remove);
379 });
375 } 380 }
376 // Called each simulation step to advance vehicle characteristics 381
382 // Called each simulation step to advance vehicle characteristics.
383 // Called from Scene when doing simulation step so we're in taint processing time.
377 public void StepVehicle(float timeStep) 384 public void StepVehicle(float timeStep)
378 { 385 {
379 _vehicle.Step(timeStep, _scene); 386 if (IsPhysical)
387 _vehicle.Step(timeStep);
380 } 388 }
381 389
382 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 390 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
383 public override void SetVolumeDetect(int param) { 391 public override void SetVolumeDetect(int param) {
384 bool newValue = (param != 0); 392 bool newValue = (param != 0);
385 if (_isVolumeDetect != newValue) 393 _isVolumeDetect = newValue;
394 _scene.TaintedObject(delegate()
386 { 395 {
387 _isVolumeDetect = newValue; 396 SetObjectDynamic();
388 _scene.TaintedObject(delegate() 397 });
389 {
390 SetObjectDynamic();
391 });
392 }
393 return; 398 return;
394 } 399 }
395 400
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 { 401 public override OMV.Vector3 Velocity {
399 get { return _velocity; } 402 get { return _velocity; }
400 set { _velocity = value; 403 set {
404 _velocity = value;
401 _scene.TaintedObject(delegate() 405 _scene.TaintedObject(delegate()
402 { 406 {
407 DetailLog("{0},SetVelocity,taint,vel={1}", LocalID, _velocity);
403 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 408 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
404 }); 409 });
405 } 410 }
@@ -407,6 +412,7 @@ public sealed class BSPrim : PhysicsActor
407 public override OMV.Vector3 Torque { 412 public override OMV.Vector3 Torque {
408 get { return _torque; } 413 get { return _torque; }
409 set { _torque = value; 414 set { _torque = value;
415 DetailLog("{0},SetTorque,call,torque={1}", LocalID, _torque);
410 } 416 }
411 } 417 }
412 public override float CollisionScore { 418 public override float CollisionScore {
@@ -419,13 +425,21 @@ public sealed class BSPrim : PhysicsActor
419 set { _acceleration = value; } 425 set { _acceleration = value; }
420 } 426 }
421 public override OMV.Quaternion Orientation { 427 public override OMV.Quaternion Orientation {
422 get { return _orientation; } 428 get {
429 if (!_linkset.IsRoot(this))
430 {
431 // Children move around because tied to parent. Get a fresh value.
432 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
433 }
434 return _orientation;
435 }
423 set { 436 set {
424 _orientation = value; 437 _orientation = value;
425 // m_log.DebugFormat("{0}: set orientation: id={1}, ori={2}", LogHeader, LocalID, _orientation); 438 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
426 _scene.TaintedObject(delegate() 439 _scene.TaintedObject(delegate()
427 { 440 {
428 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 441 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
442 DetailLog("{0},SetOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
429 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 443 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
430 }); 444 });
431 } 445 }
@@ -458,25 +472,22 @@ public sealed class BSPrim : PhysicsActor
458 get { return !IsPhantom && !_isVolumeDetect; } 472 get { return !IsPhantom && !_isVolumeDetect; }
459 } 473 }
460 474
461 // make gravity work if the object is physical and not selected 475 // Make gravity work if the object is physical and not selected
462 // no locking here because only called when it is safe 476 // No locking here because only called when it is safe
477 // Only called at taint time so it is save to call into Bullet.
463 private void SetObjectDynamic() 478 private void SetObjectDynamic()
464 { 479 {
465 // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); 480 // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid);
466 // non-physical things work best with a mass of zero
467 if (IsStatic)
468 {
469 _mass = 0f;
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 481
478 } 482 RecreateGeomAndObject();
479 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), _mass); 483
484 float mass = _mass;
485 // Bullet wants static objects have a mass of zero
486 if (IsStatic)
487 mass = 0f;
488
489 DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, mass);
490 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
480 } 491 }
481 492
482 // prims don't fly 493 // prims don't fly
@@ -516,11 +527,24 @@ public sealed class BSPrim : PhysicsActor
516 set { _floatOnWater = value; } 527 set { _floatOnWater = value; }
517 } 528 }
518 public override OMV.Vector3 RotationalVelocity { 529 public override OMV.Vector3 RotationalVelocity {
519 get { return _rotationalVelocity; } 530 get {
520 set { _rotationalVelocity = value; 531 /*
532 OMV.Vector3 pv = OMV.Vector3.Zero;
533 // if close to zero, report zero
534 // This is copied from ODE but I'm not sure why it returns zero but doesn't
535 // zero the property in the physics engine.
536 if (_rotationalVelocity.ApproxEquals(pv, 0.2f))
537 return pv;
538 */
539
540 return _rotationalVelocity;
541 }
542 set {
543 _rotationalVelocity = value;
521 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 544 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
522 _scene.TaintedObject(delegate() 545 _scene.TaintedObject(delegate()
523 { 546 {
547 DetailLog("{0},SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
524 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 548 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
525 }); 549 });
526 } 550 }
@@ -533,11 +557,13 @@ public sealed class BSPrim : PhysicsActor
533 } 557 }
534 public override float Buoyancy { 558 public override float Buoyancy {
535 get { return _buoyancy; } 559 get { return _buoyancy; }
536 set { _buoyancy = value; 560 set {
537 _scene.TaintedObject(delegate() 561 _buoyancy = value;
538 { 562 _scene.TaintedObject(delegate()
539 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 563 {
540 }); 564 DetailLog("{0},SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
565 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
566 });
541 } 567 }
542 } 568 }
543 569
@@ -573,27 +599,45 @@ public sealed class BSPrim : PhysicsActor
573 public override float APIDStrength { set { return; } } 599 public override float APIDStrength { set { return; } }
574 public override float APIDDamping { set { return; } } 600 public override float APIDDamping { set { return; } }
575 601
602 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
576 public override void AddForce(OMV.Vector3 force, bool pushforce) { 603 public override void AddForce(OMV.Vector3 force, bool pushforce) {
577 if (force.IsFinite()) 604 if (force.IsFinite())
578 { 605 {
579 _force.X += force.X; 606 // _force += force;
580 _force.Y += force.Y; 607 lock (m_accumulatedForces)
581 _force.Z += force.Z; 608 m_accumulatedForces.Add(new OMV.Vector3(force));
582 } 609 }
583 else 610 else
584 { 611 {
585 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 612 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
613 return;
586 } 614 }
587 _scene.TaintedObject(delegate() 615 _scene.TaintedObject(delegate()
588 { 616 {
589 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 617 lock (m_accumulatedForces)
618 {
619 if (m_accumulatedForces.Count > 0)
620 {
621 OMV.Vector3 fSum = OMV.Vector3.Zero;
622 foreach (OMV.Vector3 v in m_accumulatedForces)
623 {
624 fSum += v;
625 }
626 m_accumulatedForces.Clear();
627
628 DetailLog("{0},SetObjectForce,taint,force={1}", LocalID, fSum);
629 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, fSum);
630 }
631 }
590 }); 632 });
591 } 633 }
592 634
593 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 635 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
636 DetailLog("{0},AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
594 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 637 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
595 } 638 }
596 public override void SetMomentum(OMV.Vector3 momentum) { 639 public override void SetMomentum(OMV.Vector3 momentum) {
640 DetailLog("{0},SetMomentum,call,mom={1}", LocalID, momentum);
597 } 641 }
598 public override void SubscribeEvents(int ms) { 642 public override void SubscribeEvents(int ms) {
599 _subscribedEventsMs = ms; 643 _subscribedEventsMs = ms;
@@ -885,6 +929,9 @@ public sealed class BSPrim : PhysicsActor
885 929
886 returnMass = _density * volume; 930 returnMass = _density * volume;
887 931
932 /*
933 * This change means each object keeps its own mass and the Mass property
934 * will return the sum if we're part of a linkset.
888 if (IsRootOfLinkset) 935 if (IsRootOfLinkset)
889 { 936 {
890 foreach (BSPrim prim in _childrenPrims) 937 foreach (BSPrim prim in _childrenPrims)
@@ -892,6 +939,7 @@ public sealed class BSPrim : PhysicsActor
892 returnMass += prim.CalculateMass(); 939 returnMass += prim.CalculateMass();
893 } 940 }
894 } 941 }
942 */
895 943
896 if (returnMass <= 0) 944 if (returnMass <= 0)
897 returnMass = 0.0001f; 945 returnMass = 0.0001f;
@@ -907,9 +955,11 @@ public sealed class BSPrim : PhysicsActor
907 // The objects needs a hull if it's physical otherwise a mesh is enough 955 // 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 956 // 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 957 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used
910 private void CreateGeom(bool forceRebuild) 958 // Returns 'true' if the geometry was rebuilt
959 private bool CreateGeom(bool forceRebuild)
911 { 960 {
912 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. 961 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
962 bool ret = false;
913 if (!_scene.NeedsMeshing(_pbs)) 963 if (!_scene.NeedsMeshing(_pbs))
914 { 964 {
915 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 965 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
@@ -917,16 +967,26 @@ public sealed class BSPrim : PhysicsActor
917 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 967 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
918 { 968 {
919 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 969 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
920 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 970 if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)
921 // Bullet native objects are scaled by the Bullet engine so pass the size in 971 {
922 _scale = _size; 972 DetailLog("{0},CreateGeom,sphere", LocalID);
973 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
974 ret = true;
975 // Bullet native objects are scaled by the Bullet engine so pass the size in
976 _scale = _size;
977 }
923 } 978 }
924 } 979 }
925 else 980 else
926 { 981 {
927 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size); 982 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size);
928 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 983 if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)
929 _scale = _size; 984 {
985 DetailLog("{0},CreateGeom,box", LocalID);
986 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
987 ret = true;
988 _scale = _size;
989 }
930 } 990 }
931 } 991 }
932 else 992 else
@@ -938,6 +998,7 @@ public sealed class BSPrim : PhysicsActor
938 // physical objects require a hull for interaction. 998 // physical objects require a hull for interaction.
939 // This will create the mesh if it doesn't already exist 999 // This will create the mesh if it doesn't already exist
940 CreateGeomHull(); 1000 CreateGeomHull();
1001 ret = true;
941 } 1002 }
942 } 1003 }
943 else 1004 else
@@ -946,9 +1007,11 @@ public sealed class BSPrim : PhysicsActor
946 { 1007 {
947 // Static (non-physical) objects only need a mesh for bumping into 1008 // Static (non-physical) objects only need a mesh for bumping into
948 CreateGeomMesh(); 1009 CreateGeomMesh();
1010 ret = true;
949 } 1011 }
950 } 1012 }
951 } 1013 }
1014 return ret;
952 } 1015 }
953 1016
954 // No locking here because this is done when we know physics is not simulating 1017 // No locking here because this is done when we know physics is not simulating
@@ -961,10 +1024,12 @@ public sealed class BSPrim : PhysicsActor
961 // if this new shape is the same as last time, don't recreate the mesh 1024 // if this new shape is the same as last time, don't recreate the mesh
962 if (_meshKey == newMeshKey) return; 1025 if (_meshKey == newMeshKey) return;
963 1026
1027 DetailLog("{0},CreateGeomMesh,create,key={1}", LocalID, _meshKey);
964 // Since we're recreating new, get rid of any previously generated shape 1028 // Since we're recreating new, get rid of any previously generated shape
965 if (_meshKey != 0) 1029 if (_meshKey != 0)
966 { 1030 {
967 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); 1031 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1032 DetailLog("{0},CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
968 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1033 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
969 _mesh = null; 1034 _mesh = null;
970 _meshKey = 0; 1035 _meshKey = 0;
@@ -981,7 +1046,6 @@ public sealed class BSPrim : PhysicsActor
981 int vi = 0; 1046 int vi = 0;
982 foreach (OMV.Vector3 vv in vertices) 1047 foreach (OMV.Vector3 vv in vertices)
983 { 1048 {
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; 1049 verticesAsFloats[vi++] = vv.X;
986 verticesAsFloats[vi++] = vv.Y; 1050 verticesAsFloats[vi++] = vv.Y;
987 verticesAsFloats[vi++] = vv.Z; 1051 verticesAsFloats[vi++] = vv.Z;
@@ -995,6 +1059,7 @@ public sealed class BSPrim : PhysicsActor
995 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1059 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
996 // meshes are already scaled by the meshmerizer 1060 // meshes are already scaled by the meshmerizer
997 _scale = new OMV.Vector3(1f, 1f, 1f); 1061 _scale = new OMV.Vector3(1f, 1f, 1f);
1062 DetailLog("{0},CreateGeomMesh,done", LocalID);
998 return; 1063 return;
999 } 1064 }
1000 1065
@@ -1008,13 +1073,17 @@ public sealed class BSPrim : PhysicsActor
1008 // if the hull hasn't changed, don't rebuild it 1073 // if the hull hasn't changed, don't rebuild it
1009 if (newHullKey == _hullKey) return; 1074 if (newHullKey == _hullKey) return;
1010 1075
1076 DetailLog("{0},CreateGeomHull,create,key={1}", LocalID, _meshKey);
1077
1011 // Since we're recreating new, get rid of any previously generated shape 1078 // Since we're recreating new, get rid of any previously generated shape
1012 if (_hullKey != 0) 1079 if (_hullKey != 0)
1013 { 1080 {
1014 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); 1081 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1082 DetailLog("{0},CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey);
1015 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1083 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1016 _hullKey = 0; 1084 _hullKey = 0;
1017 _hulls.Clear(); 1085 _hulls.Clear();
1086 DetailLog("{0},CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey);
1018 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1087 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1019 _mesh = null; // the mesh cannot match either 1088 _mesh = null; // the mesh cannot match either
1020 _meshKey = 0; 1089 _meshKey = 0;
@@ -1111,6 +1180,7 @@ public sealed class BSPrim : PhysicsActor
1111 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1180 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1112 // meshes are already scaled by the meshmerizer 1181 // meshes are already scaled by the meshmerizer
1113 _scale = new OMV.Vector3(1f, 1f, 1f); 1182 _scale = new OMV.Vector3(1f, 1f, 1f);
1183 DetailLog("{0},CreateGeomHull,done", LocalID);
1114 return; 1184 return;
1115 } 1185 }
1116 1186
@@ -1126,45 +1196,18 @@ public sealed class BSPrim : PhysicsActor
1126 // No locking here because this is done when the physics engine is not simulating 1196 // No locking here because this is done when the physics engine is not simulating
1127 private void CreateObject() 1197 private void CreateObject()
1128 { 1198 {
1129 if (IsRootOfLinkset) 1199 // 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 1200
1146 // Create a linkset by creating a compound hull at the root prim that consists of all 1201 // the mesh or hull must have already been created in Bullet
1147 // the children. 1202 ShapeData shape;
1148 // NOTE: This does not allow proper collisions with the children prims so it is not a workable solution 1203 FillShapeInfo(out shape);
1149 void CreateLinksetWithCompoundHull() 1204 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1150 { 1205 BulletSimAPI.CreateObject(_scene.WorldID, shape);
1151 // If I am the root prim of a linkset, replace my physical shape with all the 1206 // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
1152 // pieces of the children. 1207 m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID);
1153 // All of the children should have called CreateGeom so they have a hull 1208
1154 // in the physics engine already. Here we pull together all of those hulls 1209 // The root object could have been recreated. Make sure everything linksety is up to date.
1155 // into one shape. 1210 _linkset.RefreshLinkset(this);
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 } 1211 }
1169 1212
1170 // Copy prim's info into the BulletSim shape description structure 1213 // Copy prim's info into the BulletSim shape description structure
@@ -1186,44 +1229,6 @@ public sealed class BSPrim : PhysicsActor
1186 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1229 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1187 } 1230 }
1188 1231
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 1232
1228 // Rebuild the geometry and object. 1233 // Rebuild the geometry and object.
1229 // This is called when the shape changes so we need to recreate the mesh/hull. 1234 // This is called when the shape changes so we need to recreate the mesh/hull.
@@ -1252,78 +1257,71 @@ public sealed class BSPrim : PhysicsActor
1252 const float POSITION_TOLERANCE = 0.05f; 1257 const float POSITION_TOLERANCE = 0.05f;
1253 const float ACCELERATION_TOLERANCE = 0.01f; 1258 const float ACCELERATION_TOLERANCE = 0.01f;
1254 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; 1259 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1255 const bool SHOULD_DAMP_UPDATES = false;
1256 1260
1257 public void UpdateProperties(EntityProperties entprop) 1261 public void UpdateProperties(EntityProperties entprop)
1258 { 1262 {
1263 /*
1259 UpdatedProperties changed = 0; 1264 UpdatedProperties changed = 0;
1260 if (SHOULD_DAMP_UPDATES) 1265 // assign to the local variables so the normal set action does not happen
1266 // if (_position != entprop.Position)
1267 if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
1261 { 1268 {
1262 // assign to the local variables so the normal set action does not happen 1269 _position = entprop.Position;
1263 // if (_position != entprop.Position) 1270 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 } 1271 }
1309 else 1272 // if (_orientation != entprop.Rotation)
1273 if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
1310 { 1274 {
1311 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. 1275 _orientation = entprop.Rotation;
1312 1276 changed |= UpdatedProperties.Rotation;
1313 // Only updates only for individual prims and for the root object of a linkset. 1277 }
1278 // if (_velocity != entprop.Velocity)
1279 if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
1280 {
1281 _velocity = entprop.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 changed |= UpdatedProperties.Acceleration;
1289 }
1290 // if (_rotationalVelocity != entprop.RotationalVelocity)
1291 if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
1292 {
1293 _rotationalVelocity = entprop.RotationalVelocity;
1294 changed |= UpdatedProperties.RotationalVel;
1295 }
1296 if (changed != 0)
1297 {
1298 // Only update the position of single objects and linkset roots
1314 if (this._parentPrim == null) 1299 if (this._parentPrim == null)
1315 { 1300 {
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(); 1301 base.RequestPhysicsterseUpdate();
1325 } 1302 }
1326 } 1303 }
1304 */
1305
1306 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1307
1308 // Updates only for individual prims and for the root object of a linkset.
1309 if (_linkset.IsRoot(this))
1310 {
1311 // Assign to the local variables so the normal set action does not happen
1312 _position = entprop.Position;
1313 _orientation = entprop.Rotation;
1314 _velocity = entprop.Velocity;
1315 _acceleration = entprop.Acceleration;
1316 _rotationalVelocity = entprop.RotationalVelocity;
1317
1318 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
1319 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1320 DetailLog("{0},UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1321 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1322
1323 base.RequestPhysicsterseUpdate();
1324 }
1327 } 1325 }
1328 1326
1329 // I've collided with something 1327 // I've collided with something
@@ -1362,5 +1360,11 @@ public sealed class BSPrim : PhysicsActor
1362 collisionCollection.Clear(); 1360 collisionCollection.Clear();
1363 } 1361 }
1364 } 1362 }
1363
1364 // Invoke the detailed logger and output something if it's enabled.
1365 private void DetailLog(string msg, params Object[] args)
1366 {
1367 Scene.PhysicsLogging.Write(msg, args);
1368 }
1365} 1369}
1366} 1370}