3D配置模块

import * as THREE from 'three'

export const roadWidth = 12      // 道路宽度基础
export const roadLengthScale = 5 // 道路长度倍数
export const ImgLoader = new THREE.TextureLoader()

const repaintCbs = {}
let m_azimuthalAngle = null;
let m_polarAngle = null;
// 重写控制器实例的update方法,加入钩子
function decoratorCtrl(ctrl){
  const fn = ctrl.update
  ctrl.update = function() {
    let azimuthalAngle = this.getAzimuthalAngle()   // 水平旋转角度
    let polarAngle = this.getPolarAngle()           // 垂直旋转角度
    if(m_azimuthalAngle !== azimuthalAngle || m_polarAngle !== polarAngle) {
      m_azimuthalAngle = azimuthalAngle
      m_polarAngle = polarAngle
      for(let key in repaintCbs) {
        repaintCbs[key](azimuthalAngle, polarAngle)
      }
    }
    fn()
  }
}
// 注册重绘函数
function registerRepaint(uuid, fn) {
  repaintCbs[uuid] = fn
}
// 注销重绘函数
function cancelRepaint(uuid) {
  if(repaintCbs[uuid]) delete repaintCbs[uuid]
}
export { decoratorCtrl, registerRepaint, cancelRepaint }


const flashCbs = {}
const timer = setInterval(() => {
  for(let key in flashCbs) {
    flashCbs[key]()
  }
},250)

// 扩展 Mesh 的功能,加入到其原型中
let Mesh_Extension = {
  bPicked: false,           // 是否可交互(滑过有高亮)
  bSelected: false,         // 是否可选取(点击有高亮)
  onSelected: null,         // 被选中的回调函数
  onCancelSelected: null,   // 取消选中的回调函数
  choosedTarget: null,      // 被选中时,转嫁到其他网格体
  // 对自身设置高亮
  highlight: function (color = 0xff0000) {
    this.originColor = this.material.color.clone();
    this.originEmColor = this.material.emissive ? this.material.emissive.clone() : null;
    if (color) {
      this.material.color.set(color);
      this.material.emissive && this.material.emissive.set(color);
    }
  },
  // 对自身取消高亮
  unHighlight: function () {
    if(this.originColor) {
      this.material.color.set(this.originColor);
      this.originColor = null
    }
    if(this.originEmColor) {
      this.material.emissive && this.material.emissive.set(this.originEmColor);
      this.originEmColor = null
    }
  },
  // 对自身设置闪烁
  flashlight: function (color = 0xff0000) {
    flashCbs[this.uuid] = () => {
      this.flashing = !this.flashing
      if(this.flashing) {
        this.highlight(color)
      }else{
        this.unHighlight()
      }
    }
  },
  // 对自身取消闪烁
  unFlashlight: function () {
    if(flashCbs[this.uuid]) delete flashCbs[this.uuid]
  },
  // 基于物体的包围盒,增大可点击区域
  addClickBox(scale = [1,1,1], choosedTarget) {
    let mesh = this
    mesh.geometry.computeBoundingBox()
    let box = mesh.geometry.boundingBox
    let x = Math.abs(box.max.x - box.min.x) * scale[0]
    let y = Math.abs(box.max.y - box.min.y) * scale[1]
    let z = Math.abs(box.max.z - box.min.z) * scale[2]
    let boxGeom = new THREE.BoxGeometry(x, y, z);
    let boxMater = new THREE.MeshBasicMaterial({
      visible: false,
    });
    let clickBox = new THREE.Mesh(boxGeom, boxMater)
    clickBox.name = 'clickArea'
    clickBox.bPicked = true
    clickBox.bSelected = true
    mesh.add(clickBox)
    clickBox.choosedTarget = choosedTarget || mesh
  },
  // 显示/隐藏网格体
  targetMesh(target = false) {
    this.visible = target
  },
}
Object.assign(THREE.Mesh.prototype, Mesh_Extension)

import * as THREE from 'three'
import * as sceneConfig from './sceneConfig.js'
import createRoad from './model/road.js'
import createBuild from './model/building.js'
import {createLight, createPassage}  from './model/light.js'
import createArrow from './model/arrow.js'

const roadWidth = sceneConfig.roadWidth             // 道路宽度基础
const roadLengthScale = sceneConfig.roadLengthScale // 道路长度倍数
const ImgLoader = sceneConfig.ImgLoader

