star-vx

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

commit 5389b8e84a033951b807f53ec8d276e71bf25962
parent d5d860d7610ab1447e6cc0c769a186a4fd7a5949
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 26 Sep 2018 15:24:06 +0200

Do not submit invalid voxels to the [challenge_]merge functors

Diffstat:
Msrc/svx_tree_builder.h | 40++++++++++++++++++++++++++++------------
Msrc/test_svx_bintree.c | 64+++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/test_svx_octree.c | 81++++++++++++++++++++++++++++++++++++++-----------------------------------------
3 files changed, 108 insertions(+), 77 deletions(-)

diff --git a/src/svx_tree_builder.h b/src/svx_tree_builder.h @@ -169,6 +169,7 @@ XD(stack_setup_node) const uint8_t ichild_flag = (uint8_t)BIT(ichild); struct XD(node)* child = stack->nodes + ichild; int igrandchild; + size_t ngrandchildren = 0; /* #active grand children */ d3_splat(child_low, -INF); FOR_EACH(i, 0, TREE_DIMENSION) { @@ -177,33 +178,41 @@ XD(stack_setup_node) if(ichild & (NCHILDREN >> (1+i))) child_low[iaxis] += child_sz[iaxis]; } + if(!(stack->mask & ichild_flag)) continue; /* Empty child */ + /* Fetch the grandchildren data */ FOR_EACH(igrandchild, 0, NCHILDREN) { struct svx_voxel* vox = &voxels[igrandchild]; + const uint8_t igrandchild_flag = (uint8_t)BIT(igrandchild); + + if(!(child->is_valid & igrandchild_flag)) continue; /* Empty grandchild */ - voxels[igrandchild].data = child->data[igrandchild]; - voxels[igrandchild].depth = node_depth + 2; - voxels[igrandchild].id = SIZE_MAX; - voxels[igrandchild].is_leaf = (child->is_leaf & BIT(igrandchild))!=0; - voxels[igrandchild].data = child->data[igrandchild]; - data[igrandchild] = child->data[igrandchild]; + voxels[ngrandchildren].data = child->data[igrandchild]; + voxels[ngrandchildren].depth = node_depth + 2; + voxels[ngrandchildren].id = SIZE_MAX; + voxels[ngrandchildren].is_leaf = (child->is_leaf & igrandchild_flag)!=0; + voxels[ngrandchildren].data = child->data[igrandchild]; + data[ngrandchildren] = child->data[igrandchild]; d3_splat(vox->lower,-INF); d3_splat(vox->upper, INF); FOR_EACH(i, 0, TREE_DIMENSION) { const int iaxis = frame[i]; + vox->lower[iaxis] = child_low[iaxis]; if(igrandchild & (NCHILDREN >> (1+i))) { vox->lower[iaxis] += grandchild_sz[iaxis]; } vox->upper[iaxis] = vox->lower[iaxis] + grandchild_sz[iaxis]; } + + ++ngrandchildren; } - desc->merge(node->data[ichild], data, NCHILDREN, desc->context); + desc->merge(node->data[ichild], data, ngrandchildren, desc->context); if(child->is_leaf == (BIT(NCHILDREN)-1)/*all active bitmask*/ - && desc->challenge_merge(voxels, NCHILDREN, desc->context)) { - /* The node becomes a leaf : the children does not exist anymore */ + && desc->challenge_merge(voxels, ngrandchildren, desc->context)) { + /* The node becomes a leaf: the children does not exist anymore */ node->is_leaf |= ichild_flag; stack->mask ^= ichild_flag; } @@ -366,6 +375,8 @@ XD(builder_init) FOR_EACH(i, 0, TREE_DIMENSION) { const int iaxis = frame[i]; + bldr->lower[iaxis] = lower[iaxis]; + bldr->upper[iaxis] = upper[iaxis]; bldr->voxsz[iaxis] = (upper[iaxis] - lower[iaxis]) / (double)definition; } @@ -373,7 +384,6 @@ exit: return res; error: goto exit; - } static res_T @@ -490,6 +500,7 @@ XD(builder_finalize) size_t nleaves; int ilvl; int ichild; + size_t nchildren; res_T res = RES_OK; ASSERT(bldr); @@ -547,11 +558,16 @@ XD(builder_finalize) bldr->nleaves += nleaves; /* Setup the root attribs */ + nchildren = 0; ASSERT(bldr->stacks[ilvl].mask == 1); /* Only the root node is active */ FOR_EACH(ichild, 0, NCHILDREN) { - data[ichild] = bldr->stacks[ilvl].nodes[0].data[ichild]; + const int ichild_flag = BIT(ichild); + if(!(bldr->stacks[ilvl].nodes[0].is_valid & ichild_flag)) continue; + + data[nchildren] = bldr->stacks[ilvl].nodes[0].data[ichild]; + ++nchildren; } - bldr->desc->merge(root_data, data, NCHILDREN, bldr->desc->context); + bldr->desc->merge(root_data, data, nchildren, bldr->desc->context); exit: return res; diff --git a/src/test_svx_bintree.c b/src/test_svx_bintree.c @@ -146,6 +146,7 @@ get_aabb(const size_t xyz[3], void* dst, void* ctx) aabb->lower[AXIS] = (double)xyz[AXIS] * build_ctx->voxsz[AXIS] + build_ctx->lower[AXIS]; aabb->upper[AXIS] = aabb->lower[AXIS] + build_ctx->voxsz[AXIS]; + aabb->depth = build_ctx->max_depth; } @@ -153,6 +154,7 @@ static void merge_aabb(void* dst, const void* voxels[], const size_t nvoxels, void* ctx) { const struct build_context* build_ctx = ctx; + double upper[3]; double voxsz[3]; struct aabb* aabb = dst; size_t depth = SIZE_MAX; @@ -169,33 +171,30 @@ merge_aabb(void* dst, const void* voxels[], const size_t nvoxels, void* ctx) const struct aabb* vox_aabb = voxels[i]; if(depth == SIZE_MAX) { depth = vox_aabb->depth; - } else if(vox_aabb->depth != 0) { /* Not invalid */ + } else { /* Not invalid */ CHK(depth == vox_aabb->depth); - aabb->lower[AXIS] = MMIN(vox_aabb->lower[AXIS], aabb->lower[AXIS]); } + aabb->lower[AXIS] = MMIN(vox_aabb->lower[AXIS], aabb->lower[AXIS]); + aabb->upper[AXIS] = MMAX(vox_aabb->upper[AXIS], aabb->upper[AXIS]); } - if(depth == 0) { /* Invalid voxel */ - aabb->lower[AXIS] = 0; - aabb->upper[AXIS] = 0; - aabb->depth = 0; - } else { - double upper[3]; - CHK(build_ctx->max_depth >= depth); - CHK(depth > 0); - aabb->depth = depth - 1; + d3_splat(upper, INF); + d3_splat(voxsz, INF); - i = build_ctx->max_depth - aabb->depth; - voxsz[AXIS] = build_ctx->voxsz[AXIS] * (double)(1<<i); + CHK(build_ctx->max_depth >= depth); + CHK(depth > 0); + aabb->depth = depth - 1; - /* Clamp voxel to grid size */ - upper[AXIS] = MMIN(aabb->lower[AXIS] + voxsz[AXIS], build_ctx->upper[AXIS]); + i = build_ctx->max_depth - aabb->depth; + voxsz[AXIS] = build_ctx->voxsz[AXIS] * (double)(1<<i); - /* Adjust the voxel size from the clampd voxel */ - voxsz[AXIS] = upper[AXIS] - aabb->lower[AXIS]; + /* Clamp voxel to grid size */ + upper[AXIS] = MMIN(aabb->lower[AXIS] + voxsz[AXIS], build_ctx->upper[AXIS]); - CHK(eq_eps(voxsz[AXIS], aabb->upper[AXIS] - aabb->lower[AXIS], 1.e-6)); - } + /* Adjust the voxel size from the clampd voxel */ + voxsz[AXIS] = upper[AXIS] - aabb->lower[AXIS]; + + CHK(eq_eps(voxsz[AXIS], aabb->upper[AXIS] - aabb->lower[AXIS], 1.e-6)); } static int @@ -214,12 +213,22 @@ challenge_aabb(const struct svx_voxel voxels[], const size_t nvoxels, void* ctx) if(depth == SIZE_MAX) { depth = aabb->depth; - } else if(aabb->depth != 0) { /* Not invalid */ + } else { /* Not invalid */ CHK(depth == aabb->depth); - CHK(depth == voxels[i].depth); - voxsz[AXIS] = build_ctx->voxsz[AXIS] * (double)(1<<n); - CHK(eq_eps(voxsz[AXIS], aabb->upper[AXIS] - aabb->lower[AXIS], 1.e-6)); } + CHK(depth == voxels[i].depth); + CHK(eq_eps(aabb->lower[AXIS], voxels[i].lower[AXIS], 1.e-6)); + CHK(eq_eps(aabb->upper[AXIS], voxels[i].upper[AXIS], 1.e-6)); + CHK(aabb->lower[(AXIS+1)%3] == voxels[i].lower[(AXIS+1)%3]); + CHK(aabb->lower[(AXIS+2)%3] == voxels[i].lower[(AXIS+2)%3]); + CHK(aabb->lower[(AXIS+1)%3] == -INF); + CHK(aabb->lower[(AXIS+2)%3] == -INF); + CHK(aabb->upper[(AXIS+1)%3] == voxels[i].upper[(AXIS+1)%3]); + CHK(aabb->upper[(AXIS+2)%3] == voxels[i].upper[(AXIS+2)%3]); + CHK(aabb->upper[(AXIS+1)%3] == INF); + CHK(aabb->upper[(AXIS+2)%3] == INF); + voxsz[AXIS] = build_ctx->voxsz[AXIS] * (double)(1<<n); + CHK(eq_eps(voxsz[AXIS], aabb->upper[AXIS] - aabb->lower[AXIS], 1.e-6)); } return 1; } @@ -373,6 +382,15 @@ main(int argc, char** argv) test_at_accessor(tree, nvxls); CHK(svx_tree_ref_put(tree) == RES_OK); + build_ctx.max_depth = (size_t)log2i((int)round_up_pow2(nvxls)); + + d3_splat(build_ctx.lower,-INF); + d3_splat(build_ctx.upper, INF); + d3_splat(build_ctx.voxsz, INF); + build_ctx.lower[AXIS] = low;; + build_ctx.upper[AXIS] = upp; + build_ctx.voxsz[AXIS] = (upp-low)/(double)nvxls; + vox_desc.get = get_aabb; vox_desc.merge = merge_aabb; vox_desc.challenge_merge = challenge_aabb; diff --git a/src/test_svx_octree.c b/src/test_svx_octree.c @@ -208,6 +208,7 @@ static void merge_aabb(void* dst, const void* voxels[], const size_t nvoxels, void* ctx) { const struct build_context* build_ctx = ctx; + double upper[3]; double voxsz[3]; struct aabb* aabb = dst; size_t depth = SIZE_MAX; @@ -222,44 +223,39 @@ merge_aabb(void* dst, const void* voxels[], const size_t nvoxels, void* ctx) const struct aabb* vox_aabb = voxels[i]; if(depth == SIZE_MAX) { depth = vox_aabb->depth; - } else if(vox_aabb->depth != 0) { /* Not invalid */ + } else { CHK(depth == vox_aabb->depth); - aabb->lower[0] = MMIN(vox_aabb->lower[0], aabb->lower[0]); - aabb->lower[1] = MMIN(vox_aabb->lower[1], aabb->lower[1]); - aabb->lower[2] = MMIN(vox_aabb->lower[2], aabb->lower[2]); - aabb->upper[0] = MMAX(vox_aabb->upper[0], aabb->upper[0]); - aabb->upper[1] = MMAX(vox_aabb->upper[1], aabb->upper[1]); - aabb->upper[2] = MMAX(vox_aabb->upper[2], aabb->upper[2]); } + aabb->lower[0] = MMIN(vox_aabb->lower[0], aabb->lower[0]); + aabb->lower[1] = MMIN(vox_aabb->lower[1], aabb->lower[1]); + aabb->lower[2] = MMIN(vox_aabb->lower[2], aabb->lower[2]); + aabb->upper[0] = MMAX(vox_aabb->upper[0], aabb->upper[0]); + aabb->upper[1] = MMAX(vox_aabb->upper[1], aabb->upper[1]); + aabb->upper[2] = MMAX(vox_aabb->upper[2], aabb->upper[2]); } - if(depth == 0) { /* Invalid voxel */ - memset(aabb, 0, sizeof(*aabb)); - } else { - double upper[3]; - CHK(build_ctx->max_depth >= depth); - CHK(depth > 0); - aabb->depth = depth - 1; - - i = build_ctx->max_depth - aabb->depth; - voxsz[0] = build_ctx->voxsz[0] * (double)(1<<i); - voxsz[1] = build_ctx->voxsz[1] * (double)(1<<i); - voxsz[2] = build_ctx->voxsz[2] * (double)(1<<i); - - /* Clamp voxel to grid size */ - upper[0] = MMIN(aabb->lower[0] + voxsz[0], build_ctx->upper[0]); - upper[1] = MMIN(aabb->lower[1] + voxsz[1], build_ctx->upper[1]); - upper[2] = MMIN(aabb->lower[2] + voxsz[2], build_ctx->upper[2]); - - /* Adjust the voxel size from the clampd voxel */ - voxsz[0] = upper[0] - aabb->lower[0]; - voxsz[1] = upper[1] - aabb->lower[1]; - voxsz[2] = upper[2] - aabb->lower[2]; + CHK(build_ctx->max_depth >= depth); + CHK(depth > 0); + aabb->depth = depth - 1; - CHK(eq_eps(voxsz[0], aabb->upper[0] - aabb->lower[0], 1.e-6)); - CHK(eq_eps(voxsz[1], aabb->upper[1] - aabb->lower[1], 1.e-6)); - CHK(eq_eps(voxsz[2], aabb->upper[2] - aabb->lower[2], 1.e-6)); - } + i = build_ctx->max_depth - aabb->depth; + voxsz[0] = build_ctx->voxsz[0] * (double)(1<<i); + voxsz[1] = build_ctx->voxsz[1] * (double)(1<<i); + voxsz[2] = build_ctx->voxsz[2] * (double)(1<<i); + + /* Clamp voxel to grid size */ + upper[0] = MMIN(aabb->lower[0] + voxsz[0], build_ctx->upper[0]); + upper[1] = MMIN(aabb->lower[1] + voxsz[1], build_ctx->upper[1]); + upper[2] = MMIN(aabb->lower[2] + voxsz[2], build_ctx->upper[2]); + + /* Adjust the voxel size from the clampd voxel */ + voxsz[0] = upper[0] - aabb->lower[0]; + voxsz[1] = upper[1] - aabb->lower[1]; + voxsz[2] = upper[2] - aabb->lower[2]; + + CHK(eq_eps(voxsz[0], aabb->upper[0] - aabb->lower[0], 1.e-6)); + CHK(eq_eps(voxsz[1], aabb->upper[1] - aabb->lower[1], 1.e-6)); + CHK(eq_eps(voxsz[2], aabb->upper[2] - aabb->lower[2], 1.e-6)); } static int @@ -278,17 +274,18 @@ challenge_aabb(const struct svx_voxel voxels[], const size_t nvoxels, void* ctx) if(depth == SIZE_MAX) { depth = aabb->depth; - } else if(aabb->depth != 0) { /* Not invalid */ + } else { CHK(depth == aabb->depth); - CHK(depth == voxels[i].depth); - - voxsz[0] = build_ctx->voxsz[0] * (double)(1<<n); - voxsz[1] = build_ctx->voxsz[1] * (double)(1<<n); - voxsz[2] = build_ctx->voxsz[2] * (double)(1<<n); - CHK(eq_eps(voxsz[0], aabb->upper[0] - aabb->lower[0], 1.e-6)); - CHK(eq_eps(voxsz[1], aabb->upper[1] - aabb->lower[1], 1.e-6)); - CHK(eq_eps(voxsz[2], aabb->upper[2] - aabb->lower[2], 1.e-6)); } + CHK(depth == voxels[i].depth); + CHK(d3_eq_eps(aabb->lower, voxels[i].lower, 1.e-6)); + CHK(d3_eq_eps(aabb->upper, voxels[i].upper, 1.e-6)); + voxsz[0] = build_ctx->voxsz[0] * (double)(1<<n); + voxsz[1] = build_ctx->voxsz[1] * (double)(1<<n); + voxsz[2] = build_ctx->voxsz[2] * (double)(1<<n); + CHK(eq_eps(voxsz[0], aabb->upper[0] - aabb->lower[0], 1.e-6)); + CHK(eq_eps(voxsz[1], aabb->upper[1] - aabb->lower[1], 1.e-6)); + CHK(eq_eps(voxsz[2], aabb->upper[2] - aabb->lower[2], 1.e-6)); } return 1;