0
votes

I am attempting to make a simple demo, using dat.GUI to manipulate a material on an Aframe primitive . On the entity tag, I create a material, an assign a texture to the normal slot.

<a-entity id="circle" geometry="primitive:circle; radius: 2; segments: 96" 
rotation="-90 0 0"
            material="color: #335500; transparent: true; opacity: 0.9; 
normalMap: #watertex; side: double"
            water ></a-entity>

Then, in a custom component, I access its THREEjs mesh and material. I am able to get a reference to the material, but when I try to access the normalMap, it returns undefined.

I added a listener, to wait for the "loaded" event. I am not using gltf, so "model-loaded" is unnecessary. I used getObject3D("mesh"), and traversed the mesh, but still, the normal map still returns undefined. The puzzling part is that in the console, I log the material, and can clearly see the normalMap. But when log it, it returns undefined.

    AFRAME.registerComponent("water",{
        init: function(){
            let el = this.el;
            //console.log(el);
            let comp = this;
            this.counter=0;

            el.addEventListener("loaded", function(ev){
                console.log('model loaded');
                let mesh = el.getObject3D('mesh');
                if (!mesh){return;}
                mesh.traverse(function(node){
                    if (node.isMesh){
                        console.log(node);
                        console.log(node.material);
                        console.log(node.material.normalMap); <-- returns 
                                                                 undefined
                    }
                });  
            });
        },          
    });

<a-entity id="circle" geometry="primitive:circle; radius: 2; segments: 96" 
rotation="-90 0 0"
            material="color: #335500; transparent: true; opacity: 0.9; 
normalMap: #watertex; side: double"
            water ></a-entity>

I am surprised that a reference to a material shows the normal map console.log(node.material);

but a direct reference to the normal map fails console.log(node.material.normalMap);

I suspect that perhaps something is strange with texture maps made with aframe not being accessible from Threejs, but I don't know why or how to test this.

Ultimately I want to use datGUI to control params in the materials. I notice that AFrame material component does not expose all the parameters of threejs materials. Also accessing some aframe material parameters with datGUI seem a bit buggy. So this is why I want to access threejs directly.

Here is a link to the project on my server, where you can see the console logs. http://sensorium.love/experiments/demos/water/waterDemo1.html

and here is a glitch if you want to play with the code https://glitch.com/~water-demo

1

1 Answers

0
votes

It seems to be a race, where you try to access the normalMap just before it's applied.


materialtextureloadeddocs
el.addEventListener('materialtextureloaded', e => {
    // nomalMap is accessible here
})


I've seen ar.js do:

let timer = setInterval(e => {
      if (!someVal) return;

      clearInterval(timer);
      // here someVal isn't null or undefined
}, 500)

Glitch here.


I'm pretty sure you could see the normalMap in the console, because the expression gets evaluated once you click the arrow in the browser console. On chrome there's a blue "i" which says "value below was evaluated just now".