Reputation: 2596
I'm using an image as a texture several times, once via the material component, another time in a custom component. In the latter I'm using THREE.TextureLoader()
which cause the application to load the image twice. I bet there's another way.
HTML
<!-- Assets -->
<a-assets>
<img id="my-map" src="path/to/map.jpg">
<a-asset-item id="my-model" src=path/to/model.gltf""></a-asset-item>
</a-assets>
<!-- Entities -->
<a-box material="src: #my-map">
<a-entity gltf-model="src: #my-model" custom-component="mymap: #my-map">
JS
// custom-component extract
schema: { mymap: { type: 'map' } }
init: function()
{
let mesh = this.el.getObject3D('mesh')
mesh.traverse( function( child )
{
if ( child.isMesh )
{
let TextureLoader = new THREE.TextureLoader()
let mymap = TextureLoader.load( data.mymap )
child.material = new THREE.MeshPhongMaterial({ map: mymap })
child.material.needsUpdate = true;
}
})
}
How can I use the same image asset in the custom component without loading it twice?
Upvotes: 2
Views: 1265
Reputation: 2596
After some research digging in ThreeJs code I've found that TextureLoader
relies on ImageLoader
(see here) which, before loading a new image, it looks into THREE.Cache
to see if the image has already been loaded (see here).
Loading images as img
in AFrame doesn't store them in THREE.Cache
therefore the image was loaded twice. But if you load the image as a-asset-item
it does.
So there is no need to change anything in javascript. Just use a-asset-item
instead of img
.
For more info see AFrame documentation
Upvotes: 1
Reputation: 28482
You're using mesh.traverse()
which calls your function once per child of mesh
. If you have two children in your mesh, it'll call TextureLoader.load()
twice. Simply take the load call out of traverse()
, and you should see the image loaded just once.
let mesh = this.el.getObject3D('mesh')
let TextureLoader = new THREE.TextureLoader()
let mymap = TextureLoader.load( data.mymap )
mesh.traverse( function( child )
{
if ( child.isMesh )
{
child.material = new THREE.MeshPhongMaterial({ map: mymap })
child.material.needsUpdate = true;
}
})
Upvotes: 1