clipping.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * 3D Engine
  3. * clipping.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 11/03/2021.
  8. */
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <math.h>
  12. #include <assert.h>
  13. #include <clipping.h>
  14. static plane_t frustum[TOTAL_PLANES];
  15. void initFrustumPlanes(double fov, double aspectRation, double zNear, double zFar)
  16. {
  17. double radFOV = (fov * M_PI) / 180.;
  18. frustum[LEFT_PLANE].point = vec3(0, 0, 0);
  19. frustum[LEFT_PLANE].normal = vec3( cos(radFOV / 2.0) , 0, sin(radFOV / 2.0));
  20. frustum[RIGHT_PLANE].point = vec3(0, 0, 0);
  21. frustum[RIGHT_PLANE].normal = vec3( -cos(radFOV / 2.0), 0, sin(radFOV / 2.0));
  22. frustum[TOP_PLANE].point = vec3(0, 0, 0);
  23. frustum[TOP_PLANE].normal = vec3(0, -cos(radFOV / 2.0), sin(radFOV / 2.0));
  24. frustum[BOTTOM_PLANE].point = vec3(0, 0, 0);
  25. frustum[BOTTOM_PLANE].normal = vec3(0, cos(radFOV / 2.0), sin(radFOV / 2.0));
  26. frustum[NEAR_PLANE].point = vec3(0, 0, zNear);
  27. frustum[NEAR_PLANE].normal = vec3(0, 0, 1);
  28. frustum[FAR_PLANE].point = vec3(0, 0, zFar);
  29. frustum[FAR_PLANE].normal = vec3(0, 0, -1);
  30. }
  31. void createTriangleFromPolygon(polygon_t *polygon, triangle_t *triangleList, uint32_t *outNumber)
  32. {
  33. int i;
  34. *outNumber = 0;
  35. for(i = 1; i < (polygon->num_vertices - 1); i++)
  36. {
  37. triangleList[i - 1].points[0] = vec4FromVec3(polygon->vertices[0]);
  38. triangleList[i - 1].points[1] = vec4FromVec3(polygon->vertices[i]);
  39. triangleList[i - 1].points[2] = vec4FromVec3(polygon->vertices[i + 1]);
  40. (*outNumber)++;
  41. assert(*outNumber < MAX_NUM_POLYGON_TRIANGLES);
  42. }
  43. }
  44. static void clipPolygonAgainstPlane(polygon_t *poly, faceenum_t plane)
  45. {
  46. int i;
  47. vec3_t planePoint = frustum[plane].point;
  48. vec3_t planeNormal = frustum[plane].normal;
  49. vec3_t *currentVertex;
  50. vec3_t *previousVertex;
  51. double currentDot, previousDot;
  52. vec3_t newVertices[MAX_NUM_POLYGON_VERTICES];
  53. int newVerticesCount = 0;
  54. previousVertex = &poly->vertices[poly->num_vertices - 1];
  55. for(i = 0; i < poly->num_vertices; i++)
  56. {
  57. currentVertex = &poly->vertices[i];
  58. currentDot = vec3Dot(vec3SubVectors(*currentVertex, planePoint), planeNormal);
  59. previousDot = vec3Dot(vec3SubVectors(*previousVertex, planePoint), planeNormal);
  60. if ((currentDot * previousDot) < 0.0)
  61. {
  62. double t;
  63. /* we crossed the plane */
  64. vec3_t intersectionVertice;
  65. t = previousDot / (previousDot - currentDot);
  66. intersectionVertice = *currentVertex;
  67. intersectionVertice = vec3SubVectors(intersectionVertice, *previousVertex);
  68. intersectionVertice = vec3ScalarMult(intersectionVertice, t);
  69. intersectionVertice = vec3AddVectors(intersectionVertice, *previousVertex);
  70. newVertices[newVerticesCount] = intersectionVertice;
  71. newVerticesCount++;
  72. }
  73. if (currentDot > 0.0)
  74. {
  75. newVertices[newVerticesCount] = *currentVertex;
  76. newVerticesCount++;
  77. }
  78. /* Just to be sure, should never trigger */
  79. assert(newVerticesCount < MAX_NUM_POLYGON_VERTICES);
  80. previousVertex = currentVertex;
  81. }
  82. for(i = 0; i < newVerticesCount; i++)
  83. {
  84. poly->vertices[i] = newVertices[i];
  85. }
  86. poly->num_vertices = newVerticesCount;
  87. }
  88. void clipPolygon(polygon_t *poly)
  89. {
  90. clipPolygonAgainstPlane(poly, LEFT_PLANE);
  91. clipPolygonAgainstPlane(poly, TOP_PLANE);
  92. clipPolygonAgainstPlane(poly, RIGHT_PLANE);
  93. clipPolygonAgainstPlane(poly, BOTTOM_PLANE);
  94. clipPolygonAgainstPlane(poly, NEAR_PLANE);
  95. clipPolygonAgainstPlane(poly, FAR_PLANE);
  96. }