Archived

This topic is now archived and is closed to further replies.

capn_midnight

code review, matrix manipulation and projections

Recommended Posts

/****************************************************
   TITLE:     Simple GFX API
   FILE:      trans.h
   AUTHOR:    Sean T. McBeth, sm8236@ship.edu
   DATES:     part 1: 2/10/04 - 2/25/04
              part 2: 3/20/04 - 3/26/04
   PROFESSOR: Dr. David J. Mooney, djmoon@ship.edu
   COURSE:    CSC 460: Computer Graphics Algorithms
*****************************************************/
#ifndef __TRANS_H
#define __TRANS_H
#ifndef __MATH_H
#include <math.h>
#endif
#ifndef __glut_h__
#include <gl/glut.h>
#endif

#ifdef __DEBUG__
#include <stdio.h>
#endif
#define real float



////////////////////////

//necessary structures//

////////////////////////

struct point{
   real x, y, z;
};
   
struct matrix{
   //a 3D point, used for some stuff

   //a 4X4 matrix, used for some other stuff

   real a[4][4];
};


struct node{
   //Create a STACK!!!!!!!!!!!!!!!!!!!!!!

   matrix m;
   node*  n;
};

enum{PARALLEL, PERSPECTIVE};

///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////


////////////////////////////////

//matrix operations prototypes//

////////////////////////////////

void   setProjection         (const int,
                              const real,    const real,    const real,
                              const real,    const real,    const real,
                              const real,    const real,    const real);
void   setVRC                (const real,    const real,    const real,
                              const real,    const real,    const real,
                              const real,    const real,    const real);
int    clipLine              (const point&,  const point&,
                              const real,    const real,    const real,    const real);
int    clipPoint             (const point&,  const real,    const real,    const real,    const real);
void   setView               (const int,     const int,     const int,     const int);
void   rotate                (const real,    const real,    const real,    const real);
void   translate             (const real,    const real,    const real);
void   scale                 (const real,    const real,    const real);
void   multMatrix            (      matrix&, const matrix&);
void   copyMatrix            (const matrix&,       matrix&);
void   drawLine              (const point&,  const point&);
void   shearxy               (const real,    const real);
void   shearxz               (const real,    const real);
void   shearyx               (const real,    const real);
void   identMatrix           (      matrix&);
point  transformPoint        (const point&);
void   drawPoint             (const point&);
void   rotatex               (const real);
void   rotatey               (const real);
void   rotatez               (const real);
void   initializeTransMatrix (void);
void   pushMatrix            (void);
void   popMatrix             (void);

///////////////////////////////////////////////////////////////////////

//some special debugging functions

#ifdef __DEBUG__
void printMatrix(const matrix& m){
   for(int y=0;y<4;++y){
      printf("|");
      for(int x=0;x<4;++x){
         printf("%f ",m.a[y][x]);
      }
      printf("|\n");
   }
   printf("\n");
}
void printPoint(const point& p){
   printf("x%f y%f z%f\n", p.x, p.y, p.z);
}
#endif
//get rid of the debugging functions if not in debug mode

#ifndef __DEBUG__
#define printMatrix(x)
//void printMatrix(const matrix& m){   return;}

#define printPoint(x)
//void printPoint(const point& p){   return;}

#endif
///////////////////////////////////////////////////////////////////////


///////////

//globals//

///////////

matrix        transMatrix;       //the current transformation matrix

matrix        viewMatrix;        //specifies the mapping of the world window to the viewport

matrix        projMatrix;        //the current projection matrix

node*         transMatrixStack;  //the matrix stack;


///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////


////////////////////////////////

//matrix operations defintions//

////////////////////////////////

