Browse Source

Lesson 19.3

Godzil 3 years ago
parent
commit
ffea3a18dd
8 changed files with 169 additions and 38 deletions
  1. BIN
      assets/pico8.ttf
  2. 7 2
      source/include/display.h
  3. 40 0
      source/include/texture.h
  4. 10 0
      source/include/triangle.h
  5. 44 17
      source/main.c
  6. 18 18
      source/mesh.c
  7. 18 0
      source/texture.c
  8. 32 1
      source/triangle.c

BIN
assets/pico8.ttf


+ 7 - 2
source/include/display.h

@@ -27,7 +27,6 @@ typedef uint32_t colour_t;
 /***********************************************************************************************************************
  * Global variables
  **********************************************************************************************************************/
-
 extern SDL_Window *window;
 extern SDL_Renderer *renderer;
 extern uint32_t *frameBuffer;
@@ -38,7 +37,6 @@ extern int32_t windowHeight;
 /***********************************************************************************************************************
  * Prototypes
  **********************************************************************************************************************/
-
 /* --- Window functions --- */
 bool initialiseWindow(bool fullScreen);
 void destroyWindow();
@@ -63,6 +61,13 @@ static inline void intSwap(int *a, int *b)
     *b = tmp;
 }
 
+static inline void doubleSwap(double *a, double *b)
+{
+    double tmp = *a;
+    *a = *b;
+    *b = tmp;
+}
+
 #define MAKE_RGB(_r, _g, _b) ((0xFF000000) | ((_r & 0xFF) << 16) | ((_g & 0xFF) << 8) | ((_b & 0xFF)))
 #define MAKE_ARGB(_a, _r, _g, _b) (((_a & 0xFF) << 24) | ((_r & 0xFF) << 16) | ((_g & 0xFF) << 8) | ((_b & 0xFF)))
 

+ 40 - 0
source/include/texture.h

@@ -0,0 +1,40 @@
+/*
+ * 3D Engine 
+ * texture.h: 
+ * Based on pikuma.com 3D software renderer in C
+ * Copyright (c) 2021 986-Studio. All rights reserved.
+ *
+ * Created by Manoël Trapier on 07/03/2021.
+ */
+
+#ifndef THREEDENGINE_SOURCE_INCLUDE_TEXTURE_H
+#define THREEDENGINE_SOURCE_INCLUDE_TEXTURE_H
+
+#include <stdint.h>
+
+#include <display.h>
+
+/***********************************************************************************************************************
+ * Data types
+ **********************************************************************************************************************/
+typedef struct tex2_t
+{
+    double u, v;
+} tex2_t;
+
+/***********************************************************************************************************************
+ * Global variables
+ **********************************************************************************************************************/
+extern int textureWidth;
+extern int textureHeight;
+
+extern const uint8_t REDBRICK_TEXTURE[];
+
+colour_t *meshTexture;
+
+
+/***********************************************************************************************************************
+ * Prototypes
+ **********************************************************************************************************************/
+
+#endif /* THREEDENGINE_SOURCE_INCLUDE_TEXTURE_H */

+ 10 - 0
source/include/triangle.h

@@ -13,6 +13,7 @@
 #include <stdint.h>
 #include <display.h>
 #include <vector.h>
+#include <texture.h>
 
 /***********************************************************************************************************************
  * Data types
@@ -21,14 +22,21 @@
 typedef struct face_t
 {
     int a, b, c;
+
+    tex2_t a_uv, b_uv, c_uv;
+
     colour_t colour;
 } face_t;
 
 typedef struct triangle_t
 {
     vec2_t points[3];
+    tex2_t textureCoordinates[3];
+
     colour_t colour;
     double averageDepth;
+
+    uint32_t *texture;
 } triangle_t;
 
 /***********************************************************************************************************************
@@ -36,6 +44,8 @@ typedef struct triangle_t
  **********************************************************************************************************************/
 void drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, colour_t colour);
 void drawFilledTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, colour_t colour);
+void drawTextureTriangle(struct triangle_t *t);
+
 int compareTrianglesZOrder(const void *p1, const void *p2);
 
 #endif /* THREEDENGINE_SOURCE_INCLUDE_TRIANGLE_H */

+ 44 - 17
source/main.c

@@ -31,7 +31,9 @@ typedef enum displayMode_t
 {
     DISPLAY_MODE_WIREFRAME,
     DISPLAY_MODE_SOLID,
-    DISPLAY_MODE_BOTH,
+    DISPLAY_MODE_SOLID_WIRE,
+    DISPLAY_MODE_TEXTURED,
+    DISPLAY_MODE_TEXTURED_WIRE,
 } displayMode_t;
 bool displayVertex = false;
 bool doNotCull = false;
