commit 979c97d6c42619c1cdf4a237ea8cef9dc4139012
parent 70ea012ad35a3a124fd8b654f87507da7f2eb22b
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 16 Jun 2021 09:55:59 +0200
Merge branch 'release_0.2'
Diffstat:
22 files changed, 240 insertions(+), 97 deletions(-)
diff --git a/README.md b/README.md
@@ -40,6 +40,14 @@ informations on CMake.
## Release notes
+### Version 0.2
+
+- Update the profile of the functors invoked on node traversal: the ray
+ origin, direction and range are now provided as input arguments.
+- Force the invocation of the challenge and filter functors on the root node.
+ Previously these functors were not called on the root;the challenging and
+ filtering was starting on its children.
+
### Version 0.1
- Add the `svx_tree_write` and the `svx_tree_create_from_stream` functions used
@@ -47,7 +55,7 @@ informations on CMake.
## License
-Copyright (C) 2018, 2020 [|Meso|Star>](https://www.meso-star.com)
+Copyright (C) 2018, 2020, 2021 [|Meso|Star>](https://www.meso-star.com)
(<contact@meso-star.com>). Copyright (C) 2018 Université Paul Sabatier
(<contact-edstar@laplace.univ-tlse.fr>). Star-VoXel is free software released
under the GPL v3+ license: GNU GPL version 3 or later. You are welcome to
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -1,5 +1,5 @@
+# Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
# Copyright (C) 2018 Université Paul Sabatier
-# Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@ option(NO_TEST "Do not build tests" OFF)
# Check dependencies
################################################################################
find_package(RCMake 0.3 REQUIRED)
-find_package(RSys 0.6 REQUIRED)
+find_package(RSys 0.12 REQUIRED)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR})
include(rcmake)
@@ -37,7 +37,7 @@ include_directories(${RSys_INCLUDE_DIR})
# 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})
diff --git a/src/svx.h b/src/svx.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
@@ -74,10 +74,13 @@ static const struct svx_voxel SVX_VOXEL_NULL = SVX_VOXEL_NULL__;
/* Descriptor of a voxel */
struct svx_voxel_desc {
- /* Retrieve the data of the voxels*/
+ /* Retrieve the data of the voxels. Star-VoXel ensures that the Voxels are
+ * accessed according to the morton order where Z vary priorly to Y and Y
+ * priorly to X. */
void
(*get)
(const size_t xyz[3], /* Voxel coordinate in voxel space */
+ const uint64_t mcode, /* Morton code of the voxel */
void* dst, /* Where to store data */
void* ctx); /* Pointer toward user data */
@@ -158,6 +161,9 @@ typedef void
typedef int
(*svx_hit_challenge_T)
(const struct svx_hit* hit,
+ const double ray_org[3],
+ const double ray_dir[3],
+ const double ray_range[2],
void* context);
/* Hit filter function data type. The caller can define a function of this type
diff --git a/src/svx_bintree.c b/src/svx_bintree.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
@@ -102,7 +102,7 @@ svx_bintree_create
/* Retrieve the voxel data from the caller */
xyz[axis] = ivox;
- desc->get(xyz, vox.data, desc->context);
+ desc->get(xyz, ivox, vox.data, desc->context);
vox.mcode = ivox;
/* Register the voxel against the bintree */
diff --git a/src/svx_bintree_trace_ray.c b/src/svx_bintree_trace_ray.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
@@ -147,6 +147,29 @@ bintree_trace_ray
pos_min = MMAX(dir * ray_range[0] + org, 0);
pos_max = MMIN(dir * ray_range[1] + org, 1);
+ /* Challenge the root node */
+ if(challenge) {
+ struct svx_hit hit_root;
+ const double t_min = null_dir ? ray_range[0] : (pos_min - org) * ts;
+ const double t_max = null_dir ? ray_range[1] : (pos_max - org) * ts;
+ struct buffer_index iattr_dummy = buffer_get_child_attr_index
+ (&btree->buffer, btree->root, 0/*arbitrarly child index*/);
+
+ /* Use the regular setup_hit procedure by providing a dummy attribute
+ * index, and then overwrite the voxel data with the root one */
+ setup_hit(btree, iattr_dummy, t_min, t_max, 0.f/*low*/, 1.f/*scale_exp2*/,
+ 0/*depth*/, 0/*is_leaf*/, flip, &hit_root);
+ hit_root.voxel.data = btree->root_attr;
+
+ if(challenge(&hit_root, ray_org, ray_dir, ray_range, context)) {
+ if(!filter /* By default, i.e. with no filter, stop the traversal */
+ || !filter(&hit_root, ray_org, ray_dir, ray_range, context)) {
+ *hit = hit_root;
+ return RES_OK; /* Do not traverse the binary tree */
+ }
+ }
+ }
+
/* Define the first traversed child and set its lower bound */
if(pos_min <= 0.5) {
/* Note that we use less than or *equal* in the previous test to be
@@ -187,7 +210,8 @@ bintree_trace_ray
setup_hit(btree, iattr, t_min, t_max, low, scale_exp2, depth, is_leaf,
flip, &hit_tmp);
- if(is_leaf || challenge(&hit_tmp, context)) {
+ if(is_leaf
+ || challenge(&hit_tmp, ray_org, ray_dir, ray_range, context)) {
go_deeper = 0;
/* Stop the traversal if no filter is defined or if the filter
* function returns 0 */
diff --git a/src/svx_buffer.c b/src/svx_buffer.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
diff --git a/src/svx_buffer.h b/src/svx_buffer.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
diff --git a/src/svx_c.h b/src/svx_c.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
@@ -20,32 +20,6 @@
#include "svx.h"
#include <rsys/rsys.h>
-static INLINE uint64_t
-morton3D_encode_u21(const uint32_t u21)
-{
- uint64_t u64 = u21 & ((1<<21) - 1);
- ASSERT(u21 <= ((1 << 21) - 1));
- u64 = (u64 | (u64 << 32)) & 0xFFFF00000000FFFF;
- u64 = (u64 | (u64 << 16)) & 0x00FF0000FF0000FF;
- u64 = (u64 | (u64 << 8)) & 0xF00F00F00F00F00F;
- u64 = (u64 | (u64 << 4)) & 0x30C30C30C30C30C3;
- u64 = (u64 | (u64 << 2)) & 0x9249249249249249;
- return u64;
-}
-
-static INLINE uint32_t
-morton3D_decode_u21(const uint64_t u64)
-{
- uint64_t tmp = (u64 & 0x9249249249249249);
- tmp = (tmp | (tmp >> 2)) & 0x30C30C30C30C30C3;
- tmp = (tmp | (tmp >> 4)) & 0xF00F00F00F00F00F;
- tmp = (tmp | (tmp >> 8)) & 0x00FF0000FF0000FF;
- tmp = (tmp | (tmp >> 16)) & 0xFFFF00000000FFFF;
- tmp = (tmp | (tmp >> 32)) & 0x00000000FFFFFFFF;
- ASSERT(tmp <= ((1<<21)-1));
- return (uint32_t)tmp;
-}
-
/* Count the number of bits set to 1 */
static FINLINE int
popcount(const uint8_t x)
@@ -56,23 +30,6 @@ popcount(const uint8_t x)
return (n * 0x0101) >> 8;
}
-static INLINE uint64_t
-morton_xyz_encode_u21(const uint32_t xyz[3])
-{
- return (morton3D_encode_u21(xyz[0]) << 2)
- | (morton3D_encode_u21(xyz[1]) << 1)
- | (morton3D_encode_u21(xyz[2]) << 0);
-}
-
-static INLINE void
-morton_xyz_decode_u21(const uint64_t code, uint32_t xyz[3])
-{
- ASSERT(xyz && code < ((1ull << 63)-1));
- xyz[0] = (uint32_t)morton3D_decode_u21(code >> 2);
- xyz[1] = (uint32_t)morton3D_decode_u21(code >> 1);
- xyz[2] = (uint32_t)morton3D_decode_u21(code >> 0);
-}
-
static INLINE int
check_svx_voxel_desc(const struct svx_voxel_desc* desc)
{
diff --git a/src/svx_device.c b/src/svx_device.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
diff --git a/src/svx_device.h b/src/svx_device.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
diff --git a/src/svx_octree.c b/src/svx_octree.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
@@ -136,7 +136,7 @@ svx_octree_create
xyz[0] = (size_t)ui3[0];
xyz[1] = (size_t)ui3[1];
xyz[2] = (size_t)ui3[2];
- desc->get(xyz, vox.data, desc->context);
+ desc->get(xyz, mcode, vox.data, desc->context);
vox.mcode = mcode;
/* Register the voxel against the octree */
diff --git a/src/svx_octree_trace_ray.c b/src/svx_octree_trace_ray.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
@@ -206,7 +206,33 @@ trace_ray
t_max = MMIN(ray->range[1], t_max);
if(t_min >= t_max) return RES_OK; /* No intersection */
- /* Traverrsal initialisation */
+ /* Challenge the root */
+ if(challenge) {
+ struct svx_hit hit_root;
+ struct buffer_index iattr_dummy = buffer_get_child_attr_index
+ (&oct->buffer, oct->root, 0/*arbitrarly child index*/);
+
+ /* Lower left corner of the root node in the [1, 2]^3 space */
+ corner[0] = 1.f;
+ corner[1] = 1.f;
+ corner[2] = 1.f;
+
+ /* Use the regular setup_hit procedure by providing a dummy attribute
+ * index, and then overwrite the voxel data with the root one */
+ setup_hit(oct, iattr_dummy, t_min, t_max, corner, 1.f/*scale_exp2*/,
+ 0/*depth*/, 0/*is_leaf*/, ray->octant_mask, &hit_root);
+ hit_root.voxel.data = oct->root_attr;
+
+ if(challenge(&hit_root, ray->orgws, ray->dirws, ray->range, context)) {
+ if(!filter /* By default, i.e. with no filter, stop the traversal */
+ || !filter(&hit_root, ray->orgws, ray->dirws, ray->range, context)) {
+ *hit = hit_root;
+ return RES_OK; /* Do not traverse the octree */
+ }
+ }
+ }
+
+ /* Traversal initialisation */
inode = oct->root;
scale_exp2 = 0.5f;
scale = SCALE_MAX - 1;
@@ -255,7 +281,8 @@ trace_ray
setup_hit(oct, iattr, t_min, t_max_child, corner, scale_exp2, depth,
is_leaf, ray->octant_mask, &hit_tmp);
- if(is_leaf || challenge(&hit_tmp, context)) {
+ if(is_leaf
+ || challenge(&hit_tmp, ray->orgws, ray->dirws, ray->range, context)) {
go_deeper = 0;
/* Stop the traversal if no filter is defined or if the filter
* function returns 0 */
diff --git a/src/svx_tree.c b/src/svx_tree.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
diff --git a/src/svx_tree.h b/src/svx_tree.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
diff --git a/src/svx_tree_builder.h b/src/svx_tree_builder.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
@@ -21,6 +21,7 @@
#include "svx_buffer.h"
#include <rsys/double3.h>
+#include <rsys/morton.h>
#define TREE_DEPTH_MAX 16 /* Maximum depth of a tree */
diff --git a/src/svx_tree_generic_func.h b/src/svx_tree_generic_func.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
diff --git a/src/test_svx_bintree.c b/src/test_svx_bintree.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
@@ -52,12 +52,13 @@ struct build_context {
static void
-get(const size_t xyz[3], void* dst, void* ctx)
+get(const size_t xyz[3], const uint64_t mcode, void* dst, void* ctx)
{
double* val = dst;
CHK(xyz != NULL);
CHK(val != NULL);
CHK((intptr_t)ctx == 0xDECAFBAD);
+ CHK(mcode == xyz[AXIS]);
*val = (double)xyz[AXIS];
}
@@ -137,11 +138,12 @@ check_leaves
}
static void
-get_aabb(const size_t xyz[3], void* dst, void* ctx)
+get_aabb(const size_t xyz[3], const uint64_t mcode, void* dst, void* ctx)
{
const struct build_context* build_ctx = ctx;
struct aabb* aabb = dst;
+ CHK(mcode == xyz[AXIS]);
d3_splat(aabb->lower,-INF);
d3_splat(aabb->upper, INF);
aabb->lower[AXIS] =
diff --git a/src/test_svx_bintree_trace_ray.c b/src/test_svx_bintree_trace_ray.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
@@ -39,7 +39,7 @@ rand_canonic(void)
}
static void
-voxel_get(const size_t xyz[3], void* dst, void* ctx)
+voxel_get(const size_t xyz[3], const uint64_t mcode, void* dst, void* ctx)
{
const struct scene* scn = ctx;
char* val = dst;
@@ -50,6 +50,7 @@ voxel_get(const size_t xyz[3], void* dst, void* ctx)
CHK(xyz != NULL);
CHK(dst != NULL);
CHK(ctx != NULL);
+ CHK(mcode == xyz[scn->axis]);
/* Compute the range of the voxel */
low = (double)xyz[scn->axis] * scn->vxsz + scn->origin;
@@ -102,15 +103,49 @@ voxels_challenge_merge
}
static int
-hit_challenge(const struct svx_hit* hit, void* context)
+hit_challenge
+ (const struct svx_hit* hit,
+ const double ray_org[3],
+ const double ray_dir[3],
+ const double ray_range[2],
+ void* context)
{
(void)context;
- CHK(hit);
+ CHK(hit && ray_org && ray_dir && ray_range);
CHK(!SVX_HIT_NONE(hit));
return 1;
}
static int
+hit_challenge_root
+ (const struct svx_hit* hit,
+ const double ray_org[3],
+ const double ray_dir[3],
+ const double ray_range[2],
+ void* context)
+{
+ (void)hit, (void)ray_org, (void)ray_dir, (void)ray_range, (void)context;
+ return hit->voxel.depth == 0;
+}
+
+static int
+hit_challenge_pass_through
+ (const struct svx_hit* hit,
+ const double ray_org[3],
+ const double ray_dir[3],
+ const double ray_range[2],
+ void* context)
+{
+ const struct ray* ray = context;
+ CHK(hit && ray_org && ray_dir && ray_range && context);
+ CHK(!SVX_HIT_NONE(hit));
+ CHK(d3_eq(ray->org, ray_org));
+ CHK(d3_eq(ray->dir, ray_dir));
+ CHK(d2_eq(ray->range, ray_range));
+ return 0;
+}
+
+static int
hit_filter
(const struct svx_hit* hit,
const double ray_org[3],
@@ -186,8 +221,8 @@ draw_image(struct image* img, struct svx_tree* btree)
pix[0] = (double)ix / (double)width;
camera_ray(&cam, pix, &r);
- CHK(svx_tree_trace_ray
- (btree, r.org, r.dir, r.range, NULL, hit_filter, &r, &hit) == RES_OK);
+ CHK(svx_tree_trace_ray(btree, r.org, r.dir, r.range,
+ hit_challenge_pass_through, hit_filter, &r, &hit) == RES_OK);
pixels[ipix+0] = 0;
pixels[ipix+1] = 0;
pixels[ipix+2] = 0;
@@ -331,7 +366,8 @@ main(int argc, char** argv)
CHK(eq_eps(hit.distance[1], (hit.voxel.lower[0]-r.org[0])/r.dir[0], 1.e-6));
/* Use filter function to discard leaves with a value == 0 */
- CHK(RT(btree, r.org, r.dir, r.range, NULL, hit_filter, &r, &hit) == RES_OK);
+ CHK(RT(btree, r.org, r.dir, r.range, hit_challenge_pass_through, hit_filter,
+ &r, &hit) == RES_OK);
CHK(!SVX_HIT_NONE(&hit));
CHK(hit.voxel.is_leaf == 1);
CHK(hit.voxel.depth == 5);
@@ -426,7 +462,7 @@ main(int argc, char** argv)
CHK(*(char*)hit2.voxel.data == 1);
CHK(hit2.voxel.depth < 3);
- /* Stil lcheck a ray with null dir along the tree axis */
+ /* Still check a ray with null dir along the tree axis */
d3(r.org, -0.51, 31, 41);
CHK(RT(btree, r.org, r.dir, r.range, NULL, NULL, NULL, &hit) == RES_OK);
CHK(eq_eps(hit.distance[0], r.range[0], 1.e-6));
@@ -448,6 +484,24 @@ main(int argc, char** argv)
CHK(SVX_HIT_NONE(&hit));
CHK(accum == 1);
+ /* Check the root node challenge */
+ d3(r.org, 1.01, 1234, 10);
+ d3_normalize(r.dir, d3(r.dir, -1, -1, -1));
+ CHK(RT(btree, r.org, r.dir, r.range, hit_challenge_root, NULL, NULL, &hit)
+ == RES_OK);
+ CHK(!SVX_HIT_NONE(&hit));
+ CHK(hit.voxel.lower[0] == -1);
+ CHK(hit.voxel.upper[0] == 1);
+ CHK(IS_INF(hit.voxel.lower[1]));
+ CHK(IS_INF(hit.voxel.upper[1]));
+ CHK(IS_INF(hit.voxel.lower[2]));
+ CHK(IS_INF(hit.voxel.upper[2]));
+ CHK(hit.voxel.depth == 0);
+ CHK(hit.voxel.is_leaf == 0);
+ CHK(*((char*)hit.voxel.data) == 1);
+ CHK(eq_eps(hit.distance[0], (hit.voxel.upper[0]-r.org[0])/r.dir[0], 1.e-4));
+ CHK(eq_eps(hit.distance[1], (hit.voxel.lower[0]-r.org[0])/r.dir[0], 1.e-4));
+
image_init(NULL, &img);
image_init(NULL, &img2);
draw_image(&img, btree);
diff --git a/src/test_svx_device.c b/src/test_svx_device.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
diff --git a/src/test_svx_octree.c b/src/test_svx_octree.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
@@ -15,10 +15,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "svx.h"
-#include "svx_c.h" /* For morton_xyz_encode_u21 */
#include "test_svx_utils.h"
#include <rsys/double3.h>
+#include <rsys/morton.h>
#include <string.h>
@@ -101,10 +101,9 @@ keep_max(void* dst, const void* voxels[], const size_t nvoxels, void* ctx)
}
static void
-get(const size_t xyz[3], void* dst, void* ctx)
+get(const size_t xyz[3], const uint64_t mcode, void* dst, void* ctx)
{
uint32_t ui3[3];
- uint64_t mcode;
double* val = dst;
CHK(xyz != NULL);
CHK(val != NULL);
@@ -114,7 +113,11 @@ get(const size_t xyz[3], void* dst, void* ctx)
ui3[1] = (uint32_t)xyz[1];
ui3[2] = (uint32_t)xyz[2];
- mcode = morton_xyz_encode_u21(ui3);
+ CHK(mcode == morton_xyz_encode_u21(ui3));
+ CHK(mcode ==
+ ( morton3D_encode_u21(ui3[0]) << 2
+ | morton3D_encode_u21(ui3[1]) << 1
+ | morton3D_encode_u21(ui3[2]) << 0));
*val = (double)mcode;
}
@@ -193,14 +196,20 @@ max_lod
}
static void
-get_aabb(const size_t xyz[3], void* dst, void* ctx)
+get_aabb(const size_t xyz[3], const uint64_t mcode, void* dst, void* ctx)
{
const struct build_context* build_ctx = ctx;
struct aabb* aabb = dst;
+ uint32_t ui3[3];
aabb->lower[0] = (double)xyz[0] * build_ctx->voxsz[0] + build_ctx->lower[0];
aabb->lower[1] = (double)xyz[1] * build_ctx->voxsz[1] + build_ctx->lower[1];
aabb->lower[2] = (double)xyz[2] * build_ctx->voxsz[2] + build_ctx->lower[2];
+
+ ui3[0] = (uint32_t)xyz[0];
+ ui3[1] = (uint32_t)xyz[1];
+ ui3[2] = (uint32_t)xyz[2];
+ CHK(mcode == morton_xyz_encode_u21(ui3));
d3_add(aabb->upper, aabb->lower, build_ctx->voxsz);
aabb->depth = build_ctx->max_depth;
}
diff --git a/src/test_svx_octree_trace_ray.c b/src/test_svx_octree_trace_ray.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
@@ -26,6 +26,7 @@
#include <rsys/double3.h>
#include <rsys/image.h>
#include <rsys/math.h>
+#include <rsys/morton.h>
struct scene {
double origin[3];
@@ -59,12 +60,13 @@ sphere_intersect_aabb
}
static void
-voxel_get(const size_t xyz[3], void* dst, void* ctx)
+voxel_get(const size_t xyz[3], const uint64_t mcode, void* dst, void* ctx)
{
const struct scene* scn = ctx;
char* val = dst;
double low[3];
double upp[3];
+ uint32_t ui3[3];
CHK(xyz != NULL);
CHK(dst != NULL);
CHK(ctx != NULL);
@@ -77,6 +79,11 @@ voxel_get(const size_t xyz[3], void* dst, void* ctx)
upp[1] = low[1] + scn->vxsz[1];
upp[2] = low[2] + scn->vxsz[2];
+ ui3[0] = (uint32_t)xyz[0];
+ ui3[1] = (uint32_t)xyz[1];
+ ui3[2] = (uint32_t)xyz[2];
+ CHK(mcode == morton_xyz_encode_u21(ui3));
+
/* Binary octree, i.e. it stores if the voxel intersect the sphere or not */
*val = sphere_intersect_aabb(scn->sphere_pos, scn->sphere_radius, low, upp);
}
@@ -180,14 +187,48 @@ hit_filter3
}
static int
-hit_challenge(const struct svx_hit* hit, void* context)
+hit_challenge
+ (const struct svx_hit* hit,
+ const double ray_org[3],
+ const double ray_dir[3],
+ const double ray_range[2],
+ void* context)
{
(void)context;
- CHK(hit);
+ CHK(hit && ray_org && ray_dir && ray_range);
CHK(!SVX_HIT_NONE(hit));
return 1;
}
+static int
+hit_challenge_pass_through
+ (const struct svx_hit* hit,
+ const double ray_org[3],
+ const double ray_dir[3],
+ const double ray_range[2],
+ void* context)
+{
+ const struct ray* ray = context;
+ CHK(hit && ray_org && ray_dir && ray_range);
+ CHK(!SVX_HIT_NONE(hit));
+ CHK(d3_eq(ray->org, ray_org));
+ CHK(d3_eq(ray->dir, ray_dir));
+ CHK(d2_eq(ray->range, ray_range));
+ return 0;
+}
+
+static int
+hit_challenge_root
+ (const struct svx_hit* hit,
+ const double ray_org[3],
+ const double ray_dir[3],
+ const double ray_range[2],
+ void* context)
+{
+ (void)hit, (void)ray_org, (void)ray_dir, (void)ray_range, (void)context;
+ return hit->voxel.depth == 0;
+}
+
static void
draw_image(struct image* img, struct svx_tree* oct, const struct scene* scn)
{
@@ -220,8 +261,8 @@ draw_image(struct image* img, struct svx_tree* oct, const struct scene* scn)
pix[0] = (double)ix / (double)width;
camera_ray(&cam, pix, &r);
- CHK(svx_tree_trace_ray
- (oct, r.org, r.dir, r.range, NULL, hit_filter, &r, &hit) == RES_OK);
+ CHK(svx_tree_trace_ray(oct, r.org, r.dir, r.range,
+ hit_challenge_pass_through, hit_filter, &r, &hit) == RES_OK);
if(SVX_HIT_NONE(&hit)) {
pixels[ipix+0] = 0;
pixels[ipix+1] = 0;
@@ -336,7 +377,8 @@ main(int argc, char** argv)
CHK(eq_eps(hit.distance[0], hit2.distance[0], 1.e-6));
/* Use filter function to discard leaves with a value == 0 */
- CHK(RT(oct, r.org, r.dir, r.range, NULL, hit_filter, &r, &hit) == RES_OK);
+ CHK(RT(oct, r.org, r.dir, r.range, hit_challenge_pass_through, hit_filter,
+ &r, &hit) == RES_OK);
CHK(!SVX_HIT_NONE(&hit));
CHK(eq_eps(hit.distance[0], hit.voxel.lower[1] - r.org[1], 1.e-6));
CHK(eq_eps(hit.distance[1], hit.voxel.upper[1] - r.org[1], 1.e-6));
@@ -345,7 +387,8 @@ main(int argc, char** argv)
/* Use the ray range to avoid the intersection with the closest voxel */
r.range[1] = nextafter(hit.distance[0], -1);
- CHK(RT(oct, r.org, r.dir, r.range, NULL, hit_filter, &r, &hit) == RES_OK);
+ CHK(RT(oct, r.org, r.dir, r.range, hit_challenge_pass_through, hit_filter,
+ &r, &hit) == RES_OK);
CHK(SVX_HIT_NONE(&hit));
r.range[1] = INF;
@@ -393,6 +436,18 @@ main(int argc, char** argv)
CHK(SVX_HIT_NONE(&hit));
CHK(accum != 0);
+ /* Check the root node challenge */
+ CHK(RT(oct, r.org, r.dir, r.range, hit_challenge_root, NULL, NULL, &hit)
+ == RES_OK);
+ CHK(!SVX_HIT_NONE(&hit));
+ CHK(d3_eq_eps(hit.voxel.lower, lower, 1.e-6));
+ CHK(d3_eq_eps(hit.voxel.upper, upper, 1.e-6));
+ CHK(hit.voxel.depth == 0);
+ CHK(hit.voxel.is_leaf == 0);
+ CHK(*(char*)hit.voxel.data == 1);
+ CHK(eq_eps(hit.distance[0], hit.voxel.lower[1] - r.org[1], 1.e-6));
+ CHK(eq_eps(hit.distance[1], hit.voxel.upper[1] - r.org[1], 1.e-6));
+
image_init(NULL, &img);
image_init(NULL, &img2);
draw_image(&img, oct, &scn);
diff --git a/src/test_svx_utils.h b/src/test_svx_utils.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2020 |Meso|Star> (contact@meso-star.com)
+/* Copyright (C) 2018, 2020, 2021 |Meso|Star> (contact@meso-star.com)
* Copyright (C) 2018 Université Paul Sabatier
*
* This program is free software: you can redistribute it and/or modify
@@ -14,8 +14,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#ifndef TEST_HTVOX_UTILS_H
-#define TEST_HTVOX_UTILS_H
+#ifndef TEST_SVX_UTILS_H
+#define TEST_SVX_UTILS_H
#include <rsys/double2.h>
#include <rsys/double3.h>
@@ -217,5 +217,5 @@ check_memory_allocator(struct mem_allocator* allocator)
}
}
-#endif /* TEST_HTVOX_UTILS_H */
+#endif /* TEST_SVX_UTILS_H */