| | |
| | | "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", |
| | |
| | | * @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 |
| | |
| | | _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) |
| | |
| | | } |
| | | //循环渲染界面 |
| | | animation(start) { |
| | | // console.log(this.scene) |
| | | if (start) { |
| | | console.log('已经启动持续更新'); |
| | | this.startState = true; |
| | |
| | | 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); |
| | |
| | | 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) { |
| | |
| | | _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); |
| | | } |
| | | } |
| | | }) |
| | |
| | | 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直线和所有模型相交的数组集合 |
| | |
| | | _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; |
| | | } |
| | | } |
| | | } |
| | |
| | | * @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"); |
| | |
| | | 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: [ |
| | | //地板 |
| | |
| | | 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, |
| | | }, |
| | |
| | | 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, |
| | | }, |
| | |
| | | }], //旋转 表示x方向0度 |
| | | x: 0, |
| | | y: 100, |
| | | z: 1200, |
| | | z: 900, |
| | | style: { |
| | | skinColor: 0xfefefe, |
| | | skin: { |
| | |
| | | degree: 0 * Math.PI |
| | | }], //旋转 表示x方向0度 |
| | | x: 1000, |
| | | y: 100, |
| | | y: 80, |
| | | z: 500, |
| | | style: { |
| | | skinColor: 0xfefefe, |
| | |
| | | uuid: "", |
| | | name: 'distribution', |
| | | objType: 'cube', |
| | | length: 90, |
| | | length: 80, |
| | | width: 180, |
| | | height: 160, |
| | | rotation: [{ |
| | |
| | | degree: 0.5 * Math.PI |
| | | }], //旋转 表示x方向0度 |
| | | x: 1000, |
| | | y: 100, |
| | | y: 80, |
| | | z: 0, |
| | | style: { |
| | | skinColor: 0xfefefe, |
| | |
| | | } |
| | | } |
| | | }, |
| | | //配电器 |
| | | //调速柜 |
| | | { |
| | | 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, |
| | | }, |
| | | } |
| | | } |
| | |
| | | dbclick: [], |
| | | mouseDown: {}, |
| | | mouseUp: {}, |
| | | mouseMove: {} |
| | | mouseMove: {}, |
| | | hidePanel: {} |
| | | }, |
| | | } |
| | | |
New file |
| | |
| | | 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: "topoGraph", |
| | | }, |
| | | { |
| | | label: "3D机房", |
| | | label: "3D拓扑图", |
| | | icon: "el-icon-s-platform", |
| | | name: "room3D", |
| | | src: "room3D", |
| | |
| | | props: { |
| | | position: { |
| | | type: Array, |
| | | default: [] |
| | | default () { |
| | | return [] |
| | | } |
| | | }, |
| | | title: { |
| | | type: String, |
| | |
| | | <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, |
| | | }, |
| | | }; |
| | | }, |
| | |
| | | //初始化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() { |
| | |
| | | overflow: hidden; |
| | | transition: 0.3s; |
| | | } |
| | | |
| | | #remap /deep/ canvas { |
| | | outline: none; |
| | | } |
| | | </style> |
| | |
| | | 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: {} |
| | | }; |