pastebin

Paste #70110: ThreeD.cpp

#include "ThreeD.h"
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <exception>
#include <string>
#include <math.h>
#include <unistd.h>
#include "lines.cpp"

using namespace std;


/*  Implement the following routines into your file */


#define ROW 4
#define COL 4
#define INITIALTOP 0


/* Definitions of the types of structures and variables used in the following
   code.  Use these or implement your own. */

typedef struct                  /* structure definitions */
{
   float  mat[ROW][COL];
}  matrix_unit;

typedef struct
{
   float i;
   float j;
   float k;
} Vector;

typedef struct
{
   float x;
   float y;
   float z;
   float r;
   float g;
   float b;
} Vertex_unit;

typedef struct
{
  float mat41[ROW];
} matrix41;

static float Near, Far;

float w;

matrix_unit *stack[50];    /* array of pointers to act as a stack */




void Cross(Vector *x, Vector *y, Vector *z);
void Unitvec(float x, float y, float z, Vector *vec);
int Mult_end(matrix_unit *M, matrix41 *V, matrix41 *result);
int Mult_mat(matrix_unit *left, matrix_unit *right, matrix_unit *result);
int Copy_mat(matrix_unit *from, matrix_unit *to);
void clearStack();



static matrix_unit I = {
   { 1., 0., 0., 0.,
     0., 1., 0., 0.,
     0., 0., 1., 0.,
     0., 0., 0., 1  },
};
static int perspflag=0;
static int top = INITIALTOP;                   /* points to top of the stack */

int width, height;         /* height and width of frame buffer */

static matrix_unit orth;       /* global ortho and perspective matrices */
                               /* to be used in Vertex3f */
static matrix_unit perspect;


void ThreeD::reset()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glRasterPos2i(0,0);
	glFlush();
	clearStack();
}

void clearStack()
{
	top = INITIALTOP;
	Copy_mat(&I,stack[INITIALTOP]);
}

void ThreeD::pop()
{
	if(top == INITIALTOP)
	{
		printf("Matrix stack is empty and could not be popped\n");
	}
	else
	{
		top--;
	}
}

void ThreeD::push()
{
	if(top >= 50)
	{
		printf("Matrix stack is full and cannot accommodate another transformation matrix\n");
	}
	else
	{
		Copy_mat(stack[top],stack[top+1]);
		top++;
	}
}

void ThreeD::translate(float x, float y, float z)
{
	matrix_unit translation = {
		{ 1., 0., 0., x,
		  0., 1., 0., y,
		  0., 0., 1., z,
		  0., 0., 0., 1  },
		};
	Mult_mat(stack[top], &translation, stack[top]);
}

void ThreeD::scale(float sx, float sy, float sz)
{
	matrix_unit scale = {
		{ sx, 0., 0., 0.,
		  0., sy, 0., 0.,
		  0., 0., sz, 0.,
		  0., 0., 0., 1  },
		};
	Mult_mat(stack[top], &scale, stack[top]);
}

void rotate(float rotationAngle, float referenceX,float referenceY,float referenceZ)
{
	Vector vec;
	Unitvec(referenceX, referenceY, referenceZ, &vec);
	float x = vec.i;
	float y = vec.j;
	float z = vec.k;
	float rotationAngleRadians = rotationAngle * (4 * atan(1.))/180.;
	float c = cos(rotationAngleRadians);
	float s = sin(rotationAngleRadians);

	matrix_unit rotation = {
			{ x*x+(1-x*x)*c, x*y*(1-c)-z*s, x*z*(1-c)+y*s, 0.,
			  x*y*(1-c)+z*s, y*y+(1-y*y)*c, y*z*(1-c)-x*s, 0.,
			  x*z*(1-c)-y*s, y*z*(1-c)+x*s, z*z+(1-z*z)*c, 0.,
			  0., 0., 0., 1  },
			};
	Mult_mat(stack[top], &rotation, stack[top]);
}

void ortho(float leftX, float rightX, float bottomY, float topY, float nearZ, float farZ)
{
	farZ = -farZ;
	nearZ = -nearZ;
	matrix_unit orth_ = {
				{ 2/(rightX-leftX), 0., 0., -(rightX+leftX)/(rightX-leftX),
				  0., 2/(topY-bottomY), 0., -(topY+bottomY)/(topY-bottomY),
				  0., 0.,-2/(farZ-nearZ), -(farZ+nearZ)/(farZ-nearZ),
				  0., 0., 0., 1},
			};
	Copy_mat(&orth_,&orth);
}

