Skip to content

Commit

Permalink
gltfpack: Preserve scenes during processing
Browse files Browse the repository at this point in the history
Before this change gltfack wasn't scene aware, and would process all
nodes regardless of which scene they come from.

With this change, we now output the same number of scenes that the input
file contained. When merging meshes and converting nodes to mesh instances,
the process is limited to cases where the mesh is not used in multiple
scenes.

Fixes #184
  • Loading branch information
zeux committed Oct 10, 2020
1 parent 58cc432 commit fd6330b
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 16 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
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 fd6330b

Please sign in to comment.