Skip to content

Commit

Permalink
[editor] fixed gimbal lock when rotating an entity using the transfor…
Browse files Browse the repository at this point in the history
…m property boxes
  • Loading branch information
PanosK92 committed Jan 1, 2025
1 parent 2f3393e commit 7fd4ce5
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 19 deletions.
31 changes: 21 additions & 10 deletions editor/Widgets/Properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,28 +204,39 @@ void Properties::Inspect(const shared_ptr<Material> material)
m_inspected_material = material;
}

void Properties::ShowTransform(shared_ptr<Entity> entity) const
void Properties::ShowTransform(shared_ptr<Entity> entity) const
{
if (component_begin("Transform", IconType::Component_Transform, nullptr, true, false))
{
//= REFLECT ==================================================
Vector3 position = entity->GetPositionLocal();
Vector3 rotation = entity->GetRotationLocal().ToEulerAngles();
Vector3 scale = entity->GetScaleLocal();
//============================================================
//= REFLECT =====================================
Vector3 position = entity->GetPositionLocal();
Quaternion rotation = entity->GetRotationLocal();
Vector3 scale = entity->GetScaleLocal();
//===============================================

// convert current rotation to Euler angles for display
static Vector3 last_frame_euler = rotation.ToEulerAngles();
Vector3 current_euler = last_frame_euler;

ImGui::AlignTextToFramePadding();
ImGuiSp::vector3("Position (m)", position);
ImGui::SameLine();
ImGuiSp::vector3("Rotation (degrees)", rotation);
ImGuiSp::vector3("Rotation (degrees)", current_euler);
ImGui::SameLine();
ImGuiSp::vector3("Scale", scale);

//= MAP ========================================================
// calculate the the rotation delta, convert it to a quaternion, and apply it, avoiding gimbal lock
Vector3 delta_euler = current_euler - last_frame_euler;
last_frame_euler = current_euler;
Quaternion delta_quaternion = Quaternion::FromEulerAngles(delta_euler);
rotation = delta_quaternion * rotation;
rotation.Normalize();

//= MAP ===========================
entity->SetPositionLocal(position);
entity->SetScaleLocal(scale);
entity->SetRotationLocal(Quaternion::FromEulerAngles(rotation));
//==============================================================
entity->SetRotationLocal(rotation);
//=================================
}
component_end();
}
Expand Down
17 changes: 8 additions & 9 deletions runtime/Math/Quaternion.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ namespace Spartan::Math
);
}

static inline Quaternion FromToRotation(const Vector3& start, const Vector3& end)
static Quaternion FromToRotation(const Vector3& start, const Vector3& end)
{
const Vector3 normStart = start.Normalized();
const Vector3 normEnd = end.Normalized();
Expand Down Expand Up @@ -144,7 +144,7 @@ namespace Spartan::Math
}
}

static inline Quaternion FromLookRotation(const Vector3& direction, const Vector3& up_direction = Vector3::Up)
static Quaternion FromLookRotation(const Vector3& direction, const Vector3& up_direction = Vector3::Up)
{
Quaternion result;
const Vector3 forward = direction.Normalized();
Expand All @@ -165,9 +165,9 @@ namespace Spartan::Math
return result;
}

static inline Quaternion FromToRotation(const Quaternion& start, const Quaternion& end) { return start.Inverse() * end; }
static Quaternion FromToRotation(const Quaternion& start, const Quaternion& end) { return start.Inverse() * end; }

static inline Quaternion Lerp(const Quaternion& a, const Quaternion& b, const float t)
static Quaternion Lerp(const Quaternion& a, const Quaternion& b, const float t)
{
Quaternion quaternion;

Expand All @@ -183,7 +183,7 @@ namespace Spartan::Math
return quaternion.Normalized();
}

static inline Quaternion Multiply(const Quaternion& Qa, const Quaternion& Qb)
static Quaternion Multiply(const Quaternion& Qa, const Quaternion& Qb)
{
const float x = Qa.x;
const float y = Qa.y;
Expand Down Expand Up @@ -254,7 +254,6 @@ namespace Spartan::Math
}
}

// Returns Euler angles in degrees
Vector3 ToEulerAngles() const
{
// Derivation from http://www.geometrictools.com/Documentation/EulerAngles.pdf
Expand Down Expand Up @@ -289,9 +288,9 @@ namespace Spartan::Math
);
}

// Euler angles to quaternion (input in degrees)
static inline auto FromEulerAngles(const Vector3& rotation) { return FromYawPitchRoll(rotation.y * Helper::DEG_TO_RAD, rotation.x * Helper::DEG_TO_RAD, rotation.z * Helper::DEG_TO_RAD); }
static inline auto FromEulerAngles(float rotationX, float rotationY, float rotationZ) { return FromYawPitchRoll(rotationY * Helper::DEG_TO_RAD, rotationX * Helper::DEG_TO_RAD, rotationZ * Helper::DEG_TO_RAD); }
// euler angles to quaternion (input in degrees)
static Quaternion FromEulerAngles(const Vector3& rotation) { return FromYawPitchRoll(rotation.y * Helper::DEG_TO_RAD, rotation.x * Helper::DEG_TO_RAD, rotation.z * Helper::DEG_TO_RAD); }
static Quaternion FromEulerAngles(float rotationX, float rotationY, float rotationZ) { return FromYawPitchRoll(rotationY * Helper::DEG_TO_RAD, rotationX * Helper::DEG_TO_RAD, rotationZ * Helper::DEG_TO_RAD); }

// Returns yaw in degrees
float Yaw() const { return ToEulerAngles().y; }
Expand Down

0 comments on commit 7fd4ce5

Please sign in to comment.