Альфа-анимация в Aframe для модели объекта

У меня есть один 3d-объект с его файлом obj и mtl, который отображается с помощью Aframe. Я хочу применить анимацию, которая постепенно меняет значение альфа-канала для эффекта затухания.

Я прошел AFrame док. но не смог найти ничего связанного с альфа-анимацией 3D-объекта.

3 ответа

Решение

Встроенный material компонент в основном работает с примитивами, поэтому material="opacity: 0.5" и так же opacity="0.5" не будет работать здесь. Вам нужно будет изменить материалы THREE.js, созданные вашей моделью, используя пользовательский компонент. Пример:

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;
      }
    });
  }
});

Затем вы можете использовать и анимировать компонент следующим образом:

<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>

Подробнее о том, как это работает, смотрите документацию по THREE.Material и написание компонента.

Для меня материал был полностью белым, поэтому мне пришлось изменить компонент Дона, чтобы поддержать число:

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;
      }
    });
  }
});

Мне пришлось изменить приведенные выше примеры, так как у меня было несколько материалов, поэтому мне пришлось использовать forEach и настроить для каждого из них:

      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;
        })
      }
    });
  }
});
Другие вопросы по тегам