Skip to content
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: option to disable mesh consolidation? #151

Closed
kfarr opened this issue Jun 13, 2020 · 12 comments
Closed

gltfpack: option to disable mesh consolidation? #151

kfarr opened this issue Jun 13, 2020 · 12 comments
Labels

Comments

@kfarr
Copy link

kfarr commented Jun 13, 2020

I want to get the "goodness" of gltfpack while still allowing a web application to access some individual meshes that I've grouped for accessing individually in a web app.

Perhaps I'm doing something that should be done through separate gltf files, in other words maybe it doesn't make sense to have this option since it's a core feature of gltfpack?

I can provide code example if helpful but at least wanted to start the thread to see if this makes sense as an issue.

I'm using this component for A-Frame to access individual parts of the gltf:
https://github.com/supermedium/superframe/tree/master/components/gltf-part/

Versions:
A-Frame Version: 1.0.4 (Date 2020-05-07, Commit #9022b97e)
THREE Version (https://github.com/supermedium/three.js): ^0.115.1
installed gltfpack with npm install -g gltfpack, I think it's using commit hash 9e89bf3

@zeux
Copy link
Owner

zeux commented Jun 14, 2020

gltfpack has a command-line option -kn that preserves unconsolidated meshes attached to named nodes. The general idea there is that for an application to be able to retrieve nodes, they must be accessible using some stable identifier, which is a name in glTF.

@zeux zeux added the gltfpack label Jun 14, 2020
@kfarr
Copy link
Author

kfarr commented Jun 14, 2020

Perfect, I should have simply read the help text on the CLI. I was looking in gltf/readme.md assuming that was the complete set of options, sorry!

I tried using -kn and now my project no longer throws a console error saying the parts can't be found, however it's not rendering anything. It could be a gltf loader issue and it's an exercise for me to figure out since it does load fine in https://gltf-viewer.donmccurdy.com/ so it's probably an error in my gltf loader component or some other application logic.

I'll mark this ticket as closed since gltfpack already supports this feature.

@kfarr
Copy link
Author

kfarr commented Aug 2, 2020

Tried this again using -kn and -ke

I still can't seem to access meshes using their name after using gltfpack as I am able to prior to using gltfpack.

In my example file, the pre-gltfpack code has 3 nodes. The output has 6 nodes - 3 with meshes but no name, and then 3 with names but no meshes.

Original GLTF (left), gltfpack output (right)

image

@zeux
Copy link
Owner

zeux commented Aug 2, 2020

That's expected - the extra matrices are dequantization matrices. I'm not sure why you need to access the mesh specifically, since you should be able to perform transformation on the node - if you need to of course you can find the mesh in the subtree.

You can disable quantization by using -noq to get rid of those but that's not recommended as it will result in larger file sizes and larger memory consumption.

@kfarr
Copy link
Author

kfarr commented Aug 3, 2020

You're right -noq did fix that at the expense of a much larger file size.

The culprit must be in the way that the three.js / A-Frame gltf loader I'm using access the named mesh. Here is the function:
https://github.com/supermedium/superframe/blob/master/components/gltf-part/index.js#L56

@donmccurdy I hope you don't mind me tagging you but since you brought up gltfpack originally I don't feel as guilty -- do you mind weighing in if there is a way for the gltf-part A-Frame component to exhibit same behavior when a gltf file processed with gltfpack? See thread above for context.

@donmccurdy
Copy link
Contributor

It looks like after gltf-part clones a part of a model, it should be applying that part's matrixWorld to its matrix, or at least keeping the inherited scale. Otherwise that information is lost when the part is reattached somewhere else. There are two ways this could play out depending on the model, so a JSFiddle might help. I'd consider that a bug in gltf-part, or at least a limitation... maybe related to supermedium/superframe#115.

I'm not sure why you need to access the mesh specifically, since you should be able to perform transformation on the node...

This would be accessing the parsed result of GLTFLoader, where the node/mesh pair may be flattened to a THREE.Mesh. Would gltfpack always apply the the quantization transform to the mesh's parent node, or might it ever be further up the tree?

@zeux
Copy link
Owner

zeux commented Aug 3, 2020

Would gltfpack always apply the the quantization transform to the mesh's parent node, or might it ever be further up the tree?

The structure is always:
original_node -> dequant_node with a .mesh reference

@donmccurdy
Copy link
Contributor

In that case, @kfarr, you may find that the model already has names on parents or grandparents of the mesh that you can use with gltf-part, rather than the name of the mesh itself. If you're not sure of the final structure in three.js/A-Frame, try opening the model in https://gltf-viewer.donmccurdy.com/ and viewing the printed graph in the JS console.

@kfarr
Copy link
Author

kfarr commented Aug 27, 2020

Hi Don and Arseny, sorry for long delay. I have posted a full example of the failing attempt to load just a part of the gltf model by name when using gltfpack and a-frame "gltf-part" component loader:
https://kfarr.github.io/aframe-gltf-helpers/examples/09-meshopt-gltf-part.html

You can find docs, full source, and the sample models here:
https://github.com/kfarr/aframe-gltf-helpers

Would love any advice on my path to create a reasonable gltf pipeline web 3d projects with many assets if I'm going in the wrong direction here.

@donmccurdy
Copy link
Contributor

I'm not sure I can say why that workflow isn't giving the results you expect, but changing an object's parent without using its worldMatrix would not be safe. It will be necessary to call .updateMatrixWorld() at least once on the root of the glTF model, and then use its world position — rather than its local position — after parenting it to an object whose own parents are at the origin.

Translating all of that into the aframe scene graph is tricky, and converting BufferGeometry -> Geometry in the process makes me a bit nervous as well.

The approach in https://github.com/pmndrs/gltfjsx is an interesting option, they generate the declarative syntax for the model offline. But either approach feels a little hard to manage if/when your assets get more complicated. I think it would be easier to have every asset centered at the origin, and have some external source of truth for where they should be placed in the application?

If you want to script any of this offline, some other workflows might be possible with https://gltf-transform.donmccurdy.com "merge" and "dedup" commands, which would let you export individual assets, then merge them and deduplicate their textures.

@zeux
Copy link
Owner

zeux commented Sep 26, 2020

@kfarr Is that more or less how this should've looked?

image

(don't have an uncompressed glb to verify this)

I think the actual selection in your code is working fine, it's able to find the right mesh properly (although there's actually two meshes attached to the node with that name). But what doesn't work well is this code:

    if (this.data.buffer) {
      mesh.geometry = mesh.geometry.toNonIndexed();
      return mesh;
    }
    mesh.geometry = new THREE.Geometry().fromBufferGeometry(mesh.geometry);
    return mesh;
  }

If I comment out both assignments to mesh.geometry I get the screenshot above. I believe the issue is that toNonIndexed at least doesn't correctly support interleaved geometry, which quantized geometry extension uses in this case, so you get mangled geometry.

This is something I can fix in three.js but I'm wondering, why do you need to run this code in the first place?

@kfarr
Copy link
Author

kfarr commented Sep 27, 2020

Thanks Don and Zeux, yes that's the correct model display in your screenshot.

The goal here was to gltf-pack on an entire set of assets in one glb that share material to then load selectively for scenes that change. There are good workarounds already, such as just having them as separate files anyway, so I don't think any more work is warranted here but I highly appreciate your and Don's willingness to take a look. I think the best answer is simply to use separate files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants