commit 83ec660c02f1f7f925c2e17abfac7e15c7cf634b
parent bdc9d040617eb14b891abfb5b2816a1f8cc70236
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 18 Jan 2018 15:58:03 +0100
Test the sampling of scene view with a spherical shape
Diffstat:
8 files changed, 171 insertions(+), 36 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -142,15 +142,16 @@ if(NOT NO_TEST)
endfunction()
new_test(test_s3d_device)
- new_test(test_s3d_primitive)
new_test(test_s3d_sampler)
+ new_test(test_s3d_sample_sphere)
new_test(test_s3d_scene)
new_test(test_s3d_scene_view)
+ new_test(test_s3d_seams)
new_test(test_s3d_shape)
new_test(test_s3d_sphere)
+ new_test(test_s3d_primitive)
new_test(test_s3d_trace_ray_instance)
new_test(test_s3d_trace_ray_sphere)
- new_test(test_s3d_seams)
build_test(test_s3d_trace_ray)
register_test(test_s3d_trace_ray_legacy test_s3d_trace_ray)
diff --git a/src/s3d_primitive.c b/src/s3d_primitive.c
@@ -58,7 +58,13 @@ mesh_get_primitive_attrib
ASSERT(geom && geom->type == GEOM_MESH && prim && prim->shape__ == geom);
ASSERT(uv && attrib);
+ /* Unormalized barycentric coordinates */
w = CLAMP(1.f - uv[0] - uv[1], 0.f, 1.f);
+ if(uv[0] < 0.f || uv[1] < 0.f || uv[0] > 1.f || uv[1] > 1.f
+ || !eq_epsf(w + uv[0] + uv[1], 1.f, 1.e-3f)) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
/* The mesh haven't the required mesh attrib */
if(usage != S3D_GEOMETRY_NORMAL && !geom->data.mesh->attribs[usage]) {
@@ -146,11 +152,11 @@ sphere_get_attrib
double phi, cos_theta, sin_theta;
float P[3];
float N[3];
- ASSERT(geom && geom->type == GEOM_MESH && prim && prim->shape__ == geom);
+ ASSERT(geom && geom->type == GEOM_SPHERE && prim && prim->shape__ == geom);
ASSERT(uv && attrib);
/* Only position and geometry normal are valid sphere attribs */
- if(usage != S3D_GEOMETRY_NORMAL || usage != S3D_POSITION) {
+ if(usage != S3D_GEOMETRY_NORMAL && usage != S3D_POSITION) {
res = RES_BAD_ARG;
goto error;
}
@@ -221,14 +227,6 @@ s3d_primitive_get_attrib
goto error;
}
- /* Unormalized barycentric coordinates */
- w = CLAMP(1.f - uv[0] - uv[1], 0.f, 1.f);
- if(uv[0] < 0.f || uv[1] < 0.f || uv[0] > 1.f || uv[1] > 1.f
- || !eq_epsf(w + uv[0] + uv[1], 1.f, 1.e-3f)) {
- res = RES_BAD_ARG;
- goto error;
- }
-
if(prim->inst__ == NULL) {
geom_shape = (struct geometry*)prim->shape__;
flip_surface = geom_shape->flip_surface;
diff --git a/src/test_s3d_primitive.c b/src/test_s3d_primitive.c
@@ -49,14 +49,6 @@ static const unsigned plane_nverts = sizeof(plane_verts) / sizeof(float[3]);
static const unsigned plane_ids[] = { 0, 1, 2, 2, 3, 0 };
static const unsigned plane_ntris = sizeof(plane_ids) / sizeof(unsigned[3]);
-static float
-rand_canonic(void)
-{
- int r;
- while((r = rand()) == RAND_MAX);
- return (float)r / (float)RAND_MAX;
-}
-
static void
plane_get_ids(const unsigned itri, unsigned ids[3], void* data)
{
diff --git a/src/test_s3d_sample_sphere.c b/src/test_s3d_sample_sphere.c
@@ -0,0 +1,142 @@
+/* Copyright (C) |Meso|Star> 2015-2018 (contact@meso-star.com)
+ *
+ * This software is a computer program whose purpose is to describe a
+ * virtual 3D environment that can be ray-traced and sampled both robustly
+ * and efficiently.
+ *
+ * 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 "s3d.h"
+#include "test_s3d_utils.h"
+
+#include <rsys/float2.h>
+#include <rsys/float3.h>
+
+int
+main(int argc, char** argv)
+{
+ struct mem_allocator allocator;
+ struct s3d_attrib attr0;
+ struct s3d_attrib attr1;
+ struct s3d_primitive prim0;
+ struct s3d_primitive prim1;
+ struct s3d_device* dev;
+ struct s3d_shape* sphere0;
+ struct s3d_shape* sphere1;
+ struct s3d_scene* scn;
+ struct s3d_scene_view* view;
+ unsigned sphere0_id;
+ unsigned sphere1_id;
+ float center[3];
+ float st0[2];
+ float st1[2];
+ int N = 10000;
+ int i;
+ float sum;
+ float E, V, SE;
+ (void)argc, (void)argv;
+
+ CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK);
+ CHK(s3d_device_create(NULL, &allocator, 0, &dev) == RES_OK);
+ CHK(s3d_scene_create(dev, &scn) == RES_OK);
+
+ CHK(s3d_shape_create_sphere(dev, &sphere0) == RES_OK);
+ CHK(s3d_shape_create_sphere(dev, &sphere1) == RES_OK);
+ CHK(s3d_shape_get_id(sphere0, &sphere0_id) == RES_OK);
+ CHK(s3d_shape_get_id(sphere1, &sphere1_id) == RES_OK);
+
+ CHK(s3d_sphere_setup(sphere0, f3(center,-1.5, 0, 0), 2) == RES_OK);
+ CHK(s3d_sphere_setup(sphere1, f3(center, 1.5, 0, 0), 2) == RES_OK);
+ CHK(s3d_scene_attach_shape(scn, sphere0) == RES_OK);
+ CHK(s3d_scene_attach_shape(scn, sphere1) == RES_OK);
+
+ CHK(s3d_scene_view_create(scn, S3D_SAMPLE, &view) == RES_OK);
+ CHK(s3d_scene_view_sample(view, 0, 0, 0, &prim0, st0) == RES_OK);
+ CHK(prim0.prim_id == 0);
+ CHK(prim0.geom_id == sphere0_id || prim0.geom_id == sphere1_id);
+ CHK(prim0.inst_id == S3D_INVALID_ID);
+
+ CHK(s3d_scene_view_sample(view, 0, 0, 0, &prim1, st1) == RES_OK);
+ CHK(S3D_PRIMITIVE_EQ(&prim0, &prim1));
+ CHK(f2_eq(st0, st1));
+
+ CHK(s3d_primitive_get_attrib(&prim0, S3D_ATTRIB_0, st0, &attr0) == RES_BAD_ARG);
+ CHK(s3d_primitive_get_attrib(&prim0, S3D_ATTRIB_1, st0, &attr0) == RES_BAD_ARG);
+ CHK(s3d_primitive_get_attrib(&prim0, S3D_ATTRIB_2, st0, &attr0) == RES_BAD_ARG);
+ CHK(s3d_primitive_get_attrib(&prim0, S3D_ATTRIB_3, st0, &attr0) == RES_BAD_ARG);
+ CHK(s3d_primitive_get_attrib(&prim0, S3D_POSITION, st0, &attr0) == RES_OK);
+ CHK(s3d_primitive_get_attrib
+ (&prim0, S3D_GEOMETRY_NORMAL, st0, &attr1) == RES_OK);
+
+ if(prim0.geom_id == sphere0_id) {
+ f3_sub(attr0.value, attr0.value, f3(center,-1.5, 0, 0));
+ } else {
+ f3_sub(attr0.value, attr0.value, f3(center, 1.5, 0, 0));
+ }
+ f3_mulf(attr1.value, attr1.value, 2.f);
+ CHK(f3_eq_eps(attr0.value, attr1.value, 1.e-3f));
+
+ /* Check that 50 percents of samples lie onto "sphere0" */
+ FOR_EACH(i, 0, N) {
+ const float u = rand_canonic();
+ const float v = rand_canonic();
+ const float w = rand_canonic();
+
+ CHK(s3d_scene_view_sample(view, u, v, w, &prim0, st0) == RES_OK);
+ if(prim0.geom_id == sphere0_id) {
+ sum += 1;
+ }
+
+ CHK(s3d_primitive_get_attrib(&prim0, S3D_POSITION, st0, &attr0) == RES_OK);
+ CHK(s3d_primitive_get_attrib
+ (&prim0, S3D_GEOMETRY_NORMAL, st0, &attr1) == RES_OK);
+
+ if(prim0.geom_id == sphere0_id) {
+ f3_sub(attr0.value, attr0.value, f3(center,-1.5, 0, 0));
+ } else {
+ f3_sub(attr0.value, attr0.value, f3(center, 1.5, 0, 0));
+ }
+ f3_mulf(attr1.value, attr1.value, 2.f);
+ CHK(f3_eq_eps(attr0.value, attr1.value, 1.e-3f));
+ }
+ E = sum / (float)N;
+ V = sum / (float)N - E*E;
+ SE = (float)sqrt(V/(float)N);
+ CHK(eq_epsf(E, 0.5, SE));
+
+ CHK(s3d_device_ref_put(dev) == RES_OK);
+ CHK(s3d_scene_ref_put(scn) == RES_OK);
+ CHK(s3d_shape_ref_put(sphere0) == RES_OK);
+ CHK(s3d_shape_ref_put(sphere1) == RES_OK);
+ CHK(s3d_scene_view_ref_put(view) == RES_OK);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHK(mem_allocated_size() == 0);
+ return 0;
+}
+
diff --git a/src/test_s3d_sampler.c b/src/test_s3d_sampler.c
@@ -38,14 +38,6 @@
#define NSAMPS 4096
-static float
-rand_canonic(void)
-{
- int r;
- while((r = rand()) == RAND_MAX);
- return (float)r / (float)RAND_MAX;
-}
-
int
main(int argc, char** argv)
{
diff --git a/src/test_s3d_scene_view.c b/src/test_s3d_scene_view.c
@@ -99,14 +99,6 @@ static const unsigned plane_ntris = sizeof(plane_ids) / sizeof(unsigned[3]);
/*******************************************************************************
* helper function
******************************************************************************/
-static float
-rand_canonic(void)
-{
- int r;
- while((r = rand()) == RAND_MAX);
- return (float)r / (float)RAND_MAX;
-}
-
static void
get_ids(const unsigned itri, unsigned ids[3], void* data)
{
diff --git a/src/test_s3d_trace_ray_sphere.c b/src/test_s3d_trace_ray_sphere.c
@@ -94,13 +94,23 @@ main(int argc, char** argv)
((uint8_t*)img.pixels)[ipix+1] = 0;
((uint8_t*)img.pixels)[ipix+2] = 0;
} else {
+ struct s3d_attrib attr;
float normal[3] = {0.f, 0.f, 0.f};
float tmp[3];
float len;
float dot;
+
f3_normalize(normal, hit.normal);
+ CHK(s3d_primitive_get_attrib
+ (&hit.prim, S3D_GEOMETRY_NORMAL, hit.uv, &attr) == RES_OK);
+ f3_normalize(attr.value, attr.value);
+ CHK(f3_eq_eps(normal, attr.value, 1.e-3f));
f3_add(pos, org, f3_mulf(pos, dir, hit.distance));
+ CHK(s3d_primitive_get_attrib
+ (&hit.prim, S3D_POSITION, hit.uv, &attr) == RES_OK);
+ CHK(f3_eq_eps(pos, attr.value, 1.e-3f));
+
len = f3_len(f3_sub(pos, pos, center));
CHK(eq_epsf(len, radius, 1.e-3f));
CHK(f3_eq_eps(f3_mulf(tmp, normal, radius), pos, 1.e-3f));
diff --git a/src/test_s3d_utils.h b/src/test_s3d_utils.h
@@ -36,6 +36,14 @@
#include <rsys/mem_allocator.h>
#include <stdio.h>
+static INLINE float
+rand_canonic(void)
+{
+ int r;
+ while((r = rand()) == RAND_MAX);
+ return (float)r / (float)RAND_MAX;
+}
+
static void
check_memory_allocator(struct mem_allocator* allocator)
{