1
0
Fork 0
mirror of https://github.com/ctruLua/ctruLua.git synced 2025-10-28 16:59:30 +00:00

Updated all the libs, added citro3d, added ctr.swkbd (WIP, untested)

This commit is contained in:
Firew0lf 2016-08-05 17:30:24 +02:00
parent 68a44645f7
commit 49c87e5526
97 changed files with 7341 additions and 944 deletions

2
libs/citro3d/source/maths/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.d
*.o

View file

@ -0,0 +1,34 @@
#include <c3d/maths.h>
void Mtx_FromQuat(C3D_Mtx* m, C3D_FQuat q)
{
float ii = q.i*q.i;
float ij = q.i*q.j;
float ik = q.i*q.k;
float jj = q.j*q.j;
float jk = q.j*q.k;
float kk = q.k*q.k;
float ri = q.r*q.i;
float rj = q.r*q.j;
float rk = q.r*q.k;
m->r[0].x = 1.0f - (2.0f * (jj + kk));
m->r[1].x = 2.0f * (ij + rk);
m->r[2].x = 2.0f * (ik - rj);
m->r[3].x = 0.0f;
m->r[0].y = 2.0f * (ij - rk);
m->r[1].y = 1.0f - (2.0f * (ii + kk));
m->r[2].y = 2.0f * (jk + ri);
m->r[3].y = 0.0f;
m->r[0].z = 2.0f * (ik + rj);
m->r[1].z = 2.0f * (jk - ri);
m->r[2].z = 1.0f - (2.0f * (ii + jj));
m->r[3].z = 0.0f;
m->r[0].w = 0.0f;
m->r[1].w = 0.0f;
m->r[2].w = 0.0f;
m->r[3].w = 1.0f;
}

View file

@ -0,0 +1,10 @@
#include <c3d/maths.h>
void Mtx_Identity(C3D_Mtx* out)
{
// http://www.wolframalpha.com/input/?i={{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}
int i;
for (i = 0; i < 16; ++i)
out->m[i] = 0.0f;
out->r[0].x = out->r[1].y = out->r[2].z = out->r[3].w = 1.0f;
}

View file

