forked from Shirakumo/cl-fbx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ufbx.h
4768 lines (3824 loc) · 169 KB
/
ufbx.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifndef UFBX_UFBX_H_INCLUDED
#define UFBX_UFBX_H_INCLUDED
// -- User configuration
#if defined(UFBX_CONFIG_HEADER)
#include UFBX_CONFIG_HEADER
#endif
// -- Headers
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
// -- Platform
#ifndef UFBX_STDC
#if defined(__STDC_VERSION__)
#define UFBX_STDC __STDC_VERSION__
#else
#define UFBX_STDC 0
#endif
#endif
#ifndef UFBX_CPP
#if defined(__cplusplus)
#define UFBX_CPP __cplusplus
#else
#define UFBX_CPP 0
#endif
#endif
#ifndef UFBX_PLATFORM_MSC
#if !defined(UFBX_STANDARD_C) && defined(_MSC_VER)
#define UFBX_PLATFORM_MSC _MSC_VER
#else
#define UFBX_PLATFORM_MSC 0
#endif
#endif
#ifndef UFBX_PLATFORM_GNUC
#if !defined(UFBX_STANDARD_C) && defined(__GNUC__)
#define UFBX_PLATFORM_GNUC __GNUC__
#else
#define UFBX_PLATFORM_GNUC 0
#endif
#endif
#ifndef UFBX_CPP11
// MSVC does not advertise C++11 by default so we need special detection
#if UFBX_CPP >= 201103L || (UFBX_CPP > 0 && UFBX_PLATFORM_MSC >= 1900)
#define UFBX_CPP11 1
#else
#define UFBX_CPP11 0
#endif
#endif
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4201) // nonstandard extension used: nameless struct/union
#pragma warning(disable: 4505) // unreferenced local function has been removed
#elif defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpedantic"
#if defined(__cplusplus)
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#pragma clang diagnostic ignored "-Wold-style-cast"
#endif
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#if defined(__cplusplus)
#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#endif
#endif
#if UFBX_PLATFORM_MSC
#define ufbx_inline static __forceinline
#elif UFBX_PLATFORM_GNUC
#define ufbx_inline static inline __attribute__((always_inline, unused))
#else
#define ufbx_inline static
#endif
#ifndef ufbx_assert
#if !defined(UFBX_NO_ASSERT)
#include <assert.h>
#define ufbx_assert(cond) assert(cond)
#else
#define ufbx_assert(cond) (void)0
#endif
#endif
// Pointer may be `NULL`.
#define ufbx_nullable
// Changing this value from default can lead into breaking API guarantees.
#define ufbx_unsafe
#ifndef ufbx_abi
#define ufbx_abi
#endif
// -- Configuration
#if defined(UFBX_REAL_IS_FLOAT)
typedef float ufbx_real;
#else
typedef double ufbx_real;
#endif
#define UFBX_ERROR_STACK_MAX_DEPTH 8
#define UFBX_PANIC_MESSAGE_LENGTH 128
#define UFBX_ERROR_INFO_LENGTH 256
// -- Language
#if defined(__cplusplus)
#define UFBX_LIST_TYPE(p_name, p_type) struct p_name { p_type *data; size_t count; \
p_type &operator[](size_t index) const { ufbx_assert(index < count); return data[index]; } \
p_type *begin() const { return data; } \
p_type *end() const { return data + count; } }
#else
#define UFBX_LIST_TYPE(p_name, p_type) typedef struct p_name { p_type *data; size_t count; } p_name
#endif
#if UFBX_STDC >= 202311L || UFBX_CPP11
#define UFBX_ENUM_REPR : int
#define UFBX_ENUM_FORCE_WIDTH(p_prefix)
#define UFBX_FLAG_REPR : int
#define UFBX_FLAG_FORCE_WIDTH(p_prefix)
#else
#define UFBX_ENUM_REPR
#define UFBX_ENUM_FORCE_WIDTH(p_prefix) p_prefix##_FORCE_32BIT = 0x7fffffff
#define UFBX_FLAG_REPR
#define UFBX_FLAG_FORCE_WIDTH(p_prefix) p_prefix##_FORCE_32BIT = 0x7fffffff
#endif
#define UFBX_ENUM_TYPE(p_name, p_prefix, p_last) \
enum { p_prefix##_COUNT = p_last + 1 }
#if UFBX_CPP
#define UFBX_VERTEX_ATTRIB_IMPL(p_type) \
p_type &operator[](size_t index) const { ufbx_assert(index < indices.count); return values.data[indices.data[index]]; }
#else
#define UFBX_VERTEX_ATTRIB_IMPL(p_type)
#endif
#if UFBX_CPP11
#define UFBX_CALLBACK_IMPL(p_name, p_fn, p_return, p_params, p_args) \
template <typename F> static p_return _cpp_adapter p_params { F &f = *static_cast<F*>(user); return f p_args; } \
p_name() = default; \
p_name(p_fn *f) : fn(f), user(nullptr) { } \
template <typename F> p_name(F *f) : fn(&_cpp_adapter<F>), user(static_cast<void*>(f)) { }
#else
#define UFBX_CALLBACK_IMPL(p_name, p_fn, p_return, p_params, p_args)
#endif
// -- Version
#define ufbx_pack_version(major, minor, patch) ((uint32_t)(major)*1000000u + (uint32_t)(minor)*1000u + (uint32_t)(patch))
#define ufbx_version_major(version) ((uint32_t)(version)/1000000u%1000u)
#define ufbx_version_minor(version) ((uint32_t)(version)/1000u%1000u)
#define ufbx_version_patch(version) ((uint32_t)(version)%1000u)
#define UFBX_HEADER_VERSION ufbx_pack_version(0, 5, 0)
#define UFBX_VERSION UFBX_HEADER_VERSION
// -- Basic types
#define UFBX_NO_INDEX ((uint32_t)~0u)
// Null-terminated UTF-8 encoded string within an FBX file
typedef struct ufbx_string {
const char *data;
size_t length;
} ufbx_string;
// Opaque byte buffer blob
typedef struct ufbx_blob {
const void *data;
size_t size;
} ufbx_blob;
// 2D vector
typedef struct ufbx_vec2 {
union {
struct { ufbx_real x, y; };
ufbx_real v[2];
};
} ufbx_vec2;
// 3D vector
typedef struct ufbx_vec3 {
union {
struct { ufbx_real x, y, z; };
ufbx_real v[3];
};
} ufbx_vec3;
// 4D vector
typedef struct ufbx_vec4 {
union {
struct { ufbx_real x, y, z, w; };
ufbx_real v[4];
};
} ufbx_vec4;
// Quaternion
typedef struct ufbx_quat {
union {
struct { ufbx_real x, y, z, w; };
ufbx_real v[4];
};
} ufbx_quat;
// Order in which Euler-angle rotation axes are applied for a transform
// NOTE: The order in the name refers to the order of axes *applied*,
// not the multiplication order: eg. `UFBX_ROTATION_XYZ` is `Z*Y*X`
// [TODO: Figure out what the spheric rotation order is...]
typedef enum ufbx_rotation_order UFBX_ENUM_REPR {
UFBX_ROTATION_ORDER_XYZ,
UFBX_ROTATION_ORDER_XZY,
UFBX_ROTATION_ORDER_YZX,
UFBX_ROTATION_ORDER_YXZ,
UFBX_ROTATION_ORDER_ZXY,
UFBX_ROTATION_ORDER_ZYX,
UFBX_ROTATION_ORDER_SPHERIC,
UFBX_ENUM_FORCE_WIDTH(UFBX_ROTATION_ORDER)
} ufbx_rotation_order;
UFBX_ENUM_TYPE(ufbx_rotation_order, UFBX_ROTATION_ORDER, UFBX_ROTATION_ORDER_SPHERIC);
// Explicit translation+rotation+scale transformation.
// NOTE: Rotation is a quaternion, not Euler angles!
typedef struct ufbx_transform {
ufbx_vec3 translation;
ufbx_quat rotation;
ufbx_vec3 scale;
} ufbx_transform;
// 4x3 matrix encoding an affine transformation.
// `cols[0..2]` are the X/Y/Z basis vectors, `cols[3]` is the translation
typedef struct ufbx_matrix {
union {
struct {
ufbx_real m00, m10, m20;
ufbx_real m01, m11, m21;
ufbx_real m02, m12, m22;
ufbx_real m03, m13, m23;
};
ufbx_vec3 cols[4];
ufbx_real v[12];
};
} ufbx_matrix;
typedef struct ufbx_void_list {
void *data;
size_t count;
} ufbx_void_list;
UFBX_LIST_TYPE(ufbx_bool_list, bool);
UFBX_LIST_TYPE(ufbx_uint32_list, uint32_t);
UFBX_LIST_TYPE(ufbx_real_list, ufbx_real);
UFBX_LIST_TYPE(ufbx_vec2_list, ufbx_vec2);
UFBX_LIST_TYPE(ufbx_vec3_list, ufbx_vec3);
UFBX_LIST_TYPE(ufbx_vec4_list, ufbx_vec4);
UFBX_LIST_TYPE(ufbx_string_list, ufbx_string);
// -- Document object model
typedef enum ufbx_dom_value_type UFBX_ENUM_REPR {
UFBX_DOM_VALUE_NUMBER,
UFBX_DOM_VALUE_STRING,
UFBX_DOM_VALUE_ARRAY_I8,
UFBX_DOM_VALUE_ARRAY_I32,
UFBX_DOM_VALUE_ARRAY_I64,
UFBX_DOM_VALUE_ARRAY_F32,
UFBX_DOM_VALUE_ARRAY_F64,
UFBX_DOM_VALUE_ARRAY_RAW_STRING,
UFBX_DOM_VALUE_ARRAY_IGNORED,
UFBX_ENUM_FORCE_WIDTH(UFBX_DOM_VALUE_TYPE)
} ufbx_dom_value_type;
UFBX_ENUM_TYPE(ufbx_dom_value_type, UFBX_DOM_VALUE_TYPE, UFBX_DOM_VALUE_ARRAY_IGNORED);
typedef struct ufbx_dom_node ufbx_dom_node;
typedef struct ufbx_dom_value {
ufbx_dom_value_type type;
ufbx_string value_str;
ufbx_blob value_blob;
int64_t value_int;
double value_float;
} ufbx_dom_value;
UFBX_LIST_TYPE(ufbx_dom_node_list, ufbx_dom_node*);
UFBX_LIST_TYPE(ufbx_dom_value_list, ufbx_dom_value);
struct ufbx_dom_node {
ufbx_string name;
ufbx_dom_node_list children;
ufbx_dom_value_list values;
};
// -- Properties
// FBX elements have properties which are arbitrary key/value pairs that can
// have inherited default values or be animated. In most cases you don't need
// to access these unless you need a feature not implemented directly in ufbx.
// NOTE: Prefer using `ufbx_find_prop[_len](...)` to search for a property by
// name as it can find it from the defaults if necessary.
typedef struct ufbx_prop ufbx_prop;
typedef struct ufbx_props ufbx_props;
// Data type contained within the property. All the data fields are always
// populated regardless of type, so there's no need to switch by type usually
// eg. `prop->value_real` and `prop->value_int` have the same value (well, close)
// if `prop->type == UFBX_PROP_INTEGER`. String values are not converted from/to.
typedef enum ufbx_prop_type UFBX_ENUM_REPR {
UFBX_PROP_UNKNOWN,
UFBX_PROP_BOOLEAN,
UFBX_PROP_INTEGER,
UFBX_PROP_NUMBER,
UFBX_PROP_VECTOR,
UFBX_PROP_COLOR,
UFBX_PROP_COLOR_WITH_ALPHA,
UFBX_PROP_STRING,
UFBX_PROP_DATE_TIME,
UFBX_PROP_TRANSLATION,
UFBX_PROP_ROTATION,
UFBX_PROP_SCALING,
UFBX_PROP_DISTANCE,
UFBX_PROP_COMPOUND,
UFBX_PROP_BLOB,
UFBX_PROP_REFERENCE,
UFBX_ENUM_FORCE_WIDTH(UFBX_PROP_TYPE)
} ufbx_prop_type;
UFBX_ENUM_TYPE(ufbx_prop_type, UFBX_PROP_TYPE, UFBX_PROP_REFERENCE);
// Property flags: Advanced information about properties, not usually needed.
typedef enum ufbx_prop_flags UFBX_FLAG_REPR {
// Supports animation.
// NOTE: ufbx ignores this and allows animations on non-animatable properties.
UFBX_PROP_FLAG_ANIMATABLE = 0x1,
// User defined (custom) property.
UFBX_PROP_FLAG_USER_DEFINED = 0x2,
// Hidden in UI.
UFBX_PROP_FLAG_HIDDEN = 0x4,
// Disallow modification from UI for components.
UFBX_PROP_FLAG_LOCK_X = 0x10,
UFBX_PROP_FLAG_LOCK_Y = 0x20,
UFBX_PROP_FLAG_LOCK_Z = 0x40,
UFBX_PROP_FLAG_LOCK_W = 0x80,
// Disable animation from components.
UFBX_PROP_FLAG_MUTE_X = 0x100,
UFBX_PROP_FLAG_MUTE_Y = 0x200,
UFBX_PROP_FLAG_MUTE_Z = 0x400,
UFBX_PROP_FLAG_MUTE_W = 0x800,
// Property created by ufbx when an element has a connected `ufbx_anim_prop`
// but doesn't contain the `ufbx_prop` it's referring to.
// NOTE: The property may have been found in the templated defaults.
UFBX_PROP_FLAG_SYNTHETIC = 0x1000,
// The property has at least one `ufbx_anim_prop` in some layer.
UFBX_PROP_FLAG_ANIMATED = 0x2000,
// Used by `ufbx_evaluate_prop()` to indicate the the property was not found.
UFBX_PROP_FLAG_NOT_FOUND = 0x4000,
// The property is connected to another one.
// This use case is relatively rare so `ufbx_prop` does not track connections
// directly. You can find connections from `ufbx_element.connections_dst` where
// `ufbx_connection.dst_prop` is this property and `ufbx_connection.src_prop` is defined.
UFBX_PROP_FLAG_CONNECTED = 0x8000,
// The value of this property is undefined (represented as zero).
UFBX_PROP_FLAG_NO_VALUE = 0x10000,
// This property has been overridden by the user.
// See `ufbx_anim.prop_overrides` for more information.
UFBX_PROP_FLAG_OVERRIDDEN = 0x20000,
// Value type.
// `REAL/VEC2/VEC3/VEC4` are mutually exclusive but may coexist with eg. `STRING`
// in some rare cases where the string defines the unit for the vector.
UFBX_PROP_FLAG_VALUE_REAL = 0x100000,
UFBX_PROP_FLAG_VALUE_VEC2 = 0x200000,
UFBX_PROP_FLAG_VALUE_VEC3 = 0x400000,
UFBX_PROP_FLAG_VALUE_VEC4 = 0x800000,
UFBX_PROP_FLAG_VALUE_INT = 0x1000000,
UFBX_PROP_FLAG_VALUE_STR = 0x2000000,
UFBX_PROP_FLAG_VALUE_BLOB = 0x4000000,
UFBX_FLAG_FORCE_WIDTH(UFBX_PROP_FLAGS)
} ufbx_prop_flags;
// Single property with name/type/value.
struct ufbx_prop {
ufbx_string name;
uint32_t _internal_key;
ufbx_prop_type type;
ufbx_prop_flags flags;
ufbx_string value_str;
ufbx_blob value_blob;
int64_t value_int;
union {
ufbx_real value_real_arr[4];
ufbx_real value_real;
ufbx_vec2 value_vec2;
ufbx_vec3 value_vec3;
ufbx_vec4 value_vec4;
};
};
UFBX_LIST_TYPE(ufbx_prop_list, ufbx_prop);
// List of alphabetically sorted properties with potential defaults.
// For animated objects in as scene from `ufbx_evaluate_scene()` this list
// only has the animated properties, the originals are stored under `defaults`.
struct ufbx_props {
ufbx_prop_list props;
size_t num_animated;
ufbx_nullable ufbx_props *defaults;
};
typedef struct ufbx_scene ufbx_scene;
// -- Elements
// Element is the lowest level representation of the FBX file in ufbx.
// An element contains type, id, name, and properties (see `ufbx_props` above)
// Elements may be connected to each other arbitrarily via `ufbx_connection`
typedef struct ufbx_element ufbx_element;
// Unknown
typedef struct ufbx_unknown ufbx_unknown;
// Nodes
typedef struct ufbx_node ufbx_node;
// Node attributes (common)
typedef struct ufbx_mesh ufbx_mesh;
typedef struct ufbx_light ufbx_light;
typedef struct ufbx_camera ufbx_camera;
typedef struct ufbx_bone ufbx_bone;
typedef struct ufbx_empty ufbx_empty;
// Node attributes (curves/surfaces)
typedef struct ufbx_line_curve ufbx_line_curve;
typedef struct ufbx_nurbs_curve ufbx_nurbs_curve;
typedef struct ufbx_nurbs_surface ufbx_nurbs_surface;
typedef struct ufbx_nurbs_trim_surface ufbx_nurbs_trim_surface;
typedef struct ufbx_nurbs_trim_boundary ufbx_nurbs_trim_boundary;
// Node attributes (advanced)
typedef struct ufbx_procedural_geometry ufbx_procedural_geometry;
typedef struct ufbx_stereo_camera ufbx_stereo_camera;
typedef struct ufbx_camera_switcher ufbx_camera_switcher;
typedef struct ufbx_marker ufbx_marker;
typedef struct ufbx_lod_group ufbx_lod_group;
// Deformers
typedef struct ufbx_skin_deformer ufbx_skin_deformer;
typedef struct ufbx_skin_cluster ufbx_skin_cluster;
typedef struct ufbx_blend_deformer ufbx_blend_deformer;
typedef struct ufbx_blend_channel ufbx_blend_channel;
typedef struct ufbx_blend_shape ufbx_blend_shape;
typedef struct ufbx_cache_deformer ufbx_cache_deformer;
typedef struct ufbx_cache_file ufbx_cache_file;
// Materials
typedef struct ufbx_material ufbx_material;
typedef struct ufbx_texture ufbx_texture;
typedef struct ufbx_video ufbx_video;
typedef struct ufbx_shader ufbx_shader;
typedef struct ufbx_shader_binding ufbx_shader_binding;
// Animation
typedef struct ufbx_anim_stack ufbx_anim_stack;
typedef struct ufbx_anim_layer ufbx_anim_layer;
typedef struct ufbx_anim_value ufbx_anim_value;
typedef struct ufbx_anim_curve ufbx_anim_curve;
// Collections
typedef struct ufbx_display_layer ufbx_display_layer;
typedef struct ufbx_selection_set ufbx_selection_set;
typedef struct ufbx_selection_node ufbx_selection_node;
// Constraints
typedef struct ufbx_character ufbx_character;
typedef struct ufbx_constraint ufbx_constraint;
// Miscellaneous
typedef struct ufbx_pose ufbx_pose;
typedef struct ufbx_metadata_object ufbx_metadata_object;
UFBX_LIST_TYPE(ufbx_element_list, ufbx_element*);
UFBX_LIST_TYPE(ufbx_unknown_list, ufbx_unknown*);
UFBX_LIST_TYPE(ufbx_node_list, ufbx_node*);
UFBX_LIST_TYPE(ufbx_mesh_list, ufbx_mesh*);
UFBX_LIST_TYPE(ufbx_light_list, ufbx_light*);
UFBX_LIST_TYPE(ufbx_camera_list, ufbx_camera*);
UFBX_LIST_TYPE(ufbx_bone_list, ufbx_bone*);
UFBX_LIST_TYPE(ufbx_empty_list, ufbx_empty*);
UFBX_LIST_TYPE(ufbx_line_curve_list, ufbx_line_curve*);
UFBX_LIST_TYPE(ufbx_nurbs_curve_list, ufbx_nurbs_curve*);
UFBX_LIST_TYPE(ufbx_nurbs_surface_list, ufbx_nurbs_surface*);
UFBX_LIST_TYPE(ufbx_nurbs_trim_surface_list, ufbx_nurbs_trim_surface*);
UFBX_LIST_TYPE(ufbx_nurbs_trim_boundary_list, ufbx_nurbs_trim_boundary*);
UFBX_LIST_TYPE(ufbx_procedural_geometry_list, ufbx_procedural_geometry*);
UFBX_LIST_TYPE(ufbx_stereo_camera_list, ufbx_stereo_camera*);
UFBX_LIST_TYPE(ufbx_camera_switcher_list, ufbx_camera_switcher*);
UFBX_LIST_TYPE(ufbx_marker_list, ufbx_marker*);
UFBX_LIST_TYPE(ufbx_lod_group_list, ufbx_lod_group*);
UFBX_LIST_TYPE(ufbx_skin_deformer_list, ufbx_skin_deformer*);
UFBX_LIST_TYPE(ufbx_skin_cluster_list, ufbx_skin_cluster*);
UFBX_LIST_TYPE(ufbx_blend_deformer_list, ufbx_blend_deformer*);
UFBX_LIST_TYPE(ufbx_blend_channel_list, ufbx_blend_channel*);
UFBX_LIST_TYPE(ufbx_blend_shape_list, ufbx_blend_shape*);
UFBX_LIST_TYPE(ufbx_cache_deformer_list, ufbx_cache_deformer*);
UFBX_LIST_TYPE(ufbx_cache_file_list, ufbx_cache_file*);
UFBX_LIST_TYPE(ufbx_material_list, ufbx_material*);
UFBX_LIST_TYPE(ufbx_texture_list, ufbx_texture*);
UFBX_LIST_TYPE(ufbx_video_list, ufbx_video*);
UFBX_LIST_TYPE(ufbx_shader_list, ufbx_shader*);
UFBX_LIST_TYPE(ufbx_shader_binding_list, ufbx_shader_binding*);
UFBX_LIST_TYPE(ufbx_anim_stack_list, ufbx_anim_stack*);
UFBX_LIST_TYPE(ufbx_anim_layer_list, ufbx_anim_layer*);
UFBX_LIST_TYPE(ufbx_anim_value_list, ufbx_anim_value*);
UFBX_LIST_TYPE(ufbx_anim_curve_list, ufbx_anim_curve*);
UFBX_LIST_TYPE(ufbx_display_layer_list, ufbx_display_layer*);
UFBX_LIST_TYPE(ufbx_selection_set_list, ufbx_selection_set*);
UFBX_LIST_TYPE(ufbx_selection_node_list, ufbx_selection_node*);
UFBX_LIST_TYPE(ufbx_character_list, ufbx_character*);
UFBX_LIST_TYPE(ufbx_constraint_list, ufbx_constraint*);
UFBX_LIST_TYPE(ufbx_pose_list, ufbx_pose*);
UFBX_LIST_TYPE(ufbx_metadata_object_list, ufbx_metadata_object*);
typedef enum ufbx_element_type UFBX_ENUM_REPR {
UFBX_ELEMENT_UNKNOWN, // < `ufbx_unknown`
UFBX_ELEMENT_NODE, // < `ufbx_node`
UFBX_ELEMENT_MESH, // < `ufbx_mesh`
UFBX_ELEMENT_LIGHT, // < `ufbx_light`
UFBX_ELEMENT_CAMERA, // < `ufbx_camera`
UFBX_ELEMENT_BONE, // < `ufbx_bone`
UFBX_ELEMENT_EMPTY, // < `ufbx_empty`
UFBX_ELEMENT_LINE_CURVE, // < `ufbx_line_curve`
UFBX_ELEMENT_NURBS_CURVE, // < `ufbx_nurbs_curve`
UFBX_ELEMENT_NURBS_SURFACE, // < `ufbx_nurbs_surface`
UFBX_ELEMENT_NURBS_TRIM_SURFACE, // < `ufbx_nurbs_trim_surface`
UFBX_ELEMENT_NURBS_TRIM_BOUNDARY, // < `ufbx_nurbs_trim_boundary`
UFBX_ELEMENT_PROCEDURAL_GEOMETRY, // < `ufbx_procedural_geometry`
UFBX_ELEMENT_STEREO_CAMERA, // < `ufbx_stereo_camera`
UFBX_ELEMENT_CAMERA_SWITCHER, // < `ufbx_camera_switcher`
UFBX_ELEMENT_MARKER, // < `ufbx_marker`
UFBX_ELEMENT_LOD_GROUP, // < `ufbx_lod_group`
UFBX_ELEMENT_SKIN_DEFORMER, // < `ufbx_skin_deformer`
UFBX_ELEMENT_SKIN_CLUSTER, // < `ufbx_skin_cluster`
UFBX_ELEMENT_BLEND_DEFORMER, // < `ufbx_blend_deformer`
UFBX_ELEMENT_BLEND_CHANNEL, // < `ufbx_blend_channel`
UFBX_ELEMENT_BLEND_SHAPE, // < `ufbx_blend_shape`
UFBX_ELEMENT_CACHE_DEFORMER, // < `ufbx_cache_deformer`
UFBX_ELEMENT_CACHE_FILE, // < `ufbx_cache_file`
UFBX_ELEMENT_MATERIAL, // < `ufbx_material`
UFBX_ELEMENT_TEXTURE, // < `ufbx_texture`
UFBX_ELEMENT_VIDEO, // < `ufbx_video`
UFBX_ELEMENT_SHADER, // < `ufbx_shader`
UFBX_ELEMENT_SHADER_BINDING, // < `ufbx_shader_binding`
UFBX_ELEMENT_ANIM_STACK, // < `ufbx_anim_stack`
UFBX_ELEMENT_ANIM_LAYER, // < `ufbx_anim_layer`
UFBX_ELEMENT_ANIM_VALUE, // < `ufbx_anim_value`
UFBX_ELEMENT_ANIM_CURVE, // < `ufbx_anim_curve`
UFBX_ELEMENT_DISPLAY_LAYER, // < `ufbx_display_layer`
UFBX_ELEMENT_SELECTION_SET, // < `ufbx_selection_set`
UFBX_ELEMENT_SELECTION_NODE, // < `ufbx_selection_node`
UFBX_ELEMENT_CHARACTER, // < `ufbx_character`
UFBX_ELEMENT_CONSTRAINT, // < `ufbx_constraint`
UFBX_ELEMENT_POSE, // < `ufbx_pose`
UFBX_ELEMENT_METADATA_OBJECT, // < `ufbx_metadata_object`
UFBX_ELEMENT_TYPE_FIRST_ATTRIB = UFBX_ELEMENT_MESH,
UFBX_ELEMENT_TYPE_LAST_ATTRIB = UFBX_ELEMENT_LOD_GROUP,
UFBX_ENUM_FORCE_WIDTH(UFBX_ELEMENT_TYPE)
} ufbx_element_type;
UFBX_ENUM_TYPE(ufbx_element_type, UFBX_ELEMENT_TYPE, UFBX_ELEMENT_METADATA_OBJECT);
// Connection between two elements.
// Source and destination are somewhat arbitrary but the destination is
// often the "container" like a parent node or mesh containing a deformer.
typedef struct ufbx_connection {
ufbx_element *src;
ufbx_element *dst;
ufbx_string src_prop;
ufbx_string dst_prop;
} ufbx_connection;
UFBX_LIST_TYPE(ufbx_connection_list, ufbx_connection);
// Element "base-class" common to each element.
// Some fields (like `connections_src`) are advanced and not visible
// in the specialized element structs.
// NOTE: The `element_id` value is consistent when loading the
// _same_ file, but re-exporting the file will invalidate them. (TOMOVE)
struct ufbx_element {
ufbx_string name;
ufbx_props props;
uint32_t element_id;
uint32_t typed_id;
ufbx_node_list instances;
ufbx_element_type type;
ufbx_connection_list connections_src;
ufbx_connection_list connections_dst;
ufbx_nullable ufbx_dom_node *dom_node;
ufbx_scene *scene;
};
// -- Unknown
struct ufbx_unknown {
// Shared "base-class" header, see `ufbx_element`.
union { ufbx_element element; struct {
ufbx_string name;
ufbx_props props;
uint32_t element_id;
uint32_t typed_id;
}; };
// FBX format specific type information.
// In ASCII FBX format:
// super_type: ID, "type::name", "sub_type" { ... }
ufbx_string type;
ufbx_string super_type;
ufbx_string sub_type;
};
// -- Nodes
// Inherit type specifies how hierarchial node transforms are combined.
// `UFBX_INHERIT_NORMAL` is combined using the "proper" multiplication
// `UFBX_INHERIT_NO_SHEAR` does component-wise { pos+pos, rot*rot, scale*scale }
// `UFBX_INHERIT_NO_SCALE` ignores the parent scale { pos+pos, rot*rot, scale }
typedef enum ufbx_inherit_type UFBX_ENUM_REPR {
UFBX_INHERIT_NO_SHEAR, // R*r*S*s
UFBX_INHERIT_NORMAL, // R*S*r*s
UFBX_INHERIT_NO_SCALE, // R*r*s
UFBX_ENUM_FORCE_WIDTH(UFBX_INHERIT_TYPE)
} ufbx_inherit_type;
UFBX_ENUM_TYPE(ufbx_inherit_type, UFBX_INHERIT_TYPE, UFBX_INHERIT_NO_SCALE);
// Nodes form the scene transformation hierarchy and can contain attached
// elements such as meshes or lights. In normal cases a single `ufbx_node`
// contains only a single attached element, so using `type/mesh/...` is safe.
struct ufbx_node {
union { ufbx_element element; struct {
ufbx_string name;
ufbx_props props;
uint32_t element_id;
uint32_t typed_id;
}; };
// Node hierarchy
// Parent node containing this one if not root.
//
// Always non-`NULL` for non-root nodes unless
// `ufbx_load_opts.allow_nodes_out_of_root` is enabled.
ufbx_nullable ufbx_node *parent;
// List of child nodes parented to this node.
ufbx_node_list children;
// Attached element type and typed pointers.
//
// Set to `NULL` if not in use, so checking `attrib_type` is not required.
ufbx_nullable ufbx_mesh *mesh;
ufbx_nullable ufbx_light *light;
ufbx_nullable ufbx_camera *camera;
ufbx_nullable ufbx_bone *bone;
// Less common attributes use these fields.
//
// Defined even if it is one of the above, eg. `ufbx_mesh`. In case there
// is multiple attributes this will be the first one.
ufbx_nullable ufbx_element *attrib;
// Geometry transform helper if one exists.
// See `UFBX_GEOMETRY_TRANSFORM_HANDLING_HELPER_NODES`.
ufbx_nullable ufbx_node *geometry_transform_helper;
// `attrib->type` if `attrib` is defined, otherwise `UFBX_ELEMENT_UNKNOWN`.
ufbx_element_type attrib_type;
// List of _all_ attached attribute elements.
//
// In most cases there is only zero or one attributes per node, but if you
// have a very exotic FBX file nodes may have multiple attributes.
ufbx_element_list all_attribs;
// Local transform in parent, geometry transform is a non-inherited
// transform applied only to attachments like meshes
ufbx_inherit_type inherit_type;
ufbx_transform local_transform;
ufbx_transform geometry_transform;
// Raw Euler angles in degrees for those who want them
// Specifies the axis order `euler_rotation` is applied in.
ufbx_rotation_order rotation_order;
// Rotation around the local X/Y/Z axes in `rotation_order`.
// The angles are specified in degrees.
ufbx_vec3 euler_rotation;
// Transform to the global "world" space, may be incorrect if the node
// uses `UFBX_INHERIT_NORMAL`, prefer using the `node_to_world` matrix.
ufbx_transform world_transform;
// Matrices derived from the transformations, for transforming geometry
// prefer using `geometry_to_world` as that supports geometric transforms.
// Transform from this node to `parent` space.
// Equivalent to `ufbx_transform_to_matrix(&local_transform)`.
ufbx_matrix node_to_parent;
// Transform from this node to the world space, ie. multiplying all the
// `node_to_parent` matrices of the parent chain together.
// NOTE: Not the same as `ufbx_transform_to_matrix(&world_transform)`
// as this matrix will account for potential shear (if `inherit_type == UFBX_INHERIT_NORMAL`).
ufbx_matrix node_to_world;
// Transform from the attribute to this node. Does not affect the transforms
// of `children`!
// Equivalent to `ufbx_transform_to_matrix(&geometry_transform)`.
ufbx_matrix geometry_to_node;
// Transform from attribute space to world space.
// Equivalent to `ufbx_matrix_mul(&node_to_world, &geometry_to_node)`.
ufbx_matrix geometry_to_world;
// ufbx-specific adjustment for switching between coodrinate/unit systems.
// HINT: In most cases you don't need to deal with these as these are baked
// into all the transforms above and into `ufbx_evaluate_transform()`.
ufbx_quat adjust_pre_rotation; // < Rotation applied between parent and self
ufbx_vec3 adjust_pre_scale; // < Scaling applied between parent and self
ufbx_quat adjust_post_rotation; // < Rotation applied in local space at the end
// Materials used by `mesh` or other `attrib`.
// There may be multiple copies of a single `ufbx_mesh` with different materials
// in the `ufbx_node` instances.
ufbx_material_list materials;
// Visibility state.
bool visible;
// True if this node is the implicit root node of the scene.
bool is_root;
// True if the node has a non-identity `geometry_transform`.
bool has_geometry_transform;
// If `true` the transform is adjusted by ufbx, not enabled by default.
// See `adjust_pre_rotation`, `adjust_pre_scale`, `adjust_post_rotation`.
bool has_adjust_transform;
// True if this node is node is a synthetic geometry transform helper.
// See `UFBX_GEOMETRY_TRANSFORM_HANDLING_HELPER_NODES`.
bool is_geometry_transform_helper;
// How deep is this node in the parent hierarchy. Root node is at depth `0`
// and the immediate children of root at `1`.
uint32_t node_depth;
};
// Vertex attribute: All attributes are stored in a consistent indexed format
// regardless of how it's actually stored in the file.
//
// `values` is a contiguous array of attribute values.
// `indices` maps each mesh index into a value in the `values` array.
//
// If `unique_per_vertex` is set then the attribute is guaranteed to have a
// single defined value per vertex accessible via:
// attrib.values.data[attrib.indices.data[mesh->vertex_first_index[vertex_ix]]
typedef struct ufbx_vertex_attrib {
bool exists;
ufbx_void_list values;
ufbx_uint32_list indices;
size_t value_reals;
bool unique_per_vertex;
} ufbx_vertex_attrib;
// 1D vertex attribute, see `ufbx_vertex_attrib` for information
typedef struct ufbx_vertex_real {
bool exists;
ufbx_real_list values;
ufbx_uint32_list indices;
size_t value_reals;
bool unique_per_vertex;
UFBX_VERTEX_ATTRIB_IMPL(ufbx_real)
} ufbx_vertex_real;
// 2D vertex attribute, see `ufbx_vertex_attrib` for information
typedef struct ufbx_vertex_vec2 {
bool exists;
ufbx_vec2_list values;
ufbx_uint32_list indices;
size_t value_reals;
bool unique_per_vertex;
UFBX_VERTEX_ATTRIB_IMPL(ufbx_vec2)
} ufbx_vertex_vec2;
// 3D vertex attribute, see `ufbx_vertex_attrib` for information
typedef struct ufbx_vertex_vec3 {
bool exists;
ufbx_vec3_list values;
ufbx_uint32_list indices;
size_t value_reals;
bool unique_per_vertex;
UFBX_VERTEX_ATTRIB_IMPL(ufbx_vec3)
} ufbx_vertex_vec3;
// 4D vertex attribute, see `ufbx_vertex_attrib` for information
typedef struct ufbx_vertex_vec4 {
bool exists;
ufbx_vec4_list values;
ufbx_uint32_list indices;
size_t value_reals;
bool unique_per_vertex;
UFBX_VERTEX_ATTRIB_IMPL(ufbx_vec4)
} ufbx_vertex_vec4;
// Vertex UV set/layer
typedef struct ufbx_uv_set {
ufbx_string name;
uint32_t index;
// Vertex attributes, see `ufbx_mesh` attributes for more information
ufbx_vertex_vec2 vertex_uv; // < UV / texture coordinates
ufbx_vertex_vec3 vertex_tangent; // < (optional) Tangent vector in UV.x direction
ufbx_vertex_vec3 vertex_bitangent; // < (optional) Tangent vector in UV.y direction
} ufbx_uv_set;
// Vertex color set/layer
typedef struct ufbx_color_set {
ufbx_string name;
uint32_t index;
// Vertex attributes, see `ufbx_mesh` attributes for more information
ufbx_vertex_vec4 vertex_color; // < Per-vertex RGBA color
} ufbx_color_set;
UFBX_LIST_TYPE(ufbx_uv_set_list, ufbx_uv_set);
UFBX_LIST_TYPE(ufbx_color_set_list, ufbx_color_set);
// Edge between two _indices_ in a mesh
typedef struct ufbx_edge {
union {
struct { uint32_t a, b; };
uint32_t indices[2];
};
} ufbx_edge;
UFBX_LIST_TYPE(ufbx_edge_list, ufbx_edge);
// Polygonal face with arbitrary number vertices, a single face contains a
// contiguous range of mesh indices, eg. `{5,3}` would have indices 5, 6, 7
//
// NOTE: `num_indices` maybe less than 3 in which case the face is invalid!
// [TODO #23: should probably remove the bad faces at load time]
typedef struct ufbx_face {
uint32_t index_begin;
uint32_t num_indices;
} ufbx_face;
UFBX_LIST_TYPE(ufbx_face_list, ufbx_face);
typedef struct ufbx_mesh_material {
ufbx_nullable ufbx_material *material;
// Sub-set of the geometry that uses this specific material
size_t num_faces; // < Number of faces (polygons) using this material
size_t num_triangles; // < Number of triangles using this material if triangulated
size_t num_empty_faces; // < Number of faces with zero vertices
size_t num_point_faces; // < Number of faces with a single vertex
size_t num_line_faces; // < Number of faces with two vertices
// Indices to `ufbx_mesh.faces[]` that use this material.
// Always contains `num_faces` elements.
ufbx_uint32_list face_indices;
} ufbx_mesh_material;
UFBX_LIST_TYPE(ufbx_mesh_material_list, ufbx_mesh_material);
typedef struct ufbx_face_group {
int32_t id; // < Numerical ID for this group.
ufbx_string name; // < Name for the face group.
// Sub-set of the geometry in this face group
size_t num_faces; // < Number of faces (polygons) using this material
size_t num_triangles; // < Number of triangles using this material if triangulated
// Indices to `ufbx_mesh.faces[]` that use this material.
// Always contains `num_faces` elements.
ufbx_uint32_list face_indices;
} ufbx_face_group;
UFBX_LIST_TYPE(ufbx_face_group_list, ufbx_face_group);
typedef struct ufbx_subdivision_weight_range {
uint32_t weight_begin;
uint32_t num_weights;
} ufbx_subdivision_weight_range;
UFBX_LIST_TYPE(ufbx_subdivision_weight_range_list, ufbx_subdivision_weight_range);
typedef struct ufbx_subdivision_weight {
ufbx_real weight;
uint32_t index;
} ufbx_subdivision_weight;
UFBX_LIST_TYPE(ufbx_subdivision_weight_list, ufbx_subdivision_weight);
typedef struct ufbx_subdivision_result {
size_t result_memory_used;
size_t temp_memory_used;
size_t result_allocs;
size_t temp_allocs;
// Weights of vertices in the source model.
// Defined if `ufbx_subdivide_opts.evaluate_source_vertices` is set.
ufbx_subdivision_weight_range_list source_vertex_ranges;
ufbx_subdivision_weight_list source_vertex_weights;
// Weights of skin clusters in the source model.
// Defined if `ufbx_subdivide_opts.evaluate_skin_weights` is set.
ufbx_subdivision_weight_range_list skin_cluster_ranges;
ufbx_subdivision_weight_list skin_cluster_weights;
} ufbx_subdivision_result;
typedef enum ufbx_subdivision_display_mode UFBX_ENUM_REPR {
UFBX_SUBDIVISION_DISPLAY_DISABLED,
UFBX_SUBDIVISION_DISPLAY_HULL,
UFBX_SUBDIVISION_DISPLAY_HULL_AND_SMOOTH,
UFBX_SUBDIVISION_DISPLAY_SMOOTH,
UFBX_ENUM_FORCE_WIDTH(UFBX_SUBDIVISION_DISPLAY_MODE)
} ufbx_subdivision_display_mode;
UFBX_ENUM_TYPE(ufbx_subdivision_display_mode, UFBX_SUBDIVISION_DISPLAY_MODE, UFBX_SUBDIVISION_DISPLAY_SMOOTH);
typedef enum ufbx_subdivision_boundary UFBX_ENUM_REPR {
UFBX_SUBDIVISION_BOUNDARY_DEFAULT,
UFBX_SUBDIVISION_BOUNDARY_LEGACY,
// OpenSubdiv: `VTX_BOUNDARY_EDGE_AND_CORNER` / `FVAR_LINEAR_CORNERS_ONLY`
UFBX_SUBDIVISION_BOUNDARY_SHARP_CORNERS,
// OpenSubdiv: `VTX_BOUNDARY_EDGE_ONLY` / `FVAR_LINEAR_NONE`
UFBX_SUBDIVISION_BOUNDARY_SHARP_NONE,
// OpenSubdiv: `FVAR_LINEAR_BOUNDARIES`
UFBX_SUBDIVISION_BOUNDARY_SHARP_BOUNDARY,
// OpenSubdiv: `FVAR_LINEAR_ALL`
UFBX_SUBDIVISION_BOUNDARY_SHARP_INTERIOR,
UFBX_ENUM_FORCE_WIDTH(UFBX_SUBDIVISION_BOUNDARY)
} ufbx_subdivision_boundary;
UFBX_ENUM_TYPE(ufbx_subdivision_boundary, UFBX_SUBDIVISION_BOUNDARY, UFBX_SUBDIVISION_BOUNDARY_SHARP_INTERIOR);
// Polygonal mesh geometry.
//
// Example mesh with two triangles (x, z) and a quad (y).
// The faces have a constant UV coordinate x/y/z.
// The vertices have _per vertex_ normals that point up/down.
//
// ^ ^ ^
// A---B-----C
// |x / /|
// | / y / |