/*
   FUNC: setProjection
   PRE:  type, prp<x,y,z>, left, right, bottom, top, front, and back are all set
         0<=type<=1
         left<right && bottom<top && front<back
         setVRC has been previously called
   POST: the world window-to-viewport transformation will be finished
         the current projection matrix will be set

*/
void   setProjection         (const int type,
                              const real prpx,   const real prpy,    const real prpz,
                              const real left,   const real right,   const real bottom,
                              const real top,    const real front,   const real back){
   real shx, shy, dh, dv, dd, t1, t2;
   dh = right - left;
   dv = top - bottom;
   dd = front - back;
   pushMatrix();
   if(viewMatrix.a[3][3]==1)
      copyMatrix(viewMatrix, transMatrix);
   else
      initializeTransMatrix();
   scale( 1/(right - left), 1/(top - bottom), 1);
   translate( -left, -bottom, 0);
   copyMatrix(transMatrix, viewMatrix);

   /*
      At this point, the viewport is only half-set. More information is
      needed for the world window-to-viewport transformation. This inof
      will be provided by setView.
   */

   copyMatrix(projMatrix, transMatrix);
   
   if(type == PERSPECTIVE){
      //T(-COP)

      translate(-prpx, -prpy, -prpz);
   }
   
   //H(DOP || to z axis)

   shx = ( dh / 2) - prpx;
   shy = ( dv / 2) - prpy;
   shearxy(shx, shy);

   if(type == PARALLEL){
      //T(-CW)

      translate( -dh / 2, -dv / 2, -front);
      //scale to canonical parallel view volume

      scale( 2 / dh, 2 / dv, 1 / dd );
   }
   else{
      //scale to canonical perspective view volume

      t1 = 2 * -prpz;
      t2 = -prpz + back;
      scale( t1 / ( dh * t2 ), t1 / ( dv * t2 ), -1 / t2 );
   }
   /*
      projection matrix is set!
   */
   popMatrix();
}

/*
   FUNC: setVRC
   PRE:  vrp<x,y,z> is set. vpn<x,y,z> and vup<x,y,z> are non-parallel vectors
   POST: view reference coordinate system will be initialized
         call setProjection next
*/
void   setVRC                (const real vrpx,    const real vrpy,    const real vrpz,
                              const real vpnx,    const real vpny,    const real vpnz,
                              const real vupx,    const real vupy,    const real vupz){
   matrix temp;
   real vpnLen;
   real tx, ty, tz, tlen;
   pushMatrix();
   initializeTransMatrix();
   
   //T(-VRP)

   translate(-vrpx, -vrpy, -vrpz);
   identMatrix(temp);
   
   //Rz = VPN / ||VPN||

   vpnLen = sqrt( vpnx*vpnx + vpny*vpny + vpnz*vpnz );
   temp.a[2][0] = vpnx/vpnLen;
   temp.a[2][1] = vpny/vpnLen;
   temp.a[2][2] = vpnz/vpnLen;

   //Rx = (VUP X Rz) / ||(VUP X Rz)||

   tx = vupy*temp.a[2][2] - vupz*temp.a[2][1];
   ty = vupz*temp.a[2][0] - vupx*temp.a[2][2];
   tz = vupx*temp.a[2][1] - vupy*temp.a[2][0];
   tlen = sqrt( tx*tx + ty*ty + tz*tz );
   temp.a[0][0] = tx/tlen;
   temp.a[0][1] = ty/tlen;
   temp.a[0][2] = tz/tlen;

   //Ry = Rz X Rx

   tx = temp.a[2][1]*temp.a[0][2] - temp.a[2][2]*temp.a[0][1];
   ty = temp.a[2][2]*temp.a[0][0] - temp.a[2][0]*temp.a[0][2];
   tz = temp.a[2][0]*temp.a[0][1] - temp.a[2][1]*temp.a[0][0];
   tlen = sqrt( tx*tx + ty*ty + tz*tz );
   temp.a[1][0] = tx/tlen;
   temp.a[1][1] = ty/tlen;
   temp.a[1][2] = tz/tlen;
   
   //Rotate VRC inline with cartesian coordinate system

   multMatrix(transMatrix, temp);
   copyMatrix(projMatrix, transMatrix);
   /*
      At this point, the projection matrix is only half complete.
   */
   popMatrix();
}
int    clipLine              (const point&,  const point&,
                              const real,    const real,    const real,    const real);
