Merge pull request #399 from recp/ray

Some missing ray functions
This commit is contained in:
Recep Aslantas
2024-03-23 11:26:17 +03:00
committed by GitHub
30 changed files with 1031 additions and 12 deletions

14
CREDITS
View File

@@ -82,3 +82,17 @@ http://github.com/microsoft/DirectXMath
17. Pick Matrix 17. Pick Matrix
glu project -> project.c glu project -> project.c
18. Ray sphere intersection
RAY TRACING GEMS
HIGH-QUALITY AND REAL-TIME RENDERING WITH DXR AND OTHER APIS
CHAPTER 7
Precision Improvements for Ray/Sphere Intersection
Eric Haines (1), Johannes Günther (2), and Tomas Akenine-Möller (1)
(1) NVIDIA
(2) Intel
Wyman, C., and Haines, E. Getting Started with RTX Ray Tracing.
https://github.com/NVIDIAGameWorks/GettingStartedWithRTXRayTracing

View File

@@ -216,7 +216,8 @@ cglm_struct_HEADERS = include/cglm/struct/mat4.h \
include/cglm/struct/project.h \ include/cglm/struct/project.h \
include/cglm/struct/sphere.h \ include/cglm/struct/sphere.h \
include/cglm/struct/color.h \ include/cglm/struct/color.h \
include/cglm/struct/curve.h include/cglm/struct/curve.h \
include/cglm/struct/ray.h
cglm_struct_clipspacedir=$(includedir)/cglm/struct/clipspace cglm_struct_clipspacedir=$(includedir)/cglm/struct/clipspace
cglm_struct_clipspace_HEADERS = include/cglm/struct/clipspace/persp_lh_no.h \ cglm_struct_clipspace_HEADERS = include/cglm/struct/clipspace/persp_lh_no.h \

View File

@@ -13,6 +13,8 @@ Table of contents (click to go):
Functions: Functions:
1. :c:func:`glm_ray_triangle` 1. :c:func:`glm_ray_triangle`
#. :c:func:`glm_ray_sphere`
#. :c:func:`glm_ray_at`
Functions documentation Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
@@ -29,3 +31,37 @@ Functions documentation
| *[in]* **v2** third vertex of triangle | *[in]* **v2** third vertex of triangle
| *[in, out]* **d** float pointer to save distance to intersection | *[in, out]* **d** float pointer to save distance to intersection
| *[out]* **intersection** whether there is intersection | *[out]* **intersection** whether there is intersection
.. c:function:: bool glm_ray_sphere(vec3 origin, vec3 dir, vec4 s, float * __restrict t1, float * __restrict t2)
ray sphere intersection
- 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
- 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
Parameters:
| *[in]* **origin** ray origin
| *[in]* **dir** normalized ray direction
| *[in]* **s** sphere [center.x, center.y, center.z, radii]
| *[out]* **t1** near point1 (closer to origin)
| *[out]* **t2** far point2 (farther from origin)
Return:
| whether there is intersection
.. c:function:: bool glm_ray_at(vec3 orig, vec3 dir, float t, vec3 point)
point using t by 𝐏(𝑡)=𝐀+𝑡𝐛
Parameters:
| *[in]* **origin** ray origin
| *[in]* **dir** ray direction
| *[out]* **t** parameter
| *[out]* **point** point at t
Return:
| point at t

View File

@@ -53,6 +53,8 @@ Functions:
#. :c:func:`glm_vec2_clamp` #. :c:func:`glm_vec2_clamp`
#. :c:func:`glm_vec2_lerp` #. :c:func:`glm_vec2_lerp`
#. :c:func:`glm_vec2_make` #. :c:func:`glm_vec2_make`
#. :c:func:`glm_vec2_reflect`
#. :c:func:`glm_vec2_refract`
Functions documentation Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
@@ -394,3 +396,25 @@ Functions documentation
Parameters: Parameters:
| *[in]* **src** pointer to an array of floats | *[in]* **src** pointer to an array of floats
| *[out]* **dest** destination vector | *[out]* **dest** destination vector
.. c:function:: void glm_vec2_reflect(vec2 I, vec2 N, vec2 dest)
Reflection vector using an incident ray and a surface normal
Parameters:
| *[in]* **I** incident vector
| *[in]* **N** *❗️ normalized ❗️* normal vector
| *[out]* **dest** destination: reflection result
.. c:function:: void glm_vec2_refract(vec2 I, vec2 N, float eta, vec2 dest)
Refraction vector using entering ray, surface normal and refraction index
If the angle between the entering ray I and the surface normal N is too
great for a given refraction index, the return value is zero
Parameters:
| *[in]* **I** *❗️ normalized ❗️* incident vector
| *[in]* **N** *❗️ normalized ❗️* normal vector
| *[in]* **eta** ratio of indices of refraction ( η )
| *[out]* **dest** destination: refraction result

View File

@@ -80,6 +80,9 @@ Functions:
#. :c:func:`glm_vec3_clamp` #. :c:func:`glm_vec3_clamp`
#. :c:func:`glm_vec3_lerp` #. :c:func:`glm_vec3_lerp`
#. :c:func:`glm_vec3_make` #. :c:func:`glm_vec3_make`
#. :c:func:`glm_vec3_faceforward`
#. :c:func:`glm_vec3_reflect`
#. :c:func:`glm_vec3_refract`
Functions documentation Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
@@ -512,3 +515,35 @@ Functions documentation
Parameters: Parameters:
| *[in]* **src** pointer to an array of floats | *[in]* **src** pointer to an array of floats
| *[out]* **dest** destination vector | *[out]* **dest** destination vector
.. c:function:: void glm_vec3_faceforward(vec3 N, vec3 I, vec3 Nref, vec3 dest)
A vector pointing in the same direction as another
Parameters:
| *[in]* **N** vector to orient
| *[in]* **I** incident vector
| *[in]* **Nref** reference vector
| *[out]* **dest** destination: oriented vector, pointing away from the surface.
.. c:function:: void glm_vec3_reflect(vec3 I, vec3 N, vec3 dest)
Reflection vector using an incident ray and a surface normal
Parameters:
| *[in]* **I** incident vector
| *[in]* **N** *❗️ normalized ❗️* normal vector
| *[out]* **dest** destination: reflection result
.. c:function:: void glm_vec3_refract(vec3 I, vec3 N, float eta, vec3 dest)
Refraction vector using entering ray, surface normal and refraction index
If the angle between the entering ray I and the surface normal N is too
great for a given refraction index, the return value is zero
Parameters:
| *[in]* **I** *❗️ normalized ❗️* incident vector
| *[in]* **N** *❗️ normalized ❗️* normal vector
| *[in]* **eta** ratio of indices of refraction ( η )
| *[out]* **dest** destination: refraction result

View File