void perspective(float angleVerticleFOV, float aspectRatio, float nearZ, float farZ)
{

}




/*========================================================================*/
/* Finds a cross product of two vectors                                   */
/*========================================================================*/
void Cross(Vector *x, Vector *y, Vector *z) {

    z->i = x->j * y->k - x->k * y->j;
    z->j = x->k * y->i - x->i * y->k;
    z->k = x->i * y->j - x->j * y->i;
}


/*========================================================================*/
/* Finds a unit vector in the direction of a given vector                 */
/*========================================================================*/
void Unitvec(float x, float y, float z, Vector *vec){
    float vec_length;

    vec_length = sqrt(x*x + y*y + z*z);
    vec->i = x/vec_length;
    vec->j = y/vec_length;
    vec->k = z/vec_length;
}

/*========================================================================*/
/* Multiplies a 4x4 matrix by a 4x1 vector                                */
/* Returns 0 upon success and 1 if pointers are not pointing to matrices  */
/*========================================================================*/
int Mult_end(matrix_unit *M, matrix41 *V, matrix41 *result) {
    int i, j;

    if (M == NULL || V == NULL || result == NULL) {
        printf("error in matrix multiplication \n");
        return 1;
    }
    for (i=0; i<4; i++) {
            (result->mat41)[i] = 0;
        for (j=0; j<4; j++)
                (result->mat41)[i] += (M->mat)[i][j]*(V->mat41)[j];
    }

    return 0;
}

/*========================================================================*/
/* Multiplies two 4x4 matrices                                            */
/* Returns 0 upon success and 1 if pointers are not pointing to matrices  */
/*========================================================================*/
int Mult_mat(matrix_unit *left, matrix_unit *right, matrix_unit *result) {
    int i, j, k;

    if (left == NULL || right == NULL || result == NULL) {
        printf("error in matrix multiplication -- matrix not allocated\n");
        return 1;
    }
    for (i=0; i<4; i++) {
        for (j=0; j<4; j++) {
            (result->mat)[i][j] = 0;
            for (k=0; k<4; k++)
                (result->mat)[i][j] += (left->mat)[i][k]*(right->mat)[k][j];
        }
    }
    return 0;
}

int Copy_mat(matrix_unit *from, matrix_unit *to) {
    int i, j;
    if (from != NULL && to != NULL) {
        for (i=0; i<ROW; i++)
            for (j=0; j<ROW; j++)
                (to->mat)[i][j] = (from->mat)[i][j];
        return 0;
    }
    else {
        printf(" Cannot copy matrix\n");
        return 1;
    }
}

void lookAt( float fx, float fy, float fz, float atx, float aty,
	       float atz, float upx, float upy, float upz)
{
   float dx, dy, dz ;
   Vector slnv, rx, ry, rz, up;
   matrix_unit ltrans, tmpsln, *t, rfin, lookat;
   Vertex_unit v, sv;
   int i, j;

   /*   translation */
   Copy_mat(&I,<rans);
   t = <rans;
   t->mat[0][3] = -fx;
   t->mat[1][3] = -fy;
   t->mat[2][3] = -fz;

   up.i = upx; up.j = upy; up.k = upz;
   Unitvec(up.i, up.j, up.k, &slnv);
   up = slnv;

   /*  make P1P2  (rz) vector */
   dx = atx - fx;   dy = aty - fy;  dz = atz - fz;
   Unitvec( dx, dy, dz, &rz);

   rfin = I;
      /* make rx */
   Cross(&rz, &up, &rx);
   Unitvec( rx.i, rx.j, rx.k, &slnv);
   rx = slnv;

      /* make ry */
   Cross(&rx, &rz, &ry);

   rfin.mat[0][0] = rx.i; rfin.mat[0][1] = rx.j; rfin.mat[0][2] = rx.k;
   rfin.mat[1][0] = ry.i; rfin.mat[1][1] = ry.j; rfin.mat[1][2] = ry.k;
   rfin.mat[2][0] = -rz.i; rfin.mat[2][1] = -rz.j; rfin.mat[2][2] = -rz.k;

   Mult_mat(&rfin, <rans, &lookat);

   /* Multiply the lookat matrix by the matrix currently on the top
      of the stack.  This then becomes the new top of the stack. */

   /*  This will depend on how you implemented your stack */
  Mult_mat(stack[top], &lookat, &tmpsln);
  Copy_mat(&tmpsln, stack[top]);

}



