updated openfbx
This commit is contained in:
parent
5d84bddebf
commit
111e3d8722
3 changed files with 694 additions and 56 deletions
565
external/openfbx/ofbx.cpp
vendored
565
external/openfbx/ofbx.cpp
vendored
|
@ -8,8 +8,14 @@
|
|||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
#if __cplusplus >= 202002L
|
||||
#include <bit> // for std::bit_cast (C++20 and later)
|
||||
#endif
|
||||
#include <map>
|
||||
|
||||
namespace ofbx
|
||||
{
|
||||
|
||||
|
@ -83,7 +89,19 @@ struct Video
|
|||
struct Error
|
||||
{
|
||||
Error() {}
|
||||
Error(const char* msg) { s_message = msg; }
|
||||
Error(const char* msg)
|
||||
{
|
||||
s_message = msg;
|
||||
}
|
||||
|
||||
// Format a message with printf-style arguments.
|
||||
template <typename... Args>
|
||||
Error(const char* fmt, Args... args)
|
||||
{
|
||||
char buf[1024];
|
||||
std::snprintf(buf, sizeof(buf), fmt, args...);
|
||||
s_message = buf;
|
||||
}
|
||||
|
||||
static const char* s_message;
|
||||
};
|
||||
|
@ -349,6 +367,11 @@ u32 DataView::toU32() const
|
|||
return (u32)atoll((const char*)begin);
|
||||
}
|
||||
|
||||
bool DataView::toBool() const
|
||||
{
|
||||
return toInt() != 0;
|
||||
}
|
||||
|
||||
|
||||
double DataView::toDouble() const
|
||||
{
|
||||
|
@ -582,6 +605,20 @@ static OptionalError<DataView> readLongString(Cursor* cursor)
|
|||
return value;
|
||||
}
|
||||
|
||||
// Cheat sheet: //
|
||||
/*
|
||||
'S': Long string
|
||||
'Y': 16-bit signed integer
|
||||
'C': 8-bit signed integer
|
||||
'I': 32-bit signed integer
|
||||
'F': Single precision floating-point number
|
||||
'D': Double precision floating-point number
|
||||
'L': 64-bit signed integer
|
||||
'R': Binary data
|
||||
'b', 'f', 'd', 'l', 'c' and 'i': Arrays of binary data
|
||||
|
||||
Src: https://code.blender.org/2013/08/fbx-binary-file-format-specification/
|
||||
*/
|
||||
|
||||
static OptionalError<Property*> readProperty(Cursor* cursor, Allocator& allocator)
|
||||
{
|
||||
|
@ -617,6 +654,7 @@ static OptionalError<Property*> readProperty(Cursor* cursor, Allocator& allocato
|
|||
break;
|
||||
}
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'f':
|
||||
case 'd':
|
||||
case 'l':
|
||||
|
@ -630,14 +668,18 @@ static OptionalError<Property*> readProperty(Cursor* cursor, Allocator& allocato
|
|||
cursor->current += comp_len.getValue();
|
||||
break;
|
||||
}
|
||||
default: return Error("Unknown property type");
|
||||
default:
|
||||
{
|
||||
char str[32];
|
||||
snprintf(str, sizeof(str), "Unknown property type: %c", prop->type);
|
||||
return Error(str);
|
||||
}
|
||||
}
|
||||
prop->value.end = cursor->current;
|
||||
return prop;
|
||||
}
|
||||
|
||||
|
||||
static OptionalError<u64> readElementOffset(Cursor* cursor, u16 version)
|
||||
static OptionalError<u64> readElementOffset(Cursor* cursor, u32 version)
|
||||
{
|
||||
if (version >= 7500)
|
||||
{
|
||||
|
@ -962,13 +1004,22 @@ static OptionalError<Element*> tokenizeText(const u8* data, size_t size, Allocat
|
|||
|
||||
static OptionalError<Element*> tokenize(const u8* data, size_t size, u32& version, Allocator& allocator)
|
||||
{
|
||||
if (size < sizeof(Header)) return Error("Invalid header");
|
||||
|
||||
Cursor cursor;
|
||||
cursor.begin = data;
|
||||
cursor.current = data;
|
||||
cursor.end = data + size;
|
||||
|
||||
const Header* header = (const Header*)cursor.current;
|
||||
cursor.current += sizeof(*header);
|
||||
#if __cplusplus >= 202002L
|
||||
const Header* header = std::bit_cast<const Header*>(cursor.current);
|
||||
#else
|
||||
Header header_temp;
|
||||
std::memcpy(&header_temp, cursor.current, sizeof(Header));
|
||||
const Header* header = &header_temp;
|
||||
#endif
|
||||
|
||||
cursor.current += sizeof(Header);
|
||||
version = header->version;
|
||||
|
||||
Element* root = allocator.allocate<Element>();
|
||||
|
@ -982,16 +1033,17 @@ static OptionalError<Element*> tokenize(const u8* data, size_t size, u32& versio
|
|||
for (;;)
|
||||
{
|
||||
OptionalError<Element*> child = readElement(&cursor, header->version, allocator);
|
||||
if (child.isError()) {
|
||||
if (child.isError())
|
||||
{
|
||||
return Error();
|
||||
}
|
||||
|
||||
*element = child.getValue();
|
||||
if (!*element) return root;
|
||||
element = &(*element)->sibling;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void parseTemplates(const Element& root)
|
||||
{
|
||||
const Element* defs = findChild(root, "Definitions");
|
||||
|
@ -1535,6 +1587,178 @@ struct TextureImpl : Texture
|
|||
Type getType() const override { return Type::TEXTURE; }
|
||||
};
|
||||
|
||||
struct LightImpl : Light
|
||||
{
|
||||
LightImpl(const Scene& _scene, const IElement& _element)
|
||||
: Light(_scene, _element)
|
||||
{
|
||||
// Initialize the light properties here
|
||||
}
|
||||
|
||||
Type getType() const override { return Type::LIGHT; }
|
||||
|
||||
// Light type
|
||||
LightType getLightType() const override { return lightType; }
|
||||
|
||||
// Light properties
|
||||
bool doesCastLight() const override { return castLight; }
|
||||
|
||||
bool doesDrawVolumetricLight() const override
|
||||
{
|
||||
// Return the draw volumetric light property based on the stored data (WIP)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool doesDrawGroundProjection() const override
|
||||
{
|
||||
// Return the draw ground projection property based on the stored data (WIP)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool doesDrawFrontFacingVolumetricLight() const override
|
||||
{
|
||||
// Return the draw front-facing volumetric light property based on the stored data (WIP)
|
||||
return false;
|
||||
}
|
||||
|
||||
Color getColor() const override { return color; }
|
||||
double getIntensity() const override { return intensity; }
|
||||
double getInnerAngle() const override { return innerAngle; }
|
||||
double getOuterAngle() const override { return outerAngle; }
|
||||
|
||||
double getFog() const override { return fog; }
|
||||
|
||||
DecayType getDecayType() const override { return decayType; }
|
||||
double getDecayStart() const override { return decayStart; }
|
||||
|
||||
// Near attenuation
|
||||
bool doesEnableNearAttenuation() const override { return enableNearAttenuation; }
|
||||
double getNearAttenuationStart() const override { return nearAttenuationStart; }
|
||||
double getNearAttenuationEnd() const override { return nearAttenuationEnd; }
|
||||
|
||||
// Far attenuation
|
||||
bool doesEnableFarAttenuation() const override { return enableFarAttenuation; }
|
||||
double getFarAttenuationStart() const override { return farAttenuationStart; }
|
||||
double getFarAttenuationEnd() const override { return farAttenuationEnd; }
|
||||
|
||||
// Shadows
|
||||
const Texture* getShadowTexture() const override { return shadowTexture; }
|
||||
bool doesCastShadows() const override { return castShadows; }
|
||||
Color getShadowColor() const override { return shadowColor; }
|
||||
|
||||
// Member variables to store light properties
|
||||
//-------------------------------------------------------------------------
|
||||
LightType lightType = LightType::POINT; // Light type
|
||||
bool castLight = true; // Whether the light casts light on objects
|
||||
Color color = {1, 1, 1}; // Light color (RGB values)
|
||||
double intensity = 100.0; // Light intensity
|
||||
|
||||
// Spotlight properties
|
||||
double innerAngle = 0.0;
|
||||
double outerAngle = 45.0;
|
||||
|
||||
// Light fog intensity
|
||||
double fog = 50;
|
||||
|
||||
// Light decay properties
|
||||
DecayType decayType = DecayType::QUADRATIC;
|
||||
double decayStart = 1.0;
|
||||
|
||||
// Near attenuation properties
|
||||
bool enableNearAttenuation = false;
|
||||
double nearAttenuationStart = 0.0;
|
||||
double nearAttenuationEnd = 0.0;
|
||||
|
||||
// Far attenuation properties
|
||||
bool enableFarAttenuation = false;
|
||||
double farAttenuationStart = 0.0;
|
||||
double farAttenuationEnd = 0.0;
|
||||
|
||||
// Shadow properties
|
||||
const Texture* shadowTexture = nullptr;
|
||||
bool castShadows = true;
|
||||
Color shadowColor = {0, 0, 0};
|
||||
};
|
||||
|
||||
static float M_PI = 3.14159265358979323846f;
|
||||
struct CameraImpl : public Camera
|
||||
{
|
||||
CameraImpl(const Scene& _scene, const IElement& _element)
|
||||
: Camera(_scene, _element)
|
||||
{
|
||||
// Initialize camera properties here
|
||||
}
|
||||
|
||||
// Member variables to store camera properties
|
||||
//-------------------------------------------------------------------------
|
||||
ProjectionType projectionType = ProjectionType::PERSPECTIVE; // Projection type
|
||||
ApertureMode apertureMode = ApertureMode::HORIZONTAL; // Used to determine the FOV
|
||||
|
||||
double filmHeight = 36.0;
|
||||
double filmWidth = 24.0;
|
||||
|
||||
double aspectHeight = 1.0;
|
||||
double aspectWidth = 1.0;
|
||||
|
||||
double nearPlane = 0.1;
|
||||
double farPlane = 1000.0;
|
||||
bool autoComputeClipPanes = true;
|
||||
|
||||
GateFit gateFit = GateFit::HORIZONTAL;
|
||||
double filmAspectRatio = 1.0;
|
||||
double focalLength = 50.0;
|
||||
double focusDistance = 50.0;
|
||||
|
||||
Vec3 backgroundColor = {0, 0, 0};
|
||||
Vec3 interestPosition = {0, 0, 0};
|
||||
|
||||
double fieldOfView = 60.0;
|
||||
|
||||
// Member functions to get camera properties
|
||||
//-------------------------------------------------------------------------
|
||||
Type getType() const override { return Type::CAMERA; }
|
||||
ProjectionType getProjectionType() const override { return projectionType; }
|
||||
ApertureMode getApertureMode() const override { return apertureMode; }
|
||||
|
||||
double getFilmHeight() const override { return filmHeight; }
|
||||
double getFilmWidth() const override { return filmWidth; }
|
||||
|
||||
double getAspectHeight() const override { return aspectHeight; }
|
||||
double getAspectWidth() const override { return aspectWidth; }
|
||||
|
||||
double getNearPlane() const override { return nearPlane; }
|
||||
double getFarPlane() const override { return farPlane; }
|
||||
bool doesAutoComputeClipPanes() const override { return autoComputeClipPanes; }
|
||||
|
||||
GateFit getGateFit() const override { return gateFit; }
|
||||
double getFilmAspectRatio() const override { return filmAspectRatio; }
|
||||
double getFocalLength() const override { return focalLength; }
|
||||
double getFocusDistance() const override { return focusDistance; }
|
||||
|
||||
Vec3 getBackgroundColor() const override { return backgroundColor; }
|
||||
Vec3 getInterestPosition() const override { return interestPosition; }
|
||||
|
||||
void CalculateFOV()
|
||||
{
|
||||
switch (apertureMode)
|
||||
{
|
||||
case Camera::ApertureMode::HORIZONTAL:
|
||||
fieldOfView = 2.0 * atan(filmWidth / (2.0 * focalLength)) * 180.0 / M_PI;
|
||||
return;
|
||||
case Camera::ApertureMode::VERTICAL:
|
||||
fieldOfView = 2.0 * atan(filmHeight / (2.0 * focalLength)) * 180.0 / M_PI;
|
||||
return;
|
||||
case Camera::ApertureMode::HORIZANDVERT:
|
||||
fieldOfView = 2.0 * atan(sqrt(filmWidth * filmWidth + filmHeight * filmHeight) / (2.0 * focalLength)) * 180.0 / M_PI;
|
||||
return;
|
||||
case Camera::ApertureMode::FOCALLENGTH:
|
||||
fieldOfView = 2.0 * atan(filmHeight / (2.0 * focalLength)) * 180.0 / M_PI; // Same as vertical ¯\_(ツ)_/¯
|
||||
return;
|
||||
default:
|
||||
fieldOfView = 60.0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Root : Object
|
||||
{
|
||||
|
@ -1555,13 +1779,16 @@ struct Scene : IScene
|
|||
enum Type
|
||||
{
|
||||
OBJECT_OBJECT,
|
||||
OBJECT_PROPERTY
|
||||
OBJECT_PROPERTY,
|
||||
PROPERTY_OBJECT,
|
||||
PROPERTY_PROPERTY,
|
||||
};
|
||||
|
||||
Type type = OBJECT_OBJECT;
|
||||
u64 from = 0;
|
||||
u64 to = 0;
|
||||
DataView property;
|
||||
DataView fromProperty;
|
||||
DataView toProperty;
|
||||
};
|
||||
|
||||
struct ObjectPair
|
||||
|
@ -1627,6 +1854,32 @@ struct Scene : IScene
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Cameras
|
||||
const Camera* getCamera(int index) const override
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < m_cameras.size());
|
||||
return m_cameras[index];
|
||||
}
|
||||
|
||||
int getCameraCount() const override
|
||||
{
|
||||
return (int)m_cameras.size();
|
||||
}
|
||||
|
||||
// Lights
|
||||
const Light* getLight(int index) const override
|
||||
{
|
||||
assert(index >= 0);
|
||||
assert(index < m_lights.size());
|
||||
return m_lights[index];
|
||||
}
|
||||
|
||||
int getLightCount() const override
|
||||
{
|
||||
return (int)m_lights.size();
|
||||
}
|
||||
|
||||
|
||||
const IElement* getRootElement() const override { return m_root_element; }
|
||||
const Object* getRoot() const override { return m_root; }
|
||||
|
@ -1650,6 +1903,8 @@ struct Scene : IScene
|
|||
std::vector<Mesh*> m_meshes;
|
||||
std::vector<Geometry*> m_geometries;
|
||||
std::vector<AnimationStack*> m_animation_stacks;
|
||||
std::vector<Camera*> m_cameras;
|
||||
std::vector<Light*> m_lights;
|
||||
std::vector<Connection> m_connections;
|
||||
std::vector<u8> m_data;
|
||||
std::vector<TakeInfo> m_take_infos;
|
||||
|
@ -1798,6 +2053,33 @@ struct AnimationLayerImpl : AnimationLayer
|
|||
std::vector<AnimationCurveNodeImpl*> curve_nodes;
|
||||
};
|
||||
|
||||
/*
|
||||
DEBUGGING ONLY (but im not your boss so do what you want)
|
||||
- maps the contents of the given node for viewing in the debugger
|
||||
|
||||
std::map<std::string, ofbx::IElementProperty*, std::less<>> allProperties;
|
||||
mapProperties(element, allProperties);
|
||||
*/
|
||||
void mapProperties(const ofbx::IElement& parent, std::map<std::string, ofbx::IElementProperty*, std::less<>>& propMap)
|
||||
{
|
||||
for (const ofbx::IElement* element = parent.getFirstChild(); element; element = element->getSibling())
|
||||
{
|
||||
char key[32];
|
||||
|
||||
if (element->getFirstProperty())
|
||||
element->getFirstProperty()->getValue().toString(key);
|
||||
else
|
||||
element->getID().toString(key);
|
||||
|
||||
|
||||
ofbx::IElementProperty* prop = element->getFirstProperty();
|
||||
propMap.insert({key, prop});
|
||||
|
||||
if (element->getFirstChild()) mapProperties(*element, propMap);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void parseVideo(Scene& scene, const Element& element, Allocator& allocator)
|
||||
{
|
||||
if (!element.first_property) return;
|
||||
|
@ -1845,6 +2127,132 @@ struct OptionalError<Object*> parseTexture(const Scene& scene, const Element& el
|
|||
return texture;
|
||||
}
|
||||
|
||||
struct OptionalError<Object*> parseLight(Scene& scene, const Element& element, Allocator& allocator)
|
||||
{
|
||||
LightImpl* light = allocator.allocate<LightImpl>(scene, element);
|
||||
|
||||
light->lightType = static_cast<Light::LightType>(resolveEnumProperty(*light, "LightType", (int)Light::LightType::POINT));
|
||||
|
||||
const Element* prop = findChild(element, "Properties70");
|
||||
if (prop) prop = prop->child;
|
||||
|
||||
// Can be replaced with a std::map for a Big O of O(log n) instead of O(n) for the if else statements - Possibly faster
|
||||
while (prop)
|
||||
{
|
||||
if (prop->id == "P" && prop->first_property)
|
||||
{
|
||||
if (prop->first_property->value == "Color")
|
||||
{
|
||||
light->color.r = (float)prop->getProperty(4)->getValue().toDouble();
|
||||
light->color.g = (float)prop->getProperty(5)->getValue().toDouble();
|
||||
light->color.b = (float)prop->getProperty(6)->getValue().toDouble();
|
||||
}
|
||||
if (prop->first_property->value == "ShadowColor")
|
||||
{
|
||||
light->shadowColor.r = (float)prop->getProperty(4)->getValue().toDouble();
|
||||
light->shadowColor.g = (float)prop->getProperty(5)->getValue().toDouble();
|
||||
light->shadowColor.b = (float)prop->getProperty(6)->getValue().toDouble();
|
||||
}
|
||||
else if (prop->first_property->value == "CastShadows")
|
||||
{
|
||||
light->castShadows = prop->getProperty(4)->getValue().toBool();
|
||||
}
|
||||
else if (prop->first_property->value == "InnerAngle")
|
||||
{
|
||||
light->innerAngle = (float)prop->getProperty(4)->getValue().toDouble();
|
||||
}
|
||||
else if (prop->first_property->value == "OuterAngle")
|
||||
{
|
||||
light->outerAngle = (float)prop->getProperty(4)->getValue().toDouble();
|
||||
}
|
||||
else if (prop->first_property->value == "Intensity")
|
||||
{
|
||||
light->intensity = (float)prop->getProperty(4)->getValue().toDouble();
|
||||
}
|
||||
}
|
||||
prop = prop->sibling;
|
||||
}
|
||||
|
||||
scene.m_lights.push_back(light); // Implicit inheritance downcast
|
||||
return light;
|
||||
}
|
||||
|
||||
struct OptionalError<Object*> parseCamera(Scene& scene, const Element& element, Allocator& allocator)
|
||||
{
|
||||
CameraImpl* camera = allocator.allocate<CameraImpl>(scene, element);
|
||||
|
||||
camera->projectionType = static_cast<Camera::ProjectionType>(resolveEnumProperty(*camera, "ProjectionType", (int)Camera::ProjectionType::PERSPECTIVE)); // ProjectionType
|
||||
camera->apertureMode = static_cast<Camera::ApertureMode>(resolveEnumProperty(*camera, "ApertureMode", (int)Camera::ApertureMode::HORIZANDVERT)); // ApertureMode
|
||||
camera->gateFit = static_cast<Camera::GateFit>(resolveEnumProperty(*camera, "GateFit", (int)Camera::GateFit::HORIZONTAL)); // GateFit
|
||||
|
||||
const Element* prop = findChild(element, "Properties70");
|
||||
if (prop) prop = prop->child;
|
||||
|
||||
// Can be replaced with a std::map for a Big O of O(log n) instead of O(n) for the if else statements - Possibly faster
|
||||
while (prop)
|
||||
{
|
||||
if (prop->id == "P" && prop->first_property)
|
||||
{
|
||||
if (prop->first_property->value == "InterestPosition")
|
||||
{
|
||||
camera->interestPosition.x = (float)prop->getProperty(4)->getValue().toDouble();
|
||||
camera->interestPosition.y = (float)prop->getProperty(5)->getValue().toDouble();
|
||||
camera->interestPosition.z = (float)prop->getProperty(6)->getValue().toDouble();
|
||||
}
|
||||
else if (prop->first_property->value == "BackgroundColor")
|
||||
{
|
||||
camera->backgroundColor.x = (float)prop->getProperty(4)->getValue().toDouble();
|
||||
camera->backgroundColor.y = (float)prop->getProperty(5)->getValue().toDouble();
|
||||
camera->backgroundColor.z = (float)prop->getProperty(6)->getValue().toDouble();
|
||||
}
|
||||
else if (prop->first_property->value == "FocalLength")
|
||||
{
|
||||
camera->focalLength = prop->getProperty(4)->getValue().toDouble();
|
||||
}
|
||||
else if (prop->first_property->value == "FocusDistance")
|
||||
{
|
||||
camera->focusDistance = prop->getProperty(4)->getValue().toDouble();
|
||||
}
|
||||
else if (prop->first_property->value == "FilmAspectRatio")
|
||||
{
|
||||
camera->filmAspectRatio = prop->getProperty(4)->getValue().toDouble();
|
||||
}
|
||||
else if (prop->first_property->value == "FilmWidth")
|
||||
{
|
||||
camera->filmWidth = prop->getProperty(4)->getValue().toDouble();
|
||||
}
|
||||
else if (prop->first_property->value == "FilmHeight")
|
||||
{
|
||||
camera->filmHeight = prop->getProperty(4)->getValue().toDouble();
|
||||
}
|
||||
else if (prop->first_property->value == "AspectHeight")
|
||||
{
|
||||
camera->aspectHeight = prop->getProperty(4)->getValue().toDouble();
|
||||
}
|
||||
else if (prop->first_property->value == "AspectWidth")
|
||||
{
|
||||
camera->aspectWidth = prop->getProperty(4)->getValue().toDouble();
|
||||
}
|
||||
else if (prop->first_property->value == "AutoComputeClipPanes")
|
||||
{
|
||||
camera->autoComputeClipPanes = prop->getProperty(4)->getValue().toBool();
|
||||
}
|
||||
else if (prop->first_property->value == "NearPlane")
|
||||
{
|
||||
camera->nearPlane = prop->getProperty(4)->getValue().toDouble();
|
||||
}
|
||||
else if (prop->first_property->value == "FarPlane")
|
||||
{
|
||||
camera->farPlane = prop->getProperty(4)->getValue().toDouble();
|
||||
}
|
||||
}
|
||||
prop = prop->sibling;
|
||||
}
|
||||
|
||||
camera->CalculateFOV();
|
||||
scene.m_cameras.push_back(camera); // Implicit inheritance downcast
|
||||
return camera;
|
||||
}
|
||||
|
||||
struct OptionalError<Object*> parsePose(const Scene& scene, const Element& element, Allocator& allocator)
|
||||
{
|
||||
|
@ -2375,7 +2783,7 @@ static void splat(std::vector<T>* out,
|
|||
for (int i = 0, c = (int)original_indices.size(); i < c; ++i)
|
||||
{
|
||||
int idx = decodeIndex(original_indices[i]);
|
||||
if ((idx < data_size) && (idx >= 0))
|
||||
if ((idx < data_size) && (idx >= 0)) //-V560
|
||||
(*out)[i] = data[idx];
|
||||
else
|
||||
(*out)[i] = T();
|
||||
|
@ -2481,7 +2889,7 @@ static void triangulate(
|
|||
for (int i = 0; i < (int)old_indices.size(); ++i)
|
||||
{
|
||||
int idx = getIdx(i);
|
||||
if (in_polygon_idx <= 2)
|
||||
if (in_polygon_idx <= 2) //-V1051
|
||||
{
|
||||
to_old_vertices->push_back(idx);
|
||||
to_old_indices->push_back(i);
|
||||
|
@ -2814,29 +3222,57 @@ static bool parseConnections(const Element& root, Scene* scene)
|
|||
while (connection)
|
||||
{
|
||||
if (!isString(connection->first_property)
|
||||
|| !isLong(connection->first_property->next)
|
||||
|| !isLong(connection->first_property->next->next))
|
||||
|| !isLong(connection->first_property->next) ||
|
||||
!(isLong(connection->first_property->next->next) || isString(connection->first_property->next->next)))
|
||||
{
|
||||
Error::s_message = "Invalid connection";
|
||||
return false;
|
||||
}
|
||||
|
||||
Scene::Connection c;
|
||||
c.from = connection->first_property->next->value.toU64();
|
||||
c.to = connection->first_property->next->next->value.toU64();
|
||||
if (connection->first_property->value == "OO")
|
||||
{
|
||||
c.type = Scene::Connection::OBJECT_OBJECT;
|
||||
c.from = connection->first_property->next->value.toU64();
|
||||
c.to = connection->first_property->next->next->value.toU64();
|
||||
}
|
||||
else if (connection->first_property->value == "OP")
|
||||
{
|
||||
c.type = Scene::Connection::OBJECT_PROPERTY;
|
||||
c.from = connection->first_property->next->value.toU64();
|
||||
c.to = connection->first_property->next->next->value.toU64();
|
||||
if (!connection->first_property->next->next->next)
|
||||
{
|
||||
Error::s_message = "Invalid connection";
|
||||
return false;
|
||||
}
|
||||
c.property = connection->first_property->next->next->next->value;
|
||||
c.toProperty = connection->first_property->next->next->next->value;
|
||||
}
|
||||
else if (connection->first_property->value == "PO")
|
||||
{
|
||||
c.type = Scene::Connection::PROPERTY_OBJECT;
|
||||
c.from = connection->first_property->next->value.toU64();
|
||||
c.fromProperty = connection->first_property->next->next->value;
|
||||
if (!connection->first_property->next->next->next)
|
||||
{
|
||||
Error::s_message = "Invalid connection";
|
||||
return false;
|
||||
}
|
||||
c.to = connection->first_property->next->next->next->value.toU64();
|
||||
}
|
||||
else if (connection->first_property->value == "PP")
|
||||
{
|
||||
c.type = Scene::Connection::PROPERTY_PROPERTY;
|
||||
c.from = connection->first_property->next->value.toU64();
|
||||
c.fromProperty = connection->first_property->next->next->value;
|
||||
c.to = connection->first_property->next->next->next->value.toU64();
|
||||
|
||||
if (!connection->first_property->next->next->next->next)
|
||||
{
|
||||
Error::s_message = "Invalid connection";
|
||||
return false;
|
||||
}
|
||||
c.toProperty = connection->first_property->next->next->next->next->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3009,12 +3445,27 @@ void sync_job_processor(JobFunction fn, void*, void* data, u32 size, u32 count)
|
|||
}
|
||||
}
|
||||
|
||||
static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator& allocator, JobProcessor job_processor, void* job_user_ptr)
|
||||
static bool parseObjects(const Element& root, Scene* scene, u16 flags, Allocator& allocator, JobProcessor job_processor, void* job_user_ptr)
|
||||
{
|
||||
if (!job_processor) job_processor = &sync_job_processor;
|
||||
const bool triangulate = (flags & (u64)LoadFlags::TRIANGULATE) != 0;
|
||||
const bool ignore_geometry = (flags & (u64)LoadFlags::IGNORE_GEOMETRY) != 0;
|
||||
const bool ignore_blend_shapes = (flags & (u64)LoadFlags::IGNORE_BLEND_SHAPES) != 0;
|
||||
const bool triangulate = (flags & (u16)LoadFlags::TRIANGULATE) != 0;
|
||||
|
||||
const bool ignore_geometry = (flags & (u16)LoadFlags::IGNORE_GEOMETRY) != 0;
|
||||
const bool ignore_blend_shapes = (flags & (u16)LoadFlags::IGNORE_BLEND_SHAPES) != 0;
|
||||
const bool ignore_cameras = (flags & (u16)LoadFlags::IGNORE_CAMERAS) != 0;
|
||||
const bool ignore_lights = (flags & (u16)LoadFlags::IGNORE_LIGHTS) != 0;
|
||||
const bool ignore_textures = (flags & (u16)LoadFlags::IGNORE_TEXTURES) != 0;
|
||||
const bool ignore_skin = (flags & (u16)LoadFlags::IGNORE_SKIN) != 0;
|
||||
const bool ignore_bones = (flags & (u16)LoadFlags::IGNORE_BONES) != 0;
|
||||
const bool ignore_pivots = (flags & (u16)LoadFlags::IGNORE_PIVOTS) != 0;
|
||||
const bool ignore_animations = (flags & (u16)LoadFlags::IGNORE_ANIMATIONS) != 0;
|
||||
const bool ignore_materials = (flags & (u16)LoadFlags::IGNORE_MATERIALS) != 0;
|
||||
const bool ignore_poses = (flags & (u16)LoadFlags::IGNORE_POSES) != 0;
|
||||
const bool ignore_videos = (flags & (u16)LoadFlags::IGNORE_VIDEOS) != 0;
|
||||
const bool ignore_limbs = (flags & (u16)LoadFlags::IGNORE_LIMBS) != 0;
|
||||
const bool ignore_meshes = (flags & (u16)LoadFlags::IGNORE_MESHES) != 0;
|
||||
const bool ignore_models = (flags & (u16)LoadFlags::IGNORE_MODELS) != 0;
|
||||
|
||||
const Element* objs = findChild(root, "Objects");
|
||||
if (!objs) return true;
|
||||
|
||||
|
@ -3043,11 +3494,11 @@ static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator
|
|||
|
||||
if (iter.second.object == scene->m_root) continue;
|
||||
|
||||
if (iter.second.element->id == "Geometry")
|
||||
if (iter.second.element->id == "Geometry" && !ignore_geometry)
|
||||
{
|
||||
Property* last_prop = iter.second.element->first_property;
|
||||
while (last_prop->next) last_prop = last_prop->next;
|
||||
if (last_prop && last_prop->value == "Mesh" && !ignore_geometry)
|
||||
if (last_prop && last_prop->value == "Mesh")
|
||||
{
|
||||
GeometryImpl* geom = allocator.allocate<GeometryImpl>(*scene, *iter.second.element);
|
||||
scene->m_geometries.push_back(geom);
|
||||
|
@ -3055,16 +3506,16 @@ static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator
|
|||
parse_geom_jobs.push_back(job);
|
||||
continue;
|
||||
}
|
||||
if (last_prop && last_prop->value == "Shape" && !ignore_geometry)
|
||||
if (last_prop && last_prop->value == "Shape")
|
||||
{
|
||||
obj = allocator.allocate<ShapeImpl>(*scene, *iter.second.element);
|
||||
}
|
||||
}
|
||||
else if (iter.second.element->id == "Material")
|
||||
else if (iter.second.element->id == "Material" && !ignore_materials)
|
||||
{
|
||||
obj = parseMaterial(*scene, *iter.second.element, allocator);
|
||||
}
|
||||
else if (iter.second.element->id == "AnimationStack")
|
||||
else if (iter.second.element->id == "AnimationStack" && !ignore_animations)
|
||||
{
|
||||
obj = parse<AnimationStackImpl>(*scene, *iter.second.element, allocator);
|
||||
if (!obj.isError())
|
||||
|
@ -3073,19 +3524,19 @@ static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator
|
|||
scene->m_animation_stacks.push_back(stack);
|
||||
}
|
||||
}
|
||||
else if (iter.second.element->id == "AnimationLayer")
|
||||
else if (iter.second.element->id == "AnimationLayer" && !ignore_animations)
|
||||
{
|
||||
obj = parse<AnimationLayerImpl>(*scene, *iter.second.element, allocator);
|
||||
}
|
||||
else if (iter.second.element->id == "AnimationCurve")
|
||||
else if (iter.second.element->id == "AnimationCurve" && !ignore_animations)
|
||||
{
|
||||
obj = parseAnimationCurve(*scene, *iter.second.element, allocator);
|
||||
}
|
||||
else if (iter.second.element->id == "AnimationCurveNode")
|
||||
else if (iter.second.element->id == "AnimationCurveNode" && !ignore_animations)
|
||||
{
|
||||
obj = parse<AnimationCurveNodeImpl>(*scene, *iter.second.element, allocator);
|
||||
}
|
||||
else if (iter.second.element->id == "Deformer")
|
||||
else if (iter.second.element->id == "Deformer" && !ignore_blend_shapes)
|
||||
{
|
||||
IElementProperty* class_prop = iter.second.element->getProperty(2);
|
||||
|
||||
|
@ -3102,16 +3553,34 @@ static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator
|
|||
}
|
||||
}
|
||||
else if (iter.second.element->id == "NodeAttribute")
|
||||
{
|
||||
|
||||
// Add the support for lights and camera here.
|
||||
Property* last_prop = iter.second.element->first_property;
|
||||
while (last_prop->next) last_prop = last_prop->next;
|
||||
if (last_prop)
|
||||
{
|
||||
if (last_prop->value == "Light" && !ignore_lights)
|
||||
{
|
||||
obj = parseLight(*scene, *iter.second.element, allocator);
|
||||
}
|
||||
else if (last_prop->value == "Camera" && !ignore_cameras)
|
||||
{
|
||||
obj = parseCamera(*scene, *iter.second.element, allocator);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = parseNodeAttribute(*scene, *iter.second.element, allocator);
|
||||
}
|
||||
else if (iter.second.element->id == "Model")
|
||||
}
|
||||
else if (iter.second.element->id == "Model" && !ignore_models)
|
||||
{
|
||||
IElementProperty* class_prop = iter.second.element->getProperty(2);
|
||||
|
||||
if (class_prop)
|
||||
{
|
||||
if (class_prop->getValue() == "Mesh")
|
||||
if (class_prop->getValue() == "Mesh" && !ignore_meshes)
|
||||
{
|
||||
obj = parseMesh(*scene, *iter.second.element, allocator);
|
||||
if (!obj.isError())
|
||||
|
@ -3121,21 +3590,21 @@ static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator
|
|||
obj = mesh;
|
||||
}
|
||||
}
|
||||
else if (class_prop->getValue() == "LimbNode")
|
||||
else if (class_prop->getValue() == "LimbNode" && !ignore_limbs)
|
||||
obj = parseLimbNode(*scene, *iter.second.element, allocator);
|
||||
else
|
||||
obj = parse<NullImpl>(*scene, *iter.second.element, allocator);
|
||||
}
|
||||
}
|
||||
else if (iter.second.element->id == "Texture")
|
||||
else if (iter.second.element->id == "Texture" && !ignore_textures)
|
||||
{
|
||||
obj = parseTexture(*scene, *iter.second.element, allocator);
|
||||
}
|
||||
else if (iter.second.element->id == "Video")
|
||||
else if (iter.second.element->id == "Video" && !ignore_videos)
|
||||
{
|
||||
parseVideo(*scene, *iter.second.element, allocator);
|
||||
}
|
||||
else if (iter.second.element->id == "Pose")
|
||||
else if (iter.second.element->id == "Pose" && !ignore_poses)
|
||||
{
|
||||
obj = parsePose(*scene, *iter.second.element, allocator);
|
||||
}
|
||||
|
@ -3168,6 +3637,8 @@ static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator
|
|||
|
||||
for (const Scene::Connection& con : scene->m_connections)
|
||||
{
|
||||
if (con.type == Scene::Connection::PROPERTY_PROPERTY) continue;
|
||||
|
||||
Object* parent = scene->m_object_map[con.to].object;
|
||||
Object* child = scene->m_object_map[con.from].object;
|
||||
if (!child) continue;
|
||||
|
@ -3188,7 +3659,7 @@ static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator
|
|||
{
|
||||
AnimationCurveNodeImpl* node = (AnimationCurveNodeImpl*)child;
|
||||
node->bone = parent;
|
||||
node->bone_link_property = con.property;
|
||||
node->bone_link_property = con.toProperty;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3260,19 +3731,19 @@ static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator
|
|||
if (child->getType() == Object::Type::TEXTURE)
|
||||
{
|
||||
Texture::TextureType type = Texture::COUNT;
|
||||
if (con.property == "NormalMap")
|
||||
if (con.toProperty == "NormalMap")
|
||||
type = Texture::NORMAL;
|
||||
else if (con.property == "DiffuseColor")
|
||||
else if (con.toProperty == "DiffuseColor")
|
||||
type = Texture::DIFFUSE;
|
||||
else if (con.property == "SpecularColor")
|
||||
else if (con.toProperty == "SpecularColor")
|
||||
type = Texture::SPECULAR;
|
||||
else if (con.property == "ShininessExponent")
|
||||
else if (con.toProperty == "ShininessExponent")
|
||||
type = Texture::SHININESS;
|
||||
else if (con.property == "EmissiveColor")
|
||||
else if (con.toProperty == "EmissiveColor")
|
||||
type = Texture::EMISSIVE;
|
||||
else if (con.property == "AmbientColor")
|
||||
else if (con.toProperty == "AmbientColor")
|
||||
type = Texture::AMBIENT;
|
||||
else if (con.property == "ReflectionFactor")
|
||||
else if (con.toProperty == "ReflectionFactor")
|
||||
type = Texture::REFLECTION;
|
||||
if (type == Texture::COUNT) break;
|
||||
|
||||
|
@ -3323,7 +3794,7 @@ static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator
|
|||
if (child->getType() == Object::Type::ANIMATION_CURVE)
|
||||
{
|
||||
char tmp[32];
|
||||
con.property.toString(tmp);
|
||||
con.toProperty.toString(tmp);
|
||||
if (strcmp(tmp, "d|X") == 0)
|
||||
{
|
||||
node->curves[0].connection = &con;
|
||||
|
@ -3551,7 +4022,7 @@ Object* Object::resolveObjectLink(Object::Type type, const char* property, int i
|
|||
Object* obj = scene.m_object_map.find(connection.from)->second.object;
|
||||
if (obj && obj->getType() == type)
|
||||
{
|
||||
if (property == nullptr || connection.property == property)
|
||||
if (property == nullptr || connection.toProperty == property)
|
||||
{
|
||||
if (idx == 0) return obj;
|
||||
--idx;
|
||||
|
@ -3582,7 +4053,7 @@ Object* Object::getParent() const
|
|||
}
|
||||
|
||||
|
||||
IScene* load(const u8* data, int size, u64 flags, JobProcessor job_processor, void* job_user_ptr)
|
||||
IScene* load(const u8* data, int size, u16 flags, JobProcessor job_processor, void* job_user_ptr)
|
||||
{
|
||||
std::unique_ptr<Scene> scene(new Scene());
|
||||
scene->m_data.resize(size);
|
||||
|
|
179
external/openfbx/ofbx.h
vendored
179
external/openfbx/ofbx.h
vendored
|
@ -25,12 +25,36 @@ static_assert(sizeof(i64) == 8, "i64 is not 8 bytes");
|
|||
using JobFunction = void (*)(void*);
|
||||
using JobProcessor = void (*)(JobFunction, void*, void*, u32, u32);
|
||||
|
||||
enum class LoadFlags : u64 {
|
||||
// Ignoring certain nodes will only stop them from being processed not tokenised (i.e. they will still be in the tree)
|
||||
enum class LoadFlags : u16
|
||||
{
|
||||
TRIANGULATE = 1 << 0,
|
||||
IGNORE_GEOMETRY = 1 << 1,
|
||||
IGNORE_BLEND_SHAPES = 1 << 2,
|
||||
IGNORE_CAMERAS = 1 << 3,
|
||||
IGNORE_LIGHTS = 1 << 4,
|
||||
IGNORE_TEXTURES = 1 << 5,
|
||||
IGNORE_SKIN = 1 << 6,
|
||||
IGNORE_BONES = 1 << 7,
|
||||
IGNORE_PIVOTS = 1 << 8,
|
||||
IGNORE_ANIMATIONS = 1 << 9,
|
||||
IGNORE_MATERIALS = 1 << 10,
|
||||
IGNORE_POSES = 1 << 11,
|
||||
IGNORE_VIDEOS = 1 << 12,
|
||||
IGNORE_LIMBS = 1 << 13,
|
||||
IGNORE_MESHES = 1 << 14,
|
||||
IGNORE_MODELS = 1 << 15,
|
||||
};
|
||||
|
||||
constexpr LoadFlags operator|(LoadFlags lhs, LoadFlags rhs)
|
||||
{
|
||||
return static_cast<LoadFlags>(static_cast<u16>(lhs) | static_cast<u16>(rhs));
|
||||
}
|
||||
|
||||
constexpr LoadFlags& operator|=(LoadFlags& lhs, LoadFlags rhs)
|
||||
{
|
||||
return lhs = lhs | rhs;
|
||||
}
|
||||
|
||||
struct Vec2
|
||||
{
|
||||
|
@ -81,6 +105,7 @@ struct DataView
|
|||
i64 toI64() const;
|
||||
int toInt() const;
|
||||
u32 toU32() const;
|
||||
bool toBool() const;
|
||||
double toDouble() const;
|
||||
float toFloat() const;
|
||||
|
||||
|
@ -168,6 +193,8 @@ struct Object
|
|||
TEXTURE,
|
||||
LIMB_NODE,
|
||||
NULL_NODE,
|
||||
CAMERA,
|
||||
LIGHT,
|
||||
NODE_ATTRIBUTE,
|
||||
CLUSTER,
|
||||
SKIN,
|
||||
|
@ -255,6 +282,124 @@ struct Texture : Object
|
|||
virtual DataView getEmbeddedData() const = 0;
|
||||
};
|
||||
|
||||
struct Light : Object
|
||||
{
|
||||
public:
|
||||
enum class LightType
|
||||
{
|
||||
POINT,
|
||||
DIRECTIONAL,
|
||||
SPOT,
|
||||
AREA,
|
||||
VOLUME,
|
||||
COUNT
|
||||
};
|
||||
|
||||
enum class DecayType
|
||||
{
|
||||
NO_DECAY,
|
||||
LINEAR,
|
||||
QUADRATIC,
|
||||
CUBIC,
|
||||
COUNT
|
||||
};
|
||||
|
||||
Light(const Scene& _scene, const IElement& _element)
|
||||
: Object(_scene, _element)
|
||||
{
|
||||
// Initialize the light properties here
|
||||
}
|
||||
|
||||
// Light type
|
||||
virtual LightType getLightType() const = 0;
|
||||
|
||||
// Light properties
|
||||
virtual bool doesCastLight() const = 0;
|
||||
virtual bool doesDrawVolumetricLight() const = 0;
|
||||
virtual bool doesDrawGroundProjection() const = 0;
|
||||
virtual bool doesDrawFrontFacingVolumetricLight() const = 0;
|
||||
virtual Color getColor() const = 0;
|
||||
virtual double getIntensity() const = 0;
|
||||
virtual double getInnerAngle() const = 0;
|
||||
virtual double getOuterAngle() const = 0;
|
||||
virtual double getFog() const = 0;
|
||||
virtual DecayType getDecayType() const = 0;
|
||||
virtual double getDecayStart() const = 0;
|
||||
|
||||
// Near attenuation
|
||||
virtual bool doesEnableNearAttenuation() const = 0;
|
||||
virtual double getNearAttenuationStart() const = 0;
|
||||
virtual double getNearAttenuationEnd() const = 0;
|
||||
|
||||
// Far attenuation
|
||||
virtual bool doesEnableFarAttenuation() const = 0;
|
||||
virtual double getFarAttenuationStart() const = 0;
|
||||
virtual double getFarAttenuationEnd() const = 0;
|
||||
|
||||
// Shadows
|
||||
virtual const Texture* getShadowTexture() const = 0;
|
||||
virtual bool doesCastShadows() const = 0;
|
||||
virtual Color getShadowColor() const = 0;
|
||||
};
|
||||
|
||||
struct Camera : Object
|
||||
{
|
||||
enum class ProjectionType
|
||||
{
|
||||
PERSPECTIVE,
|
||||
ORTHOGRAPHIC,
|
||||
COUNT
|
||||
};
|
||||
|
||||
enum class ApertureMode // Used to determine how to calculate the FOV
|
||||
{
|
||||
HORIZANDVERT,
|
||||
HORIZONTAL,
|
||||
VERTICAL,
|
||||
FOCALLENGTH,
|
||||
COUNT
|
||||
};
|
||||
|
||||
enum class GateFit
|
||||
{
|
||||
NONE,
|
||||
VERTICAL,
|
||||
HORIZONTAL,
|
||||
FILL,
|
||||
OVERSCAN,
|
||||
STRETCH,
|
||||
COUNT
|
||||
};
|
||||
|
||||
static const Type s_type = Type::CAMERA;
|
||||
|
||||
Camera(const Scene& _scene, const IElement& _element)
|
||||
: Object(_scene, _element)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Type getType() const { return Type::CAMERA; }
|
||||
virtual ProjectionType getProjectionType() const = 0;
|
||||
virtual ApertureMode getApertureMode() const = 0;
|
||||
|
||||
virtual double getFilmHeight() const = 0;
|
||||
virtual double getFilmWidth() const = 0;
|
||||
|
||||
virtual double getAspectHeight() const = 0;
|
||||
virtual double getAspectWidth() const = 0;
|
||||
|
||||
virtual double getNearPlane() const = 0;
|
||||
virtual double getFarPlane() const = 0;
|
||||
virtual bool doesAutoComputeClipPanes() const = 0;
|
||||
|
||||
virtual GateFit getGateFit() const = 0;
|
||||
virtual double getFilmAspectRatio() const = 0;
|
||||
virtual double getFocalLength() const = 0;
|
||||
virtual double getFocusDistance() const = 0;
|
||||
|
||||
virtual Vec3 getBackgroundColor() const = 0;
|
||||
virtual Vec3 getInterestPosition() const = 0;
|
||||
};
|
||||
|
||||
struct Material : Object
|
||||
{
|
||||
|
@ -508,29 +653,51 @@ struct GlobalSettings
|
|||
struct IScene
|
||||
{
|
||||
virtual void destroy() = 0;
|
||||
|
||||
// Root Node
|
||||
virtual const IElement* getRootElement() const = 0;
|
||||
virtual const Object* getRoot() const = 0;
|
||||
virtual const TakeInfo* getTakeInfo(const char* name) const = 0;
|
||||
virtual int getGeometryCount() const = 0;
|
||||
|
||||
// Meshes
|
||||
virtual int getMeshCount() const = 0;
|
||||
virtual float getSceneFrameRate() const = 0;
|
||||
virtual const GlobalSettings* getGlobalSettings() const = 0;
|
||||
virtual const Mesh* getMesh(int index) const = 0;
|
||||
|
||||
// Geometry
|
||||
virtual int getGeometryCount() const = 0;
|
||||
virtual const Geometry* getGeometry(int index) const = 0;
|
||||
|
||||
// Animations
|
||||
virtual int getAnimationStackCount() const = 0;
|
||||
virtual const AnimationStack* getAnimationStack(int index) const = 0;
|
||||
|
||||
// Cameras
|
||||
virtual int getCameraCount() const = 0;
|
||||
virtual const Camera* getCamera(int index) const = 0;
|
||||
|
||||
// Lights
|
||||
virtual int getLightCount() const = 0;
|
||||
virtual const Light* getLight(int index) const = 0;
|
||||
|
||||
// Scene Objects (Everything in scene)
|
||||
virtual const Object* const* getAllObjects() const = 0;
|
||||
virtual int getAllObjectCount() const = 0;
|
||||
|
||||
// Embedded files/Data
|
||||
virtual int getEmbeddedDataCount() const = 0;
|
||||
virtual DataView getEmbeddedData(int index) const = 0;
|
||||
virtual DataView getEmbeddedFilename(int index) const = 0;
|
||||
|
||||
// Scene Misc
|
||||
virtual const TakeInfo* getTakeInfo(const char* name) const = 0;
|
||||
virtual float getSceneFrameRate() const = 0;
|
||||
virtual const GlobalSettings* getGlobalSettings() const = 0;
|
||||
|
||||
protected:
|
||||
virtual ~IScene() {}
|
||||
};
|
||||
|
||||
|
||||
IScene* load(const u8* data, int size, u64 flags, JobProcessor job_processor = nullptr, void* job_user_ptr = nullptr);
|
||||
IScene* load(const u8* data, int size, u16 flags, JobProcessor job_processor = nullptr, void* job_user_ptr = nullptr);
|
||||
const char* getError();
|
||||
double fbxTimeToSeconds(i64 value);
|
||||
i64 secondsToFbxTime(double value);
|
||||
|
|
|
@ -933,8 +933,8 @@ bool FBXImporter::setSource(const char* filename, bool ignore_geometry, bool for
|
|||
OutputMemoryStream data(m_allocator);
|
||||
if (!m_filesystem.getContentSync(Path(filename), data)) return false;
|
||||
|
||||
const u64 flags = ignore_geometry ? (u64)ofbx::LoadFlags::IGNORE_GEOMETRY : (u64)ofbx::LoadFlags::TRIANGULATE;
|
||||
scene = ofbx::load(data.data(), (i32)data.size(), flags, &ofbx_job_processor, nullptr);
|
||||
const ofbx::LoadFlags flags = ignore_geometry ? ofbx::LoadFlags::IGNORE_GEOMETRY : ofbx::LoadFlags::TRIANGULATE;
|
||||
scene = ofbx::load(data.data(), (i32)data.size(), static_cast<u16>(flags), &ofbx_job_processor, nullptr);
|
||||
if (!scene)
|
||||
{
|
||||
logError("Failed to import \"", filename, ": ", ofbx::getError(), "\n"
|
||||
|
|
Loading…
Reference in a new issue