Browse Source

Lesson 19.9

Godzil 3 years ago
parent
commit
7b1a944e57
1 changed files with 63 additions and 5 deletions
  1. 63 5
      source/triangle.c

+ 63 - 5
source/triangle.c

@@ -9,6 +9,7 @@
 
 #include <display.h>
 #include <triangle.h>
+#include <math.h>
 
 void drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, colour_t colour)
 {
@@ -109,6 +110,51 @@ void drawFilledTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t
 }
 
 /* ----------------------------------- Textured triangles ----------------------------------- */
+static vec3_t barycentricWeights(vec2_t a, vec2_t b, vec2_t c, vec2_t p)
+{
+    vec2_t ab = vec2SubVectors(b, a);
+    vec2_t bc = vec2SubVectors(c, b);
+    vec2_t ac = vec2SubVectors(c, a);
+    vec2_t ap = vec2SubVectors(p, a);
+    vec2_t bp = vec2SubVectors(p, b);
+    vec3_t ret;
+
+    double areaTriangleABC = (ab.x * ac.y) - (ab.y * ac.x);
+
+    double alpha = ((bc.x * bp.y) - (bp.x * bc.y)) / areaTriangleABC;
+    double beta = ((ap.x * ac.y) - (ac.x * ap.y)) / areaTriangleABC;
+    double gamma = 1 - alpha - beta;
+
+    ret.x = alpha;
+    ret.y = beta;
+    ret.z = gamma;
+
+    return ret;
+}
+
+static void drawTexel(int32_t x, int32_t y, vec2_t a, vec2_t b, vec2_t c, tex2_t ta, tex2_t tb, tex2_t tc, uint32_t *texture)
+{
+    vec2_t pointP = { x, y };
+    vec3_t weights = barycentricWeights(a, b, c, pointP);
+
+    double alpha = weights.x;
+    double beta = weights.y;
+    double gamma = weights.z;
+    double interpolatedU, interpolatedV;
+    int32_t texX, texY;
+
+    interpolatedU = ta.u * alpha + tb.u * beta + tc.u * gamma;
+    interpolatedV = ta.v * alpha + tb.v * beta + tc.v * gamma;
+
+    texX = abs((int32_t)(interpolatedU * textureWidth));
+    texY = abs((int32_t)(interpolatedV * textureHeight));
+
+    texX = texX % textureWidth;
+    texY = texY % textureWidth;
+
+    drawPixel(x, y, texture[(texY * textureWidth) + texX]);
+}
+
 
 void drawTextureTriangle(struct triangle_t *t)
 {
@@ -133,12 +179,16 @@ void drawTextureTriangle(struct triangle_t *t)
         doubleSwap(&t->textureCoordinates[0].v, &t->textureCoordinates[1].v);
     }
 
+    vec2_t a = t->points[0];
+    vec2_t b = t->points[1];
+    vec2_t c = t->points[2];
+
     /* Render the top part */
     double inverseSlope1 = 0;
     double inverseSlope2 = 0;
-    int32_t x0 = t->points[0].x, y0 = t->points[0].y;
-    int32_t x1 = t->points[1].x, y1 = t->points[1].y;
-    int32_t x2 = t->points[2].x, y2 = t->points[2].y;
+    int32_t x0 = a.x, y0 = a.y;
+    int32_t x1 = b.x, y1 = b.y;
+    int32_t x2 = c.x, y2 = c.y;
 
     if ((y1 - y0) != 0) { inverseSlope1 = (double)(x1 - x0) / abs(y1 - y0); }
     if ((y2 - y0) != 0) { inverseSlope2 = (double)(x2 - x0) / abs(y2 - y0); }
@@ -157,7 +207,11 @@ void drawTextureTriangle(struct triangle_t *t)
 
             for (x = xStart ; x <= xEnd ; x++)
             {
-                drawPixel(x, y, (x%2 == 0)?0xFFFF00FF:0xFF000000);
+                drawTexel(x, y, a, b, c,
+                          t->textureCoordinates[0],
+                          t->textureCoordinates[1],
+                          t->textureCoordinates[2],
+                          t->texture);
             }
         }
     }
@@ -180,7 +234,11 @@ void drawTextureTriangle(struct triangle_t *t)
 
             for (x = xStart ; x <= xEnd ; x++)
             {
-                drawPixel(x, y, (x%2 == 0)?0xFFFF00FF:0xFF000000);
+                drawTexel(x, y, a, b, c,
+                          t->textureCoordinates[0],
+                          t->textureCoordinates[1],
+                          t->textureCoordinates[2],
+                          t->texture);
             }
         }
     }