void ThreeD::vertex(float x, float y, float z)

{
  matrix41 printvec, tmp, vertex1, vertex2, pvert1, pvert2, permat1, permat2;
  float x0, y0, z0, x1, y1, z1;
  static int printflag=0;
  static matrix41 savemat;
  float xpixel1, ypixel1, xpixel2, ypixel2;

  printvec.mat41[0]=x;    /* set up 4x1 matrix of the vertex */
  printvec.mat41[1]=y;
  printvec.mat41[2]=z;
  printvec.mat41[3]=1;

/*Mult_end is a function to multiply matrix a * matrix b and put the
  solution in sln.  This function multiplies [4][4]*[4][1].  This will
  vary depending on your implementation. */

  Mult_end(stack[top],&printvec, &tmp);

  printflag++;       /* increase counter */

  if(printflag==1) { /* if the first vertex, save the points */
    savemat.mat41[0]=tmp.mat41[0];
    savemat.mat41[1]=tmp.mat41[1];
    savemat.mat41[2]=tmp.mat41[2];
    savemat.mat41[3]=1;
  }
  if(printflag==2) { /* if the second vertex, test clipping */

    x1=tmp.mat41[0];
    y1=tmp.mat41[1];
    z1=tmp.mat41[2];

    x0=savemat.mat41[0];
    y0=savemat.mat41[1];
    z0=savemat.mat41[2];

    /* if clipping occurs and points are within view volume, draw line */
    /* from v1 to v2 */
    if(near_far_clip(Near, Far, &x0, &y0, &z0, &x1, &y1, &z1)==1) {

	pvert1.mat41[0]=x0;
	pvert1.mat41[1]=y0;
	pvert1.mat41[2]=z0;
	pvert1.mat41[3]=1;
	pvert2.mat41[0]=x1;
	pvert2.mat41[1]=y1;
	pvert2.mat41[2]=z1;
	pvert2.mat41[3]=1;

	if(perspflag==0) {  /* if not a perpective projection, use ortho */

	  Mult_end(&orth, &pvert1, &vertex1); /* calculate 2d coordinates */
	  Mult_end(&orth, &pvert2, &vertex2);

	  draw_line(vertex1.mat41[0], vertex1.mat41[1],
		    vertex2.mat41[0], vertex2.mat41[1]);

	  printflag=0;
	}
	else {   /* if a perspective projection, use persp */

	  permat1.mat41[0]=x0/abs(z0);   /* divide by abs(z) to account for */
	  permat1.mat41[1]=y0/abs(z0);  /* z=1 assumption in gtPerspective */
	  permat1.mat41[2]=1.0;
	  permat1.mat41[3]=(float)(1/abs(z0));
	  permat2.mat41[0]=x1/abs(z1);
	  permat2.mat41[1]=y1/abs(z1);
	  permat2.mat41[2]=1.0;
	  permat2.mat41[3]=(float)(1/abs(z1));

	  Mult_end(&perspect, &permat1, &vertex1);
	  Mult_end(&perspect, &permat2, &vertex2);

	  draw_line(vertex1.mat41[0],
		    vertex1.mat41[1],
		    vertex2.mat41[0],
		    vertex2.mat41[1]);


	  printflag=0; /* set counter=0 to look for another set of vertices */
	}
    }

    else
      printflag=0;  /* if vertices beyond clipping plane, reset counter */

  }
}



int ThreeD::push(char * arg[])
{
	try
	{
		push();
		return 0;
	}
	catch(...)
	{
		return 1;
	}
}

int ThreeD::pop(char * arg[])
{
	try
	{
		pop();
		return 0;
	}
	catch(...)
	{
		return 1;
	}
}

int ThreeD::translate(char * arg[])
{
	try
	{
		float param[3];
	    int i = 1;
	    char *leftover;
	    while (arg[i] != NULL && i <= 3) {
	        param[i] = strtof(arg[i],&leftover);
	        if ( leftover[0] != '\0' ) {
	            printf("Error in Translate: Invalid argument \n");
	            return 1;
	        }
	        i++;
	    }
	    for (int j = i; j<=3; j++) param[j] = 0.;
	    translate(param[0],param[1],param[2]);
		return 0;
	}
	catch(...)
	{
		return 1;
	}
}

