home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
3D Color Clip Art
/
3D_Color_Clip_Art.bin
/
3d-progs
/
rad386
/
utils.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-11-15
|
13KB
|
502 lines
/*
Utility Routines Used By the Previewer.
V3Dot, V3Cross, V3Normalize, V3Length,ViewTransform,MatMul taken from GraphicsGems.
-----
Sumant
15 May 1991
*/
#include <stdio.h>
#include <math.h>
#include "preview.h"
extern int view_type;
extern int oneview_flag;
extern float eyepoint_distance;
static Matrix ModelMatrix={
{1,0,0,0},
{0,1,0,0},
{0,0,1,0},
{0,0,0,1}
};
static double V3SquaredLength(a)
Vector3 *a;
{
return((a->x * a->x)+(a->y * a->y)+(a->z * a->z));
}
static double V3Dot(a, b)
Vector3 *a, *b;
{
return((a->x*b->x)+(a->y*b->y)+(a->z*b->z));
}
static Vector3 *V3Cross(a, b, c)
Vector3 *a, *b, *c;
{
c->x = (a->y*b->z) - (a->z*b->y);
c->y = (a->z*b->x) - (a->x*b->z);
c->z = (a->x*b->y) - (a->y*b->x);
return(c);
}
static double V3Length(a)
Vector3 *a;
{
return(sqrt(V3SquaredLength(a)));
}
Vector3 *V3Normalize(v,name)
Vector3 *v;
char *name;
{
double len = V3Length(v);
if (len != 0.0) { v->x /= len; v->y /= len; v->z /= len; }
else fprintf(stderr,"V3Normalize : Zero Length Vector in %s.",name);
return(v);
}
static void dump_matrix(T)
Matrix T;
{
int i,j;
for (i=0;i<4;i++){
for(j=0;j<4;j++)
fprintf(stderr,"%g\t",T[i][j]);
fprintf(stderr,"\n");
}
}
static void ViewTransform( VRP, EV, UP, T)
Point3 VRP, EV, UP;
Matrix T;
{
Vector3 U, V, N;
float dot;
/*
* N = EV and normalize N
*/
N = EV;
V3Normalize(&N,"ViewTransform : Normal Calc.");
/*
* V = UP
* Make vector V orthogonal to N and normalize V
*/
V=UP;
dot = V3Dot(&V,&N);
V.x -= dot * N.x; V.y -= dot * N.y; V.z -= dot * N.z;
V3Normalize(&V,"ViewTransform : UP Vector Calc.");
/*
* Compute vector U = V x N (cross product)
*/
V3Cross(&V,&N,&U);
/*
* Write the vectors U, V, and N as the first three rows of the
* first, second, and third columns of ViewMatrix, respectively
*/
T[0][0] = U.x; /* column 1 , vector U */
T[1][0] = U.y;
T[2][0] = U.z;
T[0][1] = V.x; /* column 2 , vector V */
T[1][1] = V.y;
T[2][1] = V.z;
T[0][2] = N.x; /* column 3 , vector N */
T[1][2] = N.y;
T[2][2] = N.z;
/*
* Compute the fourth row of ViewMatrix to include the translation of
* VRP to the origin
*/
T[3][0] = - U.x * VRP.x - U.y * VRP.y - U.z * VRP.z;
T[3][1] = - V.x * VRP.x - V.y * VRP.y - V.z * VRP.z;
T[3][2] = - N.x * VRP.x - N.y * VRP.y - N.z * VRP.z;
/* Fourth Column is constant */
T[0][3] = T[1][3] = T[2][3] = 0.0; T[3][3] = 1.0;
return;
}
/* multiply together matrices c = ab */
/* note that c must not point to either of the input matrices */
static void MatMul(a, b, c)
Matrix a, b, c;
{
int i, j, k;
for (i=0; i<4; i++) {
for (j=0; j<4; j++) {
c[i][j] = 0;
for (k=0; k<4; k++) c[i][j] +=
a[i][k] * b[k][j];
}
}
}
static void loadmatrix(mat)
Matrix mat;
{
int i;
float *s=(float *)mat;
float *t=(float *)ModelMatrix;
for (i = 0; i < 16; i++) *t++ = *s++;
}
void identmatrix(a)
Matrix a;
{
int i;
register float *p=(float *)a;
for (i=0; i<16; i++) *p++ = 0.0;
a[0][0] = a[1][1] = a[2][2] = a[3][3] = 1.0;
}
static void multvector(v, a, b)
Vector v, a;
Matrix b;
{
int i,j;
for(i=0;i<4;i++) for(j=0,v[i]=0.;j<4;j++) v[i] += a[j]*b[j][i];
}
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define check {\
multvector(v,a,m);\
if(v[3] ==0) error("Division By Zero","get_min_max");\
x = v[0]/v[3]; y = v[1]/v[3];\
*min_x=MIN(*min_x,x); *max_x=MAX(*max_x,x);\
*min_y=MIN(*min_y,y); *max_y=MAX(*max_y,y);\
}
static void get_min_max(m,left, right, front, back, bottom,top,min_x,min_y,max_x,max_y)
Matrix m;
float left, right, front, back, bottom,top;
float *min_x,*min_y,*max_x,*max_y;
{
Vector a,v;
float x,y;
*min_x = *min_y = Large;
*max_x = *max_y = -Large;
a[0]=left;a[1]=front;a[2]=bottom;a[3]=1.0; check
a[0]=right;a[1]=front;a[2]=bottom;a[3]=1.0; check
a[0]=left;a[1]=back;a[2]=bottom;a[3]=1.0; check
a[0]=right;a[1]=back;a[2]=bottom;a[3]=1.0; check
a[0]=left;a[1]=front;a[2]=top;a[3]=1.0; check
a[0]=right;a[1]=front;a[2]=top;a[3]=1.0; check
a[0]=left;a[1]=back;a[2]=top;a[3]=1.0; check
a[0]=right;a[1]=back;a[2]=top;a[3]=1.0; check
}
#undef check
static Matrix ViewMatrix[Maxviews];
static int Vx1[MaxviewsX2],Vy1[MaxviewsX2],Vx2[MaxviewsX2],Vy2[MaxviewsX2];
static float Wx1[Maxviews],Wy1[Maxviews],Wx2[Maxviews],Wy2[Maxviews];
void set_screen_transformation(left, right, front, back, bottom,top)
float left, right, front, back, bottom, top;
{
extern int window_x_size,window_y_size;
Point3 VRP,EP,UP;
Vector box[8];
float min_x,min_y,max_x,max_y;
float deltax,deltay,deltaz,maxdelta;
if ((deltax=(right - left))== 0.0)
error("Left clipping plane same as right one.",
"utils.c");
if ((deltaz=(top - bottom))== 0.0)
error("Bottom clipping plane same as top one.",
"utils.c");
if ((deltay=(back - front))== 0.0)
error("Front clipping plane same as back one.",
"utils.c");
maxdelta = deltax;
if (deltay > maxdelta) maxdelta = deltay;
if (deltaz > maxdelta) maxdelta = deltaz;
left -= (maxdelta-deltax)/2.;
right += (maxdelta-deltax)/2.;
bottom -= (maxdelta-deltaz)/2.;
top += (maxdelta-deltaz)/2.;
front -= (maxdelta-deltay)/2.;
back += (maxdelta-deltay)/2.;
identmatrix(ModelMatrix);
VRP.x = 0.5*(left+right); VRP.y = 0.5*(front+back); VRP.z = 0.5*(bottom+top);
/* Elevation */
UP.x = UP.y = 0.0; UP.z = 1.0;
EP.y = -1.0; EP.x = EP.z = 0.0;
ViewTransform(VRP,EP,UP,ViewMatrix[0]);
get_min_max(ViewMatrix[0],left, right, front, back, bottom, top,
&min_x,&min_y,&max_x,&max_y);
Wx1[0] = min_x; Wy1[0] = min_y; Wx2[0] = max_x; Wy2[0] = max_y;
Vx1[0] = 1; Vy1[0] = window_y_size/2-2; Vx2[0] = window_x_size/2-2; Vy2[0] = 1;
/* Side */
EP.x =1.0; EP.z = EP.y = 0.0;
ViewTransform(VRP,EP,UP,ViewMatrix[1]);
get_min_max(ViewMatrix[1],left, right, front, back, bottom, top,
&min_x,&min_y,&max_x,&max_y);
Wx1[1] = min_x; Wy1[1] = min_y; Wx2[1] = max_x; Wy2[1] = max_y;
Vx1[1] = window_x_size/2+1; Vy1[1] = window_y_size/2-2;
Vx2[1] = window_x_size-2; Vy2[1] = 1;
/* Plan */
UP.z = UP.x = 0.0; UP.y = 1.0;
EP.z = 1.0; EP.y = EP.x = 0.0;
ViewTransform(VRP,EP,UP,ViewMatrix[2]);
get_min_max(ViewMatrix[2],left, right, front, back, bottom, top,
&min_x,&min_y,&max_x,&max_y);
Wx1[2] = min_x; Wy1[2] = min_y; Wx2[2] = max_x; Wy2[2] = max_y;
Vx1[2] = 1; Vy1[2] = window_y_size-2;
Vx2[2] = window_x_size/2-2; Vy2[2] = window_y_size/2+1;
/* Isometry */
UP.x = UP.y = 0.0; UP.z = 1.0;
EP.z = 1.0; EP.y = 1.0;EP.x = 1.0;
ViewTransform(VRP,EP,UP,ViewMatrix[3]);
ViewTransform(VRP,EP,UP,ViewMatrix[4]);
get_min_max(ViewMatrix[3],left, right, front, back, bottom, top,
&min_x,&min_y,&max_x,&max_y);
Wx1[3] = Wx1[4] = min_x; Wy1[3] = Wy1[4] = min_y;
Wx2[3] = Wx2[4] = max_x; Wy2[3] = Wy2[4] = max_y;
Vx1[3] = Vx1[4] = window_x_size/2+1;
Vy1[3] = Vy1[4] = window_y_size-2;
Vx2[3] = Vx2[4] = window_x_size-2;
Vy2[3] = Vy2[4] = window_y_size/2+1;
Vx1[5] = Vx1[6] = Vx1[7] = Vx1[8] = Vx1[9] = 1;
Vy1[5] = Vy1[6] = Vy1[7] = Vy1[8] = Vy1[9] = window_y_size-2;
Vx2[5] = Vx2[6] = Vx2[7] = Vx2[8] = Vx2[9] = window_x_size-2;
Vy2[5] = Vy2[6] = Vy2[7] = Vy2[8] = Vy2[9] = 1;
}
compute_perspective_matrix(left, right, front, back, bottom, top)
float left, right, front, back, bottom, top;
{
extern int window_x_size,window_y_size;
Matrix m,m1;
Point3 EP,VRP,UP;
float min_x,min_y,max_x,max_y;
fprintf(stderr,"Screen Extents are <%g %g %g> to <%g %g %g>.\n",
bound_min_x,bound_min_y,bound_min_z,
bound_max_x,bound_max_y,bound_max_z);
fprintf(stderr,"Give the view params:\n");
fprintf(stderr,"Eye Point : ");
scanf("%lf%lf%lf",&(EP.x),&(EP.y),&(EP.z));
fprintf(stderr,"View Reference Point : ");
scanf("%lf%lf%lf",&(VRP.x),&(VRP.y),&(VRP.z));
fprintf(stderr,"Up Point : ");
scanf("%lf%lf%lf",&(UP.x),&(UP.y),&(UP.z));
ViewTransform(VRP,EP,UP,ViewMatrix[4]);
/* Project on a view plane 1 unit away */
identmatrix(m);
m[2][2]=m[3][3]=0.; m[2][3] = 1.;
MatMul(m1,m,ViewMatrix[4]);
get_min_max(ViewMatrix[4],left, right, front, back, bottom, top,
&min_x,&min_y,&max_x,&max_y);
Wx1[4] = min_x; Wy1[4] = min_y; Wx2[4] = max_x; Wy2[4] = max_y;
Vx1[4] = window_x_size/2+1; Vy1[4] = window_y_size-2;
Vx2[4] = window_x_size-2; Vy2[4] = window_y_size/2+1;
}
static int get_screen_xy(n,deltan,x,y,z,sx,sy)
int n,deltan;
float x,y,z;
int *sx,*sy;
{
Vector v,v1,vv;
v[0]=x; v[1]=y; v[2]=z; v[3]=1.0;
/* Model Transform the Point */
multvector(v1,v,ModelMatrix);
/* View Transform the point */
multvector(vv,v1,ViewMatrix[n]);
if (vv[3] == 0.0){
warn("get_screen_xy : Homogeneous Coordinate.", "utils.c");
return(1);
}
/* Window to View port Map */
*sx = Vx1[n+deltan] + (vv[0]/vv[3] - Wx1[n])*
(Vx2[n+deltan]-Vx1[n+deltan])/(Wx2[n]-Wx1[n]);
*sy = Vy1[n+deltan] + (vv[1]/vv[3] - Wy1[n])*
(Vy2[n+deltan]-Vy1[n+deltan])/(Wy2[n]-Wy1[n]);
return(0);
}
static int previous_screen_x[4]={0,320,0,320},
previous_screen_y[4]={319,319,639,639};
#define Code(x,y,c) {\
c = 0x00;\
if (x < min_x) c |= left;\
else if (x > max_x) c |= right;\
if (y > min_y) c |= bottom;\
else if (y < max_y) c |= top;\
}
void clip_and_draw(x1,y1,x2,y2,min_x,min_y,max_x,max_y)
int x1,y1,x2,y2,min_x,max_y,max_x,min_y;
{
unsigned char left=0x01,right=0x02,bottom=0x04,top=0x08;
int x,y;
unsigned char c,c1,c2;
Code(x1,y1,c1); Code(x2,y2,c2);
while (c1 || c2){
if (c1 & c2) return;
c = c1; if (!c) c = c2;
if (c & left){
y = y1 + ((float)(y2 - y1)*(min_x-x1))/(x2-x1);
x = min_x;
}
else if (c & right){
y = y1 + ((float)(y2 - y1)*(max_x-x1))/(x2-x1);
x = max_x;
}
else if (c & bottom){
x = x1 + ((float)(x2 - x1)*(min_y-y1))/(y2-y1);
y = min_y;
}
else if (c & top){
x = x1 + ((float)(x2 - x1)*(max_y-y1))/(y2-y1);
y = max_y;
}
if (c == c1) {
x1 = x; y1 = y; Code(x,y,c1);
}
else{
x2 = x; y2 = y; Code(x,y,c2);
}
}
Xdraw(x1,y1,x2,y2);
}
#undef Code
void draw(x,y,z)
float x,y,z;
{
int i;
int sx,sy;
if (view_type == ONE){
if (get_screen_xy(oneview_flag,Maxviews,x,y,z,&sx,&sy))
return;
Xdraw(previous_screen_x[0],previous_screen_y[0],sx,sy);
previous_screen_x[0]=sx; previous_screen_y[0]=sy;
}
else for(i=0;i<4;i++){
if (get_screen_xy(i,0,x,y,z,&sx,&sy))
continue;
clip_and_draw(
previous_screen_x[i],previous_screen_y[i],sx,sy,
Vx1[i],Vy1[i],Vx2[i],Vy2[i]);
previous_screen_x[i]=sx; previous_screen_y[i]=sy;
}
}
void move(x,y,z)
float x,y,z;
{
int i;
int sx,sy;
if (view_type == ONE){
if (get_screen_xy(oneview_flag,Maxviews,x,y,z,&sx,&sy))
return;
previous_screen_x[0]=sx; previous_screen_y[0]=sy;
}
else for(i=0;i<4;i++){
if (get_screen_xy(i,0,x,y,z,&sx,&sy))
continue;
previous_screen_x[i]=sx; previous_screen_y[i]=sy;
}
}
#define MaxStackSize 100
static float stack[MaxStackSize];
static int topofstack=0;
void pushmatrix()
{
if ((topofstack+16)< MaxStackSize){
int i;
float *m=(float *)ModelMatrix;
for(i=0;i<16;i++) stack[topofstack++] = *m++;
}
else error("pushmatrix : Stack overflow","utils.c");
}
void popmatrix()
{
if (topofstack < 16) error("popmatrix : Empty Stack","utils.c");
else {
int i;
float *m=(float *)ModelMatrix;
for(i=0,m+=15;i<16;i++) *m--=stack[--topofstack];
}
}
void translate(x,y,z)
float x,y,z;
{
Matrix m,m1;
identmatrix(m);
m[3][0] = x; m[3][1] = y; m[3][2] = z;
MatMul(m,ModelMatrix,m1);
loadmatrix(m1);
}
void rotate(r,axis)
float r;
char axis;
{
float sintheta=sin((double)(DTOR * r));
float costheta=cos((double)(DTOR * r));
float tmp;
Matrix m,m1;
identmatrix(m);
switch(axis){
case 'x':
case 'X':
m[1][1]=m[2][2]= costheta;
m[1][2]= sintheta;
m[2][1]= -sintheta;
break;
case 'y':
case 'Y':
m[0][0] = m[2][2] = costheta;
m[0][2] = -sintheta;
m[2][0] = sintheta;
break;
case 'z':
case 'Z':
m[0][0] = m[1][1] = costheta;
m[0][1] = sintheta;
m[1][0] = -sintheta;
break;
default: error("rotate : Illegal axis.","utils.c"); break;
}
MatMul(m,ModelMatrix,m1);
loadmatrix(m1);
}
void multmatrix(m)
Matrix m;
{
Matrix m1;
MatMul(m,ModelMatrix,m1);
loadmatrix(m1);
}
void circle(radius)
float radius;
{
extern int circle_precision;
int i;
float cx, cy, dx, dy;
float angle=2.0 * PI /circle_precision;
float cosine = cos((double)angle);
float sine = sin((double)angle);
cx = radius;
cy = 0.0;
move(cx,cy,0.0);
for (i = 0; i < (circle_precision - 1); i++) {
dx = cx;
dy = cy;
cx = dx * cosine - dy * sine;
cy = dx * sine + dy * cosine;
draw(cx, cy,0.0);
}
draw(radius,0.0,0.0);
}