@@ -73,8 +75,10 @@ void setup()
     globalLight.direction.z = 1;
     vec3Normalize(&globalLight.direction);
 
-    loadOBJFile("assets/f22.obj");
-    //loadCubeMeshData();
+    meshTexture = (colour_t *)REDBRICK_TEXTURE;
+
+    //loadOBJFile("assets/f22.obj");
+    loadCubeMeshData();
 
 exit:
     return;
@@ -114,7 +118,17 @@ void processInput()
 
         case SDLK_4:
             displayVertex = false;
-            currentDisplayMode = DISPLAY_MODE_BOTH;
+            currentDisplayMode = DISPLAY_MODE_SOLID_WIRE;
+            break;
+
+        case SDLK_5:
+            displayVertex = false;
+            currentDisplayMode = DISPLAY_MODE_TEXTURED;
+            break;
+
+        case SDLK_6:
+            displayVertex = false;
+            currentDisplayMode = DISPLAY_MODE_TEXTURED_WIRE;
             break;
 
         case SDLK_c:
@@ -157,7 +171,7 @@ void update()
     waitTime = (waitTime + (getMicroSecTime() - ticks) / 1000.) / 2.0;
     ticks = getMicroSecTime();
 
-    mesh.rotation.x += 0.001;
+    mesh.rotation.x += 0.01;
     mesh.translation.z = 5;
 
     worldMatrix = mat4Identity;
@@ -173,7 +187,15 @@ void update()
     faceCount = arrayGetSize(mesh.faces);
     for(i = 0; i < faceCount; i++)
     {
-        triangle_t currentTriangle;
+        triangle_t currentTriangle =
+        {
+            .textureCoordinates =
+            {
+                [0] = { mesh.faces[i].a_uv.u, mesh.faces[i].a_uv.v },
+                [1] = { mesh.faces[i].b_uv.u, mesh.faces[i].b_uv.v },
+                [2] = { mesh.faces[i].c_uv.u, mesh.faces[i].c_uv.v }
+            }
+        };
         vec4_t transformedVertices[3];
         vec3_t triangleNormal;
 
@@ -233,10 +255,10 @@ void update()
         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);
     }
 
@@ -263,28 +285,33 @@ void render()
         switch(currentDisplayMode)
         {
         case DISPLAY_MODE_SOLID:
+        case DISPLAY_MODE_SOLID_WIRE:
             drawFilledTriangle(projectedTriangles[i].points[0].x, projectedTriangles[i].points[0].y,
                                projectedTriangles[i].points[1].x, projectedTriangles[i].points[1].y,
                                projectedTriangles[i].points[2].x, projectedTriangles[i].points[2].y,
                                projectedTriangles[i].colour);
             break;
 
+        case DISPLAY_MODE_TEXTURED:
+        case DISPLAY_MODE_TEXTURED_WIRE:
+            drawTextureTriangle(&projectedTriangles[i]);
+            break;
+
+        default:
+            break;
+        }
+
+        switch (currentDisplayMode)
+        {
+        case DISPLAY_MODE_SOLID_WIRE:
+        case DISPLAY_MODE_TEXTURED_WIRE:
         case DISPLAY_MODE_WIREFRAME:
             drawTriangle(projectedTriangles[i].points[0].x, projectedTriangles[i].points[0].y,
                          projectedTriangles[i].points[1].x, projectedTriangles[i].points[1].y,
                          projectedTriangles[i].points[2].x, projectedTriangles[i].points[2].y,
                          projectedTriangles[i].colour);
             break;
-
-        case DISPLAY_MODE_BOTH:
-            drawFilledTriangle(projectedTriangles[i].points[0].x, projectedTriangles[i].points[0].y,
-                               projectedTriangles[i].points[1].x, projectedTriangles[i].points[1].y,
-                               projectedTriangles[i].points[2].x, projectedTriangles[i].points[2].y,
-                               projectedTriangles[i].colour);
-            drawTriangle(projectedTriangles[i].points[0].x, projectedTriangles[i].points[0].y,
-                         projectedTriangles[i].points[1].x, projectedTriangles[i].points[1].y,
-                         projectedTriangles[i].points[2].x, projectedTriangles[i].points[2].y,
-                         0xFF000000 | ~projectedTriangles[i].colour);
+        default:
             break;
         }
 

+ 18 - 18
source/mesh.c

