From e1a2c44ebe8f10cf00a14578e44b000ff16b68df Mon Sep 17 00:00:00 2001
From: Mic Bowman
Date: Fri, 13 Jan 2012 14:48:56 -0800
Subject: Cleaned up the LookAt code in SOP and SOG. Added support for
 incrementally rotating physical objects. This does not use physics. Currently
 the rate of change is determined as 1 / (PI * Strength).

---
 .../Region/Framework/Scenes/SceneObjectGroup.cs    |  6 --
 OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 69 ++++++++++------------
 .../Shared/Api/Implementation/LSL_Api.cs           |  8 +--
 3 files changed, 34 insertions(+), 49 deletions(-)

diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 8860764..cad09b8 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1613,12 +1613,6 @@ namespace OpenSim.Region.Framework.Scenes
                 RootPart.PhysActor.PIDActive = false;
         }
         
-        public void stopLookAt()
-        {
-            if (RootPart.PhysActor != null)
-                RootPart.PhysActor.APIDActive = false;
-        }
-
         /// <summary>
         /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
         /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index e9c33eb..ad3bcd5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -217,11 +217,10 @@ namespace OpenSim.Region.Framework.Scenes
 
         public Quaternion SpinOldOrientation = Quaternion.Identity;
 
-        public Quaternion m_APIDTarget = Quaternion.Identity;
-
-        public float m_APIDDamp = 0;
-        
-        public float m_APIDStrength = 0;
+        protected int m_APIDIterations = 0;
+        protected Quaternion m_APIDTarget = Quaternion.Identity;
+        protected float m_APIDDamp = 0;
+        protected float m_APIDStrength = 0;
 
         /// <summary>
         /// This part's inventory
@@ -563,22 +562,21 @@ namespace OpenSim.Region.Framework.Scenes
             }
         }
 
-        
-        public Quaternion APIDTarget
+        protected Quaternion APIDTarget
         {
             get { return m_APIDTarget; }
             set { m_APIDTarget = value; }
         }
 
         
-        public float APIDDamp
+        protected float APIDDamp
         {
             get { return m_APIDDamp; }
             set { m_APIDDamp = value; }
         }
 
         
-        public float APIDStrength
+        protected float APIDStrength
         {
             get { return m_APIDStrength; }
             set { m_APIDStrength = value; }
@@ -2697,11 +2695,6 @@ namespace OpenSim.Region.Framework.Scenes
         
         public void RotLookAt(Quaternion target, float strength, float damping)
         {
-            rotLookAt(target, strength, damping);
-        }
-
-        public void rotLookAt(Quaternion target, float strength, float damping)
-        {
             if (ParentGroup.IsAttachment)
             {
                 /*
@@ -2716,17 +2709,26 @@ namespace OpenSim.Region.Framework.Scenes
                 APIDDamp = damping;
                 APIDStrength = strength;
                 APIDTarget = target;
+
+                if (APIDStrength <= 0)
+                {
+                    m_log.WarnFormat("[SceneObjectPart] Invalid rotation strength {0}",APIDStrength);
+                    return;
+                }
+                
+                m_APIDIterations = 1 + (int)(Math.PI * APIDStrength);
             }
+
+            // Necessary to get the lookat deltas applied
+            ParentGroup.QueueForUpdateCheck();
         }
 
-        public void startLookAt(Quaternion rot, float damp, float strength)
+        public void StartLookAt(Quaternion target, float strength, float damping)
         {
-            APIDDamp = damp;
-            APIDStrength = strength;
-            APIDTarget = rot;
+            RotLookAt(target,strength,damping);
         }
 
-        public void stopLookAt()
+        public void StopLookAt()
         {
             APIDTarget = Quaternion.Identity;
         }
@@ -3417,13 +3419,6 @@ namespace OpenSim.Region.Framework.Scenes
             }
         }
         
-        public void StopLookAt()
-        {
-            ParentGroup.stopLookAt();
-
-            ParentGroup.ScheduleGroupForTerseUpdate();
-        }
-        
         /// <summary>
         /// Set the text displayed for this part.
         /// </summary>
@@ -4731,24 +4726,20 @@ namespace OpenSim.Region.Framework.Scenes
             {
                 if (APIDTarget != Quaternion.Identity)
                 {
-                    if (Single.IsNaN(APIDTarget.W) == true)
+                    if (m_APIDIterations <= 1)
                     {
+                        UpdateRotation(APIDTarget);
                         APIDTarget = Quaternion.Identity;
                         return;
                     }
-                    Quaternion rot = RotationOffset;
-                    Quaternion dir = (rot - APIDTarget);
-                    float speed = ((APIDStrength / APIDDamp) * (float)(Math.PI / 180.0f));
-                    if (dir.Z > speed)
-                    {
-                        rot.Z -= speed;
-                    }
-                    if (dir.Z < -speed)
-                    {
-                        rot.Z += speed;
-                    }
-                    rot.Normalize();
+
+                    Quaternion rot = Quaternion.Slerp(RotationOffset,APIDTarget,1.0f/(float)m_APIDIterations);
                     UpdateRotation(rot);
+
+                    m_APIDIterations--;
+
+                    // This ensures that we'll check this object on the next iteration
+                    ParentGroup.QueueForUpdateCheck();
                 }
             }
             catch (Exception ex)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 30145c7..ab175ba 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -2865,13 +2865,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
             
             // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
             // set the rotation of the object, copy that behavior
-            if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
+            if (strength == 0 || m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
             {
                 llSetRot(rot);
             }
             else
             {
-                m_host.startLookAt(Rot2Quaternion(rot), (float)damping, (float)strength);
+                m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping);
             }
         }
 
@@ -3251,13 +3251,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
             
             // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
             // set the rotation of the object, copy that behavior
-            if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
+            if (strength == 0 || m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
             {
                 llSetLocalRot(target);
             }
             else
             {
-                m_host.RotLookAt(Rot2Quaternion(target), (float)damping, (float)strength);
+                m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping);
             }
         }
 
-- 
cgit v1.1