suvm.h (9295B)
1 /* Copyright (C) 2020-2023 |Méso|Star> (contact@meso-star.com) 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #ifndef SUVM_H 17 #define SUVM_H 18 19 #include <rsys/hash.h> 20 #include <rsys/rsys.h> 21 #include <float.h> 22 23 /* Library symbol management */ 24 #if defined(SUVM_SHARED_BUILD) /* Build shared library */ 25 #define SUVM_API extern EXPORT_SYM 26 #elif defined(SUVM_STATIC) /* Use/build static library */ 27 #define SUVM_API extern LOCAL_SYM 28 #else /* Use shared library */ 29 #define SUVM_API extern IMPORT_SYM 30 #endif 31 32 /* Helper macro that asserts if the invocation of the suvm function `Func' 33 * returns an error. One should use this macro on suvm function calls for 34 * which no explicit error checking is performed */ 35 #ifndef NDEBUG 36 #define SUVM(Func) ASSERT(suvm_ ## Func == RES_OK) 37 #else 38 #define SUVM(Func) suvm_ ## Func 39 #endif 40 41 /* Maximum number of vertices per volumetric primitive */ 42 #define SUVM_PRIMITIVE_MAX_VERTICES_COUNT 4 43 44 enum suvm_volume_cpnt_flag { 45 SUVM_POSITIONS = BIT(0), 46 SUVM_INDICES = BIT(1), 47 SUVM_PRIMITIVE_DATA = BIT(2), 48 SUVM_VERTEX_DATA = BIT(3) 49 }; 50 51 struct suvm_data { 52 void (*get)(const size_t id, void* data, void* ctx); /* Data getter */ 53 size_t size; /* Size of the data in bytes */ 54 size_t alignment; /* Alignment of the data */ 55 }; 56 #define SUVM_DATA_NULL__ {NULL, 0, 0} 57 static const struct suvm_data SUVM_DATA_NULL = SUVM_DATA_NULL__; 58 59 struct suvm_primitive { 60 const void* data; /* Data of the primitive */ 61 const void* vertex_data[SUVM_PRIMITIVE_MAX_VERTICES_COUNT]; /* Vertex data */ 62 size_t indices[SUVM_PRIMITIVE_MAX_VERTICES_COUNT]; /* Vertex indices */ 63 size_t iprim; /* Identifier of the primitive */ 64 size_t nvertices; /* #vertices of the primitive */ 65 66 /* Internal data */ 67 const struct suvm_volume* volume__; 68 }; 69 #define SUVM_PRIMITIVE_NULL__ { \ 70 NULL, /* Primitive data */ \ 71 {NULL}, /* Vertex data */ \ 72 {0}, /* Vertex indices */ \ 73 SIZE_MAX, /* Primitive id */ \ 74 SIZE_MAX, /* #vertices */ \ 75 NULL /* Pointer toward its associated volume */ \ 76 } 77 static const struct suvm_primitive SUVM_PRIMITIVE_NULL = SUVM_PRIMITIVE_NULL__; 78 79 #define SUVM_PRIMITIVE_NONE(Prim) ((Prim)->iprim == SIZE_MAX) 80 81 /* Precomputed data from a suvm_primitive used to speed up AABB/primitive 82 * intersection tests */ 83 struct suvm_polyhedron { 84 float v[4/*#vertices*/][3/*#coords*/]; /* Vertices */ 85 float N[4/*#vertices*/][3/*#coords*/]; /* Normals */ 86 float D[4/*#facets*/]; /* Slope parameter of the plane (D = -(Ax+By+Cz)) */ 87 88 /* 2D equation of the silhouette edges projected along the X, Y and Z axis of 89 * the form Ax + By + C = 0, with (A, B) the normals of the edge */ 90 float Ep[3/*#axes*/][4/*#edges max*/][3/*#equation parameters*/]; 91 92 /* Number of silhouette edges in the ZY, XZ and XY planes (3 or 4) */ 93 int nEp[3/*#coords*/]; 94 95 /* Tetrahedron axis aligned bounding box */ 96 float lower[3/*#coords*/]; 97 float upper[3/*#coords*/]; 98 }; 99 100 /* Internal copy of the unstructured mesh */ 101 struct suvm_mesh_desc { 102 const float* positions; 103 const uint32_t* indices; 104 size_t nvertices; 105 size_t nprimitives; 106 unsigned dvertex; /* Dimension of a vertex */ 107 unsigned dprimitive; /* Dimension of a primitive */ 108 }; 109 #define SUVM_MESH_DESC_NULL__ {NULL, NULL, 0, 0, 0, 0} 110 static const struct suvm_mesh_desc SUVM_MESH_DESC_NULL = SUVM_MESH_DESC_NULL__; 111 112 struct suvm_tetrahedral_mesh_args { 113 size_t ntetrahedra; /* #tetrahedra */ 114 size_t nvertices; /* #vertices */ 115 116 /* Each tetrahedron has to list the bottom triangle in counterclockwise order, 117 * and then the top vertex. */ 118 void (*get_indices)(const size_t itetra, size_t ids[4], void* ctx); 119 void (*get_position)(const size_t ivert, double pos[3], void* ctx); 120 121 /* Per tetrahedron/vertex data. SUVM_DATA_NULL <=> no data */ 122 struct suvm_data tetrahedron_data; 123 struct suvm_data vertex_data; 124 125 /* Define whether tetrahedron normals are precomputed or not. When 126 * precomputed, the normals of each tetrahedron facet are explicitly stored 127 * and thus increase the memory footprint but speed up accessors that use 128 * them (e.g. suvm_volume_at). */ 129 int precompute_normals; 130 131 void* context; /* Client data set as the last param of the callbacks */ 132 }; 133 #define SUVM_TETRAHEDRAL_MESH_ARGS_NULL__ { \ 134 0, 0, NULL, NULL, SUVM_DATA_NULL__, SUVM_DATA_NULL__, 0, NULL \ 135 } 136 static const struct suvm_tetrahedral_mesh_args SUVM_TETRAHEDRAL_MESH_ARGS_NULL = 137 SUVM_TETRAHEDRAL_MESH_ARGS_NULL__; 138 139 enum suvm_intersection_type { 140 SUVM_INTERSECT_NONE, 141 SUVM_INTERSECT_INCLUDE, 142 SUVM_INTERSECT_IS_INCLUDED, 143 SUVM_INTERSECT_PARTIAL 144 }; 145 146 /* Callback invoked on suvm_volume_intersect_aabb invocation on each primitives 147 * intersected by the submitted Axis Aligned Bounding Box */ 148 typedef void 149 (*suvm_primitive_intersect_aabb_T) 150 (const struct suvm_primitive* primitive, /* Intersected primitive */ 151 const double low[3], /* AABB lower bound */ 152 const double upp[3], /* AABB upper bound */ 153 void* context); /* User data */ 154 155 /* Forward declaration of external data types */ 156 struct logger; 157 struct mem_allocator; 158 159 /* Forward declaration of opaque data types */ 160 struct suvm_device; 161 struct suvm_volume; 162 163 BEGIN_DECLS 164 165 /******************************************************************************* 166 * Device API 167 ******************************************************************************/ 168 SUVM_API res_T 169 suvm_device_create 170 (struct logger* logger, /* NULL <=> use default logger */ 171 struct mem_allocator* allocator, /* NULL <=> use default allocator */ 172 const int verbose, /* Verbosity */ 173 struct suvm_device** suvm); 174 175 SUVM_API res_T 176 suvm_device_ref_get 177 (struct suvm_device* dev); 178 179 SUVM_API res_T 180 suvm_device_ref_put 181 (struct suvm_device* dev); 182 183 /******************************************************************************* 184 * Volume mesh API 185 ******************************************************************************/ 186 SUVM_API res_T 187 suvm_tetrahedral_mesh_create 188 (struct suvm_device* dev, 189 const struct suvm_tetrahedral_mesh_args* args, 190 struct suvm_volume** volume); 191 192 SUVM_API res_T 193 suvm_volume_ref_get 194 (struct suvm_volume* volume); 195 196 SUVM_API res_T 197 suvm_volume_ref_put 198 (struct suvm_volume* volume); 199 200 SUVM_API res_T 201 suvm_volume_get_aabb 202 (const struct suvm_volume* volume, 203 double lower[3], 204 double upper[3]); 205 206 /* Return the primitive into which `pos' lies and the barycentric coordinates 207 * of `pos' into this primitive. The returned primitive is SUVM_PRIMITIVE_NULL 208 * if `pos' is not included into any volumic primitive. One can use the 209 * SUVM_PRIMIIVE_NONE macro to check this case. */ 210 SUVM_API res_T 211 suvm_volume_at 212 (struct suvm_volume* volume, 213 const double pos[3], 214 struct suvm_primitive* prim, /* Geometric primitive where `pos' lies */ 215 double barycentric_coords[4]); /* `pos' into the primitive */ 216 217 /* Iterate over the volumetric primitives intersecting the submitted Axis 218 * Aligned Bounding Box and invoke the `clbk' function onto them. */ 219 SUVM_API res_T 220 suvm_volume_intersect_aabb 221 (struct suvm_volume* volume, 222 const double low[3], /* AABB lower bound */ 223 const double upp[3], /* AABB upper bound */ 224 suvm_primitive_intersect_aabb_T clbk, 225 void* context); /* User data sent as the last argument of clbk */ 226 227 SUVM_API res_T 228 suvm_volume_get_primitives_count 229 (const struct suvm_volume* volume, 230 size_t* nprims); 231 232 SUVM_API res_T 233 suvm_volume_get_primitive 234 (const struct suvm_volume* volume, 235 const size_t iprim, /* In [0, suvm_volume_get_primitives_count[ */ 236 struct suvm_primitive* prim); 237 238 SUVM_API res_T 239 suvm_volume_compute_hash 240 (const struct suvm_volume* volume, 241 const int cpnt_mask, /* Combination of suvm_volume_cpnt_flag */ 242 hash256_T hash); 243 244 SUVM_API res_T 245 suvm_volume_get_mesh_desc 246 (const struct suvm_volume* volume, 247 struct suvm_mesh_desc* desc); 248 249 SUVM_API res_T 250 suvm_mesh_desc_compute_hash 251 (const struct suvm_mesh_desc* desc, 252 hash256_T hash); 253 254 /******************************************************************************* 255 * Primitive API 256 ******************************************************************************/ 257 SUVM_API res_T 258 suvm_primitive_setup_polyhedron 259 (const struct suvm_primitive* prim, 260 struct suvm_polyhedron* poly); 261 262 SUVM_API enum suvm_intersection_type 263 suvm_polyhedron_intersect_aabb 264 (const struct suvm_polyhedron* poly, 265 const float low[3], 266 const float upp[3]); 267 268 END_DECLS 269 270 #endif /* SUVM_H */ 271