@@ -36,24 +36,24 @@ vec3_t cubeVertices[N_CUBE_VERTICES] =
 
 face_t cubeFaces[N_CUBE_FACES] =
 {
-    /* Front */
-    { .a = 1, .b = 2, .c = 3, .colour = 0xFFFF0000 },
-    { .a = 1, .b = 3, .c = 4, .colour = 0xFFFF0000 },
-    /* Right */
-    { .a = 4, .b = 3, .c = 5, .colour = 0xFF00FF00 },
-    { .a = 4, .b = 5, .c = 6, .colour = 0xFF00FF00 },
-    /* Back */
-    { .a = 6, .b = 5, .c = 7, .colour = 0xFF0000FF },
-    { .a = 6, .b = 7, .c = 8, .colour = 0xFF0000FF },
-    /* Left */
-    { .a = 8, .b = 7, .c = 2, .colour = 0xFFFFFF00 },
-    { .a = 8, .b = 2, .c = 1, .colour = 0xFFFFFF00 },
-    /* Top */
-    { .a = 2, .b = 7, .c = 5, .colour = 0xFFFF00FF },
-    { .a = 2, .b = 5, .c = 3, .colour = 0xFFFF00FF },
-    /* Bottom */
-    { .a = 6, .b = 8, .c = 1, .colour = 0xFF00FFFF },
-    { .a = 6, .b = 1, .c = 4, .colour = 0xFF00FFFF },
+    // front
+    { .a = 1, .b = 2, .c = 3, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .colour = 0xFFFFFFFF },
+    { .a = 1, .b = 3, .c = 4, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .colour = 0xFFFFFFFF },
+    // right
+    { .a = 4, .b = 3, .c = 5, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .colour = 0xFFFFFFFF },
+    { .a = 4, .b = 5, .c = 6, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .colour = 0xFFFFFFFF },
+    // back
+    { .a = 6, .b = 5, .c = 7, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .colour = 0xFFFFFFFF },
+    { .a = 6, .b = 7, .c = 8, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .colour = 0xFFFFFFFF },
+    // left
+    { .a = 8, .b = 7, .c = 2, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .colour = 0xFFFFFFFF },
+    { .a = 8, .b = 2, .c = 1, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .colour = 0xFFFFFFFF },
+    // top
+    { .a = 2, .b = 7, .c = 5, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .colour = 0xFFFFFFFF },
+    { .a = 2, .b = 5, .c = 3, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .colour = 0xFFFFFFFF },
+    // bottom
+    { .a = 6, .b = 8, .c = 1, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .colour = 0xFFFFFFFF },
+    { .a = 6, .b = 1, .c = 4, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .colour = 0xFFFFFFFF }
 };
 
 mesh_t mesh =

File diff suppressed because it is too large
+ 18 - 0
source/texture.c


+ 32 - 1
source/triangle.c

@@ -17,6 +17,8 @@ void drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, in
     drawLine(x2, y2, x0, y0, colour);
 }
 
+/* ----------------------------------- Filled triangles ----------------------------------- */
+
 /* This function expect Point 0 to be the top, 1 to be the bottom left, 2 to be the bottom right */
 static void drawFillBottomFlatTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, colour_t colour)
 {
@@ -106,6 +108,35 @@ void drawFilledTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t
     }
 }
 
+/* ----------------------------------- Textured triangles ----------------------------------- */
+
+void drawTextureTriangle(struct triangle_t *t)
+{
+    double My, Mx, Mu, Mv;
+
+    if (t->points[0].y > t->points[1].y)
+    {
+        doubleSwap(&t->points[0].x, &t->points[1].x); doubleSwap(&t->points[0].y, &t->points[1].y);
+        doubleSwap(&t->textureCoordinates[0].u, &t->textureCoordinates[1].u);
+        doubleSwap(&t->textureCoordinates[0].v, &t->textureCoordinates[1].v);
+    }
+    if (t->points[1].y > t->points[2].y)
+    {
+        doubleSwap(&t->points[1].x, &t->points[2].x); doubleSwap(&t->points[1].y, &t->points[2].y);
+        doubleSwap(&t->textureCoordinates[1].u, &t->textureCoordinates[2].u);
+        doubleSwap(&t->textureCoordinates[1].v, &t->textureCoordinates[2].v);
+    }
+    if (t->points[0].y > t->points[1].y)
+    {
+        doubleSwap(&t->points[0].x, &t->points[1].x); doubleSwap(&t->points[0].y, &t->points[1].y);
+        doubleSwap(&t->textureCoordinates[0].u, &t->textureCoordinates[1].u);
+        doubleSwap(&t->textureCoordinates[0].v, &t->textureCoordinates[1].v);
+    }
+    
+}
+
+/* ---- Utility ---- */
+
 int compareTrianglesZOrder(const void *p1, const void *p2)
 {
     triangle_t *t1 = (struct triangle_t *)p1;
@@ -121,4 +152,4 @@ int compareTrianglesZOrder(const void *p1, const void *p2)
     }
 
     return 0;
-}
+}

Some files were not shown because too many files changed in this diff