export default {
  ARROW_SHAPE: {},
  choosedMesh: null,  //被选中的物体, 暂时仅支持单选
  // 高亮
  HighLight(mesh) {
    if (this.tempObject) this.tempObject.unHighlight()
    this.tempObject = mesh;
    this.tempObject.highlight(0xff0000)
  },
  // 取消高亮
  NoHighLight() {
    if (this.tempObject) this.tempObject.unHighlight()
  },
  // 获取后代网格体
  findAllChildrenMesh(root, meshs) {
    root = root || window.SceneApp.scene
    meshs = meshs || []
    if (root.isMesh || root.isGroup) {
      meshs.push(root)
    }
    root.children.forEach((v) => {
      meshs.concat(this.findAllChildrenMesh(v, meshs))
    })
    return meshs
  },
  // 获取一个路口及其子网格体
  getRoadMesh() {
    return createRoad()
  },
  // 设置路口方位
  setCrossroadPos(crossroad, dir, roadType) {
    if (!crossroad || !dir) return;
    let radius;
    let shape = this.getCrossroadShape(roadType)
    switch (shape) {
      case 4:
        radius = 0.5
        break;
      case 6:
        radius = Math.sqrt(3) / 2
        break;
      case 8:
        radius = 0.5 / Math.tan(Math.PI / 8)
        break;
      default:
        break;
    };
    switch (dir) {
      case 1:
        crossroad.rotation.set(-0.5 * Math.PI, 0, 0.25 * Math.PI);
        if (shape === 4) {
          crossroad.position.set(-radius * roadWidth * (1 + roadLengthScale) / Math.sqrt(2), 0, radius * roadWidth * (1 + roadLengthScale) / Math.sqrt(2))
        } else if (shape === 6) {
          if (roadType.every((v) => { return [1, 3, 4, 6, 7, 9].indexOf(v) >= 0 })) {
            crossroad.position.set(-(roadLengthScale / 4 + radius / 2) * roadWidth, 0, roadWidth * ((roadLengthScale / 2 + radius) * radius));
            crossroad.rotation.set(-0.5 * Math.PI, 0, Math.PI / 3);
          } else {
            crossroad.position.set(-(roadLengthScale / 2 + 1) * radius * roadWidth + 1.5, 0, roadWidth * (roadLengthScale / 4 + radius / 2));
            crossroad.rotation.set(-0.5 * Math.PI, 0, Math.PI / 6);
          }
        } else {
          crossroad.position.set(-(radius + 0.5 * roadLengthScale) / Math.sqrt(2) * roadWidth, 0, (radius + 0.5 * roadLengthScale) / Math.sqrt(2) * roadWidth);
        }
        break;
      case 2:
        crossroad.rotation.set(-0.5 * Math.PI, 0, 0.5 * Math.PI);
        if (shape === 6) {
          crossroad.position.set(0, 0, roadWidth * (radius + 0.5 * roadLengthScale));
        } else {
          crossroad.position.set(0, 0, (radius + 0.5 * roadLengthScale) * roadWidth);
        }
        break;
      case 3:
        crossroad.rotation.set(-0.5 * Math.PI, 0, 0.75 * Math.PI);
        if (shape === 4) {
          crossroad.position.set(radius * roadWidth * (1 + roadLengthScale) / Math.sqrt(2), 0, radius * roadWidth * (1 + roadLengthScale) / Math.sqrt(2))
        } else if (shape === 6) {
          if (roadType.every((v) => [1, 3, 4, 6, 7, 9].indexOf(v) >= 0)) {
            crossroad.position.set((roadLengthScale / 4 + radius / 2) * roadWidth, 0, roadWidth * ((roadLengthScale / 2 + radius) * radius));
            crossroad.rotation.set(-0.5 * Math.PI, 0, Math.PI * 2 / 3);
          } else {
            crossroad.position.set((roadLengthScale / 2 + 1) * radius * roadWidth - 1.5, 0, roadWidth * (roadLengthScale / 4 + radius / 2));
            crossroad.rotation.set(-0.5 * Math.PI, 0, Math.PI * 5 / 6);
          }
        } else {
          crossroad.position.set((radius + 0.5 * roadLengthScale) / Math.sqrt(2) * roadWidth, 0, (radius + 0.5 * roadLengthScale) / Math.sqrt(2) * roadWidth);
        }
        break;
      case 4:
        crossroad.rotation.set(-0.5 * Math.PI, 0, 0);
        if (shape === 6) {
          crossroad.position.set(-roadWidth * (radius + 0.5 * roadLengthScale), 0, 0);
        } else {
          crossroad.position.set(-(radius + 0.5 * roadLengthScale) * roadWidth, 0, 0);
        }
        break;
      case 6:
        crossroad.rotation.set(-0.5 * Math.PI, 0, -Math.PI);
        if (shape === 6) {
          crossroad.position.set(roadWidth * (radius + 0.5 * roadLengthScale), 0, 0);
        } else {
          crossroad.position.set((radius + 0.5 * roadLengthScale) * roadWidth, 0, 0);
        }
        break;
      case 7:
        crossroad.rotation.set(-0.5 * Math.PI, 0, -0.25 * Math.PI);
        if (shape === 4) {
          crossroad.position.set(-radius * roadWidth * (1 + roadLengthScale) / Math.sqrt(2), 0, -radius * roadWidth * (1 + roadLengthScale) / Math.sqrt(2))
        } else if (shape === 6) {
          if (roadType.every((v) => [1, 3, 4, 6, 7, 9].indexOf(v) >= 0)) {
            crossroad.position.set(-(roadLengthScale / 4 + radius / 2) * roadWidth, 0, -roadWidth * ((roadLengthScale / 2 + radius) * radius));
            crossroad.rotation.set(-0.5 * Math.PI, 0, -Math.PI / 3);
          } else {
            crossroad.position.set(-(roadLengthScale / 2 + 1) * radius * roadWidth + 1.5, 0, -roadWidth * (roadLengthScale / 4 + radius / 2));
            crossroad.rotation.set(-0.5 * Math.PI, 0, -Math.PI / 6);
          }
        } else {
          crossroad.position.set(-(radius + 0.5 * roadLengthScale) / Math.sqrt(2) * roadWidth, 0, -(radius + 0.5 * roadLengthScale) / Math.sqrt(2) * roadWidth);
        }
        break;
      case 8:
        crossroad.rotation.set(-0.5 * Math.PI, 0, -0.5 * Math.PI);
        if (shape === 6) {
          crossroad.position.set(0, 0, -roadWidth * (radius + 0.5 * roadLengthScale));
        } else {
          crossroad.position.set(0, 0, -(radius + 0.5 * roadLengthScale) * roadWidth);
        }
        break;
      case 9:
        crossroad.rotation.set(-0.5 * Math.PI, 0, -0.75 * Math.PI);
        if (shape === 4) {
          crossroad.position.set(radius * roadWidth * (1 + roadLengthScale) / Math.sqrt(2), 0, -radius * roadWidth * (1 + roadLengthScale) / Math.sqrt(2))
        } else if (shape === 6) {
          if (roadType.every((v) => [1, 3, 4, 6, 7, 9].indexOf(v) >= 0)) {
            crossroad.position.set((roadLengthScale / 4 + radius / 2) * roadWidth, 0, -roadWidth * ((roadLengthScale / 2 + radius) * radius));
            crossroad.rotation.set(-0.5 * Math.PI, 0, -Math.PI * 2 / 3);
          } else {
            crossroad.position.set((roadLengthScale / 2 + 1) * radius * roadWidth - 1.5, 0, -roadWidth * (roadLengthScale / 4 + radius / 2));
            crossroad.rotation.set(-0.5 * Math.PI, 0, -Math.PI * 5 / 6);
          }
        } else {
          crossroad.position.set((radius + 0.5 * roadLengthScale) / Math.sqrt(2) * roadWidth, 0, -(radius + 0.5 * roadLengthScale) / Math.sqrt(2) * roadWidth);
        }
        break;
      default:
        break;
    }
    if(shape === 4) crossroad.setLightPos({ x: (0.5 * roadLengthScale + 1 + 0.3) * roadWidth, y: -roadWidth / 2.3, z: 1.5 })
    if(shape === 6) crossroad.setLightPos({ x: (0.5 * roadLengthScale + 1 + 1.1) * roadWidth, y: -roadWidth / 2.3, z: 1.5 })
    if(shape === 8) crossroad.setLightPos({ x: (0.5 * roadLengthScale + 1 + 1.8) * roadWidth, y: -roadWidth / 2.3, z: 1.5 })
  },
  /** 获取路口形状,根据所选的路口,确定使用正四边形、正六边形 或 正八边形
   * @param: roadType: 方向集合,例 [2,4,6,8]
   * return 4|6|8
  */
  getCrossroadShape(roadType) {
    if (roadType.every((v) => { return [2, 4, 6, 8].indexOf(v) >= 0 }) || roadType.every((v) => { return [1, 3, 7, 9].indexOf(v) >= 0 })) {
      return 4
    } else if (roadType.every((v) => { return [1, 3, 4, 6, 7, 9].indexOf(v) >= 0 })
      || roadType.every((v) => { return [1, 2, 3, 7, 8, 9].indexOf(v) >= 0 })
            /*|| roadType.every(function(v){return [2,3,4,6,7,8].indexOf(v) >= 0})
            || roadType.every(function(v){return [1,2,4,6,8,9].indexOf(v) >= 0})*/) {
      return 6
    } else {
      return 8
    }
  },
  // 根据路口形状,填补中间处的空白
  getCenterRoad(shape, roadType) {
    let texture = ImgLoader.load("/static/scene/roadBg.png");	//图片路径
    texture.wrapT = THREE.RepeatWrapping;
    texture.wrapS = THREE.RepeatWrapping;
    let planeMaterial;
    let planeGeometry;
    let road;
    switch (shape) {
      case 4:
        texture.repeat.set(10, 10)
        planeMaterial = new THREE.MeshLambertMaterial({ map: texture })
        planeGeometry = new THREE.PlaneGeometry(roadWidth, roadWidth);
        road = new THREE.Mesh(planeGeometry, planeMaterial);
        road.rotation.set(-0.5 * Math.PI, 0, 0);
        if (roadType.every((v) => [1, 3, 7, 9].indexOf(v) >= 0)) {
          road.rotation.set(-0.5 * Math.PI, 0, 0.25 * Math.PI);
        }
        break;
      case 6:   // 此处的底图形状绘制非最佳方案,应参考八边形,待修改
        planeMaterial = new THREE.MeshLambertMaterial({ map: texture })
        var roadArr = []
        var offset;
        if (roadType.every((v) => [1, 3, 4, 6, 7, 9].indexOf(v) >= 0)) {
          roadArr = [
            null,
            { dir: 1, x: -0.5 * roadWidth, y: -0.25 * Math.sqrt(3) * roadWidth },
            { dir: 3, x: 0, y: 0.5 * roadWidth / Math.sqrt(3) - 0.5 * roadWidth * Math.sqrt(3) },
            { dir: 6, x: 0.5 * roadWidth, y: -0.25 * Math.sqrt(3) * roadWidth },
            { dir: 9, x: 0.5 * roadWidth, y: 0.25 * Math.sqrt(3) * roadWidth },
            { dir: 7, x: 0, y: 0.5 * roadWidth * Math.sqrt(3) - 0.5 * roadWidth / Math.sqrt(3) },
            { dir: 4, x: -0.5 * roadWidth, y: 0.25 * Math.sqrt(3) * roadWidth },
          ]
          offset = [1, 3, 6, 9, 7, 4].findIndex(v => roadType.indexOf(v) > -1)
        } else {
          roadArr = [
            null,
            { dir: 1, x: -0.5 * roadWidth, y: -0.25 * Math.sqrt(3) * roadWidth },
            { dir: 2, x: 0, y: 0.5 * roadWidth / Math.sqrt(3) - 0.5 * roadWidth * Math.sqrt(3) },
            { dir: 3, x: 0.5 * roadWidth, y: -0.25 * Math.sqrt(3) * roadWidth },
            { dir: 9, x: 0.5 * roadWidth, y: 0.25 * Math.sqrt(3) * roadWidth },
            { dir: 8, x: 0, y: 0.5 * roadWidth * Math.sqrt(3) - 0.5 * roadWidth / Math.sqrt(3) },
            { dir: 7, x: -0.5 * roadWidth, y: 0.25 * Math.sqrt(3) * roadWidth },
          ]
          offset = [1, 2, 3, 9, 7, 8].findIndex(v => roadType.indexOf(v) > -1)
        }
        var points = [  // 从方向1的左侧开始
          { x: -roadWidth, y: 0 },
          { x: -0.5 * roadWidth, y: -0.5 * Math.sqrt(3) * roadWidth },
          { x: 0.5 * roadWidth, y: -0.5 * Math.sqrt(3) * roadWidth },
          { x: roadWidth, y: 0 },
          { x: 0.5 * roadWidth, y: 0.5 * Math.sqrt(3) * roadWidth },
          { x: -0.5 * roadWidth, y: 0.5 * Math.sqrt(3) * roadWidth },
        ]
        points = points.splice(offset).concat(points)
        let _arr = roadArr.splice(offset + 1)
        roadArr.splice(1, 0, ..._arr)
        var roadShape = new THREE.Shape();
        roadArr.forEach((v, i, arr) => {
          if (i === 0) {
            roadShape.moveTo(points[0].x, points[0].y);
          } else {
            let road = v;
            let index = i % 6
            let lastIndex = (i + 4) % 6 + 1 // 当前方向的上一方向
            let secondIndex = (index + 1) % 7 // 当前方向的下一方向
            let thirdIndex = secondIndex % 6 + 1 // 当前方向的下二方向
            let fourthIndex = thirdIndex % 6 + 1 // 当前方向的下三方向

            let target = points[index]
            if (!roadType.find(v => v === road.dir)) { // 当前方向没有车道
              if (!roadType.find(v => v === roadArr[secondIndex].dir)) {  // 判断下一个方向是否有车道, 连续两个方向没有车道时
                if (!roadType.find(v => v === roadArr[thirdIndex].dir)) {
                  if (!roadType.find(v => v === roadArr[fourthIndex].dir)) { // 连续四个方向没有车道
                    let second = roadArr[secondIndex]
                    let third = roadArr[thirdIndex]
                    roadShape.quadraticCurveTo((second.x + third.x) / 2, (second.y + third.y) / 2, points[fourthIndex % 6].x, points[fourthIndex % 6].y);
                  } else { // 连续三个方向没有车道
                    roadShape.quadraticCurveTo(roadArr[secondIndex].x, roadArr[secondIndex].y, points[thirdIndex % 6].x, points[thirdIndex % 6].y);
                  }
                } else {
                  return;
                }
              } else if (!roadType.find(v => v === roadArr[lastIndex].dir)) {
                roadShape.lineTo(target.x, target.y);
              } else {
                roadShape.quadraticCurveTo(road.x, road.y, target.x, target.y);
              }
            } else {
              roadShape.lineTo(target.x, target.y);
            }
          }
        })
        planeGeometry = new THREE.ShapeGeometry(roadShape)
        road = new THREE.Mesh(planeGeometry, planeMaterial)
        road.rotation.set(-0.5 * Math.PI, 0, 0);
        if (roadType.every((v) => [1, 3, 4, 6, 7, 9].indexOf(v) >= 0)) {
          road.rotation.set(-0.5 * Math.PI, 0, Math.PI / 6);
        }
        break;
      case 8:
        planeMaterial = new THREE.MeshLambertMaterial({ map: texture })
        var points = [  // 从方向1的左侧开始
          { x: -(0.5 + 1 / Math.sqrt(2)) * roadWidth, y: -0.5 * roadWidth },
          { x: -0.5 * roadWidth, y: -(0.5 + 1 / Math.sqrt(2)) * roadWidth },
          { x: 0.5 * roadWidth, y: -(0.5 + 1 / Math.sqrt(2)) * roadWidth },
          { x: (0.5 + 1 / Math.sqrt(2)) * roadWidth, y: -0.5 * roadWidth },
          { x: (0.5 + 1 / Math.sqrt(2)) * roadWidth, y: 0.5 * roadWidth },
          { x: 0.5 * roadWidth, y: (0.5 + 1 / Math.sqrt(2)) * roadWidth },
          { x: -0.5 * roadWidth, y: (0.5 + 1 / Math.sqrt(2)) * roadWidth },
          { x: -(0.5 + 1 / Math.sqrt(2)) * roadWidth, y: 0.5 * roadWidth },
        ]
        var roadArr = [
          null,
          { dir: 1, x: -0.5 * roadWidth, y: -0.5 * roadWidth },
          { dir: 2, x: 0, y: -1 / Math.sqrt(2) * roadWidth },
          { dir: 3, x: 0.5 * roadWidth, y: -0.5 * roadWidth },
          { dir: 6, x: 1 / Math.sqrt(2) * roadWidth, y: 0 },
          { dir: 9, x: 0.5 * roadWidth, y: 0.5 * roadWidth },
          { dir: 8, x: 0, y: 1 / Math.sqrt(2) * roadWidth },
          { dir: 7, x: -0.5 * roadWidth, y: 0.5 * roadWidth },
          { dir: 4, x: -1 / Math.sqrt(2) * roadWidth, y: 0 },
        ]
        var offset = [1, 2, 3, 6, 9, 7, 8, 4].findIndex(v => roadType.indexOf(v) > -1)
        points = points.splice(offset).concat(points)
        var _arr = roadArr.splice(offset + 1)
        roadArr.splice(1, 0, ..._arr)
        var roadShape = new THREE.Shape()
        let sites = []
        roadArr.forEach((road, i, arr) => {
          let index = i % 8
          let target = points[index]
          if (i === 0) {
            sites.push({ x: points[0].x, y: points[0].y })
          } else {
            if (!roadType.find(v => v === road.dir)) { // 当前方向没有车道
              let offsetX = road.x
              let offsetY = road.y
              if (sites[sites.length - 1].noLane) {  // 连续的无车道方向
                sites.pop()
                let startIndex = points.findIndex(v => v.x === sites[sites.length - 1].x && v.y === sites[sites.length - 1].y)
                let endIndex = points.findIndex(v => v.x === target.x && v.y === target.y) || 8
                offsetX = (arr[startIndex + 1].x + arr[endIndex].x) / 2
                offsetY = (arr[startIndex + 1].y + arr[endIndex].y) / 2
              }
              sites.push({ x: target.x, y: target.y, type: "curve", noLane: true, offsetX: offsetX, offsetY: offsetY })
            } else {
              sites.push({ x: target.x, y: target.y, type: "straight" })
            }
          }
        })
        sites.forEach((site, i) => {
          if (i === 0) {
            roadShape.moveTo(site.x, site.y)
          } else if (site.type === 'curve') {
            roadShape.quadraticCurveTo(site.offsetX, site.offsetY, site.x, site.y);
          } else {
            roadShape.lineTo(site.x, site.y);
          }
        })
        planeGeometry = new THREE.ShapeGeometry(roadShape);
        road = new THREE.Mesh(planeGeometry, planeMaterial)
        road.rotation.set(-0.5 * Math.PI, 0, 0);
        window.SceneApp.scene.add(road);
        break;
      default:
        break;
    };
    road.receiveShadow = true;
    road.name = 'centerRoad';
    return road
  },
  // 根据路口形状,绘制装饰物
  drawDecoration(scene, shape, roadType) {
    if (roadType.every((v) => [2, 4, 6, 8].indexOf(v) >= 0)) {
      let build = createBuild({ x: roadWidth * 3.5, y: roadWidth * 1.5, z: roadWidth * 3.5 }, { x: 0, y: -1 * Math.PI, z: 0 });
      scene.add(build)
      build = createBuild({ x: roadWidth * -3.5, y: roadWidth * 1.5, z: roadWidth * 3.5 }, { x: 0, y: 0.5 * Math.PI, z: 0 });
      scene.add(build)
      build = createBuild({ x: roadWidth * 3.5, y: roadWidth * 1.5, z: roadWidth * -3.5 }, { x: 0, y: -0.5 * Math.PI, z: 0 });
      scene.add(build)
      build = createBuild({ x: roadWidth * -3.5, y: roadWidth * 1.5, z: roadWidth * -3.5 }, { x: 0, y: -2 * Math.PI, z: 0 });
      scene.add(build)
    } else if (roadType.every((v) => [1, 3, 7, 9].indexOf(v) >= 0)) {
      let build = createBuild({ x: roadWidth * -3.5 * Math.sqrt(2), y: roadWidth * 1.5, z: 0 }, { x: 0, y: 0.25 * Math.PI, z: 0 });
      scene.add(build)
      build = createBuild({ x: 0, y: roadWidth * 1.5, z: roadWidth * 3.5 * Math.sqrt(2) }, { x: 0, y: 0.75 * Math.PI, z: 0 });
      scene.add(build)
      build = createBuild({ x: roadWidth * 3.5 * Math.sqrt(2), y: roadWidth * 1.5, z: 0 }, { x: 0, y: -0.75 * Math.PI, z: 0 });
      scene.add(build)
      build = createBuild({ x: 0, y: roadWidth * 1.5, z: roadWidth * -3.5 * Math.sqrt(2) }, { x: 0, y: -0.25 * Math.PI, z: 0 });
      scene.add(build)
    } else {
      let roadTexture = ImgLoader.load("/static/scene/road.jpg");	//图片路径
      roadTexture.wrapT = THREE.RepeatWrapping;
      roadTexture.wrapS = THREE.RepeatWrapping;
      roadTexture.repeat.set(30, 30);
      let roadMaterial = new THREE.MeshLambertMaterial({ map: roadTexture });
      let roadGeometry = new THREE.PlaneGeometry(roadWidth * roadLengthScale * 2.5, roadWidth * roadLengthScale * 2.5);
      let road = new THREE.Mesh(roadGeometry, roadMaterial);
      road.rotation.set(-0.5 * Math.PI, 0, 0);
      road.position.set(0, -0.1, 0)
      road.receiveShadow = true;
      road.name = "decorations"
      scene.add(road)
    }
  },
  // 创建方向标注
  createDirTitle(scene) {
    var spriteMaterial = new THREE.SpriteMaterial({ map: ImgLoader.load("/static/scene/dirN.png") });
    var sprite = new THREE.Sprite(spriteMaterial);
    sprite.scale.set(2, 2, 2)
    sprite.position.set(0, 2, -1.8 * roadWidth)
    scene.add(sprite);
  },
  // 画车道线
  drawLane(laneList, crossroad) {
    // 人行道
    const pavement = laneList.find((v) => {
      return v.type === "pavement"
    })
    let zebra = this.findAllChildrenMesh(crossroad).find((v) => { return v.name === 'zebra' })
    if (zebra) {
      zebra.userData = pavement
      zebra.targetMesh(!!pavement)
    }

    // 车道
    const _laneList = laneList.filter((v) => {
      return v.type !== "pavement"
    })
    const laneNum = _laneList.length
    _laneList.forEach((lane, index) => {
      let i = index + 1
      if (i < laneNum) {
        let lineWidth = roadWidth / 5
        let lineGeometry = new THREE.PlaneGeometry(lineWidth, roadWidth / 150);
        let lineMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff });
        let line = new THREE.Mesh(lineGeometry, lineMaterial);
        line.position.set(0.5 * roadWidth * roadLengthScale - lineWidth - 0.3, -i * roadWidth / 2 / laneNum, 0.05);
        line.name = "laneLine";
        crossroad.add(line);
      }
      // 加箭头
      let arrow = createArrow(lane.type, laneNum);
      arrow.position.set(0.5 * roadWidth * roadLengthScale - 2.75, (0.5 - i) * roadWidth / 2 / laneNum, 0.05);
      arrow.userData = lane
      crossroad.add(arrow);
    })
  },
  // 画信号灯
  drawLight(channels, crossroad) {
    // 行人通道
    let passageChannel = channels.find((v) => {
      return v.type == 31
    })
    let passageMesh = this.findAllChildrenMesh(crossroad).find((v) => { return v.name === 'passageChannel' })
    if(passageMesh) {
      passageMesh.userData = passageChannel
      passageMesh.targetMesh(!!passageChannel)
    }

    let _channels = channels.filter((v) => {
      return v.type != 31
    })
    var light = createLight(_channels);  // 返回灯杆主体
    crossroad.add(light);
    crossroad.setLightPos();
  },
  // 绘制路口名称
  drawRoadName(parent, text = "", width = 4, height = 1) {
    const base = 64
    width = width * base
    height = height * base
    let bgColor = "#fff"
    let font = {
      size: 30,
      color: '#000'
    }
    let canvas = document.createElement('canvas');
    let ctx = canvas.getContext('2d');
    canvas.width = width;
    canvas.height = height;
    ctx.fillStyle = bgColor;
    ctx.fillRect(0, 0, width, height);
    ctx.font = font.size + 'px " bold';
    ctx.fillStyle = font.color;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(text, width / 2, height / 2, width);
    let texture = new THREE.CanvasTexture(canvas)
    var spriteMaterial = new THREE.SpriteMaterial({ map: texture });
    var sprite = new THREE.Sprite(spriteMaterial);
    sprite.name = "roadName"
    sprite.scale.set(width / base * 2, height / base * 2)
    sprite.position.set((0.5 * roadLengthScale - 1) * roadWidth, 0, 1);
    let _nameSprite = parent.children.find(v => v.name === "roadName")    // 删除原来的道路名,更好的方式应该是更换材质,待修改
    if (_nameSprite) parent.remove(_nameSprite)
    if (!text) return;
    parent.add(sprite)
  },
}

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务