Browse Source

Added projection matrix and modified rasterizer.

angel 7 years ago
parent
commit
609268c8cf
7 changed files with 133 additions and 76 deletions
  1. 2 2
      include/matrix.h
  2. 2 0
      include/vector3.h
  3. 4 15
      src/engine.cpp
  4. 44 11
      src/matrix.cpp
  5. 1 1
      src/model.cpp
  6. 76 47
      src/rasterizer.cpp
  7. 4 0
      src/vector.cpp

+ 2 - 2
include/matrix.h

@@ -18,7 +18,7 @@ class Matrix4{
         }
         Matrix4 operator* (Matrix4 &rhs);
 
-        Vector3 matMultVec(Vector3 &vec, float w);
+        Vector3 matMultVec(Vector3 &vec);
         
         void printMat();
 
@@ -35,7 +35,7 @@ class Matrix4{
         Matrix4 static lookAt(Vector3& position, Vector3& target, Vector3& temp);
 
         //2D to 3D projection matrix
-        Matrix4 static makeProjectionMatrix(float fov, float far, float near);
+        Matrix4 static makeProjectionMatrix(float fov, float AR, float near, float far);
 
 
     private:

+ 2 - 0
include/vector3.h

@@ -27,6 +27,8 @@ struct Vector3{
 
     float   dotProduct(Vector3 &rhs);
 
+    void print();
+
 };
 
 #endif

+ 4 - 15
src/engine.cpp

@@ -78,9 +78,9 @@ void Engine::loadModels(){
 
     //We also initialize the model position here position here
     TransformParameters initParameters;
-    initParameters.scaling = Vector3(90, 90, 90);
+    //initParameters.scaling = Vector3(1, 60, 60);
     initParameters.rotation = Vector3(0,0,0);
-    initParameters.translation = Vector3(0, 0, 0);
+    initParameters.translation = Vector3(0, -1, 0);
 
     sceneModels->initPosition(initParameters);
 
@@ -92,18 +92,7 @@ void Engine::loadModels(){
 //Actually it should probably be moved by user input
 void Engine::moveModels(int dt){
 
-    //Creating view matrix
-    
-
-
-    // //Getting vector of vertices
-    // Mesh * modelMesh = sceneModels->getMesh();
-    // int size = modelMesh->numVertices;
-    // std::vector<Vector3> * vertices = &modelMesh->vertices;
-
-    // //Applying the multiplication
-    // for (int i = 0;i < size; ++i){
-    //     (*vertices)[i] = viewMatrix.matMultVec((*vertices)[i],1);
-    // }
+    //I freed the engine from moving stuff!
+    //Now it's technically the camera that moves and everything else follows
 
 }

+ 44 - 11
src/matrix.cpp

@@ -1,22 +1,40 @@
 #include "matrix.h"
 #include <math.h>
 
-Vector3 Matrix4::matMultVec(Vector3 &vec, float w){
+
+Vector3 Matrix4::matMultVec(Vector3 &vec){
+
     Vector3 newVec(0,0,0);
+    float w2 = 0;
     newVec.x = vec.x*(*this)(0,0)+
                vec.y*(*this)(0,1)+
                vec.z*(*this)(0,2)+
-               w*(*this)(0,3);
+               (*this)(0,3); //Assuming wO of vec always  = 1
 
     newVec.y = vec.x*(*this)(1,0)+
                vec.y*(*this)(1,1)+
                vec.z*(*this)(1,2)+
-               w*(*this)(1,3);
+               (*this)(1,3); //Assuming wO of vec always  = 1
 
     newVec.z = vec.x*(*this)(2,0)+
                vec.y*(*this)(2,1)+
                vec.z*(*this)(2,2)+
-               w*(*this)(2,3);
+               (*this)(2,3); //Assuming wO of vec always  = 1
+
+    w2       = vec.x*(*this)(3,0)+
+               vec.y*(*this)(3,1)+
+               vec.z*(*this)(3,2)+
+               (*this)(3,3); //Assuming wO of vec always  = 1
+    
+    //Division is expensive, only do it if you need it
+    //Also here is where perspective divide happens!
+    //vec.print();
+    //printf("%f\n",w2);
+    if(w2 != 1){
+        newVec.x /= w2;
+        newVec.y /= w2;
+        newVec.z /= w2;
+    }
 
     return newVec;
 }
@@ -147,16 +165,31 @@ Matrix4 Matrix4::transformMatrix(TransformParameters transform){
     return  translationMatrix*(temp);
 }
 
-Matrix4 Matrix4::makeProjectionMatrix(float fov, float far, float near){
+Matrix4 Matrix4::makeProjectionMatrix(float fov, float AR, float near, float far){
+    float top   =  tan( (fov/2) * (M_PI / 180) ) * near;
+    float bot   =  -top;
+    float right =  top * AR;
+    float left  =  bot * AR;
     Matrix4 projectionMat;
-    //float scale   = 1 / tan( (fov/2) * (M_PI / 180) );
-    //float zScale1 = 
+    float scale   = 1 / tan( (fov/2) * (M_PI / 180) );
 
-    projectionMat(0,0) = 1;
-    projectionMat(1,1) = 1;
-    projectionMat(2,2) = -1;
-    projectionMat(3,2) = -1;
 
+    //First Row
+    projectionMat(0,0) = 2 * near / (right - left);
+    projectionMat(0,2) = (right + left) / (right - left);
+
+    //Second row
+    projectionMat(1,1) = 2 * near / (top - bot);
+    projectionMat(1,2) = (top+bot) / (top - bot);
+
+    //Third row
+    projectionMat(2,2) = - (far + near) / (far - near);
+    projectionMat(2,3) = -2 * (far * near) / (far - near);
+    
+    //Fourth row
+    projectionMat(3,2) = -1;
+    
+    return projectionMat;
 }
 
 Matrix4 Matrix4::lookAt(Vector3& position, Vector3& target, Vector3& temp){

+ 1 - 1
src/model.cpp

@@ -82,6 +82,6 @@ void Model::initPosition(TransformParameters initVals){
 
     //Applying the multiplication
     for (int i = 0;i < size; ++i){
-        (*vertices)[i] = modelMatrix.matMultVec((*vertices)[i],1);
+        (*vertices)[i] = modelMatrix.matMultVec((*vertices)[i]);
     }
 }

+ 76 - 47
src/rasterizer.cpp

@@ -38,66 +38,95 @@ void Rasterizer::drawModels(Model * models){
     std::vector<Vector3> * faces = &modelMesh->faces;
     std::vector<Vector3> * vertices = &modelMesh->vertices;
 
+    //View Matrix stuff, to be moved elsewhere
+    //Represents a camera rotating around the origin
     float t = static_cast<float>(SDL_GetTicks());
-    float radius = 10;
-    float camX   = std::sin(t/4000) * radius;
-    float camZ   = std::cos(t/4000) * radius;
+    float radius = 8;
+    float camX   = std::sin(t/5000) * radius;
+    float camZ   = std::cos(t/5000) * radius;
     Vector3 pos(camX, 0, camZ);
     Vector3 tar;
     Vector3 v(0,1,0);
     Matrix4 viewMatrix = Matrix4::lookAt(pos,tar,v);
+    viewMatrix = Matrix4::makeTranslateMat(0,camX,0)*viewMatrix;
+
+    //Creating perspective matrix
+    //No need to build it each frame since fov and near far clipping is normally
+    //Not something that changes every frame
+    float fov = 90;
+    float aspectRatio = mCanvas->mWidth / (float)mCanvas->mHeight;
+    float near = 0.1;
+    float far  = 100;
+    Matrix4 perspectiveMatrix = Matrix4::makeProjectionMatrix(fov, aspectRatio, near,far);
+
+    //perspectiveMatrix.printMat();
+    //SDL_Delay(1000);
+
+    Matrix4 viewProjectionMatrix = perspectiveMatrix*viewMatrix;
+
+    //viewProjectionMatrix.printMat();
+
+    //SDL_Delay(1000);
 
     for (Vector3 f : *faces ){
-        Vector3 v1 = viewMatrix.matMultVec((*vertices)[f.x-1],1); //-1 because .obj file starts face count
-        Vector3 v2 = viewMatrix.matMultVec((*vertices)[f.y-1],1); // from 1. Should probably fix this 
-        Vector3 v3 = viewMatrix.matMultVec((*vertices)[f.z-1],1); // At some point
-        drawLine(v1, v2, red);
-        drawLine(v2, v3, green);
-        drawLine(v1, v3, blue);
+        //(*vertices)[f.x-1].print();
+        Vector3 v1 = viewProjectionMatrix.matMultVec((*vertices)[f.x-1]); //-1 because .obj file starts face count
+        //Vector3 v2 = viewProjectionMatrix.matMultVec((*vertices)[f.y-1]); // from 1. Should probably fix this 
+        //Vector3 v3 = viewProjectionMatrix.matMultVec((*vertices)[f.z-1]); // At some point
+       // v1.print();
+        if(v1.x < -1 || v1.x > 1 || v1.y < -1 || v1.y > 1 || v1.z > 1 || v1.z < -1) continue;
+        //if(v2.x < -1 || v2.x > 1 || v2.y < -1 || v2.y > 1) continue;
+        //v1.print();
+        //SDL_Delay(1000);
+        drawLine(v1, v1, red);
+        //drawLine(v2, v3, green);
+        //drawLine(v1, v3, blue);
     }
 
 }   
 
 void Rasterizer::drawLine(Vector3 vertex1, Vector3 vertex2, Uint32 color){
 
-        int x1 = (vertex1.x ) + mCanvas->mWidth * 1 / 2;
-        int y1 = (-vertex1.y ) + mCanvas->mHeight * 2 / 3;
-        int x2 = (vertex2.x  ) + mCanvas->mWidth  * 1 / 2;
-        int y2 = (-vertex2.y ) + mCanvas->mHeight * 2 / 3;
-        
-        //transpose line if it is too steep
-        bool steep = false;
-        if (std::abs(x1-x2) < std::abs(y1-y2) ){
-            std::swap(x1,y1);
-            std::swap(x2,y2);
-            steep = true;
-        }
-
-        //Redefine line so that it is left to right
-        if ( x1  > x2 ){
-            std::swap(x1,x2);
-            std::swap(y1,y2);
-        }
-        int dx = x2 - x1;
-        int dy = y2 - y1;
-        int derror2 = std::abs(dy)*2;
-        int error2 = 0;
-        int y = y1;
-
-        for(int x=x1; x <= x2 ; x++){
-            if(steep){
-                    setPixelColor(color, y, x);
-                }
-                else{
-                    setPixelColor(color, x, y);
-                }
-            error2 += derror2;
-            if (error2 > dx){
-                y += (y2 > y1  ? 1 : -1);
-                error2 -= dx*2;
-            }
-
-        }
+        int x1 = (vertex1.x + 1 ) * mCanvas->mWidth * 0.5;
+        int y1 = (-vertex1.y + 1 ) * mCanvas->mHeight * 0.5;
+        //int x2 = (vertex2.x +1 ) * mCanvas->mWidth  * 0.5;
+        //int y2 = (-vertex2.y +1 ) * mCanvas->mHeight * 0.5;
+
+        setPixelColor(color, x1, y1);
+
+        // //transpose line if it is too steep
+        // bool steep = false;
+        // if (std::abs(x1-x2) < std::abs(y1-y2) ){
+        //     std::swap(x1,y1);
+        //     std::swap(x2,y2);
+        //     steep = true;
+        // }
+
+        // //Redefine line so that it is left to right
+        // if ( x1  > x2 ){
+        //     std::swap(x1,x2);
+        //     std::swap(y1,y2);
+        // }
+        // int dx = x2 - x1;
+        // int dy = y2 - y1;
+        // int derror2 = std::abs(dy)*2;
+        // int error2 = 0;
+        // int y = y1;
+
+        // for(int x=x1; x <= x2 ; x++){
+        //     if(steep){
+        //             setPixelColor(color, y, x);
+        //         }
+        //         else{
+        //             setPixelColor(color, x, y);
+        //         }
+        //     error2 += derror2;
+        //     if (error2 > dx){
+        //         y += (y2 > y1  ? 1 : -1);
+        //         error2 -= dx*2;
+        //     }
+
+        // }
         
 }
 

+ 4 - 0
src/vector.cpp

@@ -39,4 +39,8 @@ float Vector3::length(){
     return std::sqrt((this->x * this->x) +
                      (this->y * this->y) +
                      (this->z * this->z));
+}
+
+void Vector3::print(){
+    printf("Vec: %f\t%f\t%f\n",x,y,z);
 }