diff options
author | Robert Adams | 2012-09-13 08:11:54 -0700 |
---|---|---|
committer | Robert Adams | 2012-09-15 15:31:29 -0700 |
commit | 2c5ff9399063080276a23bcd06fb696d653bef2e (patch) | |
tree | 3428eaff2697b562880c75f5f83eafcbb855c93e | |
parent | Add basic asset connector tests to check behaviour for normal, local and temp... (diff) | |
download | opensim-SC-2c5ff9399063080276a23bcd06fb696d653bef2e.zip opensim-SC-2c5ff9399063080276a23bcd06fb696d653bef2e.tar.gz opensim-SC-2c5ff9399063080276a23bcd06fb696d653bef2e.tar.bz2 opensim-SC-2c5ff9399063080276a23bcd06fb696d653bef2e.tar.xz |
BulletSim: Way too many changes in one commit.
Many changes to BSDynamic for readability and commentary.
Linkset hacking for vehicles: don't over mass the root prim.
Add parameter for link constraint solver iterations.
Correct uses of timestep in timescale calculations for vehicles.
Reorganize code/logic for making objects static and dynamic for readability
and use of API2.
Changed most calls in BSPrim to use API2 calls (the new way).
Avatars do not generate default Bullet collision events but do call up
to the simulator for every avatar. Reduces overhead.
Objects added to collision list only if they are processing collisions.
Reduces overhead especially for large numbers of avatars.
Generalize call for water height to GetWaterHeightAtXYZ().
Catch and correct exception getting terrain height when out of bounds.
Correct race condition in Terrain Manager where creation wasn't at taint-time.
Add API calls for constructing compound shapes.
Move NeedsMeshing() logic into object class.
Reorganize logic for object meshing to reduce rebuilding of meshs/hulls.
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 17 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | 16 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 218 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 32 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | 2 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 196 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 67 | ||||
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs | 60 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 29 |
9 files changed, 351 insertions, 286 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index fa22c78..a9b1365 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -131,8 +131,6 @@ public class BSCharacter : BSPhysObject | |||
131 | BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); | 131 | BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy); |
132 | 132 | ||
133 | BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID)); | 133 | BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID)); |
134 | // avatars get all collisions no matter what (makes walking on ground and such work) | ||
135 | BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
136 | }); | 134 | }); |
137 | 135 | ||
138 | return; | 136 | return; |
@@ -480,11 +478,10 @@ public class BSCharacter : BSPhysObject | |||
480 | // Stop collision events | 478 | // Stop collision events |
481 | public override void UnSubscribeEvents() { | 479 | public override void UnSubscribeEvents() { |
482 | _subscribedEventsMs = 0; | 480 | _subscribedEventsMs = 0; |
483 | // Avatars get all their collision events | 481 | Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate() |
484 | // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate() | 482 | { |
485 | // { | 483 | BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); |
486 | // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | 484 | }); |
487 | // }); | ||
488 | } | 485 | } |
489 | // Return 'true' if someone has subscribed to events | 486 | // Return 'true' if someone has subscribed to events |
490 | public override bool SubscribedEvents() { | 487 | public override bool SubscribedEvents() { |
@@ -532,10 +529,12 @@ public class BSCharacter : BSPhysObject | |||
532 | // The collision, if it should be reported to the character, is placed in a collection | 529 | // The collision, if it should be reported to the character, is placed in a collection |
533 | // that will later be sent to the simulator when SendCollisions() is called. | 530 | // that will later be sent to the simulator when SendCollisions() is called. |
534 | CollisionEventUpdate collisionCollection = null; | 531 | CollisionEventUpdate collisionCollection = null; |
535 | public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) | 532 | public override bool Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) |
536 | { | 533 | { |
537 | // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); | 534 | // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); |
538 | 535 | ||
536 | bool ret = false; | ||
537 | |||
539 | // The following makes IsColliding() and IsCollidingGround() work | 538 | // The following makes IsColliding() and IsCollidingGround() work |
540 | _collidingStep = Scene.SimulationStep; | 539 | _collidingStep = Scene.SimulationStep; |
541 | if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) | 540 | if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) |
@@ -553,8 +552,10 @@ public class BSCharacter : BSPhysObject | |||
553 | if (collisionCollection == null) | 552 | if (collisionCollection == null) |
554 | collisionCollection = new CollisionEventUpdate(); | 553 | collisionCollection = new CollisionEventUpdate(); |
555 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); | 554 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); |
555 | ret = true; | ||
556 | } | 556 | } |
557 | } | 557 | } |
558 | return ret; | ||
558 | } | 559 | } |
559 | 560 | ||
560 | public override void SendCollisions() | 561 | public override void SendCollisions() |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index 2e15ced..1376a29 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | |||
@@ -74,6 +74,17 @@ public abstract class BSConstraint : IDisposable | |||
74 | return ret; | 74 | return ret; |
75 | } | 75 | } |
76 | 76 | ||
77 | public virtual bool SetSolverIterations(float cnt) | ||
78 | { | ||
79 | bool ret = false; | ||
80 | if (m_enabled) | ||
81 | { | ||
82 | BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.Ptr, cnt); | ||
83 | ret = true; | ||
84 | } | ||
85 | return ret; | ||
86 | } | ||
87 | |||
77 | public virtual bool CalculateTransforms() | 88 | public virtual bool CalculateTransforms() |
78 | { | 89 | { |
79 | bool ret = false; | 90 | bool ret = false; |
@@ -96,12 +107,9 @@ public abstract class BSConstraint : IDisposable | |||
96 | ret = CalculateTransforms(); | 107 | ret = CalculateTransforms(); |
97 | if (ret) | 108 | if (ret) |
98 | { | 109 | { |
99 | // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}", | ||
100 | // BSScene.DetailLogZero, Body1.ID, Body2.ID); | ||
101 | |||
102 | // Setting an object's mass to zero (making it static like when it's selected) | 110 | // Setting an object's mass to zero (making it static like when it's selected) |
103 | // automatically disables the constraints. | 111 | // automatically disables the constraints. |
104 | // If enabled, be sure to set the constraint itself to enabled. | 112 | // If the link is enabled, be sure to set the constraint itself to enabled. |
105 | BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); | 113 | BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); |
106 | } | 114 | } |
107 | else | 115 | else |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 8169e99..098fea7 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -80,7 +80,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
80 | // Linear properties | 80 | // Linear properties |
81 | private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time | 81 | private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time |
82 | private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL | 82 | private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL |
83 | private Vector3 m_dir = Vector3.Zero; // velocity applied to body | 83 | private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body |
84 | private Vector3 m_linearFrictionTimescale = Vector3.Zero; | 84 | private Vector3 m_linearFrictionTimescale = Vector3.Zero; |
85 | private float m_linearMotorDecayTimescale = 0; | 85 | private float m_linearMotorDecayTimescale = 0; |
86 | private float m_linearMotorTimescale = 0; | 86 | private float m_linearMotorTimescale = 0; |
@@ -475,32 +475,33 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
475 | frcount = 0; | 475 | frcount = 0; |
476 | 476 | ||
477 | MoveLinear(pTimestep); | 477 | MoveLinear(pTimestep); |
478 | MoveAngular(pTimestep); | 478 | // MoveAngular(pTimestep); |
479 | LimitRotation(pTimestep); | 479 | LimitRotation(pTimestep); |
480 | 480 | ||
481 | // remember the position so next step we can limit absolute movement effects | ||
482 | m_lastPositionVector = m_prim.Position; | ||
483 | |||
481 | VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", | 484 | VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", |
482 | m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); | 485 | m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); |
483 | }// end Step | 486 | }// end Step |
484 | 487 | ||
485 | private void MoveLinear(float pTimestep) | 488 | private void MoveLinear(float pTimestep) |
486 | { | 489 | { |
487 | // requested m_linearMotorDirection is significant | 490 | // m_linearMotorDirection is the direction we are moving relative to the vehicle coordinates |
488 | // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) | 491 | // m_lastLinearVelocityVector is the speed we are moving in that direction |
489 | if (m_linearMotorDirection.LengthSquared() > 0.0001f) | 492 | if (m_linearMotorDirection.LengthSquared() > 0.001f) |
490 | { | 493 | { |
491 | Vector3 origDir = m_linearMotorDirection; | 494 | Vector3 origDir = m_linearMotorDirection; |
492 | Vector3 origVel = m_lastLinearVelocityVector; | 495 | Vector3 origVel = m_lastLinearVelocityVector; |
493 | 496 | ||
494 | // add drive to body | 497 | // add drive to body |
495 | // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); | 498 | // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale / pTimestep); |
496 | Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale); | 499 | Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale / pTimestep); |
497 | // lastLinearVelocityVector is the current body velocity vector? | 500 | // lastLinearVelocityVector is the current body velocity vector |
498 | // RA: Not sure what the *10 is for. A correction for pTimestep? | 501 | // RA: Not sure what the *10 is for. A correction for pTimestep? |
499 | // m_lastLinearVelocityVector += (addAmount*10); | 502 | // m_lastLinearVelocityVector += (addAmount*10); |
500 | m_lastLinearVelocityVector += addAmount; | 503 | m_lastLinearVelocityVector += addAmount; |
501 | 504 | ||
502 | // This will work temporarily, but we really need to compare speed on an axis | ||
503 | // KF: Limit body velocity to applied velocity? | ||
504 | // Limit the velocity vector to less than the last set linear motor direction | 505 | // Limit the velocity vector to less than the last set linear motor direction |
505 | if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) | 506 | if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) |
506 | m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; | 507 | m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; |
@@ -509,34 +510,29 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
509 | if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) | 510 | if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) |
510 | m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; | 511 | m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; |
511 | 512 | ||
513 | /* | ||
512 | // decay applied velocity | 514 | // decay applied velocity |
513 | Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); | 515 | Vector3 decayfraction = Vector3.One/(m_linearMotorDecayTimescale / pTimestep); |
516 | // (RA: do not know where the 0.5f comes from) | ||
514 | m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; | 517 | m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; |
515 | |||
516 | /* | ||
517 | Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale; | ||
518 | m_lastLinearVelocityVector += addAmount; | ||
519 | |||
520 | float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale); | ||
521 | m_linearMotorDirection *= decayfraction; | ||
522 | |||
523 | */ | 518 | */ |
519 | float keepfraction = 1.0f - (1.0f / (m_linearMotorDecayTimescale / pTimestep)); | ||
520 | m_linearMotorDirection *= keepfraction; | ||
524 | 521 | ||
525 | VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", | 522 | VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},notDecay={4},dir={5},vel={6}", |
526 | m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); | 523 | m_prim.LocalID, origDir, origVel, addAmount, keepfraction, m_linearMotorDirection, m_lastLinearVelocityVector); |
527 | } | 524 | } |
528 | else | 525 | else |
529 | { | 526 | { |
530 | // if what remains of applied is small, zero it. | 527 | // if what remains of direction is very small, zero it. |
531 | // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) | ||
532 | // m_lastLinearVelocityVector = Vector3.Zero; | ||
533 | m_linearMotorDirection = Vector3.Zero; | 528 | m_linearMotorDirection = Vector3.Zero; |
534 | m_lastLinearVelocityVector = Vector3.Zero; | 529 | m_lastLinearVelocityVector = Vector3.Zero; |
530 | VDetailLog("{0},MoveLinear,zeroed", m_prim.LocalID); | ||
535 | } | 531 | } |
536 | 532 | ||
537 | // convert requested object velocity to object relative vector | 533 | // convert requested object velocity to object relative vector |
538 | Quaternion rotq = m_prim.Orientation; | 534 | Quaternion rotq = m_prim.Orientation; |
539 | m_dir = m_lastLinearVelocityVector * rotq; | 535 | m_newVelocity = m_lastLinearVelocityVector * rotq; |
540 | 536 | ||
541 | // Add the various forces into m_dir which will be our new direction vector (velocity) | 537 | // Add the various forces into m_dir which will be our new direction vector (velocity) |
542 | 538 | ||
@@ -544,60 +540,31 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
544 | // KF: So far I have found no good method to combine a script-requested | 540 | // KF: So far I have found no good method to combine a script-requested |
545 | // .Z velocity and gravity. Therefore only 0g will used script-requested | 541 | // .Z velocity and gravity. Therefore only 0g will used script-requested |
546 | // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. | 542 | // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. |
547 | Vector3 grav = Vector3.Zero; | ||
548 | // There is some gravity, make a gravity force vector that is applied after object velocity. | 543 | // There is some gravity, make a gravity force vector that is applied after object velocity. |
549 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; | 544 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; |
550 | grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); | 545 | Vector3 grav = m_prim.Scene.DefaultGravity * (m_prim.Mass * (1f - m_VehicleBuoyancy)); |
546 | |||
547 | /* | ||
548 | * RA: Not sure why one would do this | ||
551 | // Preserve the current Z velocity | 549 | // Preserve the current Z velocity |
552 | Vector3 vel_now = m_prim.Velocity; | 550 | Vector3 vel_now = m_prim.Velocity; |
553 | m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity | 551 | m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity |
552 | */ | ||
554 | 553 | ||
555 | Vector3 pos = m_prim.Position; | 554 | Vector3 pos = m_prim.Position; |
556 | Vector3 posChange = pos; | ||
557 | // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); | 555 | // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); |
558 | double Zchange = Math.Abs(posChange.Z); | ||
559 | if (m_BlockingEndPoint != Vector3.Zero) | ||
560 | { | ||
561 | bool changed = false; | ||
562 | if (pos.X >= (m_BlockingEndPoint.X - (float)1)) | ||
563 | { | ||
564 | pos.X -= posChange.X + 1; | ||
565 | changed = true; | ||
566 | } | ||
567 | if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) | ||
568 | { | ||
569 | pos.Y -= posChange.Y + 1; | ||
570 | changed = true; | ||
571 | } | ||
572 | if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) | ||
573 | { | ||
574 | pos.Z -= posChange.Z + 1; | ||
575 | changed = true; | ||
576 | } | ||
577 | if (pos.X <= 0) | ||
578 | { | ||
579 | pos.X += posChange.X + 1; | ||
580 | changed = true; | ||
581 | } | ||
582 | if (pos.Y <= 0) | ||
583 | { | ||
584 | pos.Y += posChange.Y + 1; | ||
585 | changed = true; | ||
586 | } | ||
587 | if (changed) | ||
588 | { | ||
589 | m_prim.Position = pos; | ||
590 | VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", | ||
591 | m_prim.LocalID, m_BlockingEndPoint, posChange, pos); | ||
592 | } | ||
593 | } | ||
594 | 556 | ||
595 | // If below the terrain, move us above the ground a little. | 557 | // If below the terrain, move us above the ground a little. |
596 | if (pos.Z < m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos)) | 558 | float terrainHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos); |
559 | // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. | ||
560 | // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. | ||
561 | // Vector3 rotatedSize = m_prim.Size * m_prim.Orientation; | ||
562 | // if (rotatedSize.Z < terrainHeight) | ||
563 | if (pos.Z < terrainHeight) | ||
597 | { | 564 | { |
598 | pos.Z = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2; | 565 | pos.Z = terrainHeight + 2; |
599 | m_prim.Position = pos; | 566 | m_prim.Position = pos; |
600 | VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); | 567 | VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", m_prim.LocalID, terrainHeight, pos); |
601 | } | 568 | } |
602 | 569 | ||
603 | // Check if hovering | 570 | // Check if hovering |
@@ -606,11 +573,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
606 | // We should hover, get the target height | 573 | // We should hover, get the target height |
607 | if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) | 574 | if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) |
608 | { | 575 | { |
609 | m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; | 576 | m_VhoverTargetHeight = m_prim.Scene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight; |
610 | } | 577 | } |
611 | if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) | 578 | if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) |
612 | { | 579 | { |
613 | m_VhoverTargetHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; | 580 | m_VhoverTargetHeight = terrainHeight + m_VhoverHeight; |
614 | } | 581 | } |
615 | if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) | 582 | if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) |
616 | { | 583 | { |
@@ -635,82 +602,92 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
635 | // Replace Vertical speed with correction figure if significant | 602 | // Replace Vertical speed with correction figure if significant |
636 | if (Math.Abs(herr0) > 0.01f) | 603 | if (Math.Abs(herr0) > 0.01f) |
637 | { | 604 | { |
638 | m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); | 605 | m_newVelocity.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); |
639 | //KF: m_VhoverEfficiency is not yet implemented | 606 | //KF: m_VhoverEfficiency is not yet implemented |
640 | } | 607 | } |
641 | else | 608 | else |
642 | { | 609 | { |
643 | m_dir.Z = 0f; | 610 | m_newVelocity.Z = 0f; |
644 | } | 611 | } |
645 | } | 612 | } |
646 | 613 | ||
647 | VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); | 614 | VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight); |
615 | } | ||
648 | 616 | ||
649 | // m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped | 617 | Vector3 posChange = pos - m_lastPositionVector; |
650 | // m_VhoverTimescale = 0f; // time to acheive height | 618 | if (m_BlockingEndPoint != Vector3.Zero) |
651 | // pTimestep is time since last frame,in secs | 619 | { |
620 | bool changed = false; | ||
621 | if (pos.X >= (m_BlockingEndPoint.X - (float)1)) | ||
622 | { | ||
623 | pos.X -= posChange.X + 1; | ||
624 | changed = true; | ||
625 | } | ||
626 | if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) | ||
627 | { | ||
628 | pos.Y -= posChange.Y + 1; | ||
629 | changed = true; | ||
630 | } | ||
631 | if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) | ||
632 | { | ||
633 | pos.Z -= posChange.Z + 1; | ||
634 | changed = true; | ||
635 | } | ||
636 | if (pos.X <= 0) | ||
637 | { | ||
638 | pos.X += posChange.X + 1; | ||
639 | changed = true; | ||
640 | } | ||
641 | if (pos.Y <= 0) | ||
642 | { | ||
643 | pos.Y += posChange.Y + 1; | ||
644 | changed = true; | ||
645 | } | ||
646 | if (changed) | ||
647 | { | ||
648 | m_prim.Position = pos; | ||
649 | VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", | ||
650 | m_prim.LocalID, m_BlockingEndPoint, posChange, pos); | ||
651 | } | ||
652 | } | 652 | } |
653 | 653 | ||
654 | float Zchange = Math.Abs(posChange.Z); | ||
654 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) | 655 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) |
655 | { | 656 | { |
656 | //Start Experimental Values | ||
657 | if (Zchange > .3) | 657 | if (Zchange > .3) |
658 | { | ||
659 | grav.Z = (float)(grav.Z * 3); | 658 | grav.Z = (float)(grav.Z * 3); |
660 | } | ||
661 | if (Zchange > .15) | 659 | if (Zchange > .15) |
662 | { | ||
663 | grav.Z = (float)(grav.Z * 2); | 660 | grav.Z = (float)(grav.Z * 2); |
664 | } | ||
665 | if (Zchange > .75) | 661 | if (Zchange > .75) |
666 | { | ||
667 | grav.Z = (float)(grav.Z * 1.5); | 662 | grav.Z = (float)(grav.Z * 1.5); |
668 | } | ||
669 | if (Zchange > .05) | 663 | if (Zchange > .05) |
670 | { | ||
671 | grav.Z = (float)(grav.Z * 1.25); | 664 | grav.Z = (float)(grav.Z * 1.25); |
672 | } | ||
673 | if (Zchange > .025) | 665 | if (Zchange > .025) |
674 | { | ||
675 | grav.Z = (float)(grav.Z * 1.125); | 666 | grav.Z = (float)(grav.Z * 1.125); |
676 | } | 667 | float postemp = (pos.Z - terrainHeight); |
677 | float terraintemp = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos); | ||
678 | float postemp = (pos.Z - terraintemp); | ||
679 | if (postemp > 2.5f) | 668 | if (postemp > 2.5f) |
680 | { | ||
681 | grav.Z = (float)(grav.Z * 1.037125); | 669 | grav.Z = (float)(grav.Z * 1.037125); |
682 | } | ||
683 | VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); | 670 | VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); |
684 | //End Experimental Values | ||
685 | } | 671 | } |
686 | if ((m_flags & (VehicleFlag.NO_X)) != 0) | 672 | if ((m_flags & (VehicleFlag.NO_X)) != 0) |
687 | { | 673 | m_newVelocity.X = 0; |
688 | m_dir.X = 0; | ||
689 | } | ||
690 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) | 674 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) |
691 | { | 675 | m_newVelocity.Y = 0; |
692 | m_dir.Y = 0; | ||
693 | } | ||
694 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) | 676 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) |
695 | { | 677 | m_newVelocity.Z = 0; |
696 | m_dir.Z = 0; | ||
697 | } | ||
698 | |||
699 | m_lastPositionVector = m_prim.Position; | ||
700 | 678 | ||
701 | // Apply velocity | 679 | // Apply velocity |
702 | m_prim.Velocity = m_dir; | 680 | m_prim.Velocity = m_newVelocity; |
703 | // apply gravity force | 681 | // apply gravity force |
704 | // Why is this set here? The physics engine already does gravity. | 682 | // Why is this set here? The physics engine already does gravity. |
705 | // m_prim.AddForce(grav, false); | 683 | // m_prim.AddForce(grav, false); |
706 | // m_prim.Force = grav; | ||
707 | 684 | ||
708 | // Apply friction | 685 | // Apply friction |
709 | Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); | 686 | Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); |
710 | m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; | 687 | m_lastLinearVelocityVector *= keepFraction; |
711 | 688 | ||
712 | VDetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", | 689 | VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}", |
713 | m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); | 690 | m_prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction); |
714 | 691 | ||
715 | } // end MoveLinear() | 692 | } // end MoveLinear() |
716 | 693 | ||
@@ -735,17 +712,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
735 | // There are m_angularMotorApply steps. | 712 | // There are m_angularMotorApply steps. |
736 | Vector3 origAngularVelocity = m_angularMotorVelocity; | 713 | Vector3 origAngularVelocity = m_angularMotorVelocity; |
737 | // ramp up to new value | 714 | // ramp up to new value |
738 | // current velocity += error / (time to get there / step interval) | 715 | // current velocity += error / ( time to get there / step interval) |
739 | // requested speed - last motor speed | 716 | // requested speed - last motor speed |
740 | m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); | 717 | m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); |
741 | m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); | 718 | m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); |
742 | m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); | 719 | m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); |
743 | 720 | ||
744 | VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", | 721 | VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},dir={5},vel={6}", |
745 | m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); | 722 | m_prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); |
746 | 723 | ||
747 | m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected | 724 | // This is done so that if script request rate is less than phys frame rate the expected |
748 | // velocity may still be acheived. | 725 | // velocity may still be acheived. |
726 | m_angularMotorApply--; | ||
749 | } | 727 | } |
750 | else | 728 | else |
751 | { | 729 | { |
@@ -760,7 +738,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
760 | Vector3 vertattr = Vector3.Zero; | 738 | Vector3 vertattr = Vector3.Zero; |
761 | if (m_verticalAttractionTimescale < 300) | 739 | if (m_verticalAttractionTimescale < 300) |
762 | { | 740 | { |
763 | float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); | 741 | float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep); |
764 | // get present body rotation | 742 | // get present body rotation |
765 | Quaternion rotq = m_prim.Orientation; | 743 | Quaternion rotq = m_prim.Orientation; |
766 | // make a vector pointing up | 744 | // make a vector pointing up |
@@ -863,16 +841,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
863 | m_rot.Y = 0; | 841 | m_rot.Y = 0; |
864 | changed = true; | 842 | changed = true; |
865 | } | 843 | } |
866 | if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) | ||
867 | { | ||
868 | m_rot.X = 0; | ||
869 | m_rot.Y = 0; | ||
870 | changed = true; | ||
871 | } | ||
872 | if (changed) | 844 | if (changed) |
845 | { | ||
873 | m_prim.Orientation = m_rot; | 846 | m_prim.Orientation = m_rot; |
847 | VDetailLog("{0},LimitRotation,done,orig={1},new={2}", m_prim.LocalID, rotq, m_rot); | ||
848 | } | ||
874 | 849 | ||
875 | VDetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot); | ||
876 | } | 850 | } |
877 | 851 | ||
878 | // Invoke the detailed logger and output something if it's enabled. | 852 | // Invoke the detailed logger and output something if it's enabled. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 5f6601d..dc1de6c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -206,7 +206,7 @@ public class BSLinkset | |||
206 | // its internal properties. | 206 | // its internal properties. |
207 | public void Refresh(BSPhysObject requestor) | 207 | public void Refresh(BSPhysObject requestor) |
208 | { | 208 | { |
209 | // If there are no children, there aren't any constraints to recompute | 209 | // If there are no children, there can't be any constraints to recompute |
210 | if (!HasAnyChildren) | 210 | if (!HasAnyChildren) |
211 | return; | 211 | return; |
212 | 212 | ||
@@ -225,11 +225,12 @@ public class BSLinkset | |||
225 | // from a linkset to make sure the constraints know about the new mass and | 225 | // from a linkset to make sure the constraints know about the new mass and |
226 | // geometry. | 226 | // geometry. |
227 | // Must only be called at taint time!! | 227 | // Must only be called at taint time!! |
228 | private bool RecomputeLinksetConstraintVariables() | 228 | private void RecomputeLinksetConstraintVariables() |
229 | { | 229 | { |
230 | float linksetMass = LinksetMass; | 230 | float linksetMass = LinksetMass; |
231 | lock (m_linksetActivityLock) | 231 | lock (m_linksetActivityLock) |
232 | { | 232 | { |
233 | bool somethingMissing = false; | ||
233 | foreach (BSPhysObject child in m_children) | 234 | foreach (BSPhysObject child in m_children) |
234 | { | 235 | { |
235 | BSConstraint constrain; | 236 | BSConstraint constrain; |
@@ -241,16 +242,29 @@ public class BSLinkset | |||
241 | } | 242 | } |
242 | else | 243 | else |
243 | { | 244 | { |
244 | // Non-fatal error that can happen when children are being added to the linkset but | 245 | // Non-fatal error that happens when children are being added to the linkset but |
245 | // their constraints have not been created yet. | 246 | // their constraints have not been created yet. |
246 | // Caused by the fact that m_children is built at run time but building constraints | 247 | // Caused by the fact that m_children is built at run time but building constraints |
247 | // happens at taint time. | 248 | // happens at taint time. |
248 | // m_physicsScene.Logger.ErrorFormat("{0} RecomputeLinksetConstraintVariables: constraint not found for root={1}, child={2}", | 249 | somethingMissing = true; |
249 | // LogHeader, m_linksetRoot.Body.ID, child.Body.ID); | 250 | break; |
250 | } | 251 | } |
251 | } | 252 | } |
253 | |||
254 | // If the whole linkset is not here, doesn't make sense to recompute the root prim now. | ||
255 | if (!somethingMissing) | ||
256 | { | ||
257 | // The root prim takes on the weight of the whole linkset | ||
258 | /* | ||
259 | OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(LinksetRoot.BSShape.Ptr, linksetMass); | ||
260 | BulletSimAPI.SetMassProps2(LinksetRoot.BSBody.Ptr, linksetMass, inertia); | ||
261 | OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); | ||
262 | BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity); | ||
263 | BulletSimAPI.UpdateInertiaTensor2(LinksetRoot.BSBody.Ptr); | ||
264 | */ | ||
265 | } | ||
252 | } | 266 | } |
253 | return false; | 267 | return; |
254 | } | 268 | } |
255 | 269 | ||
256 | // I am the root of a linkset and a new child is being added | 270 | // I am the root of a linkset and a new child is being added |
@@ -296,9 +310,9 @@ public class BSLinkset | |||
296 | DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); | 310 | DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); |
297 | 311 | ||
298 | PhysicallyUnlinkAChildFromRoot(rootx, childx); | 312 | PhysicallyUnlinkAChildFromRoot(rootx, childx); |
313 | RecomputeLinksetConstraintVariables(); | ||
299 | }); | 314 | }); |
300 | 315 | ||
301 | RecomputeLinksetConstraintVariables(); | ||
302 | } | 316 | } |
303 | else | 317 | else |
304 | { | 318 | { |
@@ -377,6 +391,10 @@ public class BSLinkset | |||
377 | PhysicsScene.Params.linkConstraintTransMotorMaxVel, | 391 | PhysicsScene.Params.linkConstraintTransMotorMaxVel, |
378 | PhysicsScene.Params.linkConstraintTransMotorMaxForce); | 392 | PhysicsScene.Params.linkConstraintTransMotorMaxForce); |
379 | constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); | 393 | constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); |
394 | if (PhysicsScene.Params.linkConstraintSolverIterations != 0f) | ||
395 | { | ||
396 | constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); | ||
397 | } | ||
380 | 398 | ||
381 | RecomputeLinksetConstraintVariables(); | 399 | RecomputeLinksetConstraintVariables(); |
382 | } | 400 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index e411fcb..969c53e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | |||
@@ -41,7 +41,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
41 | { | 41 | { |
42 | public abstract BSLinkset Linkset { get; set; } | 42 | public abstract BSLinkset Linkset { get; set; } |
43 | 43 | ||
44 | public abstract void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, | 44 | public abstract bool Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, |
45 | OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth); | 45 | OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth); |
46 | public abstract void SendCollisions(); | 46 | public abstract void SendCollisions(); |
47 | 47 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 6d0af63..481a8db 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -136,11 +136,11 @@ public sealed class BSPrim : BSPhysObject | |||
136 | Linkset = new BSLinkset(Scene, this); // a linkset of one | 136 | Linkset = new BSLinkset(Scene, this); // a linkset of one |
137 | _vehicle = new BSDynamics(Scene, this); // add vehicleness | 137 | _vehicle = new BSDynamics(Scene, this); // add vehicleness |
138 | _mass = CalculateMass(); | 138 | _mass = CalculateMass(); |
139 | // do the actual object creation at taint time | ||
140 | DetailLog("{0},BSPrim.constructor,call", LocalID); | 139 | DetailLog("{0},BSPrim.constructor,call", LocalID); |
140 | // do the actual object creation at taint time | ||
141 | _scene.TaintedObject("BSPrim.create", delegate() | 141 | _scene.TaintedObject("BSPrim.create", delegate() |
142 | { | 142 | { |
143 | RecreateGeomAndObject(); | 143 | CreateGeomAndObject(true); |
144 | 144 | ||
145 | // Get the pointer to the physical body for this object. | 145 | // Get the pointer to the physical body for this object. |
146 | // At the moment, we're still letting BulletSim manage the creation and destruction | 146 | // At the moment, we're still letting BulletSim manage the creation and destruction |
@@ -186,9 +186,10 @@ public sealed class BSPrim : BSPhysObject | |||
186 | _scene.TaintedObject("BSPrim.setSize", delegate() | 186 | _scene.TaintedObject("BSPrim.setSize", delegate() |
187 | { | 187 | { |
188 | _mass = CalculateMass(); // changing size changes the mass | 188 | _mass = CalculateMass(); // changing size changes the mass |
189 | BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); | 189 | // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct |
190 | DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); | 190 | // scale and margins are set. |
191 | RecreateGeomAndObject(); | 191 | CreateGeomAndObject(true); |
192 | DetailLog("{0}: BSPrim.setSize: size={1}, scale={2}, mass={3}, physical={4}", LocalID, _size, _scale, _mass, IsPhysical); | ||
192 | }); | 193 | }); |
193 | } | 194 | } |
194 | } | 195 | } |
@@ -198,7 +199,7 @@ public sealed class BSPrim : BSPhysObject | |||
198 | _scene.TaintedObject("BSPrim.setShape", delegate() | 199 | _scene.TaintedObject("BSPrim.setShape", delegate() |
199 | { | 200 | { |
200 | _mass = CalculateMass(); // changing the shape changes the mass | 201 | _mass = CalculateMass(); // changing the shape changes the mass |
201 | RecreateGeomAndObject(); | 202 | CreateGeomAndObject(false); |
202 | }); | 203 | }); |
203 | } | 204 | } |
204 | } | 205 | } |
@@ -279,7 +280,7 @@ public sealed class BSPrim : BSPhysObject | |||
279 | get { | 280 | get { |
280 | if (!Linkset.IsRoot(this)) | 281 | if (!Linkset.IsRoot(this)) |
281 | // child prims move around based on their parent. Need to get the latest location | 282 | // child prims move around based on their parent. Need to get the latest location |
282 | _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); | 283 | _position = BulletSimAPI.GetPosition2(BSBody.Ptr); |
283 | 284 | ||
284 | // don't do the GetObjectPosition for root elements because this function is called a zillion times | 285 | // don't do the GetObjectPosition for root elements because this function is called a zillion times |
285 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); | 286 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); |
@@ -291,7 +292,7 @@ public sealed class BSPrim : BSPhysObject | |||
291 | _scene.TaintedObject("BSPrim.setPosition", delegate() | 292 | _scene.TaintedObject("BSPrim.setPosition", delegate() |
292 | { | 293 | { |
293 | DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 294 | DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
294 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); | 295 | BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation); |
295 | }); | 296 | }); |
296 | } | 297 | } |
297 | } | 298 | } |
@@ -302,7 +303,8 @@ public sealed class BSPrim : BSPhysObject | |||
302 | { | 303 | { |
303 | get | 304 | get |
304 | { | 305 | { |
305 | return Linkset.LinksetMass; | 306 | // return Linkset.LinksetMass; |
307 | return _mass; | ||
306 | } | 308 | } |
307 | } | 309 | } |
308 | 310 | ||
@@ -328,7 +330,6 @@ public sealed class BSPrim : BSPhysObject | |||
328 | _scene.TaintedObject("BSPrim.setForce", delegate() | 330 | _scene.TaintedObject("BSPrim.setForce", delegate() |
329 | { | 331 | { |
330 | DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); | 332 | DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); |
331 | // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); | ||
332 | BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); | 333 | BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force); |
333 | }); | 334 | }); |
334 | } | 335 | } |
@@ -406,7 +407,7 @@ public sealed class BSPrim : BSPhysObject | |||
406 | _scene.TaintedObject("BSPrim.setVelocity", delegate() | 407 | _scene.TaintedObject("BSPrim.setVelocity", delegate() |
407 | { | 408 | { |
408 | DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); | 409 | DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); |
409 | BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); | 410 | BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, _velocity); |
410 | }); | 411 | }); |
411 | } | 412 | } |
412 | } | 413 | } |
@@ -430,7 +431,7 @@ public sealed class BSPrim : BSPhysObject | |||
430 | if (!Linkset.IsRoot(this)) | 431 | if (!Linkset.IsRoot(this)) |
431 | { | 432 | { |
432 | // Children move around because tied to parent. Get a fresh value. | 433 | // Children move around because tied to parent. Get a fresh value. |
433 | _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); | 434 | _orientation = BulletSimAPI.GetOrientation2(BSBody.Ptr); |
434 | } | 435 | } |
435 | return _orientation; | 436 | return _orientation; |
436 | } | 437 | } |
@@ -441,7 +442,7 @@ public sealed class BSPrim : BSPhysObject | |||
441 | { | 442 | { |
442 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); | 443 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); |
443 | DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 444 | DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
444 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); | 445 | BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation); |
445 | }); | 446 | }); |
446 | } | 447 | } |
447 | } | 448 | } |
@@ -483,31 +484,37 @@ public sealed class BSPrim : BSPhysObject | |||
483 | { | 484 | { |
484 | // If it's becoming dynamic, it will need hullness | 485 | // If it's becoming dynamic, it will need hullness |
485 | VerifyCorrectPhysicalShape(); | 486 | VerifyCorrectPhysicalShape(); |
487 | UpdatePhysicalParameters(); | ||
488 | } | ||
486 | 489 | ||
490 | private void UpdatePhysicalParameters() | ||
491 | { | ||
492 | /* | ||
487 | // Bullet wants static objects to have a mass of zero | 493 | // Bullet wants static objects to have a mass of zero |
488 | float mass = IsStatic ? 0f : _mass; | 494 | float mass = IsStatic ? 0f : _mass; |
489 | 495 | ||
490 | BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); | 496 | BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); |
491 | /* | 497 | */ |
492 | BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr); | 498 | BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr); |
493 | 499 | ||
494 | // Set up the object physicalness (static or dynamic) | 500 | // Set up the object physicalness (does gravity and collisions move this object) |
495 | MakeDynamic(); | 501 | MakeDynamic(IsStatic); |
496 | 502 | ||
497 | // Make solid or not and arrange for collisions, etc | 503 | // Make solid or not (do things bounce off or pass through this object) |
498 | MakeSolid(); | 504 | MakeSolid(IsSolid); |
499 | 505 | ||
500 | m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr); | 506 | // Arrange for collisions events if the simulator wants them |
507 | EnableCollisions(SubscribedEvents()); | ||
501 | 508 | ||
502 | BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr); | 509 | BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr); |
503 | */ | ||
504 | 510 | ||
505 | // Recompute any linkset parameters. | 511 | // Recompute any linkset parameters. |
506 | // When going from non-physical to physical, this re-enables the constraints that | 512 | // When going from non-physical to physical, this re-enables the constraints that |
507 | // had been automatically disabled when the mass was set to zero. | 513 | // had been automatically disabled when the mass was set to zero. |
508 | Linkset.Refresh(this); | 514 | Linkset.Refresh(this); |
509 | 515 | ||
510 | DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, m_currentCollisionFlags); | 516 | DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,static={1},solid={2},mass={3}, cf={4}", |
517 | LocalID, IsStatic, IsSolid, _mass, m_currentCollisionFlags); | ||
511 | } | 518 | } |
512 | 519 | ||
513 | // "Making dynamic" means changing to and from static. | 520 | // "Making dynamic" means changing to and from static. |
@@ -515,12 +522,12 @@ public sealed class BSPrim : BSPhysObject | |||
515 | // When dynamic, the object can fall and be pushed by others. | 522 | // When dynamic, the object can fall and be pushed by others. |
516 | // This is independent of its 'solidness' which controls what passes through | 523 | // This is independent of its 'solidness' which controls what passes through |
517 | // this object and what interacts with it. | 524 | // this object and what interacts with it. |
518 | private void MakeDynamic() | 525 | private void MakeDynamic(bool makeStatic) |
519 | { | 526 | { |
520 | if (IsStatic) | 527 | if (makeStatic) |
521 | { | 528 | { |
522 | // Become a Bullet 'static' object type | 529 | // Become a Bullet 'static' object type |
523 | BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); | 530 | m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); |
524 | // Stop all movement | 531 | // Stop all movement |
525 | BulletSimAPI.ClearAllForces2(BSBody.Ptr); | 532 | BulletSimAPI.ClearAllForces2(BSBody.Ptr); |
526 | // Mass is zero which disables a bunch of physics stuff in Bullet | 533 | // Mass is zero which disables a bunch of physics stuff in Bullet |
@@ -533,12 +540,11 @@ public sealed class BSPrim : BSPhysObject | |||
533 | else | 540 | else |
534 | { | 541 | { |
535 | // Not a Bullet static object | 542 | // Not a Bullet static object |
536 | BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); | 543 | m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT); |
537 | // A dynamic object has mass | 544 | // A dynamic object has mass |
538 | BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, OMV.Vector3.Zero); | ||
539 | // The shape is interesting and has mass and a center of gravity | ||
540 | IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr); | 545 | IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr); |
541 | BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass, OMV.Vector3.Zero); | 546 | OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass); |
547 | BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, inertia); | ||
542 | // Inertia is based on our new mass | 548 | // Inertia is based on our new mass |
543 | BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); | 549 | BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr); |
544 | // Force activation of the object so Bullet will act on it. | 550 | // Force activation of the object so Bullet will act on it. |
@@ -546,8 +552,31 @@ public sealed class BSPrim : BSPhysObject | |||
546 | } | 552 | } |
547 | } | 553 | } |
548 | 554 | ||
549 | private void MakeSolid() | 555 | // "Making solid" means that other object will not pass through this object. |
556 | private void MakeSolid(bool makeSolid) | ||
550 | { | 557 | { |
558 | if (makeSolid) | ||
559 | { | ||
560 | // Easy in Bullet -- just remove the object flag that controls collision response | ||
561 | m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | ||
562 | } | ||
563 | else | ||
564 | { | ||
565 | m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | ||
566 | } | ||
567 | } | ||
568 | |||
569 | // Turn on or off the flag controlling whether collision events are returned to the simulator. | ||
570 | private void EnableCollisions(bool wantsCollisionEvents) | ||
571 | { | ||
572 | if (wantsCollisionEvents) | ||
573 | { | ||
574 | m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
575 | } | ||
576 | else | ||
577 | { | ||
578 | m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); | ||
579 | } | ||
551 | } | 580 | } |
552 | 581 | ||
553 | // prims don't fly | 582 | // prims don't fly |
@@ -607,7 +636,7 @@ public sealed class BSPrim : BSPhysObject | |||
607 | _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() | 636 | _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() |
608 | { | 637 | { |
609 | DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); | 638 | DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); |
610 | BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); | 639 | BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity); |
611 | }); | 640 | }); |
612 | } | 641 | } |
613 | } | 642 | } |
@@ -624,7 +653,10 @@ public sealed class BSPrim : BSPhysObject | |||
624 | _scene.TaintedObject("BSPrim.setBuoyancy", delegate() | 653 | _scene.TaintedObject("BSPrim.setBuoyancy", delegate() |
625 | { | 654 | { |
626 | DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); | 655 | DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
627 | BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); | 656 | // Buoyancy is faked by changing the gravity applied to the object |
657 | float grav = Scene.Params.gravity * (1f - _buoyancy); | ||
658 | BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav)); | ||
659 | // BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); | ||
628 | }); | 660 | }); |
629 | } | 661 | } |
630 | } | 662 | } |
@@ -686,8 +718,8 @@ public sealed class BSPrim : BSPhysObject | |||
686 | } | 718 | } |
687 | m_accumulatedForces.Clear(); | 719 | m_accumulatedForces.Clear(); |
688 | } | 720 | } |
689 | DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); | 721 | DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); |
690 | // For unknown reason, "ApplyCentralForce" is really additive. | 722 | // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. |
691 | BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum); | 723 | BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum); |
692 | }); | 724 | }); |
693 | } | 725 | } |
@@ -1030,29 +1062,36 @@ public sealed class BSPrim : BSPhysObject | |||
1030 | // Returns 'true' if the geometry was rebuilt | 1062 | // Returns 'true' if the geometry was rebuilt |
1031 | private bool CreateGeom(bool forceRebuild) | 1063 | private bool CreateGeom(bool forceRebuild) |
1032 | { | 1064 | { |
1033 | // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. | ||
1034 | bool ret = false; | 1065 | bool ret = false; |
1035 | if (!_scene.NeedsMeshing(_pbs)) | 1066 | bool haveShape = false; |
1067 | |||
1068 | // If the prim attributes are simple, this could be a simple Bullet native shape | ||
1069 | if ((_pbs.SculptEntry && !Scene.ShouldMeshSculptedPrim) | ||
1070 | || (_pbs.ProfileBegin == 0 && _pbs.ProfileEnd == 0 | ||
1071 | && _pbs.ProfileHollow == 0 | ||
1072 | && _pbs.PathTwist == 0 && _pbs.PathTwistBegin == 0 | ||
1073 | && _pbs.PathBegin == 0 && _pbs.PathEnd == 0 | ||
1074 | && _pbs.PathTaperX == 0 && _pbs.PathTaperY == 0 | ||
1075 | && _pbs.PathScaleX == 100 && _pbs.PathScaleY == 100 | ||
1076 | && _pbs.PathShearX == 0 && _pbs.PathShearY == 0) ) | ||
1036 | { | 1077 | { |
1037 | if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) | 1078 | if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) |
1038 | { | 1079 | { |
1039 | // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) | 1080 | haveShape = true; |
1040 | // { | 1081 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) |
1041 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); | 1082 | { |
1042 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) | 1083 | DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); |
1043 | { | 1084 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; |
1044 | DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); | 1085 | // Bullet native objects are scaled by the Bullet engine so pass the size in |
1045 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; | 1086 | _scale = _size; |
1046 | // Bullet native objects are scaled by the Bullet engine so pass the size in | 1087 | // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? |
1047 | _scale = _size; | 1088 | ret = true; |
1048 | // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? | 1089 | } |
1049 | ret = true; | ||
1050 | } | ||
1051 | // } | ||
1052 | } | 1090 | } |
1053 | else | 1091 | else |
1054 | { | 1092 | { |
1055 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); | 1093 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); |
1094 | haveShape = true; | ||
1056 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) | 1095 | if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) |
1057 | { | 1096 | { |
1058 | DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); | 1097 | DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); |
@@ -1063,16 +1102,16 @@ public sealed class BSPrim : BSPhysObject | |||
1063 | } | 1102 | } |
1064 | } | 1103 | } |
1065 | } | 1104 | } |
1066 | else | 1105 | // If a simple shape isn't happening, create a mesh and possibly a hull |
1106 | if (!haveShape) | ||
1067 | { | 1107 | { |
1068 | if (IsPhysical) | 1108 | if (IsPhysical) |
1069 | { | 1109 | { |
1070 | if (forceRebuild || _hullKey == 0) | 1110 | if (forceRebuild || _hullKey == 0) |
1071 | { | 1111 | { |
1072 | // physical objects require a hull for interaction. | 1112 | // physical objects require a hull for interaction. |
1073 | // This will create the mesh if it doesn't already exist | 1113 | // This also creates the mesh if it doesn't already exist |
1074 | CreateGeomHull(); | 1114 | ret = CreateGeomHull(); |
1075 | ret = true; | ||
1076 | } | 1115 | } |
1077 | } | 1116 | } |
1078 | else | 1117 | else |
@@ -1080,8 +1119,7 @@ public sealed class BSPrim : BSPhysObject | |||
1080 | if (forceRebuild || _meshKey == 0) | 1119 | if (forceRebuild || _meshKey == 0) |
1081 | { | 1120 | { |
1082 | // Static (non-physical) objects only need a mesh for bumping into | 1121 | // Static (non-physical) objects only need a mesh for bumping into |
1083 | CreateGeomMesh(); | 1122 | ret = CreateGeomMesh(); |
1084 | ret = true; | ||
1085 | } | 1123 | } |
1086 | } | 1124 | } |
1087 | } | 1125 | } |
@@ -1089,7 +1127,8 @@ public sealed class BSPrim : BSPhysObject | |||
1089 | } | 1127 | } |
1090 | 1128 | ||
1091 | // No locking here because this is done when we know physics is not simulating | 1129 | // No locking here because this is done when we know physics is not simulating |
1092 | private void CreateGeomMesh() | 1130 | // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). |
1131 | private bool CreateGeomMesh() | ||
1093 | { | 1132 | { |
1094 | // level of detail based on size and type of the object | 1133 | // level of detail based on size and type of the object |
1095 | float lod = _scene.MeshLOD; | 1134 | float lod = _scene.MeshLOD; |
@@ -1103,7 +1142,7 @@ public sealed class BSPrim : BSPhysObject | |||
1103 | // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); | 1142 | // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); |
1104 | 1143 | ||
1105 | // if this new shape is the same as last time, don't recreate the mesh | 1144 | // if this new shape is the same as last time, don't recreate the mesh |
1106 | if (_meshKey == newMeshKey) return; | 1145 | if (_meshKey == newMeshKey) return false; |
1107 | 1146 | ||
1108 | DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); | 1147 | DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); |
1109 | // Since we're recreating new, get rid of any previously generated shape | 1148 | // Since we're recreating new, get rid of any previously generated shape |
@@ -1140,19 +1179,19 @@ public sealed class BSPrim : BSPhysObject | |||
1140 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; | 1179 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; |
1141 | // meshes are already scaled by the meshmerizer | 1180 | // meshes are already scaled by the meshmerizer |
1142 | _scale = new OMV.Vector3(1f, 1f, 1f); | 1181 | _scale = new OMV.Vector3(1f, 1f, 1f); |
1143 | DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); | 1182 | return true; |
1144 | return; | ||
1145 | } | 1183 | } |
1146 | 1184 | ||
1147 | // No locking here because this is done when we know physics is not simulating | 1185 | // No locking here because this is done when we know physics is not simulating |
1148 | private void CreateGeomHull() | 1186 | // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). |
1187 | private bool CreateGeomHull() | ||
1149 | { | 1188 | { |
1150 | float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; | 1189 | float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; |
1151 | ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); | 1190 | ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); |
1152 | // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); | 1191 | // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); |
1153 | 1192 | ||
1154 | // if the hull hasn't changed, don't rebuild it | 1193 | // if the hull hasn't changed, don't rebuild it |
1155 | if (newHullKey == _hullKey) return; | 1194 | if (newHullKey == _hullKey) return false; |
1156 | 1195 | ||
1157 | DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); | 1196 | DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); |
1158 | 1197 | ||
@@ -1255,7 +1294,7 @@ public sealed class BSPrim : BSPhysObject | |||
1255 | // meshes are already scaled by the meshmerizer | 1294 | // meshes are already scaled by the meshmerizer |
1256 | _scale = new OMV.Vector3(1f, 1f, 1f); | 1295 | _scale = new OMV.Vector3(1f, 1f, 1f); |
1257 | DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); | 1296 | DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); |
1258 | return; | 1297 | return true; |
1259 | } | 1298 | } |
1260 | 1299 | ||
1261 | // Callback from convex hull creater with a newly created hull. | 1300 | // Callback from convex hull creater with a newly created hull. |
@@ -1268,20 +1307,12 @@ public sealed class BSPrim : BSPhysObject | |||
1268 | 1307 | ||
1269 | private void VerifyCorrectPhysicalShape() | 1308 | private void VerifyCorrectPhysicalShape() |
1270 | { | 1309 | { |
1271 | if (IsStatic) | 1310 | if (!IsStatic) |
1272 | { | ||
1273 | // if static, we don't need a hull so, if there is one, rebuild without it | ||
1274 | if (_hullKey != 0) | ||
1275 | { | ||
1276 | RecreateGeomAndObject(); | ||
1277 | } | ||
1278 | } | ||
1279 | else | ||
1280 | { | 1311 | { |
1281 | // if not static, it will need a hull to efficiently collide with things | 1312 | // if not static, it will need a hull to efficiently collide with things |
1282 | if (_hullKey == 0) | 1313 | if (_hullKey == 0) |
1283 | { | 1314 | { |
1284 | RecreateGeomAndObject(); | 1315 | CreateGeomAndObject(false); |
1285 | } | 1316 | } |
1286 | 1317 | ||
1287 | } | 1318 | } |
@@ -1300,8 +1331,9 @@ public sealed class BSPrim : BSPhysObject | |||
1300 | // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); | 1331 | // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); |
1301 | bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); | 1332 | bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); |
1302 | 1333 | ||
1303 | // the CreateObject() may have recreated the rigid body. Make sure we have the latest. | 1334 | // the CreateObject() may have recreated the rigid body. Make sure we have the latest address. |
1304 | BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); | 1335 | BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); |
1336 | BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); | ||
1305 | 1337 | ||
1306 | return ret; | 1338 | return ret; |
1307 | } | 1339 | } |
@@ -1325,15 +1357,20 @@ public sealed class BSPrim : BSPhysObject | |||
1325 | shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; | 1357 | shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; |
1326 | } | 1358 | } |
1327 | 1359 | ||
1328 | |||
1329 | // Rebuild the geometry and object. | 1360 | // Rebuild the geometry and object. |
1330 | // This is called when the shape changes so we need to recreate the mesh/hull. | 1361 | // This is called when the shape changes so we need to recreate the mesh/hull. |
1331 | // No locking here because this is done when the physics engine is not simulating | 1362 | // No locking here because this is done when the physics engine is not simulating |
1332 | private void RecreateGeomAndObject() | 1363 | private void CreateGeomAndObject(bool forceRebuild) |
1333 | { | 1364 | { |
1334 | // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); | 1365 | // m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, _localID, forceRebuild); |
1335 | if (CreateGeom(true)) | 1366 | // Create the geometry that will make up the object |
1367 | if (CreateGeom(forceRebuild)) | ||
1368 | { | ||
1369 | // Create the object and place it into the world | ||
1336 | CreateObject(); | 1370 | CreateObject(); |
1371 | // Make sure the properties are set on the new object | ||
1372 | UpdatePhysicalParameters(); | ||
1373 | } | ||
1337 | return; | 1374 | return; |
1338 | } | 1375 | } |
1339 | 1376 | ||
@@ -1430,9 +1467,10 @@ public sealed class BSPrim : BSPhysObject | |||
1430 | // I've collided with something | 1467 | // I've collided with something |
1431 | // Called at taint time from within the Step() function | 1468 | // Called at taint time from within the Step() function |
1432 | CollisionEventUpdate collisionCollection; | 1469 | CollisionEventUpdate collisionCollection; |
1433 | public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) | 1470 | public override bool Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) |
1434 | { | 1471 | { |
1435 | // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); | 1472 | // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); |
1473 | bool ret = false; | ||
1436 | 1474 | ||
1437 | // The following lines make IsColliding() and IsCollidingGround() work | 1475 | // The following lines make IsColliding() and IsCollidingGround() work |
1438 | _collidingStep = _scene.SimulationStep; | 1476 | _collidingStep = _scene.SimulationStep; |
@@ -1446,7 +1484,7 @@ public sealed class BSPrim : BSPhysObject | |||
1446 | // prims in the same linkset cannot collide with each other | 1484 | // prims in the same linkset cannot collide with each other |
1447 | if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) | 1485 | if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) |
1448 | { | 1486 | { |
1449 | return; | 1487 | return ret; |
1450 | } | 1488 | } |
1451 | 1489 | ||
1452 | // if someone has subscribed for collision events.... | 1490 | // if someone has subscribed for collision events.... |
@@ -1459,8 +1497,10 @@ public sealed class BSPrim : BSPhysObject | |||
1459 | if (collisionCollection == null) | 1497 | if (collisionCollection == null) |
1460 | collisionCollection = new CollisionEventUpdate(); | 1498 | collisionCollection = new CollisionEventUpdate(); |
1461 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); | 1499 | collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); |
1500 | ret = true; | ||
1462 | } | 1501 | } |
1463 | } | 1502 | } |
1503 | return ret; | ||
1464 | } | 1504 | } |
1465 | 1505 | ||
1466 | // The scene is telling us it's time to pass our collected collisions into the simulator | 1506 | // The scene is telling us it's time to pass our collected collisions into the simulator |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 4a468af..eea899f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -79,7 +79,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
79 | private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>(); | 79 | private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>(); |
80 | // Following is a kludge and can be removed when avatar animation updating is | 80 | // Following is a kludge and can be removed when avatar animation updating is |
81 | // moved to a better place. | 81 | // moved to a better place. |
82 | private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>(); | 82 | private HashSet<BSPhysObject> m_avatarsWithCollisions = new HashSet<BSPhysObject>(); |
83 | 83 | ||
84 | // List of all the objects that have vehicle properties and should be called | 84 | // List of all the objects that have vehicle properties and should be called |
85 | // to update each physics step. | 85 | // to update each physics step. |
@@ -132,8 +132,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
132 | private EntityProperties[] m_updateArray; | 132 | private EntityProperties[] m_updateArray; |
133 | private GCHandle m_updateArrayPinnedHandle; | 133 | private GCHandle m_updateArrayPinnedHandle; |
134 | 134 | ||
135 | private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed | 135 | public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed |
136 | private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes | 136 | public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes |
137 | 137 | ||
138 | public float PID_D { get; private set; } // derivative | 138 | public float PID_D { get; private set; } // derivative |
139 | public float PID_P { get; private set; } // proportional | 139 | public float PID_P { get; private set; } // proportional |
@@ -153,6 +153,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
153 | { | 153 | { |
154 | get { return new Vector3(0f, 0f, Params.gravity); } | 154 | get { return new Vector3(0f, 0f, Params.gravity); } |
155 | } | 155 | } |
156 | // Just the Z value of the gravity | ||
157 | public float DefaultGravityZ | ||
158 | { | ||
159 | get { return Params.gravity; } | ||
160 | } | ||
156 | 161 | ||
157 | public float MaximumObjectMass { get; private set; } | 162 | public float MaximumObjectMass { get; private set; } |
158 | 163 | ||
@@ -171,8 +176,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
171 | callback = c; | 176 | callback = c; |
172 | } | 177 | } |
173 | } | 178 | } |
179 | private Object _taintLock = new Object(); // lock for using the next object | ||
174 | private List<TaintCallbackEntry> _taintedObjects; | 180 | private List<TaintCallbackEntry> _taintedObjects; |
175 | private Object _taintLock = new Object(); | ||
176 | 181 | ||
177 | // A pointer to an instance if this structure is passed to the C++ code | 182 | // A pointer to an instance if this structure is passed to the C++ code |
178 | // Used to pass basic configuration values to the unmanaged code. | 183 | // Used to pass basic configuration values to the unmanaged code. |
@@ -478,6 +483,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
478 | 483 | ||
479 | // Some of the prims operate with special vehicle properties | 484 | // Some of the prims operate with special vehicle properties |
480 | ProcessVehicles(timeStep); | 485 | ProcessVehicles(timeStep); |
486 | numTaints += _taintedObjects.Count; | ||
481 | ProcessTaints(); // the vehicles might have added taints | 487 | ProcessTaints(); // the vehicles might have added taints |
482 | 488 | ||
483 | // step the physical world one interval | 489 | // step the physical world one interval |
@@ -506,6 +512,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
506 | // Get a value for 'now' so all the collision and update routines don't have to get their own | 512 | // Get a value for 'now' so all the collision and update routines don't have to get their own |
507 | SimulationNowTime = Util.EnvironmentTickCount(); | 513 | SimulationNowTime = Util.EnvironmentTickCount(); |
508 | 514 | ||
515 | // This is a kludge to get avatar movement updates. | ||
516 | // ODE sends collisions for avatars even if there are have been no collisions. This updates | ||
517 | // avatar animations and stuff. | ||
518 | // If you fix avatar animation updates, remove this overhead and let collisions happen. | ||
519 | m_objectsWithCollisions = new HashSet<BSPhysObject>(m_avatarsWithCollisions); | ||
520 | |||
509 | // If there were collisions, process them by sending the event to the prim. | 521 | // If there were collisions, process them by sending the event to the prim. |
510 | // Collisions must be processed before updates. | 522 | // Collisions must be processed before updates. |
511 | if (collidersCount > 0) | 523 | if (collidersCount > 0) |
@@ -527,13 +539,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
527 | bsp.SendCollisions(); | 539 | bsp.SendCollisions(); |
528 | m_objectsWithCollisions.Clear(); | 540 | m_objectsWithCollisions.Clear(); |
529 | 541 | ||
530 | // This is a kludge to get avatar movement updated. | ||
531 | // ODE sends collisions even if there are none and this is used to update | ||
532 | // avatar animations and stuff. | ||
533 | foreach (BSPhysObject bpo in m_avatarsWithCollisions) | ||
534 | bpo.SendCollisions(); | ||
535 | // m_avatarsWithCollisions.Clear(); | ||
536 | |||
537 | // If any of the objects had updated properties, tell the object it has been changed by the physics engine | 542 | // If any of the objects had updated properties, tell the object it has been changed by the physics engine |
538 | if (updatedEntityCount > 0) | 543 | if (updatedEntityCount > 0) |
539 | { | 544 | { |
@@ -544,7 +549,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
544 | if (PhysObjects.TryGetValue(entprop.ID, out pobj)) | 549 | if (PhysObjects.TryGetValue(entprop.ID, out pobj)) |
545 | { | 550 | { |
546 | pobj.UpdateProperties(entprop); | 551 | pobj.UpdateProperties(entprop); |
547 | continue; | ||
548 | } | 552 | } |
549 | } | 553 | } |
550 | } | 554 | } |
@@ -600,8 +604,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
600 | 604 | ||
601 | // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); | 605 | // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); |
602 | 606 | ||
603 | collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration); | 607 | if (collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration)) |
604 | m_objectsWithCollisions.Add(collider); | 608 | { |
609 | // If a collision was posted, remember to send it to the simulator | ||
610 | m_objectsWithCollisions.Add(collider); | ||
611 | } | ||
605 | 612 | ||
606 | return; | 613 | return; |
607 | } | 614 | } |
@@ -619,9 +626,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
619 | public override void SetWaterLevel(float baseheight) | 626 | public override void SetWaterLevel(float baseheight) |
620 | { | 627 | { |
621 | m_waterLevel = baseheight; | 628 | m_waterLevel = baseheight; |
622 | // TODO: pass to physics engine so things will float? | ||
623 | } | 629 | } |
624 | public float GetWaterLevel() | 630 | // Someday.... |
631 | public float GetWaterLevelAtXYZ(Vector3 loc) | ||
625 | { | 632 | { |
626 | return m_waterLevel; | 633 | return m_waterLevel; |
627 | } | 634 | } |
@@ -672,7 +679,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
672 | 679 | ||
673 | // int iPropertiesNotSupportedDefault = 0; | 680 | // int iPropertiesNotSupportedDefault = 0; |
674 | 681 | ||
675 | if (pbs.SculptEntry && !_meshSculptedPrim) | 682 | if (pbs.SculptEntry && !ShouldMeshSculptedPrim) |
676 | { | 683 | { |
677 | // Render sculpties as boxes | 684 | // Render sculpties as boxes |
678 | return false; | 685 | return false; |
@@ -680,7 +687,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
680 | 687 | ||
681 | // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet | 688 | // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet |
682 | // can use an internal representation for the prim | 689 | // can use an internal representation for the prim |
683 | if (!_forceSimplePrimMeshing) | 690 | if (!ShouldForceSimplePrimMeshing) |
684 | { | 691 | { |
685 | if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) | 692 | if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) |
686 | || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 | 693 | || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 |
@@ -782,7 +789,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
782 | if (!m_initialized) return; | 789 | if (!m_initialized) return; |
783 | 790 | ||
784 | lock (_taintLock) | 791 | lock (_taintLock) |
792 | { | ||
785 | _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); | 793 | _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); |
794 | } | ||
795 | |||
786 | return; | 796 | return; |
787 | } | 797 | } |
788 | 798 | ||
@@ -919,14 +929,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
919 | { | 929 | { |
920 | new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", | 930 | new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", |
921 | ConfigurationParameters.numericTrue, | 931 | ConfigurationParameters.numericTrue, |
922 | (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, | 932 | (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, |
923 | (s) => { return s.NumericBool(s._meshSculptedPrim); }, | 933 | (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); }, |
924 | (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ), | 934 | (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ), |
925 | new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", | 935 | new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", |
926 | ConfigurationParameters.numericFalse, | 936 | ConfigurationParameters.numericFalse, |
927 | (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, | 937 | (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, |
928 | (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, | 938 | (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, |
929 | (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), | 939 | (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), |
930 | 940 | ||
931 | new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", | 941 | new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", |
932 | 8f, | 942 | 8f, |
@@ -1162,8 +1172,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1162 | (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, | 1172 | (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, |
1163 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, | 1173 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, |
1164 | (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), | 1174 | (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), |
1165 | new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0", | 1175 | new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", |
1166 | 0.0f, | 1176 | 0.1f, |
1167 | (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, | 1177 | (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, |
1168 | (s) => { return s.m_params[0].linkConstraintCFM; }, | 1178 | (s) => { return s.m_params[0].linkConstraintCFM; }, |
1169 | (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), | 1179 | (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), |
@@ -1172,6 +1182,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
1172 | (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, | 1182 | (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, |
1173 | (s) => { return s.m_params[0].linkConstraintERP; }, | 1183 | (s) => { return s.m_params[0].linkConstraintERP; }, |
1174 | (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), | 1184 | (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), |
1185 | new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", | ||
1186 | 40, | ||
1187 | (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); }, | ||
1188 | (s) => { return s.m_params[0].linkConstraintSolverIterations; }, | ||
1189 | (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ), | ||
1175 | 1190 | ||
1176 | new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", | 1191 | new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", |
1177 | 0f, | 1192 | 0f, |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 47d7199..d48462e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs | |||
@@ -154,27 +154,31 @@ public class BSTerrainManager | |||
154 | 154 | ||
155 | // The simulator wants to set a new heightmap for the terrain. | 155 | // The simulator wants to set a new heightmap for the terrain. |
156 | public void SetTerrain(float[] heightMap) { | 156 | public void SetTerrain(float[] heightMap) { |
157 | if (m_worldOffset != Vector3.Zero && m_parentScene != null) | 157 | float[] localHeightMap = heightMap; |
158 | m_physicsScene.TaintedObject("TerrainManager.SetTerrain", delegate() | ||
158 | { | 159 | { |
159 | // If a child of a mega-region, we shouldn't have any terrain allocated for us | 160 | if (m_worldOffset != Vector3.Zero && m_parentScene != null) |
160 | ReleaseGroundPlaneAndTerrain(); | ||
161 | // If doing the mega-prim stuff and we are the child of the zero region, | ||
162 | // the terrain is added to our parent | ||
163 | if (m_parentScene is BSScene) | ||
164 | { | 161 | { |
165 | DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", | 162 | // If a child of a mega-region, we shouldn't have any terrain allocated for us |
166 | BSScene.DetailLogZero, m_worldOffset, m_worldMax); | 163 | ReleaseGroundPlaneAndTerrain(); |
167 | ((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, | 164 | // If doing the mega-prim stuff and we are the child of the zero region, |
168 | heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false); | 165 | // the terrain is added to our parent |
166 | if (m_parentScene is BSScene) | ||
167 | { | ||
168 | DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", | ||
169 | BSScene.DetailLogZero, m_worldOffset, m_worldMax); | ||
170 | ((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, | ||
171 | localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); | ||
172 | } | ||
169 | } | 173 | } |
170 | } | 174 | else |
171 | else | 175 | { |
172 | { | 176 | // If not doing the mega-prim thing, just change the terrain |
173 | // If not doing the mega-prim thing, just change the terrain | 177 | DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); |
174 | DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); | ||
175 | 178 | ||
176 | UpdateOrCreateTerrain(BSScene.TERRAIN_ID, heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false); | 179 | UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); |
177 | } | 180 | } |
181 | }); | ||
178 | } | 182 | } |
179 | 183 | ||
180 | // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain | 184 | // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain |
@@ -319,6 +323,8 @@ public class BSTerrainManager | |||
319 | 323 | ||
320 | // Make sure the new shape is processed. | 324 | // Make sure the new shape is processed. |
321 | BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true); | 325 | BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true); |
326 | |||
327 | m_terrainModified = true; | ||
322 | }; | 328 | }; |
323 | 329 | ||
324 | // There is the option to do the changes now (we're already in 'taint time'), or | 330 | // There is the option to do the changes now (we're already in 'taint time'), or |
@@ -357,6 +363,8 @@ public class BSTerrainManager | |||
357 | m_heightMaps.Add(terrainRegionBase, mapInfo); | 363 | m_heightMaps.Add(terrainRegionBase, mapInfo); |
358 | // Build the terrain | 364 | // Build the terrain |
359 | UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); | 365 | UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); |
366 | |||
367 | m_terrainModified = true; | ||
360 | }; | 368 | }; |
361 | 369 | ||
362 | // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. | 370 | // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. |
@@ -383,7 +391,7 @@ public class BSTerrainManager | |||
383 | private float lastHeightTX = 999999f; | 391 | private float lastHeightTX = 999999f; |
384 | private float lastHeightTY = 999999f; | 392 | private float lastHeightTY = 999999f; |
385 | private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; | 393 | private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; |
386 | public float GetTerrainHeightAtXY(float tX, float tY) | 394 | private float GetTerrainHeightAtXY(float tX, float tY) |
387 | { | 395 | { |
388 | // You'd be surprized at the number of times this routine is called | 396 | // You'd be surprized at the number of times this routine is called |
389 | // with the same parameters as last time. | 397 | // with the same parameters as last time. |
@@ -403,11 +411,18 @@ public class BSTerrainManager | |||
403 | { | 411 | { |
404 | float regionX = tX - offsetX; | 412 | float regionX = tX - offsetX; |
405 | float regionY = tY - offsetY; | 413 | float regionY = tY - offsetY; |
406 | if (regionX >= mapInfo.sizeX || regionX < 0f) regionX = 0; | ||
407 | if (regionY >= mapInfo.sizeY || regionY < 0f) regionY = 0; | ||
408 | int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX; | 414 | int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX; |
409 | ret = mapInfo.heightMap[mapIndex]; | 415 | try |
410 | m_terrainModified = false; | 416 | { |
417 | ret = mapInfo.heightMap[mapIndex]; | ||
418 | } | ||
419 | catch | ||
420 | { | ||
421 | // Sometimes they give us wonky values of X and Y. Give a warning and return something. | ||
422 | m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}", | ||
423 | LogHeader, terrainBaseXY, regionX, regionY); | ||
424 | ret = HEIGHT_GETHEIGHT_RET; | ||
425 | } | ||
411 | // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}", | 426 | // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}", |
412 | // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret); | 427 | // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret); |
413 | } | 428 | } |
@@ -416,6 +431,7 @@ public class BSTerrainManager | |||
416 | m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", | 431 | m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", |
417 | LogHeader, m_physicsScene.RegionName, tX, tY); | 432 | LogHeader, m_physicsScene.RegionName, tX, tY); |
418 | } | 433 | } |
434 | m_terrainModified = false; | ||
419 | lastHeight = ret; | 435 | lastHeight = ret; |
420 | return ret; | 436 | return ret; |
421 | } | 437 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index e579cf2..043423e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | |||
@@ -213,6 +213,7 @@ public struct ConfigurationParameters | |||
213 | public float linkConstraintTransMotorMaxForce; | 213 | public float linkConstraintTransMotorMaxForce; |
214 | public float linkConstraintERP; | 214 | public float linkConstraintERP; |
215 | public float linkConstraintCFM; | 215 | public float linkConstraintCFM; |
216 | public float linkConstraintSolverIterations; | ||
216 | 217 | ||
217 | public const float numericTrue = 1f; | 218 | public const float numericTrue = 1f; |
218 | public const float numericFalse = 0f; | 219 | public const float numericFalse = 0f; |
@@ -395,23 +396,6 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey); | |||
395 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 396 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
396 | public static extern bool CreateObject(uint worldID, ShapeData shapeData); | 397 | public static extern bool CreateObject(uint worldID, ShapeData shapeData); |
397 | 398 | ||
398 | /* Remove old functionality | ||
399 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
400 | public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); | ||
401 | |||
402 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
403 | public static extern void AddConstraint(uint worldID, uint id1, uint id2, | ||
404 | Vector3 frame1, Quaternion frame1rot, | ||
405 | Vector3 frame2, Quaternion frame2rot, | ||
406 | Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular); | ||
407 | |||
408 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
409 | public static extern bool RemoveConstraintByID(uint worldID, uint id1); | ||
410 | |||
411 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
412 | public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); | ||
413 | */ | ||
414 | |||
415 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 399 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
416 | public static extern Vector3 GetObjectPosition(uint WorldID, uint id); | 400 | public static extern Vector3 GetObjectPosition(uint WorldID, uint id); |
417 | 401 | ||
@@ -545,6 +529,15 @@ public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); | |||
545 | public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); | 529 | public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); |
546 | 530 | ||
547 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 531 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
532 | public static extern IntPtr CreateCompoundShape2(IntPtr sim); | ||
533 | |||
534 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
535 | public static extern void AddChildToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); | ||
536 | |||
537 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
538 | public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr removeShape); | ||
539 | |||
540 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
548 | public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo); | 541 | public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo); |
549 | 542 | ||
550 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 543 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
@@ -1010,7 +1003,7 @@ public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale); | |||
1010 | public static extern Vector3 GetLocalScaling2(IntPtr shape); | 1003 | public static extern Vector3 GetLocalScaling2(IntPtr shape); |
1011 | 1004 | ||
1012 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 1005 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1013 | public static extern void CalculateLocalInertia2(IntPtr shape, float mass, Vector3 inertia); | 1006 | public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass); |
1014 | 1007 | ||
1015 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 1008 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
1016 | public static extern int GetShapeType2(IntPtr shape); | 1009 | public static extern int GetShapeType2(IntPtr shape); |