Browse Source

Removed nlerp animation blending as it was prone to artifacts.
Removed nlerp and operations using fast square root / fast inverse square root.

Lasse Öörni 14 years ago
parent
commit
3f36d0ffc9

+ 1 - 2
Bin/Data/Scripts/TestSceneOld.as

@@ -177,9 +177,8 @@ void InitScene()
         object.maxLights = 2;
 
         AnimationState@ anim = object.AddAnimationState(cache.GetResource("Animation", "Models/Jack_Walk.ani"));
-        anim.useNlerp = true;
         anim.looped = true;
-        anim.weight = 1;
+        anim.weight = 1.0;
 
         animatingObjects.Push(newNode);
     }

+ 0 - 2
Engine/Engine/GraphicsAPI.cpp

@@ -620,8 +620,6 @@ static void RegisterAnimatedModel(asIScriptEngine* engine)
     engine->RegisterObjectMethod("AnimationState", "float get_time() const", asMETHOD(AnimationState, GetTime), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimationState", "void set_layer(uint8)", asMETHOD(AnimationState, SetLayer), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimationState", "uint8 get_layer() const", asMETHOD(AnimationState, GetLayer), asCALL_THISCALL);
-    engine->RegisterObjectMethod("AnimationState", "void set_useNlerp(bool)", asMETHOD(AnimationState, SetUseNlerp), asCALL_THISCALL);
-    engine->RegisterObjectMethod("AnimationState", "bool get_useNlerp() const", asMETHOD(AnimationState, GetUseNlerp), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimationState", "Animation@+ get_animation() const", asMETHOD(AnimationState, GetAnimation), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimationState", "bool get_enabled() const", asMETHOD(AnimationState, IsEnabled), asCALL_THISCALL);
     engine->RegisterObjectMethod("AnimationState", "float get_length() const", asMETHOD(AnimationState, GetLength), asCALL_THISCALL);

+ 0 - 1
Engine/Engine/MathAPI.cpp

@@ -385,7 +385,6 @@ static void RegisterQuaternion(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Quaternion", "Quaternion Normalized() const", asMETHOD(Quaternion, Normalized), asCALL_THISCALL);
     engine->RegisterObjectMethod("Quaternion", "Quaternion Inverse() const", asMETHOD(Quaternion, Inverse), asCALL_THISCALL);
     engine->RegisterObjectMethod("Quaternion", "float DotProduct(const Quaternion&in) const", asMETHOD(Quaternion, DotProduct), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Quaternion", "Quaternion Nlerp(const Quaternion&in, float) const", asMETHOD(Quaternion, Nlerp), asCALL_THISCALL);
     engine->RegisterObjectMethod("Quaternion", "Quaternion Slerp(const Quaternion&in, float) const", asMETHOD(Quaternion, Slerp), asCALL_THISCALL);
     engine->RegisterObjectMethod("Quaternion", "String ToString() const", asMETHOD(Quaternion, ToString), asCALL_THISCALL);
     engine->RegisterObjectMethod("Quaternion", "Vector3 get_eulerAngles() const", asMETHOD(Quaternion, EulerAngles), asCALL_THISCALL);

+ 0 - 2
Engine/Graphics/AnimatedModel.cpp

@@ -701,7 +701,6 @@ void AnimatedModel::SetAnimationStatesAttr(VariantVector value)
             state->SetWeight(value[index++].GetFloat());
             state->SetTime(value[index++].GetFloat());
             state->SetLayer(value[index++].GetInt());
-            state->SetUseNlerp(value[index++].GetBool());
         }
         else
             index += 6;
@@ -735,7 +734,6 @@ VariantVector AnimatedModel::GetAnimationStatesAttr() const
         ret.Push(state->GetWeight());
         ret.Push(state->GetTime());
         ret.Push((int)state->GetLayer());
-        ret.Push(state->GetUseNlerp());
     }
     return ret;
 }

+ 4 - 8
Engine/Graphics/AnimationController.cpp

@@ -39,11 +39,10 @@
 static String noBoneName;
 
 static const unsigned char CTRL_LOOPED = 0x1;
-static const unsigned char CTRL_NLERP = 0x2;
-static const unsigned char CTRL_STARTBONE = 0x4;
-static const unsigned char CTRL_AUTOFADE = 0x8;
-static const unsigned char CTRL_SETTIME = 0x10;
-static const unsigned char CTRL_SETWEIGHT = 0x20;
+static const unsigned char CTRL_STARTBONE = 0x2;
+static const unsigned char CTRL_AUTOFADE = 0x4;
+static const unsigned char CTRL_SETTIME = 0x08;
+static const unsigned char CTRL_SETWEIGHT = 0x10;
 static const float EXTRA_ANIM_FADEOUT_TIME = 0.1f;
 static const float COMMAND_STAY_TIME = 0.25f;
 
