glTF Exporter in three.js and A-Frame

A brief introduction

When creating WebVR experiences developers usually face a common problem: it’s hard to find assets other than just basic primitives. There’re several 3D packages to generate custom objects and scenes that use custom file formats, and although they give you the option to export to a common file format like Collada or OBJ, each exporter saves the information in a slightly different way. Because of these differences, when we try to import these files in the 3D engine that we are using, we often find that the result that we see on the screen is quite different from what we created initially.

The Khronos Group created the glTF 3d file format to have an open, application agnostic and well defined structure that can be imported and exported in a consistent way. The resulting file is smaller than most of the availables alternatives, it’s also optimized for real time applications to be fast to read since we don’t need to consolidate the data. Once we’ve read the buffers we can push them directly to the GPU.
The main features that glTF provides and a 3D file format comparison can be found in this article by Juan Linietsky

A few months ago feiss wrote an introduction to the glTF workflow he used to create the assets for our A-Saturday-Night demo.
Many things have improved since then. The glTF blender exporter is already stable and has glTF 2.0 support. The same goes for three.js and A-Frame: both have a much better support for 2.0.
Now, most of the pain he experienced by converting from Blender to collada and then to glTF has gone, and we can export directly to glTF from Blender.

glTF is here to stay and its support has grown widely in the last months, being available in most of the 3D web engines and applications out there like three.js, babylonjs, cesium, sketchfab, blocks ...
The following video from the first glTF BOF (held on Siggraph this year) illustrates how the community has embraced the format:


glTF Exporter on the web

One of the most requested features for A-Painter has been the ability to export to some standard format so people could reuse the drawing as an asset or placeholder in 3D content creation software (3ds Max, Maya,...) or engines like Unity or Unreal.
I started playing with the idea of exporting to OBJ but lot of changes were required on the original three.js exporter because of the lack of triangle_strip fully support so I left it in standby.

After seeing all the industry support and adoption of glTF at Siggraph 2017 I decided to give it a second try.

The work was much easier than expected thanks to the nice THREE.js / A-Frame loaders that Don McCurdy and Takahiro have been driving. I thought it would be great to export content created directly on the web to glTF, and it would serve as a great excuse to go deep on the spec and understand it better.

glTF Exporter in three.js

Thanks to the great glTF spec documentation and examples, I got a glTF exporter working pretty fast.

The first version of the exporter has already landed in r87 is still in early stage and under development. There’s an open issue If you want to get involved and follow the conversations about the missing features: https://github.com/mrdoob/three.js/issues/11951

API

The API follows the same structure of the existing exporters available in three.js:

  • Create an instance of THREE.GLTFExporter.
  • Call parse with the objects or scene that you want to export.
  • Get the result in a callback and use it as you want.
var gltfExporter = new THREE.GLTFExporter();  
gltfExporter.parse( input, function( result ) {

  var output = JSON.stringify( result, null, 2 );
  console.log( output );
  downloadJSON( output, 'scene.gltf' );

}, options );

More detailed and updated information for the API can be found on the three.js docs

Together with the exporter I created a simple example in three.js trying to combine the different type of primitives, helpers, rendering modes and materials and exposing all the options the exporter has so we could use it as a testing scene through the development

Simple three.js example

Integration in three.js editor

The integration with the three.js editor was pretty straightforward and I think it’s one of the most useful features, since the editor supports importing plenty of 3d formats, it can be used an an advanced converter from these formats to glTF, allowing the user to delete unneeded data, tweak parameters, modify materials etc before exporting.

Exporting to glTF from three.js editor


glTF Exporter on A-Frame

Please note that as three.js v87 is required to use the GLTFExporter currently just master branch of A-Frame is supported, and the first stable version compatible will be 0.7.0 to be released later this month.

Integration with A-Frame inspector

After the successful integration with three.js’ editor the next step was to integrate the same functionality into the A-Frame inspector.
I’ve added two options to export the content to GLTF:

  • Clicking on the export icon on the scenegraph will export the whole scene to glTF

Export scene

  • Clicking on the entity’s attributes panel will export the selected entity to glTF

Export entity

Exporter component in A-Frame

Last but not least, I’ve created an A-Frame component so users could export scenes and entities programmatically.

The API is quite simple, just call the export function from the gltf-exporter system:

sceneEl.systems['gltf-exporter'].export(input, options);  

The function accepts severals different input values: None (export the whole scene), one entity, an array of entities, or a NodeList (eg: the result from a querySelectorAll)

The options accepted are the same as the original three.js function.

A-Painter exporter

The whole history wouldn’t be complete if the initial issue that made me go into glTF wasn’t satisfied :) After all the previous work described above it was trivial to add support to export to gltf in A-Painter.

  • Include the aframe-gltf-exporter-component script:
<script src="https://unpkg.com/aframe-gltf-exporter-component/dist/aframe-gltf-exporter-component.min.js"></script>  
  • Attach the component to a-scene:
<a-scene gltf-exporter/>  
  • And finally register a shortcut (g) to save the current drawing to glTF:
if (event.keyCode === 71) {  
  // Export to GTF (g)
  var drawing = document.querySelector('.a-drawing');
  self.sceneEl.systems['gltf-exporter'].export(drawing);
}

Exporting A-Painter robot to glTF


Extra: Exporter bookmarklet

While developing the exporter I found very useful creating a bookmarklet to inject the exporter code on every A-Frame or three.js page. This way I could just export the whole scene by clicking on it.
If A-FRAME is defined it will export AFRAME.scenes[0] as is the default scene loaded. If not, it will try to look for the global variable scene that is the most commonly used in three.js examples.
It is not bulletproof so you may need to do some changes if it doesn’t work on your app, probably by looking for something else than scene.

To use it you should create a new bookmark on your browser and paste the following code on the URL input box:

Bookmarklet setup in firefox and chrome

What’s next?

From Mozilla we are committed to help improving the glTF specification and its ecosystem.
glTF will keep evolving and many interesting features are being proposed on the roadmap discussion. If you have any suggestion don't hesitate to comment there, since all proposals are being discussed and taken into account.

As I stated before the glTF exporter is still in an early stage but it’s being actively developed so please feel free to jump into the discussion to prioritize on new features.

Finally: wouldn't it be great to see more content creation tools on the web with glTF support so you don't depend on a desktop application to generate your assets?.