commit 9a0ea621bfcd545bffc28618e5552fad6a6661a2
parent 0fa37740758f22fe522feb75edaeb9cd3e0e8519
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 13 Jul 2015 11:09:50 +0200
Add and test the uniform sampling of a triangle
Diffstat:
3 files changed, 137 insertions(+), 1 deletion(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -66,7 +66,7 @@ rcmake_append_runtime_dirs(_runtime_dirs RSys ${Boost_LIBRARY_DIRS})
# Configure and define targets
################################################################################
set(VERSION_MAJOR 0)
-set(VERSION_MINOR 1)
+set(VERSION_MINOR 2)
set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
@@ -141,6 +141,7 @@ if(NOT NO_TEST)
endif()
new_test(test_ssp_ran_hemisphere ${MATH_LIB})
new_test(test_ssp_ran_sphere ${MATH_LIB})
+ new_test(test_ssp_ran_triangle ${MATH_LIB})
new_test(test_ssp_rng_proxy)
endif()
diff --git a/src/ssp.h b/src/ssp.h
@@ -242,6 +242,45 @@ ssp_ran_sphere_pdf(void)
}
/*******************************************************************************
+ * Triangle distribution
+ ******************************************************************************/
+/* Uniform sampling of a triangle */
+static INLINE float*
+ssp_ran_triangle_uniform
+ (struct ssp_rng* rng,
+ const float v0[3], const float v1[3], const float v2[3],/*triangle vertices*/
+ float sample[3]) /* Sampled position */
+{
+ double u, v, one_minus_u;
+ int i;
+ ASSERT(rng && v0 && v1 && v2 && sample);
+
+ u = ssp_rng_canonical(rng);
+ v = ssp_rng_canonical(rng);
+ one_minus_u = 1.0 - u;
+
+ FOR_EACH(i, 0, 3) {
+ sample[i] = (float)
+ (v2[i] + one_minus_u * (v0[i] - v2[i]) + (v*u) * (v1[i] - v2[i]));
+ }
+ return sample;
+}
+
+static INLINE float
+ssp_ran_triangle_uniform_pdf
+ (const float v0[3],
+ const float v1[3],
+ const float v2[3])
+{
+ float vec0[3], vec1[3], tmp[3];
+ ASSERT(v0 && v1 && v2);
+
+ f3_sub(vec0, v0, v2);
+ f3_sub(vec1, v1, v2);
+ return 1.f / (f3_len(f3_cross(tmp, vec0, vec1)) * 0.5f);
+}
+
+/*******************************************************************************
* Hemisphere distribution
******************************************************************************/
/* Uniform sampling of an unit hemisphere whose up direction is implicitly the
diff --git a/src/test_ssp_ran_triangle.c b/src/test_ssp_ran_triangle.c
@@ -0,0 +1,96 @@
+/* Copyright (C) |Meso|Star> 2015 (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 "ssp.h"
+#include "test_ssp_utils.h"
+
+#include <rsys/float4.h>
+
+#define NSAMPS 128
+
+int
+main(int argc, char** argv)
+{
+ struct ssp_rng* rng;
+ struct mem_allocator allocator;
+ float samps[NSAMPS][3];
+ float A[3], B[3], C[3];
+ float v0[3], v1[3], v2[3], v3[3], v4[3], v5[3];
+ float plane[4];
+ int i;
+ (void)argc, (void)argv;
+
+ mem_init_proxy_allocator(&allocator, &mem_default_allocator);
+
+ CHECK(ssp_rng_create(&allocator, &ssp_rng_mt19937_64, &rng), RES_OK);
+
+ FOR_EACH(i, 0, 3) {
+ A[i] = (float)ssp_rng_uniform_double(rng, 0.0, 1.0);
+ B[i] = (float)ssp_rng_uniform_double(rng, 0.0, 1.0);
+ C[i] = (float)ssp_rng_uniform_double(rng, 0.0, 1.0);
+ }
+
+ f3_sub(v0, B, A);
+ f3_sub(v1, C, A);
+ f3_sub(v2, C, B);
+ f3_minus(v3, v0);
+ f3_minus(v4, v1);
+ f3_minus(v5, v2);
+ f3_cross(plane, v0, v1);
+ plane[3] = -f3_dot(plane, C);
+
+ FOR_EACH(i, 0, NSAMPS) {
+ float tmp0[3], tmp1[3];
+ float dot = 0.f;
+ float area = 0.f;
+
+ CHECK(ssp_ran_triangle_uniform(rng, A, B, C, samps[i]), samps[i]);
+ CHECK(eq_epsf(f3_dot(plane, samps[i]), -plane[3], 1.e-6f), 1);
+
+ f3_sub(tmp0, samps[i], A);
+ dot = f3_dot(f3_cross(tmp0, tmp0, v0), f3_cross(tmp1, v1, v0 ));
+ CHECK(signf(dot), 1.f );
+ f3_sub(tmp0, samps[i], B);
+ dot = f3_dot(f3_cross(tmp0, tmp0, v2), f3_cross(tmp1, v3, v2));
+ CHECK(signf(dot), 1.f);
+ f3_sub(tmp0, samps[i], C);
+ dot = f3_dot(f3_cross(tmp0, tmp0, v4), f3_cross(tmp1, v5, v4));
+ CHECK(signf(dot), 1.f);
+
+ area = f3_len(tmp1) * 0.5f;
+ CHECK(eq_epsf(1.f / area, ssp_ran_triangle_uniform_pdf(A, B, C), 1.e-6f), 1);
+ }
+
+ ssp_rng_ref_put(rng);
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHECK(mem_allocated_size(), 0);
+
+ return 0;
+}
+