如何在附加到 gltf 元素的自定义组件中引用多种材料

How to reference multiple materials inside a custom component attached to a gltf element

我有一个附加了 gltf-model 组件的元素。在内部,我想使用具有组件级范围(即架构属性)的变量来获取对某些 material 的引用。我注意到(在 aframe 文档中)模式对象的类型是 'string' 或 'number',我想存储对 THREE.js material 的引用(不确定这是否作品)。我试过了,有点用,但范围仅限于侦听器功能,所以显然,它不起作用。如何存储对 THREE.objects 的引用,这些引用可以在我的组件中的任何位置访问?最终我想存储许多对各种 material 的引用,并在 ('model-loaded') 侦听器函数之外的其他侦听器函数 ('loaded') 中修改它们的属性。

我尝试使用架构 属性 来存储 THREE.material 这样的

schema:{ 
  bonsaiMat:{type:'string'}...
     update:function(){ 
        let data = this.data;
          el.addEventListener('model-loaded', function(ev){
            data.bonsaiMat = node.material;

但在侦听器函数之外记录 data.bonsaiMat returns 什么都没有(在侦听器函数内工作正常)。

也试过了 this.bonsaiMat = node.material; // 错误

AFRAME.registerComponent("bonsai-gltf", { 
            schema:{ 
                bonsaiMat:{type:'string'}               
            },
            update:function(){
                let el = this.el;
                let scene = el.sceneEl.object3D;
                let data = this.data;

                // Initialize materials setup on the scultpure.
                el.addEventListener('model-loaded', function(ev){
                   // console.log('bonsai loaded');
                    let mesh = el.getObject3D('mesh');

                    // Get references to Materials, to be adjusted later.
                    mesh.traverse(function(node){
                        if(node.isMesh){
                            if(node.material.name === 'pbr_Metal'){                               
                                data.bonsaiMat = node.material;
                                console.log(bonsaiMat); // <--this works
                            }                          
                        }
                    });
                 console.log(data.bonsaiMat); // <--this fails

我希望存储在架构中的变量,即 this.data.myMaterial 可以在组件中的任何地方使用,但范围仅限于侦听器函数,所以出了点问题。架构 属性 的数据类型?还有其他方法可以获得组件范围吗? 我的项目相当庞大,所以把它放在故障中会很乏味,但如果需要我可以做到。

您可以使用数组/对象作为组件主作用域的 属性。 要获取材料,您可以遍历模型子项:

let mesh = this.el.getObject3D('mesh')
this.materials = {}
mesh.traverse( node => {
    if (!node.isMesh())
       return;
    let material = node.material // reference to the material
    this.materials[node.uuid] = node.material // keep it in a map
})


通过范围快速概览。 this.stuff 在下面的例子中引用了同一个对象:

AFRAME.registerComponent('foo', {
   init: function() {
      this.stuff = null 
      var self = this
      // anonymous function 
      this.el.addEventListener('model-loaded', function() {
         self.stuff //= otherstuff
      }
      // lambda capture - same scope
      this.el.addEventListener('loaded', e => {
         this.stuff //= otherstuff
      })
      // custom functions need to have to scope bound (bind / apply / call)
      this.customFunction = this.customFunction.bind(this)
   },
   tick: function() {
      this.stuff //= otherstuff
   },
   customFunction: function() {
      this.stuff //= otherstuff
   }
})


另一方面,我会尽量减少使用它。喜欢这里:

var stuff // no need for this to be global if i only need it here:
this.el.addEventListener('model-loaded', function() {
    // can access stuff here !
})
this.el.addEventListener('model-loaded, e => {
    // as well as here !
})

Cool anwser on polluting scopes vs garbage collection.