int ThreeD::scale(char * arg[])
{
	try
	{
		float param[3];
	    int i = 1;
	    char *leftover;
	    while (arg[i] != NULL && i <= 3) {
	        param[i] = strtof(arg[i],&leftover);
	        if ( leftover[0] != '\0' ) {
	            printf("Error in Scale: Invalid argument \n");
	            return 1;
	        }
	        i++;
	    }
	    for (int j = i; j<=3; j++) param[j] = 1.;
	    scale(param[0],param[1],param[2]);
		return 0;
	}
	catch(...)
	{
		return 1;
	}

}

int ThreeD::rotate(char * arg[])
{
	try
	{
		float param[4];
	    int i = 1;
	    char *leftover;
	    while (arg[i] != NULL && i <= 4) {
	        param[i] = strtof(arg[i],&leftover);
	        if ( leftover[0] != '\0' ) {
	            printf("Error in Rotate: Invalid argument \n");
	            return 1;
	        }
	        i++;
	    }
	    for (int j = i; j<=4; j++) param[j] = 0.;
	    rotate(param[0],param[1],param[2],param[3]);
		return 0;
	}
	catch(...)
	{
		return 1;
	}
}

int ThreeD::ortho(char * arg[])
{
	try
	{
		float param[6];
	    int i = 1;
	    char *leftover;
	    while (arg[i] != NULL && i <= 6) {
	        param[i] = strtof(arg[i],&leftover);
	        if ( leftover[0] != '\0' ) {
	            printf("Error in Ortho: Invalid argument \n");
	            return 1;
	        }
	        i++;
	    }
	   if(i<=6)
	   {
		   printf("Error in Ortho: Not enough arguments \n");
		   return 1;
	   }
	   ortho(param[0],param[1],param[2],param[3],param[4],param[5]);
	   return 0;
	}
	catch(...)
	{
		return 1;
	}
}

int ThreeD::perspective(char * arg[])
{
	try
	{
		float param[4];
			    int i = 1;
			    char *leftover;
			    while (arg[i] != NULL && i <= 4) {
			        param[i] = strtof(arg[i],&leftover);
			        if ( leftover[0] != '\0' ) {
			            printf("Error in Perspective: Invalid argument \n");
			            return 1;
			        }
			        i++;
			    }
			   if(i<=4)
			   {
				   printf("Error in Perspective: Not enough arguments \n");
				   return 1;
			   }
			   perspective(param[0],param[1],param[2],param[3]);
		return 0;
	}
	catch(...)
	{
		return 1;
	}
}

int ThreeD::lookAt(char * arg[])
{
	try
	{
		float param[9];
		int i = 1;
		char *leftover;
		while (arg[i] != NULL && i <= 9) {
			param[i] = strtof(arg[i],&leftover);
			if ( leftover[0] != '\0' ) {
				printf("Error in LookAt: Invalid argument \n");
			    return 1;
			}
			i++;
		}
		if(i<=9)
		{
			printf("Error in LookAt: Not enough arguments \n");
			return 1;
		}
		lookAt(param[0],param[1],param[2],param[3],param[4],param[5],param[6],param[7],param[8]);
		return 0;
	}
	catch(...)
	{
		return 1;
	}
}

int ThreeD::vertex(char * arg[])
{
	try
	{
		float param[3];
		int i = 1;
		char *leftover;
		while (arg[i] != NULL && i <= 3) {
			param[i] = strtof(arg[i],&leftover);
			if ( leftover[0] != '\0' ) {
				printf("Error in Vertex: Invalid argument \n");
			    return 1;
			}
			i++;
		}
		for (int j = i; j<=3; j++) param[j] = 0.;
			vertex(param[0],param[1],param[2]);
		return 0;
	}
	catch(...)
	{
		return 1;
	}
}

int ThreeD::reset(char * arg[])
{
	try
	{
		reset();
		return 0;
	}
	catch(...)
	{
		return 1;
	}
}

New paste

  Language:
Private   — Wrap long lines  —  3 + 1 =   —  

About this pastebin

Welcome to the bulix.org / pastebin. Please don't use this pastebin for illegal purposes, defamation or kitten-squashing.

This pastebin is written using PHP and MySQL and relies on Alex Gorbatchev's syntax hhighlighter (JavaScript based). To avoid spam, you will be required to complete a small mathematical challenge when adding a new paste.

New! Try the pastebin command-line tool: paste.py (requires Python and python-beautifulsoup).

Powered by the Bulix.org Code Pastebin, by Maxime Petazzoni. View pastebin statistics.