/*
* matrix.c -- matrix efuns.
* 2-93 : Dwayne Fontenot : original coding.
*/
#include "config.h"
#include <math.h>
#include "efuns.h"
#include "efuns_matrix.h"
#ifdef MATRIX
static Matrix identity = {1., 0., 0., 0.,
0., 1., 0., 0.,
0., 0., 1., 0.,
0., 0., 0., 1.};
void f_id_matrix(num_arg, instruction)
int num_arg, instruction;
{
struct vector *matrix;
int i;
matrix = allocate_array(16);
for(i=0;i<16;i++){
matrix->item[i].type = T_REAL;
matrix->item[i].u.real = identity[i];
}
push_vector(matrix);
matrix->ref--;
}
void f_translate(num_arg, instruction)
int num_arg, instruction;
{
struct vector *matrix;
double x, y, z;
Matrix current_matrix;
Matrix trans_matrix;
Matrix final_matrix;
int i;
if ((sp-1)->type != T_REAL) {
bad_arg(3, instruction);
}
if (sp->type != T_REAL) {
bad_arg(4, instruction);
}
/*
* get arguments from stack.
*/
matrix = (sp-3)->u.vec;
x = (sp-2)->u.real;
y = (sp-1)->u.real;
z = sp->u.real;
pop_n_elems(3);
/*
* convert vec matrix to float matrix.
*/
for(i=0;i<16;i++){
current_matrix[i] = matrix->item[i].u.real;
}
/*
* create translation matrix.
*/
translate_matrix(x, y, z, trans_matrix);
/*
* compute transformed matrix.
*/
mult_matrix(current_matrix, trans_matrix, final_matrix);
/*
* convert float matrix to vec matrix.
*/
for(i=0;i<16;i++){
matrix->item[i].u.real = final_matrix[i];
}
}
void f_scale(num_arg, instruction)
int num_arg, instruction;
{
struct vector *matrix;
double x, y, z;
Matrix current_matrix;
Matrix scaling_matrix;
Matrix final_matrix;
int i;
if ((sp-1)->type != T_REAL) {
bad_arg(3, instruction);
}
if (sp->type != T_REAL) {
bad_arg(4, instruction);
}
/*
* get arguments from stack.
*/
matrix = (sp-3)->u.vec;
x = (sp-2)->u.real;
y = (sp-1)->u.real;
z = sp->u.real;
pop_n_elems(3);
/*
* convert vec matrix to float matrix.
*/
for(i=0;i<16;i++){
current_matrix[i] = matrix->item[i].u.real;
}
/*
* create scaling matrix.
*/
scale_matrix(x, y, z, scaling_matrix);
/*
* compute transformed matrix.
*/
mult_matrix(current_matrix, scaling_matrix, final_matrix);
/*
* convert float matrix to vec matrix.
*/
for(i=0;i<16;i++){
matrix->item[i].u.real = final_matrix[i];
}
}
void f_rotate_x(num_arg, instruction)
int num_arg, instruction;
{
struct vector *matrix;
double angle;
Matrix current_matrix;
Matrix rot_matrix;
Matrix final_matrix;
int i;
/*
* get arguments from stack.
*/
matrix = (sp-1)->u.vec;
angle = sp->u.real;
pop_n_elems(1);
/*
* convert vec matrix to float matrix.
*/
for(i=0;i<16;i++){
current_matrix[i] = matrix->item[i].u.real;
}
/*
* create x rotation matrix.
*/
rotate_x_matrix(angle, rot_matrix);
/*
* compute transformed matrix.
*/
mult_matrix(current_matrix, rot_matrix, final_matrix);
/*
* convert float matrix to vec matrix.
*/
for(i=0;i<16;i++){
matrix->item[i].u.real = final_matrix[i];
}
}
void f_rotate_y(num_arg, instruction)
int num_arg, instruction;
{
struct vector *matrix;
double angle;
Matrix current_matrix;
Matrix rot_matrix;
Matrix final_matrix;
int i;
/*
* get arguments from stack.
*/
matrix = (sp-1)->u.vec;
angle = sp->u.real;
pop_n_elems(1);
/*
* convert vec matrix to float matrix.
*/
for(i=0;i<16;i++){
current_matrix[i] = matrix->item[i].u.real;
}
/*
* create y rotation matrix.
*/
rotate_y_matrix(angle, rot_matrix);
/*
* compute transformed matrix.
*/
mult_matrix(current_matrix, rot_matrix, final_matrix);
/*
* convert float matrix to vec matrix.
*/
for(i=0;i<16;i++){
matrix->item[i].u.real = final_matrix[i];
}
}
void f_rotate_z(num_arg, instruction)
int num_arg, instruction;
{
struct vector *matrix;
double angle;
Matrix current_matrix;
Matrix rot_matrix;
Matrix final_matrix;
int i;
/*
* get arguments from stack.
*/
matrix = (sp-1)->u.vec;
angle = sp->u.real;
pop_n_elems(1);
/*
* convert vec matrix to float matrix.
*/
for(i=0;i<16;i++){
current_matrix[i] = matrix->item[i].u.real;
}
/*
* create z rotation matrix.
*/
rotate_z_matrix(angle, rot_matrix);
/*
* compute transformed matrix.
*/
mult_matrix(current_matrix, rot_matrix, final_matrix);
/*
* convert float matrix to vec matrix.
*/
for(i=0;i<16;i++){
matrix->item[i].u.real = final_matrix[i];
}
}
void f_lookat_rotate(num_arg, instruction)
int num_arg, instruction;
{
struct vector *matrix;
double x, y, z;
Matrix current_matrix;
Matrix lookat_matrix;
int i;
if ((sp-1)->type != T_REAL) {
bad_arg(3, instruction);
}
if (sp->type != T_REAL) {
bad_arg(4, instruction);
}
/*
* get arguments from stack.
*/
matrix = (sp-3)->u.vec;
x = (sp-2)->u.real;
y = (sp-1)->u.real;
z = sp->u.real;
pop_n_elems(3);
/*
* convert vec matrix to float matrix.
*/
for(i=0;i<16;i++){
current_matrix[i] = matrix->item[i].u.real;
}
/*
* create new viewing transformation matrix.
*/
lookat_rotate(current_matrix, x, y, z, lookat_matrix);
/*
* convert float matrix to vec matrix.
*/
for(i=0;i<16;i++){
matrix->item[i].u.real = lookat_matrix[i];
}
}
void f_lookat_rotate2(num_arg, instruction)
int num_arg, instruction;
{
struct vector *matrix;
double ex, ey, ez, lx, ly, lz;
Matrix current_matrix;
Matrix lookat_matrix;
int i, j;
for (j = 4; j >= 0; j--) {
if ((sp-j)->type != T_REAL) {
bad_arg(7 - j, instruction);
}
}
/*
* get arguments from stack.
*/
matrix = (sp-6)->u.vec;
ex = (sp-5)->u.real;
ey = (sp-4)->u.real;
ez = (sp-3)->u.real;
lx = (sp-2)->u.real;
ly = (sp-1)->u.real;
lz = sp->u.real;
pop_n_elems(6);
/*
* convert vec matrix to float matrix.
*/
for(i=0;i<16;i++){
current_matrix[i] = matrix->item[i].u.real;
}
/*
* create new viewing transformation matrix.
*/
lookat_rotate2(ex, ey, ez, lx, ly, lz, lookat_matrix);
/*
* convert float matrix to vec matrix.
*/
for(i=0;i<16;i++){
matrix->item[i].u.real = lookat_matrix[i];
}
}
void print_matrix(m, label)
Matrix m;
char *label;
{
int i;
int j;
fprintf(stderr,"%s:\n", label);
for(i=0;i<4;i++){
for(j=0;j<4;j++){
fprintf(stderr,"%f\t", m[i * 4 + j]);
}
fprintf(stderr,"\n");
}
}
void print_vector(v, label)
Vector *v;
char *label;
{
fprintf(stderr,"%s:\t%f\t%f\t%f\n", label, v->x, v->y, v->z);
}
Vector *normalize_vector(v)
Vector *v;
{
double xx,yy,zz,mm,m;
xx = v->x * v->x ; yy = v->y * v->y ; zz = v->z * v->z;
mm = xx + yy + zz;
m = sqrt(mm);
if (m) {
v->x /= m ; v->y /= m ; v->z /= m;
}
return(v);
}
Vector *cross_product(v, va, vb)
Vector *v;
Vector *va;
Vector *vb;
{
v->x = (va->y*vb->z) - (va->z*vb->y);
v->y = (va->z*vb->x) - (va->x*vb->z);
v->z = (va->x*vb->y) - (va->y*vb->x);
return(v);
}
Vector *points_to_vector(v, pa, pb)
Vector *v;
Vector *pa;
Vector *pb;
{
v->x = pa->x - pb->x ; v->y = pa->y - pb->y ; v->z = pa->z - pb->z;
return(v);
}
void lookat_rotate(T, x, y, z, M)
Matrix T;
double x, y, z;
Matrix M;
{
static Vector N, V, U;
static Vector ep, lp;
lp.x = x; lp.y = y; lp.z = z;
ep.x = T[12]; ep.y = T[13]; ep.z = T[14];
points_to_vector(&N, &lp, &ep);
normalize_vector(&N);
U.x = T[0]; U.y = T[4]; U.z = T[8];
cross_product(&V, &N, &U);
normalize_vector(&V);
cross_product(&U, &V, &N);
normalize_vector(&U);
M[0] = U.x; M[1] = V.x; M[2] = N.x; M[3] = 0.;
M[4] = U.y; M[5] = V.y; M[6] = N.y; M[7] = 0.;
M[8] = U.z; M[9] = V.z; M[10]= N.z; M[11]= 0.;
#if 0
M[12]= ep.x; M[13]= ep.y; M[14]= ep.z; M[15]= 1.;
#endif
#if 0
M[12] = - U.x * ep.x - U.y * ep.y - U.z * ep.z;
M[13] = - V.x * ep.x - V.y * ep.y - V.z * ep.z;
M[14] = - N.x * ep.x - N.y * ep.y - N.z * ep.z;
#endif
M[12] = ((U.x * ep.x) + (U.y * ep.y) + (U.z * ep.z));
M[13] = ((V.x * ep.x) + (V.y * ep.y) + (V.z * ep.z));
M[14] = ((N.x * ep.x) + (N.y * ep.y) + (N.z * ep.z));
M[15] = 1.;
#ifdef DEBUG
print_vector(&lp, "look point");
print_vector(&ep, "eye point");
print_vector(&N, "normal vector");
print_vector(&V, "V = N x U");
print_vector(&U, "U = V x N");
print_matrix(&M, "final matrix");
#endif /* DEBUG */
}
void lookat_rotate2(ex, ey, ez, lx, ly, lz, M)
double ex, ey, ez;
double lx, ly, lz;
Matrix M;
{
static Vector N, V, U;
static Vector ep, lp;
ep.x = ex; ep.y = ey; ep.z = ez;
lp.x = lx; lp.y = ly; lp.z = lz;
points_to_vector(&N, &lp, &ep);
normalize_vector(&N);
U.x = 0.; U.y = 1.; U.z = 0.;
cross_product(&V, &N, &U);
normalize_vector(&V);
cross_product(&U, &V, &N);
normalize_vector(&U);
M[0] = U.x; M[1] = V.x; M[2] = N.x; M[3] = 0.;
M[4] = U.y; M[5] = V.y; M[6] = N.y; M[7] = 0.;
M[8] = U.z; M[9] = V.z; M[10]= N.z; M[11]= 0.;
#if 0
M[12]= ep.x; M[13]= ep.y; M[14]= ep.z; M[15]= 1.;
#endif
#if 0
M[12] = - U.x * ep.x - U.y * ep.y - U.z * ep.z;
M[13] = - V.x * ep.x - V.y * ep.y - V.z * ep.z;
M[14] = - N.x * ep.x - N.y * ep.y - N.z * ep.z;
#endif
M[12] = ((U.x * ep.x) + (U.y * ep.y) + (U.z * ep.z));
M[13] = ((V.x * ep.x) + (V.y * ep.y) + (V.z * ep.z));
M[14] = ((N.x * ep.x) + (N.y * ep.y) + (N.z * ep.z));
M[15] = 1.;
#ifdef DEBUG
print_vector(&lp, "look point");
print_vector(&ep, "eye point");
print_vector(&N, "normal vector");
print_vector(&V, "V = N x U");
print_vector(&U, "U = V x N");
print_matrix(&M, "final matrix");
#endif /* DEBUG */
}
void translate_matrix(x, y, z, m)
double x, y, z;
Matrix m;
{
m[0] = 1. ; m[1] = 0. ; m[2] = 0. ; m[3] = 0.;
m[4] = 0. ; m[5] = 1. ; m[6] = 0. ; m[7] = 0.;
m[8] = 0. ; m[9] = 0. ; m[10]= 1. ; m[11]= 0.;
m[12]= x ; m[13]= y ; m[14]= z ; m[15]= 1.;
}
void scale_matrix(x, y, z, m)
double x, y, z;
Matrix m;
{
m[0] = x ; m[1] = 0. ; m[2] = 0. ; m[3] = 0.;
m[4] = 0. ; m[5] = y ; m[6] = 0. ; m[7] = 0.;
m[8] = 0. ; m[9] = 0. ; m[10]= z ; m[11]= 0.;
m[12]= 0. ; m[13]= 0. ; m[14]= 0. ; m[15]= 1.;
}
void rotate_x_matrix(a, m)
double a;
Matrix m;
{
double a_rad;
double c, s;
a_rad = (double)(a * RADIANS_PER_DEGREE);
c = cos(a_rad);
s = sin(a_rad);
m[0] = 1. ; m[1] = 0. ; m[2] = 0. ; m[3] = 0.;
m[4] = 0. ; m[5] = c ; m[6] = s ; m[7] = 0.;
m[8] = 0. ; m[9] = -s ; m[10]= c ; m[11]= 0.;
m[12]= 0. ; m[13]= 0. ; m[14]= 0. ; m[15]= 1.;
}
void rotate_y_matrix(a, m)
double a;
Matrix m;
{
double a_rad;
double c, s;
a_rad = (double)(a * RADIANS_PER_DEGREE);
c = cos(a_rad);
s = sin(a_rad);
m[0] = c ; m[1] = 0. ; m[2] = -s ; m[3] = 0.;
m[4] = 0. ; m[5] = 1. ; m[6] = 0. ; m[7] = 0.;
m[8] = s ; m[9] = 0. ; m[10]= c ; m[11]= 0.;
m[12]= 0. ; m[13]= 0. ; m[14]= 0. ; m[15]= 1.;
}
void rotate_z_matrix(a, m)
double a;
Matrix m;
{
double a_rad;
double c, s;
a_rad = (double)(a * RADIANS_PER_DEGREE);
c = cos(a_rad);
s = sin(a_rad);
m[0] = c ; m[1] = s ; m[2] = 0. ; m[3] = 0.;
m[4] = -s ; m[5] = c ; m[6] = 0. ; m[7] = 0.;
m[8] = 0. ; m[9] = 0. ; m[10]= 1. ; m[11]= 0.;
m[12]= 0. ; m[13]= 0. ; m[14]= 0. ; m[15]= 1.;
}
void mult_matrix(ma, mb, m)
Matrix ma, mb, m;
{
m[0] = ma[0]*mb[0]+ma[1]*mb[4]+ma[2]*mb[8]+ma[3]*mb[12];
m[1] = ma[0]*mb[1]+ma[1]*mb[5]+ma[2]*mb[9]+ma[3]*mb[13];
m[2] = ma[0]*mb[2]+ma[1]*mb[6]+ma[2]*mb[10]+ma[3]*mb[14];
m[3] = ma[0]*mb[3]+ma[1]*mb[7]+ma[2]*mb[11]+ma[3]*mb[15];
m[4] = ma[4]*mb[0]+ma[5]*mb[4]+ma[6]*mb[8]+ma[7]*mb[12];
m[5] = ma[4]*mb[1]+ma[5]*mb[5]+ma[6]*mb[9]+ma[7]*mb[13];
m[6] = ma[4]*mb[2]+ma[5]*mb[6]+ma[6]*mb[10]+ma[7]*mb[14];
m[7] = ma[4]*mb[3]+ma[5]*mb[7]+ma[6]*mb[11]+ma[7]*mb[15];
m[8] = ma[8]*mb[0]+ma[9]*mb[4]+ma[10]*mb[8]+ma[11]*mb[12];
m[9] = ma[8]*mb[1]+ma[9]*mb[5]+ma[10]*mb[9]+ma[11]*mb[13];
m[10]= ma[8]*mb[2]+ma[9]*mb[6]+ma[10]*mb[10]+ma[11]*mb[14];
m[11]= ma[8]*mb[3]+ma[9]*mb[7]+ma[10]*mb[11]+ma[11]*mb[15];
m[12]= ma[12]*mb[0]+ma[13]*mb[4]+ma[14]*mb[8]+ma[15]*mb[12];
m[13]= ma[12]*mb[1]+ma[13]*mb[5]+ma[14]*mb[9]+ma[15]*mb[13];
m[14]= ma[12]*mb[2]+ma[13]*mb[6]+ma[14]*mb[10]+ma[15]*mb[14];
m[15]= ma[12]*mb[3]+ma[13]*mb[7]+ma[14]*mb[11]+ma[15]*mb[15];
}
#endif /* MATRIX */