diff --git a/examples/common/bounds.cpp b/examples/common/bounds.cpp index 7ba949146..b43054f96 100644 --- a/examples/common/bounds.cpp +++ b/examples/common/bounds.cpp @@ -647,6 +647,92 @@ bool intersect(const Ray& _ray, const Cylinder& _cylinder, bool _capsule, Inters return false; } +bool intersect(const Ray& _ray, const Cone& _cone, Intersection* _intersection) +{ + float axis[3]; + bx::vec3Sub(axis, _cone.m_end, _cone.m_pos); + + float normal[3]; + const float len = bx::vec3Norm(normal, axis); + + Disk disk; + bx::vec3Move(disk.m_center, _cone.m_pos); + bx::vec3Neg(disk.m_normal, normal); + disk.m_radius = _cone.m_radius; + + if (intersect(_ray, disk, _intersection) ) + { + return true; + } + + float rs[3]; + bx::vec3Sub(rs, _ray.m_pos, _cone.m_end); + + const float hyp = bx::fsqrt(bx::fsq(_cone.m_radius) + bx::fsq(len) ); + const float cosa = len/hyp; + + const float cosaSq = bx::fsq(cosa); + + const float rsdotaxis = bx::vec3Dot(rs, normal); + const float rdota = bx::vec3Dot(normal, _ray.m_dir); + + const float aa = bx::fsq(rdota) - cosaSq; + const float bb = 2.0f * (rdota*rsdotaxis - bx::vec3Dot(_ray.m_dir, rs)*cosaSq); + const float cc = bx::fsq(rsdotaxis) - bx::vec3Dot(rs, rs)*cosaSq; + + float det = bb*bb - 4.0f*aa*cc; + + if (0.0f > det) + { + return false; + } + + det = bx::fsqrt(det); + + float t1 = (-bb - det) / (2.0f * aa); + float t2 = (-bb + det) / (2.0f * aa); + + float tt = t1; + if (0.0f > t1 + || (0.0f < t2 && t2 < t1) ) + { + tt = t2; + } + + if (0.0f > tt) + { + return false; + } + + float point[3]; + getPointAt(point, _ray, tt); + + const float hh = bx::vec3Dot(normal, point); + + if (0.0f > hh + || len < hh) + { + return false; + } + + if (NULL != _intersection) + { + _intersection->m_dist = tt; + + bx::vec3Move(_intersection->m_pos, point); + + const float scale = hh / bx::vec3Dot(point, point); + float pointScaled[3]; + bx::vec3Mul(pointScaled, point, scale); + + float tmp[3]; + bx::vec3Sub(tmp, pointScaled, normal); + bx::vec3Norm(_intersection->m_normal, tmp); + } + + return true; +} + bool intersect(const Ray& _ray, const Plane& _plane, Intersection* _intersection) { float equation = bx::vec3Dot(_ray.m_pos, _plane.m_normal) + _plane.m_dist; diff --git a/examples/common/bounds.h b/examples/common/bounds.h index 604892c3f..a0d6d47bf 100644 --- a/examples/common/bounds.h +++ b/examples/common/bounds.h @@ -19,6 +19,13 @@ struct Cylinder float m_radius; }; +struct Cone +{ + float m_pos[3]; + float m_end[3]; + float m_radius; +}; + struct Disk { float m_center[3]; @@ -118,6 +125,9 @@ bool intersect(const Ray& _ray, const Aabb& _aabb, Intersection* _intersection = /// Intersect ray / cylinder. bool intersect(const Ray& _ray, const Cylinder& _cylinder, bool _capsule, Intersection* _intersection = NULL); +/// Intersect ray / cone. +bool intersect(const Ray& _ray, const Cone& _cone, Intersection* _intersection = NULL); + /// Intersect ray / disk. bool intersect(const Ray& _ray, const Disk& _disk, Intersection* _intersection = NULL);