336 lines
7.6 KiB
C++
336 lines
7.6 KiB
C++
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
|
// This file is part of the "Nazara Engine - Utility module"
|
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
|
|
|
#include <Nazara/Utility/Node.hpp>
|
|
#include <Nazara/Utility/Debug.hpp>
|
|
|
|
namespace Nz
|
|
{
|
|
Node::~Node()
|
|
{
|
|
OnNodeRelease(this);
|
|
|
|
for (Node* child : m_childs)
|
|
{
|
|
// child->SetParent(nullptr); serait problématique car elle nous appellerait
|
|
child->m_parent = nullptr;
|
|
child->InvalidateNode(Invalidation::InvalidateRecursively);
|
|
child->OnParenting(nullptr);
|
|
}
|
|
|
|
SetParent(nullptr);
|
|
}
|
|
|
|
NodeType Node::GetNodeType() const
|
|
{
|
|
return NodeType::Default;
|
|
}
|
|
|
|
Node& Node::Interpolate(const Node& nodeA, const Node& nodeB, float interpolation, CoordSys coordSys, Invalidation invalidation)
|
|
{
|
|
switch (coordSys)
|
|
{
|
|
case CoordSys::Global:
|
|
nodeA.EnsureDerivedUpdate();
|
|
nodeB.EnsureDerivedUpdate();
|
|
|
|
m_position = ToLocalPosition(Vector3f::Lerp(nodeA.m_derivedPosition, nodeB.m_derivedPosition, interpolation));
|
|
m_rotation = ToLocalRotation(Quaternionf::Slerp(nodeA.m_derivedRotation, nodeB.m_derivedRotation, interpolation));
|
|
m_scale = ToLocalScale(Vector3f::Lerp(nodeA.m_derivedScale, nodeB.m_derivedScale, interpolation));
|
|
break;
|
|
|
|
case CoordSys::Local:
|
|
m_position = Vector3f::Lerp(nodeA.m_position, nodeB.m_position, interpolation);
|
|
m_rotation = Quaternionf::Slerp(nodeA.m_rotation, nodeB.m_rotation, interpolation);
|
|
m_scale = Vector3f::Lerp(nodeA.m_scale, nodeB.m_scale, interpolation);
|
|
break;
|
|
}
|
|
|
|
Invalidate(invalidation);
|
|
|
|
return *this;
|
|
}
|
|
|
|
Node& Node::Move(const Vector3f& movement, CoordSys coordSys, Invalidation invalidation)
|
|
{
|
|
switch (coordSys)
|
|
{
|
|
case CoordSys::Global:
|
|
{
|
|
if (m_parent)
|
|
{
|
|
m_parent->EnsureDerivedUpdate();
|
|
|
|
m_position += (m_parent->m_derivedRotation.GetConjugate()*(movement - m_parent->m_derivedPosition))/m_parent->m_derivedScale; // Compensation
|
|
}
|
|
else
|
|
m_position += movement; // Rien n'affecte le node
|
|
|
|
break;
|
|
}
|
|
|
|
case CoordSys::Local:
|
|
m_position += m_rotation * movement;
|
|
break;
|
|
}
|
|
|
|
Invalidate(invalidation);
|
|
|
|
return *this;
|
|
}
|
|
|
|
Node& Node::Rotate(const Quaternionf& rotation, CoordSys coordSys, Invalidation invalidation)
|
|
{
|
|
switch (coordSys)
|
|
{
|
|
case CoordSys::Global:
|
|
{
|
|
EnsureDerivedUpdate();
|
|
|
|
m_rotation *= m_derivedRotation.GetInverse() * rotation * m_derivedRotation; ///FIXME: Correct ?
|
|
break;
|
|
}
|
|
|
|
case CoordSys::Local:
|
|
m_rotation *= rotation;
|
|
break;
|
|
}
|
|
|
|
m_rotation.Normalize();
|
|
|
|
Invalidate(invalidation);
|
|
|
|
return *this;
|
|
}
|
|
|
|
void Node::SetParent(const Node* node, bool keepDerived, Invalidation invalidation)
|
|
{
|
|
#if NAZARA_UTILITY_SAFE
|
|
// On vérifie que le node n'est pas son propre parent
|
|
const Node* parentNode = node;
|
|
while (parentNode)
|
|
{
|
|
if (parentNode == this)
|
|
{
|
|
NazaraError("A node cannot be it's own parent");
|
|
return;
|
|
}
|
|
|
|
parentNode = parentNode->GetParent();
|
|
}
|
|
#endif
|
|
|
|
if (m_parent == node)
|
|
return;
|
|
|
|
if (keepDerived)
|
|
{
|
|
EnsureDerivedUpdate();
|
|
|
|
if (m_parent)
|
|
m_parent->RemoveChild(this);
|
|
|
|
m_parent = node;
|
|
if (m_parent)
|
|
m_parent->AddChild(this);
|
|
|
|
SetRotation(m_derivedRotation, CoordSys::Global, Invalidation::DontInvalidate);
|
|
SetScale(m_derivedScale, CoordSys::Global, Invalidation::DontInvalidate);
|
|
SetPosition(m_derivedPosition, CoordSys::Global, Invalidation::DontInvalidate);
|
|
|
|
Invalidate(invalidation);
|
|
}
|
|
else
|
|
{
|
|
if (m_parent)
|
|
m_parent->RemoveChild(this);
|
|
|
|
m_parent = node;
|
|
if (m_parent)
|
|
m_parent->AddChild(this);
|
|
|
|
Invalidate(invalidation);
|
|
}
|
|
|
|
OnParenting(node);
|
|
}
|
|
|
|
void Node::SetPosition(const Vector3f& position, CoordSys coordSys, Invalidation invalidation)
|
|
{
|
|
switch (coordSys)
|
|
{
|
|
case CoordSys::Global:
|
|
{
|
|
if (m_parent && m_inheritPosition)
|
|
{
|
|
m_parent->EnsureDerivedUpdate();
|
|
|
|
m_position = (m_parent->m_derivedRotation.GetConjugate() * (position - m_parent->m_derivedPosition)) / m_parent->m_derivedScale - m_initialPosition;
|
|
}
|
|
else
|
|
m_position = position - m_initialPosition;
|
|
break;
|
|
}
|
|
|
|
case CoordSys::Local:
|
|
m_position = position;
|
|
break;
|
|
}
|
|
|
|
Invalidate(invalidation);
|
|
}
|
|
|
|
void Node::SetRotation(const Quaternionf& rotation, CoordSys coordSys, Invalidation invalidation)
|
|
{
|
|
switch (coordSys)
|
|
{
|
|
case CoordSys::Global:
|
|
if (m_parent && m_inheritRotation)
|
|
{
|
|
Quaternionf rot(m_parent->GetRotation() * m_initialRotation);
|
|
|
|
m_rotation = rot.GetConjugate() * rotation;
|
|
}
|
|
else
|
|
m_rotation = rotation;
|
|
|
|
break;
|
|
|
|
case CoordSys::Local:
|
|
m_rotation = rotation;
|
|
break;
|
|
}
|
|
|
|
Invalidate(invalidation);
|
|
}
|
|
|
|
void Node::SetScale(const Vector3f& scale, CoordSys coordSys, Invalidation invalidation)
|
|
{
|
|
switch (coordSys)
|
|
{
|
|
case CoordSys::Global:
|
|
if (m_parent && m_inheritScale)
|
|
m_scale = scale / (m_initialScale * m_parent->GetScale());
|
|
else
|
|
m_scale = scale / m_initialScale;
|
|
break;
|
|
|
|
case CoordSys::Local:
|
|
m_scale = scale;
|
|
break;
|
|
}
|
|
|
|
Invalidate(invalidation);
|
|
}
|
|
|
|
void Node::SetTransform(const Vector3f& position, const Quaternionf& rotation, const Vector3f& scale, CoordSys coordSys, Invalidation invalidation)
|
|
{
|
|
switch (coordSys)
|
|
{
|
|
case CoordSys::Global:
|
|
{
|
|
// Position
|
|
if (m_parent && m_inheritPosition)
|
|
{
|
|
m_parent->EnsureDerivedUpdate();
|
|
|
|
m_position = (m_parent->m_derivedRotation.GetConjugate() * (position - m_parent->m_derivedPosition)) / m_parent->m_derivedScale - m_initialPosition;
|
|
}
|
|
else
|
|
m_position = position - m_initialPosition;
|
|
|
|
// Rotation
|
|
if (m_parent && m_inheritRotation)
|
|
{
|
|
Quaternionf rot(m_parent->GetRotation() * m_initialRotation);
|
|
|
|
m_rotation = rot.GetConjugate() * rotation;
|
|
}
|
|
else
|
|
m_rotation = rotation;
|
|
|
|
// Scale
|
|
if (m_parent && m_inheritScale)
|
|
m_scale = scale / (m_initialScale * m_parent->GetScale());
|
|
else
|
|
m_scale = scale / m_initialScale;
|
|
|
|
break;
|
|
}
|
|
|
|
case CoordSys::Local:
|
|
m_position = position;
|
|
m_rotation = rotation;
|
|
m_scale = scale;
|
|
break;
|
|
}
|
|
|
|
Invalidate(invalidation);
|
|
}
|
|
|
|
void Node::InvalidateNode(Invalidation invalidation)
|
|
{
|
|
m_derivedUpdated = false;
|
|
m_transformMatrixUpdated = false;
|
|
|
|
if (invalidation == Invalidation::InvalidateRecursively)
|
|
{
|
|
for (Node* node : m_childs)
|
|
node->InvalidateNode(invalidation);
|
|
}
|
|
|
|
OnNodeInvalidation(this);
|
|
}
|
|
|
|
void Node::OnParenting(const Node* parent)
|
|
{
|
|
OnNodeNewParent(this, parent);
|
|
}
|
|
|
|
void Node::UpdateDerived() const
|
|
{
|
|
if (m_parent)
|
|
{
|
|
m_parent->EnsureDerivedUpdate();
|
|
|
|
if (m_inheritPosition)
|
|
m_derivedPosition = m_parent->m_derivedRotation*(m_parent->m_derivedScale * (m_initialPosition + m_position)) + m_parent->m_derivedPosition;
|
|
else
|
|
m_derivedPosition = m_initialPosition + m_position;
|
|
|
|
if (m_inheritRotation)
|
|
{
|
|
Quaternionf rotation = m_initialRotation * m_rotation;
|
|
if (m_inheritScale)
|
|
rotation = Quaternionf::Mirror(rotation, m_parent->m_derivedScale);
|
|
|
|
m_derivedRotation = m_parent->m_derivedRotation * rotation;
|
|
m_derivedRotation.Normalize();
|
|
}
|
|
else
|
|
m_derivedRotation = m_initialRotation * m_rotation;
|
|
|
|
m_derivedScale = m_initialScale * m_scale;
|
|
if (m_inheritScale)
|
|
m_derivedScale *= m_parent->m_derivedScale;
|
|
}
|
|
else
|
|
{
|
|
m_derivedPosition = m_initialPosition + m_position;
|
|
m_derivedRotation = m_initialRotation * m_rotation;
|
|
m_derivedScale = m_initialScale * m_scale;
|
|
}
|
|
|
|
m_derivedUpdated = true;
|
|
}
|
|
|
|
void Node::UpdateTransformMatrix() const
|
|
{
|
|
EnsureDerivedUpdate();
|
|
|
|
m_transformMatrix.MakeTransform(m_derivedPosition, m_derivedRotation, m_derivedScale);
|
|
m_transformMatrixUpdated = true;
|
|
}
|
|
}
|