@@ -536,7 +535,6 @@ void AnimationController::SetNetAnimationsAttr(const PODVector<unsigned char>& v
         unsigned char ctrl = buf.ReadUByte();
         state->SetLayer(buf.ReadUByte());
         state->SetLooped((ctrl & CTRL_LOOPED) != 0);
-        state->SetUseNlerp((ctrl & CTRL_NLERP) != 0);
         animations_[index].speed_ = (float)buf.ReadShort() / 2048.0f; // 11 bits of decimal precision, max. 16x playback speed
         animations_[index].targetWeight_ = (float)buf.ReadUByte() / 255.0f; // 8 bits of decimal precision
         animations_[index].fadeTime_ = (float)buf.ReadUByte() / 64.0f; // 6 bits of decimal precision, max. 4 seconds fade
@@ -626,8 +624,6 @@ const PODVector<unsigned char>& AnimationController::GetNetAnimationsAttr() cons
         Bone* startBone = state->GetStartBone();
         if (state->IsLooped())
             ctrl |= CTRL_LOOPED;
-        if (state->GetUseNlerp())
-            ctrl |= CTRL_NLERP;
         if (startBone && startBone != model->GetSkeleton().GetRootBone())
             ctrl |= CTRL_STARTBONE;
         if (i->autoFadeTime_ > 0.0f)

+ 5 - 29
Engine/Graphics/AnimationState.cpp

@@ -38,8 +38,7 @@ AnimationState::AnimationState(AnimatedModel* model, Animation* animation) :
     looped_(false),
     weight_(0.0f),
     time_(0.0f),
-    layer_(0),
-    useNlerp_(false)
+    layer_(0)
 {
     SetStartBone(0);
     
@@ -162,11 +161,6 @@ void AnimationState::SetLayer(unsigned char layer)
     }
 }
 
-void AnimationState::SetUseNlerp(bool enable)
-{
-    useNlerp_ = enable;
-}
-
 Bone* AnimationState::GetStartBone() const
 {
     return model_ ? startBone_ : 0;
@@ -235,12 +229,7 @@ void AnimationState::Apply()
                 if (channelMask & CHANNEL_POSITION)
                     boneNode->SetPosition(keyFrame->position_.Lerp(nextKeyFrame->position_, t));
                 if (channelMask & CHANNEL_ROTATION)
-                {
-                    if (!useNlerp_)
-                        boneNode->SetRotation(keyFrame->rotation_.Slerp(nextKeyFrame->rotation_, t));
-                    else
-                        boneNode->SetRotation(keyFrame->rotation_.NlerpFast(nextKeyFrame->rotation_, t));
-                }
+                    boneNode->SetRotation(keyFrame->rotation_.Slerp(nextKeyFrame->rotation_, t));
                 if (channelMask & CHANNEL_SCALE)
                     boneNode->SetScale(keyFrame->scale_.Lerp(nextKeyFrame->scale_, t));
             }
@@ -282,12 +271,7 @@ void AnimationState::Apply()
                 if (channelMask & CHANNEL_POSITION)
                     boneNode->SetPosition(boneNode->GetPosition().Lerp(keyFrame->position_, weight_));
                 if (channelMask & CHANNEL_ROTATION)
-                {
-                    if (!useNlerp_)
-                        boneNode->SetRotation(boneNode->GetRotation().Slerp(keyFrame->rotation_, weight_));
-                    else
-                        boneNode->SetRotation(boneNode->GetRotation().NlerpFast(keyFrame->rotation_, weight_));
-                }
+                    boneNode->SetRotation(boneNode->GetRotation().Slerp(keyFrame->rotation_, weight_));
                 if (channelMask & CHANNEL_SCALE)
                     boneNode->SetScale(boneNode->GetScale().Lerp(keyFrame->scale_, weight_));
             }
