Browse Source

Lesson 24.13

Godzil 3 years ago
parent
commit
4f0e0de559
3 changed files with 122 additions and 59 deletions
  1. 31 12
      source/clipping.c
  2. 4 2
      source/include/clipping.h
  3. 87 45
      source/main.c

+ 31 - 12
source/clipping.c

@@ -16,19 +16,20 @@
 
 static plane_t frustum[TOTAL_PLANES];
 
-void initFrustumPlanes(double fov, double aspectRation, double zNear, double zFar)
+void  initFrustumPlanes(double fov, double aspectRation, double zNear, double zFar)
 {
+    double radFOV = (fov * M_PI) / 180.;
     frustum[LEFT_PLANE].point = vec3(0, 0, 0);
-    frustum[LEFT_PLANE].normal = vec3( cos(fov) / 2, 0, sin(fov) / 2);
+    frustum[LEFT_PLANE].normal = vec3( cos(radFOV / 2.0) , 0, sin(radFOV / 2.0));
 
     frustum[RIGHT_PLANE].point = vec3(0, 0, 0);
-    frustum[RIGHT_PLANE].normal = vec3( -cos(fov) / 2, 0, sin(fov) / 2);
+    frustum[RIGHT_PLANE].normal = vec3( -cos(radFOV / 2.0), 0, sin(radFOV / 2.0));
 
     frustum[TOP_PLANE].point = vec3(0, 0, 0);
-    frustum[TOP_PLANE].normal = vec3(0, -cos(fov) / 2, sin(fov) / 2);
+    frustum[TOP_PLANE].normal = vec3(0, -cos(radFOV / 2.0), sin(radFOV / 2.0));
 
     frustum[BOTTOM_PLANE].point = vec3(0, 0, 0);
-    frustum[BOTTOM_PLANE].normal = vec3(0, cos(fov) / 2, sin(fov) / 2);
+    frustum[BOTTOM_PLANE].normal = vec3(0, cos(radFOV / 2.0), sin(radFOV / 2.0));
 
     frustum[NEAR_PLANE].point = vec3(0, 0, zNear);
     frustum[NEAR_PLANE].normal = vec3(0, 0, 1);
@@ -37,6 +38,20 @@ void initFrustumPlanes(double fov, double aspectRation, double zNear, double zFa
     frustum[FAR_PLANE].normal = vec3(0, 0, -1);
 }
 
+void createTriangleFromPolygon(polygon_t *polygon, triangle_t *triangleList, uint32_t *outNumber)
+{
+    int i;
+    *outNumber = 0;
+    for(i = 1; i < (polygon->num_vertices - 1); i++)
+    {
+        triangleList[i - 1].points[0] = vec4FromVec3(polygon->vertices[0]);
+        triangleList[i - 1].points[1] = vec4FromVec3(polygon->vertices[i]);
+        triangleList[i - 1].points[2] = vec4FromVec3(polygon->vertices[i + 1]);
+
+        (*outNumber)++;
+        assert(*outNumber < MAX_NUM_POLYGON_TRIANGLES);
+    }
+}
 
 static void clipPolygonAgainstPlane(polygon_t *poly, faceenum_t plane)
 {
@@ -50,9 +65,9 @@ static void clipPolygonAgainstPlane(polygon_t *poly, faceenum_t plane)
     vec3_t newVertices[MAX_NUM_POLYGON_VERTICES];
     int newVerticesCount = 0;
 
-    previousVertex = &poly->vertices[poly->num_verticices - 1];
+    previousVertex = &poly->vertices[poly->num_vertices - 1];
 
-    for(i = 0; i < poly->num_verticices; i++)
+    for(i = 0; i < poly->num_vertices; i++)
     {
         currentVertex = &poly->vertices[i];
 
@@ -63,14 +78,18 @@ static void clipPolygonAgainstPlane(polygon_t *poly, faceenum_t plane)
         {
             double t;
             /* we crossed the plane */
+            vec3_t intersectionVertice;
             t = previousDot / (previousDot - currentDot);
-            newVertices[newVerticesCount] = vec3SubVectors(*currentVertex, *previousVertex);
-            vec3ScalarMult(newVertices[newVerticesCount], t);
-            newVertices[newVerticesCount] = vec3AddVectors(*currentVertex, newVertices[newVerticesCount]);
+            intersectionVertice = *currentVertex;
+            intersectionVertice = vec3SubVectors(intersectionVertice, *previousVertex);
+            intersectionVertice = vec3ScalarMult(intersectionVertice, t);
+            intersectionVertice = vec3AddVectors(intersectionVertice, *previousVertex);
+
+            newVertices[newVerticesCount] = intersectionVertice;
             newVerticesCount++;
         }
 
-        if (currentDot >= 0.0)
+        if (currentDot > 0.0)
         {
             newVertices[newVerticesCount] = *currentVertex;
             newVerticesCount++;
@@ -86,7 +105,7 @@ static void clipPolygonAgainstPlane(polygon_t *poly, faceenum_t plane)
     {
         poly->vertices[i] = newVertices[i];
     }
-    poly->num_verticices = newVerticesCount;
+    poly->num_vertices = newVerticesCount;
 }
 
 void clipPolygon(polygon_t *poly)

+ 4 - 2
source/include/clipping.h

@@ -17,6 +17,7 @@
  * Constants
  **********************************************************************************************************************/
 #define MAX_NUM_POLYGON_VERTICES (10)
+#define MAX_NUM_POLYGON_TRIANGLES (10)
 
 /***********************************************************************************************************************
  * Data types
@@ -43,7 +44,7 @@ typedef struct plane_t
 typedef struct polygon_t
 {
     vec3_t vertices[MAX_NUM_POLYGON_VERTICES];
-    int num_verticices;
+    int num_vertices;
 } polygon_t;
 
 /***********************************************************************************************************************
@@ -54,6 +55,7 @@ void initFrustumPlanes(double fov, double aspectRation, double zNear, double zFa
 /* ---- Public polygon stuff ---- */
 void clipPolygon(polygon_t *poly);
 
+void createTriangleFromPolygon(polygon_t *polygon, triangle_t *triangleList, uint32_t *outNumber);
 static inline polygon_t createPolygonFromTriangle(vec3_t p1, vec3_t p2, vec3_t p3)
 {
     polygon_t ret =
@@ -64,7 +66,7 @@ static inline polygon_t createPolygonFromTriangle(vec3_t p1, vec3_t p2, vec3_t p
             [1] = p2,
             [2] = p3,
         },
-        .num_verticices = 3
+        .num_vertices = 3
     };
     return ret;
 }

+ 87 - 45
source/main.c

@@ -43,6 +43,7 @@ typedef enum displayMode_t
 bool displayVertex = false;
 bool doNotCull = false;
 bool doZBuffer = true;
+bool doClipping = true;
 enum displayMode_t currentDisplayMode = DISPLAY_MODE_WIREFRAME;
 matrix4_t projectionMatrix;
 matrix4_t viewMatrix;
@@ -54,10 +55,10 @@ static const vec3_t origin = {0, 0, 0 };
 
 void setup()
 {
-    double FOV = 90;
+    double FOV = 60;
     double aspectRatio = (double)windowHeight / windowWidth;
-    double zNear = 0.1;
-    double zFar = 100;
+    double zNear = 1;
+    double zFar = 20;
 
     frameBuffer = (uint32_t *)calloc(windowWidth * windowHeight, sizeof(uint32_t));
     if (!frameBuffer)
@@ -172,10 +173,18 @@ void processInput()
             doZBuffer = true;
             break;
 
-        case SDLK_p:
+        case SDLK_l:
             doZBuffer = false;
             break;
 
+        case SDLK_y:
+            doClipping = true;
+            break;
+
+        case SDLK_h:
+            doClipping = false;
+            break;
+
         case SDLK_w:
             camera.forwardVelocity = vec3ScalarMult(camera.direction, 5 * deltaTime);
             camera.position = vec3AddVectors(camera.position, camera.forwardVelocity);
@@ -217,13 +226,57 @@ uint32_t getMicroSecTime()
     return ((curTime.tv_sec) * 1000 * 1000) + (curTime.tv_usec);
 }
 
+static void projectTriangle(triangle_t *baseTriangle, triangle_t *workTriangle, vec3_t *triangleNormal, colour_t colour)
+{
+    int j;
+    struct triangle_t currentTriangle = *baseTriangle;
+
+    for (j = 0 ; j < 3 ; j++)
+    {
+        vec4_t projected = mat4ProdVec4Project(projectionMatrix, workTriangle->points[j]);
+
+
+        projected.x *= windowWidth / 2.;
+        projected.y *= windowHeight / 2.;
+
+        /* Screen Y axis increase down, 3D world Y grows up, so we need to invert. */
+        projected.y *= -1.0;
+
+        projected.x += (windowWidth / 2.);
+        projected.y += (windowHeight / 2.);
+
+        currentTriangle.points[j].x = projected.x;
+        currentTriangle.points[j].y = projected.y;
+        currentTriangle.points[j].w = projected.w;
+        currentTriangle.points[j].z = projected.z;
+    }
+
+    if (doNotCull)
+    {
+        currentTriangle.colour = colour;
+    }
+    else
+    {
+        double lightLevel = -vec3Dot(*triangleNormal, globalLight.direction);
+        currentTriangle.colour = applyLight(colour, lightLevel);
+    }
+    currentTriangle.averageDepth = (workTriangle->points[0].z +
+                                    workTriangle->points[1].z +
+                                    workTriangle->points[2].z) / 3.0;
+
+    currentTriangle.texture = meshTexture;
+    arrayAdd(projectedTriangles, currentTriangle);
+}
+
 void update()
 {
     uint32_t i, j;
     uint32_t faceCount;
+    uint32_t numberOfClippedTriangles;
     uint32_t timeToWait = FRAME_TARGET_TIME - (SDL_GetTicks() - previousFrameTime);
     matrix4_t worldMatrix;
     uint32_t ticks = getMicroSecTime();
+    triangle_t trianglesAfterClipping[MAX_NUM_POLYGON_TRIANGLES];
 
     if (timeToWait <= FRAME_TARGET_TIME)
     {
@@ -252,7 +305,7 @@ void update()
     worldMatrix = mat4ProdMat4(mat4Translate(mesh.translation.x, mesh.translation.y, mesh.translation.z), worldMatrix);
 
     /* Not sure for now */
-    //worldMatrix = mat4ProdMat4(viewMatrix, worldMatrix);
+    worldMatrix = mat4ProdMat4(viewMatrix, worldMatrix);
 
     arrayEmpty(projectedTriangles);
 
@@ -260,10 +313,8 @@ void update()
     for(i = 0; i < faceCount; i++)
     {
         polygon_t polygon;
-        /* TODO: REMOVE ASAP */
-        if (i != 4) continue;
 
-        triangle_t currentTriangle =
+        triangle_t baseTriangle =
         {
             .textureCoordinates =
             {
@@ -288,7 +339,7 @@ void update()
 
             transformedVertices[j] = mat4ProdVec4(worldMatrix, transformedVertices[j]);
 
-            transformedVertices[j] = mat4ProdVec4(viewMatrix, transformedVertices[j]);
+            //transformedVertices[j] = mat4ProdVec4(viewMatrix, transformedVertices[j]);
         }
 
         vec3_t vectorBA = vec3SubVectors(vec3FromVec4(transformedVertices[1]), vec3FromVec4(transformedVertices[0]));
@@ -311,42 +362,33 @@ void update()
             }
         }
 
-        polygon = createPolygonFromTriangle(vec3FromVec4(transformedVertices[0]),
-                                            vec3FromVec4(transformedVertices[1]),
-                                            vec3FromVec4(transformedVertices[2]));
-
-        clipPolygon(&polygon);
-
-        // triangles = polyFan(&polygon)
-
-        for (j = 0 ; j < 3 ; j++)
+        if (doClipping)
         {
-            vec4_t projected = mat4ProdVec4Project(projectionMatrix, transformedVertices[j]);
-
-
-            projected.x *= windowWidth / 2.;
-            projected.y *= windowHeight / 2.;
-
-            /* Screen Y axis increase down, 3D world Y grows up, so we need to invert. */
-            projected.y *= -1.0;
+            polygon = createPolygonFromTriangle(vec3FromVec4(transformedVertices[0]),
+                                                vec3FromVec4(transformedVertices[1]),
+                                                vec3FromVec4(transformedVertices[2]));
 
-            projected.x += (windowWidth / 2.);
-            projected.y += (windowHeight / 2.);
-
-            currentTriangle.points[j].x = projected.x;
-            currentTriangle.points[j].y = projected.y;
-            currentTriangle.points[j].w = projected.w;
-            currentTriangle.points[j].z = projected.z;
+            clipPolygon(&polygon);
+            createTriangleFromPolygon(&polygon, trianglesAfterClipping, &numberOfClippedTriangles);
+            for(j = 0; j < numberOfClippedTriangles; j++)
+            {
+                projectTriangle(&baseTriangle, &trianglesAfterClipping[j], &triangleNormal, mesh.faces[i].colour);
+            }
         }
-
-        double lightLevel = -vec3Dot(triangleNormal, globalLight.direction);
-
-        currentTriangle.colour = applyLight(mesh.faces[i].colour, lightLevel);
-        currentTriangle.averageDepth = (transformedVertices[0].z +
-                                        transformedVertices[1].z +
-                                        transformedVertices[2].z) / 3.0;
-        currentTriangle.texture = meshTexture;
-        arrayAdd(projectedTriangles, currentTriangle);
+        else
+        {
+            triangle_t workTriangle =
+            {
+                .points =
+                {
+                    [0] = transformedVertices[0],
+                    [1] = transformedVertices[1],
+                    [2] = transformedVertices[2]
+                }
+            };
+
+            projectTriangle(&baseTriangle, &workTriangle, &triangleNormal, mesh.faces[i].colour);
+        };
     }
 
     if (!doZBuffer)
@@ -409,7 +451,7 @@ void render()
                 drawRectangle(projectedTriangles[i].points[j].x - 1,
                               projectedTriangles[i].points[j].y - 1,
                               3, 3,
-                              0xFFFF0000);
+                              MAKE_RGB(255, 0, 0));
             }
         }
 
@@ -426,8 +468,8 @@ void render()
     drawText(5, 29, 0x11FF22, "Render time: %02.2f ms", renderTime);
     drawText(5, 41, 0x11FF22, "FPS: %.1f | dT: %.3f", 1000 / (waitTime + updateTime + renderTime), deltaTime);
     drawText(5, 53, 0x11FF22, "Triangles: %d / %d", triangleCount, trianglesTotal);
-    drawText(5, 65, 0x11FF22, "Cull: %s | PeCo: %s | ZB: %s",
-             doNotCull?"N":"Y", doPerpectiveCorrection?"Y":"N", doZBuffer?"Y":"N");
+    drawText(5, 65, 0x11FF22, "Cull: %c | PeCo: %c | ZB: %c, | CP: %c",
+             doNotCull?'N':'Y', doPerpectiveCorrection?'Y':'N', doZBuffer?'Y':'N', doClipping?'Y':'N');
     SDL_RenderPresent(renderer);
 }