s3d.h (22040B)
1 /* Copyright (C) 2015-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 S3D_H 17 #define S3D_H 18 19 #include <rsys/rsys.h> 20 #include <float.h> 21 22 /* Library symbol management */ 23 #if defined(S3D_SHARED_BUILD) /* Build shared library */ 24 #define S3D_API extern EXPORT_SYM 25 #elif defined(S3D_STATIC) /* Use/build static library */ 26 #define S3D_API extern LOCAL_SYM 27 #else /* Use shared library */ 28 #define S3D_API extern IMPORT_SYM 29 #endif 30 31 /* Helper macro that asserts if the invocation of the s3d function `Func' 32 * returns an error. One should use this macro on s3d function calls for which 33 * no explicit error checking is performed */ 34 #ifndef NDEBUG 35 #define S3D(Func) ASSERT(s3d_ ## Func == RES_OK) 36 #else 37 #define S3D(Func) s3d_ ## Func 38 #endif 39 40 /* Syntactic sugar use during the setup of the shape. Setting a vertex data 41 * functor to S3D_KEEP means that this vertex data will not be updated */ 42 #define S3D_KEEP NULL 43 44 #define S3D_INVALID_ID ((unsigned)-1) /* Value of an invalid identifer */ 45 46 enum s3d_rays_flag { 47 S3D_RAYS_SINGLE_ORIGIN = BIT(0), /* The rays have the same origin */ 48 S3D_RAYS_SINGLE_DIRECTION = BIT(1), /* The rays have the same direction */ 49 S3D_RAYS_SINGLE_RANGE = BIT(2), /* The rays have the same range */ 50 S3D_RAYS_SINGLE_DATA = BIT(3) /* The rays shared the same user defined data */ 51 }; 52 53 /* Attributes of a shape */ 54 enum s3d_attrib_usage { 55 S3D_POSITION, /* World space position */ 56 S3D_ATTRIB_0, /* Generic attrib 0 */ 57 S3D_ATTRIB_1, /* Generic attrib 1 */ 58 S3D_ATTRIB_2, /* Generic attrib 2 */ 59 S3D_ATTRIB_3, /* Generic attrib 3 */ 60 S3D_ATTRIBS_COUNT__, 61 /* Unormalized world space face normal. For triangular meshes, the outward 62 * orientation is defined with respect to the Clock Wise vertex ordering */ 63 S3D_GEOMETRY_NORMAL 64 }; 65 66 enum s3d_type { 67 S3D_FLOAT, 68 S3D_FLOAT2, 69 S3D_FLOAT3, 70 S3D_FLOAT4 71 }; 72 73 enum s3d_transform_space { 74 S3D_LOCAL_TRANSFORM, /* The transformation is local to the shape space */ 75 S3D_WORLD_TRANSFORM /* The transformation is expressed in world space */ 76 }; 77 78 /* Primitive descriptor. The <geom|inst> indentifiers cover a compact ranges of 79 * value. They can be used in conjunction with a dynamic array to map from s3d 80 * geometry to application geometry */ 81 struct s3d_primitive { 82 unsigned prim_id; /* Primitive identifier */ 83 unsigned geom_id; /* Geometry identifier */ 84 unsigned inst_id; /* Instance identifier */ 85 unsigned scene_prim_id; /* Identifier of the primitive in the scene */ 86 /* Internal data. Should not be accessed */ 87 void* shape__; 88 void* inst__; 89 }; 90 91 #define S3D_PRIMITIVE_NULL__ { \ 92 S3D_INVALID_ID, S3D_INVALID_ID, S3D_INVALID_ID, S3D_INVALID_ID, NULL, NULL \ 93 } 94 static const struct s3d_primitive S3D_PRIMITIVE_NULL = S3D_PRIMITIVE_NULL__; 95 96 /* Helper macro that defines whether or not 2 primites are equal */ 97 #define S3D_PRIMITIVE_EQ(Prim0, Prim1) \ 98 ( (Prim0)->prim_id == (Prim1)->prim_id \ 99 && (Prim0)->geom_id == (Prim1)->geom_id \ 100 && (Prim0)->inst_id == (Prim1)->inst_id) 101 102 /* Untyped vertex attribute */ 103 struct s3d_attrib { 104 float value[4]; 105 enum s3d_type type; 106 enum s3d_attrib_usage usage; 107 }; 108 109 /* Describe a per vertex data */ 110 struct s3d_vertex_data { 111 /* Semantic of the data. Note that the S3D_GEOMETRY_NORMAL is not a valid 112 * vertex usage */ 113 enum s3d_attrib_usage usage; 114 enum s3d_type type; 115 /* Retreive the vertex data value of `ivert'. Set it to S3D_KEEP, to keep the 116 * previously set data */ 117 void (*get) 118 (const unsigned ivert, /* Index of the vertex */ 119 float* value, /* Retrieved attrib value */ 120 void* ctx); /* Pointer to user data */ 121 }; 122 123 /* Invalid vertex data */ 124 #define S3D_VERTEX_DATA_NULL__ { S3D_ATTRIBS_COUNT__, S3D_FLOAT, NULL } 125 static const struct s3d_vertex_data S3D_VERTEX_DATA_NULL = S3D_VERTEX_DATA_NULL__; 126 127 /* Intersection point */ 128 struct s3d_hit { 129 struct s3d_primitive prim; /* Intersected primitive */ 130 float normal[3]; /* Un-normalized geometry normal (left hand convention) */ 131 float uv[2]; /* Barycentric coordinates of the hit onto `prim' */ 132 float distance; /* Hit distance from the query origin */ 133 }; 134 135 /* Constant defining a NULL intersection. Should be used to initialize a hit */ 136 #define S3D_HIT_NULL__ { \ 137 {S3D_INVALID_ID, S3D_INVALID_ID, S3D_INVALID_ID, S3D_INVALID_ID, NULL, NULL},\ 138 {0.f, 0.f, 0.f}, \ 139 {0.f, 0.f}, \ 140 FLT_MAX \ 141 } 142 143 static const struct s3d_hit S3D_HIT_NULL = S3D_HIT_NULL__; 144 145 enum s3d_scene_view_flag { 146 S3D_TRACE = BIT(0), 147 S3D_SAMPLE = BIT(1), 148 S3D_GET_PRIMITIVE = BIT(2) 149 }; 150 151 /* Helper macro that defines whether or not the hit is valid, i.e. the ray 152 * intersects a shape or not */ 153 #define S3D_HIT_NONE(Hit) ((Hit)->distance >= FLT_MAX) 154 155 /* Quality of the partitioning data structure used to accelerate geometry 156 * queries. The lowest the structure quality is, the fastest it is built. On 157 * the counterpart, a weak structure quality means that the partitioning of the 158 * geometry is sub-optimal, leading to lower geometry query performances. */ 159 enum s3d_accel_struct_quality { 160 S3D_ACCEL_STRUCT_QUALITY_LOW, 161 S3D_ACCEL_STRUCT_QUALITY_MEDIUM, 162 S3D_ACCEL_STRUCT_QUALITY_HIGH 163 }; 164 165 /* Define the properties of the partitioning data structure used to accelerate 166 * geometry queries */ 167 enum s3d_accel_struct_flag { 168 /* Avoid optimisations that reduce arithmetic accuracy */ 169 S3D_ACCEL_STRUCT_FLAG_ROBUST = BIT(0), 170 /* Improve the building performances of the acceleration structure for 171 * dynamic scenes */ 172 S3D_ACCEL_STRUCT_FLAG_DYNAMIC = BIT(1), 173 /* Reduce the memory consumption of the acceleration structure */ 174 S3D_ACCEL_STRUCT_FLAG_COMPACT = BIT(2) 175 }; 176 177 /* Configuration of the partitioning structure used to accelerate geometry 178 * queries */ 179 struct s3d_accel_struct_conf { 180 enum s3d_accel_struct_quality quality; 181 int mask; /* combination of s3d_accel_struct_flag */ 182 }; 183 #define S3D_ACCEL_STRUCT_CONF_DEFAULT__ { \ 184 S3D_ACCEL_STRUCT_QUALITY_MEDIUM, \ 185 S3D_ACCEL_STRUCT_FLAG_ROBUST \ 186 } 187 static const struct s3d_accel_struct_conf S3D_ACCEL_STRUCT_CONF_DEFAULT = 188 S3D_ACCEL_STRUCT_CONF_DEFAULT__; 189 190 /* Filter function data type. One can define such function to discard 191 * intersections along a ray or the result of a closest point query with 192 * respect to user defined criteria, e.g.: masked/transparent primitive, etc. 193 * Return 0 if or the intersection is not discarded and a value not equal to zero 194 * otherwise. */ 195 typedef int 196 (*s3d_hit_filter_function_T) 197 (const struct s3d_hit* hit, 198 const float org[3], 199 const float dir[3], /* Direction from `org' to `hit' */ 200 const float range[2], /* Submitted range */ 201 void* query_data, /* User data submitted on query invocation */ 202 void* filter_data); /* Data defined on the setup of the filter function */ 203 204 /* Forward declaration of s3d opaque data types */ 205 struct s3d_device; /* Entry point of the library */ 206 struct s3d_scene; /* Collection of shapes */ 207 struct s3d_scene_view; /* Scene state */ 208 struct s3d_shape; /* Surfacic geometry */ 209 210 /* Forward declaration of external data types */ 211 struct logger; 212 struct mem_allocator; 213 214 /* 215 * All the s3d structures are ref counted. Once created with the appropriated 216 * `s3d_<TYPE>_create' function, the caller implicitly owns the created data, 217 * i.e. its reference counter is set to 1. The s3d_<TYPE>_ref_<get|put> 218 * functions get or release a reference on the data, i.e. they increment or 219 * decrement the reference counter, respectively. When this counter reach 0 the 220 * object is silently destroyed and cannot be used anymore. 221 */ 222 223 BEGIN_DECLS 224 225 /******************************************************************************* 226 * Device API - A device is the entry point of the s3d library. Applications 227 * use a s3d_device to create others s3d resources. 228 ******************************************************************************/ 229 S3D_API res_T 230 s3d_device_create 231 (struct logger* logger, /* May be NULL <=> use default logger */ 232 struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ 233 const int verbose, /* Define the level of verbosity */ 234 struct s3d_device** dev); 235 236 S3D_API res_T 237 s3d_device_ref_get 238 (struct s3d_device* dev); 239 240 S3D_API res_T 241 s3d_device_ref_put 242 (struct s3d_device* dev); 243 244 /******************************************************************************* 245 * Scene API - A scene is a collection of untyped shapes. It can be ray-traced 246 * and/or "instantiated" through a shape. 247 ******************************************************************************/ 248 S3D_API res_T 249 s3d_scene_create 250 (struct s3d_device* dev, 251 struct s3d_scene** scn); 252 253 S3D_API res_T 254 s3d_scene_ref_get 255 (struct s3d_scene* scn); 256 257 S3D_API res_T 258 s3d_scene_ref_put 259 (struct s3d_scene* scn); 260 261 S3D_API res_T 262 s3d_scene_instantiate 263 (struct s3d_scene* scn, 264 struct s3d_shape** shape); 265 266 /* Attach the shape to the scene. On success, the scene gets a reference onto 267 * the attached shape */ 268 S3D_API res_T 269 s3d_scene_attach_shape 270 (struct s3d_scene* scn, 271 struct s3d_shape* shape); 272 273 /* Remove the shape from the scene. After its detachment, the scene 274 * release its reference on the shape */ 275 S3D_API res_T 276 s3d_scene_detach_shape 277 (struct s3d_scene* scn, 278 struct s3d_shape* shape); 279 280 /* Detach all the shapes from the scene and release the reference that the 281 * scene takes onto them */ 282 S3D_API res_T 283 s3d_scene_clear 284 (struct s3d_scene* scn); 285 286 S3D_API res_T 287 s3d_scene_get_device 288 (struct s3d_scene* scn, 289 struct s3d_device** dev); 290 291 S3D_API res_T 292 s3d_scene_get_shapes_count 293 (struct s3d_scene* scn, 294 size_t* nshapes); 295 296 /******************************************************************************* 297 * Scene view API - State of the scene geometry 298 ******************************************************************************/ 299 S3D_API res_T 300 s3d_scene_view_create 301 (struct s3d_scene* scn, 302 const int mask, /* Combination of s3d_scene_view_flag */ 303 struct s3d_scene_view** scnview); 304 305 S3D_API res_T 306 s3d_scene_view_create2 307 (struct s3d_scene* scn, 308 const int mask, /* Combination of s3d_scene_view_flag */ 309 /* Ignored if (mask & S3D_TRACE) == 0 310 * NULL <=> use S3D_ACCEL_STRUCT_CONF_DEFAULT */ 311 const struct s3d_accel_struct_conf* cfg, 312 struct s3d_scene_view** scnview); 313 314 S3D_API res_T 315 s3d_scene_view_ref_get 316 (struct s3d_scene_view* scnview); 317 318 S3D_API res_T 319 s3d_scene_view_ref_put 320 (struct s3d_scene_view* scnview); 321 322 S3D_API res_T 323 s3d_scene_view_get_mask 324 (struct s3d_scene_view* scnview, 325 int* mask); 326 327 /* Trace a ray into the scene and return the closest intersection along it. The 328 * ray is defined by `origin' + t*`direction' = 0 with t in [`range[0]', 329 * `range[1]'). Note that if a range is degenerated (i.e. `range[0]' >= 330 * `range[1]') then the ray is not traced and `hit' is set to S3D_HIT_NULL. Can 331 * be called only if the scnview was created with the S3D_TRACE flag. */ 332 S3D_API res_T 333 s3d_scene_view_trace_ray 334 (struct s3d_scene_view* scnview, 335 const float origin[3], /* Ray origin */ 336 const float direction[3], /* Ray direction. Must be normalized */ 337 const float range[2], /* In [0, INF)^2 */ 338 void* ray_data, /* User ray data sent to the hit filter func. May be NULL */ 339 struct s3d_hit* hit); 340 341 /* Trace a bundle of rays into the scene. Can be called only if the scnview was 342 * created with the S3D_TRACE flag. */ 343 S3D_API res_T 344 s3d_scene_view_trace_rays 345 (struct s3d_scene_view* scnview, 346 const size_t nrays, /* # rays */ 347 const int mask, /* Combination of s3d_rays_flag */ 348 const float* origins, /* List of 3D ray origins */ 349 const float* directions, /* List of 3D ray directions */ 350 const float* ranges, /* List of 2D ray ranges. in [0, INF)^2 */ 351 void* rays_data, /* User ray data sent to the hit filter func. May be NULL */ 352 const size_t sizeof_ray_data, /* Size in Bytes of *one* ray data */ 353 struct s3d_hit* hits); 354 355 /* Return the point onto the scene surfaces that is the closest of the 356 * submitted `pos'. Note that even though only one point is returned, several 357 * position can have the same minimal distance to the queried position. The 358 * `radius' parameter defines the maximum search distance around `pos'. Each 359 * candidate position are internally filtered by the hit_filter_function 360 * attached to the corresponding shape; the user can thus reject a candidate 361 * position according to its own criteria. This function can be called only if 362 * the scnview was created with the S3D_TRACE flag which is actually the flag 363 * used to tell Star-3D to internally build an acceleration structure on which 364 * this function relies. */ 365 S3D_API res_T 366 s3d_scene_view_closest_point 367 (struct s3d_scene_view* scnview, 368 const float pos[3], /* Position to query */ 369 const float radius, /* Search distance in [0, radius[ */ 370 void* query_data, /* User data sent to the hit filter func. May be NULL */ 371 struct s3d_hit* hit); 372 373 /* Uniformly sample the scene and return the sampled primitive and its sample 374 * uv position. Can be called only if the scnview was created with the 375 * S3D_SAMPLE flag */ 376 S3D_API res_T 377 s3d_scene_view_sample 378 (struct s3d_scene_view* scnview, 379 const float u, const float v, const float w, /* Random numbers in [0, 1) */ 380 struct s3d_primitive* primitive, /* Sampled primitive */ 381 float st[2]); /* Sampled parametric coordinates on the primitive */ 382 383 /* Retrieve a primitive from the scene. Can be called only if the scnview was 384 * created with the S3D_GET_PRIMITIVE flag */ 385 S3D_API res_T 386 s3d_scene_view_get_primitive 387 (struct s3d_scene_view* scnview, 388 const unsigned iprim, /* in [0, #prims) */ 389 struct s3d_primitive* prim); 390 391 /* Return the overall number of scene primitives */ 392 S3D_API res_T 393 s3d_scene_view_primitives_count 394 (struct s3d_scene_view* scnview, 395 size_t* primitives_count); 396 397 /* Compute the overall scene surface area */ 398 S3D_API res_T 399 s3d_scene_view_compute_area 400 (struct s3d_scene_view* scnview, 401 float* area); 402 403 /* This function assumes that the scene defines a closed volume and that the 404 * normals point into the volume. */ 405 S3D_API res_T 406 s3d_scene_view_compute_volume 407 (struct s3d_scene_view* scnview, 408 float* volume); 409 410 /* Retrieve the Axis Aligned Bounding Box of the scene */ 411 S3D_API res_T 412 s3d_scene_view_get_aabb 413 (struct s3d_scene_view* scnview, 414 float lower[3], /* AABB lower bound */ 415 float upper[3]); /* AABB upper bound */ 416 417 /******************************************************************************* 418 * Shape API - A shape defines a geometry that can be attached to a scene. 419 ******************************************************************************/ 420 S3D_API res_T 421 s3d_shape_ref_get 422 (struct s3d_shape* shape); 423 424 S3D_API res_T 425 s3d_shape_ref_put 426 (struct s3d_shape* shape); 427 428 /* Retrieve the id of the shape. This id covers a compact range of value. 429 * Consequently, it can be used to map from the s3d shapes to the geometry 430 * representation of the caller with a simple dynamic array */ 431 S3D_API res_T 432 s3d_shape_get_id 433 (const struct s3d_shape* shape, 434 unsigned* id); 435 436 /* Enable/disable the shape, i.e. it cannot be hit when its associated scene is 437 * ray-traced or sampled */ 438 S3D_API res_T 439 s3d_shape_enable 440 (struct s3d_shape* shape, 441 const char enable); 442 443 /* Return whether or not the shape is enabled, i.e. ray-traced. Default is 1 */ 444 S3D_API res_T 445 s3d_shape_is_enabled 446 (const struct s3d_shape* shape, 447 char* is_enabled); 448 449 /* Flip the surface orientation, i.e. flip the geometric normal of the surface */ 450 S3D_API res_T 451 s3d_shape_flip_surface 452 (struct s3d_shape* shape); 453 454 /******************************************************************************* 455 * Primitive API - Define a geometric primitive of a shape 456 ******************************************************************************/ 457 /* Retrieve the attribute of the shape primitive `prim' at the barycentric 458 * coordinates `uv' */ 459 S3D_API res_T 460 s3d_primitive_get_attrib 461 (const struct s3d_primitive* prim, 462 const enum s3d_attrib_usage attr, /* Attribute to retrieve */ 463 const float st[2], /* Parametric coordinates of `attr' on `prim' */ 464 struct s3d_attrib* attrib); /* Resulting attrib */ 465 466 /* Retrieve if the primitive `prim' has the attribute `attr' */ 467 S3D_API res_T 468 s3d_primitive_has_attrib 469 (const struct s3d_primitive* prim, 470 const enum s3d_attrib_usage attr, 471 char* has_attrib); 472 473 /* Uniform sampling of the primitive */ 474 S3D_API res_T 475 s3d_primitive_sample 476 (const struct s3d_primitive* prim, 477 const float u, const float v, /* Random numbers in [0, 1) */ 478 float st[2]); /* Sampled parametric coordinates on prim */ 479 480 S3D_API res_T 481 s3d_primitive_compute_area 482 (const struct s3d_primitive* prim, 483 float* area); 484 485 S3D_API res_T 486 s3d_primitive_get_transform 487 (const struct s3d_primitive* prim, 488 float transform[12]); /* 3x4 column major matrix */ 489 490 S3D_API res_T 491 s3d_triangle_get_vertex_attrib 492 (const struct s3d_primitive* prim, 493 const size_t ivertex, /* in [0..3[ */ 494 const enum s3d_attrib_usage usage, 495 struct s3d_attrib* attrib); 496 497 /******************************************************************************* 498 * Sphere API - Manage a spherical shape. By default, the sphere normals point 499 * outward the sphere. One can use the s3d_shape_flip_surface function to 500 * revert them. 501 ******************************************************************************/ 502 S3D_API res_T 503 s3d_shape_create_sphere 504 (struct s3d_device* dev, 505 struct s3d_shape** sphere); 506 507 S3D_API res_T 508 s3d_sphere_setup 509 (struct s3d_shape* shape, 510 const float position[3], 511 const float radius); 512 513 /* Define an intersection filter function. The filter function is invoked at 514 * each intersection found during the s3d_scene_trace_ray(s) calls. If func 515 * does not return 0, then the intersection is ignored and the ray pursues its 516 * traversal. */ 517 S3D_API res_T 518 s3d_sphere_set_hit_filter_function 519 (struct s3d_shape* shape, 520 s3d_hit_filter_function_T func, 521 void* filter_data); 522 523 S3D_API res_T 524 s3d_sphere_get_hit_filter_data 525 (struct s3d_shape* shape, 526 void** data); 527 528 /******************************************************************************* 529 * Mesh API - Manage a triangular meshes 530 ******************************************************************************/ 531 S3D_API res_T 532 s3d_shape_create_mesh 533 (struct s3d_device* dev, 534 struct s3d_shape** shape); 535 536 /* Set/update the data of the indexed triangular meshes */ 537 S3D_API res_T 538 s3d_mesh_setup_indexed_vertices 539 (struct s3d_shape* shape, 540 const unsigned ntris, 541 void (*get_indices) /* May be S3D_KEEP, i.e. do not update the indices */ 542 (const unsigned itri, unsigned ids[3], void* ctx), 543 const unsigned nverts, 544 /* List of the shape vertex data. Must have at least an attrib with the 545 * S3D_POSITION usage. */ 546 struct s3d_vertex_data attribs[], 547 const unsigned nattribs, /* # attributes in the attribs list */ 548 void* data); /* Client data set as the last param of the callbacks */ 549 550 /* Copy the mesh data from `src' to `dst' */ 551 S3D_API res_T 552 s3d_mesh_copy 553 (const struct s3d_shape* src, 554 struct s3d_shape* dst); 555 556 S3D_API res_T 557 s3d_mesh_get_vertices_count 558 (const struct s3d_shape* shape, 559 unsigned* nverts); 560 561 S3D_API res_T 562 s3d_mesh_get_vertex_attrib 563 (const struct s3d_shape* shape, 564 const unsigned ivert, 565 const enum s3d_attrib_usage usage, 566 struct s3d_attrib* attrib); 567 568 S3D_API res_T 569 s3d_mesh_get_triangles_count 570 (const struct s3d_shape* shape, 571 unsigned* ntris); 572 573 S3D_API res_T 574 s3d_mesh_get_triangle_indices 575 (const struct s3d_shape* shape, 576 const unsigned itri, 577 unsigned ids[3]); 578 579 /* Define an intersection filter function. The filter function is invoked at 580 * each intersection found during the s3d_scene_trace_ray(s) calls. If func 581 * does not return 0, then the intersection is ignored and the ray pursues its 582 * traversal. */ 583 S3D_API res_T 584 s3d_mesh_set_hit_filter_function 585 (struct s3d_shape* shape, 586 s3d_hit_filter_function_T func, 587 void* filter_data); 588 589 S3D_API res_T 590 s3d_mesh_get_hit_filter_data 591 (struct s3d_shape* shape, 592 void** data); 593 594 /******************************************************************************* 595 * Instance API - An instance is a shape that encapsulates a scene and that 596 * supports a local to world transformation. Since the scene geometry is stored 597 * only a single time even though it is instantiated in several positions, one 598 * can use this feature to create extremely large scene. 599 ******************************************************************************/ 600 S3D_API res_T 601 s3d_instance_set_position 602 (struct s3d_shape* shape, 603 const float position[3]); 604 605 S3D_API res_T 606 s3d_instance_translate 607 (struct s3d_shape* shape, 608 const enum s3d_transform_space space, 609 const float translation[3]); 610 611 S3D_API res_T 612 s3d_instance_set_transform 613 (struct s3d_shape* shape, 614 const float transform[12]); /* 3x4 column major matrix */ 615 616 S3D_API res_T 617 s3d_instance_transform 618 (struct s3d_shape* shape, 619 const enum s3d_transform_space space, 620 const float transform[12]); /* 3x4 column major matrix */ 621 622 END_DECLS 623 624 #endif /* S3D_H */ 625