plane_src.cxx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file plane_src.cxx
  10. * @author drose
  11. * @date 2001-04-03
  12. */
  13. /**
  14. * This computes a transform matrix that reflects the universe to the other
  15. * side of the plane, as in a mirror.
  16. */
  17. FLOATNAME(LMatrix4) FLOATNAME(LPlane)::
  18. get_reflection_mat() const {
  19. FLOATTYPE aa = _v(0) * _v(0);
  20. FLOATTYPE ab = _v(0) * _v(1);
  21. FLOATTYPE ac = _v(0) * _v(2);
  22. FLOATTYPE ad = _v(0) * _v(3);
  23. FLOATTYPE bb = _v(1) * _v(1);
  24. FLOATTYPE bc = _v(1) * _v(2);
  25. FLOATTYPE bd = _v(1) * _v(3);
  26. FLOATTYPE cc = _v(2) * _v(2);
  27. FLOATTYPE cd = _v(2) * _v(3);
  28. return FLOATNAME(LMatrix4)( 1-2*aa, -2*ab, -2*ac, 0,
  29. -2*ab, 1-2*bb, -2*bc, 0,
  30. -2*ac, -2*bc, 1-2*cc, 0,
  31. -2*ad, -2*bd, -2*cd, 1 );
  32. }
  33. /**
  34. * Returns an arbitrary point in the plane. This can be used along with the
  35. * normal returned by get_normal() to reconstruct the plane.
  36. */
  37. FLOATNAME(LPoint3) FLOATNAME(LPlane)::
  38. get_point() const {
  39. // Choose the denominator based on the largest axis in the normal.
  40. if (cabs(_v(0)) >= cabs(_v(1)) && cabs(_v(0)) >= cabs(_v(2))) {
  41. nassertr(_v(0) != 0.0f, FLOATNAME(LPoint3)(0.0f, 0.0f, 0.0f));
  42. return FLOATNAME(LPoint3)(-_v(3) / _v(0), 0.0f, 0.0f);
  43. } else if (cabs(_v(1)) >= cabs(_v(2))) {
  44. nassertr(_v(1) != 0.0f, FLOATNAME(LPoint3)(0.0f, 0.0f, 0.0f));
  45. return FLOATNAME(LPoint3)(0.0f, -_v(3) / _v(1), 0.0f);
  46. } else {
  47. nassertr(_v(2) != 0.0f, FLOATNAME(LPoint3)(0.0f, 0.0f, 0.0f));
  48. return FLOATNAME(LPoint3)(0.0f, 0.0f, -_v(3) / _v(2));
  49. }
  50. }
  51. /**
  52. * Returns true if the two planes intersect, false if they do not. If they do
  53. * intersect, then from and delta are filled in with the parametric
  54. * representation of the line of intersection: that is, from is a point on
  55. * that line, and delta is a vector showing the direction of the line.
  56. */
  57. bool FLOATNAME(LPlane)::
  58. intersects_plane(FLOATNAME(LPoint3) &from,
  59. FLOATNAME(LVector3) &delta,
  60. const FLOATNAME(LPlane) &other) const {
  61. FLOATNAME(LVector3) n1 = get_normal();
  62. FLOATNAME(LVector3) n2 = other.get_normal();
  63. // The delta will be the cross product of the planes' normals.
  64. delta = cross(n1, n2);
  65. // If the delta came out to zero, the planes were parallel and do not
  66. // intersect.
  67. if (delta.almost_equal(FLOATNAME(LVector3)::zero())) {
  68. return false;
  69. }
  70. FLOATTYPE n1n1 = ::dot(n1, n1);
  71. FLOATTYPE n2n2 = ::dot(n2, n2);
  72. FLOATTYPE n1n2 = ::dot(n1, n2);
  73. FLOATTYPE determinant_inv = 1.0f / (n1n1 * n2n2 - n1n2 * n1n2);
  74. FLOATTYPE c1 = (other._v(3) * n1n2 - _v(3) * n2n2) * determinant_inv;
  75. FLOATTYPE c2 = (_v(3) * n1n2 - other._v(3) * n1n1) * determinant_inv;
  76. from = n1 * c1 + n2 * c2;
  77. return true;
  78. }
  79. /**
  80. * Determines whether and where the indicated parabola intersects with the
  81. * plane.
  82. *
  83. * If there is no intersection with the plane, the function returns false and
  84. * leaves t1 and t2 undefined. If there is an intersection with the plane,
  85. * the function returns true and sets t1 and t2 to the parametric value that
  86. * defines the two points of intersection. If the parabola is exactly tangent
  87. * to the plane, then t1 == t2.
  88. */
  89. bool FLOATNAME(LPlane)::
  90. intersects_parabola(FLOATTYPE &t1, FLOATTYPE &t2,
  91. const FLOATNAME(LParabola) &parabola) const {
  92. /*
  93. * The parabola intersects the plane wherever: a * t^2 + b * t + c == 0 where
  94. * a = normal dot parabola.get_a(), b = normal dot parabola.get_b(), c =
  95. * normal dot parabola.get_c() + d.
  96. */
  97. FLOATNAME(LVector3) normal = get_normal();
  98. FLOATTYPE a = normal.dot(parabola.get_a());
  99. FLOATTYPE b = normal.dot(parabola.get_b());
  100. FLOATTYPE c = normal.dot(parabola.get_c()) + _v(3);
  101. if (IS_NEARLY_ZERO(a)) {
  102. // It's not quadratic. The equation is actually: b * t + c == 0. Which
  103. // means: t = -c b.
  104. if (IS_NEARLY_ZERO(b)) {
  105. // It's not even linear. The parabola must be completely parallel to
  106. // the plane, or if c == 0, it's completely within the plane. In both
  107. // cases, we'll call it no intersection.
  108. return false;
  109. }
  110. t1 = -c / b;
  111. t2 = t1;
  112. return true;
  113. }
  114. // Now use the quadratic equation to solve for t.
  115. FLOATTYPE discriminant = b * b - 4.0 * a * c;
  116. if (discriminant < 0.0f) {
  117. // No intersection.
  118. return false;
  119. }
  120. FLOATTYPE sqrd = csqrt(discriminant);
  121. t1 = (-b - sqrd) / (2.0 * a);
  122. t2 = (-b + sqrd) / (2.0 * a);
  123. return true;
  124. }
  125. /**
  126. *
  127. */
  128. void FLOATNAME(LPlane)::
  129. output(std::ostream &out) const {
  130. out << "LPlane(";
  131. FLOATNAME(LVecBase4)::output(out);
  132. out << ")";
  133. }
  134. /**
  135. *
  136. */
  137. void FLOATNAME(LPlane)::
  138. write(std::ostream &out, int indent_level) const {
  139. indent(out, indent_level) << *this << "\n";
  140. }
  141. /**
  142. * Returns a string representation of this LPlane.
  143. */
  144. std::string FLOATNAME(LPlane)::
  145. __repr__() const {
  146. std::ostringstream out;
  147. out << "LPlane" << FLOATTOKEN << "("
  148. << MAYBE_ZERO(_v(0)) << ", "
  149. << MAYBE_ZERO(_v(1)) << ", "
  150. << MAYBE_ZERO(_v(2)) << ", "
  151. << MAYBE_ZERO(_v(3)) << ")";
  152. return out.str();
  153. }