clipping.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. frustum[LEFT_PLANE].point = vec3(0, 0, 0);
  18. frustum[LEFT_PLANE].normal = vec3( cos(fov) / 2, 0, sin(fov) / 2);
  19. frustum[RIGHT_PLANE].point = vec3(0, 0, 0);
  20. frustum[RIGHT_PLANE].normal = vec3( -cos(fov) / 2, 0, sin(fov) / 2);
  21. frustum[TOP_PLANE].point = vec3(0, 0, 0);
  22. frustum[TOP_PLANE].normal = vec3(0, -cos(fov) / 2, sin(fov) / 2);
  23. frustum[BOTTOM_PLANE].point = vec3(0, 0, 0);
  24. frustum[BOTTOM_PLANE].normal = vec3(0, cos(fov) / 2, sin(fov) / 2);
  25. frustum[NEAR_PLANE].point = vec3(0, 0, zNear);
  26. frustum[NEAR_PLANE].normal = vec3(0, 0, 1);
  27. frustum[FAR_PLANE].point = vec3(0, 0, zFar);
  28. frustum[FAR_PLANE].normal = vec3(0, 0, -1);
  29. }
  30. static void clipPolygonAgainstPlane(polygon_t *poly, faceenum_t plane)
  31. {
  32. int i;
  33. vec3_t planePoint = frustum[plane].point;
  34. vec3_t planeNormal = frustum[plane].normal;
  35. vec3_t *currentVertex;
  36. vec3_t *previousVertex;
  37. double currentDot, previousDot;
  38. vec3_t newVertices[MAX_NUM_POLYGON_VERTICES];
  39. int newVerticesCount = 0;
  40. previousVertex = &poly->vertices[poly->num_verticices - 1];
  41. for(i = 0; i < poly->num_verticices; i++)
  42. {
  43. currentVertex = &poly->vertices[i];
  44. currentDot = vec3Dot(vec3SubVectors(*currentVertex, planePoint), planeNormal);
  45. previousDot = vec3Dot(vec3SubVectors(*previousVertex, planePoint), planeNormal);
  46. if ((currentDot * previousDot) < 0.0)
  47. {
  48. double t;
  49. /* we crossed the plane */
  50. t = previousDot / (previousDot - currentDot);
  51. newVertices[newVerticesCount] = vec3SubVectors(*currentVertex, *previousVertex);
  52. vec3ScalarMult(newVertices[newVerticesCount], t);
  53. newVertices[newVerticesCount] = vec3AddVectors(*currentVertex, newVertices[newVerticesCount]);
  54. newVerticesCount++;
  55. }
  56. if (currentDot >= 0.0)
  57. {
  58. newVertices[newVerticesCount] = *currentVertex;
  59. newVerticesCount++;
  60. }
  61. /* Just to be sure, should never trigger */
  62. assert(newVerticesCount < MAX_NUM_POLYGON_VERTICES);
  63. previousVertex = currentVertex;
  64. }
  65. for(i = 0; i < newVerticesCount; i++)
  66. {
  67. poly->vertices[i] = newVertices[i];
  68. }
  69. poly->num_verticices = newVerticesCount;
  70. }
  71. void clipPolygon(polygon_t *poly)
  72. {
  73. clipPolygonAgainstPlane(poly, LEFT_PLANE);
  74. clipPolygonAgainstPlane(poly, TOP_PLANE);
  75. clipPolygonAgainstPlane(poly, RIGHT_PLANE);
  76. clipPolygonAgainstPlane(poly, BOTTOM_PLANE);
  77. clipPolygonAgainstPlane(poly, NEAR_PLANE);
  78. clipPolygonAgainstPlane(poly, FAR_PLANE);
  79. }