I would like to use this issue to keep track of the GLTF2 exporter features. I've copied the initial list of features discussed on the PR https://github.com/mrdoob/three.js/pull/11917 and I'll keep updating the list as we progress in the implementation.
trs
to export TRS instead of matrixinput
:truncateDrawRange
: force exporting just the attribute values defined by drawRange
:userData
in extras
?material.wireframe === true
pbrMetallicRoughness
for MeshStandardMaterial
baseColorFactor
metallicFactor
roughnessFactor
baseColorTexture
: It's supported (material.map
) but the texCoord
is always set to 0.doubleSided
uri
using map.image.src
uri
base64bufferView
flipY
images[ ] Accessors
bufferView
for the same componentType instead of creating a new one for each attribute (WIP @takahirox)sparse
?bufferView
byteOffset
: Currently it's using 0 always as I'm creating a new bufferView for each accessor.componentType
count
max
min
type
:SCALAR
VEC2
VEC3
VEC4
[ ] BufferViews: Currently I'm creating a new bufferView
for each Accessor
, this should be fixed to use just one for these attributes that share the same componentType
buffer
byteOffset
byteLength
byteStride
target
stats
option to log the number of items exported and maybe some timing?Current demo:
Exported gltf loaded on @donmccurdy 's gltf viewer
GLTF: https://gist.github.com/fernandojsg/0e86638d81839708bcbb78ab67142640
This is looking really good!
By the way, we are planning to remove THREE.GLTFLoader
and rename GLTF2Loader
βGLTFLoader
sometime soon*. Might be a good idea to rename the exporter as GLTFExporter before r87 lands, to avoid any confusion and so there won't be a name change required between releases. Oops, I missed that you already named it that way.. carry on! π
* @mrdoob, any preference on when that should happen? IMO we could do this now, unless we want to keep GLTFLoader
in r87 with just a deprecation warning, and remove it in r88?
I think the sooner the better. As long as the new GLTFLoader
is able to detect 1.0 and warn the user that we only support 2.0+.
IIRC we can detect by seeing asset
as I mentioned before.
IIRC we can detect by seeing asset as I mentioned before.
Cool! But I've found a minor bug. I'm making PR now. Let's merge before we rename.
Can we specify the items that someone is working on in the checklist?
@takahirox sure! people could just write comments here and I could update the list and point to a PR if there's something going on already
The next thing I'll be working is on the textures, to convert them to base64 instead of using just the url
Thanks! I wanna help making glTF exporter. I'm looking into what I can help in the checklist...
BTW have you purposely let two variables WEBGL_CONSTANTS
and THREE_TO_WEBGL
global?
@takahirox cool!
Regarding the two variables, this is something I'm going to address in the following PR to make it part of the WebGLUtils
and just import it. It doesn't make sense that each one that needs these constants need to redefine them again every time.
@takahirox btw feel free to propose new items to the list of course! ;)
@fernandojsg Sure! About the variables, I wanted to propose to move them to somewhere if they're purposely declared as global so it's nice to know that you do.
I wanna work on shared buffer view.
BufferViews: Currently I'm creating a new bufferView for each Accessor, this should be fixed to use just one for these attributes that share the same componentType
The reason why one for the attributes that share the same componentType, not one for all the attributes, is for data alignment, correct?
https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment
Cool, I've just added you to the list π Yep, basically you want to share the same buffer view for component with the same type, for example if you have position and normal you'll have two VEC3 accessors but they'll point to the same bufferview. That could be a great starting point ;)
I meant, the reason why we don't let buffer view be shared among different componentType (ex: float and short) is to keep good data alignment, correct?
I believe you can store in the same buffer view different component types as long as they've the same target
, for example normal (Vec3)
, position (Vec3)
and uv (Vec2)
could be in the same buffer view but indices
not. @donmccurdy could you confirm it?
Yep, agreed. And as this glTF specification mentions
https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment
The offset of an accessor into a bufferView (i.e., accessor.byteOffset) and the offset of an accessor into a buffer (i.e., accessor.byteOffset + bufferView.byteOffset) must be a multiple of the size of the accessor's component type.
It's a good idea that we separate buffer views between the different componentType(=data type like float and short, not vec2 or vec3) for the simplicity. If we separate them between different data length componentType, it'd be more optimized.
BTW is there any special reasons why the current exporter supports only accessor.componentType
float, uint, and ushort? glTF 2.0 can handle char, uchar, and short, in addition to them.
https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#accessorcomponenttype-white_check_mark
@takahirox not really, I just defined these by now because are the ones used for the type of attributes we support right now (positions, normals, colors, uvs, indices..).
The next step I'm working on is the textures so there we'll need others like uchar
for example
OK, so I first will work on the accessor.componentType
s unless you already started to impl.
Almost ready but my PR should conflict with #11978.
So I send mine once #11978 is merged and I fix the conflict.
Would you add animation to the list?
@takahirox sure, it could be great to add animation. I just didn't add it because I wasn't familiar enough with the current state of the animation features on three.js, but if you feel like taking over it, it would be great ;)
Do you plan to support BufferGeometry groups?
Do the GLTF specs cover that or would it result in creating a new Mesh for every group?
This must also take care of, the material property of a Mesh being an array of materials.
@marcatec The glTF spec does have a "mesh" vs. "primitive" distinction that would allow you to create BufferGeometry groups that could each reference a different material. Currently THREE.GLTFLoader does not optimize loading primitives β it creates separate meshes β but that could be implemented.
Great work, great list and good to know there is already so much support on the format! Also works very well together with gltf blender exporter too. Can't wait for lights support! Keep up the great work.
I concur, great work!
Are there plans to add support for other materials apart from StandardMaterial?
Thanks!
@homerjam any material properties shared with MeshStandardMaterial will be preserved β so for example, a MeshPhongMaterial using map
and normalMap
would export with those textures intact, but when you import it back to three.js it will be a MeshStandardMaterial. The exporter currently does a naΓ―ve conversion to PBR for this.
Round-trip support (export Phong from GLTFExporter, load Phong from GLTFLoader) will require in-progress work on the glTF format: https://github.com/KhronosGroup/glTF/pull/1150
baseColorTexture
: It's supported (material.map) but the texCoord is always set to 0
@fernandojsg could you clarify what is missing here? Since .map
is always the first UV set in three.js, this sounds like the correct way to represent that in glTF?
Also a heads up, I crossed out three items on the list. Reasoning below:
By exporting to GLB from the editor I've noticed that alphaMap
, roughnessMap
and metalnessMap
don't get exported.
In #13397 I said normalMap
neither gets exported but seems like I was wrong.
By exporting to GLB from the editor I've noticed that alphaMap, roughnessMap and metalnessMap don't get exported.
I'll work on this today unless anyone already started.
@donmccurdy
sparse accessors
I think this is best left to post-export optimization, like mattdesl's script.
Feeling like letting exporter support sparse accessors for morph. I'll try later.
@takahirox cool! go ahead!
I don't think alphaMap
is supported in glTF 2.0.
https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#material
Yeah, I feared that.... What about metalnessMap
and roughnessMap
?
I'm working on them now!
Regarding image formats. glTF 2.0 supports only .png and .jpg as external image files. I'm considering how to handle non supported image format files (eg: .bmp) on non embedImages
mode.
I prefer 1. Any thoughts?
Wow, really appreciating the works of you guys.
Hope that Multi-material meshes
will be implemented asap because most of 3D models are using Multi-materials.
- Convert to .png or .jpg and embed
- Don't care. Export as original image files
- Don't export
I vote for 3 and logging a warning in the console.
Hope that Multi-material meshes will be implemented asap because most of 3D models are using Multi-materials.
Agreed, for me this is the number one issue preventing use of the exporter.
Hope that Multi-material meshes will be implemented asap because most of 3D models are using Multi-materials.
As I said in the other thread, I'm working on it.
- Convert to .png or .jpg and embed
- Don't care. Export as original image files
- Don't export
I vote for 3 and logging a warning in the console
Yeah, I came to think 3. would be simpler and not confusing to users. Getting embedded image on non emedImages
mode would be a bit confusing.
The reason why I prefer 1. was for converting from other formats to glTF. Some (or many) of other formats don't have image format limitation.
The exporter converts on embedImages
mode. So adding "use embedImages option if you wanna convert" to console warning would be good, I'm thinking.
I'd go also for 3 too. As converting from other formats could be tedious, and you'll need anyway to prioritize some formats against others. Probably it's worth to do 3 right now and wait to see if gltf add support to new texture formats like ktx or so and we could revisit the implementation.
As discussed in https://github.com/mrdoob/three.js/pull/13415#issuecomment-369022383, it would be nice if the exporter was able to compose the ambientRoughnessMetalness
texture for the user. Probably better to place that code in ImageUtils
though.
I've updated the checklist with the latest changes. I've added @takahirox to the multimaterial
item, and I'll take myself the images compose task.
I've added also material_unlit extension, although is still in draft I believe it's quite close to release and won't change that much (/cc @donmccurdy)
Hope that Multi-material meshes will be implemented asap because most of 3D models are using Multi-materials.
As I said in the other thread, I'm working on it.
WIP... (Miku has multi-material)
About non-supported image formats, ok let's go for 3.
@takahirox looking good! π
BTW, are you folks interested in zip archive support? .glTF + external .bin and textures would be fitting to other authoring tools (maybe), but hard to do with non-archive. So zip archive would be necessary. And we can reduce the exported file size.
I want it and tried in my local branch before, I can share later if you're interested.
Isn't that pretty much the same as gzipping a glb?
.glTF + external .bin and textures would be fitting to other authoring tools (maybe)
I hope authoring tools won't require separate files; we're encouraging everyone to use GLB by default. But it's easier to hand-edit an image if it isn't embedded, for sure.
No strong opinion about whether we want to put that functionality into THREE.GLTFExporter
directly... but I almost think that we should not have too many options that could instead be post-optimizations on the glTF. Another example, Draco is sort of complicated and requires several external files, so maybe it's better to let specialized glTF-to-glTF tools do that optimization? And similarly we could make a glb-unpacker (opposite of http://glb-packer.glitch.me/) to help people unpack files from GLB to ZIP if we find out that people need it.
From https://github.com/KhronosGroup/glTF/issues/1256 β
... the original intent of gltf-pipeline - and really glTF in general - make exporters as simple as possible and push the optimizations to a common tool. It will also, of course, help with fragmentation.
that said, no glb-unpacker exists yet that I know of...
@mrdoob
I wanted texture images to be external, rather than .glTF vs .glb.
@donmccurdy
I followed up https://github.com/KhronosGroup/glTF/issues/1117 discussion and agree with encouraging .glb + embedded files and pipeline approach now. One .glb is good for data transmission especially for web and pipeline approach can keep exporters and tools simple and reusable. (I like UNIX/Linux command pipeline approach, too!)
So I don't think the exporter needs zip archive support now. And maybe it also doesn't need sparse accessor and draco support because of the same reason.
Regarding glb-unpacker, I may be gonna make it in my free time. I think some artists like .glTF + external files because they're readable without any glTF specific tools. And sometimes external files can reduce loading time due to parallel loading file so it could be used for optimization purpose.
Regarding pipeline/optimization tools, I wanna note that we don't wanna transfer huge data over network. Users wanna optimize/compress before ~transforming~ transferring data. So glTF optimization web service sometimes doesn't work well for huge data because user needs to send huge file to the server.
Plus, for Three.js and other JavaScript browser based engines, we'd be happy if we have glTF optimization tools which run on browser. We can optimize/compress before data is passed to users. Without them users need to manually download exported data and then pass it to pipeline tools because of browser limitations.
From this point of view, I want a tool to be able to run anywhere, on browser, on server, CUI, and so on, to have it more common and reusable. We don't wanna make the same purpose tools twice or more for different platforms. So node.js based tool would be good? Does glTF (pipeline) team have any suggestions? (Maybe this discussion should be done in glTF, not here.)
Just in case, in GLTFLoader
binary support is implemented as extension but .glb is in core spec of glTF 2.0, correct?
Just in case, in GLTFLoader binary support is implemented as extension but .glb is in core spec of glTF 2.0, correct?
Yeah, it was an extension in glTF 1.0 and I just never relocated or renamed that code after it became part of core glTF 2.0 spec.
From this point of view, I want a [optimization tools] to be able to run anywhere, on browser, on server, CUI, and so on, to have it more common and reusable. So node.js based tool would be good? Does glTF (pipeline) team have any suggestions? (Maybe this discussion should be done in glTF, not here.)
It would be worth asking about the glTF-Pipeline roadmap... not sure how general they want glTF-Pipeline to be, or if it is mainly for Cesium uses, or if it's just an issue of limited developer time. Also glTF-Toolkit looks relevant, but (currently) only runs on Windows. I personally like Node.js but C++ or Rust could be reasonable choices with compilation to WASM.
Oh, I was missing the compilation to WASM. Specifying some recommended dev platforms would be nice to optimization devs. So I'd propose to an appropriate thread.
I agree with @donmccurdy as I feel these optimizations on the pipeline could live in a different repo than three.js, so everyone could benefit from them. I still need to check the differences between the gltf pipeline and toolkit tools, but I would expect this kind of features to be included on them.
I also agree that as long as we'll have a WASM it wouldn't really matter the source language, but it's also true that if it's written in node.js probably many of the community around the 3d web engines could help improving them as right now are the main target for this file format anyway.
I'm not sure I understand about "optimizing before transforming" ... there are several types of transformations a pipeline might do on a model, and optimizations are probably the most common type of transformation?
Agreed beyond that. Good to have low level, focused tools that can be used to build other tools or plugged into a more user-friendly GUI.
Oops, it's typo. Not transforming but transferring. I meant, most users wanna optimize/compress before sending data over network. I've updated the posts to have them clearer.
Hi guys
I'm using the THREE.js GLTF Exporter to export an entire aframe scene as a gltf object.
How can I get the a-animation tags defined on aframe to be a part of the animations in the gltf object ?
@donmccurdy @fernandojsg @mrdoob
Hi @siddhartpai β THREE.GLTFExporter
only converts THREE.AnimationClip
objects to glTF animations, whereas A-Frame's animation system uses TweenJS. So currently this isn't possible. You may want to open an issue on A-Frame or the A-Frame Inspector, which also use GLTFExporter
, to request it as a future feature.
Multi-material support #13536
I've just noticed that the validator throws an error on every normal element on a bufferview that is not normalized. eg If I stored uninitialized values like [0,0,0] it will throw that error.
As it's a error and not a warning/notice I see it's sensitive to fix. What do you think about ensure the normal bufferview elements are normalized? Even so, for values that can't be normalized such as [0,0,0], should we use a valid unit vector? /cc @donmccurdy
Seems like NORMAL
should be normalized.
https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#meshes
NORMAL | "VEC3" | 5126Β (FLOAT) | Normalized XYZ vertex normals
Agreed with ensuring because Three.js normal doesn't have such a limitation.
Yep, but what to do when you don't have an actual normal, like an unused value of [0,0,0], just create a valid one and that's all right? let's say [1,0,0]. So we should modify the bufferview code to detect that we're parsing a normal attribute and normalize each one before saving it to the dataview.
what to do when you don't have an actual normal, like an unused value of [0,0,0]
Hm.... replacing with a valid one and displaying warning?
So we should modify the bufferview code to detect that we're parsing a normal attribute and normalize each one before saving it to the dataview.
I prefer doing that in processMesh()
because it'd be simpler, like
var originalNormal = geometry.attributes.normal;
if ( hasNonNormalizedValues( originalNormal ) ) {
geometry.attributes.normal = createNormalizedAttribute( originalNormal );
}
processAccessorHere();
geometry.attributes.normal = originalNormal;
If we do that in processBufferView()
, the code would become a bit complex because we need to care if data is shared among different attributes, for example position and normal. (I know it's very rare use case but Three.js doesn't restrict.)
Yep I like that approach, I was afraid to modify the normals after exporting, but it should be ok if we save a reference put them back again after finishing. :+1: Would you mind pushing a PR with these changes? or want me to do it?
OK, I will. (Are you in hurry to fix that?)
@takahirox cool, thanks! but no rush I was just reviewing the state of the exporter ^_^
OK, then I'll do ~tomorrow~ this week.
Right, glTF does not allow for omitting normals on particular vertices but not others in a single primitive. We'll need to provide some sort of value, strip these vertices, or throw an error.
I would prefer to make things easier for the user so my vote is for creating a new normals array normalizing them and adding a (0,1,0) value for the empty ones.
Seems good. If it's slow for large models we might want a checkNormals
option or something like that, so users who don't need this can opt out, rather than scanning every vertex.
Yep I was just about to write the same! :D
If it's slow for large models we might want a checkNormals option or something like that, so users who don't need this can opt out, rather than scanning every vertex.
I'm gonna make PR without that option first. Let's add when/if necessary. Personally I suppose this check doesn't slow much.
I'm gonna make PR without that option first. Let's add when/if necessary. Personally I suppose this check doesn't slow much.
I was normalizing the whole buffers when loading each stroke on a-painter and it quite slow
Even if just checking if they're normalized?
@takahirox you will need to compute the length anyway so I guess it won't change that much
Hm, ok. I'll evaluate with the PR.
It is the first GLTFExporter feature we've introduced that does any computation with each vertex (except relative/absolute morph target conversion) so yeah potentially slower.. either way though.
Great work! IMHO should be merged into core three.js, rather than in "examples".
Would love to see KHR_lights_punctual
support!
PR https://github.com/mrdoob/three.js/pull/15519 adds KHR_lights_punctual. :)
I think this issue can probably be closed β the remaining items are less critical convenience or optimization, and can be tracked elsewhere:
Hey guys, does anyone know how can I export a custom shaped mesh by morph changes applying the morphs and removing it from the final object?
Like this question https://stackoverflow.com/questions/57423471/how-to-export-morph-changed-meshes-from-threejs-application
Thanks in advance!
@vini-guerrero Please use the forums (https://discourse.threejs.org/) or Stack Overflow for help, rather than GitHub issues.
Most helpful comment
As I said in the other thread, I'm working on it.