sg3d.h (16758B)
1 /* Copyright (C) 2019, 2020, 2023, 2024 |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 STAR_GEOMETRY3D_H__ 17 #define STAR_GEOMETRY3D_H__ 18 19 #include <rsys/rsys.h> 20 #include <rsys/dynamic_array_uint.h> 21 22 #include <limits.h> 23 24 /* Library symbol management */ 25 #if defined(SG3D_SHARED_BUILD) 26 #define SG3D_API extern EXPORT_SYM 27 #elif defined(SG3D_STATIC_BUILD) 28 #define SG3D_API extern LOCAL_SYM 29 #else /* Use shared library */ 30 #define SG3D_API extern IMPORT_SYM 31 #endif 32 33 /* Helper macro that asserts if the invocation of the star-geometry-3d function 34 * `Func' returns an error. One should use this macro on star-geometry-3d 35 * function calls for which no explicit error checking is performed. */ 36 #ifndef NDEBUG 37 #define SG3D(Func) ASSERT(sg3d_ ## Func == RES_OK) 38 #else 39 #define SG3D(Func) sg3d_ ## Func 40 #endif 41 42 /* Forward declaration of external opaque data types */ 43 struct logger; 44 struct mem_allocator; 45 struct senc_scene; 46 47 /* Forward declaration of the star-geometry-3d opaque data types. These data 48 * types are ref counted. Once created the caller implicitly owns the created 49 * data, i.e. its reference counter is set to 1. The sg3d_<TYPE>_ref_<get|put> 50 * functions get or release a reference on the data, i.e. they increment or 51 * decrement the reference counter, respectively. When this counter reaches 0, 52 * the object is silently destroyed and cannot be used anymore. */ 53 struct sg3d_device; 54 struct sg3d_geometry; 55 56 /****************************************************************************** 57 * The dimension of the geometry used in the library. 58 *****************************************************************************/ 59 #define SG3D_GEOMETRY_DIMENSION 3 60 61 /****************************************************************************** 62 * A type to list the different user properties attached to triangles. 63 *****************************************************************************/ 64 enum sg3d_property_type { 65 SG3D_FRONT, 66 SG3D_BACK, 67 SG3D_INTFACE, 68 SG3D_PROP_TYPES_COUNT__ 69 }; 70 71 /****************************************************************************** 72 * A type to list the different possible partitions of triangles. 73 *****************************************************************************/ 74 enum sg3d_obj_dump_content { 75 SG3D_OBJ_DUMP_MERGE_CONFLICTS = BIT(0), 76 SG3D_OBJ_DUMP_PROPERTY_CONFLICTS = BIT(1), 77 SG3D_OBJ_DUMP_VALID_PRIMITIVE = BIT(2), 78 SG3D_OBJ_DUMP_ALL = 79 SG3D_OBJ_DUMP_MERGE_CONFLICTS 80 | SG3D_OBJ_DUMP_PROPERTY_CONFLICTS 81 | SG3D_OBJ_DUMP_VALID_PRIMITIVE 82 }; 83 84 /****************************************************************************** 85 * A type to list the different qualifiers of C code variable output. 86 *****************************************************************************/ 87 enum sg3d_c_dump_qualifiers { 88 SG3D_C_DUMP_CONST = BIT(0), 89 SG3D_C_DUMP_STATIC = BIT(1) 90 }; 91 92 /****************************************************************************** 93 * The value that should be used for properties attached to triangles (i.e. 94 * media or interface) when let unspecified. 95 * SG3D_UNSPECIFIED_PROPERTY can be used for a property that has already been 96 * defined; in this case the previous value will remain. 97 *****************************************************************************/ 98 #define SG3D_UNSPECIFIED_PROPERTY UINT_MAX 99 100 /***************************************************************************** 101 * A type to hold callbacks for sg3d_geometry_add. 102 ****************************************************************************/ 103 struct sg3d_geometry_add_callbacks { 104 /* User function that provides vertices ids for added triangles */ 105 void(*get_indices) 106 (const unsigned itri, 107 unsigned ids[SG3D_GEOMETRY_DIMENSION], 108 void* context); 109 /* User function that provides properties for added triangles */ 110 void(*get_properties) /* Can be NULL <=> SG3D_UNSPECIFIED_PROPERTY used */ 111 (const unsigned itri, 112 /* It is OK to have side and interface properties sharing the same IDs, 113 * i.e. side and interface IDs both starting from 0 */ 114 unsigned properties[SG3D_PROP_TYPES_COUNT__], 115 void* context); 116 /* User function that provides coordinates for added vertices */ 117 void(*get_position) 118 (const unsigned ivert, double pos[SG3D_GEOMETRY_DIMENSION], void* context); 119 /* Called if the itri_th triangle of the current sg3d_geometry_add is a new 120 * triangle (i.e. not a duplicate) so that the client app can manage its own 121 * triangle data/properties/attributes. 122 * If return is not RES_OK, sg3d_geometry_add stops immediately and returns 123 * whatever value add_triangle returned. */ 124 res_T(*add_triangle) /* Can be NULL */ 125 (const unsigned unique_id, const unsigned itri, void* context); 126 /* Called if the itri_th triangle of the current sg3d_geometry_add is a 127 * duplicate of the unique_id_th unique triangle so that the client app can 128 * merge its own triangle data, rule merge validity, and possibly change the 129 * recorded properties. 130 * The reversed_triangle arg indicates if the triangle vertices' order is 131 * the same it was when the triangle was first added. 132 * The merge_conflict_status argument can be set to any value. Any non-0 133 * value is accounted for a conflict and is kept as-is in dumps, allowing 134 * different shades of conflict. 135 * The triangle_properties and merged_properties args contain the involved 136 * properties. */ 137 res_T(*merge_triangle) /* Can be NULL */ 138 (const unsigned unique_id, 139 const unsigned itri, 140 const int reversed_triangle, 141 unsigned triangle_properties[SG3D_PROP_TYPES_COUNT__], 142 const unsigned merged_properties[SG3D_PROP_TYPES_COUNT__], 143 void* context, 144 int* merge_conflict_status); 145 /* Called if the itri_th triangle is degenerated. According to the value 146 * of abort, sg3d_geometry_add will stop and return RES_BAD_ARG or continue 147 * silently. */ 148 res_T(*degenerated_triangle) /* Can be NULL <=> Drop triangle, don't abort */ 149 (const unsigned itri, void* context, int* abort); 150 }; 151 #define SG3D_ADD_CALLBACKS_NULL__ { NULL, NULL, NULL, NULL, NULL, NULL } 152 153 BEGIN_DECLS 154 155 /****************************************************************************** 156 * A helper function on properties compatibility. 157 *****************************************************************************/ 158 static INLINE int 159 sg3d_compatible_property 160 (const unsigned p1, 161 const unsigned p2) 162 { 163 if(p1 == SG3D_UNSPECIFIED_PROPERTY || p2 == SG3D_UNSPECIFIED_PROPERTY) 164 return 1; 165 return (p1 == p2); 166 } 167 168 /****************************************************************************** 169 * star-geometry-3d device. It is an handle toward the star-geometry-3d 170 * library. It manages the star-geometry-3d resources. 171 *****************************************************************************/ 172 SG3D_API res_T 173 sg3d_device_create 174 (struct logger* logger, /* Can be NULL <=> use default logger */ 175 struct mem_allocator* allocator, /* Can be NULL <=> use default allocator */ 176 const int verbose, /* Verbosity level */ 177 struct sg3d_device** dev); 178 179 SG3D_API res_T 180 sg3d_device_ref_get 181 (struct sg3d_device* dev); 182 183 SG3D_API res_T 184 sg3d_device_ref_put 185 (struct sg3d_device* dev); 186 187 /****************************************************************************** 188 * star-geometry-3d geometry. 189 * It stores decorated geometry accumulated through calls to sg3d_geometry_add, 190 * information related to this geometry and its creation process, including 191 * merge conflicts. 192 *****************************************************************************/ 193 /* Create a geometry that can be used to accumulate vertices and triangles 194 * decorated with properties. */ 195 SG3D_API res_T 196 sg3d_geometry_create 197 (struct sg3d_device* dev, 198 struct sg3d_geometry** geometry); 199 200 /* Reserve memory according to anticipated geometry size. */ 201 SG3D_API res_T 202 sg3d_geometry_reserve 203 (struct sg3d_geometry* geometry, 204 const unsigned vertices_count, 205 const unsigned triangles_count, 206 const unsigned properties_count); 207 208 /* Add a new set of 3D vertices and triangles to the geometry; triangles can 209 * be decorated with 3 properties (front and back media and interface) that can 210 * be let unspecified using the SG3D_UNSPECIFIED_PROPERTY special value. 211 * Vertices can be duplicates and are silently deduplicated, always valid. 212 * Triangles can be duplicates, but this can be ruled invalid due to property 213 * inconsistency. Triangle duplicates are silently deduplicated, even if 214 * invalid. Consistency is to be understood as the consistency of the 215 * successive values for the same property across calls of sg3d_geometry_add, 216 * not as the consistency of the values of the 3 properties of a triangle at 217 * some given time (this question has its own callback (validate) in the 218 * sg3d_geometry_validate_properties API call). 219 * Duplicate triangles validity is either ruled by the user-provided 220 * merge_triangle callback, or is just a matter of properties consistency if no 221 * callback is provided. In either case, sg3d_geometry_add never stops 222 * prematurely nor returns an error code due to a merge conflict. 223 * - if provided, the callback must return the consistency status using the 224 * merge_conflict_status int* paramater (0 for consistent; any other value 225 * for inconsistent, this value being recorded); regardless of 226 * merge_conflict_status, the callback can change the properties of the 227 * triangle before the SG3D_UNSPECIFIED_PROPERTY overwriting step; 228 * - if not, a non-SG3D_UNSPECIFIED_PROPERTY is only consistent with itself and 229 * with SG3D_UNSPECIFIED_PROPERTY (if inconsistent, merge_conflict_status is 230 * set to 1 and recorded) ; regardless of merge_conflict_status, a 231 * non-SG3D_UNSPECIFIED_PROPERTY property is never overridden. 232 * When deduplicating triangles, the first occurence remains (with its 233 * original index in user world). After consistency being computed, a final 234 * step consists in rewriting SG3D_UNSPECIFIED_PROPERTY properties if the 235 * merged property is defined. */ 236 SG3D_API res_T 237 sg3d_geometry_add 238 (struct sg3d_geometry* geometry, 239 const unsigned vertices_count, 240 const unsigned triangles_count, 241 const struct sg3d_geometry_add_callbacks* callbacks, 242 void* context); /* Can be NULL */ 243 244 /* Apply a validation callback on each triangle included in this geometry that 245 * is not already flagged with a merge error. If validate returns a non-RES_OK 246 * value, the validation stops and returns the same error value; on the other 247 * hand, validation goes to the end regardless of properties conflicts. 248 * The properties_conflict_status argument can be set to any value. Any non-0 249 * value is accounted for a conflict and is kept as-is in dumps, allowing 250 * different shades of conflict. 251 * If validation is processed again, the properties conflict count is reset, 252 * as well as the properties_conflict_status status of the triangles. */ 253 SG3D_API res_T 254 sg3d_geometry_validate_properties 255 (struct sg3d_geometry* geometry, 256 res_T(*validate) 257 (const unsigned itri, 258 const unsigned properties[SG3D_PROP_TYPES_COUNT__], 259 void* context, 260 int* properties_conflict_status), 261 void* context); /* Can be NULL */ 262 263 /* Get the number of unique vertices. */ 264 SG3D_API res_T 265 sg3d_geometry_get_unique_vertices_count 266 (const struct sg3d_geometry* geometry, 267 unsigned* count); 268 269 /* Get the ivtx_th vertex. */ 270 SG3D_API res_T 271 sg3d_geometry_get_unique_vertex 272 (const struct sg3d_geometry* geometry, 273 const unsigned ivtx, 274 double coord[SG3D_GEOMETRY_DIMENSION]); 275 276 /* Get the number of triangles added to the geometry, regardless of unicity. */ 277 SG3D_API res_T 278 sg3d_geometry_get_added_triangles_count 279 (const struct sg3d_geometry* geometry, 280 unsigned* count); 281 282 /* Get the number of unique triangles. */ 283 SG3D_API res_T 284 sg3d_geometry_get_unique_triangles_count 285 (const struct sg3d_geometry* geometry, 286 unsigned* count); 287 288 /* Get the vertex indices of the itri_th unique triangle. */ 289 SG3D_API res_T 290 sg3d_geometry_get_unique_triangle_vertices 291 (const struct sg3d_geometry* geometry, 292 const unsigned itri, 293 unsigned indices[SG3D_GEOMETRY_DIMENSION]); 294 295 /* Get the properties of the itri_th unique triangle. */ 296 SG3D_API res_T 297 sg3d_geometry_get_unique_triangle_properties 298 (const struct sg3d_geometry* geometry, 299 const unsigned itri, 300 unsigned properties[SG3D_PROP_TYPES_COUNT__]); 301 302 /* Get the user ID of the itri_th unique triangle, that is the user world's 303 * index of the triangle that first created this unique triangle. 304 * User world index starts at 0 and increases for every triangle that is 305 * submitted to sg3d_geometry_add calls, regardless of duplication or 306 * sg3d_geometry_add failures (non-RES_OK return value). */ 307 SG3D_API res_T 308 sg3d_geometry_get_unique_triangle_user_id 309 (const struct sg3d_geometry* geometry, 310 const unsigned itri, 311 unsigned* user_id); 312 313 /* Get the number of triangles with (at least) one unspecified side. */ 314 SG3D_API res_T 315 sg3d_geometry_get_unique_triangles_with_unspecified_side_count 316 (const struct sg3d_geometry* geometry, 317 unsigned* count); 318 319 /* Get the number of triangles with unspecified interface. */ 320 SG3D_API res_T 321 sg3d_geometry_get_unique_triangles_with_unspecified_interface_count 322 (const struct sg3d_geometry* geometry, 323 unsigned* count); 324 325 /* Get the number of triangles flagged with a merge conflict. */ 326 SG3D_API res_T 327 sg3d_geometry_get_unique_triangles_with_merge_conflict_count 328 (const struct sg3d_geometry* geometry, 329 unsigned* count); 330 331 /* Get the number of triangles flagged with a property conflict. Only 332 * meaningful after sg3d_geometry_validate_properties has been called. */ 333 SG3D_API res_T 334 sg3d_geometry_get_unique_triangles_with_properties_conflict_count 335 (const struct sg3d_geometry* geometry, 336 unsigned* count); 337 338 /* Dump a geometry in the provided stream in the OBJ format. 339 * The geometry can include conflicts, but cannot be empty. 340 * The dump is made of the vertices and some triangles, without their 341 * properties. The dumped triangles are defined by the flags argument, that 342 * must be ORed enum sg3d_obj_dump_content values. 343 * The dumped triangles are partitioned in the following groups: 344 * - Valid_triangles 345 * - Merge_conflicts 346 * - Property_conflict */ 347 SG3D_API res_T 348 sg3d_geometry_dump_as_obj 349 (const struct sg3d_geometry* geometry, 350 FILE* stream, 351 int flags); 352 353 /* Dump a geometry in the provided stream in the VTK ascii format. 354 * The geometry can include conflicts, but cannot be empty. 355 * The dump is made of the vertices and triangles, with most of their 356 * properties: 357 * - Front_medium (medium ID of the front side, INT_MAX for both unspecified 358 * and conflicted) 359 * - Back_medium (medium ID of the back side, INT_MAX for both unspecified and 360 * conflicted) 361 * - Interface (interface ID, INT_MAX for both unspecified and conflicted) 362 * - Merge_conflict (merge conflict status) 363 * - Property_conflict (property conflict status) 364 * - Created_at_sg3d_geometry_add (rank of the sg3d_geometry_add that created 365 * the triangle) */ 366 SG3D_API res_T 367 sg3d_geometry_dump_as_vtk 368 (const struct sg3d_geometry* geometry, 369 FILE* stream); 370 371 /* Dump the geometry as C code. 372 * The geometry cannot be empty and must be conflict-free. 373 * The C code defines the 3 variables: 374 * - [static] [const] unsigned <name_prefix>_vertices_count = N1; 375 * - [static] [const] double <name_prefix>_vertices[<N1>] = { .... }; 376 * - [static] [const] unsigned <name_prefix>_triangles_count = N2; 377 * - [static] [const] unsigned <name_prefix>_triangles[<N2>] = { .... }; 378 * - [static] [const] unsigned <name_prefix>_properties[<N2>] = { .... }; 379 * Where <N1> is 3 * vertices_count and <N2> is 3 * triangles_count. 380 * The two qualifiers static and const are output or not according to flags; 381 * flags must be ORed enum sg3d_c_dump_qualifiers values. */ 382 SG3D_API res_T 383 sg3d_geometry_dump_as_c_code 384 (const struct sg3d_geometry* geometry, 385 FILE* stream, 386 const char* name_prefix, /* Can be NULL or "" */ 387 const int flags); 388 389 SG3D_API res_T 390 sg3d_geometry_ref_get 391 (struct sg3d_geometry* geometry); 392 393 SG3D_API res_T 394 sg3d_geometry_ref_put 395 (struct sg3d_geometry* geometry); 396 397 END_DECLS 398 399 #endif /* STAR_GEOMETRY3D_H__ */