Skip to content

Commit

Permalink
fix(types/Quaternion): removed the weird angle flip that was causing …
Browse files Browse the repository at this point in the history
…issues with world transforms
  • Loading branch information
tomezpl committed Oct 16, 2024
1 parent 830b63a commit 9e0382e
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 22 deletions.
22 changes: 14 additions & 8 deletions src/examples/demo/DemoApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,15 @@ class DemoApp : public system::BaseApp
{
float deltaX = (xpos - m_MouseState.lastX) / 300.0;
float deltaY = (ypos - m_MouseState.lastY) / 300.0;
lepus::types::Quaternion rotationYaw = lepus::types::Quaternion(0.f, 1.f, 0.f, -deltaX);
lepus::types::Quaternion rotationYaw = lepus::types::Quaternion(0.f, 1.f, 0.f, deltaX);

auto combined = rotationYaw;
float angle = combined.Angle();
if (abs(angle) > 0.001f)
{
m_Camera.Transform().Rotate(rotationYaw);
}
lepus::types::Quaternion rotationPitch = lepus::types::Quaternion(m_Camera.Transform().Right(), -deltaY);
lepus::types::Quaternion rotationPitch = lepus::types::Quaternion(m_Camera.Transform().Right(), deltaY);
angle = rotationPitch.Angle();
if (abs(angle) > 0.001f)
{
Expand Down Expand Up @@ -155,17 +155,17 @@ class DemoApp : public system::BaseApp

cube.GetTransform()->Origin(lepus::types::Vector3(0.f, 0.f, -2.f));
cube2.GetTransform()->Origin(lepus::types::Vector3(2.f, 0.f, 0.f));
cube3.GetTransform()->Origin(lepus::types::Vector3(-3.f, 0.f, -3.f));
cube4.GetTransform()->Origin(lepus::types::Vector3(0.f, 0.f, 6.f));
cube3.GetTransform()->Origin(lepus::types::Vector3(0.f, 0.f, 2.f));
cube4.GetTransform()->Origin(lepus::types::Vector3(0.f, -2.f, 0.f));

auto rootNode = api.GetSceneGraph().AddChild(&cube);
auto childNode1 = rootNode->AddChild(&cube2);
auto childNode2 = childNode1->AddChild(&cube3);
auto childNode3 = childNode2->AddChild(&cube4);
// auto childNode3 = childNode2->AddChild(&cube4);

cube.GetTransform()->Rotate(lepus::types::Quaternion(0.f, 1.f, 0.f, (float)PI * -0.5f));
cube2.GetTransform()->SetScale(1.f / 1.5f);
cube3.GetTransform()->Rotate(lepus::types::Quaternion(0.f, 1.f, 0.f, (float)PI * (-50.f / 180.f)));
// cube2.GetTransform()->SetScale(1.f / 1.5f);
cube2.GetTransform()->Rotate(lepus::types::Quaternion(1.f, 0.f, 0.f, (float)PI * (-90.f / 180.f)));

auto cubeNode = api.GetSceneGraph().AddChild(&cube);

Expand Down Expand Up @@ -208,7 +208,13 @@ class DemoApp : public system::BaseApp
UpdateInput(keys, windowing);

// Rotate the parent cube
cube.GetTransform()->Rotate(lepus::types::Quaternion(lepus::types::Vector3(0.f, 1.f, 0.f), deltaTime * 0.5f));
if (!keys.e && eKeyPressedLastFrame)
{
cube.GetTransform()->Rotate(lepus::types::Quaternion(lepus::types::Vector3(0.f, 1.f, 0.f), PI * -0.25f));
}
cube.GetTransform()->Rotate(lepus::types::Quaternion(lepus::types::Vector3(0.f, 1.f, 0.f), -deltaTime));
cube2.GetTransform()->Rotate(lepus::types::Quaternion(lepus::types::Vector3(1.f, 0.f, 0.f), -deltaTime));
cube3.GetTransform()->Rotate(lepus::types::Quaternion(lepus::types::Vector3(1.f, 1.f, 1.f), -deltaTime));

// Move the child cube back and forth along the parent's Z-axis
// cube2.GetTransform()->Origin(lepus::types::Vector3(0.f, 0.f, -1.f + ((sinf(runningTime) + 1.f) * 0.5f) * -2.f));
Expand Down
49 changes: 42 additions & 7 deletions src/lepus/gfx/SceneGraph/Transformable.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,23 +76,58 @@ namespace lepus
lepus::types::Vector4 rotated(leaves[i]->GetTransformable()->GetTransform()->Origin() * accScale);
rotated.w(1.f);
accScale.Multiply(parentTransform.Scale());

//
parentTransform.Origin(lepus::types::Vector3());
//
lepus::types::Quaternion normParentRot = parentTransform.Rotation().Normalised();
lepus::types::Vector3 axis = normParentRot.Axis();
float angle = normParentRot.Angle();

accRot = accRot * (parentTransform.Rotation());
parentTransform.Rotation(accRot);
lepus::math::Matrix4x4 mat = parentTransform.BuildMatrix();
rotated = mat.Multiply(rotated);
lepus::types::Vector4 rotatedAxis = mat.Multiply(lepus::types::Vector4(axis));

accPos.x(accPos.x() + rotated.x());
accPos.y(accPos.y() + rotated.y());
accPos.z(accPos.z() + rotated.z());
parentTransform.Rotation(lepus::types::Quaternion(rotatedAxis.x(), rotatedAxis.y(), rotatedAxis.z(), angle));
mat = parentTransform.BuildMatrix();
// rotated = mat.Multiply(rotated);
// rotated = accRot.Rotate(rotated);

accRot = accRot * (parentTransform.Rotation());
parentTransform.Rotation(accRot);
mat = parentTransform.BuildMatrix();
auto fwd = mat.Multiply(lepus::types::Vector4(0, 0, 1, 1)),
rgt = mat.Multiply(lepus::types::Vector4(1, 0, 0, 1)),
up = mat.Multiply(lepus::types::Vector4(0, 1, 0, 1));

auto forward = lepus::types::Vector3(fwd.x(), fwd.y(), fwd.z());
auto right = lepus::types::Vector3(rgt.x(), rgt.y(), rgt.z());
auto newUp = lepus::types::Vector3(up.x(), up.y(), up.z());

// if (i == 1)
// {
// accPos.x(accPos.x() + rotated.x());
// accPos.y(accPos.y() + rotated.y());
// accPos.z(accPos.z() + rotated.z());
// }
// else
{
accPos = accPos + forward * rotated.z() + right * rotated.x() + newUp * rotated.y();
}
}

lepus::math::Transform worldTransform = lepus::math::Transform();

lepus::types::Quaternion normRot = this->m_Transform->Rotation().Normalised();
lepus::types::Vector3 axis = normRot.Axis();
float angle = normRot.Angle();
worldTransform.Rotation(accRot);
lepus::types::Vector4 rotatedAxis = worldTransform.BuildMatrix().Multiply(lepus::types::Vector4(axis));
axis.x(rotatedAxis.x());
axis.y(rotatedAxis.y());
axis.z(rotatedAxis.z());

worldTransform.Origin(accPos);
worldTransform.Rotate(accRot * this->m_Transform->Rotation());
worldTransform.Rotate(lepus::types::Quaternion(axis, angle));
accScale = accScale * this->m_Transform->Scale();
worldTransform.SetScale(accScale.x(), accScale.y(), accScale.z());

Expand Down
4 changes: 1 addition & 3 deletions src/lepus/utility/types/Quaternion.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ namespace lepus
/// @param angle Rotation angle around the axis
Quaternion(float axisX, float axisY, float axisZ, float angle)
{
// Negating the angle here so that the Quaternion represents a clockwise rotation along an axis as observed looking towards the origin/object.
angle *= -1.f;
float const q[] = {axisX * sinf(angle / 2.f), axisY * sinf(angle / 2.f), axisZ * sinf(angle / 2.f), cos(angle / 2.f)};
init((float*)q);
}
Expand Down Expand Up @@ -123,7 +121,7 @@ namespace lepus
inline lepus::types::Vector3 Rotate(const lepus::types::Vector3& v) const
{
Quaternion p = Quaternion();
p.w(0.f);
p.w(1.f);
p.x(v.x());
p.y(v.y());
p.z(v.z());
Expand Down
8 changes: 4 additions & 4 deletions tests/L3D/SceneGraph/SceneGraphTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ TEST(SceneGraphTest, SceneGraphChildIsAddedCorrectly)
/// C's local coords are scaled by (1.0/1.5), and are therefore (-2, 0, -2) away from B in world units, and (0, 0, -2) away fom A in world units.
/// Therefore, C should end up at (2, 0, -2) in world space, effectively taking B's original world-space position.
/// C is also rotated counter-clockwise around the Y axis by 50 degrees. Before applying A's rotation, D ends up at approx. (-3.1, 0, -0.55) away from A in world units.
/// Once A's 90deg rotation is applied then, D should end up at approx (-0.55, 0, -5.06) in world space.
/// Once A's 90deg rotation is applied then, D should end up at approx (-0.57, 0, -5.06) in world space.
///
/// (it may be helpful to draw this on a piece of paper)
TEST(SceneGraphTest, SceneGraphChildTransformsCreateCorrectWorldCoords)
Expand All @@ -60,9 +60,9 @@ TEST(SceneGraphTest, SceneGraphChildTransformsCreateCorrectWorldCoords)
auto childNode2 = childNode1->AddChild(&childTransformable2);
auto childNode3 = childNode2->AddChild(&childTransformable3);

const float nodeCTheta = -50.f;
const float nodeCTheta = 50.f;

rootTransformable.GetTransform()->Rotate(lepus::types::Quaternion(0.f, 1.f, 0.f, (float)PI * -0.5f));
rootTransformable.GetTransform()->Rotate(lepus::types::Quaternion(0.f, 1.f, 0.f, (float)PI * 0.5f));
childTransformable1.GetTransform()->SetScale(1.f / 1.5f);
childTransformable2.GetTransform()->Rotate(lepus::types::Quaternion(0.f, 1.f, 0.f, (float)PI * (nodeCTheta / 180.f)));

Expand Down Expand Up @@ -99,5 +99,5 @@ TEST(SceneGraphTest, SceneGraphChildTransformsCreateCorrectWorldCoords)
float cn3PreRotZ = -4.f + 4.f * cosf((float)PI * (nodeCTheta / 180.f));
ASSERT_NEAR(cn3X, 0.f - (cn3PreRotZ - -2.f), 0.0001f);
ASSERT_NEAR(cn3Y, 0.f, 0.0001f);
ASSERT_NEAR(cn3Z, -2.f + (cn3PreRotX - 0.f), 0.0001f);
ASSERT_NEAR(cn3Z, -2.f - (cn3PreRotX - 0.f), 0.0001f);
}

0 comments on commit 9e0382e

Please sign in to comment.