Skip to content

Commit

Permalink
Merge pull request #147 from zeux/gltf-memory
Browse files Browse the repository at this point in the history
gltfpack: Substantiall reduce memory footprint
  • Loading branch information
zeux authored May 19, 2020
2 parents eaaf3f0 + bd8dfc2 commit ced117c
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 62 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ gltfpack.js: gltf/bin/gltfpack.js

gltf/bin/gltfpack.js: ${LIBRARY_SOURCES} ${GLTFPACK_SOURCES} tools/meshloader.cpp
@mkdir -p gltf/bin
emcc $^ -o $@ -Os -DNDEBUG -s ALLOW_MEMORY_GROWTH=1 -s NODERAWFS=1
emcc $^ -o $@ -Os -DNDEBUG -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s NODERAWFS=1
sed -i '1s;^;#!/usr/bin/env node\n;' $@

build/decoder_base.wasm: $(WASM_SOURCES)
Expand Down
74 changes: 42 additions & 32 deletions gltf/gltfpack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,40 +21,41 @@ std::string getVersion()
return result;
}

static void finalizeBufferViews(std::string& json, std::vector<BufferView>& views, std::string& bin, std::string& fallback)
static void finalizeBufferViews(std::string& json, std::vector<BufferView>& views, std::string& bin, std::string* fallback, size_t& fallback_size)
{
for (size_t i = 0; i < views.size(); ++i)
{
BufferView& view = views[i];

size_t bin_offset = bin.size();
size_t fallback_offset = fallback.size();
size_t fallback_offset = fallback_size;

size_t count = view.data.size() / view.stride;

switch (view.compression)
if (view.compression == BufferView::Compression_None)
{
case BufferView::Compression_None:
bin += view.data;
break;

case BufferView::Compression_Attribute:
compressVertexStream(bin, view.data, count, view.stride);
fallback += view.data;
break;

case BufferView::Compression_Index:
compressIndexStream(bin, view.data, count, view.stride);
fallback += view.data;
break;

case BufferView::Compression_IndexSequence:
compressIndexSequence(bin, view.data, count, view.stride);
fallback += view.data;
break;
}
else
{
switch (view.compression)
{
case BufferView::Compression_Attribute:
compressVertexStream(bin, view.data, count, view.stride);
break;
case BufferView::Compression_Index:
compressIndexStream(bin, view.data, count, view.stride);
break;
case BufferView::Compression_IndexSequence:
compressIndexSequence(bin, view.data, count, view.stride);
break;
default:
assert(!"Unknown compression type");
}

default:
assert(!"Unknown compression type");
if (fallback)
*fallback += view.data;
fallback_size += view.data.size();
}

size_t raw_offset = (view.compression != BufferView::Compression_None) ? fallback_offset : bin_offset;
Expand All @@ -67,7 +68,9 @@ static void finalizeBufferViews(std::string& json, std::vector<BufferView>& view

// align each bufferView by 4 bytes
bin.resize((bin.size() + 3) & ~3);
fallback.resize((fallback.size() + 3) & ~3);
if (fallback)
fallback->resize((fallback->size() + 3) & ~3);
fallback_size = (fallback_size + 3) & ~3;
}
}

Expand Down Expand Up @@ -154,7 +157,7 @@ static void printAttributeStats(const std::vector<BufferView>& views, BufferView
}
}