@@ -307,16 +291,8 @@ void AnimationState::Apply()
                 }
                 if (channelMask & CHANNEL_ROTATION)
                 {
-                    if (!useNlerp_)
-                    {
-                        boneNode->SetRotation(boneNode->GetRotation().Slerp(
-                            keyFrame->rotation_.Slerp(nextKeyFrame->rotation_, t), weight_));
-                    }
-                    else
-                    {
-                        boneNode->SetRotation(boneNode->GetRotation().NlerpFast(
-                            keyFrame->rotation_.NlerpFast(nextKeyFrame->rotation_, t), weight_));
-                    }
+                    boneNode->SetRotation(boneNode->GetRotation().Slerp(
+                        keyFrame->rotation_.Slerp(nextKeyFrame->rotation_, t), weight_));
                 }
                 if (channelMask & CHANNEL_SCALE)
                 {

+ 0 - 6
Engine/Graphics/AnimationState.h

@@ -57,8 +57,6 @@ public:
     void AddTime(float delta);
     /// %Set blending layer.
     void SetLayer(unsigned char layer);
-    /// %Set whether to use nlerp instead of slerp for rotation, default false.
-    void SetUseNlerp(bool enable);
     
     /// Return animation.
     Animation* GetAnimation() const { return animation_; }
@@ -76,8 +74,6 @@ public:
     float GetLength() const;
     /// Return blending layer.
     unsigned char GetLayer() const { return layer_; }
-    /// Return whether using nlerp for rotation.
-    bool GetUseNlerp() const { return useNlerp_; }
     
     /// Apply to the animated model's skeleton. Called by AnimatedModel.
     void Apply();
@@ -101,6 +97,4 @@ private:
     float time_;
     /// Blending layer.
     unsigned char layer_;
-    /// Nlerp flag.
-    bool useNlerp_;
 };

+ 1 - 1
Engine/Graphics/Camera.cpp

@@ -361,7 +361,7 @@ Vector3 Camera::GetUpVector()
 float Camera::GetDistance(const Vector3& worldPos)
 {
     if (!orthographic_)
-        return (worldPos - GetWorldPosition()).LengthFast();
+        return (worldPos - GetWorldPosition()).Length();
     else
         return fabsf((GetInverseWorldTransform() * worldPos).z_);
 }

+ 5 - 5
Engine/Graphics/Light.cpp

