| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- #include "BsRay.h"
- #include "BsPlane.h"
- #include "BsSphere.h"
- #include "BsAABox.h"
- namespace BansheeEngine
- {
- void Ray::transform(const Matrix4& matrix)
- {
- Vector3 end = getPoint(1.0f);
- mOrigin = matrix.multiply(mOrigin);
- end = matrix.multiply(end);
- mDirection = Vector3::normalize(end - mOrigin);
- }
- void Ray::transformAffine(const Matrix4& matrix)
- {
- Vector3 end = getPoint(1.0f);
- mOrigin = matrix.multiply3x4(mOrigin);
- end = matrix.multiply3x4(end);
- mDirection = Vector3::normalize(end - mOrigin);
- }
- std::pair<bool, float> Ray::intersects(const Plane& p) const
- {
- return p.intersects(*this);
- }
- std::pair<bool, float> Ray::intersects(const Sphere& s) const
- {
- return s.intersects(*this);
- }
- std::pair<bool, float> Ray::intersects(const AABox& box) const
- {
- return box.intersects(*this);
- }
- std::pair<bool, float> Ray::intersects(const Vector3& a,
- const Vector3& b, const Vector3& c, const Vector3& normal,
- bool positiveSide, bool negativeSide) const
- {
- // Calculate intersection with plane.
- float t;
- {
- float denom = normal.dot(getDirection());
- // Check intersect side
- if (denom > + std::numeric_limits<float>::epsilon())
- {
- if (!negativeSide)
- return std::pair<bool, float>(false, 0.0f);
- }
- else if (denom < - std::numeric_limits<float>::epsilon())
- {
- if (!positiveSide)
- return std::pair<bool, float>(false, 0.0f);
- }
- else
- {
- // Parallel or triangle area is close to zero when
- // the plane normal not normalized.
- return std::pair<bool, float>(false, 0.0f);
- }
- t = normal.dot(a - getOrigin()) / denom;
- if (t < 0)
- {
- // Intersection is behind origin
- return std::pair<bool, float>(false, 0.0f);
- }
- }
- // Calculate the largest area projection plane in X, Y or Z.
- UINT32 i0, i1;
- {
- float n0 = Math::abs(normal[0]);
- float n1 = Math::abs(normal[1]);
- float n2 = Math::abs(normal[2]);
- i0 = 1; i1 = 2;
- if (n1 > n2)
- {
- if (n1 > n0) i0 = 0;
- }
- else
- {
- if (n2 > n0) i1 = 0;
- }
- }
- // Check the intersection point is inside the triangle.
- {
- float u1 = b[i0] - a[i0];
- float v1 = b[i1] - a[i1];
- float u2 = c[i0] - a[i0];
- float v2 = c[i1] - a[i1];
- float u0 = t * getDirection()[i0] + getOrigin()[i0] - a[i0];
- float v0 = t * getDirection()[i1] + getOrigin()[i1] - a[i1];
- float alpha = u0 * v2 - u2 * v0;
- float beta = u1 * v0 - u0 * v1;
- float area = u1 * v2 - u2 * v1;
- // Epsilon to avoid float precision errors.
- const float EPSILON = 1e-6f;
- float tolerance = - EPSILON * area;
- if (area > 0)
- {
- if (alpha < tolerance || beta < tolerance || alpha+beta > area-tolerance)
- return std::pair<bool, float>(false, 0.0f);
- }
- else
- {
- if (alpha > tolerance || beta > tolerance || alpha+beta < area-tolerance)
- return std::pair<bool, float>(false, 0.0f);
- }
- }
- return std::pair<bool, float>(true, t);
- }
- }
|