쿼터니언
짐벌락
bool Matrix::Decompose(Vector3& scale, Quaternion& rotation, Vector3& translation)
Component
Transform
//Local
Vec3 GetLocalScale() { return localScale; }
Vec3 GetLocalRotation() { return localRotation; }
Vec3 GetLocalPosition() { return localPosition; }
//World
Vec3 GetScale() { return scale; }
Vec3 GetRotation() { return rotation; }
Vec3 GetPosition() { return position; }
Matrix GetWorldMatrix() { return matWorld; }
//계층 관계
bool HasParnet() { return parent != nullptr; }
shared_ptr<Transform> GetParent() { return parent; }
void SetParent(shared_ptr<Transform> Parent) { parent = Parent; }
const vector<shared_ptr<Transform>>& GetChildren() { return children; }
void AddChild(shared_ptr<Transform> Child) { children.push_back(Child); }
...
Vec3 Transform::ToEulerAngles(Quaternion q)
{
Vec3 angles;
// roll (x-axis rotation)
double sinr_cosp = 2 * (q.w * q.x + q.y * q.z);
double cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y);
angles.x = std::atan2(sinr_cosp, cosr_cosp);
// pitch (y-axis rotation)
double sinp = std::sqrt(1 + 2 * (q.w * q.y - q.x * q.z));
double cosp = std::sqrt(1 - 2 * (q.w * q.y - q.x * q.z));
angles.y = 2 * std::atan2(sinp, cosp) - 3.14159f / 2;
// yaw (z-axis rotation)
double siny_cosp = 2 * (q.w * q.z + q.x * q.y);
double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
angles.z = std::atan2(siny_cosp, cosy_cosp);
return angles;
}
void Transform::UpdateTransform()
{
Matrix matscale = Matrix::CreateScale(localScale);
Matrix matrotation = Matrix::CreateRotationX(localRotation.x);
matrotation *= Matrix::CreateRotationY(localRotation.y);
matrotation *= Matrix::CreateRotationZ(localRotation.z);
Matrix mattranslation = Matrix::CreateTranslation(localPosition);
matLocal = matscale * matrotation * mattranslation;
if (HasParnet() == true)
matWorld = matLocal * parent->GetWorldMatrix();
else
matWorld = matLocal;
Quaternion quat;
matWorld.Decompose(scale, quat, position);
rotation = ToEulerAngles(quat);
right = Vec3::TransformNormal(Vec3::Right, matWorld);
up = Vec3::TransformNormal(Vec3::Up, matWorld);
look = Vec3::TransformNormal(Vec3::Backward, matWorld);
//Dx에서 왼존 좌표계를 사용하지만 SimpleMath는 오른손 좌표계로 만들어져 있어 Forward가 아닌 Backward를 사용함
//Children
for (const shared_ptr<Transform>& c : children)
c->UpdateTransform();
}
void Transform::SetLocalScale(const Vec3& Scale)
{
localScale = Scale;
UpdateTransform();
}
void Transform::SetLocalRotation(const Vec3& Rotation)
{
localRotation = Rotation;
UpdateTransform();
}
void Transform::SetLocalPosition(const Vec3& Position)
{
localPosition = Position;
UpdateTransform();
}
void Transform::SetScale(const Vec3& Scale)
{
if (HasParnet() == true)
{
Vec3 parentScale = parent->GetScale();
Vec3 tempScale = Scale;
tempScale.x /= parentScale.x;
tempScale.y /= parentScale.y;
tempScale.z /= parentScale.z;
SetLocalScale(tempScale);
}
else
SetLocalScale(Scale);
}
void Transform::SetRotation(const Vec3& Rotation)
{
if (HasParnet() == true)
{
Matrix worldToParentLocalMatrix = parent->GetWorldMatrix().Invert();
Vec3 tempRotation;
tempRotation.Transform(Rotation, worldToParentLocalMatrix);
SetLocalRotation(tempRotation);
}
else
SetLocalRotation(Rotation);
}
void Transform::SetPosition(const Vec3& Position)
{
if (HasParnet() == true)
{
//부모의 local에서 world로 가는 변환 행렬의 역행렬을 구하면 월드 좌표계를 기준으로 존재한 좌표를
//부모좌표계를 기준으로 좌표를 변환할 수 있다
Matrix worldToParentLocalMatrix = parent->GetWorldMatrix().Invert();
Vec3 tempPosition;
tempPosition.Transform(Position, worldToParentLocalMatrix);
SetLocalPosition(tempPosition);
}
else
SetLocalPosition(Position);
}
void GameObject::Update()
{
//Vec3 pos = transform->GetPosition();
//pos.x += 0.001f;
//transform->SetPosition(pos);
Vec3 pos = parent->GetPosition();
pos.x += 0.001f;
parent->SetPosition(pos);
Vec3 rot = parent->GetRotation();
rot.z += 0.001f;
parent->SetRotation(rot);
transformData.World = transform->GetWorldMatrix();
constantBuffer->CopyData(transformData);
}