@@ -60,6 +60,8 @@ Functions:
#. :c:func:`glm_vec4_lerp` #. :c:func:`glm_vec4_lerp`
#. :c:func:`glm_vec4_cubic` #. :c:func:`glm_vec4_cubic`
#. :c:func:`glm_vec4_make` #. :c:func:`glm_vec4_make`
#. :c:func:`glm_vec4_reflect`
#. :c:func:`glm_vec4_refract`
Functions documentation Functions documentation
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
@@ -424,3 +426,29 @@ Functions documentation
Parameters: Parameters:
| *[in]* **src** pointer to an array of floats | *[in]* **src** pointer to an array of floats
| *[out]* **dest** destination vector | *[out]* **dest** destination vector
.. c:function:: void glm_vec4_reflect(vec4 I, vec4 N, vec4 dest)
Reflection vector using an incident ray and a surface normal
Parameters:
| *[in]* **I** incident vector
| *[in]* **N** *❗️ normalized ❗️* normal vector
| *[out]* **dest** destination: reflection result
.. c:function:: void glm_vec4_refract(vec4 I, vec4 N, float eta, vec4 dest)
Refraction vector using entering ray, surface normal and refraction index
If the angle between the entering ray I and the surface normal N is too
great for a given refraction index, the return value is zero
this implementation does not explicitly preserve the 'w' component of the
incident vector 'I' in the output 'dest', users requiring the preservation of
the 'w' component should manually adjust 'dest' after calling this function.
Parameters:
| *[in]* **I** *❗️ normalized ❗️* incident vector
| *[in]* **N** *❗️ normalized ❗️* normal vector
| *[in]* **eta** ratio of indices of refraction ( η )
| *[out]* **dest** destination: refraction result

View File

@@ -20,7 +20,19 @@ glmc_ray_triangle(vec3 origin,
vec3 v1, vec3 v1,
vec3 v2, vec3 v2,
float *d); float *d);
CGLM_EXPORT
bool
glmc_ray_sphere(vec3 origin,
vec3 dir,
vec4 s,
float * __restrict t1,
float * __restrict t2);
CGLM_EXPORT
void
glmc_ray_at(vec3 orig, vec3 dir, float t, vec3 point);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -197,6 +197,14 @@ CGLM_EXPORT
void void
glmc_vec2_make(const float * __restrict src, vec2 dest); glmc_vec2_make(const float * __restrict src, vec2 dest);
CGLM_EXPORT
void
glmc_vec2_reflect(vec2 I, vec2 N, vec2 dest);
CGLM_EXPORT
void
glmc_vec2_refract(vec2 I, vec2 N, float eta, vec2 dest);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -334,6 +334,18 @@ CGLM_EXPORT
void void
glmc_vec3_make(const float * __restrict src, vec3 dest); glmc_vec3_make(const float * __restrict src, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_faceforward(vec3 N, vec3 I, vec3 Nref, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_reflect(vec3 I, vec3 N, vec3 dest);
CGLM_EXPORT
void
glmc_vec3_refract(vec3 I, vec3 N, float eta, vec3 dest);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -311,6 +311,14 @@ CGLM_EXPORT
void void
glmc_vec4_make(const float * __restrict src, vec4 dest); glmc_vec4_make(const float * __restrict src, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_reflect(vec4 I, vec4 N, vec4 dest);
CGLM_EXPORT
void
glmc_vec4_refract(vec4 I, vec4 N, float eta, vec4 dest);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -7,12 +7,18 @@
/* /*
Functions: Functions:
CGLM_INLINE bool glm_line_triangle_intersect(vec3 origin, CGLM_INLINE bool glm_ray_triangle(vec3 origin,
vec3 direction, vec3 direction,
vec3 v0, vec3 v0,
vec3 v1, vec3 v1,
vec3 v2, vec3 v2,
float *d); 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 #ifndef cglm_ray_h
@@ -31,7 +37,6 @@
* @param[in, out] d distance to intersection * @param[in, out] d distance to intersection
* @return whether there is intersection * @return whether there is intersection
*/ */
CGLM_INLINE CGLM_INLINE
bool bool
glm_ray_triangle(vec3 origin, glm_ray_triangle(vec3 origin,
@@ -74,4 +79,93 @@ glm_ray_triangle(vec3 origin,
return dist > epsilon; return dist > epsilon;
} }
/*!
* @brief ray sphere intersection
*
* - 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
* - 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)
*/
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;
}
/*!
* @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 #endif

View File

@@ -41,6 +41,7 @@ extern "C" {
#include "struct/sphere.h" #include "struct/sphere.h"
#include "struct/curve.h" #include "struct/curve.h"
#include "struct/affine2d.h" #include "struct/affine2d.h"
#include "struct/ray.h"
#ifdef __cplusplus #ifdef __cplusplus
} }

82
include/cglm/struct/ray.h Normal file
View File

@@ -0,0 +1,82 @@
/*
* 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öllerTrumbore 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
*
* - 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
* - 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)
*/
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);
}
/*!
* @brief point using t by 𝐏(𝑡)=𝐀+𝑡𝐛
*
* @param[in] orig origin of ray
* @param[in] dir direction of ray
* @param[in] t parameter
* @returns point point at t
*/
CGLM_INLINE
vec3s
glms_ray_(at)(vec3s orig, vec3s dir, float t) {
vec3s r;
glm_ray_at(orig.raw, orig.raw, t, r.raw);
return r;
}
#endif /* cglms_ray_h */

View File

@@ -54,6 +54,8 @@
CGLM_INLINE vec2s glms_vec2_clamp(vec2s v, float minVal, float maxVal) CGLM_INLINE vec2s glms_vec2_clamp(vec2s v, float minVal, float maxVal)
CGLM_INLINE vec2s glms_vec2_lerp(vec2s from, vec2s to, float t) CGLM_INLINE vec2s glms_vec2_lerp(vec2s from, vec2s to, float t)
CGLM_INLINE vec2s glms_vec2_make(float * restrict src) CGLM_INLINE vec2s glms_vec2_make(float * restrict src)
CGLM_INLINE vec2s glms_vec2_reflect(vec2s I, vec2s N)
CGLM_INLINE vec2s glms_vec2_refract(vec2s I, vec2s N, float eta)
*/ */
#ifndef cglms_vec2s_h #ifndef cglms_vec2s_h
@@ -691,4 +693,38 @@ glms_vec2_(make)(const float * __restrict src) {
return dest; return dest;
} }
/*!
* @brief reflection vector using an incident ray and a surface normal
*
* @param[in] I incident vector
* @param[in] N normalized normal vector
* @returns reflection result
*/
CGLM_INLINE
vec2s
glms_vec2_(reflect)(vec2s I, vec2s N) {
vec2s dest;
glm_vec2_reflect(I.raw, N.raw, dest.raw);
return dest;
}
/*!
* @brief refraction vector using entering ray, surface normal and refraction index
*
* if the angle between the entering ray I and the surface normal N is too great
* for a given refraction index, the return value is zero
*
* @param[in] I normalized incident vector
* @param[in] N normalized normal vector
* @param[in] eta ratio of indices of refraction
* @param[out] dest refraction result
*/
CGLM_INLINE
vec2s
glms_vec2_(refract)(vec2s I, vec2s N, float eta) {
vec2s dest;
glm_vec2_refract(I.raw, N.raw, eta, dest.raw);
return dest;
}
#endif /* cglms_vec2s_h */ #endif /* cglms_vec2s_h */

