GLEssentials/Source/Utility/matrixUtil.c
/* |
Copyright (C) 2015 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
Functions for performing matrix math. |
*/ |
#include "matrixUtil.h" |
#include "vectorUtil.h" |
#include <math.h> |
#include <memory.h> |
void mtxMultiply(float* ret, const float* lhs, const float* rhs) |
{ |
// [ 0 4 8 12 ] [ 0 4 8 12 ] |
// [ 1 5 9 13 ] x [ 1 5 9 13 ] |
// [ 2 6 10 14 ] [ 2 6 10 14 ] |
// [ 3 7 11 15 ] [ 3 7 11 15 ] |
ret[ 0] = lhs[ 0]*rhs[ 0] + lhs[ 4]*rhs[ 1] + lhs[ 8]*rhs[ 2] + lhs[12]*rhs[ 3]; |
ret[ 1] = lhs[ 1]*rhs[ 0] + lhs[ 5]*rhs[ 1] + lhs[ 9]*rhs[ 2] + lhs[13]*rhs[ 3]; |
ret[ 2] = lhs[ 2]*rhs[ 0] + lhs[ 6]*rhs[ 1] + lhs[10]*rhs[ 2] + lhs[14]*rhs[ 3]; |
ret[ 3] = lhs[ 3]*rhs[ 0] + lhs[ 7]*rhs[ 1] + lhs[11]*rhs[ 2] + lhs[15]*rhs[ 3]; |
ret[ 4] = lhs[ 0]*rhs[ 4] + lhs[ 4]*rhs[ 5] + lhs[ 8]*rhs[ 6] + lhs[12]*rhs[ 7]; |
ret[ 5] = lhs[ 1]*rhs[ 4] + lhs[ 5]*rhs[ 5] + lhs[ 9]*rhs[ 6] + lhs[13]*rhs[ 7]; |
ret[ 6] = lhs[ 2]*rhs[ 4] + lhs[ 6]*rhs[ 5] + lhs[10]*rhs[ 6] + lhs[14]*rhs[ 7]; |
ret[ 7] = lhs[ 3]*rhs[ 4] + lhs[ 7]*rhs[ 5] + lhs[11]*rhs[ 6] + lhs[15]*rhs[ 7]; |
ret[ 8] = lhs[ 0]*rhs[ 8] + lhs[ 4]*rhs[ 9] + lhs[ 8]*rhs[10] + lhs[12]*rhs[11]; |
ret[ 9] = lhs[ 1]*rhs[ 8] + lhs[ 5]*rhs[ 9] + lhs[ 9]*rhs[10] + lhs[13]*rhs[11]; |
ret[10] = lhs[ 2]*rhs[ 8] + lhs[ 6]*rhs[ 9] + lhs[10]*rhs[10] + lhs[14]*rhs[11]; |
ret[11] = lhs[ 3]*rhs[ 8] + lhs[ 7]*rhs[ 9] + lhs[11]*rhs[10] + lhs[15]*rhs[11]; |
ret[12] = lhs[ 0]*rhs[12] + lhs[ 4]*rhs[13] + lhs[ 8]*rhs[14] + lhs[12]*rhs[15]; |
ret[13] = lhs[ 1]*rhs[12] + lhs[ 5]*rhs[13] + lhs[ 9]*rhs[14] + lhs[13]*rhs[15]; |
ret[14] = lhs[ 2]*rhs[12] + lhs[ 6]*rhs[13] + lhs[10]*rhs[14] + lhs[14]*rhs[15]; |
ret[15] = lhs[ 3]*rhs[12] + lhs[ 7]*rhs[13] + lhs[11]*rhs[14] + lhs[15]*rhs[15];} |
void mtxLoadPerspective(float* mtx, float fov, float aspect, float nearZ, float farZ) |
{ |
float f = 1.0f / tanf( (fov * (M_PI/180)) / 2.0f); |
mtx[0] = f / aspect; |
mtx[1] = 0.0f; |
mtx[2] = 0.0f; |
mtx[3] = 0.0f; |
mtx[4] = 0.0f; |
mtx[5] = f; |
mtx[6] = 0.0f; |
mtx[7] = 0.0f; |
mtx[8] = 0.0f; |
mtx[9] = 0.0f; |
mtx[10] = (farZ+nearZ) / (nearZ-farZ); |
mtx[11] = -1.0f; |
mtx[12] = 0.0f; |
mtx[13] = 0.0f; |
mtx[14] = 2 * farZ * nearZ / (nearZ-farZ); |
mtx[15] = 0.0f; |
} |
void mtxLoadOrthographic(float* mtx, |
float left, float right, |
float bottom, float top, |
float nearZ, float farZ) |
{ |
//See appendix G of OpenGL Red Book |
mtx[ 0] = 2.0f / (right - left); |
mtx[ 1] = 0.0; |
mtx[ 2] = 0.0; |
mtx[ 3] = 0.0; |
mtx[ 4] = 0.0; |
mtx[ 5] = 2.0f / (top - bottom); |
mtx[ 6] = 0.0; |
mtx[ 7] = 0.0; |
mtx[ 8] = 0.0; |
mtx[ 9] = 0.0; |
mtx[10] = -2.0f / (farZ - nearZ); |
mtx[11] = 0.0; |
mtx[12] = -(right + left) / (right - left); |
mtx[13] = -(top + bottom) / (top - bottom); |
mtx[14] = -(farZ + nearZ) / (farZ - nearZ); |
mtx[15] = 1.0f; |
} |
static inline float sgn(float val) |
{ |
return (val > 0.0f) ? 1.0f : ((val < 0.0f) ? -1.0f : 0.0f); |
} |
void mtxModifyObliqueProjection(float* mtx, const float* src, const float* plane) |
{ |
float vec[4]; |
memcpy(mtx, src, 16 * sizeof(float)); |
vec[0] = (sgn(plane[0]) + mtx[8]) / mtx[0]; |
vec[1] = (sgn(plane[1]) + mtx[9]) / mtx[5]; |
vec[2] = -1.0f; |
vec[3] = (1.0f + mtx[10]) / mtx[14]; |
float dot = vec4DotProduct(plane, vec); |
vec[0] = plane[0] * (2.0f / dot); |
vec[1] = plane[1] * (2.0f / dot); |
vec[2] = plane[2] * (2.0f / dot); |
vec[3] = plane[3] * (2.0f / dot); |
// Replace the third row of the projection matrix |
mtx[ 2] = vec[0]; |
mtx[ 6] = vec[1]; |
mtx[10] = vec[2]; |
mtx[14] = vec[3]; |
} |
void mtxTranspose(float* mtx, const float* src) |
{ |
//Use a temp to swap in case mtx == src |
float tmp; |
mtx[0] = src[0]; |
mtx[5] = src[5]; |
mtx[10] = src[10]; |
mtx[15] = src[15]; |
tmp = src[4]; |
mtx[4] = src[1]; |
mtx[1] = tmp; |
tmp = src[8]; |
mtx[8] = src[2]; |
mtx[2] = tmp; |
tmp = src[12]; |
mtx[12] = src[3]; |
mtx[3] = tmp; |
tmp = src[9]; |
mtx[9] = src[6]; |
mtx[6] = tmp; |
tmp = src[13]; |
mtx[13] = src[7]; |
mtx[ 7] = tmp; |
tmp = src[14]; |
mtx[14] = src[11]; |
mtx[11] = tmp; |
} |
void mtxInvert(float* mtx, const float* src) |
{ |
float tmp[16]; |
float val, val2, val_inv; |
int i, j, i4, i8, i12, ind; |
mtxTranspose(tmp, src); |
mtxLoadIdentity(mtx); |
for(i = 0; i != 4; i++) |
{ |
val = tmp[(i << 2) + i]; |
ind = i; |
i4 = i + 4; |
i8 = i + 8; |
i12 = i + 12; |
for (j = i + 1; j != 4; j++) |
{ |
if(fabsf(tmp[(i << 2) + j]) > fabsf(val)) |
{ |
ind = j; |
val = tmp[(i << 2) + j]; |
} |
} |
if(ind != i) |
{ |
val2 = mtx[i]; |
mtx[i] = mtx[ind]; |
mtx[ind] = val2; |
val2 = tmp[i]; |
tmp[i] = tmp[ind]; |
tmp[ind] = val2; |
ind += 4; |
val2 = mtx[i4]; |
mtx[i4] = mtx[ind]; |
mtx[ind] = val2; |
val2 = tmp[i4]; |
tmp[i4] = tmp[ind]; |
tmp[ind] = val2; |
ind += 4; |
val2 = mtx[i8]; |
mtx[i8] = mtx[ind]; |
mtx[ind] = val2; |
val2 = tmp[i8]; |
tmp[i8] = tmp[ind]; |
tmp[ind] = val2; |
ind += 4; |
val2 = mtx[i12]; |
mtx[i12] = mtx[ind]; |
mtx[ind] = val2; |
val2 = tmp[i12]; |
tmp[i12] = tmp[ind]; |
tmp[ind] = val2; |
} |
if(val == 0) |
{ |
mtxLoadIdentity(mtx); |
return; |
} |
val_inv = 1.0f / val; |
tmp[i] *= val_inv; |
mtx[i] *= val_inv; |
tmp[i4] *= val_inv; |
mtx[i4] *= val_inv; |
tmp[i8] *= val_inv; |
mtx[i8] *= val_inv; |
tmp[i12] *= val_inv; |
mtx[i12] *= val_inv; |
if(i != 0) |
{ |
val = tmp[i << 2]; |
tmp[0] -= tmp[i] * val; |
mtx[0] -= mtx[i] * val; |
tmp[4] -= tmp[i4] * val; |
mtx[4] -= mtx[i4] * val; |
tmp[8] -= tmp[i8] * val; |
mtx[8] -= mtx[i8] * val; |
tmp[12] -= tmp[i12] * val; |
mtx[12] -= mtx[i12] * val; |
} |
if(i != 1) |
{ |
val = tmp[(i << 2) + 1]; |
tmp[1] -= tmp[i] * val; |
mtx[1] -= mtx[i] * val; |
tmp[5] -= tmp[i4] * val; |
mtx[5] -= mtx[i4] * val; |
tmp[9] -= tmp[i8] * val; |
mtx[9] -= mtx[i8] * val; |
tmp[13] -= tmp[i12] * val; |
mtx[13] -= mtx[i12] * val; |
} |
if(i != 2) |
{ |
val = tmp[(i << 2) + 2]; |
tmp[2] -= tmp[i] * val; |
mtx[2] -= mtx[i] * val; |
tmp[6] -= tmp[i4] * val; |
mtx[6] -= mtx[i4] * val; |
tmp[10] -= tmp[i8] * val; |
mtx[10] -= mtx[i8] * val; |
tmp[14] -= tmp[i12] * val; |
mtx[14] -= mtx[i12] * val; |
} |
if(i != 3) |
{ |
val = tmp[(i << 2) + 3]; |
tmp[3] -= tmp[i] * val; |
mtx[3] -= mtx[i] * val; |
tmp[7] -= tmp[i4] * val; |
mtx[7] -= mtx[i4] * val; |
tmp[11] -= tmp[i8] * val; |
mtx[11] -= mtx[i8] * val; |
tmp[15] -= tmp[i12] * val; |
mtx[15] -= mtx[i12] * val; |
} |
} |
} |
void mtxLoadIdentity(float* mtx) |
{ |
// [ 0 4 8 12 ] |
// [ 1 5 9 13 ] |
// [ 2 6 10 14 ] |
// [ 3 7 11 15 ] |
mtx[ 0] = mtx[ 5] = mtx[10] = mtx[15] = 1.0f; |
mtx[ 1] = mtx[ 2] = mtx[ 3] = mtx[ 4] = |
mtx[ 6] = mtx[ 7] = mtx[ 8] = mtx[ 9] = |
mtx[11] = mtx[12] = mtx[13] = mtx[14] = 0.0; |
} |
void mtxLoadTranslate(float* mtx, float xTrans, float yTrans, float zTrans) |
{ |
// [ 0 4 8 x ] |
// [ 1 5 9 y ] |
// [ 2 6 10 z ] |
// [ 3 7 11 15 ] |
mtx[ 0] = mtx[ 5] = mtx[10] = mtx[15] = 1.0f; |
mtx[ 1] = mtx[ 2] = mtx[ 3] = mtx[ 4] = |
mtx[ 6] = mtx[ 7] = mtx[ 8] = mtx[ 9] = |
mtx[11] = 0.0; |
mtx[12] = xTrans; |
mtx[13] = yTrans; |
mtx[14] = zTrans; |
} |
void mtxLoadScale(float* mtx, float xScale, float yScale, float zScale) |
{ |
// [ x 4 8 12 ] |
// [ 1 y 9 13 ] |
// [ 2 6 z 14 ] |
// [ 3 7 11 15 ] |
mtx[ 0] = xScale; |
mtx[ 5] = yScale; |
mtx[10] = zScale; |
mtx[15] = 1.0f; |
mtx[ 1] = mtx[ 2] = mtx[ 3] = mtx[ 4] = |
mtx[ 6] = mtx[ 7] = mtx[ 8] = mtx[ 9] = |
mtx[11] = mtx[12] = mtx[13] = mtx[14] = 0.0; |
} |
void mtxLoadRotateX(float* mtx, float rad) |
{ |
// [ 0 4 8 12 ] |
// [ 1 cos -sin 13 ] |
// [ 2 sin cos 14 ] |
// [ 3 7 11 15 ] |
mtx[10] = mtx[ 5] = cosf(rad); |
mtx[ 6] = sinf(rad); |
mtx[ 9] = -mtx[ 6]; |
mtx[ 0] = mtx[15] = 1.0f; |
mtx[ 1] = mtx[ 2] = mtx[ 3] = mtx[ 4] = |
mtx[ 7] = mtx[ 8] = mtx[11] = mtx[12] = |
mtx[13] = mtx[14] = 0.0; |
} |
void mtxLoadRotateY(float* mtx, float rad) |
{ |
// [ cos 4 -sin 12 ] |
// [ 1 5 9 13 ] |
// [ sin 6 cos 14 ] |
// [ 3 7 11 15 ] |
mtx[ 0] = mtx[10] = cosf(rad); |
mtx[ 2] = sinf(rad); |
mtx[ 8] = -mtx[2]; |
mtx[ 5] = mtx[15] = 1.0; |
mtx[ 1] = mtx[ 3] = mtx[ 4] = mtx[ 6] = |
mtx[ 7] = mtx[ 9] = mtx[11] = mtx[12] = |
mtx[13] = mtx[14] = 0.0; |
} |
void mtxLoadRotateZ(float* mtx, float rad) |
{ |
// [ cos -sin 8 12 ] |
// [ sin cos 9 13 ] |
// [ 2 6 10 14 ] |
// [ 3 7 11 15 ] |
mtx[ 0] = mtx[ 5] = cosf(rad); |
mtx[ 1] = sinf(rad); |
mtx[ 4] = -mtx[1]; |
mtx[10] = mtx[15] = 1.0; |
mtx[ 2] = mtx[ 3] = mtx[ 6] = mtx[ 7] = |
mtx[ 8] = mtx[ 9] = mtx[11] = mtx[12] = |
mtx[13] = mtx[14] = 0.0; |
} |
void mtxLoadRotate(float* mtx, float deg, float xAxis, float yAxis, float zAxis) |
{ |
float rad = deg * M_PI/180.0f; |
float sin_a = sinf(rad); |
float cos_a = cosf(rad); |
// Calculate coeffs. No need to check for zero magnitude because we wouldn't be here. |
float magnitude = sqrtf(xAxis * xAxis + yAxis * yAxis + zAxis * zAxis); |
float p = 1.0f / magnitude; |
float cos_am = 1.0f - cos_a; |
float xp = xAxis * p; |
float yp = yAxis * p; |
float zp = zAxis * p; |
float xx = xp * xp; |
float yy = yp * yp; |
float zz = zp * zp; |
float xy = xp * yp * cos_am; |
float yz = yp * zp * cos_am; |
float zx = zp * xp * cos_am; |
xp *= sin_a; |
yp *= sin_a; |
zp *= sin_a; |
// Load coefs |
float m0 = xx + cos_a * (1.0f - xx); |
float m1 = xy + zp; |
float m2 = zx - yp; |
float m4 = xy - zp; |
float m5 = yy + cos_a * (1.0f - yy); |
float m6 = yz + xp; |
float m8 = zx + yp; |
float m9 = yz - xp; |
float m10 = zz + cos_a * (1.0f - zz); |
// Apply rotation |
float c1 = mtx[0]; |
float c2 = mtx[4]; |
float c3 = mtx[8]; |
mtx[0] = c1 * m0 + c2 * m1 + c3 * m2; |
mtx[4] = c1 * m4 + c2 * m5 + c3 * m6; |
mtx[8] = c1 * m8 + c2 * m9 + c3 * m10; |
c1 = mtx[1]; |
c2 = mtx[5]; |
c3 = mtx[9]; |
mtx[1] = c1 * m0 + c2 * m1 + c3 * m2; |
mtx[5] = c1 * m4 + c2 * m5 + c3 * m6; |
mtx[9] = c1 * m8 + c2 * m9 + c3 * m10; |
c1 = mtx[2]; |
c2 = mtx[6]; |
c3 = mtx[10]; |
mtx[2] = c1 * m0 + c2 * m1 + c3 * m2; |
mtx[6] = c1 * m4 + c2 * m5 + c3 * m6; |
mtx[10] = c1 * m8 + c2 * m9 + c3 * m10; |
c1 = mtx[3]; |
c2 = mtx[7]; |
c3 = mtx[11]; |
mtx[3] = c1 * m0 + c2 * m1 + c3 * m2; |
mtx[7] = c1 * m4 + c2 * m5 + c3 * m6; |
mtx[11] = c1 * m8 + c2 * m9 + c3 * m10; |
mtx[12] = mtx[13] = mtx[14] = 0.0; |
mtx[15] = 1.0f; |
} |
void mtxTranslateApply(float* mtx, float xTrans, float yTrans, float zTrans) |
{ |
// [ 0 4 8 12 ] [ 1 0 0 x ] |
// [ 1 5 9 13 ] x [ 0 1 0 y ] |
// [ 2 6 10 14 ] [ 0 0 1 z ] |
// [ 3 7 11 15 ] [ 0 0 0 1 ] |
mtx[12] += mtx[0]*xTrans + mtx[4]*yTrans + mtx[ 8]*zTrans; |
mtx[13] += mtx[1]*xTrans + mtx[5]*yTrans + mtx[ 9]*zTrans; |
mtx[14] += mtx[2]*xTrans + mtx[6]*yTrans + mtx[10]*zTrans; |
} |
void mtxScaleApply(float* mtx, float xScale, float yScale, float zScale) |
{ |
// [ 0 4 8 12 ] [ x 0 0 0 ] |
// [ 1 5 9 13 ] x [ 0 y 0 0 ] |
// [ 2 6 10 14 ] [ 0 0 z 0 ] |
// [ 3 7 11 15 ] [ 0 0 0 1 ] |
mtx[ 0] *= xScale; |
mtx[ 4] *= yScale; |
mtx[ 8] *= zScale; |
mtx[ 1] *= xScale; |
mtx[ 5] *= yScale; |
mtx[ 9] *= zScale; |
mtx[ 2] *= xScale; |
mtx[ 6] *= yScale; |
mtx[10] *= zScale; |
mtx[ 3] *= xScale; |
mtx[ 7] *= yScale; |
mtx[11] *= xScale; |
} |
void mtxTranslateMatrix(float* mtx, float xTrans, float yTrans, float zTrans) |
{ |
// [ 1 0 0 x ] [ 0 4 8 12 ] |
// [ 0 1 0 y ] x [ 1 5 9 13 ] |
// [ 0 0 1 z ] [ 2 6 10 14 ] |
// [ 0 0 0 1 ] [ 3 7 11 15 ] |
mtx[ 0] += xTrans * mtx[ 3]; |
mtx[ 1] += yTrans * mtx[ 3]; |
mtx[ 2] += zTrans * mtx[ 3]; |
mtx[ 4] += xTrans * mtx[ 7]; |
mtx[ 5] += yTrans * mtx[ 7]; |
mtx[ 6] += zTrans * mtx[ 7]; |
mtx[ 8] += xTrans * mtx[11]; |
mtx[ 9] += yTrans * mtx[11]; |
mtx[10] += zTrans * mtx[11]; |
mtx[12] += xTrans * mtx[15]; |
mtx[13] += yTrans * mtx[15]; |
mtx[14] += zTrans * mtx[15]; |
} |
void mtxRotateXApply(float* mtx, float deg) |
{ |
// [ 0 4 8 12 ] [ 1 0 0 0 ] |
// [ 1 5 9 13 ] x [ 0 cos -sin 0 ] |
// [ 2 6 10 14 ] [ 0 sin cos 0 ] |
// [ 3 7 11 15 ] [ 0 0 0 1 ] |
float rad = deg * (M_PI/180.0f); |
float cosrad = cosf(rad); |
float sinrad = sinf(rad); |
float mtx04 = mtx[4]; |
float mtx05 = mtx[5]; |
float mtx06 = mtx[6]; |
float mtx07 = mtx[7]; |
mtx[ 4] = mtx[ 8]*sinrad + mtx04*cosrad; |
mtx[ 8] = mtx[ 8]*cosrad - mtx04*sinrad; |
mtx[ 5] = mtx[ 9]*sinrad + mtx05*cosrad; |
mtx[ 9] = mtx[ 9]*cosrad - mtx05*sinrad; |
mtx[ 6] = mtx[10]*sinrad + mtx06*cosrad; |
mtx[10] = mtx[10]*cosrad - mtx06*sinrad; |
mtx[ 7] = mtx[11]*sinrad + mtx07*cosrad; |
mtx[11] = mtx[11]*cosrad - mtx07*sinrad; |
} |
void mtxRotateYApply(float* mtx, float deg) |
{ |
// [ 0 4 8 12 ] [ cos 0 -sin 0 ] |
// [ 1 5 9 13 ] x [ 0 1 0 0 ] |
// [ 2 6 10 14 ] [ sin 0 cos 0 ] |
// [ 3 7 11 15 ] [ 0 0 0 1 ] |
float rad = deg * (M_PI/180.0f); |
float cosrad = cosf(rad); |
float sinrad = sinf(rad); |
float mtx00 = mtx[0]; |
float mtx01 = mtx[1]; |
float mtx02 = mtx[2]; |
float mtx03 = mtx[3]; |
mtx[ 0] = mtx[ 8]*sinrad + mtx00*cosrad; |
mtx[ 8] = mtx[ 8]*cosrad - mtx00*sinrad; |
mtx[ 1] = mtx[ 9]*sinrad + mtx01*cosrad; |
mtx[ 9] = mtx[ 9]*cosrad - mtx01*sinrad; |
mtx[ 2] = mtx[10]*sinrad + mtx02*cosrad; |
mtx[10] = mtx[10]*cosrad - mtx02*sinrad; |
mtx[ 3] = mtx[11]*sinrad + mtx03*cosrad; |
mtx[11] = mtx[11]*cosrad - mtx03*sinrad; |
} |
void mtxRotateZApply(float* mtx, float deg) |
{ |
// [ 0 4 8 12 ] [ cos -sin 0 0 ] |
// [ 1 5 9 13 ] x [ sin cos 0 0 ] |
// [ 2 6 10 14 ] [ 0 0 1 0 ] |
// [ 3 7 11 15 ] [ 0 0 0 1 ] |
float rad = deg * (M_PI/180.0f); |
float cosrad = cosf(rad); |
float sinrad = sinf(rad); |
float mtx00 = mtx[0]; |
float mtx01 = mtx[1]; |
float mtx02 = mtx[2]; |
float mtx03 = mtx[3]; |
mtx[ 0] = mtx[ 4]*sinrad + mtx00*cosrad; |
mtx[ 4] = mtx[ 4]*cosrad - mtx00*sinrad; |
mtx[ 1] = mtx[ 5]*sinrad + mtx01*cosrad; |
mtx[ 5] = mtx[ 5]*cosrad - mtx01*sinrad; |
mtx[ 2] = mtx[ 6]*sinrad + mtx02*cosrad; |
mtx[ 6] = mtx[ 6]*cosrad - mtx02*sinrad; |
mtx[ 3] = mtx[ 7]*sinrad + mtx03*cosrad; |
mtx[ 7] = mtx[ 7]*cosrad - mtx03*sinrad; |
} |
void mtxRotateApply(float* mtx, float deg, float xAxis, float yAxis, float zAxis) |
{ |
if(yAxis == 0.0f && zAxis == 0.0f) |
{ |
mtxRotateXApply(mtx, deg); |
} |
else if(xAxis == 0.0f && zAxis == 0.0f) |
{ |
mtxRotateYApply(mtx, deg); |
} |
else if(xAxis == 0.0f && yAxis == 0.0f) |
{ |
mtxRotateZApply(mtx, deg); |
} |
else |
{ |
float rad = deg * M_PI/180.0f; |
float sin_a = sinf(rad); |
float cos_a = cosf(rad); |
// Calculate coeffs. No need to check for zero magnitude because we wouldn't be here. |
float magnitude = sqrtf(xAxis * xAxis + yAxis * yAxis + zAxis * zAxis); |
float p = 1.0f / magnitude; |
float cos_am = 1.0f - cos_a; |
float xp = xAxis * p; |
float yp = yAxis * p; |
float zp = zAxis * p; |
float xx = xp * xp; |
float yy = yp * yp; |
float zz = zp * zp; |
float xy = xp * yp * cos_am; |
float yz = yp * zp * cos_am; |
float zx = zp * xp * cos_am; |
xp *= sin_a; |
yp *= sin_a; |
zp *= sin_a; |
// Load coefs |
float m0 = xx + cos_a * (1.0f - xx); |
float m1 = xy + zp; |
float m2 = zx - yp; |
float m4 = xy - zp; |
float m5 = yy + cos_a * (1.0f - yy); |
float m6 = yz + xp; |
float m8 = zx + yp; |
float m9 = yz - xp; |
float m10 = zz + cos_a * (1.0f - zz); |
// Apply rotation |
float c1 = mtx[0]; |
float c2 = mtx[4]; |
float c3 = mtx[8]; |
mtx[0] = c1 * m0 + c2 * m1 + c3 * m2; |
mtx[4] = c1 * m4 + c2 * m5 + c3 * m6; |
mtx[8] = c1 * m8 + c2 * m9 + c3 * m10; |
c1 = mtx[1]; |
c2 = mtx[5]; |
c3 = mtx[9]; |
mtx[1] = c1 * m0 + c2 * m1 + c3 * m2; |
mtx[5] = c1 * m4 + c2 * m5 + c3 * m6; |
mtx[9] = c1 * m8 + c2 * m9 + c3 * m10; |
c1 = mtx[2]; |
c2 = mtx[6]; |
c3 = mtx[10]; |
mtx[2] = c1 * m0 + c2 * m1 + c3 * m2; |
mtx[6] = c1 * m4 + c2 * m5 + c3 * m6; |
mtx[10] = c1 * m8 + c2 * m9 + c3 * m10; |
c1 = mtx[3]; |
c2 = mtx[7]; |
c3 = mtx[11]; |
mtx[3] = c1 * m0 + c2 * m1 + c3 * m2; |
mtx[7] = c1 * m4 + c2 * m5 + c3 * m6; |
mtx[11] = c1 * m8 + c2 * m9 + c3 * m10; |
} |
} |
void mtxScaleMatrix(float* mtx, float xScale, float yScale, float zScale) |
{ |
// [ x 0 0 0 ] [ 0 4 8 12 ] |
// [ 0 y 0 0 ] x [ 1 5 9 13 ] |
// [ 0 0 z 0 ] [ 2 6 10 14 ] |
// [ 0 0 0 1 ] [ 3 7 11 15 ] |
mtx[ 0] *= xScale; |
mtx[ 4] *= xScale; |
mtx[ 8] *= xScale; |
mtx[12] *= xScale; |
mtx[ 1] *= yScale; |
mtx[ 5] *= yScale; |
mtx[ 9] *= yScale; |
mtx[13] *= yScale; |
mtx[ 2] *= zScale; |
mtx[ 6] *= zScale; |
mtx[10] *= zScale; |
mtx[14] *= zScale; |
} |
void mtxRotateXMatrix(float* mtx, float rad) |
{ |
// [ 1 0 0 0 ] [ 0 4 8 12 ] |
// [ 0 cos -sin 0 ] x [ 1 5 9 13 ] |
// [ 0 sin cos 0 ] [ 2 6 10 14 ] |
// [ 0 0 0 1 ] [ 3 7 11 15 ] |
float cosrad = cosf(rad); |
float sinrad = sinf(rad); |
float mtx01 = mtx[ 1]; |
float mtx05 = mtx[ 5]; |
float mtx09 = mtx[ 9]; |
float mtx13 = mtx[13]; |
mtx[ 1] = cosrad*mtx01 - sinrad*mtx[ 2]; |
mtx[ 2] = sinrad*mtx01 + cosrad*mtx[ 2]; |
mtx[ 5] = cosrad*mtx05 - sinrad*mtx[ 6]; |
mtx[ 6] = sinrad*mtx05 + cosrad*mtx[ 6]; |
mtx[ 9] = cosrad*mtx09 - sinrad*mtx[10]; |
mtx[10] = sinrad*mtx09 + cosrad*mtx[10]; |
mtx[13] = cosrad*mtx13 - sinrad*mtx[14]; |
mtx[14] = sinrad*mtx13 + cosrad*mtx[14]; |
} |
void mtxRotateYMatrix(float* mtx, float rad) |
{ |
// [ cos 0 -sin 0 ] [ 0 4 8 12 ] |
// [ 0 1 0 0 ] x [ 1 5 9 13 ] |
// [ sin 0 cos 0 ] [ 2 6 10 14 ] |
// [ 0 0 0 1 ] [ 3 7 11 15 ] |
float cosrad = cosf(rad); |
float sinrad = sinf(rad); |
float mtx00 = mtx[ 0]; |
float mtx04 = mtx[ 4]; |
float mtx08 = mtx[ 8]; |
float mtx12 = mtx[12]; |
mtx[ 0] = cosrad*mtx00 - sinrad*mtx[ 2]; |
mtx[ 2] = sinrad*mtx00 + cosrad*mtx[ 2]; |
mtx[ 4] = cosrad*mtx04 - sinrad*mtx[ 6]; |
mtx[ 6] = sinrad*mtx04 + cosrad*mtx[ 6]; |
mtx[ 8] = cosrad*mtx08 - sinrad*mtx[10]; |
mtx[10] = sinrad*mtx08 + cosrad*mtx[10]; |
mtx[12] = cosrad*mtx12 - sinrad*mtx[14]; |
mtx[14] = sinrad*mtx12 + cosrad*mtx[14]; |
} |
void mtxRotateZMatrix(float* mtx, float rad) |
{ |
// [ cos -sin 0 0 ] [ 0 4 8 12 ] |
// [ sin cos 0 0 ] x [ 1 5 9 13 ] |
// [ 0 0 1 0 ] [ 2 6 10 14 ] |
// [ 0 0 0 1 ] [ 3 7 11 15 ] |
float cosrad = cosf(rad); |
float sinrad = sinf(rad); |
float mtx00 = mtx[ 0]; |
float mtx04 = mtx[ 4]; |
float mtx08 = mtx[ 8]; |
float mtx12 = mtx[12]; |
mtx[ 0] = cosrad*mtx00 - sinrad*mtx[ 1]; |
mtx[ 1] = sinrad*mtx00 + cosrad*mtx[ 1]; |
mtx[ 4] = cosrad*mtx04 - sinrad*mtx[ 5]; |
mtx[ 5] = sinrad*mtx04 + cosrad*mtx[ 5]; |
mtx[ 8] = cosrad*mtx08 - sinrad*mtx[ 9]; |
mtx[ 9] = sinrad*mtx08 + cosrad*mtx[ 9]; |
mtx[12] = cosrad*mtx12 - sinrad*mtx[13]; |
mtx[13] = sinrad*mtx12 + cosrad*mtx[13]; |
} |
void mtxRotateMatrix(float* mtx, float rad, float xAxis, float yAxis, float zAxis) |
{ |
float rotMtx[16]; |
mtxLoadRotate(rotMtx, rad, xAxis, yAxis, zAxis); |
mtxMultiply(mtx, rotMtx, mtx); |
} |
void mtx3x3LoadIdentity(float* mtx) |
{ |
mtx[0] = mtx[4] = mtx[8] = 1.0f; |
mtx[1] = mtx[2] = mtx[3] = |
mtx[5] = mtx[6] = mtx[7] = 0.0f; |
} |
void mtx3x3FromTopLeftOf4x4(float* mtx, const float* src) |
{ |
mtx[0] = src[0]; |
mtx[1] = src[1]; |
mtx[2] = src[2]; |
mtx[3] = src[4]; |
mtx[4] = src[5]; |
mtx[5] = src[6]; |
mtx[6] = src[8]; |
mtx[7] = src[9]; |
mtx[8] = src[10]; |
} |
void mtx3x3Transpose(float* mtx, const float* src) |
{ |
float tmp; |
mtx[0] = src[0]; |
mtx[4] = src[4]; |
mtx[8] = src[8]; |
tmp = src[1]; |
mtx[1] = src[3]; |
mtx[3] = tmp; |
tmp = src[2]; |
mtx[2] = src[6]; |
mtx[6] = tmp; |
tmp = src[5]; |
mtx[5] = src[7]; |
mtx[7] = tmp; |
} |
void mtx3x3Invert(float* mtx, const float* src) |
{ |
float cpy[9]; |
float det = |
src[0] * (src[4]*src[8] - src[7]*src[5]) - |
src[1] * (src[3]*src[8] - src[6]*src[5]) + |
src[2] * (src[3]*src[7] - src[6]*src[4]); |
if ( fabs( det ) < 0.0005 ) |
{ |
mtx3x3LoadIdentity(mtx); |
return; |
} |
memcpy(cpy, src, 9 * sizeof(float)); |
mtx[0] = cpy[4]*cpy[8] - cpy[5]*cpy[7] / det; |
mtx[1] = -(cpy[1]*cpy[8] - cpy[7]*cpy[2]) / det; |
mtx[2] = cpy[1]*cpy[5] - cpy[4]*cpy[2] / det; |
mtx[3] = -(cpy[3]*cpy[8] - cpy[5]*cpy[6]) / det; |
mtx[4] = cpy[0]*cpy[8] - cpy[6]*cpy[2] / det; |
mtx[5] = -(cpy[0]*cpy[5] - cpy[3]*cpy[2]) / det; |
mtx[6] = cpy[3]*cpy[7] - cpy[6]*cpy[4] / det; |
mtx[7] = -(cpy[0]*cpy[7] - cpy[6]*cpy[1]) / det; |
mtx[8] = cpy[0]*cpy[4] - cpy[1]*cpy[3] / det; |
} |
void mtx3x3Multiply(float* mtx, const float* lhs, const float* rhs) |
{ |
mtx[0] = lhs[0]*rhs[0] + lhs[3] * rhs[1] + lhs[6] * rhs[2]; |
mtx[1] = lhs[1]*rhs[0] + lhs[4] * rhs[1] + lhs[7] * rhs[2]; |
mtx[2] = lhs[2]*rhs[0] + lhs[5] * rhs[1] + lhs[8] * rhs[2]; |
mtx[3] = lhs[0]*rhs[3] + lhs[3] * rhs[4] + lhs[6] * rhs[5]; |
mtx[4] = lhs[1]*rhs[3] + lhs[4] * rhs[4] + lhs[7] * rhs[5]; |
mtx[5] = lhs[2]*rhs[3] + lhs[5] * rhs[4] + lhs[8] * rhs[5]; |
mtx[6] = lhs[0]*rhs[6] + lhs[3] * rhs[7] + lhs[6] * rhs[8]; |
mtx[7] = lhs[1]*rhs[6] + lhs[4] * rhs[7] + lhs[7] * rhs[8]; |
mtx[8] = lhs[2]*rhs[6] + lhs[5] * rhs[7] + lhs[8] * rhs[8]; |
} |
Copyright © 2015 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2015-08-07