9#include <unordered_map>
36 template <
typename T,
typename... Args>
T*
allocate(Args&&... args)
58 std::vector<float>
tmp;
122 error_checked =
true;
132 bool error_checked =
false;
165 return {-v.
x, -v.
y, -v.
z};
172 for (
int j = 0; j < 4; ++j)
174 for (
int i = 0; i < 4; ++i)
177 for (
int k = 0; k < 4; ++k)
179 tmp += lhs.
m[i + k * 4] * rhs.
m[k + j * 4];
181 res.
m[i + j * 4] = tmp;
190 return {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
200 m.
m[5] = m.
m[10] = c;
214 m.
m[0] = m.
m[10] = c;
238 const double TO_RAD = 3.1415926535897932384626433832795028 / 180.0;
258 return double(value) / 46186158000L;
264 return i64(value * 46186158000L);
270 return {v.
x * f, v.
y * f, v.
z * f};
276 return {a.
x + b.
x, a.
y + b.
y, a.
z + b.
z};
280template <
int SIZE>
static bool copyString(
char (&destination)[SIZE],
const char* source)
282 const char* src = source;
283 char* dest = destination;
285 if (!src)
return false;
287 while (*src &&
length > 1)
305 memcpy(&result,
begin,
sizeof(
u64));
308 static_assert(
sizeof(
unsigned long long) >=
sizeof(
u64),
"can't use strtoull");
309 return strtoull((
const char*)
begin,
nullptr, 10);
319 memcpy(&result,
begin,
sizeof(
i64));
322 static_assert(
sizeof(
long long) >=
sizeof(
i64),
"can't use atoll");
323 return atoll((
const char*)
begin);
333 memcpy(&result,
begin,
sizeof(
int));
336 return atoi((
const char*)
begin);
346 memcpy(&result,
begin,
sizeof(
u32));
349 return (
u32)atoll((
const char*)
begin);
359 memcpy(&result,
begin,
sizeof(
double));
362 return atof((
const char*)
begin);
372 memcpy(&result,
begin,
sizeof(
float));
375 return (
float)atof((
const char*)
begin);
382 const char* c2 = (
const char*)
begin;
383 while (*c && c2 != (
const char*)
end)
385 if (*c != *c2)
return false;
389 return c2 == (
const char*)
end && *c ==
'\0';
442 for (
int i = 0; i < idx; ++i)
444 if (prop ==
nullptr)
return nullptr;
462 if ((*iter)->id ==
id)
return *iter;
472 if (!props)
return nullptr;
490 if (!element)
return default_value;
492 if (!x)
return default_value;
501 if (!element)
return default_value;
503 if (!x || !x->
next || !x->
next->
next)
return default_value;
513 , node_attribute(nullptr)
516 if (e.first_property && e.first_property->next)
518 e.first_property->next->value.toString(
name);
547 if (cursor->
current +
sizeof(
T) > cursor->
end)
return Error(
"Reading past the end");
588 if (cursor->
current == cursor->
end)
return Error(
"Reading past the end");
591 prop->
next =
nullptr;
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;
633 default:
return Error(
"Unknown property type");
659 if (end_offset.
getValue() == 0)
return nullptr;
666 if (
id.isError())
return Error();
670 element->
id =
id.getValue();
672 element->
child =
nullptr;
685 prop_link = &(*prop_link)->
next;
690 int BLOCK_SENTINEL_LENGTH = version >= 7500 ? 25 : 13;
693 while (cursor->
current - cursor->
begin < ((ptrdiff_t)end_offset.
getValue() - BLOCK_SENTINEL_LENGTH))
706 if (cursor->
current + BLOCK_SENTINEL_LENGTH > cursor->
end)
708 return Error(
"Reading past the end");
711 cursor->
current += BLOCK_SENTINEL_LENGTH;
754 return isalnum(c) || c ==
'_' || c ==
'-';
775 prop->
next =
nullptr;
851 if (is_any) ++prop->
count;
859 if (is_any) ++prop->
count;
866 return Error(
"TODO");
873 if (cursor->
current == cursor->
end)
return Error(
"Unexpected end of file");
874 if (*cursor->
current !=
':')
return Error(
"Unexpected character");
878 if (cursor->
current == cursor->
end)
return Error(
"Unexpected end of file");
899 prop_link = &(*prop_link)->
next;
930 cursor.
end = data + size;
935 root->
id.
end =
nullptr;
936 root->
child =
nullptr;
954 if (!*element)
return root;
955 element = &(*element)->
sibling;
968 cursor.
end = data + size;
971 cursor.
current +=
sizeof(*header);
977 root->
id.
end =
nullptr;
978 root->
child =
nullptr;
989 if (!*element)
return root;
990 element = &(*element)->
sibling;
1000 std::unordered_map<std::string, Element*> templates;
1004 if (def->
id ==
"ObjectType")
1009 if (subdef->
id ==
"PropertyTemplate")
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;
1030 :
Object(_scene, _element)
1038 :
Mesh(_scene, _element)
1051 scale_mtx.m[0] = (float)
scale.x;
1052 scale_mtx.m[5] = (
float)
scale.y;
1053 scale_mtx.m[10] = (float)
scale.z;
1057 return scale_mtx * mtx;
1077 :
Object(_scene, _element)
1129 :
Object(_scene, _element)
1140 :
Object(_scene, _element)
1149 :
Object(_scene, _element)
1169 :
Object(_scene, _element)
1217 const Vec2*
getUVs(
int index = 0)
const override {
return index < 0 || index >=
s_uvs_max ||
uvs[index].empty() ? nullptr : &
uvs[index][0]; }
1227 :
Object(_scene, _element)
1238 :
Shape(_scene, _element)
1254 :
Object(_scene, _element)
1280 if (!geom)
return false;
1300 int* ir = allocator.
int_tmp.empty() ? nullptr : &allocator.
int_tmp[0];
1302 for (
int i = 0, c = (
int)allocator.
int_tmp.size(); i < c; ++i)
1304 int old_idx = ir[i];
1307 if (n->
index == -1)
continue;
1331 :
Object(_scene, _element)
1337 :
Object(_scene, _element)
1343 :
Object(_scene, _element)
1349 :
Object(_scene, _element)
1364 return resolveObjectLink<AnimationLayer>(index);
1390 :
Object(_scene, _element)
1398 :
Skin(_scene, _element)
1412 :
Object(_scene, _element)
1435 if (!geom)
return false;
1449 for (
int i = 0; i < (int)
shapes.size(); i++)
1452 if (!shape->postprocess(geom, allocator))
return false;
1467 :
Object(_scene, _element)
1489 :
Object(_scene, _element)
1495 :
Object(_scene, _element)
1503 :
Pose(_scene, _element)
1542 :
Object(_scene, _element)
1625 if (info.name == name)
return &info;
1728 assert(idx >= 0 && idx < 3);
1737 auto getCoord = [&](
const Curve& curve,
i64 fbx_time,
int idx) {
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)
1748 if (times[i] >= fbx_time)
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;
1757 return {getCoord(
curves[0], fbx_time, 0), getCoord(
curves[1], fbx_time, 1), getCoord(
curves[2], fbx_time, 2)};
1795 if (index >= (
int)
curve_nodes.size() || index < 0)
return nullptr;
1804 if (node->bone_link_property == prop && node->bone == &bone)
return node;
1821 if (!content_element)
return;
1826 if (!filename_element)
return;
1841 if (texture_filename && texture_filename->first_property)
1843 texture->
filename = texture_filename->first_property->value;
1852 const Element* texture_relative_filename =
findChild(element,
"RelativeFilename");
1853 if (texture_relative_filename && texture_relative_filename->
first_property)
1878template <
typename T>
1881 T* obj = allocator.
allocate<
T>(scene, element);
1891 if (transform_link && transform_link->first_property)
1896 return Error(
"Failed to parse TransformLink");
1904 return Error(
"Failed to parse Transform");
1916 if (type_flags && type_flags->first_property)
1931 return Error(
"Invalid limb node");
1946 return Error(
"Invalid mesh");
1958 if (prop) prop = prop->child;
1961 if (prop->id ==
"P" && prop->first_property)
1963 if (prop->first_property->value ==
"DiffuseColor")
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();
1969 else if (prop->first_property->value ==
"SpecularColor")
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();
1975 else if (prop->first_property->value ==
"Shininess")
1977 material->
shininess = (float)prop->getProperty(4)->getValue().toDouble();
1979 else if (prop->first_property->value ==
"ShininessExponent")
1983 else if (prop->first_property->value ==
"ReflectionColor")
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();
1989 else if (prop->first_property->value ==
"AmbientColor")
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();
1995 else if (prop->first_property->value ==
"EmissiveColor")
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();
2001 else if (prop->first_property->value ==
"ReflectionFactor")
2003 material->
reflection_factor = (float)prop->getProperty(4)->getValue().toDouble();
2005 else if (prop->first_property->value ==
"BumpFactor")
2007 material->
bump_factor = (float)prop->getProperty(4)->getValue().toDouble();
2009 else if (prop->first_property->value ==
"AmbientFactor")
2011 material->
ambient_factor = (float)prop->getProperty(4)->getValue().toDouble();
2013 else if (prop->first_property->value ==
"DiffuseFactor")
2015 material->
diffuse_factor = (float)prop->getProperty(4)->getValue().toDouble();
2017 else if (prop->first_property->value ==
"SpecularFactor")
2019 material->
specular_factor = (float)prop->getProperty(4)->getValue().toDouble();
2021 else if (prop->first_property->value ==
"EmissiveFactor")
2023 material->
emissive_factor = (float)prop->getProperty(4)->getValue().toDouble();
2026 prop = prop->sibling;
2032template <
typename T>
static bool parseTextArrayRaw(
const Property& property,
T* out,
int max_size);
2041 switch (property.
type)
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;
2050 const u8* data =
property.value.begin +
sizeof(
u32) * 3;
2051 if (data > property.
value.
end)
return false;
2053 u32 count =
property.getCount();
2059 if ((
int)len > max_size)
return false;
2060 if (data + len > property.
value.
end)
return false;
2061 memcpy(out, data, len);
2066 if (
int(elem_size * count) > max_size)
return false;
2067 return decompress(data, len, (
u8*)out, elem_size * count);
2077template <
typename T>
const char*
fromString(
const char* str,
const char* end,
T* val);
2081 const char* iter = str;
2082 while (iter < end && *iter !=
',') ++iter;
2083 if (iter < end) ++iter;
2084 return (
const char*)iter;
2090 *val = strtoull(str,
nullptr, 10);
2091 const char* iter = str;
2092 while (iter < end && *iter !=
',') ++iter;
2093 if (iter < end) ++iter;
2094 return (
const char*)iter;
2101 const char* iter = str;
2102 while (iter < end && *iter !=
',') ++iter;
2103 if (iter < end) ++iter;
2104 return (
const char*)iter;
2111 const char* iter = str;
2112 while (iter < end && *iter !=
',') ++iter;
2113 if (iter < end) ++iter;
2114 return (
const char*)iter;
2120 *val = (float)atof(str);
2121 const char* iter = str;
2122 while (iter < end && *iter !=
',') ++iter;
2123 if (iter < end) ++iter;
2124 return (
const char*)iter;
2128const char*
fromString(
const char* str,
const char* end,
double* val,
int count)
2130 const char* iter = str;
2131 for (
int i = 0; i < count; ++i)
2135 while (iter < end && *iter !=
',') ++iter;
2136 if (iter < end) ++iter;
2138 if (iter == end)
return iter;
2140 return (
const char*)iter;
2170 const u8* iter =
property.value.begin;
2174 iter = (
const u8*)fromString<T>((
const char*)iter, (
const char*)property.
value.
end, &val);
2175 out->push_back(val);
2182 const u8* iter =
property.value.begin;
2187 iter = (
const u8*)fromString<T>((
const char*)iter, (
const char*)property.
value.
end, out);
2189 if (out - out_raw == max_size /
sizeof(
T))
return true;
2191 return out - out_raw == max_size /
sizeof(
T);
2200 u32 count =
property.getCount();
2202 switch (property.
type)
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;
2209 int elem_count =
sizeof(
T) / elem_size;
2210 out->resize(count / elem_count);
2212 if (count == 0)
return true;
2213 return parseArrayRaw(property, &(*out)[0],
int(
sizeof((*out)[0]) * out->size()));
2232 if (property.
type ==
'd')
2238 assert(
sizeof((*out_vec)[0].x) ==
sizeof(
double));
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)
2258 switch (property.
type)
2260 case 'D': elem_size = 8;
break;
2261 case 'F': elem_size = 4;
break;
2262 default:
return false;
2264 const u8* data =
property.value.begin;
2265 if (data > property.
value.
end)
return false;
2266 memcpy(out, data, elem_size);
2277template <
typename T>
2280 const char* index_name,
2281 std::vector<T>* out,
2282 std::vector<int>* out_indices,
2284 std::vector<float>* tmp)
2289 if (!data_element || !data_element->
first_property)
return false;
2291 const Element* mapping_element =
findChild(element,
"MappingInformationType");
2292 const Element* reference_element =
findChild(element,
"ReferenceInformationType");
2293 out_indices->clear();
2335 return (idx < 0) ? (-idx - 1) : idx;
2341 return last ? (-idx - 1) : idx;
2345template <
typename T>
2348 const std::vector<T>& data,
2349 const std::vector<int>& indices,
2350 const std::vector<int>& original_indices)
2357 if (indices.empty())
2359 out->resize(data.size());
2360 memcpy(&(*out)[0], &data[0],
sizeof(data[0]) * data.size());
2364 out->resize(indices.size());
2365 int data_size = (int)data.size();
2366 for (
int i = 0, c = (
int)indices.size(); i < c; ++i)
2368 int index = indices[i];
2370 if ((index < data_size) && (index >= 0))
2371 (*out)[i] = data[index];
2383 out->resize(original_indices.size());
2385 int data_size = (int)data.size();
2386 for (
int i = 0, c = (
int)original_indices.size(); i < c; ++i)
2389 if ((idx < data_size) && (idx >= 0))
2390 (*out)[i] = data[idx];
2402template <
typename T>
static void remap(std::vector<T>* out,
const std::vector<int>& map)
2404 if (out->empty())
return;
2408 int old_size = (int)old.size();
2409 for (
int i = 0, c = (
int)map.size(); i < c; ++i)
2411 out->push_back(map[i] < old_size ? old[map[i]] :
T());
2423 if (times && times->first_property)
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])))
2428 return Error(
"Invalid animation curve");
2437 return Error(
"Invalid animation curve");
2441 if (curve->
times.size() != curve->
values.size())
return Error(
"Invalid animation curve");
2450 while (indices[*idx + 1 + count] >= 0)
2455 *idx = *idx + 2 + count;
2462 if (vtx.
index == -1)
2479 const std::vector<int>& old_indices,
2480 std::vector<int>* to_old_vertices,
2481 std::vector<int>* to_old_indices)
2486 auto getIdx = [&old_indices](
int i) ->
int {
2487 int idx = old_indices[i];
2491 int in_polygon_idx = 0;
2492 for (
int i = 0; i < (int)old_indices.size(); ++i)
2494 int idx = getIdx(i);
2495 if (in_polygon_idx <= 2)
2497 to_old_vertices->push_back(idx);
2498 to_old_indices->push_back(i);
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);
2510 if (old_indices[i] < 0)
2520 const std::vector<Vec3>& vertices,
2521 const std::vector<int>& original_indices,
2522 std::vector<int>& to_old_indices,
2523 bool triangulationEnabled)
2525 if (triangulationEnabled) {
2537 for (
size_t i = 0; i < original_indices.size(); ++i) {
2540 geom->
indices = original_indices;
2541 to_old_indices.resize(original_indices.size());
2542 iota(to_old_indices.begin(), to_old_indices.end(), 0);
2549 int old = to_old_vertices[i];
2558 const std::vector<int>& original_indices)
2560 const Element* layer_material_element =
findChild(element,
"LayerElementMaterial");
2561 if (layer_material_element)
2563 const Element* mapping_element =
findChild(*layer_material_element,
"MappingInformationType");
2564 const Element* reference_element =
findChild(*layer_material_element,
"ReferenceInformationType");
2566 if (!mapping_element || !reference_element)
return Error(
"Invalid LayerElementMaterial");
2574 const Element* indices_element =
findChild(*layer_material_element,
"Materials");
2575 if (!indices_element || !indices_element->
first_property)
return Error(
"Invalid LayerElementMaterial");
2577 std::vector<int> int_tmp;
2581 for (
int poly = 0, c = (
int)int_tmp.size(); poly < c; ++poly)
2584 for (
int i = 0; i < tri_count; ++i) {
2585 geom->
materials.push_back(int_tmp[poly]);
2601 const std::vector<int>& original_indices,
2602 const std::vector<int>& to_old_indices,
2606 while (layer_uv_element)
2608 const int uv_index =
2612 std::vector<Vec2>& uvs = geom->
uvs[uv_index];
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))
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);
2629 layer_uv_element = layer_uv_element->
sibling;
2630 }
while (layer_uv_element && layer_uv_element->
id !=
"LayerElementUV");
2639 const std::vector<int>& original_indices,
2640 const std::vector<int>& to_old_indices,
2643 const Element* layer_tangent_element =
findChild(element,
"LayerElementTangents");
2644 if (!layer_tangent_element ) {
2645 layer_tangent_element =
findChild(element,
"LayerElementTangent");
2647 if (layer_tangent_element)
2650 if (
findChild(*layer_tangent_element,
"Tangents"))
2652 if (!
parseVertexData(*layer_tangent_element,
"Tangents",
"TangentsIndex", &tmp->
v3, &tmp->
i, &mapping, &tmp->
f))
2653 return Error(
"Invalid tangets");
2657 if (!
parseVertexData(*layer_tangent_element,
"Tangent",
"TangentIndex", &tmp->
v3, &tmp->
i, &mapping, &tmp->
f))
2658 return Error(
"Invalid tangets");
2660 if (!tmp->
v3.empty())
2673 const std::vector<int>& original_indices,
2674 const std::vector<int>& to_old_indices,
2677 const Element* layer_color_element =
findChild(element,
"LayerElementColor");
2678 if (layer_color_element)
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())
2685 splat(&geom->
colors, mapping, tmp->
v4, tmp->
i, original_indices);
2696 const std::vector<int>& original_indices,
2697 const std::vector<int>& to_old_indices,
2700 const Element* layer_normal_element =
findChild(element,
"LayerElementNormal");
2701 if (layer_normal_element)
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())
2729 std::vector<Vec3> vertices;
2730 std::vector<int> original_indices;
2731 std::vector<int> to_old_indices;
2739 if (materialParsingError.
isError())
return materialParsingError;
2742 if (uvParsingError.
isError())
return uvParsingError;
2745 if (tangentsParsingError.
isError())
return tangentsParsingError;
2748 if (colorsParsingError.
isError())
return colorsParsingError;
2751 if (normalsParsingError.
isError())
return normalsParsingError;
2784 int* ir = &allocator.
int_tmp[0];
2785 for (
int i = 0, c = (
int)allocator.
int_tmp.size(); i < c; ++i)
2787 int old_idx = ir[i];
2789 if (n->
index == -1)
continue;
2804 if (!prop)
return false;
2811 if (!prop)
return false;
2821 if (!connections)
return true;
2860 connection = connection->
sibling;
2869 if (!takes)
return true;
2874 if (object->
id ==
"Take")
2883 take.
name =
object->first_property->value;
2922 object =
object->sibling;
2956 if (!settings)
return;
2959 if (!props70)
return;
2962 if (!node->first_property)
continue;
2964 #define get_property(name, field, type, getter) if(node->first_property->value == name) \
2966 IElementProperty* prop = node->getProperty(4); \
2969 DataView value = prop->getValue(); \
2970 scene->m_settings.field = (type)value.getter(); \
2974 #define get_time_property(name, field, type, getter) if(node->first_property->value == name) \
2976 IElementProperty* prop = node->getProperty(4); \
2979 DataView value = prop->getValue(); \
2980 scene->m_settings.field = fbxTimeToSeconds((type)value.getter()); \
2987 get_property(
"FrontAxisSign", FrontAxisSign,
int, 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);
2997 get_property(
"CustomFrameRate", CustomFrameRate,
float, toDouble);
3000 #undef get_time_property
3016 u8* ptr = (
u8*)data;
3017 for(
u32 i = 0; i < count; ++i) {
3030 if (!objs)
return true;
3045 u64 id =
object->first_property->value.toU64();
3050 std::vector<ParseGeometryJob> parse_geom_jobs;
3055 if (iter.second.object == scene->
m_root)
continue;
3057 if (iter.second.element->id ==
"Geometry")
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)
3064 scene->m_geometries.push_back(geom);
3066 parse_geom_jobs.push_back(job);
3069 if (last_prop && last_prop->
value ==
"Shape" && !ignore_geometry)
3074 else if (iter.second.element->id ==
"Material")
3076 obj =
parseMaterial(*scene, *iter.second.element, allocator);
3078 else if (iter.second.element->id ==
"AnimationStack")
3080 obj = parse<AnimationStackImpl>(*scene, *iter.second.element, allocator);
3087 else if (iter.second.element->id ==
"AnimationLayer")
3089 obj = parse<AnimationLayerImpl>(*scene, *iter.second.element, allocator);
3091 else if (iter.second.element->id ==
"AnimationCurve")
3095 else if (iter.second.element->id ==
"AnimationCurveNode")
3097 obj = parse<AnimationCurveNodeImpl>(*scene, *iter.second.element, allocator);
3099 else if (iter.second.element->id ==
"Deformer")
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);
3115 else if (iter.second.element->id ==
"NodeAttribute")
3119 else if (iter.second.element->id ==
"Model")
3125 if (class_prop->
getValue() ==
"Mesh")
3127 obj =
parseMesh(*scene, *iter.second.element, allocator);
3135 else if (class_prop->
getValue() ==
"LimbNode")
3136 obj =
parseLimbNode(*scene, *iter.second.element, allocator);
3138 obj = parse<NullImpl>(*scene, *iter.second.element, allocator);
3141 else if (iter.second.element->id ==
"Texture")
3143 obj =
parseTexture(*scene, *iter.second.element, allocator);
3145 else if (iter.second.element->id ==
"Video")
3147 parseVideo(*scene, *iter.second.element, allocator);
3149 else if (iter.second.element->id ==
"Pose")
3151 obj =
parsePose(*scene, *iter.second.element, allocator);
3154 if (obj.
isError())
return false;
3164 if (!parse_geom_jobs.empty()) {
3165 (*job_processor)([](
void* ptr){
3168 }, job_user_ptr, &parse_geom_jobs[0], (
u32)
sizeof(parse_geom_jobs[0]), (
u32)parse_geom_jobs.size());
3172 if (job.is_error)
return false;
3176 job.geom->id = job.id;
3184 if (!child)
continue;
3185 if (!parent)
continue;
3201 node->
bone = parent;
3238 cluster->
skin = skin;
3264 blendShapeChannel->
shapes.push_back(shape);
3276 else if (con.
property ==
"DiffuseColor")
3278 else if (con.
property ==
"SpecularColor")
3280 else if (con.
property ==
"ShininessExponent")
3282 else if (con.
property ==
"EmissiveColor")
3284 else if (con.
property ==
"AmbientColor")
3286 else if (con.
property ==
"ReflectionFactor")
3313 if (cluster->
link && cluster->
link != child)
3319 cluster->
link = child;
3338 if (strcmp(tmp,
"d|X") == 0)
3343 else if (strcmp(tmp,
"d|Y") == 0)
3348 else if (strcmp(tmp,
"d|Z") == 0)
3359 if (!ignore_geometry) {
3362 Object* obj = iter.second.object;
3378 if (!((
PoseImpl*)iter.second.object)->postprocess(scene)) {
3443 s.
m[10] = scaling.
z;
3471 return t * r_off * r_p * r_pre * r * r_post_inv * r_p_inv * s_off * s_p * s * s_p_inv;
3520 if (connection.from ==
id && connection.to != 0)
3524 if (obj && obj->
getType() == type)
return obj;
3542 if (connection.to ==
id && connection.from != 0)
3547 if (idx == 0)
return obj;
3561 if (connection.to ==
id && connection.from != 0)
3564 if (obj && obj->
getType() == type)
3566 if (property ==
nullptr || connection.property == property)
3568 if (idx == 0)
return obj;
3580 Object* parent =
nullptr;
3583 if (connection.from ==
id)
3586 if (obj && obj->
is_node && obj !=
this)
3588 assert(parent ==
nullptr);
3599 std::unique_ptr<Scene> scene(
new Scene());
3600 scene->m_data.resize(size);
3601 memcpy(&scene->m_data[0], data, size);
3604 const bool is_binary = size >= 18 && strncmp((
const char*)data,
"Kaydara FBX Binary", 18) == 0;
3607 root =
tokenize(&scene->m_data[0], size, version, scene->m_allocator);
3610 Error::s_message =
"Unsupported FBX file format version. Minimum supported version is 6.2";
3616 if (root.
isError())
return nullptr;
3620 root =
tokenizeText(&scene->m_data[0], size, scene->m_allocator);
3621 if (root.
isError())
return nullptr;
3624 scene->m_root_element = root.
getValue();
3625 assert(scene->m_root_element);
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;
3633 return scene.release();
int mz_inflateInit(mz_streamp pStream)
int mz_inflate(mz_streamp pStream, int flush)
int mz_inflateEnd(mz_streamp pStream)
DYN_FUNC Complex< Real > sin(const Complex< Real > &)
DYN_FUNC Complex< Real > cos(const Complex< Real > &)
static int resolveEnumProperty(const Object &object, const char *name, int default_value)
static int codeIndex(int idx, bool last)
const char * fromString< i64 >(const char *str, const char *end, i64 *val)
static Matrix rotationY(double angle)
static OptionalError< Element * > readTextElement(Cursor *cursor, Allocator &allocator)
static OptionalError< DataView > readShortString(Cursor *cursor)
const char * fromString(const char *str, const char *end, T *val)
const char * fromString< Vec4 >(const char *str, const char *end, Vec4 *val)
void(*)(JobFunction, void *, void *, u32, u32) JobProcessor
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)
static OptionalError< Object * > parse(const Scene &scene, const Element &element, Allocator &allocator)
static int decodeIndex(int idx)
void(*)(void *) JobFunction
static float getFramerateFromTimeMode(FrameRate time_mode, float custom_frame_rate)
static bool parseDoubleVecData(Property &property, std::vector< T > *out_vec, std::vector< float > *tmp)
static OptionalError< Property * > readTextProperty(Cursor *cursor, Allocator &allocator)
static OptionalError< Object * > parseGeometryNormals(GeometryImpl *geom, const Element &element, const std::vector< int > &original_indices, const std::vector< int > &to_old_indices, Temporaries *tmp)
static IElement * resolveProperty(const Object &obj, const char *name)
static OptionalError< Object * > parseMaterial(const Scene &scene, const Element &element, Allocator &allocator)
struct OptionalError< Object * > parsePose(const Scene &scene, const Element &element, Allocator &allocator)
static OptionalError< Element * > readElement(Cursor *cursor, u32 version, Allocator &allocator)
static Matrix makeIdentity()
static Matrix rotationZ(double angle)
double fbxTimeToSeconds(i64 value)
static void remap(std::vector< T > *out, const std::vector< int > &map)
static bool decompress(const u8 *in, size_t in_size, u8 *out, size_t out_size)
static bool parseArrayRaw(const Property &property, T *out, int max_size)
static bool isTextTokenChar(char c)
static bool copyString(char(&destination)[SIZE], const char *source)
static void parseTemplates(const Element &root)
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)
i64 secondsToFbxTime(double value)
static OptionalError< Object * > parseLimbNode(const Scene &scene, const Element &element, Allocator &allocator)
const char * fromString< Vec3 >(const char *str, const char *end, Vec3 *val)
const char * fromString< int >(const char *str, const char *end, int *val)
@ FrameRate_NTSC_FULL_FRAME
@ FrameRate_NTSC_DROP_FRAME
static OptionalError< Object * > parseAnimationCurve(const Scene &scene, const Element &element, Allocator &allocator)
static Vec3 operator+(const Vec3 &a, const Vec3 &b)
static void skipInsignificantWhitespaces(Cursor *cursor)
static bool parseConnections(const Element &root, Scene *scene)
const char * fromString< u64 >(const char *str, const char *end, u64 *val)
static OptionalError< u64 > readElementOffset(Cursor *cursor, u16 version)
static DataView readTextToken(Cursor *cursor)
static void skipLine(Cursor *cursor)
static OptionalError< DataView > readLongString(Cursor *cursor)
static OptionalError< Object * > parseGeometryColors(GeometryImpl *geom, const Element &element, const std::vector< int > &original_indices, const std::vector< int > &to_old_indices, Temporaries *tmp)
void parseVideo(Scene &scene, const Element &element, Allocator &allocator)
static OptionalError< Object * > parseCluster(const Scene &scene, const Element &element, Allocator &allocator)
static void parseGlobalSettings(const Element &root, Scene *scene)
static OptionalError< Object * > parseGeometryUVs(GeometryImpl *geom, const Element &element, const std::vector< int > &original_indices, const std::vector< int > &to_old_indices, Temporaries *tmp)
static bool isString(const Property *prop)
static Matrix operator*(const Matrix &lhs, const Matrix &rhs)
static bool isEndLine(const Cursor &cursor)
const char * fromString< float >(const char *str, const char *end, float *val)
static OptionalError< Object * > parseNodeAttribute(const Scene &scene, const Element &element, Allocator &allocator)
const char * fromString< double >(const char *str, const char *end, double *val)
static bool parseTextArrayRaw(const Property &property, T *out, int max_size)
static OptionalError< Property * > readProperty(Cursor *cursor, Allocator &allocator)
static OptionalError< Object * > parseGeometryTangents(GeometryImpl *geom, const Element &element, const std::vector< int > &original_indices, const std::vector< int > &to_old_indices, Temporaries *tmp)
static bool parseObjects(const Element &root, Scene *scene, u64 flags, Allocator &allocator, JobProcessor job_processor, void *job_user_ptr)
static OptionalError< Element * > tokenizeText(const u8 *data, size_t size, Allocator &allocator)
static OptionalError< Object * > parseGeometryMaterials(GeometryImpl *geom, const Element &element, const std::vector< int > &original_indices)
static bool parseDouble(Property &property, double *out)
static const Element * findChild(const Element &element, const char *id)
const char * fromString< Vec2 >(const char *str, const char *end, Vec2 *val)
static void triangulate(const std::vector< int > &old_indices, std::vector< int > *to_old_vertices, std::vector< int > *to_old_indices)
static Matrix rotationX(double angle)
static bool parseTakes(Scene *scene)
static bool parseBinaryArray(const Property &property, std::vector< T > *out)
static void skipWhitespaces(Cursor *cursor)
static bool isLong(const Property *prop)
static Matrix getRotationMatrix(const Vec3 &euler, RotationOrder order)
static Vec3 resolveVec3Property(const Object &object, const char *name, const Vec3 &default_value)
IScene * load(const u8 *data, int size, u64 flags, JobProcessor job_processor, void *job_user_ptr)
static void setTranslation(const Vec3 &t, Matrix *mtx)
static void buildGeometryVertexData(GeometryImpl *geom, const std::vector< Vec3 > &vertices, const std::vector< int > &original_indices, std::vector< int > &to_old_indices, bool triangulationEnabled)
static Vec3 operator-(const Vec3 &v)
static void parseTextArray(const Property &property, std::vector< T > *out)
struct OptionalError< Object * > parseTexture(const Scene &scene, const Element &element, Allocator &allocator)
static int getTriCountFromPoly(const std::vector< int > &indices, int *idx)
static OptionalError< Object * > parseGeometry(const Element &element, bool triangulate, GeometryImpl *geom)
const char * fromString< Matrix >(const char *str, const char *end, Matrix *val)
void sync_job_processor(JobFunction fn, void *, void *data, u32 size, u32 count)
static OptionalError< Element * > tokenize(const u8 *data, size_t size, u32 &version, Allocator &allocator)
static OptionalError< Object * > parseMesh(const Scene &scene, const Element &element, Allocator &allocator)
static void add(GeometryImpl::NewVertex &vtx, int index)
static OptionalError< T > read(Cursor *cursor)
TEMPLATE_TYPENAME_T MAT4_T scale(MAT4_T const &m, VEC3_T const &v)
TEMPLATE_TYPENAME_T T angle(QUAT_T const &q)
TEMPLATE_TYPENAME_T T length(const VEC2_T &v)
#define get_property(name, field, type, getter)
#define get_time_property(name, field, type, getter)
const unsigned char * next_in
struct ofbx::Allocator::Page::@28 header
std::vector< int > int_tmp
std::vector< Vec3 > vec3_tmp2
std::vector< Vec3 > vec3_tmp
T * allocate(Args &&... args)
std::vector< double > double_tmp
AnimationCurve(const Scene &_scene, const IElement &_element)
virtual int getKeyCount() const =0
virtual const i64 * getKeyTime() const =0
virtual const float * getKeyValue() const =0
const i64 * getKeyTime() const override
AnimationCurveImpl(const Scene &_scene, const IElement &_element)
int getKeyCount() const override
const float * getKeyValue() const override
std::vector< float > values
Type getType() const override
AnimationCurveNode(const Scene &_scene, const IElement &_element)
const AnimationCurve * curve
const Scene::Connection * connection
const Object * getBone() const override
float getAnimationDY() const
float getAnimationDX() const
enum ofbx::AnimationCurveNodeImpl::Mode mode
AnimationCurveNodeImpl(const Scene &_scene, const IElement &_element)
Type getType() const override
DataView bone_link_property
float getAnimationDZ() const
Vec3 getNodeLocalTransform(double time) const override
const AnimationCurve * getCurve(int idx) const override
AnimationLayer(const Scene &_scene, const IElement &_element)
Type getType() const override
const AnimationCurveNode * getCurveNode(int index) const override
AnimationLayerImpl(const Scene &_scene, const IElement &_element)
const AnimationCurveNode * getCurveNode(const Object &bone, const char *prop) const override
std::vector< AnimationCurveNodeImpl * > curve_nodes
AnimationStack(const Scene &_scene, const IElement &_element)
const AnimationLayer * getLayer(int index) const override
AnimationStackImpl(const Scene &_scene, const IElement &_element)
Type getType() const override
BlendShapeChannel(const Scene &_scene, const IElement &_element)
int getShapeCount() const override
std::vector< Shape * > shapes
bool postprocess(Allocator &allocator)
std::vector< double > fullWeights
Type getType() const override
double getDeformPercent() const override
const Shape * getShape(int idx) const override
BlendShapeChannelImpl(const Scene &_scene, const IElement &_element)
BlendShape(const Scene &_scene, const IElement &_element)
const BlendShapeChannel * getBlendShapeChannel(int idx) const override
BlendShapeImpl(const Scene &_scene, const IElement &_element)
int getBlendShapeChannelCount() const override
std::vector< BlendShapeChannel * > blendShapeChannels
Type getType() const override
Cluster(const Scene &_scene, const IElement &_element)
int getIndicesCount() const override
bool postprocess(Allocator &allocator)
Matrix getTransformLinkMatrix() const override
std::vector< double > weights
std::vector< int > indices
ClusterImpl(const Scene &_scene, const IElement &_element)
int getWeightsCount() const override
const int * getIndices() const override
const double * getWeights() const override
Object * getLink() const override
Matrix transform_link_matrix
Type getType() const override
Matrix getTransformMatrix() const override
bool operator==(const char *rhs) const
void toString(char(&out)[N]) const
IElementProperty * getFirstProperty() const override
DataView getID() const override
IElementProperty * getProperty(int idx) const
Property * first_property
IElement * getFirstChild() const override
IElement * getSibling() const override
static const char * s_message
static const int s_uvs_max
Geometry(const Scene &_scene, const IElement &_element)
int getIndexCount() const override
const Vec2 * getUVs(int index=0) const override
const Skin * getSkin() const override
std::vector< NewVertex > to_new_vertices
const BlendShape * blendShape
std::vector< int > materials
const Vec3 * getTangents() const override
std::vector< Vec3 > normals
std::vector< int > to_old_vertices
const Vec4 * getColors() const override
std::vector< Vec3 > vertices
GeometryImpl(const Scene &_scene, const IElement &_element)
int getVertexCount() const override
const BlendShape * getBlendShape() const override
const int * getMaterials() const override
std::vector< Vec3 > tangents
std::vector< Vec4 > colors
const int * getFaceIndices() const override
const Vec3 * getNormals() const override
std::vector< int > indices
std::vector< Vec2 > uvs[s_uvs_max]
const Vec3 * getVertices() const override
Type getType() const override
virtual IElementProperty * getFirstProperty() const =0
virtual IElementProperty * getNext() const =0
virtual DataView getValue() const =0
LimbNodeImpl(const Scene &_scene, const IElement &_element)
Type getType() const override
Material(const Scene &_scene, const IElement &_element)
double getReflectionFactor() const override
Color getAmbientColor() const override
double getDiffuseFactor() const override
double getShininessExponent() const override
Color getSpecularColor() const override
MaterialImpl(const Scene &_scene, const IElement &_element)
Type getType() const override
Color getEmissiveColor() const override
Color getReflectionColor() const override
const Texture * getTexture(Texture::TextureType type) const override
double getShininess() const override
double getSpecularFactor() const override
double getAmbientFactor() const override
double shininess_exponent
const Texture * textures[Texture::TextureType::COUNT]
double getBumpFactor() const override
double getEmissiveFactor() const override
Color getDiffuseColor() const override
Mesh(const Scene &_scene, const IElement &_element)
const Material * getMaterial(int index) const override
const Pose * getPose() const override
const Geometry * getGeometry() const override
MeshImpl(const Scene &_scene, const IElement &_element)
std::vector< const Material * > materials
Type getType() const override
const Geometry * geometry
Matrix getGeometricMatrix() const override
int getMaterialCount() const override
NodeAttribute(const Scene &_scene, const IElement &_element)
NodeAttributeImpl(const Scene &_scene, const IElement &_element)
Type getType() const override
DataView getAttributeType() const override
NullImpl(const Scene &_scene, const IElement &_element)
Type getType() const override
Matrix getLocalTransform() const
Vec3 getScalingOffset() const
Vec3 getRotationPivot() const
virtual Type getType() const =0
Matrix evalLocal(const Vec3 &translation, const Vec3 &rotation) const
Vec3 getLocalScaling() const
Vec3 getScalingPivot() const
Object * resolveObjectLinkReverse(Type type) const
const IScene & getScene() const
Object * resolveObjectLink(int idx) const
RotationOrder getRotationOrder() const
Vec3 getLocalTranslation() const
Vec3 getPostRotation() const
Vec3 getRotationOffset() const
Matrix getGlobalTransform() const
const Object * node_attribute
Vec3 getPreRotation() const
Object(const Scene &_scene, const IElement &_element)
Object * getParent() const
Vec3 getLocalRotation() const
OptionalError(Error error)
Pose(const Scene &_scene, const IElement &_element)
Matrix getMatrix() const override
const Object * getNode() const override
Type getType() const override
bool postprocess(Scene *scene)
PoseImpl(const Scene &_scene, const IElement &_element)
IElementProperty * getNext() const override
Type getType() const override
bool getValues(u64 *values, int max_size) const override
bool getValues(i64 *values, int max_size) const override
bool getValues(int *values, int max_size) const override
int getCount() const override
bool getValues(float *values, int max_size) const override
DataView getValue() const override
bool getValues(double *values, int max_size) const override
Root(const Scene &_scene, const IElement &_element)
Type getType() const override
std::vector< Connection > m_connections
const AnimationStack * getAnimationStack(int index) const override
DataView getEmbeddedData(int index) const override
GlobalSettings m_settings
std::vector< AnimationStack * > m_animation_stacks
int getGeometryCount() const override
int getMeshCount() const override
const Geometry * getGeometry(int index) const override
const Object *const * getAllObjects() const override
const Object * getRoot() const override
const GlobalSettings * getGlobalSettings() const override
DataView getEmbeddedFilename(int index) const override
const IElement * getRootElement() const override
float getSceneFrameRate() const override
int getAllObjectCount() const override
const TakeInfo * getTakeInfo(const char *name) const override
std::vector< TakeInfo > m_take_infos
std::unordered_map< u64, ObjectPair > m_object_map
std::vector< Video > m_videos
std::vector< Object * > m_all_objects
const Mesh * getMesh(int index) const override
int getAnimationStackCount() const override
int getEmbeddedDataCount() const override
std::vector< Mesh * > m_meshes
std::vector< Geometry * > m_geometries
Shape(const Scene &_scene, const IElement &_element)
bool postprocess(GeometryImpl *geom, Allocator &allocator)
const Vec3 * getNormals() const override
ShapeImpl(const Scene &_scene, const IElement &_element)
Type getType() const override
int getVertexCount() const override
std::vector< Vec3 > vertices
const Vec3 * getVertices() const override
std::vector< Vec3 > normals
Skin(const Scene &_scene, const IElement &_element)
const Cluster * getCluster(int idx) const override
SkinImpl(const Scene &_scene, const IElement &_element)
std::vector< Cluster * > clusters
Type getType() const override
int getClusterCount() const override
double reference_time_from
Texture(const Scene &_scene, const IElement &_element)
DataView getEmbeddedData() const override
DataView getRelativeFileName() const override
DataView getFileName() const override
DataView relative_filename
Type getType() const override
TextureImpl(const Scene &_scene, const IElement &_element)