在javascript中使用A-frame img资产

时间:2017-06-30 16:25:41

标签: javascript three.js aframe

我多次使用图像作为纹理,一次通过material组件,另一次使用自定义组件。在后者我使用THREE.TextureLoader()导致应用程序加载图像两次。我打赌还有另一种方式。

现状

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;
        }
    })
}

问题

如何在自定义组件中使用相同的图像资源而不加载两次?

2 个答案:

答案 0 :(得分:1)

您正在使用mesh.traverse(),每个mesh的孩子都会调用您的函数一次。如果你的网格中有两个孩子,它会调用TextureLoader.load()两次。只需从traverse()中取出加载调用,您就会看到只加载一次图像。

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;
    }
})

答案 1 :(得分:0)

经过一些研究挖掘ThreeJs代码后,我发现TextureLoader依赖于ImageLoader(请参阅here),在加载新图片之前,它会查看THREE.Cache查看图片是否已加载(参见here)。

在AFrame中将图片加载为img不会将其存储在THREE.Cache中,因此图片已加载两次。但是,如果您将图片加载为a-asset-item,那么。

因此无需在javascript中更改任何内容。只需使用a-asset-item代替img即可。

有关详细信息,请参阅AFrame documentation