star-vx

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

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