commit 962edc30dcf467b31d3479a3dee901e0f5107564
parent bbdbd6d4ca6182ccd2c9977289e76f997419e6c2
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 12 Jan 2018 14:48:10 +0100
Add a advanced scene view tests
Diffstat:
3 files changed, 303 insertions(+), 301 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -134,8 +134,7 @@ if(NOT NO_TEST)
new_test(test_s2d_sample)
new_test(test_s2d_scene)
new_test(test_s2d_scene_view)
-# new_test(test_s2d_session_advanced)
-# new_test(test_s2d_shape)
+ new_test(test_s2d_scene_view2)
# new_test(test_s2d_trace_ray)
# new_test(test_s2d_trace_ray_3d)
endif(NOT NO_TEST)
diff --git a/src/test_s2d_scene_view2.c b/src/test_s2d_scene_view2.c
@@ -0,0 +1,302 @@
+/* Copyright (C) |Meso|Star> 2016-2018 (contact@meso-star.com)
+ *
+ * This software is governed by the CeCILL license under French law and
+ * abiding by the rules of distribution of free software. You can use,
+ * modify and/or redistribute the software under the terms of the CeCILL
+ * license as circulated by CEA, CNRS and INRIA at the following URL
+ * "http://www.cecill.info".
+ *
+ * As a counterpart to the access to the source code and rights to copy,
+ * modify and redistribute granted by the license, users are provided only
+ * with a limited warranty and the software's author, the holder of the
+ * economic rights, and the successive licensors have only limited
+ * liability.
+ *
+ * In this respect, the user's attention is drawn to the risks associated
+ * with loading, using, modifying and/or developing or reproducing the
+ * software by the user in light of its specific status of free software,
+ * that may mean that it is complicated to manipulate, and that also
+ * therefore means that it is reserved for developers and experienced
+ * professionals having in-depth computer knowledge. Users are therefore
+ * encouraged to load and test the software's suitability as regards their
+ * requirements in conditions enabling the security of their systems and/or
+ * data to be ensured and, more generally, to use and operate it in the
+ * same conditions as regards security.
+ *
+ * The fact that you are presently reading this means that you have had
+ * knowledge of the CeCILL license and that you accept its terms. */
+
+#include "s2d.h"
+#include "test_s2d_utils.h"
+
+#include <rsys/float2.h>
+#include <rsys/stretchy_array.h>
+
+#include <string.h>
+
+#define NSAMPS 10000
+
+static INLINE float*
+ran_semi_disk_cos_local(float samp[2])
+{
+ samp[0] = rand_canonic() * 2.f - 1.f;
+ samp[1] = (float)sqrt(1 - samp[0]*samp[0]);
+ return samp;
+}
+
+static INLINE float*
+ran_semi_disk_cos(const float up[2], float samp[2])
+{
+ float tmp[2], v[2];
+ CHK(f2_is_normalized(samp) == 1);
+ ran_semi_disk_cos_local(tmp);
+ v[0] = -up[1] * tmp[0] + up[0]*tmp[1];
+ v[1] = up[0] * tmp[0] + up[1]*tmp[1];;
+ CHK(f2_is_normalized(v) == 1);
+ return f2_set(samp, v);
+}
+
+static int
+discard_self_hit
+ (const struct s2d_hit* hit,
+ const float org[2],
+ const float dir[2],
+ void* ray_data,
+ void* filter_data)
+{
+ struct s2d_primitive* prim_from = ray_data;
+ CHK(hit != NULL);
+ CHK(org != NULL);
+ CHK(dir != NULL);
+ CHK((intptr_t)filter_data == (intptr_t)0xDECAFBAD);
+ if(!ray_data) return 0;
+ return S2D_PRIMITIVE_EQ(prim_from, &hit->prim);
+}
+
+static struct s2d_shape*
+create_circle_shape
+ (struct s2d_device* dev,
+ const float radius,
+ const float center[2],
+ const unsigned nsteps)
+{
+ float* positions = NULL;
+ unsigned* indices = NULL;
+ struct s2d_shape* shape;
+ struct s2d_vertex_data vdata;
+ struct line_segments_desc desc = { NULL, NULL };
+ const double step = 2.0*PI/(double)nsteps;
+ unsigned i;
+
+ CHK(s2d_shape_create_line_segments(dev, &shape) == RES_OK);
+ CHK(s2d_line_segments_set_hit_filter_function
+ (shape, discard_self_hit, (void*)0xDECAFBAD) == RES_OK);
+
+ CHK(nsteps > 4);
+ CHK(center != NULL);
+ CHK(sa_add(positions, nsteps*2/*#coords per vertex*/) != NULL);
+ CHK(sa_add(indices, nsteps*2/*#ids per segment*/) != NULL);
+
+ FOR_EACH(i, 0, nsteps) {
+ const double theta = i*step;
+ const double x = radius*cos(theta) + center[0];
+ const double y = radius*sin(theta) + center[1];
+ positions[i*2 + 0] = (float)x;
+ positions[i*2 + 1] = (float)y;
+ }
+
+ FOR_EACH(i, 0, nsteps) {
+ indices[i*2 + 0] = i;
+ indices[i*2 + 1] = (i+1) % nsteps;
+ }
+
+ desc.vertices = positions;
+ desc.indices = indices;
+
+ vdata.type = S2D_FLOAT2;
+ vdata.usage = S2D_POSITION;
+ vdata.get = line_segments_get_position;
+
+ CHK(s2d_line_segments_setup_indexed_vertices
+ (shape, nsteps, line_segments_get_ids, nsteps, &vdata, 1, (void*)&desc)
+ == RES_OK);
+
+ CHK(s2d_shape_flip_contour(shape) == RES_OK);
+
+ sa_release(positions);
+ sa_release(indices);
+ return shape;
+}
+
+int
+main(int argc, char** argv)
+{
+ struct mem_allocator allocator;
+ struct s2d_device* dev;
+ struct s2d_scene* scn;
+ struct s2d_scene_view* scnview;
+ struct s2d_shape* shape;
+ struct s2d_primitive prim;
+ unsigned shape_nsteps[3] = { 16, 8, 5 };
+ unsigned shape_ids[3];
+ int* shape_prims[3] ={ NULL, NULL, NULL };
+ int* scene_prims = NULL;
+ size_t i;
+ size_t nprims;
+ float tmp[2];
+ float sum, sum_sqr;
+ float E, V, SE;
+ float area, length;
+ int ishape;
+ (void)argc, (void)argv;
+
+ mem_init_proxy_allocator(&allocator, &mem_default_allocator);
+
+ CHK(s2d_device_create(NULL, &allocator, 0, &dev) == RES_OK);
+ CHK(s2d_scene_create(dev, &scn) == RES_OK);
+
+ CHK(sa_add(shape_prims[0], shape_nsteps[0]) != NULL);
+ CHK(sa_add(shape_prims[1], shape_nsteps[1]) != NULL);
+ CHK(sa_add(shape_prims[2], shape_nsteps[2]) != NULL);
+ CHK(sa_add
+ (scene_prims, shape_nsteps[0]+shape_nsteps[1]+shape_nsteps[2]) != NULL);
+
+ shape = create_circle_shape(dev, 1.f, f2(tmp, 0.f, 0.f), shape_nsteps[0]);
+ CHK(s2d_shape_get_id(shape, &shape_ids[0]) == RES_OK);
+ CHK(shape_ids[0] != S2D_INVALID_ID);
+ CHK(s2d_scene_attach_shape(scn, shape) == RES_OK);
+ CHK(s2d_shape_ref_put(shape) == RES_OK);
+
+ shape = create_circle_shape(dev, 0.5f, f2(tmp, 2.f, 0.5f), shape_nsteps[1]);
+ CHK(s2d_shape_get_id(shape, &shape_ids[1]) == RES_OK);
+ CHK(shape_ids[1] != S2D_INVALID_ID);
+ CHK(shape_ids[1] != shape_ids[0]);
+ CHK(s2d_scene_attach_shape(scn, shape) == RES_OK);
+ CHK(s2d_shape_ref_put(shape) == RES_OK);
+
+ shape = create_circle_shape(dev, 0.25f, f2(tmp, 1.5f, -0.25f), shape_nsteps[2]);
+ CHK(s2d_shape_get_id(shape, &shape_ids[2]) == RES_OK);
+ CHK(shape_ids[2] != S2D_INVALID_ID);
+ CHK(shape_ids[2] != shape_ids[0]);
+ CHK(shape_ids[2] != shape_ids[1]);
+ CHK(s2d_scene_attach_shape(scn, shape) == RES_OK);
+ CHK(s2d_shape_ref_put(shape) == RES_OK);
+
+ CHK(s2d_scene_view_create
+ (scn, S2D_SAMPLE|S2D_GET_PRIMITIVE|S2D_TRACE, &scnview) == RES_OK);
+
+ /* Test sampling */
+ memset(shape_prims[0], 0, sa_size(shape_prims[0])*sizeof(shape_prims[0][0]));
+ memset(shape_prims[1], 0, sa_size(shape_prims[1])*sizeof(shape_prims[1][0]));
+ memset(shape_prims[2], 0, sa_size(shape_prims[2])*sizeof(shape_prims[2][0]));
+ memset(scene_prims, 0, sa_size(scene_prims)*sizeof(scene_prims[0]));
+ FOR_EACH(i, 0, 1024) {
+ struct s2d_attrib attr;
+ float s;
+ CHK(s2d_scene_view_sample(scnview, rand_canonic(), rand_canonic(), &prim, &s)
+ == RES_OK);
+ CHK(s2d_primitive_get_attrib(&prim, S2D_POSITION, s, &attr) == RES_OK);
+ CHK(attr.type == S2D_FLOAT2);
+
+ FOR_EACH(ishape, 0, 3) if(prim.geom_id == shape_ids[ishape]) break;
+ CHK(ishape != 3);
+
+ /* Mark the shape primitive as sampled */
+ CHK(prim.prim_id < shape_nsteps[ishape]);
+ shape_prims[ishape][prim.prim_id] = 1;
+
+ /* Mark the scene primitive as sampled */
+ CHK(prim.scene_prim_id < sa_size(scene_prims));
+ scene_prims[prim.scene_prim_id] = 1;
+ }
+
+ /* Check that all primitives were sampled */
+ FOR_EACH(i, 0, sa_size(shape_prims[0])) CHK(shape_prims[0][i] == 1);
+ FOR_EACH(i, 0, sa_size(shape_prims[1])) CHK(shape_prims[1][i] == 1);
+ FOR_EACH(i, 0, sa_size(shape_prims[2])) CHK(shape_prims[2][i] == 1);
+ FOR_EACH(i, 0, sa_size(scene_prims)) CHK(scene_prims[i] == 1);
+
+ /* Check iteration */
+ memset(shape_prims[0], 0, sa_size(shape_prims[0])*sizeof(shape_prims[0][0]));
+ memset(shape_prims[1], 0, sa_size(shape_prims[1])*sizeof(shape_prims[1][0]));
+ memset(shape_prims[2], 0, sa_size(shape_prims[2])*sizeof(shape_prims[2][0]));
+ memset(scene_prims, 0, sa_size(scene_prims)*sizeof(scene_prims[0]));
+ CHK(s2d_scene_view_primitives_count(scnview, &nprims) == RES_OK);
+ CHK(sa_size(scene_prims) == nprims);
+ FOR_EACH(i, 0, nprims) {
+
+ CHK(s2d_scene_view_get_primitive(scnview, (unsigned)i, &prim) == RES_OK);
+ FOR_EACH(ishape, 0, 3) if(prim.geom_id == shape_ids[ishape]) break;
+ CHK(ishape != 3);
+
+ /* Mark the shape primitive as visited */
+ CHK(prim.prim_id < shape_nsteps[ishape]);
+ shape_prims[ishape][prim.prim_id] = 1;
+
+ /* Mark the scene primitive as visited */
+ CHK(prim.scene_prim_id < sa_size(scene_prims));
+ scene_prims[prim.scene_prim_id] = 1;
+ }
+
+ /* Check that all primitives were visited */
+ FOR_EACH(i, 0, sa_size(shape_prims[0])) CHK(shape_prims[0][i] == 1);
+ FOR_EACH(i, 0, sa_size(shape_prims[1])) CHK(shape_prims[1][i] == 1);
+ FOR_EACH(i, 0, sa_size(shape_prims[2])) CHK(shape_prims[2][i] == 1);
+ FOR_EACH(i, 0, sa_size(scene_prims)) CHK(scene_prims[i] == 1);
+
+ /* Check the ray tracing by numerically compute PI*S/P aka 4V/S in 2D */
+ sum = sum_sqr = 0;
+ FOR_EACH(i, 0, NSAMPS) {
+ const float range[2] = { 0.f, FLT_MAX };
+ struct s2d_attrib attr;
+ struct s2d_hit hit;
+ float P[2], N[2];
+ float s;
+
+ CHK(s2d_scene_view_sample
+ (scnview, rand_canonic(), rand_canonic(), &prim, &s) == RES_OK);
+
+ CHK(s2d_primitive_get_attrib(&prim, S2D_POSITION, s, &attr) == RES_OK);
+ CHK(attr.type == S2D_FLOAT2);
+ f2_set(P, attr.value);
+
+ CHK(s2d_primitive_get_attrib(&prim, S2D_GEOMETRY_NORMAL, s, &attr) == RES_OK);
+ CHK(attr.type == S2D_FLOAT2);
+ CHK(f2_normalize(N, attr.value) != 0.f);
+
+ f2_normalize(tmp, f2(tmp, 1, 1));
+ ran_semi_disk_cos(N, tmp);
+
+ CHK(s2d_scene_view_trace_ray(scnview, P, tmp, range, &prim, &hit) == RES_OK);
+ CHK(S2D_HIT_NONE(&hit) == 0);
+
+ sum += hit.distance;
+ sum_sqr += hit.distance*hit.distance;
+ }
+
+ CHK(s2d_scene_view_compute_contour_length(scnview, &length) == RES_OK);
+ CHK(s2d_scene_view_compute_area(scnview, &area) == RES_OK);
+
+ E = sum / (float)NSAMPS;
+ V = sum_sqr / (float)NSAMPS - E*E;
+ SE = (float)sqrt(V/(float)NSAMPS);
+ printf("PI*S / P = %g ~ %g +/- %g\n",(float)PI*area / length, E, SE);
+ CHK(eq_epsf((float)PI*area / length, E, SE) == 1);
+
+ CHK(s2d_scene_view_ref_put(scnview) == RES_OK);
+
+ CHK(s2d_scene_ref_put(scn) == RES_OK);
+ CHK(s2d_device_ref_put(dev) == RES_OK);
+
+ sa_release(scene_prims);
+ sa_release(shape_prims[0]);
+ sa_release(shape_prims[1]);
+ sa_release(shape_prims[2]);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHK(mem_allocated_size() == 0);
+
+ return 0;
+}
+
diff --git a/src/test_s2d_session_advanced.c b/src/test_s2d_session_advanced.c
@@ -1,299 +0,0 @@
-/* Copyright (C) |Meso|Star> 2016-2018 (contact@meso-star.com)
- *
- * This software is governed by the CeCILL license under French law and
- * abiding by the rules of distribution of free software. You can use,
- * modify and/or redistribute the software under the terms of the CeCILL
- * license as circulated by CEA, CNRS and INRIA at the following URL
- * "http://www.cecill.info".
- *
- * As a counterpart to the access to the source code and rights to copy,
- * modify and redistribute granted by the license, users are provided only
- * with a limited warranty and the software's author, the holder of the
- * economic rights, and the successive licensors have only limited
- * liability.
- *
- * In this respect, the user's attention is drawn to the risks associated
- * with loading, using, modifying and/or developing or reproducing the
- * software by the user in light of its specific status of free software,
- * that may mean that it is complicated to manipulate, and that also
- * therefore means that it is reserved for developers and experienced
- * professionals having in-depth computer knowledge. Users are therefore
- * encouraged to load and test the software's suitability as regards their
- * requirements in conditions enabling the security of their systems and/or
- * data to be ensured and, more generally, to use and operate it in the
- * same conditions as regards security.
- *
- * The fact that you are presently reading this means that you have had
- * knowledge of the CeCILL license and that you accept its terms. */
-
-#include "s2d.h"
-#include "test_s2d_utils.h"
-
-#include <rsys/float2.h>
-#include <rsys/stretchy_array.h>
-
-#include <string.h>
-
-#define NSAMPS 10000
-
-static INLINE float*
-ran_semi_disk_cos_local(float samp[2])
-{
- samp[0] = rand_canonic() * 2.f - 1.f;
- samp[1] = (float)sqrt(1 - samp[0]*samp[0]);
- return samp;
-}
-
-static INLINE float*
-ran_semi_disk_cos(const float up[2], float samp[2])
-{
- float tmp[2], v[2];
- CHK(f2_is_normalized(samp) == 1);
- ran_semi_disk_cos_local(tmp);
- v[0] = -up[1] * tmp[0] + up[0]*tmp[1];
- v[1] = up[0] * tmp[0] + up[1]*tmp[1];;
- CHK(f2_is_normalized(v) == 1);
- return f2_set(samp, v);
-}
-
-static int
-discard_self_hit
- (const struct s2d_hit* hit,
- const float org[2],
- const float dir[2],
- void* ray_data,
- void* filter_data)
-{
- struct s2d_primitive* prim_from = ray_data;
- CHK(hit != NULL);
- CHK(org != NULL);
- CHK(dir != NULL);
- CHK((intptr_t)filter_data == (intptr_t)0xDECAFBAD);
- if(!ray_data) return 0;
- return S2D_PRIMITIVE_EQ(prim_from, &hit->prim);
-}
-
-static struct s2d_shape*
-create_circle_shape
- (struct s2d_device* dev,
- const float radius,
- const float center[2],
- const unsigned nsteps)
-{
- float* positions = NULL;
- unsigned* indices = NULL;
- struct s2d_shape* shape;
- struct s2d_vertex_data vdata;
- struct line_segments_desc desc = { NULL, NULL };
- const double step = 2.0*PI/(double)nsteps;
- unsigned i;
-
- CHK(s2d_shape_create_line_segments(dev, &shape) == RES_OK);
- CHECK(s2d_line_segments_set_hit_filter_function
- (shape, discard_self_hit, (void*)0xDECAFBAD), RES_OK);
-
- CHK(nsteps > 4 == 1);
- CHK(center != NULL);
- CHK(sa_add(positions, nsteps*2/*#coords per vertex*/) != NULL);
- CHK(sa_add(indices, nsteps*2/*#ids per segment*/) != NULL);
-
- FOR_EACH(i, 0, nsteps) {
- const double theta = i*step;
- const double x = radius*cos(theta) + center[0];
- const double y = radius*sin(theta) + center[1];
- positions[i*2 + 0] = (float)x;
- positions[i*2 + 1] = (float)y;
- }
-
- FOR_EACH(i, 0, nsteps) {
- indices[i*2 + 0] = i;
- indices[i*2 + 1] = (i+1) % nsteps;
- }
-
- desc.vertices = positions;
- desc.indices = indices;
-
- vdata.type = S2D_FLOAT2;
- vdata.usage = S2D_POSITION;
- vdata.get = line_segments_get_position;
-
- CHECK(s2d_line_segments_setup_indexed_vertices
- (shape, nsteps, line_segments_get_ids, nsteps, &vdata, 1, (void*)&desc),
- RES_OK);
-
- CHK(s2d_shape_flip_contour(shape) == RES_OK);
-
- sa_release(positions);
- sa_release(indices);
- return shape;
-}
-
-int
-main(int argc, char** argv)
-{
- struct mem_allocator allocator;
- struct s2d_device* dev;
- struct s2d_scene* scn;
- struct s2d_shape* shape;
- struct s2d_primitive prim;
- unsigned shape_nsteps[3] = { 16, 8, 5 };
- unsigned shape_ids[3];
- int* shape_prims[3] ={ NULL, NULL, NULL };
- int* scene_prims = NULL;
- size_t i;
- size_t nprims;
- float tmp[2];
- float sum, sum_sqr;
- float E, V, SE;
- float area, length;
- int ishape;
- (void)argc, (void)argv;
-
- mem_init_proxy_allocator(&allocator, &mem_default_allocator);
-
- CHK(s2d_device_create(NULL, &allocator, 0, &dev) == RES_OK);
- CHK(s2d_scene_create(dev, &scn) == RES_OK);
-
- CHK(sa_add(shape_prims[0], shape_nsteps[0]) != NULL);
- CHK(sa_add(shape_prims[1], shape_nsteps[1]) != NULL);
- CHK(sa_add(shape_prims[2], shape_nsteps[2]) != NULL);
- NCHECK(sa_add
- (scene_prims, shape_nsteps[0]+shape_nsteps[1]+shape_nsteps[2]), NULL);
-
- shape = create_circle_shape(dev, 1.f, f2(tmp, 0.f, 0.f), shape_nsteps[0]);
- CHK(s2d_shape_get_id(shape, &shape_ids[0]) == RES_OK);
- CHK(shape_ids[0] != S2D_INVALID_ID);
- CHK(s2d_scene_attach_shape(scn, shape) == RES_OK);
- CHK(s2d_shape_ref_put(shape) == RES_OK);
-
- shape = create_circle_shape(dev, 0.5f, f2(tmp, 2.f, 0.5f), shape_nsteps[1]);
- CHK(s2d_shape_get_id(shape, &shape_ids[1]) == RES_OK);
- CHK(shape_ids[1] != S2D_INVALID_ID);
- CHK(shape_ids[1] != shape_ids[0]);
- CHK(s2d_scene_attach_shape(scn, shape) == RES_OK);
- CHK(s2d_shape_ref_put(shape) == RES_OK);
-
- shape = create_circle_shape(dev, 0.25f, f2(tmp, 1.5f, -0.25f), shape_nsteps[2]);
- CHK(s2d_shape_get_id(shape, &shape_ids[2]) == RES_OK);
- CHK(shape_ids[2] != S2D_INVALID_ID);
- CHK(shape_ids[2] != shape_ids[0]);
- CHK(shape_ids[2] != shape_ids[1]);
- CHK(s2d_scene_attach_shape(scn, shape) == RES_OK);
- CHK(s2d_shape_ref_put(shape) == RES_OK);
-
- CHECK(s2d_scene_begin_session
- (scn, S2D_SAMPLE|S2D_GET_PRIMITIVE|S2D_TRACE), RES_OK);
-
- /* Test sampling */
- memset(shape_prims[0], 0, sa_size(shape_prims[0])*sizeof(shape_prims[0][0]));
- memset(shape_prims[1], 0, sa_size(shape_prims[1])*sizeof(shape_prims[1][0]));
- memset(shape_prims[2], 0, sa_size(shape_prims[2])*sizeof(shape_prims[2][0]));
- memset(scene_prims, 0, sa_size(scene_prims)*sizeof(scene_prims[0]));
- FOR_EACH(i, 0, 1024) {
- struct s2d_attrib attr;
- float s;
- CHK(s2d_scene_sample(scn, rand_canonic(), rand_canonic(), &prim, &s) == RES_OK);
- CHK(s2d_primitive_get_attrib(&prim, S2D_POSITION, s, &attr) == RES_OK);
- CHK(attr.type == S2D_FLOAT2);
-
- FOR_EACH(ishape, 0, 3) if(prim.geom_id == shape_ids[ishape]) break;
- CHK(ishape != 3);
-
- /* Mark the shape primitive as sampled */
- CHK(prim.prim_id < shape_nsteps[ishape] == 1);
- shape_prims[ishape][prim.prim_id] = 1;
-
- /* Mark the scene primitive as sampled */
- CHK(prim.scene_prim_id < sa_size(scene_prims) == 1);
- scene_prims[prim.scene_prim_id] = 1;
- }
-
- /* Check that all primitives were sampled */
- FOR_EACH(i, 0, sa_size(shape_prims[0])) CHK(shape_prims[0][i] == 1);
- FOR_EACH(i, 0, sa_size(shape_prims[1])) CHK(shape_prims[1][i] == 1);
- FOR_EACH(i, 0, sa_size(shape_prims[2])) CHK(shape_prims[2][i] == 1);
- FOR_EACH(i, 0, sa_size(scene_prims)) CHK(scene_prims[i] == 1);
-
- /* Check iteration */
- memset(shape_prims[0], 0, sa_size(shape_prims[0])*sizeof(shape_prims[0][0]));
- memset(shape_prims[1], 0, sa_size(shape_prims[1])*sizeof(shape_prims[1][0]));
- memset(shape_prims[2], 0, sa_size(shape_prims[2])*sizeof(shape_prims[2][0]));
- memset(scene_prims, 0, sa_size(scene_prims)*sizeof(scene_prims[0]));
- CHK(s2d_scene_primitives_count(scn, &nprims) == RES_OK);
- CHK(sa_size(scene_prims) == nprims);
- FOR_EACH(i, 0, nprims) {
-
- CHK(s2d_scene_get_primitive(scn, (unsigned)i, &prim) == RES_OK);
- FOR_EACH(ishape, 0, 3) if(prim.geom_id == shape_ids[ishape]) break;
- CHK(ishape != 3);
-
- /* Mark the shape primitive as visited */
- CHK(prim.prim_id < shape_nsteps[ishape] == 1);
- shape_prims[ishape][prim.prim_id] = 1;
-
- /* Mark the scene primitive as visited */
- CHK(prim.scene_prim_id < sa_size(scene_prims) == 1);
- scene_prims[prim.scene_prim_id] = 1;
- }
-
- /* Check that all primitives were visited */
- FOR_EACH(i, 0, sa_size(shape_prims[0])) CHK(shape_prims[0][i] == 1);
- FOR_EACH(i, 0, sa_size(shape_prims[1])) CHK(shape_prims[1][i] == 1);
- FOR_EACH(i, 0, sa_size(shape_prims[2])) CHK(shape_prims[2][i] == 1);
- FOR_EACH(i, 0, sa_size(scene_prims)) CHK(scene_prims[i] == 1);
-
- /* Check the ray tracing by numerically compute PI*S/P aka 4V/S in 2D */
- sum = sum_sqr = 0;
- FOR_EACH(i, 0, NSAMPS) {
- const float range[2] = { 0.f, FLT_MAX };
- struct s2d_attrib attr;
- struct s2d_hit hit;
- float P[2], N[2];
- float s;
-
- CHK(s2d_scene_sample(scn, rand_canonic(), rand_canonic(), &prim, &s) == RES_OK);
-
- CHK(s2d_primitive_get_attrib(&prim, S2D_POSITION, s, &attr) == RES_OK);
- CHK(attr.type == S2D_FLOAT2);
- f2_set(P, attr.value);
-
- CHK(s2d_primitive_get_attrib(&prim, S2D_GEOMETRY_NORMAL, s, &attr) == RES_OK);
- CHK(attr.type == S2D_FLOAT2);
- CHK(f2_normalize(N, attr.value) != 0.f);
-
- f2_normalize(tmp, f2(tmp, 1, 1));
- ran_semi_disk_cos(N, tmp);
-
- CHK(s2d_scene_trace_ray(scn, P, tmp, range, &prim, &hit) == RES_OK);
- CHK(S2D_HIT_NONE(&hit) == 0);
-
- sum += hit.distance;
- sum_sqr += hit.distance*hit.distance;
- }
-
- CHK(s2d_scene_compute_contour_length(scn, &length) == RES_OK);
- CHK(s2d_scene_compute_area(scn, &area) == RES_OK);
-
- E = sum / (float)NSAMPS;
- V = sum_sqr / (float)NSAMPS - E*E;
- SE = (float)sqrt(V/(float)NSAMPS);
- printf("PI*S / P = %g ~ %g +/- %g\n",(float)PI*area / length, E, SE);
- CHK(eq_epsf((float)PI*area / length, E, SE) == 1);
-
- CHK(s2d_scene_end_session(scn) == RES_OK);
-
- CHK(s2d_scene_ref_put(scn) == RES_OK);
- CHK(s2d_device_ref_put(dev) == RES_OK);
-
- sa_release(scene_prims);
- sa_release(shape_prims[0]);
- sa_release(shape_prims[1]);
- sa_release(shape_prims[2]);
-
- check_memory_allocator(&allocator);
- mem_shutdown_proxy_allocator(&allocator);
- CHK(mem_allocated_size() == 0);
-
- return 0;
-}
-