欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

2、智能变电站--地面、围护结构图和动态绘图

最编程 2024-03-22 08:55:28
...

创建基础场景、摄像头等

  1. threejs相关类库引入
import * as THREE from "three";

import { Clock, GridHelper } from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { TWEEN } from "three/examples/jsm/libs/tween.module.min.js";
import dat from "three/examples/jsm/libs/dat.gui.module";
import Stats from "three/examples/jsm/libs/stats.module";
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader.js";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";

import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass';
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass';
  1. 先把一些three变量放到vue外面,可以提高渲染性能
// 变量放外层可以解决动画卡顿帧数变低的问题
let stats = null;
let scene = null;
let gui = null;
let datGui = null;
let clock = null;
let light = null;
let camera = null;
let renderer = null;
let controls = null;
  1. 创建基础对象:scene、gui、render、leight、camera、controls、states、helper
// 创建场景
createScene() {
  scene = new THREE.Scene();
  let textureLoader = new THREE.TextureLoader();
  let texture = textureLoader.load('/zhangyan-substation/images/page-bg.jpg');
  scene.background = texture;
  clock = new Clock();
  // 先将场景给工具类,方便工具类创建操作
  requestUtils.SetScene(scene);
},
createGui: function() {
  //声明一个保存需求修改的相关数据的对象
  gui = {};
  datGui = new dat.GUI();
  //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)
},
// 创建渲染器
createRender() {
  const element = document.getElementById("container");
  renderer = new THREE.WebGLRenderer({
    alpha: true,
    antialias: true
  });
  renderer.shadowMap.enabled = false; // 允许阴影投射
  // renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  renderer.setPixelRatio(window.devicePixelRatio); // 为了兼容高清屏幕
  renderer.setSize(element.clientWidth, element.clientHeight); // 设置渲染区域尺寸
  renderer.setClearAlpha(0.5);
  // renderer.setClearColor(0x040203, 0.9); // 设置背景颜色
  element.appendChild(renderer.domElement);
},
// 创建光源
createLight() {
  // 环境光(如果是全白,在地面就看不出阴影,但可以把模型照亮)
  scene.add(new THREE.AmbientLight(0x999999, 1));
  // 另一种平行光
  light = new THREE.DirectionalLight(0xffffff, 0.5); // 从正上方(不是位置)照射过来的平行光,0.7的强度
  light.position.set(100, 100, 100);
  light.position.multiplyScalar(1);
  light.castShadow = true;
  light.shadow.mapSize = new THREE.Vector2(1024, 1024);
  scene.add(new THREE.DirectionalLightHelper(light, 5));
  scene.add(light);
},
// 创建相机
createCamera() {
  const element = document.getElementById("container");
  camera = new THREE.PerspectiveCamera(
    45,
    element.clientWidth / element.clientHeight,
    0.1,
    1000
  );
  camera.position.x = -80; // 正视
  camera.position.y = 70; // 俯视
  camera.position.z = 40; // 离模型有多远
  camera.lookAt(new THREE.Vector3(0, 0, 0)); // 设置相机方向
  scene.add(camera);
},
// 创建控件对象
createControls() {
  // 初始化控制器
  controls = new OrbitControls(camera, renderer.domElement);
  controls.target.set(-25, 5, 0); // ------------------
  // controls.minDistance = 80
  // controls.maxDistance = 500000
  // controls.maxPolarAngle = Math.PI / 3  // 仰看角度
  controls.update();
},
createStats: function() {
  stats = new Stats();
  document.body.appendChild(stats.dom);
},
creatHelper: function() {
  // 三维坐标系
  let helper = new THREE.AxesHelper(50);
  scene.add(helper);
},
  1. 到此步骤效果图如下,可以看到一个有背景,有三维坐标辅助线的界面了

image.png

创建变电站地面并动态贴图

  1. 在进行以上步骤之后,去先创建底板(创建一个有水泥贴图的底板,添加到场景里)
