Newer
Older
reroad-test / 2020-ryusei / aframe-master / src / components / obj-model.js
@ryusei ryusei on 22 Oct 2020 2 KB パノラマ表示
var debug = require('../utils/debug');
var registerComponent = require('../core/component').registerComponent;
var THREE = require('../lib/three');

var warn = debug('components:obj-model:warn');

module.exports.Component = registerComponent('obj-model', {
  schema: {
    mtl: {type: 'model'},
    obj: {type: 'model'}
  },

  init: function () {
    var self = this;

    this.model = null;
    this.objLoader = new THREE.OBJLoader();
    this.mtlLoader = new THREE.MTLLoader(this.objLoader.manager);
    // Allow cross-origin images to be loaded.
    this.mtlLoader.crossOrigin = '';

    this.el.addEventListener('componentinitialized', function (evt) {
      if (!self.model) { return; }
      if (evt.detail.name !== 'material') { return; }
      self.applyMaterial();
    });
  },

  update: function () {
    var data = this.data;
    if (!data.obj) { return; }
    this.resetMesh();
    this.loadObj(data.obj, data.mtl);
  },

  remove: function () {
    if (!this.model) { return; }
    this.resetMesh();
  },

  resetMesh: function () {
    this.el.removeObject3D('mesh');
  },

  loadObj: function (objUrl, mtlUrl) {
    var self = this;
    var el = this.el;
    var mtlLoader = this.mtlLoader;
    var objLoader = this.objLoader;
    var rendererSystem = this.el.sceneEl.systems.renderer;
    var BASE_PATH = mtlUrl.substr(0, mtlUrl.lastIndexOf('/') + 1);

    if (mtlUrl) {
      // .OBJ with an .MTL.
      if (el.hasAttribute('material')) {
        warn('Material component properties are ignored when a .MTL is provided');
      }
      mtlLoader.setResourcePath(BASE_PATH);
      mtlLoader.load(mtlUrl, function (materials) {
        materials.preload();
        objLoader.setMaterials(materials);
        objLoader.load(objUrl, function (objModel) {
          self.model = objModel;
          self.model.traverse(function (object) {
            if (object.isMesh) {
              var material = object.material;
              if (material.color) rendererSystem.applyColorCorrection(material.color);
              if (material.map) rendererSystem.applyColorCorrection(material.map);
              if (material.emissive) rendererSystem.applyColorCorrection(material.emissive);
              if (material.emissiveMap) rendererSystem.applyColorCorrection(material.emissiveMap);
            }
          });
          el.setObject3D('mesh', objModel);
          el.emit('model-loaded', {format: 'obj', model: objModel});
        });
      });
      return;
    }

    // .OBJ only.
    objLoader.load(objUrl, function loadObjOnly (objModel) {
      self.model = objModel;
      self.applyMaterial();
      el.setObject3D('mesh', objModel);
      el.emit('model-loaded', {format: 'obj', model: objModel});
    });
  },

  /**
   * Apply material from material component recursively.
   */
  applyMaterial: function () {
    var material = this.el.components.material;
    if (!material) { return; }
    this.model.traverse(function (child) {
      if (child instanceof THREE.Mesh) {
        child.material = material.material;
      }
    });
  }
});