Files
XCEngine/tests/Components/test_transform_component.cpp

304 lines
8.1 KiB
C++
Raw Normal View History

#include <gtest/gtest.h>
#include <XCEngine/Components/TransformComponent.h>
#include <XCEngine/Math/Math.h>
using namespace XCEngine::Components;
using namespace XCEngine::Math;
namespace {
class TransformComponentTest : public ::testing::Test {
protected:
void SetUp() override {
transform = std::make_unique<TransformComponent>();
}
std::unique_ptr<TransformComponent> transform;
};
TEST(TransformComponent_Test, DefaultConstructor_IdentityValues) {
TransformComponent tc;
EXPECT_EQ(tc.GetLocalPosition(), Vector3::Zero());
EXPECT_TRUE(tc.GetLocalRotation().Dot(Quaternion::Identity()) > 0.99f);
EXPECT_EQ(tc.GetLocalScale(), Vector3::One());
}
TEST(TransformComponent_Test, LocalPosition_GetSet) {
TransformComponent tc;
Vector3 pos(1.0f, 2.0f, 3.0f);
tc.SetLocalPosition(pos);
EXPECT_EQ(tc.GetLocalPosition(), pos);
}
TEST(TransformComponent_Test, LocalRotation_GetSet) {
TransformComponent tc;
Quaternion rot = Quaternion::FromAxisAngle(Vector3::Up(), PI * 0.5f);
tc.SetLocalRotation(rot);
EXPECT_TRUE(tc.GetLocalRotation().Dot(rot) > 0.99f);
}
TEST(TransformComponent_Test, LocalScale_GetSet) {
TransformComponent tc;
Vector3 scale(2.0f, 2.0f, 2.0f);
tc.SetLocalScale(scale);
EXPECT_EQ(tc.GetLocalScale(), scale);
}
TEST(TransformComponent_Test, LocalEulerAngles_GetSet) {
TransformComponent tc;
Vector3 eulers(45.0f, 30.0f, 60.0f);
tc.SetLocalEulerAngles(eulers);
Vector3 result = tc.GetLocalEulerAngles();
EXPECT_TRUE(result.Magnitude() > 0.0f);
}
TEST(TransformComponent_Test, WorldPosition_NoParent_EqualsLocal) {
TransformComponent tc;
Vector3 pos(1.0f, 2.0f, 3.0f);
tc.SetLocalPosition(pos);
EXPECT_EQ(tc.GetPosition(), pos);
}
TEST(TransformComponent_Test, WorldPosition_WithParent) {
TransformComponent parent;
TransformComponent child;
parent.SetLocalPosition(Vector3(1.0f, 0.0f, 0.0f));
child.SetParent(&parent);
child.SetLocalPosition(Vector3(2.0f, 0.0f, 0.0f));
Vector3 worldPos = child.GetPosition();
EXPECT_NEAR(worldPos.x, 3.0f, 0.001f);
}
TEST(TransformComponent_Test, WorldRotation_WithParent) {
TransformComponent parent;
TransformComponent child;
parent.SetLocalRotation(Quaternion::FromAxisAngle(Vector3::Up(), PI * 0.5f));
child.SetParent(&parent);
child.SetLocalRotation(Quaternion::FromAxisAngle(Vector3::Up(), PI * 0.5f));
Quaternion worldRot = child.GetRotation();
EXPECT_TRUE(worldRot.Magnitude() > 0.0f);
}
TEST(TransformComponent_Test, WorldScale_WithParent) {
TransformComponent parent;
TransformComponent child;
parent.SetLocalScale(Vector3(2.0f, 2.0f, 2.0f));
child.SetParent(&parent);
child.SetLocalScale(Vector3(2.0f, 2.0f, 2.0f));
Vector3 worldScale = child.GetScale();
EXPECT_NEAR(worldScale.x, 4.0f, 0.001f);
EXPECT_NEAR(worldScale.y, 4.0f, 0.001f);
EXPECT_NEAR(worldScale.z, 4.0f, 0.001f);
}
TEST(TransformComponent_Test, DirectionVectors_Forward) {
TransformComponent tc;
Vector3 forward = tc.GetForward();
EXPECT_NEAR(forward.z, 1.0f, 0.001f);
}
TEST(TransformComponent_Test, DirectionVectors_Right) {
TransformComponent tc;
Vector3 right = tc.GetRight();
EXPECT_NEAR(right.x, 1.0f, 0.001f);
}
TEST(TransformComponent_Test, DirectionVectors_Up) {
TransformComponent tc;
Vector3 up = tc.GetUp();
EXPECT_NEAR(up.y, 1.0f, 0.001f);
}
TEST(TransformComponent_Test, LocalToWorldMatrix_Identity) {
TransformComponent tc;
const Matrix4x4& matrix = tc.GetLocalToWorldMatrix();
EXPECT_EQ(matrix[0][0], 1.0f);
EXPECT_EQ(matrix[1][1], 1.0f);
EXPECT_EQ(matrix[2][2], 1.0f);
EXPECT_EQ(matrix[3][3], 1.0f);
}
TEST(TransformComponent_Test, LocalToWorldMatrix_Translation) {
TransformComponent tc;
Vector3 pos(5.0f, 10.0f, 15.0f);
tc.SetLocalPosition(pos);
const Matrix4x4& matrix = tc.GetLocalToWorldMatrix();
EXPECT_NEAR(matrix[0][3], pos.x, 0.001f);
EXPECT_NEAR(matrix[1][3], pos.y, 0.001f);
EXPECT_NEAR(matrix[2][3], pos.z, 0.001f);
}
TEST(TransformComponent_Test, LocalToWorldMatrix_Rotation) {
TransformComponent tc;
tc.SetLocalRotation(Quaternion::FromAxisAngle(Vector3::Up(), PI * 0.5f));
const Matrix4x4& matrix = tc.GetLocalToWorldMatrix();
EXPECT_NEAR(matrix[0][0], 0.0f, 0.001f);
EXPECT_NEAR(matrix[0][2], 1.0f, 0.001f);
}
TEST(TransformComponent_Test, LookAt_Target) {
TransformComponent tc;
Vector3 target(10.0f, 0.0f, 0.0f);
tc.SetPosition(Vector3::Zero());
tc.LookAt(target);
Vector3 forward = tc.GetForward();
EXPECT_TRUE(forward.Magnitude() > 0.9f);
}
TEST(TransformComponent_Test, Rotate_Eulers) {
TransformComponent tc;
tc.Rotate(Vector3(90.0f, 0.0f, 0.0f));
Vector3 eulers = tc.GetLocalEulerAngles();
EXPECT_TRUE(eulers.Magnitude() > 0.0f);
}
TEST(TransformComponent_Test, Translate_Self) {
TransformComponent tc;
Vector3 initialPos = tc.GetLocalPosition();
tc.Translate(Vector3(1.0f, 2.0f, 3.0f), Space::Self);
Vector3 newPos = tc.GetLocalPosition();
EXPECT_NEAR(newPos.x, initialPos.x + 1.0f, 0.001f);
EXPECT_NEAR(newPos.y, initialPos.y + 2.0f, 0.001f);
EXPECT_NEAR(newPos.z, initialPos.z + 3.0f, 0.001f);
}
TEST(TransformComponent_Test, TransformPoint_LocalToWorld) {
TransformComponent tc;
tc.SetLocalPosition(Vector3(1.0f, 2.0f, 3.0f));
Vector3 localPoint(1.0f, 0.0f, 0.0f);
Vector3 worldPoint = tc.TransformPoint(localPoint);
EXPECT_NEAR(worldPoint.x, 2.0f, 0.001f);
EXPECT_NEAR(worldPoint.y, 2.0f, 0.001f);
EXPECT_NEAR(worldPoint.z, 3.0f, 0.001f);
}
TEST(TransformComponent_Test, InverseTransformPoint_WorldToLocal) {
TransformComponent tc;
tc.SetLocalPosition(Vector3(1.0f, 2.0f, 3.0f));
Vector3 worldPoint(2.0f, 2.0f, 3.0f);
Vector3 localPoint = tc.InverseTransformPoint(worldPoint);
EXPECT_NEAR(localPoint.x, 1.0f, 0.001f);
EXPECT_NEAR(localPoint.y, 0.0f, 0.001f);
EXPECT_NEAR(localPoint.z, 0.0f, 0.001f);
}
TEST(TransformComponent_Test, TransformDirection) {
TransformComponent tc;
tc.SetLocalRotation(Quaternion::FromAxisAngle(Vector3::Up(), PI * 0.5f));
Vector3 localDir(1.0f, 0.0f, 0.0f);
Vector3 worldDir = tc.TransformDirection(localDir);
EXPECT_NEAR(worldDir.z, -1.0f, 0.1f);
}
TEST(TransformComponent_Test, SetDirty_PropagatesToChildren) {
TransformComponent parent;
TransformComponent child;
child.SetParent(&parent);
parent.SetLocalPosition(Vector3(1.0f, 2.0f, 3.0f));
child.SetLocalPosition(Vector3(1.0f, 0.0f, 0.0f));
Vector3 childWorldPosBefore = child.GetPosition();
parent.SetLocalPosition(Vector3(10.0f, 0.0f, 0.0f));
Vector3 childWorldPosAfter = child.GetPosition();
EXPECT_NE(childWorldPosBefore.x, childWorldPosAfter.x);
}
TEST(TransformComponent_Test, GetChildCount_Empty) {
TransformComponent tc;
EXPECT_EQ(tc.GetChildCount(), 0u);
}
TEST(TransformComponent_Test, GetChild_InvalidIndex) {
TransformComponent tc;
EXPECT_EQ(tc.GetChild(0), nullptr);
}
TEST(TransformComponent_Test, DetachChildren) {
TransformComponent parent;
TransformComponent child1;
TransformComponent child2;
child1.SetParent(&parent);
child2.SetParent(&parent);
EXPECT_EQ(parent.GetChildCount(), 2u);
parent.DetachChildren();
EXPECT_EQ(parent.GetChildCount(), 0u);
}
TEST(TransformComponent_Test, SetAsFirstSibling) {
TransformComponent parent;
TransformComponent child1;
TransformComponent child2;
child1.SetParent(&parent);
child2.SetParent(&parent);
child2.SetAsFirstSibling();
EXPECT_EQ(child2.GetSiblingIndex(), 0);
}
TEST(TransformComponent_Test, SetAsLastSibling) {
TransformComponent parent;
TransformComponent child1;
TransformComponent child2;
child1.SetParent(&parent);
child2.SetParent(&parent);
child1.SetAsLastSibling();
EXPECT_EQ(child1.GetSiblingIndex(), 1);
}
} // namespace