Skip to content
This repository was archived by the owner on Mar 15, 2025. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions dang-gl/include/dang-gl/Math/Transform.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,34 @@ class Transform {
public:
using Event = dutils::Event<Transform>;

/// @brief Creates a new pointer-based transform.
static UniqueTransform create();
/// @brief Allows for implicit construction from a dual quaternion.
Transform(const dquat& own_transform = {});

// TODO: Copy is currently disabled because of event subscription
// Implement copy to properly update the subscription

/// @brief The own transformation, without any parent transform.
const dquat& ownTransform() const;
/// @brief Sets the own transform to the given quaternion, triggering the on_change event.
void setOwnTransform(const dquat& transform);

/// @brief The full transformation, including all parent transformations.
const dquat& fullTransform();
const dquat& fullTransform() const;

/// @brief The optional parent of this transformation.
SharedTransform parent() const;
const SharedTransform& parent() const;
/// @brief Checks, if the chain of parents contains the given transform.
bool parentChainContains(const Transform& transform) const;
/// @brief UNSAFE! Forces the parent of this transform to the given transform, without checking for potential
/// cycles.
/// @remark A cycle will cause an immediate stack overflow, from recursively calling parent change events.
void forceParent(const SharedTransform& parent);
void forceParent(SharedTransform parent);
/// @brief Tries to set the parent of this transform to the given transform and returns false if it would introduce
/// a cycle.
bool trySetParent(const SharedTransform& parent);
bool trySetParent(SharedTransform parent);
/// @brief Tries to set the parent of this transform to the given transform and throws a TransformCycleError if it
/// would introduce a cycle.
void setParent(const SharedTransform& parent);
void setParent(SharedTransform parent);
/// @brief Removes the current parent, which is the same as setting the parent to nullptr.
void resetParent();

Expand All @@ -59,7 +62,7 @@ class Transform {

private:
dquat own_transform_;
std::optional<dquat> full_transform_;
mutable std::optional<dquat> full_transform_;
SharedTransform parent_;
Event::Subscription parent_change_;
};
Expand Down
2 changes: 1 addition & 1 deletion dang-gl/include/dang-gl/Rendering/Camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class Camera {

private:
SharedProjectionProvider projection_provider_;
SharedTransform transform_ = Transform::create();
SharedTransform transform_ = std::make_shared<Transform>();
mutable std::vector<CameraUniforms> uniforms_;
};

Expand Down
32 changes: 15 additions & 17 deletions dang-gl/src/Math/Transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace dang::gl {

UniqueTransform Transform::create() { return std::make_unique<Transform>(); }
Transform::Transform(const dquat& own_transform)
: own_transform_(own_transform)
{}

const dquat& Transform::ownTransform() const { return own_transform_; }

Expand All @@ -13,18 +15,14 @@ void Transform::setOwnTransform(const dquat& transform)
on_change(*this);
}

const dquat& Transform::fullTransform()
const dquat& Transform::fullTransform() const
{
if (!full_transform_) {
if (parent_)
full_transform_ = own_transform_ * parent_->fullTransform();
else
full_transform_ = own_transform_;
}
if (!full_transform_)
full_transform_ = parent_ ? own_transform_ * parent_->fullTransform() : own_transform_;
return *full_transform_;
}

SharedTransform Transform::parent() const { return parent_; }
const SharedTransform& Transform::parent() const { return parent_; }

bool Transform::parentChainContains(const Transform& transform) const
{
Expand All @@ -39,15 +37,15 @@ bool Transform::parentChainContains(const Transform& transform) const
return false;
}

void Transform::forceParent(const SharedTransform& parent)
void Transform::forceParent(SharedTransform parent)
{
parent_ = parent;
if (parent) {
parent_ = std::move(parent);
if (parent_) {
auto parent_change = [&] {
full_transform_.reset();
on_change(*this);
};
parent_change_ = parent->on_change.subscribe(parent_change);
parent_change_ = parent_->on_change.subscribe(parent_change);
}
else {
parent_change_.remove();
Expand All @@ -57,22 +55,22 @@ void Transform::forceParent(const SharedTransform& parent)
on_change(*this);
}

bool Transform::trySetParent(const SharedTransform& parent)
bool Transform::trySetParent(SharedTransform parent)
{
if (parent == parent_)
return true;

if (parent && parent->parentChainContains(*this))
return false;

forceParent(parent);
forceParent(std::move(parent));

return true;
}

void Transform::setParent(const SharedTransform& parent)
void Transform::setParent(SharedTransform parent)
{
if (!trySetParent(parent))
if (!trySetParent(std::move(parent)))
throw TransformCycleError("Cannot set transform parent, as it would introduce a cycle.");
}

Expand Down