#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;
}
}
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.