Alpha Animation in Aframe for a-object-model
Asked Answered
D

3

6

I have one 3d object with its obj and mtl file which is displayed using in Aframe. I want to apply animation on it which change its Alpha value gradually for Fade out effect.

I went through AFrame doc. but couldn't find anything related to 3d object alpha animation.

Dealate answered 11/5, 2017 at 12:0 Comment(0)
I
11

The built-in material component primarily works with primitives, so material="opacity: 0.5" and similarly opacity="0.5" will not work here. You'll need to modify the THREE.js materials created by your model, using a custom component. Example:

AFRAME.registerComponent('model-opacity', {
  schema: {default: 1.0},
  init: function () {
    this.el.addEventListener('model-loaded', this.update.bind(this));
  },
  update: function () {
    var mesh = this.el.getObject3D('mesh');
    var data = this.data;
    if (!mesh) { return; }
    mesh.traverse(function (node) {
      if (node.isMesh) {
        node.material.opacity = data;
        node.material.transparent = data < 1.0;
        node.material.needsUpdate = true;
      }
    });
  }
});

You can then use, and animate, the component like this:

<a-entity obj-model="obj: model.obj; mtl: model.mtl;" model-opacity="1">
  <a-animation attribute="model-opacity"
               dur="10000"
               from="1"
               to="0"
               repeat="indefinite"></a-animation>
</a-entity>

For more on how this works, see the docs on THREE.Material and writing a component.

Icebreaker answered 11/5, 2017 at 14:12 Comment(4)
it is not working for another 3d object. does it do with some material?Dealate
If you can console.log(node.material) that may be helpful. There are different types of THREE._____Material objects, each with different settings in the three.js docs. But most should support opacity I think, excluding maybe ShaderMaterial.Icebreaker
its multimaterial type. i think thats issue and its not providing any way to get it. is there any workaround?Dealate
@elopio Yes, except with glTF 1.0 models that contain custom shaders, as opposed to the "common materials" extension. There should be no issue with glTF 2.0.Icebreaker
C
5

For me, the material was all white, so I had to change the component by Don to support a number:

AFRAME.registerComponent("model-opacity", {
  schema: {
    opacity: { type: "number", default: 0.5 }
  },
  init: function() {
    this.el.addEventListener("model-loaded", this.update.bind(this));
  },
  update: function() {
    var mesh = this.el.getObject3D("mesh");
    var data = this.data;
    if (!mesh) {
      return;
    }
    mesh.traverse(function(node) {
      if (node.isMesh) {
        console.log(node);
        node.material.opacity = data.opacity;
        node.material.transparent = data.opacity < 1.0;
        node.material.needsUpdate = true;
      }
    });
  }
});
Combatant answered 12/3, 2020 at 15:38 Comment(2)
This worked great. Do you know how I can animate this?Ahrens
Like this, IIRC: <a-entity gltf-model="model.glb" animation="property: model-opacity.opacity;from: 1; to: 0; dur: 2500; easing: easeInOutSine; loop: true; dir: alternate; startEvents: mouseenter" ></a-entity> @Jason SmallCombatant
A
0

I had to modify the above examples as mine had multiple materials, so I had to use forEach and adjust for all of them:

AFRAME.registerComponent("model-opacity", {
  schema: {
    opacity: { type: "number", default: 0.5 }
  },
  init: function() {
    this.el.addEventListener("model-loaded", this.update.bind(this));
  },
  update: function() {
    var mesh = this.el.getObject3D("mesh");
    var data = this.data;
    if (!mesh) {
      return;
    }
    mesh.traverse(function(node) {
      if (node.isMesh) {
        console.log(node);
        node.material.forEach( (mtl) =>{
            mtl.opacity = data.opacity;
            mtl.transparent = data.opacity < 1.0;
            mtl.needsUpdate = true;
        })
      }
    });
  }
});
Antecedents answered 17/2, 2022 at 5:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.