More additions and enhancements to math code, see details (#19)

Added C3D_AngleFromDegrees
Added FVec4_PerspDivide
Added LH option for projections
This commit is contained in:
mtheall 2016-08-04 14:23:28 -05:00 committed by fincs
parent dde8877f38
commit dc4d81eea9
11 changed files with 253 additions and 103 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
*~
*.3dsx
*.elf
*.exe
*.smdh
*.tar.bz2
Thumbs.db

View File

@ -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

View File

@ -1,6 +1,6 @@
#include <c3d/maths.h>
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;
}

View File

@ -1,6 +1,6 @@
#include <c3d/maths.h>
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;
}

View File

@ -1,6 +1,6 @@
#include <c3d/maths.h>
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;
}
}

View File

@ -1,6 +1,6 @@
#include <c3d/maths.h>
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;
}
}

View File

@ -1,6 +1,6 @@
#include <c3d/maths.h>
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;
}
}

View File

@ -1,6 +1,6 @@
#include <c3d/maths.h>
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;
}
}

View File

@ -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);

View File

@ -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)

View File

@ -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