View File

@@ -76,6 +76,9 @@
CGLM_INLINE vec3s glms_vec3_smoothinterpc(vec3s from, vec3s to, float t); CGLM_INLINE vec3s glms_vec3_smoothinterpc(vec3s from, vec3s to, float t);
CGLM_INLINE vec3s glms_vec3_swizzle(vec3s v, int mask); CGLM_INLINE vec3s glms_vec3_swizzle(vec3s v, int mask);
CGLM_INLINE vec3s glms_vec3_make(float * restrict src); CGLM_INLINE vec3s glms_vec3_make(float * restrict src);
CGLM_INLINE vec3s glms_vec3_faceforward(vec3s N, vec3s I, vec3s Nref);
CGLM_INLINE vec3s glms_vec3_reflect(vec3s I, vec3s N);
CGLM_INLINE vec3s glms_vec3_refract(vec3s I, vec3s N, float eta);
Convenient: Convenient:
CGLM_INLINE vec3s glms_cross(vec3s a, vec3s b); CGLM_INLINE vec3s glms_cross(vec3s a, vec3s b);
@@ -1083,4 +1086,56 @@ glms_vec3_(make)(const float * __restrict src) {
return dest; return dest;
} }
/*!
* @brief a vector pointing in the same direction as another
*
* orients a vector to point away from a surface as defined by its normal
*
* @param[in] N vector to orient.
* @param[in] I incident vector
* @param[in] Nref reference vector
* @returns oriented vector, pointing away from the surface.
*/
CGLM_INLINE
vec3s
glms_vec3_(faceforward)(vec3s N, vec3s I, vec3s Nref) {
vec3s dest;
glm_vec3_faceforward(N.raw, I.raw, Nref.raw, dest.raw);
return dest;
}
/*!
* @brief reflection vector using an incident ray and a surface normal
*
* @param[in] I incident vector
* @param[in] N normalized normal vector
* @returns reflection result
*/
CGLM_INLINE
vec3s
glms_vec3_(reflect)(vec3s I, vec3s N) {
vec3s dest;
glm_vec3_reflect(I.raw, N.raw, dest.raw);
return dest;
}
/*!
* @brief refraction vector using entering ray, surface normal and refraction index
*
* if the angle between the entering ray I and the surface normal N is too great
* for a given refraction index, the return value is zero
*
* @param[in] I normalized incident vector
* @param[in] N normalized normal vector
* @param[in] eta ratio of indices of refraction
* @returns refraction result
*/
CGLM_INLINE
vec3s
glms_vec3_(refract)(vec3s I, vec3s N, float eta) {
vec3s dest;
glm_vec3_refract(I.raw, N.raw, eta, dest.raw);
return dest;
}
#endif /* cglms_vec3s_h */ #endif /* cglms_vec3s_h */

View File

@@ -67,6 +67,8 @@
CGLM_INLINE vec4s glms_vec4_cubic(float s); CGLM_INLINE vec4s glms_vec4_cubic(float s);
CGLM_INLINE vec4s glms_vec4_swizzle(vec4s v, int mask); CGLM_INLINE vec4s glms_vec4_swizzle(vec4s v, int mask);
CGLM_INLINE vec4s glms_vec4_make(float * restrict src); CGLM_INLINE vec4s glms_vec4_make(float * restrict src);
CGLM_INLINE vec4s glms_vec4_reflect(vec4s I, vec4s N);
CGLM_INLINE vec4s glms_vec4_refract(vec4s I, vec4s N, float eta);
*/ */
#ifndef cglms_vec4s_h #ifndef cglms_vec4s_h
@@ -927,4 +929,42 @@ glms_vec4_(make)(const float * __restrict src) {
return dest; return dest;
} }
/*!
* @brief reflection vector using an incident ray and a surface normal
*
* @param[in] I incident vector
* @param[in] N normalized normal vector
* @returns reflection result
*/
CGLM_INLINE
vec4s
glms_vec4_(reflect)(vec4s I, vec4s N) {
vec4s dest;
glm_vec4_reflect(I.raw, N.raw, dest.raw);
return dest;
}
/*!
* @brief refraction vector using entering ray, surface normal and refraction index
*
* if the angle between the entering ray I and the surface normal N is too great
* for a given refraction index, the return value is zero
*
* this implementation does not explicitly preserve the 'w' component of the
* incident vector 'I' in the output 'dest', users requiring the preservation of
* the 'w' component should manually adjust 'dest' after calling this function.
*
* @param[in] I normalized incident vector
* @param[in] N normalized normal vector
* @param[in] eta ratio of indices of refraction
* @returns refraction result
*/
CGLM_INLINE
vec4s
glms_vec4_(refract)(vec4s I, vec4s N, float eta) {
vec4s dest;
glm_vec4_refract(I.raw, N.raw, eta, dest.raw);
return dest;
}
#endif /* cglms_vec4s_h */ #endif /* cglms_vec4s_h */

View File

@@ -55,7 +55,8 @@
CGLM_INLINE void glm_vec2_clamp(vec2 v, float minVal, float maxVal) CGLM_INLINE void glm_vec2_clamp(vec2 v, float minVal, float maxVal)
CGLM_INLINE void glm_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest) CGLM_INLINE void glm_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest)
CGLM_INLINE void glm_vec2_make(float * restrict src, vec2 dest) CGLM_INLINE void glm_vec2_make(float * restrict src, vec2 dest)
CGLM_INLINE void glm_vec2_reflect(vec2 I, vec2 N, vec2 dest)
CGLM_INLINE void glm_vec2_refract(vec2 I, vec2 N, float eta, vec2 dest)
*/ */
#ifndef cglm_vec2_h #ifndef cglm_vec2_h
@@ -712,4 +713,48 @@ glm_vec2_make(const float * __restrict src, vec2 dest) {
dest[0] = src[0]; dest[1] = src[1]; dest[0] = src[0]; dest[1] = src[1];
} }
/*!
* @brief reflection vector using an incident ray and a surface normal
*
* @param[in] I incident vector
* @param[in] N normalized normal vector
* @param[out] dest destination vector for the reflection result
*/
CGLM_INLINE
void
glm_vec2_reflect(vec2 I, vec2 N, vec2 dest) {
vec2 temp;
glm_vec2_scale(N, 2.0f * glm_vec2_dot(I, N), temp);
glm_vec2_sub(I, temp, dest);
}
/*!
* @brief refraction vector using entering ray, surface normal and refraction index
*
* if the angle between the entering ray I and the surface normal N is too great
* for a given refraction index, the return value is zero
*
* @param[in] I normalized incident vector
* @param[in] N normalized normal vector
* @param[in] eta ratio of indices of refraction
* @param[out] dest refraction result
*/
CGLM_INLINE
void
glm_vec2_refract(vec2 I, vec2 N, float eta, vec2 dest) {
float ndi, eni, k;
ndi = glm_vec2_dot(N, I);
eni = eta * ndi;
k = 1.0f + eta * eta - eni * eni;
if (k < 0.0f) {
glm_vec2_zero(dest);
return;
}
glm_vec2_scale(I, eta, dest);
glm_vec2_mulsubs(N, eni + sqrtf(k), dest);
}
#endif /* cglm_vec2_h */ #endif /* cglm_vec2_h */

