whyczyk
2021-04-27 4fb5dc7b3680da8a767fddf82f27b5bf552b4a36
3d机房提交
21个文件已修改
11个文件已添加
2018 ■■■■■ 已修改文件
package.json 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/AFE/behind.jpg 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/AFE/fore.jpg 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/AFE/left.jpg 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/AFE/top.jpg 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/adjustSpeed/fore.png 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/distribution/behind.jpg 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/distribution/fore.jpg 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/distribution/left.jpg 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/distribution/top.jpg 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/rectifier/behind.png 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/rectifier/left.png 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/rectifier/right.png 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/rectifier/top.png 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/switchStation/behind.jpg 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/switchStation/fore.jpg 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/switchStation/left.jpg 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/switchStation/top.jpg 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/torque/fore.png 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/torque/left.png 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/torque/right.png 补丁 | 查看 | 原始文档 | blame | 历史
public/three/images/torque/top.png 补丁 | 查看 | 原始文档 | blame | 历史
public/three/models/electric.stl 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/three/InitThree.js 89 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/three/data.js 305 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/three/plugin/three-obj-mtl-loader.js 1368 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PageMenu.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/smallModule/DiagramPanel.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/home/topoGraphdiagram/images/dynamometry.png 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/home/topoGraphdiagram/images/electric.png 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/room.vue 209 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/user.js 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -7,15 +7,15 @@
    "build": "vue-cli-service build"
  },
  "dependencies": {
    "@types/three": "^0.103.2",
    "axios": "^0.19.2",
    "core-js": "^3.6.5",
    "element-ui": "^2.13.2",
    "postcss-px2rem": "^0.3.0",
    "three": "^0.111.0",
    "vue": "^2.6.11",
    "vue-router": "^3.2.0",
    "vuex": "^3.4.0",
    "three": "^0.111.0",
    "@types/three": "^0.103.2"
    "vuex": "^3.4.0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
public/three/images/AFE/behind.jpg
public/three/images/AFE/fore.jpg
public/three/images/AFE/left.jpg
public/three/images/AFE/top.jpg
public/three/images/adjustSpeed/fore.png
public/three/images/distribution/behind.jpg

public/three/images/distribution/fore.jpg

public/three/images/distribution/left.jpg

public/three/images/distribution/top.jpg

public/three/images/rectifier/behind.png

public/three/images/rectifier/left.png

public/three/images/rectifier/right.png

public/three/images/rectifier/top.png

public/three/images/switchStation/behind.jpg

public/three/images/switchStation/fore.jpg

public/three/images/switchStation/left.jpg

public/three/images/switchStation/top.jpg

public/three/images/torque/fore.png
public/three/images/torque/left.png
public/three/images/torque/right.png
public/three/images/torque/top.png
public/three/models/electric.stl
Binary files differ
src/assets/js/three/InitThree.js
@@ -3,11 +3,10 @@
 * @Autor: ZengYK
 * @Date: 2021-01-13 09:45:45
 */
import {
  _
} from "core-js";
import * as THREE from 'three'
import "three/examples/js/controls/OrbitControls"
import "three/examples/js/controls/TransformControls"
import "three/examples/js/loaders/STLLoader"
import "./plugin/DragControls"
import {
  loadBSP
@@ -169,7 +168,8 @@
    _this.renderer.shadowMap.enabled = true; //
    _this.renderer.shadowMapSoft = true;
    _this.renderer.domElement.addEventListener('mousedown', (e) => {
      _this.onDocumentMouseDown(e)
      _this.onDocumentMouseDown(e);
      _this.hidePanel(e);
    }, false);
    _this.renderer.domElement.addEventListener('mouseup', (e) => {
      _this.onDocumentMouseUp(e)
@@ -337,6 +337,7 @@
  }
  //循环渲染界面
  animation(start) {
    // console.log(this.scene)
    if (start) {
      console.log('已经启动持续更新');
      this.startState = true;
@@ -407,6 +408,9 @@
        case 'channel':
          _tempObj = _this.createChannelGeometry(_this, _obj);
          _this.addObject(_tempObj);
          break;
        case 'OBJLoader':
          _tempObj = _this.createOBJLoader(_this, _obj);
          break;
        case 'plane':
          _tempObj = _this.createPlaneGeometry(_this, _obj);
@@ -1007,9 +1011,49 @@
    var channel = new THREE.Mesh(tubeGeometry, tubeMaterial);
    // 使用加减法可以设置不同的运动方向
    setInterval(() => {
      texture.offset.x += 0.0076
      texture.offset.x -= 0.0076
    })
    return channel;
  }
  //加载OBJ模型
  createOBJLoader(_this, _obj) {
    var _this = this;
    var STLLoader = new THREE.STLLoader();
    let scala = _obj.scala || 1;
    STLLoader.load(_obj.url, function (geometry) {
      var material = new THREE.MeshPhongMaterial({
        color: 0xe7e7e7,
        specular: 'gray',
        shininess: 10
      });
      var mesh = new THREE.Mesh(geometry, material);
      // object.scale.multiplyScalar(scala); // 缩放模型大小
      mesh.name = _obj.name;
      mesh.uuid = _obj.uuid;
      mesh.position.x = _obj.x;
      mesh.position.y = _obj.y;
      mesh.position.z = _obj.z;
      if (_obj.rotation != null && typeof (_obj.rotation) != 'undefined' && _obj.rotation.length > 0) {
        _obj.rotation.forEach(function (v, i) {
          switch (v.direction) {
            case 'x':
              mesh.rotateX(v.degree);
              break;
            case 'y':
              mesh.rotateY(v.degree);
              break;
            case 'z':
              mesh.rotateZ(v.degree);
              break;
            case 'arb':
              mesh.rotateOnAxis(new THREE.Vector3(v.degree[0], v.degree[1], v.degree[2]), v.degree[3]);
              break;
          }
        })
      }
      _this.addObject(mesh);
    })
  }
  //创建二维平面-长方形
  createPlaneGeometry(_this, _obj) {
@@ -1381,11 +1425,11 @@
          _this.eventList.dbclick.forEach(function (v, i) {
            if ("string" == typeof (v.obj_name)) {
              if (v.obj_name == _this.SELECTED.name) {
                v.obj_event(_this.SELECTED, _this);
                v.obj_event(_this.SELECTED, event);
              }
            } else if (v.findObject != null || 'function' == typeof (v.findObject)) {
              if (v.findObject(_this.SELECTED.name)) {
                v.obj_event(_this.SELECTED, _this);
                v.obj_event(_this.SELECTED, event);
              }
            }
          })
@@ -1398,9 +1442,12 @@
  onDocumentMouseUp(event) {
    var _this = this;
    event.preventDefault();
    let getBoundingClientRect = this.element.getBoundingClientRect()
    //通过鼠标点击的位置计算出raycaster所需要的点的位置,以屏幕中心为原点,值的范围为-1到1.
    _this.mouseClick.x = (event.clientX / _this.width) * 2 - 1;
    _this.mouseClick.y = -(event.clientY / _this.height) * 2 + 1;
    // _this.mouseClick.x = (event.clientX / _this.width) * 2 - 1;
    // _this.mouseClick.y = -(event.clientY / _this.height) * 2 + 1;
    _this.mouseClick.x = ((event.clientX - getBoundingClientRect.left) / this.element.offsetWidth) * 2 - 1; // 标准设备横坐标
    _this.mouseClick.y = -((event.clientY - getBoundingClientRect.top) / this.element.offsetHeight) * 2 + 1; // 标准设备纵坐标
    // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
    _this.raycaster.setFromCamera(_this.mouseClick, _this.camera);
    // 获取raycaster直线和所有模型相交的数组集合
@@ -1415,4 +1462,28 @@
      _this.controls.enabled = true;
    }
  }
  //隐藏面板
  hidePanel(event) {
    var _this = this;
    event.preventDefault();
    let getBoundingClientRect = this.element.getBoundingClientRect()
    //通过鼠标点击的位置计算出raycaster所需要的点的位置,以屏幕中心为原点,值的范围为-1到1.
    // _this.mouseClick.x = (event.clientX / _this.width) * 2 - 1;
    // _this.mouseClick.y = -(event.clientY / _this.height) * 2 + 1;
    _this.mouseClick.x = ((event.clientX - getBoundingClientRect.left) / this.element.offsetWidth) * 2 - 1; // 标准设备横坐标
    _this.mouseClick.y = -((event.clientY - getBoundingClientRect.top) / this.element.offsetHeight) * 2 + 1; // 标准设备纵坐标
    // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
    _this.raycaster.setFromCamera(_this.mouseClick, _this.camera);
    // 获取raycaster直线和所有模型相交的数组集合
    var intersects = _this.raycaster.intersectObjects(_this.objects, true);
    if (intersects.length > 0) {
      //先通过当前点击位置的坐标和相机计算出raycaster线,然后计算出相交的所有模型,修改模型参数。
      _this.controls.enabled = false;
      _this.SELECTED = intersects[0].object;
      if (_this.eventList != null && _this.eventList.hidePanel != null) {
        _this.eventList.hidePanel.obj_event(_this.SELECTED, event);
      }
      _this.controls.enabled = true;
    }
  }
}
src/assets/js/three/data.js
@@ -4,7 +4,6 @@
 * @Date: 2021-01-12 09:39:43
 */
const floorB = require('../../../../public/three/images/floor3.jpg');
const aircondition = require("../../../../public/three/images/aircondition.png");
const switchStationBehind = require("../../../../public/three/images/switchStation/behind.jpg");
const switchStationFore = require("../../../../public/three/images/switchStation/fore.jpg");
const switchStationLeft = require("../../../../public/three/images/switchStation/left.jpg");
@@ -18,7 +17,17 @@
const distributionLeft = require("../../../../public/three/images/distribution/left.jpg");
const distributionRight = require("../../../../public/three/images/distribution/right.jpg");
const distributionTop = require("../../../../public/three/images/distribution/top.jpg");
const adjustSpeed = require("../../../../public/three/images/adjustSpeed/fore.png");
const torqueFore = require("../../../../public/three/images/torque/fore.png");
const torqueLeft = require("../../../../public/three/images/torque/left.png");
const torqueRight = require("../../../../public/three/images/torque/right.png");
const torqueTop = require("../../../../public/three/images/torque/top.png");
const AFEbehind = require("../../../../public/three/images/AFE/behind.jpg");
const AFEfore = require("../../../../public/three/images/AFE/fore.jpg");
const AFEleft = require("../../../../public/three/images/AFE/left.jpg");
const AFEtop = require("../../../../public/three/images/AFE/top.jpg");
const channel = require("../../../../public/three/images/channel.jpg");
const electric = "./three/models/electric.stl";
let Aobjects = {
  objects: [
    //地板
@@ -71,13 +80,13 @@
      radius: 6,
      closed: true,
      path: [{
        x: 0,
        x: 50,
        y: 40,
        z: 1200
        z: 900
      }, {
        x: 0,
        x: 50,
        y: 40,
        z: 485
        z: 490
      }],
      imgurl: channel,
    },
@@ -88,14 +97,104 @@
      objType: 'channel',
      radius: 6,
      closed: true,
      path: [, {
        x: 0,
      path: [{
        x: 50,
        y: 40,
        z: 500
      }, , {
      }, {
        x: 1000,
        y: 40,
        z: 500
      }],
      imgurl: channel,
    },
    {
      show: true,
      name: 'channel3',
      uuid: "",
      objType: 'channel',
      radius: 6,
      closed: true,
      path: [{
        x: 1000,
        y: 40,
        z: 500
      }, {
        x: 1000,
        y: 40,
        z: -500
      }],
      imgurl: channel,
    },
    {
      show: true,
      name: 'channel4',
      uuid: "",
      objType: 'channel',
      radius: 6,
      closed: true,
      path: [{
        x: 1000,
        y: 40,
        z: -500
      }, {
        x: -1000,
        y: 40,
        z: -500
      }],
      imgurl: channel,
    },
    {
      show: true,
      name: 'channel5',
      uuid: "",
      objType: 'channel',
      radius: 6,
      closed: true,
      path: [{
        x: -1000,
        y: 40,
        z: -500
      }, {
        x: -1000,
        y: 40,
        z: 500
      }],
      imgurl: channel,
    },
    {
      show: true,
      name: 'channel6',
      uuid: "",
      objType: 'channel',
      radius: 6,
      closed: true,
      path: [{
        x: -1000,
        y: 40,
        z: 500
      }, {
        x: -34,
        y: 40,
        z: 500
      }],
      imgurl: channel,
    },
    {
      show: true,
      name: 'channel7',
      uuid: "",
      objType: 'channel',
      radius: 6,
      closed: true,
      path: [{
        x: -50,
        y: 40,
        z: 500
      }, {
        x: -50,
        y: 40,
        z: 900
      }],
      imgurl: channel,
    },
@@ -114,7 +213,7 @@
      }], //旋转 表示x方向0度
      x: 0,
      y: 100,
      z: 1200,
      z: 900,
      style: {
        skinColor: 0xfefefe,
        skin: {
@@ -159,7 +258,7 @@
        degree: 0 * Math.PI
      }], //旋转 表示x方向0度
      x: 1000,
      y: 100,
      y: 80,
      z: 500,
      style: {
        skinColor: 0xfefefe,
@@ -196,7 +295,7 @@
      uuid: "",
      name: 'distribution',
      objType: 'cube',
      length: 90,
      length: 80,
      width: 180,
      height: 160,
      rotation: [{
@@ -204,7 +303,7 @@
        degree: 0.5 * Math.PI
      }], //旋转 表示x方向0度
      x: 1000,
      y: 100,
      y: 80,
      z: 0,
      style: {
        skinColor: 0xfefefe,
@@ -235,47 +334,204 @@
        }
      }
    },
    //配电器
    //调速柜
    {
      show: true,
      uuid: "",
      name: 'distribution2',
      name: 'adjustSpeed',
      objType: 'cube',
      length: 90,
      width: 180,
      height: 160,
      length: 50,
      width: 140,
      height: 100,
      rotation: [{
        direction: 'y',
        degree: 0.5 * Math.PI
      }], //旋转 表示x方向0度
      x: 1000,
      y: 100,
      y: 50,
      z: -500,
      style: {
        skinColor: 0xe7e7e7,
        skin: {
          skin_fore: {
            imgurl: adjustSpeed,
          },
        }
      }
    },
    //电机
    {
      show: true,
      uuid: "",
      name: 'electric',
      objType: 'OBJLoader',
      url: electric,
      rotation: [{
        direction: 'y',
        degree: 0.5 * Math.PI
      }], //旋转 表示x方向0度
      scala: 0.5,
      x: 400,
      y: 10,
      z: -345
    },
    //扭矩转速柜
    {
      show: true,
      uuid: "",
      name: 'torque',
      objType: 'cube',
      length: 80,
      width: 80,
      height: 80,
      rotation: [{
        direction: 'y',
        degree: 0.5 * Math.PI
      }], //旋转 表示x方向0度
      x: -400,
      y: 50,
      z: -500,
      style: {
        skinColor: 0xfefefe,
        skin: {
          skin_fore: {
            skinColor: 0xfefefe,
            imgurl: distributionFore,
            imgurl: torqueFore,
          },
          skin_behind: {
            skinColor: 0xfefefe,
            imgurl: distributionBehind,
            imgurl: torqueLeft,
          },
          skin_down: {
            skinColor: 0xfefefe,
            imgurl: torqueTop,
          },
          skin_up: {
            skinColor: 0xfefefe,
            imgurl: torqueTop,
          },
          skin_left: {
            skinColor: 0xfefefe,
            imgurl: torqueLeft,
          },
          skin_right: {
            skinColor: 0xfefefe,
            imgurl: torqueRight,
          },
        }
      }
    },
    //测功机
    {
      show: true,
      uuid: "",
      name: 'adjustSpeed4',
      objType: 'cube',
      length: 50,
      width: 140,
      height: 100,
      rotation: [{
        direction: 'y',
        degree: 0.5 * Math.PI
      }], //旋转 表示x方向0度
      x: -1000,
      y: 50,
      z: -500,
      style: {
        skinColor: 0xe7e7e7,
        skin: {
          skin_fore: {
            imgurl: adjustSpeed,
          },
        }
      }
    },
    //AFE
    {
      show: true,
      uuid: "",
      name: 'AFE',
      objType: 'cube',
      length: 80,
      width: 180,
      height: 160,
      rotation: [{
        direction: 'y',
        degree: 0.5 * Math.PI
      }], //旋转 表示x方向0度
      x: -1000,
      y: 80,
      z: 0,
      style: {
        skinColor: 0xfefefe,
        skin: {
          skin_fore: {
            skinColor: 0xfefefe,
            imgurl: AFEfore,
          },
          skin_behind: {
            skinColor: 0xfefefe,
            imgurl: AFEbehind,
          },
          skin_down: {
            skinColor: 0xfefefe,
          },
          skin_up: {
            skinColor: 0xfefefe,
            imgurl: distributionTop,
            imgurl: AFEtop,
          },
          skin_left: {
            skinColor: 0xfefefe,
            imgurl: distributionLeft,
            imgurl: AFEleft,
          },
          skin_right: {
            skinColor: 0xfefefe,
            imgurl: distributionRight,
            imgurl: AFEleft,
          },
        }
      }
    },
    //变压器
    {
      show: true,
      uuid: "",
      name: 'rectifier',
      objType: 'cube',
      length: 177,
      width: 84,
      height: 160,
      rotation: [{
        direction: 'y',
        degree: 0 * Math.PI
      }], //旋转 表示x方向0度
      x: -1000,
      y: 80,
      z: 500,
      style: {
        skinColor: 0xfefefe,
        skin: {
          skin_fore: {
            skinColor: 0xfefefe,
            imgurl: rectifierBehind,
          },
          skin_behind: {
            skinColor: 0xfefefe,
            imgurl: rectifierBehind,
          },
          skin_down: {
            skinColor: 0xfefefe,
          },
          skin_up: {
            skinColor: 0xfefefe,
            imgurl: rectifierTop,
          },
          skin_left: {
            skinColor: 0xfefefe,
            imgurl: rectifierLeft,
          },
          skin_right: {
            skinColor: 0xfefefe,
            imgurl: rectifierRight,
          },
        }
      }
@@ -286,7 +542,8 @@
    dbclick: [],
    mouseDown: {},
    mouseUp: {},
    mouseMove: {}
    mouseMove: {},
    hidePanel: {}
  },
}
src/assets/js/three/plugin/three-obj-mtl-loader.js
New file
@@ -0,0 +1,1368 @@
var THREE = require('three')
/**
 * Loads a Wavefront .mtl file specifying materials
 *
 * @author angelxuanchang
 */
THREE.MTLLoader = function (manager) {
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
};
THREE.MTLLoader.prototype = {
    constructor: THREE.MTLLoader,
    /**
     * Loads and parses a MTL asset from a URL.
     *
     * @param {String} url - URL to the MTL file.
     * @param {Function} [onLoad] - Callback invoked with the loaded object.
     * @param {Function} [onProgress] - Callback for download progress.
     * @param {Function} [onError] - Callback for download errors.
     *
     * @see setPath setTexturePath
     *
     * @note In order for relative texture references to resolve correctly
     * you must call setPath and/or setTexturePath explicitly prior to load.
     */
    load: function (url, onLoad, onProgress, onError) {
        var scope = this;
        var loader = new THREE.FileLoader(this.manager);
        loader.setPath(this.path);
        loader.load(url, function (text) {
            onLoad(scope.parse(text));
        }, onProgress, onError);
    },
    /**
     * Set base path for resolving references.
     * If set this path will be prepended to each loaded and found reference.
     *
     * @see setTexturePath
     * @param {String} path
     * @return {THREE.MTLLoader}
     *
     * @example
     *     mtlLoader.setPath( 'assets/obj/' );
     *     mtlLoader.load( 'my.mtl', ... );
     */
    setPath: function (path) {
        this.path = path;
        return this;
    },
    /**
     * Set base path for resolving texture references.
     * If set this path will be prepended found texture reference.
     * If not set and setPath is, it will be used as texture base path.
     *
     * @see setPath
     * @param {String} path
     * @return {THREE.MTLLoader}
     *
     * @example
     *     mtlLoader.setPath( 'assets/obj/' );
     *     mtlLoader.setTexturePath( 'assets/textures/' );
     *     mtlLoader.load( 'my.mtl', ... );
     */
    setTexturePath: function (path) {
        this.texturePath = path;
        return this;
    },
    setBaseUrl: function (path) {
        console.warn('THREE.MTLLoader: .setBaseUrl() is deprecated. Use .setTexturePath( path ) for texture path or .setPath( path ) for general base path instead.');
        return this.setTexturePath(path);
    },
    setCrossOrigin: function (value) {
        this.crossOrigin = value;
        return this;
    },
    setMaterialOptions: function (value) {
        this.materialOptions = value;
        return this;
    },
    /**
     * Parses a MTL file.
     *
     * @param {String} text - Content of MTL file
     * @return {THREE.MTLLoader.MaterialCreator}
     *
     * @see setPath setTexturePath
     *
     * @note In order for relative texture references to resolve correctly
     * you must call setPath and/or setTexturePath explicitly prior to parse.
     */
    parse: function (text) {
        var lines = text.split('\n');
        var info = {};
        var delimiter_pattern = /\s+/;
        var materialsInfo = {};
        for (var i = 0; i < lines.length; i++) {
            var line = lines[i];
            line = line.trim();
            if (line.length === 0 || line.charAt(0) === '#') {
                // Blank line or comment ignore
                continue;
            }
            var pos = line.indexOf(' ');
            var key = (pos >= 0) ? line.substring(0, pos) : line;
            key = key.toLowerCase();
            var value = (pos >= 0) ? line.substring(pos + 1) : '';
            value = value.trim();
            if (key === 'newmtl') {
                // New material
                info = {
                    name: value
                };
                materialsInfo[value] = info;
            } else if (info) {
                if (key === 'ka' || key === 'kd' || key === 'ks') {
                    var ss = value.split(delimiter_pattern, 3);
                    info[key] = [parseFloat(ss[0]), parseFloat(ss[1]), parseFloat(ss[2])];
                } else {
                    info[key] = value;
                }
            }
        }
        var materialCreator = new THREE.MTLLoader.MaterialCreator(this.texturePath || this.path, this.materialOptions);
        materialCreator.setCrossOrigin(this.crossOrigin);
        materialCreator.setManager(this.manager);
        materialCreator.setMaterials(materialsInfo);
        return materialCreator;
    }
};
/**
 * Create a new THREE-MTLLoader.MaterialCreator
 * @param baseUrl - Url relative to which textures are loaded
 * @param options - Set of options on how to construct the materials
 *                  side: Which side to apply the material
 *                        THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide
 *                  wrap: What type of wrapping to apply for textures
 *                        THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
 *                  normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
 *                                Default: false, assumed to be already normalized
 *                  ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
 *                                  Default: false
 * @constructor
 */
THREE.MTLLoader.MaterialCreator = function (baseUrl, options) {
    this.baseUrl = baseUrl || '';
    this.options = options;
    this.materialsInfo = {};
    this.materials = {};
    this.materialsArray = [];
    this.nameLookup = {};
    this.side = (this.options && this.options.side) ? this.options.side : THREE.FrontSide;
    this.wrap = (this.options && this.options.wrap) ? this.options.wrap : THREE.RepeatWrapping;
};
THREE.MTLLoader.MaterialCreator.prototype = {
    constructor: THREE.MTLLoader.MaterialCreator,
    crossOrigin: 'Anonymous',
    setCrossOrigin: function (value) {
        this.crossOrigin = value;
    },
    setManager: function (value) {
        this.manager = value;
    },
    setMaterials: function (materialsInfo) {
        this.materialsInfo = this.convert(materialsInfo);
        this.materials = {};
        this.materialsArray = [];
        this.nameLookup = {};
    },
    convert: function (materialsInfo) {
        if (!this.options) return materialsInfo;
        var converted = {};
        for (var mn in materialsInfo) {
            // Convert materials info into normalized form based on options
            var mat = materialsInfo[mn];
            var covmat = {};
            converted[mn] = covmat;
            for (var prop in mat) {
                var save = true;
                var value = mat[prop];
                var lprop = prop.toLowerCase();
                switch (lprop) {
                    case 'kd':
                    case 'ka':
                    case 'ks':
                        // Diffuse color (color under white light) using RGB values
                        if (this.options && this.options.normalizeRGB) {
                            value = [value[0] / 255, value[1] / 255, value[2] / 255];
                        }
                        if (this.options && this.options.ignoreZeroRGBs) {
                            if (value[0] === 0 && value[1] === 0 && value[2] === 0) {
                                // ignore
                                save = false;
                            }
                        }
                        break;
                    default:
                        break;
                }
                if (save) {
                    covmat[lprop] = value;
                }
            }
        }
        return converted;
    },
    preload: function () {
        for (var mn in this.materialsInfo) {
            this.create(mn);
        }
    },
    getIndex: function (materialName) {
        return this.nameLookup[materialName];
    },
    getAsArray: function () {
        var index = 0;
        for (var mn in this.materialsInfo) {
            this.materialsArray[index] = this.create(mn);
            this.nameLookup[mn] = index;
            index++;
        }
        return this.materialsArray;
    },
    create: function (materialName) {
        if (this.materials[materialName] === undefined) {
            this.createMaterial_(materialName);
        }
        return this.materials[materialName];
    },
    createMaterial_: function (materialName) {
        // Create material
        var scope = this;
        var mat = this.materialsInfo[materialName];
        var params = {
            name: materialName,
            side: this.side
        };
        function resolveURL(baseUrl, url) {
            if (typeof url !== 'string' || url === '')
                return '';
            // Absolute URL
            if (/^https?:\/\//i.test(url)) return url;
            return baseUrl + url;
        }
        function setMapForType(mapType, value) {
            if (params[mapType]) return; // Keep the first encountered texture
            var texParams = scope.getTextureParams(value, params);
            var map = scope.loadTexture(resolveURL(scope.baseUrl, texParams.url));
            map.repeat.copy(texParams.scale);
            map.offset.copy(texParams.offset);
            map.wrapS = scope.wrap;
            map.wrapT = scope.wrap;
            params[mapType] = map;
        }
        for (var prop in mat) {
            var value = mat[prop];
            var n;
            if (value === '') continue;
            switch (prop.toLowerCase()) {
                // Ns is material specular exponent
                case 'kd':
                    // Diffuse color (color under white light) using RGB values
                    params.color = new THREE.Color().fromArray(value);
                    break;
                case 'ks':
                    // Specular color (color when light is reflected from shiny surface) using RGB values
                    params.specular = new THREE.Color().fromArray(value);
                    break;
                case 'map_kd':
                    // Diffuse texture map
                    setMapForType("map", value);
                    break;
                case 'map_ks':
                    // Specular map
                    setMapForType("specularMap", value);
                    break;
                case 'norm':
                    setMapForType("normalMap", value);
                    break;
                case 'map_bump':
                case 'bump':
                    // Bump texture map
                    setMapForType("bumpMap", value);
                    break;
                case 'ns':
                    // The specular exponent (defines the focus of the specular highlight)
                    // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.
                    params.shininess = parseFloat(value);
                    break;
                case 'd':
                    n = parseFloat(value);
                    if (n < 1) {
                        params.opacity = n;
                        params.transparent = true;
                    }
                    break;
                case 'tr':
                    n = parseFloat(value);
                    if (this.options && this.options.invertTrProperty) n = 1 - n;
                    if (n > 0) {
                        params.opacity = 1 - n;
                        params.transparent = true;
                    }
                    break;
                default:
                    break;
            }
        }
        this.materials[materialName] = new THREE.MeshPhongMaterial(params);
        return this.materials[materialName];
    },
    getTextureParams: function (value, matParams) {
        var texParams = {
            scale: new THREE.Vector2(1, 1),
            offset: new THREE.Vector2(0, 0)
        };
        var items = value.split(/\s+/);
        var pos;
        pos = items.indexOf('-bm');
        if (pos >= 0) {
            matParams.bumpScale = parseFloat(items[pos + 1]);
            items.splice(pos, 2);
        }
        pos = items.indexOf('-s');
        if (pos >= 0) {
            texParams.scale.set(parseFloat(items[pos + 1]), parseFloat(items[pos + 2]));
            items.splice(pos, 4); // we expect 3 parameters here!
        }
        pos = items.indexOf('-o');
        if (pos >= 0) {
            texParams.offset.set(parseFloat(items[pos + 1]), parseFloat(items[pos + 2]));
            items.splice(pos, 4); // we expect 3 parameters here!
        }
        texParams.url = items.join(' ').trim();
        return texParams;
    },
    loadTexture: function (url, mapping, onLoad, onProgress, onError) {
        var texture;
        var loader = THREE.Loader.Handlers.get(url);
        var manager = (this.manager !== undefined) ? this.manager : THREE.DefaultLoadingManager;
        if (loader === null) {
            loader = new THREE.TextureLoader(manager);
        }
        if (loader.setCrossOrigin) loader.setCrossOrigin(this.crossOrigin);
        texture = loader.load(url, onLoad, onProgress, onError);
        if (mapping !== undefined) texture.mapping = mapping;
        return texture;
    }
};
/**
 * @author mrdoob / http://mrdoob.com/
 */
THREE.OBJLoader = (function () {
    // o object_name | g group_name
    var object_pattern = /^[og]\s*(.+)?/;
    // mtllib file_reference
    var material_library_pattern = /^mtllib /;
    // usemtl material_name
    var material_use_pattern = /^usemtl /;
    function ParserState() {
        var state = {
            objects: [],
            object: {},
            vertices: [],
            normals: [],
            colors: [],
            uvs: [],
            materialLibraries: [],
            startObject: function (name, fromDeclaration) {
                // If the current object (initial from reset) is not from a g/o declaration in the parsed
                // file. We need to use it for the first parsed g/o to keep things in sync.
                if (this.object && this.object.fromDeclaration === false) {
                    this.object.name = name;
                    this.object.fromDeclaration = (fromDeclaration !== false);
                    return;
                }
                var previousMaterial = (this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined);
                if (this.object && typeof this.object._finalize === 'function') {
                    this.object._finalize(true);
                }
                this.object = {
                    name: name || '',
                    fromDeclaration: (fromDeclaration !== false),
                    geometry: {
                        vertices: [],
                        normals: [],
                        colors: [],
                        uvs: []
                    },
                    materials: [],
                    smooth: true,
                    startMaterial: function (name, libraries) {
                        var previous = this._finalize(false);
                        // New usemtl declaration overwrites an inherited material, except if faces were declared
                        // after the material, then it must be preserved for proper MultiMaterial continuation.
                        if (previous && (previous.inherited || previous.groupCount <= 0)) {
                            this.materials.splice(previous.index, 1);
                        }
                        var material = {
                            index: this.materials.length,
                            name: name || '',
                            mtllib: (Array.isArray(libraries) && libraries.length > 0 ? libraries[libraries.length - 1] : ''),
                            smooth: (previous !== undefined ? previous.smooth : this.smooth),
                            groupStart: (previous !== undefined ? previous.groupEnd : 0),
                            groupEnd: -1,
                            groupCount: -1,
                            inherited: false,
                            clone: function (index) {
                                var cloned = {
                                    index: (typeof index === 'number' ? index : this.index),
                                    name: this.name,
                                    mtllib: this.mtllib,
                                    smooth: this.smooth,
                                    groupStart: 0,
                                    groupEnd: -1,
                                    groupCount: -1,
                                    inherited: false
                                };
                                cloned.clone = this.clone.bind(cloned);
                                return cloned;
                            }
                        };
                        this.materials.push(material);
                        return material;
                    },
                    currentMaterial: function () {
                        if (this.materials.length > 0) {
                            return this.materials[this.materials.length - 1];
                        }
                        return undefined;
                    },
                    _finalize: function (end) {
                        var lastMultiMaterial = this.currentMaterial();
                        if (lastMultiMaterial && lastMultiMaterial.groupEnd === -1) {
                            lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
                            lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;
                            lastMultiMaterial.inherited = false;
                        }
                        // Ignore objects tail materials if no face declarations followed them before a new o/g started.
                        if (end && this.materials.length > 1) {
                            for (var mi = this.materials.length - 1; mi >= 0; mi--) {
                                if (this.materials[mi].groupCount <= 0) {
                                    this.materials.splice(mi, 1);
                                }
                            }
                        }
                        // Guarantee at least one empty material, this makes the creation later more straight forward.
                        if (end && this.materials.length === 0) {
                            this.materials.push({
                                name: '',
                                smooth: this.smooth
                            });
                        }
                        return lastMultiMaterial;
                    }
                };
                // Inherit previous objects material.
                // Spec tells us that a declared material must be set to all objects until a new material is declared.
                // If a usemtl declaration is encountered while this new object is being parsed, it will
                // overwrite the inherited material. Exception being that there was already face declarations
                // to the inherited material, then it will be preserved for proper MultiMaterial continuation.
                if (previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function') {
                    var declared = previousMaterial.clone(0);
                    declared.inherited = true;
                    this.object.materials.push(declared);
                }
                this.objects.push(this.object);
            },
            finalize: function () {
                if (this.object && typeof this.object._finalize === 'function') {
                    this.object._finalize(true);
                }
            },
            parseVertexIndex: function (value, len) {
                var index = parseInt(value, 10);
                return (index >= 0 ? index - 1 : index + len / 3) * 3;
            },
            parseNormalIndex: function (value, len) {
                var index = parseInt(value, 10);
                return (index >= 0 ? index - 1 : index + len / 3) * 3;
            },
            parseUVIndex: function (value, len) {
                var index = parseInt(value, 10);
                return (index >= 0 ? index - 1 : index + len / 2) * 2;
            },
            addVertex: function (a, b, c) {
                var src = this.vertices;
                var dst = this.object.geometry.vertices;
                dst.push(src[a + 0], src[a + 1], src[a + 2]);
                dst.push(src[b + 0], src[b + 1], src[b + 2]);
                dst.push(src[c + 0], src[c + 1], src[c + 2]);
            },
            addVertexPoint: function (a) {
                var src = this.vertices;
                var dst = this.object.geometry.vertices;
                dst.push(src[a + 0], src[a + 1], src[a + 2]);
            },
            addVertexLine: function (a) {
                var src = this.vertices;
                var dst = this.object.geometry.vertices;
                dst.push(src[a + 0], src[a + 1], src[a + 2]);
            },
            addNormal: function (a, b, c) {
                var src = this.normals;
                var dst = this.object.geometry.normals;
                dst.push(src[a + 0], src[a + 1], src[a + 2]);
                dst.push(src[b + 0], src[b + 1], src[b + 2]);
                dst.push(src[c + 0], src[c + 1], src[c + 2]);
            },
            addColor: function (a, b, c) {
                var src = this.colors;
                var dst = this.object.geometry.colors;
                dst.push(src[a + 0], src[a + 1], src[a + 2]);
                dst.push(src[b + 0], src[b + 1], src[b + 2]);
                dst.push(src[c + 0], src[c + 1], src[c + 2]);
            },
            addUV: function (a, b, c) {
                var src = this.uvs;
                var dst = this.object.geometry.uvs;
                dst.push(src[a + 0], src[a + 1]);
                dst.push(src[b + 0], src[b + 1]);
                dst.push(src[c + 0], src[c + 1]);
            },
            addUVLine: function (a) {
                var src = this.uvs;
                var dst = this.object.geometry.uvs;
                dst.push(src[a + 0], src[a + 1]);
            },
            addFace: function (a, b, c, ua, ub, uc, na, nb, nc) {
                var vLen = this.vertices.length;
                var ia = this.parseVertexIndex(a, vLen);
                var ib = this.parseVertexIndex(b, vLen);
                var ic = this.parseVertexIndex(c, vLen);
                this.addVertex(ia, ib, ic);
                if (ua !== undefined && ua !== '') {
                    var uvLen = this.uvs.length;
                    ia = this.parseUVIndex(ua, uvLen);
                    ib = this.parseUVIndex(ub, uvLen);
                    ic = this.parseUVIndex(uc, uvLen);
                    this.addUV(ia, ib, ic);
                }
                if (na !== undefined && na !== '') {
                    // Normals are many times the same. If so, skip function call and parseInt.
                    var nLen = this.normals.length;
                    ia = this.parseNormalIndex(na, nLen);
                    ib = na === nb ? ia : this.parseNormalIndex(nb, nLen);
                    ic = na === nc ? ia : this.parseNormalIndex(nc, nLen);
                    this.addNormal(ia, ib, ic);
                }
                if (this.colors.length > 0) {
                    this.addColor(ia, ib, ic);
                }
            },
            addPointGeometry: function (vertices) {
                this.object.geometry.type = 'Points';
                var vLen = this.vertices.length;
                for (var vi = 0, l = vertices.length; vi < l; vi++) {
                    this.addVertexPoint(this.parseVertexIndex(vertices[vi], vLen));
                }
            },
            addLineGeometry: function (vertices, uvs) {
                this.object.geometry.type = 'Line';
                var vLen = this.vertices.length;
                var uvLen = this.uvs.length;
                for (var vi = 0, l = vertices.length; vi < l; vi++) {
                    this.addVertexLine(this.parseVertexIndex(vertices[vi], vLen));
                }
                for (var uvi = 0, l = uvs.length; uvi < l; uvi++) {
                    this.addUVLine(this.parseUVIndex(uvs[uvi], uvLen));
                }
            }
        };
        state.startObject('', false);
        return state;
    }
    //
    function OBJLoader(manager) {
        this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
        this.materials = null;
    }
    OBJLoader.prototype = {
        constructor: OBJLoader,
        load: function (url, onLoad, onProgress, onError) {
            var scope = this;
            var loader = new THREE.FileLoader(scope.manager);
            loader.setPath(this.path);
            loader.load(url, function (text) {
                onLoad(scope.parse(text));
            }, onProgress, onError);
        },
        setPath: function (value) {
            this.path = value;
            return this;
        },
        setMaterials: function (materials) {
            this.materials = materials;
            return this;
        },
        parse: function (text) {
            console.time('OBJLoader');
            var state = new ParserState();
            if (text.indexOf('\r\n') !== -1) {
                // This is faster than String.split with regex that splits on both
                text = text.replace(/\r\n/g, '\n');
            }
            if (text.indexOf('\\\n') !== -1) {
                // join lines separated by a line continuation character (\)
                text = text.replace(/\\\n/g, '');
            }
            var lines = text.split('\n');
            var line = '',
                lineFirstChar = '';
            var lineLength = 0;
            var result = [];
            // Faster to just trim left side of the line. Use if available.
            var trimLeft = (typeof ''.trimLeft === 'function');
            for (var i = 0, l = lines.length; i < l; i++) {
                line = lines[i];
                line = trimLeft ? line.trimLeft() : line.trim();
                lineLength = line.length;
                if (lineLength === 0) continue;
                lineFirstChar = line.charAt(0);
                // @todo invoke passed in handler if any
                if (lineFirstChar === '#') continue;
                if (lineFirstChar === 'v') {
                    var data = line.split(/\s+/);
                    switch (data[0]) {
                        case 'v':
                            state.vertices.push(
                                parseFloat(data[1]),
                                parseFloat(data[2]),
                                parseFloat(data[3])
                            );
                            if (data.length === 8) {
                                state.colors.push(
                                    parseFloat(data[4]),
                                    parseFloat(data[5]),
                                    parseFloat(data[6])
                                );
                            }
                            break;
                        case 'vn':
                            state.normals.push(
                                parseFloat(data[1]),
                                parseFloat(data[2]),
                                parseFloat(data[3])
                            );
                            break;
                        case 'vt':
                            state.uvs.push(
                                parseFloat(data[1]),
                                parseFloat(data[2])
                            );
                            break;
                    }
                } else if (lineFirstChar === 'f') {
                    var lineData = line.substr(1).trim();
                    var vertexData = lineData.split(/\s+/);
                    var faceVertices = [];
                    // Parse the face vertex data into an easy to work with format
                    for (var j = 0, jl = vertexData.length; j < jl; j++) {
                        var vertex = vertexData[j];
                        if (vertex.length > 0) {
                            var vertexParts = vertex.split('/');
                            faceVertices.push(vertexParts);
                        }
                    }
                    // Draw an edge between the first vertex and all subsequent vertices to form an n-gon
                    var v1 = faceVertices[0];
                    for (var j = 1, jl = faceVertices.length - 1; j < jl; j++) {
                        var v2 = faceVertices[j];
                        var v3 = faceVertices[j + 1];
                        state.addFace(
                            v1[0], v2[0], v3[0],
                            v1[1], v2[1], v3[1],
                            v1[2], v2[2], v3[2]
                        );
                    }
                } else if (lineFirstChar === 'l') {
                    var lineParts = line.substring(1).trim().split(" ");
                    var lineVertices = [],
                        lineUVs = [];
                    if (line.indexOf("/") === -1) {
                        lineVertices = lineParts;
                    } else {
                        for (var li = 0, llen = lineParts.length; li < llen; li++) {
                            var parts = lineParts[li].split("/");
                            if (parts[0] !== "") lineVertices.push(parts[0]);
                            if (parts[1] !== "") lineUVs.push(parts[1]);
                        }
                    }
                    state.addLineGeometry(lineVertices, lineUVs);
                } else if (lineFirstChar === 'p') {
                    var lineData = line.substr(1).trim();
                    var pointData = lineData.split(" ");
                    state.addPointGeometry(pointData);
                } else if ((result = object_pattern.exec(line)) !== null) {
                    // o object_name
                    // or
                    // g group_name
                    // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
                    // var name = result[ 0 ].substr( 1 ).trim();
                    var name = (" " + result[0].substr(1).trim()).substr(1);
                    state.startObject(name);
                } else if (material_use_pattern.test(line)) {
                    // material
                    state.object.startMaterial(line.substring(7).trim(), state.materialLibraries);
                } else if (material_library_pattern.test(line)) {
                    // mtl file
                    state.materialLibraries.push(line.substring(7).trim());
                } else if (lineFirstChar === 's') {
                    result = line.split(' ');
                    // smooth shading
                    // @todo Handle files that have varying smooth values for a set of faces inside one geometry,
                    // but does not define a usemtl for each face set.
                    // This should be detected and a dummy material created (later MultiMaterial and geometry groups).
                    // This requires some care to not create extra material on each smooth value for "normal" obj files.
                    // where explicit usemtl defines geometry groups.
                    // Example asset: examples/models/obj/cerberus/Cerberus.obj
                    /*
                     * http://paulbourke.net/dataformats/obj/
                     * or
                     * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf
                     *
                     * From chapter "Grouping" Syntax explanation "s group_number":
                     * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off.
                     * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form
                     * surfaces, smoothing groups are either turned on or off; there is no difference between values greater
                     * than 0."
                     */
                    if (result.length > 1) {
                        var value = result[1].trim().toLowerCase();
                        state.object.smooth = (value !== '0' && value !== 'off');
                    } else {
                        // ZBrush can produce "s" lines #11707
                        state.object.smooth = true;
                    }
                    var material = state.object.currentMaterial();
                    if (material) material.smooth = state.object.smooth;
                } else {
                    // Handle null terminated files without exception
                    if (line === '\0') continue;
                    throw new Error('THREE.OBJLoader: Unexpected line: "' + line + '"');
                }
            }
            state.finalize();
            var container = new THREE.Group();
            container.materialLibraries = [].concat(state.materialLibraries);
            for (var i = 0, l = state.objects.length; i < l; i++) {
                var object = state.objects[i];
                var geometry = object.geometry;
                var materials = object.materials;
                var isLine = (geometry.type === 'Line');
                var isPoints = (geometry.type === 'Points');
                var hasVertexColors = false;
                // Skip o/g line declarations that did not follow with any faces
                if (geometry.vertices.length === 0) continue;
                var buffergeometry = new THREE.BufferGeometry();
                buffergeometry.addAttribute('position', new THREE.Float32BufferAttribute(geometry.vertices, 3));
                if (geometry.normals.length > 0) {
                    buffergeometry.addAttribute('normal', new THREE.Float32BufferAttribute(geometry.normals, 3));
                } else {
                    buffergeometry.computeVertexNormals();
                }
                if (geometry.colors.length > 0) {
                    hasVertexColors = true;
                    buffergeometry.addAttribute('color', new THREE.Float32BufferAttribute(geometry.colors, 3));
                }
                if (geometry.uvs.length > 0) {
                    buffergeometry.addAttribute('uv', new THREE.Float32BufferAttribute(geometry.uvs, 2));
                }
                // Create materials
                var createdMaterials = [];
                for (var mi = 0, miLen = materials.length; mi < miLen; mi++) {
                    var sourceMaterial = materials[mi];
                    var material = undefined;
                    if (this.materials !== null) {
                        material = this.materials.create(sourceMaterial.name);
                        // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
                        if (isLine && material && !(material instanceof THREE.LineBasicMaterial)) {
                            var materialLine = new THREE.LineBasicMaterial();
                            materialLine.copy(material);
                            materialLine.lights = false; // TOFIX
                            material = materialLine;
                        } else if (isPoints && material && !(material instanceof THREE.PointsMaterial)) {
                            var materialPoints = new THREE.PointsMaterial({
                                size: 10,
                                sizeAttenuation: false
                            });
                            materialLine.copy(material);
                            material = materialPoints;
                        }
                    }
                    if (!material) {
                        if (isLine) {
                            material = new THREE.LineBasicMaterial();
                        } else if (isPoints) {
                            material = new THREE.PointsMaterial({
                                size: 1,
                                sizeAttenuation: false
                            });
                        } else {
                            material = new THREE.MeshPhongMaterial();
                        }
                        material.name = sourceMaterial.name;
                    }
                    material.flatShading = sourceMaterial.smooth ? false : true;
                    material.vertexColors = hasVertexColors ? THREE.VertexColors : THREE.NoColors;
                    createdMaterials.push(material);
                }
                // Create mesh
                var mesh;
                if (createdMaterials.length > 1) {
                    for (var mi = 0, miLen = materials.length; mi < miLen; mi++) {
                        var sourceMaterial = materials[mi];
                        buffergeometry.addGroup(sourceMaterial.groupStart, sourceMaterial.groupCount, mi);
                    }
                    if (isLine) {
                        mesh = new THREE.LineSegments(buffergeometry, createdMaterials);
                    } else if (isPoints) {
                        mesh = new THREE.Points(buffergeometry, createdMaterials);
                    } else {
                        mesh = new THREE.Mesh(buffergeometry, createdMaterials);
                    }
                } else {
                    if (isLine) {
                        mesh = new THREE.LineSegments(buffergeometry, createdMaterials[0]);
                    } else if (isPoints) {
                        mesh = new THREE.Points(buffergeometry, createdMaterials[0]);
                    } else {
                        mesh = new THREE.Mesh(buffergeometry, createdMaterials[0]);
                    }
                }
                mesh.name = object.name;
                container.add(mesh);
            }
            console.timeEnd('OBJLoader');
            return container;
        }
    };
    return OBJLoader;
})();
exports.MTLLoader = THREE.MTLLoader;
exports.OBJLoader = THREE.OBJLoader;
src/components/PageMenu.vue
@@ -38,7 +38,7 @@
                            src: "topoGraph",
                        },
                        {
                            label: "3D机房",
                            label: "3D拓扑图",
                            icon: "el-icon-s-platform",
                            name: "room3D",
                            src: "room3D",
src/components/smallModule/DiagramPanel.vue
@@ -10,7 +10,9 @@
        props: {
            position: {
                type: Array,
                default: []
                default () {
                    return []
                }
            },
            title: {
                type: String,
src/pages/home/topoGraphdiagram/images/dynamometry.png

src/pages/home/topoGraphdiagram/images/electric.png

src/pages/room.vue
@@ -1,25 +1,99 @@
<template>
    <div class="contentBox threeRoom">
        <div id="remap"></div>
        <transition name="el-zoom-in-top">
            <diagram-panel :position="text4Pos" title="电源参数" ref="text4Pos" v-show="showtext4">
                <div class="panel-item"><span class="label">电压:</span>
                    <el-input class="input" readonly="readonly" :value="panel4.rectifierVol"></el-input>
                    <span class="unit">V</span>
                </div>
                <div class="panel-item"><span class="label">电流:</span>
                    <el-input class="input" readonly="readonly" :value="panel4.rectifierCurr"></el-input>
                    <span class="unit">A</span>
                </div>
            </diagram-panel>
        </transition>
        <transition name="el-zoom-in-top">
            <diagram-panel :position="text5Pos" title="直流主配电板参数" ref="text5Pos" v-show="showtext5">
                <div class="panel-item">
                    <span class="label">1号进线屏开关:</span>
                    <el-input class="input" readonly="readonly" :value="panel5.switchClose1st2500A==1?'合闸':'分闸'">
                    </el-input>
                    <span class="label" style="margin-left:20px;">2号进线屏开关:</span>
                    <el-input class="input" readonly="readonly" :value="panel5.switchClose2st2500A==1?'合闸':'分闸'">
                    </el-input>
                </div>
                <div class="panel-item">
                    <span class="label">母联屏开关:</span>
                    <el-input class="input" readonly="readonly" :value="panel5.switchCloseBusScreen==1?'合闸':'分闸'">
                    </el-input>
                </div>
                <div class="panel-item">
                    <span class="label">1号负载屏开关:</span>
                    <el-input class="input" readonly="readonly" :value="panel5.switchClose1st2500ALoad==1?'合闸':'分闸'">
                    </el-input>
                    <span class="label" style="margin-left:20px;">2号负载屏开关:</span>
                    <el-input class="input" readonly="readonly" :value="panel5.switchClose2st2500ALoad==1?'合闸':'分闸'">
                    </el-input>
                </div>
                <div class="panel-item">
                    <span class="label">A排电压:</span>
                    <el-input class="input" readonly="readonly" :value="panel5.volA"></el-input>
                    <span class="unit">V</span>
                    <span class="label" style="margin-left:20px;">B排电压:</span>
                    <el-input class="input" readonly="readonly" :value="panel5.volB"></el-input>
                    <span class="unit">V</span>
                </div>
                <div class="panel-item">
                    <span class="label">A排电流:</span>
                    <el-input class="input" readonly="readonly" :value="panel5.currA"></el-input>
                    <span class="unit">A</span>
                    <span class="label" style="margin-left:20px;">B排电流:</span>
                    <el-input class="input" readonly="readonly" :value="panel5.currB"></el-input>
                    <span class="unit">A</span>
                </div>
            </diagram-panel>
        </transition>
    </div>
</template>
<script>
    import * as THREE from 'three'
    import TWEEN from "@/assets/js/three/plugin/Tween"
    import {
        InitThree
    } from "@/assets/js/three/InitThree";
    import {
        Aobjects,
    } from "@/assets/js/three/data";
    import DiagramPanel from '@/components/smallModule/DiagramPanel.vue';
    let threeBuild;
    export default {
        components: {
            DiagramPanel,
        },
        data() {
            return {
                initOption: {
                    cameraPosition: [0, 800, -1500], //初始化相机视角位置
                    cameraPosition: [0, 1200, -1800], //初始化相机视角位置
                    showAxisHelper: true,
                },
                showtext4: false,
                text4Pos: [],
                showtext5: false,
                text5Pos: [],
                panel4: {
                    rectifierVol: 0,
                    rectifierCurr: 0,
                },
                panel5: {
                    switchClose1st2500A: 0,
                    switchClose2st2500A: 0,
                    switchCloseBusScreen: 0,
                    switchClose1st2500ALoad: 0,
                    switchClose2st2500ALoad: 0,
                    currA: 0,
                    volA: 0,
                    currB: 0,
                    volB: 0,
                },
            };
        },
@@ -35,92 +109,61 @@
            //初始化three机房相关点击事件
            initThreeEvent() {
                let _this = this;
                Aobjects.events.mouseUp = { //单机选中机柜或货架
                    obj_event: function (_obj) {}
                }
                Aobjects.events.dbclick = [{
                        findObject: function (_objname) { //查找机柜门的对象
                            if (_objname.indexOf("cabinet") >= 0 && _objname.indexOf("door") >= 0) {
                                return true;
                            } else {
                                return false;
                            }
                        },
                        obj_uuid: "",
                        obj_event: function (_obj) {
                            _this.opcabinetdoor(_obj);
                    findObject: function (_objname) { //点击整流器
                        if (_objname.indexOf("rectifier") >= 0) {
                            return true;
                        } else {
                            return false;
                        }
                    },
                    {
                        findObject: function (_objname) { //查找符合服务器的对象
                            if (_objname.indexOf("cabinetServe") >= 0) {
                                return true;
                            } else {
                                return false;
                            }
                        },
                        obj_uuid: "",
                        obj_event: function (_obj) {
                            _this.ejectServe(_obj);
                        }
                    },
                    {
                        findObject: function (_objname) { //查找符合货架电池的对象
                            if (_objname.indexOf("shelvesBatter") >= 0) {
                                return true;
                            } else {
                                return false;
                            }
                        },
                        obj_uuid: "",
                        obj_event: function (_obj) {
                            _this.batterInfo(_obj);
                        }
                    obj_uuid: "",
                    obj_event: function (_obj, event) {
                        _this.rectifierInfo(_obj, event);
                    }
                ]
            },
            //打开机柜门
            opcabinetdoor(_obj) {
                var doorstate = "close";
                var tempobj = null;
                if (_obj.doorState != null && typeof (_obj.doorState) != 'undefined') {
                    doorstate = _obj.doorState;
                    tempobj = _obj.parent;
                } else {
                    var _objparent = _obj.parent;
                    tempobj = new THREE.Object3D();
                    tempobj.position.set(_obj.position.x, _obj.position.y, _obj.position.z + _obj.geometry.parameters.depth / 2);
                    _obj.position.set(0, 0, -_obj.geometry.parameters.depth / 2);
                    tempobj.add(_obj);
                    _objparent.add(tempobj);
                }, {
                    findObject: function (_objname) { //点击配电器
                        if (_objname.indexOf("distribution") >= 0) {
                            return true;
                        } else {
                            return false;
                        }
                    },
                    obj_uuid: "",
                    obj_event: function (_obj, event) {
                        _this.distributionInfo(_obj, event);
                    }
                }, ]
                //隐藏面板
                Aobjects.events.hidePanel = {
                    obj_event: function (_obj, event) {
                        _this.hidePanel(_obj, event);
                    }
                }
                _obj.doorState = (doorstate == "close" ? "open" : "close");
                if (doorstate == "close") {
                    new TWEEN.Tween(tempobj.rotation).to({
                        y: 0.5 * Math.PI
                    }, 1500).easing(TWEEN.Easing.Elastic.Out).start();
                } else {
                    new TWEEN.Tween(tempobj.rotation).to({
                        y: 0 * 2 * Math.PI
                    }, 300).start();
                }
            },
            //弹出服务器
            ejectServe(_obj) {
                var cardstate = "in";
                if (_obj.cardstate != null && typeof (_obj.cardstate) != 'undefined') {
                    cardstate = _obj.cardstate;
                } else {
                    _obj.cardstate = "out";
                }
                _obj.cardstate = (cardstate == "in" ? "out" : "in");
                new TWEEN.Tween(_obj.position).to({
                    x: (cardstate == "in" ? _obj.position.x - 30 : _obj.position.x + 30),
                }, 500).easing(TWEEN.Easing.Elastic.Out).start();
            },
            //点击电池
            batterInfo(_obj) {
                alert("您双击了" + _obj.name + "电池!");
                alert("您双击了" + _obj.name + "点击!");
            },
            rectifierInfo(_obj, event) {
                if (!this.showtext4) {
                    this.text4Pos = [event.offsetX + 20, event.offsetY - 40];
                }
                this.showtext4 = !this.showtext4;
            },
            //点击配电器
            distributionInfo(_obj, event) {
                if (!this.showtext5) {
                    this.text5Pos = [event.offsetX + 20, event.offsetY - 40];
                }
                this.showtext5 = !this.showtext5;
            },
            //隐藏面板
            hidePanel(_obj, event) {
                if (_obj.name == 'floor') {
                    this.showtext4 = false
                    this.showtext5 = false
                }
            }
        },
        destroyed() {
@@ -143,4 +186,8 @@
        overflow: hidden;
        transition: 0.3s;
    }
    #remap /deep/ canvas {
        outline: none;
    }
</style>
src/store/user.js
@@ -1,42 +1,43 @@
export default {
    state() {
        return {
            username: sessionStorage.getItem("username") || ""
            ,uid: -1
            username: sessionStorage.getItem("username") || "",
            uid: -1
        }
    }
    ,mutations:{
        setLogin (state, user) {
            if(user && user.name.trim()) {
    },
    mutations: {
        setLogin(state, user) {
            if (user && user.name.trim()) {
                // 设置session
                sessionStorage.setItem("username", user.name);
                sessionStorage.setItem('uid', user.uid);
                state.username = user.name;
                state.uid = user.uid;
            }else {
            } else {
                // 设置session
                sessionStorage.setItem("username", "");
                sessionStorage.setItem('uid', -1);
                state.username = "";
                state.uid = -1;
            }
        }
        // 页面刷新时 从sessionStorage读取用户信息同步到store中
        ,replaceUserInfo (state, user) {
        ,
        replaceUserInfo(state, user) {
            state.username = user.name;
            state.uid = user.uid;
        }
    }
    ,actions: {
        setLogin (context, user) {
    },
    actions: {
        setLogin(context, user) {
            debugger
            context.commit('setLogin', user);
        }
        ,replaceUserInfo (context, user) {
        },
        replaceUserInfo(context, user) {
            context.commit('replaceUserInfo', user);
        }
    }
    ,getters: {
    }
    },
    getters: {}
};