e9438a8659
and xserver)...
182 lines
4.6 KiB
C
182 lines
4.6 KiB
C
/*
|
|
* 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
|