Skip to content

Commit

Permalink
Merge pull request #188 from zeux/gltf-scenes
Browse files Browse the repository at this point in the history
gltfpack: Preserve scenes during processing
  • Loading branch information
zeux authored Oct 11, 2020
2 parents 58cc432 + 7e8b5cf commit 8a76413
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 33 deletions.
58 changes: 42 additions & 16 deletions gltf/gltfpack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ static void process(cgltf_data* data, const char* input_path, const char* output

std::vector<NodeInfo> nodes(data->nodes_count);

markScenes(data, nodes);
markAnimated(data, nodes, animations);

for (size_t i = 0; i < meshes.size(); ++i)
Expand Down Expand Up @@ -260,6 +261,15 @@ static void process(cgltf_data* data, const char* input_path, const char* output
if (any_animated)
continue;

int scene = nodes[mesh.nodes[0] - data->nodes].scene;
bool any_other_scene = false;
for (size_t j = 0; j < mesh.nodes.size(); ++j)
any_other_scene |= scene != nodes[mesh.nodes[j] - data->nodes].scene;

// we only merge instances when all nodes have a single consistent scene
if (scene < 0 || any_other_scene)
continue;

// we only merge multiple instances together if requested
// this often makes the scenes faster to render by reducing the draw call count, but can result in larger files
if (mesh.nodes.size() > 1 && !settings.mesh_merge && !settings.mesh_instancing)
Expand All @@ -280,6 +290,8 @@ static void process(cgltf_data* data, const char* input_path, const char* output
mergeMeshInstances(mesh);
}

mesh.scene = scene;

assert(mesh.nodes.empty());
}

Expand Down Expand Up @@ -348,7 +360,7 @@ static void process(cgltf_data* data, const char* input_path, const char* output
std::string json_meshes;
std::string json_nodes;
std::string json_skins;
std::string json_roots;
std::vector<std::string> json_roots(data->scenes_count);
std::string json_animations;
std::string json_cameras;
std::string json_lights;
Expand Down Expand Up @@ -536,8 +548,9 @@ static void process(cgltf_data* data, const char* input_path, const char* output
}
else if (mesh.instances.size())
{
comma(json_roots);
append(json_roots, node_offset);
assert(mesh.scene >= 0);
comma(json_roots[mesh.scene]);
append(json_roots[mesh.scene], node_offset);

size_t instance_accr = writeInstances(views, json_accessors, accr_offset, mesh.instances, qp, settings);

Expand All @@ -548,8 +561,9 @@ static void process(cgltf_data* data, const char* input_path, const char* output
}
else
{
comma(json_roots);
append(json_roots, node_offset);
assert(mesh.scene >= 0);
comma(json_roots[mesh.scene]);
append(json_roots[mesh.scene], node_offset);

writeMeshNode(json_nodes, mesh_offset, NULL, mesh.skin, data, settings.quantize ? &qp : NULL);

Expand All @@ -574,12 +588,6 @@ static void process(cgltf_data* data, const char* input_path, const char* output

const cgltf_node& node = data->nodes[i];

if (!node.parent)
{
comma(json_roots);
append(json_roots, size_t(ni.remap));
}

comma(json_nodes);
append(json_nodes, "{");
writeNode(json_nodes, node, nodes, data);
Expand All @@ -588,6 +596,20 @@ static void process(cgltf_data* data, const char* input_path, const char* output
append(json_nodes, "}");
}

for (size_t i = 0; i < data->scenes_count; ++i)
{
for (size_t j = 0; j < data->scenes[i].nodes_count; ++j)
{
NodeInfo& ni = nodes[data->scenes[i].nodes[j] - data->nodes];

if (ni.keep)
{
comma(json_roots[i]);
append(json_roots[i], size_t(ni.remap));
}
}
}

for (size_t i = 0; i < data->skins_count; ++i)
{
const cgltf_skin& skin = data->skins[i];
Expand Down Expand Up @@ -658,9 +680,11 @@ static void process(cgltf_data* data, const char* input_path, const char* output
if (!json_roots.empty())
{
append(json, ",\"scenes\":[");
append(json, "{\"nodes\":[");
append(json, json_roots);
append(json, "]}]");

for (size_t i = 0; i < data->scenes_count; ++i)
writeScene(json, data->scenes[i], json_roots[i]);

append(json, "]");
}

writeArray(json, "cameras", json_cameras);
Expand All @@ -671,9 +695,11 @@ static void process(cgltf_data* data, const char* input_path, const char* output
append(json, json_lights);
append(json, "]}}");
}
if (!json_roots.empty())

if (data->scene)
{
append(json, ",\"scene\":0");
append(json, ",\"scene\":");
append(json, size_t(data->scene - data->scenes));
}

if (settings.verbose)
Expand Down
5 changes: 5 additions & 0 deletions gltf/gltfpack.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct Transform

struct Mesh
{
int scene;
std::vector<cgltf_node*> nodes;
std::vector<Transform> instances;

Expand Down Expand Up @@ -157,6 +158,8 @@ struct StreamFormat

struct NodeInfo
{
int scene;

bool keep;
bool animated;

Expand Down Expand Up @@ -261,6 +264,7 @@ std::string basisToKtx(const std::string& data, bool srgb, bool uastc);
bool checkKtx(bool verbose);
bool encodeKtx(const std::string& data, const char* mime_type, std::string& result, bool normal_map, bool srgb, int quality, float scale, bool pow2, bool uastc, bool verbose);

void markScenes(cgltf_data* data, std::vector<NodeInfo>& nodes);
void markAnimated(cgltf_data* data, std::vector<NodeInfo>& nodes, const std::vector<Animation>& animations);
void markNeededNodes(cgltf_data* data, std::vector<NodeInfo>& nodes, const std::vector<Mesh>& meshes, const std::vector<Animation>& animations, const Settings& settings);
void remapNodes(cgltf_data* data, std::vector<NodeInfo>& nodes, size_t& node_offset);
Expand Down Expand Up @@ -309,6 +313,7 @@ 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 std::string& data, const cgltf_extras& extras);
void writeScene(std::string& json, const cgltf_scene& scene, const std::string& roots);

/**
* Copyright (c) 2016-2020 Arseny Kapoulkine
Expand Down
3 changes: 3 additions & 0 deletions gltf/mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ static bool canMergeMeshNodes(cgltf_node* lhs, cgltf_node* rhs, const Settings&

static bool canMergeMeshes(const Mesh& lhs, const Mesh& rhs, const Settings& settings)
{
if (lhs.scene != rhs.scene)
return false;

if (lhs.nodes.size() != rhs.nodes.size())
return false;

Expand Down
26 changes: 26 additions & 0 deletions gltf/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,32 @@
#include <math.h>
#include <string.h>

void markScenes(cgltf_data* data, std::vector<NodeInfo>& nodes)
{
for (size_t i = 0; i < nodes.size(); ++i)
nodes[i].scene = -1;

for (size_t i = 0; i < data->scenes_count; ++i)
for (size_t j = 0; j < data->scenes[i].nodes_count; ++j)
{
NodeInfo& ni = nodes[data->scenes[i].nodes[j] - data->nodes];

if (ni.scene >= 0)
ni.scene = -2; // multiple scenes
else
ni.scene = int(i);
}

for (size_t i = 0; i < data->nodes_count; ++i)
{
cgltf_node* root = &data->nodes[i];
while (root->parent)
root = root->parent;

nodes[i].scene = nodes[root - data->nodes].scene;
}
}

void markAnimated(cgltf_data* data, std::vector<NodeInfo>& nodes, const std::vector<Animation>& animations)
{
for (size_t i = 0; i < animations.size(); ++i)
Expand Down
2 changes: 2 additions & 0 deletions gltf/parsegltf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ static void parseMeshesGltf(cgltf_data* data, std::vector<Mesh>& meshes, std::ve
meshes.push_back(Mesh());
Mesh& result = meshes.back();

result.scene = -1;

result.material = primitive.material;

result.type = primitive.type;
Expand Down
3 changes: 3 additions & 0 deletions gltf/parseobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ static cgltf_data* parseSceneObj(fastObjMesh* obj)
}
}

data->scenes = (cgltf_scene*)calloc(1, sizeof(cgltf_scene));
data->scenes_count = 1;

return data;
}

Expand Down
31 changes: 14 additions & 17 deletions gltf/wasistubs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,24 @@ extern "C" void* __cxa_allocate_exception(size_t thrown_size)
abort();
}

__wasi_errno_t __wasi_path_open32(__wasi_fd_t fd, __wasi_lookupflags_t dirflags, const char *path, size_t path_len, __wasi_oflags_t oflags, uint32_t fs_rights_base, uint32_t fs_rights_inherting, __wasi_fdflags_t fdflags, __wasi_fd_t *opened_fd)
__attribute__((
__import_module__("wasi_snapshot_preview1"),
__import_name__("path_open32"),
__warn_unused_result__
));

__wasi_errno_t __wasi_path_open(__wasi_fd_t fd, __wasi_lookupflags_t dirflags, const char *path, size_t path_len, __wasi_oflags_t oflags, __wasi_rights_t fs_rights_base, __wasi_rights_t fs_rights_inherting, __wasi_fdflags_t fdflags, __wasi_fd_t *opened_fd)
__wasi_errno_t __wasi_path_open32(__wasi_fd_t fd, __wasi_lookupflags_t dirflags, const char* path, size_t path_len, __wasi_oflags_t oflags, uint32_t fs_rights_base, uint32_t fs_rights_inherting, __wasi_fdflags_t fdflags, __wasi_fd_t* opened_fd)
__attribute__((
__import_module__("wasi_snapshot_preview1"),
__import_name__("path_open32"),
__warn_unused_result__));

__wasi_errno_t __wasi_path_open(__wasi_fd_t fd, __wasi_lookupflags_t dirflags, const char* path, size_t path_len, __wasi_oflags_t oflags, __wasi_rights_t fs_rights_base, __wasi_rights_t fs_rights_inherting, __wasi_fdflags_t fdflags, __wasi_fd_t* opened_fd)
{
return __wasi_path_open32(fd, dirflags, path, path_len, oflags, fs_rights_base, fs_rights_inherting, fdflags, opened_fd);

}

__wasi_errno_t __wasi_fd_seek32(__wasi_fd_t fd, int32_t offset, __wasi_whence_t whence, int32_t *newoffset)
__attribute__((
__import_module__("wasi_snapshot_preview1"),
__import_name__("fd_seek32"),
__warn_unused_result__
));
__wasi_errno_t __wasi_fd_seek32(__wasi_fd_t fd, int32_t offset, __wasi_whence_t whence, int32_t* newoffset)
__attribute__((
__import_module__("wasi_snapshot_preview1"),
__import_name__("fd_seek32"),
__warn_unused_result__));

__wasi_errno_t __wasi_fd_seek(__wasi_fd_t fd, __wasi_filedelta_t offset, __wasi_whence_t whence, __wasi_filesize_t *newoffset)
__wasi_errno_t __wasi_fd_seek(__wasi_fd_t fd, __wasi_filedelta_t offset, __wasi_whence_t whence, __wasi_filesize_t* newoffset)
{
int32_t newoffset32 = 0;
__wasi_errno_t result = __wasi_fd_seek32(fd, int32_t(offset), whence, &newoffset32);
Expand All @@ -46,7 +43,7 @@ extern "C" int system(const char* command)
{
// WASI doesn't provide a system() equivalent; we highjack readlink here, the reasoning being that if we run against a real WASI implementation,
// the effect is more likely to be benign.
return __wasi_path_readlink(-1, command, strlen(command), 0, 0, 0);
return __wasi_path_readlink(-1, command, strlen(command), 0, 0, 0);
}

#endif
20 changes: 20 additions & 0 deletions gltf/write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1453,3 +1453,23 @@ void writeExtras(std::string& json, const std::string& data, const cgltf_extras&
append(json, "\"extras\":");
appendJson(json, data.c_str() + extras.start_offset, data.c_str() + extras.end_offset);
}

void writeScene(std::string& json, const cgltf_scene& scene, const std::string& roots)
{
comma(json);
append(json, "{");
if (scene.name && *scene.name)
{
append(json, "\"name\":\"");
append(json, scene.name);
append(json, "\"");
}
if (!roots.empty())
{
comma(json);
append(json, "\"nodes\":[");
append(json, roots);
append(json, "]");
}
append(json, "}");
}

0 comments on commit 8a76413

Please sign in to comment.