PeriDyno 0.8.2
ofbx.cpp
Go to the documentation of this file.
1#include "ofbx.h"
2#include "miniz.h"
3#include <cassert>
4#include <math.h>
5#include <ctype.h>
6#include <memory>
7#include <numeric>
8#include <string>
9#include <unordered_map>
10#include <vector>
11
12
13namespace ofbx
14{
15
16
17struct Allocator {
18 struct Page {
19 struct {
20 Page* next = nullptr;
23 u8 data[4096 * 1024 - 12];
24 };
25 Page* first = nullptr;
26
28 Page* p = first;
29 while (p) {
30 Page* n = p->header.next;
31 delete p;
32 p = n;
33 }
34 }
35
36 template <typename T, typename... Args> T* allocate(Args&&... args)
37 {
38 assert(sizeof(T) <= sizeof(first->data));
39 if (!first) {
40 first = new Page;
41 }
42 Page* p = first;
43 if (p->header.offset % alignof(T) != 0) {
44 p->header.offset += alignof(T) - p->header.offset % alignof(T);
45 }
46
47 if (p->header.offset + sizeof(T) > sizeof(p->data)) {
48 p = new Page;
49 p->header.next = first;
50 first = p;
51 }
52 T* res = new (p->data + p->header.offset) T(args...);
53 p->header.offset += sizeof(T);
54 return res;
55 }
56
57 // store temporary data, can be reused
58 std::vector<float> tmp;
59 std::vector<int> int_tmp;
60 std::vector<Vec3> vec3_tmp;
61 std::vector<double> double_tmp;
62 std::vector<Vec3> vec3_tmp2;
63};
64
65
67 std::vector<float> f;
68 std::vector<int> i;
69 std::vector<Vec2> v2;
70 std::vector<Vec3> v3;
71 std::vector<Vec4> v4;
72};
73
74
75struct Video
76{
80};
81
82
83struct Error
84{
85 Error() {}
86 Error(const char* msg) { s_message = msg; }
87
88 static const char* s_message;
89};
90
91
92const char* Error::s_message = "";
93
94
95template <typename T> struct OptionalError
96{
98 : is_error(true)
99 {
100 }
101
102
104 : value(_value)
105 , is_error(false)
106 {
107 }
108
109
110 T getValue() const
111 {
112#ifdef _DEBUG
113 assert(error_checked);
114#endif
115 return value;
116 }
117
118
119 bool isError()
120 {
121#ifdef _DEBUG
122 error_checked = true;
123#endif
124 return is_error;
125 }
126
127
128private:
131#ifdef _DEBUG
132 bool error_checked = false;
133#endif
134};
135
136
137#pragma pack(1)
138struct Header
139{
143};
144#pragma pack()
145
146
147struct Cursor
148{
149 const u8* current;
150 const u8* begin;
151 const u8* end;
152};
153
154
155static void setTranslation(const Vec3& t, Matrix* mtx)
156{
157 mtx->m[12] = t.x;
158 mtx->m[13] = t.y;
159 mtx->m[14] = t.z;
160}
161
162
163static Vec3 operator-(const Vec3& v)
164{
165 return {-v.x, -v.y, -v.z};
166}
167
168
169static Matrix operator*(const Matrix& lhs, const Matrix& rhs)
170{
171 Matrix res;
172 for (int j = 0; j < 4; ++j)
173 {
174 for (int i = 0; i < 4; ++i)
175 {
176 double tmp = 0;
177 for (int k = 0; k < 4; ++k)
178 {
179 tmp += lhs.m[i + k * 4] * rhs.m[k + j * 4];
180 }
181 res.m[i + j * 4] = tmp;
182 }
183 }
184 return res;
185}
186
187
189{
190 return {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
191}
192
193
194static Matrix rotationX(double angle)
195{
196 Matrix m = makeIdentity();
197 double c = cos(angle);
198 double s = sin(angle);
199
200 m.m[5] = m.m[10] = c;
201 m.m[9] = -s;
202 m.m[6] = s;
203
204 return m;
205}
206
207
208static Matrix rotationY(double angle)
209{
210 Matrix m = makeIdentity();
211 double c = cos(angle);
212 double s = sin(angle);
213
214 m.m[0] = m.m[10] = c;
215 m.m[8] = s;
216 m.m[2] = -s;
217
218 return m;
219}
220
221
222static Matrix rotationZ(double angle)
223{
224 Matrix m = makeIdentity();
225 double c = cos(angle);
226 double s = sin(angle);
227
228 m.m[0] = m.m[5] = c;
229 m.m[4] = -s;
230 m.m[1] = s;
231
232 return m;
233}
234
235
236static Matrix getRotationMatrix(const Vec3& euler, RotationOrder order)
237{
238 const double TO_RAD = 3.1415926535897932384626433832795028 / 180.0;
239 Matrix rx = rotationX(euler.x * TO_RAD);
240 Matrix ry = rotationY(euler.y * TO_RAD);
241 Matrix rz = rotationZ(euler.z * TO_RAD);
242 switch (order)
243 {
244 default:
245 case RotationOrder::EULER_XYZ: return rz * ry * rx;
246 case RotationOrder::EULER_XZY: return ry * rz * rx;
247 case RotationOrder::EULER_YXZ: return rz * rx * ry;
248 case RotationOrder::EULER_YZX: return rx * rz * ry;
249 case RotationOrder::EULER_ZXY: return ry * rx * rz;
250 case RotationOrder::EULER_ZYX: return rx * ry * rz;
251 case RotationOrder::SPHERIC_XYZ: assert(false); Error::s_message = "Unsupported rotation order."; return rx * ry * rz;
252 }
253}
254
255
257{
258 return double(value) / 46186158000L;
259}
260
261
263{
264 return i64(value * 46186158000L);
265}
266
267
268static Vec3 operator*(const Vec3& v, float f)
269{
270 return {v.x * f, v.y * f, v.z * f};
271}
272
273
274static Vec3 operator+(const Vec3& a, const Vec3& b)
275{
276 return {a.x + b.x, a.y + b.y, a.z + b.z};
277}
278
279
280template <int SIZE> static bool copyString(char (&destination)[SIZE], const char* source)
281{
282 const char* src = source;
283 char* dest = destination;
284 int length = SIZE;
285 if (!src) return false;
286
287 while (*src && length > 1)
288 {
289 *dest = *src;
290 --length;
291 ++dest;
292 ++src;
293 }
294 *dest = 0;
295 return *src == '\0';
296}
297
298
300{
301 if (is_binary)
302 {
303 assert(end - begin == sizeof(u64));
304 u64 result;
305 memcpy(&result, begin, sizeof(u64));
306 return result;
307 }
308 static_assert(sizeof(unsigned long long) >= sizeof(u64), "can't use strtoull");
309 return strtoull((const char*)begin, nullptr, 10);
310}
311
312
314{
315 if (is_binary)
316 {
317 assert(end - begin == sizeof(i64));
318 i64 result;
319 memcpy(&result, begin, sizeof(i64));
320 return result;
321 }
322 static_assert(sizeof(long long) >= sizeof(i64), "can't use atoll");
323 return atoll((const char*)begin);
324}
325
326
328{
329 if (is_binary)
330 {
331 assert(end - begin == sizeof(int));
332 int result;
333 memcpy(&result, begin, sizeof(int));
334 return result;
335 }
336 return atoi((const char*)begin);
337}
338
339
341{
342 if (is_binary)
343 {
344 assert(end - begin == sizeof(u32));
345 u32 result;
346 memcpy(&result, begin, sizeof(u32));
347 return result;
348 }
349 return (u32)atoll((const char*)begin);
350}
351
352
353double DataView::toDouble() const
354{
355 if (is_binary)
356 {
357 assert(end - begin == sizeof(double));
358 double result;
359 memcpy(&result, begin, sizeof(double));
360 return result;
361 }
362 return atof((const char*)begin);
363}
364
365
366float DataView::toFloat() const
367{
368 if (is_binary)
369 {
370 assert(end - begin == sizeof(float));
371 float result;
372 memcpy(&result, begin, sizeof(float));
373 return result;
374 }
375 return (float)atof((const char*)begin);
376}
377
378
379bool DataView::operator==(const char* rhs) const
380{
381 const char* c = rhs;
382 const char* c2 = (const char*)begin;
383 while (*c && c2 != (const char*)end)
384 {
385 if (*c != *c2) return false;
386 ++c;
387 ++c2;
388 }
389 return c2 == (const char*)end && *c == '\0';
390}
391
392
393struct Property;
394template <typename T> static bool parseArrayRaw(const Property& property, T* out, int max_size);
395template <typename T> static bool parseBinaryArray(const Property& property, std::vector<T>* out);
396static bool parseDouble(Property& property, double* out);
397
398
400{
401 Type getType() const override { return (Type)type; }
402 IElementProperty* getNext() const override { return next; }
403 DataView getValue() const override { return value; }
404 int getCount() const override
405 {
407 if (value.is_binary)
408 {
409 int i;
410 memcpy(&i, value.begin, sizeof(i));
411 return i;
412 }
413 return count;
414 }
415
416 bool getValues(double* values, int max_size) const override { return parseArrayRaw(*this, values, max_size); }
417
418 bool getValues(float* values, int max_size) const override { return parseArrayRaw(*this, values, max_size); }
419
420 bool getValues(u64* values, int max_size) const override { return parseArrayRaw(*this, values, max_size); }
421
422 bool getValues(i64* values, int max_size) const override { return parseArrayRaw(*this, values, max_size); }
423
424 bool getValues(int* values, int max_size) const override { return parseArrayRaw(*this, values, max_size); }
425
426 int count = 0;
429 Property* next = nullptr;
430};
431
432
434{
435 IElement* getFirstChild() const override { return child; }
436 IElement* getSibling() const override { return sibling; }
437 DataView getID() const override { return id; }
440 {
442 for (int i = 0; i < idx; ++i)
443 {
444 if (prop == nullptr) return nullptr;
445 prop = prop->getNext();
446 }
447 return prop;
448 }
449
451 Element* child = nullptr;
452 Element* sibling = nullptr;
454};
455
456
457static const Element* findChild(const Element& element, const char* id)
458{
459 Element* const* iter = &element.child;
460 while (*iter)
461 {
462 if ((*iter)->id == id) return *iter;
463 iter = &(*iter)->sibling;
464 }
465 return nullptr;
466}
467
468
469static IElement* resolveProperty(const Object& obj, const char* name)
470{
471 const Element* props = findChild((const Element&)obj.element, "Properties70");
472 if (!props) return nullptr;
473
474 Element* prop = props->child;
475 while (prop)
476 {
477 if (prop->first_property && prop->first_property->value == name)
478 {
479 return prop;
480 }
481 prop = prop->sibling;
482 }
483 return nullptr;
484}
485
486
487static int resolveEnumProperty(const Object& object, const char* name, int default_value)
488{
489 Element* element = (Element*)resolveProperty(object, name);
490 if (!element) return default_value;
491 Property* x = (Property*)element->getProperty(4);
492 if (!x) return default_value;
493
494 return x->value.toInt();
495}
496
497
498static Vec3 resolveVec3Property(const Object& object, const char* name, const Vec3& default_value)
499{
500 Element* element = (Element*)resolveProperty(object, name);
501 if (!element) return default_value;
502 Property* x = (Property*)element->getProperty(4);
503 if (!x || !x->next || !x->next->next) return default_value;
504
505 return {x->value.toDouble(), x->next->value.toDouble(), x->next->next->value.toDouble()};
506}
507
508
509Object::Object(const Scene& _scene, const IElement& _element)
510 : scene(_scene)
511 , element(_element)
512 , is_node(false)
513 , node_attribute(nullptr)
514{
515 auto& e = (Element&)_element;
516 if (e.first_property && e.first_property->next)
517 {
518 e.first_property->next->value.toString(name);
519 }
520 else
521 {
522 name[0] = '\0';
523 }
524}
525
526
527static bool decompress(const u8* in, size_t in_size, u8* out, size_t out_size)
528{
529 mz_stream stream = {};
530 mz_inflateInit(&stream);
531
532 stream.avail_in = (int)in_size;
533 stream.next_in = in;
534 stream.avail_out = (int)out_size;
535 stream.next_out = out;
536
537 int status = mz_inflate(&stream, Z_SYNC_FLUSH);
538
539 if (status != Z_STREAM_END) return false;
540
541 return mz_inflateEnd(&stream) == Z_OK;
542}
543
544
545template <typename T> static OptionalError<T> read(Cursor* cursor)
546{
547 if (cursor->current + sizeof(T) > cursor->end) return Error("Reading past the end");
548 T value = *(const T*)cursor->current;
549 cursor->current += sizeof(T);
550 return value;
551}
552
553
555{
556 DataView value;
557 OptionalError<u8> length = read<u8>(cursor);
558 if (length.isError()) return Error();
559
560 if (cursor->current + length.getValue() > cursor->end) return Error("Reading past the end");
561 value.begin = cursor->current;
562 cursor->current += length.getValue();
563
564 value.end = cursor->current;
565
566 return value;
567}
568
569
571{
572 DataView value;
573 OptionalError<u32> length = read<u32>(cursor);
574 if (length.isError()) return Error();
575
576 if (cursor->current + length.getValue() > cursor->end) return Error("Reading past the end");
577 value.begin = cursor->current;
578 cursor->current += length.getValue();
579
580 value.end = cursor->current;
581
582 return value;
583}
584
585
587{
588 if (cursor->current == cursor->end) return Error("Reading past the end");
589
590 Property* prop = allocator.allocate<Property>();
591 prop->next = nullptr;
592 prop->type = *cursor->current;
593 ++cursor->current;
594 prop->value.begin = cursor->current;
595
596 switch (prop->type)
597 {
598 case 'S':
599 {
601 if (val.isError()) return Error();
602 prop->value = val.getValue();
603 break;
604 }
605 case 'Y': cursor->current += 2; break;
606 case 'C': cursor->current += 1; break;
607 case 'I': cursor->current += 4; break;
608 case 'F': cursor->current += 4; break;
609 case 'D': cursor->current += 8; break;
610 case 'L': cursor->current += 8; break;
611 case 'R':
612 {
613 OptionalError<u32> len = read<u32>(cursor);
614 if (len.isError()) return Error();
615 if (cursor->current + len.getValue() > cursor->end) return Error("Reading past the end");
616 cursor->current += len.getValue();
617 break;
618 }
619 case 'b':
620 case 'f':
621 case 'd':
622 case 'l':
623 case 'i':
624 {
625 OptionalError<u32> length = read<u32>(cursor);
626 OptionalError<u32> encoding = read<u32>(cursor);
627 OptionalError<u32> comp_len = read<u32>(cursor);
628 if (length.isError() || encoding.isError() || comp_len.isError()) return Error();
629 if (cursor->current + comp_len.getValue() > cursor->end) return Error("Reading past the end");
630 cursor->current += comp_len.getValue();
631 break;
632 }
633 default: return Error("Unknown property type");
634 }
635 prop->value.end = cursor->current;
636 return prop;
637}
638
639
641{
642 if (version >= 7500)
643 {
644 OptionalError<u64> tmp = read<u64>(cursor);
645 if (tmp.isError()) return Error();
646 return tmp.getValue();
647 }
648
649 OptionalError<u32> tmp = read<u32>(cursor);
650 if (tmp.isError()) return Error();
651 return tmp.getValue();
652}
653
654
655static OptionalError<Element*> readElement(Cursor* cursor, u32 version, Allocator& allocator)
656{
657 OptionalError<u64> end_offset = readElementOffset(cursor, version);
658 if (end_offset.isError()) return Error();
659 if (end_offset.getValue() == 0) return nullptr;
660
661 OptionalError<u64> prop_count = readElementOffset(cursor, version);
662 OptionalError<u64> prop_length = readElementOffset(cursor, version);
663 if (prop_count.isError() || prop_length.isError()) return Error();
664
666 if (id.isError()) return Error();
667
668 Element* element = allocator.allocate<Element>();
669 element->first_property = nullptr;
670 element->id = id.getValue();
671
672 element->child = nullptr;
673 element->sibling = nullptr;
674
675 Property** prop_link = &element->first_property;
676 for (u32 i = 0; i < prop_count.getValue(); ++i)
677 {
678 OptionalError<Property*> prop = readProperty(cursor, allocator);
679 if (prop.isError())
680 {
681 return Error();
682 }
683
684 *prop_link = prop.getValue();
685 prop_link = &(*prop_link)->next;
686 }
687
688 if (cursor->current - cursor->begin >= (ptrdiff_t)end_offset.getValue()) return element;
689
690 int BLOCK_SENTINEL_LENGTH = version >= 7500 ? 25 : 13;
691
692 Element** link = &element->child;
693 while (cursor->current - cursor->begin < ((ptrdiff_t)end_offset.getValue() - BLOCK_SENTINEL_LENGTH))
694 {
695 OptionalError<Element*> child = readElement(cursor, version, allocator);
696 if (child.isError())
697 {
698 return Error();
699 }
700
701 *link = child.getValue();
702 if (child.getValue() == 0) break;
703 link = &(*link)->sibling;
704 }
705
706 if (cursor->current + BLOCK_SENTINEL_LENGTH > cursor->end)
707 {
708 return Error("Reading past the end");
709 }
710
711 cursor->current += BLOCK_SENTINEL_LENGTH;
712 return element;
713}
714
715
716static bool isEndLine(const Cursor& cursor)
717{
718 return *cursor.current == '\n' || *cursor.current == '\r' && cursor.current + 1 < cursor.end && *(cursor.current + 1) != '\n';
719}
720
721
723{
724 while (cursor->current < cursor->end && isspace(*cursor->current) && !isEndLine(*cursor))
725 {
726 ++cursor->current;
727 }
728}
729
730
731static void skipLine(Cursor* cursor)
732{
733 while (cursor->current < cursor->end && !isEndLine(*cursor))
734 {
735 ++cursor->current;
736 }
737 if (cursor->current < cursor->end) ++cursor->current;
739}
740
741
742static void skipWhitespaces(Cursor* cursor)
743{
744 while (cursor->current < cursor->end && isspace(*cursor->current))
745 {
746 ++cursor->current;
747 }
748 while (cursor->current < cursor->end && *cursor->current == ';') skipLine(cursor);
749}
750
751
752static bool isTextTokenChar(char c)
753{
754 return isalnum(c) || c == '_' || c == '-';
755}
756
757
759{
760 DataView ret;
761 ret.begin = cursor->current;
762 while (cursor->current < cursor->end && isTextTokenChar(*cursor->current))
763 {
764 ++cursor->current;
765 }
766 ret.end = cursor->current;
767 return ret;
768}
769
770
772{
773 Property* prop = allocator.allocate<Property>();
774 prop->value.is_binary = false;
775 prop->next = nullptr;
776 if (*cursor->current == '"')
777 {
778 prop->type = 'S';
779 ++cursor->current;
780 prop->value.begin = cursor->current;
781 while (cursor->current < cursor->end && *cursor->current != '"')
782 {
783 ++cursor->current;
784 }
785 prop->value.end = cursor->current;
786 if (cursor->current < cursor->end) ++cursor->current; // skip '"'
787 return prop;
788 }
789
790 if (isdigit(*cursor->current) || *cursor->current == '-')
791 {
792 prop->type = 'L';
793 prop->value.begin = cursor->current;
794 if (*cursor->current == '-') ++cursor->current;
795 while (cursor->current < cursor->end && isdigit(*cursor->current))
796 {
797 ++cursor->current;
798 }
799 prop->value.end = cursor->current;
800
801 if (cursor->current < cursor->end && *cursor->current == '.')
802 {
803 prop->type = 'D';
804 ++cursor->current;
805 while (cursor->current < cursor->end && isdigit(*cursor->current))
806 {
807 ++cursor->current;
808 }
809 if (cursor->current < cursor->end && (*cursor->current == 'e' || *cursor->current == 'E'))
810 {
811 // 10.5e-013
812 ++cursor->current;
813 if (cursor->current < cursor->end && *cursor->current == '-') ++cursor->current;
814 while (cursor->current < cursor->end && isdigit(*cursor->current)) ++cursor->current;
815 }
816
817
818 prop->value.end = cursor->current;
819 }
820 return prop;
821 }
822
823 if (*cursor->current == 'T' || *cursor->current == 'Y' || *cursor->current == 'W' || *cursor->current == 'C')
824 {
825 // WTF is this
826 prop->type = *cursor->current;
827 prop->value.begin = cursor->current;
828 ++cursor->current;
829 prop->value.end = cursor->current;
830 return prop;
831 }
832
833 if (*cursor->current == '*')
834 {
835 prop->type = 'l';
836 ++cursor->current;
837 // Vertices: *10740 { a: 14.2760353088379,... }
838 while (cursor->current < cursor->end && *cursor->current != ':')
839 {
840 ++cursor->current;
841 }
842 if (cursor->current < cursor->end) ++cursor->current; // skip ':'
844 prop->value.begin = cursor->current;
845 prop->count = 0;
846 bool is_any = false;
847 while (cursor->current < cursor->end && *cursor->current != '}')
848 {
849 if (*cursor->current == ',')
850 {
851 if (is_any) ++prop->count;
852 is_any = false;
853 }
854 else if (!isspace(*cursor->current) && !isEndLine(*cursor))
855 is_any = true;
856 if (*cursor->current == '.') prop->type = 'd';
857 ++cursor->current;
858 }
859 if (is_any) ++prop->count;
860 prop->value.end = cursor->current;
861 if (cursor->current < cursor->end) ++cursor->current; // skip '}'
862 return prop;
863 }
864
865 assert(false);
866 return Error("TODO");
867}
868
869
871{
872 DataView id = readTextToken(cursor);
873 if (cursor->current == cursor->end) return Error("Unexpected end of file");
874 if (*cursor->current != ':') return Error("Unexpected character");
875 ++cursor->current;
876
878 if (cursor->current == cursor->end) return Error("Unexpected end of file");
879
880 Element* element = allocator.allocate<Element>();
881 element->id = id;
882
883 Property** prop_link = &element->first_property;
884 while (cursor->current < cursor->end && !isEndLine(*cursor) && *cursor->current != '{')
885 {
886 OptionalError<Property*> prop = readTextProperty(cursor, allocator);
887 if (prop.isError())
888 {
889 return Error();
890 }
891 if (cursor->current < cursor->end && *cursor->current == ',')
892 {
893 ++cursor->current;
894 skipWhitespaces(cursor);
895 }
897
898 *prop_link = prop.getValue();
899 prop_link = &(*prop_link)->next;
900 }
901
902 Element** link = &element->child;
903 if (*cursor->current == '{')
904 {
905 ++cursor->current;
906 skipWhitespaces(cursor);
907 while (cursor->current < cursor->end && *cursor->current != '}')
908 {
909 OptionalError<Element*> child = readTextElement(cursor, allocator);
910 if (child.isError())
911 {
912 return Error();
913 }
914 skipWhitespaces(cursor);
915
916 *link = child.getValue();
917 link = &(*link)->sibling;
918 }
919 if (cursor->current < cursor->end) ++cursor->current; // skip '}'
920 }
921 return element;
922}
923
924
925static OptionalError<Element*> tokenizeText(const u8* data, size_t size, Allocator& allocator)
926{
927 Cursor cursor;
928 cursor.begin = data;
929 cursor.current = data;
930 cursor.end = data + size;
931
932 Element* root = allocator.allocate<Element>();
933 root->first_property = nullptr;
934 root->id.begin = nullptr;
935 root->id.end = nullptr;
936 root->child = nullptr;
937 root->sibling = nullptr;
938
939 Element** element = &root->child;
940 while (cursor.current < cursor.end)
941 {
942 if (*cursor.current == ';' || *cursor.current == '\r' || *cursor.current == '\n')
943 {
944 skipLine(&cursor);
945 }
946 else
947 {
948 OptionalError<Element*> child = readTextElement(&cursor, allocator);
949 if (child.isError())
950 {
951 return Error();
952 }
953 *element = child.getValue();
954 if (!*element) return root;
955 element = &(*element)->sibling;
956 }
957 }
958
959 return root;
960}
961
962
963static OptionalError<Element*> tokenize(const u8* data, size_t size, u32& version, Allocator& allocator)
964{
965 Cursor cursor;
966 cursor.begin = data;
967 cursor.current = data;
968 cursor.end = data + size;
969
970 const Header* header = (const Header*)cursor.current;
971 cursor.current += sizeof(*header);
972 version = header->version;
973
974 Element* root = allocator.allocate<Element>();
975 root->first_property = nullptr;
976 root->id.begin = nullptr;
977 root->id.end = nullptr;
978 root->child = nullptr;
979 root->sibling = nullptr;
980
981 Element** element = &root->child;
982 for (;;)
983 {
984 OptionalError<Element*> child = readElement(&cursor, header->version, allocator);
985 if (child.isError()) {
986 return Error();
987 }
988 *element = child.getValue();
989 if (!*element) return root;
990 element = &(*element)->sibling;
991 }
992}
993
994
995static void parseTemplates(const Element& root)
996{
997 const Element* defs = findChild(root, "Definitions");
998 if (!defs) return;
999
1000 std::unordered_map<std::string, Element*> templates;
1001 Element* def = defs->child;
1002 while (def)
1003 {
1004 if (def->id == "ObjectType")
1005 {
1006 Element* subdef = def->child;
1007 while (subdef)
1008 {
1009 if (subdef->id == "PropertyTemplate")
1010 {
1011 DataView prop1 = def->first_property->value;
1012 DataView prop2 = subdef->first_property->value;
1013 std::string key((const char*)prop1.begin, prop1.end - prop1.begin);
1014 key += std::string((const char*)prop1.begin, prop1.end - prop1.begin);
1015 templates[key] = subdef;
1016 }
1017 subdef = subdef->sibling;
1018 }
1019 }
1020 def = def->sibling;
1021 }
1022 // TODO
1023}
1024
1025
1026struct Scene;
1027
1028
1029Mesh::Mesh(const Scene& _scene, const IElement& _element)
1030 : Object(_scene, _element)
1031{
1032}
1033
1034
1036{
1037 MeshImpl(const Scene& _scene, const IElement& _element)
1038 : Mesh(_scene, _element)
1039 {
1040 is_node = true;
1041 }
1042
1043
1045 {
1046 Vec3 translation = resolveVec3Property(*this, "GeometricTranslation", {0, 0, 0});
1047 Vec3 rotation = resolveVec3Property(*this, "GeometricRotation", {0, 0, 0});
1048 Vec3 scale = resolveVec3Property(*this, "GeometricScaling", {1, 1, 1});
1049
1050 Matrix scale_mtx = makeIdentity();
1051 scale_mtx.m[0] = (float)scale.x;
1052 scale_mtx.m[5] = (float)scale.y;
1053 scale_mtx.m[10] = (float)scale.z;
1055 setTranslation(translation, &mtx);
1056
1057 return scale_mtx * mtx;
1058 }
1059
1060
1061 Type getType() const override { return Type::MESH; }
1062
1063
1064 const Pose* getPose() const override { return pose; }
1065 const Geometry* getGeometry() const override { return geometry; }
1066 const Material* getMaterial(int index) const override { return materials[index]; }
1067 int getMaterialCount() const override { return (int)materials.size(); }
1068
1069
1070 const Pose* pose = nullptr;
1071 const Geometry* geometry = nullptr;
1072 std::vector<const Material*> materials;
1073};
1074
1075
1076Material::Material(const Scene& _scene, const IElement& _element)
1077 : Object(_scene, _element)
1078{
1079}
1080
1081
1083{
1084 MaterialImpl(const Scene& _scene, const IElement& _element)
1085 : Material(_scene, _element)
1086 {
1087 for (const Texture*& tex : textures) tex = nullptr;
1088 }
1089
1090 Type getType() const override { return Type::MATERIAL; }
1091
1092 const Texture* getTexture(Texture::TextureType type) const override { return textures[type]; }
1093 Color getDiffuseColor() const override { return diffuse_color; }
1094 Color getSpecularColor() const override { return specular_color; }
1095 Color getReflectionColor() const override { return reflection_color; };
1096 Color getAmbientColor() const override { return ambient_color; };
1097 Color getEmissiveColor() const override { return emissive_color; };
1098
1099 double getDiffuseFactor() const override { return diffuse_factor; };
1100 double getSpecularFactor() const override { return specular_factor; };
1101 double getReflectionFactor() const override { return reflection_factor; };
1102 double getShininess() const override { return shininess; };
1103 double getShininessExponent() const override { return shininess_exponent; };
1104 double getAmbientFactor() const override { return ambient_factor; };
1105 double getBumpFactor() const override { return bump_factor; };
1106 double getEmissiveFactor() const override { return emissive_factor; };
1107
1108 const Texture* textures[Texture::TextureType::COUNT];
1114
1123 };
1124
1125
1127{
1128 LimbNodeImpl(const Scene& _scene, const IElement& _element)
1129 : Object(_scene, _element)
1130 {
1131 is_node = true;
1132 }
1133 Type getType() const override { return Type::LIMB_NODE; }
1134};
1135
1136
1138{
1139 NullImpl(const Scene& _scene, const IElement& _element)
1140 : Object(_scene, _element)
1141 {
1142 is_node = true;
1143 }
1144 Type getType() const override { return Type::NULL_NODE; }
1145};
1146
1147
1148NodeAttribute::NodeAttribute(const Scene& _scene, const IElement& _element)
1149 : Object(_scene, _element)
1150{
1151}
1152
1153
1155{
1156 NodeAttributeImpl(const Scene& _scene, const IElement& _element)
1157 : NodeAttribute(_scene, _element)
1158 {
1159 }
1160 Type getType() const override { return Type::NODE_ATTRIBUTE; }
1161 DataView getAttributeType() const override { return attribute_type; }
1162
1163
1165};
1166
1167
1168Geometry::Geometry(const Scene& _scene, const IElement& _element)
1169 : Object(_scene, _element)
1170{
1171}
1172
1173
1175{
1177 {
1180 BY_VERTEX
1182
1184 {
1185 ~NewVertex() { delete next; }
1186
1187 int index = -1;
1188 NewVertex* next = nullptr;
1189 };
1190
1191 std::vector<Vec3> vertices;
1192 std::vector<Vec3> normals;
1193 std::vector<Vec2> uvs[s_uvs_max];
1194 std::vector<Vec4> colors;
1195 std::vector<Vec3> tangents;
1196 std::vector<int> materials;
1197
1198 const Skin* skin = nullptr;
1199 const BlendShape* blendShape = nullptr;
1200
1201 std::vector<int> indices;
1202 std::vector<int> to_old_vertices;
1203 std::vector<NewVertex> to_new_vertices;
1204
1205 GeometryImpl(const Scene& _scene, const IElement& _element)
1206 : Geometry(_scene, _element)
1207 {
1208 }
1209
1210
1211 Type getType() const override { return Type::GEOMETRY; }
1212 int getVertexCount() const override { return (int)vertices.size(); }
1213 const int* getFaceIndices() const override { return indices.empty() ? nullptr : &indices[0]; }
1214 int getIndexCount() const override { return (int)indices.size(); }
1215 const Vec3* getVertices() const override { return &vertices[0]; }
1216 const Vec3* getNormals() const override { return normals.empty() ? nullptr : &normals[0]; }
1217 const Vec2* getUVs(int index = 0) const override { return index < 0 || index >= s_uvs_max || uvs[index].empty() ? nullptr : &uvs[index][0]; }
1218 const Vec4* getColors() const override { return colors.empty() ? nullptr : &colors[0]; }
1219 const Vec3* getTangents() const override { return tangents.empty() ? nullptr : &tangents[0]; }
1220 const Skin* getSkin() const override { return skin; }
1221 const BlendShape* getBlendShape() const override { return blendShape; }
1222 const int* getMaterials() const override { return materials.empty() ? nullptr : &materials[0]; }
1223};
1224
1225
1226Shape::Shape(const Scene& _scene, const IElement& _element)
1227 : Object(_scene, _element)
1228{
1229}
1230
1231
1233{
1234 std::vector<Vec3> vertices;
1235 std::vector<Vec3> normals;
1236
1237 ShapeImpl(const Scene& _scene, const IElement& _element)
1238 : Shape(_scene, _element)
1239 {
1240 }
1241
1242
1243 bool postprocess(GeometryImpl* geom, Allocator& allocator);
1244
1245
1246 Type getType() const override { return Type::SHAPE; }
1247 int getVertexCount() const override { return (int)vertices.size(); }
1248 const Vec3* getVertices() const override { return &vertices[0]; }
1249 const Vec3* getNormals() const override { return normals.empty() ? nullptr : &normals[0]; }
1250};
1251
1252
1253Cluster::Cluster(const Scene& _scene, const IElement& _element)
1254 : Object(_scene, _element)
1255{
1256}
1257
1258
1260{
1261 ClusterImpl(const Scene& _scene, const IElement& _element)
1262 : Cluster(_scene, _element)
1263 {
1264 }
1265
1266 const int* getIndices() const override { return &indices[0]; }
1267 int getIndicesCount() const override { return (int)indices.size(); }
1268 const double* getWeights() const override { return &weights[0]; }
1269 int getWeightsCount() const override { return (int)weights.size(); }
1270 Matrix getTransformMatrix() const override { return transform_matrix; }
1272 Object* getLink() const override { return link; }
1273
1274
1275 bool postprocess(Allocator& allocator)
1276 {
1277 assert(skin);
1278
1280 if (!geom) return false;
1281
1282 allocator.int_tmp.clear(); // old indices
1283 const Element* indexes = findChild((const Element&)element, "Indexes");
1284 if (indexes && indexes->first_property)
1285 {
1286 if (!parseBinaryArray(*indexes->first_property, &allocator.int_tmp)) return false;
1287 }
1288
1289 allocator.double_tmp.clear(); // old weights
1290 const Element* weights_el = findChild((const Element&)element, "Weights");
1291 if (weights_el && weights_el->first_property)
1292 {
1293 if (!parseBinaryArray(*weights_el->first_property, &allocator.double_tmp)) return false;
1294 }
1295
1296 if (allocator.int_tmp.size() != allocator.double_tmp.size()) return false;
1297
1298 indices.reserve(allocator.int_tmp.size());
1299 weights.reserve(allocator.int_tmp.size());
1300 int* ir = allocator.int_tmp.empty() ? nullptr : &allocator.int_tmp[0];
1301 double* wr = allocator.double_tmp.empty() ? nullptr : &allocator.double_tmp[0];
1302 for (int i = 0, c = (int)allocator.int_tmp.size(); i < c; ++i)
1303 {
1304 int old_idx = ir[i];
1305 double w = wr[i];
1306 GeometryImpl::NewVertex* n = &geom->to_new_vertices[old_idx];
1307 if (n->index == -1) continue; // skip vertices which aren't indexed.
1308 while (n)
1309 {
1310 indices.push_back(n->index);
1311 weights.push_back(w);
1312 n = n->next;
1313 }
1314 }
1315
1316 return true;
1317 }
1318
1319
1320 Object* link = nullptr;
1321 Skin* skin = nullptr;
1322 std::vector<int> indices;
1323 std::vector<double> weights;
1326 Type getType() const override { return Type::CLUSTER; }
1327};
1328
1329
1330AnimationStack::AnimationStack(const Scene& _scene, const IElement& _element)
1331 : Object(_scene, _element)
1332{
1333}
1334
1335
1336AnimationLayer::AnimationLayer(const Scene& _scene, const IElement& _element)
1337 : Object(_scene, _element)
1338{
1339}
1340
1341
1342AnimationCurve::AnimationCurve(const Scene& _scene, const IElement& _element)
1343 : Object(_scene, _element)
1344{
1345}
1346
1347
1349 : Object(_scene, _element)
1350{
1351}
1352
1353
1355{
1356 AnimationStackImpl(const Scene& _scene, const IElement& _element)
1357 : AnimationStack(_scene, _element)
1358 {
1359 }
1360
1361
1362 const AnimationLayer* getLayer(int index) const override
1363 {
1364 return resolveObjectLink<AnimationLayer>(index);
1365 }
1366
1367
1368 Type getType() const override { return Type::ANIMATION_STACK; }
1369};
1370
1371
1373{
1374 AnimationCurveImpl(const Scene& _scene, const IElement& _element)
1375 : AnimationCurve(_scene, _element)
1376 {
1377 }
1378
1379 int getKeyCount() const override { return (int)times.size(); }
1380 const i64* getKeyTime() const override { return &times[0]; }
1381 const float* getKeyValue() const override { return &values[0]; }
1382
1383 std::vector<i64> times;
1384 std::vector<float> values;
1385 Type getType() const override { return Type::ANIMATION_CURVE; }
1386};
1387
1388
1389Skin::Skin(const Scene& _scene, const IElement& _element)
1390 : Object(_scene, _element)
1391{
1392}
1393
1394
1396{
1397 SkinImpl(const Scene& _scene, const IElement& _element)
1398 : Skin(_scene, _element)
1399 {
1400 }
1401
1402 int getClusterCount() const override { return (int)clusters.size(); }
1403 const Cluster* getCluster(int idx) const override { return clusters[idx]; }
1404
1405 Type getType() const override { return Type::SKIN; }
1406
1407 std::vector<Cluster*> clusters;
1408};
1409
1410
1412 : Object(_scene, _element)
1413{
1414}
1415
1416
1418{
1419 BlendShapeChannelImpl(const Scene& _scene, const IElement& _element)
1420 : BlendShapeChannel(_scene, _element)
1421 {
1422 }
1423
1424 double getDeformPercent() const override { return deformPercent; }
1425 int getShapeCount() const override { return (int)shapes.size(); }
1426 const Shape* getShape(int idx) const override { return shapes[idx]; }
1427
1428 Type getType() const override { return Type::BLEND_SHAPE_CHANNEL; }
1429
1430 bool postprocess(Allocator& allocator)
1431 {
1433
1435 if (!geom) return false;
1436
1437 const Element* deform_percent_el = findChild((const Element&)element, "DeformPercent");
1438 if (deform_percent_el && deform_percent_el->first_property)
1439 {
1440 if (!parseDouble(*deform_percent_el->first_property, &deformPercent)) return false;
1441 }
1442
1443 const Element* full_weights_el = findChild((const Element&)element, "FullWeights");
1444 if (full_weights_el && full_weights_el->first_property)
1445 {
1446 if (!parseBinaryArray(*full_weights_el->first_property, &fullWeights)) return false;
1447 }
1448
1449 for (int i = 0; i < (int)shapes.size(); i++)
1450 {
1451 auto shape = (ShapeImpl*)shapes[i];
1452 if (!shape->postprocess(geom, allocator)) return false;
1453 }
1454
1455 return true;
1456 }
1457
1458
1460 double deformPercent = 0;
1461 std::vector<double> fullWeights;
1462 std::vector<Shape*> shapes;
1463};
1464
1465
1466BlendShape::BlendShape(const Scene& _scene, const IElement& _element)
1467 : Object(_scene, _element)
1468{
1469}
1470
1471
1473{
1474 BlendShapeImpl(const Scene& _scene, const IElement& _element)
1475 : BlendShape(_scene, _element)
1476 {
1477 }
1478
1479 int getBlendShapeChannelCount() const override { return (int)blendShapeChannels.size(); }
1480 const BlendShapeChannel* getBlendShapeChannel(int idx) const override { return blendShapeChannels[idx]; }
1481
1482 Type getType() const override { return Type::BLEND_SHAPE; }
1483
1484 std::vector<BlendShapeChannel*> blendShapeChannels;
1485};
1486
1487
1488Texture::Texture(const Scene& _scene, const IElement& _element)
1489 : Object(_scene, _element)
1490{
1491}
1492
1493
1494Pose::Pose(const Scene& _scene, const IElement& _element)
1495 : Object(_scene, _element)
1496{
1497}
1498
1499
1501{
1502 PoseImpl(const Scene& _scene, const IElement& _element)
1503 : Pose(_scene, _element)
1504 {
1505 }
1506
1507 bool postprocess(Scene* scene);
1508
1509
1510 Matrix getMatrix() const override { return matrix; }
1511 const Object* getNode() const override { return node; }
1512
1513 Type getType() const override { return Type::POSE; }
1514
1516 Object* node = nullptr;
1518};
1519
1520
1522{
1523 TextureImpl(const Scene& _scene, const IElement& _element)
1524 : Texture(_scene, _element)
1525 {
1526 }
1527
1529 DataView getFileName() const override { return filename; }
1530 DataView getEmbeddedData() const override;
1531
1535 Type getType() const override { return Type::TEXTURE; }
1536};
1537
1538
1539struct Root : Object
1540{
1541 Root(const Scene& _scene, const IElement& _element)
1542 : Object(_scene, _element)
1543 {
1544 copyString(name, "RootNode");
1545 is_node = true;
1546 }
1547 Type getType() const override { return Type::ROOT; }
1548};
1549
1550
1552{
1554 {
1555 enum Type
1556 {
1560
1563 u64 to = 0;
1565 };
1566
1568 {
1571 };
1572
1573
1574 int getAnimationStackCount() const override { return (int)m_animation_stacks.size(); }
1575 int getGeometryCount() const override { return (int)m_geometries.size(); }
1576 int getMeshCount() const override { return (int)m_meshes.size(); }
1577 float getSceneFrameRate() const override { return m_scene_frame_rate; }
1578 const GlobalSettings* getGlobalSettings() const override { return &m_settings; }
1579
1580 const Object* const* getAllObjects() const override { return m_all_objects.empty() ? nullptr : &m_all_objects[0]; }
1581
1582
1583 int getAllObjectCount() const override { return (int)m_all_objects.size(); }
1584
1585 int getEmbeddedDataCount() const override {
1586 return (int)m_videos.size();
1587 }
1588
1589 DataView getEmbeddedData(int index) const override {
1590 return m_videos[index].content;
1591 }
1592
1593 DataView getEmbeddedFilename(int index) const override {
1594 return m_videos[index].filename;
1595 }
1596
1597 const AnimationStack* getAnimationStack(int index) const override
1598 {
1599 assert(index >= 0);
1600 assert(index < m_animation_stacks.size());
1601 return m_animation_stacks[index];
1602 }
1603
1604
1605 const Mesh* getMesh(int index) const override
1606 {
1607 assert(index >= 0);
1608 assert(index < m_meshes.size());
1609 return m_meshes[index];
1610 }
1611
1612
1613 const Geometry* getGeometry(int index) const override
1614 {
1615 assert(index >= 0);
1616 assert(index < m_geometries.size());
1617 return m_geometries[index];
1618 }
1619
1620
1621 const TakeInfo* getTakeInfo(const char* name) const override
1622 {
1623 for (const TakeInfo& info : m_take_infos)
1624 {
1625 if (info.name == name) return &info;
1626 }
1627 return nullptr;
1628 }
1629
1630
1631 const IElement* getRootElement() const override { return m_root_element; }
1632 const Object* getRoot() const override { return m_root; }
1633
1634
1635 void destroy() override { delete this; }
1636
1637
1638 ~Scene() override {
1639 for(auto ptr : m_all_objects)
1640 ptr->~Object();
1641 }
1642
1643
1645 Root* m_root = nullptr;
1648 std::unordered_map<u64, ObjectPair> m_object_map;
1649 std::vector<Object*> m_all_objects;
1650 std::vector<Mesh*> m_meshes;
1651 std::vector<Geometry*> m_geometries;
1652 std::vector<AnimationStack*> m_animation_stacks;
1653 std::vector<Connection> m_connections;
1654 std::vector<u8> m_data;
1655 std::vector<TakeInfo> m_take_infos;
1656 std::vector<Video> m_videos;
1658};
1659
1660
1662 if (!media.begin) return media;
1663 for (const Video& v : scene.m_videos) {
1664 if (v.media.end - v.media.begin != media.end - media.begin) continue;
1665 const size_t len = v.media.end - v.media.begin;
1666 if (memcmp(v.media.begin, media.begin, len) != 0) continue;
1667
1668 return v.content;
1669 }
1670 return {};
1671}
1672
1673
1675{
1676 node = scene->m_object_map[node_id.toU64()].object;
1677 if (node && node->getType() == Object::Type::MESH) {
1678 static_cast<MeshImpl*>(node)->pose = this;
1679 }
1680 return true;
1681}
1682
1683
1685{
1686 AnimationCurveNodeImpl(const Scene& _scene, const IElement& _element)
1687 : AnimationCurveNode(_scene, _element)
1688 {
1690 Element* dx = static_cast<Element*>(resolveProperty(*this, "d|X"));
1691 Element* dy = static_cast<Element*>(resolveProperty(*this, "d|Y"));
1692 Element* dz = static_cast<Element*>(resolveProperty(*this, "d|Z"));
1693
1694 if (dx) {
1695 Property* x = (Property*)dx->getProperty(4);
1696 if (x) default_values[0] = (float)x->value.toDouble();
1697 }
1698 if (dy) {
1699 Property* y = (Property*)dy->getProperty(4);
1700 if (y) default_values[1] = (float)y->value.toDouble();
1701 }
1702 if (dz) {
1703 Property* z = (Property*)dz->getProperty(4);
1704 if (z) default_values[2] = (float)z->value.toDouble();
1705 }
1706 }
1707
1708
1709 const Object* getBone() const override
1710 {
1711 return bone;
1712 }
1713
1714 float getAnimationDX() const
1715 {
1716 return default_values[0];
1717 }
1718 float getAnimationDY() const
1719 {
1720 return default_values[1];
1721 }
1722 float getAnimationDZ() const
1723 {
1724 return default_values[2];
1725 }
1726
1727 const AnimationCurve* getCurve(int idx) const override {
1728 assert(idx >= 0 && idx < 3);
1729 return curves[idx].curve;
1730 }
1731
1732
1733 Vec3 getNodeLocalTransform(double time) const override
1734 {
1735 i64 fbx_time = secondsToFbxTime(time);
1736
1737 auto getCoord = [&](const Curve& curve, i64 fbx_time, int idx) {
1738 if (!curve.curve) return default_values[idx];
1739
1740 const i64* times = curve.curve->getKeyTime();
1741 const float* values = curve.curve->getKeyValue();
1742 int count = curve.curve->getKeyCount();
1743
1744 if (fbx_time < times[0]) fbx_time = times[0];
1745 if (fbx_time > times[count - 1]) fbx_time = times[count - 1];
1746 for (int i = 1; i < count; ++i)
1747 {
1748 if (times[i] >= fbx_time)
1749 {
1750 float t = float(double(fbx_time - times[i - 1]) / double(times[i] - times[i - 1]));
1751 return values[i - 1] * (1 - t) + values[i] * t;
1752 }
1753 }
1754 return values[0];
1755 };
1756
1757 return {getCoord(curves[0], fbx_time, 0), getCoord(curves[1], fbx_time, 1), getCoord(curves[2], fbx_time, 2)};
1758 }
1759
1760
1761 struct Curve
1762 {
1763 const AnimationCurve* curve = nullptr;
1765 };
1766
1767
1769 Object* bone = nullptr;
1771 Type getType() const override { return Type::ANIMATION_CURVE_NODE; }
1773 enum Mode
1774 {
1777 SCALE
1779};
1780
1781
1783{
1784 AnimationLayerImpl(const Scene& _scene, const IElement& _element)
1785 : AnimationLayer(_scene, _element)
1786 {
1787 }
1788
1789
1790 Type getType() const override { return Type::ANIMATION_LAYER; }
1791
1792
1793 const AnimationCurveNode* getCurveNode(int index) const override
1794 {
1795 if (index >= (int)curve_nodes.size() || index < 0) return nullptr;
1796 return curve_nodes[index];
1797 }
1798
1799
1800 const AnimationCurveNode* getCurveNode(const Object& bone, const char* prop) const override
1801 {
1802 for (const AnimationCurveNodeImpl* node : curve_nodes)
1803 {
1804 if (node->bone_link_property == prop && node->bone == &bone) return node;
1805 }
1806 return nullptr;
1807 }
1808
1809
1810 std::vector<AnimationCurveNodeImpl*> curve_nodes;
1811};
1812
1813void parseVideo(Scene& scene, const Element& element, Allocator& allocator)
1814{
1815 if (!element.first_property) return;
1816 if (!element.first_property->next) return;
1817 if (element.first_property->next->getType() != IElementProperty::STRING) return;
1818
1819 const Element* content_element = findChild(element, "Content");
1820
1821 if (!content_element) return;
1822 if (!content_element->first_property) return;
1823 if (content_element->first_property->getType() != IElementProperty::BINARY) return;
1824
1825 const Element* filename_element = findChild(element, "Filename");
1826 if (!filename_element) return;
1827 if (!filename_element->first_property) return;
1828 if (filename_element->first_property->getType() != IElementProperty::STRING) return;
1829
1830 Video video;
1831 video.content = content_element->first_property->value;
1832 video.filename = filename_element->first_property->value;
1833 video.media = element.first_property->next->value;
1834 scene.m_videos.push_back(video);
1835}
1836
1837struct OptionalError<Object*> parseTexture(const Scene& scene, const Element& element, Allocator& allocator)
1838{
1839 TextureImpl* texture = allocator.allocate<TextureImpl>(scene, element);
1840 const Element* texture_filename = findChild(element, "FileName");
1841 if (texture_filename && texture_filename->first_property)
1842 {
1843 texture->filename = texture_filename->first_property->value;
1844 }
1845
1846 const Element* media = findChild(element, "Media");
1847 if (media && media->first_property)
1848 {
1849 texture->media = media->first_property->value;
1850 }
1851
1852 const Element* texture_relative_filename = findChild(element, "RelativeFilename");
1853 if (texture_relative_filename && texture_relative_filename->first_property)
1854 {
1855 texture->relative_filename = texture_relative_filename->first_property->value;
1856 }
1857 return texture;
1858}
1859
1860
1861struct OptionalError<Object*> parsePose(const Scene& scene, const Element& element, Allocator& allocator)
1862{
1863 PoseImpl* pose = allocator.allocate<PoseImpl>(scene, element);
1864 const Element* pose_node = findChild(element, "PoseNode");
1865 if (pose_node) {
1866 const Element* node = findChild(*pose_node, "Node");
1867 const Element* matrix = findChild(*pose_node, "Matrix");
1868
1869 if (matrix->first_property) {
1870 parseArrayRaw(*matrix->first_property, &pose->matrix, sizeof(pose->matrix));
1871 }
1872 pose->node_id = node->first_property->value;
1873 }
1874 return pose;
1875}
1876
1877
1878template <typename T>
1879static OptionalError<Object*> parse(const Scene& scene, const Element& element, Allocator& allocator)
1880{
1881 T* obj = allocator.allocate<T>(scene, element);
1882 return obj;
1883}
1884
1885
1886static OptionalError<Object*> parseCluster(const Scene& scene, const Element& element, Allocator& allocator)
1887{
1888 ClusterImpl* obj = allocator.allocate<ClusterImpl>(scene, element);
1889
1890 const Element* transform_link = findChild(element, "TransformLink");
1891 if (transform_link && transform_link->first_property)
1892 {
1893 if (!parseArrayRaw(
1894 *transform_link->first_property, &obj->transform_link_matrix, sizeof(obj->transform_link_matrix)))
1895 {
1896 return Error("Failed to parse TransformLink");
1897 }
1898 }
1899 const Element* transform = findChild(element, "Transform");
1900 if (transform && transform->first_property)
1901 {
1902 if (!parseArrayRaw(*transform->first_property, &obj->transform_matrix, sizeof(obj->transform_matrix)))
1903 {
1904 return Error("Failed to parse Transform");
1905 }
1906 }
1907
1908 return obj;
1909}
1910
1911
1912static OptionalError<Object*> parseNodeAttribute(const Scene& scene, const Element& element, Allocator& allocator)
1913{
1914 NodeAttributeImpl* obj = allocator.allocate<NodeAttributeImpl>(scene, element);
1915 const Element* type_flags = findChild(element, "TypeFlags");
1916 if (type_flags && type_flags->first_property)
1917 {
1918 obj->attribute_type = type_flags->first_property->value;
1919 }
1920 return obj;
1921}
1922
1923
1924static OptionalError<Object*> parseLimbNode(const Scene& scene, const Element& element, Allocator& allocator)
1925{
1926 if (!element.first_property
1927 || !element.first_property->next
1928 || !element.first_property->next->next
1929 || element.first_property->next->next->value != "LimbNode")
1930 {
1931 return Error("Invalid limb node");
1932 }
1933
1934 LimbNodeImpl* obj = allocator.allocate<LimbNodeImpl>(scene, element);
1935 return obj;
1936}
1937
1938
1939static OptionalError<Object*> parseMesh(const Scene& scene, const Element& element, Allocator& allocator)
1940{
1941 if (!element.first_property
1942 || !element.first_property->next
1943 || !element.first_property->next->next
1944 || element.first_property->next->next->value != "Mesh")
1945 {
1946 return Error("Invalid mesh");
1947 }
1948
1949 return allocator.allocate<MeshImpl>(scene, element);
1950}
1951
1952
1953static OptionalError<Object*> parseMaterial(const Scene& scene, const Element& element, Allocator& allocator)
1954{
1955 MaterialImpl* material = allocator.allocate<MaterialImpl>(scene, element);
1956 const Element* prop = findChild(element, "Properties70");
1957 material->diffuse_color = {1, 1, 1};
1958 if (prop) prop = prop->child;
1959 while (prop)
1960 {
1961 if (prop->id == "P" && prop->first_property)
1962 {
1963 if (prop->first_property->value == "DiffuseColor")
1964 {
1965 material->diffuse_color.r = (float)prop->getProperty(4)->getValue().toDouble();
1966 material->diffuse_color.g = (float)prop->getProperty(5)->getValue().toDouble();
1967 material->diffuse_color.b = (float)prop->getProperty(6)->getValue().toDouble();
1968 }
1969 else if (prop->first_property->value == "SpecularColor")
1970 {
1971 material->specular_color.r = (float)prop->getProperty(4)->getValue().toDouble();
1972 material->specular_color.g = (float)prop->getProperty(5)->getValue().toDouble();
1973 material->specular_color.b = (float)prop->getProperty(6)->getValue().toDouble();
1974 }
1975 else if (prop->first_property->value == "Shininess")
1976 {
1977 material->shininess = (float)prop->getProperty(4)->getValue().toDouble();
1978 }
1979 else if (prop->first_property->value == "ShininessExponent")
1980 {
1981 material->shininess_exponent = (float)prop->getProperty(4)->getValue().toDouble();
1982 }
1983 else if (prop->first_property->value == "ReflectionColor")
1984 {
1985 material->reflection_color.r = (float)prop->getProperty(4)->getValue().toDouble();
1986 material->reflection_color.g = (float)prop->getProperty(5)->getValue().toDouble();
1987 material->reflection_color.b = (float)prop->getProperty(6)->getValue().toDouble();
1988 }
1989 else if (prop->first_property->value == "AmbientColor")
1990 {
1991 material->ambient_color.r = (float)prop->getProperty(4)->getValue().toDouble();
1992 material->ambient_color.g = (float)prop->getProperty(5)->getValue().toDouble();
1993 material->ambient_color.b = (float)prop->getProperty(6)->getValue().toDouble();
1994 }
1995 else if (prop->first_property->value == "EmissiveColor")
1996 {
1997 material->emissive_color.r = (float)prop->getProperty(4)->getValue().toDouble();
1998 material->emissive_color.g = (float)prop->getProperty(5)->getValue().toDouble();
1999 material->emissive_color.b = (float)prop->getProperty(6)->getValue().toDouble();
2000 }
2001 else if (prop->first_property->value == "ReflectionFactor")
2002 {
2003 material->reflection_factor = (float)prop->getProperty(4)->getValue().toDouble();
2004 }
2005 else if (prop->first_property->value == "BumpFactor")
2006 {
2007 material->bump_factor = (float)prop->getProperty(4)->getValue().toDouble();
2008 }
2009 else if (prop->first_property->value == "AmbientFactor")
2010 {
2011 material->ambient_factor = (float)prop->getProperty(4)->getValue().toDouble();
2012 }
2013 else if (prop->first_property->value == "DiffuseFactor")
2014 {
2015 material->diffuse_factor = (float)prop->getProperty(4)->getValue().toDouble();
2016 }
2017 else if (prop->first_property->value == "SpecularFactor")
2018 {
2019 material->specular_factor = (float)prop->getProperty(4)->getValue().toDouble();
2020 }
2021 else if (prop->first_property->value == "EmissiveFactor")
2022 {
2023 material->emissive_factor = (float)prop->getProperty(4)->getValue().toDouble();
2024 }
2025 }
2026 prop = prop->sibling;
2027 }
2028 return material;
2029}
2030
2031
2032template <typename T> static bool parseTextArrayRaw(const Property& property, T* out, int max_size);
2033
2034template <typename T> static bool parseArrayRaw(const Property& property, T* out, int max_size)
2035{
2036 if (property.value.is_binary)
2037 {
2038 assert(out);
2039
2040 int elem_size = 1;
2041 switch (property.type)
2042 {
2043 case 'l': elem_size = 8; break;
2044 case 'd': elem_size = 8; break;
2045 case 'f': elem_size = 4; break;
2046 case 'i': elem_size = 4; break;
2047 default: return false;
2048 }
2049
2050 const u8* data = property.value.begin + sizeof(u32) * 3;
2051 if (data > property.value.end) return false;
2052
2053 u32 count = property.getCount();
2054 u32 enc = *(const u32*)(property.value.begin + 4);
2055 u32 len = *(const u32*)(property.value.begin + 8);
2056
2057 if (enc == 0)
2058 {
2059 if ((int)len > max_size) return false;
2060 if (data + len > property.value.end) return false;
2061 memcpy(out, data, len);
2062 return true;
2063 }
2064 else if (enc == 1)
2065 {
2066 if (int(elem_size * count) > max_size) return false;
2067 return decompress(data, len, (u8*)out, elem_size * count);
2068 }
2069
2070 return false;
2071 }
2072
2073 return parseTextArrayRaw(property, out, max_size);
2074}
2075
2076
2077template <typename T> const char* fromString(const char* str, const char* end, T* val);
2078template <> const char* fromString<int>(const char* str, const char* end, int* val)
2079{
2080 *val = atoi(str);
2081 const char* iter = str;
2082 while (iter < end && *iter != ',') ++iter;
2083 if (iter < end) ++iter; // skip ','
2084 return (const char*)iter;
2085}
2086
2087
2088template <> const char* fromString<u64>(const char* str, const char* end, u64* val)
2089{
2090 *val = strtoull(str, nullptr, 10);
2091 const char* iter = str;
2092 while (iter < end && *iter != ',') ++iter;
2093 if (iter < end) ++iter; // skip ','
2094 return (const char*)iter;
2095}
2096
2097
2098template <> const char* fromString<i64>(const char* str, const char* end, i64* val)
2099{
2100 *val = atoll(str);
2101 const char* iter = str;
2102 while (iter < end && *iter != ',') ++iter;
2103 if (iter < end) ++iter; // skip ','
2104 return (const char*)iter;
2105}
2106
2107
2108template <> const char* fromString<double>(const char* str, const char* end, double* val)
2109{
2110 *val = atof(str);
2111 const char* iter = str;
2112 while (iter < end && *iter != ',') ++iter;
2113 if (iter < end) ++iter; // skip ','
2114 return (const char*)iter;
2115}
2116
2117
2118template <> const char* fromString<float>(const char* str, const char* end, float* val)
2119{
2120 *val = (float)atof(str);
2121 const char* iter = str;
2122 while (iter < end && *iter != ',') ++iter;
2123 if (iter < end) ++iter; // skip ','
2124 return (const char*)iter;
2125}
2126
2127
2128const char* fromString(const char* str, const char* end, double* val, int count)
2129{
2130 const char* iter = str;
2131 for (int i = 0; i < count; ++i)
2132 {
2133 *val = atof(iter);
2134 ++val;
2135 while (iter < end && *iter != ',') ++iter;
2136 if (iter < end) ++iter; // skip ','
2137
2138 if (iter == end) return iter;
2139 }
2140 return (const char*)iter;
2141}
2142
2143
2144template <> const char* fromString<Vec2>(const char* str, const char* end, Vec2* val)
2145{
2146 return fromString(str, end, &val->x, 2);
2147}
2148
2149
2150template <> const char* fromString<Vec3>(const char* str, const char* end, Vec3* val)
2151{
2152 return fromString(str, end, &val->x, 3);
2153}
2154
2155
2156template <> const char* fromString<Vec4>(const char* str, const char* end, Vec4* val)
2157{
2158 return fromString(str, end, &val->x, 4);
2159}
2160
2161
2162template <> const char* fromString<Matrix>(const char* str, const char* end, Matrix* val)
2163{
2164 return fromString(str, end, &val->m[0], 16);
2165}
2166
2167
2168template <typename T> static void parseTextArray(const Property& property, std::vector<T>* out)
2169{
2170 const u8* iter = property.value.begin;
2171 while (iter < property.value.end)
2172 {
2173 T val;
2174 iter = (const u8*)fromString<T>((const char*)iter, (const char*)property.value.end, &val);
2175 out->push_back(val);
2176 }
2177}
2178
2179
2180template <typename T> static bool parseTextArrayRaw(const Property& property, T* out_raw, int max_size)
2181{
2182 const u8* iter = property.value.begin;
2183
2184 T* out = out_raw;
2185 while (iter < property.value.end)
2186 {
2187 iter = (const u8*)fromString<T>((const char*)iter, (const char*)property.value.end, out);
2188 ++out;
2189 if (out - out_raw == max_size / sizeof(T)) return true;
2190 }
2191 return out - out_raw == max_size / sizeof(T);
2192}
2193
2194
2195template <typename T> static bool parseBinaryArray(const Property& property, std::vector<T>* out)
2196{
2197 assert(out);
2198 if (property.value.is_binary)
2199 {
2200 u32 count = property.getCount();
2201 int elem_size = 1;
2202 switch (property.type)
2203 {
2204 case 'd': elem_size = 8; break;
2205 case 'f': elem_size = 4; break;
2206 case 'i': elem_size = 4; break;
2207 default: return false;
2208 }
2209 int elem_count = sizeof(T) / elem_size;
2210 out->resize(count / elem_count);
2211
2212 if (count == 0) return true;
2213 return parseArrayRaw(property, &(*out)[0], int(sizeof((*out)[0]) * out->size()));
2214 }
2215 else
2216 {
2217 parseTextArray(property, out);
2218 return true;
2219 }
2220}
2221
2222
2223template <typename T> static bool parseDoubleVecData(Property& property, std::vector<T>* out_vec, std::vector<float>* tmp)
2224{
2225 assert(out_vec);
2226 if (!property.value.is_binary)
2227 {
2228 parseTextArray(property, out_vec);
2229 return true;
2230 }
2231
2232 if (property.type == 'd')
2233 {
2234 return parseBinaryArray(property, out_vec);
2235 }
2236
2237 assert(property.type == 'f');
2238 assert(sizeof((*out_vec)[0].x) == sizeof(double));
2239 tmp->clear();
2240 if (!parseBinaryArray(property, tmp)) return false;
2241 int elem_count = sizeof((*out_vec)[0]) / sizeof((*out_vec)[0].x);
2242 out_vec->resize(tmp->size() / elem_count);
2243 double* out = &(*out_vec)[0].x;
2244 for (int i = 0, c = (int)tmp->size(); i < c; ++i)
2245 {
2246 out[i] = (*tmp)[i];
2247 }
2248 return true;
2249}
2250
2251
2252static bool parseDouble(Property& property, double* out)
2253{
2254 assert(out);
2255 if (property.value.is_binary)
2256 {
2257 int elem_size = 1;
2258 switch (property.type)
2259 {
2260 case 'D': elem_size = 8; break;
2261 case 'F': elem_size = 4; break;
2262 default: return false;
2263 }
2264 const u8* data = property.value.begin;
2265 if (data > property.value.end) return false;
2266 memcpy(out, data, elem_size);
2267 return true;
2268 }
2269 else
2270 {
2271 fromString<double>((const char*)property.value.begin, (const char*)property.value.end, out);
2272 return true;
2273 }
2274}
2275
2276
2277template <typename T>
2278static bool parseVertexData(const Element& element,
2279 const char* name,
2280 const char* index_name,
2281 std::vector<T>* out,
2282 std::vector<int>* out_indices,
2284 std::vector<float>* tmp)
2285{
2286 assert(out);
2287 assert(mapping);
2288 const Element* data_element = findChild(element, name);
2289 if (!data_element || !data_element->first_property) return false;
2290
2291 const Element* mapping_element = findChild(element, "MappingInformationType");
2292 const Element* reference_element = findChild(element, "ReferenceInformationType");
2293 out_indices->clear();
2294 if (mapping_element && mapping_element->first_property)
2295 {
2296 if (mapping_element->first_property->value == "ByPolygonVertex")
2297 {
2299 }
2300 else if (mapping_element->first_property->value == "ByPolygon")
2301 {
2302 *mapping = GeometryImpl::BY_POLYGON;
2303 }
2304 else if (mapping_element->first_property->value == "ByVertice" ||
2305 mapping_element->first_property->value == "ByVertex")
2306 {
2307 *mapping = GeometryImpl::BY_VERTEX;
2308 }
2309 else
2310 {
2311 return false;
2312 }
2313 }
2314 if (reference_element && reference_element->first_property)
2315 {
2316 if (reference_element->first_property->value == "IndexToDirect")
2317 {
2318 const Element* indices_element = findChild(element, index_name);
2319 if (indices_element && indices_element->first_property)
2320 {
2321 if (!parseBinaryArray(*indices_element->first_property, out_indices)) return false;
2322 }
2323 }
2324 else if (reference_element->first_property->value != "Direct")
2325 {
2326 return false;
2327 }
2328 }
2329 return parseDoubleVecData(*data_element->first_property, out, tmp);
2330}
2331
2332
2333static int decodeIndex(int idx)
2334{
2335 return (idx < 0) ? (-idx - 1) : idx;
2336}
2337
2338
2339static int codeIndex(int idx, bool last)
2340{
2341 return last ? (-idx - 1) : idx;
2342}
2343
2344
2345template <typename T>
2346static void splat(std::vector<T>* out,
2348 const std::vector<T>& data,
2349 const std::vector<int>& indices,
2350 const std::vector<int>& original_indices)
2351{
2352 assert(out);
2353 assert(!data.empty());
2354
2355 if (mapping == GeometryImpl::BY_POLYGON_VERTEX)
2356 {
2357 if (indices.empty())
2358 {
2359 out->resize(data.size());
2360 memcpy(&(*out)[0], &data[0], sizeof(data[0]) * data.size());
2361 }
2362 else
2363 {
2364 out->resize(indices.size());
2365 int data_size = (int)data.size();
2366 for (int i = 0, c = (int)indices.size(); i < c; ++i)
2367 {
2368 int index = indices[i];
2369
2370 if ((index < data_size) && (index >= 0))
2371 (*out)[i] = data[index];
2372 else
2373 (*out)[i] = T();
2374 }
2375 }
2376 }
2377 else if (mapping == GeometryImpl::BY_VERTEX)
2378 {
2379 // v0 v1 ...
2380 // uv0 uv1 ...
2381 assert(indices.empty());
2382
2383 out->resize(original_indices.size());
2384
2385 int data_size = (int)data.size();
2386 for (int i = 0, c = (int)original_indices.size(); i < c; ++i)
2387 {
2388 int idx = decodeIndex(original_indices[i]);
2389 if ((idx < data_size) && (idx >= 0)) //-V560
2390 (*out)[i] = data[idx];
2391 else
2392 (*out)[i] = T();
2393 }
2394 }
2395 else
2396 {
2397 assert(false);
2398 }
2399}
2400
2401
2402template <typename T> static void remap(std::vector<T>* out, const std::vector<int>& map)
2403{
2404 if (out->empty()) return;
2405
2406 std::vector<T> old;
2407 old.swap(*out);
2408 int old_size = (int)old.size();
2409 for (int i = 0, c = (int)map.size(); i < c; ++i)
2410 {
2411 out->push_back(map[i] < old_size ? old[map[i]] : T());
2412 }
2413}
2414
2415
2416static OptionalError<Object*> parseAnimationCurve(const Scene& scene, const Element& element, Allocator& allocator)
2417{
2418 AnimationCurveImpl* curve = allocator.allocate<AnimationCurveImpl>(scene, element);
2419
2420 const Element* times = findChild(element, "KeyTime");
2421 const Element* values = findChild(element, "KeyValueFloat");
2422
2423 if (times && times->first_property)
2424 {
2425 curve->times.resize(times->first_property->getCount());
2426 if (!times->first_property->getValues(&curve->times[0], (int)curve->times.size() * sizeof(curve->times[0])))
2427 {
2428 return Error("Invalid animation curve");
2429 }
2430 }
2431
2432 if (values && values->first_property)
2433 {
2434 curve->values.resize(values->first_property->getCount());
2435 if (!values->first_property->getValues(&curve->values[0], (int)curve->values.size() * sizeof(curve->values[0])))
2436 {
2437 return Error("Invalid animation curve");
2438 }
2439 }
2440
2441 if (curve->times.size() != curve->values.size()) return Error("Invalid animation curve");
2442
2443 return curve;
2444}
2445
2446
2447static int getTriCountFromPoly(const std::vector<int>& indices, int* idx)
2448{
2449 int count = 1;
2450 while (indices[*idx + 1 + count] >= 0)
2451 {
2452 ++count;
2453 }
2454
2455 *idx = *idx + 2 + count;
2456 return count;
2457}
2458
2459
2460static void add(GeometryImpl::NewVertex& vtx, int index)
2461{
2462 if (vtx.index == -1)
2463 {
2464 vtx.index = index;
2465 }
2466 else if (vtx.next)
2467 {
2468 add(*vtx.next, index);
2469 }
2470 else
2471 {
2472 vtx.next = new GeometryImpl::NewVertex;
2473 vtx.next->index = index;
2474 }
2475}
2476
2477
2478static void triangulate(
2479 const std::vector<int>& old_indices,
2480 std::vector<int>* to_old_vertices,
2481 std::vector<int>* to_old_indices)
2482{
2483 assert(to_old_vertices);
2484 assert(to_old_indices);
2485
2486 auto getIdx = [&old_indices](int i) -> int {
2487 int idx = old_indices[i];
2488 return decodeIndex(idx);
2489 };
2490
2491 int in_polygon_idx = 0;
2492 for (int i = 0; i < (int)old_indices.size(); ++i)
2493 {
2494 int idx = getIdx(i);
2495 if (in_polygon_idx <= 2) //-V1051
2496 {
2497 to_old_vertices->push_back(idx);
2498 to_old_indices->push_back(i);
2499 }
2500 else
2501 {
2502 to_old_vertices->push_back(old_indices[i - in_polygon_idx]);
2503 to_old_indices->push_back(i - in_polygon_idx);
2504 to_old_vertices->push_back(old_indices[i - 1]);
2505 to_old_indices->push_back(i - 1);
2506 to_old_vertices->push_back(idx);
2507 to_old_indices->push_back(i);
2508 }
2509 ++in_polygon_idx;
2510 if (old_indices[i] < 0)
2511 {
2512 in_polygon_idx = 0;
2513 }
2514 }
2515}
2516
2517
2519 GeometryImpl* geom,
2520 const std::vector<Vec3>& vertices,
2521 const std::vector<int>& original_indices,
2522 std::vector<int>& to_old_indices,
2523 bool triangulationEnabled)
2524{
2525 if (triangulationEnabled) {
2526 triangulate(original_indices, &geom->to_old_vertices, &to_old_indices);
2527 geom->vertices.resize(geom->to_old_vertices.size());
2528 geom->indices.resize(geom->vertices.size());
2529 for (int i = 0, c = (int)geom->to_old_vertices.size(); i < c; ++i)
2530 {
2531 geom->vertices[i] = vertices[geom->to_old_vertices[i]];
2532 geom->indices[i] = codeIndex(i, i % 3 == 2);
2533 }
2534 } else {
2535 geom->vertices = vertices;
2536 geom->to_old_vertices.resize(original_indices.size());
2537 for (size_t i = 0; i < original_indices.size(); ++i) {
2538 geom->to_old_vertices[i] = decodeIndex(original_indices[i]);
2539 }
2540 geom->indices = original_indices;
2541 to_old_indices.resize(original_indices.size());
2542 iota(to_old_indices.begin(), to_old_indices.end(), 0);
2543 }
2544
2545 geom->to_new_vertices.resize(vertices.size()); // some vertices can be unused, so this isn't necessarily the same size as to_old_vertices.
2546 const int* to_old_vertices = geom->to_old_vertices.empty() ? nullptr : &geom->to_old_vertices[0];
2547 for (int i = 0, c = (int)geom->to_old_vertices.size(); i < c; ++i)
2548 {
2549 int old = to_old_vertices[i];
2550 add(geom->to_new_vertices[old], i);
2551 }
2552}
2553
2554
2556 GeometryImpl* geom,
2557 const Element& element,
2558 const std::vector<int>& original_indices)
2559{
2560 const Element* layer_material_element = findChild(element, "LayerElementMaterial");
2561 if (layer_material_element)
2562 {
2563 const Element* mapping_element = findChild(*layer_material_element, "MappingInformationType");
2564 const Element* reference_element = findChild(*layer_material_element, "ReferenceInformationType");
2565
2566 if (!mapping_element || !reference_element) return Error("Invalid LayerElementMaterial");
2567
2568 if (mapping_element->first_property->value == "ByPolygon" &&
2569 reference_element->first_property->value == "IndexToDirect")
2570 {
2571 geom->materials.reserve(geom->vertices.size() / 3);
2572 for (int& i : geom->materials) i = -1;
2573
2574 const Element* indices_element = findChild(*layer_material_element, "Materials");
2575 if (!indices_element || !indices_element->first_property) return Error("Invalid LayerElementMaterial");
2576
2577 std::vector<int> int_tmp;
2578 if (!parseBinaryArray(*indices_element->first_property, &int_tmp)) return Error("Failed to parse material indices");
2579
2580 int tmp_i = 0;
2581 for (int poly = 0, c = (int)int_tmp.size(); poly < c; ++poly)
2582 {
2583 int tri_count = getTriCountFromPoly(original_indices, &tmp_i);
2584 for (int i = 0; i < tri_count; ++i) {
2585 geom->materials.push_back(int_tmp[poly]);
2586 }
2587 }
2588 }
2589 else
2590 {
2591 if (mapping_element->first_property->value != "AllSame") return Error("Mapping not supported");
2592 }
2593 }
2594 return {nullptr};
2595}
2596
2597
2599 GeometryImpl* geom,
2600 const Element& element,
2601 const std::vector<int>& original_indices,
2602 const std::vector<int>& to_old_indices,
2603 Temporaries* tmp)
2604{
2605 const Element* layer_uv_element = findChild(element, "LayerElementUV");
2606 while (layer_uv_element)
2607 {
2608 const int uv_index =
2609 layer_uv_element->first_property ? layer_uv_element->first_property->getValue().toInt() : 0;
2610 if (uv_index >= 0 && uv_index < Geometry::s_uvs_max)
2611 {
2612 std::vector<Vec2>& uvs = geom->uvs[uv_index];
2613
2614 tmp->v2.clear();
2615 tmp->i.clear();
2617 if (!parseVertexData(*layer_uv_element, "UV", "UVIndex", &tmp->v2, &tmp->i, &mapping, &tmp->f))
2618 return Error("Invalid UVs");
2619 if (!tmp->v2.empty() && (tmp->i.empty() || tmp->i[0] != -1))
2620 {
2621 uvs.resize(tmp->i.empty() ? tmp->v2.size() : tmp->i.size());
2622 splat(&uvs, mapping, tmp->v2, tmp->i, original_indices);
2623 remap(&uvs, to_old_indices);
2624 }
2625 }
2626
2627 do
2628 {
2629 layer_uv_element = layer_uv_element->sibling;
2630 } while (layer_uv_element && layer_uv_element->id != "LayerElementUV");
2631 }
2632 return {nullptr};
2633}
2634
2635
2637 GeometryImpl* geom,
2638 const Element& element,
2639 const std::vector<int>& original_indices,
2640 const std::vector<int>& to_old_indices,
2641 Temporaries* tmp)
2642{
2643 const Element* layer_tangent_element = findChild(element, "LayerElementTangents");
2644 if (!layer_tangent_element ) {
2645 layer_tangent_element = findChild(element, "LayerElementTangent");
2646 }
2647 if (layer_tangent_element)
2648 {
2650 if (findChild(*layer_tangent_element, "Tangents"))
2651 {
2652 if (!parseVertexData(*layer_tangent_element, "Tangents", "TangentsIndex", &tmp->v3, &tmp->i, &mapping, &tmp->f))
2653 return Error("Invalid tangets");
2654 }
2655 else
2656 {
2657 if (!parseVertexData(*layer_tangent_element, "Tangent", "TangentIndex", &tmp->v3, &tmp->i, &mapping, &tmp->f))
2658 return Error("Invalid tangets");
2659 }
2660 if (!tmp->v3.empty())
2661 {
2662 splat(&geom->tangents, mapping, tmp->v3, tmp->i, original_indices);
2663 remap(&geom->tangents, to_old_indices);
2664 }
2665 }
2666 return {nullptr};
2667}
2668
2669
2671 GeometryImpl* geom,
2672 const Element& element,
2673 const std::vector<int>& original_indices,
2674 const std::vector<int>& to_old_indices,
2675 Temporaries* tmp)
2676{
2677 const Element* layer_color_element = findChild(element, "LayerElementColor");
2678 if (layer_color_element)
2679 {
2681 if (!parseVertexData(*layer_color_element, "Colors", "ColorIndex", &tmp->v4, &tmp->i, &mapping, &tmp->f))
2682 return Error("Invalid colors");
2683 if (!tmp->v4.empty())
2684 {
2685 splat(&geom->colors, mapping, tmp->v4, tmp->i, original_indices);
2686 remap(&geom->colors, to_old_indices);
2687 }
2688 }
2689 return {nullptr};
2690}
2691
2692
2694 GeometryImpl* geom,
2695 const Element& element,
2696 const std::vector<int>& original_indices,
2697 const std::vector<int>& to_old_indices,
2698 Temporaries* tmp)
2699{
2700 const Element* layer_normal_element = findChild(element, "LayerElementNormal");
2701 if (layer_normal_element)
2702 {
2704 if (!parseVertexData(*layer_normal_element, "Normals", "NormalsIndex", &tmp->v3, &tmp->i, &mapping, &tmp->f))
2705 return Error("Invalid normals");
2706 if (!tmp->v3.empty())
2707 {
2708 splat(&geom->normals, mapping, tmp->v3, tmp->i, original_indices);
2709 remap(&geom->normals, to_old_indices);
2710 }
2711 }
2712 return {nullptr};
2713}
2714
2715
2717{
2718 assert(element.first_property);
2719
2720 const Element* vertices_element = findChild(element, "Vertices");
2721 if (!vertices_element || !vertices_element->first_property)
2722 {
2723 return geom;
2724 }
2725
2726 const Element* polys_element = findChild(element, "PolygonVertexIndex");
2727 if (!polys_element || !polys_element->first_property) return Error("Indices missing");
2728
2729 std::vector<Vec3> vertices;
2730 std::vector<int> original_indices;
2731 std::vector<int> to_old_indices;
2732 Temporaries tmp;
2733 if (!parseDoubleVecData(*vertices_element->first_property, &vertices, &tmp.f)) return Error("Failed to parse vertices");
2734 if (!parseBinaryArray(*polys_element->first_property, &original_indices)) return Error("Failed to parse indices");
2735
2736 buildGeometryVertexData(geom, vertices, original_indices, to_old_indices, triangulate);
2737
2738 OptionalError<Object*> materialParsingError = parseGeometryMaterials(geom, element, original_indices);
2739 if (materialParsingError.isError()) return materialParsingError;
2740
2741 OptionalError<Object*> uvParsingError = parseGeometryUVs(geom, element, original_indices, to_old_indices, &tmp);
2742 if (uvParsingError.isError()) return uvParsingError;
2743
2744 OptionalError<Object*> tangentsParsingError = parseGeometryTangents(geom, element, original_indices, to_old_indices, &tmp);
2745 if (tangentsParsingError.isError()) return tangentsParsingError;
2746
2747 OptionalError<Object*> colorsParsingError = parseGeometryColors(geom, element, original_indices, to_old_indices, &tmp);
2748 if (colorsParsingError.isError()) return colorsParsingError;
2749
2750 OptionalError<Object*> normalsParsingError = parseGeometryNormals(geom, element, original_indices, to_old_indices, &tmp);
2751 if (normalsParsingError.isError()) return normalsParsingError;
2752
2753 return geom;
2754}
2755
2756
2758{
2759 assert(geom);
2760
2761 const Element* vertices_element = findChild((const Element&)element, "Vertices");
2762 const Element* normals_element = findChild((const Element&)element, "Normals");
2763 const Element* indexes_element = findChild((const Element&)element, "Indexes");
2764 if (!vertices_element || !vertices_element->first_property ||
2765 !indexes_element || !indexes_element->first_property)
2766 {
2767 return false;
2768 }
2769
2770 allocator.vec3_tmp.clear(); // old vertices
2771 allocator.vec3_tmp2.clear(); // old normals
2772 allocator.int_tmp.clear(); // old indices
2773 if (!parseDoubleVecData(*vertices_element->first_property, &allocator.vec3_tmp, &allocator.tmp)) return true;
2774 if (!parseDoubleVecData(*normals_element->first_property, &allocator.vec3_tmp2, &allocator.tmp)) return true;
2775 if (!parseBinaryArray(*indexes_element->first_property, &allocator.int_tmp)) return true;
2776
2777 if (allocator.vec3_tmp.size() != allocator.int_tmp.size() || allocator.vec3_tmp2.size() != allocator.int_tmp.size()) return false;
2778
2779 vertices = geom->vertices;
2780 normals = geom->normals;
2781
2782 Vec3* vr = &allocator.vec3_tmp[0];
2783 Vec3* nr = &allocator.vec3_tmp2[0];
2784 int* ir = &allocator.int_tmp[0];
2785 for (int i = 0, c = (int)allocator.int_tmp.size(); i < c; ++i)
2786 {
2787 int old_idx = ir[i];
2788 GeometryImpl::NewVertex* n = &geom->to_new_vertices[old_idx];
2789 if (n->index == -1) continue; // skip vertices which aren't indexed.
2790 while (n)
2791 {
2792 vertices[n->index] = vertices[n->index] + vr[i];
2793 normals[n->index] = vertices[n->index] + nr[i];
2794 n = n->next;
2795 }
2796 }
2797
2798 return true;
2799}
2800
2801
2802static bool isString(const Property* prop)
2803{
2804 if (!prop) return false;
2805 return prop->getType() == Property::STRING;
2806}
2807
2808
2809static bool isLong(const Property* prop)
2810{
2811 if (!prop) return false;
2812 return prop->getType() == Property::LONG;
2813}
2814
2815
2816static bool parseConnections(const Element& root, Scene* scene)
2817{
2818 assert(scene);
2819
2820 const Element* connections = findChild(root, "Connections");
2821 if (!connections) return true;
2822
2823 scene->m_connections.reserve(1024);
2824 const Element* connection = connections->child;
2825 while (connection)
2826 {
2827 if (!isString(connection->first_property)
2828 || !isLong(connection->first_property->next)
2829 || !isLong(connection->first_property->next->next))
2830 {
2831 Error::s_message = "Invalid connection";
2832 return false;
2833 }
2834
2836 c.from = connection->first_property->next->value.toU64();
2837 c.to = connection->first_property->next->next->value.toU64();
2838 if (connection->first_property->value == "OO")
2839 {
2841 }
2842 else if (connection->first_property->value == "OP")
2843 {
2845 if (!connection->first_property->next->next->next)
2846 {
2847 Error::s_message = "Invalid connection";
2848 return false;
2849 }
2850 c.property = connection->first_property->next->next->next->value;
2851 }
2852 else
2853 {
2854 assert(false);
2855 Error::s_message = "Not supported";
2856 return false;
2857 }
2858 scene->m_connections.push_back(c);
2859
2860 connection = connection->sibling;
2861 }
2862 return true;
2863}
2864
2865
2866static bool parseTakes(Scene* scene)
2867{
2868 const Element* takes = findChild((const Element&)*scene->getRootElement(), "Takes");
2869 if (!takes) return true;
2870
2871 const Element* object = takes->child;
2872 while (object)
2873 {
2874 if (object->id == "Take")
2875 {
2876 if (!isString(object->first_property))
2877 {
2878 Error::s_message = "Invalid name in take";
2879 return false;
2880 }
2881
2882 TakeInfo take;
2883 take.name = object->first_property->value;
2884 const Element* filename = findChild(*object, "FileName");
2885 if (filename)
2886 {
2887 if (!isString(filename->first_property))
2888 {
2889 Error::s_message = "Invalid filename in take";
2890 return false;
2891 }
2892 take.filename = filename->first_property->value;
2893 }
2894 const Element* local_time = findChild(*object, "LocalTime");
2895 if (local_time)
2896 {
2897 if (!isLong(local_time->first_property) || !isLong(local_time->first_property->next))
2898 {
2899 Error::s_message = "Invalid local time in take";
2900 return false;
2901 }
2902
2905 }
2906 const Element* reference_time = findChild(*object, "ReferenceTime");
2907 if (reference_time)
2908 {
2909 if (!isLong(reference_time->first_property) || !isLong(reference_time->first_property->next))
2910 {
2911 Error::s_message = "Invalid reference time in take";
2912 return false;
2913 }
2914
2917 }
2918
2919 scene->m_take_infos.push_back(take);
2920 }
2921
2922 object = object->sibling;
2923 }
2924
2925 return true;
2926}
2927
2928
2929static float getFramerateFromTimeMode(FrameRate time_mode, float custom_frame_rate)
2930{
2931 switch (time_mode)
2932 {
2933 case FrameRate_DEFAULT: return 14;
2934 case FrameRate_120: return 120;
2935 case FrameRate_100: return 100;
2936 case FrameRate_60: return 60;
2937 case FrameRate_50: return 50;
2938 case FrameRate_48: return 48;
2939 case FrameRate_30: return 30;
2940 case FrameRate_30_DROP: return 30;
2941 case FrameRate_NTSC_DROP_FRAME: return 29.9700262f;
2942 case FrameRate_NTSC_FULL_FRAME: return 29.9700262f;
2943 case FrameRate_PAL: return 25;
2944 case FrameRate_CINEMA: return 24;
2945 case FrameRate_1000: return 1000;
2946 case FrameRate_CINEMA_ND: return 23.976f;
2947 case FrameRate_CUSTOM: return custom_frame_rate;
2948 }
2949 return -1;
2950}
2951
2952
2953static void parseGlobalSettings(const Element& root, Scene* scene)
2954{
2955 const Element* settings = findChild(root, "GlobalSettings");
2956 if (!settings) return;
2957
2958 const Element* props70 = findChild(*settings, "Properties70");
2959 if (!props70) return;
2960
2961 for (Element* node = props70->child; node; node = node->sibling) {
2962 if (!node->first_property) continue;
2963
2964 #define get_property(name, field, type, getter) if(node->first_property->value == name) \
2965 { \
2966 IElementProperty* prop = node->getProperty(4); \
2967 if (prop) \
2968 { \
2969 DataView value = prop->getValue(); \
2970 scene->m_settings.field = (type)value.getter(); \
2971 } \
2972 }
2973
2974 #define get_time_property(name, field, type, getter) if(node->first_property->value == name) \
2975 { \
2976 IElementProperty* prop = node->getProperty(4); \
2977 if (prop) \
2978 { \
2979 DataView value = prop->getValue(); \
2980 scene->m_settings.field = fbxTimeToSeconds((type)value.getter()); \
2981 } \
2982 }
2983
2984 get_property("UpAxis", UpAxis, UpVector, toInt);
2985 get_property("UpAxisSign", UpAxisSign, int, toInt);
2986 get_property("FrontAxis", FrontAxis, int, toInt);
2987 get_property("FrontAxisSign", FrontAxisSign, int, toInt);
2988 get_property("CoordAxis", CoordAxis, CoordSystem, toInt);
2989 get_property("CoordAxisSign", CoordAxisSign, int, toInt);
2990 get_property("OriginalUpAxis", OriginalUpAxis, int, toInt);
2991 get_property("OriginalUpAxisSign", OriginalUpAxisSign, int, toInt);
2992 get_property("UnitScaleFactor", UnitScaleFactor, float, toDouble);
2993 get_property("OriginalUnitScaleFactor", OriginalUnitScaleFactor, float, toDouble);
2994 get_time_property("TimeSpanStart", TimeSpanStart, u64, toU64);
2995 get_time_property("TimeSpanStop", TimeSpanStop, u64, toU64);
2996 get_property("TimeMode", TimeMode, FrameRate, toInt);
2997 get_property("CustomFrameRate", CustomFrameRate, float, toDouble);
2998
2999 #undef get_property
3000 #undef get_time_property
3001
3003 }
3004}
3005
3006
3013};
3014
3015void sync_job_processor(JobFunction fn, void*, void* data, u32 size, u32 count) {
3016 u8* ptr = (u8*)data;
3017 for(u32 i = 0; i < count; ++i) {
3018 fn(ptr);
3019 ptr += size;
3020 }
3021}
3022
3023static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator& allocator, JobProcessor job_processor, void* job_user_ptr)
3024{
3025 if (!job_processor) job_processor = &sync_job_processor;
3026 const bool triangulate = (flags & (u64)LoadFlags::TRIANGULATE) != 0;
3027 const bool ignore_geometry = (flags & (u64)LoadFlags::IGNORE_GEOMETRY) != 0;
3028 const bool ignore_blend_shapes = (flags & (u64)LoadFlags::IGNORE_BLEND_SHAPES) != 0;
3029 const Element* objs = findChild(root, "Objects");
3030 if (!objs) return true;
3031
3032 scene->m_root = allocator.allocate<Root>(*scene, root);
3033 scene->m_root->id = 0;
3034 scene->m_object_map[0] = {&root, scene->m_root};
3035
3036 const Element* object = objs->child;
3037 while (object)
3038 {
3039 if (!isLong(object->first_property))
3040 {
3041 Error::s_message = "Invalid";
3042 return false;
3043 }
3044
3045 u64 id = object->first_property->value.toU64();
3046 scene->m_object_map[id] = {object, nullptr};
3047 object = object->sibling;
3048 }
3049
3050 std::vector<ParseGeometryJob> parse_geom_jobs;
3051 for (auto iter : scene->m_object_map)
3052 {
3053 OptionalError<Object*> obj = nullptr;
3054
3055 if (iter.second.object == scene->m_root) continue;
3056
3057 if (iter.second.element->id == "Geometry")
3058 {
3059 Property* last_prop = iter.second.element->first_property;
3060 while (last_prop->next) last_prop = last_prop->next;
3061 if (last_prop && last_prop->value == "Mesh" && !ignore_geometry)
3062 {
3063 GeometryImpl* geom = allocator.allocate<GeometryImpl>(*scene, *iter.second.element);
3064 scene->m_geometries.push_back(geom);
3065 ParseGeometryJob job {iter.second.element, triangulate, geom, iter.first, false};
3066 parse_geom_jobs.push_back(job);
3067 continue;
3068 }
3069 if (last_prop && last_prop->value == "Shape" && !ignore_geometry)
3070 {
3071 obj = allocator.allocate<ShapeImpl>(*scene, *iter.second.element);
3072 }
3073 }
3074 else if (iter.second.element->id == "Material")
3075 {
3076 obj = parseMaterial(*scene, *iter.second.element, allocator);
3077 }
3078 else if (iter.second.element->id == "AnimationStack")
3079 {
3080 obj = parse<AnimationStackImpl>(*scene, *iter.second.element, allocator);
3081 if (!obj.isError())
3082 {
3084 scene->m_animation_stacks.push_back(stack);
3085 }
3086 }
3087 else if (iter.second.element->id == "AnimationLayer")
3088 {
3089 obj = parse<AnimationLayerImpl>(*scene, *iter.second.element, allocator);
3090 }
3091 else if (iter.second.element->id == "AnimationCurve")
3092 {
3093 obj = parseAnimationCurve(*scene, *iter.second.element, allocator);
3094 }
3095 else if (iter.second.element->id == "AnimationCurveNode")
3096 {
3097 obj = parse<AnimationCurveNodeImpl>(*scene, *iter.second.element, allocator);
3098 }
3099 else if (iter.second.element->id == "Deformer")
3100 {
3101 IElementProperty* class_prop = iter.second.element->getProperty(2);
3102
3103 if (class_prop)
3104 {
3105 if (class_prop->getValue() == "Cluster")
3106 obj = parseCluster(*scene, *iter.second.element, allocator);
3107 else if (class_prop->getValue() == "Skin")
3108 obj = parse<SkinImpl>(*scene, *iter.second.element, allocator);
3109 else if (class_prop->getValue() == "BlendShape" && !ignore_blend_shapes)
3110 obj = parse<BlendShapeImpl>(*scene, *iter.second.element, allocator);
3111 else if (class_prop->getValue() == "BlendShapeChannel" && !ignore_blend_shapes)
3112 obj = parse<BlendShapeChannelImpl>(*scene, *iter.second.element, allocator);
3113 }
3114 }
3115 else if (iter.second.element->id == "NodeAttribute")
3116 {
3117 obj = parseNodeAttribute(*scene, *iter.second.element, allocator);
3118 }
3119 else if (iter.second.element->id == "Model")
3120 {
3121 IElementProperty* class_prop = iter.second.element->getProperty(2);
3122
3123 if (class_prop)
3124 {
3125 if (class_prop->getValue() == "Mesh")
3126 {
3127 obj = parseMesh(*scene, *iter.second.element, allocator);
3128 if (!obj.isError())
3129 {
3130 Mesh* mesh = (Mesh*)obj.getValue();
3131 scene->m_meshes.push_back(mesh);
3132 obj = mesh;
3133 }
3134 }
3135 else if (class_prop->getValue() == "LimbNode")
3136 obj = parseLimbNode(*scene, *iter.second.element, allocator);
3137 else
3138 obj = parse<NullImpl>(*scene, *iter.second.element, allocator);
3139 }
3140 }
3141 else if (iter.second.element->id == "Texture")
3142 {
3143 obj = parseTexture(*scene, *iter.second.element, allocator);
3144 }
3145 else if (iter.second.element->id == "Video")
3146 {
3147 parseVideo(*scene, *iter.second.element, allocator);
3148 }
3149 else if (iter.second.element->id == "Pose")
3150 {
3151 obj = parsePose(*scene, *iter.second.element, allocator);
3152 }
3153
3154 if (obj.isError()) return false;
3155
3156 scene->m_object_map[iter.first].object = obj.getValue();
3157 if (obj.getValue())
3158 {
3159 scene->m_all_objects.push_back(obj.getValue());
3160 obj.getValue()->id = iter.first;
3161 }
3162 }
3163
3164 if (!parse_geom_jobs.empty()) {
3165 (*job_processor)([](void* ptr){
3167 job->is_error = parseGeometry(*job->element, job->triangulate, job->geom).isError();
3168 }, job_user_ptr, &parse_geom_jobs[0], (u32)sizeof(parse_geom_jobs[0]), (u32)parse_geom_jobs.size());
3169 }
3170
3171 for (const ParseGeometryJob& job : parse_geom_jobs) {
3172 if (job.is_error) return false;
3173 scene->m_object_map[job.id].object = job.geom;
3174 if (job.geom) {
3175 scene->m_all_objects.push_back(job.geom);
3176 job.geom->id = job.id;
3177 }
3178 }
3179
3180 for (const Scene::Connection& con : scene->m_connections)
3181 {
3182 Object* parent = scene->m_object_map[con.to].object;
3183 Object* child = scene->m_object_map[con.from].object;
3184 if (!child) continue;
3185 if (!parent) continue;
3186
3187 switch (child->getType())
3188 {
3190 if (parent->node_attribute)
3191 {
3192 Error::s_message = "Invalid node attribute";
3193 return false;
3194 }
3195 parent->node_attribute = (NodeAttribute*)child;
3196 break;
3198 if (parent->isNode())
3199 {
3201 node->bone = parent;
3202 node->bone_link_property = con.property;
3203 }
3204 break;
3205 }
3206
3207 switch (parent->getType())
3208 {
3209 case Object::Type::MESH:
3210 {
3211 MeshImpl* mesh = (MeshImpl*)parent;
3212 switch (child->getType())
3213 {
3215 if (mesh->geometry)
3216 {
3217 Error::s_message = "Invalid mesh";
3218 return false;
3219 }
3220 mesh->geometry = (Geometry*)child;
3221 break;
3222 case Object::Type::MATERIAL: mesh->materials.push_back((Material*)child); break;
3223 }
3224 break;
3225 }
3226 case Object::Type::SKIN:
3227 {
3228 SkinImpl* skin = (SkinImpl*)parent;
3229 if (child->getType() == Object::Type::CLUSTER)
3230 {
3231 ClusterImpl* cluster = (ClusterImpl*)child;
3232 skin->clusters.push_back(cluster);
3233 if (cluster->skin)
3234 {
3235 Error::s_message = "Invalid cluster";
3236 return false;
3237 }
3238 cluster->skin = skin;
3239 }
3240 break;
3241 }
3243 {
3244 BlendShapeImpl* blendShape = (BlendShapeImpl*)parent;
3246 {
3247 BlendShapeChannelImpl* blendShapeChannel = (BlendShapeChannelImpl*)child;
3248 blendShape->blendShapeChannels.push_back(blendShapeChannel);
3249 if (blendShapeChannel->blendShape)
3250 {
3251 Error::s_message = "Invalid blend shape";
3252 return false;
3253 }
3254 blendShapeChannel->blendShape = blendShape;
3255 }
3256 break;
3257 }
3259 {
3260 BlendShapeChannelImpl* blendShapeChannel = (BlendShapeChannelImpl*)parent;
3261 if (child->getType() == Object::Type::SHAPE)
3262 {
3263 ShapeImpl* shape = (ShapeImpl*)child;
3264 blendShapeChannel->shapes.push_back(shape);
3265 }
3266 break;
3267 }
3269 {
3270 MaterialImpl* mat = (MaterialImpl*)parent;
3271 if (child->getType() == Object::Type::TEXTURE)
3272 {
3274 if (con.property == "NormalMap")
3275 type = Texture::NORMAL;
3276 else if (con.property == "DiffuseColor")
3277 type = Texture::DIFFUSE;
3278 else if (con.property == "SpecularColor")
3279 type = Texture::SPECULAR;
3280 else if (con.property == "ShininessExponent")
3281 type = Texture::SHININESS;
3282 else if (con.property == "EmissiveColor")
3283 type = Texture::EMISSIVE;
3284 else if (con.property == "AmbientColor")
3285 type = Texture::AMBIENT;
3286 else if (con.property == "ReflectionFactor")
3287 type = Texture::REFLECTION;
3288 if (type == Texture::COUNT) break;
3289
3290 if (mat->textures[type])
3291 {
3292 break; // This may happen for some models (eg. 2 normal maps in use)
3293 }
3294
3295 mat->textures[type] = (Texture*)child;
3296 }
3297 break;
3298 }
3300 {
3301 GeometryImpl* geom = (GeometryImpl*)parent;
3302 if (child->getType() == Object::Type::SKIN)
3303 geom->skin = (Skin*)child;
3304 else if (child->getType() == Object::Type::BLEND_SHAPE)
3305 geom->blendShape = (BlendShape*)child;
3306 break;
3307 }
3309 {
3310 ClusterImpl* cluster = (ClusterImpl*)parent;
3311 if (child->getType() == Object::Type::LIMB_NODE || child->getType() == Object::Type::MESH || child->getType() == Object::Type::NULL_NODE)
3312 {
3313 if (cluster->link && cluster->link != child)
3314 {
3315 Error::s_message = "Invalid cluster";
3316 return false;
3317 }
3318
3319 cluster->link = child;
3320 }
3321 break;
3322 }
3324 {
3326 {
3327 ((AnimationLayerImpl*)parent)->curve_nodes.push_back((AnimationCurveNodeImpl*)child);
3328 }
3329 }
3330 break;
3332 {
3334 if (child->getType() == Object::Type::ANIMATION_CURVE)
3335 {
3336 char tmp[32];
3337 con.property.toString(tmp);
3338 if (strcmp(tmp, "d|X") == 0)
3339 {
3340 node->curves[0].connection = &con;
3341 node->curves[0].curve = (AnimationCurve*)child;
3342 }
3343 else if (strcmp(tmp, "d|Y") == 0)
3344 {
3345 node->curves[1].connection = &con;
3346 node->curves[1].curve = (AnimationCurve*)child;
3347 }
3348 else if (strcmp(tmp, "d|Z") == 0)
3349 {
3350 node->curves[2].connection = &con;
3351 node->curves[2].curve = (AnimationCurve*)child;
3352 }
3353 }
3354 break;
3355 }
3356 }
3357 }
3358
3359 if (!ignore_geometry) {
3360 for (auto iter : scene->m_object_map)
3361 {
3362 Object* obj = iter.second.object;
3363 if (!obj) continue;
3364 switch (obj->getType()) {
3366 if (!((ClusterImpl*)iter.second.object)->postprocess(scene->m_allocator)) {
3367 Error::s_message = "Failed to postprocess cluster";
3368 return false;
3369 }
3370 break;
3372 if (!((BlendShapeChannelImpl*)iter.second.object)->postprocess(scene->m_allocator)) {
3373 Error::s_message = "Failed to postprocess blend shape channel";
3374 return false;
3375 }
3376 break;
3377 case Object::Type::POSE:
3378 if (!((PoseImpl*)iter.second.object)->postprocess(scene)) {
3379 Error::s_message = "Failed to postprocess pose";
3380 return false;
3381 }
3382 break;
3383 }
3384 }
3385 }
3386
3387 return true;
3388}
3389
3390
3392{
3393 // This assumes that the default rotation order is EULER_XYZ.
3394 return (RotationOrder) resolveEnumProperty(*this, "RotationOrder", (int) RotationOrder::EULER_XYZ);
3395}
3396
3397
3399{
3400 return resolveVec3Property(*this, "RotationOffset", {0, 0, 0});
3401}
3402
3403
3405{
3406 return resolveVec3Property(*this, "RotationPivot", {0, 0, 0});
3407}
3408
3409
3411{
3412 return resolveVec3Property(*this, "PostRotation", {0, 0, 0});
3413}
3414
3415
3417{
3418 return resolveVec3Property(*this, "ScalingOffset", {0, 0, 0});
3419}
3420
3421
3423{
3424 return resolveVec3Property(*this, "ScalingPivot", {0, 0, 0});
3425}
3426
3427
3428Matrix Object::evalLocal(const Vec3& translation, const Vec3& rotation) const
3429{
3430 return evalLocal(translation, rotation, getLocalScaling());
3431}
3432
3433
3434Matrix Object::evalLocal(const Vec3& translation, const Vec3& rotation, const Vec3& scaling) const
3435{
3436 Vec3 rotation_pivot = getRotationPivot();
3437 Vec3 scaling_pivot = getScalingPivot();
3438 RotationOrder rotation_order = getRotationOrder();
3439
3440 Matrix s = makeIdentity();
3441 s.m[0] = scaling.x;
3442 s.m[5] = scaling.y;
3443 s.m[10] = scaling.z;
3444
3445 Matrix t = makeIdentity();
3446 setTranslation(translation, &t);
3447
3448 Matrix r = getRotationMatrix(rotation, rotation_order);
3451
3452 Matrix r_off = makeIdentity();
3454
3455 Matrix r_p = makeIdentity();
3456 setTranslation(rotation_pivot, &r_p);
3457
3458 Matrix r_p_inv = makeIdentity();
3459 setTranslation(-rotation_pivot, &r_p_inv);
3460
3461 Matrix s_off = makeIdentity();
3463
3464 Matrix s_p = makeIdentity();
3465 setTranslation(scaling_pivot, &s_p);
3466
3467 Matrix s_p_inv = makeIdentity();
3468 setTranslation(-scaling_pivot, &s_p_inv);
3469
3470 // http://help.autodesk.com/view/FBX/2017/ENU/?guid=__files_GUID_10CDD63C_79C1_4F2D_BB28_AD2BE65A02ED_htm
3471 return t * r_off * r_p * r_pre * r * r_post_inv * r_p_inv * s_off * s_p * s * s_p_inv;
3472}
3473
3474
3475
3477{
3478 return resolveVec3Property(*this, "Lcl Translation", {0, 0, 0});
3479}
3480
3481
3483{
3484 return resolveVec3Property(*this, "PreRotation", {0, 0, 0});
3485}
3486
3487
3489{
3490 return resolveVec3Property(*this, "Lcl Rotation", {0, 0, 0});
3491}
3492
3493
3495{
3496 return resolveVec3Property(*this, "Lcl Scaling", {1, 1, 1});
3497}
3498
3499
3501{
3502 const Object* parent = getParent();
3503 if (!parent) return evalLocal(getLocalTranslation(), getLocalRotation());
3504
3506}
3507
3508
3510{
3512}
3513
3514
3516{
3518 for (auto& connection : scene.m_connections)
3519 {
3520 if (connection.from == id && connection.to != 0)
3521 {
3522 const Scene::ObjectPair& pair = scene.m_object_map.find(connection.to)->second;
3523 Object* obj = pair.object;
3524 if (obj && obj->getType() == type) return obj;
3525 }
3526 }
3527 return nullptr;
3528}
3529
3530
3532{
3533 return scene;
3534}
3535
3536
3538{
3540 for (auto& connection : scene.m_connections)
3541 {
3542 if (connection.to == id && connection.from != 0)
3543 {
3544 Object* obj = scene.m_object_map.find(connection.from)->second.object;
3545 if (obj)
3546 {
3547 if (idx == 0) return obj;
3548 --idx;
3549 }
3550 }
3551 }
3552 return nullptr;
3553}
3554
3555
3556Object* Object::resolveObjectLink(Object::Type type, const char* property, int idx) const
3557{
3559 for (auto& connection : scene.m_connections)
3560 {
3561 if (connection.to == id && connection.from != 0)
3562 {
3563 Object* obj = scene.m_object_map.find(connection.from)->second.object;
3564 if (obj && obj->getType() == type)
3565 {
3566 if (property == nullptr || connection.property == property)
3567 {
3568 if (idx == 0) return obj;
3569 --idx;
3570 }
3571 }
3572 }
3573 }
3574 return nullptr;
3575}
3576
3577
3579{
3580 Object* parent = nullptr;
3581 for (auto& connection : scene.m_connections)
3582 {
3583 if (connection.from == id)
3584 {
3585 Object* obj = scene.m_object_map.find(connection.to)->second.object;
3586 if (obj && obj->is_node && obj != this)
3587 {
3588 assert(parent == nullptr);
3589 parent = obj;
3590 }
3591 }
3592 }
3593 return parent;
3594}
3595
3596
3597IScene* load(const u8* data, int size, u64 flags, JobProcessor job_processor, void* job_user_ptr)
3598{
3599 std::unique_ptr<Scene> scene(new Scene());
3600 scene->m_data.resize(size);
3601 memcpy(&scene->m_data[0], data, size);
3602 u32 version;
3603
3604 const bool is_binary = size >= 18 && strncmp((const char*)data, "Kaydara FBX Binary", 18) == 0;
3605 OptionalError<Element*> root(nullptr);
3606 if (is_binary) {
3607 root = tokenize(&scene->m_data[0], size, version, scene->m_allocator);
3608 if (version < 6200)
3609 {
3610 Error::s_message = "Unsupported FBX file format version. Minimum supported version is 6.2";
3611 return nullptr;
3612 }
3613 if (root.isError())
3614 {
3615 Error::s_message = "";
3616 if (root.isError()) return nullptr;
3617 }
3618 }
3619 else {
3620 root = tokenizeText(&scene->m_data[0], size, scene->m_allocator);
3621 if (root.isError()) return nullptr;
3622 }
3623
3624 scene->m_root_element = root.getValue();
3625 assert(scene->m_root_element);
3626
3627 // if (parseTemplates(*root.getValue()).isError()) return nullptr;
3628 if (!parseConnections(*root.getValue(), scene.get())) return nullptr;
3629 if (!parseTakes(scene.get())) return nullptr;
3630 if (!parseObjects(*root.getValue(), scene.get(), flags, scene->m_allocator, job_processor, job_user_ptr)) return nullptr;
3631 parseGlobalSettings(*root.getValue(), scene.get());
3632
3633 return scene.release();
3634}
3635
3636
3637const char* getError()
3638{
3639 return Error::s_message;
3640}
3641
3642
3643} // namespace ofbx
QWindow * w
Definition: QtImGui.cpp:152
assert(queueCount >=1)
#define T(t)
int mz_inflateInit(mz_streamp pStream)
Definition: miniz.c:395
int mz_inflate(mz_streamp pStream, int flush)
Definition: miniz.c:400
int mz_inflateEnd(mz_streamp pStream)
Definition: miniz.c:512
#define Z_STREAM_END
Definition: miniz.h:404
#define Z_OK
Definition: miniz.h:403
#define Z_SYNC_FLUSH
Definition: miniz.h:399
DYN_FUNC Complex< Real > sin(const Complex< Real > &)
Definition: Complex.inl:564
DYN_FUNC Complex< Real > cos(const Complex< Real > &)
Definition: Complex.inl:573
Definition: ofbx.cpp:14
static int resolveEnumProperty(const Object &object, const char *name, int default_value)
Definition: ofbx.cpp:487
static int codeIndex(int idx, bool last)
Definition: ofbx.cpp:2339
const char * fromString< i64 >(const char *str, const char *end, i64 *val)
Definition: ofbx.cpp:2098
static Matrix rotationY(double angle)
Definition: ofbx.cpp:208
static OptionalError< Element * > readTextElement(Cursor *cursor, Allocator &allocator)
Definition: ofbx.cpp:870
static OptionalError< DataView > readShortString(Cursor *cursor)
Definition: ofbx.cpp:554
const char * fromString(const char *str, const char *end, T *val)
const char * fromString< Vec4 >(const char *str, const char *end, Vec4 *val)
Definition: ofbx.cpp:2156
void(*)(JobFunction, void *, void *, u32, u32) JobProcessor
Definition: ofbx.h:26
static bool parseVertexData(const Element &element, const char *name, const char *index_name, std::vector< T > *out, std::vector< int > *out_indices, GeometryImpl::VertexDataMapping *mapping, std::vector< float > *tmp)
Definition: ofbx.cpp:2278
static OptionalError< Object * > parse(const Scene &scene, const Element &element, Allocator &allocator)
Definition: ofbx.cpp:1879
static int decodeIndex(int idx)
Definition: ofbx.cpp:2333
CoordSystem
Definition: ofbx.h:465
void(*)(void *) JobFunction
Definition: ofbx.h:25
static float getFramerateFromTimeMode(FrameRate time_mode, float custom_frame_rate)
Definition: ofbx.cpp:2929
static bool parseDoubleVecData(Property &property, std::vector< T > *out_vec, std::vector< float > *tmp)
Definition: ofbx.cpp:2223
static OptionalError< Property * > readTextProperty(Cursor *cursor, Allocator &allocator)
Definition: ofbx.cpp:771
static OptionalError< Object * > parseGeometryNormals(GeometryImpl *geom, const Element &element, const std::vector< int > &original_indices, const std::vector< int > &to_old_indices, Temporaries *tmp)
Definition: ofbx.cpp:2693
static IElement * resolveProperty(const Object &obj, const char *name)
Definition: ofbx.cpp:469
static OptionalError< Object * > parseMaterial(const Scene &scene, const Element &element, Allocator &allocator)
Definition: ofbx.cpp:1953
struct OptionalError< Object * > parsePose(const Scene &scene, const Element &element, Allocator &allocator)
Definition: ofbx.cpp:1861
long i64
Definition: ofbx.h:15
static OptionalError< Element * > readElement(Cursor *cursor, u32 version, Allocator &allocator)
Definition: ofbx.cpp:655
static Matrix makeIdentity()
Definition: ofbx.cpp:188
static Matrix rotationZ(double angle)
Definition: ofbx.cpp:222
RotationOrder
Definition: ofbx.h:142
double fbxTimeToSeconds(i64 value)
Definition: ofbx.cpp:256
static void remap(std::vector< T > *out, const std::vector< int > &map)
Definition: ofbx.cpp:2402
static bool decompress(const u8 *in, size_t in_size, u8 *out, size_t out_size)
Definition: ofbx.cpp:527
static bool parseArrayRaw(const Property &property, T *out, int max_size)
Definition: ofbx.cpp:2034
static bool isTextTokenChar(char c)
Definition: ofbx.cpp:752
static bool copyString(char(&destination)[SIZE], const char *source)
Definition: ofbx.cpp:280
static void parseTemplates(const Element &root)
Definition: ofbx.cpp:995
static void splat(std::vector< T > *out, GeometryImpl::VertexDataMapping mapping, const std::vector< T > &data, const std::vector< int > &indices, const std::vector< int > &original_indices)
Definition: ofbx.cpp:2346
i64 secondsToFbxTime(double value)
Definition: ofbx.cpp:262
static OptionalError< Object * > parseLimbNode(const Scene &scene, const Element &element, Allocator &allocator)
Definition: ofbx.cpp:1924
const char * fromString< Vec3 >(const char *str, const char *end, Vec3 *val)
Definition: ofbx.cpp:2150
const char * fromString< int >(const char *str, const char *end, int *val)
Definition: ofbx.cpp:2078
FrameRate
Definition: ofbx.h:473
@ FrameRate_PAL
Definition: ofbx.h:484
@ FrameRate_30
Definition: ofbx.h:480
@ FrameRate_NTSC_FULL_FRAME
Definition: ofbx.h:483
@ FrameRate_CINEMA_ND
Definition: ofbx.h:487
@ FrameRate_30_DROP
Definition: ofbx.h:481
@ FrameRate_48
Definition: ofbx.h:479
@ FrameRate_DEFAULT
Definition: ofbx.h:474
@ FrameRate_1000
Definition: ofbx.h:486
@ FrameRate_CUSTOM
Definition: ofbx.h:488
@ FrameRate_NTSC_DROP_FRAME
Definition: ofbx.h:482
@ FrameRate_CINEMA
Definition: ofbx.h:485
@ FrameRate_100
Definition: ofbx.h:476
@ FrameRate_120
Definition: ofbx.h:475
@ FrameRate_50
Definition: ofbx.h:478
@ FrameRate_60
Definition: ofbx.h:477
static OptionalError< Object * > parseAnimationCurve(const Scene &scene, const Element &element, Allocator &allocator)
Definition: ofbx.cpp:2416
static Vec3 operator+(const Vec3 &a, const Vec3 &b)
Definition: ofbx.cpp:274
static void skipInsignificantWhitespaces(Cursor *cursor)
Definition: ofbx.cpp:722
static bool parseConnections(const Element &root, Scene *scene)
Definition: ofbx.cpp:2816
const char * fromString< u64 >(const char *str, const char *end, u64 *val)
Definition: ofbx.cpp:2088
static OptionalError< u64 > readElementOffset(Cursor *cursor, u16 version)
Definition: ofbx.cpp:640
static DataView readTextToken(Cursor *cursor)
Definition: ofbx.cpp:758
static void skipLine(Cursor *cursor)
Definition: ofbx.cpp:731
static OptionalError< DataView > readLongString(Cursor *cursor)
Definition: ofbx.cpp:570
static OptionalError< Object * > parseGeometryColors(GeometryImpl *geom, const Element &element, const std::vector< int > &original_indices, const std::vector< int > &to_old_indices, Temporaries *tmp)
Definition: ofbx.cpp:2670
void parseVideo(Scene &scene, const Element &element, Allocator &allocator)
Definition: ofbx.cpp:1813
static OptionalError< Object * > parseCluster(const Scene &scene, const Element &element, Allocator &allocator)
Definition: ofbx.cpp:1886
const char * getError()
Definition: ofbx.cpp:3637
static void parseGlobalSettings(const Element &root, Scene *scene)
Definition: ofbx.cpp:2953
static OptionalError< Object * > parseGeometryUVs(GeometryImpl *geom, const Element &element, const std::vector< int > &original_indices, const std::vector< int > &to_old_indices, Temporaries *tmp)
Definition: ofbx.cpp:2598
static bool isString(const Property *prop)
Definition: ofbx.cpp:2802
unsigned char u8
Definition: ofbx.h:8
static Matrix operator*(const Matrix &lhs, const Matrix &rhs)
Definition: ofbx.cpp:169
static bool isEndLine(const Cursor &cursor)
Definition: ofbx.cpp:716
const char * fromString< float >(const char *str, const char *end, float *val)
Definition: ofbx.cpp:2118
static OptionalError< Object * > parseNodeAttribute(const Scene &scene, const Element &element, Allocator &allocator)
Definition: ofbx.cpp:1912
const char * fromString< double >(const char *str, const char *end, double *val)
Definition: ofbx.cpp:2108
static bool parseTextArrayRaw(const Property &property, T *out, int max_size)
Definition: ofbx.cpp:2180
static OptionalError< Property * > readProperty(Cursor *cursor, Allocator &allocator)
Definition: ofbx.cpp:586
static OptionalError< Object * > parseGeometryTangents(GeometryImpl *geom, const Element &element, const std::vector< int > &original_indices, const std::vector< int > &to_old_indices, Temporaries *tmp)
Definition: ofbx.cpp:2636
static bool parseObjects(const Element &root, Scene *scene, u64 flags, Allocator &allocator, JobProcessor job_processor, void *job_user_ptr)
Definition: ofbx.cpp:3023
static OptionalError< Element * > tokenizeText(const u8 *data, size_t size, Allocator &allocator)
Definition: ofbx.cpp:925
static OptionalError< Object * > parseGeometryMaterials(GeometryImpl *geom, const Element &element, const std::vector< int > &original_indices)
Definition: ofbx.cpp:2555
unsigned long u64
Definition: ofbx.h:16
static bool parseDouble(Property &property, double *out)
Definition: ofbx.cpp:2252
static const Element * findChild(const Element &element, const char *id)
Definition: ofbx.cpp:457
const char * fromString< Vec2 >(const char *str, const char *end, Vec2 *val)
Definition: ofbx.cpp:2144
unsigned short u16
Definition: ofbx.h:9
static void triangulate(const std::vector< int > &old_indices, std::vector< int > *to_old_vertices, std::vector< int > *to_old_indices)
Definition: ofbx.cpp:2478
static Matrix rotationX(double angle)
Definition: ofbx.cpp:194
static bool parseTakes(Scene *scene)
Definition: ofbx.cpp:2866
unsigned int u32
Definition: ofbx.h:10
static bool parseBinaryArray(const Property &property, std::vector< T > *out)
Definition: ofbx.cpp:2195
static void skipWhitespaces(Cursor *cursor)
Definition: ofbx.cpp:742
static bool isLong(const Property *prop)
Definition: ofbx.cpp:2809
static Matrix getRotationMatrix(const Vec3 &euler, RotationOrder order)
Definition: ofbx.cpp:236
static Vec3 resolveVec3Property(const Object &object, const char *name, const Vec3 &default_value)
Definition: ofbx.cpp:498
IScene * load(const u8 *data, int size, u64 flags, JobProcessor job_processor, void *job_user_ptr)
Definition: ofbx.cpp:3597
static void setTranslation(const Vec3 &t, Matrix *mtx)
Definition: ofbx.cpp:155
static void buildGeometryVertexData(GeometryImpl *geom, const std::vector< Vec3 > &vertices, const std::vector< int > &original_indices, std::vector< int > &to_old_indices, bool triangulationEnabled)
Definition: ofbx.cpp:2518
static Vec3 operator-(const Vec3 &v)
Definition: ofbx.cpp:163
static void parseTextArray(const Property &property, std::vector< T > *out)
Definition: ofbx.cpp:2168
struct OptionalError< Object * > parseTexture(const Scene &scene, const Element &element, Allocator &allocator)
Definition: ofbx.cpp:1837
static int getTriCountFromPoly(const std::vector< int > &indices, int *idx)
Definition: ofbx.cpp:2447
static OptionalError< Object * > parseGeometry(const Element &element, bool triangulate, GeometryImpl *geom)
Definition: ofbx.cpp:2716
UpVector
Definition: ofbx.h:456
const char * fromString< Matrix >(const char *str, const char *end, Matrix *val)
Definition: ofbx.cpp:2162
void sync_job_processor(JobFunction fn, void *, void *data, u32 size, u32 count)
Definition: ofbx.cpp:3015
static OptionalError< Element * > tokenize(const u8 *data, size_t size, u32 &version, Allocator &allocator)
Definition: ofbx.cpp:963
static OptionalError< Object * > parseMesh(const Scene &scene, const Element &element, Allocator &allocator)
Definition: ofbx.cpp:1939
static void add(GeometryImpl::NewVertex &vtx, int index)
Definition: ofbx.cpp:2460
static OptionalError< T > read(Cursor *cursor)
Definition: ofbx.cpp:545
TEMPLATE_TYPENAME_T MAT4_T scale(MAT4_T const &m, VEC3_T const &v)
Definition: vgMath.h:506
TEMPLATE_TYPENAME_T T angle(QUAT_T const &q)
Definition: vgMath.h:511
TEMPLATE_TYPENAME_T T length(const VEC2_T &v)
Definition: vgMath.h:400
#define get_property(name, field, type, getter)
#define get_time_property(name, field, type, getter)
unsigned char * next_out
Definition: miniz.h:276
unsigned int avail_out
Definition: miniz.h:277
const unsigned char * next_in
Definition: miniz.h:272
unsigned int avail_in
Definition: miniz.h:273
u8 data[4096 *1024 - 12]
Definition: ofbx.cpp:23
struct ofbx::Allocator::Page::@28 header
std::vector< int > int_tmp
Definition: ofbx.cpp:59
std::vector< Vec3 > vec3_tmp2
Definition: ofbx.cpp:62
std::vector< Vec3 > vec3_tmp
Definition: ofbx.cpp:60
T * allocate(Args &&... args)
Definition: ofbx.cpp:36
Page * first
Definition: ofbx.cpp:25
std::vector< float > tmp
Definition: ofbx.cpp:58
std::vector< double > double_tmp
Definition: ofbx.cpp:61
AnimationCurve(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1342
virtual int getKeyCount() const =0
virtual const i64 * getKeyTime() const =0
virtual const float * getKeyValue() const =0
const i64 * getKeyTime() const override
Definition: ofbx.cpp:1380
AnimationCurveImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1374
int getKeyCount() const override
Definition: ofbx.cpp:1379
const float * getKeyValue() const override
Definition: ofbx.cpp:1381
std::vector< float > values
Definition: ofbx.cpp:1384
Type getType() const override
Definition: ofbx.cpp:1385
std::vector< i64 > times
Definition: ofbx.cpp:1383
AnimationCurveNode(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1348
const AnimationCurve * curve
Definition: ofbx.cpp:1763
const Scene::Connection * connection
Definition: ofbx.cpp:1764
const Object * getBone() const override
Definition: ofbx.cpp:1709
float getAnimationDY() const
Definition: ofbx.cpp:1718
float getAnimationDX() const
Definition: ofbx.cpp:1714
enum ofbx::AnimationCurveNodeImpl::Mode mode
AnimationCurveNodeImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1686
Type getType() const override
Definition: ofbx.cpp:1771
float getAnimationDZ() const
Definition: ofbx.cpp:1722
Vec3 getNodeLocalTransform(double time) const override
Definition: ofbx.cpp:1733
const AnimationCurve * getCurve(int idx) const override
Definition: ofbx.cpp:1727
AnimationLayer(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1336
Type getType() const override
Definition: ofbx.cpp:1790
const AnimationCurveNode * getCurveNode(int index) const override
Definition: ofbx.cpp:1793
AnimationLayerImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1784
const AnimationCurveNode * getCurveNode(const Object &bone, const char *prop) const override
Definition: ofbx.cpp:1800
std::vector< AnimationCurveNodeImpl * > curve_nodes
Definition: ofbx.cpp:1810
AnimationStack(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1330
const AnimationLayer * getLayer(int index) const override
Definition: ofbx.cpp:1362
AnimationStackImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1356
Type getType() const override
Definition: ofbx.cpp:1368
BlendShapeChannel(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1411
int getShapeCount() const override
Definition: ofbx.cpp:1425
std::vector< Shape * > shapes
Definition: ofbx.cpp:1462
BlendShape * blendShape
Definition: ofbx.cpp:1459
bool postprocess(Allocator &allocator)
Definition: ofbx.cpp:1430
std::vector< double > fullWeights
Definition: ofbx.cpp:1461
Type getType() const override
Definition: ofbx.cpp:1428
double getDeformPercent() const override
Definition: ofbx.cpp:1424
const Shape * getShape(int idx) const override
Definition: ofbx.cpp:1426
BlendShapeChannelImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1419
BlendShape(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1466
const BlendShapeChannel * getBlendShapeChannel(int idx) const override
Definition: ofbx.cpp:1480
BlendShapeImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1474
int getBlendShapeChannelCount() const override
Definition: ofbx.cpp:1479
std::vector< BlendShapeChannel * > blendShapeChannels
Definition: ofbx.cpp:1484
Type getType() const override
Definition: ofbx.cpp:1482
Cluster(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1253
int getIndicesCount() const override
Definition: ofbx.cpp:1267
bool postprocess(Allocator &allocator)
Definition: ofbx.cpp:1275
Matrix getTransformLinkMatrix() const override
Definition: ofbx.cpp:1271
Matrix transform_matrix
Definition: ofbx.cpp:1324
std::vector< double > weights
Definition: ofbx.cpp:1323
std::vector< int > indices
Definition: ofbx.cpp:1322
ClusterImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1261
int getWeightsCount() const override
Definition: ofbx.cpp:1269
const int * getIndices() const override
Definition: ofbx.cpp:1266
const double * getWeights() const override
Definition: ofbx.cpp:1268
Object * getLink() const override
Definition: ofbx.cpp:1272
Matrix transform_link_matrix
Definition: ofbx.cpp:1325
Type getType() const override
Definition: ofbx.cpp:1326
Object * link
Definition: ofbx.cpp:1320
Matrix getTransformMatrix() const override
Definition: ofbx.cpp:1270
float b
Definition: ofbx.h:67
float r
Definition: ofbx.h:67
float g
Definition: ofbx.h:67
const u8 * current
Definition: ofbx.cpp:149
const u8 * end
Definition: ofbx.cpp:151
const u8 * begin
Definition: ofbx.cpp:150
bool operator==(const char *rhs) const
Definition: ofbx.cpp:379
const u8 * begin
Definition: ofbx.h:73
int toInt() const
Definition: ofbx.cpp:327
u64 toU64() const
Definition: ofbx.cpp:299
bool is_binary
Definition: ofbx.h:75
i64 toI64() const
Definition: ofbx.cpp:313
void toString(char(&out)[N]) const
Definition: ofbx.h:88
float toFloat() const
Definition: ofbx.cpp:366
double toDouble() const
Definition: ofbx.cpp:353
u32 toU32() const
Definition: ofbx.cpp:340
const u8 * end
Definition: ofbx.h:74
Element * sibling
Definition: ofbx.cpp:452
IElementProperty * getFirstProperty() const override
Definition: ofbx.cpp:438
DataView getID() const override
Definition: ofbx.cpp:437
DataView id
Definition: ofbx.cpp:450
IElementProperty * getProperty(int idx) const
Definition: ofbx.cpp:439
Property * first_property
Definition: ofbx.cpp:453
IElement * getFirstChild() const override
Definition: ofbx.cpp:435
Element * child
Definition: ofbx.cpp:451
IElement * getSibling() const override
Definition: ofbx.cpp:436
static const char * s_message
Definition: ofbx.cpp:88
Error(const char *msg)
Definition: ofbx.cpp:86
static const int s_uvs_max
Definition: ofbx.h:349
Geometry(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1168
int getIndexCount() const override
Definition: ofbx.cpp:1214
const Vec2 * getUVs(int index=0) const override
Definition: ofbx.cpp:1217
const Skin * getSkin() const override
Definition: ofbx.cpp:1220
std::vector< NewVertex > to_new_vertices
Definition: ofbx.cpp:1203
const BlendShape * blendShape
Definition: ofbx.cpp:1199
std::vector< int > materials
Definition: ofbx.cpp:1196
const Vec3 * getTangents() const override
Definition: ofbx.cpp:1219
std::vector< Vec3 > normals
Definition: ofbx.cpp:1192
std::vector< int > to_old_vertices
Definition: ofbx.cpp:1202
const Vec4 * getColors() const override
Definition: ofbx.cpp:1218
std::vector< Vec3 > vertices
Definition: ofbx.cpp:1191
GeometryImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1205
int getVertexCount() const override
Definition: ofbx.cpp:1212
const BlendShape * getBlendShape() const override
Definition: ofbx.cpp:1221
const int * getMaterials() const override
Definition: ofbx.cpp:1222
std::vector< Vec3 > tangents
Definition: ofbx.cpp:1195
const Skin * skin
Definition: ofbx.cpp:1198
std::vector< Vec4 > colors
Definition: ofbx.cpp:1194
const int * getFaceIndices() const override
Definition: ofbx.cpp:1213
const Vec3 * getNormals() const override
Definition: ofbx.cpp:1216
std::vector< int > indices
Definition: ofbx.cpp:1201
std::vector< Vec2 > uvs[s_uvs_max]
Definition: ofbx.cpp:1193
const Vec3 * getVertices() const override
Definition: ofbx.cpp:1215
Type getType() const override
Definition: ofbx.cpp:1211
float CustomFrameRate
Definition: ofbx.h:509
FrameRate TimeMode
Definition: ofbx.h:508
u32 version
Definition: ofbx.cpp:142
u8 magic[21]
Definition: ofbx.cpp:140
u8 reserved[2]
Definition: ofbx.cpp:141
virtual IElementProperty * getFirstProperty() const =0
virtual IElementProperty * getNext() const =0
virtual DataView getValue() const =0
LimbNodeImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1128
Type getType() const override
Definition: ofbx.cpp:1133
Material(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1076
double getReflectionFactor() const override
Definition: ofbx.cpp:1101
Color getAmbientColor() const override
Definition: ofbx.cpp:1096
double bump_factor
Definition: ofbx.cpp:1121
double getDiffuseFactor() const override
Definition: ofbx.cpp:1099
double diffuse_factor
Definition: ofbx.cpp:1115
double shininess
Definition: ofbx.cpp:1118
double getShininessExponent() const override
Definition: ofbx.cpp:1103
Color getSpecularColor() const override
Definition: ofbx.cpp:1094
Color specular_color
Definition: ofbx.cpp:1110
MaterialImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1084
Type getType() const override
Definition: ofbx.cpp:1090
Color getEmissiveColor() const override
Definition: ofbx.cpp:1097
Color ambient_color
Definition: ofbx.cpp:1112
double ambient_factor
Definition: ofbx.cpp:1120
Color getReflectionColor() const override
Definition: ofbx.cpp:1095
Color reflection_color
Definition: ofbx.cpp:1111
Color emissive_color
Definition: ofbx.cpp:1113
const Texture * getTexture(Texture::TextureType type) const override
Definition: ofbx.cpp:1092
double getShininess() const override
Definition: ofbx.cpp:1102
double getSpecularFactor() const override
Definition: ofbx.cpp:1100
Color diffuse_color
Definition: ofbx.cpp:1109
double reflection_factor
Definition: ofbx.cpp:1117
double getAmbientFactor() const override
Definition: ofbx.cpp:1104
double shininess_exponent
Definition: ofbx.cpp:1119
const Texture * textures[Texture::TextureType::COUNT]
Definition: ofbx.cpp:1108
double specular_factor
Definition: ofbx.cpp:1116
double emissive_factor
Definition: ofbx.cpp:1122
double getBumpFactor() const override
Definition: ofbx.cpp:1105
double getEmissiveFactor() const override
Definition: ofbx.cpp:1106
Color getDiffuseColor() const override
Definition: ofbx.cpp:1093
double m[16]
Definition: ofbx.h:55
Mesh(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1029
const Material * getMaterial(int index) const override
Definition: ofbx.cpp:1066
const Pose * getPose() const override
Definition: ofbx.cpp:1064
const Geometry * getGeometry() const override
Definition: ofbx.cpp:1065
MeshImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1037
std::vector< const Material * > materials
Definition: ofbx.cpp:1072
Type getType() const override
Definition: ofbx.cpp:1061
const Geometry * geometry
Definition: ofbx.cpp:1071
Matrix getGeometricMatrix() const override
Definition: ofbx.cpp:1044
const Pose * pose
Definition: ofbx.cpp:1070
int getMaterialCount() const override
Definition: ofbx.cpp:1067
NodeAttribute(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1148
NodeAttributeImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1156
DataView attribute_type
Definition: ofbx.cpp:1164
Type getType() const override
Definition: ofbx.cpp:1160
DataView getAttributeType() const override
Definition: ofbx.cpp:1161
NullImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1139
Type getType() const override
Definition: ofbx.cpp:1144
Matrix getLocalTransform() const
Definition: ofbx.cpp:3509
Vec3 getScalingOffset() const
Definition: ofbx.cpp:3416
Vec3 getRotationPivot() const
Definition: ofbx.cpp:3404
virtual Type getType() const =0
const IElement & element
Definition: ofbx.h:220
Matrix evalLocal(const Vec3 &translation, const Vec3 &rotation) const
Definition: ofbx.cpp:3428
Vec3 getLocalScaling() const
Definition: ofbx.cpp:3494
bool isNode() const
Definition: ofbx.h:210
Vec3 getScalingPivot() const
Definition: ofbx.cpp:3422
Object * resolveObjectLinkReverse(Type type) const
Definition: ofbx.cpp:3515
const IScene & getScene() const
Definition: ofbx.cpp:3531
Object * resolveObjectLink(int idx) const
Definition: ofbx.cpp:3537
char name[128]
Definition: ofbx.h:219
RotationOrder getRotationOrder() const
Definition: ofbx.cpp:3391
Vec3 getLocalTranslation() const
Definition: ofbx.cpp:3476
Vec3 getPostRotation() const
Definition: ofbx.cpp:3410
Vec3 getRotationOffset() const
Definition: ofbx.cpp:3398
Matrix getGlobalTransform() const
Definition: ofbx.cpp:3500
const Object * node_attribute
Definition: ofbx.h:221
const Scene & scene
Definition: ofbx.h:225
u64 id
Definition: ofbx.h:218
Vec3 getPreRotation() const
Definition: ofbx.cpp:3482
bool is_node
Definition: ofbx.h:224
Object(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:509
Object * getParent() const
Definition: ofbx.cpp:3578
Vec3 getLocalRotation() const
Definition: ofbx.cpp:3488
OptionalError(Error error)
Definition: ofbx.cpp:97
OptionalError(T _value)
Definition: ofbx.cpp:103
T getValue() const
Definition: ofbx.cpp:110
GeometryImpl * geom
Definition: ofbx.cpp:3010
const Element * element
Definition: ofbx.cpp:3008
Pose(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1494
Matrix getMatrix() const override
Definition: ofbx.cpp:1510
Matrix matrix
Definition: ofbx.cpp:1515
const Object * getNode() const override
Definition: ofbx.cpp:1511
DataView node_id
Definition: ofbx.cpp:1517
Type getType() const override
Definition: ofbx.cpp:1513
bool postprocess(Scene *scene)
Definition: ofbx.cpp:1674
PoseImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1502
Object * node
Definition: ofbx.cpp:1516
IElementProperty * getNext() const override
Definition: ofbx.cpp:402
Type getType() const override
Definition: ofbx.cpp:401
bool getValues(u64 *values, int max_size) const override
Definition: ofbx.cpp:420
bool getValues(i64 *values, int max_size) const override
Definition: ofbx.cpp:422
DataView value
Definition: ofbx.cpp:428
bool getValues(int *values, int max_size) const override
Definition: ofbx.cpp:424
int getCount() const override
Definition: ofbx.cpp:404
bool getValues(float *values, int max_size) const override
Definition: ofbx.cpp:418
Property * next
Definition: ofbx.cpp:429
DataView getValue() const override
Definition: ofbx.cpp:403
bool getValues(double *values, int max_size) const override
Definition: ofbx.cpp:416
Root(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1541
Type getType() const override
Definition: ofbx.cpp:1547
const Element * element
Definition: ofbx.cpp:1569
std::vector< Connection > m_connections
Definition: ofbx.cpp:1653
const AnimationStack * getAnimationStack(int index) const override
Definition: ofbx.cpp:1597
DataView getEmbeddedData(int index) const override
Definition: ofbx.cpp:1589
GlobalSettings m_settings
Definition: ofbx.cpp:1647
~Scene() override
Definition: ofbx.cpp:1638
void destroy() override
Definition: ofbx.cpp:1635
std::vector< AnimationStack * > m_animation_stacks
Definition: ofbx.cpp:1652
std::vector< u8 > m_data
Definition: ofbx.cpp:1654
int getGeometryCount() const override
Definition: ofbx.cpp:1575
int getMeshCount() const override
Definition: ofbx.cpp:1576
float m_scene_frame_rate
Definition: ofbx.cpp:1646
Root * m_root
Definition: ofbx.cpp:1645
const Geometry * getGeometry(int index) const override
Definition: ofbx.cpp:1613
const Object *const * getAllObjects() const override
Definition: ofbx.cpp:1580
const Object * getRoot() const override
Definition: ofbx.cpp:1632
const GlobalSettings * getGlobalSettings() const override
Definition: ofbx.cpp:1578
DataView getEmbeddedFilename(int index) const override
Definition: ofbx.cpp:1593
const IElement * getRootElement() const override
Definition: ofbx.cpp:1631
float getSceneFrameRate() const override
Definition: ofbx.cpp:1577
Element * m_root_element
Definition: ofbx.cpp:1644
int getAllObjectCount() const override
Definition: ofbx.cpp:1583
const TakeInfo * getTakeInfo(const char *name) const override
Definition: ofbx.cpp:1621
std::vector< TakeInfo > m_take_infos
Definition: ofbx.cpp:1655
Allocator m_allocator
Definition: ofbx.cpp:1657
std::unordered_map< u64, ObjectPair > m_object_map
Definition: ofbx.cpp:1648
std::vector< Video > m_videos
Definition: ofbx.cpp:1656
std::vector< Object * > m_all_objects
Definition: ofbx.cpp:1649
const Mesh * getMesh(int index) const override
Definition: ofbx.cpp:1605
int getAnimationStackCount() const override
Definition: ofbx.cpp:1574
int getEmbeddedDataCount() const override
Definition: ofbx.cpp:1585
std::vector< Mesh * > m_meshes
Definition: ofbx.cpp:1650
std::vector< Geometry * > m_geometries
Definition: ofbx.cpp:1651
Shape(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1226
bool postprocess(GeometryImpl *geom, Allocator &allocator)
Definition: ofbx.cpp:2757
const Vec3 * getNormals() const override
Definition: ofbx.cpp:1249
ShapeImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1237
Type getType() const override
Definition: ofbx.cpp:1246
int getVertexCount() const override
Definition: ofbx.cpp:1247
std::vector< Vec3 > vertices
Definition: ofbx.cpp:1234
const Vec3 * getVertices() const override
Definition: ofbx.cpp:1248
std::vector< Vec3 > normals
Definition: ofbx.cpp:1235
Skin(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1389
const Cluster * getCluster(int idx) const override
Definition: ofbx.cpp:1403
SkinImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1397
std::vector< Cluster * > clusters
Definition: ofbx.cpp:1407
Type getType() const override
Definition: ofbx.cpp:1405
int getClusterCount() const override
Definition: ofbx.cpp:1402
double reference_time_from
Definition: ofbx.h:449
DataView name
Definition: ofbx.h:445
DataView filename
Definition: ofbx.h:446
double reference_time_to
Definition: ofbx.h:450
double local_time_to
Definition: ofbx.h:448
double local_time_from
Definition: ofbx.h:447
std::vector< int > i
Definition: ofbx.cpp:68
std::vector< Vec3 > v3
Definition: ofbx.cpp:70
std::vector< Vec4 > v4
Definition: ofbx.cpp:71
std::vector< float > f
Definition: ofbx.cpp:67
std::vector< Vec2 > v2
Definition: ofbx.cpp:69
Texture(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1488
@ SPECULAR
Definition: ofbx.h:244
@ EMISSIVE
Definition: ofbx.h:247
@ REFLECTION
Definition: ofbx.h:248
@ SHININESS
Definition: ofbx.h:245
DataView getEmbeddedData() const override
Definition: ofbx.cpp:1661
DataView getRelativeFileName() const override
Definition: ofbx.cpp:1528
DataView getFileName() const override
Definition: ofbx.cpp:1529
DataView relative_filename
Definition: ofbx.cpp:1534
DataView media
Definition: ofbx.cpp:1532
Type getType() const override
Definition: ofbx.cpp:1535
TextureImpl(const Scene &_scene, const IElement &_element)
Definition: ofbx.cpp:1523
DataView filename
Definition: ofbx.cpp:1533
double x
Definition: ofbx.h:37
double y
Definition: ofbx.h:43
double z
Definition: ofbx.h:43
double x
Definition: ofbx.h:43
double x
Definition: ofbx.h:49
DataView media
Definition: ofbx.cpp:79
DataView filename
Definition: ofbx.cpp:77
DataView content
Definition: ofbx.cpp:78