SP3-16 Quaternions #112

Merged
direnbharwani merged 17 commits from SP3-16-Math into main 2022-10-23 20:07:17 +08:00
21 changed files with 645 additions and 299 deletions

View File

@ -83,11 +83,13 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::LateUpdateRoutine>(); SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::LateUpdateRoutine>();
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::FrameCleanUpRoutine>(); SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::FrameCleanUpRoutine>();
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostLogicUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>(); SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformUpdateRoutine>(); SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>(); SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>(); SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();

View File

@ -67,9 +67,9 @@ namespace Sandbox
customMat->SetProperty("data.alpha", 0.1f); customMat->SetProperty("data.alpha", 0.1f);
// Create Stress Test Objects // Create Stress Test Objects
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One * 0.5f; static const SHVec3 TEST_OBJ_SCALE = SHVec3::One;
constexpr int NUM_ROWS = 0; constexpr int NUM_ROWS = 3;
constexpr int NUM_COLS = 0; constexpr int NUM_COLS = 1;
static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f }; static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f };
static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f }; static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f };
@ -91,13 +91,13 @@ namespace Sandbox
//Set initial positions //Set initial positions
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f) }); transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f) });
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f}); //transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber()); transform.SetWorldRotation(SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f));
transform.SetWorldScale(TEST_OBJ_SCALE); transform.SetWorldScale(TEST_OBJ_SCALE);
if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN) //if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN)
collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero); collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero);
else //else
collider.AddBoundingSphere(0.5f, SHVec3::Zero); // collider.AddBoundingSphere(0.5f, SHVec3::Zero);
stressTestObjects.emplace_back(entity); stressTestObjects.emplace_back(entity);
} }

View File

@ -5,8 +5,9 @@ typedef uint32_t SHEventIdentifier;
typedef uint32_t SHEventHandle; typedef uint32_t SHEventHandle;
//Add your event identifiers here: //Add your event identifiers here:
constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0}; constexpr SHEventIdentifier SH_EXAMPLE_EVENT { 0 };
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 }; constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT { 1 };
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 }; constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 };
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT{ 3 }; constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 };
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT{ 4 }; constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };

View File

