blob: 8e210f41db68eed9d4e7934b9c736b7076da37a5 [file] [log] [blame]
/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
/******************************************************************************
* *
* view.c: Compute viewing direction. *
* *
******************************************************************************/
#include "incl.h"
#define XAXIS 1 /* Positive X-axis points rightwards */
#define YAXIS 2 /* Positive Y-axis points upwards */
#define ZAXIS 3 /* Positive Z-axis points into screen */
float transformation_matrix[4][4];/* current transformation matrix of floats */
float out_invvertex[2][2][2][NM]; /* Image and object space centers */
/* of outer voxels in output map */
float uout_invvertex[2][2][2][NM];/* Image and object space vertices */
/* of output map unit voxel */
long frust_len; /* Size of clipping frustum */
/* (mins will be 0 in this program, */
/* {x,y}len will be <= IK{X,Y}SIZE) */
float out_diag_len[NM]; /* Per-axis lengths and combined length of */
float out_diag_length; /* diagonal of input map in image space */
float depth_cueing[MAX_OUTLEN]; /* Pre-computed table of depth cueing */
long image_zlen; /* number of samples along viewing ray */
float in_max[NM]; /* Pre-computed clipping aids */
long opc_xlen,opc_xylen;
long norm_xlen,norm_xylen;
float invmatrix[4][4]; /* Inverse of viewing matrix: */
/* 4 x 4 viewing transformation matrix */
/* (orthographic projection used, so */
/* matrix[][3] = 0, matrix[3][3] = 1) */
EXTERN_ENV
void Compute_Pre_View()
{
long i, outz;
for (i=0; i<NM; i++)
out_diag_len[i] = opc_len[i]-1;
out_diag_length = out_diag_len[X]*out_diag_len[X] +
out_diag_len[Y]*out_diag_len[Y] +
out_diag_len[Z]*out_diag_len[Z];
out_diag_length = sqrt(out_diag_length);
frust_len = NINT(out_diag_length)+1;
image_zlen = frust_len - 1;
/* Pre-compute table of depth cueing attenuation fractions as */
/* exponential falloff from intensity of depth_hither*full at */
/* hither (outz=0) to depth_yon*full at yon (frust_len-1). */
/* Exponent > 1.0 falls off slower than linear, < 1.0 falls faster. */
/* Clip fractions to valid range to allow agressive user */
/* to set hither or yon outside the range 0.0..1.0. */
if (image_zlen > MAX_OUTLEN)
Error ("MAX_OUTLEN exceeded in Ray_Trace.\n");
for (outz=0; outz<=image_zlen; outz++) {
depth_cueing[outz] = depth_hither -
pow((float)(outz)/(float)image_zlen,depth_exponent) *
(depth_hither - depth_yon);
depth_cueing[outz] = MIN(MAX(depth_cueing[outz],0.0),1.0);
}
/* Pre-compute clipping aids */
in_max[X] = (float)(opc_len[X]-1)-SMALL-1.0/(float)MAX_PIXEL;
in_max[Y] = (float)(opc_len[Y]-1)-SMALL-1.0/(float)MAX_PIXEL;
in_max[Z] = (float)(opc_len[Z]-1)-SMALL-1.0/(float)MAX_PIXEL;
/* Pre-compute subscripting aids */
opc_xlen = opc_len[X] + 1;
opc_xylen = opc_len[X] * opc_len[Y] + 1;
norm_xlen = norm_len[X] + 1;
norm_xylen = norm_len[X] * norm_len[Y] + 1;
}
void Select_View(delta_angle, axis)
float delta_angle;
long axis;
{
Load_Identity_Matrix(invmatrix);
/* Moves input map from all-positive octant to center of */
/* coordinate system so subsequent rotations spin object */
/* in place. Must be first after initialization to work. */
Inverse_Concatenate_Translation(invmatrix,
(float)(out_diag_len[X])/2.0,
(float)(out_diag_len[Y])/2.0,
(float)(out_diag_len[Z])/2.0);
/* scale dataset size in Z-direction for 256x256x113 dataset */
Inverse_Concatenate_Scaling(invmatrix,1.0,1.0,1.0/(float)ZSCALE);
/* rotation about axis by angle */
if (frame != 0)
angle[axis] = angle[axis] + delta_angle;
Inverse_Concatenate_Rotation(invmatrix,XAXIS,-angle[X]);
Inverse_Concatenate_Rotation(invmatrix,YAXIS,-angle[Y]);
/* Inverse_Concatenate_Rotation(invmatrix,ZAXIS,-angle[Z]);*/
Inverse_Concatenate_Rotation(invmatrix,XAXIS,30.0);
/* Moves input map from center of coordinate system back */
/* to within all-positive octant such that any rotation */
/* (e.g. by using pre-matrix, rotations, and anpost-matrix) */
/* exactly falls in the octant, preventing low-side clipping.*/
/* Fails if non-isotropic image space scaling is applied */
/* (i.e. different scaling in X,Y, or Z after rotations). */
Inverse_Concatenate_Translation(invmatrix,
-out_diag_length/2.0,
-out_diag_length/2.0,
-out_diag_length/2.0);
/* Insures that frustum entirely encloses any rotation of */
/* map assuming they fall within the all-positive octant */
/* (e.g. by using pre-matrix, rotations, and anpost-matrix), */
Load_Transformation_Matrix(invmatrix);
Compute_Input_Dimensions();
Compute_Input_Unit_Vector();
}
void Compute_Input_Dimensions()
{
long x,y,z;
float in_invvertex[2][2][2][NM]; /* Image and object space centers */
in_invvertex[0][0][0][X] = 0;
in_invvertex[0][0][0][Y] = 0;
in_invvertex[0][0][0][Z] = 0;
in_invvertex[0][0][1][X] = frust_len-1;
in_invvertex[0][0][1][Y] = 0;
in_invvertex[0][0][1][Z] = 0;
in_invvertex[0][1][0][X] = 0;
in_invvertex[0][1][0][Y] = frust_len-1;
in_invvertex[0][1][0][Z] = 0;
in_invvertex[0][1][1][X] = frust_len-1;
in_invvertex[0][1][1][Y] = frust_len-1;
in_invvertex[0][1][1][Z] = 0;
in_invvertex[1][0][0][X] = 0;
in_invvertex[1][0][0][Y] = 0;
in_invvertex[1][0][0][Z] = frust_len-1;
in_invvertex[1][0][1][X] = frust_len-1;
in_invvertex[1][0][1][Y] = 0;
in_invvertex[1][0][1][Z] = frust_len-1;
in_invvertex[1][1][0][X] = 0;
in_invvertex[1][1][0][Y] = frust_len-1;
in_invvertex[1][1][0][Z] = frust_len-1;
in_invvertex[1][1][1][X] = frust_len-1;
in_invvertex[1][1][1][Y] = frust_len-1;
in_invvertex[1][1][1][Z] = frust_len-1;
for (z=0; z<2; z++) {
for (y=0; y<2; y++) {
for (x=0; x<2; x++) {
Transform_Point(in_invvertex[z][y][x][X],
in_invvertex[z][y][x][Y],
in_invvertex[z][y][x][Z],
&out_invvertex[z][y][x][X],
&out_invvertex[z][y][x][Y],
&out_invvertex[z][y][x][Z]);
}
}
}
}
void Compute_Input_Unit_Vector()
{
long x,y,z;
float uin_invvertex[2][2][2][NM];
uin_invvertex[0][0][0][X] = 0;
uin_invvertex[0][0][0][Y] = 0;
uin_invvertex[0][0][0][Z] = 0;
uin_invvertex[0][0][1][X] = 1.0;
uin_invvertex[0][0][1][Y] = 0;
uin_invvertex[0][0][1][Z] = 0;
uin_invvertex[0][1][0][X] = 0;
uin_invvertex[0][1][0][Y] = 1.0;
uin_invvertex[0][1][0][Z] = 0;
uin_invvertex[0][1][1][X] = 1.0;
uin_invvertex[0][1][1][Y] = 1.0;
uin_invvertex[0][1][1][Z] = 0;
uin_invvertex[1][0][0][X] = 0;
uin_invvertex[1][0][0][Y] = 0;
uin_invvertex[1][0][0][Z] = 1.0;
uin_invvertex[1][0][1][X] = 1.0;
uin_invvertex[1][0][1][Y] = 0;
uin_invvertex[1][0][1][Z] = 1.0;
uin_invvertex[1][1][0][X] = 0;
uin_invvertex[1][1][0][Y] = 1.0;
uin_invvertex[1][1][0][Z] = 1.0;
uin_invvertex[1][1][1][X] = 1.0;
uin_invvertex[1][1][1][Y] = 1.0;
uin_invvertex[1][1][1][Z] = 1.0;
for (z=0; z<2; z++) {
for (y=0; y<2; y++) {
for (x=0; x<2; x++) {
Transform_Point(uin_invvertex[z][y][x][X],
uin_invvertex[z][y][x][Y],
uin_invvertex[z][y][x][Z],
&uout_invvertex[z][y][x][X],
&uout_invvertex[z][y][x][Y],
&uout_invvertex[z][y][x][Z]);
}
}
}
}
void Load_Transformation_Matrix(matrix)
float matrix[4][4];
{
Copy_Matrix(matrix,transformation_matrix);
}
void Transform_Point(xold,yold,zold,xnew,ynew,znew)
float xold,yold,zold;
float *xnew,*ynew,*znew;
{
*xnew =
xold * transformation_matrix[0][0] +
yold * transformation_matrix[1][0] +
zold * transformation_matrix[2][0] +
transformation_matrix[3][0];
*ynew =
xold * transformation_matrix[0][1] +
yold * transformation_matrix[1][1] +
zold * transformation_matrix[2][1] +
transformation_matrix[3][1];
*znew =
xold * transformation_matrix[0][2] +
yold * transformation_matrix[1][2] +
zold * transformation_matrix[2][2] +
transformation_matrix[3][2];
}
void Inverse_Concatenate_Translation(matrix,xoffset,yoffset,zoffset)
float matrix[4][4],xoffset,yoffset,zoffset;
{
float translation_matrix[4][4];
Load_Translation_Matrix(translation_matrix,xoffset,yoffset,zoffset);
Inverse_Concatenate_Transform(matrix,translation_matrix);
}
void Inverse_Concatenate_Scaling(matrix,xscale,yscale,zscale)
float matrix[4][4],xscale,yscale,zscale;
{
float scaling_matrix[4][4];
Load_Scaling_Matrix(scaling_matrix,xscale,yscale,zscale);
Inverse_Concatenate_Transform(matrix,scaling_matrix);
}
void Inverse_Concatenate_Rotation(matrix,axis,angle)
float matrix[4][4],angle;
long axis;
{
float rotation_matrix[4][4];
Load_Rotation_Matrix(rotation_matrix,axis,angle);
Inverse_Concatenate_Transform(matrix,rotation_matrix);
}
void Load_Identity_Matrix(matrix)
float matrix[4][4];
{
long i,j;
for (i=0; i<4; i++) {
for (j=0; j<4; j++) {
matrix[i][j] = 0;
}
matrix[i][i] = 1.0;
}
}
void Load_Translation_Matrix(matrix,xoffset,yoffset,zoffset)
float matrix[4][4],xoffset,yoffset,zoffset;
{
Load_Identity_Matrix(matrix);
matrix[3][0] = xoffset;
matrix[3][1] = yoffset;
matrix[3][2] = zoffset;
}
void Load_Scaling_Matrix(matrix,xscale,yscale,zscale)
float matrix[4][4],xscale,yscale,zscale;
{
Load_Identity_Matrix(matrix);
matrix[0][0] = xscale;
matrix[1][1] = yscale;
matrix[2][2] = zscale;
}
void Load_Rotation_Matrix(matrix,axis,angle)
float matrix[4][4],angle;
long axis;
{
Load_Identity_Matrix(matrix);
if (axis == XAXIS) {
matrix[1][1] = cos(angle/180.0*PI);
matrix[1][2] = sin(angle/180.0*PI);
matrix[2][1] = -sin(angle/180.0*PI);
matrix[2][2] = cos(angle/180.0*PI);
}
else if (axis == YAXIS) {
matrix[0][0] = cos(angle/180.0*PI);
matrix[0][2] = -sin(angle/180.0*PI);
matrix[2][0] = sin(angle/180.0*PI);
matrix[2][2] = cos(angle/180.0*PI);
}
else if (axis == ZAXIS) {
matrix[0][0] = cos(angle/180.0*PI);
matrix[0][1] = sin(angle/180.0*PI);
matrix[1][0] = -sin(angle/180.0*PI);
matrix[1][1] = cos(angle/180.0*PI);
}
}
void Concatenate_Transform(composite_matrix,transformation_matrix)
float composite_matrix[][4],transformation_matrix[][4];
{
float temp_matrix[4][4];
Multiply_Matrices(composite_matrix,transformation_matrix,temp_matrix);
Copy_Matrix(temp_matrix,composite_matrix);
}
void Inverse_Concatenate_Transform(composite_matrix,transformation_matrix)
float composite_matrix[][4],transformation_matrix[][4];
{
float temp_matrix[4][4];
Multiply_Matrices(transformation_matrix,composite_matrix,temp_matrix);
Copy_Matrix(temp_matrix,composite_matrix);
}
void Multiply_Matrices(input_matrix1,input_matrix2,output_matrix)
float input_matrix1[][4],input_matrix2[][4],output_matrix[][4];
{
long i,j;
for (i=0; i<4; i++) {
for (j=0; j<4; j++) {
output_matrix[i][j] =
input_matrix1[i][0] *
input_matrix2[0][j] +
input_matrix1[i][1] *
input_matrix2[1][j] +
input_matrix1[i][2] *
input_matrix2[2][j] +
input_matrix1[i][3] *
input_matrix2[3][j];
}
}
}
void Copy_Matrix(input_matrix,output_matrix)
float input_matrix[][4],output_matrix[][4];
{
long i,j;
for (i=0; i<4; i++) {
for (j=0; j<4; j++) {
output_matrix[i][j] = input_matrix[i][j];
}
}
}