@@ -483,7 +483,7 @@ void Light::SetIntensitySortValue(const BoundingBox& box)
         {
             Vector3 centerPos = box.Center();
             Vector3 lightPos = GetWorldPosition();
-            Vector3 lightDir = (centerPos - lightPos).NormalizedFast();
+            Vector3 lightDir = (centerPos - lightPos).Normalized();
             Ray lightRay(lightPos, lightDir);
             float distance = lightRay.HitDistance(box);
             float normDistance = distance / range_;
@@ -500,16 +500,16 @@ void Light::SetIntensitySortValue(const BoundingBox& box)
             Ray lightRay(lightPos, lightDir);
             
             Vector3 centerProj = lightRay.Project(centerPos);
-            float centerDistance = (centerProj - lightPos).LengthFast();
-            Ray centerRay(centerProj, (centerPos - centerProj).NormalizedFast());
+            float centerDistance = (centerProj - lightPos).Length();
+            Ray centerRay(centerProj, (centerPos - centerProj).Normalized());
             float centerAngle = centerRay.HitDistance(box) / centerDistance;
             
             // Check if a corner of the bounding box is closer to the light ray than the center, use its angle in that case
             Vector3 cornerPos = centerPos + box.HalfSize() * Vector3(centerPos.x_ < centerProj.x_ ? 1.0f : -1.0f,
                 centerPos.y_ < centerProj.y_ ? 1.0f : -1.0f, centerPos.z_ < centerProj.z_ ? 1.0f : -1.0f);
             Vector3 cornerProj = lightRay.Project(cornerPos);
-            float cornerDistance = (cornerProj - lightPos).LengthFast();
-            float cornerAngle = (cornerPos - cornerProj).LengthFast() / cornerDistance;
+            float cornerDistance = (cornerProj - lightPos).Length();
+            float cornerAngle = (cornerPos - cornerProj).Length() / cornerDistance;
             
             float spotAngle = Min(centerAngle, cornerAngle);
             float maxAngle = tanf(fov_ * M_DEGTORAD * 0.5f);

+ 6 - 6
Engine/Graphics/View.cpp

@@ -490,7 +490,7 @@ void View::GetDrawables()
             // as the bounding boxes are also used for shadow focusing
             const BoundingBox& geomBox = drawable->GetWorldBoundingBox();
             BoundingBox geomViewBox = geomBox.Transformed(view);
-            if (geomBox.Size().LengthFast() < M_LARGE_VALUE)
+            if (geomBox.Size().LengthSquared() < M_LARGE_VALUE * M_LARGE_VALUE)
             {
                 sceneBox_.Merge(geomBox);
                 sceneViewBox_.Merge(geomViewBox);
@@ -1480,7 +1480,7 @@ void View::UpdateOccluders(PODVector<Drawable*>& occluders, Camera* camera)
         {
             // Check that occluder is big enough on the screen
             const BoundingBox& box = occluder->GetWorldBoundingBox();
-            float diagonal = (box.max_ - box.min_).LengthFast();
+            float diagonal = (box.max_ - box.min_).Length();
             float compare;
             if (!camera->IsOrthographic())
                 compare = diagonal * halfViewSize / occluder->GetDistance();
@@ -1730,7 +1730,7 @@ bool View::IsShadowCasterVisible(Drawable* drawable, BoundingBox lightViewBox, C
         Ray extrusionRay(center, center.Normalized());
         
         float extrusionDistance = shadowCamera->GetFarClip();
-        float originalDistance = Clamp(center.LengthFast(), M_EPSILON, extrusionDistance);
+        float originalDistance = Clamp(center.Length(), M_EPSILON, extrusionDistance);
         
         // Because of the perspective, the bounding box must also grow when it is extruded to the distance
         float sizeFactor = extrusionDistance / originalDistance;
@@ -1804,7 +1804,7 @@ void View::OptimizeLightByStencil(Light* light)
         float lightDist;
         
         if (type == LIGHT_POINT)
-            lightDist = Sphere(light->GetWorldPosition(), light->GetRange() * 1.25f).DistanceFast(camera_->GetWorldPosition());
+            lightDist = Sphere(light->GetWorldPosition(), light->GetRange() * 1.25f).Distance(camera_->GetWorldPosition());
         else
             lightDist = light->GetFrustum().Distance(camera_->GetWorldPosition());
         
@@ -1988,7 +1988,7 @@ void View::SetupDirLightShadowCamera(Camera* shadowCamera, Light* light, float n
         {
             // Skip "infinite" objects like the skybox
             const BoundingBox& geomBox = geometries_[i]->GetWorldBoundingBox();
-            if (geomBox.Size().LengthFast() < M_LARGE_VALUE)
+            if (geomBox.Size().LengthSquared() < M_LARGE_VALUE * M_LARGE_VALUE)
             {
                 if (geometryDepthBounds_[i].min_ <= farSplit && geometryDepthBounds_[i].max_ >= nearSplit &&
                     (GetLightMask(geometries_[i]) & light->GetLightMask()))
@@ -2345,7 +2345,7 @@ void View::SetupLightVolumeBatch(Batch& batch)
     if (type != LIGHT_DIRECTIONAL)
     {
         if (type == LIGHT_POINT)
-            lightDist = Sphere(light->GetWorldPosition(), light->GetRange() * 1.25f).DistanceFast(camera_->GetWorldPosition());
+            lightDist = Sphere(light->GetWorldPosition(), light->GetRange() * 1.25f).Distance(camera_->GetWorldPosition());
         else
             lightDist = light->GetFrustum().Distance(camera_->GetWorldPosition());
         

+ 0 - 33
Engine/Math/MathDefs.h

@@ -109,41 +109,8 @@ inline unsigned NextPowerOfTwo(unsigned value)
     return ret;
 }
 
-/// Fast square root.
-inline float FastSqrt(float x)
-{
-    union
-    {
-        float f;
-        int i;
-    } u;
-    
-    u.f = x;
-    u.i -= 1 << 23;
-    u.i >>= 1;
-    u.i += 1 << 29;
-    return u.f;
-}
-
-/// Fast inverse square root.
-inline float FastInvSqrt(float x)
-{
-    union
-    {
-        float f;
-        int i;
-    } u;
-    
-    float xHalf = 0.5f * x;
-    u.f = x;
-    u.i = 0x5f3759df - (u.i >> 1);
-    x = u.f * (1.5f - xHalf * u.f * u.f);
-    return x;
-}
-
 /// Update a hash with the given 8-bit value using the SDBM algorithm.
 inline unsigned SDBMHash(unsigned hash, unsigned char c) { return c + (hash << 6) + (hash << 16) - hash; }
-
 /// Return a random float between 0.0 (inclusive) and 1.0 (exclusive.)
 inline float Random() { return (Rand() & 32767) / 32768.0f; }
 /// Return a random float between 0.0 and range, inclusive.

+ 0 - 17
Engine/Math/Quaternion.h

@@ -176,16 +176,6 @@ public:
         return len;
     }
     
-    /// Normalize to unit length using fast inverse square root.
-    void NormalizeFast()
-    {
-        float invLen = FastInvSqrt(w_ * w_ + x_ * x_ + y_ * y_ + z_ * z_);
-        w_ *= invLen;
-        x_ *= invLen;
-        y_ *= invLen;
-        z_ *= invLen;
-    }
-    
     /// Return normalized to unit length.
     Quaternion Normalized() const
     {
@@ -196,9 +186,6 @@ public:
             return IDENTITY;
     }
     
-    /// Return normalized to unit length, using fast inverse square root.
-    Quaternion NormalizedFast() const { return *this * FastInvSqrt(w_ * w_ + x_ * x_ + y_ * y_ + z_ * z_); }
-    
     /// Return inverse.
     Quaternion Inverse() const
     {
@@ -221,10 +208,6 @@ public:
     float LengthSquared() const { return w_ * w_ + x_ * x_ + y_ * y_ + z_ * z_; }
     /// Calculate dot product.
     float DotProduct(const Quaternion& rhs) const { return w_ * rhs.w_ + x_ * rhs.x_ + y_ * rhs.y_ + z_ * rhs.z_; }
-    /// Normalized interpolation with another quaternion.
-    Quaternion Nlerp(const Quaternion& rhs, float t) const { return (*this * (1.0f - t) + rhs * t).Normalized(); }
-    /// Normalized interpolation with another quaternion, using fast inverse square root.
-    Quaternion NlerpFast(const Quaternion& rhs, float t) const { return (*this * (1.0f - t) + rhs * t).NormalizedFast(); }
     
     /// Return Euler angles in degrees.
     Vector3 EulerAngles() const;

+ 0 - 3
Engine/Math/Sphere.h

@@ -205,9 +205,6 @@ public:
     /// Return distance of a point to the surface, or 0 if inside.
     float Distance(const Vector3& point) const { return Max((point - center_).Length() - radius_, 0.0f); }
     
-    /// Return distance of a point to the surface, or 0 if inside, using fast square root.
-    float DistanceFast(const Vector3& point) const { return Max((point - center_).LengthFast() - radius_, 0.0f); }
-    
     /// Sphere center.
     Vector3 center_;
     /// Sphere radius.

+ 0 - 13
Engine/Math/Vector2.h

@@ -146,18 +146,8 @@ public:
         return len;
     }
     
-    /// Normalize to unit length using fast inverse square root.
-    void NormalizeFast()
-    {
-        float invLen = FastInvSqrt(x_ * x_ + y_ * y_);
-        x_ *= invLen;
-        y_ *= invLen;
-    }
-    
     /// Return length.
     float Length() const { return sqrtf(x_ * x_ + y_ * y_); }
-    /// Return length using fast square root.
-    float LengthFast() const { return FastSqrt(x_ * x_ + y_ * y_); }
     /// Return squared length.
     float LengthSquared() const { return x_ * x_ + y_ * y_; }
     /// Calculate dot product.
@@ -179,9 +169,6 @@ public:
             return *this;
     }
     
-    /// Return normalized to unit length using fast inverse square root.
-    Vector2 NormalizedFast() const { return *this * FastInvSqrt(x_ * x_ + y_ * y_); }
-    
     /// Return float data.
     const float* GetData() const { return &x_; }
     /// Return as string.

+ 0 - 14
Engine/Math/Vector3.h

@@ -164,19 +164,8 @@ public:
         return len;
     }
     
-    /// Normalize to unit length using fast inverse square root.
-    void NormalizeFast()
-    {
-        float invLen = FastInvSqrt(x_ * x_ + y_ * y_ + z_ * z_);
-        x_ *= invLen;
-        y_ *= invLen;
-        z_ *= invLen;
-    }
-    
     /// Return length.
     float Length() const { return sqrtf(x_ * x_ + y_ * y_ + z_ * z_); }
-    /// Return length using fast square root.
-    float LengthFast() const { return FastSqrt(x_ * x_ + y_ * y_ + z_ * z_); }
     /// Return squared length.
     float LengthSquared() const { return x_ * x_ + y_ * y_ + z_ * z_; }
     /// Calculate dot product.
@@ -209,9 +198,6 @@ public:
             return *this;
     }
     
-    /// Return normalized to unit length using fast inverse square root.
-    Vector3 NormalizedFast() const { return *this * FastInvSqrt(x_ * x_ + y_ * y_ + z_ * z_); }
-    
     /// Return float data.
     const float* GetData() const { return &x_; }
     /// Return as string.

+ 1 - 1
Engine/Network/Connection.cpp

@@ -1082,7 +1082,7 @@ void Connection::ProcessExistingNode(Node* node)
     NetworkPriority* priority = node->GetComponent<NetworkPriority>();
     if (priority && (!priority->GetAlwaysUpdateOwner() || node->GetOwner() != this))
     {
-        float distance = (node->GetWorldPosition() - position_).LengthFast();
+        float distance = (node->GetWorldPosition() - position_).Length();
         if (!priority->CheckUpdate(distance, nodeState.priorityAcc_))
             return;
     }