@ -295,32 +295,33 @@ namespace SHADE
) != 0; ) != 0;
} }
SHMatrix::operator XMMATRIX() const noexcept
{
return XMLoadFloat4x4(this);
}
SHMatrix operator*(float lhs, const SHMatrix& rhs) noexcept SHMatrix operator*(float lhs, const SHMatrix& rhs) noexcept
{ {
return rhs * lhs; return rhs * lhs;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Function Member Definitions */ /* Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHMatrix::Transpose() noexcept void SHMatrix::Transpose() noexcept
{ {
const XMMATRIX M = XMLoadFloat4x4(this); XMStoreFloat4x4(this, XMMatrixTranspose(*this));
XMStoreFloat4x4(this, XMMatrixTranspose(M));
} }
void SHMatrix::Invert() noexcept void SHMatrix::Invert() noexcept
{ {
const XMMATRIX M = XMLoadFloat4x4(this); XMStoreFloat4x4(this, XMMatrixInverse(nullptr, *this));
XMStoreFloat4x4(this, XMMatrixInverse(nullptr, M));
} }
float SHMatrix::Determinant() const noexcept float SHMatrix::Determinant() const noexcept
{ {
const XMMATRIX M = XMLoadFloat4x4(this); return XMVectorGetX(XMMatrixDeterminant(*this));
return XMVectorGetX(XMMatrixDeterminant(M));
} }
std::string SHMatrix::ToString() const noexcept std::string SHMatrix::ToString() const noexcept
@ -337,9 +338,8 @@ namespace SHADE
bool SHMatrix::Decompose(SHVec3& translation, SHVec3& rotation, SHVec3& scale) const noexcept bool SHMatrix::Decompose(SHVec3& translation, SHVec3& rotation, SHVec3& scale) const noexcept
{ {
XMVECTOR s, r, t; XMVECTOR s, r, t;
const XMMATRIX M = XMLoadFloat4x4(this);
if (!XMMatrixDecompose(&s, &r, &t, M)) if (!XMMatrixDecompose(&s, &r, &t, *this))
return false; return false;
SHQuaternion orientation; SHQuaternion orientation;
@ -356,9 +356,8 @@ namespace SHADE
bool SHMatrix::Decompose(SHVec3& translation, SHQuaternion& orientation, SHVec3& scale) const noexcept bool SHMatrix::Decompose(SHVec3& translation, SHQuaternion& orientation, SHVec3& scale) const noexcept
{ {
XMVECTOR s, r, t; XMVECTOR s, r, t;
const XMMATRIX M = XMLoadFloat4x4(this);
if (!XMMatrixDecompose(&s, &r, &t, M)) if (!XMMatrixDecompose(&s, &r, &t, *this))
return false; return false;
XMStoreFloat3(&scale, s); XMStoreFloat3(&scale, s);
@ -376,8 +375,7 @@ namespace SHADE
{ {
SHMatrix result; SHMatrix result;
const XMMATRIX M = XMLoadFloat4x4(&matrix); XMStoreFloat4x4(&result, XMMatrixTranspose(matrix));
XMStoreFloat4x4(&result, XMMatrixTranspose(M));
return result; return result;
} }
@ -385,8 +383,7 @@ namespace SHADE
{ {
SHMatrix result; SHMatrix result;
const XMMATRIX M = XMLoadFloat4x4(&matrix); XMStoreFloat4x4(&result, XMMatrixInverse(nullptr, matrix));
XMStoreFloat4x4(&result, XMMatrixInverse(nullptr, M));
return result; return result;
} }
@ -401,8 +398,8 @@ namespace SHADE
SHMatrix SHMatrix::Translate(const SHVec3& pos) noexcept SHMatrix SHMatrix::Translate(const SHVec3& pos) noexcept
{ {
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixTranslation(pos.x, pos.y, pos.z));
XMStoreFloat4x4(&result, XMMatrixTranslation(pos.x, pos.y, pos.z));
return result; return result;
} }
@ -410,25 +407,23 @@ namespace SHADE
{ {
SHMatrix result; SHMatrix result;
const XMVECTOR A = XMLoadFloat3(&axis); XMStoreFloat4x4(&result, XMMatrixRotationAxis(axis, angleInRad));
XMStoreFloat4x4(&result, XMMatrixRotationAxis(A, angleInRad));
return result; return result;
} }
SHMatrix SHMatrix::Rotate(float yaw, float pitch, float roll) noexcept SHMatrix SHMatrix::Rotate(float yaw, float pitch, float roll) noexcept
{ {
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(pitch, yaw, roll));
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(pitch, yaw, roll));
return result; return result;
} }
SHMatrix SHMatrix::Rotate(const SHVec3& eulerAngles) noexcept SHMatrix SHMatrix::Rotate(const SHVec3& eulerAngles) noexcept
{ {
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(eulerAngles.x, eulerAngles.y, eulerAngles.z));
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYawFromVector(eulerAngles));
return result; return result;
} }
@ -436,57 +431,55 @@ namespace SHADE
{ {
SHMatrix result; SHMatrix result;
const XMVECTOR Q = XMLoadFloat4(&q); XMStoreFloat4x4(&result, XMMatrixRotationQuaternion(q));
XMStoreFloat4x4(&result, XMMatrixRotationQuaternion(Q));
return result; return result;
} }
SHMatrix SHMatrix::RotateX(float angleInRad) noexcept SHMatrix SHMatrix::RotateX(float angleInRad) noexcept
{ {
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixRotationX(angleInRad));
XMStoreFloat4x4(&result, XMMatrixRotationX(angleInRad));
return result; return result;
} }
SHMatrix SHMatrix::RotateY(float angleInRad) noexcept SHMatrix SHMatrix::RotateY(float angleInRad) noexcept
{ {
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixRotationY(angleInRad));
XMStoreFloat4x4(&result, XMMatrixRotationY(angleInRad));
return result; return result;
} }
SHMatrix SHMatrix::RotateZ(float angleInRad) noexcept SHMatrix SHMatrix::RotateZ(float angleInRad) noexcept
{ {
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixRotationZ(angleInRad));
XMStoreFloat4x4(&result, XMMatrixRotationZ(angleInRad));
return result; return result;
} }
SHMatrix SHMatrix::Scale(float uniformScaleFactor) noexcept SHMatrix SHMatrix::Scale(float uniformScaleFactor) noexcept
{ {
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixScaling(uniformScaleFactor, uniformScaleFactor, uniformScaleFactor));
XMStoreFloat4x4(&result, XMMatrixScaling(uniformScaleFactor, uniformScaleFactor, uniformScaleFactor));
return result; return result;
} }
SHMatrix SHMatrix::Scale(float x, float y, float z) noexcept SHMatrix SHMatrix::Scale(float x, float y, float z) noexcept
{ {
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixScaling(x, y, z));
XMStoreFloat4x4(&result, XMMatrixScaling(x, y, z));
return result; return result;
} }
SHMatrix SHMatrix::Scale(const SHVec3& scale) noexcept SHMatrix SHMatrix::Scale(const SHVec3& scale) noexcept
{ {
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixScaling(scale.x, scale.y, scale.z));
XMStoreFloat4x4(&result, XMMatrixScalingFromVector(scale));
return result; return result;
} }
@ -494,12 +487,7 @@ namespace SHADE
{ {
SHMatrix result; SHMatrix result;
const XMVECTOR EYE = XMLoadFloat3(&eye); XMStoreFloat4x4(&result, XMMatrixLookAtRH(eye, target, up));
const XMVECTOR TGT = XMLoadFloat3(&target);
const XMVECTOR UP = XMLoadFloat3(&up);
XMStoreFloat4x4(&result, XMMatrixLookAtRH(EYE, TGT, UP));
return result; return result;
} }
@ -507,12 +495,7 @@ namespace SHADE
{ {
SHMatrix result; SHMatrix result;
const XMVECTOR EYE = XMLoadFloat3(&eye); XMStoreFloat4x4(&result, XMMatrixLookAtLH(eye, target, up));
const XMVECTOR TGT = XMLoadFloat3(&target);
const XMVECTOR UP = XMLoadFloat3(&up);
XMStoreFloat4x4(&result, XMMatrixLookAtLH(EYE, TGT, UP));
return result; return result;
} }
@ -522,8 +505,8 @@ namespace SHADE
const SHVec3 FWD_HAT = SHVec3::Normalise(-forward); const SHVec3 FWD_HAT = SHVec3::Normalise(-forward);
const XMVECTOR Z_HAT = XMVector3Normalize(XMLoadFloat3(&FWD_HAT)); const XMVECTOR Z_HAT = XMVector3Normalize(FWD_HAT);
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(XMLoadFloat3(&up), Z_HAT)); const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(up, Z_HAT));
const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT); const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT);
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT); XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT);
@ -543,8 +526,8 @@ namespace SHADE
const SHVec3 FWD_HAT = SHVec3::Normalise(forward); const SHVec3 FWD_HAT = SHVec3::Normalise(forward);
const XMVECTOR Z_HAT = XMVector3Normalize(XMLoadFloat3(&FWD_HAT)); const XMVECTOR Z_HAT = XMVector3Normalize(FWD_HAT);
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(XMLoadFloat3(&up), Z_HAT)); const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(up, Z_HAT));
const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT); const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT);
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT); XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT);
@ -563,7 +546,6 @@ namespace SHADE
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixPerspectiveFovRH(fov, aspectRatio, nearPlane, farPlane)); XMStoreFloat4x4(&result, XMMatrixPerspectiveFovRH(fov, aspectRatio, nearPlane, farPlane));
return result; return result;
} }
@ -572,7 +554,6 @@ namespace SHADE
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixPerspectiveFovLH(fov, aspectRatio, nearPlane, farPlane)); XMStoreFloat4x4(&result, XMMatrixPerspectiveFovLH(fov, aspectRatio, nearPlane, farPlane));
return result; return result;
} }
@ -581,7 +562,6 @@ namespace SHADE
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixPerspectiveRH(width, height, nearPlane, farPlane)); XMStoreFloat4x4(&result, XMMatrixPerspectiveRH(width, height, nearPlane, farPlane));
return result; return result;
} }
@ -590,7 +570,6 @@ namespace SHADE
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixPerspectiveLH(width, height, nearPlane, farPlane)); XMStoreFloat4x4(&result, XMMatrixPerspectiveLH(width, height, nearPlane, farPlane));
return result; return result;
} }
@ -599,7 +578,6 @@ namespace SHADE
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixOrthographicRH(width, height, nearPlane, farPlane)); XMStoreFloat4x4(&result, XMMatrixOrthographicRH(width, height, nearPlane, farPlane));
return result; return result;
} }
@ -608,7 +586,6 @@ namespace SHADE
SHMatrix result; SHMatrix result;
XMStoreFloat4x4(&result, XMMatrixOrthographicLH(width, height, nearPlane, farPlane)); XMStoreFloat4x4(&result, XMMatrixOrthographicLH(width, height, nearPlane, farPlane));
return result; return result;
} }

View File

@ -77,6 +77,8 @@ namespace SHADE
SHMatrix& operator= (const SHMatrix& rhs) = default; SHMatrix& operator= (const SHMatrix& rhs) = default;
SHMatrix& operator= (SHMatrix&& rhs) = default; SHMatrix& operator= (SHMatrix&& rhs) = default;
operator DirectX::XMMATRIX () const noexcept;
SHMatrix& operator+= (const SHMatrix& rhs) noexcept; SHMatrix& operator+= (const SHMatrix& rhs) noexcept;
SHMatrix& operator-= (const SHMatrix& rhs) noexcept; SHMatrix& operator-= (const SHMatrix& rhs) noexcept;
SHMatrix& operator*= (const SHMatrix& rhs) noexcept; SHMatrix& operator*= (const SHMatrix& rhs) noexcept;

View File

@ -36,44 +36,18 @@ namespace SHADE
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
{} {}
SHQuaternion::SHQuaternion(const SHVec4& vec4) noexcept
: XMFLOAT4( vec4.x, vec4.y, vec4.z, vec4.w )
{}
SHQuaternion::SHQuaternion(float _x, float _y, float _z, float _w) noexcept SHQuaternion::SHQuaternion(float _x, float _y, float _z, float _w) noexcept
: XMFLOAT4( _x, _y, _z, _w ) : XMFLOAT4( _x, _y, _z, _w )
{} {}
SHQuaternion::SHQuaternion(float yaw, float pitch, float roll) noexcept
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
{
XMStoreFloat4(this, XMQuaternionRotationRollPitchYaw(pitch, yaw, roll));
}
SHQuaternion::SHQuaternion(const SHVec3& eulerAngles) noexcept
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
{
const XMVECTOR V = XMLoadFloat3(&eulerAngles);
XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V));
}
SHQuaternion::SHQuaternion(const SHVec3& axis, float angleInRad) noexcept
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
{
const XMVECTOR AXIS = XMLoadFloat3(&axis);
XMStoreFloat4(this, XMQuaternionRotationAxis(AXIS, angleInRad));
}
SHQuaternion::SHQuaternion(const SHMatrix& rotationMatrix) noexcept
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
{
const XMMATRIX M = XMLoadFloat4x4(&rotationMatrix);
XMStoreFloat4(this, XMQuaternionRotationMatrix(M));
}
SHQuaternion::SHQuaternion(const reactphysics3d::Vector3& rp3dEuler) noexcept SHQuaternion::SHQuaternion(const reactphysics3d::Vector3& rp3dEuler) noexcept
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
{ {
const SHVec3& SHADE_VEC{ rp3dEuler }; XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(SHVec3 { rp3dEuler }));
const XMVECTOR V = XMLoadFloat3(&SHADE_VEC);
XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V));
} }
SHQuaternion::SHQuaternion(const reactphysics3d::Quaternion& rp3dQuat) noexcept SHQuaternion::SHQuaternion(const reactphysics3d::Quaternion& rp3dQuat) noexcept
@ -113,10 +87,7 @@ namespace SHADE
{ {
SHQuaternion result; SHQuaternion result;
const XMVECTOR Q1 = XMLoadFloat4(this); XMStoreFloat4(&result, XMVectorAdd(*this, rhs));
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
XMStoreFloat4(&result, XMVectorAdd(Q1, Q2));
return result; return result;
} }
@ -124,10 +95,7 @@ namespace SHADE
{ {
SHQuaternion result; SHQuaternion result;
const XMVECTOR Q1 = XMLoadFloat4(this); XMStoreFloat4(&result, XMVectorSubtract(*this, rhs));
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
XMStoreFloat4(&result, XMVectorSubtract(Q1, Q2));
return result; return result;
} }
@ -135,9 +103,7 @@ namespace SHADE
{ {
SHQuaternion result; SHQuaternion result;
const XMVECTOR Q = XMLoadFloat4(this); XMStoreFloat4(&result, XMVectorNegate(*this));
XMStoreFloat4(&result, XMVectorNegate(Q));
return result; return result;
} }
@ -145,10 +111,7 @@ namespace SHADE
{ {
SHQuaternion result; SHQuaternion result;
const XMVECTOR Q1 = XMLoadFloat4(this); XMStoreFloat4(&result, XMQuaternionMultiply(*this, rhs));
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
XMStoreFloat4(&result, XMQuaternionMultiply(Q1, Q2));
return result; return result;
} }
@ -156,9 +119,7 @@ namespace SHADE
{ {
SHQuaternion result; SHQuaternion result;
const XMVECTOR Q = XMLoadFloat4(this); XMStoreFloat4(&result, XMVectorScale(*this, rhs));
XMStoreFloat4(&result, XMVectorScale(Q, rhs));
return result; return result;
} }
@ -166,27 +127,18 @@ namespace SHADE
{ {
SHQuaternion result; SHQuaternion result;
const XMVECTOR Q1 = XMLoadFloat4(this); XMStoreFloat4(&result, XMQuaternionMultiply(*this, XMQuaternionInverse(rhs)));
const XMVECTOR Q2 = XMQuaternionInverse(XMLoadFloat4(&rhs));
XMStoreFloat4(&result, XMQuaternionMultiply(Q1, Q2));
return result; return result;
} }
bool SHQuaternion::operator==(const SHQuaternion& rhs) const noexcept bool SHQuaternion::operator==(const SHQuaternion& rhs) const noexcept
{ {
const XMVECTOR Q1 = XMLoadFloat4(this); return XMQuaternionEqual(*this, rhs);
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
return XMQuaternionEqual(Q1, Q2);
} }
bool SHQuaternion::operator!=(const SHQuaternion& rhs) const noexcept bool SHQuaternion::operator!=(const SHQuaternion& rhs) const noexcept
{ {
const XMVECTOR Q1 = XMLoadFloat4(this); return XMQuaternionNotEqual(*this, rhs);
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
return XMQuaternionNotEqual(Q1, Q2);
} }
SHQuaternion::operator reactphysics3d::Quaternion() const noexcept SHQuaternion::operator reactphysics3d::Quaternion() const noexcept
@ -199,6 +151,11 @@ namespace SHADE
return reactphysics3d::Vector3{ ToEuler() }; return reactphysics3d::Vector3{ ToEuler() };
} }
SHQuaternion::operator XMVECTOR() const noexcept
{
return XMLoadFloat4(this);
}
SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept
{ {
return rhs * lhs; return rhs * lhs;
@ -213,8 +170,7 @@ namespace SHADE
XMVECTOR axis; XMVECTOR axis;
float angle; float angle;
const XMVECTOR Q = XMLoadFloat4(this); XMQuaternionToAxisAngle(&axis, &angle, *this);
XMQuaternionToAxisAngle(&axis, &angle, Q);
return angle; return angle;
} }
@ -223,8 +179,7 @@ namespace SHADE
XMVECTOR axis; XMVECTOR axis;
float angle; float angle;
const XMVECTOR Q = XMLoadFloat4(this); XMQuaternionToAxisAngle(&axis, &angle, *this);
XMQuaternionToAxisAngle(&axis, &angle, Q);
return SHVec4{XMVectorGetX(axis), XMVectorGetY(axis), XMVectorGetZ(axis), angle}; return SHVec4{XMVectorGetX(axis), XMVectorGetY(axis), XMVectorGetZ(axis), angle};
@ -238,64 +193,49 @@ namespace SHADE
void SHQuaternion::Invert() noexcept void SHQuaternion::Invert() noexcept
{ {
const XMVECTOR Q = XMLoadFloat4(this); XMStoreFloat4(this, XMQuaternionInverse(*this));
XMStoreFloat4(this, XMQuaternionInverse(Q));
} }
float SHQuaternion::Length() const noexcept float SHQuaternion::Length() const noexcept
{ {
const XMVECTOR Q = XMLoadFloat4(this); return XMVectorGetX(XMQuaternionLength(*this));
return XMVectorGetX(XMQuaternionLength(Q));
} }
float SHQuaternion::LengthSquared() const noexcept float SHQuaternion::LengthSquared() const noexcept
{ {
const XMVECTOR Q = XMLoadFloat4(this); return XMVectorGetX(XMQuaternionLengthSq(*this));
return XMVectorGetX(XMQuaternionLengthSq(Q));
} }
float SHQuaternion::Dot(const SHQuaternion& rhs) const noexcept float SHQuaternion::Dot(const SHQuaternion& rhs) const noexcept
{ {
const XMVECTOR Q1 = XMLoadFloat4(this); return XMVectorGetX(XMQuaternionDot(*this, rhs));
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
return XMVectorGetX(XMQuaternionDot(Q1, Q2));
}
SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion&, float) const noexcept
{
SHQuaternion result;
// TODO (Diren)
return result;
} }
SHVec3 SHQuaternion::ToEuler() const noexcept SHVec3 SHQuaternion::ToEuler() const noexcept
{ {
const float xx = x * x; const float XX = x * x;
const float yy = y * y; const float YY = y * y;
const float zz = z * z; const float ZZ = z * z;
const float m31 = 2.f * x * z + 2.f * y * w; const float M_31 = 2.f * x * z + 2.f * y * w;
const float m32 = 2.f * y * z - 2.f * x * w; const float M_32 = 2.f * y * z - 2.f * x * w;
const float m33 = 1.f - 2.f * xx - 2.f * yy; const float M_33 = 1.f - 2.f * XX - 2.f * YY;
const float cy = sqrtf(m33 * m33 + m31 * m31); const float CY = sqrtf(M_33 * M_33 + M_31 * M_31);
const float cx = atan2f(-m32, cy); const float CX = atan2f(-M_32, CY);
if (cy > 16.0f * SHMath::EPSILON) if (CY > 16.0f * SHMath::EPSILON)
{ {
const float m12 = 2.f * x * y + 2.f * z * w; const float M_12 = 2.f * x * y + 2.f * z * w;
const float m22 = 1.f - 2.f * xx - 2.f * zz; const float M_22 = 1.f - 2.f * XX - 2.f * ZZ;
return SHVec3(cx, atan2f(m31, m33), atan2f(m12, m22)); return SHVec3(CX, atan2f(M_31, M_33), atan2f(M_12, M_22));
} }
else else
{ {
const float m11 = 1.f - 2.f * yy - 2.f * zz; const float m11 = 1.f - 2.f * YY - 2.f * ZZ;
const float m21 = 2.f * x * y - 2.f * z * w; const float m21 = 2.f * x * y - 2.f * z * w;
return SHVec3(cx, 0.f, atan2f(-m21, m11)); return SHVec3(CX, 0.f, atan2f(-m21, m11));
} }
} }
@ -311,13 +251,43 @@ namespace SHADE
/* Static Function Member Definitions */ /* Static Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHQuaternion SHQuaternion::FromEuler(const SHVec3& eulerAngles) noexcept
{
SHQuaternion result;
XMStoreFloat4(&result, XMQuaternionRotationRollPitchYawFromVector(eulerAngles));
return result;
}
SHQuaternion SHQuaternion::FromPitchYawRoll(float pitch, float yaw, float roll) noexcept
{
SHQuaternion result;
XMStoreFloat4(&result, XMQuaternionRotationRollPitchYaw(pitch, yaw, roll));
return result;
}
SHQuaternion SHQuaternion::FromAxisAngle(const SHVec3& axis, float angle) noexcept
{
SHQuaternion result;
XMStoreFloat4(&result, XMQuaternionRotationAxis(axis, angle));
return result;
}
SHQuaternion SHQuaternion::FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept
{
SHQuaternion result;
XMStoreFloat4(&result, XMQuaternionRotationMatrix(rotationMatrix));
return result;
}
SHQuaternion SHQuaternion::Normalise(const SHQuaternion& q) noexcept SHQuaternion SHQuaternion::Normalise(const SHQuaternion& q) noexcept
{ {
SHQuaternion result; SHQuaternion result;
const XMVECTOR Q = XMLoadFloat4(&q); XMStoreFloat4(&result, XMQuaternionNormalize(q));
XMStoreFloat4(&result, XMQuaternionNormalize(Q));
return result; return result;
} }
@ -325,9 +295,7 @@ namespace SHADE
{ {
SHQuaternion result; SHQuaternion result;
const XMVECTOR Q = XMLoadFloat4(&q); XMStoreFloat4(&result, XMQuaternionConjugate(q));
XMStoreFloat4(&result, XMQuaternionConjugate(Q));
return result; return result;
} }
@ -335,26 +303,37 @@ namespace SHADE
{ {
SHQuaternion result; SHQuaternion result;
const XMVECTOR Q = XMLoadFloat4(&q); XMStoreFloat4(&result, XMQuaternionInverse(q));
XMStoreFloat4(&result, XMQuaternionInverse(Q));
return result; return result;
} }
float SHQuaternion::Angle(const SHQuaternion&, const SHQuaternion&) noexcept float SHQuaternion::Angle(const SHQuaternion& q1, const SHQuaternion& q2) noexcept
{ {
// TODO (Diren) XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(q1), q2);
return 0.0f; const float RS = XMVectorGetW(R);
R = XMVector3Length(R);
return 2.0f * atan2f(XMVectorGetX(R), RS);
} }
SHQuaternion SHQuaternion::Lerp(const SHQuaternion&, const SHQuaternion&, float) noexcept SHQuaternion SHQuaternion::Lerp(const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept
{ {
SHQuaternion result; SHQuaternion result;
// TODO (Diren) XMVECTOR R = XMVectorZero();
if (XMVector4GreaterOrEqual(XMVector4Dot(q1, q2), R))
{
R = XMVectorLerp(q1, q2, t);
}
else
{
const XMVECTOR X0 = XMVectorMultiply(q1, XMVectorReplicate(1.f - t));
const XMVECTOR X1 = XMVectorMultiply(q2, XMVectorReplicate(t));
R = XMVectorSubtract(X0, X1);
}
XMStoreFloat4(&result, XMQuaternionNormalize(R));
return result; return result;
} }
@ -362,19 +341,105 @@ namespace SHADE
{ {
SHQuaternion result; SHQuaternion result;
const XMVECTOR Q1 = XMLoadFloat4(&q1); XMStoreFloat4(&result, XMQuaternionSlerp(q1, q2, t));
const XMVECTOR Q2 = XMLoadFloat4(&q2);
XMStoreFloat4(&result, XMQuaternionSlerp(Q1, Q2, t));
return result; return result;
} }
SHQuaternion SHQuaternion::Rotate(const SHVec3& , const SHVec3&) noexcept SHQuaternion SHQuaternion::ClampedLerp(const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin, float tMax) noexcept
{
return Lerp(q1, q2, std::clamp(t, tMin, tMax));
}
SHQuaternion SHQuaternion::ClampedSlerp(const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin, float tMax) noexcept
{
return Slerp(q1, q2, std::clamp(t, tMin, tMax));
}
SHQuaternion SHQuaternion::FromToRotation(const SHVec3& from, const SHVec3& to) noexcept
{
// Melax, "The Shortest Arc Quaternion", Game Programming Gems
SHQuaternion result;
const XMVECTOR F = XMVector3Normalize(from);
const XMVECTOR T = XMVector3Normalize(to);
const float dot = XMVectorGetX(XMVector3Dot(F, T));
if (dot >= 1.f)
{
result = Identity;
}
else if (dot <= -1.f)
{
XMVECTOR axis = XMVector3Cross(F, SHVec3::Right);
if (XMVector3NearEqual(XMVector3LengthSq(axis), g_XMZero, g_XMEpsilon))
{
axis = XMVector3Cross(F, SHVec3::Up);
}
const XMVECTOR Q = XMQuaternionRotationAxis(axis, XM_PI);
XMStoreFloat4(&result, Q);
}
else
{
const XMVECTOR C = XMVector3Cross(F, T);
XMStoreFloat4(&result, C);
const float s = sqrtf((1.f + dot) * 2.f);
result.x /= s;
result.y /= s;
result.z /= s;
result.w = s * 0.5f;
}
return result;
}
SHQuaternion SHQuaternion::LookRotation(const SHVec3& forward, const SHVec3& up) noexcept
{ {
SHQuaternion result; SHQuaternion result;
// TODO (Diren) const SHQuaternion Q1 = FromToRotation(SHVec3::Forward, forward);
const XMVECTOR C = XMVector3Cross(forward, up);
if (XMVector3NearEqual(XMVector3LengthSq(C), g_XMZero, g_XMEpsilon))
{
// forward and up are co-linear
return Q1;
}
SHVec3 qU;
XMStoreFloat3(&qU, XMQuaternionMultiply(Q1, SHVec3::Up));
const SHQuaternion Q2 = FromToRotation(qU, up);
XMStoreFloat4(&result, XMQuaternionMultiply(Q2, Q1));
return result;
}
SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion& from, const SHQuaternion& to, float maxAngleInRad) noexcept
{
SHQuaternion result;
// We can use the conjugate here instead of inverse assuming q1 & q2 are normalized.
const XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(from), to);
const float RS = XMVectorGetW(R);
const XMVECTOR L = XMVector3Length(R);
const float angle = 2.f * atan2f(XMVectorGetX(L), RS);
if (angle > maxAngleInRad)
{
const XMVECTOR delta = XMQuaternionRotationAxis(R, maxAngleInRad);
const XMVECTOR Q = XMQuaternionMultiply(delta, from);
XMStoreFloat4(&result, Q);
}
else
{
// Don't overshoot.
result = to;
}
return result; return result;
} }

View File

@ -49,11 +49,8 @@ namespace SHADE
SHQuaternion (SHQuaternion&& rhs) = default; SHQuaternion (SHQuaternion&& rhs) = default;
SHQuaternion () noexcept; SHQuaternion () noexcept;
SHQuaternion (const SHVec4& vec4) noexcept;
SHQuaternion (float x, float y, float z, float w) noexcept; SHQuaternion (float x, float y, float z, float w) noexcept;
SHQuaternion (float yaw, float pitch, float roll) noexcept;
SHQuaternion (const SHVec3& eulerAngles) noexcept;
SHQuaternion (const SHVec3& axis, float angleInRad) noexcept;
SHQuaternion (const SHMatrix& rotationMatrix) noexcept;
// Conversion from other math types // Conversion from other math types
@ -87,6 +84,7 @@ namespace SHADE
operator reactphysics3d::Quaternion () const noexcept; operator reactphysics3d::Quaternion () const noexcept;
operator reactphysics3d::Vector3 () const noexcept; operator reactphysics3d::Vector3 () const noexcept;
operator DirectX::XMVECTOR () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
@ -99,29 +97,37 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void Invert () noexcept; void Invert () noexcept;
[[nodiscard]] float Length () const noexcept; [[nodiscard]] float Length () const noexcept;
[[nodiscard]] float LengthSquared () const noexcept; [[nodiscard]] float LengthSquared () const noexcept;
[[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept; [[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept;
[[nodiscard]] SHQuaternion RotateTowards (const SHQuaternion& target, float maxAngleInRad) const noexcept;
[[nodiscard]] SHVec3 ToEuler () const noexcept; [[nodiscard]] SHVec3 ToEuler () const noexcept;
[[nodiscard]] std::string ToString () const noexcept; [[nodiscard]] std::string ToString () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Static Function Members */ /* Static Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) noexcept; [[nodiscard]] static SHQuaternion FromEuler (const SHVec3& eulerAngles) noexcept;
[[nodiscard]] static SHQuaternion Conjugate (const SHQuaternion& q) noexcept; [[nodiscard]] static SHQuaternion FromPitchYawRoll (float pitch, float yaw, float roll) noexcept;
[[nodiscard]] static SHQuaternion Inverse (const SHQuaternion& q) noexcept; [[nodiscard]] static SHQuaternion FromAxisAngle (const SHVec3& axis, float angle) noexcept;
[[nodiscard]] static float Angle (const SHQuaternion& q1, const SHQuaternion& q2) noexcept; [[nodiscard]] static SHQuaternion FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept;
[[nodiscard]] static SHQuaternion Lerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept; [[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) noexcept;
[[nodiscard]] static SHQuaternion Slerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept; [[nodiscard]] static SHQuaternion Conjugate (const SHQuaternion& q) noexcept;
[[nodiscard]] static SHQuaternion Inverse (const SHQuaternion& q) noexcept;
[[nodiscard]] static float Angle (const SHQuaternion& q1, const SHQuaternion& q2) noexcept;
[[nodiscard]] static SHQuaternion Rotate (const SHVec3& from, const SHVec3& to) noexcept; [[nodiscard]] static SHQuaternion Lerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept;
[[nodiscard]] static SHQuaternion Slerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept;
[[nodiscard]] static SHQuaternion ClampedLerp (const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept;
[[nodiscard]] static SHQuaternion ClampedSlerp (const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept;
[[nodiscard]] static SHQuaternion FromToRotation (const SHVec3& from, const SHVec3& to) noexcept;
[[nodiscard]] static SHQuaternion LookRotation (const SHVec3& forward, const SHVec3& up) noexcept;
[[nodiscard]] static SHQuaternion RotateTowards (const SHQuaternion& from, const SHQuaternion& to, float maxAngleInRad) noexcept;
}; };
SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept; SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept;

View File

@ -26,15 +26,15 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHTransform::SHTransform() noexcept SHTransform::SHTransform() noexcept
: position { SHVec3::Zero } : position { SHVec3::Zero }
, rotation { SHVec3::Zero } , orientation { SHQuaternion::Identity }
, scale { SHVec3::One } , scale { SHVec3::One }
{} {}
SHTransform::SHTransform(const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept SHTransform::SHTransform(const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept
: position { pos } : position { pos }
, rotation { rot } , orientation { SHQuaternion::FromEuler(rot) }
, scale { scl } , scale { scl }
{} {}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -43,12 +43,12 @@ namespace SHADE
bool SHTransform::operator==(const SHTransform& rhs) const noexcept bool SHTransform::operator==(const SHTransform& rhs) const noexcept
{ {
return !(position != rhs.position || rotation != rhs.rotation || scale != rhs.scale); return !(position != rhs.position || orientation != rhs.orientation || scale != rhs.scale);
} }
bool SHTransform::operator!=(const SHTransform& rhs) const noexcept bool SHTransform::operator!=(const SHTransform& rhs) const noexcept
{ {
return (position != rhs.position || rotation != rhs.rotation || scale != rhs.scale); return (position != rhs.position || orientation != rhs.orientation || scale != rhs.scale);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -59,7 +59,7 @@ namespace SHADE
{ {
const SHMatrix T = SHMatrix::Translate(position); const SHMatrix T = SHMatrix::Translate(position);
const SHMatrix R = SHMatrix::Rotate(rotation); const SHMatrix R = SHMatrix::Rotate(orientation);
const SHMatrix S = SHMatrix::Scale(scale); const SHMatrix S = SHMatrix::Scale(scale);
trs = S * R * T; trs = S * R * T;

View File

@ -12,8 +12,8 @@
// Project Headers // Project Headers
#include "SH_API.h" #include "SH_API.h"
#include "Math/Vector/SHVec2.h"
#include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec3.h"
#include "Math/SHQuaternion.h"
#include "Math/SHMatrix.h" #include "Math/SHMatrix.h"
namespace SHADE namespace SHADE
@ -31,22 +31,23 @@ namespace SHADE
static const SHTransform Identity; static const SHTransform Identity;
SHVec3 position; SHVec3 position;
SHVec3 rotation; SHQuaternion orientation;
SHVec3 scale; SHVec3 scale;
SHMatrix trs; SHMatrix trs;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */ /* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHTransform (const SHTransform&) = default; SHTransform (const SHTransform&) = default;
SHTransform (SHTransform&&) = default; SHTransform (SHTransform&&) = default;
~SHTransform () = default; ~SHTransform () = default;
SHTransform () noexcept; SHTransform () noexcept;
SHTransform (const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept; SHTransform (const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept;
SHTransform (const SHVec3& pos, const SHQuaternion& quat, const SHVec3& scl) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Operator Overloads */ /* Operator Overloads */
@ -63,7 +64,6 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
const SHMatrix& ComputeTRS(); const SHMatrix& ComputeTRS();
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -12,6 +12,8 @@
// Primary Header // Primary Header
#include "SHTransformComponent.h" #include "SHTransformComponent.h"
// Project Headers
#include "Math/SHMathHelpers.h"
namespace SHADE namespace SHADE
{ {
@ -40,7 +42,12 @@ namespace SHADE
const SHVec3& SHTransformComponent::GetLocalRotation() const noexcept const SHVec3& SHTransformComponent::GetLocalRotation() const noexcept
{ {
return local.rotation; return localRotation;
}
const SHQuaternion& SHTransformComponent::GetLocalOrientation() const noexcept
{
return local.orientation;
} }
const SHVec3& SHTransformComponent::GetLocalScale() const noexcept const SHVec3& SHTransformComponent::GetLocalScale() const noexcept
@ -55,7 +62,12 @@ namespace SHADE
const SHVec3& SHTransformComponent::GetWorldRotation() const noexcept const SHVec3& SHTransformComponent::GetWorldRotation() const noexcept
{ {
return world.rotation; return worldRotation;
}
const SHQuaternion& SHTransformComponent::GetWorldOrientation() const noexcept
{
return world.orientation;
} }
const SHVec3& SHTransformComponent::GetWorldScale() const noexcept const SHVec3& SHTransformComponent::GetWorldScale() const noexcept
@ -91,16 +103,28 @@ namespace SHADE
void SHTransformComponent::SetLocalRotation(const SHVec3& newLocalRotation) noexcept void SHTransformComponent::SetLocalRotation(const SHVec3& newLocalRotation) noexcept
{ {
dirty = true; dirty = true;
local.rotation = newLocalRotation;
localRotation = newLocalRotation;
updateQueue.push({ UpdateCommandType::LOCAL_ROTATION, newLocalRotation });
} }
void SHTransformComponent::SetLocalRotation(float pitch, float yaw, float roll) noexcept void SHTransformComponent::SetLocalRotation(float pitch, float yaw, float roll) noexcept
{ {
dirty = true; dirty = true;
local.rotation.x = pitch; localRotation.x = pitch;
local.rotation.y = yaw; localRotation.y = yaw;
local.rotation.z = roll; localRotation.z = roll;
updateQueue.push({ UpdateCommandType::LOCAL_ROTATION, SHVec3{pitch, yaw, roll} });
}
void SHTransformComponent::SetLocalOrientation(const SHQuaternion& newLocalOrientation) noexcept
{
dirty = true;
local.orientation = newLocalOrientation;
updateQueue.push({ UpdateCommandType::LOCAL_ORIENTATION, newLocalOrientation });
} }
void SHTransformComponent::SetLocalScale(const SHVec3& newLocalScale) noexcept void SHTransformComponent::SetLocalScale(const SHVec3& newLocalScale) noexcept
@ -121,7 +145,7 @@ namespace SHADE
{ {
dirty = true; dirty = true;
world.rotation = newWorldRotation; worldRotation = newWorldRotation;
updateQueue.push({ UpdateCommandType::WORLD_ROTATION, newWorldRotation }); updateQueue.push({ UpdateCommandType::WORLD_ROTATION, newWorldRotation });
} }
@ -129,13 +153,21 @@ namespace SHADE
{ {
dirty = true; dirty = true;
world.rotation.x = pitch; worldRotation.x = pitch;
world.rotation.y = yaw; worldRotation.y = yaw;
world.rotation.z = roll; worldRotation.z = roll;
updateQueue.push({ UpdateCommandType::WORLD_ROTATION, SHVec3{ pitch, yaw, roll} }); updateQueue.push({ UpdateCommandType::WORLD_ROTATION, SHVec3{ pitch, yaw, roll} });
} }
void SHTransformComponent::SetWorldOrientation(const SHQuaternion& newWorldOrientation) noexcept
{
dirty = true;
world.orientation = newWorldOrientation;
updateQueue.push({ UpdateCommandType::WORLD_ORIENTATION, newWorldOrientation });
}
void SHTransformComponent::SetWorldScale(const SHVec3& newWorldScale) noexcept void SHTransformComponent::SetWorldScale(const SHVec3& newWorldScale) noexcept
{ {
dirty = true; dirty = true;
@ -153,6 +185,6 @@ RTTR_REGISTRATION
registration::class_<SHTransformComponent>("Transform Component") registration::class_<SHTransformComponent>("Transform Component")
.property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition ) .property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition )
.property("Rotate" , &SHTransformComponent::GetLocalRotation , select_overload<void(SHVec3 const&)>(&SHTransformComponent::SetLocalRotation) ) .property("Rotate" , &SHTransformComponent::GetLocalRotation , select_overload<void(const SHVec3&)>(&SHTransformComponent::SetLocalRotation) )
.property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale ); .property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale );
} }

