triangle.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * 3D Engine
  3. * triangle.c:
  4. * Based on pikuma.com 3D software renderer in C
  5. * Copyright (c) 2021 986-Studio. All rights reserved.
  6. *
  7. * Created by Manoël Trapier on 04/03/2021.
  8. */
  9. #include <display.h>
  10. #include <triangle.h>
  11. void drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, colour_t colour)
  12. {
  13. drawLine(x0, y0, x1, y1, colour);
  14. drawLine(x1, y1, x2, y2, colour);
  15. drawLine(x2, y2, x0, y0, colour);
  16. }
  17. /* ----------------------------------- Filled triangles ----------------------------------- */
  18. /* This function expect Point 0 to be the top, 1 to be the bottom left, 2 to be the bottom right */
  19. static void drawFillBottomFlatTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, colour_t colour)
  20. {
  21. int i;
  22. int32_t deltaXL = x1 - x0;
  23. int32_t deltaXR = x2 - x0;
  24. int32_t deltaY = y1 - y0;
  25. int32_t sideLength = abs(deltaY);
  26. double incrementXL = deltaXL / (double)sideLength;
  27. double incrementXR = deltaXR / (double)sideLength;
  28. double incrementY = deltaY / (double)sideLength;
  29. double currentXL = x0;
  30. double currentXR = x0;
  31. double currentY = y0;
  32. for(i = 0; i < sideLength; i++)
  33. {
  34. drawHLine(round(currentXL), round(currentY), round(currentXR), colour);
  35. currentXL += incrementXL;
  36. currentXR += incrementXR;
  37. currentY += incrementY;
  38. }
  39. }
  40. /* This function expect Point 2 to be the bottom, 0 to be the top left, 1 to be the top right */
  41. static void drawFillTopFlatTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, colour_t colour)
  42. {
  43. int i;
  44. int32_t deltaXL = x0 - x2;
  45. int32_t deltaXR = x1 - x2;
  46. int32_t deltaY = y0 - y2;
  47. int32_t sideLength = abs(deltaY);
  48. if (sideLength == 0)
  49. {
  50. return;
  51. }
  52. double incrementXL = deltaXL / (double)sideLength;
  53. double incrementXR = deltaXR / (double)sideLength;
  54. double incrementY = deltaY / (double)sideLength;
  55. double currentXL = x2;
  56. double currentXR = x2;
  57. double currentY = y2;
  58. for(i = 0; i <= sideLength; i++)
  59. {
  60. drawHLine(round(currentXL), round(currentY), round(currentXR), colour);
  61. currentXL += incrementXL;
  62. currentXR += incrementXR;
  63. currentY += incrementY;
  64. }
  65. }
  66. void drawFilledTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, colour_t colour)
  67. {
  68. int32_t My, Mx;
  69. if (y0 > y1)
  70. {
  71. intSwap(&x0, &x1); intSwap(&y0, &y1);
  72. }
  73. if (y1 > y2)
  74. {
  75. intSwap(&x1, &x2); intSwap(&y1, &y2);
  76. }
  77. if (y0 > y1)
  78. {
  79. intSwap(&x0, &x1); intSwap(&y0, &y1);
  80. }
  81. /* Determine the mid intersection and point */
  82. My = y1;
  83. Mx = x0 + (double)((x2 - x0) * (y1 - y0)) / (double)(y2 - y0);
  84. /* Fill top */
  85. if (y0 != y1)
  86. {
  87. drawFillBottomFlatTriangle(x0, y0, x1, y1, Mx, My, colour);
  88. }
  89. /* Fill bottom */
  90. if (y1 != y2)
  91. {
  92. drawFillTopFlatTriangle(x1, y1, Mx, My, x2, y2, colour);
  93. }
  94. }
  95. /* ----------------------------------- Textured triangles ----------------------------------- */
  96. void drawTextureTriangle(struct triangle_t *t)
  97. {
  98. double My, Mx, Mu, Mv;
  99. if (t->points[0].y > t->points[1].y)
  100. {
  101. doubleSwap(&t->points[0].x, &t->points[1].x); doubleSwap(&t->points[0].y, &t->points[1].y);
  102. doubleSwap(&t->textureCoordinates[0].u, &t->textureCoordinates[1].u);
  103. doubleSwap(&t->textureCoordinates[0].v, &t->textureCoordinates[1].v);
  104. }
  105. if (t->points[1].y > t->points[2].y)
  106. {
  107. doubleSwap(&t->points[1].x, &t->points[2].x); doubleSwap(&t->points[1].y, &t->points[2].y);
  108. doubleSwap(&t->textureCoordinates[1].u, &t->textureCoordinates[2].u);
  109. doubleSwap(&t->textureCoordinates[1].v, &t->textureCoordinates[2].v);
  110. }
  111. if (t->points[0].y > t->points[1].y)
  112. {
  113. doubleSwap(&t->points[0].x, &t->points[1].x); doubleSwap(&t->points[0].y, &t->points[1].y);
  114. doubleSwap(&t->textureCoordinates[0].u, &t->textureCoordinates[1].u);
  115. doubleSwap(&t->textureCoordinates[0].v, &t->textureCoordinates[1].v);
  116. }
  117. }
  118. /* ---- Utility ---- */
  119. int compareTrianglesZOrder(const void *p1, const void *p2)
  120. {
  121. triangle_t *t1 = (struct triangle_t *)p1;
  122. triangle_t *t2 = (struct triangle_t *)p2;
  123. if (t1->averageDepth > t2->averageDepth)
  124. {
  125. return -1;
  126. }
  127. else if (t1->averageDepth < t2->averageDepth)
  128. {
  129. return 1;
  130. }
  131. return 0;
  132. }