star-vx

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

commit 887b3e5faa0f439eb5b3eb57f15364819fb2a25a
parent 885b0d3698d20224bd88a1bbbea9658265c5f57f
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri,  4 May 2018 15:08:29 +0200

Rename the svx_octree_for_each_leaf function

Make it generic to the tree dimension. Its name is thus
svx_tree_for_each_leaf and can be invoke on both octree and binary tree.

Diffstat:
Mcmake/CMakeLists.txt | 4+++-
Msrc/svx.h | 2+-
Msrc/svx_bintree.c | 1+
Msrc/svx_octree.c | 3+++
Msrc/svx_tree.c | 22++++++++++++++++++++++
Asrc/svx_tree_generic_func.h | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_svx_octree.c | 2+-
Msrc/test_svx_utils.h | 6+++---
8 files changed, 174 insertions(+), 6 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -51,7 +51,9 @@ set(SSOL_FILES_INC svx_buffer.h svx_device.h svx_octree.h - svx_tree.h) + svx_tree.h + svx_tree_builder.h + svx_tree_generic_func.h) set(SSOL_FILES_INC_API svx.h) diff --git a/src/svx.h b/src/svx.h @@ -236,7 +236,7 @@ svx_tree_get_desc struct svx_tree_desc* desc); SVX_API res_T -svx_octree_for_each_leaf +svx_tree_for_each_leaf (struct svx_tree* tree, svx_leaf_function_T functor, void* context); /* Client data sent as the last argument of the functor */ diff --git a/src/svx_bintree.c b/src/svx_bintree.c @@ -135,3 +135,4 @@ error: goto exit; } + diff --git a/src/svx_octree.c b/src/svx_octree.c @@ -18,6 +18,7 @@ #include "svx_device.h" #include "svx_tree.h" #include "svx_tree_builder.h" +#include "svx_tree_generic_func.h" #include <rsys/double3.h> #include <rsys/mem_allocator.h> @@ -168,6 +169,7 @@ error: goto exit; } +#if 0 res_T svx_octree_for_each_leaf (struct svx_tree* oct, svx_leaf_function_T func, void* ctx) @@ -250,6 +252,7 @@ svx_octree_for_each_leaf return RES_OK; } +#endif res_T svx_octree_at diff --git a/src/svx_tree.c b/src/svx_tree.c @@ -15,10 +15,19 @@ #include "svx_device.h" #include "svx_tree.h" +#include "svx_tree_generic_func.h" #include <rsys/double3.h> #include <rsys/mem_allocator.h> +/* Generate the generic binary functions */ +#define TREE_DIMENSION 1 +#include "svx_tree_generic_func.h" + +/* Generate the generic octree functions */ +#define TREE_DIMENSION 3 +#include "svx_tree_generic_func.h" + /******************************************************************************* * Helper function ******************************************************************************/ @@ -69,6 +78,19 @@ svx_tree_get_desc return RES_OK; } +res_T +svx_tree_for_each_leaf(struct svx_tree* tree, svx_leaf_function_T func, void* ctx) +{ + res_T res = RES_OK; + if(!tree || !func) return RES_BAD_ARG; + switch(tree->type) { + case SVX_BINTREE: res = bintree_for_each_leaf(tree, func, ctx); break; + case SVX_OCTREE: res = octree_for_each_leaf(tree, func, ctx); break; + default: FATAL("Unreachable code.\n"); break; + } + return res; +} + /******************************************************************************* * Local functions ******************************************************************************/ diff --git a/src/svx_tree_generic_func.h b/src/svx_tree_generic_func.h @@ -0,0 +1,140 @@ +/* Copyright (C) 2018 Université Paul Sabatier, |Meso|Star> + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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 TREE_DIMENSION + +#ifndef SVX_TREE_GENERIC_FUNC_H +#define SVX_TREE_GENERIC_FUNC_H + +#include "svx.h" +#include "svx_tree.h" +#include "svx_tree_builder.h" /* For the TREE_DEPTH_MAX constant */ + +#endif /* SVX_TREE_GENERIC_FUNC_H */ +#else /*!TREE_DIMENSION */ + +#ifdef COMPILER_GCC + #pragma GCC push_options + #pragma GCC optimize("unroll-loops") +#endif + +#if TREE_DIMENSION == 1 + #define TREE_FUNC(Func) CONCAT(bintree_, Func) + #define SVX_TREE_TYPE SVX_BINTREE +#elif TREE_DIMENSION == 3 + #define TREE_FUNC(Func) CONCAT(octree_, Func) + #define SVX_TREE_TYPE SVX_OCTREE +#else + #error "Invalid TREE_DIMENSION value" +#endif + +#define NCHILDREN BIT(TREE_DIMENSION) + +static res_T +TREE_FUNC(for_each_leaf) + (struct svx_tree* oct, svx_leaf_function_T func, void* ctx) +{ + struct stack_entry { + struct buffer_index inode; + size_t depth; + double low[TREE_DIMENSION]; + double hsz[TREE_DIMENSION]; /* Half size */ + } stack[TREE_DEPTH_MAX*NCHILDREN]; + int istack; + struct svx_voxel leaf = SVX_VOXEL_NULL; + size_t ileaf = 0; + int i; + + if(!oct || !func || oct->type != SVX_TREE_TYPE) return RES_BAD_ARG; + + stack[0].depth = 0; + stack[0].inode = oct->root; + + FOR_EACH(i, 0, TREE_DIMENSION) { + stack[0].low[i] = oct->tree_low[oct->frame[i]]; + stack[0].hsz[i] = + (oct->tree_upp[oct->frame[i]] - oct->tree_low[oct->frame[i]])*0.5; + } + istack = 1; + + do { + const struct stack_entry entry = stack[--istack]; + const size_t child_depth = entry.depth + 1; + double child_hsz[TREE_DIMENSION]; + double mid[TREE_DIMENSION]; /* Middle point of the current node */ + struct buffer_xnode* node; + int ichild; + + node = buffer_get_node(&oct->buffer, entry.inode); + + FOR_EACH(i, 0, TREE_DIMENSION) { + mid[i] = entry.low[i] + entry.hsz[i]; + child_hsz[i] = entry.hsz[i] * 0.5; + } + + FOR_EACH(ichild, 0, NCHILDREN) { + const uint8_t ichild_flag = (uint8_t)BIT(ichild); + double low[TREE_DIMENSION]; + + if((node->is_valid & ichild_flag) == 0) continue; /* Empty node */ + + FOR_EACH(i, 0, TREE_DIMENSION) { + low[i] = ichild & BIT(TREE_DIMENSION-1-i) ? mid[i] : entry.low[i]; + } + + if(node->is_leaf & ichild_flag) { + struct buffer_index iattr; + + iattr = buffer_get_child_attr_index + (&oct->buffer, entry.inode, ichild); + + FOR_EACH(i, 0, TREE_DIMENSION) { + leaf.lower[oct->frame[i]] = low[i]; + leaf.upper[oct->frame[i]] = low[i] + entry.hsz[i]; + } + leaf.data = buffer_get_attr(&oct->buffer, iattr); + leaf.id = buffer_absolute_attr_index(&oct->buffer, iattr); + leaf.depth = child_depth; + leaf.is_leaf = 1; + + func(&leaf, ileaf++, ctx); + } else { + struct stack_entry* top = stack + istack; + + top->inode = buffer_get_child_node_index + (&oct->buffer, entry.inode, ichild); + FOR_EACH(i, 0, TREE_DIMENSION) { + top->low[i] = low[i]; + top->hsz[i] = child_hsz[i]; + } + top->depth = child_depth; + ++istack; + } + } + } while(istack); + + return RES_OK; +} + +#undef TREE_FUNC +#undef SVX_TREE_TYPE +#undef TREE_DIMENSION +#undef NCHILDREN + +#ifdef COMPILER_GCC + #pragma GCC pop_options +#endif + +#endif /* !TREE_DIMENSION */ diff --git a/src/test_svx_octree.c b/src/test_svx_octree.c @@ -337,7 +337,7 @@ main(int argc, char** argv) CHK(NEW_SCN(dev, low, upp, nvxls, &voxdesc, &oct) == RES_OK); - CHK(svx_octree_for_each_leaf(oct, check_leaves, &ctx) == RES_OK); + CHK(svx_tree_for_each_leaf(oct, check_leaves, &ctx) == RES_OK); CHK(svx_tree_get_desc(NULL, &tree_desc) == RES_BAD_ARG); CHK(svx_tree_get_desc(oct, NULL) == RES_BAD_ARG); diff --git a/src/test_svx_utils.h b/src/test_svx_utils.h @@ -107,12 +107,12 @@ dump_data CHK(svx_tree_get_desc(tree, &desc) == RES_OK); CHK(desc.type == SVX_OCTREE); /* FIXME currently only octree are supported */ fprintf(stream, "POINTS %lu float\n", (unsigned long)(desc.nleaves* 8)); - CHK(svx_octree_for_each_leaf(tree, write_leaf_vertices, stream) == RES_OK); + CHK(svx_tree_for_each_leaf(tree, write_leaf_vertices, stream) == RES_OK); fprintf(stream, "CELLS %lu %lu\n", (unsigned long)desc.nleaves, (unsigned long)(desc.nleaves*(8/*#verts per leaf*/ + 1/*1st field of a cell*/))); - CHK(svx_octree_for_each_leaf(tree, write_leaf_cells, stream) == RES_OK); + CHK(svx_tree_for_each_leaf(tree, write_leaf_cells, stream) == RES_OK); fprintf(stream, "CELL_TYPES %lu\n", (unsigned long)desc.nleaves); FOR_EACH(ileaf, 0, desc.nleaves) fprintf(stream, "11\n"); @@ -120,7 +120,7 @@ dump_data fprintf(stream, "CELL_DATA %lu\n", (unsigned long)desc.nleaves); fprintf(stream, "SCALARS K %s %lu\n", data_type_to_string(type), numcomps); fprintf(stream, "LOOKUP_TABLE default\n"); - CHK(svx_octree_for_each_leaf(tree, write_leaf_data, stream) == RES_OK); + CHK(svx_tree_for_each_leaf(tree, write_leaf_data, stream) == RES_OK); }