[Added] Three Vue vue in the project, and to achieve obj, mtl load

Previous articles, has introduced the basic use Threejs, this article will explain how to join Threejs and OBJ in the Vue, MTL loaded.

First on the effect of:

Document structure (note the version before the vue3, obj and other resources to put static below):

In fact, the use threejs vue in more simple, the only thing to note is that version, I've used this one 84 edition cited is the latest version of the 106, in the handling of the camera feel the difference with the old version.

step:

npm cnpm vue related environment is no longer here to say.

1. Install threejs

cnpm install three -s -d

2. Install the obj mtl load

cnpm install three-obj-mtl-loader -s -d

3. The front-end code

<template>
  <div style="height: 100%">
    <div>
      <button @click="triggerTips('m1')">m1</button>
      <button @click="triggerTips('m2')">m2</button>
      <button @click="triggerTips('m3')">m3</button>
    </div>
    <div id="container">

    </div>
  </div>

</template>

<script>
  import * as Three from 'three';
  import {OBJLoader, MTLLoader} from 'three-obj-mtl-loader'

  export default {
    data() {
      return {
        camera: null,
        scene: null,
        renderer: null,
        light: null,
        elements: [],
        tipsBottom: 5 + 200,
        tipsTop:5 + 200 + 40
      }
    },
    mounted() {
      this.initThree(document.getElementById('container'))
      this.animation();

    },
    methods: {
      createSphere(color) {
        //创建球体
        let radius = 10, segemnt = 16, rings = 16;
        let sphereMaterial = new Three.MeshLambertMaterial({
          color: color,
          transparent: true,
          opacity: 0.8
        });
        let sphere = new Three.Mesh(
          new Three.SphereGeometry(radius, segemnt, rings),
          sphereMaterial
        );
        sphere.geometry.verticesNeedUpdate = true;
        sphere.geometry.normalsNeedUpdate = true;
        return sphere;
      },
      triggerTips(id) {
        let element = this.elements.find(x => {
          if (x.id == id) {
            return x;
          }
        })
        if (!element) {
          console.log("不存在该id");
          return;
        }
        if (element.timeKey) {
          clearInterval(element.timeKey);
          element.timeKey = undefined;
          element.model.children.forEach(o => {
            for (let m in element.materials.materials) {
              if (o.name.indexOf(m) != -1) {
                o.material = element.materials.materials[m];
              }
            }

          })
          element.cylis.forEach(x => {
            this.scene.remove(x.cyli);
          })
          element.cylis.splice(0, element.cylis.length);
        } else {
          this.crateTips(element);
          element.timeIndex = 0;
          element.timeKey = setInterval(() => {
            element.model.children.forEach(o => {
              if (element.timeIndex == 0) {
                o.material = new Three.MeshBasicMaterial({color: 0xFF0000});
              } else {
                for (let m in element.materials.materials) {
                  if (o.name.indexOf(m) != -1) {
                    o.material = element.materials.materials[m];
                  }
                }
              }
            })
            element.timeIndex = ++element.timeIndex % 2;
          }, 500);
        }
      },
      crateTips(element) {
        element.cylis = [];
        let cyliMesh01 = this.createSphere(0xFF0000);
        cyliMesh01.position.set(element.model.position.x, this.tipsBottom, element.model.position.z);
        this.scene.add(cyliMesh01);
        element.cylis.push({cyli: cyliMesh01});

        let cyliMesh02 = this.createSphere(0xFFFF00);
        cyliMesh02.position.set(element.model.position.x, this.tipsTop, element.model.position.z);
        this.scene.add(cyliMesh02);
        element.cylis.push({cyli: cyliMesh02});
      },
      onResize() {
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(window.innerWidth, window.innerHeight);
      },
      animation() {
        this.elements.forEach(x => {
          x.cylis.forEach(c => {
            let cyl = c.cyli;
            if (cyl.position.y >= this.tipsTop) {
              c.direction = -1;
            } else if (cyl.position.y <=this.tipsBottom) {
              c.direction = 1;
            }

            cyl.position.setY(cyl.position.y + c.direction * 1.2);
          })

        })

        //刷新页面
        this.renderer.render(this.scene, this.camera);
        requestAnimationFrame(this.animation);
      },
      loadObj(id, baseUrl, objName, multiplyScalar, position, materials) {
        let obj = {id: id, isTips: false,cylis:[]};
        if (!multiplyScalar) {
          multiplyScalar = 1;
        }
        let manager = new Three.LoadingManager();
        let loader = new OBJLoader(manager);
        if (multiplyScalar) {
          loader.setMaterials(materials);
          obj.materials = materials;
        }
        loader.setPath(baseUrl);
        loader.load(objName, object => {
          //显示比例
          object.scale.multiplyScalar(multiplyScalar);
          //加入到页面中
          this.scene.add(object);
          object.castShadow = true;
          object.receiveShadow = true;
          obj.model = object;
          object.position.set(position.x, position.y, position.z);
          this.elements.push(obj);
        });
      },
      loadObjWithMaterials(id, baseUrl, objName, mtlName, position, multiplyScalar) {
        let mtlLoader = new MTLLoader();
        mtlLoader.setPath(baseUrl);
        mtlLoader.load(mtlName, materials => {
          this.loadObj(id, baseUrl, objName, multiplyScalar, position, materials);
        });
      },
      initThree(element) {
        let container = element;
        //初始化相机
        this.camera = new Three.PerspectiveCamera(70, element.clientWidth / element.clientHeight, 1, 10000);
        this.camera.position.x = 0;
        this.camera.position.y = 1000;
        this.camera.position.z = 1000;
        this.camera.rotation.x -= 45 * (Math.PI / 180);
        //场景
        this.scene = new Three.Scene();
        //渲染
        this.renderer = new Three.WebGLRenderer({antialias: true});
        this.renderer.setSize(element.clientWidth, element.clientHeight);
        element.appendChild(this.renderer.domElement);
        //灯光
        this.light = new Three.AmbientLight(0xFFFFFF);
        this.scene.add(this.light);

        //创建地面
        let plane = new Three.Mesh(
          new Three.PlaneBufferGeometry(2000, 2000),
          new Three.MeshPhongMaterial({
            color: 0x999999,
            specular: 0x101010
          })
        );
        plane.rotation.x = -Math.PI / 2;
        plane.position.y = -0.5;
        this.scene.add(plane);
        plane.receiveShadow = true;

        window.addEventListener('resize', this.onResize, false);
        this.loadObjWithMaterials("m1", 'static/model/female02/', 'female02.obj', 'female02.mtl', {
          x: 0,
          y: 0,
          z: 0
        }, 1,)
        this.loadObjWithMaterials("m2", 'static/model/female02/', 'female02.obj', 'female02.mtl', {
          x: 500,
          y: 0,
          z: 0
        }, 1,)
        this.loadObjWithMaterials("m3", 'static/model/female02/', 'female02.obj', 'female02.mtl', {
          x: 0,
          y: 0,
          z: 600
        }, 1,)
      }
    }
  }
</script>

<style>
  #container {
    height: 100%;
  }
</style>

The final say webstrom write front-end is really cool, no matter vue single page, or threejs very smooth, suggesting also in place.

Published 47 original articles · won praise 4 · Views 7489

Guess you like

Origin blog.csdn.net/weixin_39370093/article/details/97378082