s2d.h (16901B)
1 /* Copyright (C) 2016-2021, 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 S2D_H 17 #define S2D_H 18 19 #include <rsys/rsys.h> 20 #include <float.h> 21 22 /* Library symbol management */ 23 #if defined(S2D_SHARED_BUILD) /* Build shared library */ 24 #define S2D_API extern EXPORT_SYM 25 #elif defined(S2D_STATIC) /* Use/build static library */ 26 #define S2D_API extern LOCAL_SYM 27 #else /* Use shared library */ 28 #define S2D_API extern IMPORT_SYM 29 #endif 30 31 /* Helper macro that asserts if the invocation of the s2d function `Func' 32 * returns an error. One should use this macro on s2d function calls for which 33 * no explicit error checking is performed */ 34 #ifndef NDEBUG 35 #define S2D(Func) ASSERT(s2d_ ## Func == RES_OK) 36 #else 37 #define S2D(Func) s2d_ ## Func 38 #endif 39 40 /* Syntactic sugar use during the setup of the shape. Setting a vertex data 41 * functor to S2D_KEEP means that this vertex data will not be updated */ 42 #define S2D_KEEP NULL 43 44 #define S2D_INVALID_ID ((unsigned)-1) /* Value of an invalid identifer */ 45 46 enum s2d_attrib_usage { 47 S2D_POSITION, /* World space position */ 48 S2D_ATTRIB_0, /* Generic attrib 0 */ 49 S2D_ATTRIB_1, /* Generic attrib 1 */ 50 S2D_ATTRIB_2, /* Generic attrib 2 */ 51 S2D_ATTRIB_3, /* Generic attrib 3 */ 52 S2D_ATTRIBS_COUNT__, 53 /* Unormalized world space face normal. For line segments, the outward 54 * orientation is defined with respect to the Clock Wise vertex ordering */ 55 S2D_GEOMETRY_NORMAL 56 }; 57 58 enum s2d_type { 59 S2D_FLOAT, 60 S2D_FLOAT2, 61 S2D_FLOAT3 62 }; 63 64 /* Primitive descriptor. The geom indentifier covers a compact ranges of value. 65 * They can be used in conjunction with a dynamic array to map from s2d 66 * geometry to application geometry */ 67 struct s2d_primitive { 68 unsigned prim_id; /* Primitive identifier */ 69 unsigned geom_id; /* Geometry identifier */ 70 unsigned scene_prim_id; /* Identifier of the primitive in the scene */ 71 /* Internal data. Should not be accessed */ 72 void* mesh__; 73 }; 74 75 #define S2D_PRIMITIVE_NULL__ { \ 76 S2D_INVALID_ID, S2D_INVALID_ID, S2D_INVALID_ID, NULL \ 77 } 78 static const struct s2d_primitive S2D_PRIMITIVE_NULL = S2D_PRIMITIVE_NULL__; 79 80 /* Helper macro that defines whether or not 2 primitives are equal */ 81 #define S2D_PRIMITIVE_EQ(Prim0, Prim1) \ 82 ( (Prim0)->prim_id == (Prim1)->prim_id \ 83 && (Prim0)->geom_id == (Prim1)->geom_id) 84 85 /* Untyped vertex attribute */ 86 struct s2d_attrib { 87 float value[3]; 88 enum s2d_type type; 89 enum s2d_attrib_usage usage; 90 }; 91 92 /* Describe a per vertex data */ 93 struct s2d_vertex_data { 94 /* Semantic of the data. Note that the S2D_GEOMETRY_NORMAL is not a valid 95 * vertex usage */ 96 enum s2d_attrib_usage usage; 97 enum s2d_type type; 98 /* Retreive the vertex data value of `ivert'. Set it to S2D_KEEP, to keep the 99 * previously set data */ 100 void (*get) 101 (const unsigned ivert, /* Index of the vertex */ 102 float* value, /* Retrieved attrib value */ 103 void* ctx); /* Pointer to user data */ 104 }; 105 106 /* Invalid vertex data */ 107 #define S2D_VERTEX_DATA_NULL__ { S2D_ATTRIBS_COUNT__, S2D_FLOAT, NULL } 108 static const struct s2d_vertex_data S2D_VERTEX_DATA_NULL = S2D_VERTEX_DATA_NULL__; 109 110 /* Intersection point */ 111 struct s2d_hit { 112 struct s2d_primitive prim; /* Intersected primitive */ 113 float normal[2]; /* Unormalized geometry normal (left hand convention) */ 114 float u; /* Barycentric coordinates onto `prim'. pos = (1 - u)*v0 + u*v1 */ 115 float distance; /* Hit distance from the ray origin */ 116 }; 117 118 /* Constant defining a NULL intersection. Should be used to initialize a hit */ 119 #define S2D_HIT_NULL__ { \ 120 S2D_PRIMITIVE_NULL__, \ 121 { 0.f, 0.f }, \ 122 0.f, \ 123 FLT_MAX \ 124 } 125 static const struct s2d_hit S2D_HIT_NULL = S2D_HIT_NULL__; 126 127 /* Helper macro that defines whether or not the hit is valid, i.e. the ray 128 * intersects a shape or not */ 129 #define S2D_HIT_NONE(Hit) ((Hit)->distance >= FLT_MAX) 130 131 enum s2d_scene_view_flag { 132 S2D_TRACE = BIT(0), 133 S2D_SAMPLE = BIT(1), 134 S2D_GET_PRIMITIVE = BIT(2) 135 }; 136 137 /* Filter function data type. One can define such function to discard 138 * intersections along a ray or the result of a closest point query with 139 * respect to user defined criteria, e.g.: masked/transparent primitive, etc. 140 * Return 0 if the intersection is not discarded and a value not equal to zero 141 * otherwise. */ 142 typedef int 143 (*s2d_hit_filter_function_T) 144 (const struct s2d_hit* hit, 145 const float ray_org[2], 146 const float ray_dir[], 147 const float ray_range[2], 148 void* ray_data, /* User data submitted on trace ray(s) invocation */ 149 void* filter_data); /* Data defined on the setup of the filter function */ 150 151 /* Forward declaration of s2d opaque data types */ 152 struct s2d_device; 153 struct s2d_scene; 154 struct s2d_scene_view; 155 struct s2d_shape; 156 157 /* Forward declaration of external data types */ 158 struct logger; 159 struct mem_allocator; 160 161 BEGIN_DECLS 162 163 /******************************************************************************* 164 * Device API - entry point of the s2d library 165 ******************************************************************************/ 166 S2D_API res_T 167 s2d_device_create 168 (struct logger* logger, /* May be NULL <=> use default logger */ 169 struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ 170 const int verbose, /* Define the level of verbosity */ 171 struct s2d_device** dev); 172 173 S2D_API res_T 174 s2d_device_ref_get 175 (struct s2d_device* dev); 176 177 S2D_API res_T 178 s2d_device_ref_put 179 (struct s2d_device* dev); 180 181 /******************************************************************************* 182 * Scene API - collection of shapes 183 ******************************************************************************/ 184 S2D_API res_T 185 s2d_scene_create 186 (struct s2d_device* dev, 187 struct s2d_scene** scn); 188 189 S2D_API res_T 190 s2d_scene_ref_get 191 (struct s2d_scene* scn); 192 193 S2D_API res_T 194 s2d_scene_ref_put 195 (struct s2d_scene* scn); 196 197 /* Attach the shape to the scene. On success, the scene gets a reference onto 198 * the attached shape */ 199 S2D_API res_T 200 s2d_scene_attach_shape 201 (struct s2d_scene* scn, 202 struct s2d_shape* shape); 203 204 /* Remove the shape from the scene. After its detachment, the scene 205 * release its reference on the shape */ 206 S2D_API res_T 207 s2d_scene_detach_shape 208 (struct s2d_scene* scn, 209 struct s2d_shape* shape); 210 211 /* Detach all the shapes from the scene and release the reference that the 212 * scene takes onto them */ 213 S2D_API res_T 214 s2d_scene_clear 215 (struct s2d_scene* scn); 216 217 /* Retrieve the device from which the scene was created */ 218 S2D_API res_T 219 s2d_scene_get_device 220 (struct s2d_scene* scn, 221 struct s2d_device** dev); 222 223 S2D_API res_T 224 s2d_scene_get_shapes_count 225 (struct s2d_scene* scn, 226 size_t* nshapes); 227 228 /******************************************************************************* 229 * Scene view API - State of the scene geometry 230 ******************************************************************************/ 231 S2D_API res_T 232 s2d_scene_view_create 233 (struct s2d_scene* scn, 234 const int mask, /* Combination of s2d_scene_view_flag */ 235 struct s2d_scene_view** scnview); 236 237 S2D_API res_T 238 s2d_scene_view_ref_get 239 (struct s2d_scene_view* scnview); 240 241 S2D_API res_T 242 s2d_scene_view_ref_put 243 (struct s2d_scene_view* scnview); 244 245 S2D_API res_T 246 s2d_scene_view_get_mask 247 (struct s2d_scene_view* scnview, 248 int* mask); 249 250 /* Trace a ray into the `scn' and return the closest intersection. The ray is 251 * defined by `origin' + t*`direction' = 0 with t in [`range[0]', `range[1]'). 252 * Note that if range is degenerated (i.e. `range[0]' >= `range[1]') then the 253 * ray is not traced and `hit' is set to S2D_HIT_NULL. Can be called only if 254 * the scnview was created with the S2D_TRACE flag. */ 255 S2D_API res_T 256 s2d_scene_view_trace_ray 257 (struct s2d_scene_view* scnview, 258 const float origin[2], /* Ray origin */ 259 const float direction[2], /* Ray direction. Must be normalized */ 260 const float range[2], /* In [0, INF)^2 */ 261 void* ray_data, /* User ray data sent to the hit filter func. May be NULL */ 262 struct s2d_hit* hit); 263 264 /* Trace a 3D ray into `scn' and return the closest intersection. The third 265 * dimension of the scene primitives is assumed to be infinite, i.e. the 266 * contours are extruded to the infinity in Z. The ray is defined by `origin' + 267 * t*`direction' = 0 with t in [`range[0]', `range[1]'). The ray range as well 268 * as the potential hit distance are expressed with respect to the 3D 269 * direction. Note that if range is degenerated (i.e. `range[0]' >= 270 * `range[1]') then the ray is not traced and `hit' is set to S2D_HIT_NULL. Can 271 * be called only if te scnview was created with the S2D_TRACE flag. */ 272 S2D_API res_T 273 s2d_scene_view_trace_ray_3d 274 (struct s2d_scene_view* scnview, 275 const float origin[2], 276 const float dir[3], 277 const float range[2], 278 void* ray_data, 279 struct s2d_hit* hit); 280 281 /* Return the point onto the scene segments that is the closest of the 282 * submitted `pos'. Note that even though only one point is returned, several 283 * position can have the same minimal distance to the queried position. The 284 * `radius' parameter defines the maximum search distance around `pos'. Each 285 * candidate position are internally filtered by the hit_filter_function 286 * attached to the corresponding shape; the user can thus reject a candidate 287 * position according to its own criteria. This function can be called only if 288 * the scnview was created with the S2D_TRACE flag which is actually the flag 289 * used to tell Star-2D to internally build an acceleration structure on which 290 * this function relies. */ 291 S2D_API res_T 292 s2d_scene_view_closest_point 293 (struct s2d_scene_view* scnview, 294 const float pos[2], /* Position to query */ 295 const float radius, /* Search distance in [0, radius[ */ 296 void* query_data, /* User data sent to the hit filter func. May be NULL */ 297 struct s2d_hit* hit); 298 299 /* Uniformly sample the scene and returned the sampled primitive and its sample 300 * position. Can be called only if the scnview was created with the 301 * S2D_SAMPLE flag */ 302 S2D_API res_T 303 s2d_scene_view_sample 304 (struct s2d_scene_view* scnview, 305 const float u, const float v, /* Random numbers in [0, 1) */ 306 struct s2d_primitive* primitive, /* Sampled primitive */ 307 float* s); /* Sampled parametric coordinates on the primitive */ 308 309 /* Retrieve a primitive from the scene. Can be called only if the scnview was 310 * created with the S2D_GET_PRIMITIVE flag */ 311 S2D_API res_T 312 s2d_scene_view_get_primitive 313 (struct s2d_scene_view* scnview, 314 const unsigned iprim, /* in [0, #prims) */ 315 struct s2d_primitive* prim); 316 317 /* Retrieve the number of scene primitives. Can be called only if the scnview 318 * was created with the S2D_GET_PRIMITIVE flag */ 319 S2D_API res_T 320 s2d_scene_view_primitives_count 321 (struct s2d_scene_view* scnview, 322 size_t* primitives_count); 323 324 /* Compute the overall length of the shape contours */ 325 S2D_API res_T 326 s2d_scene_view_compute_contour_length 327 (struct s2d_scene_view* scnview, 328 float* length); 329 330 /* This function assumes that the scene defines a closed polygon and that the 331 * normals point into the polygon. */ 332 S2D_API res_T 333 s2d_scene_view_compute_area 334 (struct s2d_scene_view* scnview, 335 float* area); 336 337 /* Retrieve the Axis Aligned Bounding Box of the scene. */ 338 S2D_API res_T 339 s2d_scene_view_get_aabb 340 (struct s2d_scene_view* scnview, 341 float lower[2], /* AABB lower bound */ 342 float upper[2]); /* AABB upper bound */ 343 344 /******************************************************************************* 345 * Shape API - define a 2D contour that can be attached to a scene. 346 ******************************************************************************/ 347 S2D_API res_T 348 s2d_shape_create_line_segments 349 (struct s2d_device* dev, 350 struct s2d_shape** shape); 351 352 S2D_API res_T 353 s2d_shape_ref_get 354 (struct s2d_shape* shape); 355 356 S2D_API res_T 357 s2d_shape_ref_put 358 (struct s2d_shape* shape); 359 360 /* Retrieve the id of the shape. This id covers a compact range of value. 361 * Consequently, it can be used to map from the s2d shapes to the geometry 362 * representation of the caller with a simple dynamic array */ 363 S2D_API res_T 364 s2d_shape_get_id 365 (const struct s2d_shape* shape, 366 unsigned* id); 367 368 /* Enable/disable the shape, i.e. it cannot be hit when its associated scene is 369 * ray-traced or sampled */ 370 S2D_API res_T 371 s2d_shape_enable 372 (struct s2d_shape* shape, 373 const char enable); 374 375 /* Return whether or not the shape is enabled, i.e. ray-traced or sampled. 376 * Default is 1 */ 377 S2D_API res_T 378 s2d_shape_is_enabled 379 (const struct s2d_shape* shape, 380 char* is_enabled); 381 382 /* Define whether the shape is attached or not */ 383 S2D_API res_T 384 s2d_shape_is_attached 385 (const struct s2d_shape* shape, 386 char* is_attached); 387 388 /* Flip the contour orientation, i.e. flip the normal of the contour */ 389 S2D_API res_T 390 s2d_shape_flip_contour 391 (struct s2d_shape* shape); 392 393 /******************************************************************************* 394 * Primitive API - Define a geometric primitive of a shape 395 ******************************************************************************/ 396 /* Retrieve the attribute of the shape primitive `iprim' at the barycentric 397 * coordinates `uv' */ 398 S2D_API res_T 399 s2d_primitive_get_attrib 400 (const struct s2d_primitive* prim, 401 const enum s2d_attrib_usage attr, /* Attribute to retrieve */ 402 const float s, /* Parametric coordinates of `attr' on `prim' */ 403 struct s2d_attrib* attrib); /* Resulting attrib */ 404 405 /* Uniform sampling of the primitive */ 406 S2D_API res_T 407 s2d_primitive_sample 408 (const struct s2d_primitive* prim, 409 const float u, /* Random numbers in [0, 1) */ 410 float* s); /* Sampled parametric coordinates on prim */ 411 412 S2D_API res_T 413 s2d_primitive_compute_length 414 (const struct s2d_primitive* prim, 415 float* area); 416 417 S2D_API res_T 418 s2d_segment_get_vertex_attrib 419 (const struct s2d_primitive* prim, 420 const size_t ivertex, /* in [0..2[ */ 421 const enum s2d_attrib_usage usage, 422 struct s2d_attrib* attrib); /* Resulting attrib */ 423 424 /******************************************************************************* 425 * Line Segments API - manage a list of segments. Normal segments point toward 426 * the semi space whose orientation is clock wise. 427 ******************************************************************************/ 428 S2D_API res_T 429 s2d_line_segments_setup_indexed_vertices 430 (struct s2d_shape* shape, 431 const unsigned nsegments, 432 void (*get_indices) /* May be S2D_KEEP, i.e. do not update the indices */ 433 (const unsigned isegment, unsigned ids[2], void* ctx), 434 const unsigned nverts, 435 /* List of the shape vertex data. Must have at least an attrib with the 436 * S2D_POSITION usage. */ 437 struct s2d_vertex_data attribs[], 438 const unsigned nattribs, /* # attributes in the attribs list */ 439 void* data); /* Client data set as the last param of the callbacks */ 440 441 /* Copy the line segments data from `src' to `dst' */ 442 S2D_API res_T 443 s2d_line_segments_copy 444 (const struct s2d_shape* src, 445 struct s2d_shape* dst); 446 447 S2D_API res_T 448 s2d_line_segments_get_vertices_count 449 (const struct s2d_shape* shape, 450 unsigned* nverts); 451 452 S2D_API res_T 453 s2d_line_segments_get_vertex_attrib 454 (const struct s2d_shape* shape, 455 const unsigned ivert, 456 const enum s2d_attrib_usage usage, 457 struct s2d_attrib* attrib); 458 459 S2D_API res_T 460 s2d_line_segments_get_segments_count 461 (const struct s2d_shape* shape, 462 unsigned* nsegments); 463 464 S2D_API res_T 465 s2d_line_segments_get_segment_indices 466 (const struct s2d_shape* shape, 467 const unsigned isegment, 468 unsigned ids[2]); 469 470 /* Define a intersection filter function. The filter function is invoked at 471 * each intersection found during the s2d_scene_trace_ray calls. If func does 472 * not return 0, then the intersection is ignored and the ray pursues its 473 * traversal. */ 474 S2D_API res_T 475 s2d_line_segments_set_hit_filter_function 476 (struct s2d_shape* shape, 477 s2d_hit_filter_function_T func, 478 void* filter_data); 479 480 S2D_API res_T 481 s2d_line_segments_get_hit_filter_data 482 (struct s2d_shape* shape, 483 void** data); 484 485 END_DECLS 486 487 #endif /* S2D_H */ 488