star-vx

Structuring voxels for ray-tracing
git clone git://git.meso-star.fr/star-vx.git
Log | Files | Refs | README | LICENSE

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:
MREADME.md | 10+++++++++-
Mcmake/CMakeLists.txt | 6+++---
Msrc/svx.h | 10++++++++--
Msrc/svx_bintree.c | 4++--
Msrc/svx_bintree_trace_ray.c | 28++++++++++++++++++++++++++--
Msrc/svx_buffer.c | 2+-
Msrc/svx_buffer.h | 2+-
Msrc/svx_c.h | 45+--------------------------------------------
Msrc/svx_device.c | 2+-
Msrc/svx_device.h | 2+-
Msrc/svx_octree.c | 4++--
Msrc/svx_octree_trace_ray.c | 33++++++++++++++++++++++++++++++---
Msrc/svx_tree.c | 2+-
Msrc/svx_tree.h | 2+-
Msrc/svx_tree_builder.h | 3++-
Msrc/svx_tree_generic_func.h | 2+-
Msrc/test_svx_bintree.c | 8+++++---
Msrc/test_svx_bintree_trace_ray.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/test_svx_device.c | 2+-
Msrc/test_svx_octree.c | 21+++++++++++++++------
Msrc/test_svx_octree_trace_ray.c | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/test_svx_utils.h | 8++++----
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 */