浏览代码

Do not concatenate worldscale separately.
Use matrix math to calculate new transform when node is reparented, instead of setting T/R/S separately. This allows better match of effective scale even when parent node has nonuniform scale.

Lasse Öörni 12 年之前
父节点
当前提交
5d07d7aa23
共有 2 个文件被更改,包括 10 次插入26 次删除
  1. 7 21
      Engine/Scene/Node.cpp
  2. 3 5
      Engine/Scene/Node.h

+ 7 - 21
Engine/Scene/Node.cpp

@@ -52,7 +52,6 @@ Node::Node(Context* context) :
     rotation_(Quaternion::IDENTITY),
     scale_(Vector3::ONE),
     worldRotation_(Quaternion::IDENTITY),
-    worldScale_(Vector3::ONE),
     owner_(0)
 {
 }
@@ -299,28 +298,17 @@ void Node::SetTransform(const Vector3& position, const Quaternion& rotation, con
 
 void Node::SetWorldPosition(const Vector3& position)
 {
-    if (!parent_)
-        SetPosition(position);
-    else
-        SetPosition(parent_->GetWorldTransform().Inverse() * position);
+    SetPosition(parent_ ? parent_->GetWorldTransform().Inverse() * position : position);
 }
 
 void Node::SetWorldRotation(const Quaternion& rotation)
 {
-    if (!parent_)
-        SetRotation(rotation);
-    else
-        SetRotation(parent_->GetWorldRotation().Inverse() * rotation);
+    SetRotation(parent_ ? parent_->GetWorldRotation().Inverse() * rotation : rotation);
 }
 
 void Node::SetWorldDirection(const Vector3& direction)
 {
-    Vector3 localDirection;
-    if (!parent_)
-        localDirection = direction;
-    else
-        localDirection = parent_->GetWorldRotation().Inverse() * direction;
-    
+    Vector3 localDirection = parent_ ? parent_->GetWorldRotation().Inverse() * direction : direction;
     SetRotation(Quaternion(Vector3::FORWARD, localDirection));
 }
 
@@ -676,12 +664,12 @@ void Node::SetParent(Node* parent)
 {
     if (parent)
     {
-        Vector3 oldWorldPos = GetWorldPosition();
-        Quaternion oldWorldRot = GetWorldRotation();
-        Vector3 oldWorldScale = GetWorldScale();;
+        Matrix3x4 oldWorldTransform = GetWorldTransform();
         
         parent->AddChild(this);
-        SetWorldTransform(oldWorldPos, oldWorldRot, oldWorldScale);
+        
+        Matrix3x4 newTransform = parent->GetWorldTransform().Inverse() * oldWorldTransform;
+        SetTransform(newTransform.Translation(), newTransform.Rotation(), newTransform.Scale());
     }
 }
 
@@ -1273,13 +1261,11 @@ void Node::UpdateWorldTransform() const
     {
         worldTransform_ = parent_->GetWorldTransform() * transform;
         worldRotation_ = parent_->GetWorldRotation() * rotation_;
-        worldScale_ = parent_->GetWorldScale() * scale_;
     }
     else
     {
         worldTransform_ = transform;
         worldRotation_ = rotation_;
-        worldScale_ = scale_;
     }
     
     dirty_ = false;

+ 3 - 5
Engine/Scene/Node.h

@@ -224,16 +224,16 @@ public:
         return worldRotation_ * Vector3::FORWARD;
     }
 
-    /// Return scale in world space. May not be correct when transform includes shearing (rotation + nonuniform scale).
+    /// Return scale in world space.
     Vector3 GetWorldScale() const
     {
         if (dirty_)
             UpdateWorldTransform();
         
-        return worldScale_;
+        return worldTransform_.Scale();
     }
 
-    /// Return transform matrix in world space. Note: to handle non-uniform parent scale correctly, do not extract rotation or scale from this.
+    /// Return transform matrix in world space.
     const Matrix3x4& GetWorldTransform() const
     {
         if (dirty_)
@@ -378,8 +378,6 @@ private:
     Vector3 scale_;
     /// World-space rotation.
     mutable Quaternion worldRotation_;
-    /// World-space scale.
-    mutable Vector3 worldScale_;
     /// Components.
     Vector<SharedPtr<Component> > components_;
     /// Child scene nodes.