mirror of
https://github.com/openharmony/third_party_meshoptimizer.git
synced 2026-07-20 04:13:44 -04:00
gltfpack: Minor mesh processing refactoring
The logic for detaching mesh from nodes is fairly complex but it's a little difficult to separate into individual components due to multiple scenes handling, so for now just extract it into a separate function to make the high level processing flow easier to read.
This commit is contained in:
+63
-66
@@ -250,6 +250,68 @@ static bool canTransformMesh(const Mesh& mesh)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void detachMesh(Mesh& mesh, cgltf_data* data, const std::vector<NodeInfo>& nodes, const Settings& settings)
|
||||
{
|
||||
// mesh is already instanced, skip
|
||||
if (!mesh.instances.empty())
|
||||
return;
|
||||
|
||||
// mesh is already world space, skip
|
||||
if (mesh.nodes.empty())
|
||||
return;
|
||||
|
||||
// note: when -kn is specified, we keep mesh-node attachment so that named nodes can be transformed
|
||||
if (settings.keep_nodes)
|
||||
return;
|
||||
|
||||
// we keep skinned meshes or meshes with morph targets as is
|
||||
// in theory we could transform both, but in practice transforming morph target meshes is more involved,
|
||||
// and reparenting skinned meshes leads to incorrect bounding box generated in three.js
|
||||
if (mesh.skin || mesh.targets)
|
||||
return;
|
||||
|
||||
bool any_animated = false;
|
||||
for (size_t j = 0; j < mesh.nodes.size(); ++j)
|
||||
any_animated |= nodes[mesh.nodes[j] - data->nodes].animated;
|
||||
|
||||
// animated meshes will be anchored to the same node that they used to be in to retain the animation
|
||||
if (any_animated)
|
||||
return;
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
// 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)
|
||||
return;
|
||||
|
||||
// prefer instancing if possible, use merging otherwise
|
||||
if (mesh.nodes.size() > 1 && settings.mesh_instancing)
|
||||
{
|
||||
mesh.instances.resize(mesh.nodes.size());
|
||||
|
||||
for (size_t j = 0; j < mesh.nodes.size(); ++j)
|
||||
cgltf_node_transform_world(mesh.nodes[j], mesh.instances[j].data);
|
||||
|
||||
mesh.nodes.clear();
|
||||
mesh.scene = scene;
|
||||
}
|
||||
else if (canTransformMesh(mesh))
|
||||
{
|
||||
mergeMeshInstances(mesh);
|
||||
|
||||
assert(mesh.nodes.empty());
|
||||
mesh.scene = scene;
|
||||
}
|
||||
}
|
||||
|
||||
static bool isExtensionSupported(const ExtensionInfo* extensions, size_t count, const char* name)
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
@@ -269,9 +331,7 @@ static void process(cgltf_data* data, const char* input_path, const char* output
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < animations.size(); ++i)
|
||||
{
|
||||
processAnimation(animations[i], settings);
|
||||
}
|
||||
|
||||
std::vector<NodeInfo> nodes(data->nodes_count);
|
||||
|
||||
@@ -279,68 +339,7 @@ static void process(cgltf_data* data, const char* input_path, const char* output
|
||||
markAnimated(data, nodes, animations);
|
||||
|
||||
for (size_t i = 0; i < meshes.size(); ++i)
|
||||
{
|
||||
Mesh& mesh = meshes[i];
|
||||
|
||||
// mesh is already instanced, skip
|
||||
if (!mesh.instances.empty())
|
||||
continue;
|
||||
|
||||
// mesh is already world space, skip
|
||||
if (mesh.nodes.empty())
|
||||
continue;
|
||||
|
||||
// note: when -kn is specified, we keep mesh-node attachment so that named nodes can be transformed
|
||||
if (settings.keep_nodes)
|
||||
continue;
|
||||
|
||||
// we keep skinned meshes or meshes with morph targets as is
|
||||
// in theory we could transform both, but in practice transforming morph target meshes is more involved,
|
||||
// and reparenting skinned meshes leads to incorrect bounding box generated in three.js
|
||||
if (mesh.skin || mesh.targets)
|
||||
continue;
|
||||
|
||||
bool any_animated = false;
|
||||
for (size_t j = 0; j < mesh.nodes.size(); ++j)
|
||||
any_animated |= nodes[mesh.nodes[j] - data->nodes].animated;
|
||||
|
||||
// animated meshes will be anchored to the same node that they used to be in to retain the animation
|
||||
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)
|
||||
continue;
|
||||
|
||||
// prefer instancing if possible, use merging otherwise
|
||||
if (mesh.nodes.size() > 1 && settings.mesh_instancing)
|
||||
{
|
||||
mesh.instances.resize(mesh.nodes.size());
|
||||
|
||||
for (size_t j = 0; j < mesh.nodes.size(); ++j)
|
||||
cgltf_node_transform_world(mesh.nodes[j], mesh.instances[j].data);
|
||||
|
||||
mesh.nodes.clear();
|
||||
mesh.scene = scene;
|
||||
}
|
||||
else if (canTransformMesh(mesh))
|
||||
{
|
||||
mergeMeshInstances(mesh);
|
||||
|
||||
assert(mesh.nodes.empty());
|
||||
mesh.scene = scene;
|
||||
}
|
||||
}
|
||||
detachMesh(meshes[i], data, nodes, settings);
|
||||
|
||||
// material information is required for mesh and image processing
|
||||
std::vector<MaterialInfo> materials(data->materials_count);
|
||||
@@ -406,9 +405,7 @@ static void process(cgltf_data* data, const char* input_path, const char* output
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < meshes.size(); ++i)
|
||||
{
|
||||
processMesh(meshes[i], settings);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
meshes.insert(meshes.end(), debug_meshes.begin(), debug_meshes.end());
|
||||
|
||||
Reference in New Issue
Block a user