git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@219 626c5289-ae23-0410-ae9c-e8d60b6d4f22
343 lines
8.5 KiB
C
343 lines
8.5 KiB
C
/* -----------------------------------------------------------------------------
|
|
* matrix.c
|
|
*
|
|
* Some 4x4 matrix operations
|
|
*
|
|
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
|
* Copyright (C) 1995-1996
|
|
*
|
|
* See the file LICENSE for information on usage and redistribution.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
#define MATRIX
|
|
#include "gifplot.h"
|
|
#include <math.h>
|
|
|
|
/* ------------------------------------------------------------------------
|
|
Matrix new_Matrix()
|
|
|
|
Create a new 4x4 matrix.
|
|
------------------------------------------------------------------------ */
|
|
Matrix
|
|
new_Matrix() {
|
|
Matrix m;
|
|
m = (Matrix) malloc(16*sizeof(double));
|
|
return m;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
delete_Matrix(Matrix *m);
|
|
|
|
Destroy a matrix
|
|
------------------------------------------------------------------------ */
|
|
|
|
void
|
|
delete_Matrix(Matrix m) {
|
|
if (m)
|
|
free((char *) m);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
Matrix Matrix_copy(Matrix a)
|
|
|
|
Makes a copy of matrix a and returns it.
|
|
------------------------------------------------------------------------ */
|
|
|
|
Matrix Matrix_copy(Matrix a) {
|
|
int i;
|
|
Matrix r = 0;
|
|
if (a) {
|
|
r = new_Matrix();
|
|
if (r) {
|
|
for (i = 0; i < 16; i++)
|
|
r[i] = a[i];
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
Matrix_multiply(Matrix a, Matrix b, Matrix c)
|
|
|
|
Multiplies a*b = c
|
|
c may be one of the source matrices
|
|
------------------------------------------------------------------------ */
|
|
void
|
|
Matrix_multiply(Matrix a, Matrix b, Matrix c) {
|
|
double temp[16];
|
|
int i,j,k;
|
|
|
|
for (i =0; i < 4; i++)
|
|
for (j = 0; j < 4; j++) {
|
|
temp[i*4+j] = 0.0;
|
|
for (k = 0; k < 4; k++)
|
|
temp[i*4+j] += a[i*4+k]*b[k*4+j];
|
|
}
|
|
for (i = 0; i < 16; i++)
|
|
c[i] = temp[i];
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
Matrix_identity(Matrix a)
|
|
|
|
Puts an identity matrix in matrix a
|
|
------------------------------------------------------------------------ */
|
|
|
|
void
|
|
Matrix_identity(Matrix a) {
|
|
int i;
|
|
for (i = 0; i < 16; i++) a[i] = 0;
|
|
a[0] = 1;
|
|
a[5] = 1;
|
|
a[10] = 1;
|
|
a[15] = 1;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
Matrix_zero(Matrix a)
|
|
|
|
Puts a zero matrix in matrix a
|
|
------------------------------------------------------------------------ */
|
|
void
|
|
Matrix_zero(Matrix a) {
|
|
int i;
|
|
for (i = 0; i < 16; i++) a[i] = 0;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
Matrix_transpose(Matrix a, Matrix result)
|
|
|
|
Transposes matrix a and puts it in result.
|
|
------------------------------------------------------------------------ */
|
|
void
|
|
Matrix_transpose(Matrix a, Matrix result) {
|
|
double temp[16];
|
|
int i,j;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
for (j = 0; j < 4; j++)
|
|
temp[4*i+j] = a[4*j+i];
|
|
|
|
for (i = 0; i < 16; i++)
|
|
result[i] = temp[i];
|
|
}
|
|
|
|
|
|
/* ------------------------------------------------------------------------
|
|
Matrix_gauss(Matrix a, Matrix b)
|
|
|
|
Solves ax=b for x, using Gaussian elimination. Destroys a.
|
|
Really only used for calculating inverses of 4x4 transformation
|
|
matrices.
|
|
------------------------------------------------------------------------ */
|
|
|
|
void Matrix_gauss(Matrix a, Matrix b) {
|
|
int ipiv[4], indxr[4], indxc[4];
|
|
int i,j,k,l,ll;
|
|
int irow=0, icol=0;
|
|
double big, pivinv;
|
|
double dum;
|
|
for (j = 0; j < 4; j++)
|
|
ipiv[j] = 0;
|
|
for (i = 0; i < 4; i++) {
|
|
big = 0;
|
|
for (j = 0; j < 4; j++) {
|
|
if (ipiv[j] != 1) {
|
|
for (k = 0; k < 4; k++) {
|
|
if (ipiv[k] == 0) {
|
|
if (fabs(a[4*j+k]) >= big) {
|
|
big = fabs(a[4*j+k]);
|
|
irow = j;
|
|
icol = k;
|
|
}
|
|
} else if (ipiv[k] > 1)
|
|
return; /* Singular matrix */
|
|
}
|
|
}
|
|
}
|
|
ipiv[icol] = ipiv[icol]+1;
|
|
if (irow != icol) {
|
|
for (l = 0; l < 4; l++) {
|
|
dum = a[4*irow+l];
|
|
a[4*irow+l] = a[4*icol+l];
|
|
a[4*icol+l] = dum;
|
|
}
|
|
for (l = 0; l < 4; l++) {
|
|
dum = b[4*irow+l];
|
|
b[4*irow+l] = b[4*icol+l];
|
|
b[4*icol+l] = dum;
|
|
}
|
|
}
|
|
indxr[i] = irow;
|
|
indxc[i] = icol;
|
|
if (a[4*icol+icol] == 0) return;
|
|
pivinv = 1.0/a[4*icol+icol];
|
|
a[4*icol+icol] = 1.0;
|
|
for (l = 0; l < 4; l++)
|
|
a[4*icol+l] = a[4*icol+l]*pivinv;
|
|
for (l = 0; l < 4; l++)
|
|
b[4*icol+l] = b[4*icol+l]*pivinv;
|
|
for (ll = 0; ll < 4; ll++) {
|
|
if (ll != icol) {
|
|
dum = a[4*ll+icol];
|
|
a[4*ll+icol] = 0;
|
|
for (l = 0; l < 4; l++)
|
|
a[4*ll+l] = a[4*ll+l] - a[4*icol+l]*dum;
|
|
for (l = 0; l < 4; l++)
|
|
b[4*ll+l] = b[4*ll+l] - b[4*icol+l]*dum;
|
|
}
|
|
}
|
|
}
|
|
for (l = 3; l >= 0; l--) {
|
|
if (indxr[l] != indxc[l]) {
|
|
for (k = 0; k < 4; k++) {
|
|
dum = a[4*k+indxr[l]];
|
|
a[4*k+indxr[l]] = a[4*k+indxc[l]];
|
|
a[4*k+indxc[l]] = dum;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
Matrix_invert(Matrix a, Matrix inva)
|
|
|
|
Inverts Matrix a and places the result in inva.
|
|
Relies on the Gaussian Elimination code above. (See Numerical recipes).
|
|
------------------------------------------------------------------------ */
|
|
void
|
|
Matrix_invert(Matrix a, Matrix inva) {
|
|
|
|
double temp[16];
|
|
int i;
|
|
|
|
for (i = 0; i < 16; i++)
|
|
temp[i] = a[i];
|
|
Matrix_identity(inva);
|
|
Matrix_gauss(temp,inva);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
Matrix_transform(Matrix a, GL_Vector *r, GL_Vector *t)
|
|
|
|
Transform a vector. a*r ----> t
|
|
------------------------------------------------------------------------ */
|
|
|
|
void Matrix_transform(Matrix a, GL_Vector *r, GL_Vector *t) {
|
|
|
|
double rx, ry, rz, rw;
|
|
|
|
rx = r->x;
|
|
ry = r->y;
|
|
rz = r->z;
|
|
rw = r->w;
|
|
t->x = a[0]*rx + a[1]*ry + a[2]*rz + a[3]*rw;
|
|
t->y = a[4]*rx + a[5]*ry + a[6]*rz + a[7]*rw;
|
|
t->z = a[8]*rx + a[9]*ry + a[10]*rz + a[11]*rw;
|
|
t->w = a[12]*rx + a[13]*ry + a[14]*rz + a[15]*rw;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
Matrix_transform4(Matrix a, double x, double y, double z, double w, GL_Vector *t)
|
|
|
|
Transform a vector from a point specified as 4 doubles
|
|
------------------------------------------------------------------------ */
|
|
|
|
void Matrix_transform4(Matrix a, double rx, double ry, double rz, double rw,
|
|
GL_Vector *t) {
|
|
|
|
t->x = a[0]*rx + a[1]*ry + a[2]*rz + a[3]*rw;
|
|
t->y = a[4]*rx + a[5]*ry + a[6]*rz + a[7]*rw;
|
|
t->z = a[8]*rx + a[9]*ry + a[10]*rz + a[11]*rw;
|
|
t->w = a[12]*rx + a[13]*ry + a[14]*rz + a[15]*rw;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
Matrix_translate(Matrix a, double tx, double ty, double tz)
|
|
|
|
Put a translation matrix in Matrix a
|
|
---------------------------------------------------------------------- */
|
|
|
|
void Matrix_translate(Matrix a, double tx, double ty, double tz) {
|
|
Matrix_identity(a);
|
|
a[3] = tx;
|
|
a[7] = ty;
|
|
a[11] = tz;
|
|
a[15] = 1;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------
|
|
Matrix_rotatex(Matrix a, double deg)
|
|
|
|
Produce an x-rotation matrix for given angle in degrees.
|
|
----------------------------------------------------------------------- */
|
|
void
|
|
Matrix_rotatex(Matrix a, double deg) {
|
|
double r;
|
|
|
|
r = 3.1415926*deg/180.0;
|
|
Matrix_zero(a);
|
|
a[0] = 1.0;
|
|
a[5] = cos(r);
|
|
a[6] = -sin(r);
|
|
a[9] = sin(r);
|
|
a[10] = cos(r);
|
|
a[15] = 1.0;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------
|
|
Matrix_rotatey(Matrix a, double deg)
|
|
|
|
Produce an y-rotation matrix for given angle in degrees.
|
|
----------------------------------------------------------------------- */
|
|
void
|
|
Matrix_rotatey(Matrix a, double deg) {
|
|
double r;
|
|
|
|
r = 3.1415926*deg/180.0;
|
|
Matrix_zero(a);
|
|
a[0] = cos(r);
|
|
a[2] = sin(r);
|
|
a[5] = 1.0;
|
|
a[8] = -sin(r);
|
|
a[10] = cos(r);
|
|
a[15] = 1;
|
|
|
|
}
|
|
/* -----------------------------------------------------------------------
|
|
Matrix_RotateZ(Matrix a, double deg)
|
|
|
|
Produce an z-rotation matrix for given angle in degrees.
|
|
----------------------------------------------------------------------- */
|
|
void
|
|
Matrix_rotatez(Matrix a, double deg) {
|
|
double r;
|
|
|
|
r = 3.1415926*deg/180.0;
|
|
Matrix_zero(a);
|
|
a[0] = cos(r);
|
|
a[1] = -sin(r);
|
|
a[4] = sin(r);
|
|
a[5] = cos(r);
|
|
a[10] = 1.0;
|
|
a[15] = 1.0;
|
|
}
|
|
|
|
|
|
/* A debugging routine */
|
|
|
|
void Matrix_set(Matrix a, int i, int j, double val) {
|
|
a[4*j+i] = val;
|
|
}
|
|
|
|
void Matrix_print(Matrix a) {
|
|
int i,j;
|
|
for (i = 0; i < 4; i++) {
|
|
for (j = 0; j < 4; j++) {
|
|
fprintf(stdout,"%10f ",a[4*i+j]);
|
|
}
|
|
fprintf(stdout,"\n");
|
|
}
|
|
fprintf(stdout,"\n");
|
|
}
|
|
|