diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 224 |
1 files changed, 161 insertions, 63 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 819635a..dbc9039 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -54,10 +54,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
54 | { | 54 | { |
55 | public sealed class BSDynamics | 55 | public sealed class BSDynamics |
56 | { | 56 | { |
57 | private static string LogHeader = "[BULLETSIM VEHICLE]"; | ||
58 | |||
57 | private BSScene PhysicsScene { get; set; } | 59 | private BSScene PhysicsScene { get; set; } |
58 | // the prim this dynamic controller belongs to | 60 | // the prim this dynamic controller belongs to |
59 | private BSPrim Prim { get; set; } | 61 | private BSPrim Prim { get; set; } |
60 | 62 | ||
63 | // mass of the vehicle fetched each time we're calles | ||
64 | private float m_vehicleMass; | ||
65 | |||
61 | // Vehicle properties | 66 | // Vehicle properties |
62 | public Vehicle Type { get; set; } | 67 | public Vehicle Type { get; set; } |
63 | 68 | ||
@@ -516,7 +521,29 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
516 | // Friction effects are handled by this vehicle code | 521 | // Friction effects are handled by this vehicle code |
517 | BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f); | 522 | BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f); |
518 | BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f); | 523 | BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f); |
524 | |||
525 | // BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, 0.8f); | ||
526 | |||
527 | VDetailLog("{0},BSDynamics.Refresh,zeroingFriction and adding damping", Prim.LocalID); | ||
528 | } | ||
529 | } | ||
530 | |||
531 | public bool RemoveBodyDependencies(BSPhysObject prim) | ||
532 | { | ||
533 | // If active, we need to add our properties back when the body is rebuilt. | ||
534 | return IsActive; | ||
535 | } | ||
536 | |||
537 | public void RestoreBodyDependencies(BSPhysObject prim) | ||
538 | { | ||
539 | if (Prim.LocalID != prim.LocalID) | ||
540 | { | ||
541 | // The call should be on us by our prim. Error if not. | ||
542 | PhysicsScene.Logger.ErrorFormat("{0} RestoreBodyDependencies: called by not my prim. passedLocalID={1}, vehiclePrimLocalID={2}", | ||
543 | LogHeader, prim.LocalID, Prim.LocalID); | ||
544 | return; | ||
519 | } | 545 | } |
546 | Refresh(); | ||
520 | } | 547 | } |
521 | 548 | ||
522 | // One step of the vehicle properties for the next 'pTimestep' seconds. | 549 | // One step of the vehicle properties for the next 'pTimestep' seconds. |
@@ -533,16 +560,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
533 | // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG: | 560 | // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG: |
534 | // END DEBUG | 561 | // END DEBUG |
535 | 562 | ||
563 | m_vehicleMass = Prim.Linkset.LinksetMass; | ||
564 | |||
536 | MoveLinear(pTimestep); | 565 | MoveLinear(pTimestep); |
566 | // Commented out for debug | ||
537 | MoveAngular(pTimestep); | 567 | MoveAngular(pTimestep); |
538 | LimitRotation(pTimestep); | 568 | // Prim.ApplyTorqueImpulse(-Prim.RotationalVelocity * m_vehicleMass, false); // DEBUG DEBUG |
569 | // Prim.ForceRotationalVelocity = -Prim.RotationalVelocity; // DEBUG DEBUG | ||
539 | 570 | ||
540 | // DEBUG: Trying to figure out why Bullet goes crazy when the root prim is moved. | 571 | LimitRotation(pTimestep); |
541 | // BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // DEBUG DEBUG DEBUG | ||
542 | 572 | ||
543 | // remember the position so next step we can limit absolute movement effects | 573 | // remember the position so next step we can limit absolute movement effects |
544 | m_lastPositionVector = Prim.ForcePosition; | 574 | m_lastPositionVector = Prim.ForcePosition; |
545 | 575 | ||
576 | VDetailLog("{0},BSDynamics.Step,frict={1},grav={2},inertia={3},mass={4}", // DEBUG DEBUG | ||
577 | Prim.LocalID, | ||
578 | BulletSimAPI.GetFriction2(Prim.PhysBody.ptr), | ||
579 | BulletSimAPI.GetGravity2(Prim.PhysBody.ptr), | ||
580 | Prim.Inertia, | ||
581 | m_vehicleMass | ||
582 | ); | ||
546 | VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", | 583 | VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", |
547 | Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); | 584 | Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); |
548 | }// end Step | 585 | }// end Step |
@@ -555,25 +592,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
555 | // m_lastLinearVelocityVector is the current speed we are moving in that direction | 592 | // m_lastLinearVelocityVector is the current speed we are moving in that direction |
556 | if (m_linearMotorDirection.LengthSquared() > 0.001f) | 593 | if (m_linearMotorDirection.LengthSquared() > 0.001f) |
557 | { | 594 | { |
558 | Vector3 origDir = m_linearMotorDirection; | 595 | Vector3 origDir = m_linearMotorDirection; // DEBUG |
559 | Vector3 origVel = m_lastLinearVelocityVector; | 596 | Vector3 origVel = m_lastLinearVelocityVector; // DEBUG |
597 | // DEBUG: the vehicle velocity rotated to be relative to vehicle coordinates for comparison | ||
560 | Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG | 598 | Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG |
561 | 599 | ||
562 | // add drive to body | 600 | // Add (desiredVelocity - lastAppliedVelocity) / howLongItShouldTakeToComplete |
563 | Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep; | 601 | Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep; |
564 | // lastLinearVelocityVector is the current body velocity vector | ||
565 | m_lastLinearVelocityVector += addAmount; | 602 | m_lastLinearVelocityVector += addAmount; |
566 | 603 | ||
567 | float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep; | 604 | float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep; |
568 | m_linearMotorDirection *= (1f - decayFactor); | 605 | m_linearMotorDirection *= (1f - decayFactor); |
569 | 606 | ||
570 | Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep; | ||
571 | m_lastLinearVelocityVector *= (Vector3.One - frictionFactor); | ||
572 | |||
573 | // Rotate new object velocity from vehicle relative to world coordinates | 607 | // Rotate new object velocity from vehicle relative to world coordinates |
574 | m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; | 608 | m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; |
575 | 609 | ||
576 | VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lmVel={8},newVel={9}", | 610 | // Apply friction for next time |
611 | Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep; | ||
612 | m_lastLinearVelocityVector *= (Vector3.One - frictionFactor); | ||
613 | |||
614 | VDetailLog("{0},MoveLinear,nonZero,origlmDir={1},origlvVel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lvVec={8},newVel={9}", | ||
577 | Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor, | 615 | Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor, |
578 | m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity); | 616 | m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity); |
579 | } | 617 | } |
@@ -607,7 +645,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
607 | // If below the terrain, move us above the ground a little. | 645 | // If below the terrain, move us above the ground a little. |
608 | float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); | 646 | float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); |
609 | // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. | 647 | // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. |
610 | // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. | 648 | // TODO: Add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. |
611 | // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation; | 649 | // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation; |
612 | // if (rotatedSize.Z < terrainHeight) | 650 | // if (rotatedSize.Z < terrainHeight) |
613 | if (pos.Z < terrainHeight) | 651 | if (pos.Z < terrainHeight) |
@@ -638,13 +676,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
638 | 676 | ||
639 | if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) | 677 | if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) |
640 | { | 678 | { |
641 | // If body is aready heigher, use its height as target height | 679 | // If body is already heigher, use its height as target height |
642 | if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; | 680 | if (pos.Z > m_VhoverTargetHeight) |
681 | m_VhoverTargetHeight = pos.Z; | ||
643 | } | 682 | } |
644 | if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) | 683 | if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) |
645 | { | 684 | { |
646 | if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) | 685 | if (Math.Abs(pos.Z - m_VhoverTargetHeight) > 0.2f) |
647 | { | 686 | { |
687 | pos.Z = m_VhoverTargetHeight; | ||
648 | Prim.ForcePosition = pos; | 688 | Prim.ForcePosition = pos; |
649 | } | 689 | } |
650 | } | 690 | } |
@@ -709,25 +749,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
709 | } | 749 | } |
710 | } | 750 | } |
711 | 751 | ||
712 | // Limit absolute vertical change | 752 | #region downForce |
713 | float Zchange = Math.Abs(posChange.Z); | 753 | Vector3 downForce = Vector3.Zero; |
754 | |||
714 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) | 755 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) |
715 | { | 756 | { |
716 | if (Zchange > .3) | 757 | // If the vehicle is motoring into the sky, get it going back down. |
717 | grav.Z = (float)(grav.Z * 3); | 758 | // Is this an angular force or both linear and angular?? |
718 | if (Zchange > .15) | 759 | float distanceAboveGround = pos.Z - terrainHeight; |
719 | grav.Z = (float)(grav.Z * 2); | 760 | if (distanceAboveGround > 2f) |
720 | if (Zchange > .75) | 761 | { |
721 | grav.Z = (float)(grav.Z * 1.5); | 762 | // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); |
722 | if (Zchange > .05) | 763 | // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); |
723 | grav.Z = (float)(grav.Z * 1.25); | 764 | downForce = new Vector3(0, 0, -distanceAboveGround); |
724 | if (Zchange > .025) | 765 | } |
725 | grav.Z = (float)(grav.Z * 1.125); | 766 | // TODO: this calculation is all wrong. From the description at |
726 | float postemp = (pos.Z - terrainHeight); | 767 | // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce |
727 | if (postemp > 2.5f) | 768 | // has a decay factor. This says this force should |
728 | grav.Z = (float)(grav.Z * 1.037125); | 769 | // be computed with a motor. |
729 | VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav); | 770 | VDetailLog("{0},MoveLinear,limitMotorUp,distAbove={1},downForce={2}", |
771 | Prim.LocalID, distanceAboveGround, downForce); | ||
730 | } | 772 | } |
773 | #endregion // downForce | ||
731 | 774 | ||
732 | // If not changing some axis, reduce out velocity | 775 | // If not changing some axis, reduce out velocity |
733 | if ((m_flags & (VehicleFlag.NO_X)) != 0) | 776 | if ((m_flags & (VehicleFlag.NO_X)) != 0) |
@@ -737,13 +780,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
737 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) | 780 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) |
738 | m_newVelocity.Z = 0; | 781 | m_newVelocity.Z = 0; |
739 | 782 | ||
740 | // Apply velocity | 783 | // Clamp REALLY high or low velocities |
784 | if (m_newVelocity.LengthSquared() > 1e6f) | ||
785 | { | ||
786 | m_newVelocity /= m_newVelocity.Length(); | ||
787 | m_newVelocity *= 1000f; | ||
788 | } | ||
789 | else if (m_newVelocity.LengthSquared() < 1e-6f) | ||
790 | m_newVelocity = Vector3.Zero; | ||
791 | |||
792 | // Stuff new linear velocity into the vehicle | ||
741 | Prim.ForceVelocity = m_newVelocity; | 793 | Prim.ForceVelocity = m_newVelocity; |
742 | // Prim.AddForce(m_newVelocity * Prim.Linkset.LinksetMass, false); | 794 | // Prim.ApplyForceImpulse((m_newVelocity - Prim.Velocity) * m_vehicleMass, false); // DEBUG DEBUG |
743 | Prim.AddForce(grav * Prim.Linkset.LinksetMass, false); | ||
744 | 795 | ||
745 | VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4}", | 796 | Vector3 totalDownForce = downForce + grav; |
746 | Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav); | 797 | if (totalDownForce != Vector3.Zero) |
798 | { | ||
799 | Prim.AddForce(totalDownForce * m_vehicleMass, false); | ||
800 | // Prim.ApplyForceImpulse(totalDownForce * m_vehicleMass, false); | ||
801 | } | ||
802 | |||
803 | VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},primVel={4},totalDown={5}", | ||
804 | Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, Prim.Velocity, totalDownForce); | ||
747 | 805 | ||
748 | } // end MoveLinear() | 806 | } // end MoveLinear() |
749 | 807 | ||
@@ -765,7 +823,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
765 | Vector3 origDir = m_angularMotorDirection; | 823 | Vector3 origDir = m_angularMotorDirection; |
766 | 824 | ||
767 | // new velocity += error / ( time to get there / step interval) | 825 | // new velocity += error / ( time to get there / step interval) |
768 | // requested speed - last motor speed | 826 | // requested direction - current vehicle direction |
769 | m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep); | 827 | m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep); |
770 | // decay requested direction | 828 | // decay requested direction |
771 | m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale)); | 829 | m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale)); |
@@ -784,10 +842,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
784 | Vector3 deflection = Vector3.Zero; | 842 | Vector3 deflection = Vector3.Zero; |
785 | Vector3 banking = Vector3.Zero; | 843 | Vector3 banking = Vector3.Zero; |
786 | 844 | ||
845 | // If vertical attaction timescale is reasonable and we applied an angular force last time... | ||
787 | if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) | 846 | if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) |
788 | { | 847 | { |
789 | float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale; | 848 | float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale; |
790 | if (Prim.Linkset.LinksetIsColliding) | 849 | if (Prim.IsColliding) |
791 | VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale); | 850 | VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale); |
792 | 851 | ||
793 | VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); | 852 | VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); |
@@ -806,7 +865,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
806 | verticalError.X = 2.0f - verticalError.X; | 865 | verticalError.X = 2.0f - verticalError.X; |
807 | verticalError.Y = 2.0f - verticalError.Y; | 866 | verticalError.Y = 2.0f - verticalError.Y; |
808 | } | 867 | } |
809 | // scale it by VAservo | 868 | // scale it by VAservo (timestep and timescale) |
810 | verticalError = verticalError * VAservo; | 869 | verticalError = verticalError * VAservo; |
811 | 870 | ||
812 | // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y | 871 | // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y |
@@ -822,25 +881,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
822 | vertattr.X += bounce * angularVelocity.X; | 881 | vertattr.X += bounce * angularVelocity.X; |
823 | vertattr.Y += bounce * angularVelocity.Y; | 882 | vertattr.Y += bounce * angularVelocity.Y; |
824 | 883 | ||
825 | VDetailLog("{0},MoveAngular,verticalAttraction,verticalError={1},bounce={2},vertattr={3}", | 884 | VDetailLog("{0},MoveAngular,verticalAttraction,VAservo={1},effic={2},verticalError={3},bounce={4},vertattr={5}", |
826 | Prim.LocalID, verticalError, bounce, vertattr); | 885 | Prim.LocalID, VAservo, m_verticalAttractionEfficiency, verticalError, bounce, vertattr); |
827 | 886 | ||
828 | } | 887 | } |
829 | #endregion // Vertical attactor | 888 | #endregion // Vertical attactor |
830 | 889 | ||
831 | #region Deflection | 890 | #region Deflection |
832 | 891 | ||
833 | //Forward is the prefered direction, but if the reference frame has changed, we need to take this into account as well | ||
834 | if (m_angularDeflectionEfficiency != 0) | 892 | if (m_angularDeflectionEfficiency != 0) |
835 | { | 893 | { |
836 | Vector3 preferredAxisOfMotion = | 894 | // Compute a scaled vector that points in the preferred axis (X direction) |
895 | Vector3 scaledDefaultDirection = | ||
837 | new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); | 896 | new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); |
838 | preferredAxisOfMotion *= Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); | 897 | // Adding the current vehicle orientation and reference frame displaces the orientation to the frame. |
898 | // Rotate the scaled default axix relative to the actual vehicle direction giving where it should point. | ||
899 | Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); | ||
839 | 900 | ||
901 | // Scale by efficiency and timescale | ||
840 | deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; | 902 | deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; |
841 | 903 | ||
842 | VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", | 904 | VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", |
843 | Prim.LocalID, preferredAxisOfMotion, deflection); | 905 | Prim.LocalID, preferredAxisOfMotion, deflection); |
906 | // This deflection computation is not correct. | ||
907 | deflection = Vector3.Zero; | ||
844 | } | 908 | } |
845 | 909 | ||
846 | #endregion | 910 | #endregion |
@@ -875,7 +939,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
875 | } | 939 | } |
876 | else | 940 | else |
877 | banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4; | 941 | banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4; |
878 | if (!Prim.Linkset.LinksetIsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) | 942 | if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) |
879 | //If they are colliding, we probably shouldn't shove the prim around... probably | 943 | //If they are colliding, we probably shouldn't shove the prim around... probably |
880 | { | 944 | { |
881 | float angVelZ = m_angularMotorVelocity.X*-1; | 945 | float angVelZ = m_angularMotorVelocity.X*-1; |
@@ -904,6 +968,40 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
904 | // Sum velocities | 968 | // Sum velocities |
905 | m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection; | 969 | m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection; |
906 | 970 | ||
971 | #region Linear Motor Offset | ||
972 | |||
973 | //Offset section | ||
974 | if (m_linearMotorOffset != Vector3.Zero) | ||
975 | { | ||
976 | //Offset of linear velocity doesn't change the linear velocity, | ||
977 | // but causes a torque to be applied, for example... | ||
978 | // | ||
979 | // IIIII >>> IIIII | ||
980 | // IIIII >>> IIIII | ||
981 | // IIIII >>> IIIII | ||
982 | // ^ | ||
983 | // | Applying a force at the arrow will cause the object to move forward, but also rotate | ||
984 | // | ||
985 | // | ||
986 | // The torque created is the linear velocity crossed with the offset | ||
987 | |||
988 | // NOTE: this computation does should be in the linear section | ||
989 | // because there we know the impulse being applied. | ||
990 | Vector3 torqueFromOffset = Vector3.Zero; | ||
991 | // torqueFromOffset = Vector3.Cross(m_linearMotorOffset, appliedImpulse); | ||
992 | if (float.IsNaN(torqueFromOffset.X)) | ||
993 | torqueFromOffset.X = 0; | ||
994 | if (float.IsNaN(torqueFromOffset.Y)) | ||
995 | torqueFromOffset.Y = 0; | ||
996 | if (float.IsNaN(torqueFromOffset.Z)) | ||
997 | torqueFromOffset.Z = 0; | ||
998 | torqueFromOffset *= m_vehicleMass; | ||
999 | Prim.ApplyTorqueImpulse(torqueFromOffset, true); | ||
1000 | VDetailLog("{0},BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); | ||
1001 | } | ||
1002 | |||
1003 | #endregion | ||
1004 | |||
907 | if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) | 1005 | if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) |
908 | { | 1006 | { |
909 | m_lastAngularVelocity.X = 0; | 1007 | m_lastAngularVelocity.X = 0; |
@@ -914,25 +1012,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
914 | if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) | 1012 | if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) |
915 | { | 1013 | { |
916 | m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. | 1014 | m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. |
917 | VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); | 1015 | Prim.ZeroAngularMotion(true); |
1016 | VDetailLog("{0},MoveAngular,zeroAngularMotion,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); | ||
1017 | } | ||
1018 | else | ||
1019 | { | ||
1020 | // Apply to the body. | ||
1021 | // The above calculates the absolute angular velocity needed. Angular velocity is massless. | ||
1022 | // Since we are stuffing the angular velocity directly into the object, the computed | ||
1023 | // velocity needs to be scaled by the timestep. | ||
1024 | Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep) - Prim.ForceRotationalVelocity); | ||
1025 | Prim.ForceRotationalVelocity = applyAngularForce; | ||
1026 | |||
1027 | // Decay the angular movement for next time | ||
1028 | Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep; | ||
1029 | m_lastAngularVelocity *= Vector3.One - decayamount; | ||
1030 | |||
1031 | VDetailLog("{0},MoveAngular,done,newRotVel={1},decay={2},lastAngular={3}", | ||
1032 | Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity); | ||
918 | } | 1033 | } |
919 | |||
920 | // Apply to the body | ||
921 | // The above calculates the absolute angular velocity needed | ||
922 | // Prim.ForceRotationalVelocity = m_lastAngularVelocity; | ||
923 | |||
924 | // Apply a force to overcome current angular velocity | ||
925 | Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity) * Prim.Linkset.LinksetMass; | ||
926 | // Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity); | ||
927 | // Prim.AddAngularForce(applyAngularForce, false); | ||
928 | Prim.ApplyTorqueImpulse(applyAngularForce, false); | ||
929 | |||
930 | // Apply friction for next time | ||
931 | Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep; | ||
932 | m_lastAngularVelocity *= Vector3.One - decayamount; | ||
933 | |||
934 | VDetailLog("{0},MoveAngular,done,applyAForce={1},decay={2},lastAngular={3}", | ||
935 | Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity); | ||
936 | } //end MoveAngular | 1034 | } //end MoveAngular |
937 | 1035 | ||
938 | internal void LimitRotation(float timestep) | 1036 | internal void LimitRotation(float timestep) |