View File

@ -56,42 +56,52 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] bool HasChanged () const noexcept; [[nodiscard]] bool HasChanged () const noexcept;
[[nodiscard]] const SHVec3& GetLocalPosition () const noexcept; [[nodiscard]] const SHVec3& GetLocalPosition () const noexcept;
[[nodiscard]] const SHVec3& GetLocalRotation () const noexcept; [[nodiscard]] const SHVec3& GetLocalRotation () const noexcept;
[[nodiscard]] const SHVec3& GetLocalScale () const noexcept; [[nodiscard]] const SHQuaternion& GetLocalOrientation () const noexcept;
[[nodiscard]] const SHVec3& GetWorldPosition () const noexcept; [[nodiscard]] const SHVec3& GetLocalScale () const noexcept;
[[nodiscard]] const SHVec3& GetWorldRotation () const noexcept; [[nodiscard]] const SHVec3& GetWorldPosition () const noexcept;
[[nodiscard]] const SHVec3& GetWorldScale () const noexcept; [[nodiscard]] const SHVec3& GetWorldRotation () const noexcept;
[[nodiscard]] const SHQuaternion& GetWorldOrientation () const noexcept;
[[nodiscard]] const SHVec3& GetWorldScale () const noexcept;
[[nodiscard]] const SHMatrix& GetLocalToWorld () const noexcept; [[nodiscard]] const SHMatrix& GetLocalToWorld () const noexcept;
[[nodiscard]] SHMatrix GetWorldToLocal () const noexcept; [[nodiscard]] SHMatrix GetWorldToLocal () const noexcept;
[[nodiscard]] const SHMatrix& GetTRS () const noexcept; [[nodiscard]] const SHMatrix& GetTRS () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SetLocalPosition (const SHVec3& newLocalPosition) noexcept; void SetLocalPosition (const SHVec3& newLocalPosition) noexcept;
void SetLocalRotation (const SHVec3& newLocalRotation) noexcept; void SetLocalRotation (const SHVec3& newLocalRotation) noexcept;
void SetLocalRotation (float pitch, float yaw, float roll) noexcept; void SetLocalRotation (float pitch, float yaw, float roll) noexcept;
void SetLocalScale (const SHVec3& newLocalScale) noexcept; void SetLocalOrientation (const SHQuaternion& newLocalOrientation) noexcept;
void SetWorldPosition (const SHVec3& newWorldPosition) noexcept; void SetLocalScale (const SHVec3& newLocalScale) noexcept;
void SetWorldRotation (const SHVec3& newWorldRotation) noexcept; void SetWorldPosition (const SHVec3& newWorldPosition) noexcept;
void SetWorldRotation (float pitch, float yaw, float roll) noexcept; void SetWorldRotation (const SHVec3& newWorldRotation) noexcept;
void SetWorldScale (const SHVec3& newWorldScale) noexcept; void SetWorldRotation (float pitch, float yaw, float roll) noexcept;
void SetWorldOrientation (const SHQuaternion& newWorldOrientation) noexcept;
void SetWorldScale (const SHVec3& newWorldScale) noexcept;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
// Differentiate between rotation and orientation for setters
// Setting a quaternion directly is different from using euler angle rotations.
enum class UpdateCommandType enum class UpdateCommandType
{ {
WORLD_POSITION LOCAL_ROTATION
, LOCAL_ORIENTATION
, WORLD_POSITION
, WORLD_ROTATION , WORLD_ROTATION
, WORLD_ORIENTATION
, WORLD_SCALE , WORLD_SCALE
}; };
@ -103,7 +113,7 @@ namespace SHADE
/*-------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------*/
UpdateCommandType type; UpdateCommandType type;
SHVec3 data; SHVec4 data;
}; };
using UpdateQueue = std::queue<UpdateCommand>; using UpdateQueue = std::queue<UpdateCommand>;
@ -114,6 +124,12 @@ namespace SHADE
bool dirty; bool dirty;
// We store euler angle rotations separately to interface with transform quaternions.
// Reading quaternions are unreliable.
SHVec3 localRotation; // Stored in Radians
SHVec3 worldRotation; // Stored in Radians
SHTransform local; // Local TRS holds Local To World Transform SHTransform local; // Local TRS holds Local To World Transform
SHTransform world; SHTransform world;

