home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
GRAPHICS
/
rayshade.lzh
/
matrix.c
< prev
next >
Wrap
Text File
|
1990-05-08
|
10KB
|
386 lines
/*
* matrix.c
*
* Copyright (C) 1989, Craig E. Kolb
*
* This software may be freely copied, modified, and redistributed,
* provided that this copyright notice is preserved on all copies.
*
* There is no warranty or other guarantee of fitness for this software,
* it is provided solely . Bug reports or fixes may be sent
* to the author, who may or may not act on them as he desires.
*
* You may not include this software in a program or other software product
* without supplying the source, or without informing the end-user that the
* source is available for no extra charge.
*
* If you modify this software, you should include a notice giving the
* name of the person performing the modification, the date of modification,
* and the reason for such modification.
*
* $Id: matrix.c,v 3.0.1.1 89/11/18 14:05:11 craig Exp Locker: craig $
*
* $Log: matrix.c,v $
* Revision 3.0.1.1 89/11/18 14:05:11 craig
* patch1: Renamed rotate(), translate() and scale() to avoid problems
* patch1: with external libraries.
*
* Revision 3.0 89/10/27 02:05:56 craig
* Baseline for first official release.
*
*/
#include <math.h>
#include <stdio.h>
#include "typedefs.h"
#include "constants.h"
#include "funcdefs.h"
/*
* Matrices are indexed row-first; that is:
* matrix[ROW][COLUMN]
*/
/*
* Allocate new structure which holds both object-to-world and
* world-to-object space transformation structures. It probably
* should hold pointers to these structures.
*/
Trans *
new_trans(t, it)
TransInfo *t, *it;
{
Trans *res;
res = (Trans *)Malloc(sizeof(Trans));
res->obj2world = *t;
res->world2obj = *it;
return res;
}
/*
* Allocate new transformation structure.
*/
TransInfo *
new_transinfo()
{
TransInfo *res;
res = (TransInfo *)Malloc(sizeof(TransInfo));
init_trans(res);
return res;
}
/*
* Set up matrix for counter-clockwise rotation about vector (x, y, z) by
* theta radians.
*/
rotate_trans(trans, x, y, z, theta)
TransInfo *trans;
double x, y, z, theta;
{
double n1, n2, n3, sintheta, costheta;
Vector vector;
vector.x = x;
vector.y = y;
vector.z = z;
(void)normalize(&vector);
sintheta = sin(theta);
costheta = cos(theta);
n1 = vector.x; n2 = vector.y; n3 = vector.z;
trans->matrix[0][0] = (double)(n1*n1 + (1. - n1*n1)*costheta);
trans->matrix[1][0] = (double)(n1*n2*(1 - costheta) + n3*sintheta);
trans->matrix[2][0] = (double)(n1*n3*(1 - costheta) - n2*sintheta);
trans->matrix[0][1] = (double)(n1*n2*(1 - costheta) - n3*sintheta);
trans->matrix[1][1] = (double)(n2*n2 + (1 - n2*n2)*costheta);
trans->matrix[2][1] = (double)(n2*n3*(1 - costheta) + n1*sintheta);
trans->matrix[0][2] = (double)(n1*n3*(1 - costheta) + n2*sintheta);
trans->matrix[1][2] = (double)(n2*n3*(1 - costheta) - n1*sintheta);
trans->matrix[2][2] = (double)(n3*n3 + (1 - n3*n3)*costheta);
trans->translate.x = trans->translate.y = trans->translate.z = 0.;
}
/*
* Apply translation by (vec) to trans.
*/
RS_translate(trans, vec)
TransInfo *trans;
Vector *vec;
{
trans->translate.x += vec->x;
trans->translate.y += vec->y;
trans->translate.z += vec->z;
}
/*
* Apply rotation about (dir) to matrix.
*/
RS_rotate(trans, dir, radians)
TransInfo *trans;
double radians;
Vector *dir;
{
TransInfo ttmp;
rotate_trans(&ttmp, dir->x, dir->y, dir->z, radians);
mmult(trans, &ttmp, trans);
}
/*
* Apply scale of (x, y, z) to trans.
*/
RS_scale(trans, x, y, z)
TransInfo *trans;
double x, y, z;
{
trans->matrix[0][0] *= x;
trans->matrix[1][0] *= x;
trans->matrix[2][0] *= x;
trans->matrix[0][1] *= y;
trans->matrix[1][1] *= y;
trans->matrix[2][1] *= y;
trans->matrix[0][2] *= z;
trans->matrix[1][2] *= z;
trans->matrix[2][2] *= z;
trans->translate.x *= x;
trans->translate.y *= y;
trans->translate.z *= z;
}
/*
* Multiply m1 and m2, copy result into "res".
*/
mmult(t1, t2, res)
TransInfo *t1, *t2, *res;
{
register int i, j, k;
TransInfo tmp;
for(i = 0; i < 3; i++) {
for(j = 0; j < 3;j++) {
tmp.matrix[i][j] = 0.;
for(k = 0; k < 3;k++)
tmp.matrix[i][j] += t1->matrix[i][k] *
t2->matrix[k][j];
}
}
tmp.translate.x = t1->translate.x * t2->matrix[0][0] +
t1->translate.y * t2->matrix[1][0] +
t1->translate.z * t2->matrix[2][0] +
t2->translate.x;
tmp.translate.y = t1->translate.x * t2->matrix[0][1] +
t1->translate.y * t2->matrix[1][1] +
t1->translate.z * t2->matrix[2][1] +
t2->translate.y;
tmp.translate.z = t1->translate.x * t2->matrix[0][2] +
t1->translate.y * t2->matrix[1][2] +
t1->translate.z * t2->matrix[2][2] +
t2->translate.z;
copy_trans(res, &tmp);
}
/*
* Copy a given transformation structure.
*/
copy_trans(into, from)
TransInfo *into, *from;
{
register int i;
for(i = 0;i < 3;i++) {
into->matrix[i][0] = from->matrix[i][0];
into->matrix[i][1] = from->matrix[i][1];
into->matrix[i][2] = from->matrix[i][2];
}
into->translate = from->translate;
}
/*
* Initialize transformation structure.
*/
init_trans(trans)
TransInfo *trans;
{
register int i, j;
for(i = 0;i < 3;i++)
for(j = 0;j < 3;j++)
trans->matrix[i][j] = (double)(i == j);
trans->translate.x = trans->translate.y = trans->translate.z = 0.;
}
/*
* Calculate inverse of the given transformation structure.
*/
invert_trans(inverse, trans)
TransInfo *inverse, *trans;
{
TransInfo ttmp;
int i;
double d;
extern int yylineno;
ttmp.matrix[0][0] = trans->matrix[1][1]*trans->matrix[2][2] -
trans->matrix[1][2]*trans->matrix[2][1];
ttmp.matrix[1][0] = trans->matrix[1][0]*trans->matrix[2][2] -
trans->matrix[1][2]*trans->matrix[2][0];
ttmp.matrix[2][0] = trans->matrix[1][0]*trans->matrix[2][1] -
trans->matrix[1][1]*trans->matrix[2][0];
ttmp.matrix[0][1] = trans->matrix[0][1]*trans->matrix[2][2] -
trans->matrix[0][2]*trans->matrix[2][1];
ttmp.matrix[1][1] = trans->matrix[0][0]*trans->matrix[2][2] -
trans->matrix[0][2]*trans->matrix[2][0];
ttmp.matrix[2][1] = trans->matrix[0][0]*trans->matrix[2][1] -
trans->matrix[0][1]*trans->matrix[2][0];
ttmp.matrix[0][2] = trans->matrix[0][1]*trans->matrix[1][2] -
trans->matrix[0][2]*trans->matrix[1][1];
ttmp.matrix[1][2] = trans->matrix[0][0]*trans->matrix[1][2] -
trans->matrix[0][2]*trans->matrix[1][0];
ttmp.matrix[2][2] = trans->matrix[0][0]*trans->matrix[1][1] -
trans->matrix[0][1]*trans->matrix[1][0];
d = trans->matrix[0][0]*ttmp.matrix[0][0] -
trans->matrix[0][1]*ttmp.matrix[1][0] +
trans->matrix[0][2]*ttmp.matrix[2][0];
if (abs(d) < EPSILON*EPSILON) {
fprintf(stderr,"Singular matrix (line %d):\n",yylineno);
for (i = 0; i < 3; i++)
fprintf(stderr,"%g %g %g\n", trans->matrix[i][0],
trans->matrix[i][1], trans->matrix[i][2]);
exit(0);
}
ttmp.matrix[0][0] /= d;
ttmp.matrix[0][2] /= d;
ttmp.matrix[1][1] /= d;
ttmp.matrix[2][0] /= d;
ttmp.matrix[2][2] /= d;
d = -d;
ttmp.matrix[0][1] /= d;
ttmp.matrix[1][0] /= d;
ttmp.matrix[1][2] /= d;
ttmp.matrix[2][1] /= d;
ttmp.translate.x = -(ttmp.matrix[0][0]*trans->translate.x +
ttmp.matrix[1][0]*trans->translate.y +
ttmp.matrix[2][0]*trans->translate.z);
ttmp.translate.y = -(ttmp.matrix[0][1]*trans->translate.x +
ttmp.matrix[1][1]*trans->translate.y +
ttmp.matrix[2][1]*trans->translate.z);
ttmp.translate.z = -(ttmp.matrix[0][2]*trans->translate.x +
ttmp.matrix[1][2]*trans->translate.y +
ttmp.matrix[2][2]*trans->translate.z);
copy_trans(inverse, &ttmp);
}
/*
* Apply a transformation to a point (translation affects the point).
*/
transform_point(vec, trans)
Vector *vec;
TransInfo *trans;
{
Vector tmp;
tmp.x = vec->x * trans->matrix[0][0] + vec->y * trans->matrix[1][0] +
vec->z * trans->matrix[2][0] + trans->translate.x;
tmp.y = vec->x * trans->matrix[0][1] + vec->y * trans->matrix[1][1] +
vec->z * trans->matrix[2][1] + trans->translate.y;
tmp.z = vec->x * trans->matrix[0][2] + vec->y * trans->matrix[1][2] +
vec->z * trans->matrix[2][2] + trans->translate.z;
*vec = tmp;
}
/*
* Apply an explicit transformation to the given transformation structure.
* 'c1x' is the X (0th) component of the first column, and so on.
*/
explicit_trans(trans, c1x,c1y,c1z, c2x,c2y,c2z, c3x,c3y,c3z, tx, ty, tz, res)
TransInfo *trans, *res;
double c1x, c1y, c1z, c2x, c2y, c2z, c3x, c3y, c3z, tx, ty, tz;
{
TransInfo tmp;
tmp.matrix[0][0] = c1x;
tmp.matrix[1][0] = c1y;
tmp.matrix[2][0] = c1z;
tmp.matrix[0][1] = c2x;
tmp.matrix[1][1] = c2y;
tmp.matrix[2][1] = c2z;
tmp.matrix[0][2] = c3x;
tmp.matrix[1][2] = c3y;
tmp.matrix[2][2] = c3z;
tmp.translate.x = tx;
tmp.translate.y = ty;
tmp.translate.z = tz;
mmult(trans, &tmp, res);
}
/*
* Apply transformation to a vector (translations have no effect).
*/
transform_vector(vec, trans)
Vector *vec;
TransInfo *trans;
{
Vector tmp;
tmp.x = vec->x*trans->matrix[0][0] +
vec->y*trans->matrix[1][0] + vec->z*trans->matrix[2][0];
tmp.y = vec->x*trans->matrix[0][1] +
vec->y*trans->matrix[1][1] + vec->z*trans->matrix[2][1];
tmp.z = vec->x*trans->matrix[0][2] +
vec->y*trans->matrix[1][2] + vec->z*trans->matrix[2][2];
*vec = tmp;
}
/*
* Transform "ray" by transforming the origin point and direction vector.
*/
double
TransformRay(ray, trans)
Ray *ray;
TransInfo *trans;
{
transform_point(&ray->pos, trans);
transform_vector(&ray->dir, trans);
return normalize(&ray->dir);
}
/*
* Transform normal -- multiply by the transpose of the given
* matrix (which is the inverse of the desired transformation).
*/
TransformNormal(norm, it)
Vector *norm;
TransInfo *it;
{
Vector onorm;
onorm = *norm;
norm->x = onorm.x*it->matrix[0][0] + onorm.y*it->matrix[0][1] +
onorm.z*it->matrix[0][2];
norm->y = onorm.x*it->matrix[1][0] + onorm.y*it->matrix[1][1] +
onorm.z*it->matrix[1][2];
norm->z = onorm.x*it->matrix[2][0] + onorm.y*it->matrix[2][1] +
onorm.z*it->matrix[2][2];
}