@ -0,0 +1,135 @@
#include <float.h>
#include <c3d/maths.h>
float Mtx_Inverse(C3D_Mtx* out)
{
//Mtx_Inverse can be used to calculate the determinant and the inverse of the matrix.
C3D_Mtx inv;
float det;
int i;
inv.r[0].x = out->r[1].y * out->r[2].z * out->r[3].w -
out->r[1].y * out->r[2].w * out->r[3].z -
out->r[2].y * out->r[1].z * out->r[3].w +
out->r[2].y * out->r[1].w * out->r[3].z +
out->r[3].y * out->r[1].z * out->r[2].w -
out->r[3].y * out->r[1].w * out->r[2].z;
inv.r[1].x = -out->r[1].x * out->r[2].z * out->r[3].w +
out->r[1].x * out->r[2].w * out->r[3].z +
out->r[2].x * out->r[1].z * out->r[3].w -
out->r[2].x * out->r[1].w * out->r[3].z -
out->r[3].x * out->r[1].z * out->r[2].w +
out->r[3].x * out->r[1].w * out->r[2].z;
inv.r[2].x = out->r[1].x * out->r[2].y * out->r[3].w -
out->r[1].x * out->r[2].w * out->r[3].y -
out->r[2].x * out->r[1].y * out->r[3].w +
out->r[2].x * out->r[1].w * out->r[3].y +
out->r[3].x * out->r[1].y * out->r[2].w -
out->r[3].x * out->r[1].w * out->r[2].y;
inv.r[3].x = -out->r[1].x * out->r[2].y * out->r[3].z +
out->r[1].x * out->r[2].z * out->r[3].y +
out->r[2].x * out->r[1].y * out->r[3].z -
out->r[2].x * out->r[1].z * out->r[3].y -
out->r[3].x * out->r[1].y * out->r[2].z +
out->r[3].x * out->r[1].z * out->r[2].y;
det = out->r[0].x * inv.r[0].x + out->r[0].y * inv.r[1].x +
out->r[0].z * inv.r[2].x + out->r[0].w * inv.r[3].x;
if (fabsf(det) < FLT_EPSILON)
//Returns 0.0f if we find the determinant is less than +/- FLT_EPSILON.
return 0.0f;
inv.r[0].y = -out->r[0].y * out->r[2].z * out->r[3].w +
out->r[0].y * out->r[2].w * out->r[3].z +
out->r[2].y * out->r[0].z * out->r[3].w -
out->r[2].y * out->r[0].w * out->r[3].z -
out->r[3].y * out->r[0].z * out->r[2].w +
out->r[3].y * out->r[0].w * out->r[2].z;
inv.r[1].y = out->r[0].x * out->r[2].z * out->r[3].w -
out->r[0].x * out->r[2].w * out->r[3].z -
out->r[2].x * out->r[0].z * out->r[3].w +
out->r[2].x * out->r[0].w * out->r[3].z +
out->r[3].x * out->r[0].z * out->r[2].w -
out->r[3].x * out->r[0].w * out->r[2].z;
inv.r[2].y = -out->r[0].x * out->r[2].y * out->r[3].w +
out->r[0].x * out->r[2].w * out->r[3].y +
out->r[2].x * out->r[0].y * out->r[3].w -
out->r[2].x * out->r[0].w * out->r[3].y -
out->r[3].x * out->r[0].y * out->r[2].w +
out->r[3].x * out->r[0].w * out->r[2].y;
inv.r[3].y = out->r[0].x * out->r[2].y * out->r[3].z -
out->r[0].x * out->r[2].z * out->r[3].y -
out->r[2].x * out->r[0].y * out->r[3].z +
out->r[2].x * out->r[0].z * out->r[3].y +
out->r[3].x * out->r[0].y * out->r[2].z -
out->r[3].x * out->r[0].z * out->r[2].y;
inv.r[0].z = out->r[0].y * out->r[1].z * out->r[3].w -
out->r[0].y * out->r[1].w * out->r[3].z -
out->r[1].y * out->r[0].z * out->r[3].w +
out->r[1].y * out->r[0].w * out->r[3].z +
out->r[3].y * out->r[0].z * out->r[1].w -
out->r[3].y * out->r[0].w * out->r[1].z;
inv.r[1].z = -out->r[0].x * out->r[1].z * out->r[3].w +
out->r[0].x * out->r[1].w * out->r[3].z +
out->r[1].x * out->r[0].z * out->r[3].w -
out->r[1].x * out->r[0].w * out->r[3].z -
out->r[3].x * out->r[0].z * out->r[1].w +
out->r[3].x * out->r[0].w * out->r[1].z;
inv.r[2].z = out->r[0].x * out->r[1].y * out->r[3].w -
out->r[0].x * out->r[1].w * out->r[3].y -
out->r[1].x * out->r[0].y * out->r[3].w +
out->r[1].x * out->r[0].w * out->r[3].y +
out->r[3].x * out->r[0].y * out->r[1].w -
out->r[3].x * out->r[0].w * out->r[1].y;
inv.r[3].z = -out->r[0].x * out->r[1].y * out->r[3].z +
out->r[0].x * out->r[1].z * out->r[3].y +
out->r[1].x * out->r[0].y * out->r[3].z -
out->r[1].x * out->r[0].z * out->r[3].y -
out->r[3].x * out->r[0].y * out->r[1].z +
out->r[3].x * out->r[0].z * out->r[1].y;
inv.r[0].w = -out->r[0].y * out->r[1].z * out->r[2].w +
out->r[0].y * out->r[1].w * out->r[2].z +
out->r[1].y * out->r[0].z * out->r[2].w -
out->r[1].y * out->r[0].w * out->r[2].z -
out->r[2].y * out->r[0].z * out->r[1].w +
out->r[2].y * out->r[0].w * out->r[1].z;
inv.r[1].w = out->r[0].x * out->r[1].z * out->r[2].w -
out->r[0].x * out->r[1].w * out->r[2].z -
out->r[1].x * out->r[0].z * out->r[2].w +
out->r[1].x * out->r[0].w * out->r[2].z +
out->r[2].x * out->r[0].z * out->r[1].w -
out->r[2].x * out->r[0].w * out->r[1].z;
inv.r[2].w = -out->r[0].x * out->r[1].y * out->r[2].w +
out->r[0].x * out->r[1].w * out->r[2].y +
out->r[1].x * out->r[0].y * out->r[2].w -
out->r[1].x * out->r[0].w * out->r[2].y -
out->r[2].x * out->r[0].y * out->r[1].w +
out->r[2].x * out->r[0].w * out->r[1].y;
inv.r[3].w = out->r[0].x * out->r[1].y * out->r[2].z -
out->r[0].x * out->r[1].z * out->r[2].y -
out->r[1].x * out->r[0].y * out->r[2].z +
out->r[1].x * out->r[0].z * out->r[2].y +
out->r[2].x * out->r[0].y * out->r[1].z -
out->r[2].x * out->r[0].z * out->r[1].y;
for (i = 0; i < 16; i++)
out->m[i] = inv.m[i] / det;
return det;
}

