diff --git a/include/cglm/call/ray.h b/include/cglm/call/ray.h index 1fff055..02fe632 100644 --- a/include/cglm/call/ray.h +++ b/include/cglm/call/ray.h @@ -20,7 +20,15 @@ glmc_ray_triangle(vec3 origin, vec3 v1, vec3 v2, float *d); - + +CGLM_EXPORT +bool +glmc_ray_sphere(vec3 origin, + vec3 dir, + vec4 s, + float * __restrict t1, + float * __restrict t2); + #ifdef __cplusplus } #endif diff --git a/include/cglm/ray.h b/include/cglm/ray.h index ced1ad6..ec993c6 100644 --- a/include/cglm/ray.h +++ b/include/cglm/ray.h @@ -7,12 +7,17 @@ /* Functions: - CGLM_INLINE bool glm_line_triangle_intersect(vec3 origin, - vec3 direction, - vec3 v0, - vec3 v1, - vec3 v2, - float *d); + 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) */ #ifndef cglm_ray_h @@ -31,7 +36,6 @@ * @param[in, out] d distance to intersection * @return whether there is intersection */ - CGLM_INLINE bool glm_ray_triangle(vec3 origin, @@ -74,4 +78,70 @@ glm_ray_triangle(vec3 origin, return dist > epsilon; } +/*! + * @brief ray sphere intersection + * + * @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) + */ +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; + + /* ensure dir is normalized */ + 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; +} + #endif diff --git a/include/cglm/struct.h b/include/cglm/struct.h index 030f45a..1426589 100644 --- a/include/cglm/struct.h +++ b/include/cglm/struct.h @@ -41,6 +41,7 @@ extern "C" { #include "struct/sphere.h" #include "struct/curve.h" #include "struct/affine2d.h" +#include "struct/ray.h" #ifdef __cplusplus } diff --git a/include/cglm/struct/ray.h b/include/cglm/struct/ray.h new file mode 100644 index 0000000..4eea68d --- /dev/null +++ b/include/cglm/struct/ray.h @@ -0,0 +1,59 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglms_ray_h +#define cglms_ray_h + +#include "../common.h" +#include "../types-struct.h" +#include "../ray.h" + +/* api definition */ +#define glms_ray_(NAME) CGLM_STRUCTAPI(ray, NAME) + +/*! + * @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 +glms_ray_(triangle)(vec3s origin, + vec3s direction, + vec3s v0, + vec3s v1, + vec3s v2, + float *d) { + return glm_ray_triangle(origin.raw, direction.raw, v0.raw, v1.raw, v2.raw, d); +} + +/*! + * @brief ray sphere intersection + * + * @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) + */ +CGLM_INLINE +bool +glms_ray_(sphere)(vec3s origin, + vec3s dir, + vec4s s, + float * __restrict t1, + float * __restrict t2) { + return glm_ray_sphere(origin.raw, dir.raw, s.raw, t1, t2); +} + +#endif /* cglms_ray_h */ diff --git a/src/ray.c b/src/ray.c index 973c059..9592b83 100644 --- a/src/ray.c +++ b/src/ray.c @@ -9,5 +9,21 @@ glmc_ray_triangle(vec3 origin, vec3 v1, vec3 v2, float *d) { - return glm_ray_triangle(origin, direction, v0, v1, v2, d); + return glm_ray_triangle(origin, direction, v0, v1, v2, d); +} + +CGLM_EXPORT +bool +glmc_ray_sphere(vec3 origin, + vec3 dir, + vec4 s, + float * __restrict t1, + float * __restrict t2) { + return glm_ray_sphere(origin, dir, s, t1, t2); +} + +CGLM_EXPORT +void +glmc_ray_at(vec3 orig, vec3 dir, float t, vec3 point) { + glm_ray_at(orig, dir, t, point); } diff --git a/win/cglm.vcxproj b/win/cglm.vcxproj index 949c994..dcca926 100644 --- a/win/cglm.vcxproj +++ b/win/cglm.vcxproj @@ -253,6 +253,7 @@ + diff --git a/win/cglm.vcxproj.filters b/win/cglm.vcxproj.filters index 71143f5..f200fb2 100644 --- a/win/cglm.vcxproj.filters +++ b/win/cglm.vcxproj.filters @@ -729,5 +729,8 @@ include\cglm\struct + + include\cglm\struct + \ No newline at end of file