star-vx

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

commit eae934e11339dc57596ea4f902d6dde1275461d2
parent b1d8a75d98c5eabf1fda261e8f66c64fb8c934cf
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed,  4 Apr 2018 11:53:26 +0200

Begin the implementation of a trace_ray test

Diffstat:
Mcmake/CMakeLists.txt | 1+
Asrc/test_svx_octree_trace_ray.c | 152+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 153 insertions(+), 0 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -88,6 +88,7 @@ if(NOT NO_TEST) new_test(test_svx_device) new_test(test_svx_octree) + new_test(test_svx_octree_trace_ray) endif() ################################################################################ diff --git a/src/test_svx_octree_trace_ray.c b/src/test_svx_octree_trace_ray.c @@ -0,0 +1,152 @@ +/* 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/>. */ + +#include "svx.h" +#include "test_svx_utils.h" + +#include <rsys/math.h> + +struct scene { + double origin[3]; + double vxsz[3]; + double sphere_pos[3]; + double sphere_radius; +}; + +static char +sphere_intersect_aabb + (const double pos[3], /* Sphere position */ + const double radius, /* Sphere radius */ + const double low[3], /* AABB lower bound */ + const double upp[3]) /* AABB upper bound */ +{ + double v[3]; + double sqr_dst; + + CHK(pos != NULL); + CHK(low != NULL); + CHK(upp != NULL); + CHK(radius > 0); + + v[0] = pos[0]<low[0] ? low[0]-pos[0] : (pos[0]>upp[0] ? pos[0]-upp[0] : 0); + v[1] = pos[1]<low[1] ? low[1]-pos[1] : (pos[1]>upp[1] ? pos[1]-upp[1] : 0); + v[2] = pos[2]<low[2] ? low[2]-pos[2] : (pos[2]>upp[2] ? pos[2]-upp[2] : 0); + + sqr_dst = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; + + return sqr_dst <= radius*radius; +} + +static void +voxel_get(const size_t xyz[3], void* dst, void* ctx) +{ + const struct scene* scn = ctx; + char* val = dst; + double low[3]; + double upp[3]; + CHK(xyz != NULL); + CHK(dst != NULL); + CHK(ctx != NULL); + + /* Compute the AABB of the voxel */ + low[0] = (double)xyz[0] * scn->vxsz[0] + scn->origin[0]; + low[1] = (double)xyz[1] * scn->vxsz[1] + scn->origin[1]; + low[2] = (double)xyz[2] * scn->vxsz[2] + scn->origin[2]; + upp[0] = low[0] + scn->vxsz[0]; + upp[1] = low[1] + scn->vxsz[1]; + upp[2] = low[2] + scn->vxsz[2]; + + /* 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); +} + +static void +voxels_merge(void* dst, const void* voxels[], const size_t nvoxels, void* ctx) +{ + size_t ivoxel; + char tmp = 0; + char* val = dst; + + CHK(dst && voxels && nvoxels && ctx); + + for(ivoxel=0; tmp && ivoxel<nvoxels; ++ivoxel) { + const char* voxel_data = voxels[ivoxel]; + tmp = *voxel_data; + } + *val = tmp; +} + +static int +voxels_challenge_merge(const void* voxels[], const size_t nvoxels, void* ctx) +{ + size_t ivoxel; + int merge = 1; + char ref; + + CHK(voxels && nvoxels && ctx); + + ref = *(char*)(voxels[0]); + + for(ivoxel=1; merge && ivoxel<nvoxels; ++ivoxel) { + const char* voxel_data = voxels[ivoxel]; + merge = (ref == *voxel_data); + } + return merge; +} + +int +main(int argc, char** argv) +{ + struct scene scn; + struct svx_device* dev = NULL; + struct svx_octree* oct = NULL; + struct svx_voxel_desc voxel_desc = SVX_VOXEL_DESC_NULL; + const double lower[3] = {-1,-1,-1}; + const double upper[3] = { 1, 1, 1}; + const size_t def[3] = {32, 32, 32}; + double scnsz[3]; + (void)argc, (void)argv; + + CHK(svx_device_create(NULL, NULL, 1, &dev) == RES_OK); + + scnsz[0] = upper[0] - lower[0]; + scnsz[1] = upper[1] - lower[1]; + scnsz[2] = upper[2] - lower[2]; + + scn.origin[0] = lower[0]; + scn.origin[1] = lower[1]; + scn.origin[2] = lower[2]; + scn.vxsz[0] = scnsz[0] / (double)def[0]; + scn.vxsz[1] = scnsz[1] / (double)def[1]; + scn.vxsz[2] = scnsz[2] / (double)def[2]; + scn.sphere_pos[0] = lower[0] + scnsz[0] * 0.5; + scn.sphere_pos[1] = lower[1] + scnsz[1] * 0.5; + scn.sphere_pos[2] = lower[2] + scnsz[2] * 0.5; + scn.sphere_radius = MMIN(MMIN(scnsz[0], scnsz[1]), scnsz[2]) * 0.25; + + voxel_desc.get = voxel_get; + voxel_desc.merge = voxels_merge; + voxel_desc.challenge_merge = voxels_challenge_merge; + voxel_desc.context = &scn; + voxel_desc.size = sizeof(char); + + CHK(svx_octree_create(dev, lower, upper, def, &voxel_desc, &oct) == RES_OK); + + CHK(svx_octree_ref_put(oct) == RES_OK); + CHK(svx_device_ref_put(dev) == RES_OK); + CHK(mem_allocated_size() == 0); + return 0; +} +