Skip to content

Commit

Permalink
base64 encoded embedded data
Browse files Browse the repository at this point in the history
  • Loading branch information
nem0 committed Oct 14, 2023
1 parent a5ba4ef commit faa3caa
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 8 deletions.
26 changes: 22 additions & 4 deletions external/openfbx/ofbx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,12 @@ struct Allocator {
};




struct Video
{
DataView filename;
DataView content;
DataView media;
bool is_base_64;
};


Expand Down Expand Up @@ -1954,6 +1953,10 @@ struct Scene : IScene
return m_videos[index].content;
}

bool isEmbeddedBase64(int index) const override {
return m_videos[index].is_base_64;
}

DataView getEmbeddedFilename(int index) const override {
return m_videos[index].filename;
}
Expand Down Expand Up @@ -2248,17 +2251,32 @@ void parseVideo(Scene& scene, const Element& element, Allocator& allocator)

const Element* content_element = findChild(element, "Content");

bool is_base64 = false;
if (!content_element) return;
if (!content_element->first_property) return;
if (content_element->first_property->getType() != IElementProperty::BINARY) return;
const Property* content_property = content_element->first_property;
if (content_element->first_property->getType() != IElementProperty::BINARY) {
/*
if this happens in text format:
Content: ,
"iVBORw0KGgoA...
this is not a proper solution, but keep doing this until it become an issue
*/
if (content_element->first_property->getType() != IElementProperty::NONE) return;
if (!content_element->first_property->next) return;
if (content_element->first_property->next->getType() != IElementProperty::STRING) return;
content_property = content_element->first_property->next;
is_base64 = true;
}

const Element* filename_element = findChild(element, "Filename");
if (!filename_element) return;
if (!filename_element->first_property) return;
if (filename_element->first_property->getType() != IElementProperty::STRING) return;

Video video;
video.content = content_element->first_property->value;
video.is_base_64 = is_base64;
video.content = content_property->value;
video.filename = filename_element->first_property->value;
video.media = element.first_property->next->value;
scene.m_videos.push_back(video);
Expand Down
1 change: 1 addition & 0 deletions external/openfbx/ofbx.h
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,7 @@ struct IScene
virtual int getEmbeddedDataCount() const = 0;
virtual DataView getEmbeddedData(int index) const = 0;
virtual DataView getEmbeddedFilename(int index) const = 0;
virtual bool isEmbeddedBase64(int index) const = 0;

// Scene Misc
virtual const TakeInfo* getTakeInfo(const char* name) const = 0;
Expand Down
52 changes: 48 additions & 4 deletions src/renderer/editor/fbx_importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,42 @@ static StringView toStringView(ofbx::DataView data) {
);
}

static void extractEmbedded(const ofbx::IScene& m_scene, StringView src_dir)
static const int B64index[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0,
0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 };

void decodeBase64(const void* data, const u32 len, OutputMemoryStream& str)
{
unsigned char* p = (unsigned char*)data;
int pad = len > 0 && (len % 4 || p[len - 1] == '=');
const u32 L = ((len + 3) / 4 - pad) * 4;
str.resize(L / 4 * 3 + pad);

for (u32 i = 0, j = 0; i < L; i += 4)
{
int n = B64index[p[i]] << 18 | B64index[p[i + 1]] << 12 | B64index[p[i + 2]] << 6 | B64index[p[i + 3]];
str[j++] = n >> 16;
str[j++] = n >> 8 & 0xFF;
str[j++] = n & 0xFF;
}
if (pad)
{
int n = B64index[p[L]] << 18 | B64index[p[L + 1]] << 12;
str[u32(str.size() - 1)] = n >> 16;

if (len > L + 2 && p[L + 2] != '=')
{
n |= B64index[p[L + 2]] << 6;
str.write(u8(n >> 8 & 0xFF));
}
}
}

static void extractEmbedded(const ofbx::IScene& m_scene, StringView src_dir, IAllocator& allocator)
{
PROFILE_FUNCTION();
for (int i = 0, c = m_scene.getEmbeddedDataCount(); i < c; ++i) {
Expand All @@ -147,8 +182,17 @@ static void extractEmbedded(const ofbx::IScene& m_scene, StringView src_dir)
return;
}

if (!file.write(embedded.begin + 4, embedded.end - embedded.begin - 4)) {
logError("Failed to write ", fullpath);
if (m_scene.isEmbeddedBase64(i)) {
OutputMemoryStream tmp(allocator);
decodeBase64(embedded.begin, u32(embedded.end - embedded.begin), tmp);
if (!file.write(tmp.data(), tmp.size())) {
logError("Failed to write ", fullpath);
}
}
else {
if (!file.write(embedded.begin + 4, embedded.end - embedded.begin - 4)) {
logError("Failed to write ", fullpath);
}
}
file.close();
}
Expand Down Expand Up @@ -1046,7 +1090,7 @@ bool FBXImporter::setSource(const Path& filename, bool ignore_geometry, bool for
}

StringView src_dir = Path::getDir(filename);
if (!ignore_geometry) extractEmbedded(*m_scene, src_dir);
if (!ignore_geometry) extractEmbedded(*m_scene, src_dir, m_allocator);
gatherMeshes();

gatherAnimations();
Expand Down

0 comments on commit faa3caa

Please sign in to comment.