View file

@ -0,0 +1,37 @@
#include <c3d/maths.h>
void Mtx_LookAt(C3D_Mtx* out, C3D_FVec cameraPosition, C3D_FVec cameraTarget, C3D_FVec cameraUpVector, bool isLeftHanded)
{
//Left-handed and Right-handed Look-At matrix functions are DirectX implementations.
//Left-handed: https://msdn.microsoft.com/en-us/library/windows/desktop/bb281710
//Right-handed: https://msdn.microsoft.com/en-us/library/windows/desktop/bb281711
C3D_FVec xaxis, yaxis, zaxis;
//Order of operations is crucial.
if (isLeftHanded)
zaxis = FVec3_Normalize(FVec3_Subtract(cameraTarget, cameraPosition));
else
zaxis = FVec3_Normalize(FVec3_Subtract(cameraPosition, cameraTarget));
xaxis = FVec3_Normalize(FVec3_Cross(cameraUpVector, zaxis));
yaxis = FVec3_Cross(zaxis, xaxis);
out->r[0].x = xaxis.x;
out->r[0].y = xaxis.y;
out->r[0].z = xaxis.z;
out->r[0].w = -FVec3_Dot(xaxis, cameraPosition);
out->r[1].x = yaxis.x;
out->r[1].y = yaxis.y;
out->r[1].z = yaxis.z;
out->r[1].w = -FVec3_Dot(yaxis, cameraPosition);
out->r[2].x = zaxis.x;
out->r[2].y = zaxis.y;
out->r[2].z = zaxis.z;
out->r[2].w = -FVec3_Dot(zaxis, cameraPosition);
out->r[3].x = 0.0f;
out->r[3].y = 0.0f;
out->r[3].z = 0.0f;
out->r[3].w = 1.0f;
}

View file

@ -0,0 +1,19 @@
#include <c3d/maths.h>
void Mtx_Multiply(C3D_Mtx* out, const C3D_Mtx* a, const C3D_Mtx* b)
{
// if out is a or b, then we need to avoid overwriting them
if(out == a || out == b)
{
C3D_Mtx tmp;
Mtx_Multiply(&tmp, a, b);
Mtx_Copy(out, &tmp);
return;
}
// http://www.wolframalpha.com/input/?i={{a,b,c,d},{e,f,g,h},{i,j,k,l},{m,n,o,p}}{{α,β,γ,δ},{ε,θ,ι,κ},{λ,μ,ν,ξ},{ο,π,ρ,σ}}
int i, j;
for (j = 0; j < 4; ++j)
for (i = 0; i < 4; ++i)
out->r[j].c[i] = a->r[j].x*b->r[0].c[i] + a->r[j].y*b->r[1].c[i] + a->r[j].z*b->r[2].c[i] + a->r[j].w*b->r[3].c[i];
}

View file

@ -0,0 +1,11 @@
#include <c3d/maths.h>
C3D_FVec Mtx_MultiplyFVec3(const C3D_Mtx* mtx, C3D_FVec v)
{
// http://www.wolframalpha.com/input/?i={{a,b,c},{d,e,f},{g,h,i}}{x,y,z}
float x = FVec3_Dot(mtx->r[0], v);
float y = FVec3_Dot(mtx->r[1], v);
float z = FVec3_Dot(mtx->r[2], v);
return FVec3_New(x, y, z);
}

View file

