plane.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // closest distance from an arbitrary point to the plane
  2. float planePointDist3p(Plane* pl, Vector3* p) {
  3. Vector3 a;
  4. vScale3p(&pl->n, pl->d, &a);
  5. return fabs(vDot3(vSub3(a, *p), pl->n));
  6. }
  7. // signed closest distance from an arbitrary point to the plane
  8. float planePointDistSigned3p(Plane* pl, Vector3* p) {
  9. Vector3 a;
  10. vScale3p(&pl->n, pl->d, &a);
  11. return vDot3(vSub3(a, *p), pl->n);
  12. }
  13. // C3DLAS_INTERSECT, _COPLANAR or _DISJOINT
  14. int planeLineFindIntersect3p(Plane* pl, Vector3* la, Vector3* lb, Vector3* out) {
  15. Vector3 ldir;
  16. float da, db;
  17. vSub3p(lb, la, &ldir);
  18. da = vDot3p(la, &pl->n) - pl->d;
  19. // bail if the line and plane are parallel
  20. if(fabs(vDot3p(&pl->n, &ldir)) < FLT_CMP_EPSILON) {
  21. // check coplanarity
  22. if(fabs(da) < FLT_CMP_EPSILON) {
  23. return C3DLAS_COPLANAR; // the end is on the plane, so the other is too
  24. }
  25. return C3DLAS_DISJOINT;
  26. }
  27. db = vDot3p(lb, &pl->n) - pl->d;
  28. // check if one of the points is on the plane
  29. if(fabs(da) < FLT_CMP_EPSILON) {
  30. *out = *la;
  31. return C3DLAS_INTERSECT;
  32. }
  33. if(fabs(db) < FLT_CMP_EPSILON) {
  34. *out = *lb;
  35. return C3DLAS_INTERSECT;
  36. }
  37. Vector3 p0, g, j;
  38. vScale3p(&pl->n, pl->d, &p0);
  39. vSub3p(&p0, la, &g);
  40. float h = vDot3p(&g, &pl->n);
  41. float i = vDot3p(&ldir, &pl->n);
  42. float d = i != 0 ? h / i : 0;
  43. // check if the plane intersects outside the two points
  44. if(d < 0 || d > vDist3p(la, lb)) {
  45. return C3DLAS_DISJOINT;
  46. }
  47. vScale3p(&ldir, d, &j);
  48. vAdd3p(la, &j, out);
  49. return C3DLAS_INTERSECT;
  50. }
  51. // Assumes full proper intersection.
  52. // C3DLAS_INTERSECT
  53. int planeLineFindIntersectFast3p(Plane* pl, Vector3* la, Vector3* lb, Vector3* out) {
  54. Vector3 ldir, p0, g, j;
  55. float h, i, d;
  56. vSub3p(lb, la, &ldir);
  57. vScale3p(&pl->n, pl->d, &p0);
  58. vSub3p(&p0, la, &g);
  59. h = vDot3p(&g, &pl->n);
  60. i = vDot3p(&ldir, &pl->n);
  61. d = i != 0 ? h / i : 0;
  62. vScale3p(&ldir, d, &j);
  63. vAdd3p(la, &j, out);
  64. return C3DLAS_INTERSECT;
  65. }
  66. // negative values of idist are "behind" ray->o
  67. int intersectPlaneRay3p(Plane* p, Ray3* r, Vector3* ipoint, float* idist) {
  68. float d = vDot3p(&p->n, &r->d);
  69. if(fabs(d) < FLT_CMP_EPSILON) return C3DLAS_PARALLEL; // TODO: check for coplanarity?
  70. float t = -(vDot3(p->n, r->o) + p->d) / d;
  71. *ipoint = vAdd3(r->o, vScale3(r->d, t));
  72. *idist = t;
  73. return t >= 0 ? C3DLAS_INTERSECT : C3DLAS_DISJOINT;
  74. }