View File

@@ -80,6 +80,9 @@
CGLM_INLINE void glm_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest); CGLM_INLINE void glm_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest);
CGLM_INLINE void glm_vec3_swizzle(vec3 v, int mask, vec3 dest); CGLM_INLINE void glm_vec3_swizzle(vec3 v, int mask, vec3 dest);
CGLM_INLINE void glm_vec3_make(float * restrict src, vec3 dest); CGLM_INLINE void glm_vec3_make(float * restrict src, vec3 dest);
CGLM_INLINE void glm_vec3_faceforward(vec3 N, vec3 I, vec3 Nref, vec3 dest);
CGLM_INLINE void glm_vec3_reflect(vec3 I, vec3 N, vec3 dest);
CGLM_INLINE void glm_vec3_refract(vec3 I, vec3 N, float eta, vec3 dest);
Convenient: Convenient:
CGLM_INLINE void glm_cross(vec3 a, vec3 b, vec3 d); CGLM_INLINE void glm_cross(vec3 a, vec3 b, vec3 d);
@@ -1202,4 +1205,70 @@ glm_vec3_make(const float * __restrict src, vec3 dest) {
dest[2] = src[2]; dest[2] = src[2];
} }
/*!
* @brief a vector pointing in the same direction as another
*
* orients a vector to point away from a surface as defined by its normal
*
* @param[in] N vector to orient
* @param[in] I incident vector
* @param[in] Nref reference vector
* @param[out] dest oriented vector, pointing away from the surface
*/
CGLM_INLINE
void
glm_vec3_faceforward(vec3 N, vec3 I, vec3 Nref, vec3 dest) {
if (glm_vec3_dot(I, Nref) < 0.0f) {
/* N is facing away from I */
glm_vec3_copy(N, dest);
} else {
/* N is facing towards I, negate it */
glm_vec3_negate_to(N, dest);
}
}
/*!
* @brief reflection vector using an incident ray and a surface normal
*
* @param[in] I incident vector
* @param[in] N normalized normal vector
* @param[out] dest reflection result
*/
CGLM_INLINE
void
glm_vec3_reflect(vec3 I, vec3 N, vec3 dest) {
vec3 temp;
glm_vec3_scale(N, 2.0f * glm_vec3_dot(I, N), temp);
glm_vec3_sub(I, temp, dest);
}
/*!
* @brief refraction vector using entering ray, surface normal and refraction index
*
* if the angle between the entering ray I and the surface normal N is too great
* for a given refraction index, the return value is zero
*
* @param[in] I normalized incident vector
* @param[in] N normalized normal vector
* @param[in] eta ratio of indices of refraction
* @param[out] dest refraction result
*/
CGLM_INLINE
void
glm_vec3_refract(vec3 I, vec3 N, float eta, vec3 dest) {
float ndi, eni, k;
ndi = glm_vec3_dot(N, I);
eni = eta * ndi;
k = 1.0f + eta * eta - eni * eni;
if (k < 0.0f) {
glm_vec3_zero(dest);
return;
}
glm_vec3_scale(I, eta, dest);
glm_vec3_mulsubs(N, eni + sqrtf(k), dest);
}
#endif /* cglm_vec3_h */ #endif /* cglm_vec3_h */

View File

@@ -65,6 +65,8 @@
CGLM_INLINE void glm_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest); CGLM_INLINE void glm_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest);
CGLM_INLINE void glm_vec4_swizzle(vec4 v, int mask, vec4 dest); CGLM_INLINE void glm_vec4_swizzle(vec4 v, int mask, vec4 dest);
CGLM_INLINE void glm_vec4_make(float * restrict src, vec4 dest); CGLM_INLINE void glm_vec4_make(float * restrict src, vec4 dest);
CGLM_INLINE void glm_vec4_reflect(vec4 I, vec4 N, vec4 dest);
CGLM_INLINE void glm_vec4_refract(vec4 I, vec4 N, float eta, vec4 dest);
DEPRECATED: DEPRECATED:
glm_vec4_dup glm_vec4_dup
@@ -1304,4 +1306,56 @@ glm_vec4_make(const float * __restrict src, vec4 dest) {
dest[2] = src[2]; dest[3] = src[3]; dest[2] = src[2]; dest[3] = src[3];
} }
/*!
* @brief reflection vector using an incident ray and a surface normal
*
* @param[in] I incident vector
* @param[in] N normalized normal vector
* @param[out] dest destination vector for the reflection result
*/
CGLM_INLINE
void
glm_vec4_reflect(vec4 I, vec4 N, vec4 dest) {
vec4 temp;
/* TODO: direct simd touch */
glm_vec4_scale(N, 2.0f * glm_vec4_dot(I, N), temp);
glm_vec4_sub(I, temp, dest);
dest[3] = I[3];
}
/*!
* @brief refraction vector using entering ray, surface normal and refraction index
*
* if the angle between the entering ray I and the surface normal N is too great
* for a given refraction index, the return value is zero
*
* this implementation does not explicitly preserve the 'w' component of the
* incident vector 'I' in the output 'dest', users requiring the preservation of
* the 'w' component should manually adjust 'dest' after calling this function.
*
* @param[in] I normalized incident vector
* @param[in] N normalized normal vector
* @param[in] eta ratio of indices of refraction
* @param[out] dest refraction result
*/
CGLM_INLINE
void
glm_vec4_refract(vec4 I, vec4 N, float eta, vec4 dest) {
float ndi, eni, k;
ndi = glm_vec4_dot(N, I);
eni = eta * ndi;
k = 1.0f + eta * eta - eni * eni;
if (k < 0.0f) {
glm_vec4_zero(dest);
return;
}
glm_vec4_scale(I, eta, dest);
glm_vec4_mulsubs(N, eni + sqrtf(k), dest);
}
#endif /* cglm_vec4_h */ #endif /* cglm_vec4_h */

View File

@@ -9,5 +9,21 @@ glmc_ray_triangle(vec3 origin,
vec3 v1, vec3 v1,
vec3 v2, vec3 v2,
float *d) { 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);
} }

View File

@@ -302,3 +302,15 @@ void
glmc_vec2_make(const float * __restrict src, vec2 dest) { glmc_vec2_make(const float * __restrict src, vec2 dest) {
glm_vec2_make(src, dest); glm_vec2_make(src, dest);
} }
CGLM_EXPORT
void
glmc_vec2_reflect(vec2 I, vec2 N, vec2 dest) {
glm_vec2_reflect(I, N, dest);
}
CGLM_EXPORT
void
glmc_vec2_refract(vec2 I, vec2 N, float eta, vec2 dest) {
glm_vec2_refract(I, N, eta, dest);
}

