diff --git a/.gitignore b/.gitignore index 5b6cd5e..2a2e8c7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *~ *.3dsx *.elf +*.exe *.smdh *.tar.bz2 Thumbs.db diff --git a/include/c3d/maths.h b/include/c3d/maths.h index 21050fc..b3aade8 100644 --- a/include/c3d/maths.h +++ b/include/c3d/maths.h @@ -8,12 +8,19 @@ /// The one true circumference-to-radius ratio #define M_TAU (2*M_PI) +/** + * @brief Convert an angle from revolutions to radians + * @param[in] _angle Proportion of a full revolution + * @return Angle in radians + */ +#define C3D_Angle(_angle) ((_angle)*M_TAU) + /** * @brief Convert an angle from degrees to radians * @param[in] _angle Angle in degrees * @return Angle in radians */ -#define C3D_Angle(_angle) ((_angle)*M_TAU) +#define C3D_AngleFromDegrees(_angle) ((_angle)*M_TAU/360.0f) #define C3D_AspectRatioTop (400.0f / 240.0f) ///< Aspect ratio for 3DS top screen #define C3D_AspectRatioBot (320.0f / 240.0f) ///< Aspect ratio for 3DS bottom screen @@ -81,6 +88,17 @@ static inline C3D_FVec FVec4_Scale(C3D_FVec v, float s) return FVec4_New(v.x*s, v.y*s, v.z*s, v.w*s); } +/** + * @brief Perspective divide + * @param[in] v Vector to divide + * @return v/v.w + */ +static inline C3D_FVec FVec4_PerspDivide(C3D_FVec v) +{ + // divide by w + return FVec4_New(v.x/v.w, v.y/v.w, v.z/v.w, 1.0f); +} + /** * @brief Dot product of two FVec4s * @param[in] lhs Left-side FVec4 @@ -383,24 +401,26 @@ void Mtx_RotateZ(C3D_Mtx* mtx, float angle, bool bRightSide); /** * @brief Orthogonal projection * @param[out] mtx Output matrix - * @param[in] left Left clip plane (X=left) - * @param[in] right Right clip plane (X=right) - * @param[in] bottom Bottom clip plane (Y=bottom) - * @param[in] top Top clip plane (Y=top) - * @param[in] near Near clip plane (Z=near) - * @param[in] far Far clip plane (Z=far) + * @param[in] left Left clip plane (X=left) + * @param[in] right Right clip plane (X=right) + * @param[in] bottom Bottom clip plane (Y=bottom) + * @param[in] top Top clip plane (Y=top) + * @param[in] near Near clip plane (Z=near) + * @param[in] far Far clip plane (Z=far) + * @param[in] isLeftHanded Whether to build a LH projection */ -void Mtx_Ortho(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far); +void Mtx_Ortho(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded); /** * @brief Perspective projection - * @param[out] mtx Output matrix - * @param[in] fovy Vertical field of view in radians - * @param[in] aspect Aspect ration of projection plane (width/height) - * @param[in] near Near clip plane (Z=near) - * @param[in] far Far clip plane (Z=far) + * @param[out] mtx Output matrix + * @param[in] fovy Vertical field of view in radians + * @param[in] aspect Aspect ration of projection plane (width/height) + * @param[in] near Near clip plane (Z=near) + * @param[in] far Far clip plane (Z=far) + * @param[in] isLeftHanded Whether to build a LH projection */ -void Mtx_Persp(C3D_Mtx* mtx, float fovy, float aspect, float near, float far); +void Mtx_Persp(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, bool isLeftHanded); /** * @brief Stereo perspective projection @@ -410,49 +430,53 @@ void Mtx_Persp(C3D_Mtx* mtx, float fovy, float aspect, float near, float far); * they will appear to be inside the screen. If objects are closer than this, * they will appear to pop out of the screen. Objects at this distance appear * to be at the screen. - * @param[out] mtx Output matrix - * @param[in] fovy Vertical field of view in radians - * @param[in] aspect Aspect ration of projection plane (width/height) - * @param[in] near Near clip plane (Z=near) - * @param[in] far Far clip plane (Z=far) - * @param[in] iod Interocular distance - * @param[in] screen Focal length + * @param[out] mtx Output matrix + * @param[in] fovy Vertical field of view in radians + * @param[in] aspect Aspect ration of projection plane (width/height) + * @param[in] near Near clip plane (Z=near) + * @param[in] far Far clip plane (Z=far) + * @param[in] iod Interocular distance + * @param[in] screen Focal length + * @param[in] isLeftHanded Whether to build a LH projection */ -void Mtx_PerspStereo(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, float iod, float screen); +void Mtx_PerspStereo(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, float iod, float screen, bool isLeftHanded); /** * @brief Orthogonal projection, tilted to account for the 3DS screen rotation - * @param[in] left Left clip plane (X=left) - * @param[in] right Right clip plane (X=right) - * @param[in] bottom Bottom clip plane (Y=bottom) - * @param[in] top Top clip plane (Y=top) - * @param[in] near Near clip plane (Z=near) - * @param[in] far Far clip plane (Z=far) + * @param[in] left Left clip plane (X=left) + * @param[in] right Right clip plane (X=right) + * @param[in] bottom Bottom clip plane (Y=bottom) + * @param[in] top Top clip plane (Y=top) + * @param[in] near Near clip plane (Z=near) + * @param[in] far Far clip plane (Z=far) + * @param[in] isLeftHanded Whether to build a LH projection */ -void Mtx_OrthoTilt(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far); +void Mtx_OrthoTilt(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded); /** * @brief Perspective projection, tilted to account for the 3DS screen rotation - * @param[out] mtx Output matrix - * @param[in] fovy Vertical field of view in radians - * @param[in] aspect Aspect ration of projection plane (width/height) - * @param[in] near Near clip plane (Z=near) - * @param[in] far Far clip plane (Z=far) + * @param[out] mtx Output matrix + * @param[in] fovy Vertical field of view in radians + * @param[in] aspect Aspect ration of projection plane (width/height) + * @param[in] near Near clip plane (Z=near) + * @param[in] far Far clip plane (Z=far) + * @param[in] isLeftHanded Whether to build a LH projection */ -void Mtx_PerspTilt(C3D_Mtx* mtx, float fovy, float aspect, float near, float far); +void Mtx_PerspTilt(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, bool isLeftHanded); /** * @brief Stereo perspective projection, tilted to account for the 3DS screen rotation * @note See the notes for Mtx_PerspStereo - * @param[out] mtx Output matrix - * @param[in] fovy Vertical field of view in radians - * @param[in] aspect Aspect ration of projection plane (width/height) - * @param[in] near Near clip plane (Z=near) - * @param[in] far Far clip plane (Z=far) - * @param[in] iod Interocular distance - * @param[in] screen Focal length + * @param[out] mtx Output matrix + * @param[in] fovy Vertical field of view in radians + * @param[in] aspect Aspect ration of projection plane (width/height) + * @param[in] near Near clip plane (Z=near) + * @param[in] far Far clip plane (Z=far) + * @param[in] iod Interocular distance + * @param[in] screen Focal length + * @param[in] isLeftHanded Whether to build a LH projection */ -void Mtx_PerspStereoTilt(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, float iod, float screen); +void Mtx_PerspStereoTilt(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, float iod, float screen, bool isLeftHanded); /** * @brief Left-handed Look-At matrix, using DirectX implementation diff --git a/source/maths/mtx_ortho.c b/source/maths/mtx_ortho.c index 3a2ea75..ba27fb5 100644 --- a/source/maths/mtx_ortho.c +++ b/source/maths/mtx_ortho.c @@ -1,6 +1,6 @@ #include -void Mtx_Ortho(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far) +void Mtx_Ortho(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded) { Mtx_Zeros(mtx); @@ -11,7 +11,10 @@ void Mtx_Ortho(C3D_Mtx* mtx, float left, float right, float bottom, float top, f mtx->r[0].w = (left + right) / (left - right); mtx->r[1].y = 2.0f / (top - bottom); mtx->r[1].w = (bottom + top) / (bottom - top); - mtx->r[2].z = 1.0f / (far - near); + if (isLeftHanded) + mtx->r[2].z = 1.0f / (far - near); + else + mtx->r[2].z = 1.0f / (near - far); mtx->r[2].w = 0.5f*(near + far) / (near - far) - 0.5f; mtx->r[3].w = 1.0f; } diff --git a/source/maths/mtx_orthotilt.c b/source/maths/mtx_orthotilt.c index b695ed3..8ebcf3c 100644 --- a/source/maths/mtx_orthotilt.c +++ b/source/maths/mtx_orthotilt.c @@ -1,6 +1,6 @@ #include -void Mtx_OrthoTilt(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far) +void Mtx_OrthoTilt(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded) { Mtx_Zeros(mtx); @@ -12,7 +12,10 @@ void Mtx_OrthoTilt(C3D_Mtx* mtx, float left, float right, float bottom, float to mtx->r[0].w = (bottom + top) / (bottom - top); mtx->r[1].x = 2.0f / (left - right); mtx->r[1].w = (left + right) / (right - left); - mtx->r[2].z = 1.0f / (far - near); + if (isLeftHanded) + mtx->r[2].z = 1.0f / (far - near); + else + mtx->r[2].z = 1.0f / (near - far); mtx->r[2].w = 0.5f*(near + far) / (near - far) - 0.5f; mtx->r[3].w = 1.0f; } diff --git a/source/maths/mtx_persp.c b/source/maths/mtx_persp.c index d7f7b30..a07a6c2 100644 --- a/source/maths/mtx_persp.c +++ b/source/maths/mtx_persp.c @@ -1,6 +1,6 @@ #include -void Mtx_Persp(C3D_Mtx* mtx, float fovy, float aspect, float near, float far) +void Mtx_Persp(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, bool isLeftHanded) { float fovy_tan = tanf(fovy/2.0f); @@ -11,7 +11,16 @@ void Mtx_Persp(C3D_Mtx* mtx, float fovy, float aspect, float near, float far) mtx->r[0].x = 1.0f / (aspect * fovy_tan); mtx->r[1].y = 1.0f / fovy_tan; - mtx->r[2].z = 0.5f*(far + near) / (near - far) + 0.5f; mtx->r[2].w = far*near / (near - far); - mtx->r[3].z = -1.0f; + + if (isLeftHanded) + { + mtx->r[2].z = 0.5f*(far + near) / (far - near) - 0.5f; + mtx->r[3].z = 1.0f; + } + else + { + mtx->r[2].z = 0.5f*(far + near) / (near - far) + 0.5f; + mtx->r[3].z = -1.0f; + } } diff --git a/source/maths/mtx_perspstereo.c b/source/maths/mtx_perspstereo.c index 6e3778d..74e6f77 100644 --- a/source/maths/mtx_perspstereo.c +++ b/source/maths/mtx_perspstereo.c @@ -1,6 +1,6 @@ #include -void Mtx_PerspStereo(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, float iod, float screen) +void Mtx_PerspStereo(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, float iod, float screen, bool isLeftHanded) { float fovy_tan = tanf(fovy/2.0f); float fovy_tan_aspect = fovy_tan*aspect; @@ -9,10 +9,20 @@ void Mtx_PerspStereo(C3D_Mtx* mtx, float fovy, float aspect, float near, float f Mtx_Zeros(mtx); mtx->r[0].x = 1.0f / fovy_tan_aspect; - mtx->r[0].z = -shift / fovy_tan_aspect; mtx->r[0].w = -iod / 2.0f; mtx->r[1].y = 1.0f / fovy_tan; - mtx->r[2].z = 0.5f*(near + far) / (near - far) + 0.5f; mtx->r[2].w = near * far / (near - far); - mtx->r[3].z = -1.0f; + + if (isLeftHanded) + { + mtx->r[0].z = shift / fovy_tan_aspect; + mtx->r[2].z = 0.5f*(near + far) / (far - near) - 0.5f; + mtx->r[3].z = 1.0f; + } + else + { + mtx->r[0].z = -shift / fovy_tan_aspect; + mtx->r[2].z = 0.5f*(near + far) / (near - far) + 0.5f; + mtx->r[3].z = -1.0f; + } } diff --git a/source/maths/mtx_perspstereotilt.c b/source/maths/mtx_perspstereotilt.c index 72c08c4..b74da90 100644 --- a/source/maths/mtx_perspstereotilt.c +++ b/source/maths/mtx_perspstereotilt.c @@ -1,6 +1,6 @@ #include -void Mtx_PerspStereoTilt(C3D_Mtx* mtx, float fovx, float invaspect, float near, float far, float iod, float screen) +void Mtx_PerspStereoTilt(C3D_Mtx* mtx, float fovx, float invaspect, float near, float far, float iod, float screen, bool isLeftHanded) { // Notes: // Once again, we are passed "fovy" and the "aspect ratio"; however the 3DS screens are sideways, @@ -15,9 +15,19 @@ void Mtx_PerspStereoTilt(C3D_Mtx* mtx, float fovx, float invaspect, float near, mtx->r[0].y = 1.0f / fovx_tan; mtx->r[1].x = -1.0f / fovx_tan_invaspect; - mtx->r[1].z = shift / fovx_tan_invaspect; mtx->r[1].w = iod / 2.0f; - mtx->r[2].z = 0.5f*(near + far) / (near - far) + 0.5f; mtx->r[2].w = near * far / (near - far); - mtx->r[3].z = -1.0f; + + if (isLeftHanded) + { + mtx->r[1].z = -shift / fovx_tan_invaspect; + mtx->r[2].z = 0.5f*(near + far) / (far - near) - 0.5f; + mtx->r[3].z = 1.0f; + } + else + { + mtx->r[1].z = shift / fovx_tan_invaspect; + mtx->r[2].z = 0.5f*(near + far) / (near - far) + 0.5f; + mtx->r[3].z = -1.0f; + } } diff --git a/source/maths/mtx_persptilt.c b/source/maths/mtx_persptilt.c index e6b260b..b3ea9e9 100644 --- a/source/maths/mtx_persptilt.c +++ b/source/maths/mtx_persptilt.c @@ -1,6 +1,6 @@ #include -void Mtx_PerspTilt(C3D_Mtx* mtx, float fovx, float invaspect, float near, float far) +void Mtx_PerspTilt(C3D_Mtx* mtx, float fovx, float invaspect, float near, float far, bool isLeftHanded) { // Notes: // We are passed "fovy" and the "aspect ratio". However, the 3DS screens are sideways, @@ -31,7 +31,16 @@ void Mtx_PerspTilt(C3D_Mtx* mtx, float fovx, float invaspect, float near, float mtx->r[0].y = 1.0f / fovx_tan; mtx->r[1].x = -1.0f / (fovx_tan*invaspect); - mtx->r[2].z = 0.5f*(far + near) / (near - far) + 0.5f; mtx->r[2].w = far*near / (near - far); - mtx->r[3].z = -1.0f; + + if (isLeftHanded) + { + mtx->r[2].z = 0.5f*(far + near) / (far - near) - 0.5f; + mtx->r[3].z = 1.0f; + } + else + { + mtx->r[2].z = 0.5f*(far + near) / (near - far) + 0.5f; + mtx->r[3].z = -1.0f; + } } diff --git a/test/3ds/source/main.cpp b/test/3ds/source/main.cpp index ec8f7f5..decdebd 100644 --- a/test/3ds/source/main.cpp +++ b/test/3ds/source/main.cpp @@ -197,7 +197,7 @@ void persp_tilt_test() C3D_RenderTargetSetClear(top, C3D_CLEAR_ALL, CLEAR_COLOR, 0); C3D_RenderTargetSetOutput(top, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); - Mtx_PerspTilt(&projection, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f); + Mtx_PerspTilt(&projection, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, false); Mtx_Identity(&modelView); Mtx_Translate(&modelView, x, y, z, true); @@ -286,7 +286,7 @@ void ortho_tilt_test() C3D_RenderTargetSetClear(top, C3D_CLEAR_ALL, CLEAR_COLOR, 0); C3D_RenderTargetSetOutput(top, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); - Mtx_OrthoTilt(&projection, 0.0f, 400.0f, 0.0f, 240.0f, 100.0f, -100.0f); + Mtx_OrthoTilt(&projection, 0.0f, 400.0f, 0.0f, 240.0f, 100.0f, -100.0f, false); Mtx_Identity(&texView); @@ -380,8 +380,8 @@ void stereo_tilt_test() C3D_RenderTargetSetOutput(topLeft, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); C3D_RenderTargetSetOutput(topRight, GFX_TOP, GFX_RIGHT, DISPLAY_TRANSFER_FLAGS); - Mtx_PerspStereoTilt(&projLeft, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, -iod, focLen); - Mtx_PerspStereoTilt(&projRight, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, iod, focLen); + Mtx_PerspStereoTilt(&projLeft, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, -iod, focLen, false); + Mtx_PerspStereoTilt(&projRight, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, iod, focLen, false); Mtx_Identity(&texView); @@ -446,8 +446,8 @@ void stereo_tilt_test() std::printf("(Y/A) focLen %.1f\n", focLen); std::printf("(3D Slider) iod %.1f\n", iod); - Mtx_PerspStereoTilt(&projLeft, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, -iod, focLen); - Mtx_PerspStereoTilt(&projRight, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, iod, focLen); + Mtx_PerspStereoTilt(&projLeft, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, -iod, focLen, false); + Mtx_PerspStereoTilt(&projRight, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, iod, focLen, false); } Mtx_Identity(&modelView); @@ -499,12 +499,12 @@ void persp_test() C3D_RenderTargetSetClear(tex, C3D_CLEAR_ALL, CLEAR_COLOR, 0); C3D_TexSetFilter(&tex->renderBuf.colorBuf, GPU_LINEAR, GPU_NEAREST); - Mtx_Persp(&projTex, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f); + Mtx_Persp(&projTex, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, false); Mtx_Identity(&modelView); Mtx_Translate(&modelView, x, y, z, true); - Mtx_OrthoTilt(&projTop, -0.5f, 0.5f, -0.5f, 0.5f, 100.0f, -100.0f); + Mtx_OrthoTilt(&projTop, -0.5f, 0.5f, -0.5f, 0.5f, 100.0f, -100.0f, false); Mtx_Identity(&texView); C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_modelView, &modelView); @@ -553,7 +553,7 @@ void persp_test() std::printf("(UP/DOWN) y %.1f\n", y); std::printf("(L/R) z %.1f\n", z); - Mtx_Persp(&projTex, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f); + Mtx_Persp(&projTex, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, false); } Mtx_Identity(&modelView); @@ -615,13 +615,13 @@ void stereo_test() C3D_TexSetFilter(&texLeft->renderBuf.colorBuf, GPU_LINEAR, GPU_NEAREST); C3D_TexSetFilter(&texRight->renderBuf.colorBuf, GPU_LINEAR, GPU_NEAREST); - Mtx_PerspStereo(&projLeft, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, -iod, focLen); - Mtx_PerspStereo(&projRight, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, iod, focLen); + Mtx_PerspStereo(&projLeft, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, -iod, focLen, false); + Mtx_PerspStereo(&projRight, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, iod, focLen, false); Mtx_Identity(&modelView); Mtx_Translate(&modelView, x, y, z, true); - Mtx_OrthoTilt(&proj, -0.5f, 0.5f, -0.5f, 0.5f, 100.0f, -100.0f); + Mtx_OrthoTilt(&proj, -0.5f, 0.5f, -0.5f, 0.5f, 100.0f, -100.0f, false); Mtx_Identity(&texView); C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_modelView, &modelView); @@ -683,8 +683,8 @@ void stereo_test() std::printf("(Y/A) focLen %.1f\n", focLen); std::printf("(3D Slider) iod %.1f\n", iod); - Mtx_PerspStereo(&projLeft, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, -iod, focLen); - Mtx_PerspStereo(&projRight, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, iod, focLen); + Mtx_PerspStereo(&projLeft, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, -iod, focLen, false); + Mtx_PerspStereo(&projRight, 60.0f*M_TAU/360.0f, 400.0f/240.0f, 1.0f, 10.0f, iod, focLen, false); } Mtx_Identity(&modelView); @@ -753,12 +753,12 @@ void ortho_test() C3D_RenderTargetSetClear(tex, C3D_CLEAR_ALL, CLEAR_COLOR, 0); C3D_TexSetFilter(&tex->renderBuf.colorBuf, GPU_LINEAR, GPU_NEAREST); - Mtx_Ortho(&projTex, 0.0f, 400.0f, 0.0f, 240.0f, 100.0f, -100.0f); + Mtx_Ortho(&projTex, 0.0f, 400.0f, 0.0f, 240.0f, 100.0f, -100.0f, false); Mtx_Identity(&modelView); Mtx_Translate(&modelView, x, y, z, true); - Mtx_OrthoTilt(&projTop, -0.5f, 0.5f, -0.5f, 0.5f, 100.0f, -100.0f); + Mtx_OrthoTilt(&projTop, -0.5f, 0.5f, -0.5f, 0.5f, 100.0f, -100.0f, false); Mtx_Identity(&texView); C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_modelView, &modelView); diff --git a/test/pc/Makefile b/test/pc/Makefile index 593678c..013d670 100644 --- a/test/pc/Makefile +++ b/test/pc/Makefile @@ -2,8 +2,9 @@ TARGET := test CFILES := $(wildcard *.c) $(wildcard ../../source/maths/*.c) CXXFILES := $(wildcard *.cpp) -OFILES := $(CXXFILES:.cpp=.o) $(CFILES:.c=.o) -DFILES := $(wildcard *.d) $(wildcard ../../source/maths/*.d) +OFILES := $(addprefix build/,$(CXXFILES:.cpp=.o)) \ + $(patsubst ../../source/maths/%,build/%,$(CFILES:.c=.o)) +DFILES := $(wildcard build/*.d) CFLAGS := -Wall -g -pipe -I../../include CXXFLAGS := $(CFLAGS) -std=gnu++11 -DGLM_FORCE_RADIANS @@ -17,15 +18,20 @@ $(TARGET): $(OFILES) @echo "Linking $@" $(CXX) -o $@ $^ $(LDFLAGS) -%.o : %.cpp $(wildcard *.h) - @echo "Compiling $@" - @$(CXX) -o $@ -c $< $(CXXFLAGS) -MMD -MP -MF $*.d +$(OFILES): | build -%.o : %.c $(wildcard *.h) +build: + @[ -d build ] || mkdir build + +build/%.o : %.cpp $(wildcard *.h) @echo "Compiling $@" - @$(CC) -o $@ -c $< $(CFLAGS) -MMD -MP -MF $*.d + @$(CXX) -o $@ -c $< $(CXXFLAGS) -MMD -MP -MF build/$*.d + +build/%.o : ../../source/maths/%.c $(wildcard *.h) + @echo "Compiling $@" + @$(CC) -o $@ -c $< $(CFLAGS) -MMD -MP -MF build/$*.d clean: - $(RM) $(OFILES) $(DFILES) $(TARGET) + $(RM) -r $(TARGET) build/ -include $(DFILES) diff --git a/test/pc/main.cpp b/test/pc/main.cpp index 0a50c5a..79dd498 100644 --- a/test/pc/main.cpp +++ b/test/pc/main.cpp @@ -207,6 +207,7 @@ print(const glm::quat &q) static const glm::vec3 x_axis(1.0f, 0.0f, 0.0f); static const glm::vec3 y_axis(0.0f, 1.0f, 0.0f); static const glm::vec3 z_axis(0.0f, 0.0f, 1.0f); +static const glm::vec3 z_flip(1.0f, 1.0f, -1.0f); static void check_matrix(generator_t &gen, distribution_t &dist) @@ -225,6 +226,52 @@ check_matrix(generator_t &gen, distribution_t &dist) assert(m == glm::mat4()); } + // ortho nominal cases + { + C3D_Mtx m; + C3D_FVec v; + float l = 0.0f, + r = 400.0f, + b = 0.0f, + t = 320.0f, + n = 0.0f, + f = 100.0f; + + Mtx_Ortho(&m, l, r, b, t, n, f, false); + + // check near clip plane + v = Mtx_MultiplyFVecH(&m, FVec3_New((r-l)/2.0f, (t-b)/2.0f, -n)); + v = FVec4_PerspDivide(v); + assert(v == FVec4_New(0.0f, 0.0f, -1.0f, 1.0f)); + + // check far clip plane + v = Mtx_MultiplyFVecH(&m, FVec3_New((r-l)/2.0f, (t-b)/2.0f, -f)); + v = FVec4_PerspDivide(v); + assert(v == FVec4_New(0.0f, 0.0f, 0.0f, 1.0f)); + } + + // perspective nominal cases + { + C3D_Mtx m; + C3D_FVec v; + float fovy = C3D_Angle(60.0f/360.0f), + aspect = C3D_AspectRatioTop, + near = 0.1f, + far = 10.0f; + + Mtx_Persp(&m, fovy, aspect, near, far, false); + + // check near clip plane + v = Mtx_MultiplyFVecH(&m, FVec3_New(0.0f, 0.0f, -near)); + v = FVec4_PerspDivide(v); + assert(v == FVec4_New(0.0f, 0.0f, -1.0f, 1.0f)); + + // check far clip plane + v = Mtx_MultiplyFVecH(&m, FVec3_New(0.0f, 0.0f, -far)); + v = FVec4_PerspDivide(v); + assert(v == FVec4_New(0.0f, 0.0f, 0.0f, 1.0f)); + } + for(size_t x = 0; x < 10000; ++x) { // check inverse @@ -270,11 +317,15 @@ check_matrix(generator_t &gen, distribution_t &dist) while(std::abs(far - near) < 0.1f) far = dist(gen); - Mtx_Persp(&m, fovy, aspect, near, far); - + // RH + Mtx_Persp(&m, fovy, aspect, near, far, false); glm::mat4 g = glm::perspective(fovy, aspect, near, far); - assert(m == fix_depth*g); + + // LH + Mtx_Persp(&m, fovy, aspect, near, far, true); + g = glm::perspective(fovy, aspect, near, far); + assert(m == fix_depth*glm::scale(g, z_flip)); } // check perspective tilt @@ -300,11 +351,15 @@ check_matrix(generator_t &gen, distribution_t &dist) while(std::abs(far - near) < 0.1f) far = dist(gen); - Mtx_PerspTilt(&m, fovy, aspect, near, far); - + // RH + Mtx_PerspTilt(&m, fovy, aspect, near, far, false); glm::mat4 g = glm::perspective(fovx, 1.0f / aspect, near, far); - assert(m == fix_depth*g*tilt); + + // LH + Mtx_PerspTilt(&m, fovy, aspect, near, far, true); + g = glm::perspective(fovx, 1.0f / aspect, near, far); + assert(m == fix_depth*glm::scale(g, z_flip)*tilt); } // check perspective stereo @@ -336,9 +391,6 @@ check_matrix(generator_t &gen, distribution_t &dist) while(focLen < 0.25f) focLen = dist(gen); - Mtx_PerspStereo(&left, fovy, aspect, near, far, -iod, focLen); - Mtx_PerspStereo(&right, fovy, aspect, near, far, iod, focLen); - glm::mat4 g = glm::perspective(fovy, aspect, near, far); fovy_tan = tanf(fovy/2.0f); @@ -351,8 +403,17 @@ check_matrix(generator_t &gen, distribution_t &dist) -iod/(focLen*2.0f), 0.0f, 1.0f, 0.0f, -iod*fovy_tan*aspect/2.0f, 0.0f, 0.0f, 1.0f); + // RH + Mtx_PerspStereo(&left, fovy, aspect, near, far, -iod, focLen, false); + Mtx_PerspStereo(&right, fovy, aspect, near, far, iod, focLen, false); assert(left == fix_depth*g*left_eye); assert(right == fix_depth*g*right_eye); + + // LH + Mtx_PerspStereo(&left, fovy, aspect, near, far, -iod, focLen, true); + Mtx_PerspStereo(&right, fovy, aspect, near, far, iod, focLen, true); + assert(left == fix_depth*glm::scale(g*left_eye, z_flip)); + assert(right == fix_depth*glm::scale(g*right_eye, z_flip)); } // check perspective stereo tilt @@ -384,9 +445,6 @@ check_matrix(generator_t &gen, distribution_t &dist) while(focLen < 0.25f) focLen = dist(gen); - Mtx_PerspStereoTilt(&left, fovy, aspect, near, far, -iod, focLen); - Mtx_PerspStereoTilt(&right, fovy, aspect, near, far, iod, focLen); - glm::mat4 g = glm::perspective(fovx, 1.0f / aspect, near, far); fovx_tan = tanf(fovx/2.0f); @@ -399,8 +457,17 @@ check_matrix(generator_t &gen, distribution_t &dist) 0.0f, iod/(focLen*2.0f), 1.0f, 0.0f, 0.0f, iod*fovx_tan/2.0f, 0.0f, 1.0f); + // RH + Mtx_PerspStereoTilt(&left, fovy, aspect, near, far, -iod, focLen, false); + Mtx_PerspStereoTilt(&right, fovy, aspect, near, far, iod, focLen, false); assert(left == fix_depth*g*left_eye*tilt); assert(right == fix_depth*g*right_eye*tilt); + + // LH + Mtx_PerspStereoTilt(&left, fovy, aspect, near, far, -iod, focLen, true); + Mtx_PerspStereoTilt(&right, fovy, aspect, near, far, iod, focLen, true); + assert(left == fix_depth*glm::scale(g*left_eye, z_flip)*tilt); + assert(right == fix_depth*glm::scale(g*right_eye, z_flip)*tilt); } // check ortho @@ -422,11 +489,15 @@ check_matrix(generator_t &gen, distribution_t &dist) while(std::abs(f-n) < 0.1f) f = dist(gen); - Mtx_Ortho(&m, l, r, b, t, n, f); - + // RH + Mtx_Ortho(&m, l, r, b, t, n, f, false); glm::mat4 g = glm::ortho(l, r, b, t, n, f); - assert(m == fix_depth*g); + + // LH + Mtx_Ortho(&m, l, r, b, t, n, f, true); + g = glm::ortho(l, r, b, t, n, f); + assert(m == fix_depth*glm::scale(g, z_flip)); } // check ortho tilt @@ -448,11 +519,15 @@ check_matrix(generator_t &gen, distribution_t &dist) while(std::abs(f-n) < 0.1f) f = dist(gen); - Mtx_OrthoTilt(&m, l, r, b, t, n, f); - + // RH + Mtx_OrthoTilt(&m, l, r, b, t, n, f, false); glm::mat4 g = glm::ortho(l, r, b, t, n, f); - assert(m == tilt*fix_depth*g); + + // LH + Mtx_OrthoTilt(&m, l, r, b, t, n, f, true); + g = glm::ortho(l, r, b, t, n, f); + assert(m == tilt*fix_depth*glm::scale(g, z_flip)); } // check multiply