commit bdcdb345322266fb95b8ab0ff4a7dac214f39ed9
parent 85cad347d896dc98aed22abb9c2a96a8536fb807
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 23 May 2018 12:54:59 +0200
Fix inaccuracies of the scene_get_medium_2d func
Due to ray tracing numerical imprecisions, this function might return
a wrong medium.
Diffstat:
1 file changed, 34 insertions(+), 20 deletions(-)
diff --git a/src/sdis_scene.c b/src/sdis_scene.c
@@ -467,34 +467,48 @@ scene_get_medium_2d
struct s2d_hit hit;
struct s2d_attrib attr;
struct s2d_primitive prim;
- float s;
const float range[2] = {0.f, FLT_MAX};
float N[2], P[2], dir[2], cos_N_dir;
- s = 1.f / 3.f;
- /* Retrieve a position onto the primitive */
- S2D(scene_view_get_primitive(scn->s2d_view, (unsigned)iprim, &prim));
- S2D(primitive_get_attrib(&prim, S2D_POSITION, s, &attr));
+ /* Range of the parametric coordinate into which positions are challenged */
+ const float s_range[2] = {0.25, 0.75};
+ const size_t s_nsteps = 3; /* #challenges per primitive into the range */
+ float s;
+ float s_step;
+
+ s_step = (s_range[1] - s_range[0]) / (float)(s_nsteps-1);
+ s = s_range[0];
+ do {
+ /* Retrieve a position onto the primitive */
+ S2D(scene_view_get_primitive(scn->s2d_view, (unsigned)iprim, &prim));
+ S2D(primitive_get_attrib(&prim, S2D_POSITION, s, &attr));
+
+ /* Trace a ray from the random walk vertex toward the retrieved primitive
+ * position */
+ f2_normalize(dir, f2_sub(dir, attr.value, f2_set_d2(P, pos)));
+ S2D(scene_view_trace_ray(scn->s2d_view, P, dir, range, NULL, &hit));
+
+ /* Unforeseen error. One has to intersect a primitive ! */
+ if(S2D_HIT_NONE(&hit)) {
+ ++nfailures;
+ if(nfailures < max_failures) {
+ continue;
+ } else {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ }
+ /* Discard the hit if it is on a vertex, i.e. between 2 segments, and
+ * target a new position onto the current primitive */
+ } while(hit_on_vertex(&hit) && (s+=s_step) <= s_range[1]);
- /* Trace a ray from the randomw walk vertex toward the retrieved primitive
- * position */
- f2_normalize(dir, f2_sub(dir, attr.value, f2_set_d2(P, pos)));
- S2D(scene_view_trace_ray(scn->s2d_view, P, dir, range, NULL, &hit));
+ /* The hits of all targeted positions on the current primitive, are on
+ * edges. Try positions on another primitive. */
+ if(s > 0.75f) continue;
f2_normalize(N, hit.normal);
cos_N_dir = f2_dot(N, dir);
- /* Unforeseen error. One has to intersect a primitive ! */
- if(S2D_HIT_NONE(&hit)) {
- ++nfailures;
- if(nfailures < max_failures) {
- continue;
- } else {
- res = RES_BAD_ARG;
- goto error;
- }
- }
-
if(absf(cos_N_dir) > 1.e-1f) { /* Not roughly orthognonal */
const struct sdis_interface* interf;
interf = scene_get_interface(scn, hit.prim.prim_id);