how to replace model material in aframe with three materials?

Viewed 410

I'm looking to replace the standard PBR material in a-frame with a three.js material.

I put a codepen here of material replacement working, however it doesn't work with obj models, would be awesome to know how to extend the code here to allow obj.

https://codepen.io/dadako/pen/ZEQEKRQ

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
    <script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
    <script>
      AFRAME.registerComponent('phong', {
 schema: {
   color: { default: '#000' },
 },
 update: function() {
   this.el.getObject3D('mesh').material.dispose();
   this.el.getObject3D('mesh').material = new THREE.MeshPhongMaterial({
  color: this.data.color,
   });
 },
  });

AFRAME.registerComponent('lambert', {
 schema: {
   color: { default: '#000' },
 },
 update: function() {
   this.el.getObject3D('mesh').material.dispose();
   this.el.getObject3D('mesh').material = new THREE.MeshLambertMaterial({
  color: this.data.color,
   });
 },
  });
    </script>
  </head>
  <body>
    <a-scene>
      
      <a-sphere position="-1 0.5 -3" rotation="0 45 0" phong="color: #4CC3D9"></a-sphere>
      <a-sphere position="0 1.25 -5" radius="1.25" lambert="color : #EF2D5E"></a-sphere>
      <a-sphere position="1 0.75 -3" radius="0.5" height="1.5" phong="color : #FFC65D"></a-sphere>
      <a-sphere position="0 0 -4" rotation="-90 0 0" width="4" height="4" lambert="color : #7BC8A4"></a-sphere>
      <a-sky material="shader : flat; color : #ECECEC"></a-sky>
    </a-scene>
  </body>
</html>

I can't put the obj in these examples because of https cross domain limits but another example with the obj model file is here https://xr.dadako.com/famicase/shader-test.html

1 Answers

You need to traverse the model and apply the material to each mesh child:

    // assuming the 'model-loaded' event already fired
    let mesh = this.el.getObject3D('mesh')
    // assuming you want all nodes to have the same material        
    var material = new THREE.MeshLambertMaterial({
      color: this.data.color,
    });
        
    mesh.traverse(function(node) {
      // change only the mesh nodes
      if(node.type != "Mesh") return;
      // apply material and clean up
      let tmp = node.material
      node.material = material
      tmp.dispose();
    })

Like here.

Related