Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add getHeaders() method + parsing headers logic #110

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions src/ofbx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1956,6 +1956,7 @@ struct Scene : IScene
int getMeshCount() const override { return (int)m_meshes.size(); }
float getSceneFrameRate() const override { return m_scene_frame_rate; }
const GlobalSettings* getGlobalSettings() const override { return &m_settings; }
const Headers* getHeaders() const override { return &m_headers; }

const Object* const* getAllObjects() const override { return m_all_objects.empty() ? nullptr : &m_all_objects[0]; }

Expand Down Expand Up @@ -2059,6 +2060,7 @@ struct Scene : IScene
Root* m_root = nullptr;
float m_scene_frame_rate = -1;
GlobalSettings m_settings;
Headers m_headers;

std::unordered_map<std::string, u64> m_fake_ids;
std::unordered_map<u64, ObjectPair> m_object_map;
Expand Down Expand Up @@ -3403,6 +3405,100 @@ static void parseGlobalSettings(const Element& root, Scene* scene)
}
}

static void parseHeaders(const Element& root, Scene* scene)
{
const Element* headers = findChild(root, "FBXHeaderExtension");
if (!headers) return;

const Element* sceneInfo = findChild(*headers, "SceneInfo");
if (sceneInfo)
{
bool is_p60 = false;
const Element* props = findChild(*sceneInfo, "Properties70");
if (!props)
{
is_p60 = true;
props = findChild(*sceneInfo, "Properties60");
if (!props) return;
}

for (Element* node = props->child; node; node = node->sibling)
{
if (!node->first_property) continue;

#define get_string_property(name, field) if (node->first_property->value == name) \
{ \
IElementProperty* prop = node->getProperty(scene->version <= 6100 ? 3 : 4); \
if (prop) \
{ \
DataView value = prop->getValue(); \
char tmp[255]; \
value.toString(tmp); \
tmp[sizeof(tmp) - 1] = '\0'; \
size_t len = strlen(tmp) + 1; \
scene->m_headers.field = new char[len]; \
memcpy(scene->m_headers.field, tmp, len); \
} \
}

get_string_property("DocumentUrl", documentUrl);
get_string_property("SrcDocumentUrl", srcDocumentUrl);
get_string_property("Original|ApplicationVendor", originalApplicationVendor);
get_string_property("Original|ApplicationName", originalApplicationName);
get_string_property("Original|ApplicationVersion", originalApplicationVersion);
get_string_property("Original|DateTime_GMT", originalDateTimeGMT); // datetime stored as string using local culture, dirty, could be improved
get_string_property("Original|Filename", originalFilename);
get_string_property("Original|ApplicationActiveProject", originalApplicationActiveProject);
get_string_property("Original|ApplicationNativeFile", originalApplicationNativeFile); // Blender FBX export only
get_string_property("LastSaved|ApplicationVendor", lastSavedApplicationVendor);
get_string_property("LastSaved|ApplicationName", lastSavedApplicationName);
get_string_property("LastSaved|ApplicationVersion", lastSavedApplicationVersion);
get_string_property("LastSaved|DateTime_GMT", lastSavedDateTimeGMT); // datetime stored as string using local culture, dirty, could be improved

#undef get_string_property
}
}

for (Element* node = headers->child; node; node = node->sibling)
{
if (!node->first_property) continue;

#define get_property(name, field, type, getter) if (node->id == name) \
{ \
IElementProperty* prop = node->getProperty(0); \
if (prop) \
{ \
DataView value = prop->getValue(); \
scene->m_headers.field = (type)value.getter(); \
} \
}

#define get_string_property(name, field) if (node->id == name) \
{ \
IElementProperty* prop = node->getProperty(0); \
if (prop) \
{ \
DataView value = prop->getValue(); \
char tmp[255]; \
value.toString(tmp); \
tmp[sizeof(tmp) - 1] = '\0'; \
size_t len = strlen(tmp) + 1; \
scene->m_headers.field = new char[len]; \
memcpy(scene->m_headers.field, tmp, len); \
} \
}

get_property("FBXHeaderVersion", fbxHeaderVersion, int, toInt);
get_property("FBXVersion", fbxVersion, int, toInt);
get_property("EncryptionType", encryptionType, int, toInt);
get_string_property("Creator", creator);
get_string_property("CreationTime", creationTime); // in Blender exports, not in 3ds max exports

#undef get_property
#undef get_string_property
}
}

void sync_job_processor(JobFunction fn, void*, void* data, u32 size, u32 count) {
u8* ptr = (u8*)data;
for(u32 i = 0; i < count; ++i) {
Expand Down Expand Up @@ -4120,6 +4216,7 @@ IScene* load(const u8* data, usize size, u16 flags, JobProcessor job_processor,
if (!parseTakes(*scene.get())) return nullptr;
if (!parseObjects(*root.getValue(), *scene.get(), flags, scene->m_allocator, job_processor, job_user_ptr)) return nullptr;
parseGlobalSettings(*root.getValue(), scene.get());
parseHeaders(*root.getValue(), scene.get());
if (!scene->finalize()) return nullptr;

return scene.release();
Expand Down
28 changes: 28 additions & 0 deletions src/ofbx.h
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,31 @@ struct GlobalSettings
float CustomFrameRate = -1.0f;
};

struct Headers
{
int fbxHeaderVersion = 0;
int fbxVersion = 0;
int encryptionType = 0;
char* creator;
char* creationTime;

char* documentUrl;
char* srcDocumentUrl;
char* originalApplicationVendor;
char* originalApplicationName;
char* originalApplicationVersion;

char* originalDateTimeGMT;

char* originalFilename;
char* originalApplicationActiveProject;
char* originalApplicationNativeFile;

char* lastSavedApplicationVendor;
char* lastSavedApplicationName;
char* lastSavedApplicationVersion;
char* lastSavedDateTimeGMT;
};

struct IScene
{
Expand Down Expand Up @@ -763,6 +788,9 @@ struct IScene
virtual const TakeInfo* getTakeInfo(const char* name) const = 0;
virtual float getSceneFrameRate() const = 0;
virtual const GlobalSettings* getGlobalSettings() const = 0;

// Headers
virtual const Headers* getHeaders() const = 0;

protected:
virtual ~IScene() {}
Expand Down