static void process(cgltf_data* data, const char* input_path, const char* output_path, std::vector<Mesh>& meshes, std::vector<Animation>& animations, const Settings& settings, std::string& json, std::string& bin, std::string& fallback)
static void process(cgltf_data* data, const char* input_path, const char* output_path, std::vector<Mesh>& meshes, std::vector<Animation>& animations, const std::string& extras, const Settings& settings, std::string& json, std::string& bin, std::string& fallback, size_t& fallback_size)
{
if (settings.verbose)
{
Expand Down Expand Up @@ -345,7 +348,7 @@ static void process(cgltf_data* data, const char* input_path, const char* output
append(json_materials, "{");
writeMaterial(json_materials, data, material, settings.quantize ? &qt_materials[i] : NULL);
if (settings.keep_extras)
writeExtras(json_materials, data, material.extras);
writeExtras(json_materials, extras, material.extras);
append(json_materials, "}");

mi.remap = int(material_offset);
Expand Down Expand Up @@ -513,7 +516,12 @@ static void process(cgltf_data* data, const char* input_path, const char* output
append(json_roots, size_t(ni.remap));
}

writeNode(json_nodes, node, nodes, data, settings);
comma(json_nodes);
append(json_nodes, "{");
writeNode(json_nodes, node, nodes, data);
if (settings.keep_extras)
writeExtras(json_nodes, extras, node.extras);
append(json_nodes, "}");
}

for (size_t i = 0; i < data->skins_count; ++i)
Expand Down Expand Up @@ -550,7 +558,7 @@ static void process(cgltf_data* data, const char* input_path, const char* output
append(json, "\"version\":\"2.0\",\"generator\":\"gltfpack ");
append(json, getVersion());
append(json, "\"");
writeExtras(json, data, data->asset.extras);
writeExtras(json, extras, data->asset.extras);
append(json, "}");

const ExtensionInfo extensions[] = {
Expand All @@ -568,7 +576,7 @@ static void process(cgltf_data* data, const char* input_path, const char* output
writeExtensions(json, extensions, sizeof(extensions) / sizeof(extensions[0]));

std::string json_views;
finalizeBufferViews(json_views, views, bin, fallback);
finalizeBufferViews(json_views, views, bin, settings.fallback ? &fallback : NULL, fallback_size);

writeArray(json, "bufferViews", json_views);
writeArray(json, "accessors", json_accessors);
Expand Down Expand Up @@ -676,13 +684,14 @@ int gltfpack(const char* input, const char* output, const Settings& settings)
cgltf_data* data = 0;
std::vector<Mesh> meshes;
std::vector<Animation> animations;
std::string extras;

const char* iext = strrchr(input, '.');

if (iext && (strcmp(iext, ".gltf") == 0 || strcmp(iext, ".GLTF") == 0 || strcmp(iext, ".glb") == 0 || strcmp(iext, ".GLB") == 0))
{
const char* error = 0;
data = parseGltf(input, meshes, animations, &error);
data = parseGltf(input, meshes, animations, extras, &error);

if (error)
{
Expand Down Expand Up @@ -717,7 +726,8 @@ int gltfpack(const char* input, const char* output, const Settings& settings)
}

std::string json, bin, fallback;
process(data, input, output, meshes, animations, settings, json, bin, fallback);
size_t fallback_size = 0;
process(data, input, output, meshes, animations, extras, settings, json, bin, fallback, fallback_size);

cgltf_free(data);

Expand Down Expand Up @@ -745,7 +755,7 @@ int gltfpack(const char* input, const char* output, const Settings& settings)
return 4;
}

std::string bufferspec = getBufferSpec(getBaseName(binpath.c_str()), bin.size(), settings.fallback ? getBaseName(fbpath.c_str()) : NULL, fallback.size(), settings.compress);
std::string bufferspec = getBufferSpec(getBaseName(binpath.c_str()), bin.size(), settings.fallback ? getBaseName(fbpath.c_str()) : NULL, fallback_size, settings.compress);

fprintf(outjson, "{");
fwrite(bufferspec.c_str(), bufferspec.size(), 1, outjson);
Expand Down Expand Up @@ -776,7 +786,7 @@ int gltfpack(const char* input, const char* output, const Settings& settings)
return 4;
}

std::string bufferspec = getBufferSpec(NULL, bin.size(), settings.fallback ? getBaseName(fbpath.c_str()) : NULL, fallback.size(), settings.compress);
std::string bufferspec = getBufferSpec(NULL, bin.size(), settings.fallback ? getBaseName(fbpath.c_str()) : NULL, fallback_size, settings.compress);

json.insert(0, "{" + bufferspec + ",");
json.push_back('}');
Expand Down
6 changes: 3 additions & 3 deletions gltf/gltfpack.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ bool readFile(const char* path, std::string& data);
bool writeFile(const char* path, const std::string& data);

cgltf_data* parseObj(const char* path, std::vector<Mesh>& meshes, const char** error);
cgltf_data* parseGltf(const char* path, std::vector<Mesh>& meshes, std::vector<Animation>& animations, const char** error);
cgltf_data* parseGltf(const char* path, std::vector<Mesh>& meshes, std::vector<Animation>& animations, std::string& extras, const char** error);

void processAnimation(Animation& animation, const Settings& settings);
void processMesh(Mesh& mesh, const Settings& settings);
Expand Down Expand Up @@ -298,13 +298,13 @@ size_t writeInstances(std::vector<BufferView>& views, std::string& json_accessor
void writeMeshNode(std::string& json, size_t mesh_offset, cgltf_node* node, cgltf_skin* skin, cgltf_data* data, const QuantizationPosition* qp);
void writeMeshNodeInstanced(std::string& json, size_t mesh_offset, size_t accr_offset);
void writeSkin(std::string& json, const cgltf_skin& skin, size_t matrix_accr, const std::vector<NodeInfo>& nodes, cgltf_data* data);
void writeNode(std::string& json, const cgltf_node& node, const std::vector<NodeInfo>& nodes, cgltf_data* data, const Settings& settings);
void writeNode(std::string& json, const cgltf_node& node, const std::vector<NodeInfo>& nodes, cgltf_data* data);
void writeAnimation(std::string& json, std::vector<BufferView>& views, std::string& json_accessors, size_t& accr_offset, const Animation& animation, size_t i, cgltf_data* data, const std::vector<NodeInfo>& nodes, const Settings& settings);
void writeCamera(std::string& json, const cgltf_camera& camera);
void writeLight(std::string& json, const cgltf_light& light);
void writeArray(std::string& json, const char* name, const std::string& contents);
void writeExtensions(std::string& json, const ExtensionInfo* extensions, size_t count);
void writeExtras(std::string& json, const cgltf_data* data, const cgltf_extras& extras);
void writeExtras(std::string& json, const std::string& data, const cgltf_extras& extras);

/**
* Copyright (c) 2016-2020 Arseny Kapoulkine
Expand Down
Loading

0 comments on commit ced117c

Please sign in to comment.