diff --git a/App/CPP_files/Graphics.cpp b/App/CPP_files/Graphics.cpp new file mode 100644 index 0000000..06dbeb9 --- /dev/null +++ b/App/CPP_files/Graphics.cpp @@ -0,0 +1,248 @@ +#include "../header_files/Graphics.h" +#include "GL/glut.h" +#include +using namespace std; + +Vec3 ICTC_color = {1,0.4,0}; + +Window::Window(int w, int h, float nearz, float farz): + width(w), height(h), nearz(nearz), farz(farz) +{ + // initialize the zbuffer + zbuffer = vector(w*h, farz-1); +} + +void Window::clear() +{ + glClear(GL_COLOR_BUFFER_BIT); + zbuffer = vector(width*height, farz-1); +} + +void Window::refresh() +{ + glutSwapBuffers(); +} + +void Window::start() +{ + glutMainLoop(); +} + +//function overloading not used + +//void Window::setPixel(const Vec2& p, const Vec3& c, float i) +//{ +// setPixel(ROUND(p.x), ROUND(p.y), p.z, c, i); +//} + +void Window::setPixel(int x, int y, float z, const Vec3& c, float i) +{ + // clipping + if (x < 0 or x > width or y < 0 or y > height) + return; + + // check z buffer +// if (z <= zbuffer[x*height + y] or z < farz or z > nearz) +// return; +// zbuffer[x*height + y] = z; + + if (z <= zbuffer[width * y + x] or z < farz or z > nearz) + return; + zbuffer[width * y + x] = z; + + + glColor3f(c.x*i, c.y*i, c.z*i); + glBegin(GL_POINTS); + glVertex2i(x, y); + glEnd(); +} + + +//DDA Algorithm Implementation + +void Window::drawLine(const Vec2& p1, const Vec2& p2, const Vec3& c) +{ +#ifdef SOLID + int del_x = ROUND(p2.x) - ROUND(p1.x); + int del_y = ROUND(p2.y) - ROUND(p1.y); +#else + float del_x = p2.x - p1.x; + float del_y = p2.y - p1.y; +#endif + float d = p1.z, del_d = p2.z - p1.z; + float i = p1.i, del_i = p2.i - p1.i; + int step = (abs(del_x) > abs(del_y))? abs(del_x) : abs(del_y); + + float x = p1.x, y = p1.y; + if (step == 0) { + setPixel(ROUND(x), ROUND(y), d, c, i); + return; + } + + for (int k = 0; k <= step; k++) { + setPixel(ROUND(x), ROUND(y), d, c, i); + //setPixel(x, y, d, c, i); + + x += del_x / step; + y += del_y / step; + d += del_d / step; + i += del_i / step; + } +} + +void Window::fillTriangle(const Vec2& v1, const Vec2& v2, const Vec2& v3) +{ + // vec2 comparer + struct Vec2Comparer{ bool operator()(const Vec2& a, const Vec2& b) { + return a.y < b.y; }}; + vector v = {v1, v2, v3}; + sort(v.begin(), v.end(), Vec2Comparer()); + + float y, x1, z1, i1, x2, z2, i2; + for (y = v[0].y; y < v[1].y; y++) { + if (v[1].y == v[0].y) { + drawLine(Vec2(v[0].x, y, v[0].z, v[0].i), Vec2(v[1].x, y, v[1].z, v[1].i), ICTC_color); + break; + } + x1 = v[0].x + (y - v[0].y) * (v[1].x - v[0].x) / (v[1].y - v[0].y); + z1 = v[0].z + (y - v[0].y) * (v[1].z - v[0].z) / (v[1].y - v[0].y); + i1 = v[0].i + (y - v[0].y) * (v[1].i - v[0].i) / (v[1].y - v[0].y); + x2 = v[0].x + (y - v[0].y) * (v[2].x - v[0].x) / (v[2].y - v[0].y); + z2 = v[0].z + (y - v[0].y) * (v[2].z - v[0].z) / (v[2].y - v[0].y); + i2 = v[0].i + (y - v[0].y) * (v[2].i - v[0].i) / (v[2].y - v[0].y); + drawLine(Vec2(x1,y,z1,i1), Vec2(x2,y,z2,i2), ICTC_color); + } + + for (y = v[1].y; y <= v[2].y; y++) { + if (v[2].y == v[1].y) { + drawLine(Vec2(v[1].x, y, v[1].z, v[1].i), Vec2(v[2].x, y, v[2].z, v[2].i),ICTC_color); + break; + } + x1 = v[1].x + (y - v[1].y) * (v[2].x - v[1].x) / (v[2].y - v[1].y); + z1 = v[1].z + (y - v[1].y) * (v[2].z - v[1].z) / (v[2].y - v[1].y); + i1 = v[1].i + (y - v[1].y) * (v[2].i - v[1].i) / (v[2].y - v[1].y); + x2 = v[0].x + (y - v[0].y) * (v[2].x - v[0].x) / (v[2].y - v[0].y); + z2 = v[0].z + (y - v[0].y) * (v[2].z - v[0].z) / (v[2].y - v[0].y); + i2 = v[0].i + (y - v[0].y) * (v[2].i - v[0].i) / (v[2].y - v[0].y); + drawLine(Vec2(x1,y,z1,i1), Vec2(x2,y,z2,i2), ICTC_color); + } +} + +void Window::wireframe(const Scene& scene, const Vec3& camera, + const Vec3& target, float angle_x, float scale, int axis_type, float Angle_x, float angle_y, float angle_z) +{ + // project points to 2d + vector vertices2d; + for (unsigned long i = 0; i < scene.vertices.size(); i++) { + // get the coordinate of vertex + Vec3 point3d = scene.vertices[i]; + // rotate the vertex about world y-axis +// if(axis_type == 1) +// point3d = RotateX(point3d, angle); +// if(axis_type == 2) +// point3d = RotateY(point3d, angle); +// if(axis_type == 3) +// point3d = RotateZ(point3d, angle); + + point3d = RotateX(point3d, Angle_x); + point3d = RotateY(point3d, angle_y); + point3d = RotateZ(point3d, angle_z); + + + point3d = Scale(point3d,scale); + // project + Vec3 points3d = world_to_pixel(point3d, camera, target, width, height ); +// Vec2 point2d = world_to_pixel_wireFrame(point3d, camera, target, width, height ); + + Vec2 point2d = project(points3d,width,height,angle_x); + vertices2d.push_back(point2d); + } + + // draw edges + for (unsigned long i = 0; i < scene.faces.size(); i += 3) { + // get the 3 vertex's index + int index1 = scene.faces[i]; + int index2 = scene.faces[i+1]; + int index3 = scene.faces[i+2]; + // get the vertices + Vec2 p1 = vertices2d[index1]; + Vec2 p2 = vertices2d[index2]; + Vec2 p3 = vertices2d[index3]; + // draw + Vec3 Mesh_color = {1,0.2,0}; + drawLine(p1, p2,Mesh_color); + drawLine(p2, p3,Mesh_color); + drawLine(p3, p1,Mesh_color); + } +} + +void Window::render(const Scene& scene, const Vec3& camera, const Vec3& target, + const Vec3& light, float angle_x,float scale, int axis_type, float Angle_x, float angle_y, float angle_z) +{ + vector vertices2d(scene.vertices.size()); + + // project to 2d as well as find the intensities + Vec3 point3d, u, v, n, L, N, R, H, V; Mat M(4,4), P(4,1); float d; + for (unsigned long i = 0; i < scene.vertices.size(); i++) { + point3d = scene.vertices[i]; + +// // rotate the point in world axis +// if(axis_type == 1) +// point3d = RotateX(point3d, angle); +// if(axis_type == 2) +// point3d = RotateY(point3d, angle); +// if(axis_type == 3) +// point3d = RotateZ(point3d, angle); + + point3d = RotateX(point3d, Angle_x); + point3d = RotateY(point3d, angle_y); + point3d = RotateZ(point3d, angle_z); + + point3d = Scale(point3d,scale); + + point3d = world_to_pixel(point3d, camera , target, width , height); // this is in camera coordinates +// // translate camera to origin +// Vec3 temp_camera ={-camera.x, -camera.y, -camera.z}; +// point3d = translate(point3d, temp_camera); +// +// // calculate u,v,n vectors +// n = (camera - target).normalize(); +// u = cross({0,1,0}, n).normalize(); +// v = cross(n, u).normalize(); +// +// // align camera axes to world axes +// M.set({u.x, u.y, u.z, 0, +// v.x, v.y, v.z, 0, +// n.x, n.y, n.z, 0, +// 0, 0, 0, 1}); +// P.set({point3d.x, point3d.y, point3d.z, 1}); +// P = M*P; +// point3d = {P(0), P(1), P(2)}; // this is in camera coordinates + + // calculate point intensity + N = scene.normals[i].normalize(); + L = (light - point3d).normalize(); + d = (light - point3d).mag(); + R = (N*(dot(N,L)*2) - L).normalize(); + V = (camera - point3d).normalize(); + //H = (L + V).normalize(); + float intensity = 0.4 + 0.5*dot(N,L) + powf(dot(R,V), 50); + if (intensity > 1) intensity = 1; + + // project to screen coordinates + vertices2d[i] = project(point3d, width, height, angle_x); + vertices2d[i].i = intensity; + } + + // now fill every triangle + Vec2 v1, v2, v3; + for (unsigned long i = 0; i < scene.faces.size(); i += 3) { + // get vertices + v1 = vertices2d[scene.faces[i]]; + v2 = vertices2d[scene.faces[i+1]]; + v3 = vertices2d[scene.faces[i+2]]; + + // fill triangle + fillTriangle(v1, v2, v3); + } +} diff --git a/App/CPP_files/Math.cpp b/App/CPP_files/Math.cpp new file mode 100644 index 0000000..a8ccfb6 --- /dev/null +++ b/App/CPP_files/Math.cpp @@ -0,0 +1,173 @@ +#include "../header_files/Math.h" +#include +using namespace std; + +ostream& operator<<(ostream& o, const Vec3& v) +{ + return o << "(" << v.x << ", " << v.y << ", " << v.z << ")"; +} + + +ostream& operator<<(ostream& o, const Vec2& v) +{ + return o << "(" << v.x << ", " << v.y << ", " << v.z << ")"; +} + + +ostream& operator<<(ostream& o, const Mat& A) +{ + o << "["; + for (int i = 0; i < A.row; i++) { + if (i != 0) o << "; "; + for (int j = 0; j < A.col; j++) { + if (j != 0) o << ", "; + o << A(i,j); + } + } + return o << "]"; +} + + +float Mat::mag(){ + float res = 0; + int pos; + for (int i =0;i < this->row; i++) + { + for (int j=0;jcol;j++) + { + pos = (this->col)*i + j; + //pos gives the value of this(i,j) + + res += data[pos] * data[pos]; + + } + } + return sqrt(res); +} +Mat& Mat::set(const std::initializer_list& args) { +// if (_data.size() != data.size()) +// throw std::length_error("invalid size of initializer_list to assign matrix"); +// data = _data; + std::initializer_list::iterator it; + int i=0; + for ( it=args.begin(); it!=args.end(); ++it) { + (*this)(i) = *it; + i++; + } + + + return *this; +} + +float Mat::dot(Mat& mat){ + if ((this->row != mat.row) || (this->col != mat.col)) + throw "ERROR"; + int pos; + float res = 0; + for (int i =0;i < this->row; i++) + { + for (int j=0;jcol;j++) + { + pos = (this->col)*i + j; + //pos gives the value of this(i,j) + + res += data[pos] * mat(i,j); + } + } + return res; + +} + +Mat Mat::operator*(Mat& mat) +{ + if (this->col != mat.row) throw "ERROR"; + int pos; + Mat res(row,mat.col); + + for(int i = 0; i< this->row; i++ ) + { + for (int j= 0; j< mat.col; j++) + { + res(i,j) = 0; + for(int k=0; k< this->col; k++) + { + pos = (this->col)*i + k ; // ith row kth column + res(i,j) += data[pos] * mat(k,j); + } + } + } + return res; +} + +float& Mat::operator() (int r, int c) +{ + int pos = col* r + c ; + return data[pos]; +} + +const float Mat::operator() (int r, int c) const +{ + int pos = col* r + c ; + return data[pos]; +} + +float& Mat::operator() (int pos) +{ + return data[pos]; +} + +const float Mat::operator() (int pos) const +{ + return data[pos]; +} + +Mat Mat::operator+(Mat& mat) +{ + if ((this->row != mat.row) || (this->col != mat.col)) + throw "ERROR"; + Mat res(this->row,this->col); + int pos; + for (int i =0;i < this->row; i++) + { + for (int j=0;jcol;j++) + { + pos = (this->col)*i + j; + res(i,j) = data[pos] + mat(i,j); + } + } + return res; +} + +Mat Mat::operator - (Mat& mat) +{ + if ((this->row != mat.row) || (this->col != mat.col)) + throw "ERROR"; + Mat res(this->row,this->col); + int pos; + for (int i =0;i < this->row; i++) + { + for (int j=0;jcol;j++) + { + pos = (this->col)*i + j; + res(i,j) = data[pos] - mat(i,j); + } + } + return res; +} + +Mat Mat::operator / (float val) +{ + Mat res(this->row,this->col); + int pos; + + for (int i =0;i < this->row; i++) + { + for (int j=0;jcol;j++) + { + pos = (this->col)*i + j; + res(i,j) = data[pos] / val ; + } + } + + return res; +} diff --git a/App/CPP_files/Transformation.cpp b/App/CPP_files/Transformation.cpp new file mode 100644 index 0000000..0eca55c --- /dev/null +++ b/App/CPP_files/Transformation.cpp @@ -0,0 +1,357 @@ +#include "../header_files/Transformation.h" +#include +#include +#include "../header_files/Math.h" +using namespace std; + +Vec3 RotateX(Vec3& Point,float theta){ + Mat T(4,4); //Transformation matrix + Mat P(4,1); //Point matrix + float angle = theta/180*pi; + //Transformation matrix + T(0,0) = 1; T(0,1) = 0; T(0,2) = 0; T(0,3) = 0; + T(1,0) = 0; T(1,1) = cos(angle);T(1,2) = -sin(angle); T(1,3) = 0; + T(2,0) = 0; T(2,1) = sin(angle);T(2,2) = cos(angle); T(2,3) = 0; + T(3,0) = 0; T(3,1) = 0; T(3,2) = 0; T(3,3) = 1; + //Point in matrix form + P(0,0) = Point.x; P(0,1) = Point.y; P(0,2) = Point.z; P(0,3) = 1; + + P = T*P; + Point.x = P(0,0); + Point.y = P(0,1); + Point.z = P(0,2); + + return Point; + +} + +Vec3 RotateY(Vec3& Point,float theta){ + Mat T(4,4); //Transformation matrix + Mat P(4,1); //Point matrix + float angle = theta/180*pi; + //Transformation matrix + T(0,0) = cos(angle); T(0,1) = 0; T(0,2) = sin(angle); T(0,3) = 0; + T(1,0) = 0; T(1,1) = 1; T(1,2) = 0; T(1,3) = 0; + T(2,0) = -sin(angle); T(2,1) = 0; T(2,2) = cos(angle); T(2,3) = 0; + T(3,0) = 0; T(3,1) = 0; T(3,2) = 0; T(3,3) = 1; + //Point in matrix form + P(0,0) = Point.x; P(0,1) = Point.y; P(0,2) = Point.z; P(0,3) = 1; + + P = T*P; + Point.x = P(0,0); + Point.y = P(0,1); + Point.z = P(0,2); + + return Point; + +} + + +Vec3 RotateZ(Vec3& Point,float theta){ + Mat T(4,4); //Transformation matrix + Mat P(4,1); //Point matrix + float angle = theta/180*pi; + //Transformation matrix + T(0,0) = cos(angle); T(0,1) = -sin(theta); T(0,2) = 0; T(0,3) = 0; + T(1,0) = sin(angle); T(1,1) = cos(theta); T(1,2) = 0; T(1,3) = 0; + T(2,0) = 0; T(2,1) = 0; T(2,2) = 1; T(2,3) = 0; + T(3,0) = 0; T(3,1) = 0; T(3,2) = 0; T(3,3) = 1; + //Point in matrix form + P(0,0) = Point.x; P(0,1) = Point.y; P(0,2) = Point.z; P(0,3) = 1; + + P = T*P; + Point.x = P(0,0); + Point.y = P(0,1); + Point.z = P(0,2); + + return Point; + + +} + +Vec3 translate(Vec3& Point,const Vec3& tMat){ + Mat T(4,4); //Transformation matrix + Mat P(4,1); //Point matrix + //Transformation matrix + T(0,0) = 1; T(0,1) = 0; T(0,2) = 0; T(0,3) = tMat.x; + T(1,0) = 0; T(1,1) = 1; T(1,2) = 0; T(1,3) = tMat.y; + T(2,0) = 0; T(2,1) = 0; T(2,2) = 1; T(2,3) = tMat.z; + T(3,0) = 0; T(3,1) = 0; T(3,2) = 0; T(3,3) = 1; + //Point in matrix form + P(0,0) = Point.x; P(0,1) = Point.y; P(0,2) = Point.z; P(0,3) = 1; + + P = T*P; + Point.x = P(0,0); + Point.y = P(0,1); + Point.z = P(0,2); + + return Point; + +} + +Vec3 Reflect_Y(Vec3& Point,const Vec3& tMat){ + Mat T(4,4); //Transformation matrix + Mat P(4,1); //Point matrix + //Transformation matrix + T(0,0) = 0; T(0,1) = 1; T(0,2) = 0; T(0,3) = tMat.x; + T(1,0) = 1; T(1,1) = 0; T(1,2) = 0; T(1,3) = tMat.y; + T(2,0) = 0; T(2,1) = 0; T(2,2) = 1; T(2,3) = tMat.z; + T(3,0) = 0; T(3,1) = 0; T(3,2) = 0; T(3,3) = 1; + //Point in matrix form + P(0,0) = Point.x; P(0,1) = Point.y; P(0,2) = Point.z; P(0,3) = 1; + + P = T*P; + Point.x = P(0,0); + Point.y = P(0,1); + Point.z = P(0,2); + + return Point; + +} + + +Vec3 Scale(Vec3& Point,float scale){ + Mat T(4,4); //Transformation matrix + Mat P(4,1); //Point matrix + //Transformation matrix + T(0,0) = scale; T(0,1) = 0; T(0,2) = 0; T(0,3) = 0; + T(1,0) = 0; T(1,1) = scale; T(1,2) = 0; T(1,3) = 0; + T(2,0) = 0; T(2,1) = 0; T(2,2) = scale; T(2,3) = 0; + T(3,0) = 0; T(3,1) = 0; T(3,2) = 0; T(3,3) = 1; + //Point in matrix form + P(0,0) = Point.x; P(0,1) = Point.y; P(0,2) = Point.z; P(0,3) = 1; + + P = T*P; + Point.x = P(0,0); + Point.y = P(0,1); + Point.z = P(0,2); + + return Point; + +} + +//Vec2 world_to_pixel(const Vec3& source ,const Vec3& camera, const Vec3& LookTo,float planeWidth, float planeHeight, float winWidth, float winHeight){ +// //first determine the World to Camera transforming matrix +// Mat WtoC(4,4); +// //for that use the concept of N, U and V unit vectors +// Vec3 N,U,V(0,1,0); +// +// //calculate the N unit vector +// //N is the vector from LookTo point to Camera point +// N = (camera-LookTo).normalize(); +//// N = N/ N.mag(); +// +// //U = V X N +// U = cross(V,N).normalize(); +//// U = U / U.mag(); +// +// +// //readjust the V vector +// V = cross(N,U).normalize(); +//// V = V / V.mag(); +// +// //Transpose matrix from World co-ordinate to View co-ordinate +// Mat T(4,4); +// T(0,0) = 1 ; T(0,1) = 0; T(0,2) = 0; T(0,3) = -camera.x; +// T(1,0) = 0 ; T(1,1) = 1; T(1,2) = 0; T(1,3) = -camera.y; +// T(2,0) = 0 ; T(2,1) = 0; T(2,2) = 1; T(2,3) = -camera.z; +// T(3,0) = 0 ; T(3,1) = 0; T(3,2) = 0; T(3,3) = 1; +// +// //Rotation Matrix +// Mat R(4,4); +// R(0,0) = U[0] ; R(0,1) = U[1]; R(0,2) = U[2]; R(0,3) = 0; +// R(1,0) = V[0] ; R(1,1) = V[1]; R(1,2) = V[2]; R(1,3) = 0; +// R(2,0) = N[0] ; R(2,1) = N[1]; R(2,2) = N[2]; R(2,3) = 0; +// R(3,0) = 0 ; R(3,1) = 0; R(3,2) = 0; R(3,3) = 1; +// +// +// //Calculating the WtoC matrix W = T*R (rotate and then translate) +// WtoC = R*T; +//// +//// std::cout << std::endl << " MATRIX START" << std::endl; +//// WtoC.print(); +//// std::cout <<"MATRIX END"<< std::endl << std::endl; +// +// Mat S(4,1); //The source point in matrix form +// S(0) = source.x ; S(1) = source.y; S(2) = source.z ; S(3) = 1; +// +// S = WtoC * S; +// //S now represents the camera co-ordinate system's values +// //calculate the screen pixels +// +// // Perspective projection: +// +// float zprp = 1; +// Mat Persp(4,4); +// Mat Projected(4,1); +// Persp(0,0) = zprp ; Persp(0,1) = 0; Persp(0,2) = 0; Persp(0,3) = 0; +// Persp(1,0) = 0 ; Persp(1,1) = zprp; Persp(1,2) = 0; Persp(1,3) = 0; +// Persp(2,0) = 0 ; Persp(2,1) = 0; Persp(2,2) = 0; Persp(2,3) = 0; +// Persp(3,0) = 0 ; Persp(3,1) = 0; Persp(3,2) = -1; Persp(3,3) = zprp; +// Projected = Persp * S; +// +// //normalize the screen pixels +// Vec2 retVal; +// retVal.x = Projected(0)/Projected(3); +// retVal.y = Projected(1)/Projected(3); +// retVal.z = S(2); +// +// retVal.x = (retVal.x + planeWidth*0.5)/planeWidth; +// retVal.y = (retVal.y + planeHeight*0.5)/planeHeight; +// +// //now to original screen pos in computer +// retVal.x = (int)(retVal.x * winWidth); +// retVal.y = (int)((1-retVal.y) * winHeight); +// +// return retVal; +//} + +Vec2 project(Vec3 p, float width, float height, float angle_x) +{ +// float angle_y, aspect_ratio; +// aspect_ratio = width / height; +// angle_x = deg2rad(angle_x); +// angle_y = 2*atan(tan(angle_x/2) / aspect_ratio); +// +// Vec2 v; +// v.x = (1 + p.x/fabs(p.z*tan(angle_x/2))) * (width/2); +// v.y = (1 + p.y/fabs(p.z*tan(angle_y/2))) * (height/2); +// v.z = p.z; +// return v; + + + Mat S(4,1); //The source point in matrix form + S(0) = p.x ; S(1) = p.y; S(2) = p.z ; S(3) = 1; + float zprp = -1; + Mat Persp(4,4); + Mat Projected(4,1); + Persp(0,0) = zprp ; Persp(0,1) = 0; Persp(0,2) = 0; Persp(0,3) = 0; + Persp(1,0) = 0 ; Persp(1,1) = zprp; Persp(1,2) = 0; Persp(1,3) = 0; + Persp(2,0) = 0 ; Persp(2,1) = 0; Persp(2,2) = zprp; Persp(2,3) = 0; + Persp(3,0) = 0 ; Persp(3,1) = 0; Persp(3,2) = -1; Persp(3,3) = -zprp; + Projected = Persp * S; + p.x = Projected(0); + p.y = Projected(1); + p.z = Projected(2); + +// Projected = Reflect_Y(p,p); + + p = translate(p,{0,3,0}); + Projected(0) = p.x; + Projected(1) = p.y; + Projected(2) = p.z; + + + //normalize the screen pixels + Vec2 retVal; + retVal.x = Projected(0)/Projected(3); + retVal.y = Projected(1)/Projected(3); + retVal.z = S(2); + + float planeWidth = .5; + float planeHeight = .3; + retVal.x = (retVal.x + planeWidth*0.5)/planeWidth; + retVal.y = (retVal.y + planeHeight*0.5)/planeHeight; + + //now to original screen pos in computer + retVal.x = (int)((1-retVal.x) * width); + retVal.y = (int)((1-retVal.y) * height); + + return retVal; +} + + + +Vec2 world_to_pixel_wireFrame(Vec3 p, Vec3 cam, Vec3 target, float win_width, float win_height, float angle_x){ + + p = world_to_pixel(p,cam,target,win_height,win_height); + float angle_y, aspect_ratio; + aspect_ratio = win_width / win_height; + angle_x = deg2rad(angle_x); + angle_y = 2*atan(tan(angle_x/2) / aspect_ratio); + + Vec2 v; + v.x = (1 + p.x/fabs(p.z*tan(angle_x/2))) * (win_width/2); + v.y = (1 + p.y/fabs(p.z*tan(angle_y/2))) * (win_height/2); + v.z = p.z; + return v; + + +} + +Vec3 world_to_pixel(Vec3 p, Vec3 cam, Vec3 target, float win_width, float win_height, float angle_x) +{ + //first determine the World to Camera transforming matrix + Mat WtoC(4,4); + //for that use the concept of N, U and V unit vectors + Vec3 N,U,V(0,1,0); + + //calculate the N unit vector + //N is the vector from LookTo point to Camera point +// N = (cam-target).normalize(); + target = {-target.x, -target.y, -target.z}; + N = translate(cam,target).normalize(); + + + //U = V X N + U = cross(V,N).normalize(); + + + //readjust the V vector + V = cross(N,U).normalize(); + + //Transpose matrix from World co-ordinate to View co-ordinate + Mat T(4,4); + T(0,0) = 1 ; T(0,1) = 0; T(0,2) = 0; T(0,3) = -cam.x; + T(1,0) = 0 ; T(1,1) = 1; T(1,2) = 0; T(1,3) = -cam.y; + T(2,0) = 0 ; T(2,1) = 0; T(2,2) = 1; T(2,3) = -cam.z; + T(3,0) = 0 ; T(3,1) = 0; T(3,2) = 0; T(3,3) = 1; + + //Rotation Matrix + Mat R(4,4); + R(0,0) = U[0] ; R(0,1) = U[1]; R(0,2) = U[2]; R(0,3) = 0; + R(1,0) = V[0] ; R(1,1) = V[1]; R(1,2) = V[2]; R(1,3) = 0; + R(2,0) = N[0] ; R(2,1) = N[1]; R(2,2) = N[2]; R(2,3) = 0; + R(3,0) = 0 ; R(3,1) = 0; R(3,2) = 0; R(3,3) = 1; + + + //Calculating the WtoC matrix W = T*R (rotate and then translate) + WtoC = R*T; + + Mat S(4,1); //The source point in matrix form + S(0) = p.x ; S(1) = p.y; S(2) = p.z ; S(3) = 1; + + S = WtoC * S; + //S now represents the camera co-ordinate system's values + + p = {S(0), S(1), S(2)}; + + + + + +// // calculate u, v, n vectors +// Vec3 n = (cam - target).normalize(); +// Vec3 u = cross(Vec3(0,1,0), n).normalize(); +// Vec3 v = cross(n, u).normalize(); +// +// // translate cam to origin +// Vec3 temp_cam = {-cam.x, -cam.y, -cam.z}; +// p = translate(p, temp_cam); +// //cout << "Translated point = " << p << endl; // DEBUG +// +// // rotate to align the axes +// Mat R(4,4); +// R.set({u.x, u.y, u.z, 0, +// v.x, v.y, v.z, 0, +// n.x, n.y, n.z, 0, +// 0, 0, 0, 1}); +// Mat P(4,1); P.set({p.x, p.y, p.z, 1}); +// P = R * P; +// p = {P(0), P(1), P(2)}; + +// return project(p, win_width, win_height, angle_x); + return p; + +} + diff --git a/App/CPP_files/load.cpp b/App/CPP_files/load.cpp new file mode 100644 index 0000000..0c74861 --- /dev/null +++ b/App/CPP_files/load.cpp @@ -0,0 +1,82 @@ +#include "../header_files/load.h" +#include +#include +#include +#include "../header_files/Math.h" +using namespace std; + +void Scene::load(const string& filename) +{ + vertices.clear(); + faces.clear(); + + ifstream objfile(filename); + if (!objfile) throw runtime_error("unable to open the object file"); + + string line, keyword; + while (getline(objfile, line)) { + istringstream linestream(line); + linestream >> keyword; + + if (keyword == "v") { + Vec3 v; + linestream >> v.x >> v.y >> v.z; + vertices.push_back(v); + } + + else if (keyword == "f") { + // get three strings + string temp; + for (int i = 0; i < 3; i++) { + linestream >> temp; + faces.push_back(stoi(temp) - 1); + } + + } + } + + // don't forget to close the file + objfile.close(); + calculateNormal(); +} + +void Scene::print() const +{ + // print vertices and normals + for (unsigned long i = 0; i < vertices.size(); i++) + cout << vertices[i] << " ==> " << normals[i] << endl; +} + +void Scene::calculateNormal() +{ + vector count(vertices.size(), 0); + normals = vector(vertices.size(), Vec3(0,0,0)); + + for (unsigned long i = 0; i < faces.size(); i += 3) { + // get 3 indices of vertices of this face + int i1 = faces[i]; + int i2 = faces[i+1]; + int i3 = faces[i+2]; + + // get the vertices + Vec3 v1 = vertices[i1]; + Vec3 v2 = vertices[i2]; + Vec3 v3 = vertices[i3]; + + // calculate normal of face + if ((v2-v1).mag() < 0.00001) v2 = v2 * 1.000001; + if ((v3-v2).mag() < 0.00001) v3 = v3 * 1.000001; + Vec3 A = (v2 - v1).normalize(); + Vec3 B = (v3 - v2).normalize(); + Vec3 N = cross(A,B).normalize(); + + // add this normal to all 3 vertices and increment respective counts + normals[i1] = normals[i1] + N; count[i1]++; + normals[i2] = normals[i2] + N; count[i2]++; + normals[i3] = normals[i3] + N; count[i3]++; + } + + // find mean normals of all vertices + for (unsigned long i = 0; i < vertices.size(); i++) + normals[i] = (normals[i]).normalize(); +} diff --git a/App/main.cpp b/App/main.cpp new file mode 100644 index 0000000..ef69979 --- /dev/null +++ b/App/main.cpp @@ -0,0 +1,137 @@ +#include "header_files/Math.h" +#include +#include "GL/glut.h" +#include "header_files/load.h" +#include "header_files/Graphics.h" +#include "header_files/Transformation.h" +#include "header_files/main.h" +using namespace std; + +// global variables +Vec3 CAMERA(0, 0, 40), TARGET(0, 0, 0), LIGHT(10, 10, 10); +Scene SCENE; +float FIELD_OF_VIEW = 45, ANGLE_X = 0, ANGLE_Y = 0, ANGLE_Z = 0; +Window WINDOW; +int type = 1; +int axis_type = 2; +float scale = 1.0; + +void display(); +void keyboard(unsigned char key, int x, int y); +void special(int key, int x, int y); + +int main(int argc, char **argv) +{ + SCENE.load(string(argv[1])); + WINDOW = Window(1366, 768, -1, -200); + + // initialize GL + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); + glutInitWindowSize(WINDOW.width, WINDOW.height); + glutCreateWindow("ICTC"); + + glClearColor(1, 1, 1, 0); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0, WINDOW.width, 0, WINDOW.height); + + glutDisplayFunc(display); + glutKeyboardFunc(keyboard); + glutSpecialFunc(special); + + WINDOW.start(); +} + +void display() +{ + WINDOW.clear(); + if(type == 1) + WINDOW.render(SCENE, CAMERA, TARGET, LIGHT, FIELD_OF_VIEW, scale, axis_type, ANGLE_X, ANGLE_Y, ANGLE_Z); + else if(type == 2) + WINDOW.wireframe(SCENE, CAMERA, TARGET, FIELD_OF_VIEW, scale, axis_type, ANGLE_X, ANGLE_Y, ANGLE_Z); + WINDOW.refresh(); +} + +void keyboard(unsigned char key, int x, int y) +{ + if (key == 'x') + type = 1; + if (key == 'z') + type = 2; + + if (key == 27) + exit(EXIT_SUCCESS); + + else if (key == 'w') + CAMERA.z--; + else if (key == 's') + CAMERA.z++; + else if (key == 'a') + CAMERA.x--; + else if (key == 'd') + CAMERA.x++; + else if (key == 'q') + CAMERA.y--; + else if (key == 'e') + CAMERA.y++; + + else if (key == 'i') + LIGHT.z--; + else if (key == 'k') + LIGHT.z++; + else if (key == 'j') + LIGHT.x--; + else if (key == 'l') + LIGHT.x++; + else if (key == 'u') + LIGHT.y--; + else if (key == 'o') + LIGHT.y++; + + else if (key == 't') + TARGET.z--; + else if (key == 'g') + TARGET.z++; + else if (key == 'f') + TARGET.x--; + else if (key == 'h') + TARGET.x++; + else if (key == 'r') + TARGET.y--; + else if (key == 'y') + TARGET.y++; + else if (key == 'b') + axis_type = 1; + else if (key == 'n') + axis_type = 2; + else if (key == 'm') + axis_type = 3; + + + glutPostRedisplay(); +} + +void special(int key, int x, int y) +{ + if (key == GLUT_KEY_LEFT) + ANGLE_Y -= 1; + else if (key == GLUT_KEY_RIGHT) + ANGLE_Y += 1; + else if (key == GLUT_KEY_DOWN) + ANGLE_Z -= .01; + else if (key == GLUT_KEY_UP) + ANGLE_Z += .01; + else if (key == GLUT_KEY_PAGE_UP) + ANGLE_X += 1; + else if (key == GLUT_KEY_PAGE_DOWN) + ANGLE_X -= 1; + else if (key ==GLUT_KEY_F1) + scale = scale* 1.1; + else if (key ==GLUT_KEY_F2) + scale = scale* 0.9; + + + + glutPostRedisplay(); +} diff --git a/Reports/pictures/five.png b/Reports/pictures/five.png new file mode 100644 index 0000000..24d32ac Binary files /dev/null and b/Reports/pictures/five.png differ diff --git a/Reports/pictures/four.png b/Reports/pictures/four.png new file mode 100644 index 0000000..92d9ce6 Binary files /dev/null and b/Reports/pictures/four.png differ diff --git a/Reports/pictures/one.png b/Reports/pictures/one.png new file mode 100644 index 0000000..bfab273 Binary files /dev/null and b/Reports/pictures/one.png differ diff --git a/Reports/pictures/three.png b/Reports/pictures/three.png new file mode 100644 index 0000000..73d619f Binary files /dev/null and b/Reports/pictures/three.png differ diff --git a/Reports/pictures/two.png b/Reports/pictures/two.png new file mode 100644 index 0000000..8d62902 Binary files /dev/null and b/Reports/pictures/two.png differ diff --git a/Reports/pictures/zero.png b/Reports/pictures/zero.png new file mode 100644 index 0000000..972b703 Binary files /dev/null and b/Reports/pictures/zero.png differ