Threejs 创建一个虚拟城市三维场景
前情回顾
前几篇文章大概讲述了threejs如何创建场景,创建几何体,纹理贴图等...
本篇文章主要讲述threejs如何去搭建一个智慧城市虚拟场景(主要讲述如何去加载模型以及加载贴图)
开发前准备
// MTL
import { MTLLoader } from "../threeLibs/loaders/MTLLoader.js";
// ObjLoader
import { OBJLoader } from "../threeLibs/loaders/OBJLoader.js";
// 模型按照数组的方式一一对应
const list = [
// 一般建筑模型
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
[ ],
];
const list2 = [
// 其他模型
[ ],
[ ],
[ ],
];
// 加载方法封装
// 加载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);
});
});
});
},
// 执行加载方法
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>
// 引入threejs
import * as THREE from "../threeLibs/three.module.js";
//鼠标控制
import { OrbitControls } from "../threeLibs/controls/OrbitControls.js";
// MTL
import { MTLLoader } from "../threeLibs/loaders/MTLLoader.js";
// ObjLoader
import { 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>
本人,某个不知名小公司的前端小菜鸡,由于技术太菜,业余时间总是喜欢捣鼓一些花里胡哨的东西,一边学习一边分享,希望能够和大家一起成长,梦想着成为一位前端大大牛。
觉得本文对你有帮助?请分享给更多人或点个在看
关注==>>「前端开发爱好者」,一起提升前端技能!