Search code examples
javascripthtmlcssaframear.js

Change the color of an object (.dae or gltf) in "AR.JS"


I'm trying to change the color of an object I created in blender. I can change the color of objects like "a-box, a-sphere" in the html code itself, but with objects inside tree.js (gltf or .dae - collada) I cannot.

CodePen (This is just a test environment for future application in my real project (AR.JS))

<html>

<head>
  <script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script>
</head>

<body>
  <a-scene>

    <a-gltf-model id="test" src="https://raw.githubusercontent.com/KurtRodrigues/KurtRodrigues.github.io/master/Arquivos%20utilizados/Pe%C3%A7a%2Bbancada_V2.gltf" color="#FF0000" position="0 0 -3" rotation="0 0 0" scale="1.5 1.5 1.5" size="20px"> </a-gltf-model>

    <a-sky color="#ECECEC"></a-sky>
  </a-scene>
</body>

</html>

Already tried:

HTML with color= # ff00000.

CSS by id .test {color: # ff0000}

JS:

var b = document.querySelector ("test");
b.setAttribute ("color", "red");

Is there any way to change the color of the object directly in the code or just at the moment I make the object (blender)?


Solution

  • Enitities that contain GLTF models are complex, as they contain many models inside the gltf container. You can't use setAttribute on the models inside a gltf like you can with other primitives. Instead you have to treat them like THREEjs models. That means you need to make a custom component that will 'traverse' through the gltf, and find the models, and store variable references to them, and then later you can change the parameters of these models on the THREEjs level. For example

    AFRAME.registerComponent('treeman', {
            init: function(){
                let el = this.el;
                let self = this;
                self.trees = [];              
                el.addEventListener("model-loaded", e =>{
                    let tree3D = el.getObject3D('mesh'); // get the THREEjs group
                    if (!tree3D){return;}    
                  console.log('tree3D', tree3D); // log the THREEjs group so you can look 
                                              at all of its contents and parameters.
                    tree3D.traverse(function(node){ // this is how you loop through 
                                                      (traverse) the models
                        if (node.isMesh){   
                          console.log(node);
                            self.trees.push(node);
                          if(node.name == "Trunk_A"){
                            self.treeMat = node.material; // store a reference to the 
                                             material you want to modify later
                          }
                          node.material.map = null; // removes the texture so we can see 
                                   color clearly
                        }
                    });
              });
    

    Then later, you can access this component with event listener functions, and do stuff to materials. like this

     el.addEventListener('changecolor', e =>{               
                let colorp = e.detail.color;
                let colorHex = Number(colorp.replace('#', '0x'));
                let color3D = new THREE.Color(colorHex);
                self.treeMat.color = color3D;                
              });
    

    Note that we have to put the color into data structures that THREEjs wants, like the color object. All of this is a lot of work compared to the simplicity of Aframe, but you have much more control and you can see precisely what is happening under the hood.

    glitch here.