@ -0,0 +1,12 @@
#include <c3d/maths.h>
C3D_FVec Mtx_MultiplyFVec4(const C3D_Mtx* mtx, C3D_FVec v)
{
// http://www.wolframalpha.com/input/?i={{a,b,c,d},{e,f,g,h},{i,j,k,l},{m,n,o,p}}{x,y,z,w}
float x = FVec4_Dot(mtx->r[0], v);
float y = FVec4_Dot(mtx->r[1], v);
float z = FVec4_Dot(mtx->r[2], v);
float w = FVec4_Dot(mtx->r[3], v);
return FVec4_New(x, y, z, w);
}

View file

@ -0,0 +1,20 @@
#include <c3d/maths.h>
void Mtx_Ortho(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded)
{
Mtx_Zeros(mtx);
// Standard orthogonal projection matrix, with a fixed depth range of [-1,0] (required by PICA)
// http://www.wolframalpha.com/input/?i={{1,0,0,0},{0,1,0,0},{0,0,0.5,-0.5},{0,0,0,1}}{{2/(r-l),0,0,(l%2Br)/(l-r)},{0,2/(t-b),0,(b%2Bt)/(b-t)},{0,0,2/(n-f),(n%2Bf)/(n-f)},{0,0,0,1}}
mtx->r[0].x = 2.0f / (right - left);
mtx->r[0].w = (left + right) / (left - right);
mtx->r[1].y = 2.0f / (top - bottom);
mtx->r[1].w = (bottom + top) / (bottom - top);
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

@ -0,0 +1,21 @@
#include <c3d/maths.h>
void Mtx_OrthoTilt(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded)
{
Mtx_Zeros(mtx);
// Standard orthogonal projection matrix, with a fixed depth range of [-1,0] (required by PICA) and rotated τ/4 radians counterclockwise around the Z axis (due to 3DS screen orientation)
// http://www.wolframalpha.com/input/?i={{0,1,0,0},{-1,0,0,0},{0,0,1,0},{0,0,0,1}}{{1,0,0,0},{0,1,0,0},{0,0,0.5,-0.5},{0,0,0,1}}
// http://www.wolframalpha.com/input/?i={{0,1,0,0},{-1,0,0,0},{0,0,0.5,-0.5},{0,0,0,1}}{{2/(r-l),0,0,(l%2Br)/(l-r)},{0,2/(t-b),0,(b%2Bt)/(b-t)},{0,0,2/(n-f),(n%2Bf)/(n-f)},{0,0,0,1}}
mtx->r[0].y = 2.0f / (top - bottom);
mtx->r[0].w = (bottom + top) / (bottom - top);
mtx->r[1].x = 2.0f / (left - right);
mtx->r[1].w = (left + right) / (right - left);
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

@ -0,0 +1,26 @@
#include <c3d/maths.h>
void Mtx_Persp(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, bool isLeftHanded)
{
float fovy_tan = tanf(fovy/2.0f);
Mtx_Zeros(mtx);
// Standard perspective projection matrix, with a fixed depth range of [-1,0] (required by PICA)
// http://www.wolframalpha.com/input/?i={{1,0,0,0},{0,1,0,0},{0,0,0.5,-0.5},{0,0,0,1}}{{1/(a*tan(v)),0,0,0},{0,1/tan(v),0,0},{0,0,(n%2Bf)/(n-f),(fn)/(n-f)},{0,0,0,-1}}
mtx->r[0].x = 1.0f / (aspect * fovy_tan);
mtx->r[1].y = 1.0f / fovy_tan;
mtx->r[2].w = far*near / (near - far);
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

@ -0,0 +1,28 @@
#include <c3d/maths.h>
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;
float shift = iod / (2.0f*screen); // 'near' not in the numerator because it cancels out in mp.r[1].z
Mtx_Zeros(mtx);
mtx->r[0].x = 1.0f / fovy_tan_aspect;
mtx->r[0].w = -iod / 2.0f;
mtx->r[1].y = 1.0f / fovy_tan;
mtx->r[2].w = near * far / (near - far);
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

@ -0,0 +1,33 @@
#include <c3d/maths.h>
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,
// 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.0f);
float fovx_tan_invaspect = fovx_tan*invaspect;
float shift = iod / (2.0f*screen); // 'near' not in the numerator because it cancels out in mp.r[1].z
Mtx_Zeros(mtx);
mtx->r[0].y = 1.0f / fovx_tan;
mtx->r[1].x = -1.0f / fovx_tan_invaspect;
mtx->r[1].w = iod / 2.0f;
mtx->r[2].w = near * far / (near - far);
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

@ -0,0 +1,46 @@
#include <c3d/maths.h>
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,
// and so are these parameters -- in fact, they are actually the fovx and the inverse
// of the aspect ratio. Therefore the formula for the perspective projection matrix
// had to be modified to be expressed in these terms instead.
// Notes:
// Includes adjusting depth range from [-1,1] to [-1,0]
// Includes rotation of the matrix one quarter of a turn clockwise in order to fix the 3DS screens' orientation
// Notes:
// fovx = 2 atan(tan(fovy/2)*w/h)
// fovy = 2 atan(tan(fovx/2)*h/w)
// invaspect = h/w
// a0,0 = h / (w*tan(fovy/2)) =
// = h / (w*tan(2 atan(tan(fovx/2)*h/w) / 2)) =
// = h / (w*tan( atan(tan(fovx/2)*h/w) )) =
// = h / (w * tan(fovx/2)*h/w) =
// = 1 / tan(fovx/2)
// a1,1 = 1 / tan(fovy/2) = (...) = w / (h*tan(fovx/2))
float fovx_tan = tanf(fovx/2.0f);
Mtx_Zeros(mtx);
mtx->r[0].y = 1.0f / fovx_tan;
mtx->r[1].x = -1.0f / (fovx_tan*invaspect);
mtx->r[2].w = far*near / (near - far);
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

@ -0,0 +1,72 @@
#include <c3d/maths.h>
void Mtx_Rotate(C3D_Mtx* mtx, C3D_FVec axis, float angle, bool bRightSide)
{
size_t i;
C3D_Mtx om;
float s = sinf(angle);
float c = cosf(angle);
float t = 1.0f - c;
axis = FVec3_Normalize(axis);
float x = axis.x;
float y = axis.y;
float z = axis.z;
float w;
om.r[0].x = t*x*x + c;
om.r[1].x = t*x*y + s*z;
om.r[2].x = t*x*z - s*y;
//om.r[3].x = 0.0f; //optimized out
om.r[0].y = t*y*x - s*z;
om.r[1].y = t*y*y + c;
om.r[2].y = t*y*z + s*x;
//om.r[3].y = 0.0f; //optimized out
om.r[0].z = t*z*x + s*y;
om.r[1].z = t*z*y - s*x;
om.r[2].z = t*z*z + c;
//om.r[3].z = 0.0f; //optimized out
/* optimized out
om.r[0].w = 0.0f;
om.r[1].w = 0.0f;
om.r[2].w = 0.0f;
om.r[3].w = 1.0f;
*/
if (bRightSide)
{
for (i = 0; i < 4; ++i)
{
x = mtx->r[i].x*om.r[0].x + mtx->r[i].y*om.r[1].x + mtx->r[i].z*om.r[2].x;
y = mtx->r[i].x*om.r[0].y + mtx->r[i].y*om.r[1].y + mtx->r[i].z*om.r[2].y;
z = mtx->r[i].x*om.r[0].z + mtx->r[i].y*om.r[1].z + mtx->r[i].z*om.r[2].z;
mtx->r[i].x = x;
mtx->r[i].y = y;
mtx->r[i].z = z;
}
}
else
{
for (i = 0; i < 3; ++i)
{
x = mtx->r[0].x*om.r[i].x + mtx->r[1].x*om.r[i].y + mtx->r[2].x*om.r[i].z;
y = mtx->r[0].y*om.r[i].x + mtx->r[1].y*om.r[i].y + mtx->r[2].y*om.r[i].z;
z = mtx->r[0].z*om.r[i].x + mtx->r[1].z*om.r[i].y + mtx->r[2].z*om.r[i].z;
w = mtx->r[0].w*om.r[i].x + mtx->r[1].w*om.r[i].y + mtx->r[2].w*om.r[i].z;
om.r[i].x = x;
om.r[i].y = y;
om.r[i].z = z;
om.r[i].w = w;
}
for (i = 0; i < 3; ++i)
mtx->r[i] = om.r[i];
}
}

View file

@ -0,0 +1,30 @@
#include <c3d/maths.h>
void Mtx_RotateX(C3D_Mtx* mtx, float angle, bool bRightSide)
{
float a, b;
float cosAngle = cosf(angle);
float sinAngle = sinf(angle);
size_t i;
if (bRightSide)
{
for (i = 0; i < 4; ++i)
{
a = mtx->r[i].y*cosAngle + mtx->r[i].z*sinAngle;
b = mtx->r[i].z*cosAngle - mtx->r[i].y*sinAngle;
mtx->r[i].y = a;
mtx->r[i].z = b;
}
}
else
{
for (i = 0; i < 4; ++i)
{
a = mtx->r[1].c[i]*cosAngle - mtx->r[2].c[i]*sinAngle;
b = mtx->r[2].c[i]*cosAngle + mtx->r[1].c[i]*sinAngle;
mtx->r[1].c[i] = a;
mtx->r[2].c[i] = b;
}
}
}

View file

@ -0,0 +1,30 @@
#include <c3d/maths.h>
void Mtx_RotateY(C3D_Mtx* mtx, float angle, bool bRightSide)
{
float a, b;
float cosAngle = cosf(angle);
float sinAngle = sinf(angle);
size_t i;
if (bRightSide)
{
for (i = 0; i < 4; ++i)
{
a = mtx->r[i].x*cosAngle - mtx->r[i].z*sinAngle;
b = mtx->r[i].z*cosAngle + mtx->r[i].x*sinAngle;
mtx->r[i].x = a;
mtx->r[i].z = b;
}
}
else
{
for (i = 0; i < 4; ++i)
{
a = mtx->r[0].c[i]*cosAngle + mtx->r[2].c[i]*sinAngle;
b = mtx->r[2].c[i]*cosAngle - mtx->r[0].c[i]*sinAngle;
mtx->r[0].c[i] = a;
mtx->r[2].c[i] = b;
}
}
}

View file

@ -0,0 +1,30 @@
#include <c3d/maths.h>
void Mtx_RotateZ(C3D_Mtx* mtx, float angle, bool bRightSide)
{
float a, b;
float cosAngle = cosf(angle);
float sinAngle = sinf(angle);
size_t i;
if (bRightSide)
{
for (i = 0; i < 4; ++i)
{
a = mtx->r[i].x*cosAngle + mtx->r[i].y*sinAngle;
b = mtx->r[i].y*cosAngle - mtx->r[i].x*sinAngle;
mtx->r[i].x = a;
mtx->r[i].y = b;
}
}
else
{
for (i = 0; i < 4; ++i)
{
a = mtx->r[0].c[i]*cosAngle - mtx->r[1].c[i]*sinAngle;
b = mtx->r[1].c[i]*cosAngle + mtx->r[0].c[i]*sinAngle;
mtx->r[0].c[i] = a;
mtx->r[1].c[i] = b;
}
}
}

View file

@ -0,0 +1,12 @@
#include <c3d/maths.h>
void Mtx_Scale(C3D_Mtx* mtx, float x, float y, float z)
{
int i;
for (i = 0; i < 4; ++i)
{
mtx->r[i].x *= x;
mtx->r[i].y *= y;
mtx->r[i].z *= z;
}
}

View file

@ -0,0 +1,21 @@
#include <c3d/maths.h>
void Mtx_Translate(C3D_Mtx* mtx, float x, float y, float z, bool bRightSide)
{
C3D_FVec v = FVec4_New(x, y, z, 1.0f);
int i, j;
if (bRightSide)
{
for (i = 0; i < 4; ++i)
mtx->r[i].w = FVec4_Dot(mtx->r[i], v);
}
else
{
for (j = 0; j < 3; ++j)
for (i = 0; i < 4; ++i)
mtx->r[j].c[i] += mtx->r[3].c[i] * v.c[3-j];
}
}

View file

@ -0,0 +1,13 @@
#include <c3d/maths.h>
C3D_FVec Quat_CrossFVec3(C3D_FQuat q, C3D_FVec v)
{
C3D_FVec qv = FVec3_New(q.i, q.j, q.k);
C3D_FVec uv = FVec3_Cross(qv, v);
C3D_FVec uuv = FVec3_Cross(qv, uv);
uv = FVec3_Scale(uv, 2.0f * q.r);
uuv = FVec3_Scale(uuv, 2.0f);
return FVec3_Add(v, FVec3_Add(uv, uuv));
}

View file

@ -0,0 +1,11 @@
#include <c3d/maths.h>
C3D_FQuat Quat_Multiply(C3D_FQuat lhs, C3D_FQuat rhs)
{
float i = lhs.r*rhs.i + lhs.i*rhs.r + lhs.j*rhs.k - lhs.k*rhs.j;
float j = lhs.r*rhs.j + lhs.j*rhs.r + lhs.k*rhs.i - lhs.i*rhs.k;
float k = lhs.r*rhs.k + lhs.k*rhs.r + lhs.i*rhs.j - lhs.j*rhs.i;
float r = lhs.r*rhs.r - lhs.i*rhs.i - lhs.j*rhs.j - lhs.k*rhs.k;
return Quat_New(i, j, k, r);
}

View file

@ -0,0 +1,23 @@
#include <float.h>
#include <c3d/maths.h>
C3D_FQuat Quat_Pow(C3D_FQuat q, float p)
{
// if the power is very near to zero, return the identity quaternion to avoid blowing up with division
if (p > -FLT_EPSILON && p < FLT_EPSILON)
return Quat_Identity();
float mag = FVec4_Magnitude(q);
// if the magnitude is very near to one, this is equivalent to raising the real component by the power
// also, acosf(1) == 0 and sinf(0) == 0 so you would get a divide-by-zero anyway
if (fabsf(q.r / mag) > 1.0f - FLT_EPSILON && fabsf(q.r / mag) < 1.0f + FLT_EPSILON)
return Quat_New(0.0f, 0.0f, 0.0f, powf(q.r, p));
float angle = acosf(q.r / mag);
float newAngle = angle * p;
float div = sinf(newAngle) / sinf(angle);
float Mag = powf(mag, p - 1.0f);
return Quat_New(q.i*div*Mag, q.j*div*Mag, q.k*div*Mag, cosf(newAngle)*mag*Mag);
}

View file

@ -0,0 +1,16 @@
#include <c3d/maths.h>
C3D_FQuat Quat_Rotate(C3D_FQuat q, C3D_FVec axis, float r, bool bRightSide)
{
float halfAngle = r/2.0f;
float s = sinf(halfAngle);
axis = FVec3_Normalize(axis);
C3D_FQuat tmp = Quat_New(axis.x*s, axis.y*s, axis.z*s, cosf(halfAngle));
if (bRightSide)
return Quat_Multiply(tmp, q);
else
return Quat_Multiply(q, tmp);
}

View file

@ -0,0 +1,12 @@
#include <c3d/maths.h>
C3D_FQuat Quat_RotateX(C3D_FQuat q, float r, bool bRightSide)
{
float c = cosf(r/2.0f);
float s = sinf(r/2.0f);
if (bRightSide)
return Quat_New(q.r*s + q.i*c, q.j*c - q.k*s, q.k*c + q.j*s, q.r*c - q.i*s);
else
return Quat_New(q.r*s + q.i*c, q.j*c + q.k*s, q.k*c - q.j*s, q.r*c - q.i*s);
}

View file

@ -0,0 +1,12 @@
#include <c3d/maths.h>
C3D_FQuat Quat_RotateY(C3D_FQuat q, float r, bool bRightSide)
{
float c = cosf(r/2.0f);
float s = sinf(r/2.0f);
if (bRightSide)
return Quat_New(q.i*c + q.k*s, q.r*s + q.j*c, q.k*c - q.i*s, q.r*c - q.j*s);
else
return Quat_New(q.i*c - q.k*s, q.r*s + q.j*c, q.k*c + q.i*s, q.r*c - q.j*s);
}

View file

@ -0,0 +1,12 @@
#include <c3d/maths.h>
C3D_FQuat Quat_RotateZ(C3D_FQuat q, float r, bool bRightSide)
{
float c = cosf(r/2.0f);
float s = sinf(r/2.0f);
if (bRightSide)
return Quat_New(q.i*c - q.j*s, q.j*c + q.i*s, q.r*s + q.k*c, q.r*c - q.k*s);
else
return Quat_New(q.i*c + q.j*s, q.j*c - q.i*s, q.r*s + q.k*c, q.r*c - q.k*s);
}