View File

@ -17,7 +17,8 @@
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
#include "Tools/SHException.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Math/SHMathHelpers.h"
namespace SHADE namespace SHADE
{ {
@ -29,8 +30,12 @@ namespace SHADE
/* Constructors & Destructor Definitions */ /* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHTransformSystem::TransformUpdateRoutine::TransformUpdateRoutine() SHTransformSystem::TransformPostLogicUpdate::TransformPostLogicUpdate()
: SHSystemRoutine { "Transform Update", true } : SHSystemRoutine { "Transform Post-Logic Update", true }
{}
SHTransformSystem::TransformPostPhysicsUpdate::TransformPostPhysicsUpdate()
: SHSystemRoutine { "Transform Post-Physics Update", false }
{} {}
@ -38,16 +43,27 @@ namespace SHADE
/* Public Function Member Definitions */ /* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHTransformSystem::TransformUpdateRoutine::Execute(double) noexcept void SHTransformSystem::TransformPostLogicUpdate::Execute(double) noexcept
{ {
// Get the current scene graph to traverse and update // Get the current scene graph to traverse and update
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
UpdateEntity(SCENE_GRAPH.GetRoot());
// TODO(Diren): Consider how to clear dirty in pause / stop mode and update physics, but do not clear in play mode.
UpdateEntity(SCENE_GRAPH.GetRoot(), false);
}
void SHTransformSystem::TransformPostPhysicsUpdate::Execute(double) noexcept
{
// Get the current scene graph to traverse and update
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
UpdateEntity(SCENE_GRAPH.GetRoot(), true);
} }
void SHTransformSystem::Init() void SHTransformSystem::Init()
{ {
std::shared_ptr thisReceiver { std::make_shared<SHEventReceiverSpec<SHTransformSystem>>(this, &SHTransformSystem::ChangeParent) };
ReceiverPtr receiver = std::dynamic_pointer_cast<SHEventReceiver>(thisReceiver);
SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, receiver);
} }
void SHTransformSystem::Exit() void SHTransformSystem::Exit()
@ -59,7 +75,97 @@ namespace SHADE
/* Private Function Member Definitions */ /* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHTransformSystem::UpdateEntity(const SHSceneNode* node) SHEventHandle SHTransformSystem::ChangeParent(SHEventPtr changeParentEvent)
{
const auto& eventData = reinterpret_cast<const SHEventSpec<SHSceneGraphChangeParentEvent>*>(changeParentEvent.get());
auto* node = eventData->data->node;
auto* tf = SHComponentManager::GetComponent_s<SHTransformComponent>(node->GetEntityID());
// Recompute local transform and store localToWorld Matrix
SHMatrix localToWorld = SHMatrix::Identity;
SHMatrix worldToLocal = SHMatrix::Identity;
auto* newParent = eventData->data->newParent;
const auto* PARENT_TF = SHComponentManager::GetComponent_s<SHTransformComponent>(newParent->GetEntityID());
if (PARENT_TF != nullptr) // Not the root
{
localToWorld = PARENT_TF->GetTRS();
worldToLocal = SHMatrix::Inverse(localToWorld);
}
// Maintain World Transform and recompute Local Transform
// Compute Local Position
tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal);
tf->localRotation = tf->worldRotation;
tf->local.scale = tf->world.scale;
if (PARENT_TF != nullptr)
{
// Compute Local Rotation
tf->localRotation -= PARENT_TF->GetLocalRotation();
// Compute Local Scale
tf->local.scale /= PARENT_TF->GetLocalScale();
}
tf->local.trs = localToWorld;
// Propagate maintaining world transform down the branch
UpdateChildrenLocalTransforms(node);
return eventData->handle;
}
void SHTransformSystem::UpdateChildrenLocalTransforms(SHSceneNode* node)
{
// Structure is similar to update entity, albeit without a queue to do being a forced update
for (const auto* child : node->GetChildren())
{
if (auto* childTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(child->GetEntityID()); childTransform)
{
const bool IS_NODE_ACTIVE = child->IsActive();
if (IS_NODE_ACTIVE && childTransform->isActive)
{
// Recompute local transform and store localToWorld Matrix
SHMatrix localToWorld = SHMatrix::Identity;
SHMatrix worldToLocal = SHMatrix::Identity;
const auto* parent = SHComponentManager::GetComponent_s<SHTransformComponent>(node->GetEntityID());
if (parent != nullptr) // Not the root
{
localToWorld = parent->GetTRS();
worldToLocal = SHMatrix::Inverse(localToWorld);
}
// Maintain World Transform and recompute Local Transform
// Compute Local Position
childTransform->local.position = SHVec3::Transform(childTransform->world.position, worldToLocal);
childTransform->localRotation = childTransform->worldRotation;
childTransform->local.scale = childTransform->world.scale;
if (parent)
{
// Compute Local Rotation
childTransform->localRotation -= parent->GetLocalRotation();
// Compute Local Scale
childTransform->local.scale /= parent->GetLocalScale();
}
childTransform->local.trs = localToWorld;
}
}
}
}
void SHTransformSystem::UpdateEntity(const SHSceneNode* node, bool clearDirtyFlag)
{ {
const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(node->GetEntityID()); const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(node->GetEntityID());
const bool HAS_PARENT_CHANGED = NODE_TRANSFORM && NODE_TRANSFORM->dirty; const bool HAS_PARENT_CHANGED = NODE_TRANSFORM && NODE_TRANSFORM->dirty;
@ -74,14 +180,17 @@ namespace SHADE
if (IS_NODE_ACTIVE && childTransform->isActive) if (IS_NODE_ACTIVE && childTransform->isActive)
{ {
if (childTransform->dirty || HAS_PARENT_CHANGED) if (childTransform->dirty || HAS_PARENT_CHANGED)
{
UpdateTransform(*childTransform, NODE_TRANSFORM); UpdateTransform(*childTransform, NODE_TRANSFORM);
childTransform->dirty = true;
}
} }
} }
UpdateEntity(child); UpdateEntity(child, clearDirtyFlag);
// Clear dirty flag after all children are updated // Clear dirty flag after all children are updated
if (childTransform) if (childTransform && clearDirtyFlag)
childTransform->dirty = false; childTransform->dirty = false;
} }
} }
@ -91,6 +200,8 @@ namespace SHADE
SHMatrix localToWorld = SHMatrix::Identity; SHMatrix localToWorld = SHMatrix::Identity;
SHMatrix worldToLocal = SHMatrix::Identity; SHMatrix worldToLocal = SHMatrix::Identity;
bool convertRotation = true;
if (parent) if (parent)
{ {
localToWorld = parent->GetTRS(); localToWorld = parent->GetTRS();
@ -103,22 +214,44 @@ namespace SHADE
switch (UPDATE_COMMAND.type) switch (UPDATE_COMMAND.type)
{ {
case SHTransformComponent::UpdateCommandType::LOCAL_ROTATION:
{
convertRotation = true;
break;
}
case SHTransformComponent::UpdateCommandType::LOCAL_ORIENTATION:
{
convertRotation = false;
break;
}
case SHTransformComponent::UpdateCommandType::WORLD_POSITION: case SHTransformComponent::UpdateCommandType::WORLD_POSITION:
{ {
tf.local.position = SHVec3::Transform(UPDATE_COMMAND.data, worldToLocal); tf.local.position = SHVec3::Transform(UPDATE_COMMAND.data.ToVec3(), worldToLocal);
break; break;
} }
case SHTransformComponent::UpdateCommandType::WORLD_ROTATION: case SHTransformComponent::UpdateCommandType::WORLD_ROTATION:
{ {
tf.local.rotation = tf.world.rotation; tf.localRotation = UPDATE_COMMAND.data.ToVec3();
if (parent) if (parent)
tf.local.rotation -= parent->GetLocalRotation(); tf.localRotation -= parent->GetLocalRotation();
convertRotation = true;
break;
}
case SHTransformComponent::UpdateCommandType::WORLD_ORIENTATION:
{
tf.local.orientation = UPDATE_COMMAND.data;
if (parent)
tf.local.orientation /= parent->GetLocalOrientation();
convertRotation = false;
break; break;
} }
case SHTransformComponent::UpdateCommandType::WORLD_SCALE: case SHTransformComponent::UpdateCommandType::WORLD_SCALE:
{ {
tf.local.scale = tf.world.scale; tf.local.scale = UPDATE_COMMAND.data.ToVec3();
if (parent) if (parent)
tf.local.scale /= parent->GetLocalScale(); tf.local.scale /= parent->GetLocalScale();
@ -133,15 +266,38 @@ namespace SHADE
tf.local.trs = localToWorld; tf.local.trs = localToWorld;
// Compute world transforms
tf.world.position = SHVec3::Transform(tf.local.position, localToWorld); tf.world.position = SHVec3::Transform(tf.local.position, localToWorld);
tf.world.rotation = tf.local.rotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero);
tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One); tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One);
tf.world.ComputeTRS();
// Transpose TRS to column major if (convertRotation)
//tf.local.trs.Transpose(); {
//tf.world.trs.Transpose(); tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero);
// Set the orientation
// Wrap rotations between -360 and 360 and convert to radians
SHVec3 worldRotRad, localRotRad;
for (size_t i = 0; i < SHVec3::SIZE; ++i)
{
worldRotRad[i] = SHMath::Wrap(tf.worldRotation[i], -SHMath::TWO_PI, SHMath::TWO_PI);
localRotRad[i] = SHMath::Wrap(tf.localRotation[i], -SHMath::TWO_PI, SHMath::TWO_PI);
}
tf.world.orientation = SHQuaternion::FromEuler(worldRotRad);
tf.local.orientation = SHQuaternion::FromEuler(localRotRad);
}
else
{
tf.world.orientation = (parent ? parent->GetLocalOrientation() : SHQuaternion::Identity) * tf.local.orientation;
// Set the euler angle rotations
tf.worldRotation = tf.world.orientation.ToEuler();
tf.localRotation = tf.local.orientation.ToEuler();
}
tf.world.ComputeTRS();
} }
} // namespace SHADE } // namespace SHADE

View File

@ -45,25 +45,52 @@ namespace SHADE
/* System Routines */ /* System Routines */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
class SH_API TransformUpdateRoutine final: public SHSystemRoutine class SH_API TransformPostLogicUpdate final: public SHSystemRoutine
{ {
public: public:
/*-------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */ /* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------*/
TransformUpdateRoutine (); TransformPostLogicUpdate ();
~TransformUpdateRoutine () = default; ~TransformPostLogicUpdate () = default;
TransformUpdateRoutine (const TransformUpdateRoutine&) = delete; TransformPostLogicUpdate (const TransformPostLogicUpdate&) = delete;
TransformUpdateRoutine (TransformUpdateRoutine&&) = delete; TransformPostLogicUpdate (TransformPostLogicUpdate&&) = delete;
/*-------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------*/
/* Operator Overloads */ /* Operator Overloads */
/*-------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------*/
TransformUpdateRoutine& operator= (const TransformUpdateRoutine&) = delete; TransformPostLogicUpdate& operator= (const TransformPostLogicUpdate&) = delete;
TransformUpdateRoutine& operator= (TransformUpdateRoutine&&) = delete; TransformPostLogicUpdate& operator= (TransformPostLogicUpdate&&) = delete;
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
void Execute(double dt) noexcept override;
};
class SH_API TransformPostPhysicsUpdate final: public SHSystemRoutine
{
public:
/*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/
TransformPostPhysicsUpdate ();
~TransformPostPhysicsUpdate () = default;
TransformPostPhysicsUpdate (const TransformPostPhysicsUpdate&) = delete;
TransformPostPhysicsUpdate (TransformPostPhysicsUpdate&&) = delete;
/*-------------------------------------------------------------------------------*/
/* Operator Overloads */
/*-------------------------------------------------------------------------------*/
TransformPostPhysicsUpdate& operator= (const TransformPostPhysicsUpdate&) = delete;
TransformPostPhysicsUpdate& operator= (TransformPostPhysicsUpdate&&) = delete;
/*-------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
@ -84,8 +111,11 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
static void UpdateEntity (const SHSceneNode* node); SHEventHandle ChangeParent (SHEventPtr changeParentEvent);
static void UpdateTransform(SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); static void UpdateChildrenLocalTransforms (SHSceneNode* node);
static void UpdateEntity (const SHSceneNode* node, bool clearDirtyFlag);
static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr);
}; };

View File

@ -38,6 +38,10 @@ namespace SHADE
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 0.0f ) : XMFLOAT4( 0.0f, 0.0f, 0.0f, 0.0f )
{} {}
SHVec4::SHVec4(const SHVec3& vec3) noexcept
: XMFLOAT4( vec3.x, vec3.y, vec3.z, 1.0f )
{}
SHVec4::SHVec4(const XMFLOAT4& xmfloat4) noexcept SHVec4::SHVec4(const XMFLOAT4& xmfloat4) noexcept
: XMFLOAT4( xmfloat4.x, xmfloat4.y, xmfloat4.z, xmfloat4.w ) : XMFLOAT4( xmfloat4.x, xmfloat4.y, xmfloat4.z, xmfloat4.w )
{} {}
@ -271,6 +275,11 @@ namespace SHADE
return result; return result;
} }
SHVec3 SHVec4::ToVec3() const noexcept
{
return SHVec3{ x, y, z };
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Static Function Member Definitions */ /* Static Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -16,6 +16,7 @@
// Project Headers // Project Headers
#include "SH_API.h" #include "SH_API.h"
#include "SHVec3.h"
namespace SHADE namespace SHADE
{ {
@ -53,6 +54,7 @@ namespace SHADE
~SHVec4 () = default; ~SHVec4 () = default;
SHVec4 () noexcept; SHVec4 () noexcept;
SHVec4 (const SHVec3& vec3) noexcept;
SHVec4 (const XMFLOAT4& xmfloat4) noexcept; SHVec4 (const XMFLOAT4& xmfloat4) noexcept;
SHVec4 (float x, float y, float z, float w) noexcept; SHVec4 (float x, float y, float z, float w) noexcept;
@ -102,16 +104,18 @@ namespace SHADE
[[nodiscard]] float Dot3D (const SHVec4& rhs) const noexcept; [[nodiscard]] float Dot3D (const SHVec4& rhs) const noexcept;
[[nodiscard]] SHVec4 Cross3D (const SHVec4& rhs) const noexcept; [[nodiscard]] SHVec4 Cross3D (const SHVec4& rhs) const noexcept;
[[nodiscard]] SHVec4 Cross (const SHVec4& v1, const SHVec4& v2) const noexcept; [[nodiscard]] SHVec4 Cross (const SHVec4& v1, const SHVec4& v2) const noexcept;
[[nodiscard]] SHVec3 ToVec3 () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Static Function Members */ /* Static Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] static SHVec4 Normalise (const SHVec4& v) noexcept; [[nodiscard]] static SHVec4 Normalise (const SHVec4& v) noexcept;
[[nodiscard]] static SHVec4 Normalise3D (const SHVec4& v) noexcept; [[nodiscard]] static SHVec4 Normalise3D (const SHVec4& v) noexcept;
[[nodiscard]] static SHVec4 Abs (const SHVec4& v) noexcept; [[nodiscard]] static SHVec4 Abs (const SHVec4& v) noexcept;
[[nodiscard]] static SHVec4 Min (const std::initializer_list<SHVec4>& vs) noexcept; [[nodiscard]] static SHVec4 Min (const std::initializer_list<SHVec4>& vs) noexcept;
[[nodiscard]] static SHVec4 Max (const std::initializer_list<SHVec4>& vs) noexcept; [[nodiscard]] static SHVec4 Max (const std::initializer_list<SHVec4>& vs) noexcept;
[[nodiscard]] static SHVec4 Clamp (const SHVec4& v, const SHVec4& vMin, const SHVec4& vMax) noexcept; [[nodiscard]] static SHVec4 Clamp (const SHVec4& v, const SHVec4& vMin, const SHVec4& vMax) noexcept;
[[nodiscard]] static SHVec4 Lerp (const SHVec4& a, const SHVec4& b, float t) noexcept; [[nodiscard]] static SHVec4 Lerp (const SHVec4& a, const SHVec4& b, float t) noexcept;
[[nodiscard]] static SHVec4 ClampedLerp (const SHVec4& a, const SHVec4& b, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept; [[nodiscard]] static SHVec4 ClampedLerp (const SHVec4& a, const SHVec4& b, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept;

View File

@ -140,12 +140,12 @@ namespace SHADE
isRigidBody = true; isRigidBody = true;
rb->position = tf->GetWorldPosition(); rb->position = tf->GetWorldPosition();
rb->orientation = tf->GetWorldRotation(); rb->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation());
if (hasColliders) if (hasColliders)
{ {
c->position = tf->GetWorldPosition(); c->position = tf->GetWorldPosition();
c->orientation = tf->GetWorldRotation(); c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation());
// Get array of colliders and add them back into the rigidbody // Get array of colliders and add them back into the rigidbody
for (auto& collider : c->colliders | std::views::keys) for (auto& collider : c->colliders | std::views::keys)
AddCollider(&collider); AddCollider(&collider);
@ -160,7 +160,7 @@ namespace SHADE
hasColliders = true; hasColliders = true;
c->position = tf->GetWorldPosition(); c->position = tf->GetWorldPosition();
c->orientation = tf->GetWorldRotation(); c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation());
for (auto& collider : c->colliders | std::views::keys) for (auto& collider : c->colliders | std::views::keys)
AddCollider(&collider); AddCollider(&collider);

View File

@ -16,6 +16,7 @@
// Project Headers // Project Headers
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
#include "Math/SHMathHelpers.h"
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
@ -315,7 +316,7 @@ namespace SHADE
if (TF->HasChanged()) if (TF->HasChanged())
{ {
physicsObject.SetPosition(TF->GetWorldPosition()); physicsObject.SetPosition(TF->GetWorldPosition());
physicsObject.SetRotation(TF->GetWorldRotation()); physicsObject.SetOrientation(TF->GetWorldOrientation());
} }
} }
} }
@ -492,8 +493,7 @@ namespace SHADE
// Convert RP3D Transform to SHADE // Convert RP3D Transform to SHADE
auto* tfComponent = SHComponentManager::GetComponent<SHTransformComponent>(entityID); auto* tfComponent = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
tfComponent->SetWorldPosition(rp3dPos); tfComponent->SetWorldPosition(rp3dPos);
tfComponent->SetWorldRotation(SHQuaternion{ rp3dRot }.ToEuler()); tfComponent->SetWorldOrientation(SHQuaternion{ rp3dRot });
// Cache transforms // Cache transforms
physicsObject.prevTransform = CURRENT_TF; physicsObject.prevTransform = CURRENT_TF;

View File

@ -15,6 +15,7 @@
// Project Headers // Project Headers
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
#include "Events/SHEventManager.hpp"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "Tools/SHException.h" #include "Tools/SHException.h"
@ -317,6 +318,11 @@ namespace SHADE
if (parentNode == nullptr) if (parentNode == nullptr)
{ {
SHLOG_WARNING("Removing Entity {}'s parent", entityID) SHLOG_WARNING("Removing Entity {}'s parent", entityID)
if (parent)
parent->RemoveChild(this);
return;
} }
// Handle self assignment // Handle self assignment
@ -359,10 +365,19 @@ namespace SHADE
} }
//////////////////////////////////////// ////////////////////////////////////////
const SHSceneGraphChangeParentEvent EVENT_DATA
{
.node = NODE_ITER->second
, .oldParent = NODE_ITER->second->GetParent()
, .newParent = parent ? parent : root
};
if (parent == nullptr) if (parent == nullptr)
parent = root; parent = root;
NODE_ITER->second->SetParent(parent); NODE_ITER->second->SetParent(parent);
SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT);
} }
void SHSceneGraph::SetParent(EntityID entityID, EntityID parent) const noexcept void SHSceneGraph::SetParent(EntityID entityID, EntityID parent) const noexcept
@ -396,8 +411,17 @@ namespace SHADE
} }
//////////////////////////////////////// ////////////////////////////////////////
const SHSceneGraphChangeParentEvent EVENT_DATA
{
.node = NODE_ITER->second
, .oldParent = NODE_ITER->second->GetParent()
, .newParent = PARENT_ITER->second
};
SHSceneNode* currentNode = NODE_ITER->second; SHSceneNode* currentNode = NODE_ITER->second;
currentNode->SetParent(PARENT_ITER->second); currentNode->SetParent(PARENT_ITER->second);
SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -558,7 +582,7 @@ namespace SHADE
ReleaseNode(node); ReleaseNode(node);
} }
void SHSceneGraph::Traverse (const UnaryPredicate& predicate) const void SHSceneGraph::Traverse (const UnaryFunction& predicate) const
{ {
TraverseAndInvokePredicate(root, predicate); TraverseAndInvokePredicate(root, predicate);
} }
@ -597,7 +621,7 @@ namespace SHADE
delete node; delete node;
} }
void SHSceneGraph::TraverseAndInvokePredicate(const SHSceneNode* node, const UnaryPredicate& predicate) void SHSceneGraph::TraverseAndInvokePredicate(const SHSceneNode* node, const UnaryFunction& predicate)
{ {
for (auto* child : node->children) for (auto* child : node->children)
{ {

View File

@ -97,9 +97,8 @@ namespace SHADE
/* Type Definitions */ /* Type Definitions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
using EntityNodeMap = std::unordered_map<EntityID, SHSceneNode*>; using EntityNodeMap = std::unordered_map<EntityID, SHSceneNode*>;
using UnaryFunction = std::function<void(SHSceneNode*)>;
using UnaryPredicate = std::function<void(SHSceneNode*)>;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -143,8 +142,7 @@ namespace SHADE
bool RemoveNode (SHSceneNode* nodeToRemove) noexcept; bool RemoveNode (SHSceneNode* nodeToRemove) noexcept;
void Reset () noexcept; void Reset () noexcept;
void Traverse (const UnaryPredicate& predicate) const; void Traverse (const UnaryFunction& predicate) const;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -160,8 +158,14 @@ namespace SHADE
SHSceneNode* AllocateNode (EntityID entityID); SHSceneNode* AllocateNode (EntityID entityID);
void ReleaseNode (SHSceneNode* node) noexcept; void ReleaseNode (SHSceneNode* node) noexcept;
static void TraverseAndInvokePredicate (const SHSceneNode* node, const UnaryPredicate& predicate); static void TraverseAndInvokePredicate (const SHSceneNode* node, const UnaryFunction& predicate);
}; };
struct SHSceneGraphChangeParentEvent
{
SHSceneNode* node;
SHSceneNode* oldParent;
SHSceneNode* newParent;
};
} // namespace SHADE } // namespace SHADE

View File

@ -0,0 +1,17 @@
/************************************************************************************//*!
\file Quaternion.hxx
\author Diren D Bharwani, diren.dbharwani, 390002520
\par email: diren.dbharwani\@digipen.edu
\date Oct 23, 2022
\brief Contains the definitions of Quaternion struct.
Note: This file is written in C++17/CLI.
Copyright (C) 2021 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// TODO(Diren)

View File

@ -11,6 +11,7 @@ Copyright (C) 2021 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited. of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/ *//*************************************************************************************/
#pragma once #pragma once
// Standard Libraries // Standard Libraries