123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- /*
- * 3D Engine
- * triangle.c:
- * Based on pikuma.com 3D software renderer in C
- * Copyright (c) 2021 986-Studio. All rights reserved.
- *
- * Created by Manoël Trapier on 04/03/2021.
- */
- #include <display.h>
- #include <triangle.h>
- void drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, colour_t colour)
- {
- drawLine(x0, y0, x1, y1, colour);
- drawLine(x1, y1, x2, y2, colour);
- 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)
- {
- int i;
- int32_t deltaXL = x1 - x0;
- int32_t deltaXR = x2 - x0;
- int32_t deltaY = y1 - y0;
- int32_t sideLength = abs(deltaY);
- double incrementXL = deltaXL / (double)sideLength;
- double incrementXR = deltaXR / (double)sideLength;
- double incrementY = deltaY / (double)sideLength;
- double currentXL = x0;
- double currentXR = x0;
- double currentY = y0;
- for(i = 0; i < sideLength; i++)
- {
- drawHLine(round(currentXL), round(currentY), round(currentXR), colour);
- currentXL += incrementXL;
- currentXR += incrementXR;
- currentY += incrementY;
- }
- }
- /* This function expect Point 2 to be the bottom, 0 to be the top left, 1 to be the top right */
- static void drawFillTopFlatTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, colour_t colour)
- {
- int i;
- int32_t deltaXL = x0 - x2;
- int32_t deltaXR = x1 - x2;
- int32_t deltaY = y0 - y2;
- int32_t sideLength = abs(deltaY);
- if (sideLength == 0)
- {
- return;
- }
- double incrementXL = deltaXL / (double)sideLength;
- double incrementXR = deltaXR / (double)sideLength;
- double incrementY = deltaY / (double)sideLength;
- double currentXL = x2;
- double currentXR = x2;
- double currentY = y2;
- for(i = 0; i <= sideLength; i++)
- {
- drawHLine(round(currentXL), round(currentY), round(currentXR), colour);
- currentXL += incrementXL;
- currentXR += incrementXR;
- currentY += incrementY;
- }
- }
- void drawFilledTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, colour_t colour)
- {
- int32_t My, Mx;
- if (y0 > y1)
- {
- intSwap(&x0, &x1); intSwap(&y0, &y1);
- }
- if (y1 > y2)
- {
- intSwap(&x1, &x2); intSwap(&y1, &y2);
- }
- if (y0 > y1)
- {
- intSwap(&x0, &x1); intSwap(&y0, &y1);
- }
- /* Determine the mid intersection and point */
- My = y1;
- Mx = x0 + (double)((x2 - x0) * (y1 - y0)) / (double)(y2 - y0);
- /* Fill top */
- if (y0 != y1)
- {
- drawFillBottomFlatTriangle(x0, y0, x1, y1, Mx, My, colour);
- }
- /* Fill bottom */
- if (y1 != y2)
- {
- drawFillTopFlatTriangle(x1, y1, Mx, My, x2, y2, colour);
- }
- }
- /* ----------------------------------- Textured triangles ----------------------------------- */
- void drawTextureTriangle(struct triangle_t *t)
- {
- int32_t x, y;
- 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);
- }
- /* 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;
- if ((y1 - y0) != 0) { inverseSlope1 = (double)(x1 - x0) / abs(y1 - y0); }
- if ((y2 - y0) != 0) { inverseSlope2 = (double)(x2 - x0) / abs(y2 - y0); }
- if ((y1 - y0) != 0)
- {
- for (y = y0 ; y <= y1 ; y++)
- {
- int32_t xStart = x1 + (y - y1) * inverseSlope1;
- int32_t xEnd = x0 + (y - y0) * inverseSlope2;
- if (xEnd < xStart)
- {
- intSwap(&xStart, &xEnd);
- }
- for (x = xStart ; x <= xEnd ; x++)
- {
- drawPixel(x, y, (x%2 == 0)?0xFFFF00FF:0xFF000000);
- }
- }
- }
- /* Render the bottom part */
- inverseSlope1 = 0;
- if ((y2 - y1) != 0) { inverseSlope1 = (double)(x2 - x1) / abs(y2 - y1); }
- if ((y2 - y1) != 0)
- {
- for (y = y1 ; y <= y2 ; y++)
- {
- int32_t xStart = x2 + (y - y2) * inverseSlope1;
- int32_t xEnd = x0 + (y - y0) * inverseSlope2;
- if (xEnd < xStart)
- {
- intSwap(&xStart, &xEnd);
- }
- for (x = xStart ; x <= xEnd ; x++)
- {
- drawPixel(x, y, (x%2 == 0)?0xFFFF00FF:0xFF000000);
- }
- }
- }
- }
- /* ---- Utility ---- */
- int compareTrianglesZOrder(const void *p1, const void *p2)
- {
- triangle_t *t1 = (struct triangle_t *)p1;
- triangle_t *t2 = (struct triangle_t *)p2;
- if (t1->averageDepth > t2->averageDepth)
- {
- return -1;
- }
- else if (t1->averageDepth < t2->averageDepth)
- {
- return 1;
- }
- return 0;
- }
|