Skip to content

Commit 9e0382e

Browse files
committed
fix(types/Quaternion): removed the weird angle flip that was causing issues with world transforms
1 parent 830b63a commit 9e0382e

File tree

4 files changed

+61
-22
lines changed

4 files changed

+61
-22
lines changed

src/examples/demo/DemoApp.h

+14-8
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,15 @@ class DemoApp : public system::BaseApp
8989
{
9090
float deltaX = (xpos - m_MouseState.lastX) / 300.0;
9191
float deltaY = (ypos - m_MouseState.lastY) / 300.0;
92-
lepus::types::Quaternion rotationYaw = lepus::types::Quaternion(0.f, 1.f, 0.f, -deltaX);
92+
lepus::types::Quaternion rotationYaw = lepus::types::Quaternion(0.f, 1.f, 0.f, deltaX);
9393

9494
auto combined = rotationYaw;
9595
float angle = combined.Angle();
9696
if (abs(angle) > 0.001f)
9797
{
9898
m_Camera.Transform().Rotate(rotationYaw);
9999
}
100-
lepus::types::Quaternion rotationPitch = lepus::types::Quaternion(m_Camera.Transform().Right(), -deltaY);
100+
lepus::types::Quaternion rotationPitch = lepus::types::Quaternion(m_Camera.Transform().Right(), deltaY);
101101
angle = rotationPitch.Angle();
102102
if (abs(angle) > 0.001f)
103103
{
@@ -155,17 +155,17 @@ class DemoApp : public system::BaseApp
155155

156156
cube.GetTransform()->Origin(lepus::types::Vector3(0.f, 0.f, -2.f));
157157
cube2.GetTransform()->Origin(lepus::types::Vector3(2.f, 0.f, 0.f));
158-
cube3.GetTransform()->Origin(lepus::types::Vector3(-3.f, 0.f, -3.f));
159-
cube4.GetTransform()->Origin(lepus::types::Vector3(0.f, 0.f, 6.f));
158+
cube3.GetTransform()->Origin(lepus::types::Vector3(0.f, 0.f, 2.f));
159+
cube4.GetTransform()->Origin(lepus::types::Vector3(0.f, -2.f, 0.f));
160160

161161
auto rootNode = api.GetSceneGraph().AddChild(&cube);
162162
auto childNode1 = rootNode->AddChild(&cube2);
163163
auto childNode2 = childNode1->AddChild(&cube3);
164-
auto childNode3 = childNode2->AddChild(&cube4);
164+
// auto childNode3 = childNode2->AddChild(&cube4);
165165

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

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

@@ -208,7 +208,13 @@ class DemoApp : public system::BaseApp
208208
UpdateInput(keys, windowing);
209209

210210
// Rotate the parent cube
211-
cube.GetTransform()->Rotate(lepus::types::Quaternion(lepus::types::Vector3(0.f, 1.f, 0.f), deltaTime * 0.5f));
211+
if (!keys.e && eKeyPressedLastFrame)
212+
{
213+
cube.GetTransform()->Rotate(lepus::types::Quaternion(lepus::types::Vector3(0.f, 1.f, 0.f), PI * -0.25f));
214+
}
215+
cube.GetTransform()->Rotate(lepus::types::Quaternion(lepus::types::Vector3(0.f, 1.f, 0.f), -deltaTime));
216+
cube2.GetTransform()->Rotate(lepus::types::Quaternion(lepus::types::Vector3(1.f, 0.f, 0.f), -deltaTime));
217+
cube3.GetTransform()->Rotate(lepus::types::Quaternion(lepus::types::Vector3(1.f, 1.f, 1.f), -deltaTime));
212218

213219
// Move the child cube back and forth along the parent's Z-axis
214220
// cube2.GetTransform()->Origin(lepus::types::Vector3(0.f, 0.f, -1.f + ((sinf(runningTime) + 1.f) * 0.5f) * -2.f));

src/lepus/gfx/SceneGraph/Transformable.h

+42-7
Original file line numberDiff line numberDiff line change
@@ -76,23 +76,58 @@ namespace lepus
7676
lepus::types::Vector4 rotated(leaves[i]->GetTransformable()->GetTransform()->Origin() * accScale);
7777
rotated.w(1.f);
7878
accScale.Multiply(parentTransform.Scale());
79-
79+
//
8080
parentTransform.Origin(lepus::types::Vector3());
81+
//
82+
lepus::types::Quaternion normParentRot = parentTransform.Rotation().Normalised();
83+
lepus::types::Vector3 axis = normParentRot.Axis();
84+
float angle = normParentRot.Angle();
8185

82-
accRot = accRot * (parentTransform.Rotation());
8386
parentTransform.Rotation(accRot);
8487
lepus::math::Matrix4x4 mat = parentTransform.BuildMatrix();
85-
rotated = mat.Multiply(rotated);
88+
lepus::types::Vector4 rotatedAxis = mat.Multiply(lepus::types::Vector4(axis));
8689

87-
accPos.x(accPos.x() + rotated.x());
88-
accPos.y(accPos.y() + rotated.y());
89-
accPos.z(accPos.z() + rotated.z());
90+
parentTransform.Rotation(lepus::types::Quaternion(rotatedAxis.x(), rotatedAxis.y(), rotatedAxis.z(), angle));
91+
mat = parentTransform.BuildMatrix();
92+
// rotated = mat.Multiply(rotated);
93+
// rotated = accRot.Rotate(rotated);
94+
95+
accRot = accRot * (parentTransform.Rotation());
96+
parentTransform.Rotation(accRot);
97+
mat = parentTransform.BuildMatrix();
98+
auto fwd = mat.Multiply(lepus::types::Vector4(0, 0, 1, 1)),
99+
rgt = mat.Multiply(lepus::types::Vector4(1, 0, 0, 1)),
100+
up = mat.Multiply(lepus::types::Vector4(0, 1, 0, 1));
101+
102+
auto forward = lepus::types::Vector3(fwd.x(), fwd.y(), fwd.z());
103+
auto right = lepus::types::Vector3(rgt.x(), rgt.y(), rgt.z());
104+
auto newUp = lepus::types::Vector3(up.x(), up.y(), up.z());
105+
106+
// if (i == 1)
107+
// {
108+
// accPos.x(accPos.x() + rotated.x());
109+
// accPos.y(accPos.y() + rotated.y());
110+
// accPos.z(accPos.z() + rotated.z());
111+
// }
112+
// else
113+
{
114+
accPos = accPos + forward * rotated.z() + right * rotated.x() + newUp * rotated.y();
115+
}
90116
}
91117

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

120+
lepus::types::Quaternion normRot = this->m_Transform->Rotation().Normalised();
121+
lepus::types::Vector3 axis = normRot.Axis();
122+
float angle = normRot.Angle();
123+
worldTransform.Rotation(accRot);
124+
lepus::types::Vector4 rotatedAxis = worldTransform.BuildMatrix().Multiply(lepus::types::Vector4(axis));
125+
axis.x(rotatedAxis.x());
126+
axis.y(rotatedAxis.y());
127+
axis.z(rotatedAxis.z());
128+
94129
worldTransform.Origin(accPos);
95-
worldTransform.Rotate(accRot * this->m_Transform->Rotation());
130+
worldTransform.Rotate(lepus::types::Quaternion(axis, angle));
96131
accScale = accScale * this->m_Transform->Scale();
97132
worldTransform.SetScale(accScale.x(), accScale.y(), accScale.z());
98133

src/lepus/utility/types/Quaternion.h

+1-3
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ namespace lepus
3737
/// @param angle Rotation angle around the axis
3838
Quaternion(float axisX, float axisY, float axisZ, float angle)
3939
{
40-
// Negating the angle here so that the Quaternion represents a clockwise rotation along an axis as observed looking towards the origin/object.
41-
angle *= -1.f;
4240
float const q[] = {axisX * sinf(angle / 2.f), axisY * sinf(angle / 2.f), axisZ * sinf(angle / 2.f), cos(angle / 2.f)};
4341
init((float*)q);
4442
}
@@ -123,7 +121,7 @@ namespace lepus
123121
inline lepus::types::Vector3 Rotate(const lepus::types::Vector3& v) const
124122
{
125123
Quaternion p = Quaternion();
126-
p.w(0.f);
124+
p.w(1.f);
127125
p.x(v.x());
128126
p.y(v.y());
129127
p.z(v.z());

tests/L3D/SceneGraph/SceneGraphTests.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ TEST(SceneGraphTest, SceneGraphChildIsAddedCorrectly)
3939
/// 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.
4040
/// Therefore, C should end up at (2, 0, -2) in world space, effectively taking B's original world-space position.
4141
/// 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.
42-
/// Once A's 90deg rotation is applied then, D should end up at approx (-0.55, 0, -5.06) in world space.
42+
/// Once A's 90deg rotation is applied then, D should end up at approx (-0.57, 0, -5.06) in world space.
4343
///
4444
/// (it may be helpful to draw this on a piece of paper)
4545
TEST(SceneGraphTest, SceneGraphChildTransformsCreateCorrectWorldCoords)
@@ -60,9 +60,9 @@ TEST(SceneGraphTest, SceneGraphChildTransformsCreateCorrectWorldCoords)
6060
auto childNode2 = childNode1->AddChild(&childTransformable2);
6161
auto childNode3 = childNode2->AddChild(&childTransformable3);
6262

63-
const float nodeCTheta = -50.f;
63+
const float nodeCTheta = 50.f;
6464

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

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

0 commit comments

Comments
 (0)