View File

@@ -459,3 +459,21 @@ void
glmc_vec3_make(const float * __restrict src, vec3 dest) { glmc_vec3_make(const float * __restrict src, vec3 dest) {
glm_vec3_make(src, dest); glm_vec3_make(src, dest);
} }
CGLM_EXPORT
void
glmc_vec3_faceforward(vec3 N, vec3 I, vec3 Nref, vec3 dest) {
glm_vec3_faceforward(N, I, Nref, dest);
}
CGLM_EXPORT
void
glmc_vec3_reflect(vec3 I, vec3 N, vec3 dest) {
glm_vec3_reflect(I, N, dest);
}
CGLM_EXPORT
void
glmc_vec3_refract(vec3 I, vec3 N, float eta, vec3 dest) {
glm_vec3_refract(I, N, eta, dest);
}

View File

@@ -423,3 +423,15 @@ void
glmc_vec4_make(const float * __restrict src, vec4 dest) { glmc_vec4_make(const float * __restrict src, vec4 dest) {
glm_vec4_make(src, dest); glm_vec4_make(src, dest);
} }
CGLM_EXPORT
void
glmc_vec4_reflect(vec4 I, vec4 N, vec4 dest) {
glm_vec4_reflect(I, N, dest);
}
CGLM_EXPORT
void
glmc_vec4_refract(vec4 I, vec4 N, float eta, vec4 dest) {
glm_vec4_refract(I, N, eta, dest);
}

View File

@@ -32,3 +32,43 @@ TEST_IMPL(GLM_PREFIX, ray_triangle) {
TEST_SUCCESS TEST_SUCCESS
} }
TEST_IMPL(GLM_PREFIX, ray_sphere) {
vec4 sphere = {5.0f, 0.0f, 0.0f, 1.0f}; /* Sphere: center at (5, 0, 0) with radius 1 */
float t1, t2;
bool hit;
/* Case 1: Ray misses the sphere */
hit = GLM(ray_sphere)((vec3){10.0f, 3.0f, 0.0f}, (vec3){1.0f, 0.0f, 0.0f}, sphere, &t1, &t2);
ASSERT(!hit); /* Expect no intersection */
/* Case 2: Ray starts inside the sphere */
hit = GLM(ray_sphere)((vec3){5.0f, 0.5f, 0.0f}, (vec3){1.0f, 0.0f, 0.0f}, sphere, &t1, &t2);
ASSERT(hit); /* Expect an intersection */
ASSERT(t1 < 0 && t2 > 0); /* Ray exits at t2 */
/* Case 3: Ray intersects the sphere from outside */
hit = GLM(ray_sphere)((vec3){0.0f, 0.0f, 0.0f}, (vec3){1.0f, 0.0f, 0.0f}, sphere, &t1, &t2);
ASSERT(hit); /* Expect an intersection */
ASSERT(t1 > 0 && t2 > 0); /* Intersections at t1 and t2 */
TEST_SUCCESS
}
TEST_IMPL(GLM_PREFIX, ray_at) {
vec3 origin = {0.0f, 0.0f, 0.0f};
vec3 direction = {1.0f, 1.0f, 1.0f}; /* Diagonal direction */
float distance = sqrtf(3.0f); /* Distance along the ray; sqrt(3) for unit length due to direction normalization */
vec3 result;
/* Normalize the direction to ensure accurate distance measurement */
glm_vec3_normalize(direction);
GLM(ray_at)(origin, direction, distance, result);
ASSERT(fabsf(result[0] - 1.0f) <= 0.0000009); /* Expecting to be 1 unit along the x-axis */
ASSERT(fabsf(result[1] - 1.0f) <= 0.0000009); /* Expecting to be 1 unit along the y-axis */
ASSERT(fabsf(result[2] - 1.0f) <= 0.0000009); /* Expecting to be 1 unit along the z-axis */
TEST_SUCCESS
}

View File

@@ -752,3 +752,70 @@ TEST_IMPL(GLM_PREFIX, vec2_make) {
TEST_SUCCESS TEST_SUCCESS
} }
TEST_IMPL(GLM_PREFIX, vec2_reflect) {
vec2 dest;
/* Reflecting off a "horizontal" surface in 2D */
vec2 I1 = {1.0f, -1.0f}; /* Incoming vector */
vec2 N1 = {0.0f, 1.0f}; /* Normal vector */
GLM(vec2_reflect)(I1, N1, dest);
ASSERT(fabsf(dest[0] - 1.0f) < 0.00001f &&
fabsf(dest[1] - 1.0f) < 0.00001f); /* Expect reflection upwards */
/* Reflecting at an angle in 2D */
vec2 I2 = {sqrtf(2)/2, -sqrtf(2)/2}; /* Incoming vector at 45 degrees */
vec2 N2 = {0.0f, 1.0f}; /* Upwards normal vector */
GLM(vec2_reflect)(I2, N2, dest);
ASSERT(fabsf(dest[0] - sqrtf(2)/2) < 0.00001f &&
fabsf(dest[1] - sqrtf(2)/2) < 0.00001f); /* Expect reflection upwards */
/* Reflecting off a line in 2D representing a "vertical" surface analogy */
vec2 I3 = {1.0f, 0.0f}; /* Incoming vector */
vec2 N3 = {-1.0f, 0.0f}; /* Normal vector representing a "vertical" line */
GLM(vec2_reflect)(I3, N3, dest);
ASSERT(fabsf(dest[0] + 1.0f) < 0.00001f &&
fabsf(dest[1]) < 0.00001f); /* Expect reflection to the left */
TEST_SUCCESS
}
TEST_IMPL(GLM_PREFIX, vec2_refract) {
vec2 I = {sqrtf(0.5f), -sqrtf(0.5f)}; /* Incoming vector at 45 degrees to normal */
vec2 N = {0.0f, 1.0f}; /* Surface normal */
vec2 dest;
float eta;
/* Water to Air (eta = 1.33/1.0) */
eta = 1.33f / 1.0f;
GLM(vec2_refract)(I, N, eta, dest);
// In 2D, we expect a similar bending behavior as in 3D, so we check dest[1]
if (!(dest[0] == 0.0f && dest[1] == 0.0f)) {
ASSERT(dest[1] < -sqrtf(0.5f)); // Refracted ray bends away from the normal
} else {
ASSERT(dest[0] == 0.0f && dest[1] == 0.0f); // Total internal reflection
}
/* Air to Glass (eta = 1.0 / 1.5) */
eta = 1.0f / 1.5f;
GLM(vec2_refract)(I, N, eta, dest);
ASSERT(dest[1] < -sqrtf(0.5f)); // Expect bending towards the normal
/* Glass to Water (eta = 1.5 / 1.33) */
eta = 1.5f / 1.33f;
GLM(vec2_refract)(I, N, eta, dest);
ASSERT(dest[1] < -sqrtf(0.5f)); // Expect bending towards the normal, less bending than air to glass
/* Diamond to Air (eta = 2.42 / 1.0) */
eta = 2.42f / 1.0f;
GLM(vec2_refract)(I, N, eta, dest);
if (!(dest[0] == 0.0f && dest[1] == 0.0f)) {
/* High potential for total internal reflection, but if it occurs, expect significant bending */
ASSERT(dest[1] < -sqrtf(0.5f));
} else {
ASSERT(dest[0] == 0.0f && dest[1] == 0.0f); // Total internal reflection
}
TEST_SUCCESS
}

