Threejs 创建一个虚拟城市三维场景

前情回顾

前几篇文章大概讲述了threejs如何创建场景,创建几何体,纹理贴图等... 

本篇文章主要讲述threejs如何去搭建一个智慧城市虚拟场景(主要讲述如何去加载模型以及加载贴图) 

开发前准备

1. 从官方下载threejs的包,引入到项目中2. 智慧城市模型一份( 本篇文章主要加载的 OBJ + MTL )
3. 具备前几章节讲到的一些基础知识(如果还不会的话请看前几篇文章哦)4. 学习了解 MTLLoader.js 和 OBJLoader.js (加载模型主要用到这两个js)
5. vue 基础 ( 本人做的所有实例都是基于vue来开发的 )

先看一波效果吧 :Threejs 创建一个虚拟城市三维场景主要代码如下所示:
1. 引入 MTLLoader.js 和 OBJLoader.js 文件


// MTLimport { MTLLoader } from "../threeLibs/loaders/MTLLoader.js";// ObjLoaderimport { OBJLoader } from "../threeLibs/loaders/OBJLoader.js";

2. 参考官方的例子,首先加载MTL,再去加载对应的OBJ; 这里由于模型比较多,每一个都写一次加载感觉比较麻烦,所以对加载的方法做了封装,具体代码如下: 