int    clipPoint             (const point&,  const real,    const real,    const real,    const real);
/*
   FUNC: setView
   PRE:  xmin, xmax, ymin, ymax are valid integers
         xmin<xmax && ymin<ymax
   POST: the preliminary informartion for creating a world window-to-viewport
         transformation will be stored in the viewMatrix.

*/
void   setView               (const int xmin,     const int xmax,     const int ymin,     const int ymax){
   pushMatrix();
   if(viewMatrix.a[3][3]==1)
      copyMatrix(viewMatrix, transMatrix);
   else
      initializeTransMatrix();
   translate(xmin, xmax, 0);
   scale( (xmax - xmin), (ymax - ymin), 1);
   copyMatrix(transMatrix, viewMatrix);
   popMatrix();
   /*
      At this point, the viewport is only half-set. More information is
      needed for the world window-to-viewport transformation. This info
      will be provided by setProjection.
   */
}

/*
   FUNC: rotate
   PRE:  [x y z] NOT zero vector
   POST: scene will be rotated by theta degrees about an arbitrary axis
*/
void   rotate                (const real theta,    const real ax,    const real ay,    const real az){
	real c=cos(theta);
   real s=sin(theta);
   matrix rot;
   identMatrix(rot);
   rot.a[0][0]=ax*ax*(1-c)+c;
   rot.a[0][1]=ax*ay*(1-c)+az*s;
   rot.a[0][2]=ax*az*(1-c)-ay*s;

   rot.a[1][0]=ay*ax*(1-c)-az*s;
   rot.a[1][1]=ay*ay*(1-c)+c;
   rot.a[1][2]=ay*az*(1-c)+ax*s;

   rot.a[2][0]=az*ax*(1-c)+ay*s;
   rot.a[2][1]=az*ay*(1-c)-ax*s;
   rot.a[2][2]=az*az*(1-c)+c;

   multMatrix(transMatrix, rot);
}
/*
   FUNC: translate
   PRE:  dx AND dy AND dz NOT NULL
   POST: current transformation matrix translated by dx, dy, dz
*/
void  translate             (const real dx,    const real dy,    const real dz){
   matrix temp;
   identMatrix(temp);
   temp.a[0][3] = dx;
   temp.a[1][3] = dy;
   temp.a[2][3] = dz;
   multMatrix(transMatrix, temp);
}

/*
   FUNC: scale
   PRE:  sx AND sy AND sz NOT NULL
   POST: current transformation matrix scaled by sx, sy, sz
*/
void  scale                 (const real sx,    const real sy,    const real sz){
   matrix temp;
   identMatrix(temp);
   temp.a[0][0] = sx;
   temp.a[1][1] = sy;
   temp.a[2][2] = sz;
   multMatrix(transMatrix, temp);
}

/*
   FUNC: multMatrix
   PRE:  m1 AND m2 NOT NULL
         m1 AND m2 valid 4X4 matrix
   POST: m1=m1*m2, via normal matrix multiplication
*/
void  multMatrix            (matrix& m1, const matrix& m2){
   matrix temp;
	for(int y = 0; y < 4; ++y){
		for(int x = 0; x < 4; ++x){
			//initialize temp

			temp.a[y][x] = 0;
			//do multiplication

			for(int i = 0; i < 4; ++i){
				temp.a[y][x] += m1.a[y][i] * m2.a[i][x];
			}
		}
	}
   copyMatrix(temp, m1);
}