View File

@@ -1840,3 +1840,89 @@ TEST_IMPL(GLM_PREFIX, vec3_make) {
TEST_SUCCESS TEST_SUCCESS
} }
TEST_IMPL(GLM_PREFIX, vec3_faceforward) {
vec3 N = {0.0f, 1.0f, 0.0f};
vec3 I = {1.0f, -1.0f, 0.0f};
vec3 Nref = {0.0f, -1.0f, 0.0f};
vec3 dest;
GLM(vec3_faceforward)(N, I, Nref, dest);
ASSERT(dest[0] == 0.0f
&& dest[1] == -1.0f
&& dest[2] == 0.0f); /* Expect N flipped */
TEST_SUCCESS
}
TEST_IMPL(GLM_PREFIX, vec3_reflect) {
vec3 dest;
/* Original test: Reflecting off a horizontal surface */
vec3 I1 = {1.0f, -1.0f, 0.0f}; /* Incoming vector */
vec3 N1 = {0.0f, 1.0f, 0.0f}; /* Normal vector */
GLM(vec3_reflect)(I1, N1, dest);
ASSERT(fabsf(dest[0] - 1.0f) < 0.00001f
&& fabsf(dest[1] - 1.0f) < 0.00001f
&& fabsf(dest[2] - 0.0f) < 0.00001f); /* Expect reflection */
/* Scenario 2: Reflecting off a vertical surface */
vec3 I2 = {1.0f, 0.0f, 0.0f}; /* Incoming vector */
vec3 N2 = {-1.0f, 0.0f, 0.0f}; /* Normal vector */
GLM(vec3_reflect)(I2, N2, dest);
ASSERT(fabsf(dest[0] + 1.0f) < 0.00001f
&& fabsf(dest[1]) < 0.00001f
&& fabsf(dest[2]) < 0.00001f); /* Expect reflection to the left */
/* Scenario 3: Reflecting at an angle */
vec3 I3 = {sqrtf(2)/2, -sqrtf(2)/2, 0.0f}; /* Incoming vector at 45 degrees */
vec3 N3 = {0.0f, 1.0f, 0.0f}; /* Upwards normal vector */
GLM(vec3_reflect)(I3, N3, dest);
ASSERT(fabsf(dest[0] - sqrtf(2)/2) < 0.00001f
&& fabsf(dest[1] - sqrtf(2)/2) < 0.00001f
&& fabsf(dest[2]) < 0.00001f); /* Expect reflection upwards */
TEST_SUCCESS
}
TEST_IMPL(GLM_PREFIX, vec3_refract) {
vec3 I = {sqrtf(0.5f), -sqrtf(0.5f), 0.0f}; /* Incoming vector at 45 degrees to normal */
vec3 N = {0.0f, 1.0f, 0.0f}; /* Surface normal */
vec3 dest;
float eta;
/* Water to Air (eta = 1.33/1.0) */
eta = 1.33f / 1.0f;
GLM(vec3_refract)(I, N, eta, dest);
if (!(dest[0] == 0.0f && dest[1] == 0.0f && dest[2] == 0.0f)) {
ASSERT(dest[1] < -sqrtf(0.5f));
} else {
ASSERT(dest[0] == 0.0f && dest[1] == 0.0f && dest[2] == 0.0f);
}
/* Air to Glass (eta = 1.0 / 1.5) */
eta = 1.0f / 1.5f;
GLM(vec3_refract)(I, N, eta, dest);
/* Expect bending towards the normal */
ASSERT(dest[1] < -sqrtf(0.5f));
/* Glass to Water (eta = 1.5 / 1.33) */
eta = 1.5f / 1.33f;
GLM(vec3_refract)(I, N, eta, dest);
/* Expect bending towards the normal, less bending than air to glass */
ASSERT(dest[1] < -sqrtf(0.5f));
/* Diamond to Air (eta = 2.42 / 1.0) */
eta = 2.42f / 1.0f;
GLM(vec3_refract)(I, N, eta, dest);
if (!(dest[0] == 0.0f && dest[1] == 0.0f && dest[2] == 0.0f)) {
/* High potential for total internal reflection, but if it occurs, expect significant bending */
ASSERT(dest[1] < -sqrtf(0.5f));
} else {
ASSERT(dest[0] == 0.0f && dest[1] == 0.0f && dest[2] == 0.0f);
}
TEST_SUCCESS
}

View File

