Vue+Three.js 入门二(导入obj文件)

LZQ plus

发布于 2020.02.20 18:10 阅读 5321 评论 0

前期爬过的坑

      关于obj文件的读取肯定是用到一个构造函数OBJLoader,然而他并不在three.js里面,vue中只是  import * as THREE from 'three'是远远不够的,然而我们如何引用OBJLoader?去官方文档没有给出明确,但是官方给了示例:

可引入的示例

three.js的核心专注于实现3D引擎中最为重要的组件。其他诸如加载器和控制器等组件,是示例文件夹中的一部分。 three.js确保这些文件能够与核心保持同步,但如果在一个项目中这些组件是必要的,用户将必须分别地引入它们。 你可以在examples/jsm文件夹中找到所有示例文件的ES6版本。 如果你是通过npm来安装three.js的,那么你可以使用类似下面的代码来引入它们:

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

请注意:当你在使用来自示例(examples)文件夹中的代码时,其中的所有文件和你的three.js主文件版本相匹配是很重要的。 比如说,three.jsR103版本不能够接受和来自R96版本的GLTFLoaderOrbitControls一起使用。

  在这里吐槽一下官方文档,对刚接触three.js的同学实在是不太友好,文档和实例分离实在是难搞;这一块我一开始没找到,后来看源码试出来的。所以这里看出认真阅读文档的重要性,哈哈哈。

  然后现在版本的three.js(目前是0.113.2)根本基本上不需要three相关的插件包(three-orbit-controls、three-obj-mtl-loader等等),需要用到哪个函数直接引用就可以了。如下:

  import * as THREE from 'three'

  import {OBJLoader} from 'three/examples/jsm/loaders/OBJLoader'

  import {MTLLoader} from 'three/examples/jsm/loaders/MTLLoader'

  import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'

 

导入一个obj文件

<template>

  <div class="main-view">

    <div id="demo2" style="width: 100%;height: 100%"></div>



    <el-button class="refresh-btn" @click="refreshView()">刷新视图</el-button>



    <div class="add-btn-view">

      <el-button type="primary" @click="addObj()">添加模型</el-button>

    </div>

  </div>

</template>



<script>

  import * as THREE from 'three'

  import {OBJLoader} from 'three/examples/jsm/loaders/OBJLoader'

  import {MTLLoader} from 'three/examples/jsm/loaders/MTLLoader'

  import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'



  export default {

    data() {

      return {

        camera: null,

        scene: null,

        renderer: null,


      }

    },

    mounted() {

      this.LOG.info(['THREE.REVISION -- ', THREE.REVISION]);

      this.init();


    },

    methods: {

      init() {

        this.scene = new THREE.Scene();

        const container = document.getElementById('demo2');

        const width = container.clientWidth;

        const height = container.clientHeight;

        this.camera = new THREE.PerspectiveCamera(75, width / height, 1, 1000);

        this.camera.position.z = 250;





        this.renderer = new THREE.WebGLRenderer({antialias: true});

        this.renderer.setSize(width, height);

        container.appendChild(this.renderer.domElement);



      },


      refreshView() {

        const container = document.getElementById('demo2');

        const width = container.clientWidth;

        const height = container.clientHeight;

        // this.camera.aspect = width / height;

        this.camera.updateProjectionMatrix();

        this.renderer.setSize(width, height)

      },



      render() {

        this.renderer.render(this.scene, this.camera)

      },



      addObj() {



        const loader = new OBJLoader();

        let material = new THREE.MeshBasicMaterial({color: 'gray', side: THREE.DoubleSide});

        loader.load('./objs/demo2/male02.obj', obj => {

          this.LOG.info(['objs/demo2/male02.obj', obj]);

          obj.traverse(function (child) {

            if (child instanceof THREE.Mesh) {

              child.material = material;

            }

          });

          this.scene.add(obj);

          this.render();

        }, xhr => {

          this.LOG.warn(['obj -- ', xhr.loaded / xhr.total * 100, ' %']);

        }, error => {

          this.LOG.error(['obj error-- ', error]);

        })

      }



    }

  }

</script>



<style scoped>



  .refresh-btn {

    position: absolute;

    top: 15px;

    right: 15px;

  }



  .add-btn-view {

    position: absolute;

    bottom: 15px;

    left: 15px;

  }

</style>