diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectPart.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 887c7fc..ea0245c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -4881,28 +4881,39 @@ namespace OpenSim.Region.Framework.Scenes | |||
4881 | { | 4881 | { |
4882 | if (APIDTarget != Quaternion.Identity) | 4882 | if (APIDTarget != Quaternion.Identity) |
4883 | { | 4883 | { |
4884 | 4884 | PhysicsActor pa = ParentGroup.RootPart.PhysActor; | |
4885 | if (m_APIDIterations <= 1) | 4885 | if (pa == null || !pa.IsPhysical) |
4886 | { | 4886 | { |
4887 | AngularVelocity = Vector3.Zero; | 4887 | StopLookAt(); |
4888 | UpdateRotation(APIDTarget); | ||
4889 | APIDTarget = Quaternion.Identity; | ||
4890 | return; | 4888 | return; |
4891 | } | 4889 | } |
4892 | 4890 | ||
4893 | Quaternion rot = Quaternion.Slerp(RotationOffset,APIDTarget,1.0f/(float)m_APIDIterations); | 4891 | Quaternion currRot = GetWorldRotation(); |
4894 | rot.Normalize(); | 4892 | currRot.Normalize(); |
4893 | |||
4894 | // difference between current orientation and desired orientation | ||
4895 | Quaternion dR = new Quaternion(currRot.X, currRot.Y, currRot.Z, -currRot.W) * APIDTarget; | ||
4896 | |||
4897 | // find axis of rotation to rotate to desired orientation | ||
4898 | Vector3 axis = Vector3.UnitX; | ||
4899 | float s = (float)Math.Sqrt(1.0f - dR.W * dR.W); | ||
4900 | if (s >= 0.001) | ||
4901 | { | ||
4902 | float invS = 1.0f / s; | ||
4903 | if (dR.W < 0) invS = -invS; | ||
4904 | axis = new Vector3(dR.X * invS, dR.Y * invS, dR.Z * invS) * currRot; | ||
4905 | axis.Normalize(); | ||
4906 | } | ||
4895 | 4907 | ||
4896 | Quaternion dR = rot / RotationOffset; | 4908 | // angle between current and desired orientation |
4897 | Vector3 axis; | 4909 | float angle = 2.0f * (float)Math.Acos(dR.W); |
4898 | float angle; | 4910 | if (angle > Math.PI) |
4899 | dR.GetAxisAngle(out axis, out angle); | 4911 | angle = 2.0f * (float)Math.PI - angle; |
4900 | axis *= RotationOffset; | 4912 | |
4901 | axis.Normalize(); | 4913 | // set angular velocity to rotate to desired orientation |
4902 | axis *= angle / 11; // simulator update frequency is 10-11 Hz | 4914 | // with velocity proportional to strength and angle |
4903 | AngularVelocity = axis; | 4915 | // the factor of 10 seems to make rotation speed closer to LL implementation |
4904 | 4916 | AngularVelocity = axis * angle * APIDStrength * (float)Math.PI * 10.0f; | |
4905 | m_APIDIterations--; | ||
4906 | 4917 | ||
4907 | // This ensures that we'll check this object on the next iteration | 4918 | // This ensures that we'll check this object on the next iteration |
4908 | ParentGroup.QueueForUpdateCheck(); | 4919 | ParentGroup.QueueForUpdateCheck(); |