@@ -1536,3 +1536,75 @@ TEST_IMPL(GLM_PREFIX, vec4_make) {
TEST_SUCCESS TEST_SUCCESS
} }
TEST_IMPL(GLM_PREFIX, vec4_reflect) {
vec4 dest;
/* Original test: Reflecting off a horizontal surface */
vec4 I1 = {1.0f, -1.0f, 0.0f, 0.0f}; /* Incoming vector */
vec4 N1 = {0.0f, 1.0f, 0.0f, 0.0f}; /* Normal vector */
GLM(vec4_reflect)(I1, N1, dest);
ASSERT(fabsf(dest[0] - 1.0f) < 0.00001f &&
fabsf(dest[1] - 1.0f) < 0.00001f &&
fabsf(dest[2] - 0.0f) < 0.00001f &&
fabsf(dest[3] - 0.0f) < 0.00001f); /* Expect reflection */
/* Scenario 2: Reflecting off a vertical surface */
vec4 I2 = {1.0f, 0.0f, 0.0f, 0.0f}; /* Incoming vector */
vec4 N2 = {-1.0f, 0.0f, 0.0f, 0.0f}; /* Normal vector */
GLM(vec4_reflect)(I2, N2, dest);
ASSERT(fabsf(dest[0] + 1.0f) < 0.00001f &&
fabsf(dest[1]) < 0.00001f &&
fabsf(dest[2]) < 0.00001f &&
fabsf(dest[3] - 0.0f) < 0.00001f); /* Expect reflection to the left */
/* Scenario 3: Reflecting at an angle */
vec4 I3 = {sqrtf(2)/2, -sqrtf(2)/2, 0.0f, 0.0f}; /* Incoming vector at 45 degrees */
vec4 N3 = {0.0f, 1.0f, 0.0f, 0.0f}; /* Upwards normal vector */
GLM(vec4_reflect)(I3, N3, dest);
ASSERT(fabsf(dest[0] - sqrtf(2)/2) < 0.00001f &&
fabsf(dest[1] - sqrtf(2)/2) < 0.00001f &&
fabsf(dest[2]) < 0.00001f &&
fabsf(dest[3] - 0.0f) < 0.00001f); /* Expect reflection upwards */
TEST_SUCCESS
}
TEST_IMPL(GLM_PREFIX, vec4_refract) {
vec4 I = {sqrtf(0.5f), -sqrtf(0.5f), 0.0f, 0.0f}; /* Incoming vector */
vec4 N = {0.0f, 1.0f, 0.0f, 0.0f}; /* Surface normal */
vec4 dest;
float eta;
/* Water to Air (eta = 1.33/1.0) */
eta = 1.33f / 1.0f;
GLM(vec4_refract)(I, N, eta, dest);
if (!(dest[0] == 0.0f && dest[1] == 0.0f && dest[2] == 0.0f && dest[3] == 0.0f)) {
ASSERT(dest[1] < -sqrtf(0.5f));
} else {
ASSERT(dest[0] == 0.0f && dest[1] == 0.0f && dest[2] == 0.0f && dest[3] == 0.0f);
}
/* Air to Glass (eta = 1.0 / 1.5) */
eta = 1.0f / 1.5f;
GLM(vec4_refract)(I, N, eta, dest);
ASSERT(dest[1] < -sqrtf(0.5f)); // Expect bending towards the normal
/* Glass to Water (eta = 1.5 / 1.33) */
eta = 1.5f / 1.33f;
GLM(vec4_refract)(I, N, eta, dest);
ASSERT(dest[1] < -sqrtf(0.5f)); // Expect bending towards the normal, less bending than air to glass
/* Diamond to Air (eta = 2.42 / 1.0) */
eta = 2.42f / 1.0f;
GLM(vec4_refract)(I, N, eta, dest);
if (!(dest[0] == 0.0f && dest[1] == 0.0f && dest[2] == 0.0f && dest[3] == 0.0f)) {
/* High potential for total internal reflection, but if it occurs, expect significant bending */
ASSERT(dest[1] < -sqrtf(0.5f));
} else {
ASSERT(dest[0] == 0.0f && dest[1] == 0.0f && dest[2] == 0.0f && dest[3] == 0.0f);
}
TEST_SUCCESS
}

View File

