SP3-16 Quaternions #112
|
@ -83,11 +83,13 @@ namespace Sandbox
|
|||
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::LateUpdateRoutine>();
|
||||
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::FrameCleanUpRoutine>();
|
||||
|
||||
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostLogicUpdate>();
|
||||
|
||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
|
||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
|
||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
|
||||
|
||||
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformUpdateRoutine>();
|
||||
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
|
||||
|
||||
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
|
||||
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
|
||||
|
|
|
@ -67,9 +67,9 @@ namespace Sandbox
|
|||
customMat->SetProperty("data.alpha", 0.1f);
|
||||
|
||||
// Create Stress Test Objects
|
||||
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One * 0.5f;
|
||||
constexpr int NUM_ROWS = 0;
|
||||
constexpr int NUM_COLS = 0;
|
||||
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One;
|
||||
constexpr int NUM_ROWS = 3;
|
||||
constexpr int NUM_COLS = 1;
|
||||
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 };
|
||||
|
||||
|
@ -91,13 +91,13 @@ namespace Sandbox
|
|||
//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({-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);
|
||||
|
||||
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);
|
||||
else
|
||||
collider.AddBoundingSphere(0.5f, SHVec3::Zero);
|
||||
//else
|
||||
// collider.AddBoundingSphere(0.5f, SHVec3::Zero);
|
||||
|
||||
stressTestObjects.emplace_back(entity);
|
||||
}
|
||||
|
|
|
@ -5,8 +5,9 @@ typedef uint32_t SHEventIdentifier;
|
|||
typedef uint32_t SHEventHandle;
|
||||
|
||||
//Add your event identifiers here:
|
||||
constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0};
|
||||
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 };
|
||||
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT{ 3 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT{ 4 };
|
||||
constexpr SHEventIdentifier SH_EXAMPLE_EVENT { 0 };
|
||||
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT { 1 };
|
||||
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
|
||||
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };
|
||||
|
|
|
@ -295,32 +295,33 @@ namespace SHADE
|
|||
) != 0;
|
||||
}
|
||||
|
||||
SHMatrix::operator XMMATRIX() const noexcept
|
||||
{
|
||||
return XMLoadFloat4x4(this);
|
||||
}
|
||||
|
||||
SHMatrix operator*(float lhs, const SHMatrix& rhs) noexcept
|
||||
{
|
||||
return rhs * lhs;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHMatrix::Transpose() noexcept
|
||||
{
|
||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
||||
XMStoreFloat4x4(this, XMMatrixTranspose(M));
|
||||
XMStoreFloat4x4(this, XMMatrixTranspose(*this));
|
||||
}
|
||||
|
||||
void SHMatrix::Invert() noexcept
|
||||
{
|
||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
||||
XMStoreFloat4x4(this, XMMatrixInverse(nullptr, M));
|
||||
XMStoreFloat4x4(this, XMMatrixInverse(nullptr, *this));
|
||||
}
|
||||
|
||||
float SHMatrix::Determinant() const noexcept
|
||||
{
|
||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
||||
return XMVectorGetX(XMMatrixDeterminant(M));
|
||||
return XMVectorGetX(XMMatrixDeterminant(*this));
|
||||
}
|
||||
|
||||
std::string SHMatrix::ToString() const noexcept
|
||||
|
@ -337,9 +338,8 @@ namespace SHADE
|
|||
bool SHMatrix::Decompose(SHVec3& translation, SHVec3& rotation, SHVec3& scale) const noexcept
|
||||
{
|
||||
XMVECTOR s, r, t;
|
||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
||||
|
||||
if (!XMMatrixDecompose(&s, &r, &t, M))
|
||||
if (!XMMatrixDecompose(&s, &r, &t, *this))
|
||||
return false;
|
||||
|
||||
SHQuaternion orientation;
|
||||
|
@ -356,9 +356,8 @@ namespace SHADE
|
|||
bool SHMatrix::Decompose(SHVec3& translation, SHQuaternion& orientation, SHVec3& scale) const noexcept
|
||||
{
|
||||
XMVECTOR s, r, t;
|
||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
||||
|
||||
if (!XMMatrixDecompose(&s, &r, &t, M))
|
||||
if (!XMMatrixDecompose(&s, &r, &t, *this))
|
||||
return false;
|
||||
|
||||
XMStoreFloat3(&scale, s);
|
||||
|
@ -376,8 +375,7 @@ namespace SHADE
|
|||
{
|
||||
SHMatrix result;
|
||||
|
||||
const XMMATRIX M = XMLoadFloat4x4(&matrix);
|
||||
XMStoreFloat4x4(&result, XMMatrixTranspose(M));
|
||||
XMStoreFloat4x4(&result, XMMatrixTranspose(matrix));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -385,8 +383,7 @@ namespace SHADE
|
|||
{
|
||||
SHMatrix result;
|
||||
|
||||
const XMMATRIX M = XMLoadFloat4x4(&matrix);
|
||||
XMStoreFloat4x4(&result, XMMatrixInverse(nullptr, M));
|
||||
XMStoreFloat4x4(&result, XMMatrixInverse(nullptr, matrix));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -401,8 +398,8 @@ namespace SHADE
|
|||
SHMatrix SHMatrix::Translate(const SHVec3& pos) noexcept
|
||||
{
|
||||
SHMatrix result;
|
||||
XMStoreFloat4x4(&result, XMMatrixTranslation(pos.x, pos.y, pos.z));
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixTranslation(pos.x, pos.y, pos.z));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -410,25 +407,23 @@ namespace SHADE
|
|||
{
|
||||
SHMatrix result;
|
||||
|
||||
const XMVECTOR A = XMLoadFloat3(&axis);
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationAxis(A, angleInRad));
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationAxis(axis, angleInRad));
|
||||
return result;
|
||||
}
|
||||
|
||||
SHMatrix SHMatrix::Rotate(float yaw, float pitch, float roll) noexcept
|
||||
{
|
||||
SHMatrix result;
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(pitch, yaw, roll));
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(pitch, yaw, roll));
|
||||
return result;
|
||||
}
|
||||
|
||||
SHMatrix SHMatrix::Rotate(const SHVec3& eulerAngles) noexcept
|
||||
{
|
||||
SHMatrix result;
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(eulerAngles.x, eulerAngles.y, eulerAngles.z));
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYawFromVector(eulerAngles));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -436,57 +431,55 @@ namespace SHADE
|
|||
{
|
||||
SHMatrix result;
|
||||
|
||||
const XMVECTOR Q = XMLoadFloat4(&q);
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationQuaternion(Q));
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationQuaternion(q));
|
||||
return result;
|
||||
}
|
||||
|
||||
SHMatrix SHMatrix::RotateX(float angleInRad) noexcept
|
||||
{
|
||||
SHMatrix result;
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationX(angleInRad));
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationX(angleInRad));
|
||||
return result;
|
||||
}
|
||||
|
||||
SHMatrix SHMatrix::RotateY(float angleInRad) noexcept
|
||||
{
|
||||
SHMatrix result;
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationY(angleInRad));
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationY(angleInRad));
|
||||
return result;
|
||||
}
|
||||
|
||||
SHMatrix SHMatrix::RotateZ(float angleInRad) noexcept
|
||||
{
|
||||
SHMatrix result;
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationZ(angleInRad));
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixRotationZ(angleInRad));
|
||||
return result;
|
||||
}
|
||||
|
||||
SHMatrix SHMatrix::Scale(float uniformScaleFactor) noexcept
|
||||
{
|
||||
SHMatrix result;
|
||||
XMStoreFloat4x4(&result, XMMatrixScaling(uniformScaleFactor, uniformScaleFactor, uniformScaleFactor));
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixScaling(uniformScaleFactor, uniformScaleFactor, uniformScaleFactor));
|
||||
return result;
|
||||
}
|
||||
|
||||
SHMatrix SHMatrix::Scale(float x, float y, float z) noexcept
|
||||
{
|
||||
SHMatrix result;
|
||||
XMStoreFloat4x4(&result, XMMatrixScaling(x, y, z));
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixScaling(x, y, z));
|
||||
return result;
|
||||
}
|
||||
|
||||
SHMatrix SHMatrix::Scale(const SHVec3& scale) noexcept
|
||||
{
|
||||
SHMatrix result;
|
||||
XMStoreFloat4x4(&result, XMMatrixScaling(scale.x, scale.y, scale.z));
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixScalingFromVector(scale));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -494,12 +487,7 @@ namespace SHADE
|
|||
{
|
||||
SHMatrix result;
|
||||
|
||||
const XMVECTOR EYE = XMLoadFloat3(&eye);
|
||||
const XMVECTOR TGT = XMLoadFloat3(&target);
|
||||
const XMVECTOR UP = XMLoadFloat3(&up);
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixLookAtRH(EYE, TGT, UP));
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixLookAtRH(eye, target, up));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -507,12 +495,7 @@ namespace SHADE
|
|||
{
|
||||
SHMatrix result;
|
||||
|
||||
const XMVECTOR EYE = XMLoadFloat3(&eye);
|
||||
const XMVECTOR TGT = XMLoadFloat3(&target);
|
||||
const XMVECTOR UP = XMLoadFloat3(&up);
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixLookAtLH(EYE, TGT, UP));
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixLookAtLH(eye, target, up));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -522,8 +505,8 @@ namespace SHADE
|
|||
|
||||
const SHVec3 FWD_HAT = SHVec3::Normalise(-forward);
|
||||
|
||||
const XMVECTOR Z_HAT = XMVector3Normalize(XMLoadFloat3(&FWD_HAT));
|
||||
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(XMLoadFloat3(&up), Z_HAT));
|
||||
const XMVECTOR Z_HAT = XMVector3Normalize(FWD_HAT);
|
||||
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(up, Z_HAT));
|
||||
const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT);
|
||||
|
||||
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT);
|
||||
|
@ -543,8 +526,8 @@ namespace SHADE
|
|||
|
||||
const SHVec3 FWD_HAT = SHVec3::Normalise(forward);
|
||||
|
||||
const XMVECTOR Z_HAT = XMVector3Normalize(XMLoadFloat3(&FWD_HAT));
|
||||
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(XMLoadFloat3(&up), Z_HAT));
|
||||
const XMVECTOR Z_HAT = XMVector3Normalize(FWD_HAT);
|
||||
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(up, Z_HAT));
|
||||
const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT);
|
||||
|
||||
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT);
|
||||
|
@ -563,7 +546,6 @@ namespace SHADE
|
|||
SHMatrix result;
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixPerspectiveFovRH(fov, aspectRatio, nearPlane, farPlane));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -572,7 +554,6 @@ namespace SHADE
|
|||
SHMatrix result;
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixPerspectiveFovLH(fov, aspectRatio, nearPlane, farPlane));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -581,7 +562,6 @@ namespace SHADE
|
|||
SHMatrix result;
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixPerspectiveRH(width, height, nearPlane, farPlane));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -590,7 +570,6 @@ namespace SHADE
|
|||
SHMatrix result;
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixPerspectiveLH(width, height, nearPlane, farPlane));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -599,7 +578,6 @@ namespace SHADE
|
|||
SHMatrix result;
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixOrthographicRH(width, height, nearPlane, farPlane));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -608,7 +586,6 @@ namespace SHADE
|
|||
SHMatrix result;
|
||||
|
||||
XMStoreFloat4x4(&result, XMMatrixOrthographicLH(width, height, nearPlane, farPlane));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,8 @@ namespace SHADE
|
|||
SHMatrix& operator= (const 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;
|
||||
|
|
|
@ -36,44 +36,18 @@ namespace SHADE
|
|||
: 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
|
||||
: 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
|
||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
||||
{
|
||||
const SHVec3& SHADE_VEC{ rp3dEuler };
|
||||
|
||||
const XMVECTOR V = XMLoadFloat3(&SHADE_VEC);
|
||||
XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V));
|
||||
XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(SHVec3 { rp3dEuler }));
|
||||
}
|
||||
|
||||
SHQuaternion::SHQuaternion(const reactphysics3d::Quaternion& rp3dQuat) noexcept
|
||||
|
@ -113,10 +87,7 @@ namespace SHADE
|
|||
{
|
||||
SHQuaternion result;
|
||||
|
||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
||||
|
||||
XMStoreFloat4(&result, XMVectorAdd(Q1, Q2));
|
||||
XMStoreFloat4(&result, XMVectorAdd(*this, rhs));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -124,10 +95,7 @@ namespace SHADE
|
|||
{
|
||||
SHQuaternion result;
|
||||
|
||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
||||
|
||||
XMStoreFloat4(&result, XMVectorSubtract(Q1, Q2));
|
||||
XMStoreFloat4(&result, XMVectorSubtract(*this, rhs));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -135,9 +103,7 @@ namespace SHADE
|
|||
{
|
||||
SHQuaternion result;
|
||||
|
||||
const XMVECTOR Q = XMLoadFloat4(this);
|
||||
|
||||
XMStoreFloat4(&result, XMVectorNegate(Q));
|
||||
XMStoreFloat4(&result, XMVectorNegate(*this));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -145,10 +111,7 @@ namespace SHADE
|
|||
{
|
||||
SHQuaternion result;
|
||||
|
||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
||||
|
||||
XMStoreFloat4(&result, XMQuaternionMultiply(Q1, Q2));
|
||||
XMStoreFloat4(&result, XMQuaternionMultiply(*this, rhs));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -156,9 +119,7 @@ namespace SHADE
|
|||
{
|
||||
SHQuaternion result;
|
||||
|
||||
const XMVECTOR Q = XMLoadFloat4(this);
|
||||
|
||||
XMStoreFloat4(&result, XMVectorScale(Q, rhs));
|
||||
XMStoreFloat4(&result, XMVectorScale(*this, rhs));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -166,27 +127,18 @@ namespace SHADE
|
|||
{
|
||||
SHQuaternion result;
|
||||
|
||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
||||
const XMVECTOR Q2 = XMQuaternionInverse(XMLoadFloat4(&rhs));
|
||||
|
||||
XMStoreFloat4(&result, XMQuaternionMultiply(Q1, Q2));
|
||||
XMStoreFloat4(&result, XMQuaternionMultiply(*this, XMQuaternionInverse(rhs)));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SHQuaternion::operator==(const SHQuaternion& rhs) const noexcept
|
||||
{
|
||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
||||
|
||||
return XMQuaternionEqual(Q1, Q2);
|
||||
return XMQuaternionEqual(*this, rhs);
|
||||
}
|
||||
|
||||
bool SHQuaternion::operator!=(const SHQuaternion& rhs) const noexcept
|
||||
{
|
||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
||||
|
||||
return XMQuaternionNotEqual(Q1, Q2);
|
||||
return XMQuaternionNotEqual(*this, rhs);
|
||||
}
|
||||
|
||||
SHQuaternion::operator reactphysics3d::Quaternion() const noexcept
|
||||
|
@ -199,6 +151,11 @@ namespace SHADE
|
|||
return reactphysics3d::Vector3{ ToEuler() };
|
||||
}
|
||||
|
||||
SHQuaternion::operator XMVECTOR() const noexcept
|
||||
{
|
||||
return XMLoadFloat4(this);
|
||||
}
|
||||
|
||||
SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept
|
||||
{
|
||||
return rhs * lhs;
|
||||
|
@ -213,8 +170,7 @@ namespace SHADE
|
|||
XMVECTOR axis;
|
||||
float angle;
|
||||
|
||||
const XMVECTOR Q = XMLoadFloat4(this);
|
||||
XMQuaternionToAxisAngle(&axis, &angle, Q);
|
||||
XMQuaternionToAxisAngle(&axis, &angle, *this);
|
||||
return angle;
|
||||
}
|
||||
|
||||
|
@ -223,8 +179,7 @@ namespace SHADE
|
|||
XMVECTOR axis;
|
||||
float angle;
|
||||
|
||||
const XMVECTOR Q = XMLoadFloat4(this);
|
||||
XMQuaternionToAxisAngle(&axis, &angle, Q);
|
||||
XMQuaternionToAxisAngle(&axis, &angle, *this);
|
||||
|
||||
|
||||
return SHVec4{XMVectorGetX(axis), XMVectorGetY(axis), XMVectorGetZ(axis), angle};
|
||||
|
@ -238,64 +193,49 @@ namespace SHADE
|
|||
|
||||
void SHQuaternion::Invert() noexcept
|
||||
{
|
||||
const XMVECTOR Q = XMLoadFloat4(this);
|
||||
XMStoreFloat4(this, XMQuaternionInverse(Q));
|
||||
XMStoreFloat4(this, XMQuaternionInverse(*this));
|
||||
}
|
||||
|
||||
float SHQuaternion::Length() const noexcept
|
||||
{
|
||||
const XMVECTOR Q = XMLoadFloat4(this);
|
||||
return XMVectorGetX(XMQuaternionLength(Q));
|
||||
return XMVectorGetX(XMQuaternionLength(*this));
|
||||
}
|
||||
|
||||
float SHQuaternion::LengthSquared() const noexcept
|
||||
{
|
||||
const XMVECTOR Q = XMLoadFloat4(this);
|
||||
return XMVectorGetX(XMQuaternionLengthSq(Q));
|
||||
return XMVectorGetX(XMQuaternionLengthSq(*this));
|
||||
}
|
||||
|
||||
float SHQuaternion::Dot(const SHQuaternion& rhs) const noexcept
|
||||
{
|
||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
||||
|
||||
return XMVectorGetX(XMQuaternionDot(Q1, Q2));
|
||||
}
|
||||
|
||||
SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion&, float) const noexcept
|
||||
{
|
||||
SHQuaternion result;
|
||||
|
||||
// TODO (Diren)
|
||||
|
||||
return result;
|
||||
return XMVectorGetX(XMQuaternionDot(*this, rhs));
|
||||
}
|
||||
|
||||
SHVec3 SHQuaternion::ToEuler() const noexcept
|
||||
{
|
||||
const float xx = x * x;
|
||||
const float yy = y * y;
|
||||
const float zz = z * z;
|
||||
const float XX = x * x;
|
||||
const float YY = y * y;
|
||||
const float ZZ = z * z;
|
||||
|
||||
const float m31 = 2.f * x * z + 2.f * y * w;
|
||||
const float m32 = 2.f * y * z - 2.f * x * w;
|
||||
const float m33 = 1.f - 2.f * xx - 2.f * yy;
|
||||
const float M_31 = 2.f * x * z + 2.f * y * w;
|
||||
const float M_32 = 2.f * y * z - 2.f * x * w;
|
||||
const float M_33 = 1.f - 2.f * XX - 2.f * YY;
|
||||
|
||||
const float cy = sqrtf(m33 * m33 + m31 * m31);
|
||||
const float cx = atan2f(-m32, cy);
|
||||
if (cy > 16.0f * SHMath::EPSILON)
|
||||
const float CY = sqrtf(M_33 * M_33 + M_31 * M_31);
|
||||
const float CX = atan2f(-M_32, CY);
|
||||
if (CY > 16.0f * SHMath::EPSILON)
|
||||
{
|
||||
const float m12 = 2.f * x * y + 2.f * z * w;
|
||||
const float m22 = 1.f - 2.f * xx - 2.f * zz;
|
||||
const float M_12 = 2.f * x * y + 2.f * z * w;
|
||||
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
|
||||
{
|
||||
const float m11 = 1.f - 2.f * yy - 2.f * zz;
|
||||
const float m21 = 2.f * x * y - 2.f * z * w;
|
||||
const float m11 = 1.f - 2.f * YY - 2.f * ZZ;
|
||||
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 */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
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 result;
|
||||
|
||||
const XMVECTOR Q = XMLoadFloat4(&q);
|
||||
|
||||
XMStoreFloat4(&result, XMQuaternionNormalize(Q));
|
||||
XMStoreFloat4(&result, XMQuaternionNormalize(q));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -325,9 +295,7 @@ namespace SHADE
|
|||
{
|
||||
SHQuaternion result;
|
||||
|
||||
const XMVECTOR Q = XMLoadFloat4(&q);
|
||||
|
||||
XMStoreFloat4(&result, XMQuaternionConjugate(Q));
|
||||
XMStoreFloat4(&result, XMQuaternionConjugate(q));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -335,26 +303,37 @@ namespace SHADE
|
|||
{
|
||||
SHQuaternion result;
|
||||
|
||||
const XMVECTOR Q = XMLoadFloat4(&q);
|
||||
XMStoreFloat4(&result, XMQuaternionInverse(Q));
|
||||
|
||||
XMStoreFloat4(&result, XMQuaternionInverse(q));
|
||||
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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -362,19 +341,105 @@ namespace SHADE
|
|||
{
|
||||
SHQuaternion result;
|
||||
|
||||
const XMVECTOR Q1 = XMLoadFloat4(&q1);
|
||||
const XMVECTOR Q2 = XMLoadFloat4(&q2);
|
||||
|
||||
XMStoreFloat4(&result, XMQuaternionSlerp(Q1, Q2, t));
|
||||
XMStoreFloat4(&result, XMQuaternionSlerp(q1, q2, t));
|
||||
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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,11 +49,8 @@ namespace SHADE
|
|||
SHQuaternion (SHQuaternion&& rhs) = default;
|
||||
|
||||
SHQuaternion () noexcept;
|
||||
SHQuaternion (const SHVec4& vec4) 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
|
||||
|
||||
|
@ -87,6 +84,7 @@ namespace SHADE
|
|||
|
||||
operator reactphysics3d::Quaternion () const noexcept;
|
||||
operator reactphysics3d::Vector3 () const noexcept;
|
||||
operator DirectX::XMVECTOR () const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
|
@ -99,29 +97,37 @@ namespace SHADE
|
|||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void Invert () noexcept;
|
||||
void Invert () noexcept;
|
||||
|
||||
[[nodiscard]] float Length () const noexcept;
|
||||
[[nodiscard]] float LengthSquared () const noexcept;
|
||||
[[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept;
|
||||
[[nodiscard]] SHQuaternion RotateTowards (const SHQuaternion& target, float maxAngleInRad) const noexcept;
|
||||
[[nodiscard]] float Length () const noexcept;
|
||||
[[nodiscard]] float LengthSquared () const noexcept;
|
||||
[[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept;
|
||||
|
||||
[[nodiscard]] SHVec3 ToEuler () const noexcept;
|
||||
[[nodiscard]] std::string ToString () const noexcept;
|
||||
[[nodiscard]] SHVec3 ToEuler () const noexcept;
|
||||
[[nodiscard]] std::string ToString () const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Static Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) 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 FromEuler (const SHVec3& eulerAngles) noexcept;
|
||||
[[nodiscard]] static SHQuaternion FromPitchYawRoll (float pitch, float yaw, float roll) noexcept;
|
||||
[[nodiscard]] static SHQuaternion FromAxisAngle (const SHVec3& axis, float angle) 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 Slerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept;
|
||||
[[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) 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;
|
||||
|
|
|
@ -26,15 +26,15 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHTransform::SHTransform() noexcept
|
||||
: position { SHVec3::Zero }
|
||||
, rotation { SHVec3::Zero }
|
||||
, scale { SHVec3::One }
|
||||
: position { SHVec3::Zero }
|
||||
, orientation { SHQuaternion::Identity }
|
||||
, scale { SHVec3::One }
|
||||
{}
|
||||
|
||||
SHTransform::SHTransform(const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept
|
||||
: position { pos }
|
||||
, rotation { rot }
|
||||
, scale { scl }
|
||||
: position { pos }
|
||||
, orientation { SHQuaternion::FromEuler(rot) }
|
||||
, scale { scl }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -43,12 +43,12 @@ namespace SHADE
|
|||
|
||||
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
|
||||
{
|
||||
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 R = SHMatrix::Rotate(rotation);
|
||||
const SHMatrix R = SHMatrix::Rotate(orientation);
|
||||
const SHMatrix S = SHMatrix::Scale(scale);
|
||||
|
||||
trs = S * R * T;
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
// Project Headers
|
||||
#include "SH_API.h"
|
||||
#include "Math/Vector/SHVec2.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
#include "Math/SHQuaternion.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
|
||||
namespace SHADE
|
||||
|
@ -31,22 +31,23 @@ namespace SHADE
|
|||
|
||||
static const SHTransform Identity;
|
||||
|
||||
SHVec3 position;
|
||||
SHVec3 rotation;
|
||||
SHVec3 scale;
|
||||
SHVec3 position;
|
||||
SHQuaternion orientation;
|
||||
SHVec3 scale;
|
||||
|
||||
SHMatrix trs;
|
||||
SHMatrix trs;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHTransform (const SHTransform&) = default;
|
||||
SHTransform (SHTransform&&) = default;
|
||||
~SHTransform () = default;
|
||||
SHTransform (const SHTransform&) = default;
|
||||
SHTransform (SHTransform&&) = default;
|
||||
~SHTransform () = default;
|
||||
|
||||
SHTransform () noexcept;
|
||||
SHTransform (const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept;
|
||||
SHTransform () 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 */
|
||||
|
@ -63,7 +64,6 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
const SHMatrix& ComputeTRS();
|
||||
|
||||
};
|
||||
|
||||
} // namespace SHADE
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
// Primary Header
|
||||
#include "SHTransformComponent.h"
|
||||
// Project Headers
|
||||
#include "Math/SHMathHelpers.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -40,7 +42,12 @@ namespace SHADE
|
|||
|
||||
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
|
||||
|
@ -55,7 +62,12 @@ namespace SHADE
|
|||
|
||||
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
|
||||
|
@ -91,16 +103,28 @@ namespace SHADE
|
|||
void SHTransformComponent::SetLocalRotation(const SHVec3& newLocalRotation) noexcept
|
||||
{
|
||||
dirty = true;
|
||||
local.rotation = newLocalRotation;
|
||||
|
||||
localRotation = newLocalRotation;
|
||||
updateQueue.push({ UpdateCommandType::LOCAL_ROTATION, newLocalRotation });
|
||||
}
|
||||
|
||||
void SHTransformComponent::SetLocalRotation(float pitch, float yaw, float roll) noexcept
|
||||
{
|
||||
dirty = true;
|
||||
|
||||
local.rotation.x = pitch;
|
||||
local.rotation.y = yaw;
|
||||
local.rotation.z = roll;
|
||||
localRotation.x = pitch;
|
||||
localRotation.y = yaw;
|
||||
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
|
||||
|
@ -121,7 +145,7 @@ namespace SHADE
|
|||
{
|
||||
dirty = true;
|
||||
|
||||
world.rotation = newWorldRotation;
|
||||
worldRotation = newWorldRotation;
|
||||
updateQueue.push({ UpdateCommandType::WORLD_ROTATION, newWorldRotation });
|
||||
}
|
||||
|
||||
|
@ -129,13 +153,21 @@ namespace SHADE
|
|||
{
|
||||
dirty = true;
|
||||
|
||||
world.rotation.x = pitch;
|
||||
world.rotation.y = yaw;
|
||||
world.rotation.z = roll;
|
||||
worldRotation.x = pitch;
|
||||
worldRotation.y = yaw;
|
||||
worldRotation.z = 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
|
||||
{
|
||||
dirty = true;
|
||||
|
@ -153,6 +185,6 @@ RTTR_REGISTRATION
|
|||
|
||||
registration::class_<SHTransformComponent>("Transform Component")
|
||||
.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 );
|
||||
}
|
|
@ -56,42 +56,52 @@ namespace SHADE
|
|||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] bool HasChanged () const noexcept;
|
||||
[[nodiscard]] bool HasChanged () const noexcept;
|
||||
|
||||
[[nodiscard]] const SHVec3& GetLocalPosition () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetLocalRotation () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetLocalScale () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetWorldPosition () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetWorldRotation () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetWorldScale () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetLocalPosition () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetLocalRotation () const noexcept;
|
||||
[[nodiscard]] const SHQuaternion& GetLocalOrientation () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetLocalScale () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetWorldPosition () 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]] SHMatrix GetWorldToLocal () const noexcept;
|
||||
[[nodiscard]] const SHMatrix& GetLocalToWorld () const noexcept;
|
||||
[[nodiscard]] SHMatrix GetWorldToLocal () const noexcept;
|
||||
|
||||
[[nodiscard]] const SHMatrix& GetTRS () const noexcept;
|
||||
[[nodiscard]] const SHMatrix& GetTRS () const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetLocalPosition (const SHVec3& newLocalPosition) noexcept;
|
||||
void SetLocalRotation (const SHVec3& newLocalRotation) noexcept;
|
||||
void SetLocalRotation (float pitch, float yaw, float roll) noexcept;
|
||||
void SetLocalScale (const SHVec3& newLocalScale) noexcept;
|
||||
void SetWorldPosition (const SHVec3& newWorldPosition) noexcept;
|
||||
void SetWorldRotation (const SHVec3& newWorldRotation) noexcept;
|
||||
void SetWorldRotation (float pitch, float yaw, float roll) noexcept;
|
||||
void SetWorldScale (const SHVec3& newWorldScale) noexcept;
|
||||
void SetLocalPosition (const SHVec3& newLocalPosition) noexcept;
|
||||
void SetLocalRotation (const SHVec3& newLocalRotation) noexcept;
|
||||
void SetLocalRotation (float pitch, float yaw, float roll) noexcept;
|
||||
void SetLocalOrientation (const SHQuaternion& newLocalOrientation) noexcept;
|
||||
void SetLocalScale (const SHVec3& newLocalScale) noexcept;
|
||||
void SetWorldPosition (const SHVec3& newWorldPosition) noexcept;
|
||||
void SetWorldRotation (const SHVec3& newWorldRotation) noexcept;
|
||||
void SetWorldRotation (float pitch, float yaw, float roll) noexcept;
|
||||
void SetWorldOrientation (const SHQuaternion& newWorldOrientation) noexcept;
|
||||
void SetWorldScale (const SHVec3& newWorldScale) noexcept;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
// Differentiate between rotation and orientation for setters
|
||||
// Setting a quaternion directly is different from using euler angle rotations.
|
||||
|
||||
enum class UpdateCommandType
|
||||
{
|
||||
WORLD_POSITION
|
||||
LOCAL_ROTATION
|
||||
, LOCAL_ORIENTATION
|
||||
, WORLD_POSITION
|
||||
, WORLD_ROTATION
|
||||
, WORLD_ORIENTATION
|
||||
, WORLD_SCALE
|
||||
};
|
||||
|
||||
|
@ -103,7 +113,7 @@ namespace SHADE
|
|||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
UpdateCommandType type;
|
||||
SHVec3 data;
|
||||
SHVec4 data;
|
||||
};
|
||||
|
||||
using UpdateQueue = std::queue<UpdateCommand>;
|
||||
|
@ -114,6 +124,12 @@ namespace SHADE
|
|||
|
||||
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 world;
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
#include "Scene/SHSceneManager.h"
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
#include "Tools/SHException.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Math/SHMathHelpers.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -29,8 +30,12 @@ namespace SHADE
|
|||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHTransformSystem::TransformUpdateRoutine::TransformUpdateRoutine()
|
||||
: SHSystemRoutine { "Transform Update", true }
|
||||
SHTransformSystem::TransformPostLogicUpdate::TransformPostLogicUpdate()
|
||||
: 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 */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHTransformSystem::TransformUpdateRoutine::Execute(double) noexcept
|
||||
void SHTransformSystem::TransformPostLogicUpdate::Execute(double) noexcept
|
||||
{
|
||||
// Get the current scene graph to traverse and update
|
||||
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()
|
||||
{
|
||||
|
||||
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()
|
||||
|
@ -59,7 +75,97 @@ namespace SHADE
|
|||
/* 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 bool HAS_PARENT_CHANGED = NODE_TRANSFORM && NODE_TRANSFORM->dirty;
|
||||
|
@ -74,14 +180,17 @@ namespace SHADE
|
|||
if (IS_NODE_ACTIVE && childTransform->isActive)
|
||||
{
|
||||
if (childTransform->dirty || HAS_PARENT_CHANGED)
|
||||
{
|
||||
UpdateTransform(*childTransform, NODE_TRANSFORM);
|
||||
childTransform->dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateEntity(child);
|
||||
UpdateEntity(child, clearDirtyFlag);
|
||||
|
||||
// Clear dirty flag after all children are updated
|
||||
if (childTransform)
|
||||
if (childTransform && clearDirtyFlag)
|
||||
childTransform->dirty = false;
|
||||
}
|
||||
}
|
||||
|
@ -91,6 +200,8 @@ namespace SHADE
|
|||
SHMatrix localToWorld = SHMatrix::Identity;
|
||||
SHMatrix worldToLocal = SHMatrix::Identity;
|
||||
|
||||
bool convertRotation = true;
|
||||
|
||||
if (parent)
|
||||
{
|
||||
localToWorld = parent->GetTRS();
|
||||
|
@ -103,22 +214,44 @@ namespace SHADE
|
|||
|
||||
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:
|
||||
{
|
||||
tf.local.position = SHVec3::Transform(UPDATE_COMMAND.data, worldToLocal);
|
||||
tf.local.position = SHVec3::Transform(UPDATE_COMMAND.data.ToVec3(), worldToLocal);
|
||||
break;
|
||||
}
|
||||
case SHTransformComponent::UpdateCommandType::WORLD_ROTATION:
|
||||
{
|
||||
tf.local.rotation = tf.world.rotation;
|
||||
tf.localRotation = UPDATE_COMMAND.data.ToVec3();
|
||||
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;
|
||||
}
|
||||
case SHTransformComponent::UpdateCommandType::WORLD_SCALE:
|
||||
{
|
||||
tf.local.scale = tf.world.scale;
|
||||
tf.local.scale = UPDATE_COMMAND.data.ToVec3();
|
||||
if (parent)
|
||||
tf.local.scale /= parent->GetLocalScale();
|
||||
|
||||
|
@ -133,15 +266,38 @@ namespace SHADE
|
|||
|
||||
tf.local.trs = localToWorld;
|
||||
|
||||
// Compute world transforms
|
||||
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.ComputeTRS();
|
||||
|
||||
// Transpose TRS to column major
|
||||
//tf.local.trs.Transpose();
|
||||
//tf.world.trs.Transpose();
|
||||
|
||||
if (convertRotation)
|
||||
{
|
||||
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
|
|
@ -45,25 +45,52 @@ namespace SHADE
|
|||
/* System Routines */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API TransformUpdateRoutine final: public SHSystemRoutine
|
||||
class SH_API TransformPostLogicUpdate final: public SHSystemRoutine
|
||||
{
|
||||
public:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
TransformUpdateRoutine ();
|
||||
~TransformUpdateRoutine () = default;
|
||||
TransformPostLogicUpdate ();
|
||||
~TransformPostLogicUpdate () = default;
|
||||
|
||||
TransformUpdateRoutine (const TransformUpdateRoutine&) = delete;
|
||||
TransformUpdateRoutine (TransformUpdateRoutine&&) = delete;
|
||||
TransformPostLogicUpdate (const TransformPostLogicUpdate&) = delete;
|
||||
TransformPostLogicUpdate (TransformPostLogicUpdate&&) = delete;
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
TransformUpdateRoutine& operator= (const TransformUpdateRoutine&) = delete;
|
||||
TransformUpdateRoutine& operator= (TransformUpdateRoutine&&) = delete;
|
||||
TransformPostLogicUpdate& operator= (const TransformPostLogicUpdate&) = 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 */
|
||||
|
@ -84,8 +111,11 @@ namespace SHADE
|
|||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
static void UpdateEntity (const SHSceneNode* node);
|
||||
static void UpdateTransform(SHTransformComponent& tf, const SHTransformComponent* parent = nullptr);
|
||||
SHEventHandle ChangeParent (SHEventPtr changeParentEvent);
|
||||
static void UpdateChildrenLocalTransforms (SHSceneNode* node);
|
||||
|
||||
static void UpdateEntity (const SHSceneNode* node, bool clearDirtyFlag);
|
||||
static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -38,6 +38,10 @@ namespace SHADE
|
|||
: 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
|
||||
: XMFLOAT4( xmfloat4.x, xmfloat4.y, xmfloat4.z, xmfloat4.w )
|
||||
{}
|
||||
|
@ -271,6 +275,11 @@ namespace SHADE
|
|||
return result;
|
||||
}
|
||||
|
||||
SHVec3 SHVec4::ToVec3() const noexcept
|
||||
{
|
||||
return SHVec3{ x, y, z };
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Static Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
// Project Headers
|
||||
#include "SH_API.h"
|
||||
#include "SHVec3.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -53,6 +54,7 @@ namespace SHADE
|
|||
~SHVec4 () = default;
|
||||
|
||||
SHVec4 () noexcept;
|
||||
SHVec4 (const SHVec3& vec3) noexcept;
|
||||
SHVec4 (const XMFLOAT4& xmfloat4) noexcept;
|
||||
SHVec4 (float x, float y, float z, float w) noexcept;
|
||||
|
||||
|
@ -103,15 +105,17 @@ namespace SHADE
|
|||
[[nodiscard]] SHVec4 Cross3D (const SHVec4& rhs) const noexcept;
|
||||
[[nodiscard]] SHVec4 Cross (const SHVec4& v1, const SHVec4& v2) const noexcept;
|
||||
|
||||
[[nodiscard]] SHVec3 ToVec3 () const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Static Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] static SHVec4 Normalise (const SHVec4& v) noexcept;
|
||||
[[nodiscard]] static SHVec4 Normalise3D (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 Max (const std::initializer_list<SHVec4>& vs) noexcept;
|
||||
[[nodiscard]] static SHVec4 Normalise (const SHVec4& v) noexcept;
|
||||
[[nodiscard]] static SHVec4 Normalise3D (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 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 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;
|
||||
|
|
|
@ -140,12 +140,12 @@ namespace SHADE
|
|||
isRigidBody = true;
|
||||
|
||||
rb->position = tf->GetWorldPosition();
|
||||
rb->orientation = tf->GetWorldRotation();
|
||||
rb->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation());
|
||||
|
||||
if (hasColliders)
|
||||
{
|
||||
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
|
||||
for (auto& collider : c->colliders | std::views::keys)
|
||||
AddCollider(&collider);
|
||||
|
@ -160,7 +160,7 @@ namespace SHADE
|
|||
hasColliders = true;
|
||||
|
||||
c->position = tf->GetWorldPosition();
|
||||
c->orientation = tf->GetWorldRotation();
|
||||
c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation());
|
||||
|
||||
for (auto& collider : c->colliders | std::views::keys)
|
||||
AddCollider(&collider);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
#include "Math/SHMathHelpers.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
|
||||
|
@ -315,7 +316,7 @@ namespace SHADE
|
|||
if (TF->HasChanged())
|
||||
{
|
||||
physicsObject.SetPosition(TF->GetWorldPosition());
|
||||
physicsObject.SetRotation(TF->GetWorldRotation());
|
||||
physicsObject.SetOrientation(TF->GetWorldOrientation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -492,8 +493,7 @@ namespace SHADE
|
|||
// Convert RP3D Transform to SHADE
|
||||
auto* tfComponent = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
|
||||
tfComponent->SetWorldPosition(rp3dPos);
|
||||
tfComponent->SetWorldRotation(SHQuaternion{ rp3dRot }.ToEuler());
|
||||
|
||||
tfComponent->SetWorldOrientation(SHQuaternion{ rp3dRot });
|
||||
|
||||
// Cache transforms
|
||||
physicsObject.prevTransform = CURRENT_TF;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
#include "Events/SHEventManager.hpp"
|
||||
#include "Tools/SHLogger.h"
|
||||
#include "Tools/SHException.h"
|
||||
|
||||
|
@ -317,6 +318,11 @@ namespace SHADE
|
|||
if (parentNode == nullptr)
|
||||
{
|
||||
SHLOG_WARNING("Removing Entity {}'s parent", entityID)
|
||||
|
||||
if (parent)
|
||||
parent->RemoveChild(this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 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)
|
||||
parent = root;
|
||||
|
||||
NODE_ITER->second->SetParent(parent);
|
||||
|
||||
SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT);
|
||||
}
|
||||
|
||||
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;
|
||||
currentNode->SetParent(PARENT_ITER->second);
|
||||
|
||||
SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -558,7 +582,7 @@ namespace SHADE
|
|||
ReleaseNode(node);
|
||||
}
|
||||
|
||||
void SHSceneGraph::Traverse (const UnaryPredicate& predicate) const
|
||||
void SHSceneGraph::Traverse (const UnaryFunction& predicate) const
|
||||
{
|
||||
TraverseAndInvokePredicate(root, predicate);
|
||||
}
|
||||
|
@ -597,7 +621,7 @@ namespace SHADE
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -97,9 +97,8 @@ namespace SHADE
|
|||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
using EntityNodeMap = std::unordered_map<EntityID, SHSceneNode*>;
|
||||
|
||||
using UnaryPredicate = std::function<void(SHSceneNode*)>;
|
||||
using EntityNodeMap = std::unordered_map<EntityID, SHSceneNode*>;
|
||||
using UnaryFunction = std::function<void(SHSceneNode*)>;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -143,8 +142,7 @@ namespace SHADE
|
|||
bool RemoveNode (SHSceneNode* nodeToRemove) noexcept;
|
||||
void Reset () noexcept;
|
||||
|
||||
void Traverse (const UnaryPredicate& predicate) const;
|
||||
|
||||
void Traverse (const UnaryFunction& predicate) const;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -160,8 +158,14 @@ namespace SHADE
|
|||
|
||||
SHSceneNode* AllocateNode (EntityID entityID);
|
||||
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
|
|
@ -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)
|
|
@ -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
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Standard Libraries
|
||||
|
|
Loading…
Reference in New Issue