diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 272 |
1 files changed, 136 insertions, 136 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 2b3fa25..758d92b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -45,7 +45,6 @@ public sealed class BSPrim : BSPhysObject | |||
45 | private static readonly string LogHeader = "[BULLETS PRIM]"; | 45 | private static readonly string LogHeader = "[BULLETS PRIM]"; |
46 | 46 | ||
47 | // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. | 47 | // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. |
48 | // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. | ||
49 | private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user | 48 | private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user |
50 | 49 | ||
51 | private bool _grabbed; | 50 | private bool _grabbed; |
@@ -93,7 +92,7 @@ public sealed class BSPrim : BSPhysObject | |||
93 | _physicsActorType = (int)ActorTypes.Prim; | 92 | _physicsActorType = (int)ActorTypes.Prim; |
94 | _position = pos; | 93 | _position = pos; |
95 | _size = size; | 94 | _size = size; |
96 | Scale = size; // the scale will be set by CreateGeom depending on object type | 95 | Scale = size; // prims are the size the user wants them to be (different for BSCharactes). |
97 | _orientation = rotation; | 96 | _orientation = rotation; |
98 | _buoyancy = 1f; | 97 | _buoyancy = 1f; |
99 | _velocity = OMV.Vector3.Zero; | 98 | _velocity = OMV.Vector3.Zero; |
@@ -108,8 +107,8 @@ public sealed class BSPrim : BSPhysObject | |||
108 | _mass = CalculateMass(); | 107 | _mass = CalculateMass(); |
109 | 108 | ||
110 | // No body or shape yet | 109 | // No body or shape yet |
111 | PhysBody = new BulletBody(LocalID, IntPtr.Zero); | 110 | PhysBody = new BulletBody(LocalID); |
112 | PhysShape = new BulletShape(IntPtr.Zero); | 111 | PhysShape = new BulletShape(); |
113 | 112 | ||
114 | DetailLog("{0},BSPrim.constructor,call", LocalID); | 113 | DetailLog("{0},BSPrim.constructor,call", LocalID); |
115 | // do the actual object creation at taint time | 114 | // do the actual object creation at taint time |
@@ -143,7 +142,9 @@ public sealed class BSPrim : BSPhysObject | |||
143 | DetailLog("{0},BSPrim.Destroy,taint,", LocalID); | 142 | DetailLog("{0},BSPrim.Destroy,taint,", LocalID); |
144 | // If there are physical body and shape, release my use of same. | 143 | // If there are physical body and shape, release my use of same. |
145 | PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); | 144 | PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); |
145 | PhysBody.Clear(); | ||
146 | PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); | 146 | PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); |
147 | PhysShape.Clear(); | ||
147 | }); | 148 | }); |
148 | } | 149 | } |
149 | 150 | ||
@@ -157,12 +158,10 @@ public sealed class BSPrim : BSPhysObject | |||
157 | // We presume the scale and size are the same. If scale must be changed for | 158 | // We presume the scale and size are the same. If scale must be changed for |
158 | // the physical shape, that is done when the geometry is built. | 159 | // the physical shape, that is done when the geometry is built. |
159 | _size = value; | 160 | _size = value; |
161 | Scale = _size; | ||
160 | ForceBodyShapeRebuild(false); | 162 | ForceBodyShapeRebuild(false); |
161 | } | 163 | } |
162 | } | 164 | } |
163 | // Scale is what we set in the physics engine. It is different than 'size' in that | ||
164 | // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>. | ||
165 | public override OMV.Vector3 Scale { get; set; } | ||
166 | 165 | ||
167 | public override PrimitiveBaseShape Shape { | 166 | public override PrimitiveBaseShape Shape { |
168 | set { | 167 | set { |
@@ -189,13 +188,17 @@ public sealed class BSPrim : BSPhysObject | |||
189 | } | 188 | } |
190 | } | 189 | } |
191 | public override bool Selected { | 190 | public override bool Selected { |
192 | set { | 191 | set |
193 | _isSelected = value; | 192 | { |
194 | PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() | 193 | if (value != _isSelected) |
195 | { | 194 | { |
196 | DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); | 195 | _isSelected = value; |
197 | SetObjectDynamic(false); | 196 | PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() |
198 | }); | 197 | { |
198 | DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); | ||
199 | SetObjectDynamic(false); | ||
200 | }); | ||
201 | } | ||
199 | } | 202 | } |
200 | } | 203 | } |
201 | public override void CrossingFailure() { return; } | 204 | public override void CrossingFailure() { return; } |
@@ -244,7 +247,8 @@ public sealed class BSPrim : BSPhysObject | |||
244 | // Zero some other properties in the physics engine | 247 | // Zero some other properties in the physics engine |
245 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() | 248 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() |
246 | { | 249 | { |
247 | BulletSimAPI.ClearAllForces2(PhysBody.ptr); | 250 | if (PhysBody.HasPhysicalBody) |
251 | BulletSimAPI.ClearAllForces2(PhysBody.ptr); | ||
248 | }); | 252 | }); |
249 | } | 253 | } |
250 | public override void ZeroAngularMotion(bool inTaintTime) | 254 | public override void ZeroAngularMotion(bool inTaintTime) |
@@ -253,8 +257,12 @@ public sealed class BSPrim : BSPhysObject | |||
253 | // Zero some other properties in the physics engine | 257 | // Zero some other properties in the physics engine |
254 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() | 258 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() |
255 | { | 259 | { |
256 | BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); | 260 | // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); |
257 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); | 261 | if (PhysBody.HasPhysicalBody) |
262 | { | ||
263 | BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, _rotationalVelocity); | ||
264 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); | ||
265 | } | ||
258 | }); | 266 | }); |
259 | } | 267 | } |
260 | 268 | ||
@@ -271,9 +279,12 @@ public sealed class BSPrim : BSPhysObject | |||
271 | } | 279 | } |
272 | public override OMV.Vector3 Position { | 280 | public override OMV.Vector3 Position { |
273 | get { | 281 | get { |
282 | /* NOTE: this refetch is not necessary. The simulator knows about linkset children | ||
283 | * and does not fetch this position info for children. Thus this is commented out. | ||
274 | // child prims move around based on their parent. Need to get the latest location | 284 | // child prims move around based on their parent. Need to get the latest location |
275 | if (!Linkset.IsRoot(this)) | 285 | if (!Linkset.IsRoot(this)) |
276 | _position = Linkset.Position(this); | 286 | _position = Linkset.PositionGet(this); |
287 | */ | ||
277 | 288 | ||
278 | // don't do the GetObjectPosition for root elements because this function is called a zillion times. | 289 | // don't do the GetObjectPosition for root elements because this function is called a zillion times. |
279 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); | 290 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); |
@@ -281,18 +292,22 @@ public sealed class BSPrim : BSPhysObject | |||
281 | } | 292 | } |
282 | set { | 293 | set { |
283 | // If the position must be forced into the physics engine, use ForcePosition. | 294 | // If the position must be forced into the physics engine, use ForcePosition. |
295 | // All positions are given in world positions. | ||
284 | if (_position == value) | 296 | if (_position == value) |
285 | { | 297 | { |
298 | DetailLog("{0},BSPrim.setPosition,taint,positionNotChanging,pos={1},orient={2}", LocalID, _position, _orientation); | ||
286 | return; | 299 | return; |
287 | } | 300 | } |
288 | _position = value; | 301 | _position = value; |
289 | // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? | ||
290 | PositionSanityCheck(false); | 302 | PositionSanityCheck(false); |
303 | |||
304 | // A linkset might need to know if a component information changed. | ||
305 | Linkset.UpdateProperties(this, false); | ||
306 | |||
291 | PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() | 307 | PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() |
292 | { | 308 | { |
293 | // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 309 | DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
294 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 310 | ForcePosition = _position; |
295 | ActivateIfPhysical(false); | ||
296 | }); | 311 | }); |
297 | } | 312 | } |
298 | } | 313 | } |
@@ -303,9 +318,11 @@ public sealed class BSPrim : BSPhysObject | |||
303 | } | 318 | } |
304 | set { | 319 | set { |
305 | _position = value; | 320 | _position = value; |
306 | // PositionSanityCheck(); // Don't do this! Causes a loop and caller should know better. | 321 | if (PhysBody.HasPhysicalBody) |
307 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 322 | { |
308 | ActivateIfPhysical(false); | 323 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); |
324 | ActivateIfPhysical(false); | ||
325 | } | ||
309 | } | 326 | } |
310 | } | 327 | } |
311 | 328 | ||
@@ -316,39 +333,46 @@ public sealed class BSPrim : BSPhysObject | |||
316 | { | 333 | { |
317 | bool ret = false; | 334 | bool ret = false; |
318 | 335 | ||
336 | if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position)) | ||
337 | { | ||
338 | // The physical object is out of the known/simulated area. | ||
339 | // Upper levels of code will handle the transition to other areas so, for | ||
340 | // the time, we just ignore the position. | ||
341 | return ret; | ||
342 | } | ||
343 | |||
319 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); | 344 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); |
320 | OMV.Vector3 upForce = OMV.Vector3.Zero; | 345 | OMV.Vector3 upForce = OMV.Vector3.Zero; |
321 | if (Position.Z < terrainHeight) | 346 | if (RawPosition.Z < terrainHeight) |
322 | { | 347 | { |
323 | DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); | 348 | DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); |
324 | float targetHeight = terrainHeight + (Size.Z / 2f); | 349 | float targetHeight = terrainHeight + (Size.Z / 2f); |
325 | // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec. | 350 | // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec. |
326 | upForce.Z = (terrainHeight - Position.Z) * 1f; | 351 | upForce.Z = (terrainHeight - RawPosition.Z) * 1f; |
327 | ret = true; | 352 | ret = true; |
328 | } | 353 | } |
329 | 354 | ||
330 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) | 355 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) |
331 | { | 356 | { |
332 | float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); | 357 | float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); |
333 | // TODO: a floating motor so object will bob in the water | 358 | // TODO: a floating motor so object will bob in the water |
334 | if (Math.Abs(Position.Z - waterHeight) > 0.1f) | 359 | if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) |
335 | { | 360 | { |
336 | // Upforce proportional to the distance away from the water. Correct the error in 1 sec. | 361 | // Upforce proportional to the distance away from the water. Correct the error in 1 sec. |
337 | upForce.Z = (waterHeight - Position.Z) * 1f; | 362 | upForce.Z = (waterHeight - RawPosition.Z) * 1f; |
338 | ret = true; | 363 | ret = true; |
339 | } | 364 | } |
340 | } | 365 | } |
341 | 366 | ||
342 | // TODO: check for out of bounds | ||
343 | |||
344 | // The above code computes a force to apply to correct any out-of-bounds problems. Apply same. | 367 | // The above code computes a force to apply to correct any out-of-bounds problems. Apply same. |
368 | // TODO: This should be intergrated with a geneal physics action mechanism. | ||
369 | // TODO: This should be moderated with PID'ness. | ||
345 | if (ret) | 370 | if (ret) |
346 | { | 371 | { |
347 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck:belowTerrain", delegate() | 372 | // Apply upforce and overcome gravity. |
348 | { | 373 | OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity; |
349 | // Apply upforce and overcome gravity. | 374 | DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce); |
350 | ForceVelocity = ForceVelocity + upForce - PhysicsScene.DefaultGravity; | 375 | AddForce(correctionForce, false, inTaintTime); |
351 | }); | ||
352 | } | 376 | } |
353 | return ret; | 377 | return ret; |
354 | } | 378 | } |
@@ -408,7 +432,8 @@ public sealed class BSPrim : BSPhysObject | |||
408 | PhysicsScene.TaintedObject("BSPrim.setForce", delegate() | 432 | PhysicsScene.TaintedObject("BSPrim.setForce", delegate() |
409 | { | 433 | { |
410 | // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); | 434 | // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); |
411 | BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); | 435 | if (PhysBody.HasPhysicalBody) |
436 | BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); | ||
412 | }); | 437 | }); |
413 | } | 438 | } |
414 | } | 439 | } |
@@ -502,7 +527,8 @@ public sealed class BSPrim : BSPhysObject | |||
502 | PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() | 527 | PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() |
503 | { | 528 | { |
504 | // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); | 529 | // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); |
505 | BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); | 530 | if (PhysBody.HasPhysicalBody) |
531 | BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); | ||
506 | }); | 532 | }); |
507 | } | 533 | } |
508 | } | 534 | } |
@@ -537,23 +563,32 @@ public sealed class BSPrim : BSPhysObject | |||
537 | } | 563 | } |
538 | public override OMV.Quaternion Orientation { | 564 | public override OMV.Quaternion Orientation { |
539 | get { | 565 | get { |
566 | /* NOTE: this refetch is not necessary. The simulator knows about linkset children | ||
567 | * and does not fetch this position info for children. Thus this is commented out. | ||
540 | // Children move around because tied to parent. Get a fresh value. | 568 | // Children move around because tied to parent. Get a fresh value. |
541 | if (!Linkset.IsRoot(this)) | 569 | if (!Linkset.IsRoot(this)) |
542 | { | 570 | { |
543 | _orientation = Linkset.Orientation(this); | 571 | _orientation = Linkset.OrientationGet(this); |
544 | } | 572 | } |
573 | */ | ||
545 | return _orientation; | 574 | return _orientation; |
546 | } | 575 | } |
547 | set { | 576 | set { |
548 | if (_orientation == value) | 577 | if (_orientation == value) |
549 | return; | 578 | return; |
550 | _orientation = value; | 579 | _orientation = value; |
551 | // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? | 580 | |
581 | // A linkset might need to know if a component information changed. | ||
582 | Linkset.UpdateProperties(this, false); | ||
583 | |||
552 | PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() | 584 | PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() |
553 | { | 585 | { |
554 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); | 586 | if (PhysBody.HasPhysicalBody) |
555 | // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 587 | { |
556 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 588 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); |
589 | // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); | ||
590 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | ||
591 | } | ||
557 | }); | 592 | }); |
558 | } | 593 | } |
559 | } | 594 | } |
@@ -644,10 +679,7 @@ public sealed class BSPrim : BSPhysObject | |||
644 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); | 679 | BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); |
645 | 680 | ||
646 | // Collision filter can be set only when the object is in the world | 681 | // Collision filter can be set only when the object is in the world |
647 | if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0) | 682 | PhysBody.ApplyCollisionMask(); |
648 | { | ||
649 | BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask); | ||
650 | } | ||
651 | 683 | ||
652 | // Recompute any linkset parameters. | 684 | // Recompute any linkset parameters. |
653 | // When going from non-physical to physical, this re-enables the constraints that | 685 | // When going from non-physical to physical, this re-enables the constraints that |
@@ -672,8 +704,12 @@ public sealed class BSPrim : BSPhysObject | |||
672 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); | 704 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); |
673 | // Stop all movement | 705 | // Stop all movement |
674 | ZeroMotion(true); | 706 | ZeroMotion(true); |
675 | // Center of mass is at the center of the object | 707 | |
676 | // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); | 708 | // Set various physical properties so other object interact properly |
709 | MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false); | ||
710 | BulletSimAPI.SetFriction2(PhysBody.ptr, matAttrib.friction); | ||
711 | BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution); | ||
712 | |||
677 | // Mass is zero which disables a bunch of physics stuff in Bullet | 713 | // Mass is zero which disables a bunch of physics stuff in Bullet |
678 | UpdatePhysicalMassProperties(0f); | 714 | UpdatePhysicalMassProperties(0f); |
679 | // Set collision detection parameters | 715 | // Set collision detection parameters |
@@ -682,24 +718,27 @@ public sealed class BSPrim : BSPhysObject | |||
682 | BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); | 718 | BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); |
683 | BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); | 719 | BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); |
684 | } | 720 | } |
685 | // There can be special things needed for implementing linksets | 721 | |
686 | Linkset.MakeStatic(this); | ||
687 | // The activation state is 'disabled' so Bullet will not try to act on it. | 722 | // The activation state is 'disabled' so Bullet will not try to act on it. |
688 | BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION); | 723 | // BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION); |
689 | // Start it out sleeping and physical actions could wake it up. | 724 | // Start it out sleeping and physical actions could wake it up. |
690 | // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); | 725 | BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ISLAND_SLEEPING); |
726 | |||
727 | // This collides like a static object | ||
728 | PhysBody.collisionType = CollisionType.Static; | ||
691 | 729 | ||
692 | PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; | 730 | // There can be special things needed for implementing linksets |
693 | PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask; | 731 | Linkset.MakeStatic(this); |
694 | } | 732 | } |
695 | else | 733 | else |
696 | { | 734 | { |
697 | // Not a Bullet static object | 735 | // Not a Bullet static object |
698 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); | 736 | CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); |
699 | 737 | ||
700 | // Set various physical properties so internal dynamic properties will get computed correctly as they are set | 738 | // Set various physical properties so other object interact properly |
701 | BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction); | 739 | MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, true); |
702 | BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution); | 740 | BulletSimAPI.SetFriction2(PhysBody.ptr, matAttrib.friction); |
741 | BulletSimAPI.SetRestitution2(PhysBody.ptr, matAttrib.restitution); | ||
703 | 742 | ||
704 | // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 | 743 | // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 |
705 | // Since this can be called multiple times, only zero forces when becoming physical | 744 | // Since this can be called multiple times, only zero forces when becoming physical |
@@ -727,16 +766,15 @@ public sealed class BSPrim : BSPhysObject | |||
727 | BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); | 766 | BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); |
728 | BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); | 767 | BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); |
729 | 768 | ||
730 | // There might be special things needed for implementing linksets. | 769 | // This collides like an object. |
731 | Linkset.MakeDynamic(this); | 770 | PhysBody.collisionType = CollisionType.Dynamic; |
732 | 771 | ||
733 | // Force activation of the object so Bullet will act on it. | 772 | // Force activation of the object so Bullet will act on it. |
734 | // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. | 773 | // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. |
735 | BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG); | 774 | BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG); |
736 | // BulletSimAPI.Activate2(BSBody.ptr, true); | ||
737 | 775 | ||
738 | PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter; | 776 | // There might be special things needed for implementing linksets. |
739 | PhysBody.collisionMask = CollisionFilterGroups.ObjectMask; | 777 | Linkset.MakeDynamic(this); |
740 | } | 778 | } |
741 | } | 779 | } |
742 | 780 | ||
@@ -763,8 +801,9 @@ public sealed class BSPrim : BSPhysObject | |||
763 | m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); | 801 | m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); |
764 | } | 802 | } |
765 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | 803 | CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); |
766 | PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; | 804 | |
767 | PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; | 805 | // Change collision info from a static object to a ghosty collision object |
806 | PhysBody.collisionType = CollisionType.VolumeDetect; | ||
768 | } | 807 | } |
769 | } | 808 | } |
770 | 809 | ||
@@ -839,15 +878,6 @@ public sealed class BSPrim : BSPhysObject | |||
839 | } | 878 | } |
840 | public override OMV.Vector3 RotationalVelocity { | 879 | public override OMV.Vector3 RotationalVelocity { |
841 | get { | 880 | get { |
842 | /* | ||
843 | OMV.Vector3 pv = OMV.Vector3.Zero; | ||
844 | // if close to zero, report zero | ||
845 | // This is copied from ODE but I'm not sure why it returns zero but doesn't | ||
846 | // zero the property in the physics engine. | ||
847 | if (_rotationalVelocity.ApproxEquals(pv, 0.2f)) | ||
848 | return pv; | ||
849 | */ | ||
850 | |||
851 | return _rotationalVelocity; | 881 | return _rotationalVelocity; |
852 | } | 882 | } |
853 | set { | 883 | set { |
@@ -856,7 +886,8 @@ public sealed class BSPrim : BSPhysObject | |||
856 | PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() | 886 | PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() |
857 | { | 887 | { |
858 | DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); | 888 | DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); |
859 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); | 889 | if (PhysBody.HasPhysicalBody) |
890 | BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); | ||
860 | }); | 891 | }); |
861 | } | 892 | } |
862 | } | 893 | } |
@@ -891,8 +922,11 @@ public sealed class BSPrim : BSPhysObject | |||
891 | _buoyancy = value; | 922 | _buoyancy = value; |
892 | // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 923 | // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
893 | // Buoyancy is faked by changing the gravity applied to the object | 924 | // Buoyancy is faked by changing the gravity applied to the object |
894 | float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); | 925 | if (PhysBody.HasPhysicalBody) |
895 | BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); | 926 | { |
927 | float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); | ||
928 | BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); | ||
929 | } | ||
896 | } | 930 | } |
897 | } | 931 | } |
898 | 932 | ||
@@ -960,7 +994,8 @@ public sealed class BSPrim : BSPhysObject | |||
960 | } | 994 | } |
961 | DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); | 995 | DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); |
962 | if (fSum != OMV.Vector3.Zero) | 996 | if (fSum != OMV.Vector3.Zero) |
963 | BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); | 997 | if (PhysBody.HasPhysicalBody) |
998 | BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); | ||
964 | }); | 999 | }); |
965 | } | 1000 | } |
966 | 1001 | ||
@@ -971,7 +1006,8 @@ public sealed class BSPrim : BSPhysObject | |||
971 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate() | 1006 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate() |
972 | { | 1007 | { |
973 | DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse); | 1008 | DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse); |
974 | BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse); | 1009 | if (PhysBody.HasPhysicalBody) |
1010 | BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse); | ||
975 | }); | 1011 | }); |
976 | } | 1012 | } |
977 | 1013 | ||
@@ -1007,18 +1043,23 @@ public sealed class BSPrim : BSPhysObject | |||
1007 | DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); | 1043 | DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); |
1008 | if (fSum != OMV.Vector3.Zero) | 1044 | if (fSum != OMV.Vector3.Zero) |
1009 | { | 1045 | { |
1010 | BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); | 1046 | if (PhysBody.HasPhysicalBody) |
1047 | BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); | ||
1011 | _torque = fSum; | 1048 | _torque = fSum; |
1012 | } | 1049 | } |
1013 | }); | 1050 | }); |
1014 | } | 1051 | } |
1015 | // A torque impulse. | 1052 | // A torque impulse. |
1053 | // ApplyTorqueImpulse adds torque directly to the angularVelocity. | ||
1054 | // AddAngularForce accumulates the force and applied it to the angular velocity all at once. | ||
1055 | // Computed as: angularVelocity += impulse * inertia; | ||
1016 | public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) | 1056 | public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) |
1017 | { | 1057 | { |
1018 | OMV.Vector3 applyImpulse = impulse; | 1058 | OMV.Vector3 applyImpulse = impulse; |
1019 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() | 1059 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() |
1020 | { | 1060 | { |
1021 | BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); | 1061 | if (PhysBody.HasPhysicalBody) |
1062 | BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); | ||
1022 | }); | 1063 | }); |
1023 | } | 1064 | } |
1024 | 1065 | ||
@@ -1326,7 +1367,7 @@ public sealed class BSPrim : BSPhysObject | |||
1326 | // Rebuild the geometry and object. | 1367 | // Rebuild the geometry and object. |
1327 | // This is called when the shape changes so we need to recreate the mesh/hull. | 1368 | // This is called when the shape changes so we need to recreate the mesh/hull. |
1328 | // Called at taint-time!!! | 1369 | // Called at taint-time!!! |
1329 | private void CreateGeomAndObject(bool forceRebuild) | 1370 | public void CreateGeomAndObject(bool forceRebuild) |
1330 | { | 1371 | { |
1331 | // If this prim is part of a linkset, we must remove and restore the physical | 1372 | // If this prim is part of a linkset, we must remove and restore the physical |
1332 | // links if the body is rebuilt. | 1373 | // links if the body is rebuilt. |
@@ -1336,12 +1377,11 @@ public sealed class BSPrim : BSPhysObject | |||
1336 | // Create the correct physical representation for this type of object. | 1377 | // Create the correct physical representation for this type of object. |
1337 | // Updates PhysBody and PhysShape with the new information. | 1378 | // Updates PhysBody and PhysShape with the new information. |
1338 | // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. | 1379 | // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. |
1339 | // Returns 'true' if either the body or the shape was changed. | ||
1340 | PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) | 1380 | PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) |
1341 | { | 1381 | { |
1342 | // Called if the current prim body is about to be destroyed. | 1382 | // Called if the current prim body is about to be destroyed. |
1343 | // Remove all the physical dependencies on the old body. | 1383 | // Remove all the physical dependencies on the old body. |
1344 | // (Maybe someday make the changing of BSShape an event handled by BSLinkset.) | 1384 | // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) |
1345 | needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); | 1385 | needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); |
1346 | needToRestoreVehicle = _vehicle.RemoveBodyDependencies(this); | 1386 | needToRestoreVehicle = _vehicle.RemoveBodyDependencies(this); |
1347 | }); | 1387 | }); |
@@ -1381,54 +1421,16 @@ public sealed class BSPrim : BSPhysObject | |||
1381 | 1421 | ||
1382 | public override void UpdateProperties(EntityProperties entprop) | 1422 | public override void UpdateProperties(EntityProperties entprop) |
1383 | { | 1423 | { |
1384 | /* | 1424 | // Updates only for individual prims and for the root object of a linkset. |
1385 | UpdatedProperties changed = 0; | 1425 | if (Linkset.IsRoot(this)) |
1386 | // assign to the local variables so the normal set action does not happen | ||
1387 | // if (_position != entprop.Position) | ||
1388 | if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE)) | ||
1389 | { | ||
1390 | _position = entprop.Position; | ||
1391 | changed |= UpdatedProperties.Position; | ||
1392 | } | ||
1393 | // if (_orientation != entprop.Rotation) | ||
1394 | if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE)) | ||
1395 | { | ||
1396 | _orientation = entprop.Rotation; | ||
1397 | changed |= UpdatedProperties.Rotation; | ||
1398 | } | ||
1399 | // if (_velocity != entprop.Velocity) | ||
1400 | if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE)) | ||
1401 | { | ||
1402 | _velocity = entprop.Velocity; | ||
1403 | changed |= UpdatedProperties.Velocity; | ||
1404 | } | ||
1405 | // if (_acceleration != entprop.Acceleration) | ||
1406 | if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE)) | ||
1407 | { | ||
1408 | _acceleration = entprop.Acceleration; | ||
1409 | changed |= UpdatedProperties.Acceleration; | ||
1410 | } | ||
1411 | // if (_rotationalVelocity != entprop.RotationalVelocity) | ||
1412 | if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE)) | ||
1413 | { | ||
1414 | _rotationalVelocity = entprop.RotationalVelocity; | ||
1415 | changed |= UpdatedProperties.RotationalVel; | ||
1416 | } | ||
1417 | if (changed != 0) | ||
1418 | { | 1426 | { |
1419 | // Only update the position of single objects and linkset roots | 1427 | // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet |
1420 | if (Linkset.IsRoot(this)) | 1428 | // TODO: handle physics introduced by Bullet with computed vehicle physics. |
1429 | if (_vehicle.IsActive) | ||
1421 | { | 1430 | { |
1422 | base.RequestPhysicsterseUpdate(); | 1431 | entprop.RotationalVelocity = OMV.Vector3.Zero; |
1423 | } | 1432 | } |
1424 | } | ||
1425 | */ | ||
1426 | |||
1427 | // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. | ||
1428 | 1433 | ||
1429 | // Updates only for individual prims and for the root object of a linkset. | ||
1430 | if (Linkset.IsRoot(this)) | ||
1431 | { | ||
1432 | // Assign directly to the local variables so the normal set action does not happen | 1434 | // Assign directly to the local variables so the normal set action does not happen |
1433 | _position = entprop.Position; | 1435 | _position = entprop.Position; |
1434 | _orientation = entprop.Rotation; | 1436 | _orientation = entprop.Rotation; |
@@ -1437,21 +1439,19 @@ public sealed class BSPrim : BSPhysObject | |||
1437 | _rotationalVelocity = entprop.RotationalVelocity; | 1439 | _rotationalVelocity = entprop.RotationalVelocity; |
1438 | 1440 | ||
1439 | // The sanity check can change the velocity and/or position. | 1441 | // The sanity check can change the velocity and/or position. |
1440 | if (PositionSanityCheck(true)) | 1442 | if (IsPhysical && PositionSanityCheck(true)) |
1441 | { | 1443 | { |
1442 | entprop.Position = _position; | 1444 | entprop.Position = _position; |
1443 | entprop.Velocity = _velocity; | 1445 | entprop.Velocity = _velocity; |
1444 | } | 1446 | } |
1445 | 1447 | ||
1446 | // remember the current and last set values | 1448 | OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG |
1447 | LastEntityProperties = CurrentEntityProperties; | ||
1448 | CurrentEntityProperties = entprop; | ||
1449 | |||
1450 | OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; | ||
1451 | DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", | 1449 | DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", |
1452 | LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); | 1450 | LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); |
1453 | 1451 | ||
1454 | // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG | 1452 | // remember the current and last set values |
1453 | LastEntityProperties = CurrentEntityProperties; | ||
1454 | CurrentEntityProperties = entprop; | ||
1455 | 1455 | ||
1456 | base.RequestPhysicsterseUpdate(); | 1456 | base.RequestPhysicsterseUpdate(); |
1457 | } | 1457 | } |
@@ -1466,7 +1466,7 @@ public sealed class BSPrim : BSPhysObject | |||
1466 | */ | 1466 | */ |
1467 | 1467 | ||
1468 | // The linkset implimentation might want to know about this. | 1468 | // The linkset implimentation might want to know about this. |
1469 | Linkset.UpdateProperties(this); | 1469 | Linkset.UpdateProperties(this, true); |
1470 | } | 1470 | } |
1471 | } | 1471 | } |
1472 | } | 1472 | } |