// 模型按照数组的方式一一对应const list = [        // 一般建筑模型        ["./city/ny1.mtl", "./city/ny1.obj"],        ["./city/ny2.mtl", "./city/ny2.obj"],        ["./city/ny3.mtl", "./city/ny3.obj"],        ["./city/ny4.mtl", "./city/ny4.obj"],        ["./city/ny5.mtl", "./city/ny5.obj"],        ["./city/ny6.mtl", "./city/ny6.obj"],        ["./city/ny7.mtl", "./city/ny7.obj"],        ["./city/ny8.mtl", "./city/ny8.obj"],      ];
      const list2 = [        // 其他模型        ["./city/multi_storied_01.mtl", "./city/multi_storied_01.obj"],        ["./city/triangle_01.mtl", "./city/triangle_01.obj"],        ["./city/white_house.mtl", "./city/white_house.obj"],      ];            // 加载方法封装      // 加载MTL OBJ    MOLoader(group, list) {      list.forEach((urlList) => {        const mtlLoader = new MTLLoader();        const objLoader = new OBJLoader();        mtlLoader.load(urlList[0], (materials) => {          materials.preload();          //实例化obj加载方法          //设置mtl文件的材质          objLoader.setMaterials(materials);          //文件名          objLoader.load(urlList[1], (object) => {            object.position.set(6691, 604.35216, 2154.6111);            group.add(object);          });        });      });    },

3. 按照分组的方式加载模型,具体 api 方法自行查阅官方文档 :  http://www.webgl3d.cn/threejs/docs/


// 执行加载方法this.building = new THREE.Group();this.othersBuilding = new THREE.Group();this.scene.add(this.building);this.scene.add(this.othersBuilding);
this.MOLoader(this.building, list);this.MOLoader(this.othersBuilding, list2);


完整代码如下:


<template>  <div class>    <div ref="content" style="position: absolute;top:0;left:0;right:0;bottom: 0;overflow: hidden"></div>    <div class style="position: fixed;z-index: 999;background: #fff">      <span class="btn" @click="getCameraPosition">获取相机位置</span>    </div>  </div></template>
<script>// 引入threejsimport * as THREE from "../threeLibs/three.module.js";//鼠标控制import { OrbitControls } from "../threeLibs/controls/OrbitControls.js";// MTLimport { MTLLoader } from "../threeLibs/loaders/MTLLoader.js";// ObjLoaderimport { OBJLoader } from "../threeLibs/loaders/OBJLoader.js";
export default {  components: {},  data() {    return {      // 创建一个场景      scene: null,      // 创建一个相机      camera: null,      // 创建一个渲染器      renderer: null,      // 模型对象      mesh: null,      // 平面      plane: null,      // 点光源      point: null,
      // step      step: 0,
      building: undefined,      othersBuilding: undefined,    };  },
  mounted() {    this.init();  },  methods: {    // 初始化    init() {      // 初始化容器      var content = this.$refs.content;
      // 创建一个场景      this.scene = new THREE.Scene();      this.scene.background = new THREE.Color("#000");      this.scene.updateMatrixWorld(true);
      // 创建几何体      //   var geometry = new THREE.SphereGeometry(30, 50, 50);      // // 纹理加载器 ( 此处加载贴图 )      // // var texture = new THREE.TextureLoader().load(require('./Earth.png'));
      //   // 几何体材质对象      //   var material = new THREE.MeshLambertMaterial({      //       color:"#000"      //   });
      //   // 创建网格模型对象      //   this.mesh = new THREE.Mesh(geometry, material);      //   //设置几何体位置      //   this.mesh.position.x = 0;      //   this.mesh.position.y = 10;      //   this.mesh.position.z = 0;      //   this.scene.add(this.mesh);
      //创建环境光      var ambient = new THREE.AmbientLight(0xffffff);      this.scene.add(ambient);
      const directionalLight = new THREE.DirectionalLight(0xffffff, 2);      directionalLight.position.set(50, 25, 10);      directionalLight.castShadow = true;      this.scene.add(directionalLight);
      // 创建一个相机      this.camera = new THREE.PerspectiveCamera(        70,        window.innerWidth / window.innerHeight,        1,        1000000      );      this.camera.position.set(6691, 604.35216, 2154.6111);
      //照相机帮助线      // var cameraHelper = new THREE.CameraHelper( this.camera);      // this.scene.add(cameraHelper);
      //坐标轴辅助器,X,Y,Z长度30      // var axes = new THREE.AxesHelper(3000);      // this.scene.add(axes);      // 辅助网格      // let gridHelper = new THREE.GridHelper(3000, 3000);      // this.scene.add(gridHelper);
      // 创建一个平面      const planeGeometry = new THREE.PlaneGeometry(6000, 6000);      const planeMaterial = new THREE.MeshLambertMaterial({        color: 0xffffff,        side: THREE.DoubleSide, //两面 // THREE.FrontSide 、THREE.BackSide      });      const plane = new THREE.Mesh(planeGeometry, planeMaterial);      //水平面旋转并且设置位置      plane.rotation.x = -0.5 * Math.PI;      plane.position.x = 0;      plane.position.y = 0;      plane.position.z = 0;      // this.scene.add(plane);
      // 创建渲染器      this.renderer = new THREE.WebGLRenderer({        // 开启抗锯齿        antialias: true,        // 开启背景透明        alpha: true,      });      this.renderer.setSize(window.innerWidth, window.innerHeight);      //插入 dom 元素      content.appendChild(this.renderer.domElement);
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      // this.controls.target.set(-8148, -604, -3919)
      // this.camera.position.set(-10176, 1666, -1674)      this.camera.position.set(6691, 604.35216, 2154.6111);
      const list = [        // 一般建筑模型        ["./city/ny1.mtl", "./city/ny1.obj"],        ["./city/ny2.mtl", "./city/ny2.obj"],        ["./city/ny3.mtl", "./city/ny3.obj"],        ["./city/ny4.mtl", "./city/ny4.obj"],        ["./city/ny5.mtl", "./city/ny5.obj"],        ["./city/ny6.mtl", "./city/ny6.obj"],        ["./city/ny7.mtl", "./city/ny7.obj"],        ["./city/ny8.mtl", "./city/ny8.obj"],      ];
      const list2 = [        // 其他模型        ["./city/multi_storied_01.mtl", "./city/multi_storied_01.obj"],        ["./city/triangle_01.mtl", "./city/triangle_01.obj"],        ["./city/white_house.mtl", "./city/white_house.obj"],      ];
      this.building = new THREE.Group();      this.othersBuilding = new THREE.Group();      this.scene.add(this.building);      this.scene.add(this.othersBuilding);
      this.MOLoader(this.building, list);      // this.MOLoader(this.othersBuilding, list2)
      const t = this;      function render() {        t.controls.update();        t.renderer.render(t.scene, t.camera);        requestAnimationFrame(render);      }      render();    },
    // 加载MTL OBJ    MOLoader(group, list) {      list.forEach((urlList) => {        const mtlLoader = new MTLLoader();        const objLoader = new OBJLoader();        mtlLoader.load(urlList[0], (materials) => {          materials.preload();          //实例化obj加载方法          //设置mtl文件的材质          objLoader.setMaterials(materials);          //文件名          objLoader.load(urlList[1], (object) => {            object.position.set(6691, 604.35216, 2154.6111);            group.add(object);          });        });      });    },
    getCameraPosition() {      console.log("控制器中心", this.controls.target);      console.log("相机位置", this.camera.position);    },  },};</script>
<style lang="scss" scoped>body {  margin: 0;  overflow: hidden;  background: url("http://pic.sc.chinaz.com/files/pic/pic9/202001/zzpic22739.jpg")    center no-repeat;  background-size: cover;}</style>



本人,某个不知名小公司的前端小菜鸡,由于技术太菜,业余时间总是喜欢捣鼓一些花里胡哨的东西,一边学习一边分享,希望能够和大家一起成长,梦想着成为一位前端大大牛。

上一篇:小程序跳转 H5 时 cookie 值处理问题


下一篇:JAVA装饰者模式(从现实生活角度理解代码原理)