MTek-GDL 0.100.4-muffintrap
Loading...
Searching...
No Matches
ufbx.h
1#ifndef UFBX_UFBX_H_INCLUDED
2#define UFBX_UFBX_H_INCLUDED
3
4// -- User configuration
5
6#if defined(UFBX_CONFIG_HEADER)
7 #include UFBX_CONFIG_HEADER
8#endif
9
10// -- Headers
11
12#include <stdint.h>
13#include <stddef.h>
14#include <stdbool.h>
15#include <string.h>
16
17// -- Platform
18
19#ifndef UFBX_STDC
20 #if defined(__STDC_VERSION__)
21 #define UFBX_STDC __STDC_VERSION__
22 #else
23 #define UFBX_STDC 0
24 #endif
25#endif
26
27#ifndef UFBX_CPP
28 #if defined(__cplusplus)
29 #define UFBX_CPP __cplusplus
30 #else
31 #define UFBX_CPP 0
32 #endif
33#endif
34
35#ifndef UFBX_PLATFORM_MSC
36 #if !defined(UFBX_STANDARD_C) && defined(_MSC_VER)
37 #define UFBX_PLATFORM_MSC _MSC_VER
38 #else
39 #define UFBX_PLATFORM_MSC 0
40 #endif
41#endif
42
43#ifndef UFBX_PLATFORM_GNUC
44 #if !defined(UFBX_STANDARD_C) && defined(__GNUC__)
45 #define UFBX_PLATFORM_GNUC __GNUC__
46 #else
47 #define UFBX_PLATFORM_GNUC 0
48 #endif
49#endif
50
51#ifndef UFBX_CPP11
52 // MSVC does not advertise C++11 by default so we need special detection
53 #if UFBX_CPP >= 201103L || (UFBX_CPP > 0 && UFBX_PLATFORM_MSC >= 1900)
54 #define UFBX_CPP11 1
55 #else
56 #define UFBX_CPP11 0
57 #endif
58#endif
59
60#if defined(_MSC_VER)
61 #pragma warning(push)
62 #pragma warning(disable: 4061) // enumerator 'ENUM' in switch of enum 'enum' is not explicitly handled by a case label
63 #pragma warning(disable: 4201) // nonstandard extension used: nameless struct/union
64 #pragma warning(disable: 4505) // unreferenced local function has been removed
65 #pragma warning(disable: 4820) // type': 'N' bytes padding added after data member 'member'
66#elif defined(__clang__)
67 #pragma clang diagnostic push
68 #pragma clang diagnostic ignored "-Wpedantic"
69 #pragma clang diagnostic ignored "-Wpadded"
70 #if defined(__cplusplus)
71 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
72 #pragma clang diagnostic ignored "-Wold-style-cast"
73 #endif
74#elif defined(__GNUC__)
75 #pragma GCC diagnostic push
76 #pragma GCC diagnostic ignored "-Wpedantic"
77 #pragma GCC diagnostic ignored "-Wpadded"
78 #if defined(__cplusplus)
79 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
80 #pragma GCC diagnostic ignored "-Wold-style-cast"
81 #else
82 #if __GNUC__ >= 5
83 #pragma GCC diagnostic ignored "-Wc90-c99-compat"
84 #pragma GCC diagnostic ignored "-Wc99-c11-compat"
85 #endif
86 #endif
87#endif
88
89#if UFBX_PLATFORM_MSC
90 #define ufbx_inline static __forceinline
91#elif UFBX_PLATFORM_GNUC
92 #define ufbx_inline static inline __attribute__((always_inline, unused))
93#else
94 #define ufbx_inline static
95#endif
96
97// Assertion function used in ufbx, defaults to C standard `assert()`.
98// You can define this to your custom preferred assert macro, but in that case
99// make sure that it is also used within `ufbx.c`.
100// Defining `UFBX_NO_ASSERT` to any value disables assertions.
101#ifndef ufbx_assert
102 #if defined(UFBX_NO_ASSERT)
103 #define ufbx_assert(cond) (void)0
104 #else
105 #include <assert.h>
106 #define ufbx_assert(cond) assert(cond)
107 #endif
108#endif
109
110// Pointer may be `NULL`.
111#define ufbx_nullable
112
113// Changing this value from default or calling this function can lead into
114// breaking API guarantees.
115#define ufbx_unsafe
116
117// Linkage of the main ufbx API functions.
118// Defaults to nothing, or `static` if `UFBX_STATIC` is defined.
119// If you want to isolate ufbx to a single translation unit you can do the following:
120// #define UFBX_STATIC
121// #include "ufbx.h"
122// #include "ufbx.c"
123#ifndef ufbx_abi
124 #if defined(UFBX_STATIC)
125 #define ufbx_abi static
126 #else
127 #define ufbx_abi
128 #endif
129#endif
130
131// Linkage of the main ufbx data fields in the header.
132// Defaults to `extern`, or `static` if `UFBX_STATIC` is defined.
133#ifndef ufbx_abi_data
134 #if defined(UFBX_STATIC)
135 #define ufbx_abi_data static
136 #else
137 #define ufbx_abi_data extern
138 #endif
139#endif
140
141// Linkage of the main ufbx data fields in the source.
142// Defaults to nothing, or `static` if `UFBX_STATIC` is defined.
143#ifndef ufbx_abi_data_definition
144 #if defined(UFBX_STATIC)
145 #define ufbx_abi_data_def static
146 #else
147 #define ufbx_abi_data_def
148 #endif
149#endif
150
151// -- Configuration
152
153#ifndef UFBX_REAL_TYPE
154 #if defined(UFBX_REAL_IS_FLOAT)
155 #define UFBX_REAL_TYPE float
156 #else
157 #define UFBX_REAL_TYPE double
158 #endif
159#endif
160
161// Limits for embedded arrays within structures.
162#define UFBX_ERROR_STACK_MAX_DEPTH 8
163#define UFBX_PANIC_MESSAGE_LENGTH 128
164#define UFBX_ERROR_INFO_LENGTH 256
165
166// Number of thread groups to use if threading is enabled.
167// A thread group processes a number of tasks and is then waited and potentially
168// re-used later. In essence, this controls the granularity of threading.
169#define UFBX_THREAD_GROUP_COUNT 4
170
171// -- Language
172
173// bindgen-disable
174
175#if UFBX_CPP11
176
177template <typename T, typename U>
178struct ufbxi_type_is { };
179
180template <typename T>
181struct ufbxi_type_is<T, T> { using type = int; };
182
183template <typename T>
184struct ufbx_converter { };
185
186#define UFBX_CONVERSION_IMPL(p_name) \
187 template <typename T, typename S=typename ufbxi_type_is<T, decltype(ufbx_converter<T>::from(*(const p_name*)nullptr))>::type> \
188 operator T() const { return ufbx_converter<T>::from(*this); }
189
190#define UFBX_CONVERSION_TO_IMPL(p_name) \
191 template <typename T, typename S=typename ufbxi_type_is<p_name, decltype(ufbx_converter<T>::to(*(const T*)nullptr))>::type> \
192 p_name(const T &t) { *this = ufbx_converter<T>::to(t); }
193
194#define UFBX_CONVERSION_LIST_IMPL(p_name) \
195 template <typename T, typename S=typename ufbxi_type_is<T, decltype(ufbx_converter<T>::from_list((p_name*)nullptr, (size_t)0))>::type> \
196 operator T() const { return ufbx_converter<T>::from_list(data, count); }
197
198#else
199
200#define UFBX_CONVERSION_IMPL(p_name)
201#define UFBX_CONVERSION_TO_IMPL(p_name)
202#define UFBX_CONVERSION_LIST_IMPL(p_name)
203
204#endif
205
206#if defined(__cplusplus)
207 #define UFBX_LIST_TYPE(p_name, p_type) struct p_name { p_type *data; size_t count; \
208 p_type &operator[](size_t index) const { ufbx_assert(index < count); return data[index]; } \
209 p_type *begin() const { return data; } \
210 p_type *end() const { return data + count; } \
211 UFBX_CONVERSION_LIST_IMPL(p_type) \
212 }
213#else
214 #define UFBX_LIST_TYPE(p_name, p_type) typedef struct p_name { p_type *data; size_t count; } p_name
215#endif
216
217// This cannot be enabled automatically if supported as the source file may be
218// compiled with a different compiler using different settings than the header
219// consumers, in practice it should work but it causes issues such as #70.
220#if (UFBX_STDC >= 202311L || UFBX_CPP11) && defined(UFBX_USE_EXPLICIT_ENUM)
221 #define UFBX_ENUM_REPR : int
222 #define UFBX_ENUM_FORCE_WIDTH(p_prefix)
223 #define UFBX_FLAG_REPR : int
224 #define UFBX_FLAG_FORCE_WIDTH(p_prefix)
225 #define UFBX_HAS_FORCE_32BIT 0
226#else
227 #define UFBX_ENUM_REPR
228 #define UFBX_ENUM_FORCE_WIDTH(p_prefix) p_prefix##_FORCE_32BIT = 0x7fffffff
229 #define UFBX_FLAG_REPR
230 #define UFBX_FLAG_FORCE_WIDTH(p_prefix) p_prefix##_FORCE_32BIT = 0x7fffffff
231 #define UFBX_HAS_FORCE_32BIT 1
232#endif
233
234#define UFBX_ENUM_TYPE(p_name, p_prefix, p_last) \
235 enum { p_prefix##_COUNT = p_last + 1 }
236
237#if UFBX_CPP
238 #define UFBX_VERTEX_ATTRIB_IMPL(p_type) \
239 p_type &operator[](size_t index) const { ufbx_assert(index < indices.count); return values.data[indices.data[index]]; }
240#else
241 #define UFBX_VERTEX_ATTRIB_IMPL(p_type)
242#endif
243
244#if UFBX_CPP11
245 #define UFBX_CALLBACK_IMPL(p_name, p_fn, p_return, p_params, p_args) \
246 template <typename F> static p_return _cpp_adapter p_params { F &f = *static_cast<F*>(user); return f p_args; } \
247 p_name() = default; \
248 p_name(p_fn *f) : fn(f), user(nullptr) { } \
249 template <typename F> p_name(F *f) : fn(&_cpp_adapter<F>), user(static_cast<void*>(f)) { }
250#else
251 #define UFBX_CALLBACK_IMPL(p_name, p_fn, p_return, p_params, p_args)
252#endif
253
254// bindgen-enable
255
256// -- Version
257
258// Packing/unpacking for `UFBX_HEADER_VERSION` and `ufbx_source_version`.
259#define ufbx_pack_version(major, minor, patch) ((uint32_t)(major)*1000000u + (uint32_t)(minor)*1000u + (uint32_t)(patch))
260#define ufbx_version_major(version) ((uint32_t)(version)/1000000u%1000u)
261#define ufbx_version_minor(version) ((uint32_t)(version)/1000u%1000u)
262#define ufbx_version_patch(version) ((uint32_t)(version)%1000u)
263
264// Version of the ufbx header.
265// `UFBX_VERSION` is simply an alias of `UFBX_HEADER_VERSION`.
266// `ufbx_source_version` contains the version of the corresponding source file.
267// HINT: The version can be compared numerically to the result of `ufbx_pack_version()`,
268// for example `#if UFBX_VERSION >= ufbx_pack_version(0, 12, 0)`.
269#define UFBX_HEADER_VERSION ufbx_pack_version(0, 14, 3)
270#define UFBX_VERSION UFBX_HEADER_VERSION
271
272// -- Basic types
273
274// Main floating point type used everywhere in ufbx, defaults to `double`.
275// If you define `UFBX_REAL_IS_FLOAT` to any value, `ufbx_real` will be defined
276// as `float` instead.
277// You can also manually define `UFBX_REAL_TYPE` to any floating point type.
278typedef UFBX_REAL_TYPE ufbx_real;
279
280// Null-terminated UTF-8 encoded string within an FBX file
281typedef struct ufbx_string {
282 const char *data;
283 size_t length;
284
285 UFBX_CONVERSION_IMPL(ufbx_string)
287
288// Opaque byte buffer blob
289typedef struct ufbx_blob {
290 const void *data;
291 size_t size;
292
293 UFBX_CONVERSION_IMPL(ufbx_blob)
294} ufbx_blob;
295
296// 2D vector
297typedef struct ufbx_vec2 {
298 union {
299 struct { ufbx_real x, y; };
300 ufbx_real v[2];
301 };
302
303 UFBX_CONVERSION_IMPL(ufbx_vec2)
304} ufbx_vec2;
305
306// 3D vector
307typedef struct ufbx_vec3 {
308 union {
309 struct { ufbx_real x, y, z; };
310 ufbx_real v[3];
311 };
312
313 UFBX_CONVERSION_IMPL(ufbx_vec3)
314} ufbx_vec3;
315
316// 4D vector
317typedef struct ufbx_vec4 {
318 union {
319 struct { ufbx_real x, y, z, w; };
320 ufbx_real v[4];
321 };
322
323 UFBX_CONVERSION_IMPL(ufbx_vec4)
324} ufbx_vec4;
325
326// Quaternion
327typedef struct ufbx_quat {
328 union {
329 struct { ufbx_real x, y, z, w; };
330 ufbx_real v[4];
331 };
332
333 UFBX_CONVERSION_IMPL(ufbx_quat)
334} ufbx_quat;
335
336// Order in which Euler-angle rotation axes are applied for a transform
337// NOTE: The order in the name refers to the order of axes *applied*,
338// not the multiplication order: eg. `UFBX_ROTATION_ORDER_XYZ` is `Z*Y*X`
339// [TODO: Figure out what the spheric rotation order is...]
340typedef enum ufbx_rotation_order UFBX_ENUM_REPR {
341 UFBX_ROTATION_ORDER_XYZ,
342 UFBX_ROTATION_ORDER_XZY,
343 UFBX_ROTATION_ORDER_YZX,
344 UFBX_ROTATION_ORDER_YXZ,
345 UFBX_ROTATION_ORDER_ZXY,
346 UFBX_ROTATION_ORDER_ZYX,
347 UFBX_ROTATION_ORDER_SPHERIC,
348
349 UFBX_ENUM_FORCE_WIDTH(UFBX_ROTATION_ORDER)
350} ufbx_rotation_order;
351
352UFBX_ENUM_TYPE(ufbx_rotation_order, UFBX_ROTATION_ORDER, UFBX_ROTATION_ORDER_SPHERIC);
353
354// Explicit translation+rotation+scale transformation.
355// NOTE: Rotation is a quaternion, not Euler angles!
356typedef struct ufbx_transform {
357 ufbx_vec3 translation;
358 ufbx_quat rotation;
359 ufbx_vec3 scale;
360
361 UFBX_CONVERSION_IMPL(ufbx_transform)
363
364// 4x3 matrix encoding an affine transformation.
365// `cols[0..2]` are the X/Y/Z basis vectors, `cols[3]` is the translation
366typedef struct ufbx_matrix {
367 union {
368 struct {
369 ufbx_real m00, m10, m20;
370 ufbx_real m01, m11, m21;
371 ufbx_real m02, m12, m22;
372 ufbx_real m03, m13, m23;
373 };
374 ufbx_vec3 cols[4];
375 ufbx_real v[12];
376 };
377
378 UFBX_CONVERSION_IMPL(ufbx_matrix)
380
381typedef struct ufbx_void_list {
382 void *data;
383 size_t count;
385
386UFBX_LIST_TYPE(ufbx_bool_list, bool);
387UFBX_LIST_TYPE(ufbx_uint32_list, uint32_t);
388UFBX_LIST_TYPE(ufbx_real_list, ufbx_real);
389UFBX_LIST_TYPE(ufbx_vec2_list, ufbx_vec2);
390UFBX_LIST_TYPE(ufbx_vec3_list, ufbx_vec3);
391UFBX_LIST_TYPE(ufbx_vec4_list, ufbx_vec4);
392UFBX_LIST_TYPE(ufbx_string_list, ufbx_string);
393
394// Sentinel value used to represent a missing index.
395#define UFBX_NO_INDEX ((uint32_t)~0u)
396
397// -- Document object model
398
399typedef enum ufbx_dom_value_type UFBX_ENUM_REPR {
400 UFBX_DOM_VALUE_NUMBER,
401 UFBX_DOM_VALUE_STRING,
402 UFBX_DOM_VALUE_ARRAY_I8,
403 UFBX_DOM_VALUE_ARRAY_I32,
404 UFBX_DOM_VALUE_ARRAY_I64,
405 UFBX_DOM_VALUE_ARRAY_F32,
406 UFBX_DOM_VALUE_ARRAY_F64,
407 UFBX_DOM_VALUE_ARRAY_RAW_STRING,
408 UFBX_DOM_VALUE_ARRAY_IGNORED,
409
410 UFBX_ENUM_FORCE_WIDTH(UFBX_DOM_VALUE_TYPE)
411} ufbx_dom_value_type;
412
413UFBX_ENUM_TYPE(ufbx_dom_value_type, UFBX_DOM_VALUE_TYPE, UFBX_DOM_VALUE_ARRAY_IGNORED);
414
415typedef struct ufbx_dom_node ufbx_dom_node;
416
417typedef struct ufbx_dom_value {
418 ufbx_dom_value_type type;
419 ufbx_string value_str;
420 ufbx_blob value_blob;
421 int64_t value_int;
422 double value_float;
424
425UFBX_LIST_TYPE(ufbx_dom_node_list, ufbx_dom_node*);
426UFBX_LIST_TYPE(ufbx_dom_value_list, ufbx_dom_value);
427
429 ufbx_string name;
430 ufbx_dom_node_list children;
431 ufbx_dom_value_list values;
432};
433
434// -- Properties
435
436// FBX elements have properties which are arbitrary key/value pairs that can
437// have inherited default values or be animated. In most cases you don't need
438// to access these unless you need a feature not implemented directly in ufbx.
439// NOTE: Prefer using `ufbx_find_prop[_len](...)` to search for a property by
440// name as it can find it from the defaults if necessary.
441
442typedef struct ufbx_prop ufbx_prop;
443typedef struct ufbx_props ufbx_props;
444
445// Data type contained within the property. All the data fields are always
446// populated regardless of type, so there's no need to switch by type usually
447// eg. `prop->value_real` and `prop->value_int` have the same value (well, close)
448// if `prop->type == UFBX_PROP_INTEGER`. String values are not converted from/to.
449typedef enum ufbx_prop_type UFBX_ENUM_REPR {
450 UFBX_PROP_UNKNOWN,
451 UFBX_PROP_BOOLEAN,
452 UFBX_PROP_INTEGER,
453 UFBX_PROP_NUMBER,
454 UFBX_PROP_VECTOR,
455 UFBX_PROP_COLOR,
456 UFBX_PROP_COLOR_WITH_ALPHA,
457 UFBX_PROP_STRING,
458 UFBX_PROP_DATE_TIME,
459 UFBX_PROP_TRANSLATION,
460 UFBX_PROP_ROTATION,
461 UFBX_PROP_SCALING,
462 UFBX_PROP_DISTANCE,
463 UFBX_PROP_COMPOUND,
464 UFBX_PROP_BLOB,
465 UFBX_PROP_REFERENCE,
466
467 UFBX_ENUM_FORCE_WIDTH(UFBX_PROP_TYPE)
468} ufbx_prop_type;
469
470UFBX_ENUM_TYPE(ufbx_prop_type, UFBX_PROP_TYPE, UFBX_PROP_REFERENCE);
471
472// Property flags: Advanced information about properties, not usually needed.
473typedef enum ufbx_prop_flags UFBX_FLAG_REPR {
474 // Supports animation.
475 // NOTE: ufbx ignores this and allows animations on non-animatable properties.
476 UFBX_PROP_FLAG_ANIMATABLE = 0x1,
477
478 // User defined (custom) property.
479 UFBX_PROP_FLAG_USER_DEFINED = 0x2,
480
481 // Hidden in UI.
482 UFBX_PROP_FLAG_HIDDEN = 0x4,
483
484 // Disallow modification from UI for components.
485 UFBX_PROP_FLAG_LOCK_X = 0x10,
486 UFBX_PROP_FLAG_LOCK_Y = 0x20,
487 UFBX_PROP_FLAG_LOCK_Z = 0x40,
488 UFBX_PROP_FLAG_LOCK_W = 0x80,
489
490 // Disable animation from components.
491 UFBX_PROP_FLAG_MUTE_X = 0x100,
492 UFBX_PROP_FLAG_MUTE_Y = 0x200,
493 UFBX_PROP_FLAG_MUTE_Z = 0x400,
494 UFBX_PROP_FLAG_MUTE_W = 0x800,
495
496 // Property created by ufbx when an element has a connected `ufbx_anim_prop`
497 // but doesn't contain the `ufbx_prop` it's referring to.
498 // NOTE: The property may have been found in the templated defaults.
499 UFBX_PROP_FLAG_SYNTHETIC = 0x1000,
500
501 // The property has at least one `ufbx_anim_prop` in some layer.
502 UFBX_PROP_FLAG_ANIMATED = 0x2000,
503
504 // Used by `ufbx_evaluate_prop()` to indicate the the property was not found.
505 UFBX_PROP_FLAG_NOT_FOUND = 0x4000,
506
507 // The property is connected to another one.
508 // This use case is relatively rare so `ufbx_prop` does not track connections
509 // directly. You can find connections from `ufbx_element.connections_dst` where
510 // `ufbx_connection.dst_prop` is this property and `ufbx_connection.src_prop` is defined.
511 UFBX_PROP_FLAG_CONNECTED = 0x8000,
512
513 // The value of this property is undefined (represented as zero).
514 UFBX_PROP_FLAG_NO_VALUE = 0x10000,
515
516 // This property has been overridden by the user.
517 // See `ufbx_anim.prop_overrides` for more information.
518 UFBX_PROP_FLAG_OVERRIDDEN = 0x20000,
519
520 // Value type.
521 // `REAL/VEC2/VEC3/VEC4` are mutually exclusive but may coexist with eg. `STRING`
522 // in some rare cases where the string defines the unit for the vector.
523 UFBX_PROP_FLAG_VALUE_REAL = 0x100000,
524 UFBX_PROP_FLAG_VALUE_VEC2 = 0x200000,
525 UFBX_PROP_FLAG_VALUE_VEC3 = 0x400000,
526 UFBX_PROP_FLAG_VALUE_VEC4 = 0x800000,
527 UFBX_PROP_FLAG_VALUE_INT = 0x1000000,
528 UFBX_PROP_FLAG_VALUE_STR = 0x2000000,
529 UFBX_PROP_FLAG_VALUE_BLOB = 0x4000000,
530
531 UFBX_FLAG_FORCE_WIDTH(UFBX_PROP_FLAGS)
532} ufbx_prop_flags;
533
534// Single property with name/type/value.
535struct ufbx_prop {
536 ufbx_string name;
537
538 uint32_t _internal_key;
539
540 ufbx_prop_type type;
541 ufbx_prop_flags flags;
542
543 ufbx_string value_str;
544 ufbx_blob value_blob;
545 int64_t value_int;
546 union {
547 ufbx_real value_real_arr[4];
548 ufbx_real value_real;
549 ufbx_vec2 value_vec2;
550 ufbx_vec3 value_vec3;
551 ufbx_vec4 value_vec4;
552 };
553};
554
555UFBX_LIST_TYPE(ufbx_prop_list, ufbx_prop);
556
557// List of alphabetically sorted properties with potential defaults.
558// For animated objects in as scene from `ufbx_evaluate_scene()` this list
559// only has the animated properties, the originals are stored under `defaults`.
561 ufbx_prop_list props;
562 size_t num_animated;
563
564 ufbx_nullable ufbx_props *defaults;
565};
566
567typedef struct ufbx_scene ufbx_scene;
568
569// -- Elements
570
571// Element is the lowest level representation of the FBX file in ufbx.
572// An element contains type, id, name, and properties (see `ufbx_props` above)
573// Elements may be connected to each other arbitrarily via `ufbx_connection`
574
575typedef struct ufbx_element ufbx_element;
576
577// Unknown
578typedef struct ufbx_unknown ufbx_unknown;
579
580// Nodes
581typedef struct ufbx_node ufbx_node;
582
583// Node attributes (common)
584typedef struct ufbx_mesh ufbx_mesh;
585typedef struct ufbx_light ufbx_light;
586typedef struct ufbx_camera ufbx_camera;
587typedef struct ufbx_bone ufbx_bone;
588typedef struct ufbx_empty ufbx_empty;
589
590// Node attributes (curves/surfaces)
591typedef struct ufbx_line_curve ufbx_line_curve;
596
597// Node attributes (advanced)
601typedef struct ufbx_marker ufbx_marker;
602typedef struct ufbx_lod_group ufbx_lod_group;
603
604// Deformers
611typedef struct ufbx_cache_file ufbx_cache_file;
612
613// Materials
614typedef struct ufbx_material ufbx_material;
615typedef struct ufbx_texture ufbx_texture;
616typedef struct ufbx_video ufbx_video;
617typedef struct ufbx_shader ufbx_shader;
619
620// Animation
621typedef struct ufbx_anim_stack ufbx_anim_stack;
622typedef struct ufbx_anim_layer ufbx_anim_layer;
623typedef struct ufbx_anim_value ufbx_anim_value;
624typedef struct ufbx_anim_curve ufbx_anim_curve;
625
626// Collections
630
631// Constraints
632typedef struct ufbx_character ufbx_character;
633typedef struct ufbx_constraint ufbx_constraint;
634
635// Audio
637typedef struct ufbx_audio_clip ufbx_audio_clip;
638
639// Miscellaneous
640typedef struct ufbx_pose ufbx_pose;
642
643UFBX_LIST_TYPE(ufbx_element_list, ufbx_element*);
644UFBX_LIST_TYPE(ufbx_unknown_list, ufbx_unknown*);
645UFBX_LIST_TYPE(ufbx_node_list, ufbx_node*);
646UFBX_LIST_TYPE(ufbx_mesh_list, ufbx_mesh*);
647UFBX_LIST_TYPE(ufbx_light_list, ufbx_light*);
648UFBX_LIST_TYPE(ufbx_camera_list, ufbx_camera*);
649UFBX_LIST_TYPE(ufbx_bone_list, ufbx_bone*);
650UFBX_LIST_TYPE(ufbx_empty_list, ufbx_empty*);
651UFBX_LIST_TYPE(ufbx_line_curve_list, ufbx_line_curve*);
652UFBX_LIST_TYPE(ufbx_nurbs_curve_list, ufbx_nurbs_curve*);
653UFBX_LIST_TYPE(ufbx_nurbs_surface_list, ufbx_nurbs_surface*);
654UFBX_LIST_TYPE(ufbx_nurbs_trim_surface_list, ufbx_nurbs_trim_surface*);
655UFBX_LIST_TYPE(ufbx_nurbs_trim_boundary_list, ufbx_nurbs_trim_boundary*);
656UFBX_LIST_TYPE(ufbx_procedural_geometry_list, ufbx_procedural_geometry*);
657UFBX_LIST_TYPE(ufbx_stereo_camera_list, ufbx_stereo_camera*);
658UFBX_LIST_TYPE(ufbx_camera_switcher_list, ufbx_camera_switcher*);
659UFBX_LIST_TYPE(ufbx_marker_list, ufbx_marker*);
660UFBX_LIST_TYPE(ufbx_lod_group_list, ufbx_lod_group*);
661UFBX_LIST_TYPE(ufbx_skin_deformer_list, ufbx_skin_deformer*);
662UFBX_LIST_TYPE(ufbx_skin_cluster_list, ufbx_skin_cluster*);
663UFBX_LIST_TYPE(ufbx_blend_deformer_list, ufbx_blend_deformer*);
664UFBX_LIST_TYPE(ufbx_blend_channel_list, ufbx_blend_channel*);
665UFBX_LIST_TYPE(ufbx_blend_shape_list, ufbx_blend_shape*);
666UFBX_LIST_TYPE(ufbx_cache_deformer_list, ufbx_cache_deformer*);
667UFBX_LIST_TYPE(ufbx_cache_file_list, ufbx_cache_file*);
668UFBX_LIST_TYPE(ufbx_material_list, ufbx_material*);
669UFBX_LIST_TYPE(ufbx_texture_list, ufbx_texture*);
670UFBX_LIST_TYPE(ufbx_video_list, ufbx_video*);
671UFBX_LIST_TYPE(ufbx_shader_list, ufbx_shader*);
672UFBX_LIST_TYPE(ufbx_shader_binding_list, ufbx_shader_binding*);
673UFBX_LIST_TYPE(ufbx_anim_stack_list, ufbx_anim_stack*);
674UFBX_LIST_TYPE(ufbx_anim_layer_list, ufbx_anim_layer*);
675UFBX_LIST_TYPE(ufbx_anim_value_list, ufbx_anim_value*);
676UFBX_LIST_TYPE(ufbx_anim_curve_list, ufbx_anim_curve*);
677UFBX_LIST_TYPE(ufbx_display_layer_list, ufbx_display_layer*);
678UFBX_LIST_TYPE(ufbx_selection_set_list, ufbx_selection_set*);
679UFBX_LIST_TYPE(ufbx_selection_node_list, ufbx_selection_node*);
680UFBX_LIST_TYPE(ufbx_character_list, ufbx_character*);
681UFBX_LIST_TYPE(ufbx_constraint_list, ufbx_constraint*);
682UFBX_LIST_TYPE(ufbx_audio_layer_list, ufbx_audio_layer*);
683UFBX_LIST_TYPE(ufbx_audio_clip_list, ufbx_audio_clip*);
684UFBX_LIST_TYPE(ufbx_pose_list, ufbx_pose*);
685UFBX_LIST_TYPE(ufbx_metadata_object_list, ufbx_metadata_object*);
686
687typedef enum ufbx_element_type UFBX_ENUM_REPR {
688 UFBX_ELEMENT_UNKNOWN, // < `ufbx_unknown`
689 UFBX_ELEMENT_NODE, // < `ufbx_node`
690 UFBX_ELEMENT_MESH, // < `ufbx_mesh`
691 UFBX_ELEMENT_LIGHT, // < `ufbx_light`
692 UFBX_ELEMENT_CAMERA, // < `ufbx_camera`
693 UFBX_ELEMENT_BONE, // < `ufbx_bone`
694 UFBX_ELEMENT_EMPTY, // < `ufbx_empty`
695 UFBX_ELEMENT_LINE_CURVE, // < `ufbx_line_curve`
696 UFBX_ELEMENT_NURBS_CURVE, // < `ufbx_nurbs_curve`
697 UFBX_ELEMENT_NURBS_SURFACE, // < `ufbx_nurbs_surface`
698 UFBX_ELEMENT_NURBS_TRIM_SURFACE, // < `ufbx_nurbs_trim_surface`
699 UFBX_ELEMENT_NURBS_TRIM_BOUNDARY, // < `ufbx_nurbs_trim_boundary`
700 UFBX_ELEMENT_PROCEDURAL_GEOMETRY, // < `ufbx_procedural_geometry`
701 UFBX_ELEMENT_STEREO_CAMERA, // < `ufbx_stereo_camera`
702 UFBX_ELEMENT_CAMERA_SWITCHER, // < `ufbx_camera_switcher`
703 UFBX_ELEMENT_MARKER, // < `ufbx_marker`
704 UFBX_ELEMENT_LOD_GROUP, // < `ufbx_lod_group`
705 UFBX_ELEMENT_SKIN_DEFORMER, // < `ufbx_skin_deformer`
706 UFBX_ELEMENT_SKIN_CLUSTER, // < `ufbx_skin_cluster`
707 UFBX_ELEMENT_BLEND_DEFORMER, // < `ufbx_blend_deformer`
708 UFBX_ELEMENT_BLEND_CHANNEL, // < `ufbx_blend_channel`
709 UFBX_ELEMENT_BLEND_SHAPE, // < `ufbx_blend_shape`
710 UFBX_ELEMENT_CACHE_DEFORMER, // < `ufbx_cache_deformer`
711 UFBX_ELEMENT_CACHE_FILE, // < `ufbx_cache_file`
712 UFBX_ELEMENT_MATERIAL, // < `ufbx_material`
713 UFBX_ELEMENT_TEXTURE, // < `ufbx_texture`
714 UFBX_ELEMENT_VIDEO, // < `ufbx_video`
715 UFBX_ELEMENT_SHADER, // < `ufbx_shader`
716 UFBX_ELEMENT_SHADER_BINDING, // < `ufbx_shader_binding`
717 UFBX_ELEMENT_ANIM_STACK, // < `ufbx_anim_stack`
718 UFBX_ELEMENT_ANIM_LAYER, // < `ufbx_anim_layer`
719 UFBX_ELEMENT_ANIM_VALUE, // < `ufbx_anim_value`
720 UFBX_ELEMENT_ANIM_CURVE, // < `ufbx_anim_curve`
721 UFBX_ELEMENT_DISPLAY_LAYER, // < `ufbx_display_layer`
722 UFBX_ELEMENT_SELECTION_SET, // < `ufbx_selection_set`
723 UFBX_ELEMENT_SELECTION_NODE, // < `ufbx_selection_node`
724 UFBX_ELEMENT_CHARACTER, // < `ufbx_character`
725 UFBX_ELEMENT_CONSTRAINT, // < `ufbx_constraint`
726 UFBX_ELEMENT_AUDIO_LAYER, // < `ufbx_audio_layer`
727 UFBX_ELEMENT_AUDIO_CLIP, // < `ufbx_audio_clip`
728 UFBX_ELEMENT_POSE, // < `ufbx_pose`
729 UFBX_ELEMENT_METADATA_OBJECT, // < `ufbx_metadata_object`
730
731 UFBX_ELEMENT_TYPE_FIRST_ATTRIB = UFBX_ELEMENT_MESH,
732 UFBX_ELEMENT_TYPE_LAST_ATTRIB = UFBX_ELEMENT_LOD_GROUP,
733
734 UFBX_ENUM_FORCE_WIDTH(UFBX_ELEMENT_TYPE)
735} ufbx_element_type;
736
737UFBX_ENUM_TYPE(ufbx_element_type, UFBX_ELEMENT_TYPE, UFBX_ELEMENT_METADATA_OBJECT);
738
739// Connection between two elements.
740// Source and destination are somewhat arbitrary but the destination is
741// often the "container" like a parent node or mesh containing a deformer.
742typedef struct ufbx_connection {
743 ufbx_element *src;
744 ufbx_element *dst;
745 ufbx_string src_prop;
746 ufbx_string dst_prop;
748
749UFBX_LIST_TYPE(ufbx_connection_list, ufbx_connection);
750
751// Element "base-class" common to each element.
752// Some fields (like `connections_src`) are advanced and not visible
753// in the specialized element structs.
754// NOTE: The `element_id` value is consistent when loading the
755// _same_ file, but re-exporting the file will invalidate them.
757 ufbx_string name;
758 ufbx_props props;
759 uint32_t element_id;
760 uint32_t typed_id;
761 ufbx_node_list instances;
762 ufbx_element_type type;
763 ufbx_connection_list connections_src;
764 ufbx_connection_list connections_dst;
765 ufbx_nullable ufbx_dom_node *dom_node;
766 ufbx_scene *scene;
767};
768
769// -- Unknown
770
772 // Shared "base-class" header, see `ufbx_element`.
773 union { ufbx_element element; struct {
774 ufbx_string name;
775 ufbx_props props;
776 uint32_t element_id;
777 uint32_t typed_id;
778 }; };
779
780 // FBX format specific type information.
781 // In ASCII FBX format:
782 // super_type: ID, "type::name", "sub_type" { ... }
783 ufbx_string type;
784 ufbx_string super_type;
785 ufbx_string sub_type;
786};
787
788// -- Nodes
789
790// Inherit type specifies how hierarchial node transforms are combined.
791// This only affects the final scaling, as rotation and translation are always
792// inherited correctly.
793// NOTE: These don't map to `"InheritType"` property as there may be new ones for
794// compatibility with various exporters.
795typedef enum ufbx_inherit_mode UFBX_ENUM_REPR {
796
797 // Normal matrix composition of hierarchy: `R*S*r*s`.
798 // child.node_to_world = parent.node_to_world * child.node_to_parent;
799 UFBX_INHERIT_MODE_NORMAL,
800
801 // Ignore parent scale when computing the transform: `R*r*s`.
802 // ufbx_transform t = node.local_transform;
803 // t.translation *= parent.inherit_scale;
804 // t.scale *= node.inherit_scale_node.inherit_scale;
805 // child.node_to_world = parent.unscaled_node_to_world * t;
806 // Also known as "Segment scale compensate" in some software.
807 UFBX_INHERIT_MODE_IGNORE_PARENT_SCALE,
808
809 // Apply parent scale component-wise: `R*r*S*s`.
810 // ufbx_transform t = node.local_transform;
811 // t.translation *= parent.inherit_scale;
812 // t.scale *= node.inherit_scale_node.inherit_scale;
813 // child.node_to_world = parent.unscaled_node_to_world * t;
814 UFBX_INHERIT_MODE_COMPONENTWISE_SCALE,
815
816 UFBX_ENUM_FORCE_WIDTH(UFBX_INHERIT_MODE)
817} ufbx_inherit_mode;
818
819UFBX_ENUM_TYPE(ufbx_inherit_mode, UFBX_INHERIT_MODE, UFBX_INHERIT_MODE_COMPONENTWISE_SCALE);
820
821// Axis used to mirror transformations for handedness conversion.
822typedef enum ufbx_mirror_axis UFBX_ENUM_REPR {
823
824 UFBX_MIRROR_AXIS_NONE,
825 UFBX_MIRROR_AXIS_X,
826 UFBX_MIRROR_AXIS_Y,
827 UFBX_MIRROR_AXIS_Z,
828
829 UFBX_ENUM_FORCE_WIDTH(UFBX_MIRROR_AXIS)
830} ufbx_mirror_axis;
831
832UFBX_ENUM_TYPE(ufbx_mirror_axis, UFBX_MIRROR_AXIS, UFBX_MIRROR_AXIS_Z);
833
834// Nodes form the scene transformation hierarchy and can contain attached
835// elements such as meshes or lights. In normal cases a single `ufbx_node`
836// contains only a single attached element, so using `type/mesh/...` is safe.
837struct ufbx_node {
838 union { ufbx_element element; struct {
839 ufbx_string name;
840 ufbx_props props;
841 uint32_t element_id;
842 uint32_t typed_id;
843 }; };
844
845 // Node hierarchy
846
847 // Parent node containing this one if not root.
848 //
849 // Always non-`NULL` for non-root nodes unless
850 // `ufbx_load_opts.allow_nodes_out_of_root` is enabled.
851 ufbx_nullable ufbx_node *parent;
852
853 // List of child nodes parented to this node.
854 ufbx_node_list children;
855
856 // Common attached element type and typed pointers. Set to `NULL` if not in
857 // use, so checking `attrib_type` is not required.
858 //
859 // HINT: If you need less common attributes access `ufbx_node.attrib`, you
860 // can use utility functions like `ufbx_as_nurbs_curve(attrib)` to convert
861 // and check the attribute in one step.
862 ufbx_nullable ufbx_mesh *mesh;
863 ufbx_nullable ufbx_light *light;
864 ufbx_nullable ufbx_camera *camera;
865 ufbx_nullable ufbx_bone *bone;
866
867 // Less common attributes use these fields.
868 //
869 // Defined even if it is one of the above, eg. `ufbx_mesh`. In case there
870 // is multiple attributes this will be the first one.
871 ufbx_nullable ufbx_element *attrib;
872
873 // Geometry transform helper if one exists.
874 // See `UFBX_GEOMETRY_TRANSFORM_HANDLING_HELPER_NODES`.
875 ufbx_nullable ufbx_node *geometry_transform_helper;
876
877 // Scale helper if one exists.
878 // See `UFBX_INHERIT_MODE_HANDLING_HELPER_NODES`.
879 ufbx_nullable ufbx_node *scale_helper;
880
881 // `attrib->type` if `attrib` is defined, otherwise `UFBX_ELEMENT_UNKNOWN`.
882 ufbx_element_type attrib_type;
883
884 // List of _all_ attached attribute elements.
885 //
886 // In most cases there is only zero or one attributes per node, but if you
887 // have a very exotic FBX file nodes may have multiple attributes.
888 ufbx_element_list all_attribs;
889
890 // Local transform in parent, geometry transform is a non-inherited
891 // transform applied only to attachments like meshes
892 ufbx_inherit_mode inherit_mode;
893 ufbx_inherit_mode original_inherit_mode;
894 ufbx_transform local_transform;
895 ufbx_transform geometry_transform;
896
897 // Combined scale when using `UFBX_INHERIT_MODE_COMPONENTWISE_SCALE`.
898 // Contains `local_transform.scale` otherwise.
899 ufbx_vec3 inherit_scale;
900
901 // Node where scale is inherited from for `UFBX_INHERIT_MODE_COMPONENTWISE_SCALE`
902 // and even for `UFBX_INHERIT_MODE_IGNORE_PARENT_SCALE`.
903 // For componentwise-scale nodes, this will point to `parent`, for scale ignoring
904 // nodes this will point to the parent of the nearest componentwise-scaled node
905 // in the parent chain.
906 ufbx_nullable ufbx_node *inherit_scale_node;
907
908 // Raw Euler angles in degrees for those who want them
909
910 // Specifies the axis order `euler_rotation` is applied in.
911 ufbx_rotation_order rotation_order;
912 // Rotation around the local X/Y/Z axes in `rotation_order`.
913 // The angles are specified in degrees.
914 ufbx_vec3 euler_rotation;
915
916 // Matrices derived from the transformations, for transforming geometry
917 // prefer using `geometry_to_world` as that supports geometric transforms.
918
919 // Transform from this node to `parent` space.
920 // Equivalent to `ufbx_transform_to_matrix(&local_transform)`.
921 ufbx_matrix node_to_parent;
922 // Transform from this node to the world space, ie. multiplying all the
923 // `node_to_parent` matrices of the parent chain together.
924 ufbx_matrix node_to_world;
925 // Transform from the attribute to this node. Does not affect the transforms
926 // of `children`!
927 // Equivalent to `ufbx_transform_to_matrix(&geometry_transform)`.
928 ufbx_matrix geometry_to_node;
929 // Transform from attribute space to world space.
930 // Equivalent to `ufbx_matrix_mul(&node_to_world, &geometry_to_node)`.
931 ufbx_matrix geometry_to_world;
932 // Transform from this node to world space, ignoring self scaling.
933 ufbx_matrix unscaled_node_to_world;
934
935 // ufbx-specific adjustment for switching between coodrinate/unit systems.
936 // HINT: In most cases you don't need to deal with these as these are baked
937 // into all the transforms above and into `ufbx_evaluate_transform()`.
938 ufbx_vec3 adjust_pre_translation; // < Translation applied between parent and self
939 ufbx_quat adjust_pre_rotation; // < Rotation applied between parent and self
940 ufbx_real adjust_pre_scale; // < Scaling applied between parent and self
941 ufbx_quat adjust_post_rotation; // < Rotation applied in local space at the end
942 ufbx_real adjust_post_scale; // < Scaling applied in local space at the end
943 ufbx_real adjust_translation_scale; // < Scaling applied to translation only
944 ufbx_mirror_axis adjust_mirror_axis; // < Mirror translation and rotation on this axis
945
946 // Materials used by `mesh` or other `attrib`.
947 // There may be multiple copies of a single `ufbx_mesh` with different materials
948 // in the `ufbx_node` instances.
949 ufbx_material_list materials;
950
951 // Bind pose
952 ufbx_nullable ufbx_pose *bind_pose;
953
954 // Visibility state.
955 bool visible;
956
957 // True if this node is the implicit root node of the scene.
958 bool is_root;
959
960 // True if the node has a non-identity `geometry_transform`.
961 bool has_geometry_transform;
962
963 // If `true` the transform is adjusted by ufbx, not enabled by default.
964 // See `adjust_pre_rotation`, `adjust_pre_scale`, `adjust_post_rotation`,
965 // and `adjust_post_scale`.
966 bool has_adjust_transform;
967
968 // Scale is adjusted by root scale.
969 bool has_root_adjust_transform;
970
971 // True if this node is a synthetic geometry transform helper.
972 // See `UFBX_GEOMETRY_TRANSFORM_HANDLING_HELPER_NODES`.
973 bool is_geometry_transform_helper;
974
975 // True if the node is a synthetic scale compensation helper.
976 // See `UFBX_INHERIT_MODE_HANDLING_HELPER_NODES`.
977 bool is_scale_helper;
978
979 // Parent node to children that can compensate for parent scale.
980 bool is_scale_compensate_parent;
981
982 // How deep is this node in the parent hierarchy. Root node is at depth `0`
983 // and the immediate children of root at `1`.
984 uint32_t node_depth;
985};
986
987// Vertex attribute: All attributes are stored in a consistent indexed format
988// regardless of how it's actually stored in the file.
989//
990// `values` is a contiguous array of attribute values.
991// `indices` maps each mesh index into a value in the `values` array.
992//
993// If `unique_per_vertex` is set then the attribute is guaranteed to have a
994// single defined value per vertex accessible via:
995// attrib.values.data[attrib.indices.data[mesh->vertex_first_index[vertex_ix]]
996typedef struct ufbx_vertex_attrib {
997 // Is this attribute defined by the mesh.
998 bool exists;
999 // List of values the attribute uses.
1000 ufbx_void_list values;
1001 // Indices into `values[]`, indexed up to `ufbx_mesh.num_indices`.
1002 ufbx_uint32_list indices;
1003 // Number of `ufbx_real` entries per value.
1004 size_t value_reals;
1005 // `true` if this attribute is defined per vertex, instead of per index.
1006 bool unique_per_vertex;
1007 // Optional 4th 'W' component for the attribute.
1008 // May be defined for the following:
1009 // ufbx_mesh.vertex_normal
1010 // ufbx_mesh.vertex_tangent / ufbx_uv_set.vertex_tangent
1011 // ufbx_mesh.vertex_bitangent / ufbx_uv_set.vertex_bitangent
1012 // NOTE: This is not loaded by default, set `ufbx_load_opts.retain_vertex_attrib_w`.
1013 ufbx_real_list values_w;
1015
1016// 1D vertex attribute, see `ufbx_vertex_attrib` for information
1017typedef struct ufbx_vertex_real {
1018 bool exists;
1019 ufbx_real_list values;
1020 ufbx_uint32_list indices;
1021 size_t value_reals;
1022 bool unique_per_vertex;
1023 ufbx_real_list values_w;
1024
1025 UFBX_VERTEX_ATTRIB_IMPL(ufbx_real)
1027
1028// 2D vertex attribute, see `ufbx_vertex_attrib` for information
1029typedef struct ufbx_vertex_vec2 {
1030 bool exists;
1031 ufbx_vec2_list values;
1032 ufbx_uint32_list indices;
1033 size_t value_reals;
1034 bool unique_per_vertex;
1035 ufbx_real_list values_w;
1036
1037 UFBX_VERTEX_ATTRIB_IMPL(ufbx_vec2)
1039
1040// 3D vertex attribute, see `ufbx_vertex_attrib` for information
1041typedef struct ufbx_vertex_vec3 {
1042 bool exists;
1043 ufbx_vec3_list values;
1044 ufbx_uint32_list indices;
1045 size_t value_reals;
1046 bool unique_per_vertex;
1047 ufbx_real_list values_w;
1048
1049 UFBX_VERTEX_ATTRIB_IMPL(ufbx_vec3)
1051
1052// 4D vertex attribute, see `ufbx_vertex_attrib` for information
1053typedef struct ufbx_vertex_vec4 {
1054 bool exists;
1055 ufbx_vec4_list values;
1056 ufbx_uint32_list indices;
1057 size_t value_reals;
1058 bool unique_per_vertex;
1059 ufbx_real_list values_w;
1060
1061 UFBX_VERTEX_ATTRIB_IMPL(ufbx_vec4)
1063
1064// Vertex UV set/layer
1065typedef struct ufbx_uv_set {
1066 ufbx_string name;
1067 uint32_t index;
1068
1069 // Vertex attributes, see `ufbx_mesh` attributes for more information
1070 ufbx_vertex_vec2 vertex_uv; // < UV / texture coordinates
1071 ufbx_vertex_vec3 vertex_tangent; // < (optional) Tangent vector in UV.x direction
1072 ufbx_vertex_vec3 vertex_bitangent; // < (optional) Tangent vector in UV.y direction
1073} ufbx_uv_set;
1074
1075// Vertex color set/layer
1076typedef struct ufbx_color_set {
1077 ufbx_string name;
1078 uint32_t index;
1079
1080 // Vertex attributes, see `ufbx_mesh` attributes for more information
1081 ufbx_vertex_vec4 vertex_color; // < Per-vertex RGBA color
1083
1084UFBX_LIST_TYPE(ufbx_uv_set_list, ufbx_uv_set);
1085UFBX_LIST_TYPE(ufbx_color_set_list, ufbx_color_set);
1086
1087// Edge between two _indices_ in a mesh
1088typedef struct ufbx_edge {
1089 union {
1090 struct { uint32_t a, b; };
1091 uint32_t indices[2];
1092 };
1093} ufbx_edge;
1094
1095UFBX_LIST_TYPE(ufbx_edge_list, ufbx_edge);
1096
1097// Polygonal face with arbitrary number vertices, a single face contains a
1098// contiguous range of mesh indices, eg. `{5,3}` would have indices 5, 6, 7
1099//
1100// NOTE: `num_indices` maybe less than 3 in which case the face is invalid!
1101// [TODO #23: should probably remove the bad faces at load time]
1102typedef struct ufbx_face {
1103 uint32_t index_begin;
1104 uint32_t num_indices;
1105} ufbx_face;
1106
1107UFBX_LIST_TYPE(ufbx_face_list, ufbx_face);
1108
1109// Subset of mesh faces used by a single material or group.
1110typedef struct ufbx_mesh_part {
1111
1112 // Index of the mesh part.
1113 uint32_t index;
1114
1115 // Sub-set of the geometry
1116 size_t num_faces; // < Number of faces (polygons)
1117 size_t num_triangles; // < Number of triangles if triangulated
1118
1119 size_t num_empty_faces; // < Number of faces with zero vertices
1120 size_t num_point_faces; // < Number of faces with a single vertex
1121 size_t num_line_faces; // < Number of faces with two vertices
1122
1123 // Indices to `ufbx_mesh.faces[]`.
1124 // Always contains `num_faces` elements.
1125 ufbx_uint32_list face_indices;
1126
1128
1129UFBX_LIST_TYPE(ufbx_mesh_part_list, ufbx_mesh_part);
1130
1131typedef struct ufbx_face_group {
1132 int32_t id; // < Numerical ID for this group.
1133 ufbx_string name; // < Name for the face group.
1135
1136UFBX_LIST_TYPE(ufbx_face_group_list, ufbx_face_group);
1137
1139 uint32_t weight_begin;
1140 uint32_t num_weights;
1142
1143UFBX_LIST_TYPE(ufbx_subdivision_weight_range_list, ufbx_subdivision_weight_range);
1144
1146 ufbx_real weight;
1147 uint32_t index;
1149
1150UFBX_LIST_TYPE(ufbx_subdivision_weight_list, ufbx_subdivision_weight);
1151
1153 size_t result_memory_used;
1154 size_t temp_memory_used;
1155 size_t result_allocs;
1156 size_t temp_allocs;
1157
1158 // Weights of vertices in the source model.
1159 // Defined if `ufbx_subdivide_opts.evaluate_source_vertices` is set.
1160 ufbx_subdivision_weight_range_list source_vertex_ranges;
1161 ufbx_subdivision_weight_list source_vertex_weights;
1162
1163 // Weights of skin clusters in the source model.
1164 // Defined if `ufbx_subdivide_opts.evaluate_skin_weights` is set.
1165 ufbx_subdivision_weight_range_list skin_cluster_ranges;
1166 ufbx_subdivision_weight_list skin_cluster_weights;
1167
1169
1170typedef enum ufbx_subdivision_display_mode UFBX_ENUM_REPR {
1171 UFBX_SUBDIVISION_DISPLAY_DISABLED,
1172 UFBX_SUBDIVISION_DISPLAY_HULL,
1173 UFBX_SUBDIVISION_DISPLAY_HULL_AND_SMOOTH,
1174 UFBX_SUBDIVISION_DISPLAY_SMOOTH,
1175
1176 UFBX_ENUM_FORCE_WIDTH(UFBX_SUBDIVISION_DISPLAY_MODE)
1177} ufbx_subdivision_display_mode;
1178
1179UFBX_ENUM_TYPE(ufbx_subdivision_display_mode, UFBX_SUBDIVISION_DISPLAY_MODE, UFBX_SUBDIVISION_DISPLAY_SMOOTH);
1180
1181typedef enum ufbx_subdivision_boundary UFBX_ENUM_REPR {
1182 UFBX_SUBDIVISION_BOUNDARY_DEFAULT,
1183 UFBX_SUBDIVISION_BOUNDARY_LEGACY,
1184 // OpenSubdiv: `VTX_BOUNDARY_EDGE_AND_CORNER` / `FVAR_LINEAR_CORNERS_ONLY`
1185 UFBX_SUBDIVISION_BOUNDARY_SHARP_CORNERS,
1186 // OpenSubdiv: `VTX_BOUNDARY_EDGE_ONLY` / `FVAR_LINEAR_NONE`
1187 UFBX_SUBDIVISION_BOUNDARY_SHARP_NONE,
1188 // OpenSubdiv: `FVAR_LINEAR_BOUNDARIES`
1189 UFBX_SUBDIVISION_BOUNDARY_SHARP_BOUNDARY,
1190 // OpenSubdiv: `FVAR_LINEAR_ALL`
1191 UFBX_SUBDIVISION_BOUNDARY_SHARP_INTERIOR,
1192
1193 UFBX_ENUM_FORCE_WIDTH(UFBX_SUBDIVISION_BOUNDARY)
1194} ufbx_subdivision_boundary;
1195
1196UFBX_ENUM_TYPE(ufbx_subdivision_boundary, UFBX_SUBDIVISION_BOUNDARY, UFBX_SUBDIVISION_BOUNDARY_SHARP_INTERIOR);
1197
1198// Polygonal mesh geometry.
1199//
1200// Example mesh with two triangles (x, z) and a quad (y).
1201// The faces have a constant UV coordinate x/y/z.
1202// The vertices have _per vertex_ normals that point up/down.
1203//
1204// ^ ^ ^
1205// A---B-----C
1206// |x / /|
1207// | / y / |
1208// |/ / z|
1209// D-----E---F
1210// v v v
1211//
1212// Attributes may have multiple values within a single vertex, for example a
1213// UV seam vertex has two UV coordinates. Thus polygons are defined using
1214// an index that counts each corner of each face polygon. If an attribute is
1215// defined (even per-vertex) it will always have a valid `indices` array.
1216//
1217// {0,3} {3,4} {7,3} faces ({ index_begin, num_indices })
1218// 0 1 2 3 4 5 6 7 8 9 index
1219//
1220// 0 1 3 1 2 4 3 2 4 5 vertex_indices[index]
1221// A B D B C E D C E F vertices[vertex_indices[index]]
1222//
1223// 0 0 1 0 0 1 1 0 1 1 vertex_normal.indices[index]
1224// ^ ^ v ^ ^ v v ^ v v vertex_normal.data[vertex_normal.indices[index]]
1225//
1226// 0 0 0 1 1 1 1 2 2 2 vertex_uv.indices[index]
1227// x x x y y y y z z z vertex_uv.data[vertex_uv.indices[index]]
1228//
1229// Vertex position can also be accessed uniformly through an accessor:
1230// 0 1 3 1 2 4 3 2 4 5 vertex_position.indices[index]
1231// A B D B C E D C E F vertex_position.data[vertex_position.indices[index]]
1232//
1233// Some geometry data is specified per logical vertex. Vertex positions are
1234// the only attribute that is guaranteed to be defined _uniquely_ per vertex.
1235// Vertex attributes _may_ be defined per vertex if `unique_per_vertex == true`.
1236// You can access the per-vertex values by first finding the first index that
1237// refers to the given vertex.
1238//
1239// 0 1 2 3 4 5 vertex
1240// A B C D E F vertices[vertex]
1241//
1242// 0 1 4 2 5 9 vertex_first_index[vertex]
1243// 0 0 0 1 1 1 vertex_normal.indices[vertex_first_index[vertex]]
1244// ^ ^ ^ v v v vertex_normal.data[vertex_normal.indices[vertex_first_index[vertex]]]
1245//
1247 union { ufbx_element element; struct {
1248 ufbx_string name;
1249 ufbx_props props;
1250 uint32_t element_id;
1251 uint32_t typed_id;
1252 ufbx_node_list instances;
1253 }; };
1254
1255 // Number of "logical" vertices that would be treated as a single point,
1256 // one vertex may be split to multiple indices for split attributes, eg. UVs
1257 size_t num_vertices; // < Number of logical "vertex" points
1258 size_t num_indices; // < Number of combiend vertex/attribute tuples
1259 size_t num_faces; // < Number of faces (polygons) in the mesh
1260 size_t num_triangles; // < Number of triangles if triangulated
1261
1262 // Number of edges in the mesh.
1263 // NOTE: May be zero in valid meshes if the file doesn't contain edge adjacency data!
1264 size_t num_edges;
1265
1266 size_t max_face_triangles; // < Maximum number of triangles in a face in this mesh
1267
1268 size_t num_empty_faces; // < Number of faces with zero vertices
1269 size_t num_point_faces; // < Number of faces with a single vertex
1270 size_t num_line_faces; // < Number of faces with two vertices
1271
1272 // Faces and optional per-face extra data
1273 ufbx_face_list faces; // < Face index range
1274 ufbx_bool_list face_smoothing; // < Should the face have soft normals
1275 ufbx_uint32_list face_material; // < Indices to `ufbx_mesh.materials[]` and `ufbx_node.materials[]`
1276 ufbx_uint32_list face_group; // < Face polygon group index, indices to `ufbx_mesh.face_groups[]`
1277 ufbx_bool_list face_hole; // < Should the face be hidden as a "hole"
1278
1279 // Edges and optional per-edge extra data
1280 ufbx_edge_list edges; // < Edge index range
1281 ufbx_bool_list edge_smoothing; // < Should the edge have soft normals
1282 ufbx_real_list edge_crease; // < Crease value for subdivision surfaces
1283 ufbx_bool_list edge_visibility; // < Should the edge be visible
1284
1285 // Logical vertices and positions, alternatively you can use
1286 // `vertex_position` for consistent interface with other attributes.
1287 ufbx_uint32_list vertex_indices;
1288 ufbx_vec3_list vertices;
1289
1290 // First index referring to a given vertex, `UFBX_NO_INDEX` if the vertex is unused.
1291 ufbx_uint32_list vertex_first_index;
1292
1293 // Vertex attributes, see the comment over the struct.
1294 //
1295 // NOTE: Not all meshes have all attributes, in that case `indices/data == NULL`!
1296 //
1297 // NOTE: UV/tangent/bitangent and color are the from first sets,
1298 // use `uv_sets/color_sets` to access the other layers.
1299 ufbx_vertex_vec3 vertex_position; // < Vertex positions
1300 ufbx_vertex_vec3 vertex_normal; // < (optional) Normal vectors, always defined if `ufbx_load_opts.generate_missing_normals`
1301 ufbx_vertex_vec2 vertex_uv; // < (optional) UV / texture coordinates
1302 ufbx_vertex_vec3 vertex_tangent; // < (optional) Tangent vector in UV.x direction
1303 ufbx_vertex_vec3 vertex_bitangent; // < (optional) Tangent vector in UV.y direction
1304 ufbx_vertex_vec4 vertex_color; // < (optional) Per-vertex RGBA color
1305 ufbx_vertex_real vertex_crease; // < (optional) Crease value for subdivision surfaces
1306
1307 // Multiple named UV/color sets
1308 // NOTE: The first set contains the same data as `vertex_uv/color`!
1309 ufbx_uv_set_list uv_sets;
1310 ufbx_color_set_list color_sets;
1311
1312 // Materials used by the mesh.
1313 // NOTE: These can be wrong if you want to support per-instance materials!
1314 // Use `ufbx_node.materials[]` to get the per-instance materials at the same indices.
1315 ufbx_material_list materials;
1316
1317 // Face groups for this mesh.
1318 ufbx_face_group_list face_groups;
1319
1320 // Segments that use a given material.
1321 // Defined even if the mesh doesn't have any materials.
1322 ufbx_mesh_part_list material_parts;
1323
1324 // Segments for each face group.
1325 ufbx_mesh_part_list face_group_parts;
1326
1327 // Order of `material_parts` by first face that refers to it.
1328 // Useful for compatibility with FBX SDK and various importers using it,
1329 // as they use this material order by default.
1330 ufbx_uint32_list material_part_usage_order;
1331
1332 // Skinned vertex positions, for efficiency the skinned positions are the
1333 // same as the static ones for non-skinned meshes and `skinned_is_local`
1334 // is set to true meaning you need to transform them manually using
1335 // `ufbx_transform_position(&node->geometry_to_world, skinned_pos)`!
1336 bool skinned_is_local;
1337 ufbx_vertex_vec3 skinned_position;
1338 ufbx_vertex_vec3 skinned_normal;
1339
1340 // Deformers
1341 ufbx_skin_deformer_list skin_deformers;
1342 ufbx_blend_deformer_list blend_deformers;
1343 ufbx_cache_deformer_list cache_deformers;
1344 ufbx_element_list all_deformers;
1345
1346 // Subdivision
1347 uint32_t subdivision_preview_levels;
1348 uint32_t subdivision_render_levels;
1349 ufbx_subdivision_display_mode subdivision_display_mode;
1350 ufbx_subdivision_boundary subdivision_boundary;
1351 ufbx_subdivision_boundary subdivision_uv_boundary;
1352
1353 // The winding of the faces has been reversed.
1354 bool reversed_winding;
1355
1356 // Normals have been generated instead of evalauted.
1357 // Either from missing normals (via `ufbx_load_opts.generate_missing_normals`), skinning,
1358 // tessellation, or subdivision.
1359 bool generated_normals;
1360
1361 // Subdivision (result)
1362 bool subdivision_evaluated;
1363 ufbx_nullable ufbx_subdivision_result *subdivision_result;
1364
1365 // Tessellation (result)
1366 bool from_tessellated_nurbs;
1367};
1368
1369// The kind of light source
1370typedef enum ufbx_light_type UFBX_ENUM_REPR {
1371 // Single point at local origin, at `node->world_transform.position`
1372 UFBX_LIGHT_POINT,
1373 // Infinite directional light pointing locally towards `light->local_direction`
1374 // For global: `ufbx_transform_direction(&node->node_to_world, light->local_direction)`
1375 UFBX_LIGHT_DIRECTIONAL,
1376 // Cone shaped light towards `light->local_direction`, between `light->inner/outer_angle`.
1377 // For global: `ufbx_transform_direction(&node->node_to_world, light->local_direction)`
1378 UFBX_LIGHT_SPOT,
1379 // Area light, shape specified by `light->area_shape`
1380 // TODO: Units?
1381 UFBX_LIGHT_AREA,
1382 // Volumetric light source
1383 // TODO: How does this work
1384 UFBX_LIGHT_VOLUME,
1385
1386 UFBX_ENUM_FORCE_WIDTH(UFBX_LIGHT_TYPE)
1387} ufbx_light_type;
1388
1389UFBX_ENUM_TYPE(ufbx_light_type, UFBX_LIGHT_TYPE, UFBX_LIGHT_VOLUME);
1390
1391// How fast does the light intensity decay at a distance
1392typedef enum ufbx_light_decay UFBX_ENUM_REPR {
1393 UFBX_LIGHT_DECAY_NONE, // < 1 (no decay)
1394 UFBX_LIGHT_DECAY_LINEAR, // < 1 / d
1395 UFBX_LIGHT_DECAY_QUADRATIC, // < 1 / d^2 (physically accurate)
1396 UFBX_LIGHT_DECAY_CUBIC, // < 1 / d^3
1397
1398 UFBX_ENUM_FORCE_WIDTH(UFBX_LIGHT_DECAY)
1399} ufbx_light_decay;
1400
1401UFBX_ENUM_TYPE(ufbx_light_decay, UFBX_LIGHT_DECAY, UFBX_LIGHT_DECAY_CUBIC);
1402
1403typedef enum ufbx_light_area_shape UFBX_ENUM_REPR {
1404 UFBX_LIGHT_AREA_SHAPE_RECTANGLE,
1405 UFBX_LIGHT_AREA_SHAPE_SPHERE,
1406
1407 UFBX_ENUM_FORCE_WIDTH(UFBX_LIGHT_AREA_SHAPE)
1408} ufbx_light_area_shape;
1409
1410UFBX_ENUM_TYPE(ufbx_light_area_shape, UFBX_LIGHT_AREA_SHAPE, UFBX_LIGHT_AREA_SHAPE_SPHERE);
1411
1412// Light source attached to a `ufbx_node`
1414 union { ufbx_element element; struct {
1415 ufbx_string name;
1416 ufbx_props props;
1417 uint32_t element_id;
1418 uint32_t typed_id;
1419 ufbx_node_list instances;
1420 }; };
1421
1422 // Color and intensity of the light, usually you want to use `color * intensity`
1423 // NOTE: `intensity` is 0.01x of the property `"Intensity"` as that matches
1424 // matches values in DCC programs before exporting.
1425 ufbx_vec3 color;
1426 ufbx_real intensity;
1427
1428 // Direction the light is aimed at in node's local space, usually -Y
1429 ufbx_vec3 local_direction;
1430
1431 // Type of the light and shape parameters
1432 ufbx_light_type type;
1433 ufbx_light_decay decay;
1434 ufbx_light_area_shape area_shape;
1435 ufbx_real inner_angle;
1436 ufbx_real outer_angle;
1437
1438 bool cast_light;
1439 bool cast_shadows;
1440};
1441
1442typedef enum ufbx_projection_mode UFBX_ENUM_REPR {
1443 // Perspective projection.
1444 UFBX_PROJECTION_MODE_PERSPECTIVE,
1445
1446 // Orthographic projection.
1447 UFBX_PROJECTION_MODE_ORTHOGRAPHIC,
1448
1449 UFBX_ENUM_FORCE_WIDTH(UFBX_PROJECTION_MODE)
1450} ufbx_projection_mode;
1451
1452UFBX_ENUM_TYPE(ufbx_projection_mode, UFBX_PROJECTION_MODE, UFBX_PROJECTION_MODE_ORTHOGRAPHIC);
1453
1454// Method of specifying the rendering resolution from properties
1455// NOTE: Handled internally by ufbx, ignore unless you interpret `ufbx_props` directly!
1456typedef enum ufbx_aspect_mode UFBX_ENUM_REPR {
1457 // No defined resolution
1458 UFBX_ASPECT_MODE_WINDOW_SIZE,
1459 // `"AspectWidth"` and `"AspectHeight"` are relative to each other
1460 UFBX_ASPECT_MODE_FIXED_RATIO,
1461 // `"AspectWidth"` and `"AspectHeight"` are both pixels
1462 UFBX_ASPECT_MODE_FIXED_RESOLUTION,
1463 // `"AspectWidth"` is pixels, `"AspectHeight"` is relative to width
1464 UFBX_ASPECT_MODE_FIXED_WIDTH,
1465 // < `"AspectHeight"` is pixels, `"AspectWidth"` is relative to height
1466 UFBX_ASPECT_MODE_FIXED_HEIGHT,
1467
1468 UFBX_ENUM_FORCE_WIDTH(UFBX_ASPECT_MODE)
1469} ufbx_aspect_mode;
1470
1471UFBX_ENUM_TYPE(ufbx_aspect_mode, UFBX_ASPECT_MODE, UFBX_ASPECT_MODE_FIXED_HEIGHT);
1472
1473// Method of specifying the field of view from properties
1474// NOTE: Handled internally by ufbx, ignore unless you interpret `ufbx_props` directly!
1475typedef enum ufbx_aperture_mode UFBX_ENUM_REPR {
1476 // Use separate `"FieldOfViewX"` and `"FieldOfViewY"` as horizontal/vertical FOV angles
1477 UFBX_APERTURE_MODE_HORIZONTAL_AND_VERTICAL,
1478 // Use `"FieldOfView"` as horizontal FOV angle, derive vertical angle via aspect ratio
1479 UFBX_APERTURE_MODE_HORIZONTAL,
1480 // Use `"FieldOfView"` as vertical FOV angle, derive horizontal angle via aspect ratio
1481 UFBX_APERTURE_MODE_VERTICAL,
1482 // Compute the field of view from the render gate size and focal length
1483 UFBX_APERTURE_MODE_FOCAL_LENGTH,
1484
1485 UFBX_ENUM_FORCE_WIDTH(UFBX_APERTURE_MODE)
1486} ufbx_aperture_mode;
1487
1488UFBX_ENUM_TYPE(ufbx_aperture_mode, UFBX_APERTURE_MODE, UFBX_APERTURE_MODE_FOCAL_LENGTH);
1489
1490// Method of specifying the render gate size from properties
1491// NOTE: Handled internally by ufbx, ignore unless you interpret `ufbx_props` directly!
1492typedef enum ufbx_gate_fit UFBX_ENUM_REPR {
1493 // Use the film/aperture size directly as the render gate
1494 UFBX_GATE_FIT_NONE,
1495 // Fit the render gate to the height of the film, derive width from aspect ratio
1496 UFBX_GATE_FIT_VERTICAL,
1497 // Fit the render gate to the width of the film, derive height from aspect ratio
1498 UFBX_GATE_FIT_HORIZONTAL,
1499 // Fit the render gate so that it is fully contained within the film gate
1500 UFBX_GATE_FIT_FILL,
1501 // Fit the render gate so that it fully contains the film gate
1502 UFBX_GATE_FIT_OVERSCAN,
1503 // Stretch the render gate to match the film gate
1504 // TODO: Does this differ from `UFBX_GATE_FIT_NONE`?
1505 UFBX_GATE_FIT_STRETCH,
1506
1507 UFBX_ENUM_FORCE_WIDTH(UFBX_GATE_FIT)
1508} ufbx_gate_fit;
1509
1510UFBX_ENUM_TYPE(ufbx_gate_fit, UFBX_GATE_FIT, UFBX_GATE_FIT_STRETCH);
1511
1512// Camera film/aperture size defaults
1513// NOTE: Handled internally by ufbx, ignore unless you interpret `ufbx_props` directly!
1514typedef enum ufbx_aperture_format UFBX_ENUM_REPR {
1515 UFBX_APERTURE_FORMAT_CUSTOM, // < Use `"FilmWidth"` and `"FilmHeight"`
1516 UFBX_APERTURE_FORMAT_16MM_THEATRICAL, // < 0.404 x 0.295 inches
1517 UFBX_APERTURE_FORMAT_SUPER_16MM, // < 0.493 x 0.292 inches
1518 UFBX_APERTURE_FORMAT_35MM_ACADEMY, // < 0.864 x 0.630 inches
1519 UFBX_APERTURE_FORMAT_35MM_TV_PROJECTION, // < 0.816 x 0.612 inches
1520 UFBX_APERTURE_FORMAT_35MM_FULL_APERTURE, // < 0.980 x 0.735 inches
1521 UFBX_APERTURE_FORMAT_35MM_185_PROJECTION, // < 0.825 x 0.446 inches
1522 UFBX_APERTURE_FORMAT_35MM_ANAMORPHIC, // < 0.864 x 0.732 inches (squeeze ratio: 2)
1523 UFBX_APERTURE_FORMAT_70MM_PROJECTION, // < 2.066 x 0.906 inches
1524 UFBX_APERTURE_FORMAT_VISTAVISION, // < 1.485 x 0.991 inches
1525 UFBX_APERTURE_FORMAT_DYNAVISION, // < 2.080 x 1.480 inches
1526 UFBX_APERTURE_FORMAT_IMAX, // < 2.772 x 2.072 inches
1527
1528 UFBX_ENUM_FORCE_WIDTH(UFBX_APERTURE_FORMAT)
1529} ufbx_aperture_format;
1530
1531UFBX_ENUM_TYPE(ufbx_aperture_format, UFBX_APERTURE_FORMAT, UFBX_APERTURE_FORMAT_IMAX);
1532
1533typedef enum ufbx_coordinate_axis UFBX_ENUM_REPR {
1534 UFBX_COORDINATE_AXIS_POSITIVE_X,
1535 UFBX_COORDINATE_AXIS_NEGATIVE_X,
1536 UFBX_COORDINATE_AXIS_POSITIVE_Y,
1537 UFBX_COORDINATE_AXIS_NEGATIVE_Y,
1538 UFBX_COORDINATE_AXIS_POSITIVE_Z,
1539 UFBX_COORDINATE_AXIS_NEGATIVE_Z,
1540 UFBX_COORDINATE_AXIS_UNKNOWN,
1541
1542 UFBX_ENUM_FORCE_WIDTH(UFBX_COORDINATE_AXIS)
1543} ufbx_coordinate_axis;
1544
1545UFBX_ENUM_TYPE(ufbx_coordinate_axis, UFBX_COORDINATE_AXIS, UFBX_COORDINATE_AXIS_UNKNOWN);
1546
1547// Coordinate axes the scene is represented in.
1548// NOTE: `front` is the _opposite_ from forward!
1549typedef struct ufbx_coordinate_axes {
1550 ufbx_coordinate_axis right;
1551 ufbx_coordinate_axis up;
1552 ufbx_coordinate_axis front;
1554
1555// Camera attached to a `ufbx_node`
1557 union { ufbx_element element; struct {
1558 ufbx_string name;
1559 ufbx_props props;
1560 uint32_t element_id;
1561 uint32_t typed_id;
1562 ufbx_node_list instances;
1563 }; };
1564
1565 // Projection mode (perspective/orthographic).
1566 ufbx_projection_mode projection_mode;
1567
1568 // If set to `true`, `resolution` reprensents actual pixel values, otherwise
1569 // it's only useful for its aspect ratio.
1570 bool resolution_is_pixels;
1571
1572 // Render resolution, either in pixels or arbitrary units, depending on above
1573 ufbx_vec2 resolution;
1574
1575 // Horizontal/vertical field of view in degrees
1576 // Valid if `projection_mode == UFBX_PROJECTION_MODE_PERSPECTIVE`.
1577 ufbx_vec2 field_of_view_deg;
1578
1579 // Component-wise `tan(field_of_view_deg)`, also represents the size of the
1580 // proection frustum slice at distance of 1.
1581 // Valid if `projection_mode == UFBX_PROJECTION_MODE_PERSPECTIVE`.
1582 ufbx_vec2 field_of_view_tan;
1583
1584 // Orthographic camera extents.
1585 // Valid if `projection_mode == UFBX_PROJECTION_MODE_ORTHOGRAPHIC`.
1586 ufbx_real orthographic_extent;
1587
1588 // Orthographic camera size.
1589 // Valid if `projection_mode == UFBX_PROJECTION_MODE_ORTHOGRAPHIC`.
1590 ufbx_vec2 orthographic_size;
1591
1592 // Size of the projection plane at distance 1.
1593 // Equal to `field_of_view_tan` if perspective, `orthographic_size` if orthographic.
1594 ufbx_vec2 projection_plane;
1595
1596 // Aspect ratio of the camera.
1597 ufbx_real aspect_ratio;
1598
1599 // Near plane of the frustum in units from the camera.
1600 ufbx_real near_plane;
1601
1602 // Far plane of the frustum in units from the camera.
1603 ufbx_real far_plane;
1604
1605 // Coordinate system that the projection uses.
1606 // FBX saves cameras with +X forward and +Y up, but you can override this using
1607 // `ufbx_load_opts.target_camera_axes` and it will be reflected here.
1608 ufbx_coordinate_axes projection_axes;
1609
1610 // Advanced properties used to compute the above
1611 ufbx_aspect_mode aspect_mode;
1612 ufbx_aperture_mode aperture_mode;
1613 ufbx_gate_fit gate_fit;
1614 ufbx_aperture_format aperture_format;
1615 ufbx_real focal_length_mm; // < Focal length in millimeters
1616 ufbx_vec2 film_size_inch; // < Film size in inches
1617 ufbx_vec2 aperture_size_inch; // < Aperture/film gate size in inches
1618 ufbx_real squeeze_ratio; // < Anamoprhic stretch ratio
1619};
1620
1621// Bone attached to a `ufbx_node`, provides the logical length of the bone
1622// but most interesting information is directly in `ufbx_node`.
1624 union { ufbx_element element; struct {
1625 ufbx_string name;
1626 ufbx_props props;
1627 uint32_t element_id;
1628 uint32_t typed_id;
1629 ufbx_node_list instances;
1630 }; };
1631
1632 // Visual radius of the bone
1633 ufbx_real radius;
1634
1635 // Length of the bone relative to the distance between two nodes
1636 ufbx_real relative_length;
1637
1638 // Is the bone a root bone
1639 bool is_root;
1640};
1641
1642// Empty/NULL/locator connected to a node, actual details in `ufbx_node`
1644 union { ufbx_element element; struct {
1645 ufbx_string name;
1646 ufbx_props props;
1647 uint32_t element_id;
1648 uint32_t typed_id;
1649 ufbx_node_list instances;
1650 }; };
1651};
1652
1653// -- Node attributes (curves/surfaces)
1654
1655// Segment of a `ufbx_line_curve`, indices refer to `ufbx_line_curve.point_indices[]`
1656typedef struct ufbx_line_segment {
1657 uint32_t index_begin;
1658 uint32_t num_indices;
1660
1661UFBX_LIST_TYPE(ufbx_line_segment_list, ufbx_line_segment);
1662
1664 union { ufbx_element element; struct {
1665 ufbx_string name;
1666 ufbx_props props;
1667 uint32_t element_id;
1668 uint32_t typed_id;
1669 ufbx_node_list instances;
1670 }; };
1671
1672 ufbx_vec3 color;
1673
1674 ufbx_vec3_list control_points; // < List of possible values the line passes through
1675 ufbx_uint32_list point_indices; // < Indices to `control_points[]` the line goes through
1676
1677 ufbx_line_segment_list segments;
1678
1679 // Tessellation (result)
1680 bool from_tessellated_nurbs;
1681};
1682
1683typedef enum ufbx_nurbs_topology UFBX_ENUM_REPR {
1684 // The endpoints are not connected.
1685 UFBX_NURBS_TOPOLOGY_OPEN,
1686 // Repeats first `ufbx_nurbs_basis.order - 1` control points after the end.
1687 UFBX_NURBS_TOPOLOGY_PERIODIC,
1688 // Repeats the first control point after the end.
1689 UFBX_NURBS_TOPOLOGY_CLOSED,
1690
1691 UFBX_ENUM_FORCE_WIDTH(UFBX_NURBS_TOPOLOGY)
1692} ufbx_nurbs_topology;
1693
1694UFBX_ENUM_TYPE(ufbx_nurbs_topology, UFBX_NURBS_TOPOLOGY, UFBX_NURBS_TOPOLOGY_CLOSED);
1695
1696// NURBS basis functions for an axis
1697typedef struct ufbx_nurbs_basis {
1698
1699 // Number of control points influencing a point on the curve/surface.
1700 // Equal to the degree plus one.
1701 uint32_t order;
1702
1703 // Topology (periodicity) of the dimension.
1704 ufbx_nurbs_topology topology;
1705
1706 // Subdivision of the parameter range to control points.
1707 ufbx_real_list knot_vector;
1708
1709 // Range for the parameter value.
1710 ufbx_real t_min;
1711 ufbx_real t_max;
1712
1713 // Parameter values of control points.
1714 ufbx_real_list spans;
1715
1716 // `true` if this axis is two-dimensional.
1717 bool is_2d;
1718
1719 // Number of control points that need to be copied to the end.
1720 // This is just for convenience as it could be derived from `topology` and
1721 // `order`. If for example `num_wrap_control_points == 3` you should repeat
1722 // the first 3 control points after the end.
1723 // HINT: You don't need to worry about this if you use ufbx functions
1724 // like `ufbx_evaluate_nurbs_curve()` as they handle this internally.
1725 size_t num_wrap_control_points;
1726
1727 // `true` if the parametrization is well defined.
1728 bool valid;
1729
1731
1733 union { ufbx_element element; struct {
1734 ufbx_string name;
1735 ufbx_props props;
1736 uint32_t element_id;
1737 uint32_t typed_id;
1738 ufbx_node_list instances;
1739 }; };
1740
1741 // Basis in the U axis
1742 ufbx_nurbs_basis basis;
1743
1744 // Linear array of control points
1745 // NOTE: The control points are _not_ homogeneous, meaning you have to multiply
1746 // them by `w` before evaluating the surface.
1747 ufbx_vec4_list control_points;
1748};
1749
1751 union { ufbx_element element; struct {
1752 ufbx_string name;
1753 ufbx_props props;
1754 uint32_t element_id;
1755 uint32_t typed_id;
1756 ufbx_node_list instances;
1757 }; };
1758
1759 // Basis in the U/V axes
1760 ufbx_nurbs_basis basis_u;
1761 ufbx_nurbs_basis basis_v;
1762
1763 // Number of control points for the U/V axes
1764 size_t num_control_points_u;
1765 size_t num_control_points_v;
1766
1767 // 2D array of control points.
1768 // Memory layout: `V * num_control_points_u + U`
1769 // NOTE: The control points are _not_ homogeneous, meaning you have to multiply
1770 // them by `w` before evaluating the surface.
1771 ufbx_vec4_list control_points;
1772
1773 // How many segments tessellate each span in `ufbx_nurbs_basis.spans`.
1774 uint32_t span_subdivision_u;
1775 uint32_t span_subdivision_v;
1776
1777 // If `true` the resulting normals should be flipped when evaluated.
1778 bool flip_normals;
1779
1780 // Material for the whole surface.
1781 // NOTE: May be `NULL`!
1782 ufbx_nullable ufbx_material *material;
1783};
1784
1786 union { ufbx_element element; struct {
1787 ufbx_string name;
1788 ufbx_props props;
1789 uint32_t element_id;
1790 uint32_t typed_id;
1791 ufbx_node_list instances;
1792 }; };
1793};
1794
1796 union { ufbx_element element; struct {
1797 ufbx_string name;
1798 ufbx_props props;
1799 uint32_t element_id;
1800 uint32_t typed_id;
1801 ufbx_node_list instances;
1802 }; };
1803};
1804
1805// -- Node attributes (advanced)
1806
1808 union { ufbx_element element; struct {
1809 ufbx_string name;
1810 ufbx_props props;
1811 uint32_t element_id;
1812 uint32_t typed_id;
1813 ufbx_node_list instances;
1814 }; };
1815};
1816
1818 union { ufbx_element element; struct {
1819 ufbx_string name;
1820 ufbx_props props;
1821 uint32_t element_id;
1822 uint32_t typed_id;
1823 ufbx_node_list instances;
1824 }; };
1825
1826 ufbx_nullable ufbx_camera *left;
1827 ufbx_nullable ufbx_camera *right;
1828};
1829
1831 union { ufbx_element element; struct {
1832 ufbx_string name;
1833 ufbx_props props;
1834 uint32_t element_id;
1835 uint32_t typed_id;
1836 ufbx_node_list instances;
1837 }; };
1838};
1839
1840typedef enum ufbx_marker_type UFBX_ENUM_REPR {
1841 UFBX_MARKER_UNKNOWN, // < Unknown marker type
1842 UFBX_MARKER_FK_EFFECTOR, // < FK (Forward Kinematics) effector
1843 UFBX_MARKER_IK_EFFECTOR, // < IK (Inverse Kinematics) effector
1844
1845 UFBX_ENUM_FORCE_WIDTH(UFBX_MARKER_TYPE)
1846} ufbx_marker_type;
1847
1848UFBX_ENUM_TYPE(ufbx_marker_type, UFBX_MARKER_TYPE, UFBX_MARKER_IK_EFFECTOR);
1849
1850// Tracking marker for effectors
1852 union { ufbx_element element; struct {
1853 ufbx_string name;
1854 ufbx_props props;
1855 uint32_t element_id;
1856 uint32_t typed_id;
1857 ufbx_node_list instances;
1858 }; };
1859
1860 // Type of the marker
1861 ufbx_marker_type type;
1862};
1863
1864// LOD level display mode.
1865typedef enum ufbx_lod_display UFBX_ENUM_REPR {
1866 UFBX_LOD_DISPLAY_USE_LOD, // < Display the LOD level if the distance is appropriate.
1867 UFBX_LOD_DISPLAY_SHOW, // < Always display the LOD level.
1868 UFBX_LOD_DISPLAY_HIDE, // < Never display the LOD level.
1869
1870 UFBX_ENUM_FORCE_WIDTH(UFBX_LOD_DISPLAY)
1871} ufbx_lod_display;
1872
1873UFBX_ENUM_TYPE(ufbx_lod_display, UFBX_LOD_DISPLAY, UFBX_LOD_DISPLAY_HIDE);
1874
1875// Single LOD level within an LOD group.
1876// Specifies properties of the Nth child of the _node_ containing the LOD group.
1877typedef struct ufbx_lod_level {
1878
1879 // Minimum distance to show this LOD level.
1880 // NOTE: In world units by default, or in screen percentage if
1881 // `ufbx_lod_group.relative_distances` is set.
1882 ufbx_real distance;
1883
1884 // LOD display mode.
1885 // NOTE: Mostly for editing, you should probably ignore this
1886 // unless making a modeling program.
1887 ufbx_lod_display display;
1888
1890
1891UFBX_LIST_TYPE(ufbx_lod_level_list, ufbx_lod_level);
1892
1893// Group of LOD (Level of Detail) levels for an object.
1894// The actual LOD models are defined in the parent `ufbx_node.children`.
1896 union { ufbx_element element; struct {
1897 ufbx_string name;
1898 ufbx_props props;
1899 uint32_t element_id;
1900 uint32_t typed_id;
1901 ufbx_node_list instances;
1902 }; };
1903
1904 // If set to `true`, `ufbx_lod_level.distance` represents a screen size percentage.
1905 bool relative_distances;
1906
1907 // LOD levels matching in order to `ufbx_node.children`.
1908 ufbx_lod_level_list lod_levels;
1909
1910 // If set to `true` don't account for parent transform when computing the distance.
1911 bool ignore_parent_transform;
1912
1913 // If `use_distance_limit` is enabled hide the group if the distance is not between
1914 // `distance_limit_min` and `distance_limit_max`.
1915 bool use_distance_limit;
1916 ufbx_real distance_limit_min;
1917 ufbx_real distance_limit_max;
1918};
1919
1920// -- Deformers
1921
1922// Method to evaluate the skinning on a per-vertex level
1923typedef enum ufbx_skinning_method UFBX_ENUM_REPR {
1924 // Linear blend skinning: Blend transformation matrices by vertex weights
1925 UFBX_SKINNING_METHOD_LINEAR,
1926 // One vertex should have only one bone attached
1927 UFBX_SKINNING_METHOD_RIGID,
1928 // Convert the transformations to dual quaternions and blend in that space
1929 UFBX_SKINNING_METHOD_DUAL_QUATERNION,
1930 // Blend between `UFBX_SKINNING_METHOD_LINEAR` and `UFBX_SKINNING_METHOD_BLENDED_DQ_LINEAR`
1931 // The blend weight can be found either per-vertex in `ufbx_skin_vertex.dq_weight`
1932 // or in `ufbx_skin_deformer.dq_vertices/dq_weights` (indexed by vertex).
1933 UFBX_SKINNING_METHOD_BLENDED_DQ_LINEAR,
1934
1935 UFBX_ENUM_FORCE_WIDTH(UFBX_SKINNING_METHOD)
1936} ufbx_skinning_method;
1937
1938UFBX_ENUM_TYPE(ufbx_skinning_method, UFBX_SKINNING_METHOD, UFBX_SKINNING_METHOD_BLENDED_DQ_LINEAR);
1939
1940// Skin weight information for a single mesh vertex
1941typedef struct ufbx_skin_vertex {
1942
1943 // Each vertex is influenced by weights from `ufbx_skin_deformer.weights[]`
1944 // The weights are sorted by decreasing weight so you can take the first N
1945 // weights to get a cheaper approximation of the vertex.
1946 // NOTE: The weights are not guaranteed to be normalized!
1947 uint32_t weight_begin; // < Index to start from in the `weights[]` array
1948 uint32_t num_weights; // < Number of weights influencing the vertex
1949
1950 // Blend weight between Linear Blend Skinning (0.0) and Dual Quaternion (1.0).
1951 // Should be used if `skinning_method == UFBX_SKINNING_METHOD_BLENDED_DQ_LINEAR`
1952 ufbx_real dq_weight;
1953
1955
1956UFBX_LIST_TYPE(ufbx_skin_vertex_list, ufbx_skin_vertex);
1957
1958// Single per-vertex per-cluster weight, see `ufbx_skin_vertex`
1959typedef struct ufbx_skin_weight {
1960 uint32_t cluster_index; // < Index into `ufbx_skin_deformer.clusters[]`
1961 ufbx_real weight; // < Amount this bone influence the vertex
1963
1964UFBX_LIST_TYPE(ufbx_skin_weight_list, ufbx_skin_weight);
1965
1966// Skin deformer specifies a binding between a logical set of bones (a skeleton)
1967// and a mesh. Each bone is represented by a `ufbx_skin_cluster` that contains
1968// the binding matrix and a `ufbx_node *bone` that has the current transformation.
1970 union { ufbx_element element; struct {
1971 ufbx_string name;
1972 ufbx_props props;
1973 uint32_t element_id;
1974 uint32_t typed_id;
1975 }; };
1976
1977 ufbx_skinning_method skinning_method;
1978
1979 // Clusters (bones) in the skin
1980 ufbx_skin_cluster_list clusters;
1981
1982 // Per-vertex weight information
1983 ufbx_skin_vertex_list vertices;
1984 ufbx_skin_weight_list weights;
1985
1986 // Largest amount of weights a single vertex can have
1987 size_t max_weights_per_vertex;
1988
1989 // Blend weights between Linear Blend Skinning (0.0) and Dual Quaternion (1.0).
1990 // HINT: You probably want to use `vertices` and `ufbx_skin_vertex.dq_weight` instead!
1991 // NOTE: These may be out-of-bounds for a given mesh, `vertices` is always safe.
1992 size_t num_dq_weights;
1993 ufbx_uint32_list dq_vertices;
1994 ufbx_real_list dq_weights;
1995};
1996
1997// Cluster of vertices bound to a single bone.
1999 union { ufbx_element element; struct {
2000 ufbx_string name;
2001 ufbx_props props;
2002 uint32_t element_id;
2003 uint32_t typed_id;
2004 }; };
2005
2006 // The bone node the cluster is attached to
2007 // NOTE: Always valid if found from `ufbx_skin_deformer.clusters[]` unless
2008 // `ufbx_load_opts.connect_broken_elements` is `true`.
2009 ufbx_nullable ufbx_node *bone_node;
2010
2011 // Binding matrix from local mesh vertices to the bone
2012 ufbx_matrix geometry_to_bone;
2013
2014 // Binding matrix from local mesh _node_ to the bone.
2015 // NOTE: Prefer `geometry_to_bone` in most use cases!
2016 ufbx_matrix mesh_node_to_bone;
2017
2018 // Matrix that specifies the rest/bind pose transform of the node,
2019 // not generally needed for skinning, use `geometry_to_bone` instead.
2020 ufbx_matrix bind_to_world;
2021
2022 // Precomputed matrix/transform that accounts for the current bone transform
2023 // ie. `ufbx_matrix_mul(&cluster->bone->node_to_world, &cluster->geometry_to_bone)`
2024 ufbx_matrix geometry_to_world;
2025 ufbx_transform geometry_to_world_transform;
2026
2027 // Raw weights indexed by each _vertex_ of a mesh (not index!)
2028 // HINT: It may be simpler to use `ufbx_skin_deformer.vertices[]/weights[]` instead!
2029 // NOTE: These may be out-of-bounds for a given mesh, `ufbx_skin_deformer.vertices` is always safe.
2030 size_t num_weights; // < Number of vertices in the cluster
2031 ufbx_uint32_list vertices; // < Vertex indices in `ufbx_mesh.vertices[]`
2032 ufbx_real_list weights; // < Per-vertex weight values
2033};
2034
2035// Blend shape deformer can contain multiple channels (think of sliders between morphs)
2036// that may optionally have in-between keyframes.
2038 union { ufbx_element element; struct {
2039 ufbx_string name;
2040 ufbx_props props;
2041 uint32_t element_id;
2042 uint32_t typed_id;
2043 }; };
2044
2045 // Independent morph targets of the deformer.
2046 ufbx_blend_channel_list channels;
2047};
2048
2049// Blend shape associated with a target weight in a series of morphs
2050typedef struct ufbx_blend_keyframe {
2051 // The target blend shape offsets.
2052 ufbx_blend_shape *shape;
2053
2054 // Weight value at which to apply the keyframe at full strength
2055 ufbx_real target_weight;
2056
2057 // The weight the shape should be currently applied with
2058 ufbx_real effective_weight;
2060
2061UFBX_LIST_TYPE(ufbx_blend_keyframe_list, ufbx_blend_keyframe);
2062
2063// Blend channel consists of multiple morph-key targets that are interpolated.
2064// In simple cases there will be only one keyframe that is the target shape.
2066 union { ufbx_element element; struct {
2067 ufbx_string name;
2068 ufbx_props props;
2069 uint32_t element_id;
2070 uint32_t typed_id;
2071 }; };
2072
2073 // Current weight of the channel
2074 ufbx_real weight;
2075
2076 // Key morph targets to blend between depending on `weight`
2077 // In usual cases there's only one target per channel
2078 ufbx_blend_keyframe_list keyframes;
2079
2080 // Final blend shape ignoring any intermediate blend shapes.
2081 ufbx_nullable ufbx_blend_shape *target_shape;
2082};
2083
2084// Blend shape target containing the actual vertex offsets
2086 union { ufbx_element element; struct {
2087 ufbx_string name;
2088 ufbx_props props;
2089 uint32_t element_id;
2090 uint32_t typed_id;
2091 }; };
2092
2093 // Vertex offsets to apply over the base mesh
2094 // NOTE: The `offset_vertices` may be out-of-bounds for a given mesh!
2095 size_t num_offsets; // < Number of vertex offsets in the following arrays
2096 ufbx_uint32_list offset_vertices; // < Indices to `ufbx_mesh.vertices[]`
2097 ufbx_vec3_list position_offsets; // < Always specified per-vertex offsets
2098 ufbx_vec3_list normal_offsets; // < Empty if not specified
2099};
2100
2101typedef enum ufbx_cache_file_format UFBX_ENUM_REPR {
2102 UFBX_CACHE_FILE_FORMAT_UNKNOWN, // < Unknown cache file format
2103 UFBX_CACHE_FILE_FORMAT_PC2, // < .pc2 Point cache file
2104 UFBX_CACHE_FILE_FORMAT_MC, // < .mc/.mcx Maya cache file
2105
2106 UFBX_ENUM_FORCE_WIDTH(UFBX_CACHE_FILE_FORMAT)
2107} ufbx_cache_file_format;
2108
2109UFBX_ENUM_TYPE(ufbx_cache_file_format, UFBX_CACHE_FILE_FORMAT, UFBX_CACHE_FILE_FORMAT_MC);
2110
2111typedef enum ufbx_cache_data_format UFBX_ENUM_REPR {
2112 UFBX_CACHE_DATA_FORMAT_UNKNOWN, // < Unknown data format
2113 UFBX_CACHE_DATA_FORMAT_REAL_FLOAT, // < `float data[]`
2114 UFBX_CACHE_DATA_FORMAT_VEC3_FLOAT, // < `struct { float x, y, z; } data[]`
2115 UFBX_CACHE_DATA_FORMAT_REAL_DOUBLE, // < `double data[]`
2116 UFBX_CACHE_DATA_FORMAT_VEC3_DOUBLE, // < `struct { double x, y, z; } data[]`
2117
2118 UFBX_ENUM_FORCE_WIDTH(UFBX_CACHE_DATA_FORMAT)
2119} ufbx_cache_data_format;
2120
2121UFBX_ENUM_TYPE(ufbx_cache_data_format, UFBX_CACHE_DATA_FORMAT, UFBX_CACHE_DATA_FORMAT_VEC3_DOUBLE);
2122
2123typedef enum ufbx_cache_data_encoding UFBX_ENUM_REPR {
2124 UFBX_CACHE_DATA_ENCODING_UNKNOWN, // < Unknown data encoding
2125 UFBX_CACHE_DATA_ENCODING_LITTLE_ENDIAN, // < Contiguous little-endian array
2126 UFBX_CACHE_DATA_ENCODING_BIG_ENDIAN, // < Contiguous big-endian array
2127
2128 UFBX_ENUM_FORCE_WIDTH(UFBX_CACHE_DATA_ENCODING)
2129} ufbx_cache_data_encoding;
2130
2131UFBX_ENUM_TYPE(ufbx_cache_data_encoding, UFBX_CACHE_DATA_ENCODING, UFBX_CACHE_DATA_ENCODING_BIG_ENDIAN);
2132
2133// Known interpretations of geometry cache data.
2134typedef enum ufbx_cache_interpretation UFBX_ENUM_REPR {
2135 // Unknown interpretation, see `ufbx_cache_channel.interpretation_name` for more information.
2136 UFBX_CACHE_INTERPRETATION_UNKNOWN,
2137
2138 // Generic "points" interpretation, FBX SDK default. Usually fine to interpret
2139 // as vertex positions if no other cache channels are specified.
2140 UFBX_CACHE_INTERPRETATION_POINTS,
2141
2142 // Vertex positions.
2143 UFBX_CACHE_INTERPRETATION_VERTEX_POSITION,
2144
2145 // Vertex normals.
2146 UFBX_CACHE_INTERPRETATION_VERTEX_NORMAL,
2147
2148 UFBX_ENUM_FORCE_WIDTH(UFBX_CACHE_INTERPRETATION)
2149} ufbx_cache_interpretation;
2150
2151UFBX_ENUM_TYPE(ufbx_cache_interpretation, UFBX_CACHE_INTERPRETATION, UFBX_CACHE_INTERPRETATION_VERTEX_NORMAL);
2152
2153typedef struct ufbx_cache_frame {
2154
2155 // Name of the channel this frame belongs to.
2156 ufbx_string channel;
2157
2158 // Time of this frame in seconds.
2159 double time;
2160
2161 // Name of the file containing the data.
2162 // The specified file may contain multiple frames, use `data_offset` etc. to
2163 // read at the right position.
2164 ufbx_string filename;
2165
2166 // Format of the wrapper file.
2167 ufbx_cache_file_format file_format;
2168
2169 // Axis to mirror the read data by.
2170 ufbx_mirror_axis mirror_axis;
2171
2172 // Factor to scale the geometry by.
2173 ufbx_real scale_factor;
2174
2175 ufbx_cache_data_format data_format; // < Format of the data in the file
2176 ufbx_cache_data_encoding data_encoding; // < Binary encoding of the data
2177 uint64_t data_offset; // < Byte offset into the file
2178 uint32_t data_count; // < Number of data elements
2179 uint32_t data_element_bytes; // < Size of a single data element in bytes
2180 uint64_t data_total_bytes; // < Size of the whole data blob in bytes
2182
2183UFBX_LIST_TYPE(ufbx_cache_frame_list, ufbx_cache_frame);
2184
2185typedef struct ufbx_cache_channel {
2186
2187 // Name of the geometry cache channel.
2188 ufbx_string name;
2189
2190 // What does the data in this channel represent.
2191 ufbx_cache_interpretation interpretation;
2192
2193 // Source name for `interpretation`, especially useful if `interpretation` is
2194 // `UFBX_CACHE_INTERPRETATION_UNKNOWN`.
2195 ufbx_string interpretation_name;
2196
2197 // List of frames belonging to this channel.
2198 // Sorted by time (`ufbx_cache_frame.time`).
2199 ufbx_cache_frame_list frames;
2200
2201 // Axis to mirror the frames by.
2202 ufbx_mirror_axis mirror_axis;
2203
2204 // Factor to scale the geometry by.
2205 ufbx_real scale_factor;
2206
2208
2209UFBX_LIST_TYPE(ufbx_cache_channel_list, ufbx_cache_channel);
2210
2211typedef struct ufbx_geometry_cache {
2212 ufbx_string root_filename;
2213 ufbx_cache_channel_list channels;
2214 ufbx_cache_frame_list frames;
2215 ufbx_string_list extra_info;
2217
2219 union { ufbx_element element; struct {
2220 ufbx_string name;
2221 ufbx_props props;
2222 uint32_t element_id;
2223 uint32_t typed_id;
2224 }; };
2225
2226 ufbx_string channel;
2227 ufbx_nullable ufbx_cache_file *file;
2228
2229 // Only valid if `ufbx_load_opts.load_external_files` is set!
2230 ufbx_nullable ufbx_geometry_cache *external_cache;
2231 ufbx_nullable ufbx_cache_channel *external_channel;
2232};
2233
2235 union { ufbx_element element; struct {
2236 ufbx_string name;
2237 ufbx_props props;
2238 uint32_t element_id;
2239 uint32_t typed_id;
2240 }; };
2241
2242 // Filename relative to the currently loaded file.
2243 // HINT: If using functions other than `ufbx_load_file()`, you can provide
2244 // `ufbx_load_opts.filename/raw_filename` to let ufbx resolve this.
2245 ufbx_string filename;
2246 // Absolute filename specified in the file.
2247 ufbx_string absolute_filename;
2248 // Relative filename specified in the file.
2249 // NOTE: May be absolute if the file is saved in a different drive.
2250 ufbx_string relative_filename;
2251
2252 // Filename relative to the loaded file, non-UTF-8 encoded.
2253 // HINT: If using functions other than `ufbx_load_file()`, you can provide
2254 // `ufbx_load_opts.filename/raw_filename` to let ufbx resolve this.
2255 ufbx_blob raw_filename;
2256 // Absolute filename specified in the file, non-UTF-8 encoded.
2257 ufbx_blob raw_absolute_filename;
2258 // Relative filename specified in the file, non-UTF-8 encoded.
2259 // NOTE: May be absolute if the file is saved in a different drive.
2260 ufbx_blob raw_relative_filename;
2261
2262 ufbx_cache_file_format format;
2263
2264 // Only valid if `ufbx_load_opts.load_external_files` is set!
2265 ufbx_nullable ufbx_geometry_cache *external_cache;
2266};
2267
2268// -- Materials
2269
2270// Material property, either specified with a constant value or a mapped texture
2271typedef struct ufbx_material_map {
2272
2273 // Constant value or factor for the map.
2274 // May be specified simultaneously with a texture, in this case most shading models
2275 // use multiplicative tinting of the texture values.
2276 union {
2277 ufbx_real value_real;
2278 ufbx_vec2 value_vec2;
2279 ufbx_vec3 value_vec3;
2280 ufbx_vec4 value_vec4;
2281 };
2282 int64_t value_int;
2283
2284 // Texture if connected, otherwise `NULL`.
2285 // May be valid but "disabled" (application specific) if `texture_enabled == false`.
2286 ufbx_nullable ufbx_texture *texture;
2287
2288 // `true` if the file has specified any of the values above.
2289 // NOTE: The value may be set to a non-zero default even if `has_value == false`,
2290 // for example missing factors are set to `1.0` if a color is defined.
2291 bool has_value;
2292
2293 // Controls whether shading should use `texture`.
2294 // NOTE: Some shading models allow this to be `true` even if `texture == NULL`.
2295 bool texture_enabled;
2296
2297 // Set to `true` if this feature should be disabled (specific to shader type).
2298 bool feature_disabled;
2299
2300 // Number of components in the value from 1 to 4 if defined, 0 if not.
2301 uint8_t value_components;
2302
2304
2305// Material feature
2307
2308 // Whether the material model uses this feature or not.
2309 // NOTE: The feature can be enabled but still not used if eg. the corresponding factor is at zero!
2310 bool enabled;
2311
2312 // Explicitly enabled/disabled by the material.
2313 bool is_explicit;
2314
2316
2317// Texture attached to an FBX property
2319 ufbx_string material_prop; // < Name of the property in `ufbx_material.props`
2320 ufbx_string shader_prop; // < Shader-specific property mapping name
2321
2322 // Texture attached to the property.
2323 ufbx_texture *texture;
2324
2326
2327UFBX_LIST_TYPE(ufbx_material_texture_list, ufbx_material_texture);
2328
2329// Shading model type
2330typedef enum ufbx_shader_type UFBX_ENUM_REPR {
2331 // Unknown shading model
2332 UFBX_SHADER_UNKNOWN,
2333 // FBX builtin diffuse material
2334 UFBX_SHADER_FBX_LAMBERT,
2335 // FBX builtin diffuse+specular material
2336 UFBX_SHADER_FBX_PHONG,
2337 // Open Shading Language standard surface
2338 // https://github.com/Autodesk/standard-surface
2339 UFBX_SHADER_OSL_STANDARD_SURFACE,
2340 // Arnold standard surface
2341 // https://docs.arnoldrenderer.com/display/A5AFMUG/Standard+Surface
2342 UFBX_SHADER_ARNOLD_STANDARD_SURFACE,
2343 // 3ds Max Physical Material
2344 // https://knowledge.autodesk.com/support/3ds-max/learn-explore/caas/CloudHelp/cloudhelp/2022/ENU/3DSMax-Lighting-Shading/files/GUID-C1328905-7783-4917-AB86-FC3CC19E8972-htm.html
2345 UFBX_SHADER_3DS_MAX_PHYSICAL_MATERIAL,
2346 // 3ds Max PBR (Metal/Rough) material
2347 // https://knowledge.autodesk.com/support/3ds-max/learn-explore/caas/CloudHelp/cloudhelp/2021/ENU/3DSMax-Lighting-Shading/files/GUID-A16234A5-6500-4662-8B20-A5EC9FE1B255-htm.html
2348 UFBX_SHADER_3DS_MAX_PBR_METAL_ROUGH,
2349 // 3ds Max PBR (Spec/Gloss) material
2350 // https://knowledge.autodesk.com/support/3ds-max/learn-explore/caas/CloudHelp/cloudhelp/2021/ENU/3DSMax-Lighting-Shading/files/GUID-18087194-B2A6-43EF-9B80-8FD1736FAE52-htm.html
2351 UFBX_SHADER_3DS_MAX_PBR_SPEC_GLOSS,
2352 // 3ds glTF Material
2353 // https://help.autodesk.com/view/3DSMAX/2023/ENU/?guid=GUID-7ABFB805-1D9F-417E-9C22-704BFDF160FA
2354 UFBX_SHADER_GLTF_MATERIAL,
2355 // Stingray ShaderFX shader graph.
2356 // Contains a serialized `"ShaderGraph"` in `ufbx_props`.
2357 UFBX_SHADER_SHADERFX_GRAPH,
2358 // Variation of the FBX phong shader that can recover PBR properties like
2359 // `metalness` or `roughness` from the FBX non-physical values.
2360 // NOTE: Enable `ufbx_load_opts.use_blender_pbr_material`.
2361 UFBX_SHADER_BLENDER_PHONG,
2362 // Wavefront .mtl format shader (used by .obj files)
2363 UFBX_SHADER_WAVEFRONT_MTL,
2364
2365 UFBX_ENUM_FORCE_WIDTH(UFBX_SHADER_TYPE)
2366} ufbx_shader_type;
2367
2368UFBX_ENUM_TYPE(ufbx_shader_type, UFBX_SHADER_TYPE, UFBX_SHADER_WAVEFRONT_MTL);
2369
2370// FBX builtin material properties, matches maps in `ufbx_material_fbx_maps`
2371typedef enum ufbx_material_fbx_map UFBX_ENUM_REPR {
2372 UFBX_MATERIAL_FBX_DIFFUSE_FACTOR,
2373 UFBX_MATERIAL_FBX_DIFFUSE_COLOR,
2374 UFBX_MATERIAL_FBX_SPECULAR_FACTOR,
2375 UFBX_MATERIAL_FBX_SPECULAR_COLOR,
2376 UFBX_MATERIAL_FBX_SPECULAR_EXPONENT,
2377 UFBX_MATERIAL_FBX_REFLECTION_FACTOR,
2378 UFBX_MATERIAL_FBX_REFLECTION_COLOR,
2379 UFBX_MATERIAL_FBX_TRANSPARENCY_FACTOR,
2380 UFBX_MATERIAL_FBX_TRANSPARENCY_COLOR,
2381 UFBX_MATERIAL_FBX_EMISSION_FACTOR,
2382 UFBX_MATERIAL_FBX_EMISSION_COLOR,
2383 UFBX_MATERIAL_FBX_AMBIENT_FACTOR,
2384 UFBX_MATERIAL_FBX_AMBIENT_COLOR,
2385 UFBX_MATERIAL_FBX_NORMAL_MAP,
2386 UFBX_MATERIAL_FBX_BUMP,
2387 UFBX_MATERIAL_FBX_BUMP_FACTOR,
2388 UFBX_MATERIAL_FBX_DISPLACEMENT_FACTOR,
2389 UFBX_MATERIAL_FBX_DISPLACEMENT,
2390 UFBX_MATERIAL_FBX_VECTOR_DISPLACEMENT_FACTOR,
2391 UFBX_MATERIAL_FBX_VECTOR_DISPLACEMENT,
2392
2393 UFBX_ENUM_FORCE_WIDTH(UFBX_MATERIAL_FBX_MAP)
2394} ufbx_material_fbx_map;
2395
2396UFBX_ENUM_TYPE(ufbx_material_fbx_map, UFBX_MATERIAL_FBX_MAP, UFBX_MATERIAL_FBX_VECTOR_DISPLACEMENT);
2397
2398// Known PBR material properties, matches maps in `ufbx_material_pbr_maps`
2399typedef enum ufbx_material_pbr_map UFBX_ENUM_REPR {
2400 UFBX_MATERIAL_PBR_BASE_FACTOR,
2401 UFBX_MATERIAL_PBR_BASE_COLOR,
2402 UFBX_MATERIAL_PBR_ROUGHNESS,
2403 UFBX_MATERIAL_PBR_METALNESS,
2404 UFBX_MATERIAL_PBR_DIFFUSE_ROUGHNESS,
2405 UFBX_MATERIAL_PBR_SPECULAR_FACTOR,
2406 UFBX_MATERIAL_PBR_SPECULAR_COLOR,
2407 UFBX_MATERIAL_PBR_SPECULAR_IOR,
2408 UFBX_MATERIAL_PBR_SPECULAR_ANISOTROPY,
2409 UFBX_MATERIAL_PBR_SPECULAR_ROTATION,
2410 UFBX_MATERIAL_PBR_TRANSMISSION_FACTOR,
2411 UFBX_MATERIAL_PBR_TRANSMISSION_COLOR,
2412 UFBX_MATERIAL_PBR_TRANSMISSION_DEPTH,
2413 UFBX_MATERIAL_PBR_TRANSMISSION_SCATTER,
2414 UFBX_MATERIAL_PBR_TRANSMISSION_SCATTER_ANISOTROPY,
2415 UFBX_MATERIAL_PBR_TRANSMISSION_DISPERSION,
2416 UFBX_MATERIAL_PBR_TRANSMISSION_ROUGHNESS,
2417 UFBX_MATERIAL_PBR_TRANSMISSION_EXTRA_ROUGHNESS,
2418 UFBX_MATERIAL_PBR_TRANSMISSION_PRIORITY,
2419 UFBX_MATERIAL_PBR_TRANSMISSION_ENABLE_IN_AOV,
2420 UFBX_MATERIAL_PBR_SUBSURFACE_FACTOR,
2421 UFBX_MATERIAL_PBR_SUBSURFACE_COLOR,
2422 UFBX_MATERIAL_PBR_SUBSURFACE_RADIUS,
2423 UFBX_MATERIAL_PBR_SUBSURFACE_SCALE,
2424 UFBX_MATERIAL_PBR_SUBSURFACE_ANISOTROPY,
2425 UFBX_MATERIAL_PBR_SUBSURFACE_TINT_COLOR,
2426 UFBX_MATERIAL_PBR_SUBSURFACE_TYPE,
2427 UFBX_MATERIAL_PBR_SHEEN_FACTOR,
2428 UFBX_MATERIAL_PBR_SHEEN_COLOR,
2429 UFBX_MATERIAL_PBR_SHEEN_ROUGHNESS,
2430 UFBX_MATERIAL_PBR_COAT_FACTOR,
2431 UFBX_MATERIAL_PBR_COAT_COLOR,
2432 UFBX_MATERIAL_PBR_COAT_ROUGHNESS,
2433 UFBX_MATERIAL_PBR_COAT_IOR,
2434 UFBX_MATERIAL_PBR_COAT_ANISOTROPY,
2435 UFBX_MATERIAL_PBR_COAT_ROTATION,
2436 UFBX_MATERIAL_PBR_COAT_NORMAL,
2437 UFBX_MATERIAL_PBR_COAT_AFFECT_BASE_COLOR,
2438 UFBX_MATERIAL_PBR_COAT_AFFECT_BASE_ROUGHNESS,
2439 UFBX_MATERIAL_PBR_THIN_FILM_THICKNESS,
2440 UFBX_MATERIAL_PBR_THIN_FILM_IOR,
2441 UFBX_MATERIAL_PBR_EMISSION_FACTOR,
2442 UFBX_MATERIAL_PBR_EMISSION_COLOR,
2443 UFBX_MATERIAL_PBR_OPACITY,
2444 UFBX_MATERIAL_PBR_INDIRECT_DIFFUSE,
2445 UFBX_MATERIAL_PBR_INDIRECT_SPECULAR,
2446 UFBX_MATERIAL_PBR_NORMAL_MAP,
2447 UFBX_MATERIAL_PBR_TANGENT_MAP,
2448 UFBX_MATERIAL_PBR_DISPLACEMENT_MAP,
2449 UFBX_MATERIAL_PBR_MATTE_FACTOR,
2450 UFBX_MATERIAL_PBR_MATTE_COLOR,
2451 UFBX_MATERIAL_PBR_AMBIENT_OCCLUSION,
2452 UFBX_MATERIAL_PBR_GLOSSINESS,
2453 UFBX_MATERIAL_PBR_COAT_GLOSSINESS,
2454 UFBX_MATERIAL_PBR_TRANSMISSION_GLOSSINESS,
2455
2456 UFBX_ENUM_FORCE_WIDTH(UFBX_MATERIAL_PBR_MAP)
2457} ufbx_material_pbr_map;
2458
2459UFBX_ENUM_TYPE(ufbx_material_pbr_map, UFBX_MATERIAL_PBR_MAP, UFBX_MATERIAL_PBR_TRANSMISSION_GLOSSINESS);
2460
2461// Known material features
2462typedef enum ufbx_material_feature UFBX_ENUM_REPR {
2463 UFBX_MATERIAL_FEATURE_PBR,
2464 UFBX_MATERIAL_FEATURE_METALNESS,
2465 UFBX_MATERIAL_FEATURE_DIFFUSE,
2466 UFBX_MATERIAL_FEATURE_SPECULAR,
2467 UFBX_MATERIAL_FEATURE_EMISSION,
2468 UFBX_MATERIAL_FEATURE_TRANSMISSION,
2469 UFBX_MATERIAL_FEATURE_COAT,
2470 UFBX_MATERIAL_FEATURE_SHEEN,
2471 UFBX_MATERIAL_FEATURE_OPACITY,
2472 UFBX_MATERIAL_FEATURE_AMBIENT_OCCLUSION,
2473 UFBX_MATERIAL_FEATURE_MATTE,
2474 UFBX_MATERIAL_FEATURE_UNLIT,
2475 UFBX_MATERIAL_FEATURE_IOR,
2476 UFBX_MATERIAL_FEATURE_DIFFUSE_ROUGHNESS,
2477 UFBX_MATERIAL_FEATURE_TRANSMISSION_ROUGHNESS,
2478 UFBX_MATERIAL_FEATURE_THIN_WALLED,
2479 UFBX_MATERIAL_FEATURE_CAUSTICS,
2480 UFBX_MATERIAL_FEATURE_EXIT_TO_BACKGROUND,
2481 UFBX_MATERIAL_FEATURE_INTERNAL_REFLECTIONS,
2482 UFBX_MATERIAL_FEATURE_DOUBLE_SIDED,
2483 UFBX_MATERIAL_FEATURE_ROUGHNESS_AS_GLOSSINESS,
2484 UFBX_MATERIAL_FEATURE_COAT_ROUGHNESS_AS_GLOSSINESS,
2485 UFBX_MATERIAL_FEATURE_TRANSMISSION_ROUGHNESS_AS_GLOSSINESS,
2486
2487 UFBX_ENUM_FORCE_WIDTH(UFBX_MATERIAL_FEATURE)
2488} ufbx_material_feature;
2489
2490UFBX_ENUM_TYPE(ufbx_material_feature, UFBX_MATERIAL_FEATURE, UFBX_MATERIAL_FEATURE_TRANSMISSION_ROUGHNESS_AS_GLOSSINESS);
2491
2493 union {
2494 ufbx_material_map maps[UFBX_MATERIAL_FBX_MAP_COUNT];
2495 struct {
2496 ufbx_material_map diffuse_factor;
2497 ufbx_material_map diffuse_color;
2498 ufbx_material_map specular_factor;
2499 ufbx_material_map specular_color;
2500 ufbx_material_map specular_exponent;
2501 ufbx_material_map reflection_factor;
2502 ufbx_material_map reflection_color;
2503 ufbx_material_map transparency_factor;
2504 ufbx_material_map transparency_color;
2505 ufbx_material_map emission_factor;
2506 ufbx_material_map emission_color;
2507 ufbx_material_map ambient_factor;
2508 ufbx_material_map ambient_color;
2509 ufbx_material_map normal_map;
2510 ufbx_material_map bump;
2511 ufbx_material_map bump_factor;
2512 ufbx_material_map displacement_factor;
2513 ufbx_material_map displacement;
2514 ufbx_material_map vector_displacement_factor;
2515 ufbx_material_map vector_displacement;
2516 };
2517 };
2519
2521 union {
2522 ufbx_material_map maps[UFBX_MATERIAL_PBR_MAP_COUNT];
2523 struct {
2524 ufbx_material_map base_factor;
2525 ufbx_material_map base_color;
2526 ufbx_material_map roughness;
2527 ufbx_material_map metalness;
2528 ufbx_material_map diffuse_roughness;
2529 ufbx_material_map specular_factor;
2530 ufbx_material_map specular_color;
2531 ufbx_material_map specular_ior;
2532 ufbx_material_map specular_anisotropy;
2533 ufbx_material_map specular_rotation;
2534 ufbx_material_map transmission_factor;
2535 ufbx_material_map transmission_color;
2536 ufbx_material_map transmission_depth;
2537 ufbx_material_map transmission_scatter;
2538 ufbx_material_map transmission_scatter_anisotropy;
2539 ufbx_material_map transmission_dispersion;
2540 ufbx_material_map transmission_roughness;
2541 ufbx_material_map transmission_extra_roughness;
2542 ufbx_material_map transmission_priority;
2543 ufbx_material_map transmission_enable_in_aov;
2544 ufbx_material_map subsurface_factor;
2545 ufbx_material_map subsurface_color;
2546 ufbx_material_map subsurface_radius;
2547 ufbx_material_map subsurface_scale;
2548 ufbx_material_map subsurface_anisotropy;
2549 ufbx_material_map subsurface_tint_color;
2550 ufbx_material_map subsurface_type;
2551 ufbx_material_map sheen_factor;
2552 ufbx_material_map sheen_color;
2553 ufbx_material_map sheen_roughness;
2554 ufbx_material_map coat_factor;
2555 ufbx_material_map coat_color;
2556 ufbx_material_map coat_roughness;
2557 ufbx_material_map coat_ior;
2558 ufbx_material_map coat_anisotropy;
2559 ufbx_material_map coat_rotation;
2560 ufbx_material_map coat_normal;
2561 ufbx_material_map coat_affect_base_color;
2562 ufbx_material_map coat_affect_base_roughness;
2563 ufbx_material_map thin_film_thickness;
2564 ufbx_material_map thin_film_ior;
2565 ufbx_material_map emission_factor;
2566 ufbx_material_map emission_color;
2567 ufbx_material_map opacity;
2568 ufbx_material_map indirect_diffuse;
2569 ufbx_material_map indirect_specular;
2570 ufbx_material_map normal_map;
2571 ufbx_material_map tangent_map;
2572 ufbx_material_map displacement_map;
2573 ufbx_material_map matte_factor;
2574 ufbx_material_map matte_color;
2575 ufbx_material_map ambient_occlusion;
2576 ufbx_material_map glossiness;
2577 ufbx_material_map coat_glossiness;
2578 ufbx_material_map transmission_glossiness;
2579 };
2580 };
2582
2584 union {
2585 ufbx_material_feature_info features[UFBX_MATERIAL_FEATURE_COUNT];
2586 struct {
2592 ufbx_material_feature_info transmission;
2596 ufbx_material_feature_info ambient_occlusion;
2600 ufbx_material_feature_info diffuse_roughness;
2601 ufbx_material_feature_info transmission_roughness;
2602 ufbx_material_feature_info thin_walled;
2604 ufbx_material_feature_info exit_to_background;
2605 ufbx_material_feature_info internal_reflections;
2606 ufbx_material_feature_info double_sided;
2607 ufbx_material_feature_info roughness_as_glossiness;
2608 ufbx_material_feature_info coat_roughness_as_glossiness;
2609 ufbx_material_feature_info transmission_roughness_as_glossiness;
2610 };
2611 };
2613
2614// Surface material properties such as color, roughness, etc. Each property may
2615// be optionally bound to an `ufbx_texture`.
2617 union { ufbx_element element; struct {
2618 ufbx_string name;
2619 ufbx_props props;
2620 uint32_t element_id;
2621 uint32_t typed_id;
2622 }; };
2623
2624 // FBX builtin properties
2625 // NOTE: These may be empty if the material is using a custom shader
2627
2628 // PBR material properties, defined for all shading models but may be
2629 // somewhat approximate if `shader == NULL`.
2631
2632 // Material features, primarily applies to `pbr`.
2633 ufbx_material_features features;
2634
2635 // Shading information
2636 ufbx_shader_type shader_type; // < Always defined
2637 ufbx_nullable ufbx_shader *shader; // < Optional extended shader information
2638 ufbx_string shading_model_name; // < Often one of `{ "lambert", "phong", "unknown" }`
2639
2640 // Prefix before shader property names with trailing `|`.
2641 // For example `"3dsMax|Parameters|"` where properties would have names like
2642 // `"3dsMax|Parameters|base_color"`. You can ignore this if you use the built-in
2643 // `ufbx_material_fbx_maps fbx` and `ufbx_material_pbr_maps pbr` structures.
2644 ufbx_string shader_prop_prefix;
2645
2646 // All textures attached to the material, if you want specific maps if might be
2647 // more convenient to use eg. `fbx.diffuse_color.texture` or `pbr.base_color.texture`
2648 ufbx_material_texture_list textures; // < Sorted by `material_prop`
2649};
2650
2651typedef enum ufbx_texture_type UFBX_ENUM_REPR {
2652
2653 // Texture associated with an image file/sequence. `texture->filename` and
2654 // and `texture->relative_filename` contain the texture's path. If the file
2655 // has embedded content `texture->content` may hold `texture->content_size`
2656 // bytes of raw image data.
2657 UFBX_TEXTURE_FILE,
2658
2659 // The texture consists of multiple texture layers blended together.
2660 UFBX_TEXTURE_LAYERED,
2661
2662 // Reserved as these _should_ exist in FBX files.
2663 UFBX_TEXTURE_PROCEDURAL,
2664
2665 // Node in a shader graph.
2666 // Use `ufbx_texture.shader` for more information.
2667 UFBX_TEXTURE_SHADER,
2668
2669 UFBX_ENUM_FORCE_WIDTH(UFBX_TEXTURE_TYPE)
2670} ufbx_texture_type;
2671
2672UFBX_ENUM_TYPE(ufbx_texture_type, UFBX_TEXTURE_TYPE, UFBX_TEXTURE_SHADER);
2673
2674// Blend modes to combine layered textures with, compatible with common blend
2675// mode definitions in many art programs. Simpler blend modes have equations
2676// specified below where `src` is the layer to composite over `dst`.
2677// See eg. https://www.w3.org/TR/2013/WD-compositing-1-20131010/#blendingseparable
2678typedef enum ufbx_blend_mode UFBX_ENUM_REPR {
2679 UFBX_BLEND_TRANSLUCENT, // < `src` effects result alpha
2680 UFBX_BLEND_ADDITIVE, // < `src + dst`
2681 UFBX_BLEND_MULTIPLY, // < `src * dst`
2682 UFBX_BLEND_MULTIPLY_2X, // < `2 * src * dst`
2683 UFBX_BLEND_OVER, // < `src * src_alpha + dst * (1-src_alpha)`
2684 UFBX_BLEND_REPLACE, // < `src` Replace the contents
2685 UFBX_BLEND_DISSOLVE, // < `random() + src_alpha >= 1.0 ? src : dst`
2686 UFBX_BLEND_DARKEN, // < `min(src, dst)`
2687 UFBX_BLEND_COLOR_BURN, // < `src > 0 ? 1 - min(1, (1-dst) / src) : 0`
2688 UFBX_BLEND_LINEAR_BURN, // < `src + dst - 1`
2689 UFBX_BLEND_DARKER_COLOR, // < `value(src) < value(dst) ? src : dst`
2690 UFBX_BLEND_LIGHTEN, // < `max(src, dst)`
2691 UFBX_BLEND_SCREEN, // < `1 - (1-src)*(1-dst)`
2692 UFBX_BLEND_COLOR_DODGE, // < `src < 1 ? dst / (1 - src)` : (dst>0?1:0)`
2693 UFBX_BLEND_LINEAR_DODGE, // < `src + dst`
2694 UFBX_BLEND_LIGHTER_COLOR, // < `value(src) > value(dst) ? src : dst`
2695 UFBX_BLEND_SOFT_LIGHT, // < https://www.w3.org/TR/2013/WD-compositing-1-20131010/#blendingsoftlight
2696 UFBX_BLEND_HARD_LIGHT, // < https://www.w3.org/TR/2013/WD-compositing-1-20131010/#blendinghardlight
2697 UFBX_BLEND_VIVID_LIGHT, // < Combination of `COLOR_DODGE` and `COLOR_BURN`
2698 UFBX_BLEND_LINEAR_LIGHT, // < Combination of `LINEAR_DODGE` and `LINEAR_BURN`
2699 UFBX_BLEND_PIN_LIGHT, // < Combination of `DARKEN` and `LIGHTEN`
2700 UFBX_BLEND_HARD_MIX, // < Produces primary colors depending on similarity
2701 UFBX_BLEND_DIFFERENCE, // < `abs(src - dst)`
2702 UFBX_BLEND_EXCLUSION, // < `dst + src - 2 * src * dst`
2703 UFBX_BLEND_SUBTRACT, // < `dst - src`
2704 UFBX_BLEND_DIVIDE, // < `dst / src`
2705 UFBX_BLEND_HUE, // < Replace hue
2706 UFBX_BLEND_SATURATION, // < Replace saturation
2707 UFBX_BLEND_COLOR, // < Replace hue and saturatio
2708 UFBX_BLEND_LUMINOSITY, // < Replace value
2709 UFBX_BLEND_OVERLAY, // < Same as `HARD_LIGHT` but with `src` and `dst` swapped
2710
2711 UFBX_ENUM_FORCE_WIDTH(UFBX_BLEND_MODE)
2712} ufbx_blend_mode;
2713
2714UFBX_ENUM_TYPE(ufbx_blend_mode, UFBX_BLEND_MODE, UFBX_BLEND_OVERLAY);
2715
2716// Blend modes to combine layered textures with, compatible with common blend
2717typedef enum ufbx_wrap_mode UFBX_ENUM_REPR {
2718 UFBX_WRAP_REPEAT, // < Repeat the texture past the [0,1] range
2719 UFBX_WRAP_CLAMP, // < Clamp the normalized texture coordinates to [0,1]
2720
2721 UFBX_ENUM_FORCE_WIDTH(UFBX_WRAP_MODE)
2722} ufbx_wrap_mode;
2723
2724UFBX_ENUM_TYPE(ufbx_wrap_mode, UFBX_WRAP_MODE, UFBX_WRAP_CLAMP);
2725
2726// Single layer in a layered texture
2727typedef struct ufbx_texture_layer {
2728 ufbx_texture *texture; // < The inner texture to evaluate, never `NULL`
2729 ufbx_blend_mode blend_mode; // < Equation to combine the layer to the background
2730 ufbx_real alpha; // < Blend weight of this layer
2732
2733UFBX_LIST_TYPE(ufbx_texture_layer_list, ufbx_texture_layer);
2734
2735typedef enum ufbx_shader_texture_type UFBX_ENUM_REPR {
2736 UFBX_SHADER_TEXTURE_UNKNOWN,
2737
2738 // Select an output of a multi-output shader.
2739 // HINT: If this type is used the `ufbx_shader_texture.main_texture` and
2740 // `ufbx_shader_texture.main_texture_output_index` fields are set.
2741 UFBX_SHADER_TEXTURE_SELECT_OUTPUT,
2742
2743 // Open Shading Language (OSL) shader.
2744 // https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
2745 UFBX_SHADER_TEXTURE_OSL,
2746
2747 UFBX_ENUM_FORCE_WIDTH(UFBX_SHADER_TEXTURE_TYPE)
2748} ufbx_shader_texture_type;
2749
2750UFBX_ENUM_TYPE(ufbx_shader_texture_type, UFBX_SHADER_TEXTURE_TYPE, UFBX_SHADER_TEXTURE_OSL);
2751
2752// Input to a shader texture, see `ufbx_shader_texture`.
2754
2755 // Name of the input.
2756 ufbx_string name;
2757
2758 // Constant value of the input.
2759 union {
2760 ufbx_real value_real;
2761 ufbx_vec2 value_vec2;
2762 ufbx_vec3 value_vec3;
2763 ufbx_vec4 value_vec4;
2764 };
2765 int64_t value_int;
2766 ufbx_string value_str;
2767 ufbx_blob value_blob;
2768
2769 // Texture connected to this input.
2770 ufbx_nullable ufbx_texture *texture;
2771
2772 // Index of the output to use if `texture` is a multi-output shader node.
2773 int64_t texture_output_index;
2774
2775 // Controls whether shading should use `texture`.
2776 // NOTE: Some shading models allow this to be `true` even if `texture == NULL`.
2777 bool texture_enabled;
2778
2779 // Property representing this input.
2780 ufbx_prop *prop;
2781
2782 // Property representing `texture`.
2783 ufbx_nullable ufbx_prop *texture_prop;
2784
2785 // Property representing `texture_enabled`.
2786 ufbx_nullable ufbx_prop *texture_enabled_prop;
2787
2789
2790UFBX_LIST_TYPE(ufbx_shader_texture_input_list, ufbx_shader_texture_input);
2791
2792// Texture that emulates a shader graph node.
2793// 3ds Max exports some materials as node graphs serialized to textures.
2794// ufbx can parse a small subset of these, as normal maps are often hidden behind
2795// some kind of bump node.
2796// NOTE: These encode a lot of details of 3ds Max internals, not recommended for direct use.
2797// HINT: `ufbx_texture.file_textures[]` contains a list of "real" textures that are connected
2798// to the `ufbx_texture` that is pretending to be a shader node.
2799typedef struct ufbx_shader_texture {
2800
2801 // Type of this shader node.
2802 ufbx_shader_texture_type type;
2803
2804 // Name of the shader to use.
2805 ufbx_string shader_name;
2806
2807 // 64-bit opaque identifier for the shader type.
2808 uint64_t shader_type_id;
2809
2810 // Input values/textures (possibly further shader textures) to the shader.
2811 // Sorted by `ufbx_shader_texture_input.name`.
2812 ufbx_shader_texture_input_list inputs;
2813
2814 // Shader source code if found.
2815 ufbx_string shader_source;
2816 ufbx_blob raw_shader_source;
2817
2818 // Representative texture for this shader.
2819 // Only specified if `main_texture.outputs[main_texture_output_index]` is semantically
2820 // equivalent to this texture.
2821 ufbx_texture *main_texture;
2822
2823 // Output index of `main_texture` if it is a multi-output shader.
2824 int64_t main_texture_output_index;
2825
2826 // Prefix for properties related to this shader in `ufbx_texture`.
2827 // NOTE: Contains the trailing '|' if not empty.
2828 ufbx_string prop_prefix;
2829
2831
2832// Unique texture within the file.
2833typedef struct ufbx_texture_file {
2834
2835 // Index in `ufbx_scene.texture_files[]`.
2836 uint32_t index;
2837
2838 // Paths to the resource.
2839
2840 // Filename relative to the currently loaded file.
2841 // HINT: If using functions other than `ufbx_load_file()`, you can provide
2842 // `ufbx_load_opts.filename/raw_filename` to let ufbx resolve this.
2843 ufbx_string filename;
2844 // Absolute filename specified in the file.
2845 ufbx_string absolute_filename;
2846 // Relative filename specified in the file.
2847 // NOTE: May be absolute if the file is saved in a different drive.
2848 ufbx_string relative_filename;
2849
2850 // Filename relative to the loaded file, non-UTF-8 encoded.
2851 // HINT: If using functions other than `ufbx_load_file()`, you can provide
2852 // `ufbx_load_opts.filename/raw_filename` to let ufbx resolve this.
2853 ufbx_blob raw_filename;
2854 // Absolute filename specified in the file, non-UTF-8 encoded.
2855 ufbx_blob raw_absolute_filename;
2856 // Relative filename specified in the file, non-UTF-8 encoded.
2857 // NOTE: May be absolute if the file is saved in a different drive.
2858 ufbx_blob raw_relative_filename;
2859
2860 // Optional embedded content blob, eg. raw .png format data
2861 ufbx_blob content;
2862
2864
2865UFBX_LIST_TYPE(ufbx_texture_file_list, ufbx_texture_file);
2866
2867// Texture that controls material appearance
2869 union { ufbx_element element; struct {
2870 ufbx_string name;
2871 ufbx_props props;
2872 uint32_t element_id;
2873 uint32_t typed_id;
2874 }; };
2875
2876 // Texture type (file / layered / procedural / shader)
2877 ufbx_texture_type type;
2878
2879 // FILE: Paths to the resource
2880
2881 // Filename relative to the currently loaded file.
2882 // HINT: If using functions other than `ufbx_load_file()`, you can provide
2883 // `ufbx_load_opts.filename/raw_filename` to let ufbx resolve this.
2884 ufbx_string filename;
2885 // Absolute filename specified in the file.
2886 ufbx_string absolute_filename;
2887 // Relative filename specified in the file.
2888 // NOTE: May be absolute if the file is saved in a different drive.
2889 ufbx_string relative_filename;
2890
2891 // Filename relative to the loaded file, non-UTF-8 encoded.
2892 // HINT: If using functions other than `ufbx_load_file()`, you can provide
2893 // `ufbx_load_opts.filename/raw_filename` to let ufbx resolve this.
2894 ufbx_blob raw_filename;
2895 // Absolute filename specified in the file, non-UTF-8 encoded.
2896 ufbx_blob raw_absolute_filename;
2897 // Relative filename specified in the file, non-UTF-8 encoded.
2898 // NOTE: May be absolute if the file is saved in a different drive.
2899 ufbx_blob raw_relative_filename;
2900
2901 // FILE: Optional embedded content blob, eg. raw .png format data
2902 ufbx_blob content;
2903
2904 // FILE: Optional video texture
2905 ufbx_nullable ufbx_video *video;
2906
2907 // FILE: Index into `ufbx_scene.texture_files[]` or `UFBX_NO_INDEX`.
2908 uint32_t file_index;
2909
2910 // FILE: True if `file_index` has a valid value.
2911 bool has_file;
2912
2913 // LAYERED: Inner texture layers, ordered from _bottom_ to _top_
2914 ufbx_texture_layer_list layers;
2915
2916 // SHADER: Shader information
2917 // NOTE: May be specified even if `type == UFBX_TEXTURE_FILE` if `ufbx_load_opts.disable_quirks`
2918 // is _not_ specified. Some known shaders that represent files are interpreted as `UFBX_TEXTURE_FILE`.
2919 ufbx_nullable ufbx_shader_texture *shader;
2920
2921 // List of file textures representing this texture.
2922 // Defined even if `type == UFBX_TEXTURE_FILE` in which case the array contains only itself.
2923 ufbx_texture_list file_textures;
2924
2925 // Name of the UV set to use
2926 ufbx_string uv_set;
2927
2928 // Wrapping mode
2929 ufbx_wrap_mode wrap_u;
2930 ufbx_wrap_mode wrap_v;
2931
2932 // UV transform
2933 bool has_uv_transform; // < Has a non-identity `transform` and derived matrices.
2934 ufbx_transform uv_transform; // < Texture transformation in UV space
2935 ufbx_matrix texture_to_uv; // < Matrix representation of `transform`
2936 ufbx_matrix uv_to_texture; // < UV coordinate to normalized texture coordinate matrix
2937};
2938
2939// TODO: Video textures
2941 union { ufbx_element element; struct {
2942 ufbx_string name;
2943 ufbx_props props;
2944 uint32_t element_id;
2945 uint32_t typed_id;
2946 }; };
2947
2948 // Paths to the resource
2949
2950 // Filename relative to the currently loaded file.
2951 // HINT: If using functions other than `ufbx_load_file()`, you can provide
2952 // `ufbx_load_opts.filename/raw_filename` to let ufbx resolve this.
2953 ufbx_string filename;
2954 // Absolute filename specified in the file.
2955 ufbx_string absolute_filename;
2956 // Relative filename specified in the file.
2957 // NOTE: May be absolute if the file is saved in a different drive.
2958 ufbx_string relative_filename;
2959
2960 // Filename relative to the loaded file, non-UTF-8 encoded.
2961 // HINT: If using functions other than `ufbx_load_file()`, you can provide
2962 // `ufbx_load_opts.filename/raw_filename` to let ufbx resolve this.
2963 ufbx_blob raw_filename;
2964 // Absolute filename specified in the file, non-UTF-8 encoded.
2965 ufbx_blob raw_absolute_filename;
2966 // Relative filename specified in the file, non-UTF-8 encoded.
2967 // NOTE: May be absolute if the file is saved in a different drive.
2968 ufbx_blob raw_relative_filename;
2969
2970 // Optional embedded content blob
2971 ufbx_blob content;
2972};
2973
2974// Shader specifies a shading model and contains `ufbx_shader_binding` elements
2975// that define how to interpret FBX properties in the shader.
2977 union { ufbx_element element; struct {
2978 ufbx_string name;
2979 ufbx_props props;
2980 uint32_t element_id;
2981 uint32_t typed_id;
2982 }; };
2983
2984 // Known shading model
2985 ufbx_shader_type type;
2986
2987 // TODO: Expose actual properties here
2988
2989 // Bindings from FBX properties to the shader
2990 // HINT: `ufbx_find_shader_prop()` translates shader properties to FBX properties
2991 ufbx_shader_binding_list bindings;
2992};
2993
2994// Binding from a material property to shader implementation
2996 ufbx_string shader_prop; // < Property name used by the shader implementation
2997 ufbx_string material_prop; // < Property name inside `ufbx_material.props`
2999
3000UFBX_LIST_TYPE(ufbx_shader_prop_binding_list, ufbx_shader_prop_binding);
3001
3002// Shader binding table
3004 union { ufbx_element element; struct {
3005 ufbx_string name;
3006 ufbx_props props;
3007 uint32_t element_id;
3008 uint32_t typed_id;
3009 }; };
3010
3011 ufbx_shader_prop_binding_list prop_bindings; // < Sorted by `shader_prop`
3012};
3013
3014// -- Animation
3015
3016typedef struct ufbx_prop_override {
3017 uint32_t element_id;
3018
3019 uint32_t _internal_key;
3020
3021 ufbx_string prop_name;
3022 ufbx_vec4 value;
3023 ufbx_string value_str;
3024 int64_t value_int;
3026
3027UFBX_LIST_TYPE(ufbx_prop_override_list, ufbx_prop_override);
3028
3030 uint32_t node_id;
3031 ufbx_transform transform;
3033
3034UFBX_LIST_TYPE(ufbx_transform_override_list, ufbx_transform_override);
3035
3036// Animation descriptor used for evaluating animation.
3037// Usually obtained from `ufbx_scene` via either global animation `ufbx_scene.anim`,
3038// per-stack animation `ufbx_anim_stack.anim` or per-layer animation `ufbx_anim_layer.anim`.
3039//
3040// For advanced usage you can use `ufbx_create_anim()` to create animation descriptors
3041// with custom layers, property overrides, special flags, etc.
3042typedef struct ufbx_anim {
3043
3044 // Time begin/end for the animation, both may be zero if absent.
3045 double time_begin;
3046 double time_end;
3047
3048 // List of layers in the animation.
3049 ufbx_anim_layer_list layers;
3050
3051 // Optional overrides for weights for each layer in `layers[]`.
3052 ufbx_real_list override_layer_weights;
3053
3054 // Sorted by `element_id, prop_name`
3055 ufbx_prop_override_list prop_overrides;
3056
3057 // Sorted by `node_id`
3058 ufbx_transform_override_list transform_overrides;
3059
3060 // Evaluate connected properties as if they would not be connected.
3061 bool ignore_connections;
3062
3063 // Custom `ufbx_anim` created by `ufbx_create_anim()`.
3064 bool custom;
3065
3066} ufbx_anim;
3067
3069 union { ufbx_element element; struct {
3070 ufbx_string name;
3071 ufbx_props props;
3072 uint32_t element_id;
3073 uint32_t typed_id;
3074 }; };
3075
3076 double time_begin;
3077 double time_end;
3078
3079 ufbx_anim_layer_list layers;
3080 ufbx_anim *anim;
3081};
3082
3083typedef struct ufbx_anim_prop {
3084 ufbx_element *element;
3085
3086 uint32_t _internal_key;
3087
3088 ufbx_string prop_name;
3089 ufbx_anim_value *anim_value;
3091
3092UFBX_LIST_TYPE(ufbx_anim_prop_list, ufbx_anim_prop);
3093
3095 union { ufbx_element element; struct {
3096 ufbx_string name;
3097 ufbx_props props;
3098 uint32_t element_id;
3099 uint32_t typed_id;
3100 }; };
3101
3102 ufbx_real weight;
3103 bool weight_is_animated;
3104 bool blended;
3105 bool additive;
3106 bool compose_rotation;
3107 bool compose_scale;
3108
3109 ufbx_anim_value_list anim_values;
3110 ufbx_anim_prop_list anim_props; // < Sorted by `element,prop_name`
3111
3112 ufbx_anim *anim;
3113
3114 uint32_t _min_element_id;
3115 uint32_t _max_element_id;
3116 uint32_t _element_id_bitmask[4];
3117};
3118
3120 union { ufbx_element element; struct {
3121 ufbx_string name;
3122 ufbx_props props;
3123 uint32_t element_id;
3124 uint32_t typed_id;
3125 }; };
3126
3127 ufbx_vec3 default_value;
3128 ufbx_nullable ufbx_anim_curve *curves[3];
3129};
3130
3131// Animation curve segment interpolation mode between two keyframes
3132typedef enum ufbx_interpolation UFBX_ENUM_REPR {
3133 UFBX_INTERPOLATION_CONSTANT_PREV, // < Hold previous key value
3134 UFBX_INTERPOLATION_CONSTANT_NEXT, // < Hold next key value
3135 UFBX_INTERPOLATION_LINEAR, // < Linear interpolation between two keys
3136 UFBX_INTERPOLATION_CUBIC, // < Cubic interpolation, see `ufbx_tangent`
3137
3138 UFBX_ENUM_FORCE_WIDTH(UFBX_INTERPOLATION)
3139} ufbx_interpolation;
3140
3141UFBX_ENUM_TYPE(ufbx_interpolation, UFBX_INTERPOLATION, UFBX_INTERPOLATION_CUBIC);
3142
3143// Tangent vector at a keyframe, may be split into left/right
3144typedef struct ufbx_tangent {
3145 float dx; // < Derivative in the time axis
3146 float dy; // < Derivative in the (curve specific) value axis
3147} ufbx_tangent;
3148
3149// Single real `value` at a specified `time`, interpolation between two keyframes
3150// is determined by the `interpolation` field of the _previous_ key.
3151// If `interpolation == UFBX_INTERPOLATION_CUBIC` the span is evaluated as a
3152// cubic bezier curve through the following points:
3153//
3154// (prev->time, prev->value)
3155// (prev->time + prev->right.dx, prev->value + prev->right.dy)
3156// (next->time - next->left.dx, next->value - next->left.dy)
3157// (next->time, next->value)
3158//
3159// HINT: You can use `ufbx_evaluate_curve(ufbx_anim_curve *curve, double time)`
3160// rather than trying to manually handle all the interpolation modes.
3161typedef struct ufbx_keyframe {
3162 double time;
3163 ufbx_real value;
3164 ufbx_interpolation interpolation;
3165 ufbx_tangent left;
3166 ufbx_tangent right;
3168
3169UFBX_LIST_TYPE(ufbx_keyframe_list, ufbx_keyframe);
3170
3172 union { ufbx_element element; struct {
3173 ufbx_string name;
3174 ufbx_props props;
3175 uint32_t element_id;
3176 uint32_t typed_id;
3177 }; };
3178
3179 ufbx_keyframe_list keyframes;
3180
3181 ufbx_real min_value;
3182 ufbx_real max_value;
3183};
3184
3185// -- Collections
3186
3187// Collection of nodes to hide/freeze
3189 union { ufbx_element element; struct {
3190 ufbx_string name;
3191 ufbx_props props;
3192 uint32_t element_id;
3193 uint32_t typed_id;
3194 }; };
3195
3196 // Nodes included in the layer (exclusively at most one layer per node)
3197 ufbx_node_list nodes;
3198
3199 // Layer state
3200 bool visible; // < Contained nodes are visible
3201 bool frozen; // < Contained nodes cannot be edited
3202
3203 ufbx_vec3 ui_color; // < Visual color for UI
3204};
3205
3206// Named set of nodes/geometry features to select.
3208 union { ufbx_element element; struct {
3209 ufbx_string name;
3210 ufbx_props props;
3211 uint32_t element_id;
3212 uint32_t typed_id;
3213 }; };
3214
3215 // Included nodes and geometry features
3216 ufbx_selection_node_list nodes;
3217};
3218
3219// Selection state of a node, potentially contains vertex/edge/face selection as well.
3221 union { ufbx_element element; struct {
3222 ufbx_string name;
3223 ufbx_props props;
3224 uint32_t element_id;
3225 uint32_t typed_id;
3226 }; };
3227
3228 // Selection targets, possibly `NULL`
3229 ufbx_nullable ufbx_node *target_node;
3230 ufbx_nullable ufbx_mesh *target_mesh;
3231 bool include_node; // < Is `target_node` included in the selection
3232
3233 // Indices to selected components.
3234 // Guaranteed to be valid as per `ufbx_load_opts.index_error_handling`
3235 // if `target_mesh` is not `NULL`.
3236 ufbx_uint32_list vertices; // < Indices to `ufbx_mesh.vertices`
3237 ufbx_uint32_list edges; // < Indices to `ufbx_mesh.edges`
3238 ufbx_uint32_list faces; // < Indices to `ufbx_mesh.faces`
3239};
3240
3241// -- Constraints
3242
3244 union { ufbx_element element; struct {
3245 ufbx_string name;
3246 ufbx_props props;
3247 uint32_t element_id;
3248 uint32_t typed_id;
3249 }; };
3250};
3251
3252// Type of property constrain eg. position or look-at
3253typedef enum ufbx_constraint_type UFBX_ENUM_REPR {
3254 UFBX_CONSTRAINT_UNKNOWN,
3255 UFBX_CONSTRAINT_AIM,
3256 UFBX_CONSTRAINT_PARENT,
3257 UFBX_CONSTRAINT_POSITION,
3258 UFBX_CONSTRAINT_ROTATION,
3259 UFBX_CONSTRAINT_SCALE,
3260 // Inverse kinematic chain to a single effector `ufbx_constraint.ik_effector`
3261 // `targets` optionally contains a list of pole targets!
3262 UFBX_CONSTRAINT_SINGLE_CHAIN_IK,
3263
3264 UFBX_ENUM_FORCE_WIDTH(UFBX_CONSTRAINT_TYPE)
3265} ufbx_constraint_type;
3266
3267UFBX_ENUM_TYPE(ufbx_constraint_type, UFBX_CONSTRAINT_TYPE, UFBX_CONSTRAINT_SINGLE_CHAIN_IK);
3268
3269// Target to follow with a constraint
3271 ufbx_node *node; // < Target node reference
3272 ufbx_real weight; // < Relative weight to other targets (does not always sum to 1)
3273 ufbx_transform transform; // < Offset from the actual target
3275
3276UFBX_LIST_TYPE(ufbx_constraint_target_list, ufbx_constraint_target);
3277
3278// Method to determine the up vector in aim constraints
3279typedef enum ufbx_constraint_aim_up_type UFBX_ENUM_REPR {
3280 UFBX_CONSTRAINT_AIM_UP_SCENE, // < Align the up vector to the scene global up vector
3281 UFBX_CONSTRAINT_AIM_UP_TO_NODE, // < Aim the up vector at `ufbx_constraint.aim_up_node`
3282 UFBX_CONSTRAINT_AIM_UP_ALIGN_NODE, // < Copy the up vector from `ufbx_constraint.aim_up_node`
3283 UFBX_CONSTRAINT_AIM_UP_VECTOR, // < Use `ufbx_constraint.aim_up_vector` as the up vector
3284 UFBX_CONSTRAINT_AIM_UP_NONE, // < Don't align the up vector to anything
3285
3286 UFBX_ENUM_FORCE_WIDTH(UFBX_CONSTRAINT_AIM_UP_TYPE)
3287} ufbx_constraint_aim_up_type;
3288
3289UFBX_ENUM_TYPE(ufbx_constraint_aim_up_type, UFBX_CONSTRAINT_AIM_UP_TYPE, UFBX_CONSTRAINT_AIM_UP_NONE);
3290
3291// Method to determine the up vector in aim constraints
3292typedef enum ufbx_constraint_ik_pole_type UFBX_ENUM_REPR {
3293 UFBX_CONSTRAINT_IK_POLE_VECTOR, // < Use towards calculated from `ufbx_constraint.targets`
3294 UFBX_CONSTRAINT_IK_POLE_NODE, // < Use `ufbx_constraint.ik_pole_vector` directly
3295
3296 UFBX_ENUM_FORCE_WIDTH(UFBX_CONSTRAINT_IK_POLE_TYPE)
3297} ufbx_constraint_ik_pole_type;
3298
3299UFBX_ENUM_TYPE(ufbx_constraint_ik_pole_type, UFBX_CONSTRAINT_IK_POLE_TYPE, UFBX_CONSTRAINT_IK_POLE_NODE);
3300
3302 union { ufbx_element element; struct {
3303 ufbx_string name;
3304 ufbx_props props;
3305 uint32_t element_id;
3306 uint32_t typed_id;
3307 }; };
3308
3309 // Type of constraint to use
3310 ufbx_constraint_type type;
3311 ufbx_string type_name;
3312
3313 // Node to be constrained
3314 ufbx_nullable ufbx_node *node;
3315
3316 // List of weighted targets for the constraint (pole vectors for IK)
3317 ufbx_constraint_target_list targets;
3318
3319 // State of the constraint
3320 ufbx_real weight;
3321 bool active;
3322
3323 // Translation/rotation/scale axes the constraint is applied to
3324 bool constrain_translation[3];
3325 bool constrain_rotation[3];
3326 bool constrain_scale[3];
3327
3328 // Offset from the constrained position
3329 ufbx_transform transform_offset;
3330
3331 // AIM: Target and up vectors
3332 ufbx_vec3 aim_vector;
3333 ufbx_constraint_aim_up_type aim_up_type;
3334 ufbx_nullable ufbx_node *aim_up_node;
3335 ufbx_vec3 aim_up_vector;
3336
3337 // SINGLE_CHAIN_IK: Target for the IK, `targets` contains pole vectors!
3338 ufbx_nullable ufbx_node *ik_effector;
3339 ufbx_nullable ufbx_node *ik_end_node;
3340 ufbx_vec3 ik_pole_vector;
3341};
3342
3343// -- Audio
3344
3346 union { ufbx_element element; struct {
3347 ufbx_string name;
3348 ufbx_props props;
3349 uint32_t element_id;
3350 uint32_t typed_id;
3351 }; };
3352
3353 // Clips contained in this layer.
3354 ufbx_audio_clip_list clips;
3355};
3356
3358 union { ufbx_element element; struct {
3359 ufbx_string name;
3360 ufbx_props props;
3361 uint32_t element_id;
3362 uint32_t typed_id;
3363 }; };
3364
3365 // Filename relative to the currently loaded file.
3366 // HINT: If using functions other than `ufbx_load_file()`, you can provide
3367 // `ufbx_load_opts.filename/raw_filename` to let ufbx resolve this.
3368 ufbx_string filename;
3369 // Absolute filename specified in the file.
3370 ufbx_string absolute_filename;
3371 // Relative filename specified in the file.
3372 // NOTE: May be absolute if the file is saved in a different drive.
3373 ufbx_string relative_filename;
3374
3375 // Filename relative to the loaded file, non-UTF-8 encoded.
3376 // HINT: If using functions other than `ufbx_load_file()`, you can provide
3377 // `ufbx_load_opts.filename/raw_filename` to let ufbx resolve this.
3378 ufbx_blob raw_filename;
3379 // Absolute filename specified in the file, non-UTF-8 encoded.
3380 ufbx_blob raw_absolute_filename;
3381 // Relative filename specified in the file, non-UTF-8 encoded.
3382 // NOTE: May be absolute if the file is saved in a different drive.
3383 ufbx_blob raw_relative_filename;
3384
3385 // Optional embedded content blob, eg. raw .png format data
3386 ufbx_blob content;
3387};
3388
3389// -- Miscellaneous
3390
3391typedef struct ufbx_bone_pose {
3392
3393 // Node to apply the pose to.
3394 ufbx_node *bone_node;
3395
3396 // Matrix from node local space to world space.
3397 ufbx_matrix bone_to_world;
3398
3399 // Matrix from node local space to parent space.
3400 // NOTE: FBX only stores world transformations so this is approximated from
3401 // the parent world transform.
3402 ufbx_matrix bone_to_parent;
3403
3405
3406UFBX_LIST_TYPE(ufbx_bone_pose_list, ufbx_bone_pose);
3407
3409 union { ufbx_element element; struct {
3410 ufbx_string name;
3411 ufbx_props props;
3412 uint32_t element_id;
3413 uint32_t typed_id;
3414 }; };
3415
3416 // Set if this pose is marked as a bind pose.
3417 bool is_bind_pose;
3418
3419 // List of bone poses.
3420 // Sorted by `ufbx_node.typed_id`.
3421 ufbx_bone_pose_list bone_poses;
3422};
3423
3425 union { ufbx_element element; struct {
3426 ufbx_string name;
3427 ufbx_props props;
3428 uint32_t element_id;
3429 uint32_t typed_id;
3430 }; };
3431};
3432
3433// -- Named elements
3434
3435typedef struct ufbx_name_element {
3436 ufbx_string name;
3437 ufbx_element_type type;
3438
3439 uint32_t _internal_key;
3440
3441 ufbx_element *element;
3443
3444UFBX_LIST_TYPE(ufbx_name_element_list, ufbx_name_element);
3445
3446// -- Scene
3447
3448// Scene is the root object loaded by ufbx that everything is accessed from.
3449
3450typedef enum ufbx_exporter UFBX_ENUM_REPR {
3451 UFBX_EXPORTER_UNKNOWN,
3452 UFBX_EXPORTER_FBX_SDK,
3453 UFBX_EXPORTER_BLENDER_BINARY,
3454 UFBX_EXPORTER_BLENDER_ASCII,
3455 UFBX_EXPORTER_MOTION_BUILDER,
3456
3457 UFBX_ENUM_FORCE_WIDTH(UFBX_EXPORTER)
3458} ufbx_exporter;
3459
3460UFBX_ENUM_TYPE(ufbx_exporter, UFBX_EXPORTER, UFBX_EXPORTER_MOTION_BUILDER);
3461
3462typedef struct ufbx_application {
3463 ufbx_string vendor;
3464 ufbx_string name;
3465 ufbx_string version;
3467
3468typedef enum ufbx_file_format UFBX_ENUM_REPR {
3469 UFBX_FILE_FORMAT_UNKNOWN, // < Unknown file format
3470 UFBX_FILE_FORMAT_FBX, // < .fbx Kaydara/Autodesk FBX file
3471 UFBX_FILE_FORMAT_OBJ, // < .obj Wavefront OBJ file
3472 UFBX_FILE_FORMAT_MTL, // < .mtl Wavefront MTL (Material template library) file
3473
3474 UFBX_ENUM_FORCE_WIDTH(UFBX_FILE_FORMAT)
3475} ufbx_file_format;
3476
3477UFBX_ENUM_TYPE(ufbx_file_format, UFBX_FILE_FORMAT, UFBX_FILE_FORMAT_MTL);
3478
3479typedef enum ufbx_warning_type UFBX_ENUM_REPR {
3480 // Missing external file file (for example .mtl for Wavefront .obj file or a
3481 // geometry cache)
3482 UFBX_WARNING_MISSING_EXTERNAL_FILE,
3483
3484 // Loaded a Wavefront .mtl file derived from the filename instead of a proper
3485 // `mtllib` statement.
3486 UFBX_WARNING_IMPLICIT_MTL,
3487
3488 // Truncated array has been auto-expanded.
3489 UFBX_WARNING_TRUNCATED_ARRAY,
3490
3491 // Geometry data has been defined but has no data.
3492 UFBX_WARNING_MISSING_GEOMETRY_DATA,
3493
3494 // Duplicated connection between two elements that shouldn't have.
3495 UFBX_WARNING_DUPLICATE_CONNECTION,
3496
3497 // Vertex 'W' attribute length differs from main attribute.
3498 UFBX_WARNING_BAD_VERTEX_W_ATTRIBUTE,
3499
3500 // Missing polygon mapping type.
3501 UFBX_WARNING_MISSING_POLYGON_MAPPING,
3502
3503 // Out-of-bounds index has been clamped to be in-bounds.
3504 // HINT: You can use `ufbx_index_error_handling` to adjust behavior.
3505 UFBX_WARNING_INDEX_CLAMPED,
3506
3507 // Non-UTF8 encoded strings.
3508 // HINT: You can use `ufbx_unicode_error_handling` to adjust behavior.
3509 UFBX_WARNING_BAD_UNICODE,
3510
3511 // Non-node element connected to root.
3512 UFBX_WARNING_BAD_ELEMENT_CONNECTED_TO_ROOT,
3513
3514 // Duplicated object ID in the file, connections will be wrong.
3515 UFBX_WARNING_DUPLICATE_OBJECT_ID,
3516
3517 // Empty face has been removed.
3518 // Use `ufbx_load_opts.allow_empty_faces` if you want to allow them.
3519 UFBX_WARNING_EMPTY_FACE_REMOVED,
3520
3521 // Unknown .obj file directive.
3522 UFBX_WARNING_UNKNOWN_OBJ_DIRECTIVE,
3523
3524 // Warnings after this one are deduplicated.
3525 // See `ufbx_warning.count` for how many times they happened.
3526 UFBX_WARNING_TYPE_FIRST_DEDUPLICATED = UFBX_WARNING_INDEX_CLAMPED,
3527
3528 UFBX_ENUM_FORCE_WIDTH(UFBX_WARNING_TYPE)
3529} ufbx_warning_type;
3530
3531UFBX_ENUM_TYPE(ufbx_warning_type, UFBX_WARNING_TYPE, UFBX_WARNING_UNKNOWN_OBJ_DIRECTIVE);
3532
3533// Warning about a non-fatal issue in the file.
3534// Often contains information about issues that ufbx has corrected about the
3535// file but it might indicate something is not working properly.
3536typedef struct ufbx_warning {
3537 // Type of the warning.
3538 ufbx_warning_type type;
3539 // Description of the warning.
3540 ufbx_string description;
3541 // The element related to this warning or `UFBX_NO_INDEX` if not related to a specific element.
3542 uint32_t element_id;
3543 // Number of times this warning was encountered.
3544 size_t count;
3545} ufbx_warning;
3546
3547UFBX_LIST_TYPE(ufbx_warning_list, ufbx_warning);
3548
3549typedef enum ufbx_thumbnail_format UFBX_ENUM_REPR {
3550 UFBX_THUMBNAIL_FORMAT_UNKNOWN, // < Unknown format
3551 UFBX_THUMBNAIL_FORMAT_RGB_24, // < 8-bit RGB pixels, in memory R,G,B
3552 UFBX_THUMBNAIL_FORMAT_RGBA_32, // < 8-bit RGBA pixels, in memory R,G,B,A
3553
3554 UFBX_ENUM_FORCE_WIDTH(UFBX_THUMBNAIL_FORMAT)
3555} ufbx_thumbnail_format;
3556
3557UFBX_ENUM_TYPE(ufbx_thumbnail_format, UFBX_THUMBNAIL_FORMAT, UFBX_THUMBNAIL_FORMAT_RGBA_32);
3558
3559// Specify how unit / coordinate system conversion should be performed.
3560// Affects how `ufbx_load_opts.target_axes` and `ufbx_load_opts.target_unit_meters` work,
3561// has no effect if neither is specified.
3562typedef enum ufbx_space_conversion UFBX_ENUM_REPR {
3563
3564 // Store the space conversion transform in the root node.
3565 // Sets `ufbx_node.local_transform` of the root node.
3566 UFBX_SPACE_CONVERSION_TRANSFORM_ROOT,
3567
3568 // Perform the conversion by using "adjust" transforms.
3569 // Compensates for the transforms using `ufbx_node.adjust_pre_rotation` and
3570 // `ufbx_node.adjust_pre_scale`. You don't need to account for these unless
3571 // you are manually building transforms from `ufbx_props`.
3572 UFBX_SPACE_CONVERSION_ADJUST_TRANSFORMS,
3573
3574 // Perform the conversion by scaling geometry in addition to adjusting transforms.
3575 // Compensates transforms like `UFBX_SPACE_CONVERSION_ADJUST_TRANSFORMS` but
3576 // applies scaling to geometry as well.
3577 UFBX_SPACE_CONVERSION_MODIFY_GEOMETRY,
3578
3579 UFBX_ENUM_FORCE_WIDTH(UFBX_SPACE_CONVERSION)
3580} ufbx_space_conversion;
3581
3582UFBX_ENUM_TYPE(ufbx_space_conversion, UFBX_SPACE_CONVERSION, UFBX_SPACE_CONVERSION_MODIFY_GEOMETRY);
3583
3584// Embedded thumbnail in the file, valid if the dimensions are non-zero.
3585typedef struct ufbx_thumbnail {
3586 ufbx_props props;
3587
3588 // Extents of the thumbnail
3589 uint32_t width;
3590 uint32_t height;
3591
3592 // Format of `ufbx_thumbnail.data`.
3593 ufbx_thumbnail_format format;
3594
3595 // Thumbnail pixel data, layout as contiguous rows from bottom to top.
3596 // See `ufbx_thumbnail.format` for the pixel format.
3597 ufbx_blob data;
3599
3600// Miscellaneous data related to the loaded file
3601typedef struct ufbx_metadata {
3602
3603 // List of non-fatal warnings about the file.
3604 // If you need to only check whether a specific warning was triggered you
3605 // can use `ufbx_metadata.has_warning[]`.
3606 ufbx_warning_list warnings;
3607
3608 // FBX ASCII file format.
3609 bool ascii;
3610
3611 // FBX version in integer format, eg. 7400 for 7.4.
3612 uint32_t version;
3613
3614 // File format of the source file.
3615 ufbx_file_format file_format;
3616
3617 // Index arrays may contain `UFBX_NO_INDEX` instead of a valid index
3618 // to indicate gaps.
3619 bool may_contain_no_index;
3620
3621 // May contain meshes with no defined vertex position.
3622 // NOTE: `ufbx_mesh.vertex_position.exists` may be `false`!
3623 bool may_contain_missing_vertex_position;
3624
3625 // Arrays may contain items with `NULL` element references.
3626 // See `ufbx_load_opts.connect_broken_elements`.
3627 bool may_contain_broken_elements;
3628
3629 // Some API guarantees do not apply (depending on unsafe options used).
3630 // Loaded with `ufbx_load_opts.allow_unsafe` enabled.
3631 bool is_unsafe;
3632
3633 // Flag for each possible warning type.
3634 // See `ufbx_metadata.warnings[]` for detailed warning information.
3635 bool has_warning[UFBX_WARNING_TYPE_COUNT];
3636
3637 ufbx_string creator;
3638 bool big_endian;
3639
3640 ufbx_string filename;
3641 ufbx_string relative_root;
3642
3643 ufbx_blob raw_filename;
3644 ufbx_blob raw_relative_root;
3645
3646 ufbx_exporter exporter;
3647 uint32_t exporter_version;
3648
3649 ufbx_props scene_props;
3650
3651 ufbx_application original_application;
3652 ufbx_application latest_application;
3653
3654 ufbx_thumbnail thumbnail;
3655
3656 bool geometry_ignored;
3657 bool animation_ignored;
3658 bool embedded_ignored;
3659
3660 size_t max_face_triangles;
3661
3662 size_t result_memory_used;
3663 size_t temp_memory_used;
3664 size_t result_allocs;
3665 size_t temp_allocs;
3666
3667 size_t element_buffer_size;
3668 size_t num_shader_textures;
3669
3670 ufbx_real bone_prop_size_unit;
3671 bool bone_prop_limb_length_relative;
3672
3673 ufbx_real ortho_size_unit;
3674
3675 int64_t ktime_second; // < One second in internal KTime units
3676
3677 ufbx_string original_file_path;
3678 ufbx_blob raw_original_file_path;
3679
3680 // Space conversion method used on the scene.
3681 ufbx_space_conversion space_conversion;
3682
3683 // Transform that has been applied to root for axis/unit conversion.
3684 ufbx_quat root_rotation;
3685 ufbx_real root_scale;
3686
3687 // Axis that the scene has been mirrored by.
3688 // All geometry has been mirrored in this axis.
3689 ufbx_mirror_axis mirror_axis;
3690
3691 // Amount geometry has been scaled.
3692 // See `UFBX_SPACE_CONVERSION_MODIFY_GEOMETRY`.
3693 ufbx_real geometry_scale;
3694
3696
3697typedef enum ufbx_time_mode UFBX_ENUM_REPR {
3698 UFBX_TIME_MODE_DEFAULT,
3699 UFBX_TIME_MODE_120_FPS,
3700 UFBX_TIME_MODE_100_FPS,
3701 UFBX_TIME_MODE_60_FPS,
3702 UFBX_TIME_MODE_50_FPS,
3703 UFBX_TIME_MODE_48_FPS,
3704 UFBX_TIME_MODE_30_FPS,
3705 UFBX_TIME_MODE_30_FPS_DROP,
3706 UFBX_TIME_MODE_NTSC_DROP_FRAME,
3707 UFBX_TIME_MODE_NTSC_FULL_FRAME,
3708 UFBX_TIME_MODE_PAL,
3709 UFBX_TIME_MODE_24_FPS,
3710 UFBX_TIME_MODE_1000_FPS,
3711 UFBX_TIME_MODE_FILM_FULL_FRAME,
3712 UFBX_TIME_MODE_CUSTOM,
3713 UFBX_TIME_MODE_96_FPS,
3714 UFBX_TIME_MODE_72_FPS,
3715 UFBX_TIME_MODE_59_94_FPS,
3716
3717 UFBX_ENUM_FORCE_WIDTH(UFBX_TIME_MODE)
3718} ufbx_time_mode;
3719
3720UFBX_ENUM_TYPE(ufbx_time_mode, UFBX_TIME_MODE, UFBX_TIME_MODE_59_94_FPS);
3721
3722typedef enum ufbx_time_protocol UFBX_ENUM_REPR {
3723 UFBX_TIME_PROTOCOL_SMPTE,
3724 UFBX_TIME_PROTOCOL_FRAME_COUNT,
3725 UFBX_TIME_PROTOCOL_DEFAULT,
3726
3727 UFBX_ENUM_FORCE_WIDTH(UFBX_TIME_PROTOCOL)
3728} ufbx_time_protocol;
3729
3730UFBX_ENUM_TYPE(ufbx_time_protocol, UFBX_TIME_PROTOCOL, UFBX_TIME_PROTOCOL_DEFAULT);
3731
3732typedef enum ufbx_snap_mode UFBX_ENUM_REPR {
3733 UFBX_SNAP_MODE_NONE,
3734 UFBX_SNAP_MODE_SNAP,
3735 UFBX_SNAP_MODE_PLAY,
3736 UFBX_SNAP_MODE_SNAP_AND_PLAY,
3737
3738 UFBX_ENUM_FORCE_WIDTH(UFBX_SNAP_MODE)
3739} ufbx_snap_mode;
3740
3741UFBX_ENUM_TYPE(ufbx_snap_mode, UFBX_SNAP_MODE, UFBX_SNAP_MODE_SNAP_AND_PLAY);
3742
3743// Global settings: Axes and time/unit scales
3744typedef struct ufbx_scene_settings {
3745 ufbx_props props;
3746
3747 // Mapping of X/Y/Z axes to world-space directions.
3748 // HINT: Use `ufbx_load_opts.target_axes` to normalize this.
3749 // NOTE: This contains the _original_ axes even if you supply `ufbx_load_opts.target_axes`.
3751
3752 // How many meters does a single world-space unit represent.
3753 // FBX files usually default to centimeters, reported as `0.01` here.
3754 // HINT: Use `ufbx_load_opts.target_unit_meters` to normalize this.
3755 ufbx_real unit_meters;
3756
3757 // Frames per second the animation is defined at.
3758 double frames_per_second;
3759
3760 ufbx_vec3 ambient_color;
3761 ufbx_string default_camera;
3762
3763 // Animation user interface settings.
3764 // HINT: Use `ufbx_scene_settings.frames_per_second` instead of interpreting these yourself.
3765 ufbx_time_mode time_mode;
3766 ufbx_time_protocol time_protocol;
3767 ufbx_snap_mode snap_mode;
3768
3769 // Original settings (?)
3770 ufbx_coordinate_axis original_axis_up;
3771 ufbx_real original_unit_meters;
3773
3775 ufbx_metadata metadata;
3776
3777 // Global settings
3778 ufbx_scene_settings settings;
3779
3780 // Node instances in the scene
3781 ufbx_node *root_node;
3782
3783 // Default animation descriptor
3784 ufbx_anim *anim;
3785
3786 union {
3787 struct {
3788 ufbx_unknown_list unknowns;
3789
3790 // Nodes
3791 ufbx_node_list nodes;
3792
3793 // Node attributes (common)
3794 ufbx_mesh_list meshes;
3795 ufbx_light_list lights;
3796 ufbx_camera_list cameras;
3797 ufbx_bone_list bones;
3798 ufbx_empty_list empties;
3799
3800 // Node attributes (curves/surfaces)
3801 ufbx_line_curve_list line_curves;
3802 ufbx_nurbs_curve_list nurbs_curves;
3803 ufbx_nurbs_surface_list nurbs_surfaces;
3804 ufbx_nurbs_trim_surface_list nurbs_trim_surfaces;
3805 ufbx_nurbs_trim_boundary_list nurbs_trim_boundaries;
3806
3807 // Node attributes (advanced)
3808 ufbx_procedural_geometry_list procedural_geometries;
3809 ufbx_stereo_camera_list stereo_cameras;
3810 ufbx_camera_switcher_list camera_switchers;
3811 ufbx_marker_list markers;
3812 ufbx_lod_group_list lod_groups;
3813
3814 // Deformers
3815 ufbx_skin_deformer_list skin_deformers;
3816 ufbx_skin_cluster_list skin_clusters;
3817 ufbx_blend_deformer_list blend_deformers;
3818 ufbx_blend_channel_list blend_channels;
3819 ufbx_blend_shape_list blend_shapes;
3820 ufbx_cache_deformer_list cache_deformers;
3821 ufbx_cache_file_list cache_files;
3822
3823 // Materials
3824 ufbx_material_list materials;
3825 ufbx_texture_list textures;
3826 ufbx_video_list videos;
3827 ufbx_shader_list shaders;
3828 ufbx_shader_binding_list shader_bindings;
3829
3830 // Animation
3831 ufbx_anim_stack_list anim_stacks;
3832 ufbx_anim_layer_list anim_layers;
3833 ufbx_anim_value_list anim_values;
3834 ufbx_anim_curve_list anim_curves;
3835
3836 // Collections
3837 ufbx_display_layer_list display_layers;
3838 ufbx_selection_set_list selection_sets;
3839 ufbx_selection_node_list selection_nodes;
3840
3841 // Constraints
3842 ufbx_character_list characters;
3843 ufbx_constraint_list constraints;
3844
3845 // Audio
3846 ufbx_audio_layer_list audio_layers;
3847 ufbx_audio_clip_list audio_clips;
3848
3849 // Miscellaneous
3850 ufbx_pose_list poses;
3851 ufbx_metadata_object_list metadata_objects;
3852 };
3853
3854 ufbx_element_list elements_by_type[UFBX_ELEMENT_TYPE_COUNT];
3855 };
3856
3857 // Unique texture files referenced by the scene.
3858 ufbx_texture_file_list texture_files;
3859
3860 // All elements and connections in the whole file
3861 ufbx_element_list elements; // < Sorted by `id`
3862 ufbx_connection_list connections_src; // < Sorted by `src,src_prop`
3863 ufbx_connection_list connections_dst; // < Sorted by `dst,dst_prop`
3864
3865 // Elements sorted by name, type
3866 ufbx_name_element_list elements_by_name;
3867
3868 // Enabled if `ufbx_load_opts.retain_dom == true`.
3869 ufbx_nullable ufbx_dom_node *dom_root;
3870};
3871
3872// -- Curves
3873
3874typedef struct ufbx_curve_point {
3875 bool valid;
3876 ufbx_vec3 position;
3877 ufbx_vec3 derivative;
3879
3880typedef struct ufbx_surface_point {
3881 bool valid;
3882 ufbx_vec3 position;
3883 ufbx_vec3 derivative_u;
3884 ufbx_vec3 derivative_v;
3886
3887// -- Mesh topology
3888
3889typedef enum ufbx_topo_flags UFBX_FLAG_REPR {
3890 UFBX_TOPO_NON_MANIFOLD = 0x1, // < Edge with three or more faces
3891
3892 UFBX_FLAG_FORCE_WIDTH(UFBX_TOPO_FLAGS)
3893} ufbx_topo_flags;
3894
3895typedef struct ufbx_topo_edge {
3896 uint32_t index; // < Starting index of the edge, always defined
3897 uint32_t next; // < Ending index of the edge / next per-face `ufbx_topo_edge`, always defined
3898 uint32_t prev; // < Previous per-face `ufbx_topo_edge`, always defined
3899 uint32_t twin; // < `ufbx_topo_edge` on the opposite side, `UFBX_NO_INDEX` if not found
3900 uint32_t face; // < Index into `mesh->faces[]`, always defined
3901 uint32_t edge; // < Index into `mesh->edges[]`, `UFBX_NO_INDEX` if not found
3902
3903 ufbx_topo_flags flags;
3905
3906// Vertex data array for `ufbx_generate_indices()`.
3907// NOTE: `ufbx_generate_indices()` compares the vertices using `memcmp()`, so
3908// any padding should be cleared to zero.
3909typedef struct ufbx_vertex_stream {
3910 void *data; // < Data pointer of shape `char[vertex_count][vertex_size]`.
3911 size_t vertex_count; // < Number of vertices in this stream, for sanity checking.
3912 size_t vertex_size; // < Size of a vertex in bytes.
3914
3915// -- Memory callbacks
3916
3917// You can optionally provide an allocator to ufbx, the default is to use the
3918// CRT malloc/realloc/free
3919
3920// Allocate `size` bytes, must be at least 8 byte aligned
3921typedef void *ufbx_alloc_fn(void *user, size_t size);
3922
3923// Reallocate `old_ptr` from `old_size` to `new_size`
3924// NOTE: If omit `alloc_fn` and `free_fn` they will be translated to:
3925// `alloc(size)` -> `realloc_fn(user, NULL, 0, size)`
3926// `free_fn(ptr, size)` -> `realloc_fn(user, ptr, size, 0)`
3927typedef void *ufbx_realloc_fn(void *user, void *old_ptr, size_t old_size, size_t new_size);
3928
3929// Free pointer `ptr` (of `size` bytes) returned by `alloc_fn` or `realloc_fn`
3930typedef void ufbx_free_fn(void *user, void *ptr, size_t size);
3931
3932// Free the allocator itself
3933typedef void ufbx_free_allocator_fn(void *user);
3934
3935// Allocator callbacks and user context
3936// NOTE: The allocator will be stored to the loaded scene and will be called
3937// again from `ufbx_free_scene()` so make sure `user` outlives that!
3938// You can use `free_allocator_fn()` to free the allocator yourself.
3939typedef struct ufbx_allocator {
3940 // Callback functions, see `typedef`s above for information
3941 ufbx_alloc_fn *alloc_fn;
3942 ufbx_realloc_fn *realloc_fn;
3943 ufbx_free_fn *free_fn;
3944 ufbx_free_allocator_fn *free_allocator_fn;
3945 void *user;
3947
3948typedef struct ufbx_allocator_opts {
3949 // Allocator callbacks
3950 ufbx_allocator allocator;
3951
3952 // Maximum number of bytes to allocate before failing
3953 size_t memory_limit;
3954
3955 // Maximum number of allocations to attempt before failing
3956 size_t allocation_limit;
3957
3958 // Threshold to swap from batched allocations to individual ones
3959 // Defaults to 1MB if set to zero
3960 // NOTE: If set to `1` ufbx will allocate everything in the smallest
3961 // possible chunks which may be useful for debugging (eg. ASAN)
3962 size_t huge_threshold;
3963
3964 // Maximum size of a single allocation containing sub-allocations.
3965 // Defaults to 16MB if set to zero
3966 // The maximum amount of wasted memory depends on `max_chunk_size` and
3967 // `huge_threshold`: each chunk can waste up to `huge_threshold` bytes
3968 // internally and the last chunk might be incomplete. So for example
3969 // with the defaults we can waste around 1MB/16MB = 6.25% overall plus
3970 // up to 32MB due to the two incomplete blocks. The actual amounts differ
3971 // slightly as the chunks start out at 4kB and double in size each time,
3972 // meaning that the maximum fixed overhead (up to 32MB with defaults) is
3973 // at most ~30% of the total allocation size.
3974 size_t max_chunk_size;
3975
3977
3978// -- IO callbacks
3979
3980// Try to read up to `size` bytes to `data`, return the amount of read bytes.
3981// Return `SIZE_MAX` to indicate an IO error.
3982typedef size_t ufbx_read_fn(void *user, void *data, size_t size);
3983
3984// Skip `size` bytes in the file.
3985typedef bool ufbx_skip_fn(void *user, size_t size);
3986
3987// Close the file
3988typedef void ufbx_close_fn(void *user);
3989
3990typedef struct ufbx_stream {
3991 ufbx_read_fn *read_fn; // < Required
3992 ufbx_skip_fn *skip_fn; // < Optional: Will use `read_fn()` if missing
3993 ufbx_close_fn *close_fn; // < Optional
3994
3995 // Context passed to other functions
3996 void *user;
3997} ufbx_stream;
3998
3999typedef enum ufbx_open_file_type UFBX_ENUM_REPR {
4000 UFBX_OPEN_FILE_MAIN_MODEL, // < Main model file
4001 UFBX_OPEN_FILE_GEOMETRY_CACHE, // < Unknown geometry cache file
4002 UFBX_OPEN_FILE_OBJ_MTL, // < .mtl material library file
4003
4004 UFBX_ENUM_FORCE_WIDTH(UFBX_OPEN_FILE_TYPE)
4005} ufbx_open_file_type;
4006
4007UFBX_ENUM_TYPE(ufbx_open_file_type, UFBX_OPEN_FILE_TYPE, UFBX_OPEN_FILE_OBJ_MTL);
4008
4009typedef struct ufbx_open_file_info {
4010 // Kind of file to load.
4011 ufbx_open_file_type type;
4012
4013 // Temporary allocator to use.
4014 ufbx_allocator temp_allocator;
4015
4016 // Original filename in the file, not resolved or UTF-8 encoded.
4017 // NOTE: Not necessarily NULL-terminated!
4018 ufbx_blob original_filename;
4020
4021// Callback for opening an external file from the filesystem
4022typedef bool ufbx_open_file_fn(void *user, ufbx_stream *stream, const char *path, size_t path_len, const ufbx_open_file_info *info);
4023
4024typedef struct ufbx_open_file_cb {
4025 ufbx_open_file_fn *fn;
4026 void *user;
4027
4028 UFBX_CALLBACK_IMPL(ufbx_open_file_cb, ufbx_open_file_fn, bool,
4029 (void *user, ufbx_stream *stream, const char *path, size_t path_len, const ufbx_open_file_info *info),
4030 (stream, path, path_len, info))
4032
4033// Memory stream options
4034typedef void ufbx_close_memory_fn(void *user, void *data, size_t data_size);
4035
4036typedef struct ufbx_close_memory_cb {
4037 ufbx_close_memory_fn *fn;
4038 void *user;
4039
4040 UFBX_CALLBACK_IMPL(ufbx_close_memory_cb, ufbx_close_memory_fn, void,
4041 (void *user, void *data, size_t data_size),
4042 (data, data_size))
4044
4045// Options for `ufbx_open_memory()`.
4047 uint32_t _begin_zero;
4048
4049 // Allocator to allocate the memory with.
4050 // NOTE: Used even if no copy is made to allocate a small metadata block.
4051 ufbx_allocator_opts allocator;
4052
4053 // Do not copy the memory.
4054 // You can use `close_cb` to free the memory when the stream is closed.
4055 // NOTE: This means the provided data pointer is referenced after creating
4056 // the memory stream, make sure the data stays valid until the stream is closed!
4057 ufbx_unsafe bool no_copy;
4058
4059 // Callback to free the memory blob.
4060 ufbx_close_memory_cb close_cb;
4061
4062 uint32_t _end_zero;
4064
4065// Detailed error stack frame
4066typedef struct ufbx_error_frame {
4067 uint32_t source_line;
4068 ufbx_string function;
4069 ufbx_string description;
4071
4072// Error causes (and `UFBX_ERROR_NONE` for no error).
4073typedef enum ufbx_error_type UFBX_ENUM_REPR {
4074
4075 // No error, operation has been performed successfully.
4076 UFBX_ERROR_NONE,
4077
4078 // Unspecified error, most likely caused by an invalid FBX file or a file
4079 // that contains something ufbx can't handle.
4080 UFBX_ERROR_UNKNOWN,
4081
4082 // File not found.
4083 UFBX_ERROR_FILE_NOT_FOUND,
4084
4085 // Empty file.
4086 UFBX_ERROR_EMPTY_FILE,
4087
4088 // External file not found.
4089 // See `ufbx_load_opts.load_external_files` for more information.
4090 UFBX_ERROR_EXTERNAL_FILE_NOT_FOUND,
4091
4092 // Out of memory (allocator returned `NULL`).
4093 UFBX_ERROR_OUT_OF_MEMORY,
4094
4095 // `ufbx_allocator_opts.memory_limit` exhausted.
4096 UFBX_ERROR_MEMORY_LIMIT,
4097
4098 // `ufbx_allocator_opts.allocation_limit` exhausted.
4099 UFBX_ERROR_ALLOCATION_LIMIT,
4100
4101 // File ended abruptly.
4102 UFBX_ERROR_TRUNCATED_FILE,
4103
4104 // IO read error.
4105 // eg. returning `SIZE_MAX` from `ufbx_stream.read_fn` or stdio `ferror()` condition.
4106 UFBX_ERROR_IO,
4107
4108 // User cancelled the loading via `ufbx_load_opts.progress_cb` returning `UFBX_PROGRESS_CANCEL`.
4109 UFBX_ERROR_CANCELLED,
4110
4111 // Could not detect file format from file data or filename.
4112 // HINT: You can supply it manually using `ufbx_load_opts.file_format` or use `ufbx_load_opts.filename`
4113 // when using `ufbx_load_memory()` to let ufbx guess the format from the extension.
4114 UFBX_ERROR_UNRECOGNIZED_FILE_FORMAT,
4115
4116 // Options struct (eg. `ufbx_load_opts`) is not cleared to zero.
4117 // Make sure you initialize the structure to zero via eg.
4118 // ufbx_load_opts opts = { 0 }; // C
4119 // ufbx_load_opts opts = { }; // C++
4120 UFBX_ERROR_UNINITIALIZED_OPTIONS,
4121
4122 // The vertex streams in `ufbx_generate_indices()` are empty.
4123 UFBX_ERROR_ZERO_VERTEX_SIZE,
4124
4125 // Vertex stream passed to `ufbx_generate_indices()`.
4126 UFBX_ERROR_TRUNCATED_VERTEX_STREAM,
4127
4128 // Invalid UTF-8 encountered in a file when loading with `UFBX_UNICODE_ERROR_HANDLING_ABORT_LOADING`.
4129 UFBX_ERROR_INVALID_UTF8,
4130
4131 // Feature needed for the operation has been compiled out.
4132 UFBX_ERROR_FEATURE_DISABLED,
4133
4134 // Attempting to tessellate an invalid NURBS object.
4135 // See `ufbx_nurbs_basis.valid`.
4136 UFBX_ERROR_BAD_NURBS,
4137
4138 // Out of bounds index in the file when loading with `UFBX_INDEX_ERROR_HANDLING_ABORT_LOADING`.
4139 UFBX_ERROR_BAD_INDEX,
4140
4141 // Node is deeper than `ufbx_load_opts.node_depth_limit` in the hierarchy.
4142 UFBX_ERROR_NODE_DEPTH_LIMIT,
4143
4144 // Error parsing ASCII array in a thread.
4145 // Threaded ASCII parsing is slightly more strict than non-threaded, for cursed files,
4146 // set `ufbx_load_opts.force_single_thread_ascii_parsing` to `true`.
4147 UFBX_ERROR_THREADED_ASCII_PARSE,
4148
4149 // Unsafe options specified without enabling `ufbx_load_opts.allow_unsafe`.
4150 UFBX_ERROR_UNSAFE_OPTIONS,
4151
4152 // Duplicated override property in `ufbx_create_anim()`
4153 UFBX_ERROR_DUPLICATE_OVERRIDE,
4154
4155 UFBX_ENUM_FORCE_WIDTH(UFBX_ERROR_TYPE)
4156} ufbx_error_type;
4157
4158UFBX_ENUM_TYPE(ufbx_error_type, UFBX_ERROR_TYPE, UFBX_ERROR_DUPLICATE_OVERRIDE);
4159
4160// Error description with detailed stack trace
4161// HINT: You can use `ufbx_format_error()` for formatting the error
4162typedef struct ufbx_error {
4163 ufbx_error_type type;
4164 ufbx_string description;
4165 uint32_t stack_size;
4166 ufbx_error_frame stack[UFBX_ERROR_STACK_MAX_DEPTH];
4167 size_t info_length;
4168 char info[UFBX_ERROR_INFO_LENGTH];
4169} ufbx_error;
4170
4171// -- Progress callbacks
4172
4173typedef struct ufbx_progress {
4174 uint64_t bytes_read;
4175 uint64_t bytes_total;
4177
4178typedef enum ufbx_progress_result UFBX_ENUM_REPR {
4179 UFBX_PROGRESS_CONTINUE = 0x100,
4180 UFBX_PROGRESS_CANCEL = 0x200,
4181
4182 UFBX_ENUM_FORCE_WIDTH(UFBX_PROGRESS_RESULT)
4183} ufbx_progress_result;
4184
4185// Called periodically with the current progress
4186// Return `false` to cancel further processing
4187typedef ufbx_progress_result ufbx_progress_fn(void *user, const ufbx_progress *progress);
4188
4189typedef struct ufbx_progress_cb {
4190 ufbx_progress_fn *fn;
4191 void *user;
4192
4193 UFBX_CALLBACK_IMPL(ufbx_progress_cb, ufbx_progress_fn, ufbx_progress_result,
4194 (void *user, const ufbx_progress *progress),
4195 (progress))
4197
4198// -- Inflate
4199
4202
4203// Source data/stream to decompress with `ufbx_inflate()`
4205 // Total size of the data in bytes
4206 size_t total_size;
4207
4208 // (optional) Initial or complete data chunk
4209 const void *data;
4210 size_t data_size;
4211
4212 // (optional) Temporary buffer, defaults to 256b stack buffer
4213 void *buffer;
4214 size_t buffer_size;
4215
4216 // (optional) Streaming read function, concatenated after `data`
4217 ufbx_read_fn *read_fn;
4218 void *read_user;
4219
4220 // (optional) Progress reporting
4221 ufbx_progress_cb progress_cb;
4222 uint64_t progress_interval_hint; // < Bytes between progress report calls
4223
4224 // (optional) Change the progress scope
4225 uint64_t progress_size_before;
4226 uint64_t progress_size_after;
4227
4228 // (optional) No the DEFLATE header
4229 bool no_header;
4230
4231 // (optional) No the Adler32 checksum
4232 bool no_checksum;
4233
4234 // (optional) Force internal fast lookup bit amount
4235 size_t internal_fast_bits;
4236};
4237
4238// Persistent data between `ufbx_inflate()` calls
4239// NOTE: You must set `initialized` to `false`, but `data` may be uninitialized
4241 bool initialized;
4242 uint64_t data[1024];
4243};
4244
4245typedef enum ufbx_index_error_handling UFBX_ENUM_REPR {
4246 // Clamp to a valid value.
4247 UFBX_INDEX_ERROR_HANDLING_CLAMP,
4248 // Set bad indices to `UFBX_NO_INDEX`.
4249 // This is the recommended way if you need to deal with files with gaps in information.
4250 // HINT: If you use this `ufbx_get_vertex_TYPE()` functions will return zero
4251 // on invalid indices instead of failing.
4252 UFBX_INDEX_ERROR_HANDLING_NO_INDEX,
4253 // Fail loading entierely when encountering a bad index.
4254 UFBX_INDEX_ERROR_HANDLING_ABORT_LOADING,
4255 // Pass bad indices through as-is.
4256 // Requires `ufbx_load_opts.allow_unsafe`.
4257 // UNSAFE: Breaks any API guarantees regarding indexes being in bounds and makes
4258 // `ufbx_get_vertex_TYPE()` memory-unsafe to use.
4259 UFBX_INDEX_ERROR_HANDLING_UNSAFE_IGNORE,
4260
4261 UFBX_ENUM_FORCE_WIDTH(UFBX_INDEX_ERROR_HANDLING)
4262} ufbx_index_error_handling;
4263
4264UFBX_ENUM_TYPE(ufbx_index_error_handling, UFBX_INDEX_ERROR_HANDLING, UFBX_INDEX_ERROR_HANDLING_UNSAFE_IGNORE);
4265
4266typedef enum ufbx_unicode_error_handling UFBX_ENUM_REPR {
4267 // Replace errors with U+FFFD "Replacement Character"
4268 UFBX_UNICODE_ERROR_HANDLING_REPLACEMENT_CHARACTER,
4269 // Replace errors with '_' U+5F "Low Line"
4270 UFBX_UNICODE_ERROR_HANDLING_UNDERSCORE,
4271 // Replace errors with '?' U+3F "Question Mark"
4272 UFBX_UNICODE_ERROR_HANDLING_QUESTION_MARK,
4273 // Remove errors from the output
4274 UFBX_UNICODE_ERROR_HANDLING_REMOVE,
4275 // Fail loading on encountering an Unicode error
4276 UFBX_UNICODE_ERROR_HANDLING_ABORT_LOADING,
4277 // Ignore and pass-through non-UTF-8 string data.
4278 // Requires `ufbx_load_opts.allow_unsafe`.
4279 // UNSAFE: Breaks API guarantee that `ufbx_string` is UTF-8 encoded.
4280 UFBX_UNICODE_ERROR_HANDLING_UNSAFE_IGNORE,
4281
4282 UFBX_ENUM_FORCE_WIDTH(UFBX_UNICODE_ERROR_HANDLING)
4283} ufbx_unicode_error_handling;
4284
4285UFBX_ENUM_TYPE(ufbx_unicode_error_handling, UFBX_UNICODE_ERROR_HANDLING, UFBX_UNICODE_ERROR_HANDLING_UNSAFE_IGNORE);
4286
4287// How to handle FBX node geometry transforms.
4288// FBX nodes can have "geometry transforms" that affect only the attached meshes,
4289// but not the children. This is not allowed in many scene representations so
4290// ufbx provides some ways to simplify them.
4291// Geometry transforms can also be used to transform any other attributes such
4292// as lights or cameras.
4293typedef enum ufbx_geometry_transform_handling UFBX_ENUM_REPR {
4294
4295 // Preserve the geometry transforms as-is.
4296 // To be correct for all files you have to use `ufbx_node.geometry_transform`,
4297 // `ufbx_node.geometry_to_node`, or `ufbx_node.geometry_to_world` to compensate
4298 // for any potential geometry transforms.
4299 UFBX_GEOMETRY_TRANSFORM_HANDLING_PRESERVE,
4300
4301 // Add helper nodes between the nodes and geometry where needed.
4302 // The created nodes have `ufbx_node.is_geometry_transform_helper` set and are
4303 // named `ufbx_load_opts.geometry_transform_helper_name`.
4304 UFBX_GEOMETRY_TRANSFORM_HANDLING_HELPER_NODES,
4305
4306 // Modify the geometry of meshes attached to nodes with geometry transforms.
4307 // Will add helper nodes like `UFBX_GEOMETRY_TRANSFORM_HANDLING_HELPER_NODES` if
4308 // necessary, for example if there are multiple instances of the same mesh with
4309 // geometry transforms.
4310 UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY,
4311
4312 // Modify the geometry of meshes attached to nodes with geometry transforms.
4313 // NOTE: This will not work correctly for instanced geometry.
4314 UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY_NO_FALLBACK,
4315
4316 UFBX_ENUM_FORCE_WIDTH(UFBX_GEOMETRY_TRANSFORM_HANDLING)
4317} ufbx_geometry_transform_handling;
4318
4319UFBX_ENUM_TYPE(ufbx_geometry_transform_handling, UFBX_GEOMETRY_TRANSFORM_HANDLING, UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY_NO_FALLBACK);
4320
4321// How to handle FBX transform inherit modes.
4322typedef enum ufbx_inherit_mode_handling UFBX_ENUM_REPR {
4323
4324 // Preserve inherit mode in `ufbx_node.inherit_mode`.
4325 // NOTE: To correctly handle all scenes you would need to handle the
4326 // non-standard inherit modes.
4327 UFBX_INHERIT_MODE_HANDLING_PRESERVE,
4328
4329 // Create scale helper nodes parented to nodes that need special inheritance.
4330 // Scale helper nodes will have `ufbx_node.is_scale_helper` and parents of
4331 // scale helpers will have `ufbx_node.scale_helper` pointing to it.
4332 UFBX_INHERIT_MODE_HANDLING_HELPER_NODES,
4333
4334 // Attempt to compensate for bone scale by inversely scaling children.
4335 // NOTE: This only works for uniform non-animated scaling, if scale is
4336 // non-uniform or animated, ufbx will add scale helpers in the same way
4337 // as `UFBX_INHERIT_MODE_HANDLING_HELPER_NODES`.
4338 UFBX_INHERIT_MODE_HANDLING_COMPENSATE,
4339
4340 // Attempt to compensate for bone scale by inversely scaling children.
4341 // Will never create helper nodes.
4342 UFBX_INHERIT_MODE_HANDLING_COMPENSATE_NO_FALLBACK,
4343
4344 // Ignore non-standard inheritance modes.
4345 // Forces all nodes to have `UFBX_INHERIT_MODE_NORMAL` regardless of the
4346 // inherit mode specified in the file. This can be useful for emulating
4347 // results from importers/programs that don't support inherit modes.
4348 UFBX_INHERIT_MODE_HANDLING_IGNORE,
4349
4350 UFBX_ENUM_FORCE_WIDTH(UFBX_INHERIT_MODE_HANDLING)
4351} ufbx_inherit_mode_handling;
4352
4353UFBX_ENUM_TYPE(ufbx_inherit_mode_handling, UFBX_INHERIT_MODE_HANDLING, UFBX_INHERIT_MODE_HANDLING_IGNORE);
4354
4355// How to handle FBX transform pivots.
4356typedef enum ufbx_pivot_handling UFBX_ENUM_REPR {
4357
4358 // Take pivots into account when computing the transform.
4359 UFBX_PIVOT_HANDLING_RETAIN,
4360
4361 // Translate objects to be located at their pivot.
4362 // NOTE: Only applied if rotation and scaling pivots are equal.
4363 // NOTE: Results in geometric translation. Use `ufbx_geometry_transform_handling`
4364 // to interpret these in a standard scene graph.
4365 UFBX_PIVOT_HANDLING_ADJUST_TO_PIVOT,
4366
4367 UFBX_ENUM_FORCE_WIDTH(UFBX_PIVOT_HANDLING)
4368} ufbx_pivot_handling;
4369
4370UFBX_ENUM_TYPE(ufbx_pivot_handling, UFBX_PIVOT_HANDLING, UFBX_PIVOT_HANDLING_ADJUST_TO_PIVOT);
4371
4372typedef enum ufbx_baked_key_flags UFBX_FLAG_REPR {
4373 // This keyframe represents a constant step from the left side
4374 UFBX_BAKED_KEY_STEP_LEFT = 0x1,
4375 // This keyframe represents a constant step from the right side
4376 UFBX_BAKED_KEY_STEP_RIGHT = 0x2,
4377 // This keyframe is the main part of a step
4378 // Bordering either `UFBX_BAKED_KEY_STEP_LEFT` or `UFBX_BAKED_KEY_STEP_RIGHT`.
4379 UFBX_BAKED_KEY_STEP_KEY = 0x4,
4380 // This keyframe is a real keyframe in the source animation
4381 UFBX_BAKED_KEY_KEYFRAME = 0x8,
4382 // This keyframe has been reduced by maximum sample rate.
4383 // See `ufbx_bake_opts.maximum_sample_rate`.
4384 UFBX_BAKED_KEY_REDUCED = 0x10,
4385
4386 UFBX_FLAG_FORCE_WIDTH(UFBX_BAKED_KEY)
4387} ufbx_baked_key_flags;
4388
4389typedef struct ufbx_baked_vec3 {
4390 double time; // < Time of the keyframe, in seconds
4391 ufbx_vec3 value; // < Value at `time`, can be linearly interpolated
4392 ufbx_baked_key_flags flags; // < Additional information about the keyframe
4394
4395UFBX_LIST_TYPE(ufbx_baked_vec3_list, ufbx_baked_vec3);
4396
4397typedef struct ufbx_baked_quat {
4398 double time; // < Time of the keyframe, in seconds
4399 ufbx_quat value; // < Value at `time`, can be (spherically) linearly interpolated
4400 ufbx_baked_key_flags flags; // < Additional information about the keyframe
4402
4403UFBX_LIST_TYPE(ufbx_baked_quat_list, ufbx_baked_quat);
4404
4405// Baked transform animation for a single node.
4406typedef struct ufbx_baked_node {
4407
4408 // Typed ID of the node, maps to `ufbx_scene.nodes[]`.
4409 uint32_t typed_id;
4410 // Element ID of the element, maps to `ufbx_scene.elements[]`.
4411 uint32_t element_id;
4412
4413 // The translation channel has constant values for the whole animation.
4414 bool constant_translation;
4415 // The rotation channel has constant values for the whole animation.
4416 bool constant_rotation;
4417 // The scale channel has constant values for the whole animation.
4418 bool constant_scale;
4419
4420 // Translation keys for the animation, maps to `ufbx_node.local_transform.translation`.
4421 ufbx_baked_vec3_list translation_keys;
4422 // Rotation keyframes, maps to `ufbx_node.local_transform.rotation`.
4423 ufbx_baked_quat_list rotation_keys;
4424 // Scale keyframes, maps to `ufbx_node.local_transform.scale`.
4425 ufbx_baked_vec3_list scale_keys;
4426
4428
4429UFBX_LIST_TYPE(ufbx_baked_node_list, ufbx_baked_node);
4430
4431// Baked property animation.
4432typedef struct ufbx_baked_prop {
4433 // Name of the property, eg. `"Visibility"`.
4434 ufbx_string name;
4435 // The value of the property is constant for the whole animation.
4436 bool constant_value;
4437 // Property value keys.
4438 ufbx_baked_vec3_list keys;
4440
4441UFBX_LIST_TYPE(ufbx_baked_prop_list, ufbx_baked_prop);
4442
4443// Baked property animation for a single element.
4444typedef struct ufbx_baked_element {
4445 // Element ID of the element, maps to `ufbx_scene.elements[]`.
4446 uint32_t element_id;
4447 // List of properties the animation modifies.
4448 ufbx_baked_prop_list props;
4450
4451UFBX_LIST_TYPE(ufbx_baked_element_list, ufbx_baked_element);
4452
4454 // Memory statistics
4455 size_t result_memory_used;
4456 size_t temp_memory_used;
4457 size_t result_allocs;
4458 size_t temp_allocs;
4460
4461// Animation baked into linearly interpolated keyframes.
4462// See `ufbx_bake_anim()`.
4463typedef struct ufbx_baked_anim {
4464
4465 // Nodes that are modified by the animation.
4466 // Some nodes may be missing if the specified animation does not transform them.
4467 // Conversely, some non-obviously animated nodes may be included as exporters
4468 // often may add dummy keyframes for objects.
4469 ufbx_baked_node_list nodes;
4470
4471 // Element properties modified by the animation.
4472 ufbx_baked_element_list elements;
4473
4474 // Playback time range for the animation.
4475 double playback_time_begin;
4476 double playback_time_end;
4477 double playback_duration;
4478
4479 // Keyframe time range.
4480 double key_time_min;
4481 double key_time_max;
4482
4483 // Additional bake information.
4484 ufbx_baked_anim_metadata metadata;
4485
4487
4488// -- Thread API
4489//
4490// NOTE: This API is still experimental and may change.
4491// Documentation is currently missing on purpose.
4492
4493typedef uintptr_t ufbx_thread_pool_context;
4494
4496 uint32_t max_concurrent_tasks;
4498
4499typedef bool ufbx_thread_pool_init_fn(void *user, ufbx_thread_pool_context ctx, const ufbx_thread_pool_info *info);
4500typedef bool ufbx_thread_pool_run_fn(void *user, ufbx_thread_pool_context ctx, uint32_t group, uint32_t start_index, uint32_t count);
4501typedef bool ufbx_thread_pool_wait_fn(void *user, ufbx_thread_pool_context ctx, uint32_t group, uint32_t max_index);
4502typedef void ufbx_thread_pool_free_fn(void *user, ufbx_thread_pool_context ctx);
4503
4504typedef struct ufbx_thread_pool {
4505 ufbx_thread_pool_init_fn *init_fn;
4506 ufbx_thread_pool_run_fn *run_fn;
4507 ufbx_thread_pool_wait_fn *wait_fn;
4508 ufbx_thread_pool_free_fn *free_fn;
4509 void *user;
4511
4512typedef struct ufbx_thread_opts {
4513 ufbx_thread_pool pool;
4514 size_t num_tasks;
4515 size_t memory_limit;
4517
4518// -- Main API
4519
4520// Options for `ufbx_load_file/memory/stream/stdio()`
4521// NOTE: Initialize to zero with `{ 0 }` (C) or `{ }` (C++)
4522typedef struct ufbx_load_opts {
4523 uint32_t _begin_zero;
4524
4525 ufbx_allocator_opts temp_allocator; // < Allocator used during loading
4526 ufbx_allocator_opts result_allocator; // < Allocator used for the final scene
4527 ufbx_thread_opts thread_opts; // < Threading options
4528
4529 // Preferences
4530 bool ignore_geometry; // < Do not load geometry datsa (vertices, indices, etc)
4531 bool ignore_animation; // < Do not load animation curves
4532 bool ignore_embedded; // < Do not load embedded content
4533 bool ignore_all_content; // < Do not load any content (geometry, animation, embedded)
4534
4535 bool evaluate_skinning; // < Evaluate skinning (see ufbx_mesh.skinned_vertices)
4536 bool evaluate_caches; // < Evaluate vertex caches (see ufbx_mesh.skinned_vertices)
4537
4538 // Try to open external files referenced by the main file automatically.
4539 // Applies to geometry caches and .mtl files for OBJ.
4540 // NOTE: This may be risky for untrusted data as the input files may contain
4541 // references to arbitrary paths in the filesystem.
4542 // NOTE: This only applies to files *implicitly* referenced by the scene, if
4543 // you request additional files via eg. `ufbx_load_opts.obj_mtl_path` they
4544 // are still loaded.
4545 // NOTE: Will fail loading if any external files are not found by default, use
4546 // `ufbx_load_opts.ignore_missing_external_files` to suppress this, in this case
4547 // you can find the errors at `ufbx_metadata.warnings[]` as `UFBX_WARNING_MISSING_EXTERNAL_FILE`.
4548 bool load_external_files;
4549
4550 // Don't fail loading if external files are not found.
4551 bool ignore_missing_external_files;
4552
4553 // Don't compute `ufbx_skin_deformer` `vertices` and `weights` arrays saving
4554 // a bit of memory and time if not needed
4555 bool skip_skin_vertices;
4556
4557 // Skip computing `ufbx_mesh.material_parts[]` and `ufbx_mesh.face_group_parts[]`.
4558 bool skip_mesh_parts;
4559
4560 // Clean-up skin weights by removing negative, zero and NAN weights.
4561 bool clean_skin_weights;
4562
4563 // Read Blender materials as PBR values.
4564 // Blender converts PBR materials to legacy FBX Phong materials in a deterministic way.
4565 // If this setting is enabled, such materials will be read as `UFBX_SHADER_BLENDER_PHONG`,
4566 // which means ufbx will be able to parse roughness and metallic textures.
4567 bool use_blender_pbr_material;
4568
4569 // Don't adjust reading the FBX file depending on the detected exporter
4570 bool disable_quirks;
4571
4572 // Don't allow partially broken FBX files to load
4573 bool strict;
4574
4575 // Force ASCII parsing to use a single thread.
4576 // The multi-threaded ASCII parsing is slightly more lenient as it ignores
4577 // the self-reported size of ASCII arrays, that threaded parsing depends on.
4578 bool force_single_thread_ascii_parsing;
4579
4580 // UNSAFE: If enabled allows using unsafe options that may fundamentally
4581 // break the API guarantees.
4582 ufbx_unsafe bool allow_unsafe;
4583
4584 // Specify how to handle broken indices.
4585 ufbx_index_error_handling index_error_handling;
4586
4587 // Connect related elements even if they are broken. If `false` (default)
4588 // `ufbx_skin_cluster` with a missing `bone` field are _not_ included in
4589 // the `ufbx_skin_deformer.clusters[]` array for example.
4590 bool connect_broken_elements;
4591
4592 // Allow nodes that are not connected in any way to the root. Conversely if
4593 // disabled, all lone nodes will be parented under `ufbx_scene.root_node`.
4594 bool allow_nodes_out_of_root;
4595
4596 // Allow meshes with no vertex position attribute.
4597 // NOTE: If this is set `ufbx_mesh.vertex_position.exists` may be `false`.
4598 bool allow_missing_vertex_position;
4599
4600 // Allow faces with zero indices.
4601 bool allow_empty_faces;
4602
4603 // Generate vertex normals for a meshes that are missing normals.
4604 // You can see if the normals have been generated from `ufbx_mesh.generated_normals`.
4605 bool generate_missing_normals;
4606
4607 // Ignore `open_file_cb` when loading the main file.
4608 bool open_main_file_with_default;
4609
4610 // Path separator character, defaults to '\' on Windows and '/' otherwise.
4611 char path_separator;
4612
4613 // Maximum depth of the node hirerachy.
4614 // Will fail with `UFBX_ERROR_NODE_DEPTH_LIMIT` if a node is deeper than this limit.
4615 // NOTE: The default of 0 allows arbitrarily deep hierarchies. Be careful if using
4616 // recursive algorithms without setting this limit.
4617 uint32_t node_depth_limit;
4618
4619 // Estimated file size for progress reporting
4620 uint64_t file_size_estimate;
4621
4622 // Buffer size in bytes to use for reading from files or IO callbacks
4623 size_t read_buffer_size;
4624
4625 // Filename to use as a base for relative file paths if not specified using
4626 // `ufbx_load_file()`. Use `length = SIZE_MAX` for NULL-terminated strings.
4627 // `raw_filename` will be derived from this if empty.
4628 ufbx_string filename;
4629
4630 // Raw non-UTF8 filename. Does not support NULL termination.
4631 // `filename` will be derived from this if empty.
4632 ufbx_blob raw_filename;
4633
4634 // Progress reporting
4635 ufbx_progress_cb progress_cb;
4636 uint64_t progress_interval_hint; // < Bytes between progress report calls
4637
4638 // External file callbacks (defaults to stdio.h)
4639 ufbx_open_file_cb open_file_cb;
4640
4641 // How to handle geometry transforms in the nodes.
4642 // See `ufbx_geometry_transform_handling` for an explanation.
4643 ufbx_geometry_transform_handling geometry_transform_handling;
4644
4645 // How to handle unconventional transform inherit modes.
4646 // See `ufbx_inherit_mode_handling` for an explanation.
4647 ufbx_inherit_mode_handling inherit_mode_handling;
4648
4649 // How to handle pivots.
4650 // See `ufbx_pivot_handling` for an explanation.
4651 ufbx_pivot_handling pivot_handling;
4652
4653 // How to perform space conversion by `target_axes` and `target_unit_meters`.
4654 // See `ufbx_space_conversion` for an explanation.
4655 ufbx_space_conversion space_conversion;
4656
4657 // Axis used to mirror for conversion between left-handed and right-handed coordinates.
4658 ufbx_mirror_axis handedness_conversion_axis;
4659
4660 // Do not change winding of faces when converting handedness.
4661 bool handedness_conversion_retain_winding;
4662
4663 // Reverse winding of all faces.
4664 // If `handedness_conversion_retain_winding` is not specified, mirrored meshes
4665 // will retain their original winding.
4666 bool reverse_winding;
4667
4668 // Apply an implicit root transformation to match axes.
4669 // Used if `ufbx_coordinate_axes_valid(target_axes)`.
4670 ufbx_coordinate_axes target_axes;
4671
4672 // Scale the scene so that one world-space unit is `target_unit_meters` meters.
4673 // By default units are not scaled.
4674 ufbx_real target_unit_meters;
4675
4676 // Target space for camera.
4677 // By default FBX cameras point towards the positive X axis.
4678 // Used if `ufbx_coordinate_axes_valid(target_camera_axes)`.
4679 ufbx_coordinate_axes target_camera_axes;
4680
4681 // Target space for directed lights.
4682 // By default FBX lights point towards the negative Y axis.
4683 // Used if `ufbx_coordinate_axes_valid(target_light_axes)`.
4684 ufbx_coordinate_axes target_light_axes;
4685
4686 // Name for dummy geometry transform helper nodes.
4687 // See `UFBX_GEOMETRY_TRANSFORM_HANDLING_HELPER_NODES`.
4688 ufbx_string geometry_transform_helper_name;
4689
4690 // Name for dummy scale helper nodes.
4691 // See `UFBX_INHERIT_MODE_HANDLING_HELPER_NODES`.
4692 ufbx_string scale_helper_name;
4693
4694 // Normalize vertex normals.
4695 bool normalize_normals;
4696
4697 // Normalize tangents and bitangents.
4698 bool normalize_tangents;
4699
4700 // Override for the root transform
4701 bool use_root_transform;
4702 ufbx_transform root_transform;
4703
4704 // Animation keyframe clamp threhsold, only applies to specific interpolation modes.
4705 double key_clamp_threshold;
4706
4707 // Specify how to handle Unicode errors in strings.
4708 ufbx_unicode_error_handling unicode_error_handling;
4709
4710 // Retain the 'W' component of mesh normal/tangent/bitangent.
4711 // See `ufbx_vertex_attrib.values_w`.
4712 bool retain_vertex_attrib_w;
4713
4714 // Retain the raw document structure using `ufbx_dom_node`.
4715 bool retain_dom;
4716
4717 // Force a specific file format instead of detecting it.
4718 ufbx_file_format file_format;
4719
4720 // How far to read into the file to determine the file format.
4721 // Default: 16kB
4722 size_t file_format_lookahead;
4723
4724 // Do not attempt to detect file format from file content.
4725 bool no_format_from_content;
4726
4727 // Do not attempt to detect file format from filename extension.
4728 // ufbx primarily detects file format from the file header,
4729 // this is just used as a fallback.
4730 bool no_format_from_extension;
4731
4732 // (.obj) Try to find .mtl file with matching filename as the .obj file.
4733 // Used if the file specified `mtllib` line is not found, eg. for a file called
4734 // `model.obj` that contains the line `usemtl materials.mtl`, ufbx would first
4735 // try to open `materials.mtl` and if that fails it tries to open `model.mtl`.
4736 bool obj_search_mtl_by_filename;
4737
4738 // (.obj) Don't split geometry into meshes by object.
4739 bool obj_merge_objects;
4740
4741 // (.obj) Don't split geometry into meshes by groups.
4742 bool obj_merge_groups;
4743
4744 // (.obj) Force splitting groups even on object boundaries.
4745 bool obj_split_groups;
4746
4747 // (.obj) Path to the .mtl file.
4748 // Use `length = SIZE_MAX` for NULL-terminated strings.
4749 // NOTE: This is used _instead_ of the one in the file even if not found
4750 // and sidesteps `load_external_files` as it's _explicitly_ requested.
4751 ufbx_string obj_mtl_path;
4752
4753 // (.obj) Data for the .mtl file.
4754 ufbx_blob obj_mtl_data;
4755
4756 // The world unit in meters that .obj files are assumed to be in.
4757 // .obj files do not define the working units. By default the unit scale
4758 // is read as zero, and no unit conversion is performed.
4759 ufbx_real obj_unit_meters;
4760
4761 // Coordinate space .obj files are assumed to be in.
4762 // .obj files do not define the coordinate space they use. By default no
4763 // coordinate space is assumed and no conversion is performed.
4764 ufbx_coordinate_axes obj_axes;
4765
4766 uint32_t _end_zero;
4768
4769// Options for `ufbx_evaluate_scene()`
4770// NOTE: Initialize to zero with `{ 0 }` (C) or `{ }` (C++)
4771typedef struct ufbx_evaluate_opts {
4772 uint32_t _begin_zero;
4773
4774 ufbx_allocator_opts temp_allocator; // < Allocator used during evaluation
4775 ufbx_allocator_opts result_allocator; // < Allocator used for the final scene
4776
4777 bool evaluate_skinning; // < Evaluate skinning (see ufbx_mesh.skinned_vertices)
4778 bool evaluate_caches; // < Evaluate vertex caches (see ufbx_mesh.skinned_vertices)
4779
4780 // WARNING: Potentially unsafe! Try to open external files such as geometry caches
4781 bool load_external_files;
4782
4783 // External file callbacks (defaults to stdio.h)
4784 ufbx_open_file_cb open_file_cb;
4785
4786 uint32_t _end_zero;
4788
4789UFBX_LIST_TYPE(ufbx_const_uint32_list, const uint32_t);
4790UFBX_LIST_TYPE(ufbx_const_real_list, const ufbx_real);
4791
4793 // Element (`ufbx_element.element_id`) to override the property from
4794 uint32_t element_id;
4795
4796 // Property name to override.
4797 ufbx_string prop_name;
4798
4799 // Override value, use `value.x` for scalars. `value_int` is initialized
4800 // from `value.x` if zero so keep `value` zeroed even if you don't need it!
4801 ufbx_vec4 value;
4802 ufbx_string value_str;
4803 int64_t value_int;
4805
4806UFBX_LIST_TYPE(ufbx_const_prop_override_desc_list, const ufbx_prop_override_desc);
4807
4808UFBX_LIST_TYPE(ufbx_const_transform_override_list, const ufbx_transform_override);
4809
4810typedef struct ufbx_anim_opts {
4811 uint32_t _begin_zero;
4812
4813 // Animation layers indices.
4814 // Corresponding to `ufbx_scene.anim_layers[]`, aka `ufbx_anim_layer.typed_id`.
4815 ufbx_const_uint32_list layer_ids;
4816
4817 // Override layer weights, parallel to `ufbx_anim_opts.layer_ids[]`.
4818 ufbx_const_real_list override_layer_weights;
4819
4820 // Property overrides.
4821 // These allow you to override FBX properties, such as 'UFBX_Lcl_Rotation`.
4822 ufbx_const_prop_override_desc_list prop_overrides;
4823
4824 // Transform overrides.
4825 // These allow you to override individual nodes' `ufbx_node.local_transform`.
4826 ufbx_const_transform_override_list transform_overrides;
4827
4828 // Ignore connected properties
4829 bool ignore_connections;
4830
4831 ufbx_allocator_opts result_allocator; // < Allocator used to create the `ufbx_anim`
4832
4833 uint32_t _end_zero;
4835
4836// Specifies how to handle stepped tangents.
4837typedef enum ufbx_bake_step_handling UFBX_ENUM_REPR {
4838
4839 // One millisecond default step duration, with potential extra slack for converting to `float`.
4840 UFBX_BAKE_STEP_HANDLING_DEFAULT,
4841
4842 // Use a custom interpolation duration for the constant step.
4843 // See `ufbx_bake_opts.step_custom_duration` and optionally `ufbx_bake_opts.step_custom_epsilon`.
4844 UFBX_BAKE_STEP_HANDLING_CUSTOM_DURATION,
4845
4846 // Stepped keyframes are represented as keyframes at the exact same time.
4847 // Use flags `UFBX_BAKED_KEY_STEP_LEFT` and `UFBX_BAKED_KEY_STEP_RIGHT` to differentiate
4848 // between the primary key and edge limits.
4849 UFBX_BAKE_STEP_HANDLING_IDENTICAL_TIME,
4850
4851 // Represent stepped keyframe times as the previous/next representable `double` value.
4852 // Using this and robust linear interpolation will handle stepped tangents correctly
4853 // without having to look at the key flags.
4854 // NOTE: Casting these values to `float` or otherwise modifying them can collapse
4855 // the keyframes to have the identical time.
4856 UFBX_BAKE_STEP_HANDLING_ADJACENT_DOUBLE,
4857
4858 // Treat all stepped tangents as linearly interpolated.
4859 UFBX_BAKE_STEP_HANDLING_IGNORE,
4860
4861 UFBX_ENUM_FORCE_WIDTH(ufbx_bake_step_handling)
4862} ufbx_bake_step_handling;
4863
4864UFBX_ENUM_TYPE(ufbx_bake_step_handling, UFBX_BAKE_STEP_HANDLING, UFBX_BAKE_STEP_HANDLING_IGNORE);
4865
4866typedef struct ufbx_bake_opts {
4867 uint32_t _begin_zero;
4868
4869 ufbx_allocator_opts temp_allocator; // < Allocator used during loading
4870 ufbx_allocator_opts result_allocator; // < Allocator used for the final baked animation
4871
4872 // Move the keyframe times to start from zero regardless of the animation start time.
4873 // For example, for an animation spanning between frames [30, 60] will be moved to
4874 // [0, 30] in the baked animation.
4875 // NOTE: This is in general not equivalent to subtracting `ufbx_anim.time_begin`
4876 // from each keyframe, as this trimming is done exactly using internal FBX ticks.
4877 bool trim_start_time;
4878
4879 // Samples per second to use for resampling non-linear animation.
4880 // Default: 30
4881 double resample_rate;
4882
4883 // Minimum sample rate to not resample.
4884 // Many exporters resample animation by default. To avoid double-resampling
4885 // keyframe rates higher or equal to this will not be resampled.
4886 // Default: 19.5
4887 double minimum_sample_rate;
4888
4889 // Maximum sample rate to use, this will remove keys if they are too close together.
4890 // Default: unlimited
4891 double maximum_sample_rate;
4892
4893 // Bake the raw versions of properties related to transforms.
4894 bool bake_transform_props;
4895
4896 // Do not bake node transforms.
4897 bool skip_node_transforms;
4898
4899 // Do not resample linear rotation keyframes.
4900 // FBX interpolates rotation in Euler angles, so this might cause incorrect interpolation.
4901 bool no_resample_rotation;
4902
4903 // Ignore layer weight animation.
4904 bool ignore_layer_weight_animation;
4905
4906 // Maximum number of segments to generate from one keyframe.
4907 // Default: 32
4908 size_t max_keyframe_segments;
4909
4910 // How to handle stepped tangents.
4911 ufbx_bake_step_handling step_handling;
4912
4913 // Interpolation duration used by `UFBX_BAKE_STEP_HANDLING_CUSTOM_DURATION`.
4914 double step_custom_duration;
4915
4916 // Interpolation epsilon used by `UFBX_BAKE_STEP_HANDLING_CUSTOM_DURATION`.
4917 // Defined as the minimum fractional decrease/increase in key time, ie.
4918 // `time / (1.0 + step_custom_epsilon)` and `time * (1.0 + step_custom_epsilon)`.
4919 double step_custom_epsilon;
4920
4921 // Enable key reduction.
4922 bool key_reduction_enabled;
4923
4924 // Enable key reduction for non-constant rotations.
4925 // Assumes rotations will be interpolated using a spherical linear interpolation at runtime.
4926 bool key_reduction_rotation;
4927
4928 // Threshold for reducing keys for linear segments.
4929 // Default `0.000001`, use negative to disable.
4930 double key_reduction_threshold;
4931
4932 // Maximum passes over the keys to reduce.
4933 // Every pass can potentially halve the the amount of keys.
4934 // Default: `4`
4935 size_t key_reduction_passes;
4936
4937 uint32_t _end_zero;
4939
4940// Options for `ufbx_tessellate_nurbs_curve()`
4941// NOTE: Initialize to zero with `{ 0 }` (C) or `{ }` (C++)
4943 uint32_t _begin_zero;
4944
4945 ufbx_allocator_opts temp_allocator; // < Allocator used during tessellation
4946 ufbx_allocator_opts result_allocator; // < Allocator used for the final line curve
4947
4948 // How many segments tessellate each span in `ufbx_nurbs_basis.spans`.
4949 size_t span_subdivision;
4950
4951 uint32_t _end_zero;
4953
4954// Options for `ufbx_tessellate_nurbs_surface()`
4955// NOTE: Initialize to zero with `{ 0 }` (C) or `{ }` (C++)
4957 uint32_t _begin_zero;
4958
4959 ufbx_allocator_opts temp_allocator; // < Allocator used during tessellation
4960 ufbx_allocator_opts result_allocator; // < Allocator used for the final mesh
4961
4962 // How many segments tessellate each span in `ufbx_nurbs_basis.spans`.
4963 // NOTE: Default is `4`, _not_ `ufbx_nurbs_surface.span_subdivision_u/v` as that
4964 // would make it easy to create an FBX file with an absurdly high subdivision
4965 // rate (similar to mesh subdivision). Please enforce copy the value yourself
4966 // enforcing whatever limits you deem reasonable.
4967 size_t span_subdivision_u;
4968 size_t span_subdivision_v;
4969
4970 // Skip computing `ufbx_mesh.material_parts[]`
4971 bool skip_mesh_parts;
4972
4973 uint32_t _end_zero;
4975
4976// Options for `ufbx_subdivide_mesh()`
4977// NOTE: Initialize to zero with `{ 0 }` (C) or `{ }` (C++)
4978typedef struct ufbx_subdivide_opts {
4979 uint32_t _begin_zero;
4980
4981 ufbx_allocator_opts temp_allocator; // < Allocator used during subdivision
4982 ufbx_allocator_opts result_allocator; // < Allocator used for the final mesh
4983
4984 ufbx_subdivision_boundary boundary;
4985 ufbx_subdivision_boundary uv_boundary;
4986
4987 // Do not generate normals
4988 bool ignore_normals;
4989
4990 // Interpolate existing normals using the subdivision rules
4991 // instead of generating new normals
4992 bool interpolate_normals;
4993
4994 // Subdivide also tangent attributes
4995 bool interpolate_tangents;
4996
4997 // Map subdivided vertices into weighted original vertices.
4998 // NOTE: May be O(n^2) if `max_source_vertices` is not specified!
4999 bool evaluate_source_vertices;
5000
5001 // Limit source vertices per subdivided vertex.
5002 size_t max_source_vertices;
5003
5004 // Calculate bone influences over subdivided vertices (if applicable).
5005 // NOTE: May be O(n^2) if `max_skin_weights` is not specified!
5006 bool evaluate_skin_weights;
5007
5008 // Limit bone influences per subdivided vertex.
5009 size_t max_skin_weights;
5010
5011 // Index of the skin deformer to use for `evaluate_skin_weights`.
5012 size_t skin_deformer_index;
5013
5014 uint32_t _end_zero;
5016
5017// Options for `ufbx_load_geometry_cache()`
5018// NOTE: Initialize to zero with `{ 0 }` (C) or `{ }` (C++)
5020 uint32_t _begin_zero;
5021
5022 ufbx_allocator_opts temp_allocator; // < Allocator used during loading
5023 ufbx_allocator_opts result_allocator; // < Allocator used for the final scene
5024
5025 // External file callbacks (defaults to stdio.h)
5026 ufbx_open_file_cb open_file_cb;
5027
5028 // FPS value for converting frame times to seconds
5029 double frames_per_second;
5030
5031 // Axis to mirror the geometry by.
5032 ufbx_mirror_axis mirror_axis;
5033
5034 // Enable scaling `scale_factor` all geometry by.
5035 bool use_scale_factor;
5036
5037 // Factor to scale the geometry by.
5038 ufbx_real scale_factor;
5039
5040 uint32_t _end_zero;
5042
5043// Options for `ufbx_read_geometry_cache_TYPE()`
5044// NOTE: Initialize to zero with `{ 0 }` (C) or `{ }` (C++)
5046 uint32_t _begin_zero;
5047
5048 // External file callbacks (defaults to stdio.h)
5049 ufbx_open_file_cb open_file_cb;
5050
5051 bool additive;
5052 bool use_weight;
5053 ufbx_real weight;
5054
5055 // Ignore scene transform.
5056 bool ignore_transform;
5057
5058 uint32_t _end_zero;
5060
5061typedef struct ufbx_panic {
5062 bool did_panic;
5063 size_t message_length;
5064 char message[UFBX_PANIC_MESSAGE_LENGTH];
5065} ufbx_panic;
5066
5067// -- API
5068
5069#ifdef __cplusplus
5070extern "C" {
5071#endif
5072
5073// Various zero/empty/identity values
5074ufbx_abi_data const ufbx_string ufbx_empty_string;
5075ufbx_abi_data const ufbx_blob ufbx_empty_blob;
5076ufbx_abi_data const ufbx_matrix ufbx_identity_matrix;
5077ufbx_abi_data const ufbx_transform ufbx_identity_transform;
5078ufbx_abi_data const ufbx_vec2 ufbx_zero_vec2;
5079ufbx_abi_data const ufbx_vec3 ufbx_zero_vec3;
5080ufbx_abi_data const ufbx_vec4 ufbx_zero_vec4;
5081ufbx_abi_data const ufbx_quat ufbx_identity_quat;
5082
5083// Commonly used coordinate axes.
5084ufbx_abi_data const ufbx_coordinate_axes ufbx_axes_right_handed_y_up;
5085ufbx_abi_data const ufbx_coordinate_axes ufbx_axes_right_handed_z_up;
5086ufbx_abi_data const ufbx_coordinate_axes ufbx_axes_left_handed_y_up;
5087ufbx_abi_data const ufbx_coordinate_axes ufbx_axes_left_handed_z_up;
5088
5089// Sizes of element types. eg `sizeof(ufbx_node)`
5090ufbx_abi_data const size_t ufbx_element_type_size[UFBX_ELEMENT_TYPE_COUNT];
5091
5092// Version of the source file, comparable to `UFBX_HEADER_VERSION`
5093ufbx_abi_data const uint32_t ufbx_source_version;
5094
5095// Practically always `true` (see below), if not you need to be careful with threads.
5096//
5097// Guaranteed to be `true` in _any_ of the following conditions:
5098// - ufbx.c has been compiled using: GCC / Clang / MSVC / ICC / EMCC / TCC
5099// - ufbx.c has been compiled as C++11 or later
5100// - ufbx.c has been compiled as C11 or later with `<stdatomic.h>` support
5101//
5102// If `false` you can't call the following functions concurrently:
5103// ufbx_evaluate_scene()
5104// ufbx_free_scene()
5105// ufbx_subdivide_mesh()
5106// ufbx_tessellate_nurbs_surface()
5107// ufbx_free_mesh()
5108ufbx_abi bool ufbx_is_thread_safe(void);
5109
5110// Load a scene from a `size` byte memory buffer at `data`
5111ufbx_abi ufbx_scene *ufbx_load_memory(
5112 const void *data, size_t data_size,
5113 const ufbx_load_opts *opts, ufbx_error *error);
5114
5115// Load a scene by opening a file named `filename`
5116ufbx_abi ufbx_scene *ufbx_load_file(
5117 const char *filename,
5118 const ufbx_load_opts *opts, ufbx_error *error);
5119ufbx_abi ufbx_scene *ufbx_load_file_len(
5120 const char *filename, size_t filename_len,
5121 const ufbx_load_opts *opts, ufbx_error *error);
5122
5123// Load a scene by reading from an `FILE *file` stream
5124// NOTE: `file` is passed as a `void` pointer to avoid including <stdio.h>
5125ufbx_abi ufbx_scene *ufbx_load_stdio(
5126 void *file,
5127 const ufbx_load_opts *opts, ufbx_error *error);
5128
5129// Load a scene by reading from an `FILE *file` stream with a prefix
5130// NOTE: `file` is passed as a `void` pointer to avoid including <stdio.h>
5131ufbx_abi ufbx_scene *ufbx_load_stdio_prefix(
5132 void *file,
5133 const void *prefix, size_t prefix_size,
5134 const ufbx_load_opts *opts, ufbx_error *error);
5135
5136// Load a scene from a user-specified stream
5137ufbx_abi ufbx_scene *ufbx_load_stream(
5138 const ufbx_stream *stream,
5139 const ufbx_load_opts *opts, ufbx_error *error);
5140
5141// Load a scene from a user-specified stream with a prefix
5142ufbx_abi ufbx_scene *ufbx_load_stream_prefix(
5143 const ufbx_stream *stream,
5144 const void *prefix, size_t prefix_size,
5145 const ufbx_load_opts *opts, ufbx_error *error);
5146
5147// Free a previously loaded or evaluated scene
5148ufbx_abi void ufbx_free_scene(ufbx_scene *scene);
5149
5150// Increment `scene` refcount
5151ufbx_abi void ufbx_retain_scene(ufbx_scene *scene);
5152
5153// Format a textual description of `error`.
5154// Always produces a NULL-terminated string to `char dst[dst_size]`, truncating if
5155// necessary. Returns the number of characters written not including the NULL terminator.
5156ufbx_abi size_t ufbx_format_error(char *dst, size_t dst_size, const ufbx_error *error);
5157
5158// Query
5159
5160// Find a property `name` from `props`, returns `NULL` if not found.
5161// Searches through `ufbx_props.defaults` as well.
5162ufbx_abi ufbx_prop *ufbx_find_prop_len(const ufbx_props *props, const char *name, size_t name_len);
5163ufbx_inline ufbx_prop *ufbx_find_prop(const ufbx_props *props, const char *name) { return ufbx_find_prop_len(props, name, strlen(name));}
5164
5165// Utility functions for finding the value of a property, returns `def` if not found.
5166// NOTE: For `ufbx_string` you need to ensure the lifetime of the default is
5167// sufficient as no copy is made.
5168ufbx_abi ufbx_real ufbx_find_real_len(const ufbx_props *props, const char *name, size_t name_len, ufbx_real def);
5169ufbx_inline ufbx_real ufbx_find_real(const ufbx_props *props, const char *name, ufbx_real def) { return ufbx_find_real_len(props, name, strlen(name), def); }
5170ufbx_abi ufbx_vec3 ufbx_find_vec3_len(const ufbx_props *props, const char *name, size_t name_len, ufbx_vec3 def);
5171ufbx_inline ufbx_vec3 ufbx_find_vec3(const ufbx_props *props, const char *name, ufbx_vec3 def) { return ufbx_find_vec3_len(props, name, strlen(name), def); }
5172ufbx_abi int64_t ufbx_find_int_len(const ufbx_props *props, const char *name, size_t name_len, int64_t def);
5173ufbx_inline int64_t ufbx_find_int(const ufbx_props *props, const char *name, int64_t def) { return ufbx_find_int_len(props, name, strlen(name), def); }
5174ufbx_abi bool ufbx_find_bool_len(const ufbx_props *props, const char *name, size_t name_len, bool def);
5175ufbx_inline bool ufbx_find_bool(const ufbx_props *props, const char *name, bool def) { return ufbx_find_bool_len(props, name, strlen(name), def); }
5176ufbx_abi ufbx_string ufbx_find_string_len(const ufbx_props *props, const char *name, size_t name_len, ufbx_string def);
5177ufbx_inline ufbx_string ufbx_find_string(const ufbx_props *props, const char *name, ufbx_string def) { return ufbx_find_string_len(props, name, strlen(name), def); }
5178ufbx_abi ufbx_blob ufbx_find_blob_len(const ufbx_props *props, const char *name, size_t name_len, ufbx_blob def);
5179ufbx_inline ufbx_blob ufbx_find_blob(const ufbx_props *props, const char *name, ufbx_blob def) { return ufbx_find_blob_len(props, name, strlen(name), def); }
5180
5181// Find property in `props` with concatendated `parts[num_parts]`.
5182ufbx_abi ufbx_prop *ufbx_find_prop_concat(const ufbx_props *props, const ufbx_string *parts, size_t num_parts);
5183
5184// Get an element connected to a property.
5185ufbx_abi ufbx_element *ufbx_get_prop_element(const ufbx_element *element, const ufbx_prop *prop, ufbx_element_type type);
5186
5187// Find an element connected to a property by name.
5188ufbx_abi ufbx_element *ufbx_find_prop_element_len(const ufbx_element *element, const char *name, size_t name_len, ufbx_element_type type);
5189ufbx_inline ufbx_element *ufbx_find_prop_element(const ufbx_element *element, const char *name, ufbx_element_type type) { return ufbx_find_prop_element_len(element, name, strlen(name), type); }
5190
5191// Find any element of type `type` in `scene` by `name`.
5192// For example if you want to find `ufbx_material` named `Mat`:
5193// (ufbx_material*)ufbx_find_element(scene, UFBX_ELEMENT_MATERIAL, "Mat");
5194ufbx_abi ufbx_element *ufbx_find_element_len(const ufbx_scene *scene, ufbx_element_type type, const char *name, size_t name_len);
5195ufbx_inline ufbx_element *ufbx_find_element(const ufbx_scene *scene, ufbx_element_type type, const char *name) { return ufbx_find_element_len(scene, type, name, strlen(name)); }
5196
5197// Find node in `scene` by `name` (shorthand for `ufbx_find_element(UFBX_ELEMENT_NODE)`).
5198ufbx_abi ufbx_node *ufbx_find_node_len(const ufbx_scene *scene, const char *name, size_t name_len);
5199ufbx_inline ufbx_node *ufbx_find_node(const ufbx_scene *scene, const char *name) { return ufbx_find_node_len(scene, name, strlen(name)); }
5200
5201// Find an animation stack in `scene` by `name` (shorthand for `ufbx_find_element(UFBX_ELEMENT_ANIM_STACK)`)
5202ufbx_abi ufbx_anim_stack *ufbx_find_anim_stack_len(const ufbx_scene *scene, const char *name, size_t name_len);
5203ufbx_inline ufbx_anim_stack *ufbx_find_anim_stack(const ufbx_scene *scene, const char *name) { return ufbx_find_anim_stack_len(scene, name, strlen(name)); }
5204
5205// Find a material in `scene` by `name` (shorthand for `ufbx_find_element(UFBX_ELEMENT_MATERIAL)`).
5206ufbx_abi ufbx_material *ufbx_find_material_len(const ufbx_scene *scene, const char *name, size_t name_len);
5207ufbx_inline ufbx_material *ufbx_find_material(const ufbx_scene *scene, const char *name) { return ufbx_find_material_len(scene, name, strlen(name)); }
5208
5209// Find a single animated property `prop` of `element` in `layer`.
5210// Returns `NULL` if not found.
5211ufbx_abi ufbx_anim_prop *ufbx_find_anim_prop_len(const ufbx_anim_layer *layer, const ufbx_element *element, const char *prop, size_t prop_len);
5212ufbx_inline ufbx_anim_prop *ufbx_find_anim_prop(const ufbx_anim_layer *layer, const ufbx_element *element, const char *prop) { return ufbx_find_anim_prop_len(layer, element, prop, strlen(prop)); }
5213
5214// Find all animated properties of `element` in `layer`.
5215ufbx_abi ufbx_anim_prop_list ufbx_find_anim_props(const ufbx_anim_layer *layer, const ufbx_element *element);
5216
5217// Get a matrix that transforms normals in the same way as Autodesk software.
5218// NOTE: The resulting normals are slightly incorrect as this function deliberately
5219// inverts geometric transformation wrong. For better results use
5220// `ufbx_matrix_for_normals(&node->geometry_to_world)`.
5221ufbx_abi ufbx_matrix ufbx_get_compatible_matrix_for_normals(const ufbx_node *node);
5222
5223// Utility
5224
5225// Decompress a DEFLATE compressed buffer.
5226// Returns the decompressed size or a negative error code (see source for details).
5227// NOTE: You must supply a valid `retain` with `ufbx_inflate_retain.initialized == false`
5228// but the rest can be uninitialized.
5229ufbx_abi ptrdiff_t ufbx_inflate(void *dst, size_t dst_size, const ufbx_inflate_input *input, ufbx_inflate_retain *retain);
5230
5231// Open a `ufbx_stream` from a file.
5232// Use `path_len == SIZE_MAX` for NULL terminated string.
5233ufbx_abi bool ufbx_open_file(ufbx_stream *stream, const char *path, size_t path_len);
5234
5235// Same as `ufbx_open_file()` but compatible with the callback in `ufbx_open_file_fn`.
5236// The `user` parameter is actually not used here.
5237ufbx_abi bool ufbx_default_open_file(void *user, ufbx_stream *stream, const char *path, size_t path_len, const ufbx_open_file_info *info);
5238
5239// NOTE: Uses the default ufbx allocator!
5240ufbx_abi bool ufbx_open_memory(ufbx_stream *stream, const void *data, size_t data_size, const ufbx_open_memory_opts *opts, ufbx_error *error);
5241
5242// Animation evaluation
5243
5244// Evaluate a single animation `curve` at a `time`.
5245// Returns `default_value` only if `curve == NULL` or it has no keyframes.
5246ufbx_abi ufbx_real ufbx_evaluate_curve(const ufbx_anim_curve *curve, double time, ufbx_real default_value);
5247
5248// Evaluate a value from bundled animation curves.
5249ufbx_abi ufbx_real ufbx_evaluate_anim_value_real(const ufbx_anim_value *anim_value, double time);
5250ufbx_abi ufbx_vec3 ufbx_evaluate_anim_value_vec3(const ufbx_anim_value *anim_value, double time);
5251
5252// Evaluate an animated property `name` from `element` at `time`.
5253// NOTE: If the property is not found it will have the flag `UFBX_PROP_FLAG_NOT_FOUND`.
5254ufbx_abi ufbx_prop ufbx_evaluate_prop_len(const ufbx_anim *anim, const ufbx_element *element, const char *name, size_t name_len, double time);
5255ufbx_inline ufbx_prop ufbx_evaluate_prop(const ufbx_anim *anim, const ufbx_element *element, const char *name, double time) {
5256 return ufbx_evaluate_prop_len(anim, element, name, strlen(name), time);
5257}
5258
5259// Evaluate all _animated_ properties of `element`.
5260// HINT: This function returns an `ufbx_props` structure with the original properties as
5261// `ufbx_props.defaults`. This lets you use `ufbx_find_prop/value()` for the results.
5262ufbx_abi ufbx_props ufbx_evaluate_props(const ufbx_anim *anim, const ufbx_element *element, double time, ufbx_prop *buffer, size_t buffer_size);
5263
5264// Flags to control `ufbx_evaluate_transform_flags()`.
5265typedef enum ufbx_transform_flags UFBX_FLAG_REPR {
5266
5267 // Ignore parent scale helper.
5268 UFBX_TRANSFORM_FLAG_IGNORE_SCALE_HELPER = 0x1,
5269
5270 // Ignore componentwise scale.
5271 // Note that if you don't specify this, ufbx will have to potentially
5272 // evaluate the entire parent chain in the worst case.
5273 UFBX_TRANSFORM_FLAG_IGNORE_COMPONENTWISE_SCALE = 0x2,
5274
5275 // Require explicit components
5276 UFBX_TRANSFORM_FLAG_EXPLICIT_INCLUDES = 0x4,
5277
5278 // If `UFBX_TRANSFORM_FLAG_EXPLICIT_INCLUDES`: Evaluate `ufbx_transform.translation`.
5279 UFBX_TRANSFORM_FLAG_INCLUDE_TRANSLATION = 0x10,
5280 // If `UFBX_TRANSFORM_FLAG_EXPLICIT_INCLUDES`: Evaluate `ufbx_transform.rotation`.
5281 UFBX_TRANSFORM_FLAG_INCLUDE_ROTATION = 0x20,
5282 // If `UFBX_TRANSFORM_FLAG_EXPLICIT_INCLUDES`: Evaluate `ufbx_transform.scale`.
5283 UFBX_TRANSFORM_FLAG_INCLUDE_SCALE = 0x40,
5284
5285 UFBX_FLAG_FORCE_WIDTH(UFBX_TRANSFORM_FLAGS)
5286} ufbx_transform_flags;
5287
5288// Evaluate the animated transform of a node given a time.
5289// The returned transform is the local transform of the node (ie. relative to the parent),
5290// comparable to `ufbx_node.local_transform`.
5291ufbx_abi ufbx_transform ufbx_evaluate_transform(const ufbx_anim *anim, const ufbx_node *node, double time);
5292ufbx_abi ufbx_transform ufbx_evaluate_transform_flags(const ufbx_anim *anim, const ufbx_node *node, double time, uint32_t flags);
5293
5294// Evaluate the blend shape weight of a blend channel.
5295// NOTE: Return value uses `1.0` for full weight, instead of `100.0` that the internal property `UFBX_Weight` uses.
5296ufbx_abi ufbx_real ufbx_evaluate_blend_weight(const ufbx_anim *anim, const ufbx_blend_channel *channel, double time);
5297
5298// Evaluate the whole `scene` at a specific `time` in the animation `anim`.
5299// The returned scene behaves as if it had been exported at a specific time
5300// in the specified animation, except that animated elements' properties contain
5301// only the animated values, the original ones are in `props->defaults`.
5302//
5303// NOTE: The returned scene refers to the original `scene` so the original
5304// scene cannot be freed until all evaluated scenes are freed.
5305ufbx_abi ufbx_scene *ufbx_evaluate_scene(const ufbx_scene *scene, const ufbx_anim *anim, double time, const ufbx_evaluate_opts *opts, ufbx_error *error);
5306
5307// Create a custom animation descriptor.
5308// `ufbx_anim_opts` is used to specify animation layers and weights.
5309// HINT: You can also leave `ufbx_anim_opts.layer_ids[]` empty and only specify
5310// overrides to evaluate the scene with different properties or local transforms.
5311ufbx_abi ufbx_anim *ufbx_create_anim(const ufbx_scene *scene, const ufbx_anim_opts *opts, ufbx_error *error);
5312
5313// Free an animation returned by `ufbx_create_anim()`.
5314ufbx_abi void ufbx_free_anim(ufbx_anim *anim);
5315
5316// Increase the animation reference count.
5317ufbx_abi void ufbx_retain_anim(ufbx_anim *anim);
5318
5319// Animation baking
5320
5321// "Bake" an animation to linearly interpolated keyframes.
5322// Composites the FBX transformation chain into quaternion rotations.
5323ufbx_abi ufbx_baked_anim *ufbx_bake_anim(const ufbx_scene *scene, const ufbx_anim *anim, const ufbx_bake_opts *opts, ufbx_error *error);
5324
5325ufbx_abi void ufbx_retain_baked_anim(ufbx_baked_anim *bake);
5326ufbx_abi void ufbx_free_baked_anim(ufbx_baked_anim *bake);
5327
5328ufbx_abi ufbx_baked_node *ufbx_find_baked_node_by_typed_id(ufbx_baked_anim *bake, uint32_t typed_id);
5329ufbx_abi ufbx_baked_node *ufbx_find_baked_node(ufbx_baked_anim *bake, ufbx_node *node);
5330
5331ufbx_abi ufbx_baked_element *ufbx_find_baked_element_by_element_id(ufbx_baked_anim *bake, uint32_t element_id);
5332ufbx_abi ufbx_baked_element *ufbx_find_baked_element(ufbx_baked_anim *bake, ufbx_element *element);
5333
5334// Evaluate baked animation `keyframes` at `time`.
5335// Internally linearly interpolates between two adjacent keyframes.
5336// Handles stepped tangents cleanly, which is not strictly necessary for custom interpolation.
5337ufbx_abi ufbx_vec3 ufbx_evaluate_baked_vec3(ufbx_baked_vec3_list keyframes, double time);
5338
5339// Evaluate baked animation `keyframes` at `time`.
5340// Internally spherically interpolates (`ufbx_quat_slerp()`) between two adjacent keyframes.
5341// Handles stepped tangents cleanly, which is not strictly necessary for custom interpolation.
5342ufbx_abi ufbx_quat ufbx_evaluate_baked_quat(ufbx_baked_quat_list keyframes, double time);
5343
5344// Poses
5345
5346// Retrieve the bone pose for `node`.
5347// Returns `NULL` if the pose does not contain `node`.
5348ufbx_abi ufbx_bone_pose *ufbx_get_bone_pose(const ufbx_pose *pose, const ufbx_node *node);
5349
5350// Materials
5351
5352// Find a texture for a given material FBX property.
5353ufbx_abi ufbx_texture *ufbx_find_prop_texture_len(const ufbx_material *material, const char *name, size_t name_len);
5354ufbx_inline ufbx_texture *ufbx_find_prop_texture(const ufbx_material *material, const char *name) {
5355 return ufbx_find_prop_texture_len(material, name, strlen(name));
5356}
5357
5358// Find a texture for a given shader property.
5359ufbx_abi ufbx_string ufbx_find_shader_prop_len(const ufbx_shader *shader, const char *name, size_t name_len);
5360ufbx_inline ufbx_string ufbx_find_shader_prop(const ufbx_shader *shader, const char *name) {
5361 return ufbx_find_shader_prop_len(shader, name, strlen(name));
5362}
5363
5364// Map from a shader property to material property.
5365ufbx_abi ufbx_shader_prop_binding_list ufbx_find_shader_prop_bindings_len(const ufbx_shader *shader, const char *name, size_t name_len);
5366ufbx_inline ufbx_shader_prop_binding_list ufbx_find_shader_prop_bindings(const ufbx_shader *shader, const char *name) {
5367 return ufbx_find_shader_prop_bindings_len(shader, name, strlen(name));
5368}
5369
5370// Find an input in a shader texture.
5371ufbx_abi ufbx_shader_texture_input *ufbx_find_shader_texture_input_len(const ufbx_shader_texture *shader, const char *name, size_t name_len);
5372ufbx_inline ufbx_shader_texture_input *ufbx_find_shader_texture_input(const ufbx_shader_texture *shader, const char *name) {
5373 return ufbx_find_shader_texture_input_len(shader, name, strlen(name));
5374}
5375
5376// Math
5377
5378// Returns `true` if `axes` forms a valid coordinate space.
5379ufbx_abi bool ufbx_coordinate_axes_valid(ufbx_coordinate_axes axes);
5380
5381// Vector math utility functions.
5382ufbx_abi ufbx_vec3 ufbx_vec3_normalize(ufbx_vec3 v);
5383
5384// Quaternion math utility functions.
5385ufbx_abi ufbx_real ufbx_quat_dot(ufbx_quat a, ufbx_quat b);
5386ufbx_abi ufbx_quat ufbx_quat_mul(ufbx_quat a, ufbx_quat b);
5387ufbx_abi ufbx_quat ufbx_quat_normalize(ufbx_quat q);
5388ufbx_abi ufbx_quat ufbx_quat_fix_antipodal(ufbx_quat q, ufbx_quat reference);
5389ufbx_abi ufbx_quat ufbx_quat_slerp(ufbx_quat a, ufbx_quat b, ufbx_real t);
5390ufbx_abi ufbx_vec3 ufbx_quat_rotate_vec3(ufbx_quat q, ufbx_vec3 v);
5391ufbx_abi ufbx_vec3 ufbx_quat_to_euler(ufbx_quat q, ufbx_rotation_order order);
5392ufbx_abi ufbx_quat ufbx_euler_to_quat(ufbx_vec3 v, ufbx_rotation_order order);
5393
5394// Matrix math utility functions.
5395ufbx_abi ufbx_matrix ufbx_matrix_mul(const ufbx_matrix *a, const ufbx_matrix *b);
5396ufbx_abi ufbx_real ufbx_matrix_determinant(const ufbx_matrix *m);
5397ufbx_abi ufbx_matrix ufbx_matrix_invert(const ufbx_matrix *m);
5398
5399// Get a matrix that can be used to transform geometry normals.
5400// NOTE: You must normalize the normals after transforming them with this matrix,
5401// eg. using `ufbx_vec3_normalize()`.
5402// NOTE: This function flips the normals if the determinant is negative.
5403ufbx_abi ufbx_matrix ufbx_matrix_for_normals(const ufbx_matrix *m);
5404
5405// Matrix transformation utilities.
5406ufbx_abi ufbx_vec3 ufbx_transform_position(const ufbx_matrix *m, ufbx_vec3 v);
5407ufbx_abi ufbx_vec3 ufbx_transform_direction(const ufbx_matrix *m, ufbx_vec3 v);
5408
5409// Conversions between `ufbx_matrix` and `ufbx_transform`.
5410ufbx_abi ufbx_matrix ufbx_transform_to_matrix(const ufbx_transform *t);
5411ufbx_abi ufbx_transform ufbx_matrix_to_transform(const ufbx_matrix *m);
5412
5413// Skinning
5414
5415// Get a matrix representing the deformation for a single vertex.
5416// Returns `fallback` if the vertex is not skinned.
5417ufbx_abi ufbx_matrix ufbx_catch_get_skin_vertex_matrix(ufbx_panic *panic, const ufbx_skin_deformer *skin, size_t vertex, const ufbx_matrix *fallback);
5418ufbx_inline ufbx_matrix ufbx_get_skin_vertex_matrix(const ufbx_skin_deformer *skin, size_t vertex, const ufbx_matrix *fallback) {
5419 return ufbx_catch_get_skin_vertex_matrix(NULL, skin, vertex, fallback);
5420}
5421
5422// Resolve the index into `ufbx_blend_shape.position_offsets[]` given a vertex.
5423// Returns `UFBX_NO_INDEX` if the vertex is not included in the blend shape.
5424ufbx_abi uint32_t ufbx_get_blend_shape_offset_index(const ufbx_blend_shape *shape, size_t vertex);
5425
5426// Get the offset for a given vertex in the blend shape.
5427// Returns `ufbx_zero_vec3` if the vertex is not a included in the blend shape.
5428ufbx_abi ufbx_vec3 ufbx_get_blend_shape_vertex_offset(const ufbx_blend_shape *shape, size_t vertex);
5429
5430// Get the _current_ blend offset given a blend deformer.
5431// NOTE: This depends on the current animated blend weight of the deformer.
5432ufbx_abi ufbx_vec3 ufbx_get_blend_vertex_offset(const ufbx_blend_deformer *blend, size_t vertex);
5433
5434// Apply the blend shape with `weight` to given vertices.
5435ufbx_abi void ufbx_add_blend_shape_vertex_offsets(const ufbx_blend_shape *shape, ufbx_vec3 *vertices, size_t num_vertices, ufbx_real weight);
5436
5437// Apply the blend deformer with `weight` to given vertices.
5438// NOTE: This depends on the current animated blend weight of the deformer.
5439ufbx_abi void ufbx_add_blend_vertex_offsets(const ufbx_blend_deformer *blend, ufbx_vec3 *vertices, size_t num_vertices, ufbx_real weight);
5440
5441// Curves/surfaces
5442
5443// Low-level utility to evaluate NURBS the basis functions.
5444ufbx_abi size_t ufbx_evaluate_nurbs_basis(const ufbx_nurbs_basis *basis, ufbx_real u, ufbx_real *weights, size_t num_weights, ufbx_real *derivatives, size_t num_derivatives);
5445
5446// Evaluate a point on a NURBS curve given the parameter `u`.
5447ufbx_abi ufbx_curve_point ufbx_evaluate_nurbs_curve(const ufbx_nurbs_curve *curve, ufbx_real u);
5448
5449// Evaluate a point on a NURBS surface given the parameter `u` and `v`.
5450ufbx_abi ufbx_surface_point ufbx_evaluate_nurbs_surface(const ufbx_nurbs_surface *surface, ufbx_real u, ufbx_real v);
5451
5452// Tessellate a NURBS curve into a polyline.
5453ufbx_abi ufbx_line_curve *ufbx_tessellate_nurbs_curve(const ufbx_nurbs_curve *curve, const ufbx_tessellate_curve_opts *opts, ufbx_error *error);
5454
5455// Tessellate a NURBS surface into a mesh.
5456ufbx_abi ufbx_mesh *ufbx_tessellate_nurbs_surface(const ufbx_nurbs_surface *surface, const ufbx_tessellate_surface_opts *opts, ufbx_error *error);
5457
5458// Free a line returned by `ufbx_tessellate_nurbs_curve()`.
5459ufbx_abi void ufbx_free_line_curve(ufbx_line_curve *curve);
5460
5461// Increase the refcount of the line.
5462ufbx_abi void ufbx_retain_line_curve(ufbx_line_curve *curve);
5463
5464// Mesh Topology
5465
5466// Find the face that contains a given `index`.
5467// Returns `UFBX_NO_INDEX` if out of bounds.
5468ufbx_abi uint32_t ufbx_find_face_index(ufbx_mesh *mesh, size_t index);
5469
5470// Triangulate a mesh face, returning the number of triangles.
5471// NOTE: You need to space for `(face.num_indices - 2) * 3 - 1` indices!
5472// HINT: Using `ufbx_mesh.max_face_triangles * 3` is always safe.
5473ufbx_abi uint32_t ufbx_catch_triangulate_face(ufbx_panic *panic, uint32_t *indices, size_t num_indices, const ufbx_mesh *mesh, ufbx_face face);
5474ufbx_inline uint32_t ufbx_triangulate_face(uint32_t *indices, size_t num_indices, const ufbx_mesh *mesh, ufbx_face face) {
5475 return ufbx_catch_triangulate_face(NULL, indices, num_indices, mesh, face);
5476}
5477
5478// Generate the half-edge representation of `mesh` to `topo[mesh->num_indices]`
5479ufbx_abi void ufbx_catch_compute_topology(ufbx_panic *panic, const ufbx_mesh *mesh, ufbx_topo_edge *topo, size_t num_topo);
5480ufbx_inline void ufbx_compute_topology(const ufbx_mesh *mesh, ufbx_topo_edge *topo, size_t num_topo) {
5481 ufbx_catch_compute_topology(NULL, mesh, topo, num_topo);
5482}
5483
5484// Get the next/previous edge around a vertex
5485// NOTE: Does not return the half-edge on the opposite side (ie. `topo[index].twin`)
5486
5487// Get the next half-edge in `topo`.
5488ufbx_abi uint32_t ufbx_catch_topo_next_vertex_edge(ufbx_panic *panic, const ufbx_topo_edge *topo, size_t num_topo, uint32_t index);
5489ufbx_inline uint32_t ufbx_topo_next_vertex_edge(const ufbx_topo_edge *topo, size_t num_topo, uint32_t index) {
5490 return ufbx_catch_topo_next_vertex_edge(NULL, topo, num_topo, index);
5491}
5492
5493// Get the previous half-edge in `topo`.
5494ufbx_abi uint32_t ufbx_catch_topo_prev_vertex_edge(ufbx_panic *panic, const ufbx_topo_edge *topo, size_t num_topo, uint32_t index);
5495ufbx_inline uint32_t ufbx_topo_prev_vertex_edge(const ufbx_topo_edge *topo, size_t num_topo, uint32_t index) {
5496 return ufbx_catch_topo_prev_vertex_edge(NULL, topo, num_topo, index);
5497}
5498
5499// Calculate a normal for a given face.
5500// The returned normal is weighted by face area.
5501ufbx_abi ufbx_vec3 ufbx_catch_get_weighted_face_normal(ufbx_panic *panic, const ufbx_vertex_vec3 *positions, ufbx_face face);
5502ufbx_inline ufbx_vec3 ufbx_get_weighted_face_normal(const ufbx_vertex_vec3 *positions, ufbx_face face) {
5503 return ufbx_catch_get_weighted_face_normal(NULL, positions, face);
5504}
5505
5506// Generate indices for normals from the topology.
5507// Respects smoothing groups.
5508ufbx_abi size_t ufbx_catch_generate_normal_mapping(ufbx_panic *panic, const ufbx_mesh *mesh,
5509 const ufbx_topo_edge *topo, size_t num_topo,
5510 uint32_t *normal_indices, size_t num_normal_indices, bool assume_smooth);
5511ufbx_abi size_t ufbx_generate_normal_mapping(const ufbx_mesh *mesh,
5512 const ufbx_topo_edge *topo, size_t num_topo,
5513 uint32_t *normal_indices, size_t num_normal_indices, bool assume_smooth);
5514
5515// Compute normals given normal indices.
5516// You can use `ufbx_generate_normal_mapping()` to generate the normal indices.
5517ufbx_abi void ufbx_catch_compute_normals(ufbx_panic *panic, const ufbx_mesh *mesh, const ufbx_vertex_vec3 *positions,
5518 const uint32_t *normal_indices, size_t num_normal_indices,
5519 ufbx_vec3 *normals, size_t num_normals);
5520ufbx_abi void ufbx_compute_normals(const ufbx_mesh *mesh, const ufbx_vertex_vec3 *positions,
5521 const uint32_t *normal_indices, size_t num_normal_indices,
5522 ufbx_vec3 *normals, size_t num_normals);
5523
5524// Subdivide a mesh using the Catmull-Clark subdivision `level` times.
5525ufbx_abi ufbx_mesh *ufbx_subdivide_mesh(const ufbx_mesh *mesh, size_t level, const ufbx_subdivide_opts *opts, ufbx_error *error);
5526
5527// Free a mesh returned from `ufbx_subdivide_mesh()` or `ufbx_tessellate_nurbs_surface()`.
5528ufbx_abi void ufbx_free_mesh(ufbx_mesh *mesh);
5529
5530// Increase the mesh reference count.
5531ufbx_abi void ufbx_retain_mesh(ufbx_mesh *mesh);
5532
5533// Geometry caches
5534
5535// Load geometry cache information from a file.
5536// As geometry caches can be massive, this does not actually read the data, but
5537// only seeks through the files to form the metadata.
5538ufbx_abi ufbx_geometry_cache *ufbx_load_geometry_cache(
5539 const char *filename,
5540 const ufbx_geometry_cache_opts *opts, ufbx_error *error);
5541ufbx_abi ufbx_geometry_cache *ufbx_load_geometry_cache_len(
5542 const char *filename, size_t filename_len,
5543 const ufbx_geometry_cache_opts *opts, ufbx_error *error);
5544
5545// Free a geometry cache returned from `ufbx_load_geometry_cache()`.
5546ufbx_abi void ufbx_free_geometry_cache(ufbx_geometry_cache *cache);
5547// Increase the geometry cache reference count.
5548ufbx_abi void ufbx_retain_geometry_cache(ufbx_geometry_cache *cache);
5549
5550// Read a frame from a geometry cache.
5551ufbx_abi size_t ufbx_read_geometry_cache_real(const ufbx_cache_frame *frame, ufbx_real *data, size_t num_data, const ufbx_geometry_cache_data_opts *opts);
5552ufbx_abi size_t ufbx_read_geometry_cache_vec3(const ufbx_cache_frame *frame, ufbx_vec3 *data, size_t num_data, const ufbx_geometry_cache_data_opts *opts);
5553// Sample the a geometry cache channel, linearly blending between adjacent frames.
5554ufbx_abi size_t ufbx_sample_geometry_cache_real(const ufbx_cache_channel *channel, double time, ufbx_real *data, size_t num_data, const ufbx_geometry_cache_data_opts *opts);
5555ufbx_abi size_t ufbx_sample_geometry_cache_vec3(const ufbx_cache_channel *channel, double time, ufbx_vec3 *data, size_t num_data, const ufbx_geometry_cache_data_opts *opts);
5556
5557// DOM
5558
5559// Find a DOM node given a name.
5560ufbx_abi ufbx_dom_node *ufbx_dom_find_len(const ufbx_dom_node *parent, const char *name, size_t name_len);
5561ufbx_inline ufbx_dom_node *ufbx_dom_find(const ufbx_dom_node *parent, const char *name) { return ufbx_dom_find_len(parent, name, strlen(name)); }
5562
5563// Utility
5564
5565// Generate an index buffer for a flat vertex buffer.
5566// `streams` specifies one or more vertex data arrays, each stream must contain `num_indices` vertices.
5567// This function compacts the data within `streams` in-place, writing the deduplicated indices to `indices`.
5568ufbx_abi size_t ufbx_generate_indices(const ufbx_vertex_stream *streams, size_t num_streams, uint32_t *indices, size_t num_indices, const ufbx_allocator_opts *allocator, ufbx_error *error);
5569
5570// Thread pool
5571
5572// Run a single thread pool task.
5573// See `ufbx_thread_pool_run_fn` for more information.
5574ufbx_unsafe ufbx_abi void ufbx_thread_pool_run_task(ufbx_thread_pool_context ctx, uint32_t index);
5575
5576// Get or set an arbitrary user pointer for the thread pool context.
5577// `ufbx_thread_pool_get_user_ptr()` returns `NULL` if unset.
5578ufbx_unsafe ufbx_abi void ufbx_thread_pool_set_user_ptr(ufbx_thread_pool_context ctx, void *user_ptr);
5579ufbx_unsafe ufbx_abi void *ufbx_thread_pool_get_user_ptr(ufbx_thread_pool_context ctx);
5580
5581// -- Inline API
5582
5583// Utility functions for reading geometry data for a single index.
5584ufbx_abi ufbx_real ufbx_catch_get_vertex_real(ufbx_panic *panic, const ufbx_vertex_real *v, size_t index);
5585ufbx_abi ufbx_vec2 ufbx_catch_get_vertex_vec2(ufbx_panic *panic, const ufbx_vertex_vec2 *v, size_t index);
5586ufbx_abi ufbx_vec3 ufbx_catch_get_vertex_vec3(ufbx_panic *panic, const ufbx_vertex_vec3 *v, size_t index);
5587ufbx_abi ufbx_vec4 ufbx_catch_get_vertex_vec4(ufbx_panic *panic, const ufbx_vertex_vec4 *v, size_t index);
5588
5589// Utility functions for reading geometry data for a single index.
5590ufbx_inline ufbx_real ufbx_get_vertex_real(const ufbx_vertex_real *v, size_t index) { ufbx_assert(index < v->indices.count); return v->values.data[(int32_t)v->indices.data[index]]; }
5591ufbx_inline ufbx_vec2 ufbx_get_vertex_vec2(const ufbx_vertex_vec2 *v, size_t index) { ufbx_assert(index < v->indices.count); return v->values.data[(int32_t)v->indices.data[index]]; }
5592ufbx_inline ufbx_vec3 ufbx_get_vertex_vec3(const ufbx_vertex_vec3 *v, size_t index) { ufbx_assert(index < v->indices.count); return v->values.data[(int32_t)v->indices.data[index]]; }
5593ufbx_inline ufbx_vec4 ufbx_get_vertex_vec4(const ufbx_vertex_vec4 *v, size_t index) { ufbx_assert(index < v->indices.count); return v->values.data[(int32_t)v->indices.data[index]]; }
5594
5595ufbx_abi ufbx_real ufbx_catch_get_vertex_w_vec3(ufbx_panic *panic, const ufbx_vertex_vec3 *v, size_t index);
5596ufbx_inline ufbx_real ufbx_get_vertex_w_vec3(const ufbx_vertex_vec3 *v, size_t index) { ufbx_assert(index < v->indices.count); return v->values_w.count > 0 ? v->values_w.data[(int32_t)v->indices.data[index]] : 0.0f; }
5597
5598// Functions for converting an untyped `ufbx_element` to a concrete type.
5599// Returns `NULL` if the element is not that type.
5600ufbx_abi ufbx_unknown *ufbx_as_unknown(const ufbx_element *element);
5601ufbx_abi ufbx_node *ufbx_as_node(const ufbx_element *element);
5602ufbx_abi ufbx_mesh *ufbx_as_mesh(const ufbx_element *element);
5603ufbx_abi ufbx_light *ufbx_as_light(const ufbx_element *element);
5604ufbx_abi ufbx_camera *ufbx_as_camera(const ufbx_element *element);
5605ufbx_abi ufbx_bone *ufbx_as_bone(const ufbx_element *element);
5606ufbx_abi ufbx_empty *ufbx_as_empty(const ufbx_element *element);
5607ufbx_abi ufbx_line_curve *ufbx_as_line_curve(const ufbx_element *element);
5608ufbx_abi ufbx_nurbs_curve *ufbx_as_nurbs_curve(const ufbx_element *element);
5609ufbx_abi ufbx_nurbs_surface *ufbx_as_nurbs_surface(const ufbx_element *element);
5610ufbx_abi ufbx_nurbs_trim_surface *ufbx_as_nurbs_trim_surface(const ufbx_element *element);
5611ufbx_abi ufbx_nurbs_trim_boundary *ufbx_as_nurbs_trim_boundary(const ufbx_element *element);
5612ufbx_abi ufbx_procedural_geometry *ufbx_as_procedural_geometry(const ufbx_element *element);
5613ufbx_abi ufbx_stereo_camera *ufbx_as_stereo_camera(const ufbx_element *element);
5614ufbx_abi ufbx_camera_switcher *ufbx_as_camera_switcher(const ufbx_element *element);
5615ufbx_abi ufbx_marker *ufbx_as_marker(const ufbx_element *element);
5616ufbx_abi ufbx_lod_group *ufbx_as_lod_group(const ufbx_element *element);
5617ufbx_abi ufbx_skin_deformer *ufbx_as_skin_deformer(const ufbx_element *element);
5618ufbx_abi ufbx_skin_cluster *ufbx_as_skin_cluster(const ufbx_element *element);
5619ufbx_abi ufbx_blend_deformer *ufbx_as_blend_deformer(const ufbx_element *element);
5620ufbx_abi ufbx_blend_channel *ufbx_as_blend_channel(const ufbx_element *element);
5621ufbx_abi ufbx_blend_shape *ufbx_as_blend_shape(const ufbx_element *element);
5622ufbx_abi ufbx_cache_deformer *ufbx_as_cache_deformer(const ufbx_element *element);
5623ufbx_abi ufbx_cache_file *ufbx_as_cache_file(const ufbx_element *element);
5624ufbx_abi ufbx_material *ufbx_as_material(const ufbx_element *element);
5625ufbx_abi ufbx_texture *ufbx_as_texture(const ufbx_element *element);
5626ufbx_abi ufbx_video *ufbx_as_video(const ufbx_element *element);
5627ufbx_abi ufbx_shader *ufbx_as_shader(const ufbx_element *element);
5628ufbx_abi ufbx_shader_binding *ufbx_as_shader_binding(const ufbx_element *element);
5629ufbx_abi ufbx_anim_stack *ufbx_as_anim_stack(const ufbx_element *element);
5630ufbx_abi ufbx_anim_layer *ufbx_as_anim_layer(const ufbx_element *element);
5631ufbx_abi ufbx_anim_value *ufbx_as_anim_value(const ufbx_element *element);
5632ufbx_abi ufbx_anim_curve *ufbx_as_anim_curve(const ufbx_element *element);
5633ufbx_abi ufbx_display_layer *ufbx_as_display_layer(const ufbx_element *element);
5634ufbx_abi ufbx_selection_set *ufbx_as_selection_set(const ufbx_element *element);
5635ufbx_abi ufbx_selection_node *ufbx_as_selection_node(const ufbx_element *element);
5636ufbx_abi ufbx_character *ufbx_as_character(const ufbx_element *element);
5637ufbx_abi ufbx_constraint *ufbx_as_constraint(const ufbx_element *element);
5638ufbx_abi ufbx_audio_layer *ufbx_as_audio_layer(const ufbx_element *element);
5639ufbx_abi ufbx_audio_clip *ufbx_as_audio_clip(const ufbx_element *element);
5640ufbx_abi ufbx_pose *ufbx_as_pose(const ufbx_element *element);
5641ufbx_abi ufbx_metadata_object *ufbx_as_metadata_object(const ufbx_element *element);
5642
5643#ifdef __cplusplus
5644}
5645#endif
5646
5647// bindgen-disable
5648
5649#if UFBX_CPP11
5650
5651struct ufbx_string_view {
5652 const char *data;
5653 size_t length;
5654
5655 ufbx_string_view() : data(nullptr), length(0) { }
5656 ufbx_string_view(const char *data_, size_t length_) : data(data_), length(length_) { }
5657 UFBX_CONVERSION_TO_IMPL(ufbx_string_view)
5658};
5659
5660ufbx_inline ufbx_scene *ufbx_load_file(ufbx_string_view filename, const ufbx_load_opts *opts, ufbx_error *error) { return ufbx_load_file_len(filename.data, filename.length, opts, error); }
5661ufbx_inline ufbx_prop *ufbx_find_prop(const ufbx_props *props, ufbx_string_view name) { return ufbx_find_prop_len(props, name.data, name.length); }
5662ufbx_inline ufbx_real ufbx_find_real(const ufbx_props *props, ufbx_string_view name, ufbx_real def) { return ufbx_find_real_len(props, name.data, name.length, def); }
5663ufbx_inline ufbx_vec3 ufbx_find_vec3(const ufbx_props *props, ufbx_string_view name, ufbx_vec3 def) { return ufbx_find_vec3_len(props, name.data, name.length, def); }
5664ufbx_inline int64_t ufbx_find_int(const ufbx_props *props, ufbx_string_view name, int64_t def) { return ufbx_find_int_len(props, name.data, name.length, def); }
5665ufbx_inline bool ufbx_find_bool(const ufbx_props *props, ufbx_string_view name, bool def) { return ufbx_find_bool_len(props, name.data, name.length, def); }
5666ufbx_inline ufbx_string ufbx_find_string(const ufbx_props *props, ufbx_string_view name, ufbx_string def) { return ufbx_find_string_len(props, name.data, name.length, def); }
5667ufbx_inline ufbx_blob ufbx_find_blob(const ufbx_props *props, ufbx_string_view name, ufbx_blob def) { return ufbx_find_blob_len(props, name.data, name.length, def); }
5668ufbx_inline ufbx_element *ufbx_find_prop_element(const ufbx_element *element, ufbx_string_view name, ufbx_element_type type) { return ufbx_find_prop_element_len(element, name.data, name.length, type); }
5669ufbx_inline ufbx_element *ufbx_find_element(const ufbx_scene *scene, ufbx_element_type type, ufbx_string_view name) { return ufbx_find_element_len(scene, type, name.data, name.length); }
5670ufbx_inline ufbx_node *ufbx_find_node(const ufbx_scene *scene, ufbx_string_view name) { return ufbx_find_node_len(scene, name.data, name.length); }
5671ufbx_inline ufbx_anim_stack *ufbx_find_anim_stack(const ufbx_scene *scene, ufbx_string_view name) { return ufbx_find_anim_stack_len(scene, name.data, name.length); }
5672ufbx_inline ufbx_material *ufbx_find_material(const ufbx_scene *scene, ufbx_string_view name) { return ufbx_find_material_len(scene, name.data, name.length); }
5673ufbx_inline ufbx_anim_prop *ufbx_find_anim_prop(const ufbx_anim_layer *layer, const ufbx_element *element, ufbx_string_view prop) { return ufbx_find_anim_prop_len(layer, element, prop.data, prop.length); }
5674ufbx_inline ufbx_prop ufbx_evaluate_prop(const ufbx_anim *anim, const ufbx_element *element, ufbx_string_view name, double time) { return ufbx_evaluate_prop_len(anim, element, name.data, name.length, time); }
5675ufbx_inline ufbx_texture *ufbx_find_prop_texture(const ufbx_material *material, ufbx_string_view name) { return ufbx_find_prop_texture_len(material, name.data, name.length); }
5676ufbx_inline ufbx_string ufbx_find_shader_prop(const ufbx_shader *shader, ufbx_string_view name) { return ufbx_find_shader_prop_len(shader, name.data, name.length); }
5677ufbx_inline ufbx_shader_prop_binding_list ufbx_find_shader_prop_bindings(const ufbx_shader *shader, ufbx_string_view name) { return ufbx_find_shader_prop_bindings_len(shader, name.data, name.length); }
5678ufbx_inline ufbx_shader_texture_input *ufbx_find_shader_texture_input(const ufbx_shader_texture *shader, ufbx_string_view name) { return ufbx_find_shader_texture_input_len(shader, name.data, name.length); }
5679ufbx_inline ufbx_geometry_cache *ufbx_load_geometry_cache(ufbx_string_view filename, const ufbx_geometry_cache_opts *opts, ufbx_error *error) { return ufbx_load_geometry_cache_len(filename.data, filename.length, opts, error); }
5680ufbx_inline ufbx_dom_node *ufbx_dom_find(const ufbx_dom_node *parent, ufbx_string_view name) { return ufbx_dom_find_len(parent, name.data, name.length); }
5681
5682#endif
5683
5684#if UFBX_CPP11
5685
5686template <typename T>
5687struct ufbx_type_traits { enum { valid = 0 }; };
5688
5689template<> struct ufbx_type_traits<ufbx_scene> {
5690 enum { valid = 1 };
5691 static void retain(ufbx_scene *ptr) { ufbx_retain_scene(ptr); }
5692 static void free(ufbx_scene *ptr) { ufbx_free_scene(ptr); }
5693};
5694
5695template<> struct ufbx_type_traits<ufbx_mesh> {
5696 enum { valid = 1 };
5697 static void retain(ufbx_mesh *ptr) { ufbx_retain_mesh(ptr); }
5698 static void free(ufbx_mesh *ptr) { ufbx_free_mesh(ptr); }
5699};
5700
5701template<> struct ufbx_type_traits<ufbx_line_curve> {
5702 enum { valid = 1 };
5703 static void retain(ufbx_line_curve *ptr) { ufbx_retain_line_curve(ptr); }
5704 static void free(ufbx_line_curve *ptr) { ufbx_free_line_curve(ptr); }
5705};
5706
5707template<> struct ufbx_type_traits<ufbx_geometry_cache> {
5708 enum { valid = 1 };
5709 static void retain(ufbx_geometry_cache *ptr) { ufbx_retain_geometry_cache(ptr); }
5710 static void free(ufbx_geometry_cache *ptr) { ufbx_free_geometry_cache(ptr); }
5711};
5712
5713template<> struct ufbx_type_traits<ufbx_anim> {
5714 enum { valid = 1 };
5715 static void retain(ufbx_anim *ptr) { ufbx_retain_anim(ptr); }
5716 static void free(ufbx_anim *ptr) { ufbx_free_anim(ptr); }
5717};
5718
5719template<> struct ufbx_type_traits<ufbx_baked_anim> {
5720 enum { valid = 1 };
5721 static void retain(ufbx_baked_anim *ptr) { ufbx_retain_baked_anim(ptr); }
5722 static void free(ufbx_baked_anim *ptr) { ufbx_free_baked_anim(ptr); }
5723};
5724
5725class ufbx_deleter {
5726public:
5727 template <typename T>
5728 void operator()(T *ptr) const {
5729 static_assert(ufbx_type_traits<T>::valid, "ufbx_deleter() unsupported for type");
5730 ufbx_type_traits<T>::free(ptr);
5731 }
5732};
5733
5734// RAII wrapper over refcounted ufbx types.
5735
5736// Behaves like `std::unique_ptr<T>`.
5737template <typename T>
5738class ufbx_unique_ptr {
5739 T *ptr;
5740 using traits = ufbx_type_traits<T>;
5741 static_assert(ufbx_type_traits<T>::valid, "ufbx_unique_ptr unsupported for type");
5742public:
5743 ufbx_unique_ptr() noexcept : ptr(nullptr) { }
5744 explicit ufbx_unique_ptr(T *ptr_) noexcept : ptr(ptr_) { }
5745 ufbx_unique_ptr(ufbx_unique_ptr &&ref) noexcept : ptr(ref.ptr) { ref.ptr = nullptr; }
5746 ~ufbx_unique_ptr() { traits::free(ptr); }
5747
5748 ufbx_unique_ptr &operator=(ufbx_unique_ptr &&ref) noexcept {
5749 if (&ref == this) return *this;
5750 ptr = ref.ptr;
5751 ref.ptr = nullptr;
5752 return *this;
5753 }
5754
5755 void reset(T *new_ptr=nullptr) noexcept {
5756 traits::free(ptr);
5757 ptr = new_ptr;
5758 }
5759
5760 void swap(ufbx_unique_ptr &ref) noexcept {
5761 T *tmp = ptr;
5762 ptr = ref.ptr;
5763 ref.ptr = tmp;
5764 }
5765
5766 T &operator*() const noexcept { return *ptr; }
5767 T *operator->() const noexcept { return ptr; }
5768 T *get() const noexcept { return ptr; }
5769 explicit operator bool() const noexcept { return ptr != nullptr; }
5770};
5771
5772// Behaves like `std::shared_ptr<T>` except uses ufbx's internal reference counting,
5773// so it is half the size of a standard `shared_ptr` but might be marginally slower.
5774template <typename T>
5775class ufbx_shared_ptr {
5776 T *ptr;
5777 using traits = ufbx_type_traits<T>;
5778 static_assert(ufbx_type_traits<T>::valid, "ufbx_shared_ptr unsupported for type");
5779public:
5780
5781 ufbx_shared_ptr() noexcept : ptr(nullptr) { }
5782 explicit ufbx_shared_ptr(T *ptr_) noexcept : ptr(ptr_) { }
5783 ufbx_shared_ptr(const ufbx_shared_ptr &ref) noexcept : ptr(ref.ptr) { traits::retain(ref.ptr); }
5784 ufbx_shared_ptr(ufbx_shared_ptr &&ref) noexcept : ptr(ref.ptr) { ref.ptr = nullptr; }
5785 ~ufbx_shared_ptr() { traits::free(ptr); }
5786
5787 ufbx_shared_ptr &operator=(const ufbx_shared_ptr &ref) noexcept {
5788 if (&ref == this) return *this;
5789 traits::free(ptr);
5790 traits::retain(ref.ptr);
5791 ptr = ref.ptr;
5792 return *this;
5793 }
5794
5795 ufbx_shared_ptr &operator=(ufbx_shared_ptr &&ref) noexcept {
5796 if (&ref == this) return *this;
5797 ptr = ref.ptr;
5798 ref.ptr = nullptr;
5799 return *this;
5800 }
5801
5802 void reset(T *new_ptr=nullptr) noexcept {
5803 traits::free(ptr);
5804 ptr = new_ptr;
5805 }
5806
5807 void swap(ufbx_shared_ptr &ref) noexcept {
5808 T *tmp = ptr;
5809 ptr = ref.ptr;
5810 ref.ptr = tmp;
5811 }
5812
5813 T &operator*() const noexcept { return *ptr; }
5814 T *operator->() const noexcept { return ptr; }
5815 T *get() const noexcept { return ptr; }
5816 explicit operator bool() const noexcept { return ptr != nullptr; }
5817};
5818
5819#endif
5820// bindgen-enable
5821
5822// -- Properties
5823
5824// Names of common properties in `ufbx_props`.
5825// Some of these differ from ufbx interpretations.
5826
5827// Local translation.
5828// Used by: `ufbx_node`
5829#define UFBX_Lcl_Translation "Lcl Translation"
5830
5831// Local rotation expressed in Euler degrees.
5832// Used by: `ufbx_node`
5833// The rotation order is defined by the `UFBX_RotationOrder` property.
5834#define UFBX_Lcl_Rotation "Lcl Rotation"
5835
5836// Local scaling factor, 3D vector.
5837// Used by: `ufbx_node`
5838#define UFBX_Lcl_Scaling "Lcl Scaling"
5839
5840// Euler rotation interpretation, used by `UFBX_Lcl_Rotation`.
5841// Used by: `ufbx_node`, enum value `ufbx_rotation_order`.
5842#define UFBX_RotationOrder "RotationOrder"
5843
5844// Scaling pivot: point around which scaling is performed.
5845// Used by: `ufbx_node`.
5846#define UFBX_ScalingPivot "ScalingPivot"
5847
5848// Scaling pivot: point around which rotation is performed.
5849// Used by: `ufbx_node`.
5850#define UFBX_RotationPivot "RotationPivot"
5851
5852// Scaling offset: translation added after scaling is performed.
5853// Used by: `ufbx_node`.
5854#define UFBX_ScalingOffset "ScalingOffset"
5855
5856// Rotation offset: translation added after rotation is performed.
5857// Used by: `ufbx_node`.
5858#define UFBX_RotationOffset "RotationOffset"
5859
5860// Pre-rotation: Rotation applied _after_ `UFBX_Lcl_Rotation`.
5861// Used by: `ufbx_node`.
5862// Affected by `UFBX_RotationPivot` but not `UFBX_RotationOrder`.
5863#define UFBX_PreRotation "PreRotation"
5864
5865// Post-rotation: Rotation applied _before_ `UFBX_Lcl_Rotation`.
5866// Used by: `ufbx_node`.
5867// Affected by `UFBX_RotationPivot` but not `UFBX_RotationOrder`.
5868#define UFBX_PostRotation "PostRotation"
5869
5870// Controls whether the node should be displayed or not.
5871// Used by: `ufbx_node`.
5872#define UFBX_Visibility "Visibility"
5873
5874// Weight of an animation layer in percentage (100.0 being full).
5875// Used by: `ufbx_anim_layer`.
5876#define UFBX_Weight "Weight"
5877
5878// Blend shape deformation weight (100.0 being full).
5879// Used by: `ufbx_blend_channel`.
5880#define UFBX_DeformPercent "DeformPercent"
5881
5882#if defined(_MSC_VER)
5883 #pragma warning(pop)
5884#elif defined(__clang__)
5885 #pragma clang diagnostic pop
5886#elif defined(__GNUC__)
5887 #pragma GCC diagnostic pop
5888#endif
5889
5890#endif
Definition ufbx.h:3948
Definition ufbx.h:3939
Definition ufbx.h:3171
Definition ufbx.h:3094
Definition ufbx.h:4810
Definition ufbx.h:3083
Definition ufbx.h:3068
Definition ufbx.h:3119
Definition ufbx.h:3042
Definition ufbx.h:3462
Definition ufbx.h:3357
Definition ufbx.h:3345
Definition ufbx.h:4866
Definition ufbx.h:4453
Definition ufbx.h:4463
Definition ufbx.h:4444
Definition ufbx.h:4406
Definition ufbx.h:4432
Definition ufbx.h:4397
Definition ufbx.h:4389
Definition ufbx.h:2065
Definition ufbx.h:2037
Definition ufbx.h:2050
Definition ufbx.h:2085
Definition ufbx.h:289
Definition ufbx.h:3391
Definition ufbx.h:1623
Definition ufbx.h:2185
Definition ufbx.h:2218
Definition ufbx.h:2234
Definition ufbx.h:2153
Definition ufbx.h:1830
Definition ufbx.h:1556
Definition ufbx.h:3243
Definition ufbx.h:4036
Definition ufbx.h:1076
Definition ufbx.h:742
Definition ufbx.h:3270
Definition ufbx.h:3301
Definition ufbx.h:1549
Definition ufbx.h:3874
Definition ufbx.h:3188
Definition ufbx.h:428
Definition ufbx.h:417
Definition ufbx.h:1088
Definition ufbx.h:756
Definition ufbx.h:1643
Definition ufbx.h:4066
Definition ufbx.h:4162
Definition ufbx.h:4771
Definition ufbx.h:1131
Definition ufbx.h:1102
Definition ufbx.h:5045
Definition ufbx.h:5019
Definition ufbx.h:2211
Definition ufbx.h:4204
Definition ufbx.h:4240
Definition ufbx.h:3161
Definition ufbx.h:1413
Definition ufbx.h:1663
Definition ufbx.h:1656
Definition ufbx.h:4522
Definition ufbx.h:1895
Definition ufbx.h:1877
Definition ufbx.h:1851
Definition ufbx.h:2492
Definition ufbx.h:2306
Definition ufbx.h:2583
Definition ufbx.h:2271
Definition ufbx.h:2520
Definition ufbx.h:2318
Definition ufbx.h:2616
Definition ufbx.h:366
Definition ufbx.h:1110
Definition ufbx.h:1246
Definition ufbx.h:3424
Definition ufbx.h:3601
Definition ufbx.h:3435
Definition ufbx.h:837
Definition ufbx.h:1697
Definition ufbx.h:1732
Definition ufbx.h:1750
Definition ufbx.h:1795
Definition ufbx.h:1785
Definition ufbx.h:4024
Definition ufbx.h:4009
Definition ufbx.h:4046
Definition ufbx.h:5061
Definition ufbx.h:3408
Definition ufbx.h:1807
Definition ufbx.h:4189
Definition ufbx.h:4173
Definition ufbx.h:4792
Definition ufbx.h:3016
Definition ufbx.h:535
Definition ufbx.h:560
Definition ufbx.h:327
Definition ufbx.h:3744
Definition ufbx.h:3774
Definition ufbx.h:3220
Definition ufbx.h:3207
Definition ufbx.h:3003
Definition ufbx.h:2995
Definition ufbx.h:2753
Definition ufbx.h:2799
Definition ufbx.h:2976
Definition ufbx.h:1998
Definition ufbx.h:1969
Definition ufbx.h:1941
Definition ufbx.h:1959
Definition ufbx.h:1817
Definition ufbx.h:3990
Definition ufbx.h:281
Definition ufbx.h:4978
Definition ufbx.h:1152
Definition ufbx.h:1138
Definition ufbx.h:1145
Definition ufbx.h:3880
Definition ufbx.h:3144
Definition ufbx.h:4942
Definition ufbx.h:4956
Definition ufbx.h:2833
Definition ufbx.h:2727
Definition ufbx.h:2868
Definition ufbx.h:4512
Definition ufbx.h:4495
Definition ufbx.h:4504
Definition ufbx.h:3585
Definition ufbx.h:3895
Definition ufbx.h:3029
Definition ufbx.h:356
Definition ufbx.h:771
Definition ufbx.h:1065
Definition ufbx.h:297
Definition ufbx.h:307
Definition ufbx.h:317
Definition ufbx.h:996
Definition ufbx.h:1017
Definition ufbx.h:3909
Definition ufbx.h:1029
Definition ufbx.h:1041
Definition ufbx.h:1053
Definition ufbx.h:2940
Definition ufbx.h:381
Definition ufbx.h:3536