1 #include "ofbx.h"
2 #include "miniz.h"
3 #include <cassert>
4 #include <cmath>
5 #include <ctype.h>
6 #include <memory>
7 #include <unordered_map>
8 #include <vector>
9 #include <string>
10
11
12 namespace ofbx
13 {
14
15
16 struct Error
17 {
Errorofbx::Error18 Error() {}
Errorofbx::Error19 Error(const char* msg) { s_message = msg; }
20
21 static const char* s_message;
22 };
23
24
25 const char* Error::s_message = "";
26
27
28 template <typename T> struct OptionalError
29 {
OptionalErrorofbx::OptionalError30 OptionalError(Error error)
31 : is_error(true)
32 {
33 }
34
35
OptionalErrorofbx::OptionalError36 OptionalError(T _value)
37 : value(_value)
38 , is_error(false)
39 {
40 }
41
42
getValueofbx::OptionalError43 T getValue() const
44 {
45 #ifdef _DEBUG
46 assert(error_checked);
47 #endif
48 return value;
49 }
50
51
isErrorofbx::OptionalError52 bool isError()
53 {
54 #ifdef _DEBUG
55 error_checked = true;
56 #endif
57 return is_error;
58 }
59
60
61 private:
62 T value;
63 bool is_error;
64 #ifdef _DEBUG
65 bool error_checked = false;
66 #endif
67 };
68
69
70 #pragma pack(1)
71 struct Header
72 {
73 u8 magic[21];
74 u8 reserved[2];
75 u32 version;
76 };
77 #pragma pack()
78
79
80 struct Cursor
81 {
82 const u8* current;
83 const u8* begin;
84 const u8* end;
85 };
86
87
setTranslation(const Vec3 & t,Matrix * mtx)88 static void setTranslation(const Vec3& t, Matrix* mtx)
89 {
90 mtx->m[12] = t.x;
91 mtx->m[13] = t.y;
92 mtx->m[14] = t.z;
93 }
94
95
operator -(const Vec3 & v)96 static Vec3 operator-(const Vec3& v)
97 {
98 return {-v.x, -v.y, -v.z};
99 }
100
101
operator *(const Matrix & lhs,const Matrix & rhs)102 static Matrix operator*(const Matrix& lhs, const Matrix& rhs)
103 {
104 Matrix res;
105 for (int j = 0; j < 4; ++j)
106 {
107 for (int i = 0; i < 4; ++i)
108 {
109 double tmp = 0;
110 for (int k = 0; k < 4; ++k)
111 {
112 tmp += lhs.m[i + k * 4] * rhs.m[k + j * 4];
113 }
114 res.m[i + j * 4] = tmp;
115 }
116 }
117 return res;
118 }
119
120
makeIdentity()121 static Matrix makeIdentity()
122 {
123 return {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
124 }
125
126
rotationX(double angle)127 static Matrix rotationX(double angle)
128 {
129 Matrix m = makeIdentity();
130 double c = cos(angle);
131 double s = sin(angle);
132
133 m.m[5] = m.m[10] = c;
134 m.m[9] = -s;
135 m.m[6] = s;
136
137 return m;
138 }
139
140
rotationY(double angle)141 static Matrix rotationY(double angle)
142 {
143 Matrix m = makeIdentity();
144 double c = cos(angle);
145 double s = sin(angle);
146
147 m.m[0] = m.m[10] = c;
148 m.m[8] = s;
149 m.m[2] = -s;
150
151 return m;
152 }
153
154
rotationZ(double angle)155 static Matrix rotationZ(double angle)
156 {
157 Matrix m = makeIdentity();
158 double c = cos(angle);
159 double s = sin(angle);
160
161 m.m[0] = m.m[5] = c;
162 m.m[4] = -s;
163 m.m[1] = s;
164
165 return m;
166 }
167
168
getRotationMatrix(const Vec3 & euler,RotationOrder order)169 static Matrix getRotationMatrix(const Vec3& euler, RotationOrder order)
170 {
171 const double TO_RAD = 3.1415926535897932384626433832795028 / 180.0;
172 Matrix rx = rotationX(euler.x * TO_RAD);
173 Matrix ry = rotationY(euler.y * TO_RAD);
174 Matrix rz = rotationZ(euler.z * TO_RAD);
175 switch (order) {
176 default:
177 case RotationOrder::SPHERIC_XYZ:
178 assert(false);
179 case RotationOrder::EULER_XYZ:
180 return rz * ry * rx;
181 case RotationOrder::EULER_XZY:
182 return ry * rz * rx;
183 case RotationOrder::EULER_YXZ:
184 return rz * rx * ry;
185 case RotationOrder::EULER_YZX:
186 return rx * rz * ry;
187 case RotationOrder::EULER_ZXY:
188 return ry * rx * rz;
189 case RotationOrder::EULER_ZYX:
190 return rx * ry * rz;
191 }
192 }
193
194
fbxTimeToSeconds(i64 value)195 static double fbxTimeToSeconds(i64 value)
196 {
197 return double(value) / 46186158000L;
198 }
199
200
secondsToFbxTime(double value)201 static i64 secondsToFbxTime(double value)
202 {
203 return i64(value * 46186158000L);
204 }
205
206
operator *(const Vec3 & v,float f)207 static Vec3 operator*(const Vec3& v, float f)
208 {
209 return {v.x * f, v.y * f, v.z * f};
210 }
211
212
operator +(const Vec3 & a,const Vec3 & b)213 static Vec3 operator+(const Vec3& a, const Vec3& b)
214 {
215 return {a.x + b.x, a.y + b.y, a.z + b.z};
216 }
217
218
copyString(char (& destination)[SIZE],const char * source)219 template <int SIZE> static bool copyString(char (&destination)[SIZE], const char* source)
220 {
221 const char* src = source;
222 char* dest = destination;
223 int length = SIZE;
224 if (!src) return false;
225
226 while (*src && length > 1)
227 {
228 *dest = *src;
229 --length;
230 ++dest;
231 ++src;
232 }
233 *dest = 0;
234 return *src == '\0';
235 }
236
237
toU64() const238 u64 DataView::toU64() const
239 {
240 if (is_binary)
241 {
242 assert(end - begin == sizeof(u64));
243 return *(u64*)begin;
244 }
245 static_assert(sizeof(unsigned long long) >= sizeof(u64), "can't use strtoull");
246 return strtoull((const char*)begin, nullptr, 10);
247 }
248
249
toI64() const250 i64 DataView::toI64() const
251 {
252 if (is_binary)
253 {
254 assert(end - begin == sizeof(i64));
255 return *(i64*)begin;
256 }
257 static_assert(sizeof(long long) >= sizeof(i64), "can't use atoll");
258 return atoll((const char*)begin);
259 }
260
261
toInt() const262 int DataView::toInt() const
263 {
264 if (is_binary)
265 {
266 assert(end - begin == sizeof(int));
267 return *(int*)begin;
268 }
269 return atoi((const char*)begin);
270 }
271
272
toU32() const273 u32 DataView::toU32() const
274 {
275 if (is_binary)
276 {
277 assert(end - begin == sizeof(u32));
278 return *(u32*)begin;
279 }
280 return (u32)atoll((const char*)begin);
281 }
282
283
toDouble() const284 double DataView::toDouble() const
285 {
286 if (is_binary)
287 {
288 assert(end - begin == sizeof(double));
289 return *(double*)begin;
290 }
291 return atof((const char*)begin);
292 }
293
294
toFloat() const295 float DataView::toFloat() const
296 {
297 if (is_binary)
298 {
299 assert(end - begin == sizeof(float));
300 return *(float*)begin;
301 }
302 return (float)atof((const char*)begin);
303 }
304
305
operator ==(const char * rhs) const306 bool DataView::operator==(const char* rhs) const
307 {
308 const char* c = rhs;
309 const char* c2 = (const char*)begin;
310 while (*c && c2 != (const char*)end)
311 {
312 if (*c != *c2) return 0;
313 ++c;
314 ++c2;
315 }
316 return c2 == (const char*)end && *c == '\0';
317 }
318
319
320 struct Property;
321 template <typename T> static bool parseArrayRaw(const Property& property, T* out, int max_size);
322 template <typename T> static bool parseBinaryArray(const Property& property, std::vector<T>* out);
323
324
325 struct Property : IElementProperty
326 {
~Propertyofbx::Property327 ~Property() { delete next; }
getTypeofbx::Property328 Type getType() const override { return (Type)type; }
getNextofbx::Property329 IElementProperty* getNext() const override { return next; }
getValueofbx::Property330 DataView getValue() const override { return value; }
getCountofbx::Property331 int getCount() const override
332 {
333 assert(type == ARRAY_DOUBLE || type == ARRAY_INT || type == ARRAY_FLOAT || type == ARRAY_LONG);
334 if (value.is_binary)
335 {
336 return int(*(u32*)value.begin);
337 }
338 return count;
339 }
340
getValuesofbx::Property341 bool getValues(double* values, int max_size) const override { return parseArrayRaw(*this, values, max_size); }
342
getValuesofbx::Property343 bool getValues(float* values, int max_size) const override { return parseArrayRaw(*this, values, max_size); }
344
getValuesofbx::Property345 bool getValues(u64* values, int max_size) const override { return parseArrayRaw(*this, values, max_size); }
346
getValuesofbx::Property347 bool getValues(i64* values, int max_size) const override { return parseArrayRaw(*this, values, max_size); }
348
getValuesofbx::Property349 bool getValues(int* values, int max_size) const override { return parseArrayRaw(*this, values, max_size); }
350
351 int count;
352 u8 type;
353 DataView value;
354 Property* next = nullptr;
355 };
356
357
358 struct Element final : IElement
359 {
getFirstChildofbx::Element360 IElement* getFirstChild() const override { return child; }
getSiblingofbx::Element361 IElement* getSibling() const override { return sibling; }
getIDofbx::Element362 DataView getID() const override { return id; }
getFirstPropertyofbx::Element363 IElementProperty* getFirstProperty() const override { return first_property; }
getPropertyofbx::Element364 IElementProperty* getProperty(int idx) const
365 {
366 IElementProperty* prop = first_property;
367 for (int i = 0; i < idx; ++i)
368 {
369 if (prop == nullptr) return nullptr;
370 prop = prop->getNext();
371 }
372 return prop;
373 }
374
375 DataView id;
376 Element* child = nullptr;
377 Element* sibling = nullptr;
378 Property* first_property = nullptr;
379 };
380
381
findChild(const Element & element,const char * id)382 static const Element* findChild(const Element& element, const char* id)
383 {
384 Element* const* iter = &element.child;
385 while (*iter)
386 {
387 if ((*iter)->id == id) return *iter;
388 iter = &(*iter)->sibling;
389 }
390 return nullptr;
391 }
392
393
resolveProperty(const Object & obj,const char * name)394 static IElement* resolveProperty(const Object& obj, const char* name)
395 {
396 const Element* props = findChild((const Element&)obj.element, "Properties70");
397 if (!props) return nullptr;
398
399 Element* prop = props->child;
400 while (prop)
401 {
402 if (prop->first_property && prop->first_property->value == name)
403 {
404 return prop;
405 }
406 prop = prop->sibling;
407 }
408 return nullptr;
409 }
410
411
resolveEnumProperty(const Object & object,const char * name,int default_value)412 static int resolveEnumProperty(const Object& object, const char* name, int default_value)
413 {
414 Element* element = (Element*)resolveProperty(object, name);
415 if (!element) return default_value;
416 Property* x = (Property*)element->getProperty(4);
417 if (!x) return default_value;
418
419 return x->value.toInt();
420 }
421
422
resolveVec3Property(const Object & object,const char * name,const Vec3 & default_value)423 static Vec3 resolveVec3Property(const Object& object, const char* name, const Vec3& default_value)
424 {
425 Element* element = (Element*)resolveProperty(object, name);
426 if (!element) return default_value;
427 Property* x = (Property*)element->getProperty(4);
428 if (!x || !x->next || !x->next->next) return default_value;
429
430 return {x->value.toDouble(), x->next->value.toDouble(), x->next->next->value.toDouble()};
431 }
432
433
Object(const Scene & _scene,const IElement & _element)434 Object::Object(const Scene& _scene, const IElement& _element)
435 : scene(_scene)
436 , element(_element)
437 , is_node(false)
438 , node_attribute(nullptr)
439 {
440 auto& e = (Element&)_element;
441 if (e.first_property && e.first_property->next)
442 {
443 e.first_property->next->value.toString(name);
444 }
445 else
446 {
447 name[0] = '\0';
448 }
449 }
450
451
decompress(const u8 * in,size_t in_size,u8 * out,size_t out_size)452 static bool decompress(const u8* in, size_t in_size, u8* out, size_t out_size)
453 {
454 mz_stream stream = {};
455 mz_inflateInit(&stream);
456
457 stream.avail_in = (int)in_size;
458 stream.next_in = in;
459 stream.avail_out = (int)out_size;
460 stream.next_out = out;
461
462 int status = mz_inflate(&stream, Z_SYNC_FLUSH);
463
464 if (status != Z_STREAM_END) return false;
465
466 return mz_inflateEnd(&stream) == Z_OK;
467 }
468
469
read(Cursor * cursor)470 template <typename T> static OptionalError<T> read(Cursor* cursor)
471 {
472 if (cursor->current + sizeof(T) > cursor->end) return Error("Reading past the end");
473 T value = *(const T*)cursor->current;
474 cursor->current += sizeof(T);
475 return value;
476 }
477
478
readShortString(Cursor * cursor)479 static OptionalError<DataView> readShortString(Cursor* cursor)
480 {
481 DataView value;
482 OptionalError<u8> length = read<u8>(cursor);
483 if (length.isError()) return Error();
484
485 if (cursor->current + length.getValue() > cursor->end) return Error("Reading past the end");
486 value.begin = cursor->current;
487 cursor->current += length.getValue();
488
489 value.end = cursor->current;
490
491 return value;
492 }
493
494
readLongString(Cursor * cursor)495 static OptionalError<DataView> readLongString(Cursor* cursor)
496 {
497 DataView value;
498 OptionalError<u32> length = read<u32>(cursor);
499 if (length.isError()) return Error();
500
501 if (cursor->current + length.getValue() > cursor->end) return Error("Reading past the end");
502 value.begin = cursor->current;
503 cursor->current += length.getValue();
504
505 value.end = cursor->current;
506
507 return value;
508 }
509
510
readProperty(Cursor * cursor)511 static OptionalError<Property*> readProperty(Cursor* cursor)
512 {
513 if (cursor->current == cursor->end) return Error("Reading past the end");
514
515 std::unique_ptr<Property> prop(new Property());
516 prop->next = nullptr;
517 prop->type = *cursor->current;
518 ++cursor->current;
519 prop->value.begin = cursor->current;
520
521 switch (prop->type)
522 {
523 case 'S':
524 {
525 OptionalError<DataView> val = readLongString(cursor);
526 if (val.isError()) return Error();
527 prop->value = val.getValue();
528 break;
529 }
530 case 'Y': cursor->current += 2; break;
531 case 'C': cursor->current += 1; break;
532 case 'I': cursor->current += 4; break;
533 case 'F': cursor->current += 4; break;
534 case 'D': cursor->current += 8; break;
535 case 'L': cursor->current += 8; break;
536 case 'R':
537 {
538 OptionalError<u32> len = read<u32>(cursor);
539 if (len.isError()) return Error();
540 if (cursor->current + len.getValue() > cursor->end) return Error("Reading past the end");
541 cursor->current += len.getValue();
542 break;
543 }
544 case 'b':
545 case 'f':
546 case 'd':
547 case 'l':
548 case 'i':
549 {
550 OptionalError<u32> length = read<u32>(cursor);
551 OptionalError<u32> encoding = read<u32>(cursor);
552 OptionalError<u32> comp_len = read<u32>(cursor);
553 if (length.isError() | encoding.isError() | comp_len.isError()) return Error();
554 if (cursor->current + comp_len.getValue() > cursor->end) return Error("Reading past the end");
555 cursor->current += comp_len.getValue();
556 break;
557 }
558 default: return Error("Unknown property type");
559 }
560 prop->value.end = cursor->current;
561 return prop.release();
562 }
563
564
deleteElement(Element * el)565 static void deleteElement(Element* el)
566 {
567 if (!el) return;
568
569 Element* iter = el;
570 // do not use recursion to delete siblings to avoid stack overflow
571 do
572 {
573 Element* next = iter->sibling;
574 delete iter->first_property;
575 deleteElement(iter->child);
576 delete iter;
577 iter = next;
578 } while (iter);
579 }
580
581
582
readElementOffset(Cursor * cursor,u16 version)583 static OptionalError<u64> readElementOffset(Cursor* cursor, u16 version)
584 {
585 if (version >= 7500)
586 {
587 OptionalError<u64> tmp = read<u64>(cursor);
588 if (tmp.isError()) return Error();
589 return tmp.getValue();
590 }
591
592 OptionalError<u32> tmp = read<u32>(cursor);
593 if (tmp.isError()) return Error();
594 return tmp.getValue();
595 }
596
597
readElement(Cursor * cursor,u32 version)598 static OptionalError<Element*> readElement(Cursor* cursor, u32 version)
599 {
600 OptionalError<u64> end_offset = readElementOffset(cursor, version);
601 if (end_offset.isError()) return Error();
602 if (end_offset.getValue() == 0) return nullptr;
603
604 OptionalError<u64> prop_count = readElementOffset(cursor, version);
605 OptionalError<u64> prop_length = readElementOffset(cursor, version);
606 if (prop_count.isError() || prop_length.isError()) return Error();
607
608 const char* sbeg = 0;
609 const char* send = 0;
610 OptionalError<DataView> id = readShortString(cursor);
611 if (id.isError()) return Error();
612
613 Element* element = new Element();
614 element->first_property = nullptr;
615 element->id = id.getValue();
616
617 element->child = nullptr;
618 element->sibling = nullptr;
619
620 Property** prop_link = &element->first_property;
621 for (u32 i = 0; i < prop_count.getValue(); ++i)
622 {
623 OptionalError<Property*> prop = readProperty(cursor);
624 if (prop.isError())
625 {
626 deleteElement(element);
627 return Error();
628 }
629
630 *prop_link = prop.getValue();
631 prop_link = &(*prop_link)->next;
632 }
633
634 if (cursor->current - cursor->begin >= (ptrdiff_t)end_offset.getValue()) return element;
635
636 int BLOCK_SENTINEL_LENGTH = version >= 7500 ? 25 : 13;
637
638 Element** link = &element->child;
639 while (cursor->current - cursor->begin < ((ptrdiff_t)end_offset.getValue() - BLOCK_SENTINEL_LENGTH))
640 {
641 OptionalError<Element*> child = readElement(cursor, version);
642 if (child.isError())
643 {
644 deleteElement(element);
645 return Error();
646 }
647
648 *link = child.getValue();
649 link = &(*link)->sibling;
650 }
651
652 if (cursor->current + BLOCK_SENTINEL_LENGTH > cursor->end)
653 {
654 deleteElement(element);
655 return Error("Reading past the end");
656 }
657
658 cursor->current += BLOCK_SENTINEL_LENGTH;
659 return element;
660 }
661
662
isEndLine(const Cursor & cursor)663 static bool isEndLine(const Cursor& cursor)
664 {
665 return *cursor.current == '\n';
666 }
667
668
skipInsignificantWhitespaces(Cursor * cursor)669 static void skipInsignificantWhitespaces(Cursor* cursor)
670 {
671 while (cursor->current < cursor->end && isspace(*cursor->current) && *cursor->current != '\n')
672 {
673 ++cursor->current;
674 }
675 }
676
677
skipLine(Cursor * cursor)678 static void skipLine(Cursor* cursor)
679 {
680 while (cursor->current < cursor->end && !isEndLine(*cursor))
681 {
682 ++cursor->current;
683 }
684 if (cursor->current < cursor->end) ++cursor->current;
685 skipInsignificantWhitespaces(cursor);
686 }
687
688
skipWhitespaces(Cursor * cursor)689 static void skipWhitespaces(Cursor* cursor)
690 {
691 while (cursor->current < cursor->end && isspace(*cursor->current))
692 {
693 ++cursor->current;
694 }
695 while (cursor->current < cursor->end && *cursor->current == ';') skipLine(cursor);
696 }
697
698
isTextTokenChar(char c)699 static bool isTextTokenChar(char c)
700 {
701 return isalnum(c) || c == '_';
702 }
703
704
readTextToken(Cursor * cursor)705 static DataView readTextToken(Cursor* cursor)
706 {
707 DataView ret;
708 ret.begin = cursor->current;
709 while (cursor->current < cursor->end && isTextTokenChar(*cursor->current))
710 {
711 ++cursor->current;
712 }
713 ret.end = cursor->current;
714 return ret;
715 }
716
717
readTextProperty(Cursor * cursor)718 static OptionalError<Property*> readTextProperty(Cursor* cursor)
719 {
720 std::unique_ptr<Property> prop(new Property());
721 prop->value.is_binary = false;
722 prop->next = nullptr;
723 if (*cursor->current == '"')
724 {
725 prop->type = 'S';
726 ++cursor->current;
727 prop->value.begin = cursor->current;
728 while (cursor->current < cursor->end && *cursor->current != '"')
729 {
730 ++cursor->current;
731 }
732 prop->value.end = cursor->current;
733 if (cursor->current < cursor->end) ++cursor->current; // skip '"'
734 return prop.release();
735 }
736
737 if (isdigit(*cursor->current) || *cursor->current == '-')
738 {
739 prop->type = 'L';
740 prop->value.begin = cursor->current;
741 if (*cursor->current == '-') ++cursor->current;
742 while (cursor->current < cursor->end && isdigit(*cursor->current))
743 {
744 ++cursor->current;
745 }
746 prop->value.end = cursor->current;
747
748 if (cursor->current < cursor->end && *cursor->current == '.')
749 {
750 prop->type = 'D';
751 ++cursor->current;
752 while (cursor->current < cursor->end && isdigit(*cursor->current))
753 {
754 ++cursor->current;
755 }
756 if (cursor->current < cursor->end && (*cursor->current == 'e' || *cursor->current == 'E'))
757 {
758 // 10.5e-013
759 ++cursor->current;
760 if (cursor->current < cursor->end && *cursor->current == '-') ++cursor->current;
761 while (cursor->current < cursor->end && isdigit(*cursor->current)) ++cursor->current;
762 }
763
764
765 prop->value.end = cursor->current;
766 }
767 return prop.release();
768 }
769
770 if (*cursor->current == 'T' || *cursor->current == 'Y')
771 {
772 // WTF is this
773 prop->type = *cursor->current;
774 prop->value.begin = cursor->current;
775 ++cursor->current;
776 prop->value.end = cursor->current;
777 return prop.release();
778 }
779
780 if (*cursor->current == '*')
781 {
782 prop->type = 'l';
783 ++cursor->current;
784 // Vertices: *10740 { a: 14.2760353088379,... }
785 while (cursor->current < cursor->end && *cursor->current != ':')
786 {
787 ++cursor->current;
788 }
789 if (cursor->current < cursor->end) ++cursor->current; // skip ':'
790 skipInsignificantWhitespaces(cursor);
791 prop->value.begin = cursor->current;
792 prop->count = 0;
793 bool is_any = false;
794 while (cursor->current < cursor->end && *cursor->current != '}')
795 {
796 if (*cursor->current == ',')
797 {
798 if (is_any) ++prop->count;
799 is_any = false;
800 }
801 else if (!isspace(*cursor->current) && *cursor->current != '\n') is_any = true;
802 if (*cursor->current == '.') prop->type = 'd';
803 ++cursor->current;
804 }
805 if (is_any) ++prop->count;
806 prop->value.end = cursor->current;
807 if (cursor->current < cursor->end) ++cursor->current; // skip '}'
808 return prop.release();
809 }
810
811 assert(false);
812 return Error("TODO");
813 }
814
815
readTextElement(Cursor * cursor)816 static OptionalError<Element*> readTextElement(Cursor* cursor)
817 {
818 DataView id = readTextToken(cursor);
819 if (cursor->current == cursor->end) return Error("Unexpected end of file");
820 if(*cursor->current != ':') return Error("Unexpected end of file");
821 ++cursor->current;
822
823 skipWhitespaces(cursor);
824 if (cursor->current == cursor->end) return Error("Unexpected end of file");
825
826 Element* element = new Element;
827 element->id = id;
828
829 Property** prop_link = &element->first_property;
830 while (cursor->current < cursor->end && *cursor->current != '\n' && *cursor->current != '{')
831 {
832 OptionalError<Property*> prop = readTextProperty(cursor);
833 if (prop.isError())
834 {
835 deleteElement(element);
836 return Error();
837 }
838 if (cursor->current < cursor->end && *cursor->current == ',')
839 {
840 ++cursor->current;
841 skipWhitespaces(cursor);
842 }
843 skipInsignificantWhitespaces(cursor);
844
845 *prop_link = prop.getValue();
846 prop_link = &(*prop_link)->next;
847 }
848
849 Element** link = &element->child;
850 if (*cursor->current == '{')
851 {
852 ++cursor->current;
853 skipWhitespaces(cursor);
854 while (cursor->current < cursor->end && *cursor->current != '}')
855 {
856 OptionalError<Element*> child = readTextElement(cursor);
857 if (child.isError())
858 {
859 deleteElement(element);
860 return Error();
861 }
862 skipWhitespaces(cursor);
863
864 *link = child.getValue();
865 link = &(*link)->sibling;
866 }
867 if (cursor->current < cursor->end) ++cursor->current; // skip '}'
868 }
869 return element;
870 }
871
872
tokenizeText(const u8 * data,size_t size)873 static OptionalError<Element*> tokenizeText(const u8* data, size_t size)
874 {
875 Cursor cursor;
876 cursor.begin = data;
877 cursor.current = data;
878 cursor.end = data + size;
879
880 Element* root = new Element();
881 root->first_property = nullptr;
882 root->id.begin = nullptr;
883 root->id.end = nullptr;
884 root->child = nullptr;
885 root->sibling = nullptr;
886
887 Element** element = &root->child;
888 while (cursor.current < cursor.end)
889 {
890 if (*cursor.current == ';' || *cursor.current == '\r' || *cursor.current == '\n')
891 {
892 skipLine(&cursor);
893 }
894 else
895 {
896 OptionalError<Element*> child = readTextElement(&cursor);
897 if (child.isError())
898 {
899 deleteElement(root);
900 return Error();
901 }
902 *element = child.getValue();
903 if (!*element) return root;
904 element = &(*element)->sibling;
905 }
906 }
907
908 return root;
909 }
910
911
tokenize(const u8 * data,size_t size)912 static OptionalError<Element*> tokenize(const u8* data, size_t size)
913 {
914 Cursor cursor;
915 cursor.begin = data;
916 cursor.current = data;
917 cursor.end = data + size;
918
919 const Header* header = (const Header*)cursor.current;
920 cursor.current += sizeof(*header);
921
922 Element* root = new Element();
923 root->first_property = nullptr;
924 root->id.begin = nullptr;
925 root->id.end = nullptr;
926 root->child = nullptr;
927 root->sibling = nullptr;
928
929 Element** element = &root->child;
930 for (;;)
931 {
932 OptionalError<Element*> child = readElement(&cursor, header->version);
933 if (child.isError())
934 {
935 deleteElement(root);
936 return Error();
937 }
938 *element = child.getValue();
939 if (!*element) return root;
940 element = &(*element)->sibling;
941 }
942 }
943
944
parseTemplates(const Element & root)945 static void parseTemplates(const Element& root)
946 {
947 const Element* defs = findChild(root, "Definitions");
948 if (!defs) return;
949
950 std::unordered_map<std::string, Element*> templates;
951 Element* def = defs->child;
952 while (def)
953 {
954 if (def->id == "ObjectType")
955 {
956 Element* subdef = def->child;
957 while (subdef)
958 {
959 if (subdef->id == "PropertyTemplate")
960 {
961 DataView prop1 = def->first_property->value;
962 DataView prop2 = subdef->first_property->value;
963 std::string key((const char*)prop1.begin, prop1.end - prop1.begin);
964 key += std::string((const char*)prop1.begin, prop1.end - prop1.begin);
965 templates[key] = subdef;
966 }
967 subdef = subdef->sibling;
968 }
969 }
970 def = def->sibling;
971 }
972 // TODO
973 }
974
975
976 struct Scene;
977
978
Mesh(const Scene & _scene,const IElement & _element)979 Mesh::Mesh(const Scene& _scene, const IElement& _element)
980 : Object(_scene, _element)
981 {
982 }
983
984
985 struct MeshImpl : Mesh
986 {
MeshImplofbx::MeshImpl987 MeshImpl(const Scene& _scene, const IElement& _element)
988 : Mesh(_scene, _element)
989 , scene(_scene)
990 {
991 is_node = true;
992 }
993
994
getGeometricMatrixofbx::MeshImpl995 Matrix getGeometricMatrix() const override
996 {
997 Vec3 translation = resolveVec3Property(*this, "GeometricTranslation", {0, 0, 0});
998 Vec3 rotation = resolveVec3Property(*this, "GeometricRotation", {0, 0, 0});
999 Vec3 scale = resolveVec3Property(*this, "GeometricScaling", {1, 1, 1});
1000
1001 Matrix scale_mtx = makeIdentity();
1002 scale_mtx.m[0] = (float)scale.x;
1003 scale_mtx.m[5] = (float)scale.y;
1004 scale_mtx.m[10] = (float)scale.z;
1005 Matrix mtx = getRotationMatrix(rotation, RotationOrder::EULER_XYZ);
1006 setTranslation(translation, &mtx);
1007
1008 return scale_mtx * mtx;
1009 }
1010
1011
getTypeofbx::MeshImpl1012 Type getType() const override { return Type::MESH; }
1013
1014
getGeometryofbx::MeshImpl1015 const Geometry* getGeometry() const override { return geometry; }
getMaterialofbx::MeshImpl1016 const Material* getMaterial(int index) const override { return materials[index]; }
getMaterialCountofbx::MeshImpl1017 int getMaterialCount() const override { return (int)materials.size(); }
1018
1019
1020 const Geometry* geometry = nullptr;
1021 const Scene& scene;
1022 std::vector<const Material*> materials;
1023 };
1024
1025
Material(const Scene & _scene,const IElement & _element)1026 Material::Material(const Scene& _scene, const IElement& _element)
1027 : Object(_scene, _element)
1028 {
1029 }
1030
1031
1032 struct MaterialImpl : Material
1033 {
MaterialImplofbx::MaterialImpl1034 MaterialImpl(const Scene& _scene, const IElement& _element)
1035 : Material(_scene, _element)
1036 {
1037 for (const Texture*& tex : textures) tex = nullptr;
1038 }
1039
getTypeofbx::MaterialImpl1040 Type getType() const override { return Type::MATERIAL; }
1041
1042
getTextureofbx::MaterialImpl1043 const Texture* getTexture(Texture::TextureType type) const override { return textures[type]; }
getDiffuseColorofbx::MaterialImpl1044 Color getDiffuseColor() const override { return diffuse_color; }
1045
1046 const Texture* textures[Texture::TextureType::COUNT];
1047 Color diffuse_color;
1048 };
1049
1050
1051 struct LimbNodeImpl : Object
1052 {
LimbNodeImplofbx::LimbNodeImpl1053 LimbNodeImpl(const Scene& _scene, const IElement& _element)
1054 : Object(_scene, _element)
1055 {
1056 is_node = true;
1057 }
getTypeofbx::LimbNodeImpl1058 Type getType() const override { return Type::LIMB_NODE; }
1059 };
1060
1061
1062 struct NullImpl : Object
1063 {
NullImplofbx::NullImpl1064 NullImpl(const Scene& _scene, const IElement& _element)
1065 : Object(_scene, _element)
1066 {
1067 is_node = true;
1068 }
getTypeofbx::NullImpl1069 Type getType() const override { return Type::NULL_NODE; }
1070 };
1071
1072
NodeAttribute(const Scene & _scene,const IElement & _element)1073 NodeAttribute::NodeAttribute(const Scene& _scene, const IElement& _element)
1074 : Object(_scene, _element)
1075 {
1076 }
1077
1078
1079 struct NodeAttributeImpl : NodeAttribute
1080 {
NodeAttributeImplofbx::NodeAttributeImpl1081 NodeAttributeImpl(const Scene& _scene, const IElement& _element)
1082 : NodeAttribute(_scene, _element)
1083 {
1084 }
getTypeofbx::NodeAttributeImpl1085 Type getType() const override { return Type::NODE_ATTRIBUTE; }
getAttributeTypeofbx::NodeAttributeImpl1086 DataView getAttributeType() const override { return attribute_type; }
1087
1088
1089 DataView attribute_type;
1090 };
1091
1092
Geometry(const Scene & _scene,const IElement & _element)1093 Geometry::Geometry(const Scene& _scene, const IElement& _element)
1094 : Object(_scene, _element)
1095 {
1096 }
1097
1098
1099 struct GeometryImpl : Geometry
1100 {
1101 enum VertexDataMapping
1102 {
1103 BY_POLYGON_VERTEX,
1104 BY_POLYGON,
1105 BY_VERTEX
1106 };
1107
1108 struct NewVertex
1109 {
~NewVertexofbx::GeometryImpl::NewVertex1110 ~NewVertex() { delete next; }
1111
1112 int index = -1;
1113 NewVertex* next = nullptr;
1114 };
1115
1116 std::vector<Vec3> vertices;
1117 std::vector<Vec3> normals;
1118 std::vector<Vec2> uvs[s_uvs_max];
1119 std::vector<Vec4> colors;
1120 std::vector<Vec3> tangents;
1121 std::vector<int> materials;
1122
1123 const Skin* skin = nullptr;
1124
1125 std::vector<int> to_old_vertices;
1126 std::vector<NewVertex> to_new_vertices;
1127
GeometryImplofbx::GeometryImpl1128 GeometryImpl(const Scene& _scene, const IElement& _element)
1129 : Geometry(_scene, _element)
1130 {
1131 }
1132
1133
getTypeofbx::GeometryImpl1134 Type getType() const override { return Type::GEOMETRY; }
getVertexCountofbx::GeometryImpl1135 int getVertexCount() const override { return (int)vertices.size(); }
getVerticesofbx::GeometryImpl1136 const Vec3* getVertices() const override { return &vertices[0]; }
getNormalsofbx::GeometryImpl1137 const Vec3* getNormals() const override { return normals.empty() ? nullptr : &normals[0]; }
getUVsofbx::GeometryImpl1138 const Vec2* getUVs(int index = 0) const override { return index < 0 || index >= s_uvs_max || uvs[index].empty() ? nullptr : &uvs[index][0]; }
getColorsofbx::GeometryImpl1139 const Vec4* getColors() const override { return colors.empty() ? nullptr : &colors[0]; }
getTangentsofbx::GeometryImpl1140 const Vec3* getTangents() const override { return tangents.empty() ? nullptr : &tangents[0]; }
getSkinofbx::GeometryImpl1141 const Skin* getSkin() const override { return skin; }
getMaterialsofbx::GeometryImpl1142 const int* getMaterials() const override { return materials.empty() ? nullptr : &materials[0]; }
1143
1144
triangulateofbx::GeometryImpl1145 void triangulate(const std::vector<int>& old_indices, std::vector<int>* indices, std::vector<int>* to_old)
1146 {
1147 assert(indices);
1148 assert(to_old);
1149
1150 auto getIdx = [&old_indices](int i) -> int {
1151 int idx = old_indices[i];
1152 return idx < 0 ? -idx - 1 : idx;
1153 };
1154
1155 int in_polygon_idx = 0;
1156 for (int i = 0; i < old_indices.size(); ++i)
1157 {
1158 int idx = getIdx(i);
1159 if (in_polygon_idx <= 2)
1160 {
1161 indices->push_back(idx);
1162 to_old->push_back(i);
1163 }
1164 else
1165 {
1166 indices->push_back(old_indices[i - in_polygon_idx]);
1167 to_old->push_back(i - in_polygon_idx);
1168 indices->push_back(old_indices[i - 1]);
1169 to_old->push_back(i - 1);
1170 indices->push_back(idx);
1171 to_old->push_back(i);
1172 }
1173 ++in_polygon_idx;
1174 if (old_indices[i] < 0)
1175 {
1176 in_polygon_idx = 0;
1177 }
1178 }
1179 }
1180 };
1181
1182
Cluster(const Scene & _scene,const IElement & _element)1183 Cluster::Cluster(const Scene& _scene, const IElement& _element)
1184 : Object(_scene, _element)
1185 {
1186 }
1187
1188
1189 struct ClusterImpl : Cluster
1190 {
ClusterImplofbx::ClusterImpl1191 ClusterImpl(const Scene& _scene, const IElement& _element)
1192 : Cluster(_scene, _element)
1193 {
1194 }
1195
getIndicesofbx::ClusterImpl1196 const int* getIndices() const override { return &indices[0]; }
getIndicesCountofbx::ClusterImpl1197 int getIndicesCount() const override { return (int)indices.size(); }
getWeightsofbx::ClusterImpl1198 const double* getWeights() const override { return &weights[0]; }
getWeightsCountofbx::ClusterImpl1199 int getWeightsCount() const override { return (int)weights.size(); }
getTransformMatrixofbx::ClusterImpl1200 Matrix getTransformMatrix() const override { return transform_matrix; }
getTransformLinkMatrixofbx::ClusterImpl1201 Matrix getTransformLinkMatrix() const override { return transform_link_matrix; }
getLinkofbx::ClusterImpl1202 Object* getLink() const override { return link; }
1203
1204
postprocessofbx::ClusterImpl1205 bool postprocess()
1206 {
1207 assert(skin);
1208
1209 GeometryImpl* geom = (GeometryImpl*)skin->resolveObjectLinkReverse(Object::Type::GEOMETRY);
1210 if (!geom) return false;
1211
1212 std::vector<int> old_indices;
1213 const Element* indexes = findChild((const Element&)element, "Indexes");
1214 if (indexes && indexes->first_property)
1215 {
1216 if (!parseBinaryArray(*indexes->first_property, &old_indices)) return false;
1217 }
1218
1219 std::vector<double> old_weights;
1220 const Element* weights_el = findChild((const Element&)element, "Weights");
1221 if (weights_el && weights_el->first_property)
1222 {
1223 if (!parseBinaryArray(*weights_el->first_property, &old_weights)) return false;
1224 }
1225
1226 if (old_indices.size() != old_weights.size()) return false;
1227
1228 indices.reserve(old_indices.size());
1229 weights.reserve(old_indices.size());
1230 int* ir = old_indices.empty() ? nullptr : &old_indices[0];
1231 double* wr = old_weights.empty() ? nullptr : &old_weights[0];
1232 for (int i = 0, c = (int)old_indices.size(); i < c; ++i)
1233 {
1234 int old_idx = ir[i];
1235 double w = wr[i];
1236 GeometryImpl::NewVertex* n = &geom->to_new_vertices[old_idx];
1237 if (n->index == -1) continue; // skip vertices which aren't indexed.
1238 while (n)
1239 {
1240 indices.push_back(n->index);
1241 weights.push_back(w);
1242 n = n->next;
1243 }
1244 }
1245
1246 return true;
1247 }
1248
1249
1250 Object* link = nullptr;
1251 Skin* skin = nullptr;
1252 std::vector<int> indices;
1253 std::vector<double> weights;
1254 Matrix transform_matrix;
1255 Matrix transform_link_matrix;
getTypeofbx::ClusterImpl1256 Type getType() const override { return Type::CLUSTER; }
1257 };
1258
1259
AnimationStack(const Scene & _scene,const IElement & _element)1260 AnimationStack::AnimationStack(const Scene& _scene, const IElement& _element)
1261 : Object(_scene, _element)
1262 {
1263 }
1264
1265
AnimationLayer(const Scene & _scene,const IElement & _element)1266 AnimationLayer::AnimationLayer(const Scene& _scene, const IElement& _element)
1267 : Object(_scene, _element)
1268 {
1269 }
1270
1271
AnimationCurve(const Scene & _scene,const IElement & _element)1272 AnimationCurve::AnimationCurve(const Scene& _scene, const IElement& _element)
1273 : Object(_scene, _element)
1274 {
1275 }
1276
1277
AnimationCurveNode(const Scene & _scene,const IElement & _element)1278 AnimationCurveNode::AnimationCurveNode(const Scene& _scene, const IElement& _element)
1279 : Object(_scene, _element)
1280 {
1281 }
1282
1283
1284 struct AnimationStackImpl : AnimationStack
1285 {
AnimationStackImplofbx::AnimationStackImpl1286 AnimationStackImpl(const Scene& _scene, const IElement& _element)
1287 : AnimationStack(_scene, _element)
1288 {
1289 }
1290
1291
getLayerofbx::AnimationStackImpl1292 const AnimationLayer* getLayer(int index) const override
1293 {
1294 return resolveObjectLink<AnimationLayer>(index);
1295 }
1296
1297
getTypeofbx::AnimationStackImpl1298 Type getType() const override { return Type::ANIMATION_STACK; }
1299 };
1300
1301
1302 struct AnimationCurveImpl : AnimationCurve
1303 {
AnimationCurveImplofbx::AnimationCurveImpl1304 AnimationCurveImpl(const Scene& _scene, const IElement& _element)
1305 : AnimationCurve(_scene, _element)
1306 {
1307 }
1308
getKeyCountofbx::AnimationCurveImpl1309 int getKeyCount() const override { return (int)times.size(); }
getKeyTimeofbx::AnimationCurveImpl1310 const i64* getKeyTime() const override { return ×[0]; }
getKeyValueofbx::AnimationCurveImpl1311 const float* getKeyValue() const override { return &values[0]; }
1312
1313 std::vector<i64> times;
1314 std::vector<float> values;
getTypeofbx::AnimationCurveImpl1315 Type getType() const override { return Type::ANIMATION_CURVE; }
1316 };
1317
1318
Skin(const Scene & _scene,const IElement & _element)1319 Skin::Skin(const Scene& _scene, const IElement& _element)
1320 : Object(_scene, _element)
1321 {
1322 }
1323
1324
1325 struct SkinImpl : Skin
1326 {
SkinImplofbx::SkinImpl1327 SkinImpl(const Scene& _scene, const IElement& _element)
1328 : Skin(_scene, _element)
1329 {
1330 }
1331
getClusterCountofbx::SkinImpl1332 int getClusterCount() const override { return (int)clusters.size(); }
getClusterofbx::SkinImpl1333 const Cluster* getCluster(int idx) const override { return clusters[idx]; }
1334
getTypeofbx::SkinImpl1335 Type getType() const override { return Type::SKIN; }
1336
1337 std::vector<Cluster*> clusters;
1338 };
1339
1340
Texture(const Scene & _scene,const IElement & _element)1341 Texture::Texture(const Scene& _scene, const IElement& _element)
1342 : Object(_scene, _element)
1343 {
1344 }
1345
1346
1347 struct TextureImpl : Texture
1348 {
TextureImplofbx::TextureImpl1349 TextureImpl(const Scene& _scene, const IElement& _element)
1350 : Texture(_scene, _element)
1351 {
1352 }
1353
getRelativeFileNameofbx::TextureImpl1354 DataView getRelativeFileName() const override { return relative_filename; }
getFileNameofbx::TextureImpl1355 DataView getFileName() const override { return filename; }
1356
1357 DataView filename;
1358 DataView relative_filename;
getTypeofbx::TextureImpl1359 Type getType() const override { return Type::TEXTURE; }
1360 };
1361
1362
1363 struct Root : Object
1364 {
Rootofbx::Root1365 Root(const Scene& _scene, const IElement& _element)
1366 : Object(_scene, _element)
1367 {
1368 copyString(name, "RootNode");
1369 is_node = true;
1370 }
getTypeofbx::Root1371 Type getType() const override { return Type::ROOT; }
1372 };
1373
1374
1375 struct Scene : IScene
1376 {
1377 struct Connection
1378 {
1379 enum Type
1380 {
1381 OBJECT_OBJECT,
1382 OBJECT_PROPERTY
1383 };
1384
1385 Type type;
1386 u64 from;
1387 u64 to;
1388 DataView property;
1389 };
1390
1391 struct ObjectPair
1392 {
1393 const Element* element;
1394 Object* object;
1395 };
1396
1397
getAnimationStackCountofbx::Scene1398 int getAnimationStackCount() const override { return (int)m_animation_stacks.size(); }
getMeshCountofbx::Scene1399 int getMeshCount() const override { return (int)m_meshes.size(); }
getSceneFrameRateofbx::Scene1400 float getSceneFrameRate() const override { return m_scene_frame_rate; }
getGlobalSettingsofbx::Scene1401 const GlobalSettings* getGlobalSettings() const override { return &m_settings; }
1402
getAllObjectsofbx::Scene1403 const Object* const* getAllObjects() const override { return m_all_objects.empty() ? nullptr : &m_all_objects[0]; }
1404
1405
getAllObjectCountofbx::Scene1406 int getAllObjectCount() const override { return (int)m_all_objects.size(); }
1407
1408
getAnimationStackofbx::Scene1409 const AnimationStack* getAnimationStack(int index) const override
1410 {
1411 assert(index >= 0);
1412 assert(index < m_animation_stacks.size());
1413 return m_animation_stacks[index];
1414 }
1415
1416
getMeshofbx::Scene1417 const Mesh* getMesh(int index) const override
1418 {
1419 assert(index >= 0);
1420 assert(index < m_meshes.size());
1421 return m_meshes[index];
1422 }
1423
1424
getTakeInfoofbx::Scene1425 const TakeInfo* getTakeInfo(const char* name) const override
1426 {
1427 for (const TakeInfo& info : m_take_infos)
1428 {
1429 if (info.name == name) return &info;
1430 }
1431 return nullptr;
1432 }
1433
1434
getRootElementofbx::Scene1435 const IElement* getRootElement() const override { return m_root_element; }
getRootofbx::Scene1436 const Object* getRoot() const override { return m_root; }
1437
1438
destroyofbx::Scene1439 void destroy() override { delete this; }
1440
1441
~Sceneofbx::Scene1442 ~Scene()
1443 {
1444 for (auto iter : m_object_map)
1445 {
1446 delete iter.second.object;
1447 }
1448
1449 deleteElement(m_root_element);
1450 }
1451
1452
1453 Element* m_root_element = nullptr;
1454 Root* m_root = nullptr;
1455 float m_scene_frame_rate = -1;
1456 GlobalSettings m_settings;
1457 std::unordered_map<u64, ObjectPair> m_object_map;
1458 std::vector<Object*> m_all_objects;
1459 std::vector<Mesh*> m_meshes;
1460 std::vector<AnimationStack*> m_animation_stacks;
1461 std::vector<Connection> m_connections;
1462 std::vector<u8> m_data;
1463 std::vector<TakeInfo> m_take_infos;
1464 };
1465
1466
1467 struct AnimationCurveNodeImpl : AnimationCurveNode
1468 {
AnimationCurveNodeImplofbx::AnimationCurveNodeImpl1469 AnimationCurveNodeImpl(const Scene& _scene, const IElement& _element)
1470 : AnimationCurveNode(_scene, _element)
1471 {
1472 }
1473
1474
getBoneofbx::AnimationCurveNodeImpl1475 const Object* getBone() const override
1476 {
1477 return bone;
1478 }
1479
1480
getNodeLocalTransformofbx::AnimationCurveNodeImpl1481 Vec3 getNodeLocalTransform(double time) const override
1482 {
1483 i64 fbx_time = secondsToFbxTime(time);
1484
1485 auto getCoord = [](const Curve& curve, i64 fbx_time) {
1486 if (!curve.curve) return 0.0f;
1487
1488 const i64* times = curve.curve->getKeyTime();
1489 const float* values = curve.curve->getKeyValue();
1490 int count = curve.curve->getKeyCount();
1491
1492 if (fbx_time < times[0]) fbx_time = times[0];
1493 if (fbx_time > times[count - 1]) fbx_time = times[count - 1];
1494 for (int i = 1; i < count; ++i)
1495 {
1496 if (times[i] >= fbx_time)
1497 {
1498 float t = float(double(fbx_time - times[i - 1]) / double(times[i] - times[i - 1]));
1499 return values[i - 1] * (1 - t) + values[i] * t;
1500 }
1501 }
1502 return values[0];
1503 };
1504
1505 return {getCoord(curves[0], fbx_time), getCoord(curves[1], fbx_time), getCoord(curves[2], fbx_time)};
1506 }
1507
1508
1509 struct Curve
1510 {
1511 const AnimationCurve* curve = nullptr;
1512 const Scene::Connection* connection = nullptr;
1513 };
1514
1515
1516 Curve curves[3];
1517 Object* bone = nullptr;
1518 DataView bone_link_property;
getTypeofbx::AnimationCurveNodeImpl1519 Type getType() const override { return Type::ANIMATION_CURVE_NODE; }
1520 enum Mode
1521 {
1522 TRANSLATION,
1523 ROTATION,
1524 SCALE
1525 } mode = TRANSLATION;
1526 };
1527
1528
1529 struct AnimationLayerImpl : AnimationLayer
1530 {
AnimationLayerImplofbx::AnimationLayerImpl1531 AnimationLayerImpl(const Scene& _scene, const IElement& _element)
1532 : AnimationLayer(_scene, _element)
1533 {
1534 }
1535
1536
getTypeofbx::AnimationLayerImpl1537 Type getType() const override { return Type::ANIMATION_LAYER; }
1538
1539
getCurveNodeofbx::AnimationLayerImpl1540 const AnimationCurveNode* getCurveNode(int index) const override
1541 {
1542 if (index >= curve_nodes.size() || index < 0) return nullptr;
1543 return curve_nodes[index];
1544 }
1545
1546
getCurveNodeofbx::AnimationLayerImpl1547 const AnimationCurveNode* getCurveNode(const Object& bone, const char* prop) const override
1548 {
1549 for (const AnimationCurveNodeImpl* node : curve_nodes)
1550 {
1551 if (node->bone_link_property == prop && node->bone == &bone) return node;
1552 }
1553 return nullptr;
1554 }
1555
1556
1557 std::vector<AnimationCurveNodeImpl*> curve_nodes;
1558 };
1559
1560
parseTexture(const Scene & scene,const Element & element)1561 struct OptionalError<Object*> parseTexture(const Scene& scene, const Element& element)
1562 {
1563 TextureImpl* texture = new TextureImpl(scene, element);
1564 const Element* texture_filename = findChild(element, "FileName");
1565 if (texture_filename && texture_filename->first_property)
1566 {
1567 texture->filename = texture_filename->first_property->value;
1568 }
1569 const Element* texture_relative_filename = findChild(element, "RelativeFilename");
1570 if (texture_relative_filename && texture_relative_filename->first_property)
1571 {
1572 texture->relative_filename = texture_relative_filename->first_property->value;
1573 }
1574 return texture;
1575 }
1576
1577
parse(const Scene & scene,const Element & element)1578 template <typename T> static OptionalError<Object*> parse(const Scene& scene, const Element& element)
1579 {
1580 T* obj = new T(scene, element);
1581 return obj;
1582 }
1583
1584
parseCluster(const Scene & scene,const Element & element)1585 static OptionalError<Object*> parseCluster(const Scene& scene, const Element& element)
1586 {
1587 std::unique_ptr<ClusterImpl> obj(new ClusterImpl(scene, element));
1588
1589 const Element* transform_link = findChild(element, "TransformLink");
1590 if (transform_link && transform_link->first_property)
1591 {
1592 if (!parseArrayRaw(
1593 *transform_link->first_property, &obj->transform_link_matrix, sizeof(obj->transform_link_matrix)))
1594 {
1595 return Error("Failed to parse TransformLink");
1596 }
1597 }
1598 const Element* transform = findChild(element, "Transform");
1599 if (transform && transform->first_property)
1600 {
1601 if (!parseArrayRaw(*transform->first_property, &obj->transform_matrix, sizeof(obj->transform_matrix)))
1602 {
1603 return Error("Failed to parse Transform");
1604
1605 }
1606 }
1607
1608 return obj.release();
1609 }
1610
1611
parseNodeAttribute(const Scene & scene,const Element & element)1612 static OptionalError<Object*> parseNodeAttribute(const Scene& scene, const Element& element)
1613 {
1614 NodeAttributeImpl* obj = new NodeAttributeImpl(scene, element);
1615 const Element* type_flags = findChild(element, "TypeFlags");
1616 if (type_flags && type_flags->first_property)
1617 {
1618 obj->attribute_type = type_flags->first_property->value;
1619 }
1620 return obj;
1621 }
1622
1623
parseLimbNode(const Scene & scene,const Element & element)1624 static OptionalError<Object*> parseLimbNode(const Scene& scene, const Element& element)
1625 {
1626 if (!element.first_property
1627 || !element.first_property->next
1628 || !element.first_property->next->next
1629 || element.first_property->next->next->value != "LimbNode")
1630 {
1631 return Error("Invalid limb node");
1632 }
1633
1634 LimbNodeImpl* obj = new LimbNodeImpl(scene, element);
1635 return obj;
1636 }
1637
1638
parseMesh(const Scene & scene,const Element & element)1639 static OptionalError<Object*> parseMesh(const Scene& scene, const Element& element)
1640 {
1641 if (!element.first_property
1642 || !element.first_property->next
1643 || !element.first_property->next->next
1644 || element.first_property->next->next->value != "Mesh")
1645 {
1646 return Error("Invalid mesh");
1647 }
1648
1649 return new MeshImpl(scene, element);
1650 }
1651
1652
parseMaterial(const Scene & scene,const Element & element)1653 static OptionalError<Object*> parseMaterial(const Scene& scene, const Element& element)
1654 {
1655 MaterialImpl* material = new MaterialImpl(scene, element);
1656 const Element* prop = findChild(element, "Properties70");
1657 material->diffuse_color = { 1, 1, 1 };
1658 if (prop) prop = prop->child;
1659 while (prop)
1660 {
1661 if (prop->id == "P" && prop->first_property)
1662 {
1663 if (prop->first_property->value == "DiffuseColor")
1664 {
1665 material->diffuse_color.r = (float)prop->getProperty(4)->getValue().toDouble();
1666 material->diffuse_color.g = (float)prop->getProperty(5)->getValue().toDouble();
1667 material->diffuse_color.b = (float)prop->getProperty(6)->getValue().toDouble();
1668 }
1669 }
1670 prop = prop->sibling;
1671 }
1672 return material;
1673 }
1674
1675
1676 template<typename T> static bool parseTextArrayRaw(const Property& property, T* out, int max_size);
1677
parseArrayRaw(const Property & property,T * out,int max_size)1678 template <typename T> static bool parseArrayRaw(const Property& property, T* out, int max_size)
1679 {
1680 if (property.value.is_binary)
1681 {
1682 assert(out);
1683
1684 int elem_size = 1;
1685 switch (property.type)
1686 {
1687 case 'l': elem_size = 8; break;
1688 case 'd': elem_size = 8; break;
1689 case 'f': elem_size = 4; break;
1690 case 'i': elem_size = 4; break;
1691 default: return false;
1692 }
1693
1694 const u8* data = property.value.begin + sizeof(u32) * 3;
1695 if (data > property.value.end) return false;
1696
1697 u32 count = property.getCount();
1698 u32 enc = *(const u32*)(property.value.begin + 4);
1699 u32 len = *(const u32*)(property.value.begin + 8);
1700
1701 if (enc == 0)
1702 {
1703 if ((int)len > max_size) return false;
1704 if (data + len > property.value.end) return false;
1705 memcpy(out, data, len);
1706 return true;
1707 }
1708 else if (enc == 1)
1709 {
1710 if (int(elem_size * count) > max_size) return false;
1711 return decompress(data, len, (u8*)out, elem_size * count);
1712 }
1713
1714 return false;
1715 }
1716
1717 return parseTextArrayRaw(property, out, max_size);
1718 }
1719
1720
1721 template <typename T> const char* fromString(const char* str, const char* end, T* val);
fromString(const char * str,const char * end,int * val)1722 template <> const char* fromString<int>(const char* str, const char* end, int* val)
1723 {
1724 *val = atoi(str);
1725 const char* iter = str;
1726 while (iter < end && *iter != ',') ++iter;
1727 if (iter < end) ++iter; // skip ','
1728 return (const char*)iter;
1729 }
1730
1731
fromString(const char * str,const char * end,u64 * val)1732 template <> const char* fromString<u64>(const char* str, const char* end, u64* val)
1733 {
1734 *val = strtoull(str, nullptr, 10);
1735 const char* iter = str;
1736 while (iter < end && *iter != ',') ++iter;
1737 if (iter < end) ++iter; // skip ','
1738 return (const char*)iter;
1739 }
1740
1741
fromString(const char * str,const char * end,i64 * val)1742 template <> const char* fromString<i64>(const char* str, const char* end, i64* val)
1743 {
1744 *val = atoll(str);
1745 const char* iter = str;
1746 while (iter < end && *iter != ',') ++iter;
1747 if (iter < end) ++iter; // skip ','
1748 return (const char*)iter;
1749 }
1750
1751
fromString(const char * str,const char * end,double * val)1752 template <> const char* fromString<double>(const char* str, const char* end, double* val)
1753 {
1754 *val = atof(str);
1755 const char* iter = str;
1756 while (iter < end && *iter != ',') ++iter;
1757 if (iter < end) ++iter; // skip ','
1758 return (const char*)iter;
1759 }
1760
1761
fromString(const char * str,const char * end,float * val)1762 template <> const char* fromString<float>(const char* str, const char* end, float* val)
1763 {
1764 *val = (float)atof(str);
1765 const char* iter = str;
1766 while (iter < end && *iter != ',') ++iter;
1767 if (iter < end) ++iter; // skip ','
1768 return (const char*)iter;
1769 }
1770
1771
fromString(const char * str,const char * end,double * val,int count)1772 const char* fromString(const char* str, const char* end, double* val, int count)
1773 {
1774 const char* iter = str;
1775 for (int i = 0; i < count; ++i)
1776 {
1777 *val = atof(iter);
1778 ++val;
1779 while (iter < end && *iter != ',') ++iter;
1780 if (iter < end) ++iter; // skip ','
1781
1782 if (iter == end) return iter;
1783
1784 }
1785 return (const char*)iter;
1786 }
1787
1788
fromString(const char * str,const char * end,Vec2 * val)1789 template <> const char* fromString<Vec2>(const char* str, const char* end, Vec2* val)
1790 {
1791 return fromString(str, end, &val->x, 2);
1792 }
1793
1794
fromString(const char * str,const char * end,Vec3 * val)1795 template <> const char* fromString<Vec3>(const char* str, const char* end, Vec3* val)
1796 {
1797 return fromString(str, end, &val->x, 3);
1798 }
1799
1800
fromString(const char * str,const char * end,Vec4 * val)1801 template <> const char* fromString<Vec4>(const char* str, const char* end, Vec4* val)
1802 {
1803 return fromString(str, end, &val->x, 4);
1804 }
1805
1806
fromString(const char * str,const char * end,Matrix * val)1807 template <> const char* fromString<Matrix>(const char* str, const char* end, Matrix* val)
1808 {
1809 return fromString(str, end, &val->m[0], 16);
1810 }
1811
1812
parseTextArray(const Property & property,std::vector<T> * out)1813 template<typename T> static void parseTextArray(const Property& property, std::vector<T>* out)
1814 {
1815 const u8* iter = property.value.begin;
1816 for(int i = 0; i < property.count; ++i)
1817 {
1818 T val;
1819 iter = (const u8*)fromString<T>((const char*)iter, (const char*)property.value.end, &val);
1820 out->push_back(val);
1821 }
1822 }
1823
1824
parseTextArrayRaw(const Property & property,T * out_raw,int max_size)1825 template<typename T> static bool parseTextArrayRaw(const Property& property, T* out_raw, int max_size)
1826 {
1827 const u8* iter = property.value.begin;
1828
1829 T* out = out_raw;
1830 while (iter < property.value.end)
1831 {
1832 iter = (const u8*)fromString<T>((const char*)iter, (const char*)property.value.end, out);
1833 ++out;
1834 if (out - out_raw == max_size / sizeof(T)) return true;
1835 }
1836 return out - out_raw == max_size / sizeof(T);
1837 }
1838
1839
parseBinaryArray(const Property & property,std::vector<T> * out)1840 template <typename T> static bool parseBinaryArray(const Property& property, std::vector<T>* out)
1841 {
1842 assert(out);
1843 if (property.value.is_binary)
1844 {
1845 u32 count = property.getCount();
1846 int elem_size = 1;
1847 switch (property.type)
1848 {
1849 case 'd': elem_size = 8; break;
1850 case 'f': elem_size = 4; break;
1851 case 'i': elem_size = 4; break;
1852 default: return false;
1853 }
1854 int elem_count = sizeof(T) / elem_size;
1855 out->resize(count / elem_count);
1856
1857 if (count == 0) return true;
1858 return parseArrayRaw(property, &(*out)[0], int(sizeof((*out)[0]) * out->size()));
1859 }
1860 else
1861 {
1862 parseTextArray(property, out);
1863 return true;
1864 }
1865 }
1866
1867
parseDoubleVecData(Property & property,std::vector<T> * out_vec)1868 template <typename T> static bool parseDoubleVecData(Property& property, std::vector<T>* out_vec)
1869 {
1870 assert(out_vec);
1871 if (!property.value.is_binary)
1872 {
1873 parseTextArray(property, out_vec);
1874 return true;
1875 }
1876
1877 if (property.type == 'd')
1878 {
1879 return parseBinaryArray(property, out_vec);
1880 }
1881
1882 assert(property.type == 'f');
1883 assert(sizeof((*out_vec)[0].x) == sizeof(double));
1884 std::vector<float> tmp;
1885 if (!parseBinaryArray(property, &tmp)) return false;
1886 int elem_count = sizeof((*out_vec)[0]) / sizeof((*out_vec)[0].x);
1887 out_vec->resize(tmp.size() / elem_count);
1888 double* out = &(*out_vec)[0].x;
1889 for (int i = 0, c = (int)tmp.size(); i < c; ++i)
1890 {
1891 out[i] = tmp[i];
1892 }
1893 return true;
1894 }
1895
1896
1897 template <typename T>
parseVertexData(const Element & element,const char * name,const char * index_name,std::vector<T> * out,std::vector<int> * out_indices,GeometryImpl::VertexDataMapping * mapping)1898 static bool parseVertexData(const Element& element,
1899 const char* name,
1900 const char* index_name,
1901 std::vector<T>* out,
1902 std::vector<int>* out_indices,
1903 GeometryImpl::VertexDataMapping* mapping)
1904 {
1905 assert(out);
1906 assert(mapping);
1907 const Element* data_element = findChild(element, name);
1908 if (!data_element || !data_element->first_property) return false;
1909
1910 const Element* mapping_element = findChild(element, "MappingInformationType");
1911 const Element* reference_element = findChild(element, "ReferenceInformationType");
1912
1913 if (mapping_element && mapping_element->first_property)
1914 {
1915 if (mapping_element->first_property->value == "ByPolygonVertex")
1916 {
1917 *mapping = GeometryImpl::BY_POLYGON_VERTEX;
1918 }
1919 else if (mapping_element->first_property->value == "ByPolygon")
1920 {
1921 *mapping = GeometryImpl::BY_POLYGON;
1922 }
1923 else if (mapping_element->first_property->value == "ByVertice" ||
1924 mapping_element->first_property->value == "ByVertex")
1925 {
1926 *mapping = GeometryImpl::BY_VERTEX;
1927 }
1928 else
1929 {
1930 return false;
1931 }
1932 }
1933 if (reference_element && reference_element->first_property)
1934 {
1935 if (reference_element->first_property->value == "IndexToDirect")
1936 {
1937 const Element* indices_element = findChild(element, index_name);
1938 if (indices_element && indices_element->first_property)
1939 {
1940 if (!parseBinaryArray(*indices_element->first_property, out_indices)) return false;
1941 }
1942 }
1943 else if (reference_element->first_property->value != "Direct")
1944 {
1945 return false;
1946 }
1947 }
1948 return parseDoubleVecData(*data_element->first_property, out);
1949 }
1950
1951
1952 template <typename T>
splat(std::vector<T> * out,GeometryImpl::VertexDataMapping mapping,const std::vector<T> & data,const std::vector<int> & indices,const std::vector<int> & original_indices)1953 static void splat(std::vector<T>* out,
1954 GeometryImpl::VertexDataMapping mapping,
1955 const std::vector<T>& data,
1956 const std::vector<int>& indices,
1957 const std::vector<int>& original_indices)
1958 {
1959 assert(out);
1960 assert(!data.empty());
1961
1962 if (mapping == GeometryImpl::BY_POLYGON_VERTEX)
1963 {
1964 if (indices.empty())
1965 {
1966 out->resize(data.size());
1967 memcpy(&(*out)[0], &data[0], sizeof(data[0]) * data.size());
1968 }
1969 else
1970 {
1971 out->resize(indices.size());
1972 int data_size = (int)data.size();
1973 for (int i = 0, c = (int)indices.size(); i < c; ++i)
1974 {
1975 if(indices[i] < data_size) (*out)[i] = data[indices[i]];
1976 else (*out)[i] = T();
1977 }
1978 }
1979 }
1980 else if (mapping == GeometryImpl::BY_VERTEX)
1981 {
1982 // v0 v1 ...
1983 // uv0 uv1 ...
1984 assert(indices.empty());
1985
1986 out->resize(original_indices.size());
1987
1988 int data_size = (int)data.size();
1989 for (int i = 0, c = (int)original_indices.size(); i < c; ++i)
1990 {
1991 int idx = original_indices[i];
1992 if (idx < 0) idx = -idx - 1;
1993 if(idx < data_size) (*out)[i] = data[idx];
1994 else (*out)[i] = T();
1995 }
1996 }
1997 else
1998 {
1999 assert(false);
2000 }
2001 }
2002
2003
remap(std::vector<T> * out,const std::vector<int> & map)2004 template <typename T> static void remap(std::vector<T>* out, const std::vector<int>& map)
2005 {
2006 if (out->empty()) return;
2007
2008 std::vector<T> old;
2009 old.swap(*out);
2010 int old_size = (int)old.size();
2011 for (int i = 0, c = (int)map.size(); i < c; ++i)
2012 {
2013 if(map[i] < old_size) out->push_back(old[map[i]]);
2014 else out->push_back(T());
2015 }
2016 }
2017
2018
parseAnimationCurve(const Scene & scene,const Element & element)2019 static OptionalError<Object*> parseAnimationCurve(const Scene& scene, const Element& element)
2020 {
2021 std::unique_ptr<AnimationCurveImpl> curve(new AnimationCurveImpl(scene, element));
2022
2023 const Element* times = findChild(element, "KeyTime");
2024 const Element* values = findChild(element, "KeyValueFloat");
2025
2026 if (times && times->first_property)
2027 {
2028 curve->times.resize(times->first_property->getCount());
2029 if (!times->first_property->getValues(&curve->times[0], (int)curve->times.size() * sizeof(curve->times[0])))
2030 {
2031 return Error("Invalid animation curve");
2032 }
2033 }
2034
2035 if (values && values->first_property)
2036 {
2037 curve->values.resize(values->first_property->getCount());
2038 if (!values->first_property->getValues(&curve->values[0], (int)curve->values.size() * sizeof(curve->values[0])))
2039 {
2040 return Error("Invalid animation curve");
2041 }
2042 }
2043
2044 if (curve->times.size() != curve->values.size()) return Error("Invalid animation curve");
2045
2046 return curve.release();
2047 }
2048
2049
getTriCountFromPoly(const std::vector<int> & indices,int * idx)2050 static int getTriCountFromPoly(const std::vector<int>& indices, int* idx)
2051 {
2052 int count = 1;
2053 while (indices[*idx + 1 + count] >= 0)
2054 {
2055 ++count;
2056 }
2057
2058 *idx = *idx + 2 + count;
2059 return count;
2060 }
2061
2062
add(GeometryImpl::NewVertex & vtx,int index)2063 static void add(GeometryImpl::NewVertex& vtx, int index)
2064 {
2065 if (vtx.index == -1)
2066 {
2067 vtx.index = index;
2068 }
2069 else if (vtx.next)
2070 {
2071 add(*vtx.next, index);
2072 }
2073 else
2074 {
2075 vtx.next = new GeometryImpl::NewVertex;
2076 vtx.next->index = index;
2077 }
2078 }
2079
2080
parseGeometry(const Scene & scene,const Element & element)2081 static OptionalError<Object*> parseGeometry(const Scene& scene, const Element& element)
2082 {
2083 assert(element.first_property);
2084
2085 const Element* vertices_element = findChild(element, "Vertices");
2086 if (!vertices_element || !vertices_element->first_property) return Error("Vertices missing");
2087
2088 const Element* polys_element = findChild(element, "PolygonVertexIndex");
2089 if (!polys_element || !polys_element->first_property) return Error("Indices missing");
2090
2091 std::unique_ptr<GeometryImpl> geom(new GeometryImpl(scene, element));
2092
2093 std::vector<Vec3> vertices;
2094 if (!parseDoubleVecData(*vertices_element->first_property, &vertices)) return Error("Failed to parse vertices");
2095 std::vector<int> original_indices;
2096 if (!parseBinaryArray(*polys_element->first_property, &original_indices)) return Error("Failed to parse indices");
2097
2098 std::vector<int> to_old_indices;
2099 geom->triangulate(original_indices, &geom->to_old_vertices, &to_old_indices);
2100 geom->vertices.resize(geom->to_old_vertices.size());
2101
2102 for (int i = 0, c = (int)geom->to_old_vertices.size(); i < c; ++i)
2103 {
2104 geom->vertices[i] = vertices[geom->to_old_vertices[i]];
2105 }
2106
2107 geom->to_new_vertices.resize(vertices.size()); // some vertices can be unused, so this isn't necessarily the same size as to_old_vertices.
2108 const int* to_old_vertices = geom->to_old_vertices.empty() ? nullptr : &geom->to_old_vertices[0];
2109 for (int i = 0, c = (int)geom->to_old_vertices.size(); i < c; ++i)
2110 {
2111 int old = to_old_vertices[i];
2112 add(geom->to_new_vertices[old], i);
2113 }
2114
2115 const Element* layer_material_element = findChild(element, "LayerElementMaterial");
2116 if (layer_material_element)
2117 {
2118 const Element* mapping_element = findChild(*layer_material_element, "MappingInformationType");
2119 const Element* reference_element = findChild(*layer_material_element, "ReferenceInformationType");
2120
2121 std::vector<int> tmp;
2122
2123 if (!mapping_element || !reference_element) return Error("Invalid LayerElementMaterial");
2124
2125 if (mapping_element->first_property->value == "ByPolygon" &&
2126 reference_element->first_property->value == "IndexToDirect")
2127 {
2128 geom->materials.reserve(geom->vertices.size() / 3);
2129 for (int& i : geom->materials) i = -1;
2130
2131 const Element* indices_element = findChild(*layer_material_element, "Materials");
2132 if (!indices_element || !indices_element->first_property) return Error("Invalid LayerElementMaterial");
2133
2134 if (!parseBinaryArray(*indices_element->first_property, &tmp)) return Error("Failed to parse material indices");
2135
2136 int tmp_i = 0;
2137 for (int poly = 0, c = (int)tmp.size(); poly < c; ++poly)
2138 {
2139 int tri_count = getTriCountFromPoly(original_indices, &tmp_i);
2140 for (int i = 0; i < tri_count; ++i)
2141 {
2142 geom->materials.push_back(tmp[poly]);
2143 }
2144 }
2145 }
2146 else
2147 {
2148 if (mapping_element->first_property->value != "AllSame") return Error("Mapping not supported");
2149 }
2150 }
2151
2152 const Element* layer_uv_element = findChild(element, "LayerElementUV");
2153 while (layer_uv_element)
2154 {
2155 const int uv_index = layer_uv_element->first_property ? layer_uv_element->first_property->getValue().toInt() : 0;
2156 if (uv_index >= 0 && uv_index < Geometry::s_uvs_max)
2157 {
2158 std::vector<Vec2>& uvs = geom->uvs[uv_index];
2159
2160 std::vector<Vec2> tmp;
2161 std::vector<int> tmp_indices;
2162 GeometryImpl::VertexDataMapping mapping;
2163 if (!parseVertexData(*layer_uv_element, "UV", "UVIndex", &tmp, &tmp_indices, &mapping)) return Error("Invalid UVs");
2164 if (!tmp.empty())
2165 {
2166 uvs.resize(tmp_indices.empty() ? tmp.size() : tmp_indices.size());
2167 splat(&uvs, mapping, tmp, tmp_indices, original_indices);
2168 remap(&uvs, to_old_indices);
2169 }
2170 }
2171
2172 do
2173 {
2174 layer_uv_element = layer_uv_element->sibling;
2175 } while (layer_uv_element && layer_uv_element->id != "LayerElementUV");
2176 }
2177
2178 const Element* layer_tangent_element = findChild(element, "LayerElementTangents");
2179 if (layer_tangent_element)
2180 {
2181 std::vector<Vec3> tmp;
2182 std::vector<int> tmp_indices;
2183 GeometryImpl::VertexDataMapping mapping;
2184 if (findChild(*layer_tangent_element, "Tangents"))
2185 {
2186 if (!parseVertexData(*layer_tangent_element, "Tangents", "TangentsIndex", &tmp, &tmp_indices, &mapping)) return Error("Invalid tangets");
2187 }
2188 else
2189 {
2190 if (!parseVertexData(*layer_tangent_element, "Tangent", "TangentIndex", &tmp, &tmp_indices, &mapping)) return Error("Invalid tangets");
2191 }
2192 if (!tmp.empty())
2193 {
2194 splat(&geom->tangents, mapping, tmp, tmp_indices, original_indices);
2195 remap(&geom->tangents, to_old_indices);
2196 }
2197 }
2198
2199 const Element* layer_color_element = findChild(element, "LayerElementColor");
2200 if (layer_color_element)
2201 {
2202 std::vector<Vec4> tmp;
2203 std::vector<int> tmp_indices;
2204 GeometryImpl::VertexDataMapping mapping;
2205 if (!parseVertexData(*layer_color_element, "Colors", "ColorIndex", &tmp, &tmp_indices, &mapping)) return Error("Invalid colors");
2206 if (!tmp.empty())
2207 {
2208 splat(&geom->colors, mapping, tmp, tmp_indices, original_indices);
2209 remap(&geom->colors, to_old_indices);
2210 }
2211 }
2212
2213 const Element* layer_normal_element = findChild(element, "LayerElementNormal");
2214 if (layer_normal_element)
2215 {
2216 std::vector<Vec3> tmp;
2217 std::vector<int> tmp_indices;
2218 GeometryImpl::VertexDataMapping mapping;
2219 if (!parseVertexData(*layer_normal_element, "Normals", "NormalsIndex", &tmp, &tmp_indices, &mapping)) return Error("Invalid normals");
2220 if (!tmp.empty())
2221 {
2222 splat(&geom->normals, mapping, tmp, tmp_indices, original_indices);
2223 remap(&geom->normals, to_old_indices);
2224 }
2225 }
2226
2227 return geom.release();
2228 }
2229
2230
isString(const Property * prop)2231 static bool isString(const Property* prop)
2232 {
2233 if (!prop) return false;
2234 return prop->getType() == Property::STRING;
2235 }
2236
2237
isLong(const Property * prop)2238 static bool isLong(const Property* prop)
2239 {
2240 if (!prop) return false;
2241 return prop->getType() == Property::LONG;
2242 }
2243
2244
parseConnections(const Element & root,Scene * scene)2245 static bool parseConnections(const Element& root, Scene* scene)
2246 {
2247 assert(scene);
2248
2249 const Element* connections = findChild(root, "Connections");
2250 if (!connections) return true;
2251
2252 const Element* connection = connections->child;
2253 while (connection)
2254 {
2255 if (!isString(connection->first_property)
2256 || !isLong(connection->first_property->next)
2257 || !isLong(connection->first_property->next->next))
2258 {
2259 Error::s_message = "Invalid connection";
2260 return false;
2261 }
2262
2263 Scene::Connection c;
2264 c.from = connection->first_property->next->value.toU64();
2265 c.to = connection->first_property->next->next->value.toU64();
2266 if (connection->first_property->value == "OO")
2267 {
2268 c.type = Scene::Connection::OBJECT_OBJECT;
2269 }
2270 else if (connection->first_property->value == "OP")
2271 {
2272 c.type = Scene::Connection::OBJECT_PROPERTY;
2273 if (!connection->first_property->next->next->next)
2274 {
2275 Error::s_message = "Invalid connection";
2276 return false;
2277 }
2278 c.property = connection->first_property->next->next->next->value;
2279 }
2280 else
2281 {
2282 assert(false);
2283 Error::s_message = "Not supported";
2284 return false;
2285 }
2286 scene->m_connections.push_back(c);
2287
2288 connection = connection->sibling;
2289 }
2290 return true;
2291 }
2292
2293
parseTakes(Scene * scene)2294 static bool parseTakes(Scene* scene)
2295 {
2296 const Element* takes = findChild((const Element&)*scene->getRootElement(), "Takes");
2297 if (!takes) return true;
2298
2299 const Element* object = takes->child;
2300 while (object)
2301 {
2302 if (object->id == "Take")
2303 {
2304 if (!isString(object->first_property))
2305 {
2306 Error::s_message = "Invalid name in take";
2307 return false;
2308 }
2309
2310 TakeInfo take;
2311 take.name = object->first_property->value;
2312 const Element* filename = findChild(*object, "FileName");
2313 if (filename)
2314 {
2315 if (!isString(filename->first_property))
2316 {
2317 Error::s_message = "Invalid filename in take";
2318 return false;
2319 }
2320 take.filename = filename->first_property->value;
2321 }
2322 const Element* local_time = findChild(*object, "LocalTime");
2323 if (local_time)
2324 {
2325 if (!isLong(local_time->first_property) || !isLong(local_time->first_property->next))
2326 {
2327 Error::s_message = "Invalid local time in take";
2328 return false;
2329 }
2330
2331 take.local_time_from = fbxTimeToSeconds(local_time->first_property->value.toI64());
2332 take.local_time_to = fbxTimeToSeconds(local_time->first_property->next->value.toI64());
2333 }
2334 const Element* reference_time = findChild(*object, "ReferenceTime");
2335 if (reference_time)
2336 {
2337 if (!isLong(reference_time->first_property) || !isLong(reference_time->first_property->next))
2338 {
2339 Error::s_message = "Invalid reference time in take";
2340 return false;
2341 }
2342
2343 take.reference_time_from = fbxTimeToSeconds(reference_time->first_property->value.toI64());
2344 take.reference_time_to = fbxTimeToSeconds(reference_time->first_property->next->value.toI64());
2345 }
2346
2347 scene->m_take_infos.push_back(take);
2348 }
2349
2350 object = object->sibling;
2351 }
2352
2353 return true;
2354 }
2355
2356
getFramerateFromTimeMode(FrameRate time_mode,float custom_frame_rate)2357 static float getFramerateFromTimeMode(FrameRate time_mode, float custom_frame_rate)
2358 {
2359 switch (time_mode)
2360 {
2361 case FrameRate_DEFAULT: return 1;
2362 case FrameRate_120: return 120;
2363 case FrameRate_100: return 100;
2364 case FrameRate_60: return 60;
2365 case FrameRate_50: return 50;
2366 case FrameRate_48: return 48;
2367 case FrameRate_30: return 30;
2368 case FrameRate_30_DROP: return 30;
2369 case FrameRate_NTSC_DROP_FRAME: return 29.9700262f;
2370 case FrameRate_NTSC_FULL_FRAME: return 29.9700262f;
2371 case FrameRate_PAL: return 25;
2372 case FrameRate_CINEMA: return 24;
2373 case FrameRate_1000: return 1000;
2374 case FrameRate_CINEMA_ND: return 23.976f;
2375 case FrameRate_CUSTOM: return custom_frame_rate;
2376 }
2377 return -1;
2378 }
2379
2380
parseGlobalSettings(const Element & root,Scene * scene)2381 static void parseGlobalSettings(const Element& root, Scene* scene)
2382 {
2383 for (ofbx::Element* settings = root.child; settings; settings = settings->sibling)
2384 {
2385 if (settings->id == "GlobalSettings")
2386 {
2387 for (ofbx::Element* props70 = settings->child; props70; props70 = props70->sibling)
2388 {
2389 if (props70->id == "Properties70")
2390 {
2391 for (ofbx::Element* node = props70->child; node; node = node->sibling)
2392 {
2393 if (!node->first_property)
2394 continue;
2395
2396 #define get_property(name, field, type) if(node->first_property->value == name) \
2397 { \
2398 ofbx::IElementProperty* prop = node->getProperty(4); \
2399 if (prop) \
2400 { \
2401 ofbx::DataView value = prop->getValue(); \
2402 scene->m_settings.field = *(type*)value.begin; \
2403 } \
2404 }
2405
2406 get_property("UpAxis", UpAxis, UpVector);
2407 get_property("UpAxisSign", UpAxisSign, int);
2408 get_property("FrontAxis", FrontAxis, FrontVector);
2409 get_property("FrontAxisSign", FrontAxisSign, int);
2410 get_property("CoordAxis", CoordAxis, CoordSystem);
2411 get_property("CoordAxisSign", CoordAxisSign, int);
2412 get_property("OriginalUpAxis", OriginalUpAxis, int);
2413 get_property("OriginalUpAxisSign", OriginalUpAxisSign, int);
2414 get_property("UnitScaleFactor", UnitScaleFactor, float);
2415 get_property("OriginalUnitScaleFactor", OriginalUnitScaleFactor, float);
2416 get_property("TimeSpanStart", TimeSpanStart, u64);
2417 get_property("TimeSpanStop", TimeSpanStop, u64);
2418 get_property("TimeMode", TimeMode, FrameRate);
2419 get_property("CustomFrameRate", CustomFrameRate, float);
2420
2421 #undef get_property
2422
2423 scene->m_scene_frame_rate = getFramerateFromTimeMode(scene->m_settings.TimeMode, scene->m_settings.CustomFrameRate);
2424 }
2425 break;
2426 }
2427 }
2428 break;
2429 }
2430 }
2431 }
2432
2433
parseObjects(const Element & root,Scene * scene)2434 static bool parseObjects(const Element& root, Scene* scene)
2435 {
2436 const Element* objs = findChild(root, "Objects");
2437 if (!objs) return true;
2438
2439 scene->m_root = new Root(*scene, root);
2440 scene->m_root->id = 0;
2441 scene->m_object_map[0] = {&root, scene->m_root};
2442
2443 const Element* object = objs->child;
2444 while (object)
2445 {
2446 if (!isLong(object->first_property))
2447 {
2448 Error::s_message = "Invalid";
2449 return false;
2450 }
2451
2452 u64 id = object->first_property->value.toU64();
2453 scene->m_object_map[id] = {object, nullptr};
2454 object = object->sibling;
2455 }
2456
2457 for (auto iter : scene->m_object_map)
2458 {
2459 OptionalError<Object*> obj = nullptr;
2460
2461 if (iter.second.object == scene->m_root) continue;
2462
2463 if (iter.second.element->id == "Geometry")
2464 {
2465 Property* last_prop = iter.second.element->first_property;
2466 while (last_prop->next) last_prop = last_prop->next;
2467 if (last_prop && last_prop->value == "Mesh")
2468 {
2469 obj = parseGeometry(*scene, *iter.second.element);
2470 }
2471 }
2472 else if (iter.second.element->id == "Material")
2473 {
2474 obj = parseMaterial(*scene, *iter.second.element);
2475 }
2476 else if (iter.second.element->id == "AnimationStack")
2477 {
2478 obj = parse<AnimationStackImpl>(*scene, *iter.second.element);
2479 if (!obj.isError())
2480 {
2481 AnimationStackImpl* stack = (AnimationStackImpl*)obj.getValue();
2482 scene->m_animation_stacks.push_back(stack);
2483 }
2484 }
2485 else if (iter.second.element->id == "AnimationLayer")
2486 {
2487 obj = parse<AnimationLayerImpl>(*scene, *iter.second.element);
2488 }
2489 else if (iter.second.element->id == "AnimationCurve")
2490 {
2491 obj = parseAnimationCurve(*scene, *iter.second.element);
2492 }
2493 else if (iter.second.element->id == "AnimationCurveNode")
2494 {
2495 obj = parse<AnimationCurveNodeImpl>(*scene, *iter.second.element);
2496 }
2497 else if (iter.second.element->id == "Deformer")
2498 {
2499 IElementProperty* class_prop = iter.second.element->getProperty(2);
2500
2501 if (class_prop)
2502 {
2503 if (class_prop->getValue() == "Cluster")
2504 obj = parseCluster(*scene, *iter.second.element);
2505 else if (class_prop->getValue() == "Skin")
2506 obj = parse<SkinImpl>(*scene, *iter.second.element);
2507 }
2508 }
2509 else if (iter.second.element->id == "NodeAttribute")
2510 {
2511 obj = parseNodeAttribute(*scene, *iter.second.element);
2512 }
2513 else if (iter.second.element->id == "Model")
2514 {
2515 IElementProperty* class_prop = iter.second.element->getProperty(2);
2516
2517 if (class_prop)
2518 {
2519 if (class_prop->getValue() == "Mesh")
2520 {
2521 obj = parseMesh(*scene, *iter.second.element);
2522 if (!obj.isError())
2523 {
2524 Mesh* mesh = (Mesh*)obj.getValue();
2525 scene->m_meshes.push_back(mesh);
2526 obj = mesh;
2527 }
2528 }
2529 else if (class_prop->getValue() == "LimbNode")
2530 obj = parseLimbNode(*scene, *iter.second.element);
2531 else if (class_prop->getValue() == "Null")
2532 obj = parse<NullImpl>(*scene, *iter.second.element);
2533 else if (class_prop->getValue() == "Root")
2534 obj = parse<NullImpl>(*scene, *iter.second.element);
2535 }
2536 }
2537 else if (iter.second.element->id == "Texture")
2538 {
2539 obj = parseTexture(*scene, *iter.second.element);
2540 }
2541
2542 if (obj.isError()) return false;
2543
2544 scene->m_object_map[iter.first].object = obj.getValue();
2545 if (obj.getValue())
2546 {
2547 scene->m_all_objects.push_back(obj.getValue());
2548 obj.getValue()->id = iter.first;
2549 }
2550 }
2551
2552 for (const Scene::Connection& con : scene->m_connections)
2553 {
2554 Object* parent = scene->m_object_map[con.to].object;
2555 Object* child = scene->m_object_map[con.from].object;
2556 if (!child) continue;
2557 if (!parent) continue;
2558
2559 switch (child->getType())
2560 {
2561 case Object::Type::NODE_ATTRIBUTE:
2562 if (parent->node_attribute)
2563 {
2564 Error::s_message = "Invalid node attribute";
2565 return false;
2566 }
2567 parent->node_attribute = (NodeAttribute*)child;
2568 break;
2569 case Object::Type::ANIMATION_CURVE_NODE:
2570 if (parent->isNode())
2571 {
2572 AnimationCurveNodeImpl* node = (AnimationCurveNodeImpl*)child;
2573 node->bone = parent;
2574 node->bone_link_property = con.property;
2575 }
2576 break;
2577 }
2578
2579 switch (parent->getType())
2580 {
2581 case Object::Type::MESH:
2582 {
2583 MeshImpl* mesh = (MeshImpl*)parent;
2584 switch (child->getType())
2585 {
2586 case Object::Type::GEOMETRY:
2587 if (mesh->geometry)
2588 {
2589 Error::s_message = "Invalid mesh";
2590 return false;
2591 }
2592 mesh->geometry = (Geometry*)child;
2593 break;
2594 case Object::Type::MATERIAL: mesh->materials.push_back((Material*)child); break;
2595 }
2596 break;
2597 }
2598 case Object::Type::SKIN:
2599 {
2600 SkinImpl* skin = (SkinImpl*)parent;
2601 if (child->getType() == Object::Type::CLUSTER)
2602 {
2603 ClusterImpl* cluster = (ClusterImpl*)child;
2604 skin->clusters.push_back(cluster);
2605 if (cluster->skin)
2606 {
2607 Error::s_message = "Invalid cluster";
2608 return false;
2609 }
2610 cluster->skin = skin;
2611 }
2612 break;
2613 }
2614 case Object::Type::MATERIAL:
2615 {
2616 MaterialImpl* mat = (MaterialImpl*)parent;
2617 if (child->getType() == Object::Type::TEXTURE)
2618 {
2619 Texture::TextureType type = Texture::COUNT;
2620 if (con.property == "NormalMap")
2621 type = Texture::NORMAL;
2622 else if (con.property == "DiffuseColor")
2623 type = Texture::DIFFUSE;
2624 if (type == Texture::COUNT) break;
2625
2626 if (mat->textures[type])
2627 {
2628 break;// This may happen for some models (eg. 2 normal maps in use)
2629 Error::s_message = "Invalid material";
2630 return false;
2631 }
2632
2633 mat->textures[type] = (Texture*)child;
2634 }
2635 break;
2636 }
2637 case Object::Type::GEOMETRY:
2638 {
2639 GeometryImpl* geom = (GeometryImpl*)parent;
2640 if (child->getType() == Object::Type::SKIN) geom->skin = (Skin*)child;
2641 break;
2642 }
2643 case Object::Type::CLUSTER:
2644 {
2645 ClusterImpl* cluster = (ClusterImpl*)parent;
2646 if (child->getType() == Object::Type::LIMB_NODE || child->getType() == Object::Type::MESH || child->getType() == Object::Type::NULL_NODE)
2647 {
2648 if (cluster->link)
2649 {
2650 Error::s_message = "Invalid cluster";
2651 return false;
2652 }
2653
2654 cluster->link = child;
2655 }
2656 break;
2657 }
2658 case Object::Type::ANIMATION_LAYER:
2659 {
2660 if (child->getType() == Object::Type::ANIMATION_CURVE_NODE)
2661 {
2662 ((AnimationLayerImpl*)parent)->curve_nodes.push_back((AnimationCurveNodeImpl*)child);
2663 }
2664 }
2665 break;
2666 case Object::Type::ANIMATION_CURVE_NODE:
2667 {
2668 AnimationCurveNodeImpl* node = (AnimationCurveNodeImpl*)parent;
2669 if (child->getType() == Object::Type::ANIMATION_CURVE)
2670 {
2671 if (!node->curves[0].curve)
2672 {
2673 node->curves[0].connection = &con;
2674 node->curves[0].curve = (AnimationCurve*)child;
2675 }
2676 else if (!node->curves[1].curve)
2677 {
2678 node->curves[1].connection = &con;
2679 node->curves[1].curve = (AnimationCurve*)child;
2680 }
2681 else if (!node->curves[2].curve)
2682 {
2683 node->curves[2].connection = &con;
2684 node->curves[2].curve = (AnimationCurve*)child;
2685 }
2686 else
2687 {
2688 Error::s_message = "Invalid animation node";
2689 return false;
2690 }
2691 }
2692 break;
2693 }
2694 }
2695 }
2696
2697 for (auto iter : scene->m_object_map)
2698 {
2699 Object* obj = iter.second.object;
2700 if (!obj) continue;
2701 if(obj->getType() == Object::Type::CLUSTER)
2702 {
2703 if (!((ClusterImpl*)iter.second.object)->postprocess())
2704 {
2705 Error::s_message = "Failed to postprocess cluster";
2706 return false;
2707 }
2708 }
2709 }
2710
2711 return true;
2712 }
2713
2714
getRotationOrder() const2715 RotationOrder Object::getRotationOrder() const
2716 {
2717 // This assumes that the default rotation order is EULER_XYZ.
2718 return (RotationOrder) resolveEnumProperty(*this, "RotationOrder", (int) RotationOrder::EULER_XYZ);
2719 }
2720
2721
getRotationOffset() const2722 Vec3 Object::getRotationOffset() const
2723 {
2724 return resolveVec3Property(*this, "RotationOffset", {0, 0, 0});
2725 }
2726
2727
getRotationPivot() const2728 Vec3 Object::getRotationPivot() const
2729 {
2730 return resolveVec3Property(*this, "RotationPivot", {0, 0, 0});
2731 }
2732
2733
getPostRotation() const2734 Vec3 Object::getPostRotation() const
2735 {
2736 return resolveVec3Property(*this, "PostRotation", {0, 0, 0});
2737 }
2738
2739
getScalingOffset() const2740 Vec3 Object::getScalingOffset() const
2741 {
2742 return resolveVec3Property(*this, "ScalingOffset", {0, 0, 0});
2743 }
2744
2745
getScalingPivot() const2746 Vec3 Object::getScalingPivot() const
2747 {
2748 return resolveVec3Property(*this, "ScalingPivot", {0, 0, 0});
2749 }
2750
2751
evalLocal(const Vec3 & translation,const Vec3 & rotation) const2752 Matrix Object::evalLocal(const Vec3& translation, const Vec3& rotation) const
2753 {
2754 return evalLocal(translation, rotation, getLocalScaling());
2755 }
2756
2757
evalLocal(const Vec3 & translation,const Vec3 & rotation,const Vec3 & scaling) const2758 Matrix Object::evalLocal(const Vec3& translation, const Vec3& rotation, const Vec3& scaling) const
2759 {
2760 Vec3 rotation_pivot = getRotationPivot();
2761 Vec3 scaling_pivot = getScalingPivot();
2762 RotationOrder rotation_order = getRotationOrder();
2763
2764 Matrix s = makeIdentity();
2765 s.m[0] = scaling.x;
2766 s.m[5] = scaling.y;
2767 s.m[10] = scaling.z;
2768
2769 Matrix t = makeIdentity();
2770 setTranslation(translation, &t);
2771
2772 Matrix r = getRotationMatrix(rotation, rotation_order);
2773 Matrix r_pre = getRotationMatrix(getPreRotation(), RotationOrder::EULER_XYZ);
2774 Matrix r_post_inv = getRotationMatrix(-getPostRotation(), RotationOrder::EULER_ZYX);
2775
2776 Matrix r_off = makeIdentity();
2777 setTranslation(getRotationOffset(), &r_off);
2778
2779 Matrix r_p = makeIdentity();
2780 setTranslation(rotation_pivot, &r_p);
2781
2782 Matrix r_p_inv = makeIdentity();
2783 setTranslation(-rotation_pivot, &r_p_inv);
2784
2785 Matrix s_off = makeIdentity();
2786 setTranslation(getScalingOffset(), &s_off);
2787
2788 Matrix s_p = makeIdentity();
2789 setTranslation(scaling_pivot, &s_p);
2790
2791 Matrix s_p_inv = makeIdentity();
2792 setTranslation(-scaling_pivot, &s_p_inv);
2793
2794 // http://help.autodesk.com/view/FBX/2017/ENU/?guid=__files_GUID_10CDD63C_79C1_4F2D_BB28_AD2BE65A02ED_htm
2795 return t * r_off * r_p * r_pre * r * r_post_inv * r_p_inv * s_off * s_p * s * s_p_inv;
2796 }
2797
2798
getLocalTranslation() const2799 Vec3 Object::getLocalTranslation() const
2800 {
2801 return resolveVec3Property(*this, "Lcl Translation", {0, 0, 0});
2802 }
2803
2804
getPreRotation() const2805 Vec3 Object::getPreRotation() const
2806 {
2807 return resolveVec3Property(*this, "PreRotation", {0, 0, 0});
2808 }
2809
2810
getLocalRotation() const2811 Vec3 Object::getLocalRotation() const
2812 {
2813 return resolveVec3Property(*this, "Lcl Rotation", {0, 0, 0});
2814 }
2815
2816
getLocalScaling() const2817 Vec3 Object::getLocalScaling() const
2818 {
2819 return resolveVec3Property(*this, "Lcl Scaling", {1, 1, 1});
2820 }
2821
2822
getGlobalTransform() const2823 Matrix Object::getGlobalTransform() const
2824 {
2825 const Object* parent = getParent();
2826 if (!parent) return evalLocal(getLocalTranslation(), getLocalRotation());
2827
2828 return parent->getGlobalTransform() * evalLocal(getLocalTranslation(), getLocalRotation());
2829 }
2830
2831
getLocalTransform() const2832 Matrix Object::getLocalTransform() const
2833 {
2834 return evalLocal(getLocalTranslation(), getLocalRotation(), getLocalScaling());
2835 }
2836
2837
resolveObjectLinkReverse(Object::Type type) const2838 Object* Object::resolveObjectLinkReverse(Object::Type type) const
2839 {
2840 u64 id = element.getFirstProperty() ? element.getFirstProperty()->getValue().toU64() : 0;
2841 for (auto& connection : scene.m_connections)
2842 {
2843 if (connection.from == id && connection.to != 0)
2844 {
2845 Object* obj = scene.m_object_map.find(connection.to)->second.object;
2846 if (obj && obj->getType() == type) return obj;
2847 }
2848 }
2849 return nullptr;
2850 }
2851
2852
getScene() const2853 const IScene& Object::getScene() const
2854 {
2855 return scene;
2856 }
2857
2858
resolveObjectLink(int idx) const2859 Object* Object::resolveObjectLink(int idx) const
2860 {
2861 u64 id = element.getFirstProperty() ? element.getFirstProperty()->getValue().toU64() : 0;
2862 for (auto& connection : scene.m_connections)
2863 {
2864 if (connection.to == id && connection.from != 0)
2865 {
2866 Object* obj = scene.m_object_map.find(connection.from)->second.object;
2867 if (obj)
2868 {
2869 if (idx == 0) return obj;
2870 --idx;
2871 }
2872 }
2873 }
2874 return nullptr;
2875 }
2876
2877
resolveObjectLink(Object::Type type,const char * property,int idx) const2878 Object* Object::resolveObjectLink(Object::Type type, const char* property, int idx) const
2879 {
2880 u64 id = element.getFirstProperty() ? element.getFirstProperty()->getValue().toU64() : 0;
2881 for (auto& connection : scene.m_connections)
2882 {
2883 if (connection.to == id && connection.from != 0)
2884 {
2885 Object* obj = scene.m_object_map.find(connection.from)->second.object;
2886 if (obj && obj->getType() == type)
2887 {
2888 if (property == nullptr || connection.property == property)
2889 {
2890 if (idx == 0) return obj;
2891 --idx;
2892 }
2893 }
2894 }
2895 }
2896 return nullptr;
2897 }
2898
2899
getParent() const2900 Object* Object::getParent() const
2901 {
2902 Object* parent = nullptr;
2903 for (auto& connection : scene.m_connections)
2904 {
2905 if (connection.from == id)
2906 {
2907 Object* obj = scene.m_object_map.find(connection.to)->second.object;
2908 if (obj && obj->is_node)
2909 {
2910 assert(parent == nullptr);
2911 parent = obj;
2912 }
2913 }
2914 }
2915 return parent;
2916 }
2917
2918
load(const u8 * data,int size)2919 IScene* load(const u8* data, int size)
2920 {
2921 std::unique_ptr<Scene> scene(new Scene());
2922 scene->m_data.resize(size);
2923 memcpy(&scene->m_data[0], data, size);
2924 OptionalError<Element*> root = tokenize(&scene->m_data[0], size);
2925 if (root.isError())
2926 {
2927 Error::s_message = "";
2928 root = tokenizeText(&scene->m_data[0], size);
2929 if (root.isError()) return nullptr;
2930 }
2931
2932 scene->m_root_element = root.getValue();
2933 assert(scene->m_root_element);
2934
2935 //if (parseTemplates(*root.getValue()).isError()) return nullptr;
2936 if(!parseConnections(*root.getValue(), scene.get())) return nullptr;
2937 if(!parseTakes(scene.get())) return nullptr;
2938 if(!parseObjects(*root.getValue(), scene.get())) return nullptr;
2939 parseGlobalSettings(*root.getValue(), scene.get());
2940
2941 return scene.release();
2942 }
2943
2944
getError()2945 const char* getError()
2946 {
2947 return Error::s_message;
2948 }
2949
2950
2951 } // namespace ofbx
2952