@@ -392,7 +392,12 @@ TEST_DECLARE(euler)
/* ray */ /* ray */
TEST_DECLARE(glm_ray_triangle) TEST_DECLARE(glm_ray_triangle)
TEST_DECLARE(glm_ray_sphere)
TEST_DECLARE(glm_ray_at)
TEST_DECLARE(glmc_ray_triangle) TEST_DECLARE(glmc_ray_triangle)
TEST_DECLARE(glmc_ray_sphere)
TEST_DECLARE(glmc_ray_at)
/* quat */ /* quat */
TEST_DECLARE(MACRO_GLM_QUAT_IDENTITY_INIT) TEST_DECLARE(MACRO_GLM_QUAT_IDENTITY_INIT)
@@ -530,6 +535,8 @@ TEST_DECLARE(glm_vec2_lerp)
TEST_DECLARE(glm_vec2_complex_mul) TEST_DECLARE(glm_vec2_complex_mul)
TEST_DECLARE(glm_vec2_complex_div) TEST_DECLARE(glm_vec2_complex_div)
TEST_DECLARE(glm_vec2_make) TEST_DECLARE(glm_vec2_make)
TEST_DECLARE(glm_vec2_reflect)
TEST_DECLARE(glm_vec2_refract)
TEST_DECLARE(glmc_vec2) TEST_DECLARE(glmc_vec2)
TEST_DECLARE(glmc_vec2_copy) TEST_DECLARE(glmc_vec2_copy)
@@ -576,6 +583,8 @@ TEST_DECLARE(glmc_vec2_lerp)
TEST_DECLARE(glmc_vec2_complex_mul) TEST_DECLARE(glmc_vec2_complex_mul)
TEST_DECLARE(glmc_vec2_complex_div) TEST_DECLARE(glmc_vec2_complex_div)
TEST_DECLARE(glmc_vec2_make) TEST_DECLARE(glmc_vec2_make)
TEST_DECLARE(glmc_vec2_reflect)
TEST_DECLARE(glmc_vec2_refract)
/* vec3 */ /* vec3 */
TEST_DECLARE(MACRO_GLM_VEC3_ONE_INIT) TEST_DECLARE(MACRO_GLM_VEC3_ONE_INIT)
@@ -678,6 +687,9 @@ TEST_DECLARE(glm_vec3_fract)
TEST_DECLARE(glm_vec3_hadd) TEST_DECLARE(glm_vec3_hadd)
TEST_DECLARE(glm_vec3_sqrt) TEST_DECLARE(glm_vec3_sqrt)
TEST_DECLARE(glm_vec3_make) TEST_DECLARE(glm_vec3_make)
TEST_DECLARE(glm_vec3_faceforward)
TEST_DECLARE(glm_vec3_reflect)
TEST_DECLARE(glm_vec3_refract)
TEST_DECLARE(glmc_vec3) TEST_DECLARE(glmc_vec3)
TEST_DECLARE(glmc_vec3_copy) TEST_DECLARE(glmc_vec3_copy)
@@ -754,6 +766,9 @@ TEST_DECLARE(glmc_vec3_fract)
TEST_DECLARE(glmc_vec3_hadd) TEST_DECLARE(glmc_vec3_hadd)
TEST_DECLARE(glmc_vec3_sqrt) TEST_DECLARE(glmc_vec3_sqrt)
TEST_DECLARE(glmc_vec3_make) TEST_DECLARE(glmc_vec3_make)
TEST_DECLARE(glmc_vec3_faceforward)
TEST_DECLARE(glmc_vec3_reflect)
TEST_DECLARE(glmc_vec3_refract)
/* vec4 */ /* vec4 */
TEST_DECLARE(MACRO_GLM_VEC4_ONE_INIT) TEST_DECLARE(MACRO_GLM_VEC4_ONE_INIT)
@@ -842,6 +857,8 @@ TEST_DECLARE(glm_vec4_fract)
TEST_DECLARE(glm_vec4_hadd) TEST_DECLARE(glm_vec4_hadd)
TEST_DECLARE(glm_vec4_sqrt) TEST_DECLARE(glm_vec4_sqrt)
TEST_DECLARE(glm_vec4_make) TEST_DECLARE(glm_vec4_make)
TEST_DECLARE(glm_vec4_reflect)
TEST_DECLARE(glm_vec4_refract)
TEST_DECLARE(glmc_vec4) TEST_DECLARE(glmc_vec4)
TEST_DECLARE(glmc_vec4_copy3) TEST_DECLARE(glmc_vec4_copy3)
@@ -914,6 +931,8 @@ TEST_DECLARE(glmc_vec4_fract)
TEST_DECLARE(glmc_vec4_hadd) TEST_DECLARE(glmc_vec4_hadd)
TEST_DECLARE(glmc_vec4_sqrt) TEST_DECLARE(glmc_vec4_sqrt)
TEST_DECLARE(glmc_vec4_make) TEST_DECLARE(glmc_vec4_make)
TEST_DECLARE(glmc_vec4_reflect)
TEST_DECLARE(glmc_vec4_refract)
/* ivec2 */ /* ivec2 */
TEST_DECLARE(glm_ivec2) TEST_DECLARE(glm_ivec2)
@@ -1548,10 +1567,15 @@ TEST_LIST {
TEST_ENTRY(glmc_euler_zyx_quat_lh) TEST_ENTRY(glmc_euler_zyx_quat_lh)
TEST_ENTRY(euler) TEST_ENTRY(euler)
/* ray */ /* ray */
TEST_ENTRY(glm_ray_triangle) TEST_ENTRY(glm_ray_triangle)
TEST_ENTRY(glm_ray_sphere)
TEST_ENTRY(glm_ray_at)
TEST_ENTRY(glmc_ray_triangle) TEST_ENTRY(glmc_ray_triangle)
TEST_ENTRY(glmc_ray_sphere)
TEST_ENTRY(glmc_ray_at)
/* quat */ /* quat */
TEST_ENTRY(MACRO_GLM_QUAT_IDENTITY_INIT) TEST_ENTRY(MACRO_GLM_QUAT_IDENTITY_INIT)
@@ -1688,6 +1712,8 @@ TEST_LIST {
TEST_ENTRY(glm_vec2_complex_mul) TEST_ENTRY(glm_vec2_complex_mul)
TEST_ENTRY(glm_vec2_complex_div) TEST_ENTRY(glm_vec2_complex_div)
TEST_ENTRY(glm_vec2_make) TEST_ENTRY(glm_vec2_make)
TEST_ENTRY(glm_vec2_reflect)
TEST_ENTRY(glm_vec2_refract)
TEST_ENTRY(glmc_vec2) TEST_ENTRY(glmc_vec2)
TEST_ENTRY(glmc_vec2_copy) TEST_ENTRY(glmc_vec2_copy)
@@ -1734,6 +1760,8 @@ TEST_LIST {
TEST_ENTRY(glmc_vec2_complex_mul) TEST_ENTRY(glmc_vec2_complex_mul)
TEST_ENTRY(glmc_vec2_complex_div) TEST_ENTRY(glmc_vec2_complex_div)
TEST_ENTRY(glmc_vec2_make) TEST_ENTRY(glmc_vec2_make)
TEST_ENTRY(glmc_vec2_reflect)
TEST_ENTRY(glmc_vec2_refract)
/* vec3 */ /* vec3 */
TEST_ENTRY(MACRO_GLM_VEC3_ONE_INIT) TEST_ENTRY(MACRO_GLM_VEC3_ONE_INIT)
@@ -1835,6 +1863,9 @@ TEST_LIST {
TEST_ENTRY(glm_vec3_hadd) TEST_ENTRY(glm_vec3_hadd)
TEST_ENTRY(glm_vec3_sqrt) TEST_ENTRY(glm_vec3_sqrt)
TEST_ENTRY(glm_vec3_make) TEST_ENTRY(glm_vec3_make)
TEST_ENTRY(glm_vec3_faceforward)
TEST_ENTRY(glm_vec3_reflect)
TEST_ENTRY(glm_vec3_refract)
TEST_ENTRY(glmc_vec3) TEST_ENTRY(glmc_vec3)
TEST_ENTRY(glmc_vec3_copy) TEST_ENTRY(glmc_vec3_copy)
@@ -1911,6 +1942,9 @@ TEST_LIST {
TEST_ENTRY(glmc_vec3_hadd) TEST_ENTRY(glmc_vec3_hadd)
TEST_ENTRY(glmc_vec3_sqrt) TEST_ENTRY(glmc_vec3_sqrt)
TEST_ENTRY(glmc_vec3_make) TEST_ENTRY(glmc_vec3_make)
TEST_ENTRY(glmc_vec3_faceforward)
TEST_ENTRY(glmc_vec3_reflect)
TEST_ENTRY(glmc_vec3_refract)
/* vec4 */ /* vec4 */
TEST_ENTRY(MACRO_GLM_VEC4_ONE_INIT) TEST_ENTRY(MACRO_GLM_VEC4_ONE_INIT)
@@ -1999,6 +2033,8 @@ TEST_LIST {
TEST_ENTRY(glm_vec4_hadd) TEST_ENTRY(glm_vec4_hadd)
TEST_ENTRY(glm_vec4_sqrt) TEST_ENTRY(glm_vec4_sqrt)
TEST_ENTRY(glm_vec4_make) TEST_ENTRY(glm_vec4_make)
TEST_ENTRY(glm_vec4_reflect)
TEST_ENTRY(glm_vec4_refract)
TEST_ENTRY(glmc_vec4) TEST_ENTRY(glmc_vec4)
TEST_ENTRY(glmc_vec4_copy3) TEST_ENTRY(glmc_vec4_copy3)
@@ -2071,6 +2107,8 @@ TEST_LIST {
TEST_ENTRY(glmc_vec4_hadd) TEST_ENTRY(glmc_vec4_hadd)
TEST_ENTRY(glmc_vec4_sqrt) TEST_ENTRY(glmc_vec4_sqrt)
TEST_ENTRY(glmc_vec4_make) TEST_ENTRY(glmc_vec4_make)
TEST_ENTRY(glmc_vec4_reflect)
TEST_ENTRY(glmc_vec4_refract)
/* ivec2 */ /* ivec2 */
TEST_ENTRY(glm_ivec2) TEST_ENTRY(glm_ivec2)

View File

@@ -253,6 +253,7 @@
<ClInclude Include="..\include\cglm\struct\plane.h" /> <ClInclude Include="..\include\cglm\struct\plane.h" />
<ClInclude Include="..\include\cglm\struct\project.h" /> <ClInclude Include="..\include\cglm\struct\project.h" />
<ClInclude Include="..\include\cglm\struct\quat.h" /> <ClInclude Include="..\include\cglm\struct\quat.h" />
<ClInclude Include="..\include\cglm\struct\ray.h" />
<ClInclude Include="..\include\cglm\struct\sphere.h" /> <ClInclude Include="..\include\cglm\struct\sphere.h" />
<ClInclude Include="..\include\cglm\struct\vec2-ext.h" /> <ClInclude Include="..\include\cglm\struct\vec2-ext.h" />
<ClInclude Include="..\include\cglm\struct\vec2.h" /> <ClInclude Include="..\include\cglm\struct\vec2.h" />

View File

@@ -729,5 +729,8 @@
<ClInclude Include="..\include\cglm\struct\ivec4.h"> <ClInclude Include="..\include\cglm\struct\ivec4.h">
<Filter>include\cglm\struct</Filter> <Filter>include\cglm\struct</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\include\cglm\struct\ray.h">
<Filter>include\cglm\struct</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>