689 lines
16 KiB
C
689 lines
16 KiB
C
/* -*-mode:c-*- */
|
|
/***************************************************************
|
|
*
|
|
* Radiosity
|
|
*
|
|
* Graphic driver for PostScript
|
|
*
|
|
*
|
|
***************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include "pslib.h"
|
|
|
|
#define SCREEN_WIDTH (6.0*72)
|
|
#define SCREEN_HEIGHT (4.8*72)
|
|
#define SCREEN_DEPTH (65536)
|
|
#define ASPECT_RATIO ((float)SCREEN_WIDTH/(float)SCREEN_HEIGHT)
|
|
|
|
#define PRE_CAT (1)
|
|
#define POST_CAT (0)
|
|
|
|
#define DEFAULT_WINDOW_HEIGHT (2000.0)
|
|
#define DEFAULT_WINDOW_WIDTH (DEFAULT_WINDOW_HEIGHT*ASPECT_RATIO)
|
|
#define DEFAULT_FRONT_PLANE_Z (2000.0)
|
|
#define DEFAULT_BACK_PLANE_Z (-4000.0)
|
|
#define DEFAULT_PRP_Z (10000.0) /* Projection point Z coord. */
|
|
|
|
/**************************************************
|
|
*
|
|
* Globals
|
|
*
|
|
***************************************************/
|
|
|
|
static Matrix trans_mtx ; /* WC -> DC */
|
|
static Vertex2 prp ; /* Projection point */
|
|
static Vertex2 active_prp ; /* Projection point in effect (WC) */
|
|
static float view_rotx, view_roty ; /* Viewing */
|
|
static float view_zoom ;
|
|
|
|
static float clip_right, clip_left ; /* View volume (X) */
|
|
static float clip_top, clip_bottom ; /* (Y) */
|
|
static float clip_front, clip_back ; /* (Z) */
|
|
|
|
|
|
static FILE *ps_fd ;
|
|
|
|
static void setup_transformation(void);
|
|
static void init_transformation(void);
|
|
static void gset_unit_matrix(Matrix *mtx);
|
|
static void gconcatenate_matrix(long precat, Matrix *m1, Matrix *m2);
|
|
static void gscale_matrix(long precat, Matrix *m1, float sx, float sy, float sz);
|
|
static void gtranslate_matrix(long precat, Matrix *m1, float tx, float ty, float tz);
|
|
static void grotate_x_matrix(long precat, Matrix *m1, float rot);
|
|
static void grotate_y_matrix(long precat, Matrix *m1, float rot);
|
|
static void gtransform(Vertex2 *v1, Vertex2 *v2, Matrix *mtx);
|
|
static void ginverse_matrix(Matrix *m1, Matrix *m2);
|
|
static double det(Matrix *m);
|
|
static double cdet(Matrix *m, long r0, long r1, long r2, long c0, long c1, long c2);
|
|
|
|
/************************************************************************
|
|
*
|
|
* ps_open()
|
|
* ps_close()
|
|
*
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
long ps_open(char *file)
|
|
{
|
|
if( (ps_fd = fopen( file, "w" )) == 0 )
|
|
{
|
|
perror( file ) ;
|
|
return( 0 ) ;
|
|
}
|
|
|
|
/* Print out preamble */
|
|
fprintf( ps_fd, "%%!PS-Adobe-1.0\n" ) ;
|
|
fprintf( ps_fd, "%%%%EndComments\n" ) ;
|
|
fprintf( ps_fd, "%%%%Pages: 1\n" ) ;
|
|
fprintf( ps_fd, "%%%%EndProlog\n" ) ;
|
|
fprintf( ps_fd, "%%%%Page: 1 1\n" ) ;
|
|
fprintf( ps_fd, "\n" ) ;
|
|
|
|
/* Default line cap/join */
|
|
fprintf( ps_fd, "1 setlinecap 1 setlinejoin\n" ) ;
|
|
|
|
/* Initialize transformation */
|
|
init_transformation() ;
|
|
setup_transformation() ;
|
|
return(0);
|
|
}
|
|
|
|
|
|
|
|
void ps_close()
|
|
{
|
|
if( ps_fd == 0 )
|
|
return ;
|
|
|
|
|
|
fprintf( ps_fd, "showpage\n" ) ;
|
|
fprintf( ps_fd, "%%%%Trailer\n" ) ;
|
|
fclose( ps_fd ) ;
|
|
|
|
ps_fd = 0 ;
|
|
}
|
|
|
|
|
|
|
|
/**************************************************
|
|
*
|
|
* ps_linewidth()
|
|
*
|
|
***************************************************/
|
|
|
|
void ps_linewidth(float w)
|
|
{
|
|
if( ps_fd == 0 )
|
|
return ;
|
|
|
|
fprintf( ps_fd, "%f setlinewidth\n", w ) ;
|
|
}
|
|
|
|
|
|
|
|
/**************************************************
|
|
*
|
|
* ps_line()
|
|
*
|
|
***************************************************/
|
|
|
|
void ps_line(Vertex *p1, Vertex *p2)
|
|
{
|
|
Vertex2 v1, v2 ;
|
|
float x1, y1, x2, y2 ;
|
|
|
|
if( ps_fd == 0 )
|
|
return ;
|
|
|
|
v1.v[0] = p1->x ; v1.v[1] = p1->y ; v1.v[2] = p1->z ; v1.v[3] = 1.0 ;
|
|
v2.v[0] = p2->x ; v2.v[1] = p2->y ; v2.v[2] = p2->z ; v2.v[3] = 1.0 ;
|
|
gtransform( &v1, &v1, &trans_mtx ) ;
|
|
gtransform( &v2, &v2, &trans_mtx ) ;
|
|
x1 = v1.v[0] / v1.v[3] ;
|
|
y1 = v1.v[1] / v1.v[3] ;
|
|
x2 = v2.v[0] / v2.v[3] ;
|
|
y2 = v2.v[1] / v2.v[3] ;
|
|
|
|
|
|
fprintf( ps_fd, "newpath\n%f %f moveto\n", x1, y1 ) ;
|
|
fprintf( ps_fd, "%f %f lineto\nstroke\n", x2, y2 ) ;
|
|
}
|
|
|
|
|
|
/**************************************************
|
|
*
|
|
* ps_polygonedge()
|
|
*
|
|
***************************************************/
|
|
|
|
void ps_polygonedge(long n, Vertex *p_list)
|
|
{
|
|
float dcx, dcy ;
|
|
Vertex2 v ;
|
|
long i ;
|
|
|
|
if( ps_fd == 0 )
|
|
return ;
|
|
|
|
/* Transform */
|
|
v.v[0] = p_list[0].x ;
|
|
v.v[1] = p_list[0].y ;
|
|
v.v[2] = p_list[0].z ;
|
|
v.v[3] = 1.0 ;
|
|
gtransform( &v, &v, &trans_mtx ) ;
|
|
dcx = v.v[0] / v.v[3] ;
|
|
dcy = v.v[1] / v.v[3] ;
|
|
fprintf( ps_fd, "newpath\n%f %f moveto\n", dcx, dcy ) ;
|
|
|
|
for( i = 1 ; i < n ; i++ )
|
|
{
|
|
/* Transform */
|
|
v.v[0] = p_list[i].x ;
|
|
v.v[1] = p_list[i].y ;
|
|
v.v[2] = p_list[i].z ;
|
|
v.v[3] = 1.0 ;
|
|
gtransform( &v, &v, &trans_mtx ) ;
|
|
dcx = v.v[0] / v.v[3] ;
|
|
dcy = v.v[1] / v.v[3] ;
|
|
|
|
fprintf( ps_fd, "%f %f lineto\n", dcx, dcy ) ;
|
|
}
|
|
|
|
fprintf( ps_fd, "closepath stroke\n" ) ;
|
|
}
|
|
|
|
|
|
/**************************************************
|
|
*
|
|
* ps_polygon()
|
|
*
|
|
***************************************************/
|
|
|
|
void ps_polygon(long n, Vertex *p_list)
|
|
{
|
|
float dcx, dcy ;
|
|
Vertex2 v ;
|
|
long i ;
|
|
|
|
if( ps_fd == 0 )
|
|
return ;
|
|
|
|
/* Transform */
|
|
v.v[0] = p_list[0].x ;
|
|
v.v[1] = p_list[0].y ;
|
|
v.v[2] = p_list[0].z ;
|
|
v.v[3] = 1.0 ;
|
|
gtransform( &v, &v, &trans_mtx ) ;
|
|
dcx = v.v[0] / v.v[3] ;
|
|
dcy = v.v[1] / v.v[3] ;
|
|
fprintf( ps_fd, "newpath\n%f %f moveto\n", dcx, dcy ) ;
|
|
|
|
for( i = 1 ; i < n ; i++ )
|
|
{
|
|
/* Transform */
|
|
v.v[0] = p_list[i].x ;
|
|
v.v[1] = p_list[i].y ;
|
|
v.v[2] = p_list[i].z ;
|
|
v.v[3] = 1.0 ;
|
|
gtransform( &v, &v, &trans_mtx ) ;
|
|
dcx = v.v[0] / v.v[3] ;
|
|
dcy = v.v[1] / v.v[3] ;
|
|
|
|
fprintf( ps_fd, "%f %f lineto\n", dcx, dcy ) ;
|
|
}
|
|
|
|
fprintf( ps_fd, "closepath fill\n" ) ;
|
|
}
|
|
|
|
|
|
/**************************************************
|
|
*
|
|
* ps_spolygon()
|
|
*
|
|
***************************************************/
|
|
|
|
void ps_spolygon(long n, Vertex *p_list, Rgb *c_list)
|
|
{
|
|
float dcx, dcy ;
|
|
Vertex2 v ;
|
|
long i ;
|
|
float gray_scale ;
|
|
|
|
if( ps_fd == 0 )
|
|
return ;
|
|
|
|
/* Transform */
|
|
v.v[0] = p_list[0].x ;
|
|
v.v[1] = p_list[0].y ;
|
|
v.v[2] = p_list[0].z ;
|
|
v.v[3] = 1.0 ;
|
|
gtransform( &v, &v, &trans_mtx ) ;
|
|
dcx = v.v[0] / v.v[3] ;
|
|
dcy = v.v[1] / v.v[3] ;
|
|
fprintf( ps_fd, "newpath\n%f %f moveto\n", dcx, dcy ) ;
|
|
|
|
for( i = 1 ; i < n ; i++ )
|
|
{
|
|
/* Transform */
|
|
v.v[0] = p_list[i].x ;
|
|
v.v[1] = p_list[i].y ;
|
|
v.v[2] = p_list[i].z ;
|
|
v.v[3] = 1.0 ;
|
|
gtransform( &v, &v, &trans_mtx ) ;
|
|
dcx = v.v[0] / v.v[3] ;
|
|
dcy = v.v[1] / v.v[3] ;
|
|
|
|
fprintf( ps_fd, "%f %f lineto\n", dcx, dcy ) ;
|
|
}
|
|
|
|
gray_scale = c_list[0].g ;
|
|
if( gray_scale > 1.0 )
|
|
gray_scale = 1.0 ;
|
|
else if( gray_scale < 0.0 )
|
|
gray_scale = 0.0 ;
|
|
|
|
fprintf( ps_fd, "closepath %f setgray fill\n", gray_scale ) ;
|
|
}
|
|
|
|
|
|
/**************************************************
|
|
*
|
|
* ps_clear()
|
|
*
|
|
***************************************************/
|
|
|
|
void ps_clear()
|
|
{
|
|
}
|
|
|
|
|
|
|
|
/**************************************************
|
|
*
|
|
* ps_setup_view()
|
|
*
|
|
***************************************************/
|
|
|
|
void ps_setup_view(float rot_x, float rot_y, float dist, float zoom)
|
|
{
|
|
prp.v[0] = 0.0 ;
|
|
prp.v[1] = 0.0 ;
|
|
prp.v[2] = (float)dist ;
|
|
prp.v[3] = 0.0 ;
|
|
view_rotx = rot_x ;
|
|
view_roty = rot_y ;
|
|
view_zoom = zoom ;
|
|
|
|
setup_transformation() ;
|
|
}
|
|
|
|
|
|
|
|
/**************************************************
|
|
*
|
|
* setup_transformation()
|
|
*
|
|
***************************************************/
|
|
|
|
static void setup_transformation()
|
|
{
|
|
float cf_z, cb_z ;
|
|
Matrix pmat ;
|
|
|
|
/* Set to unit matrix */
|
|
gset_unit_matrix( &trans_mtx ) ;
|
|
|
|
/* View orientation matrix */
|
|
grotate_x_matrix( POST_CAT, &trans_mtx, view_rotx ) ;
|
|
grotate_y_matrix( POST_CAT, &trans_mtx, view_roty ) ;
|
|
|
|
/* Compute active (currently effective) projection point */
|
|
ginverse_matrix( &pmat, &trans_mtx ) ;
|
|
gtransform( &active_prp, &prp, &pmat ) ;
|
|
|
|
/* Perspective projection */
|
|
gset_unit_matrix( &pmat ) ;
|
|
pmat.m[2][3] = - 1 / prp.v[2] ;
|
|
gconcatenate_matrix( POST_CAT, &trans_mtx, &pmat ) ;
|
|
|
|
cf_z = prp.v[2] * clip_front / ( prp.v[2] - clip_front ) ;
|
|
cb_z = prp.v[2] * clip_back / ( prp.v[2] - clip_back ) ;
|
|
|
|
/* Window-Viewport */
|
|
gscale_matrix( POST_CAT, &trans_mtx,
|
|
(float)SCREEN_WIDTH / (clip_right - clip_left),
|
|
(float)SCREEN_HEIGHT / (clip_top - clip_bottom),
|
|
(float)SCREEN_DEPTH / (cf_z - cb_z) ) ;
|
|
|
|
gtranslate_matrix( POST_CAT, &trans_mtx,
|
|
-(float)SCREEN_WIDTH * clip_left / (clip_right - clip_left),
|
|
-(float)SCREEN_HEIGHT* clip_top / (clip_bottom - clip_top),
|
|
-(float)SCREEN_DEPTH * cb_z / (cf_z - cb_z) ) ;
|
|
|
|
gtranslate_matrix( POST_CAT, &trans_mtx,
|
|
(float)(1.0*72), (float)(0.5*72), 0 ) ;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**************************************************
|
|
*
|
|
* init_transformation()
|
|
*
|
|
***************************************************/
|
|
|
|
static void init_transformation()
|
|
{
|
|
/* Initialize matrix, just in case */
|
|
gset_unit_matrix( &trans_mtx ) ;
|
|
|
|
/* Initialize Projection point */
|
|
prp.v[0] = 0.0 ;
|
|
prp.v[1] = 0.0 ;
|
|
prp.v[2] = DEFAULT_PRP_Z ;
|
|
prp.v[3] = 0.0 ;
|
|
|
|
/* Viewing */
|
|
view_rotx = view_roty = 0.0 ;
|
|
view_zoom = 1.0 ;
|
|
|
|
/* Initialize view volume boundary */
|
|
clip_right = DEFAULT_WINDOW_WIDTH / 2.0 ;
|
|
clip_left = -DEFAULT_WINDOW_WIDTH / 2.0 ;
|
|
clip_top = DEFAULT_WINDOW_HEIGHT / 2.0 ;
|
|
clip_bottom= -DEFAULT_WINDOW_HEIGHT / 2.0 ;
|
|
clip_front = DEFAULT_FRONT_PLANE_Z ;
|
|
clip_back = DEFAULT_BACK_PLANE_Z ;
|
|
}
|
|
|
|
|
|
/********************************************
|
|
*
|
|
* set_unit_matrix()
|
|
*
|
|
*********************************************/
|
|
|
|
static void gset_unit_matrix(Matrix *mtx)
|
|
{
|
|
long row, col ;
|
|
|
|
/* Clear the matrix */
|
|
for( row = 0 ; row < 4 ; row++ )
|
|
for( col = 0 ; col < 4 ; col++ )
|
|
mtx->m[row][col] = 0.0 ;
|
|
|
|
/* Set 1.0s along diagonal line */
|
|
for( row = 0 ; row < 4 ; row++ )
|
|
mtx->m[row][row] = 1.0 ;
|
|
}
|
|
|
|
|
|
|
|
|
|
/********************************************
|
|
*
|
|
* concatenate_matrix()
|
|
*
|
|
* m1 <- m1 * m2 (precat = 1)
|
|
* m1 <- m2 * m1 (precat = 0)
|
|
*
|
|
*********************************************/
|
|
|
|
static void gconcatenate_matrix(long precat, Matrix *m1, Matrix *m2)
|
|
{
|
|
long row, col, scan ;
|
|
Matrix *dest ;
|
|
Matrix temp ;
|
|
|
|
|
|
/* Swap pointer according to the concatenation mode */
|
|
dest = m1 ;
|
|
if( precat == 1 )
|
|
{
|
|
m1 = m2 ;
|
|
m2 = dest ;
|
|
}
|
|
|
|
/* concatenate it */
|
|
for( row = 0 ; row < 4 ; row++ )
|
|
for( col = 0 ; col < 4 ; col++ )
|
|
{
|
|
temp.m[row][col] = 0.0 ;
|
|
for( scan = 0 ; scan < 4 ; scan++ )
|
|
temp.m[row][col] +=
|
|
m1->m[row][scan] * m2->m[scan][col];
|
|
}
|
|
|
|
*dest = temp ;
|
|
}
|
|
|
|
|
|
/********************************************
|
|
*
|
|
* scale_matrix()
|
|
*
|
|
* m1 <- SCALE * m1 (precat = 1)
|
|
* m1 <- m1 * SCALE (precat = 0)
|
|
*
|
|
*********************************************/
|
|
|
|
static void gscale_matrix(long precat, Matrix *m1, float sx, float sy, float sz)
|
|
{
|
|
Matrix smat ;
|
|
|
|
/* Initialize to unit matrix */
|
|
gset_unit_matrix( &smat ) ;
|
|
|
|
/* Set scale values */
|
|
smat.m[0][0] = sx ;
|
|
smat.m[1][1] = sy ;
|
|
smat.m[2][2] = sz ;
|
|
|
|
/* concatenate */
|
|
gconcatenate_matrix( precat, m1, &smat ) ;
|
|
}
|
|
|
|
|
|
|
|
/********************************************
|
|
*
|
|
* translate_matrix()
|
|
*
|
|
* m1 <- T * m1 (precat = 1)
|
|
* m1 <- m1 * T (precat = 0)
|
|
*
|
|
*********************************************/
|
|
|
|
static void gtranslate_matrix(long precat, Matrix *m1, float tx, float ty, float tz)
|
|
{
|
|
Matrix tmat ;
|
|
|
|
/* Initialize to unit matrix */
|
|
gset_unit_matrix( &tmat ) ;
|
|
|
|
/* Set scale values */
|
|
tmat.m[3][0] = tx ;
|
|
tmat.m[3][1] = ty ;
|
|
tmat.m[3][2] = tz ;
|
|
|
|
/* concatenate */
|
|
gconcatenate_matrix( precat, m1, &tmat ) ;
|
|
}
|
|
|
|
|
|
|
|
/********************************************
|
|
*
|
|
* rotate_x_matrix()
|
|
* rotate_y_matrix()
|
|
* rotate_z_matrix()
|
|
*
|
|
* m1 <- ROT * m1 (precat = 1)
|
|
* m1 <- m1 * ROT (precat = 0)
|
|
*
|
|
*********************************************/
|
|
|
|
static void grotate_x_matrix(long precat, Matrix *m1, float rot)
|
|
{
|
|
Matrix rmat ;
|
|
float s_val, c_val ;
|
|
|
|
/* Initialize to unit matrix */
|
|
gset_unit_matrix( &rmat ) ;
|
|
|
|
/* Set scale values */
|
|
s_val = sin( rot * M_PI / 180.0 ) ;
|
|
c_val = cos( rot * M_PI / 180.0 ) ;
|
|
rmat.m[1][1] = c_val ;
|
|
rmat.m[1][2] = s_val ;
|
|
rmat.m[2][1] = -s_val ;
|
|
rmat.m[2][2] = c_val ;
|
|
|
|
/* concatenate */
|
|
gconcatenate_matrix( precat, m1, &rmat ) ;
|
|
}
|
|
|
|
|
|
|
|
|
|
static void grotate_y_matrix(long precat, Matrix *m1, float rot)
|
|
{
|
|
Matrix rmat ;
|
|
float s_val, c_val ;
|
|
|
|
/* Initialize to unit matrix */
|
|
gset_unit_matrix( &rmat ) ;
|
|
|
|
/* Set scale values */
|
|
s_val = sin( rot * M_PI / 180.0 ) ;
|
|
c_val = cos( rot * M_PI / 180.0 ) ;
|
|
rmat.m[0][0] = c_val ;
|
|
rmat.m[0][2] = -s_val ;
|
|
rmat.m[2][0] = s_val ;
|
|
rmat.m[2][2] = c_val ;
|
|
|
|
/* concatenate */
|
|
gconcatenate_matrix( precat, m1, &rmat ) ;
|
|
}
|
|
|
|
|
|
|
|
|
|
/********************************************
|
|
*
|
|
* transform()
|
|
*
|
|
* v1 <- v2 * mtx
|
|
*
|
|
*********************************************/
|
|
|
|
static void gtransform(Vertex2 *v1, Vertex2 *v2, Matrix *mtx)
|
|
{
|
|
float x, y, z, w ;
|
|
|
|
x = v2->v[0] * mtx->m[0][0] ;
|
|
y = v2->v[0] * mtx->m[0][1] ;
|
|
z = v2->v[0] * mtx->m[0][2] ;
|
|
w = v2->v[0] * mtx->m[0][3] ;
|
|
|
|
x += v2->v[1] * mtx->m[1][0] ;
|
|
y += v2->v[1] * mtx->m[1][1] ;
|
|
z += v2->v[1] * mtx->m[1][2] ;
|
|
w += v2->v[1] * mtx->m[1][3] ;
|
|
|
|
x += v2->v[2] * mtx->m[2][0] ;
|
|
y += v2->v[2] * mtx->m[2][1] ;
|
|
z += v2->v[2] * mtx->m[2][2] ;
|
|
w += v2->v[2] * mtx->m[2][3] ;
|
|
|
|
x += v2->v[3] * mtx->m[3][0] ;
|
|
y += v2->v[3] * mtx->m[3][1] ;
|
|
z += v2->v[3] * mtx->m[3][2] ;
|
|
w += v2->v[3] * mtx->m[3][3] ;
|
|
|
|
v1->v[0] = x ;
|
|
v1->v[1] = y ;
|
|
v1->v[2] = z ;
|
|
v1->v[3] = w ;
|
|
}
|
|
|
|
|
|
/********************************************
|
|
*
|
|
* inverse_matrix()
|
|
*
|
|
* m1 <- inv(m2)
|
|
*
|
|
*********************************************/
|
|
|
|
|
|
static void ginverse_matrix(Matrix *m1, Matrix *m2)
|
|
{
|
|
double detval ;
|
|
|
|
/* det(m2) */
|
|
detval = det( m2 ) ;
|
|
|
|
/* Clamel's solution */
|
|
m1->m[0][0] = cdet( m2, 1,2,3, 1,2,3 ) / detval ;
|
|
m1->m[0][1] = -cdet( m2, 0,2,3, 1,2,3 ) / detval ;
|
|
m1->m[0][2] = cdet( m2, 0,1,3, 1,2,3 ) / detval ;
|
|
m1->m[0][3] = -cdet( m2, 0,1,2, 1,2,3 ) / detval ;
|
|
|
|
m1->m[1][0] = -cdet( m2, 1,2,3, 0,2,3 ) / detval ;
|
|
m1->m[1][1] = cdet( m2, 0,2,3, 0,2,3 ) / detval ;
|
|
m1->m[1][2] = -cdet( m2, 0,1,3, 0,2,3 ) / detval ;
|
|
m1->m[1][3] = cdet( m2, 0,1,2, 0,2,3 ) / detval ;
|
|
|
|
m1->m[2][0] = cdet( m2, 1,2,3, 0,1,3 ) / detval ;
|
|
m1->m[2][1] = -cdet( m2, 0,2,3, 0,1,3 ) / detval ;
|
|
m1->m[2][2] = cdet( m2, 0,1,3, 0,1,3 ) / detval ;
|
|
m1->m[2][3] = -cdet( m2, 0,1,2, 0,1,3 ) / detval ;
|
|
|
|
m1->m[3][0] = -cdet( m2, 1,2,3, 0,1,2 ) / detval ;
|
|
m1->m[3][1] = cdet( m2, 0,2,3, 0,1,2 ) / detval ;
|
|
m1->m[3][2] = -cdet( m2, 0,1,3, 0,1,2 ) / detval ;
|
|
m1->m[3][3] = cdet( m2, 0,1,2, 0,1,2 ) / detval ;
|
|
}
|
|
|
|
|
|
|
|
static double det(Matrix *m)
|
|
{
|
|
double det_sum ;
|
|
|
|
/* Expand with respect to column 4 */
|
|
det_sum = 0.0 ;
|
|
if( m->m[0][3] != 0.0 )
|
|
det_sum -= m->m[0][3] * cdet( m, 1, 2, 3, 0, 1, 2 ) ;
|
|
if( m->m[1][3] != 0.0 )
|
|
det_sum += m->m[1][3] * cdet( m, 0, 2, 3, 0, 1, 2 ) ;
|
|
if( m->m[2][3] != 0.0 )
|
|
det_sum -= m->m[2][3] * cdet( m, 0, 1, 3, 0, 1, 2 ) ;
|
|
if( m->m[3][3] != 0.0 )
|
|
det_sum += m->m[3][3] * cdet( m, 0, 1, 2, 0, 1, 2 ) ;
|
|
|
|
return( det_sum ) ;
|
|
}
|
|
|
|
|
|
static double cdet(Matrix *m, long r0, long r1, long r2, long c0, long c1, long c2)
|
|
{
|
|
double temp ;
|
|
|
|
temp = m->m[r0][c0] * m->m[r1][c1] * m->m[r2][c2] ;
|
|
temp += m->m[r1][c0] * m->m[r2][c1] * m->m[r0][c2] ;
|
|
temp += m->m[r2][c0] * m->m[r0][c1] * m->m[r1][c2] ;
|
|
|
|
temp -= m->m[r2][c0] * m->m[r1][c1] * m->m[r0][c2] ;
|
|
temp -= m->m[r1][c0] * m->m[r0][c1] * m->m[r2][c2] ;
|
|
temp -= m->m[r0][c0] * m->m[r2][c1] * m->m[r1][c2] ;
|
|
|
|
return( temp ) ;
|
|
}
|