【问题标题】:Use A-frame img assets inside javascript在 javascript 中使用 A-frame img 资产
【发布时间】:2017-12-04 16:25:42
【问题描述】:

我多次使用图像作为纹理,一次通过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;
        }
    })
}

问题

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

【问题讨论】:

标签: javascript three.js aframe


【解决方案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;
    }
})

【讨论】:

  • 错了。 TextureLoader 不会加载图像两次,因为它会缓存它。它通过this line 上的ImageLoader 来实现。问题略有不同:请参阅我的答案。
【解决方案2】:

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

在 AFrame 中将图像加载为 img 不会将它们存储在 THREE.Cache 中,因此图像被加载了两次。但是,如果您将图像加载为a-asset-item,则可以。

因此无需更改 javascript 中的任何内容。只需使用a-asset-item 而不是img

欲了解更多信息,请参阅AFrame documentation

【讨论】:

猜你喜欢
  • 2017-08-21
  • 2021-02-03
  • 2017-11-28
  • 2016-12-17
  • 2018-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-17
相关资源
最近更新 更多