|
|
@@ -0,0 +1,181 @@ |
|
|
|
/* |
|
|
|
* matrix.c |
|
|
|
* |
|
|
|
* Some useful matrix functions. |
|
|
|
* |
|
|
|
* Brian Paul |
|
|
|
* 10 Feb 2004 |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <math.h> |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Pretty-print the given matrix. |
|
|
|
*/ |
|
|
|
void |
|
|
|
PrintMatrix(const float p[16]) |
|
|
|
{ |
|
|
|
printf("[ %6.3f %6.3f %6.3f %6.3f ]\n", p[0], p[4], p[8], p[12]); |
|
|
|
printf("[ %6.3f %6.3f %6.3f %6.3f ]\n", p[1], p[5], p[9], p[13]); |
|
|
|
printf("[ %6.3f %6.3f %6.3f %6.3f ]\n", p[2], p[6], p[10], p[14]); |
|
|
|
printf("[ %6.3f %6.3f %6.3f %6.3f ]\n", p[3], p[7], p[11], p[15]); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Build a glFrustum matrix. |
|
|
|
*/ |
|
|
|
void |
|
|
|
Frustum(float left, float right, float bottom, float top, float nearZ, float farZ, float *m) |
|
|
|
{ |
|
|
|
float x = (2.0F*nearZ) / (right-left); |
|
|
|
float y = (2.0F*nearZ) / (top-bottom); |
|
|
|
float a = (right+left) / (right-left); |
|
|
|
float b = (top+bottom) / (top-bottom); |
|
|
|
float c = -(farZ+nearZ) / ( farZ-nearZ); |
|
|
|
float d = -(2.0F*farZ*nearZ) / (farZ-nearZ); |
|
|
|
|
|
|
|
#define M(row,col) m[col*4+row] |
|
|
|
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F; |
|
|
|
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F; |
|
|
|
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d; |
|
|
|
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F; |
|
|
|
#undef M |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Build a glOrtho marix. |
|
|
|
*/ |
|
|
|
void |
|
|
|
Ortho(float left, float right, float bottom, float top, float nearZ, float farZ, float *m) |
|
|
|
{ |
|
|
|
#define M(row,col) m[col*4+row] |
|
|
|
M(0,0) = 2.0F / (right-left); |
|
|
|
M(0,1) = 0.0F; |
|
|
|
M(0,2) = 0.0F; |
|
|
|
M(0,3) = -(right+left) / (right-left); |
|
|
|
|
|
|
|
M(1,0) = 0.0F; |
|
|
|
M(1,1) = 2.0F / (top-bottom); |
|
|
|
M(1,2) = 0.0F; |
|
|
|
M(1,3) = -(top+bottom) / (top-bottom); |
|
|
|
|
|
|
|
M(2,0) = 0.0F; |
|
|
|
M(2,1) = 0.0F; |
|
|
|
M(2,2) = -2.0F / (farZ-nearZ); |
|
|
|
M(2,3) = -(farZ+nearZ) / (farZ-nearZ); |
|
|
|
|
|
|
|
M(3,0) = 0.0F; |
|
|
|
M(3,1) = 0.0F; |
|
|
|
M(3,2) = 0.0F; |
|
|
|
M(3,3) = 1.0F; |
|
|
|
#undef M |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Decompose a projection matrix to determine original glFrustum or |
|
|
|
* glOrtho parameters. |
|
|
|
*/ |
|
|
|
void |
|
|
|
DecomposeProjection( const float *m, |
|
|
|
int *isPerspective, |
|
|
|
float *leftOut, float *rightOut, |
|
|
|
float *botOut, float *topOut, |
|
|
|
float *nearOut, float *farOut) |
|
|
|
{ |
|
|
|
if (m[15] == 0.0) { |
|
|
|
/* perspective */ |
|
|
|
float p[16]; |
|
|
|
const float x = m[0]; /* 2N / (R-L) */ |
|
|
|
const float y = m[5]; /* 2N / (T-B) */ |
|
|
|
const float a = m[8]; /* (R+L) / (R-L) */ |
|
|
|
const float b = m[9]; /* (T+B) / (T-B) */ |
|
|
|
const float c = m[10]; /* -(F+N) / (F-N) */ |
|
|
|
const float d = m[14]; /* -2FN / (F-N) */ |
|
|
|
|
|
|
|
/* These equations found with simple algebra, knowing the arithmetic |
|
|
|
* use to set up a typical perspective projection matrix in OpenGL. |
|
|
|
*/ |
|
|
|
const float nearZ = -d / (1.0 - c); |
|
|
|
const float farZ = (c - 1.0) * nearZ / (c + 1.0); |
|
|
|
const float left = nearZ * (a - 1.0) / x; |
|
|
|
const float right = 2.0 * nearZ / x + left; |
|
|
|
const float bottom = nearZ * (b - 1.0) / y; |
|
|
|
const float top = 2.0 * nearZ / y + bottom; |
|
|
|
|
|
|
|
*isPerspective = 1; |
|
|
|
*leftOut = left; |
|
|
|
*rightOut = right; |
|
|
|
*botOut = bottom; |
|
|
|
*topOut = top; |
|
|
|
*nearOut = nearZ; |
|
|
|
*farOut = farZ; |
|
|
|
} |
|
|
|
else { |
|
|
|
/* orthographic */ |
|
|
|
const float x = m[0]; /* 2 / (R-L) */ |
|
|
|
const float y = m[5]; /* 2 / (T-B) */ |
|
|
|
const float z = m[10]; /* -2 / (F-N) */ |
|
|
|
const float a = m[12]; /* -(R+L) / (R-L) */ |
|
|
|
const float b = m[13]; /* -(T+B) / (T-B) */ |
|
|
|
const float c = m[14]; /* -(F+N) / (F-N) */ |
|
|
|
/* again, simple algebra */ |
|
|
|
const float right = -(a - 1.0) / x; |
|
|
|
const float left = right - 2.0 / x; |
|
|
|
const float top = -(b - 1.0) / y; |
|
|
|
const float bottom = top - 2.0 / y; |
|
|
|
const float farZ = (c - 1.0) / z; |
|
|
|
const float nearZ = farZ + 2.0 / z; |
|
|
|
|
|
|
|
*isPerspective = 0; |
|
|
|
*leftOut = left; |
|
|
|
*rightOut = right; |
|
|
|
*botOut = bottom; |
|
|
|
*topOut = top; |
|
|
|
*nearOut = nearZ; |
|
|
|
*farOut = farZ; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
/* test harness */ |
|
|
|
int |
|
|
|
main(int argc, char *argv[]) |
|
|
|
{ |
|
|
|
float m[16], p[16]; |
|
|
|
float l, r, b, t, n, f; |
|
|
|
int persp; |
|
|
|
int i; |
|
|
|
|
|
|
|
#if 0 |
|
|
|
l = -.9; |
|
|
|
r = 1.2; |
|
|
|
b = -0.5; |
|
|
|
t = 1.4; |
|
|
|
n = 30; |
|
|
|
f = 84; |
|
|
|
printf(" Frustum(%f, %f, %f, %f, %f, %f\n",l+1, r+1.2, b+.5, t+.3, n, f); |
|
|
|
Frustum(l+1, r+1.2, b+.5, t+.3, n, f, p); |
|
|
|
DecomposeProjection(p, &persp, &l, &r, &b, &t, &n, &f); |
|
|
|
printf("glFrustum(%f, %f, %f, %f, %f, %f)\n", |
|
|
|
l, r, b, t, n, f); |
|
|
|
PrintMatrix(p); |
|
|
|
#else |
|
|
|
printf("Ortho(-1, 1, -1, 1, 10, 84)\n"); |
|
|
|
Ortho(-1, 1, -1, 1, 10, 84, m); |
|
|
|
PrintMatrix(m); |
|
|
|
DecomposeProjection(m, &persp, &l, &r, &b, &t, &n, &f); |
|
|
|
printf("Ortho(%f, %f, %f, %f, %f, %f) %d\n", l, r, b, t, n, f, persp); |
|
|
|
#endif |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
#endif |