#pragma once #include namespace orange { struct Transform { vec3 position{ 0.0f }; quat orientation{}; // my orientation is gay vec3 scale{ 1.0f }; }; // World = Parent * Local inline Transform operator*(const Transform& parent, const Transform& local) { return Transform { .position = parent.position + parent.orientation * (parent.scale * local.position), .orientation = parent.orientation * local.orientation, .scale = parent.scale * (parent.orientation * local.scale), }; } inline Transform& operator*=(Transform& parent, const Transform& local) { parent = parent * local; return parent; } // Local = World / Parent inline Transform operator/(const Transform& world, const Transform& parent) { const Quaternion parentConjugate = conjugate(parent.orientation); return Transform { .position = (parentConjugate * (world.position - parent.position)) / parent.scale, .orientation = (parentConjugate * world.orientation), .scale = (parentConjugate * (world.scale / parent.scale)), }; } inline Transform& operator/=(Transform& world, const Transform& parent) { world = world / parent; return world; } inline vec3 transformPoint(const Transform& transform, const vec3& point) { return (conjugate(transform.orientation) * (transform.position - point)) / transform.scale; } inline Transform inverse(const Transform& t) { const Quaternion invOrientation{ conjugate(t.orientation) }; return Transform { .position = (invOrientation * -t.position) / t.scale, .orientation = (invOrientation), .scale = (invOrientation * (vec3{ 1.0f } / t.scale)), }; } // Returns true if a Transform does bugger all. bool identity(const Transform& t) { return t.position == vec3{0.0f} && t.orientation == quat{} && t.scale == vec3{1.0f}; } // TODO: mat4 transformMatrix4(const Transform& t) { return Math::translate(t.position) * quaternionToMatrix4(t.orientation) * Math::scale(t.scale); } }