// 创建底板并添加到场景
let planeGeometry = new THREE.BoxGeometry(120, 60, 1);
// 地板贴图效果
let textureLoader = new THREE.TextureLoader(); // 纹理加载器
let texture = textureLoader.load(
  "/zhangyan-substation/images/水泥地面.png",
  function(texture) {
    texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
    texture.offset.set(0, 0);
    texture.repeat.set(180, 180);
  }
);
const planeMaterial = new THREE.MeshLambertMaterial({
  map: texture
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.receiveShadow = true; // 地面接收阴影
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 0;
plane.position.y = -0.62;
plane.position.z = 0;
scene.add(plane);
  1. 灰蒙蒙的底板不好看,添加一些道路的贴图
// 横向路面贴图
let horizontalRoadTexture = new THREE.TextureLoader().load('/zhangyan-substation/images/马路背景.jpg');
horizontalRoadTexture.wrapS = horizontalRoadTexture.wrapT = THREE.RepeatWrapping;
horizontalRoadTexture.repeat.set(15, 1);

// 纵向路面贴图(A1)
let lengthwaysRoadTextureA = new THREE.TextureLoader().load('/zhangyan-substation/images/马路背景.jpg');
lengthwaysRoadTextureA.wrapS = lengthwaysRoadTextureA.wrapT = THREE.RepeatWrapping;
lengthwaysRoadTextureA.repeat.set(5, 1);

// 纵向路面贴图(B1)
let lengthwaysRoadTextureB = new THREE.TextureLoader().load('/zhangyan-substation/images/马路背景.jpg');
lengthwaysRoadTextureB.wrapS = lengthwaysRoadTextureB.wrapT = THREE.RepeatWrapping;
lengthwaysRoadTextureB.repeat.set(2.5, 1);

// 主干道(横向)
let mainRoadMaterial = new THREE.MeshLambertMaterial({
  map: horizontalRoadTexture
})
let mainRoadGeometry = new THREE.PlaneGeometry(100, 4)
let mainRoadMesh = new THREE.Mesh(mainRoadGeometry, mainRoadMaterial)
mainRoadMesh.position.set(-10, 0.1, 6);
mainRoadMesh.rotation.x = -0.5 * Math.PI;

// A1干道(纵向)
let a1RoadMaterial = new THREE.MeshLambertMaterial({
  map: lengthwaysRoadTextureA
})
let a1RoadGeometry = new THREE.PlaneGeometry(25, 2)
let a1RoadMesh = new THREE.Mesh(a1RoadGeometry, a1RoadMaterial)
a1RoadMesh.position.set(39, 0.05, -7.5);
a1RoadMesh.rotation.x = -0.5 * Math.PI;
a1RoadMesh.rotation.z = 0.5 * Math.PI;
// A2干道(横向)
let a2RoadMaterial = new THREE.MeshLambertMaterial({
  map: horizontalRoadTexture
})
let a2RoadGeometry = new THREE.PlaneGeometry(82, 2)
let a2RoadMesh = new THREE.Mesh(a2RoadGeometry, a2RoadMaterial)
a2RoadMesh.position.set(-2, 0.1, -19);
a2RoadMesh.rotation.x = -0.5 * Math.PI;
// A3干道(纵向)
let a3RoadMaterial = new THREE.MeshLambertMaterial({
  map: lengthwaysRoadTextureA
})
let a3RoadGeometry = new THREE.PlaneGeometry(25, 2)
let a3RoadMesh = new THREE.Mesh(a3RoadGeometry, a3RoadMaterial)
a3RoadMesh.position.set(-42, 0.05, -7.5);
a3RoadMesh.rotation.x = -0.5 * Math.PI;
a3RoadMesh.rotation.z = 0.5 * Math.PI;

// B1干道(纵向)
let b1RoadMaterial = new THREE.MeshLambertMaterial({
  map: lengthwaysRoadTextureB
})
let b1RoadGeometry = new THREE.PlaneGeometry(11, 2)
let b1RoadMesh = new THREE.Mesh(b1RoadGeometry, b1RoadMaterial)
b1RoadMesh.position.set(39, 0.05, 11.5);
b1RoadMesh.rotation.x = -0.5 * Math.PI;
b1RoadMesh.rotation.z = 0.5 * Math.PI;
// B2干道(横向)
let b2RoadMaterial = new THREE.MeshLambertMaterial({
  map: horizontalRoadTexture
})
let b2RoadGeometry = new THREE.PlaneGeometry(82, 2)
let b2RoadMesh = new THREE.Mesh(b2RoadGeometry, b2RoadMaterial)
b2RoadMesh.position.set(-2, 0.1, 16);
b2RoadMesh.rotation.x = -0.5 * Math.PI;
// B3干道(纵向)
let b3RoadMaterial = new THREE.MeshLambertMaterial({
  map: lengthwaysRoadTextureB
})
let b3RoadGeometry = new THREE.PlaneGeometry(11, 2)
let b3RoadMesh = new THREE.Mesh(b3RoadGeometry, b3RoadMaterial)
b3RoadMesh.position.set(-42, 0.05, 11.5);
b3RoadMesh.rotation.x = -0.5 * Math.PI;
b3RoadMesh.rotation.z = 0.5 * Math.PI;

scene.add(mainRoadMesh);
scene.add(a1RoadMesh);
scene.add(a2RoadMesh);
scene.add(a3RoadMesh);
scene.add(b1RoadMesh);
scene.add(b2RoadMesh);
scene.add(b3RoadMesh);
  1. 到此步骤效果图如下

image.png

创建四周围墙并动态贴图

  1. 接着上面的代码,我们给变电站创建四周的围墙,并且给围墙开个门口
// 外墙
let outsideWallArray = [];
let wallTexture = new THREE.TextureLoader().load('/zhangyan-substation/images/围墙.png')
wallTexture.wrapS = wallTexture.wrapT = THREE.RepeatWrapping;
wallTexture.repeat.set(5, 1);
outsideWallArray.push(new THREE.MeshPhongMaterial({map: wallTexture}));  //前
outsideWallArray.push(new THREE.MeshPhongMaterial({map: wallTexture}));  //后
outsideWallArray.push(new THREE.MeshPhongMaterial({map: wallTexture}));  //上
outsideWallArray.push(new THREE.MeshPhongMaterial({color: 0xafc0ca }));  //下
outsideWallArray.push(new THREE.MeshPhongMaterial({map: wallTexture}));  //左
outsideWallArray.push(new THREE.MeshPhongMaterial({map: wallTexture}));  //右

// 柱子
let outsidePillarArray = [];
outsidePillarArray.push(new THREE.MeshPhongMaterial({color: 0xafc0ca}));  //前
outsidePillarArray.push(new THREE.MeshPhongMaterial({color: 0xafc0ca}));  //后
outsidePillarArray.push(new THREE.MeshPhongMaterial({color: 0xafc0ca}));  //上
outsidePillarArray.push(new THREE.MeshPhongMaterial({color: 0xafc0ca }));  //下
outsidePillarArray.push(new THREE.MeshPhongMaterial({color: 0xafc0ca}));  //左
outsidePillarArray.push(new THREE.MeshPhongMaterial({color: 0xafc0ca}));  //右

this.createWallDetail(0.3, 1.6, 33.5, 0, outsideWallArray, -60, 0.8, -13.2,  "门口北墙");// 门口北墙
this.createWallDetail(0.3, 1.6, 22, 0, outsideWallArray, -60, 0.8, 19, "门口南墙");// 门口南墙
this.createWallDetail(0.4, 1.8, 0.4, 0, outsidePillarArray, -60, 0.8, 3.8, "门口北柱子");// 门口北柱子
this.createWallDetail(0.5, 0.3, 0.5, 0, outsidePillarArray, -60, 1.85, 3.8, "门口北柱子顶");// 门口北柱子顶
this.createWallDetail(0.4, 1.8, 0.4, 0, outsidePillarArray, -60, 0.8, 8.2, "门口南柱子");// 门口北柱子
this.createWallDetail(0.5, 0.3, 0.5, 0, outsidePillarArray, -60, 1.85, 8.2, "门口南柱子顶");// 门口北柱子顶

this.createWallDetail(0.3, 1.6, 120.2, 0.5, outsideWallArray, 0, 0.8, -29.8, "北墙");// 北墙
this.createWallDetail(0.3, 1.6, 120.2, 0.5, outsideWallArray, 0, 0.8, 29.9, "南墙");// 南墙
this.createWallDetail(0.3, 1.6, 60, 0, outsideWallArray, 60, 0.8, 0, "东墙");// 东墙

// 墙生成方法
createWallDetail(width, height, depth, angle, material, x, y, z, name){
  let cubeGeometry = new THREE.BoxGeometry(width, height, depth);
  let cube = new THREE.Mesh(cubeGeometry, material);
  cube.position.set(x, y, z);
  cube.rotation.y += angle * Math.PI; //-逆时针旋转,+顺时针
  cube.name = name;
  scene.add(cube);
},
  1. 到此步骤效果图如下

image.png
好了,到了这一步骤,已经把地面和围墙都搭建好了,接下来就是教大家如何加载3d模型
PS:想要此项目demo请添加wx:z13964122832