/*
   FUNC: copyMatrix
   PRE:  src is a valid matrix
   POST: dest will be a value-for-value copy of src
*/
void   copyMatrix            (const matrix& src,       matrix& dest){
   for(int y=0; y<4; ++y){
      for(int x=0; x<4; ++x){
         dest.a[y][x]=src.a[y][x];
      }
   }
}
/*
   FUNC: drawLine
   PRE:  p1 AND p2 NOT NULL
   POST: line segment represented by endpoints p1 and p2 will
         be rendered to the current rendering buffer using the
         current transformation matrix
*/
void  drawLine              (const point& p1,  const point& p2){
   point t1, t2;
   t1=transformPoint(p1);
   t2=transformPoint(p2);
   glBegin(GL_LINES);
      glVertex3f(t1.x, t1.y, t1.z);
      glVertex3f(t2.x, t2.y, t2.z);
   glEnd();   
}

/*
   FUNC: shear<xy|xz|yz>
   PRE:  none
   POST: current transformation matrix will be sheared in the axis
         specified (x and y, x and z, or y and z) by the coefficients
         hx, hy, or hz
*/
void  shearxy               (const real hx,    const real hy){
   matrix temp;
   identMatrix(temp);
   temp.a[0][2]=hx;
   temp.a[1][2]=hy;
   multMatrix(transMatrix, temp);
}

void  shearxz               (const real hx,    const real hz){
   matrix temp;
   identMatrix(temp);
   temp.a[0][1]=hx;
   temp.a[2][1]=hz;
   multMatrix(transMatrix, temp);
}

void  shearyz               (const real hy,    const real hz){
   matrix temp;
   identMatrix(temp);
   temp.a[1][0]=hy;
   temp.a[2][0]=hz;
   multMatrix(transMatrix, temp);
}

/*
   FUNC: identMatrix
   PRE:  none
   POST: m is now 4X4 identity matrix
*/
void  identMatrix           (      matrix& m){
   for(int y = 0; y < 4; ++y){
      for(int x = 0; x < 4; ++x){
         m.a[y][x] = 0;
      }
      m.a[y][y] = 1;
   }
}

/*
   FUNC: transformPoint
   PRE:  p NOT NULL
   POST: vertex p will be trasnformed by the current
         transformation matrix
*/
point transformPoint        (const point& p){
   point temp;
   temp.x=transMatrix.a[0][0]*p.x + transMatrix.a[0][1]*p.y + transMatrix.a[0][2]*p.z + transMatrix.a[0][3];
   temp.y=transMatrix.a[1][0]*p.x + transMatrix.a[1][1]*p.y + transMatrix.a[1][2]*p.z + transMatrix.a[1][3];
   temp.z=transMatrix.a[2][0]*p.x + transMatrix.a[2][1]*p.y + transMatrix.a[2][2]*p.z + transMatrix.a[2][3];
   return temp;
}

/*
   FUNC: drawPoint
   PRE:  p NOT NULL
   POST: p will be rendered to the current rendering buffer
         using the current transfomation matrix
*/
void  drawPoint             (const point& p){
   point temp=transformPoint(p);
   glBegin(GL_POINTS);
      glVertex3f(temp.x, temp.y, temp.z);
   glEnd();
}

/*
   FUNC: initializeTransMatrix
   PRE:  none
   POST: transMatrix is now 4X4 identity matrix
*/
void  initializeTransMatrix (void){
 	identMatrix(transMatrix);
}

/*
   FUNC: pushMatrix
   PRE:  transMatrix has been initialized
   POST: transMatrix pushed to top of transMatrixStack
*/
void  pushMatrix            (void){
   node* temp=new node;
   temp->m=transMatrix;
   temp->n=transMatrixStack;
   transMatrixStack=temp;
}
/*
   FUNC: popMatrix
   PRE:  transMatrixStack NOT EMPTY
   POST: transMatrix replaced with top of transMatrixStack
         transMatrixStock top replaced with transMatrixStack->n
*/
void  popMatrix             (void){
   if(transMatrixStack != 0){
      node* temp=transMatrixStack;
      transMatrixStack=temp->n;
      transMatrix=temp->m;
      delete temp;
   }
}
#endif
been working on this for about a month now, wanted to see what everyone thought, see if you notice anything out of place.
capn_midnight | Captain Midnight | deviantArt ACM | SIGGRAPH | Generation5

Share this post


Link to post
Share on other sites