svx.h (9963B)
1 /* Copyright (C) 2018, 2020-2025 |Méso|Star> (contact@meso-star.com) 2 * Copyright (C) 2018 Université Paul Sabatier 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17 #ifndef SVX_H 18 #define SVX_H 19 20 #include <rsys/rsys.h> 21 #include <float.h> 22 23 /* Library symbol management */ 24 #if defined(SVX_SHARED_BUILD) /* Build shared library */ 25 #define SVX_API extern EXPORT_SYM 26 #elif defined(SVX_STATIC) /* Use/build static library */ 27 #define SVX_API extern LOCAL_SYM 28 #else /* Use shared library */ 29 #define SVX_API extern IMPORT_SYM 30 #endif 31 32 /* Helper macro that asserts if the invocation of the svx function `Func' 33 * returns an error. One should use this macro on svx function calls for 34 * which no explicit error checking is performed */ 35 #ifndef NDEBUG 36 #define SVX(Func) ASSERT(svx_ ## Func == RES_OK) 37 #else 38 #define SVX(Func) svx_ ## Func 39 #endif 40 41 /* Maximum memory size of a voxel */ 42 #define SVX_MAX_SIZEOF_VOXEL (sizeof(double)*16) 43 44 enum svx_axis { 45 SVX_AXIS_X, 46 SVX_AXIS_Y, 47 SVX_AXIS_Z, 48 SVX_AXIS_NONE__ 49 }; 50 51 enum svx_tree_type { 52 SVX_BINTREE, 53 SVX_OCTREE 54 }; 55 56 /* Volume element */ 57 struct svx_voxel { 58 double lower[3], upper[3]; /* AABB of the voxel */ 59 const void* data; /* Data of the voxel */ 60 size_t id; /* Indentifier of the voxel */ 61 size_t depth; /* Depth of the voxel, in [0, svx_octree_desc.depth[ */ 62 int is_leaf; /* Define if the voxel is a leaf into the hierarchy */ 63 }; 64 65 #define SVX_VOXEL_NULL__ { \ 66 { DBL_MAX, DBL_MAX, DBL_MAX}, \ 67 {-DBL_MAX,-DBL_MAX,-DBL_MAX}, \ 68 NULL, SIZE_MAX, SIZE_MAX, 0 } 69 static const struct svx_voxel SVX_VOXEL_NULL = SVX_VOXEL_NULL__; 70 71 #define SVX_VOXEL_EQ(V0, V1) ((V0)->id == (V1)->id) 72 73 #define SVX_VOXEL_NONE(Voxel) ((Voxel)->id == SVX_VOXEL_NULL.id) 74 75 /* Descriptor of a voxel */ 76 struct svx_voxel_desc { 77 /* Retrieve the data of the voxels. Star-VoXel ensures that the Voxels are 78 * accessed according to the morton order where Z vary priorly to Y and Y 79 * priorly to X. */ 80 void 81 (*get) 82 (const size_t xyz[3], /* Voxel coordinate in voxel space */ 83 const uint64_t mcode, /* Morton code of the voxel */ 84 void* dst, /* Where to store data */ 85 void* ctx); /* Pointer toward user data */ 86 87 /* Merge the data of N voxels */ 88 void 89 (*merge) 90 (void* dst, /* Merged data */ 91 const void* voxels[], /* Data to merge */ 92 const size_t nvoxels, /* #submitted data */ 93 void* ctx); /* Pointer toward user data */ 94 95 /* Check if the voxel's data can be merged. Note that the `id' field of the 96 * submitted voxels is undefined since these voxels are temporaries. */ 97 int 98 (*challenge_merge) 99 (const struct svx_voxel voxels[], /* Voxels candidate to the merge */ 100 const size_t nvoxels, /* #candidates */ 101 void* ctx); /* Pointer toward user data */ 102 103 void* context; /* Client side data sent as the last argument of the clbbs */ 104 size_t size; /* Size in bytes of a voxel. Must be <= SVX_MAX_SIZEOF_VOXEL */ 105 }; 106 107 #define SVX_VOXEL_DESC_NULL__ { NULL, NULL, NULL, NULL, 0 } 108 static const struct svx_voxel_desc SVX_VOXEL_DESC_NULL = 109 SVX_VOXEL_DESC_NULL__; 110 111 struct svx_tree_desc { 112 /* Submitted Axis Aligned Bounding Box */ 113 double lower[3], upper[3]; 114 115 size_t nleaves; /* #leaves */ 116 size_t nvoxels; /* #voxels, i.e. #leaves + #parents */ 117 size_t depth; /* Depth of the octree */ 118 119 enum svx_tree_type type; 120 121 /* Define the axis in world space along which the tree is defined. In 1D, 122 * (i.e. bintree) only the first component of the frame is defined while in 123 * 3D (i.e. octree), the 3 components is always defined to SVX_AXIS_X, 124 * SVX_AXIS_Y and SVX_AXYS_Z. */ 125 enum svx_axis frame[3]; 126 }; 127 128 #define SVX_TREE_DESC_NULL__ { \ 129 { DBL_MAX, DBL_MAX, DBL_MAX}, \ 130 {-DBL_MAX,-DBL_MAX,-DBL_MAX}, \ 131 0, 0, 0, 0, \ 132 {SVX_AXIS_NONE__, SVX_AXIS_NONE__, SVX_AXIS_NONE__} \ 133 } 134 static const struct svx_tree_desc SVX_TREE_DESC_NULL = 135 SVX_TREE_DESC_NULL__; 136 137 struct svx_hit { 138 /* Distance from the ray origin the the voxel entry/exit point, respectively. 139 * These distances are clamped against the ray-range. */ 140 double distance[2]; 141 struct svx_voxel voxel; /* Intersected voxel */ 142 }; 143 144 #define SVX_HIT_NULL__ {{DBL_MAX,-DBL_MAX}, SVX_VOXEL_NULL__} 145 static const struct svx_hit SVX_HIT_NULL = SVX_HIT_NULL__; 146 147 #define SVX_HIT_NONE(Hit) ((Hit)->distance[0] > (Hit)->distance[1]) 148 149 /* Function to invoke on a leaf */ 150 typedef void 151 (*svx_leaf_function_T) 152 (const struct svx_voxel* leaf, 153 const size_t ileaf, /* Identifier of the leaf in [0, #leafs[ */ 154 void* context); 155 156 /* Hit challenge data type. The caller can implement a function of this type to 157 * control the traversal of the octree hierarchy. If the function returns 1, 158 * the octree traversal will not go deeper into the hierarchy and the traversed 159 * voxel will be treated as a leaf. Note that this function is not invoked on 160 * intersected leaves */ 161 typedef int 162 (*svx_hit_challenge_T) 163 (const struct svx_hit* hit, 164 const double ray_org[3], 165 const double ray_dir[3], 166 const double ray_range[2], 167 void* context); 168 169 /* Hit filter function data type. The caller can define a function of this type 170 * to control the treatment at each "leaf" intersected during the octree ray 171 * tracing. An intersected voxel is considered as a "leaf" if it is really a 172 * leaf, or if the svx_hit_challenge_T function returns a not null value. If 173 * the filter function returns 0, the octree traversal is stopped while a value 174 * !=0 lets the ray to pursue its traversal. Such functions can be used to 175 * discard specific voxels, to accumulate voxels data, to list the traversed 176 * voxels, etc. */ 177 typedef int 178 (*svx_hit_filter_T) 179 (const struct svx_hit* hit, 180 const double ray_org[3], 181 const double ray_dir[3], 182 const double ray_range[2], 183 void* context); /* User data submitted on trace ray invocation */ 184 185 /* At filter function data type. One can define such function to discard voxels 186 * during the traversal of the octree with respect to user defined criteria, 187 * eg, depth or size of the voxel, etc. Return 0 if the voxel is not discarded 188 * and a value not equal to zero otherwise. */ 189 typedef int 190 (*svx_at_filter_T) 191 (const struct svx_voxel* voxel, 192 const double position[3], 193 void* context); 194 195 /* Forward declaration of external data types */ 196 struct logger; 197 struct mem_allocator; 198 199 /* Forward declaration of opaque data types */ 200 struct svx_device; 201 struct svx_tree; 202 203 BEGIN_DECLS 204 205 /******************************************************************************* 206 * Device 207 ******************************************************************************/ 208 SVX_API res_T 209 svx_device_create 210 (struct logger* logger, 211 struct mem_allocator* allocator, /* NULL <=> use default allocator */ 212 const int verbose, /* Verbosity level */ 213 struct svx_device** svx); 214 215 SVX_API res_T 216 svx_device_ref_get 217 (struct svx_device* svx); 218 219 SVX_API res_T 220 svx_device_ref_put 221 (struct svx_device* svx); 222 223 /******************************************************************************* 224 * Tree 225 ******************************************************************************/ 226 SVX_API res_T 227 svx_octree_create 228 (struct svx_device* dev, 229 const double lower[3], /* Lower bound of the octree */ 230 const double upper[3], /* Upper bound of the octree */ 231 const size_t nvoxels[3], /* # voxels along the 3 axis */ 232 const struct svx_voxel_desc* desc, /* Descriptor of a voxel */ 233 struct svx_tree** octree); 234 235 SVX_API res_T 236 svx_bintree_create 237 (struct svx_device* dev, 238 const double lower, /* Lower bound of the bintree */ 239 const double upper, /* Upper bound of the bintree */ 240 const size_t nvoxels, /* #voxels along the range */ 241 const enum svx_axis axis, /* Axis along which the binary tree is defined */ 242 const struct svx_voxel_desc* desc, /* Descriptor of a voxel */ 243 struct svx_tree** tree); 244 245 SVX_API res_T 246 svx_tree_create_from_stream 247 (struct svx_device* dev, 248 FILE* stream, 249 struct svx_tree** tree); 250 251 SVX_API res_T 252 svx_tree_ref_get 253 (struct svx_tree* tree); 254 255 SVX_API res_T 256 svx_tree_ref_put 257 (struct svx_tree* tree); 258 259 SVX_API res_T 260 svx_tree_get_desc 261 (const struct svx_tree* tree, 262 struct svx_tree_desc* desc); 263 264 SVX_API res_T 265 svx_tree_for_each_leaf 266 (struct svx_tree* tree, 267 svx_leaf_function_T functor, 268 void* context); /* Client data sent as the last argument of the functor */ 269 270 SVX_API res_T 271 svx_tree_trace_ray 272 (struct svx_tree* tree, 273 const double ray_origin[3], 274 const double ray_direction[3], /* Must be normalized */ 275 const double ray_range[2], 276 const svx_hit_challenge_T challenge, /* NULL <=> Traversed up to the leaves */ 277 const svx_hit_filter_T filter, /* NULL <=> Stop RT at the 1st hit voxel */ 278 void* context, /* Data sent to the filter functor */ 279 struct svx_hit* hit); 280 281 SVX_API res_T 282 svx_tree_at 283 (struct svx_tree* tree, 284 const double position[3], 285 svx_at_filter_T filter, 286 void* context, /* Client data sent as the last argument of the filter func */ 287 struct svx_voxel* voxel); 288 289 SVX_API res_T 290 svx_tree_write 291 (const struct svx_tree* tree, 292 FILE* stream); 293 294 #endif /* SVX_H */ 295