From c79a11cbd1eeb8359ad08178830c94cc0d52f877 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Fri, 14 Nov 2008 03:32:20 +0000
Subject: Lots of experimentation yielded a fair approximation of a hip offset
 from the physical center of an avatar, for display purposes. This should keep
 the avatar feet above ground visually in most cases. Tweaked for both height
 extremes and various leg lengths. Improvements welcome

---
 OpenSim/Framework/AvatarAppearance.cs              | 13 ++++++++++++-
 OpenSim/Region/Environment/Scenes/ScenePresence.cs |  9 ++++++++-
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs
index f2ceb20..f549461 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -227,6 +227,7 @@ namespace OpenSim.Framework
         }
 
         protected float m_avatarHeight = 0;
+        protected float m_hipOffset = 0;
 
         public virtual float AvatarHeight
         {
@@ -234,6 +235,11 @@ namespace OpenSim.Framework
             set { m_avatarHeight = value; }
         }
 
+        public virtual float HipOffset
+        {
+            get { return m_hipOffset; }
+        }
+
         public AvatarAppearance()
         {
             m_wearables = new AvatarWearable[MAX_WEARABLES];
@@ -275,7 +281,12 @@ namespace OpenSim.Framework
                            + 0.08f * (float)m_visualparams[77] / 255.0f    // Shoe heel height
                            + 0.07f * (float)m_visualparams[78] / 255.0f    // Shoe platform height
                            + 0.076f * (float)m_visualparams[148] / 255.0f;    // Neck length
-
+            m_hipOffset    = (0.615385f // Half of avatar
+                           + 0.08f * (float)m_visualparams[77] / 255.0f    // Shoe heel height
+                           + 0.07f * (float)m_visualparams[78] / 255.0f    // Shoe platform height
+                           + 0.3836f * (float)m_visualparams[125] / 255.0f    // Leg length
+                           - m_avatarHeight / 2) * 0.3f - 0.04f;
+            System.Console.WriteLine("Height {0} Hip offset {1}", m_avatarHeight, m_hipOffset);
         }
 
         public virtual void SetWearable(int wearableId, AvatarWearable wearable)
diff --git a/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/OpenSim/Region/Environment/Scenes/ScenePresence.cs
index af17fac..c91027c 100644
--- a/OpenSim/Region/Environment/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Environment/Scenes/ScenePresence.cs
@@ -759,7 +759,7 @@ namespace OpenSim.Region.Environment.Scenes
             }
 
             float posZLimit = (float)m_scene.GetLandHeight((int)pos.X, (int)pos.Y);
-            float newPosZ = posZLimit + localAVHeight;
+            float newPosZ = posZLimit + localAVHeight / 2;
             if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
             {
                 pos.Z = newPosZ;
@@ -1752,6 +1752,7 @@ namespace OpenSim.Region.Environment.Scenes
             Vector3 pos = m_pos;
             Vector3 vel = Velocity;
             Quaternion rot = m_bodyRot;
+            pos.Z -= m_appearance.HipOffset;
             remoteClient.SendAvatarTerseUpdate(m_regionHandle, (ushort)(m_scene.TimeDilation * (float)ushort.MaxValue), LocalId, new Vector3(pos.X, pos.Y, pos.Z),
                                                new Vector3(vel.X, vel.Y, vel.Z), rot);
 
@@ -1835,6 +1836,9 @@ namespace OpenSim.Region.Environment.Scenes
             // Note: because Quaternion is a struct, it can't be null
             Quaternion rot = m_bodyRot;
 
+            Vector3 pos = m_pos;
+            pos.Z -= m_appearance.HipOffset;
+
             remoteAvatar.m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid,
                                                             LocalId, m_pos, m_appearance.Texture.ToBytes(),
                                                             m_parentID, rot);
@@ -1900,6 +1904,9 @@ namespace OpenSim.Region.Environment.Scenes
             // Note: because Quaternion is a struct, it can't be null
             Quaternion rot = m_bodyRot;
 
+            Vector3 pos = m_pos;
+            pos.Z -= m_appearance.HipOffset;
+
             m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId,
                                                m_pos, m_appearance.Texture.ToBytes(), m_parentID, rot);
 
-- 
cgit v1.1