| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- /*
- * Copyright (c), Recep Aslantas.
- *
- * MIT License (MIT), http://opensource.org/licenses/MIT
- * Full license can be found in the LICENSE file
- */
- /*
- Functions:
- CGLM_INLINE bool glm_ray_triangle(vec3 origin,
- vec3 direction,
- vec3 v0,
- vec3 v1,
- vec3 v2,
- float *d);
- CGLM_INLINE bool glm_ray_sphere(vec3 origin,
- vec3 dir,
- vec4 s,
- float * __restrict t1,
- float * __restrict t2)
- CGLM_INLINE void glm_ray_at(vec3 orig, vec3 dir, float t, vec3 point);
- */
- #ifndef cglm_ray_h
- #define cglm_ray_h
- #include "vec3.h"
- /*!
- * @brief Möller–Trumbore ray-triangle intersection algorithm
- *
- * @param[in] origin origin of ray
- * @param[in] direction direction of ray
- * @param[in] v0 first vertex of triangle
- * @param[in] v1 second vertex of triangle
- * @param[in] v2 third vertex of triangle
- * @param[in, out] d distance to intersection
- * @return whether there is intersection
- */
- CGLM_INLINE
- bool
- glm_ray_triangle(vec3 origin,
- vec3 direction,
- vec3 v0,
- vec3 v1,
- vec3 v2,
- float *d) {
- vec3 edge1, edge2, p, t, q;
- float det, inv_det, u, v, dist;
- const float epsilon = 0.000001f;
- glm_vec3_sub(v1, v0, edge1);
- glm_vec3_sub(v2, v0, edge2);
- glm_vec3_cross(direction, edge2, p);
- det = glm_vec3_dot(edge1, p);
- if (det > -epsilon && det < epsilon)
- return false;
- inv_det = 1.0f / det;
-
- glm_vec3_sub(origin, v0, t);
- u = inv_det * glm_vec3_dot(t, p);
- if (u < 0.0f || u > 1.0f)
- return false;
- glm_vec3_cross(t, edge1, q);
- v = inv_det * glm_vec3_dot(direction, q);
- if (v < 0.0f || u + v > 1.0f)
- return false;
- dist = inv_det * glm_vec3_dot(edge2, q);
- if (d)
- *d = dist;
- return dist > epsilon;
- }
- /*!
- * @brief ray sphere intersection
- *
- * returns false if there is no intersection if true:
- *
- * - t1 > 0, t2 > 0: ray intersects the sphere at t1 and t2 both ahead of the origin
- * - t1 < 0, t2 > 0: ray starts inside the sphere, exits at t2
- * - t1 < 0, t2 < 0: no intersection ahead of the ray ( returns false )
- * - the caller can check if the intersection points (t1 and t2) fall within a
- * specific range (for example, tmin < t1, t2 < tmax) to determine if the
- * intersections are within a desired segment of the ray
- *
- * @param[in] origin ray origin
- * @param[out] dir normalized ray direction
- * @param[in] s sphere [center.x, center.y, center.z, radii]
- * @param[in] t1 near point1 (closer to origin)
- * @param[in] t2 far point2 (farther from origin)
- *
- * @returns whether there is intersection
- */
- CGLM_INLINE
- bool
- glm_ray_sphere(vec3 origin,
- vec3 dir,
- vec4 s,
- float * __restrict t1,
- float * __restrict t2) {
- vec3 dp;
- float r2, ddp, dpp, dscr, q, tmp, _t1, _t2;
- glm_vec3_sub(s, origin, dp);
- ddp = glm_vec3_dot(dir, dp);
- dpp = glm_vec3_norm2(dp);
- /* compute the remedy term for numerical stability */
- glm_vec3_mulsubs(dir, ddp, dp); /* dp: remedy term */
- r2 = s[3] * s[3];
- dscr = r2 - glm_vec3_norm2(dp);
- if (dscr < 0.0f) {
- /* no intersection */
- return false;
- }
- dscr = sqrtf(dscr);
- q = (ddp >= 0.0f) ? (ddp + dscr) : (ddp - dscr);
- /*
- include Press, William H., Saul A. Teukolsky,
- William T. Vetterling, and Brian P. Flannery,
- "Numerical Recipes in C," Cambridge University Press, 1992.
- */
- _t1 = q;
- _t2 = (dpp - r2) / q;
- /* adjust t1 and t2 to ensure t1 is the closer intersection */
- if (_t1 > _t2) {
- tmp = _t1;
- _t1 = _t2;
- _t2 = tmp;
- }
- *t1 = _t1;
- *t2 = _t2;
- /* check if the closest intersection (t1) is behind the ray's origin */
- if (_t1 < 0.0f && _t2 < 0.0f) {
- /* both intersections are behind the ray, no visible intersection */
- return false;
- }
- return true;
- }
- /*!
- * @brief point using t by 𝐏(𝑡)=𝐀+𝑡𝐛
- *
- * @param[in] orig origin of ray
- * @param[in] dir direction of ray
- * @param[in] t parameter
- * @param[out] point point at t
- */
- CGLM_INLINE
- void
- glm_ray_at(vec3 orig, vec3 dir, float t, vec3 point) {
- vec3 dst;
- glm_vec3_scale(dir, t, dst);
- glm_vec3_add(orig, dst, point);
- }
- #endif
|