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
Add gltf-model component and system. #2333
Changes from all commits
c2b5462
eb75294
e2ba0d3
4604c6f
7feb873
8ba7ebd
e4f239e
7b7f501
6beb60d
b2fc6de
53515cb
79ddddb
1979fed
3c3a3bd
1b16020
456cdaa
05a0f03
892a854
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
--- | ||
title: gltf-model | ||
type: components | ||
layout: docs | ||
parent_section: components | ||
--- | ||
|
||
[about-gltf]: https://www.khronos.org/gltf | ||
|
||
[glTF][about-gltf] (GL Transmission Format) is an open project by Khronos providing a common, extensible format for 3D assets that is both efficient and highly interoperable with modern web technologies. | ||
|
||
The `gltf-model` component loads a 3D model using a glTF (.gltf or .glb) file. | ||
|
||
## Why use glTF? | ||
|
||
[obj-model]: ./obj-model.md | ||
[collada-model]: ./collada-model.md | ||
|
||
In comparison to the older [OBJ][obj-model] format, which supports only vertices, normals, texture coords, and basic materials, glTF provides a more powerful set of features. In addition to all of the above, glTF offers: | ||
|
||
- Hierarchical objects | ||
- Scene information (light sources, cameras) | ||
- Skeletal structure and animation | ||
- More robust materials and shaders | ||
|
||
For simple models with no animation, OBJ is nevertheless a common and reliable choice. | ||
|
||
In comparison to [COLLADA][collada-model], the supported features are very similar. However, because glTF focuses on providing a "transmission format" rather than an editor format, it is more interoperable with web technologies. By analogy, the .PSD (Adobe Photoshop) format is helpful for editing 2D images, but images are converted to .JPG for use on the web. In the same way, glTF is a simpler way of transmitting 3D assets while rendering the same result. | ||
|
||
In short, expect glTF models to work with A-Frame more reliably than COLLADA models. | ||
|
||
## Example | ||
|
||
Load a glTF model by pointing to an asset that specifies the `src` for a glTF file. | ||
|
||
```html | ||
<a-scene> | ||
<a-assets> | ||
<a-asset-item id="tree" src="/path/to/tree.gltf"></a-asset-item> | ||
</a-assets> | ||
|
||
<a-entity gltf-model="#tree"></a-entity> | ||
</a-scene> | ||
``` | ||
|
||
## Values | ||
|
||
| Type | Description | | ||
|----------|--------------------------------------| | ||
| selector | Selector to an `<a-asset-item>` | | ||
| string | `url()`-enclosed path to a glTF file | | ||
|
||
## Events | ||
|
||
| Event Name | Description | | ||
|--------------|--------------------------------------------| | ||
| model-loaded | glTF model has been loaded into the scene. | | ||
|
||
## Loading Inline | ||
|
||
Alternatively, load a glTF model by specifying the path directly within `url()`. This is less performant than using the asset management system. | ||
|
||
```html | ||
<a-entity gltf-model="url(/path/to/tree.gltf)"></a-entity> | ||
``` | ||
|
||
## More Resources | ||
|
||
The glTF format is fairly new, and few editors will export a `.gltf` file directly. Instead, various converters are available or in progress: | ||
|
||
[fbx-converter]: http://gltf.autodesk.io/ | ||
[collada-converter]: http://cesiumjs.org/convertmodel.html | ||
[obj-converter]: https://github.com/AnalyticalGraphicsInc/obj2gltf | ||
|
||
- [FBX → glTF][fbx-converter] - coming soon. | ||
- [COLLADA → glTF][collada-converter]. | ||
- [OBJ → glTF][obj-converter]. | ||
|
||
[spec]: https://github.com/KhronosGroup/glTF | ||
|
||
See the [official glTF specification][spec] for available features, community resources, and ways to contribute. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
--- | ||
title: <a-gltf-model> | ||
type: primitives | ||
layout: docs | ||
parent_section: primitives | ||
--- | ||
|
||
The glTF model primitive displays a 3D glTF model created from a 3D | ||
modeling program or downloaded from the web. | ||
|
||
## Example | ||
|
||
```html | ||
<a-scene> | ||
<a-assets> | ||
<a-asset-item id="tree" src="tree.gltf"> | ||
</a-assets> | ||
|
||
<!-- Using the asset management system. --> | ||
<a-gltf-model src="#tree"></a-gltf-model> | ||
|
||
<!-- Defining the URL inline. Not recommended but more comfortable for web developers. --> | ||
<a-gltf-model src="tree.gltf"></a-gltf-model> | ||
</a-scene> | ||
``` | ||
|
||
## Attribute | ||
|
||
[gltf]: ../components/gltf-model.md | ||
|
||
| Attribute | Component Mapping | Default Value | | ||
|-----------|------------------------|---------------| | ||
| src | [gltf-model][gltf].src | null | |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,24 +2,32 @@ | |
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Model</title> | ||
<meta name="description" content="Model - A-Frame"> | ||
<title>Models (glTF, OBJ, COLLADA)</title> | ||
<meta name="description" content="Models (glTF, OBJ, COLLADA) - A-Frame"> | ||
<script src="../../../dist/aframe-master.js"></script> | ||
</head> | ||
<body> | ||
<a-scene stats> | ||
<a-assets> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be cool to add text labels under each model for the model format. And the scene could use a better background There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could also add the different format types in the page title & meta description There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. scope creep alert 😉 Added the meta title/description, but I'm getting errors trying to do text.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is that on latest? We pushed some text patches switching to raw shader material. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the latest and greatest master, that warning has been eliminated by using RawShaderMaterial for the sdf and msdf text shaders. so... maybe needs rebase? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rebase did the trick. ✅ |
||
<a-asset-item id="crate-obj" src="../../assets/models/crate/crate.obj"></a-asset-item> | ||
<a-asset-item id="crate-mtl" src="../../assets/models/crate/crate.mtl"></a-asset-item> | ||
<a-asset-item id="brainstem" src="https://cdn.aframe.io/test-models/models/brainstem/BrainStem.gltf"></a-asset-item> | ||
<a-asset-item id="monster" src="monster/monster.dae"></a-asset-item> | ||
</a-assets> | ||
|
||
<a-entity position="0 0 -12"> | ||
<a-entity collada-model="#monster" material="color: green" scale="0.25 0.25 0.25" | ||
position="-10 0 1"></a-entity> | ||
<a-text value="COLLADA" color="#000000" position="-2 -2 6" scale="1.5 1.5 1.5"></a-text> | ||
|
||
<a-entity gltf-model="#brainstem" position="10 -1 5" scale="3 3 3"></a-entity> | ||
<a-text value="glTF" color="#000000" position="9.75 -2 6" scale="1.5 1.5 1.5"></a-text> | ||
|
||
<a-entity obj-model="obj: #crate-obj; mtl: #crate-mtl" position="5 0 5"></a-entity> | ||
<a-entity obj-model="obj: #crate-obj; mtl: #crate-mtl" position="5 2 5"></a-entity> | ||
<a-text value="OBJ" color="#000000" position="4.75 -2 6" scale="1.5 1.5 1.5"></a-text> | ||
|
||
<a-sky color="#FAFAFA"></a-sky> | ||
</a-entity> | ||
|
||
</a-scene> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
var registerComponent = require('../core/component').registerComponent; | ||
var THREE = require('../lib/three'); | ||
|
||
/** | ||
* glTF model loader. | ||
*/ | ||
module.exports.Component = registerComponent('gltf-model', { | ||
schema: {type: 'model'}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be multiprop to allow room for future props? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I slightly prefer multiprop, but can't actually think of any others we'd need. Maybe crossorigin. I'm expecting animation to be a separate component, but if not that would definitely need some properties. I've used There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alright, can just leave it as is |
||
|
||
init: function () { | ||
this.model = null; | ||
this.loader = new THREE.GLTFLoader(); | ||
}, | ||
|
||
update: function () { | ||
var self = this; | ||
var el = this.el; | ||
var src = this.data; | ||
|
||
if (!src) { return; } | ||
|
||
this.remove(); | ||
|
||
this.loader.load(src, function gltfLoaded (gltfModel) { | ||
self.model = gltfModel.scene; | ||
self.system.registerModel(self.model); | ||
el.setObject3D('mesh', self.model); | ||
el.emit('model-loaded', {format: 'gltf', model: self.model}); | ||
}); | ||
}, | ||
|
||
remove: function () { | ||
if (!this.model) { return; } | ||
this.el.removeObject3D('mesh'); | ||
this.system.unregisterModel(this.model); | ||
} | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,7 @@ | ||
var getMeshMixin = require('../getMeshMixin'); | ||
var registerPrimitive = require('../primitives').registerPrimitive; | ||
var utils = require('../../../utils/'); | ||
|
||
registerPrimitive('a-collada-model', utils.extendDeep({}, getMeshMixin(), { | ||
registerPrimitive('a-collada-model', { | ||
mappings: { | ||
src: 'collada-model' | ||
} | ||
})); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
var registerPrimitive = require('../primitives').registerPrimitive; | ||
|
||
registerPrimitive('a-gltf-model', { | ||
mappings: { | ||
src: 'gltf-model' | ||
} | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
var registerSystem = require('../core/system').registerSystem; | ||
var THREE = require('../lib/three'); | ||
|
||
/** | ||
* glTF model system. | ||
*/ | ||
module.exports.System = registerSystem('gltf-model', { | ||
init: function () { | ||
this.models = []; | ||
}, | ||
|
||
/** | ||
* Updates shaders for all glTF models in the system. | ||
*/ | ||
tick: function () { | ||
var sceneEl = this.sceneEl; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we could test this code too There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
if (sceneEl.hasLoaded && this.models.length) { | ||
THREE.GLTFLoader.Shaders.update(sceneEl.object3D, sceneEl.camera); | ||
} | ||
}, | ||
|
||
/** | ||
* Registers a glTF asset. | ||
* @param {object} gltf Asset containing a scene and (optional) animations and cameras. | ||
*/ | ||
registerModel: function (gltf) { | ||
this.models.push(gltf); | ||
}, | ||
|
||
/** | ||
* Unregisters a glTF asset. | ||
* @param {object} gltf Asset containing a scene and (optional) animations and cameras. | ||
*/ | ||
unregisterModel: function (gltf) { | ||
var models = this.models; | ||
var index = models.indexOf(gltf); | ||
if (index >= 0) { | ||
models.splice(index, 1); | ||
} | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add sections on playing animations until we get an API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but the answer is "write a component that looks very much like
animation-mixer
", so IMO it would be better to leave that for another PR.