star-uvm

Spatial structuring of unstructured volumetric meshes
git clone git://git.meso-star.fr/star-uvm.git
Log | Files | Refs | README | LICENSE

commit 3bc34f91bad49c5ba8e3a660b62069b3d6e0c4a4
parent 4451a5edc07f1d9b0c4295978720410c7d9cce73
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 17 Dec 2020 19:02:33 +0100

Push further the polhydron/aabb intersection routine

Diffstat:
Asrc/test_suvm_box.h | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_suvm_primitive_intersection.c | 172++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/test_suvm_volume.c | 33+--------------------------------
3 files changed, 192 insertions(+), 65 deletions(-)

diff --git a/src/test_suvm_box.h b/src/test_suvm_box.h @@ -0,0 +1,52 @@ +/* Copyright (C) 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 + * 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 TEST_SUVM_BOX_H +#define TEST_SUVM_BOX_H + +static const double box_vertices[9/*#vertices*/*3/*#coords per vertex*/] = { + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 0.0, 0.0, 1.0, + 1.0, 0.0, 1.0, + 0.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 0.5, 0.5, 0.5 +}; +static const size_t box_nverts = sizeof(box_vertices) / sizeof(double[3]); + +/* The following array lists the indices toward the 3D vertices of each + * boundary triangle. The index 8 references the vertex at the center of the + * box. + * ,2---,3 ,2----3 + * ,' | ,'/| ,'/| \ | Y + * 6----7' / | 6' / | \ | | + * |', | / ,1 | / ,0---,1 o--X + * | ',|/,' |/,' | ,' / + * 4----5' 4----5' Z */ +static const size_t box_indices[12/*#tetras*/*4/*#indices per tetra*/] = { + 0, 1, 2, 8, 1, 3, 2, 8, /* -Z */ + 0, 2, 4, 8, 2, 6, 4, 8, /* -X */ + 4, 6, 5, 8, 6, 7, 5, 8, /* +Z */ + 3, 5, 7, 8, 5, 3, 1, 8, /* +X */ + 2, 7, 6, 8, 7, 2, 3, 8, /* +Y */ + 0, 5, 1, 8, 5, 0, 4, 8 /* -Y */ +}; +static const size_t box_ntetras = sizeof(box_indices) / sizeof(size_t[4]); + + +#endif /* TEST_SUVM_BOX_H */ diff --git a/src/test_suvm_primitive_intersection.c b/src/test_suvm_primitive_intersection.c @@ -14,9 +14,12 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "suvm.h" +#include "test_suvm_ball.h" +#include "test_suvm_box.h" #include "test_suvm_utils.h" #include <rsys/float3.h> +#include <string.h> struct mesh { const double* vertices; /* List of double[3] */ @@ -56,9 +59,9 @@ get_position(const size_t ivert, double pos[3], void* ctx) static void write_voxels (FILE* stream, - const enum suvm_intersection_type* vxls, + const int* vxls, const size_t def[3], - const float vxl_sz[3]) + const double vxl_sz[3]) { size_t ix, iy, iz; size_t ivxl; @@ -72,13 +75,13 @@ write_voxels fprintf(stream, "DATASET RECTILINEAR_GRID\n"); fprintf(stream, "DIMENSIONS %lu %lu %lu\n", def[0]+1, def[1]+1, def[2]+1); fprintf(stream, "X_COORDINATES %lu float\n", def[0]+1); - FOR_EACH(i, 0, def[0]+1) fprintf(stream, "%g ", (float)i*vxl_sz[0]); + FOR_EACH(i, 0, def[0]+1) fprintf(stream, "%g ", (double)i*vxl_sz[0]); fprintf(stream, "\n"); fprintf(stream, "Y_COORDINATES %lu float\n", def[1]+1); - FOR_EACH(i, 0, def[1]+1) fprintf(stream, "%g ", (float)i*vxl_sz[1]); + FOR_EACH(i, 0, def[1]+1) fprintf(stream, "%g ", (double)i*vxl_sz[1]); fprintf(stream, "\n"); fprintf(stream, "Z_COORDINATES %lu float\n", def[2]+1); - FOR_EACH(i, 0, def[2]+1) fprintf(stream, "%g ", (float)i*vxl_sz[2]); + FOR_EACH(i, 0, def[2]+1) fprintf(stream, "%g ", (double)i*vxl_sz[2]); fprintf(stream, "\n"); fprintf(stream, "CELL_DATA %lu\n", def[0]*def[1]*def[2]); @@ -97,6 +100,113 @@ write_voxels } static void +voxelise_volume + (const struct suvm_volume* vol, + int* vxls, + const size_t def[3]) +{ + double low[3]; + double upp[3]; + double vxl_sz[3]; + size_t iprim; + size_t nprims; + + CHK(suvm_volume_get_aabb(vol, low, upp) == RES_OK); + CHK(suvm_volume_get_primitives_count(vol, &nprims) == RES_OK); + + memset(vxls, 0, sizeof(*vxls)*def[0]*def[1]*def[2]); + + vxl_sz[0] = (upp[0] - low[0]) / (double)def[0]; + vxl_sz[1] = (upp[1] - low[1]) / (double)def[1]; + vxl_sz[2] = (upp[2] - low[2]) / (double)def[2]; + + FOR_EACH(iprim, 0, nprims) { + struct suvm_primitive prim = SUVM_PRIMITIVE_NULL; + struct suvm_polyhedron poly; + size_t ivxl_low[3]; + size_t ivxl_upp[3]; + size_t ivxl[3]; + size_t i = 0; + + CHK(suvm_volume_get_primitive(vol, iprim, &prim) == RES_OK); + CHK(suvm_primitive_setup_polyhedron(&prim, &poly) == RES_OK); + + /* Transform the polyhedron AABB in voxel space */ + ivxl_low[0] = (size_t)((poly.lower[0] - low[0]) / vxl_sz[0]); + ivxl_low[1] = (size_t)((poly.lower[1] - low[1]) / vxl_sz[1]); + ivxl_low[2] = (size_t)((poly.lower[2] - low[2]) / vxl_sz[2]); + ivxl_upp[0] = (size_t)ceil((poly.upper[0] - low[0]) / vxl_sz[0]); + ivxl_upp[1] = (size_t)ceil((poly.upper[1] - low[1]) / vxl_sz[1]); + ivxl_upp[2] = (size_t)ceil((poly.upper[2] - low[2]) / vxl_sz[2]); + CHK(ivxl_low[0] < def[0] && ivxl_upp[0] <= def[0]); + CHK(ivxl_low[1] < def[1] && ivxl_upp[1] <= def[1]); + CHK(ivxl_low[2] < def[2] && ivxl_upp[2] <= def[2]); + + FOR_EACH(ivxl[2], ivxl_low[2], ivxl_upp[2]) { + float vxl_low[3]; + float vxl_upp[3]; + vxl_low[2] = (float)((double)ivxl[2] * vxl_sz[2] + low[2]); + vxl_upp[2] = vxl_low[2] + (float)vxl_sz[2]; + FOR_EACH(ivxl[1], ivxl_low[1], ivxl_upp[1]) { + vxl_low[1] = (float)((double)ivxl[1] * vxl_sz[1] + low[1]); + vxl_upp[1] = vxl_low[1] + (float)vxl_sz[1]; + FOR_EACH(ivxl[0], ivxl_low[0], ivxl_upp[0]) { + vxl_low[0] = (float)((double)ivxl[0] * vxl_sz[0] + low[0]); + vxl_upp[0] = vxl_low[0] + (float)vxl_sz[0]; + + i = ivxl[0] + ivxl[1]*def[0] + ivxl[2]*def[0]*def[1]; + vxls[i] += (int)suvm_polyhedron_intersect_aabb(&poly, vxl_low, vxl_upp); + } + } + } + } +} + +static void +test_mesh_voxelization + (struct suvm_device* dev, + struct mem_allocator* allocator, + struct mesh* msh, + const size_t def[3], + const char* filename) /* NULL <=> do not write the result onto disk */ +{ + struct suvm_volume* vol = NULL; + struct suvm_tetrahedral_mesh_args args = SUVM_TETRAHEDRAL_MESH_ARGS_NULL; + double low[3], upp[3]; + double vxl_sz[3]; + int* vxls = NULL; + + args.ntetrahedra = msh->ntetrahedra; + args.nvertices = msh->nvertices; + args.get_indices = get_indices; + args.get_position = get_position; + args.context = msh; + + CHK(suvm_tetrahedral_mesh_create(dev, &args, &vol) == RES_OK); + CHK(suvm_volume_get_aabb(vol, low, upp) == RES_OK); + vxl_sz[0] = (upp[0] - low[0]) / (double)def[0]; + vxl_sz[1] = (upp[1] - low[1]) / (double)def[1]; + vxl_sz[2] = (upp[2] - low[2]) / (double)def[2]; + + CHK(allocator != NULL); + vxls = MEM_CALLOC(allocator, def[0]*def[1]*def[2], sizeof(*vxls)); + CHK(vxls != NULL); + + voxelise_volume(vol, vxls, def); + + if(filename) { + FILE* fp = fopen(filename, "w"); + CHK(fp != NULL); + write_voxels(fp, vxls, def, vxl_sz); + CHK(fclose(fp) == 0); + } + + MEM_RM(allocator, vxls); + CHK(suvm_volume_ref_put(vol) == RES_OK); +} + + +static void test_tetra_aabb_intersection (struct suvm_device* dev, struct mem_allocator* allocator) @@ -115,12 +225,16 @@ test_tetra_aabb_intersection struct suvm_volume* vol= NULL; float low[3]; float upp[3]; + double vxl_sz[3]; const size_t def[3] = {16, 16, 16}; size_t nprims; - size_t ix, iy, iz; - enum suvm_intersection_type* vxls = NULL; - float vxl_sz[3]; - size_t ivxl; + int* vxls = NULL; + (void)vxl_sz; + + msh.vertices = vertices; + msh.nvertices = 4; + msh.tetrahedra = tetra; + msh.ntetrahedra = 1; args.ntetrahedra = 1; args.nvertices = 4; @@ -128,11 +242,6 @@ test_tetra_aabb_intersection args.get_position = get_position; args.context = &msh; - msh.vertices = vertices; - msh.nvertices = 4; - msh.tetrahedra = tetra; - msh.ntetrahedra = 1; - CHK(suvm_tetrahedral_mesh_create(dev, &args, &vol) == RES_OK); CHK(suvm_volume_get_primitives_count(vol, &nprims) == RES_OK); @@ -161,25 +270,8 @@ test_tetra_aabb_intersection vxls = MEM_CALLOC(allocator, def[0]*def[1]*def[2], sizeof(*vxls)); CHK(vxls != NULL); - vxl_sz[0] = 1.f/(float)def[0]; - vxl_sz[1] = 1.f/(float)def[1]; - vxl_sz[2] = 1.f/(float)def[2]; - ivxl = 0; - FOR_EACH(iz, 0, def[2]) { - low[2] = (float)iz * vxl_sz[2]; - upp[2] = low[2] + vxl_sz[2]; - FOR_EACH(iy, 0, def[1]) { - low[1] = (float)iy * vxl_sz[1]; - upp[1] = low[1] + vxl_sz[1]; - FOR_EACH(ix, 0, def[0]) { - low[0] = (float)ix * vxl_sz[0]; - upp[0] = low[0] + vxl_sz[0]; - vxls[ivxl] = suvm_polyhedron_intersect_aabb(&poly, low, upp); - ++ivxl; - } - } - } - write_voxels(stderr, vxls, def, vxl_sz); + voxelise_volume(vol, vxls, def); + MEM_RM(allocator, vxls); CHK(suvm_volume_ref_put(vol) == RES_OK); } @@ -190,13 +282,27 @@ test_tetra_aabb_intersection int main(int argc, char** argv) { + struct mesh msh = MESH_NULL; struct suvm_device* dev = NULL; + size_t def[3] = {64, 64, 64}; (void)argc, (void)argv; CHK(suvm_device_create(NULL, &mem_default_allocator, 1, &dev) == RES_OK); test_tetra_aabb_intersection(dev, &mem_default_allocator); + msh.vertices = box_vertices; + msh.nvertices = box_nverts; + msh.tetrahedra = box_indices; + msh.ntetrahedra = box_ntetras; + test_mesh_voxelization(dev, &mem_default_allocator, &msh, def, "box.vtk"); + + msh.vertices = ball_vertices; + msh.nvertices = ball_nvertices; + msh.tetrahedra = ball_tetrahedra; + msh.ntetrahedra = ball_ntetrahedra; + test_mesh_voxelization(dev, &mem_default_allocator, &msh, def, "ball.vtk"); + CHK(suvm_device_ref_put(dev) == RES_OK); check_memory_allocator(&mem_default_allocator); CHK(mem_allocated_size() == 0); diff --git a/src/test_suvm_volume.c b/src/test_suvm_volume.c @@ -16,6 +16,7 @@ #include "suvm.h" #include "test_suvm_utils.h" #include "test_suvm_ball.h" +#include "test_suvm_box.h" #include <rsys/dynamic_array.h> #include <rsys/double3.h> @@ -25,38 +26,6 @@ #define DARRAY_DATA struct suvm_primitive #include <rsys/dynamic_array.h> -static const double box_vertices[9/*#vertices*/*3/*#coords per vertex*/] = { - 0.0, 0.0, 0.0, - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 1.0, 1.0, 0.0, - 0.0, 0.0, 1.0, - 1.0, 0.0, 1.0, - 0.0, 1.0, 1.0, - 1.0, 1.0, 1.0, - 0.5, 0.5, 0.5 -}; -static const size_t box_nverts = sizeof(box_vertices) / sizeof(double[3]); - -/* The following array lists the indices toward the 3D vertices of each - * boundary triangle. The index 8 references the vertex at the center of the - * box. - * ,2---,3 ,2----3 - * ,' | ,'/| ,'/| \ | Y - * 6----7' / | 6' / | \ | | - * |', | / ,1 | / ,0---,1 o--X - * | ',|/,' |/,' | ,' / - * 4----5' 4----5' Z */ -static const size_t box_indices[12/*#tetras*/*4/*#indices per tetra*/] = { - 0, 1, 2, 8, 1, 3, 2, 8, /* -Z */ - 0, 2, 4, 8, 2, 6, 4, 8, /* -X */ - 4, 6, 5, 8, 6, 7, 5, 8, /* +Z */ - 3, 5, 7, 8, 5, 3, 1, 8, /* +X */ - 2, 7, 6, 8, 7, 2, 3, 8, /* +Y */ - 0, 5, 1, 8, 5, 0, 4, 8 /* -Y */ -}; -static const size_t box_ntetras = sizeof(box_indices) / sizeof(size_t[4]); - struct mesh { const double* vertices; /* List of double[3] */ size_t nvertices;