diff --git a/Engine/Graphics/3DRenderer.cpp b/Engine/Graphics/3DRenderer.cpp index a3b2d4e..979449a 100644 --- a/Engine/Graphics/3DRenderer.cpp +++ b/Engine/Graphics/3DRenderer.cpp @@ -59,6 +59,14 @@ void Graphic3DRenderer::UpdateCamera(CAMERA_MOVE type, const float value) { case CAMERA_MOVE_FLY: mMainCamera->Fly(value); break; + + case CAMERA_MOVE_PITCH: + mMainCamera->Pitch(value); + break; + + case CAMERA_MOVE_YAW: + mMainCamera->Yaw(value); + break; default: break; diff --git a/Engine/Graphics/3DRenderer.hpp b/Engine/Graphics/3DRenderer.hpp index 242b8fd..2d81341 100644 --- a/Engine/Graphics/3DRenderer.hpp +++ b/Engine/Graphics/3DRenderer.hpp @@ -10,7 +10,9 @@ typedef enum eCameraMovementType { CAMERA_MOVE_WALK, CAMERA_MOVE_STRAFE, - CAMERA_MOVE_FLY + CAMERA_MOVE_FLY, + CAMERA_MOVE_PITCH, + CAMERA_MOVE_YAW } CAMERA_MOVE; class Graphic3DRenderer final { diff --git a/Engine/Graphics/Camera.cpp b/Engine/Graphics/Camera.cpp index 7c06acb..f546eda 100644 --- a/Engine/Graphics/Camera.cpp +++ b/Engine/Graphics/Camera.cpp @@ -60,4 +60,21 @@ void Camera::Fly(float d) { M3D_VECTOR u = M3D_V4LoadF3(&mUp); M3D_VECTOR p = M3D_V4LoadF3(&mPos); M3D_V4StoreF3(&mPos, M3D_V4MultiplyAdd(s, u, p)); +} + +void Camera::Pitch(float angle) { + // Rotate up and look vector about the right vector. + M3D_MATRIX R = M3D_TransformMatrixRotationAxis(M3D_V4LoadF3(&mRight), angle); + + M3D_V4StoreF3(&mUp, M3D_V3TransformNormal(M3D_V4LoadF3(&mUp), R)); + M3D_V4StoreF3(&mLook, M3D_V3TransformNormal(M3D_V4LoadF3(&mLook), R)); +} + +void Camera::Yaw(float angle) { + // Rotate the basis vectors about the world y-axis. + M3D_MATRIX R = M3D_TransformMatrixRotationY(angle); + + M3D_V4StoreF3(&mRight, M3D_V3TransformNormal(M3D_V4LoadF3(&mRight), R)); + M3D_V4StoreF3(&mUp, M3D_V3TransformNormal(M3D_V4LoadF3(&mUp), R)); + M3D_V4StoreF3(&mLook, M3D_V3TransformNormal(M3D_V4LoadF3(&mLook), R)); } \ No newline at end of file diff --git a/Engine/Graphics/Camera.hpp b/Engine/Graphics/Camera.hpp index 3ef8d70..8d824dd 100644 --- a/Engine/Graphics/Camera.hpp +++ b/Engine/Graphics/Camera.hpp @@ -32,11 +32,14 @@ public: void Walk(float d); void Fly(float d); + void Pitch(float angle); + void Yaw(float angle); + private: M3D_F4X4 mProjMat = M3D_MIdentity4x4(); M3D_F4X4 mViewMat = M3D_MIdentity4x4(); - M3D_F3 mPos = {1.5f, 1.5f, 1.5f}; + M3D_F3 mPos = {0.0f, 0.0f, 0.0f}; M3D_F3 mRight = {1.0f, 0.0f, 0.0f}; M3D_F3 mUp = {0.0f, 1.0f, 0.0f}; M3D_F3 mLook = {0.0f, 0.0f, 1.0f}; diff --git a/Engine/Utils/3DMaths.hpp b/Engine/Utils/3DMaths.hpp index b9e50a3..04f2ad1 100644 --- a/Engine/Utils/3DMaths.hpp +++ b/Engine/Utils/3DMaths.hpp @@ -164,6 +164,23 @@ struct __attribute__((aligned(16))) M3D_V4I32 { #endif }; +struct M3D_F2 { + float x; + float y; + + M3D_F2() = default; + + M3D_F2(const M3D_F2&) = default; + M3D_F2& operator=(const M3D_F2&) = default; + M3D_F2(M3D_F2&&) = default; + M3D_F2& operator=(M3D_F2&&) = default; + + constexpr M3D_F2(float _x, float _y) noexcept : x(_x), y(_y) {} +}; +struct __attribute__((aligned(16))) M3D_F2A : public M3D_F2 { + using M3D_F2::M3D_F2; +}; + struct M3D_F3 { float x; float y; @@ -489,10 +506,11 @@ M3D_VECTOR M3D_QRotationMatrix(M3D_MATRIX M) noexcept; M3D_VECTOR M3D_V3Rotate(M3D_VECTOR V, M3D_VECTOR RotationQuaternion) noexcept; M3D_VECTOR M3D_V3Transform(M3D_VECTOR V, M3D_MATRIX M) noexcept; void M3D_V3Transform(M3D_F4* pOutputStream, size_t OutputStride, const M3D_F3* pInputStream, size_t InputStride, size_t VectorCount, M3D_MATRIX M) noexcept; +M3D_VECTOR M3D_V3TransformNormal(M3D_VECTOR V, M3D_MATRIX M) noexcept; M3D_VECTOR M3D_V3TransformPersDiv(M3D_VECTOR V, M3D_MATRIX M) noexcept; void M3D_V3TransformPersDiv(M3D_F3* pOutputStream, size_t OutputStride, const M3D_F3* pInputStream, size_t InputStride, size_t VectorCount, M3D_MATRIX M) noexcept; M3D_VECTOR M3D_V4Transform(M3D_VECTOR V, M3D_MATRIX M) noexcept; -void M3D_V4Transform(M3D_F4* pOutputStream, size_t OutputStride, const M3D_F3* pInputStream, size_t InputStride, size_t VectorCount, M3D_MATRIX M) noexcept; +void M3D_V4Transform(M3D_F4* pOutputStream, size_t OutputStride, const M3D_F4* pInputStream, size_t InputStride, size_t VectorCount, M3D_MATRIX M) noexcept; M3D_VECTOR M3D_V3TransformNDCToViewport(M3D_VECTOR V, float vpX, float vpY, float vpW, float vpH, float vpMinZ, float vpMaxZ) noexcept; @@ -513,6 +531,8 @@ M3D_MATRIX M3D_TransformMatrixRotationX(float Angle) noexcept; M3D_MATRIX M3D_TransformMatrixRotationY(float Angle) noexcept; M3D_MATRIX M3D_TransformMatrixRotationZ(float Angle) noexcept; M3D_MATRIX M3D_TransformMatrixRotation(M3D_VECTOR Angles) noexcept; +M3D_MATRIX M3D_TransformMatrixRotationNormal(M3D_VECTOR NormalAxis, float Angle) noexcept; +M3D_MATRIX M3D_TransformMatrixRotationAxis(M3D_VECTOR axis, float angle) noexcept; M3D_MATRIX M3D_TransformMatrixViewport(float _w, float _h, float _wOffset, float _hOffset) noexcept; diff --git a/Engine/Utils/3DMaths_mat.inl b/Engine/Utils/3DMaths_mat.inl index a7d6256..cfd21d1 100644 --- a/Engine/Utils/3DMaths_mat.inl +++ b/Engine/Utils/3DMaths_mat.inl @@ -972,6 +972,28 @@ inline void M3D_V3Transform( #endif } +inline M3D_VECTOR M3D_V3TransformNormal(M3D_VECTOR V, M3D_MATRIX M) noexcept { +#ifdef DISABLE_INTRINSICS + M3D_VECTOR Z = M3D_V4SplatZ(V); + M3D_VECTOR Y = M3D_V4SplatY(V); + M3D_VECTOR X = M3D_V4SplatX(V); + + M3D_VECTOR Result = M3D_V4Multiply(Z, M.rows[2]); + Result = M3D_V4MultiplyAdd(Y, M.rows[1], Result); + Result = M3D_V4MultiplyAdd(X, M.rows[0], Result); + + return Result; +#else + M3D_VECTOR vResult = M3D_PERMUTE_PS(V, _MM_SHUFFLE(2, 2, 2, 2)); // Z + vResult = _mm_mul_ps(vResult, M.rows[2]); + M3D_VECTOR vTemp = M3D_PERMUTE_PS(V, _MM_SHUFFLE(1, 1, 1, 1)); // Y + vResult = M3D_FMADD_PS(vTemp, M.rows[1], vResult); + vTemp = M3D_PERMUTE_PS(V, _MM_SHUFFLE(0, 0, 0, 0)); // X + vResult = M3D_FMADD_PS(vTemp, M.rows[0], vResult); + return vResult; +#endif +} + inline M3D_VECTOR M3D_V3TransformPersDiv(M3D_VECTOR V, M3D_MATRIX M) noexcept { M3D_VECTOR Z = M3D_V4SplatZ(V); M3D_VECTOR Y = M3D_V4SplatY(V); @@ -1324,7 +1346,7 @@ inline M3D_VECTOR M3D_V4Transform(M3D_VECTOR V, M3D_MATRIX M) noexcept { #endif } -inline void M3D_V4Transform(M3D_F4* pOutputStream, size_t OutputStride, const M3D_F3* pInputStream, size_t InputStride, size_t VectorCount, M3D_MATRIX M) noexcept { +inline void M3D_V4Transform(M3D_F4* pOutputStream, size_t OutputStride, const M3D_F4* pInputStream, size_t InputStride, size_t VectorCount, M3D_MATRIX M) noexcept { auto pInputVector = reinterpret_cast(pInputStream); auto pOutputVector = reinterpret_cast(pOutputStream); @@ -1584,21 +1606,20 @@ inline M3D_MATRIX M3D_TransformMatrixCamLookAtRH(M3D_VECTOR viewPos, M3D_VECTOR inline M3D_MATRIX M3D_TransformMatrixCamLookToLH(M3D_VECTOR viewPos, M3D_VECTOR viewDirection, M3D_VECTOR upDirection) noexcept { // Keep viewer's axes orthogonal to each other and of unit length M3D_VECTOR look_normal = M3D_V3Normalize(viewDirection); - M3D_VECTOR up_norm = M3D_V3Cross(upDirection, look_normal); - up_norm = M3D_V3Normalize(up_norm); + M3D_VECTOR up_norm = M3D_V3Normalize(M3D_V3Cross(upDirection, look_normal)); // U, L already ortho-normal, so no need to normalize cross product M3D_VECTOR right_norm = M3D_V3Cross(look_normal, up_norm); M3D_VECTOR viewPos_n = M3D_V4Negate(viewPos); - M3D_VECTOR right_vec = M3D_V3Dot(up_norm, viewPos_n); - M3D_VECTOR up_vec = M3D_V3Dot(right_norm, viewPos_n); + M3D_VECTOR up_vec = M3D_V3Dot(up_norm, viewPos_n); + M3D_VECTOR right_vec = M3D_V3Dot(right_norm, viewPos_n); M3D_VECTOR look_vec = M3D_V3Dot(look_normal, viewPos_n); M3D_MATRIX ret; - ret.rows[0] = M3D_V4Select(right_vec, up_norm, M3D_MSelect1110.v); - ret.rows[1] = M3D_V4Select(up_vec, right_norm, M3D_MSelect1110.v); + ret.rows[0] = M3D_V4Select(up_vec, up_norm, M3D_MSelect1110.v); + ret.rows[1] = M3D_V4Select(right_vec, right_norm, M3D_MSelect1110.v); ret.rows[2] = M3D_V4Select(look_vec, look_normal, M3D_MSelect1110.v); ret.rows[3] = M3D_MIdentityR3.v; @@ -2061,6 +2082,88 @@ inline M3D_MATRIX M3D_TransformMatrixRotation(M3D_VECTOR Angles) noexcept { #endif } +inline M3D_MATRIX M3D_TransformMatrixRotationNormal(M3D_VECTOR NormalAxis, float Angle) noexcept { + float fSinAngle; + float fCosAngle; + M3D_ScalarSinCos(&fSinAngle, &fCosAngle, Angle); + +#ifdef DISABLE_INTRINSICS + M3D_VECTOR A = M3D_V4Set(fSinAngle, fCosAngle, 1.0f - fCosAngle, 0.0f); + + M3D_VECTOR C2 = M3D_V4SplatZ(A); + M3D_VECTOR C1 = M3D_V4SplatY(A); + M3D_VECTOR C0 = M3D_V4SplatX(A); + + M3D_VECTOR N0 = M3D_V4Swizzle(NormalAxis); + M3D_VECTOR N1 = M3D_V4Swizzle(NormalAxis); + + M3D_VECTOR V0 = M3D_V4Multiply(C2, N0); + V0 = M3D_V4Multiply(V0, N1); + + M3D_VECTOR R0 = M3D_V4Multiply(C2, NormalAxis); + R0 = M3D_V4MultiplyAdd(R0, NormalAxis, C1); + + M3D_VECTOR R1 = M3D_V4MultiplyAdd(C0, NormalAxis, V0); + M3D_VECTOR R2 = M3D_V4NegativeMultiplySubtract(C0, NormalAxis, V0); + + V0 = M3D_V4Select(A, R0, M3D_MSelect1110.v); + M3D_VECTOR V1 = M3D_V4Permute(R1, R2); + M3D_VECTOR V2 = M3D_V4Permute(R1, R2); + + M3D_MATRIX M; + M.rows[0] = M3D_V4Permute(V0, V1); + M.rows[1] = M3D_V4Permute(V0, V1); + M.rows[2] = M3D_V4Permute(V0, V2); + M.rows[3] = M3D_MIdentityR3.v; + return M; +#else + M3D_VECTOR C2 = _mm_set_ps1(1.0f - fCosAngle); + M3D_VECTOR C1 = _mm_set_ps1(fCosAngle); + M3D_VECTOR C0 = _mm_set_ps1(fSinAngle); + + M3D_VECTOR N0 = M3D_PERMUTE_PS(NormalAxis, _MM_SHUFFLE(3, 0, 2, 1)); + M3D_VECTOR N1 = M3D_PERMUTE_PS(NormalAxis, _MM_SHUFFLE(3, 1, 0, 2)); + + M3D_VECTOR V0 = _mm_mul_ps(C2, N0); + V0 = _mm_mul_ps(V0, N1); + + M3D_VECTOR R0 = _mm_mul_ps(C2, NormalAxis); + R0 = _mm_mul_ps(R0, NormalAxis); + R0 = _mm_add_ps(R0, C1); + + M3D_VECTOR R1 = _mm_mul_ps(C0, NormalAxis); + R1 = _mm_add_ps(R1, V0); + M3D_VECTOR R2 = _mm_mul_ps(C0, NormalAxis); + R2 = _mm_sub_ps(V0, R2); + + V0 = _mm_and_ps(R0, M3D_MMask3); + M3D_VECTOR V1 = _mm_shuffle_ps(R1, R2, _MM_SHUFFLE(2, 1, 2, 0)); + V1 = M3D_PERMUTE_PS(V1, _MM_SHUFFLE(0, 3, 2, 1)); + M3D_VECTOR V2 = _mm_shuffle_ps(R1, R2, _MM_SHUFFLE(0, 0, 1, 1)); + V2 = M3D_PERMUTE_PS(V2, _MM_SHUFFLE(2, 0, 2, 0)); + + R2 = _mm_shuffle_ps(V0, V1, _MM_SHUFFLE(1, 0, 3, 0)); + R2 = M3D_PERMUTE_PS(R2, _MM_SHUFFLE(1, 3, 2, 0)); + + M3D_MATRIX M; + M.rows[0] = R2; + + R2 = _mm_shuffle_ps(V0, V1, _MM_SHUFFLE(3, 2, 3, 1)); + R2 = M3D_PERMUTE_PS(R2, _MM_SHUFFLE(1, 3, 0, 2)); + M.rows[1] = R2; + + V2 = _mm_shuffle_ps(V2, V0, _MM_SHUFFLE(3, 2, 1, 0)); + M.rows[2] = V2; + M.rows[3] = M3D_MIdentityR3.v; + return M; +#endif +} + +inline M3D_MATRIX M3D_TransformMatrixRotationAxis(M3D_VECTOR axis, float angle) noexcept { + M3D_VECTOR nv = M3D_V3Normalize(axis); + return M3D_TransformMatrixRotationNormal(nv, angle); +} + //TODO: transform matrix is incomplete //v_tri[v_cnt].position.z = ((far+near)/2)+((far-near)/2)*_2dCoord.z; inline M3D_MATRIX M3D_TransformMatrixViewport(float _w, float _h, float _wOffset, float _hOffset) noexcept { diff --git a/Engine/Utils/3DMaths_vec.inl b/Engine/Utils/3DMaths_vec.inl index 6d83522..7e643ff 100644 --- a/Engine/Utils/3DMaths_vec.inl +++ b/Engine/Utils/3DMaths_vec.inl @@ -1071,7 +1071,7 @@ inline M3D_VECTOR M3D_V3Cross(M3D_VECTOR V1, M3D_VECTOR V2) noexcept { // y2,z2,x2,w2 vTemp2 = M3D_PERMUTE_PS(vTemp2, _MM_SHUFFLE(3, 1, 0, 2)); // Perform the right operation - vResult = M3D_FMADD_PS(vTemp1, vTemp2, vResult); + vResult = M3D_FNMADD_PS(vTemp1, vTemp2, vResult); // Set w to zero return _mm_and_ps(vResult, M3D_MMask3); #endif diff --git a/Game.cpp b/Game.cpp index 33c1a43..1b6b8a5 100644 --- a/Game.cpp +++ b/Game.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "Engine/Utils/Perfs.hpp" @@ -77,6 +78,19 @@ GAME_STATUS Game::Tick() { return GAME_QUIT; } +void Game::EventMouseMoved(int _x, int _y) { + if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) { + float dx = M3D_Deg2Rad(0.25f * static_cast(_x - mPrevMousePos.x)); + float dy = M3D_Deg2Rad(0.25f * static_cast(_y - mPrevMousePos.y)); + + mWorld3D->UpdateCamera(CAMERA_MOVE_PITCH, dy); + mWorld3D->UpdateCamera(CAMERA_MOVE_YAW, dx); + } + + mPrevMousePos.x = _x; + mPrevMousePos.y = _y; +} + void Game::Update() { // Refresh keyboard inputs KeyboardInputsCheck(); diff --git a/Game.hpp b/Game.hpp index 1586911..d8b096b 100644 --- a/Game.hpp +++ b/Game.hpp @@ -30,6 +30,7 @@ public: Game& operator= (Game const&) = delete; GAME_STATUS Tick(); + void EventMouseMoved(int _x, int _y); private: Game(std::shared_ptr mainWnd, bool dbgFlag) noexcept(false); @@ -51,4 +52,6 @@ private: std::unique_ptr mCockpitUI; std::unique_ptr mWorldUI; + sf::Vector2i mPrevMousePos = {0, 0}; + }; \ No newline at end of file diff --git a/ProtoTank.cpp b/ProtoTank.cpp index 4458d87..3612500 100644 --- a/ProtoTank.cpp +++ b/ProtoTank.cpp @@ -46,7 +46,7 @@ int main(int argc, char** argv) { // pause(); // break; - //if (event.type == sf::Event::GainedFocus) + //case sf::Event::GainedFocus: // resume(); // break; @@ -58,7 +58,7 @@ int main(int argc, char** argv) { if (mainWindow->hasFocus()) { switch (event.type) { case sf::Event::MouseMoved: - //if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) + arcadeGame.EventMouseMoved(event.mouseMove.x, event.mouseMove.y); break; default: