From 447c5b05bb3aff3bac6761192961c0d5c2c80b63 Mon Sep 17 00:00:00 2001 From: fincs Date: Wed, 16 Sep 2015 13:29:48 +0200 Subject: [PATCH] Add Mtx_PerspStereoTilt() for stereo 3D rendering --- include/c3d/maths.h | 1 + source/maths/mtx_perspstereo.c | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 source/maths/mtx_perspstereo.c diff --git a/include/c3d/maths.h b/include/c3d/maths.h index 43af715..6ab0f21 100644 --- a/include/c3d/maths.h +++ b/include/c3d/maths.h @@ -71,3 +71,4 @@ void Mtx_RotateZ(C3D_Mtx* mtx, float angle, bool bRightSide); // Special versions of the projection matrices that take the 3DS' screen orientation into account void Mtx_OrthoTilt(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far); void Mtx_PerspTilt(C3D_Mtx* mtx, float fovy, float aspect, float near, float far); +void Mtx_PerspStereoTilt(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, float iod, float screen); diff --git a/source/maths/mtx_perspstereo.c b/source/maths/mtx_perspstereo.c new file mode 100644 index 0000000..148e8de --- /dev/null +++ b/source/maths/mtx_perspstereo.c @@ -0,0 +1,37 @@ +#include + +void Mtx_PerspStereoTilt(C3D_Mtx* mtx, float fovx, float invaspect, float near, float far, float iod, float screen) +{ + // Notes: + // Once again, we are passed "fovy" and the "aspect ratio"; however the 3DS screens are sideways, + // and the formula had to be tweaked. With stereo, left/right separation becomes top/bottom separation. + // The detailed mathematical explanation is in mtx_persptilt.c. + + float fovx_tan = tanf(fovx/2); + float fovx_tan_invaspect = fovx_tan*invaspect; + float shift = iod / (2*screen); // 'near' not in the numerator because it cancels out in mp.r[1].z + + C3D_Mtx mp; + Mtx_Zeros(&mp); + + // Build asymmetric perspective projection matrix + mp.r[0].x = 1.0f / fovx_tan; + mp.r[1].y = 1.0f / fovx_tan_invaspect; + mp.r[1].z = shift / fovx_tan_invaspect; + mp.r[2].z = (near + far) / (near - far); + mp.r[2].w = (2 * near * far) / (near - far); + mp.r[3].z = -1.0f; + + // Fix depth range to [-1, 0] + C3D_Mtx mp2; + Mtx_Identity(&mp2); + mp2.r[2].z = 0.5; + mp2.r[2].w = -0.5; + Mtx_Multiply(mtx, &mp2, &mp); + + // Translate to screen plane + Mtx_Translate(mtx, 0, iod/2, 0); + + // Rotate the matrix one quarter of a turn CCW in order to fix the 3DS screens' orientation + Mtx_RotateZ(mtx, M_TAU/4, true); +}