-
Notifications
You must be signed in to change notification settings - Fork 510
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gltfpack does not preserve node hierarchy #48
Comments
There's currently no option to preserve the node hierarchy; I can add one. In your file, is it the case that the file itself doesn't contain animations, but you'd like to move the nodes programmatically? |
yes that' right it's a robot with 3 axis and therfore has 3 "bodies" I move programmatically |
Somewhat related, I have the problem that meshes are merged, which means that the node hierarchy is not preserved. I need meshes to not merge, since you are supposed to be able to individually change materials for every object from within the application. I tried changing the |
@Shimmen Yeah this is a related issue; I'm planning to introduce two separate flags, for keeping mesh identity (which would disable mesh merging and keep all meshes in their original place in the hierarchy), and a separate flag for keeping node hierarchy just in case other nodes are relevant. On an unrelated note, changing |
That's good to hear! The meshes I have tested with now are proprietary, so I can't share any of them. I will try to reproduce it on some non-proprietary mesh and get back to you. |
@zeux it should actually be possible to merge unnamed nodes / meshes. In the first example picture all the child nodes are unnamed and could be merged ( If they have the same material) |
@zeux I can't manage to reproduce it in any other files, and importing then exporting the "broken" files through Blender results in files that do work. So clearly there is something unique about my files, despite them being valid according to the official Khronos glTF validator. I had an idea about fuzzing & anonymizing the data and sending it to you, but since I can't even export it without fixing the issue I'm not sure how to proceed. |
The PR should resolve this issue - note that currently it should be sufficient to use |
Hello the PR works but there is a huge performance hit. // if ( !settings.keep_meshes)
{
for (size_t i = 0; i < meshes.size(); ++i)
{
Mesh& mesh = meshes[i];
if (mesh.node)
{
NodeInfo& ni = nodes[mesh.node - data->nodes];
// we transform all non-skinned non-animated meshes to world space
// this makes sure that quantization doesn't introduce gaps if the original scene was watertight
if (!ni.animated && !mesh.skin && mesh.targets == 0 && !settings.keep_meshes)
{
transformMesh(mesh, mesh.node);
mesh.node = 0;
}
// skinned and animated meshes will be anchored to the same node that they used to be in
// for animated meshes, this is important since they need to be transformed by the same animation
// for skinned meshes, in theory this isn't important since the transform of the skinned node doesn't matter; in practice this affects generated bounding box in three.js
}
}
mergeMeshes(meshes);
// }
void mergeMeshes(std::vector<Mesh>& meshes)
{
for (size_t i = 0; i < meshes.size(); ++i)
{
Mesh& mesh = meshes[i];
if (mesh.node && mesh.node->name) {
continue;
}
for (size_t j = 0; j < i; ++j)
{
Mesh& target = meshes[j];
if (target.node && target.node->name) {
continue;
}
if (target.indices.size() && canMerge(mesh, target))
{
mergeMeshes(target, mesh);
mesh.streams.clear();
mesh.indices.clear();
break;
}
}
}
} But with this change it is possible to merge all meshes without unnamed nodes and the same parent Original glb file size ~ 5.8MB |
Right, I didn't want to use the fact that the nodes are named or not, but it helps to know that in your case the penalty is significant - this means we need to treat only named nodes as unmergeable. The issue is that for the usecase that @Shimmen has merging based on the node name may be dangerous. @Shimmen, in your case is the application free to change materials on any meshes? Or do they also have to be discoverable through named nodes? |
@demike By the way, are you able to share the model that has these results? It looks like models I have now mostly don't suffer severely from the lack of mesh merging, so that would help. Alternatively, if you can show the output of gltfpack when ran with |
The model is exported from siemens nx and converted with three.js -km (your pm): -km (merge unnamed, my modification) (I first remove duplicate materials): without -km (first remove duplicate materials first): without -km (without removing duplicate materials): |
By the way: {
"code": "MESH_PRIMITIVE_ATTRIBUTES_ACCESSOR_INVALID_FORMAT",
"message": "Invalid accessor format '{VEC3, UNSIGNED_SHORT}' for this attribute semantic. Must be one of ('{VEC3, FLOAT}').",
"severity": 0,
"pointer": "/meshes/0/primitives/0/attributes/POSITION"
},
{
"code": "MESH_PRIMITIVE_ATTRIBUTES_ACCESSOR_INVALID_FORMAT",
"message": "Invalid accessor format '{VEC3, BYTE normalized}' for this attribute semantic. Must be one of ('{VEC3, FLOAT}').",
"severity": 0,
"pointer": "/meshes/0/primitives/0/attributes/NORMAL"
},
... |
Right, ok - that makes sense; with lots of tiny meshes merging is essential. The validator doesn’t recognize the extension used; the extension standardization hasn’t happened yet. |
Often glTF models have many materials that are equivalent. Preserving these materials wastes space due to extra material specification, increases the rendering time by increasing the amount of state setup and also reduces the efficiency of mesh merging. This change merges materials by retargeting all meshes to use the first equivalent material in the set, and then removing materials that aren't referenced anymore from the output. As a result, in some cases the material count is reduced dramatically; for example for Buggy.gltf before this change we had 148 output primitives and 148 materials (and 90 KB of JSON data), and after this change we get 10 output primitives/materials and 7 KB of JSON data. Contributes to #48 (indirectly)
@demike Let's try this one more time? :) I've committed material merging to master - thanks for bringing this to my attention, this ends up being beneficial on some models in my test set - and added a PR #51 that implements I don't have good test data for this so I wasn't able to test |
Only named nodes show up in the tree view of the application and can therefore be modified. In the files I'm studying all nodes seem to have a name, though. Now regarding 0ccd614, it seems like it did the trick, and also no assertions are triggered. However, I now get some other crash in |
@zeux, I tried with Another example NX-export This will actually make NX models usable in the browser (no more 300MB JT2Go three.js models)!!! |
And of course the resulting node hierarchy is also the same :) ! 👍 |
I might have encountered a problem: at BufferGeometry.computeBoundingSphere :THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values. I use three.js 106 for the test and picking is not working any more because of the bounderySphere error |
@demike Ok fantastic - I'll merge the PR. Regarding three.js - yeah this is a bug in three.js, and a bug fix was just submitted yesterday (mrdoob/three.js#16989). Please use GLTFLoader.js from three.js master for the time being - the fix will be released in r107. |
For any other problems please feel free to create additional issues. @Shimmen feel free to create a separate issue for the crash - I don't quite see how views.size() can crash but if you post a callstack with a register dump and disassembly view then maybe we can figure this out. |
@zeux We decided to use the optimization API directly instead of using gltfpack, since it suited our use case better, and everything works fine there. If you would like to pursue this further I can try to help, but otherwise I will let it go. I'm quite sure by now that the files I'm testing with are weird, so it might never happen for other files.. |
@demike Do the files that you need to optimize have unique material names? I'm investigating options for preserving material names; I'd like to support this in the "keep named" mode where a named material would not be merged with other materials, but I'm concerned that this change would make your glTF files less optimal - if that's the case I will need to add separate options to do that. |
Sorry for the late reply, I was on holiday. |
Seams like all the materials have unique names |
Is there some option to keep the "body" nodes in the image below:
![image](https://user-images.githubusercontent.com/1626922/61430908-e3ad8b00-a92b-11e9-86fc-31f00033075d.png)
because running gltfpack without parameters results in a flat node list:
this makes it impossible to move the bodies
The text was updated successfully, but these errors were encountered: