| | |
| | | "integrity": "sha1-qcpLcKGLJwzLK8Cqr+/R1Ia36nQ=", |
| | | "dev": true |
| | | }, |
| | | "@types/three": { |
| | | "version": "0.103.2", |
| | | "resolved": "https://registry.npmjs.org/@types/three/-/three-0.103.2.tgz", |
| | | "integrity": "sha512-zhtf0Qs5wLJpIn1+VWCpzSgpKayj/GSWZ6woiuz09FW59KEDeLpnBkYz6lbblVpRmGdlnG8nd0unaASshOvcXw==", |
| | | "requires": { |
| | | "three": "*" |
| | | } |
| | | }, |
| | | "@types/uglify-js": { |
| | | "version": "3.11.1", |
| | | "resolved": "https://registry.npm.taobao.org/@types/uglify-js/download/@types/uglify-js-3.11.1.tgz", |
| | |
| | | "integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=", |
| | | "dev": true |
| | | }, |
| | | "ansi-styles": { |
| | | "version": "4.3.0", |
| | | "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.3.0.tgz?cache=0&sync_timestamp=1606792266928&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-styles%2Fdownload%2Fansi-styles-4.3.0.tgz", |
| | | "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=", |
| | | "dev": true, |
| | | "optional": true, |
| | | "requires": { |
| | | "color-convert": "^2.0.1" |
| | | } |
| | | }, |
| | | "cacache": { |
| | | "version": "13.0.1", |
| | | "resolved": "https://registry.npm.taobao.org/cacache/download/cacache-13.0.1.tgz?cache=0&sync_timestamp=1594429684526&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcacache%2Fdownload%2Fcacache-13.0.1.tgz", |
| | |
| | | "unique-filename": "^1.1.1" |
| | | } |
| | | }, |
| | | "chalk": { |
| | | "version": "4.1.0", |
| | | "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-4.1.0.tgz", |
| | | "integrity": "sha1-ThSHCmGNni7dl92DRf2dncMVZGo=", |
| | | "dev": true, |
| | | "optional": true, |
| | | "requires": { |
| | | "ansi-styles": "^4.1.0", |
| | | "supports-color": "^7.1.0" |
| | | } |
| | | }, |
| | | "color-convert": { |
| | | "version": "2.0.1", |
| | | "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz", |
| | | "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", |
| | | "dev": true, |
| | | "optional": true, |
| | | "requires": { |
| | | "color-name": "~1.1.4" |
| | | } |
| | | }, |
| | | "color-name": { |
| | | "version": "1.1.4", |
| | | "resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz", |
| | | "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=", |
| | | "dev": true, |
| | | "optional": true |
| | | }, |
| | | "has-flag": { |
| | | "version": "4.0.0", |
| | | "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz", |
| | | "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=", |
| | | "dev": true, |
| | | "optional": true |
| | | }, |
| | | "loader-utils": { |
| | | "version": "2.0.0", |
| | | "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-2.0.0.tgz", |
| | | "integrity": "sha1-5MrOW4FtQloWa18JfhDNErNgZLA=", |
| | | "dev": true, |
| | | "optional": true, |
| | | "requires": { |
| | | "big.js": "^5.2.2", |
| | | "emojis-list": "^3.0.0", |
| | | "json5": "^2.1.2" |
| | | } |
| | | }, |
| | | "source-map": { |
| | | "version": "0.6.1", |
| | | "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz", |
| | |
| | | "requires": { |
| | | "figgy-pudding": "^3.5.1", |
| | | "minipass": "^3.1.1" |
| | | } |
| | | }, |
| | | "supports-color": { |
| | | "version": "7.2.0", |
| | | "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1608035266405&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz", |
| | | "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", |
| | | "dev": true, |
| | | "optional": true, |
| | | "requires": { |
| | | "has-flag": "^4.0.0" |
| | | } |
| | | }, |
| | | "terser-webpack-plugin": { |
| | |
| | | "source-map": "^0.6.1", |
| | | "terser": "^4.6.12", |
| | | "webpack-sources": "^1.4.3" |
| | | } |
| | | }, |
| | | "vue-loader-v16": { |
| | | "version": "npm:vue-loader@16.1.2", |
| | | "resolved": "https://registry.npm.taobao.org/vue-loader/download/vue-loader-16.1.2.tgz?cache=0&sync_timestamp=1608187947155&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-loader%2Fdownload%2Fvue-loader-16.1.2.tgz", |
| | | "integrity": "sha1-XAO2xQ0qX5g8fOuhXFDXjKKymPQ=", |
| | | "dev": true, |
| | | "optional": true, |
| | | "requires": { |
| | | "chalk": "^4.1.0", |
| | | "hash-sum": "^2.0.0", |
| | | "loader-utils": "^2.0.0" |
| | | } |
| | | } |
| | | } |
| | |
| | | "neo-async": "^2.6.0" |
| | | } |
| | | }, |
| | | "three": { |
| | | "version": "0.111.0", |
| | | "resolved": "https://registry.npmjs.org/three/-/three-0.111.0.tgz", |
| | | "integrity": "sha512-AcTqyGJ3H75AIusOuADy0LsP958QKQwm/YhABHFMzd6RFXPNVay1rlSbbG6WYv7KM72G2THMMwqbjQd4dVHMkQ==" |
| | | }, |
| | | "throttle-debounce": { |
| | | "version": "1.1.0", |
| | | "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-1.1.0.tgz", |
| | |
| | | } |
| | | } |
| | | }, |
| | | "vue-loader-v16": { |
| | | "version": "npm:vue-loader@16.2.0", |
| | | "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.2.0.tgz", |
| | | "integrity": "sha512-TitGhqSQ61RJljMmhIGvfWzJ2zk9m1Qug049Ugml6QP3t0e95o0XJjk29roNEiPKJQBEi8Ord5hFuSuELzSp8Q==", |
| | | "dev": true, |
| | | "optional": true, |
| | | "requires": { |
| | | "chalk": "^4.1.0", |
| | | "hash-sum": "^2.0.0", |
| | | "loader-utils": "^2.0.0" |
| | | }, |
| | | "dependencies": { |
| | | "ansi-styles": { |
| | | "version": "4.3.0", |
| | | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", |
| | | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", |
| | | "dev": true, |
| | | "optional": true, |
| | | "requires": { |
| | | "color-convert": "^2.0.1" |
| | | } |
| | | }, |
| | | "chalk": { |
| | | "version": "4.1.0", |
| | | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", |
| | | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", |
| | | "dev": true, |
| | | "optional": true, |
| | | "requires": { |
| | | "ansi-styles": "^4.1.0", |
| | | "supports-color": "^7.1.0" |
| | | } |
| | | }, |
| | | "color-convert": { |
| | | "version": "2.0.1", |
| | | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", |
| | | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", |
| | | "dev": true, |
| | | "optional": true, |
| | | "requires": { |
| | | "color-name": "~1.1.4" |
| | | } |
| | | }, |
| | | "color-name": { |
| | | "version": "1.1.4", |
| | | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", |
| | | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", |
| | | "dev": true, |
| | | "optional": true |
| | | }, |
| | | "has-flag": { |
| | | "version": "4.0.0", |
| | | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", |
| | | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", |
| | | "dev": true, |
| | | "optional": true |
| | | }, |
| | | "loader-utils": { |
| | | "version": "2.0.0", |
| | | "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", |
| | | "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", |
| | | "dev": true, |
| | | "optional": true, |
| | | "requires": { |
| | | "big.js": "^5.2.2", |
| | | "emojis-list": "^3.0.0", |
| | | "json5": "^2.1.2" |
| | | } |
| | | }, |
| | | "supports-color": { |
| | | "version": "7.2.0", |
| | | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", |
| | | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", |
| | | "dev": true, |
| | | "optional": true, |
| | | "requires": { |
| | | "has-flag": "^4.0.0" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "vue-router": { |
| | | "version": "3.4.9", |
| | | "resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-3.4.9.tgz?cache=0&sync_timestamp=1607347284428&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-router%2Fdownload%2Fvue-router-3.4.9.tgz", |
| | |
| | | "postcss-px2rem": "^0.3.0", |
| | | "vue": "^2.6.11", |
| | | "vue-router": "^3.2.0", |
| | | "vuex": "^3.4.0" |
| | | "vuex": "^3.4.0", |
| | | "three": "^0.111.0", |
| | | "@types/three": "^0.103.2" |
| | | }, |
| | | "devDependencies": { |
| | | "@vue/cli-plugin-babel": "~4.5.0", |
| | |
| | | "@vue/cli-service": "~4.5.0", |
| | | "vue-template-compiler": "^2.6.11" |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | /* |
| | | * @Description: THREEjs3D机房应用方法封装 |
| | | * @Autor: ZengYK |
| | | * @Date: 2021-01-13 09:45:45 |
| | | */ |
| | | import { |
| | | _ |
| | | } from "core-js"; |
| | | import "three/examples/js/controls/OrbitControls" |
| | | import "three/examples/js/controls/TransformControls" |
| | | import "./plugin/DragControls" |
| | | import { |
| | | loadBSP |
| | | } from './plugin/ThreeBSP' |
| | | loadBSP(); |
| | | import TWEEN from "./plugin/Tween" |
| | | var isOne = 0; |
| | | var dbclick = 0; |
| | | export class InitThree { |
| | | constructor() { |
| | | this.renderer = null; //渲染器 |
| | | this.camera = null; //摄像机 |
| | | this.scene = null; //场景 |
| | | this.controls = null; //鼠标控制器 |
| | | this.transformControls = null; //变化控制器 |
| | | this.dragControls = null; //拖拽控制器 |
| | | this.startState = false; //动画开关 |
| | | this.isEdit = false; //编辑状态 |
| | | this.TransFormControlsMode = "translate"; |
| | | this.p1 = { |
| | | x: 0, |
| | | y: 0, |
| | | z: 0 |
| | | } |
| | | this.p2 = { |
| | | x: 300, |
| | | y: 300, |
| | | z: 0 |
| | | } |
| | | } |
| | | start() { |
| | | //开始 |
| | | var _this = this; |
| | | _this.initScene() |
| | | _this.initCamera() |
| | | _this.initRender() |
| | | _this.initMouseCtrl() |
| | | _this.initHelpGrid() |
| | | _this.initLight() |
| | | //添加3D对象 |
| | | _this.objList.forEach(function (v, i) { |
| | | _this.InitAddObject(v) |
| | | }) |
| | | _this.animation(true) |
| | | } |
| | | //向动画场景中添加元素 |
| | | sceneAdd(nowObjects) { |
| | | var _this = this; |
| | | _this.InitAddObject(nowObjects); |
| | | } |
| | | //向动画场景中移除元素 |
| | | sceneRemove(name) { |
| | | var _this = this; |
| | | var removeObj = _this.findObject(name); |
| | | _this.scene.remove(removeObj); |
| | | _this.objects.forEach((item, index) => { |
| | | if (item.name == name) { |
| | | _this.objects.splice(index, 1); |
| | | } |
| | | }) |
| | | _this.dragObjects.forEach((item, index) => { |
| | | if (item.name == name) { |
| | | _this.dragObjects.splice(index, 1); |
| | | } |
| | | }) |
| | | } |
| | | //向动画场景中更新元素 |
| | | updateObject(obj) { |
| | | var _this = this; |
| | | _this.sceneRemove(obj.name); |
| | | _this.sceneAdd(obj); |
| | | } |
| | | /* |
| | | 方法:初始化 |
| | | fid 画布所属div的Id |
| | | option:参数 { |
| | | antialias:true,//抗锯齿效果为设置有效 |
| | | clearCoolr:0xFFFFFF,//刷新色 |
| | | showHelpGrid:false,//是否显示网格线 |
| | | showAxisHelper:false,//是否显示坐标轴 |
| | | showlinkLine:false,//是否添加视角辅助线 |
| | | cameraPosition:[0, 50, 200],//初始化相机视角位置 |
| | | } |
| | | */ |
| | | initmsj3D(_fId, _option, _datajson) { |
| | | this.option = {}; |
| | | this.option.antialias = _option.antialias || true; |
| | | this.option.clearCoolr = _option.clearCoolr; |
| | | this.option.showHelpGrid = _option.showHelpGrid || false; |
| | | this.option.showAxisHelper = _option.showAxisHelper || false; |
| | | this.option.showlinkLine = _option.showlinkLine || false; |
| | | this.option.cameraPosition = _option.cameraPosition || [0, 50, 200]; |
| | | //对象 |
| | | this.fId = _fId; |
| | | this.element = document.getElementById(this.fId); |
| | | this.width = this.element.clientWidth; |
| | | this.height = this.element.clientHeight; |
| | | this.renderer = null; //渲染器 |
| | | this.camera = null; //摄像机 |
| | | this.scene = null; //场景 |
| | | this.SELECTED = null; |
| | | this.objects = []; |
| | | this.dragObjects = []; //拖动对象 |
| | | this.mouseClick = new THREE.Vector2(); |
| | | this.raycaster = new THREE.Raycaster(); |
| | | this.controls = null; //鼠标控制器 |
| | | this.objList = _datajson.objects; //对象列表 |
| | | this.eventList = _datajson.events; //事件对象列表 |
| | | } |
| | | //创建场景 |
| | | initScene() { |
| | | var _this = this |
| | | _this.scene = new THREE.Scene() |
| | | } |
| | | //初始化摄像机 |
| | | initCamera() { |
| | | var _this = this |
| | | var width = this.width; // 窗口宽度 |
| | | var height = this.height; // 窗口高度 |
| | | var k = width / height; // 窗口宽高比 |
| | | _this.camera = new THREE.PerspectiveCamera(45, k, 0.1, 10000); |
| | | _this.camera.name = 'mainCamera' |
| | | _this.camera.position.set(this.option.cameraPosition[0], this.option.cameraPosition[1], this.option.cameraPosition[2]); // 设置相机位置 |
| | | _this.camera.lookAt(new THREE.Vector3(0, 0, 0)); |
| | | _this.objects.push(_this.camera) |
| | | } |
| | | //灯光布置 |
| | | initLight() { |
| | | /** |
| | | * AmbientLight: 环境光,基础光源,它的颜色会被加载到整个场景和所有对象的当前颜色上。 |
| | | * PointLight: 点光源,朝着所有方向都发射光线 |
| | | * SpotLight: 聚光灯光源:类型台灯,天花板上的吊灯,手电筒等 |
| | | * DirectionalLight: 方向光,又称无限光,从这个发出的光源可以看做是平行光. |
| | | */ |
| | | var _this = this; |
| | | var light = new THREE.AmbientLight(0xcccccc); |
| | | light.position.set(0, 0, 0); |
| | | _this.scene.add(light); |
| | | |
| | | var directionalLight = new THREE.DirectionalLight(0xffffff, 0.3); //模拟远处类似太阳的光源 |
| | | directionalLight.color.setHSL(0.1, 1, 0.95); |
| | | directionalLight.position.set(0, 200, 0).normalize(); |
| | | _this.scene.add(directionalLight); |
| | | } |
| | | //初始化渲染器 |
| | | initRender() { |
| | | var _this = this; |
| | | _this.renderer = new THREE.WebGLRenderer({ |
| | | antialias: _this.option.antialias, |
| | | alpha: true, //是否可以设置背景色透明。 |
| | | logarithmicDepthBuffer: true //模型的重叠部位便不停的闪烁起来。这便是Z-Fighting问题,为解决这个问题,我们可以采用该种方法 |
| | | }); |
| | | _this.renderer.setPixelRatio(window.devicePixelRatio); |
| | | _this.renderer.setSize(_this.width, _this.height); |
| | | _this.element.appendChild(_this.renderer.domElement) |
| | | if (_this.option.clearCoolr) { |
| | | _this.renderer.setClearColor(_this.option.clearCoolr, 1.0); |
| | | } |
| | | _this.renderer.shadowMap.enabled = true; // |
| | | _this.renderer.shadowMapSoft = true; |
| | | _this.renderer.domElement.addEventListener('mousedown', (e) => { |
| | | _this.onDocumentMouseDown(e) |
| | | }, false); |
| | | _this.renderer.domElement.addEventListener('mouseup', (e) => { |
| | | _this.onDocumentMouseUp(e) |
| | | }, false); |
| | | window.addEventListener('resize', (e) => { |
| | | _this.onWindowResize(e) |
| | | }, false); |
| | | } |
| | | //创建鼠标控制器 |
| | | initMouseCtrl() { |
| | | var _this = this; |
| | | _this.controls = new THREE.OrbitControls(_this.camera, _this.renderer.domElement) |
| | | _this.controls.enableDamping = true |
| | | _this.controls.dampingFactor = 0.5 |
| | | // 视角最小距离 |
| | | _this.controls.minDistance = 100 |
| | | // 视角最远距离 |
| | | _this.controls.maxDistance = 2200 |
| | | // 最大角度 |
| | | _this.controls.maxPolarAngle = Math.PI / 2.2 |
| | | _this.controls.target = new THREE.Vector3(0, 120, 0) // 设置控制器的旋转原点 |
| | | _this.controls.autoRotateSpeed = 0.5; |
| | | _this.controls.autoRotate = true; |
| | | } |
| | | //创建变化控制器 |
| | | initTransFormControls(object, type) { |
| | | var _this = this; |
| | | _this.transformControls = new THREE.TransformControls(_this.camera, _this.renderer.domElement); |
| | | _this.transformControls.addEventListener('dragging-changed', function (event) { |
| | | _this.controls.enabled = !event.value |
| | | }); |
| | | _this.transformControls.setSize(0.5); // 设置三维坐标轴大小 |
| | | _this.transformControls.attach(object); |
| | | if (type == "rotate") { |
| | | _this.transformControls.space = "local"; |
| | | _this.transformControls.rotationSnap = 0.25 * Math.PI; |
| | | _this.transformControls.setSize(0.2); |
| | | _this.transformControls.showX = false; |
| | | _this.transformControls.showZ = false; |
| | | _this.transformControls.setMode(type); |
| | | } else if (type == "translate") { |
| | | _this.transformControls.setMode(type); |
| | | } |
| | | _this.controls.enabled = false; |
| | | _this.scene.add(_this.transformControls); |
| | | |
| | | } |
| | | //设置变化控制器变化方法 |
| | | setTransFormControlsMode(type) { |
| | | var _this = this; |
| | | _this.TransFormControlsMode = type; |
| | | } |
| | | //消除变化控制器 |
| | | DeleteTransFormControls() { |
| | | var _this = this; |
| | | _this.transformControls.detach(); |
| | | _this.controls.enabled = true; |
| | | _this.scene.remove(_this.transformControls); |
| | | }; |
| | | //创建控制变化器绑定事件 |
| | | initDragControls() { |
| | | if (this.isEdit) { |
| | | return |
| | | } |
| | | var _this = this; |
| | | _this.isEdit = true; |
| | | _this.dragControls = new THREE.DragControls(_this.dragObjects, _this.camera, _this.renderer.domElement); |
| | | // 鼠标略过事件 |
| | | _this.dragControls.addEventListener('hoveron', function (event) { |
| | | // 让变换控件对象和选中的对象绑定 |
| | | _this.initTransFormControls(event.object, _this.TransFormControlsMode); |
| | | }); |
| | | // 鼠标略出事件 |
| | | _this.dragControls.addEventListener('hoveroff', function (event) { |
| | | // 移除变换控件 |
| | | _this.DeleteTransFormControls() |
| | | _this.scene.children.forEach((item) => { |
| | | if (item.children.length > 0 && item.children[0].type == "TransformControlsGizmo") { |
| | | _this.scene.remove(item); |
| | | } |
| | | }); |
| | | }); |
| | | // 开始拖拽 |
| | | _this.dragControls.addEventListener('dragstart', function (event) { |
| | | _this.controls.enabled = false; |
| | | }); |
| | | // 拖拽结束 |
| | | _this.dragControls.addEventListener('dragend', function (event) { |
| | | _this.controls.enabled = true; |
| | | }); |
| | | } |
| | | //消除控制变化器绑定事件 |
| | | DeleteDragControls() { |
| | | var _this = this; |
| | | _this.isEdit = false; |
| | | if (_this.transformControls) { |
| | | _this.transformControls.detach(); |
| | | _this.scene.remove(_this.transformControls); |
| | | } |
| | | _this.scene.children.forEach((item) => { |
| | | if (item.children.length > 0 && item.children[0].type == "TransformControlsGizmo") { |
| | | _this.scene.remove(item); |
| | | } |
| | | }); |
| | | _this.dragControls.deactivate(); |
| | | } |
| | | //添加对象 |
| | | addObject(_obj) { |
| | | var _this = this |
| | | _this.objects.push(_obj) |
| | | _this.scene.add(_obj) |
| | | } |
| | | //创建网格线 |
| | | initHelpGrid() { |
| | | var _this = this |
| | | if (_this.option.showHelpGrid) { |
| | | var helpGrid = new THREE.GridHelper(1000, 50) |
| | | _this.scene.add(helpGrid) |
| | | } |
| | | if (_this.option.showAxisHelper) { |
| | | var AxisHelper = new THREE.AxisHelper(3000); |
| | | _this.scene.add(AxisHelper) |
| | | } |
| | | } |
| | | //创建视角引导线 |
| | | linkLine() { |
| | | var _this = this; |
| | | if (_this.option.showlinkLine) { |
| | | var pX = (_this.p1.x / _this.width) * 2 - 1; |
| | | var pY = -(_this.p1.y / _this.height) * 2 + 1; |
| | | var p = new THREE.Vector3(pX, pY, -1).unproject(_this.camera) |
| | | var geometry = new THREE.Geometry(); |
| | | var material = new THREE.LineBasicMaterial({ |
| | | color: 0xff0000 |
| | | }); |
| | | geometry.vertices.push(_this.p1) |
| | | _this.p2.x = p.x + 300 |
| | | _this.p2.y = p.y + 300 |
| | | _this.p2.z = p.z + 300 |
| | | geometry.vertices.push(_this.p2) |
| | | var line = new THREE.Line(geometry, material, THREE.LineSegments) |
| | | line.name = 'xfxian' |
| | | _this.scene.add(line) |
| | | } |
| | | } |
| | | linemove() { |
| | | var _this = this; |
| | | var xf = [..._this.scene.children].find(function (v) { |
| | | return v.name == 'xfxian' |
| | | }) |
| | | _this.p1 = _this.p1 |
| | | var pX = (400 / _this.width) * 2 - 1; |
| | | var pY = -(200 / _this.height) * 2 + 1; |
| | | var p = new THREE.Vector3(pX, pY, -1) |
| | | var p = new THREE.Vector3(pX, pY, -1).unproject(_this.camera) |
| | | _this.p2.x = p.x |
| | | _this.p2.y = p.y |
| | | _this.p2.z = p.z |
| | | xf.geometry.verticesNeedUpdate = true |
| | | } |
| | | //执行渲染 |
| | | render() { |
| | | var _this = this; |
| | | _this.renderer.render(_this.scene, _this.camera); |
| | | } |
| | | //循环渲染界面 |
| | | animation(start) { |
| | | if (start) { |
| | | console.log('已经启动持续更新'); |
| | | this.startState = true; |
| | | } |
| | | // 停止更新 |
| | | if (!this.startState || document.visibilityState != document.visibilityState) { |
| | | return; |
| | | } |
| | | var _this = this; |
| | | if (TWEEN.Tween != null && typeof (TWEEN.Tween) != 'undefined') { |
| | | TWEEN.update(); |
| | | } |
| | | requestAnimationFrame(() => { |
| | | _this.animation() |
| | | }) |
| | | _this.render(); |
| | | if (!isOne) { |
| | | this.linkLine() |
| | | isOne++ |
| | | } |
| | | if (_this.option.showlinkLine) { |
| | | _this.linemove() |
| | | } |
| | | } |
| | | //停止循环渲染界面 |
| | | stop() { |
| | | this.startState = false; |
| | | console.log('已经停止持续更新'); |
| | | } |
| | | timeRender() { |
| | | //调用一次可以渲染三秒 |
| | | var timeOut = null; |
| | | //设置为可渲染状态 |
| | | this.startState = true; |
| | | //清除上次的延迟器 |
| | | if (timeOut) { |
| | | clearTimeout(timeOut); |
| | | } |
| | | |
| | | timeOut = setTimeout(function () { |
| | | this.startState = false; |
| | | }, 3000); |
| | | } |
| | | //初始化数据对象 |
| | | InitAddObject(_obj) { |
| | | var _this = this; |
| | | if (_obj.show == null || typeof (_obj.show) == 'undefined' || _obj.show) { |
| | | var _tempObj = null; |
| | | var _tempObjList = [] |
| | | switch (_obj.objType) { |
| | | case 'Skybox': |
| | | _this.CreateSkybox(_obj); |
| | | break; |
| | | case 'cube': |
| | | _tempObj = _this.createCube(_this, _obj); |
| | | _this.addObject(_tempObj); |
| | | break; |
| | | case 'floor': |
| | | _tempObj = _this.CreateFloor(_obj) |
| | | _this.addObject(_tempObj); |
| | | break; |
| | | case 'wall': |
| | | _tempObjList = _this.CreateWall(_this, _obj); |
| | | _tempObjList.forEach((v, i) => { |
| | | _this.addObject(v) |
| | | }) |
| | | break; |
| | | case 'channel': |
| | | _tempObj = _this.createChannelGeometry(_this, _obj); |
| | | _this.addObject(_tempObj); |
| | | break; |
| | | case 'plane': |
| | | _tempObj = _this.createPlaneGeometry(_this, _obj); |
| | | _this.addObject(_tempObj); |
| | | break; |
| | | case 'glasses': |
| | | _tempObj = _this.createGlasses(_this, _obj); |
| | | _this.addObject(_tempObj); |
| | | break; |
| | | case 'emptyCabinet': |
| | | _tempObj = _this.createEmptyCabinet(_this, _obj); |
| | | _this.addObject(_tempObj); |
| | | break; |
| | | case 'shelves': |
| | | _tempObj = _this.createShelves(_this, _obj); |
| | | _this.addObject(_tempObj); |
| | | break; |
| | | case 'cloneObj': |
| | | _tempObj = _this.cloneObj(_obj.copyfrom, _obj); |
| | | _this.addObject(_tempObj); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | //创建天空盒 |
| | | CreateSkybox(_obj) { |
| | | const urls = _obj.urls |
| | | const skyboxCubeMap = new THREE.CubeTextureLoader().load(urls); |
| | | this.scene.background = skyboxCubeMap; |
| | | } |
| | | //创建地板 |
| | | CreateFloor(_obj) { |
| | | var _this = this; |
| | | var _cube = _this.createCube(_this, _obj); |
| | | return _cube; |
| | | } |
| | | //创建墙体 |
| | | CreateWall(_this, _obj) { |
| | | if (_this == null) { |
| | | _this = this; |
| | | } |
| | | var cubeList = [] |
| | | var _commonThick = _obj.thick || 40; //墙体厚度 |
| | | var _commonLength = _obj.length || 100; //墙体厚度 |
| | | var _commonHeight = _obj.height || 300; //强体高度 |
| | | var _commonSkin = _obj.style.skinColor || 0x98750f; |
| | | //建立墙面 |
| | | _obj.wallData.forEach(function (v, i) { |
| | | var wallLength = _commonLength; |
| | | var wallWidth = v.thick || _commonThick; |
| | | var positionX = ((v.startDot.x || 0) + (v.endDot.x || 0)) / 2; |
| | | var positionY = ((v.startDot.y || 0) + (v.endDot.y || 0)) / 2; |
| | | var positionZ = ((v.startDot.z || 0) + (v.endDot.z || 0)) / 2; |
| | | //z相同 表示x方向为长度 |
| | | if (v.startDot.z == v.endDot.z) { |
| | | wallLength = Math.abs(v.startDot.x - v.endDot.x); |
| | | wallWidth = v.thick || _commonThick; |
| | | } else if (v.startDot.x == v.endDot.x) { |
| | | wallLength = v.thick || _commonThick; |
| | | wallWidth = Math.abs(v.startDot.z - v.endDot.z); |
| | | } |
| | | var cubeobj = { |
| | | length: wallLength, |
| | | width: wallWidth, |
| | | height: v.height || _commonHeight, |
| | | rotation: v.rotation, |
| | | x: positionX, |
| | | y: positionY, |
| | | z: positionZ, |
| | | uuid: v.uuid, |
| | | name: v.name, |
| | | transparent: v.transparent || false, |
| | | style: { |
| | | skinColor: _commonSkin, |
| | | skin: v.skin |
| | | } |
| | | } |
| | | var _cube = _this.createCube(_this, cubeobj); |
| | | if (_this.hasObj(v.childrens) && v.childrens.length > 0) { |
| | | v.childrens.forEach(function (v1, i1) { |
| | | var _newobj = null; |
| | | _newobj = _this.CreateHole(_this, v1); |
| | | _cube = _this.mergeModel(_this, v1.op, _cube, _newobj); |
| | | }) |
| | | } |
| | | cubeList.push(_cube) |
| | | }) |
| | | return cubeList |
| | | } |
| | | //挖洞 |
| | | CreateHole(_this, _obj) { |
| | | if (_this == null) { |
| | | _this = this; |
| | | } |
| | | var _commonThick = 40; // 墙体厚度 |
| | | var _commonLength = 100; // 墙体厚度 |
| | | var _commonHeight = 300; // 强体高度 |
| | | var _commonSkin = 0x98750f; |
| | | //建立墙面 |
| | | var wallLength = _commonLength; |
| | | var wallWidth = _obj.thick || _commonThick; |
| | | var positionX = ((_obj.startDot.x || 0) + (_obj.endDot.x || 0)) / 2; |
| | | var positionY = ((_obj.startDot.y || 0) + (_obj.endDot.y || 0)) / 2; |
| | | var positionZ = ((_obj.startDot.z || 0) + (_obj.endDot.z || 0)) / 2; |
| | | //z相同 表示x方向为长度 |
| | | if (_obj.startDot.z == _obj.endDot.z) { |
| | | wallLength = Math.abs(_obj.startDot.x - _obj.endDot.x); |
| | | wallWidth = _obj.thick || _commonThick; |
| | | } else if (_obj.startDot.x == _obj.endDot.x) { |
| | | wallLength = _obj.thick || _commonThick; |
| | | wallWidth = Math.abs(_obj.startDot.z - _obj.endDot.z); |
| | | } |
| | | var cubeobj = { |
| | | length: wallLength, |
| | | width: wallWidth, |
| | | height: _obj.height || _commonHeight, |
| | | rotation: _obj.rotation, |
| | | x: positionX, |
| | | uuid: _obj.uuid, |
| | | name: _obj.name, |
| | | y: positionY, |
| | | z: positionZ, |
| | | transparent: _obj.transparent || false, |
| | | style: { |
| | | skinColor: _commonSkin, |
| | | skin: _obj.skin |
| | | } |
| | | } |
| | | var _cube = _this.createCube(_this, cubeobj); |
| | | return _cube; |
| | | } |
| | | //模型合并 使用ThreeBSP插件mergeOP计算方式 -表示减去 +表示加上 |
| | | mergeModel(_this, mergeOP, _fobj, _sobj) { |
| | | if (_this == null) { |
| | | _this = this; |
| | | } |
| | | var fobjBSP = new ThreeBSP(_fobj); |
| | | var sobjBSP = new ThreeBSP(_sobj); |
| | | var resultBSP = null; |
| | | if (mergeOP == '-') { |
| | | resultBSP = fobjBSP.subtract(sobjBSP); |
| | | } else if (mergeOP == '+') { |
| | | var subMesh = new THREE.Mesh(_sobj); |
| | | _sobj.updateMatrix(); |
| | | _fobj.geometry.merge(_sobj.geometry, _sobj.matrix); |
| | | return _fobj; |
| | | // resultBSP = fobjBSP.union(sobjBSP); |
| | | } else if (mergeOP == '&') { //交集 |
| | | resultBSP = fobjBSP.intersect(sobjBSP); |
| | | } else { |
| | | _this.addObject(_sobj); |
| | | return _fobj; |
| | | } |
| | | var cubeMaterialArray = []; |
| | | for (var i = 0; i < 1; i++) { |
| | | cubeMaterialArray.push(new THREE.MeshLambertMaterial({ |
| | | vertexColors: THREE.FaceColors |
| | | })); |
| | | } |
| | | var result = resultBSP.toMesh(cubeMaterialArray); |
| | | result.material.shading = THREE.FlatShading; |
| | | result.geometry.computeFaceNormals(); |
| | | result.geometry.computeVertexNormals(); |
| | | result.uuid = _fobj.uuid + mergeOP + _sobj.uuid; |
| | | result.name = _fobj.name + mergeOP + _sobj.name; |
| | | result.material.needsUpdate = true; |
| | | result.geometry.buffersNeedUpdate = true; |
| | | result.geometry.uvsNeedUpdate = true; |
| | | var _foreFaceSkin = null; |
| | | for (var i = 0; i < result.geometry.faces.length; i++) { |
| | | var _faceset = false; |
| | | for (var j = 0; j < _fobj.geometry.faces.length; j++) { |
| | | if (result.geometry.faces[i].vertexNormals[0].x === _fobj.geometry.faces[j].vertexNormals[0].x && |
| | | result.geometry.faces[i].vertexNormals[0].y === _fobj.geometry.faces[j].vertexNormals[0].y && |
| | | result.geometry.faces[i].vertexNormals[0].z === _fobj.geometry.faces[j].vertexNormals[0].z && |
| | | result.geometry.faces[i].vertexNormals[1].x === _fobj.geometry.faces[j].vertexNormals[1].x && |
| | | result.geometry.faces[i].vertexNormals[1].y === _fobj.geometry.faces[j].vertexNormals[1].y && |
| | | result.geometry.faces[i].vertexNormals[1].z === _fobj.geometry.faces[j].vertexNormals[1].z && |
| | | result.geometry.faces[i].vertexNormals[2].x === _fobj.geometry.faces[j].vertexNormals[2].x && |
| | | result.geometry.faces[i].vertexNormals[2].y === _fobj.geometry.faces[j].vertexNormals[2].y && |
| | | result.geometry.faces[i].vertexNormals[2].z === _fobj.geometry.faces[j].vertexNormals[2].z) { |
| | | result.geometry.faces[i].color.setHex(_fobj.geometry.faces[j].color.r * 0xff0000 + _fobj.geometry.faces[j].color.g * 0x00ff00 + _fobj.geometry.faces[j].color.b * 0x0000ff); |
| | | _foreFaceSkin = _fobj.geometry.faces[j].color.r * 0xff0000 + _fobj.geometry.faces[j].color.g * 0x00ff00 + _fobj.geometry.faces[j].color.b * 0x0000ff; |
| | | _faceset = true; |
| | | } |
| | | } |
| | | if (_faceset == false) { |
| | | for (var j = 0; j < _sobj.geometry.faces.length; j++) { |
| | | if (result.geometry.faces[i].vertexNormals[0].x === _sobj.geometry.faces[j].vertexNormals[0].x && |
| | | result.geometry.faces[i].vertexNormals[0].y === _sobj.geometry.faces[j].vertexNormals[0].y && |
| | | result.geometry.faces[i].vertexNormals[0].z === _sobj.geometry.faces[j].vertexNormals[0].z && |
| | | result.geometry.faces[i].vertexNormals[1].x === _sobj.geometry.faces[j].vertexNormals[1].x && |
| | | result.geometry.faces[i].vertexNormals[1].y === _sobj.geometry.faces[j].vertexNormals[1].y && |
| | | result.geometry.faces[i].vertexNormals[1].z === _sobj.geometry.faces[j].vertexNormals[1].z && |
| | | result.geometry.faces[i].vertexNormals[2].x === _sobj.geometry.faces[j].vertexNormals[2].x && |
| | | result.geometry.faces[i].vertexNormals[2].y === _sobj.geometry.faces[j].vertexNormals[2].y && |
| | | result.geometry.faces[i].vertexNormals[2].z === _sobj.geometry.faces[j].vertexNormals[2].z && |
| | | result.geometry.faces[i].vertexNormals[2].z === _sobj.geometry.faces[j].vertexNormals[2].z) { |
| | | result.geometry.faces[i].color.setHex(_sobj.geometry.faces[j].color.r * 0xff0000 + _sobj.geometry.faces[j].color.g * 0x00ff00 + _sobj.geometry.faces[j].color.b * 0x0000ff); |
| | | _foreFaceSkin = _sobj.geometry.faces[j].color.r * 0xff0000 + _sobj.geometry.faces[j].color.g * 0x00ff00 + _sobj.geometry.faces[j].color.b * 0x0000ff; |
| | | _faceset = true; |
| | | } |
| | | } |
| | | } |
| | | if (_faceset == false) { |
| | | result.geometry.faces[i].color.setHex(_foreFaceSkin); |
| | | } |
| | | } |
| | | result.castShadow = true; |
| | | result.receiveShadow = true; |
| | | return result; |
| | | } |
| | | //创建盒子体 |
| | | createCube(_this, _obj) { |
| | | if (_this == null) { |
| | | _this = this; |
| | | } |
| | | var _length = _obj.length || 1000; //默认1000 |
| | | var _width = _obj.width || _length; |
| | | var _height = _obj.height || 10; |
| | | var _x = _obj.x || 0, |
| | | _y = _obj.y || 0, |
| | | _z = _obj.z || 0; |
| | | var skinColor = _obj.style.skinColor || 0x98750f; |
| | | var cubeGeometry = new THREE.BoxGeometry(_length, _height, _width, 0, 0, 1); |
| | | //六面颜色 |
| | | for (var i = 0; i < cubeGeometry.faces.length; i += 2) { |
| | | var hex = skinColor || Math.random() * 0x531844; |
| | | cubeGeometry.faces[i].color.setHex(hex); |
| | | cubeGeometry.faces[i + 1].color.setHex(hex); |
| | | } |
| | | //六面纹理 |
| | | var skin_up_obj = { |
| | | vertexColors: THREE.FaceColors |
| | | } |
| | | var skin_down_obj = skin_up_obj, |
| | | skin_fore_obj = skin_up_obj, |
| | | skin_behind_obj = skin_up_obj, |
| | | skin_left_obj = skin_up_obj, |
| | | skin_right_obj = skin_up_obj; |
| | | var skin_opacity = 1; |
| | | var transparent = _obj.transparent || false; |
| | | if (_obj.style != null && typeof (_obj.style) != 'undefined' && |
| | | _obj.style.skin != null && typeof (_obj.style.skin) != 'undefined') { |
| | | //透明度 |
| | | if (_obj.style.skin.opacity != null && typeof (_obj.style.skin.opacity) != 'undefined') { |
| | | skin_opacity = _obj.style.skin.opacity; |
| | | } |
| | | //上 |
| | | skin_up_obj = _this.createSkinOptionOnj(_this, _length, _width, _obj.style.skin.skin_up, cubeGeometry, 4, skin_opacity, transparent); |
| | | //下 |
| | | skin_down_obj = _this.createSkinOptionOnj(_this, _length, _width, _obj.style.skin.skin_down, cubeGeometry, 6, skin_opacity, transparent); |
| | | //前 |
| | | skin_fore_obj = _this.createSkinOptionOnj(_this, _length, _width, _obj.style.skin.skin_fore, cubeGeometry, 0, skin_opacity, transparent); |
| | | //后 |
| | | skin_behind_obj = _this.createSkinOptionOnj(_this, _length, _width, _obj.style.skin.skin_behind, cubeGeometry, 2, skin_opacity, transparent); |
| | | //左 |
| | | skin_left_obj = _this.createSkinOptionOnj(_this, _length, _width, _obj.style.skin.skin_left, cubeGeometry, 8, skin_opacity, transparent); |
| | | //右 |
| | | skin_right_obj = _this.createSkinOptionOnj(_this, _length, _width, _obj.style.skin.skin_right, cubeGeometry, 10, skin_opacity, transparent); |
| | | } |
| | | var cubeMaterialArray = []; |
| | | cubeMaterialArray.push(new THREE.MeshLambertMaterial(skin_fore_obj)); |
| | | cubeMaterialArray.push(new THREE.MeshLambertMaterial(skin_behind_obj)); |
| | | cubeMaterialArray.push(new THREE.MeshLambertMaterial(skin_up_obj)); |
| | | cubeMaterialArray.push(new THREE.MeshLambertMaterial(skin_down_obj)); |
| | | cubeMaterialArray.push(new THREE.MeshLambertMaterial(skin_right_obj)); |
| | | cubeMaterialArray.push(new THREE.MeshLambertMaterial(skin_left_obj)); |
| | | |
| | | var cube = new THREE.Mesh(cubeGeometry, cubeMaterialArray); |
| | | cube.castShadow = true; |
| | | cube.receiveShadow = true; |
| | | cube.uuid = _obj.uuid; |
| | | cube.name = _obj.name; |
| | | cube.position.set(_x, _y, _z); |
| | | if (_obj.rotation != null && typeof (_obj.rotation) != 'undefined' && _obj.rotation.length > 0) { |
| | | _obj.rotation.forEach(function (v, i) { |
| | | switch (v.direction) { |
| | | case 'x': |
| | | cube.rotateX(v.degree); |
| | | break; |
| | | case 'y': |
| | | cube.rotateY(v.degree); |
| | | break; |
| | | case 'z': |
| | | cube.rotateZ(v.degree); |
| | | break; |
| | | case 'arb': |
| | | cube.rotateOnAxis(new THREE.Vector3(v.degree[0], v.degree[1], v.degree[2]), v.degree[3]); |
| | | break; |
| | | } |
| | | }) |
| | | } |
| | | return cube; |
| | | } |
| | | //创建皮肤参数对象 |
| | | createSkinOptionOnj(_this, flength, fwidth, _obj, _cube, _cubefacenub, opacity, transparent) { |
| | | if (_this.hasObj(_obj)) { |
| | | if (_this.hasObj(_obj.imgurl)) { |
| | | return { |
| | | map: _this.createSkin(flength, fwidth, _obj), |
| | | transparent: transparent, |
| | | opacity: opacity, |
| | | } |
| | | } else { |
| | | if (_this.hasObj(_obj.skinColor)) { |
| | | _cube.faces[_cubefacenub].color.setHex(_obj.skinColor); |
| | | _cube.faces[_cubefacenub + 1].color.setHex(_obj.skinColor); |
| | | } |
| | | return { |
| | | vertexColors: THREE.FaceColors |
| | | } |
| | | } |
| | | } else { |
| | | return { |
| | | vertexColors: THREE.FaceColors |
| | | } |
| | | } |
| | | } |
| | | //创建皮肤 |
| | | createSkin(flength, fwidth, _obj) { |
| | | var imgwidth = 128, |
| | | imgheight = 128; |
| | | if (_obj.width != null && typeof (_obj.width) != 'undefined') { |
| | | imgwidth = _obj.width; |
| | | } |
| | | if (_obj.height != null && typeof (_obj.height) != 'undefined') { |
| | | imgheight = _obj.height; |
| | | } |
| | | var texture = new THREE.TextureLoader().load(_obj.imgurl, function (e) {}, function (e) {}); |
| | | var _repeat = false; |
| | | if (_obj.repeatx != null && typeof (_obj.repeatx) != 'undefined' && _obj.repeatx == true) { |
| | | texture.wrapS = THREE.RepeatWrapping; |
| | | _repeat = true; |
| | | } |
| | | if (_obj.repeaty != null && typeof (_obj.repeaty) != 'undefined' && _obj.repeaty == true) { |
| | | texture.wrapT = THREE.RepeatWrapping; |
| | | _repeat = true; |
| | | } |
| | | if (_repeat) { |
| | | texture.repeat.set(flength / imgheight, fwidth / imgheight); |
| | | } |
| | | return texture; |
| | | } |
| | | //创建空柜子 |
| | | createEmptyCabinet(_this, _obj) { |
| | | /* 参数demo |
| | | { |
| | | show:true, |
| | | name: 'test', |
| | | uuid: 'test', |
| | | rotation: [{ direction: 'y', degree: 0.25*Math.PI}],//旋转 |
| | | objType: 'emptyCabinet', |
| | | transparent:true, |
| | | size:{length:50,width:60,height:200, thick:2}, |
| | | position: { x: -220, y: 105, z: -150 }, |
| | | doors: { |
| | | skins:[ { |
| | | skinColor: 0x333333, |
| | | skin_fore: { |
| | | imgurl: "../datacenterdemo/res/rack_door_back.jpg", |
| | | }, |
| | | skin_behind: { |
| | | imgurl: "../datacenterdemo/res/rack_front_door.jpg", |
| | | } |
| | | }] |
| | | }, |
| | | skin:{ |
| | | skinColor: 0xdddddd, |
| | | skin:{ |
| | | skinColor: 0xdddddd, |
| | | skin_up: { imgurl: "../datacenterdemo/res/rack_door_back.jpg" }, |
| | | skin_down: { imgurl: "../datacenterdemo/res/rack_door_back.jpg" }, |
| | | skin_fore: { imgurl: "../datacenterdemo/res/rack_door_back.jpg" }, |
| | | skin_behind: { imgurl: "../datacenterdemo/res/rack_door_back.jpg" }, |
| | | skin_left: { imgurl: "../datacenterdemo/res/rack_door_back.jpg" }, |
| | | skin_right: { imgurl: "../datacenterdemo/res/rack_door_back.jpg" }, |
| | | } |
| | | } |
| | | } |
| | | */ |
| | | |
| | | var _this = this; |
| | | var cabLength = Number(_obj.length) || 66; //机柜长 |
| | | var cabWidth = Number(_obj.width) || 70; //机柜宽 |
| | | var cabHeight = Number(_obj.height) || 200; //机柜高 |
| | | var cabThick = Number(_obj.thick) || 2; //机柜壁厚 |
| | | var cabPx = Number(_obj.x) || 0; //中心原点X值 |
| | | var cabPy = Number(_obj.y) || 100; //中心原点Y值 |
| | | var cabPz = Number(_obj.z) || 0; //中心原点Z值 |
| | | //创建五个面 |
| | | //上 |
| | | var upobj = { |
| | | show: true, |
| | | uuid: "", |
| | | name: 'upobj', |
| | | objType: 'cube', |
| | | length: cabLength, |
| | | width: cabWidth, |
| | | height: cabThick, |
| | | x: cabPx, |
| | | y: cabPy, |
| | | z: cabPz, |
| | | style: { |
| | | skinColor: _obj.skin.skinColor, |
| | | skin: _obj.skin.skin_up.skin |
| | | } |
| | | } |
| | | var upcube = _this.createCube(_this, upobj); |
| | | //左 |
| | | var leftobj = { |
| | | show: true, |
| | | uuid: "", |
| | | name: 'leftobj', |
| | | objType: 'cube', |
| | | length: cabLength, |
| | | width: cabThick, |
| | | height: cabHeight, |
| | | x: 0, |
| | | y: -(cabHeight / 2 - cabThick / 2), |
| | | z: 0 - (cabWidth / 2 - cabThick / 2) - 1, |
| | | style: { |
| | | skinColor: _obj.skin.skinColor, |
| | | skin: _obj.skin.skin_left.skin |
| | | } |
| | | } |
| | | var leftcube = _this.createCube(_this, leftobj); |
| | | var Cabinet = _this.mergeModel(_this, '+', upcube, leftcube); |
| | | //右 |
| | | var Rightobj = { |
| | | show: true, |
| | | uuid: "", |
| | | name: 'Rightobj', |
| | | objType: 'cube', |
| | | length: cabLength, |
| | | width: cabThick, |
| | | height: cabHeight, |
| | | x: 0, |
| | | y: -(cabHeight / 2 - cabThick / 2), |
| | | z: (cabWidth / 2 - cabThick / 2) + 1, |
| | | style: { |
| | | skinColor: _obj.skin.skinColor, |
| | | skin: _obj.skin.skin_right.skin |
| | | } |
| | | } |
| | | var Rightcube = _this.createCube(_this, Rightobj); |
| | | Cabinet = _this.mergeModel(_this, '+', Cabinet, Rightcube); |
| | | //后 |
| | | var Behidobj = { |
| | | show: true, |
| | | uuid: "", |
| | | name: 'Behidobj', |
| | | objType: 'cube', |
| | | length: cabThick, |
| | | width: cabWidth, |
| | | height: cabHeight, |
| | | x: (cabLength / 2 - cabThick / 2) + 1, |
| | | y: -(cabHeight / 2 - cabThick / 2), |
| | | z: 0, |
| | | style: { |
| | | skinColor: _obj.skin.skinColor, |
| | | skin: _obj.skin.skin_behind.skin |
| | | } |
| | | } |
| | | var Behindcube = _this.createCube(_this, Behidobj); |
| | | Cabinet = _this.mergeModel(_this, '+', Cabinet, Behindcube); |
| | | //下 |
| | | var Downobj = { |
| | | show: true, |
| | | uuid: "", |
| | | name: 'Downobj', |
| | | objType: 'cube', |
| | | length: cabLength, |
| | | width: cabWidth, |
| | | height: cabThick, |
| | | x: -1, |
| | | y: -(cabHeight - cabThick) - 1, |
| | | z: 0, |
| | | style: { |
| | | skinColor: _obj.skin.skinColor, |
| | | skin: _obj.skin.skin_down.skin |
| | | } |
| | | } |
| | | var Downcube = _this.createCube(_this, Downobj); |
| | | Cabinet = _this.mergeModel(_this, '+', Cabinet, Downcube); |
| | | |
| | | var tempobj = new THREE.Object3D(); |
| | | tempobj.add(Cabinet); |
| | | tempobj.name = _obj.name; |
| | | tempobj.uuid = _obj.uuid; |
| | | for (const key in Cabinet.position) { |
| | | tempobj.position[key] = Cabinet.position[key] |
| | | } |
| | | Cabinet.name = _obj.shellname; |
| | | Cabinet.position.set(0, cabPy, 0); |
| | | _this.objects.push(Cabinet); |
| | | //门 |
| | | if (_obj.doors != null && typeof (_obj.doors) != 'undefined') { |
| | | var doors = _obj.doors; |
| | | var singledoorobj = { |
| | | show: true, |
| | | uuid: "", |
| | | name: _obj.doors.doorname, |
| | | objType: 'cube', |
| | | length: cabThick, |
| | | width: cabWidth, |
| | | height: cabHeight, |
| | | x: -cabLength / 2, |
| | | y: cabPy - cabHeight / 2, |
| | | z: 0, |
| | | transparent: _obj.doors.transparent || false, |
| | | style: { |
| | | skinColor: _obj.doors.skins.skinColor, |
| | | skin: _obj.doors.skins |
| | | } |
| | | } |
| | | var singledoorcube = _this.createCube(_this, singledoorobj); |
| | | _this.objects.push(singledoorcube); |
| | | tempobj.add(singledoorcube); |
| | | } |
| | | if (_obj.rotation != null && typeof (_obj.rotation) != 'undefined' && _obj.rotation.length > 0) { |
| | | _obj.rotation.forEach(function (v, i) { |
| | | switch (v.direction) { |
| | | case 'x': |
| | | tempobj.rotateX(v.degree); |
| | | break; |
| | | case 'y': |
| | | tempobj.rotateY(v.degree); |
| | | break; |
| | | case 'z': |
| | | tempobj.rotateZ(v.degree); |
| | | break; |
| | | case 'arb': |
| | | tempobj.rotateOnAxis(new THREE.Vector3(v.degree[0], v.degree[1], v.degree[2]), v.degree[3]); |
| | | break; |
| | | } |
| | | }) |
| | | } |
| | | //创建机柜所属服务器 |
| | | if (_this.hasObj(_obj.childrens) && _obj.childrens.length > 0) { |
| | | _obj.childrens.forEach(function (item, m) { |
| | | var newObj = item; |
| | | newObj.length = cabLength; |
| | | newObj.width = cabWidth; |
| | | newObj.height = item.height || 20; |
| | | newObj.x = 0; |
| | | newObj.z = 0; |
| | | newObj.y = item.y; |
| | | tempobj.add(_this.createCube(_this, newObj)); |
| | | }) |
| | | } |
| | | _this.dragObjects.push(tempobj); |
| | | return tempobj; |
| | | } |
| | | //创建玻璃 |
| | | createGlasses(_this, _obj) { |
| | | var _this = this; |
| | | var tmpobj = _this.createPlaneGeometry(_this, _obj); |
| | | _this.addObject(tmpobj); |
| | | _obj.rotation.y = Math.PI + _obj.rotation.y; |
| | | var tmpobj2 = _this.createPlaneGeometry(_this, _obj); |
| | | // _this.addObject(tmpobj2); |
| | | return tmpobj2 |
| | | } |
| | | //创建管道 |
| | | createChannelGeometry(_this, _obj) { |
| | | var _this = this; |
| | | let pathArr = []; |
| | | if (_obj.path.length > 0) { |
| | | _obj.path.map(item => { |
| | | pathArr.push(new THREE.Vector3(item.x, item.y, item.z)) |
| | | }) |
| | | } else { |
| | | pathArr = [] |
| | | } |
| | | var path = new THREE.CatmullRomCurve3(pathArr); |
| | | let tubularSegments = _obj.tubularSegments || 64; |
| | | let radius = _obj.radius || 2; |
| | | let radiusSegments = _obj.radiusSegments || 18; |
| | | let closed = _obj.closed || false; |
| | | var tubeGeometry = new THREE.TubeGeometry(path, tubularSegments, radius, radiusSegments, closed); |
| | | var textureLoader = new THREE.TextureLoader(); |
| | | var texture = textureLoader.load(_obj.imgurl); |
| | | |
| | | // 设置阵列模式 RepeatWrapping |
| | | texture.wrapS = THREE.RepeatWrapping |
| | | texture.wrapT = THREE.RepeatWrapping |
| | | // 设置x方向的重复数(沿着管道路径方向) |
| | | // 设置y方向的重复数(环绕管道方向) |
| | | texture.repeat.x = 10; |
| | | texture.repeat.y = 4; |
| | | // 设置管道纹理偏移数,便于对中 |
| | | texture.offset.y = 0.5; |
| | | var tubeMaterial = new THREE.MeshPhongMaterial({ |
| | | map: texture, |
| | | transparent: true, |
| | | }); |
| | | var channel = new THREE.Mesh(tubeGeometry, tubeMaterial); |
| | | // 使用加减法可以设置不同的运动方向 |
| | | setInterval(() => { |
| | | texture.offset.x += 0.0076 |
| | | }) |
| | | return channel; |
| | | } |
| | | //创建二维平面-长方形 |
| | | createPlaneGeometry(_this, _obj) { |
| | | //options={ |
| | | // width:0, |
| | | // height:0, |
| | | // pic:"", |
| | | // transparent:true, |
| | | // opacity:1 |
| | | // blending:false, |
| | | // position: { x:,y:,z:}, |
| | | // rotation: { x:,y:,z:}, |
| | | //} |
| | | var options = _obj; |
| | | if (typeof options.pic == "string") { //传入的材质是图片路径,使用 textureloader加载图片作为材质 |
| | | var loader = new THREE.TextureLoader(); |
| | | loader.setCrossOrigin(this.crossOrigin); |
| | | var texture = loader.load(options.pic, function () {}, undefined, function () {}); |
| | | } else { |
| | | var texture = new THREE.CanvasTexture(options.pic) |
| | | } |
| | | var MaterParam = { //材质的参数 |
| | | map: texture, |
| | | // overdraw: true, |
| | | side: THREE.FrontSide, |
| | | transparent: options.transparent, |
| | | opacity: options.opacity |
| | | } |
| | | if (options.blending) { |
| | | MaterParam.blending = THREE.AdditiveBlending //使用饱和度叠加渲染 |
| | | } |
| | | var plane = new THREE.Mesh( |
| | | new THREE.PlaneGeometry(options.width, options.height, 1, 1), |
| | | new THREE.MeshBasicMaterial(MaterParam) |
| | | ); |
| | | plane.position.x = options.position.x; |
| | | plane.position.y = options.position.y; |
| | | plane.position.z = options.position.z; |
| | | plane.rotation.x = options.rotation.x; |
| | | plane.rotation.y = options.rotation.y; |
| | | plane.rotation.z = options.rotation.z; |
| | | return plane; |
| | | } |
| | | //创建货架及货架上商品(电池) |
| | | createShelves(_this, _obj) { |
| | | var _this = this; |
| | | var PLANE_LENGTH = Number(_obj.PLANE_LENGTH) || 66; //货架板面长度 |
| | | var PLANE_WIDTH = Number(_obj.PLANE_WIDTH) || 70; //货架板面宽度 |
| | | var PLANE_HEIGHT = Number(_obj.PLANE_HEIGHT) || 4; //货架板面高度 |
| | | var HOLDER_LENGTH = Number(_obj.HOLDER_LENGTH) || 4; //支架长度 |
| | | var HOLDER_WIDTH = Number(_obj.HOLDER_WIDTH) || 4; //支架宽度 |
| | | var HOLDER_HEIGHT = Number(_obj.HOLDER_HEIGHT) || 40; //支架高度 |
| | | var LAYER_NUM = Number(_obj.LAYER_NUM) + 1 || 3; //货架层数 |
| | | var COLUMN_NUM = Number(_obj.COLUMN_NUM) || 2; //货架每层列数 |
| | | var px = Number(_obj.x) || 0 //货架中心位置 |
| | | var py = Number(_obj.y) || 0 //货架中心位置 |
| | | var pz = Number(_obj.z) || 0 //货架中心位置 |
| | | var tempobj = new THREE.Object3D(); |
| | | // 创建每层货架板 |
| | | for (let i = 0; i < LAYER_NUM; i++) { |
| | | tempobj.add(_this.createCube(_this, { |
| | | show: true, |
| | | uuid: "", |
| | | name: 'layers', |
| | | objType: 'cube', |
| | | length: PLANE_LENGTH, |
| | | width: PLANE_WIDTH * COLUMN_NUM + HOLDER_WIDTH, |
| | | height: PLANE_HEIGHT, |
| | | x: px, |
| | | y: py + (HOLDER_HEIGHT + PLANE_HEIGHT) * i + PLANE_HEIGHT / 2 + 10, |
| | | z: pz, |
| | | style: { |
| | | skinColor: _obj.style.skinColor, |
| | | skin: _obj.style.skin |
| | | } |
| | | })) |
| | | if (i < LAYER_NUM - 1) { |
| | | // 创建货架支架 |
| | | for (let j = 0; j < (COLUMN_NUM + 1) * 2; j++) { |
| | | if (j < COLUMN_NUM + 1) { |
| | | tempobj.add(_this.createCube(_this, { |
| | | show: true, |
| | | uuid: "", |
| | | name: 'Bracket', |
| | | objType: 'cube', |
| | | length: HOLDER_LENGTH, |
| | | width: HOLDER_WIDTH, |
| | | height: HOLDER_HEIGHT + PLANE_HEIGHT + (10 * (i + 1)), |
| | | x: px + PLANE_LENGTH / 2 - HOLDER_LENGTH / 2, |
| | | y: py + (HOLDER_HEIGHT + PLANE_HEIGHT) * i + PLANE_HEIGHT / 2 + 10 + HOLDER_HEIGHT / 2 - PLANE_HEIGHT * (LAYER_NUM - 1), |
| | | z: pz - (PLANE_WIDTH * COLUMN_NUM) / 2 + PLANE_WIDTH * j, |
| | | style: { |
| | | skinColor: _obj.style.skinColor, |
| | | skin: _obj.style.skin |
| | | } |
| | | })) |
| | | } else { |
| | | tempobj.add(_this.createCube(_this, { |
| | | show: true, |
| | | uuid: "", |
| | | name: 'Bracket', |
| | | objType: 'cube', |
| | | length: HOLDER_LENGTH, |
| | | width: HOLDER_WIDTH, |
| | | height: HOLDER_HEIGHT + PLANE_HEIGHT + (10 * (i + 1)), |
| | | x: px - PLANE_LENGTH / 2 + HOLDER_LENGTH / 2, |
| | | y: py + (HOLDER_HEIGHT + PLANE_HEIGHT) * i + PLANE_HEIGHT / 2 + 10 + HOLDER_HEIGHT / 2 - PLANE_HEIGHT * (LAYER_NUM - 1), |
| | | z: pz - (PLANE_WIDTH * COLUMN_NUM) / 2 + PLANE_WIDTH * (j - COLUMN_NUM - 1), |
| | | style: { |
| | | skinColor: _obj.style.skinColor, |
| | | skin: _obj.style.skin |
| | | } |
| | | })) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | if (_this.hasObj(_obj.childrens) && _obj.childrens.length > 0) { |
| | | _obj.childrens.forEach(function (item, m) { |
| | | if (m < LAYER_NUM * COLUMN_NUM) { |
| | | var layers = Math.ceil((m + 1) / COLUMN_NUM) - 1; |
| | | var index; |
| | | if ((m + 1) > COLUMN_NUM) { |
| | | index = m - COLUMN_NUM * layers; |
| | | } else { |
| | | index = m |
| | | } |
| | | var _newobj = item; |
| | | _newobj.length = item.length || PLANE_LENGTH; |
| | | _newobj.width = item.width || PLANE_WIDTH - HOLDER_WIDTH; |
| | | _newobj.height = item.height || HOLDER_HEIGHT; |
| | | _newobj.x = px; |
| | | _newobj.y = py + (HOLDER_HEIGHT + PLANE_HEIGHT) * layers + PLANE_HEIGHT + 10 + _newobj.height / 2; |
| | | _newobj.z = pz - (PLANE_WIDTH / 2) * (COLUMN_NUM - 1) + PLANE_WIDTH * index |
| | | tempobj.add(_this.createCube(_this, item)) |
| | | } |
| | | }) |
| | | } |
| | | tempobj.position.set(px, py, pz); |
| | | if (tempobj.children != null && typeof (tempobj.children) != 'undefined' && tempobj.children.length > 0) { |
| | | tempobj.children.forEach((item, index) => { |
| | | item.position.x -= px; |
| | | item.position.y -= py; |
| | | item.position.z -= pz; |
| | | }); |
| | | } |
| | | if (_obj.rotation != null && typeof (_obj.rotation) != 'undefined' && _obj.rotation.length > 0) { |
| | | _obj.rotation.forEach(function (v, i) { |
| | | switch (v.direction) { |
| | | case 'x': |
| | | tempobj.rotateX(v.degree); |
| | | break; |
| | | case 'y': |
| | | tempobj.rotateY(v.degree); |
| | | break; |
| | | case 'z': |
| | | tempobj.rotateZ(v.degree); |
| | | break; |
| | | case 'arb': |
| | | tempobj.rotateOnAxis(new THREE.Vector3(v.degree[0], v.degree[1], v.degree[2]), v.degree[3]); |
| | | break; |
| | | } |
| | | }) |
| | | } |
| | | tempobj.name = _obj.name; |
| | | _this.dragObjects.push(tempobj); |
| | | return tempobj |
| | | } |
| | | //通用方法=========================================================================================== |
| | | //判断对象 |
| | | hasObj(_obj) { |
| | | if (_obj != null && typeof (_obj) != 'undefined') { |
| | | return true; |
| | | } else { |
| | | return false; |
| | | } |
| | | } |
| | | //查找对象 |
| | | findObject(_objname) { |
| | | var _this = this; |
| | | var findedobj = null; |
| | | try { |
| | | _this.objects.forEach(function (v, i) { |
| | | if (v.name != null && v.name != '') { |
| | | if (v.name == _objname) { |
| | | findedobj = v; |
| | | throw new Error('') |
| | | } |
| | | } |
| | | }) |
| | | } catch (e) {} |
| | | return findedobj; |
| | | } |
| | | //复制对象 |
| | | cloneObj(_objname, newparam) { |
| | | /*newparam |
| | | { |
| | | show: true, |
| | | uuid: |
| | | copyfrom: 'cabinet1_1', |
| | | name: |
| | | childrenname:[] |
| | | objType: 'cloneObj', |
| | | position:{x:y:z:}//相对复制品的 |
| | | scale:{x:1,y:1,z:1} |
| | | rotation: [{ direction: 'y', degree: 0.25*Math.PI}],//旋转 uuid:'', |
| | | } |
| | | */ |
| | | var _this = this; |
| | | var fobj = _this.findObject(_objname); |
| | | var newobj = newobj = fobj.clone(); |
| | | if (newobj.children != null && newobj.children.length > 1) { |
| | | newobj.children.forEach(function (v, i) { |
| | | v.name = newparam.childrenname[i]; |
| | | _this.objects.push(v); |
| | | }) |
| | | } |
| | | //位置 |
| | | if (_this.hasObj(newparam.position)) { |
| | | newobj.position.x = newparam.position.x; |
| | | newobj.position.y = newparam.position.y; |
| | | newobj.position.z = newparam.position.z; |
| | | } |
| | | //大小 |
| | | if (_this.hasObj(newparam.scale)) { |
| | | newobj.scale.x = newparam.scale.x; |
| | | newobj.scale.y = newparam.scale.y; |
| | | newobj.scale.z = newparam.scale.z; |
| | | } |
| | | //角度 |
| | | if (_this.hasObj(newparam.rotation)) { |
| | | newparam.rotation.forEach(function (v, i) { |
| | | switch (v.direction) { |
| | | case 'x': |
| | | newobj.rotateX(v.degree); |
| | | break; |
| | | case 'y': |
| | | newobj.rotateY(v.degree); |
| | | break; |
| | | case 'z': |
| | | newobj.rotateZ(v.degree); |
| | | break; |
| | | case 'arb': |
| | | newobj.rotateOnAxis(new THREE.Vector3(v.degree[0], v.degree[1], v.degree[2]), v.degree[3]); |
| | | break; |
| | | } |
| | | }) |
| | | } |
| | | newobj.name = newparam.name; |
| | | newobj.uuid = newparam.uuid; |
| | | _this.dragObjects.push(newobj); |
| | | return newobj; |
| | | } |
| | | //设置表皮颜色 |
| | | setSkinColor(_objname, _color) { |
| | | var _this = this; |
| | | var _obj = _this.findObject(_objname); |
| | | if (_this.hasObj(_obj.material.emissive)) { |
| | | _obj.material.emissive.setHex(_color); |
| | | } else if (_this.hasObj(_obj.material.materials)) { |
| | | if (_obj.material.materials.length > 0) { |
| | | _obj.material.materials.forEach(function (v, i) { |
| | | v.emissive.setHex(_color); |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | //添加图片标识 |
| | | addIdentification(_objname, _obj) { |
| | | var _this = this; |
| | | var _fobj = _this.findObject(_objname); |
| | | var loader = new THREE.TextureLoader(); |
| | | var texture = loader.load(_obj.imgurl, function () {}, undefined, function () {}); |
| | | var spriteMaterial = new THREE.SpriteMaterial({ |
| | | map: texture, |
| | | useScreenCoordinates: false |
| | | }); |
| | | var sprite = new THREE.Sprite(spriteMaterial); |
| | | sprite.name = _obj.name; |
| | | sprite.position.x = _fobj.position.x + cabPx; |
| | | sprite.position.y = _fobj.position.y + cabPy; |
| | | sprite.position.z = _fobj.position.z + cabPz; |
| | | if (_this.hasObj(_obj.size)) { |
| | | sprite.scale.set(_obj.size.x, _obj.size.y); |
| | | } else { |
| | | sprite.scale.set(1, 1); |
| | | } |
| | | _this.addObject(sprite); |
| | | } |
| | | //添加文字 |
| | | makeTextSprite(_objname, parameters) { |
| | | var _this = this; |
| | | var _fobj = _this.findObject(_objname); |
| | | if (parameters === undefined) parameters = {}; |
| | | var fontface = parameters.hasOwnProperty("fontface") ? parameters["fontface"] : "Arial"; |
| | | var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; |
| | | var borderThickness = parameters.hasOwnProperty("borderThickness") ? parameters["borderThickness"] : 4; |
| | | var textColor = parameters.hasOwnProperty("textColor") ? parameters["textColor"] : { |
| | | r: 0, |
| | | g: 0, |
| | | b: 0, |
| | | a: 1.0 |
| | | }; |
| | | var message = parameters.hasOwnProperty("message") ? parameters["message"] : "helloMsj3D"; |
| | | var x = parameters.hasOwnProperty("position") ? parameters["position"].x : 0; |
| | | var y = parameters.hasOwnProperty("position") ? parameters["position"].y : 0; |
| | | var z = parameters.hasOwnProperty("position") ? parameters["position"].z : 0; |
| | | var canvas = document.createElement('canvas'); |
| | | var context = canvas.getContext('2d'); |
| | | context.font = "Bold " + fontsize + "px " + fontface; |
| | | var metrics = context.measureText(message); |
| | | var textWidth = metrics.width; |
| | | context.lineWidth = borderThickness; |
| | | context.fillStyle = "rgba(" + textColor.r + ", " + textColor.g + ", " + textColor.b + ", 1.0)"; |
| | | context.fillText(message, borderThickness, fontsize + borderThickness); |
| | | var texture = new THREE.Texture(canvas) |
| | | texture.needsUpdate = true; |
| | | var spriteMaterial = new THREE.SpriteMaterial({ |
| | | map: texture, |
| | | useScreenCoordinates: false |
| | | }); |
| | | var sprite = new THREE.Sprite(spriteMaterial); |
| | | sprite.position.x = _fobj.position.x + x; |
| | | sprite.position.y = _fobj.position.y + y; |
| | | sprite.position.z = _fobj.position.z + z; |
| | | sprite.name = parameters.name; |
| | | sprite.scale.set(0.5 * fontsize, 0.25 * fontsize, 0.75 * fontsize); |
| | | _this.addObject(sprite); |
| | | } |
| | | /* |
| | | *事件部分 |
| | | */ |
| | | //窗口大小变化 |
| | | onWindowResize() { |
| | | var _this = this; |
| | | _this.element = document.getElementById(_this.fId); |
| | | _this.width = _this.element.clientWidth; |
| | | _this.height = _this.element.clientHeight; |
| | | _this.camera.aspect = _this.width / _this.height; |
| | | _this.camera.updateProjectionMatrix(); |
| | | _this.renderer.setSize(_this.width, _this.height); |
| | | _this.timeRender(); |
| | | } |
| | | //鼠标按下事件 |
| | | onDocumentMouseDown(event) { |
| | | dbclick++; |
| | | var _this = this; |
| | | setTimeout(function () { |
| | | dbclick = 0 |
| | | }, 300); |
| | | event.preventDefault(); |
| | | if (dbclick >= 2) { |
| | | 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.dbclick != null && _this.eventList.dbclick.length > 0) { |
| | | _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); |
| | | } |
| | | } else if (v.findObject != null || 'function' == typeof (v.findObject)) { |
| | | if (v.findObject(_this.SELECTED.name)) { |
| | | v.obj_event(_this.SELECTED, _this); |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | _this.controls.enabled = true; |
| | | } |
| | | } |
| | | } |
| | | //鼠标抬起事件 |
| | | onDocumentMouseUp(event) { |
| | | var _this = this; |
| | | event.preventDefault(); |
| | | //通过鼠标点击的位置计算出raycaster所需要的点的位置,以屏幕中心为原点,值的范围为-1到1. |
| | | _this.mouseClick.x = (event.clientX / _this.width) * 2 - 1; |
| | | _this.mouseClick.y = -(event.clientY / _this.height) * 2 + 1; |
| | | // 通过鼠标点的位置和当前相机的矩阵计算出raycaster |
| | | _this.raycaster.setFromCamera(_this.mouseClick, _this.camera); |
| | | // 获取raycaster直线和所有模型相交的数组集合 |
| | | var intersects = _this.raycaster.intersectObjects(_this.dragObjects, true); |
| | | if (intersects.length > 0) { |
| | | //先通过当前点击位置的坐标和相机计算出raycaster线,然后计算出相交的所有模型,修改模型参数。 |
| | | _this.controls.enabled = false; |
| | | _this.SELECTED = intersects[0].object.parent; |
| | | if (_this.eventList != null && _this.eventList.click != null) { |
| | | _this.eventList.mouseUp.obj_event(_this.SELECTED, _this); |
| | | } |
| | | _this.controls.enabled = true; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | /* |
| | | * @Description: 3D机房初始化数据 |
| | | * @Autor: ZengYK |
| | | * @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 switchStationTop = require("../../../../public/three/images/switchStation/top.jpg"); |
| | | const rectifierBehind = require("../../../../public/three/images/rectifier/behind.png"); |
| | | const rectifierLeft = require("../../../../public/three/images/rectifier/left.png"); |
| | | const rectifierRight = require("../../../../public/three/images/rectifier/right.png"); |
| | | const rectifierTop = require("../../../../public/three/images/rectifier/top.png"); |
| | | const distributionBehind = require("../../../../public/three/images/distribution/behind.jpg"); |
| | | const distributionFore = require("../../../../public/three/images/distribution/fore.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 channel = require("../../../../public/three/images/channel.jpg"); |
| | | let Aobjects = { |
| | | objects: [ |
| | | //地板 |
| | | { |
| | | show: true, |
| | | uuid: "", |
| | | name: 'floor', |
| | | objType: 'floor', |
| | | length: 60000, |
| | | width: 60000, |
| | | height: 1, |
| | | rotation: [{ |
| | | direction: 'x', |
| | | degree: 0 |
| | | }], //旋转 表示x方向0度 |
| | | x: 0, |
| | | y: 0, |
| | | z: 0, |
| | | style: { |
| | | skin: { |
| | | skinColor: 0x8ac9e2, |
| | | skin_up: { |
| | | skinColor: 0x98750f, |
| | | imgurl: floorB, |
| | | repeatx: true, |
| | | repeaty: true, |
| | | width: 1250, |
| | | height: 1250 |
| | | }, |
| | | skin_down: { |
| | | skinColor: 0x8ac9e2, |
| | | imgurl: floorB, |
| | | repeatx: true, |
| | | repeaty: true, |
| | | width: 1250, |
| | | height: 1250 |
| | | }, |
| | | skin_fore: { |
| | | skinColor: 0x8ac9e2, |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | //管道 |
| | | { |
| | | show: true, |
| | | name: 'channel1', |
| | | uuid: "", |
| | | objType: 'channel', |
| | | radius: 3, |
| | | closed: true, |
| | | path: [{ |
| | | x: 0, |
| | | y: 40, |
| | | z: 1200 |
| | | }, { |
| | | x: 0, |
| | | y: 40, |
| | | z: 500 |
| | | }, { |
| | | x: 1000, |
| | | y: 40, |
| | | z: 500 |
| | | }], |
| | | imgurl: channel, |
| | | }, |
| | | //开闭所 |
| | | { |
| | | show: true, |
| | | uuid: "", |
| | | name: 'switchStation', |
| | | objType: 'cube', |
| | | length: 88, |
| | | width: 339, |
| | | height: 200, |
| | | rotation: [{ |
| | | direction: 'y', |
| | | degree: 0.5 * Math.PI |
| | | }], //旋转 表示x方向0度 |
| | | x: 0, |
| | | y: 100, |
| | | z: 1200, |
| | | style: { |
| | | skinColor: 0xfefefe, |
| | | skin: { |
| | | skin_fore: { |
| | | imgurl: switchStationFore, |
| | | skinColor: 0xfefefe, |
| | | }, |
| | | skin_behind: { |
| | | imgurl: switchStationBehind, |
| | | skinColor: 0xfefefe, |
| | | }, |
| | | skin_down: { |
| | | imgurl: switchStationTop, |
| | | skinColor: 0xfefefe, |
| | | }, |
| | | skin_up: { |
| | | imgurl: switchStationTop, |
| | | skinColor: 0xfefefe, |
| | | }, |
| | | skin_left: { |
| | | imgurl: switchStationLeft, |
| | | skinColor: 0xfefefe, |
| | | }, |
| | | skin_right: { |
| | | imgurl: switchStationLeft, |
| | | skinColor: 0xfefefe, |
| | | }, |
| | | } |
| | | } |
| | | }, |
| | | //整流器 |
| | | { |
| | | 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: 100, |
| | | 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, |
| | | }, |
| | | } |
| | | } |
| | | }, |
| | | //配电器 |
| | | { |
| | | show: true, |
| | | uuid: "", |
| | | name: 'distribution', |
| | | objType: 'cube', |
| | | length: 90, |
| | | width: 180, |
| | | height: 160, |
| | | rotation: [{ |
| | | direction: 'y', |
| | | degree: 0.5 * Math.PI |
| | | }], //旋转 表示x方向0度 |
| | | x: 1000, |
| | | y: 100, |
| | | z: 0, |
| | | style: { |
| | | skinColor: 0xfefefe, |
| | | skin: { |
| | | skin_fore: { |
| | | skinColor: 0xfefefe, |
| | | imgurl: distributionFore, |
| | | }, |
| | | skin_behind: { |
| | | skinColor: 0xfefefe, |
| | | imgurl: distributionBehind, |
| | | }, |
| | | skin_down: { |
| | | skinColor: 0xfefefe, |
| | | }, |
| | | skin_up: { |
| | | skinColor: 0xfefefe, |
| | | imgurl: distributionTop, |
| | | }, |
| | | skin_left: { |
| | | skinColor: 0xfefefe, |
| | | imgurl: distributionLeft, |
| | | }, |
| | | skin_right: { |
| | | skinColor: 0xfefefe, |
| | | imgurl: distributionRight, |
| | | }, |
| | | } |
| | | } |
| | | }, |
| | | //配电器 |
| | | { |
| | | show: true, |
| | | uuid: "", |
| | | name: 'distribution2', |
| | | objType: 'cube', |
| | | length: 90, |
| | | width: 180, |
| | | height: 160, |
| | | rotation: [{ |
| | | direction: 'y', |
| | | degree: 0.5 * Math.PI |
| | | }], //旋转 表示x方向0度 |
| | | x: 1000, |
| | | y: 100, |
| | | z: -500, |
| | | style: { |
| | | skinColor: 0xfefefe, |
| | | skin: { |
| | | skin_fore: { |
| | | skinColor: 0xfefefe, |
| | | imgurl: distributionFore, |
| | | }, |
| | | skin_behind: { |
| | | skinColor: 0xfefefe, |
| | | imgurl: distributionBehind, |
| | | }, |
| | | skin_down: { |
| | | skinColor: 0xfefefe, |
| | | }, |
| | | skin_up: { |
| | | skinColor: 0xfefefe, |
| | | imgurl: distributionTop, |
| | | }, |
| | | skin_left: { |
| | | skinColor: 0xfefefe, |
| | | imgurl: distributionLeft, |
| | | }, |
| | | skin_right: { |
| | | skinColor: 0xfefefe, |
| | | imgurl: distributionRight, |
| | | }, |
| | | } |
| | | } |
| | | }, |
| | | ], |
| | | events: { |
| | | click: {}, |
| | | dbclick: [], |
| | | mouseDown: {}, |
| | | mouseUp: {}, |
| | | mouseMove: {} |
| | | }, |
| | | } |
| | | |
| | | |
| | | export { |
| | | Aobjects, |
| | | } |
New file |
| | |
| | | /** |
| | | * @author zz85 / https://github.com/zz85 |
| | | * @author mrdoob / http://mrdoob.com |
| | | * Running this will allow you to drag three.js objects around the screen. |
| | | */ |
| | | |
| | | THREE.DragControls = function (_objects, _camera, _domElement) { |
| | | |
| | | var _plane = new THREE.Plane(); |
| | | var _raycaster = new THREE.Raycaster(); |
| | | |
| | | var _mouse = new THREE.Vector2(); |
| | | var _offset = new THREE.Vector3(); |
| | | var _intersection = new THREE.Vector3(); |
| | | var _worldPosition = new THREE.Vector3(); |
| | | var _inverseMatrix = new THREE.Matrix4(); |
| | | |
| | | var _selected = null, |
| | | _hovered = null; |
| | | |
| | | // |
| | | |
| | | var scope = this; |
| | | |
| | | function activate() { |
| | | |
| | | _domElement.addEventListener('mousemove', onDocumentMouseMove, false); |
| | | _domElement.addEventListener('mousedown', onDocumentMouseDown, false); |
| | | _domElement.addEventListener('mouseup', onDocumentMouseCancel, false); |
| | | _domElement.addEventListener('mouseleave', onDocumentMouseCancel, false); |
| | | _domElement.addEventListener('touchmove', onDocumentTouchMove, false); |
| | | _domElement.addEventListener('touchstart', onDocumentTouchStart, false); |
| | | _domElement.addEventListener('touchend', onDocumentTouchEnd, false); |
| | | |
| | | } |
| | | |
| | | function deactivate() { |
| | | |
| | | _domElement.removeEventListener('mousemove', onDocumentMouseMove, false); |
| | | _domElement.removeEventListener('mousedown', onDocumentMouseDown, false); |
| | | _domElement.removeEventListener('mouseup', onDocumentMouseCancel, false); |
| | | _domElement.removeEventListener('mouseleave', onDocumentMouseCancel, false); |
| | | _domElement.removeEventListener('touchmove', onDocumentTouchMove, false); |
| | | _domElement.removeEventListener('touchstart', onDocumentTouchStart, false); |
| | | _domElement.removeEventListener('touchend', onDocumentTouchEnd, false); |
| | | |
| | | } |
| | | |
| | | function dispose() { |
| | | |
| | | deactivate(); |
| | | |
| | | } |
| | | |
| | | function onDocumentMouseMove(event) { |
| | | |
| | | event.preventDefault(); |
| | | |
| | | var rect = _domElement.getBoundingClientRect(); |
| | | |
| | | _mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; |
| | | _mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; |
| | | |
| | | _raycaster.setFromCamera(_mouse, _camera); |
| | | |
| | | if (_selected && scope.enabled) { |
| | | |
| | | if (_raycaster.ray.intersectPlane(_plane, _intersection)) { |
| | | |
| | | _selected.position.copy(_intersection.sub(_offset).applyMatrix4(_inverseMatrix)); |
| | | |
| | | } |
| | | |
| | | scope.dispatchEvent({ |
| | | type: 'drag', |
| | | object: _selected |
| | | }); |
| | | |
| | | return; |
| | | |
| | | } |
| | | |
| | | _raycaster.setFromCamera(_mouse, _camera); |
| | | |
| | | var intersects = _raycaster.intersectObjects(_objects, true); |
| | | |
| | | if (intersects.length > 0) { |
| | | |
| | | var object = intersects[0].object.parent; |
| | | |
| | | _plane.setFromNormalAndCoplanarPoint(_camera.getWorldDirection(_plane.normal), _worldPosition.setFromMatrixPosition(object.matrixWorld)); |
| | | |
| | | if (_hovered !== object) { |
| | | |
| | | scope.dispatchEvent({ |
| | | type: 'hoveron', |
| | | object: object |
| | | }); |
| | | |
| | | _domElement.style.cursor = 'pointer'; |
| | | _hovered = object; |
| | | |
| | | } |
| | | |
| | | } else { |
| | | |
| | | if (_hovered !== null) { |
| | | |
| | | scope.dispatchEvent({ |
| | | type: 'hoveroff', |
| | | object: _hovered |
| | | }); |
| | | |
| | | _domElement.style.cursor = 'auto'; |
| | | _hovered = null; |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | function onDocumentMouseDown(event) { |
| | | |
| | | event.preventDefault(); |
| | | |
| | | _raycaster.setFromCamera(_mouse, _camera); |
| | | |
| | | var intersects = _raycaster.intersectObjects(_objects, true); |
| | | |
| | | if (intersects.length > 0) { |
| | | |
| | | _selected = intersects[0].object.parent; |
| | | |
| | | if (_raycaster.ray.intersectPlane(_plane, _intersection)) { |
| | | |
| | | _inverseMatrix.getInverse(_selected.parent.matrixWorld); |
| | | _offset.copy(_intersection).sub(_worldPosition.setFromMatrixPosition(_selected.matrixWorld)); |
| | | |
| | | } |
| | | |
| | | _domElement.style.cursor = 'move'; |
| | | |
| | | scope.dispatchEvent({ |
| | | type: 'dragstart', |
| | | object: _selected |
| | | }); |
| | | |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | function onDocumentMouseCancel(event) { |
| | | |
| | | event.preventDefault(); |
| | | |
| | | if (_selected) { |
| | | |
| | | scope.dispatchEvent({ |
| | | type: 'dragend', |
| | | object: _selected |
| | | }); |
| | | |
| | | _selected = null; |
| | | |
| | | } |
| | | |
| | | _domElement.style.cursor = _hovered ? 'pointer' : 'auto'; |
| | | |
| | | } |
| | | |
| | | function onDocumentTouchMove(event) { |
| | | |
| | | event.preventDefault(); |
| | | event = event.changedTouches[0]; |
| | | |
| | | var rect = _domElement.getBoundingClientRect(); |
| | | |
| | | _mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; |
| | | _mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; |
| | | |
| | | _raycaster.setFromCamera(_mouse, _camera); |
| | | |
| | | if (_selected && scope.enabled) { |
| | | |
| | | if (_raycaster.ray.intersectPlane(_plane, _intersection)) { |
| | | |
| | | _selected.position.copy(_intersection.sub(_offset).applyMatrix4(_inverseMatrix)); |
| | | |
| | | } |
| | | |
| | | scope.dispatchEvent({ |
| | | type: 'drag', |
| | | object: _selected |
| | | }); |
| | | |
| | | return; |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | function onDocumentTouchStart(event) { |
| | | |
| | | event.preventDefault(); |
| | | event = event.changedTouches[0]; |
| | | |
| | | var rect = _domElement.getBoundingClientRect(); |
| | | |
| | | _mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; |
| | | _mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; |
| | | |
| | | _raycaster.setFromCamera(_mouse, _camera); |
| | | |
| | | var intersects = _raycaster.intersectObjects(_objects, true); |
| | | |
| | | if (intersects.length > 0) { |
| | | |
| | | _selected = intersects[0].object.parent; |
| | | |
| | | _plane.setFromNormalAndCoplanarPoint(_camera.getWorldDirection(_plane.normal), _worldPosition.setFromMatrixPosition(_selected.matrixWorld)); |
| | | |
| | | if (_raycaster.ray.intersectPlane(_plane, _intersection)) { |
| | | |
| | | _inverseMatrix.getInverse(_selected.parent.matrixWorld); |
| | | _offset.copy(_intersection).sub(_worldPosition.setFromMatrixPosition(_selected.matrixWorld)); |
| | | |
| | | } |
| | | |
| | | _domElement.style.cursor = 'move'; |
| | | |
| | | scope.dispatchEvent({ |
| | | type: 'dragstart', |
| | | object: _selected |
| | | }); |
| | | |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | function onDocumentTouchEnd(event) { |
| | | |
| | | event.preventDefault(); |
| | | |
| | | if (_selected) { |
| | | |
| | | scope.dispatchEvent({ |
| | | type: 'dragend', |
| | | object: _selected |
| | | }); |
| | | |
| | | _selected = null; |
| | | |
| | | } |
| | | |
| | | _domElement.style.cursor = 'auto'; |
| | | |
| | | } |
| | | |
| | | activate(); |
| | | |
| | | // API |
| | | |
| | | this.enabled = true; |
| | | |
| | | this.activate = activate; |
| | | this.deactivate = deactivate; |
| | | this.dispose = dispose; |
| | | |
| | | }; |
| | | |
| | | THREE.DragControls.prototype = Object.create(THREE.EventDispatcher.prototype); |
| | | THREE.DragControls.prototype.constructor = THREE.DragControls; |
New file |
| | |
| | | // Generated by CoffeeScript 1.12.7 |
| | | import * as THREE from 'three'; |
| | | |
| | | function loadBSP() { |
| | | (function () { |
| | | var BACK, COPLANAR, EPSILON, FRONT, SPANNING, Timelimit, returning, |
| | | bind = function (fn, me) { |
| | | return function () { |
| | | return fn.apply(me, arguments); |
| | | }; |
| | | }, |
| | | slice = [].slice, |
| | | extend = function (child, parent) { |
| | | for (var key in parent) { |
| | | if (hasProp.call(parent, key)) child[key] = parent[key]; |
| | | } |
| | | |
| | | function ctor() { |
| | | this.constructor = child; |
| | | } |
| | | ctor.prototype = parent.prototype; |
| | | child.prototype = new ctor(); |
| | | child.__super__ = parent.prototype; |
| | | return child; |
| | | }, |
| | | hasProp = {}.hasOwnProperty; |
| | | |
| | | EPSILON = 1e-5; |
| | | |
| | | COPLANAR = 0; |
| | | |
| | | FRONT = 1; |
| | | |
| | | BACK = 2; |
| | | |
| | | SPANNING = 3; |
| | | |
| | | returning = function (value, fn) { |
| | | fn(); |
| | | return value; |
| | | }; |
| | | |
| | | Timelimit = (function () { |
| | | function Timelimit(timeout, progress) { |
| | | this.timeout = timeout; |
| | | this.progress = progress; |
| | | this.doTask = bind(this.doTask, this); |
| | | this.finish = bind(this.finish, this); |
| | | this.start = bind(this.start, this); |
| | | this.check = bind(this.check, this); |
| | | "NOTHING"; |
| | | } |
| | | |
| | | Timelimit.prototype.check = function () { |
| | | var elapsed; |
| | | if (this.started == null) { |
| | | return; |
| | | } |
| | | return returning((elapsed = Date.now() - this.started), (function (_this) { |
| | | return function () { |
| | | var ref, ref1, ref2; |
| | | if ((ref = elapsed >= _this.timeout) != null ? ref : 2e308) { |
| | | throw new Error("Timeout reached: " + elapsed + "/" + _this.timeout + ", " + ((ref1 = _this.tasks) != null ? ref1 : 0) + " tasks unfinished " + ((ref2 = _this.done) != null ? ref2 : 0) + " finished."); |
| | | } |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | Timelimit.prototype.start = function () { |
| | | if (this.started == null) { |
| | | this.started = Date.now(); |
| | | } |
| | | if (this.tasks == null) { |
| | | this.tasks = 0; |
| | | } |
| | | if (this.total == null) { |
| | | this.total = 0; |
| | | } |
| | | this.total += 1; |
| | | this.tasks += 1; |
| | | return this.check(); |
| | | }; |
| | | |
| | | Timelimit.prototype.finish = function () { |
| | | var elapsed; |
| | | if ((this.tasks != null) && this.tasks < 1) { |
| | | throw new Error("Finished more tasks than started"); |
| | | } |
| | | this.tasks -= 1; |
| | | elapsed = this.check(); |
| | | if (this.done == null) { |
| | | this.done = 0; |
| | | } |
| | | this.done += 1; |
| | | if (this.progress != null) { |
| | | this.progress(this.done, this.total); |
| | | } |
| | | if (this.tasks === 0) { |
| | | "Finished " + this.done + " tasks in " + elapsed + "/" + this.timeout + " ms"; |
| | | return this.started = this.done = this.total = void 0; |
| | | } |
| | | }; |
| | | |
| | | Timelimit.prototype.doTask = function (block) { |
| | | var result; |
| | | this.start(); |
| | | result = block(); |
| | | this.finish(); |
| | | return result; |
| | | }; |
| | | |
| | | return Timelimit; |
| | | |
| | | })(); |
| | | |
| | | window.ThreeBSP = (function () { |
| | | function ThreeBSP(treeIsh, matrix1, options) { |
| | | var base, ref, ref1, ref2, ref3; |
| | | this.matrix = matrix1; |
| | | this.options = options != null ? options : {}; |
| | | this.intersect = bind(this.intersect, this); |
| | | this.union = bind(this.union, this); |
| | | this.subtract = bind(this.subtract, this); |
| | | this.toGeometry = bind(this.toGeometry, this); |
| | | this.toMesh = bind(this.toMesh, this); |
| | | this.toTree = bind(this.toTree, this); |
| | | this.withTimer = bind(this.withTimer, this); |
| | | if ((this.matrix != null) && !(this.matrix instanceof THREE.Matrix4)) { |
| | | this.options = this.matrix; |
| | | this.matrix = void 0; |
| | | } |
| | | if (this.options == null) { |
| | | this.options = {}; |
| | | } |
| | | if (this.matrix == null) { |
| | | this.matrix = new THREE.Matrix4(); |
| | | } |
| | | if ((base = this.options).timer == null) { |
| | | base.timer = new Timelimit((ref = (ref1 = this.options.timer) != null ? ref1.timeout : void 0) != null ? ref : this.options.timeout, (ref2 = (ref3 = this.options.timer) != null ? ref3.progress : void 0) != null ? ref2 : this.options.progress); |
| | | } |
| | | this.tree = this.toTree(treeIsh); |
| | | } |
| | | |
| | | ThreeBSP.prototype.withTimer = function (new_timer, block) { |
| | | var old_timer; |
| | | old_timer = this.options.timer; |
| | | try { |
| | | this.options.timer = new_timer; |
| | | return block(); |
| | | } finally { |
| | | this.options.timer = old_timer; |
| | | } |
| | | }; |
| | | |
| | | ThreeBSP.prototype.toTree = function (treeIsh) { |
| | | var face, fn1, geometry, i, k, len, polygons, ref; |
| | | if (treeIsh instanceof ThreeBSP.Node) { |
| | | return treeIsh; |
| | | } |
| | | polygons = []; |
| | | geometry = treeIsh instanceof THREE.Geometry ? treeIsh : treeIsh instanceof THREE.Mesh ? (treeIsh.updateMatrix(), this.matrix = treeIsh.matrix.clone(), treeIsh.geometry) : void 0; |
| | | ref = geometry.faces; |
| | | fn1 = (function (_this) { |
| | | return function (face, i) { |
| | | var faceVertexUvs, idx, l, len1, polygon, ref1, ref2, vIndex, vName, vertex; |
| | | faceVertexUvs = (ref1 = geometry.faceVertexUvs) != null ? ref1[0][i] : void 0; |
| | | if (faceVertexUvs == null) { |
| | | faceVertexUvs = [new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2()]; |
| | | } |
| | | polygon = new ThreeBSP.Polygon(); |
| | | ref2 = ['a', 'b', 'c', 'd']; |
| | | for (vIndex = l = 0, len1 = ref2.length; l < len1; vIndex = ++l) { |
| | | vName = ref2[vIndex]; |
| | | if ((idx = face[vName]) != null) { |
| | | vertex = geometry.vertices[idx]; |
| | | vertex = new ThreeBSP.Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[0], new THREE.Vector2(faceVertexUvs[vIndex].x, faceVertexUvs[vIndex].y)); |
| | | vertex.applyMatrix4(_this.matrix); |
| | | polygon.vertices.push(vertex); |
| | | } |
| | | } |
| | | return polygons.push(polygon.calculateProperties()); |
| | | }; |
| | | })(this); |
| | | for (i = k = 0, len = ref.length; k < len; i = ++k) { |
| | | face = ref[i]; |
| | | fn1(face, i); |
| | | } |
| | | return new ThreeBSP.Node(polygons, this.options); |
| | | }; |
| | | |
| | | ThreeBSP.prototype.toMesh = function (material) { |
| | | if (material == null) { |
| | | material = new THREE.MeshNormalMaterial(); |
| | | } |
| | | return this.options.timer.doTask((function (_this) { |
| | | return function () { |
| | | var geometry, mesh; |
| | | geometry = _this.toGeometry(); |
| | | return returning((mesh = new THREE.Mesh(geometry, material)), function () { |
| | | mesh.position.setFromMatrixPosition(_this.matrix); |
| | | return mesh.rotation.setFromRotationMatrix(_this.matrix); |
| | | }); |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | ThreeBSP.prototype.toGeometry = function () { |
| | | return this.options.timer.doTask((function (_this) { |
| | | return function () { |
| | | var geometry, matrix; |
| | | matrix = new THREE.Matrix4().getInverse(_this.matrix); |
| | | return returning((geometry = new THREE.Geometry()), function () { |
| | | var k, len, polygon, ref, results; |
| | | ref = _this.tree.allPolygons(); |
| | | results = []; |
| | | for (k = 0, len = ref.length; k < len; k++) { |
| | | polygon = ref[k]; |
| | | results.push(_this.options.timer.doTask(function () { |
| | | var face, idx, l, polyVerts, ref1, results1, v, vertUvs, verts; |
| | | polyVerts = (function () { |
| | | var l, len1, ref1, results1; |
| | | ref1 = polygon.vertices; |
| | | results1 = []; |
| | | for (l = 0, len1 = ref1.length; l < len1; l++) { |
| | | v = ref1[l]; |
| | | results1.push(v.clone().applyMatrix4(matrix)); |
| | | } |
| | | return results1; |
| | | })(); |
| | | results1 = []; |
| | | for (idx = l = 2, ref1 = polyVerts.length; 2 <= ref1 ? l < ref1 : l > ref1; idx = 2 <= ref1 ? ++l : --l) { |
| | | verts = [polyVerts[0], polyVerts[idx - 1], polyVerts[idx]]; |
| | | vertUvs = (function () { |
| | | var len1, m, ref2, ref3, results2; |
| | | results2 = []; |
| | | for (m = 0, len1 = verts.length; m < len1; m++) { |
| | | v = verts[m]; |
| | | results2.push(new THREE.Vector2((ref2 = v.uv) != null ? ref2.x : void 0, (ref3 = v.uv) != null ? ref3.y : void 0)); |
| | | } |
| | | return results2; |
| | | })(); |
| | | face = (function (func, args, ctor) { |
| | | ctor.prototype = func.prototype; |
| | | var child = new ctor, |
| | | result = func.apply(child, args); |
| | | return Object(result) === result ? result : child; |
| | | })(THREE.Face3, slice.call((function () { |
| | | var len1, m, results2; |
| | | results2 = []; |
| | | for (m = 0, len1 = verts.length; m < len1; m++) { |
| | | v = verts[m]; |
| | | results2.push(geometry.vertices.push(v) - 1); |
| | | } |
| | | return results2; |
| | | })()).concat([polygon.normal.clone()]), function () {}); |
| | | geometry.faces.push(face); |
| | | results1.push(geometry.faceVertexUvs[0].push(vertUvs)); |
| | | } |
| | | return results1; |
| | | })); |
| | | } |
| | | return results; |
| | | }); |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | ThreeBSP.prototype.subtract = function (other) { |
| | | return this.options.timer.doTask((function (_this) { |
| | | return function () { |
| | | return other.withTimer(_this.options.timer, function () { |
| | | var ref, them, us; |
| | | ref = [_this.tree.clone(), other.tree.clone()], us = ref[0], them = ref[1]; |
| | | us.invert().clipTo(them); |
| | | them.clipTo(us).invert().clipTo(us).invert(); |
| | | return new ThreeBSP(us.build(them.allPolygons()).invert(), _this.matrix, _this.options); |
| | | }); |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | ThreeBSP.prototype.union = function (other) { |
| | | return this.options.timer.doTask((function (_this) { |
| | | return function () { |
| | | return other.withTimer(_this.options.timer, function () { |
| | | var ref, them, us; |
| | | ref = [_this.tree.clone(), other.tree.clone()], us = ref[0], them = ref[1]; |
| | | us.clipTo(them); |
| | | them.clipTo(us).invert().clipTo(us).invert(); |
| | | return new ThreeBSP(us.build(them.allPolygons()), _this.matrix, _this.options); |
| | | }); |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | ThreeBSP.prototype.intersect = function (other) { |
| | | return this.options.timer.doTask((function (_this) { |
| | | return function () { |
| | | return other.withTimer(_this.options.timer, function () { |
| | | var ref, them, us; |
| | | ref = [_this.tree.clone(), other.tree.clone()], us = ref[0], them = ref[1]; |
| | | them.clipTo(us.invert()).invert().clipTo(us.clipTo(them)); |
| | | return new ThreeBSP(us.build(them.allPolygons()).invert(), _this.matrix, _this.options); |
| | | }); |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | return ThreeBSP; |
| | | |
| | | })(); |
| | | |
| | | ThreeBSP.Vertex = (function (superClass) { |
| | | extend(Vertex, superClass); |
| | | |
| | | function Vertex(x, y, z, normal, uv) { |
| | | this.normal = normal != null ? normal : new THREE.Vector3(); |
| | | this.uv = uv != null ? uv : new THREE.Vector2(); |
| | | this.interpolate = bind(this.interpolate, this); |
| | | this.lerp = bind(this.lerp, this); |
| | | Vertex.__super__.constructor.call(this, x, y, z); |
| | | } |
| | | |
| | | Vertex.prototype.clone = function () { |
| | | return new ThreeBSP.Vertex(this.x, this.y, this.z, this.normal.clone(), this.uv.clone()); |
| | | }; |
| | | |
| | | Vertex.prototype.lerp = function (v, alpha) { |
| | | return returning(Vertex.__super__.lerp.apply(this, arguments), (function (_this) { |
| | | return function () { |
| | | _this.uv.add(v.uv.clone().sub(_this.uv).multiplyScalar(alpha)); |
| | | return _this.normal.lerp(v, alpha); |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | Vertex.prototype.interpolate = function () { |
| | | var args, ref; |
| | | args = 1 <= arguments.length ? slice.call(arguments, 0) : []; |
| | | return (ref = this.clone()).lerp.apply(ref, args); |
| | | }; |
| | | |
| | | return Vertex; |
| | | |
| | | })(THREE.Vector3); |
| | | |
| | | ThreeBSP.Polygon = (function () { |
| | | function Polygon(vertices, normal, w) { |
| | | this.vertices = vertices != null ? vertices : []; |
| | | this.normal = normal; |
| | | this.w = w; |
| | | this.subdivide = bind(this.subdivide, this); |
| | | this.tessellate = bind(this.tessellate, this); |
| | | this.classifySide = bind(this.classifySide, this); |
| | | this.classifyVertex = bind(this.classifyVertex, this); |
| | | this.invert = bind(this.invert, this); |
| | | this.clone = bind(this.clone, this); |
| | | this.calculateProperties = bind(this.calculateProperties, this); |
| | | if (this.vertices.length) { |
| | | this.calculateProperties(); |
| | | } |
| | | } |
| | | |
| | | Polygon.prototype.calculateProperties = function () { |
| | | return returning(this, (function (_this) { |
| | | return function () { |
| | | var a, b, c, ref; |
| | | ref = _this.vertices, a = ref[0], b = ref[1], c = ref[2]; |
| | | _this.normal = b.clone().sub(a).cross(c.clone().sub(a)).normalize(); |
| | | return _this.w = _this.normal.clone().dot(a); |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | Polygon.prototype.clone = function () { |
| | | var v; |
| | | return new ThreeBSP.Polygon((function () { |
| | | var k, len, ref, results; |
| | | ref = this.vertices; |
| | | results = []; |
| | | for (k = 0, len = ref.length; k < len; k++) { |
| | | v = ref[k]; |
| | | results.push(v.clone()); |
| | | } |
| | | return results; |
| | | }).call(this), this.normal.clone(), this.w); |
| | | }; |
| | | |
| | | Polygon.prototype.invert = function () { |
| | | return returning(this, (function (_this) { |
| | | return function () { |
| | | _this.normal.multiplyScalar(-1); |
| | | _this.w *= -1; |
| | | return _this.vertices.reverse(); |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | Polygon.prototype.classifyVertex = function (vertex) { |
| | | var side; |
| | | side = this.normal.dot(vertex) - this.w; |
| | | switch (false) { |
| | | case !(side < -EPSILON): |
| | | return BACK; |
| | | case !(side > EPSILON): |
| | | return FRONT; |
| | | default: |
| | | return COPLANAR; |
| | | } |
| | | }; |
| | | |
| | | Polygon.prototype.classifySide = function (polygon) { |
| | | var back, front, k, len, ref, ref1, tally, v; |
| | | ref = [0, 0], front = ref[0], back = ref[1]; |
| | | tally = (function (_this) { |
| | | return function (v) { |
| | | switch (_this.classifyVertex(v)) { |
| | | case FRONT: |
| | | return front += 1; |
| | | case BACK: |
| | | return back += 1; |
| | | } |
| | | }; |
| | | })(this); |
| | | ref1 = polygon.vertices; |
| | | for (k = 0, len = ref1.length; k < len; k++) { |
| | | v = ref1[k]; |
| | | tally(v); |
| | | } |
| | | if (front > 0 && back === 0) { |
| | | return FRONT; |
| | | } |
| | | if (front === 0 && back > 0) { |
| | | return BACK; |
| | | } |
| | | if ((front === back && back === 0)) { |
| | | return COPLANAR; |
| | | } |
| | | return SPANNING; |
| | | }; |
| | | |
| | | Polygon.prototype.tessellate = function (poly) { |
| | | var b, count, f, i, j, k, len, polys, ref, ref1, ref2, t, ti, tj, v, vi, vj; |
| | | ref = { |
| | | f: [], |
| | | b: [], |
| | | count: poly.vertices.length |
| | | }, f = ref.f, b = ref.b, count = ref.count; |
| | | if (this.classifySide(poly) !== SPANNING) { |
| | | return [poly]; |
| | | } |
| | | ref1 = poly.vertices; |
| | | for (i = k = 0, len = ref1.length; k < len; i = ++k) { |
| | | vi = ref1[i]; |
| | | vj = poly.vertices[(j = (i + 1) % count)]; |
| | | ref2 = (function () { |
| | | var l, len1, ref2, results; |
| | | ref2 = [vi, vj]; |
| | | results = []; |
| | | for (l = 0, len1 = ref2.length; l < len1; l++) { |
| | | v = ref2[l]; |
| | | results.push(this.classifyVertex(v)); |
| | | } |
| | | return results; |
| | | }).call(this), ti = ref2[0], tj = ref2[1]; |
| | | if (ti !== BACK) { |
| | | f.push(vi); |
| | | } |
| | | if (ti !== FRONT) { |
| | | b.push(vi); |
| | | } |
| | | if ((ti | tj) === SPANNING) { |
| | | t = (this.w - this.normal.dot(vi)) / this.normal.dot(vj.clone().sub(vi)); |
| | | v = vi.interpolate(vj, t); |
| | | f.push(v); |
| | | b.push(v); |
| | | } |
| | | } |
| | | return returning((polys = []), (function (_this) { |
| | | return function () { |
| | | if (f.length >= 3) { |
| | | polys.push(new ThreeBSP.Polygon(f)); |
| | | } |
| | | if (b.length >= 3) { |
| | | return polys.push(new ThreeBSP.Polygon(b)); |
| | | } |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | Polygon.prototype.subdivide = function (polygon, coplanar_front, coplanar_back, front, back) { |
| | | var k, len, poly, ref, results, side; |
| | | ref = this.tessellate(polygon); |
| | | results = []; |
| | | for (k = 0, len = ref.length; k < len; k++) { |
| | | poly = ref[k]; |
| | | side = this.classifySide(poly); |
| | | switch (side) { |
| | | case FRONT: |
| | | results.push(front.push(poly)); |
| | | break; |
| | | case BACK: |
| | | results.push(back.push(poly)); |
| | | break; |
| | | case COPLANAR: |
| | | if (this.normal.dot(poly.normal) > 0) { |
| | | results.push(coplanar_front.push(poly)); |
| | | } else { |
| | | results.push(coplanar_back.push(poly)); |
| | | } |
| | | break; |
| | | default: |
| | | throw new Error("BUG: Polygon of classification " + side + " in subdivision"); |
| | | } |
| | | } |
| | | return results; |
| | | }; |
| | | |
| | | return Polygon; |
| | | |
| | | })(); |
| | | |
| | | ThreeBSP.Node = (function () { |
| | | Node.prototype.clone = function () { |
| | | var node; |
| | | return returning((node = new ThreeBSP.Node(this.options)), (function (_this) { |
| | | return function () { |
| | | var ref; |
| | | node.divider = (ref = _this.divider) != null ? ref.clone() : void 0; |
| | | node.polygons = _this.options.timer.doTask(function () { |
| | | var k, len, p, ref1, results; |
| | | ref1 = _this.polygons; |
| | | results = []; |
| | | for (k = 0, len = ref1.length; k < len; k++) { |
| | | p = ref1[k]; |
| | | results.push(p.clone()); |
| | | } |
| | | return results; |
| | | }); |
| | | node.front = _this.options.timer.doTask(function () { |
| | | var ref1; |
| | | return (ref1 = _this.front) != null ? ref1.clone() : void 0; |
| | | }); |
| | | return node.back = _this.options.timer.doTask(function () { |
| | | var ref1; |
| | | return (ref1 = _this.back) != null ? ref1.clone() : void 0; |
| | | }); |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | function Node(polygons, options) { |
| | | this.options = options != null ? options : {}; |
| | | this.clipTo = bind(this.clipTo, this); |
| | | this.clipPolygons = bind(this.clipPolygons, this); |
| | | this.invert = bind(this.invert, this); |
| | | this.allPolygons = bind(this.allPolygons, this); |
| | | this.isConvex = bind(this.isConvex, this); |
| | | this.build = bind(this.build, this); |
| | | this.clone = bind(this.clone, this); |
| | | if ((polygons != null) && !(polygons instanceof Array)) { |
| | | this.options = polygons; |
| | | polygons = void 0; |
| | | } |
| | | this.polygons = []; |
| | | this.options.timer.doTask((function (_this) { |
| | | return function () { |
| | | if ((polygons != null) && polygons.length) { |
| | | return _this.build(polygons); |
| | | } |
| | | }; |
| | | })(this)); |
| | | } |
| | | |
| | | Node.prototype.build = function (polygons) { |
| | | return returning(this, (function (_this) { |
| | | return function () { |
| | | var polys, results, side, sides; |
| | | sides = { |
| | | front: [], |
| | | back: [] |
| | | }; |
| | | if (_this.divider == null) { |
| | | _this.divider = polygons[0].clone(); |
| | | } |
| | | _this.options.timer.doTask(function () { |
| | | var k, len, poly, results; |
| | | results = []; |
| | | for (k = 0, len = polygons.length; k < len; k++) { |
| | | poly = polygons[k]; |
| | | results.push(_this.options.timer.doTask(function () { |
| | | return _this.divider.subdivide(poly, _this.polygons, _this.polygons, sides.front, sides.back); |
| | | })); |
| | | } |
| | | return results; |
| | | }); |
| | | results = []; |
| | | for (side in sides) { |
| | | if (!hasProp.call(sides, side)) continue; |
| | | polys = sides[side]; |
| | | if (polys.length) { |
| | | if (_this[side] == null) { |
| | | _this[side] = new ThreeBSP.Node(_this.options); |
| | | } |
| | | results.push(_this[side].build(polys)); |
| | | } else { |
| | | results.push(void 0); |
| | | } |
| | | } |
| | | return results; |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | Node.prototype.isConvex = function (polys) { |
| | | var inner, k, l, len, len1, outer; |
| | | for (k = 0, len = polys.length; k < len; k++) { |
| | | inner = polys[k]; |
| | | for (l = 0, len1 = polys.length; l < len1; l++) { |
| | | outer = polys[l]; |
| | | if (inner !== outer && outer.classifySide(inner) !== BACK) { |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | return true; |
| | | }; |
| | | |
| | | Node.prototype.allPolygons = function () { |
| | | return this.options.timer.doTask((function (_this) { |
| | | return function () { |
| | | var ref, ref1; |
| | | return _this.polygons.slice().concat(((ref1 = _this.front) != null ? ref1.allPolygons() : void 0) || []).concat(((ref = _this.back) != null ? ref.allPolygons() : void 0) || []); |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | Node.prototype.invert = function () { |
| | | return returning(this, (function (_this) { |
| | | return function () { |
| | | return _this.options.timer.doTask(function () { |
| | | var flipper, k, l, len, len1, poly, ref, ref1, ref2; |
| | | ref = _this.polygons; |
| | | for (k = 0, len = ref.length; k < len; k++) { |
| | | poly = ref[k]; |
| | | _this.options.timer.doTask(function () { |
| | | return poly.invert(); |
| | | }); |
| | | } |
| | | ref1 = [_this.divider, _this.front, _this.back]; |
| | | for (l = 0, len1 = ref1.length; l < len1; l++) { |
| | | flipper = ref1[l]; |
| | | _this.options.timer.doTask(function () { |
| | | return flipper != null ? flipper.invert() : void 0; |
| | | }); |
| | | } |
| | | return ref2 = [_this.back, _this.front], _this.front = ref2[0], _this.back = ref2[1], ref2; |
| | | }); |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | Node.prototype.clipPolygons = function (polygons) { |
| | | return this.options.timer.doTask((function (_this) { |
| | | return function () { |
| | | var back, front, k, len, poly; |
| | | if (!_this.divider) { |
| | | return polygons.slice(); |
| | | } |
| | | front = []; |
| | | back = []; |
| | | for (k = 0, len = polygons.length; k < len; k++) { |
| | | poly = polygons[k]; |
| | | _this.options.timer.doTask(function () { |
| | | return _this.divider.subdivide(poly, front, back, front, back); |
| | | }); |
| | | } |
| | | if (_this.front) { |
| | | front = _this.front.clipPolygons(front); |
| | | } |
| | | if (_this.back) { |
| | | back = _this.back.clipPolygons(back); |
| | | } |
| | | if (_this.back) { |
| | | return front.concat(back); |
| | | } else { |
| | | return front; |
| | | } |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | Node.prototype.clipTo = function (node) { |
| | | return returning(this, (function (_this) { |
| | | return function () { |
| | | return _this.options.timer.doTask(function () { |
| | | var ref, ref1; |
| | | _this.polygons = node.clipPolygons(_this.polygons); |
| | | if ((ref = _this.front) != null) { |
| | | ref.clipTo(node); |
| | | } |
| | | return (ref1 = _this.back) != null ? ref1.clipTo(node) : void 0; |
| | | }); |
| | | }; |
| | | })(this)); |
| | | }; |
| | | |
| | | return Node; |
| | | |
| | | })(); |
| | | |
| | | }).call(this); |
| | | |
| | | } |
| | | export { |
| | | loadBSP |
| | | } |
New file |
| | |
| | | /** |
| | | * Tween.js - Licensed under the MIT license |
| | | * https://github.com/tweenjs/tween.js |
| | | * ---------------------------------------------- |
| | | * |
| | | * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors. |
| | | * Thank you all, you're awesome! |
| | | */ |
| | | |
| | | var TWEEN = TWEEN || (function () { |
| | | |
| | | var _tweens = []; |
| | | |
| | | return { |
| | | |
| | | getAll: function () { |
| | | |
| | | return _tweens; |
| | | |
| | | }, |
| | | |
| | | removeAll: function () { |
| | | |
| | | _tweens = []; |
| | | |
| | | }, |
| | | |
| | | add: function (tween) { |
| | | |
| | | _tweens.push(tween); |
| | | |
| | | }, |
| | | |
| | | remove: function (tween) { |
| | | |
| | | var i = _tweens.indexOf(tween); |
| | | |
| | | if (i !== -1) { |
| | | _tweens.splice(i, 1); |
| | | } |
| | | |
| | | }, |
| | | |
| | | update: function (time, preserve) { |
| | | |
| | | if (_tweens.length === 0) { |
| | | return false; |
| | | } |
| | | |
| | | var i = 0; |
| | | |
| | | time = time !== undefined ? time : TWEEN.now(); |
| | | |
| | | while (i < _tweens.length) { |
| | | |
| | | if (_tweens[i].update(time) || preserve) { |
| | | i++; |
| | | } else { |
| | | _tweens.splice(i, 1); |
| | | } |
| | | |
| | | } |
| | | |
| | | return true; |
| | | |
| | | } |
| | | }; |
| | | |
| | | })(); |
| | | |
| | | |
| | | // Include a performance.now polyfill. |
| | | // In node.js, use process.hrtime. |
| | | if (typeof (window) === 'undefined' && typeof (process) !== 'undefined') { |
| | | TWEEN.now = function () { |
| | | var time = process.hrtime(); |
| | | |
| | | // Convert [seconds, nanoseconds] to milliseconds. |
| | | return time[0] * 1000 + time[1] / 1000000; |
| | | }; |
| | | } |
| | | // In a browser, use window.performance.now if it is available. |
| | | else if (typeof (window) !== 'undefined' && |
| | | window.performance !== undefined && |
| | | window.performance.now !== undefined) { |
| | | // This must be bound, because directly assigning this function |
| | | // leads to an invocation exception in Chrome. |
| | | TWEEN.now = window.performance.now.bind(window.performance); |
| | | } |
| | | // Use Date.now if it is available. |
| | | else if (Date.now !== undefined) { |
| | | TWEEN.now = Date.now; |
| | | } |
| | | // Otherwise, use 'new Date().getTime()'. |
| | | else { |
| | | TWEEN.now = function () { |
| | | return new Date().getTime(); |
| | | }; |
| | | } |
| | | |
| | | |
| | | function assign(target, source) { |
| | | var keys = Object.keys(source); |
| | | var length = keys.length; |
| | | |
| | | for (var i = 0; i < length; i += 1) { |
| | | target[keys[i]] = source[keys[i]]; |
| | | } |
| | | |
| | | return target; |
| | | } |
| | | |
| | | |
| | | TWEEN.Tween = function (object) { |
| | | |
| | | this._object = object; |
| | | this._valuesStart = {}; |
| | | this._valuesEnd = {}; |
| | | this._valuesStartRepeat = {}; |
| | | this._duration = 1000; |
| | | this._repeat = 0; |
| | | this._repeatDelayTime = undefined; |
| | | this._yoyo = false; |
| | | this._isPlaying = false; |
| | | this._reversed = false; |
| | | this._delayTime = 0; |
| | | this._startTime = null; |
| | | this._easingFunction = TWEEN.Easing.Linear.None; |
| | | this._interpolationFunction = TWEEN.Interpolation.Linear; |
| | | this._chainedTweens = []; |
| | | this._onStartCallback = null; |
| | | this._onStartCallbackFired = false; |
| | | this._onUpdateCallback = null; |
| | | this._onCompleteCallback = null; |
| | | this._onStopCallback = null; |
| | | |
| | | }; |
| | | |
| | | TWEEN.Tween.prototype = assign(Object.create(Object.prototype), { |
| | | to: function to(properties, duration) { |
| | | |
| | | this._valuesEnd = properties; |
| | | |
| | | if (duration !== undefined) { |
| | | this._duration = duration; |
| | | } |
| | | |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | start: function start(time) { |
| | | |
| | | TWEEN.add(this); |
| | | |
| | | this._isPlaying = true; |
| | | |
| | | this._onStartCallbackFired = false; |
| | | |
| | | this._startTime = time !== undefined ? time : TWEEN.now(); |
| | | this._startTime += this._delayTime; |
| | | |
| | | for (var property in this._valuesEnd) { |
| | | |
| | | // Check if an Array was provided as property value |
| | | if (this._valuesEnd[property] instanceof Array) { |
| | | |
| | | if (this._valuesEnd[property].length === 0) { |
| | | continue; |
| | | } |
| | | |
| | | // Create a local copy of the Array with the start value at the front |
| | | this._valuesEnd[property] = [this._object[property]].concat(this._valuesEnd[property]); |
| | | |
| | | } |
| | | |
| | | // If `to()` specifies a property that doesn't exist in the source object, |
| | | // we should not set that property in the object |
| | | if (this._object[property] === undefined) { |
| | | continue; |
| | | } |
| | | |
| | | // Save the starting value. |
| | | this._valuesStart[property] = this._object[property]; |
| | | |
| | | if ((this._valuesStart[property] instanceof Array) === false) { |
| | | this._valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings |
| | | } |
| | | |
| | | this._valuesStartRepeat[property] = this._valuesStart[property] || 0; |
| | | |
| | | } |
| | | |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | stop: function stop() { |
| | | |
| | | if (!this._isPlaying) { |
| | | return this; |
| | | } |
| | | |
| | | TWEEN.remove(this); |
| | | this._isPlaying = false; |
| | | |
| | | if (this._onStopCallback !== null) { |
| | | this._onStopCallback.call(this._object, this._object); |
| | | } |
| | | |
| | | this.stopChainedTweens(); |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | end: function end() { |
| | | |
| | | this.update(this._startTime + this._duration); |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | stopChainedTweens: function stopChainedTweens() { |
| | | |
| | | for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) { |
| | | this._chainedTweens[i].stop(); |
| | | } |
| | | |
| | | }, |
| | | |
| | | delay: function delay(amount) { |
| | | |
| | | this._delayTime = amount; |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | repeat: function repeat(times) { |
| | | |
| | | this._repeat = times; |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | repeatDelay: function repeatDelay(amount) { |
| | | |
| | | this._repeatDelayTime = amount; |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | yoyo: function yoyo(yoyo) { |
| | | |
| | | this._yoyo = yoyo; |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | easing: function easing(easing) { |
| | | |
| | | this._easingFunction = easing; |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | interpolation: function interpolation(interpolation) { |
| | | |
| | | this._interpolationFunction = interpolation; |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | chain: function chain() { |
| | | |
| | | this._chainedTweens = arguments; |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | onStart: function onStart(callback) { |
| | | |
| | | this._onStartCallback = callback; |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | onUpdate: function onUpdate(callback) { |
| | | |
| | | this._onUpdateCallback = callback; |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | onComplete: function onComplete(callback) { |
| | | |
| | | this._onCompleteCallback = callback; |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | onStop: function onStop(callback) { |
| | | |
| | | this._onStopCallback = callback; |
| | | return this; |
| | | |
| | | }, |
| | | |
| | | update: function update(time) { |
| | | |
| | | var property; |
| | | var elapsed; |
| | | var value; |
| | | |
| | | if (time < this._startTime) { |
| | | return true; |
| | | } |
| | | |
| | | if (this._onStartCallbackFired === false) { |
| | | |
| | | if (this._onStartCallback !== null) { |
| | | this._onStartCallback.call(this._object, this._object); |
| | | } |
| | | |
| | | this._onStartCallbackFired = true; |
| | | } |
| | | |
| | | elapsed = (time - this._startTime) / this._duration; |
| | | elapsed = elapsed > 1 ? 1 : elapsed; |
| | | |
| | | value = this._easingFunction(elapsed); |
| | | |
| | | for (property in this._valuesEnd) { |
| | | |
| | | // Don't update properties that do not exist in the source object |
| | | if (this._valuesStart[property] === undefined) { |
| | | continue; |
| | | } |
| | | |
| | | var start = this._valuesStart[property] || 0; |
| | | var end = this._valuesEnd[property]; |
| | | |
| | | if (end instanceof Array) { |
| | | |
| | | this._object[property] = this._interpolationFunction(end, value); |
| | | |
| | | } else { |
| | | |
| | | // Parses relative end values with start as base (e.g.: +10, -3) |
| | | if (typeof (end) === 'string') { |
| | | |
| | | if (end.charAt(0) === '+' || end.charAt(0) === '-') { |
| | | end = start + parseFloat(end); |
| | | } else { |
| | | end = parseFloat(end); |
| | | } |
| | | } |
| | | |
| | | // Protect against non numeric properties. |
| | | if (typeof (end) === 'number') { |
| | | this._object[property] = start + (end - start) * value; |
| | | } |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | if (this._onUpdateCallback !== null) { |
| | | this._onUpdateCallback.call(this._object, value); |
| | | } |
| | | |
| | | if (elapsed === 1) { |
| | | |
| | | if (this._repeat > 0) { |
| | | |
| | | if (isFinite(this._repeat)) { |
| | | this._repeat--; |
| | | } |
| | | |
| | | // Reassign starting values, restart by making startTime = now |
| | | for (property in this._valuesStartRepeat) { |
| | | |
| | | if (typeof (this._valuesEnd[property]) === 'string') { |
| | | this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]); |
| | | } |
| | | |
| | | if (this._yoyo) { |
| | | var tmp = this._valuesStartRepeat[property]; |
| | | |
| | | this._valuesStartRepeat[property] = this._valuesEnd[property]; |
| | | this._valuesEnd[property] = tmp; |
| | | } |
| | | |
| | | this._valuesStart[property] = this._valuesStartRepeat[property]; |
| | | |
| | | } |
| | | |
| | | if (this._yoyo) { |
| | | this._reversed = !this._reversed; |
| | | } |
| | | |
| | | if (this._repeatDelayTime !== undefined) { |
| | | this._startTime = time + this._repeatDelayTime; |
| | | } else { |
| | | this._startTime = time + this._delayTime; |
| | | } |
| | | |
| | | return true; |
| | | |
| | | } else { |
| | | |
| | | if (this._onCompleteCallback !== null) { |
| | | |
| | | this._onCompleteCallback.call(this._object, this._object); |
| | | } |
| | | |
| | | for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) { |
| | | // Make the chained tweens start exactly at the time they should, |
| | | // even if the `update()` method was called way past the duration of the tween |
| | | this._chainedTweens[i].start(this._startTime + this._duration); |
| | | } |
| | | |
| | | return false; |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | return true; |
| | | |
| | | } |
| | | }); |
| | | |
| | | |
| | | TWEEN.Easing = { |
| | | |
| | | Linear: { |
| | | |
| | | None: function (k) { |
| | | |
| | | return k; |
| | | |
| | | } |
| | | |
| | | }, |
| | | |
| | | Quadratic: { |
| | | |
| | | In: function (k) { |
| | | |
| | | return k * k; |
| | | |
| | | }, |
| | | |
| | | Out: function (k) { |
| | | |
| | | return k * (2 - k); |
| | | |
| | | }, |
| | | |
| | | InOut: function (k) { |
| | | |
| | | if ((k *= 2) < 1) { |
| | | return 0.5 * k * k; |
| | | } |
| | | |
| | | return -0.5 * (--k * (k - 2) - 1); |
| | | |
| | | } |
| | | |
| | | }, |
| | | |
| | | Cubic: { |
| | | |
| | | In: function (k) { |
| | | |
| | | return k * k * k; |
| | | |
| | | }, |
| | | |
| | | Out: function (k) { |
| | | |
| | | return --k * k * k + 1; |
| | | |
| | | }, |
| | | |
| | | InOut: function (k) { |
| | | |
| | | if ((k *= 2) < 1) { |
| | | return 0.5 * k * k * k; |
| | | } |
| | | |
| | | return 0.5 * ((k -= 2) * k * k + 2); |
| | | |
| | | } |
| | | |
| | | }, |
| | | |
| | | Quartic: { |
| | | |
| | | In: function (k) { |
| | | |
| | | return k * k * k * k; |
| | | |
| | | }, |
| | | |
| | | Out: function (k) { |
| | | |
| | | return 1 - (--k * k * k * k); |
| | | |
| | | }, |
| | | |
| | | InOut: function (k) { |
| | | |
| | | if ((k *= 2) < 1) { |
| | | return 0.5 * k * k * k * k; |
| | | } |
| | | |
| | | return -0.5 * ((k -= 2) * k * k * k - 2); |
| | | |
| | | } |
| | | |
| | | }, |
| | | |
| | | Quintic: { |
| | | |
| | | In: function (k) { |
| | | |
| | | return k * k * k * k * k; |
| | | |
| | | }, |
| | | |
| | | Out: function (k) { |
| | | |
| | | return --k * k * k * k * k + 1; |
| | | |
| | | }, |
| | | |
| | | InOut: function (k) { |
| | | |
| | | if ((k *= 2) < 1) { |
| | | return 0.5 * k * k * k * k * k; |
| | | } |
| | | |
| | | return 0.5 * ((k -= 2) * k * k * k * k + 2); |
| | | |
| | | } |
| | | |
| | | }, |
| | | |
| | | Sinusoidal: { |
| | | |
| | | In: function (k) { |
| | | |
| | | return 1 - Math.cos(k * Math.PI / 2); |
| | | |
| | | }, |
| | | |
| | | Out: function (k) { |
| | | |
| | | return Math.sin(k * Math.PI / 2); |
| | | |
| | | }, |
| | | |
| | | InOut: function (k) { |
| | | |
| | | return 0.5 * (1 - Math.cos(Math.PI * k)); |
| | | |
| | | } |
| | | |
| | | }, |
| | | |
| | | Exponential: { |
| | | |
| | | In: function (k) { |
| | | |
| | | return k === 0 ? 0 : Math.pow(1024, k - 1); |
| | | |
| | | }, |
| | | |
| | | Out: function (k) { |
| | | |
| | | return k === 1 ? 1 : 1 - Math.pow(2, -10 * k); |
| | | |
| | | }, |
| | | |
| | | InOut: function (k) { |
| | | |
| | | if (k === 0) { |
| | | return 0; |
| | | } |
| | | |
| | | if (k === 1) { |
| | | return 1; |
| | | } |
| | | |
| | | if ((k *= 2) < 1) { |
| | | return 0.5 * Math.pow(1024, k - 1); |
| | | } |
| | | |
| | | return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2); |
| | | |
| | | } |
| | | |
| | | }, |
| | | |
| | | Circular: { |
| | | |
| | | In: function (k) { |
| | | |
| | | return 1 - Math.sqrt(1 - k * k); |
| | | |
| | | }, |
| | | |
| | | Out: function (k) { |
| | | |
| | | return Math.sqrt(1 - (--k * k)); |
| | | |
| | | }, |
| | | |
| | | InOut: function (k) { |
| | | |
| | | if ((k *= 2) < 1) { |
| | | return -0.5 * (Math.sqrt(1 - k * k) - 1); |
| | | } |
| | | |
| | | return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1); |
| | | |
| | | } |
| | | |
| | | }, |
| | | |
| | | Elastic: { |
| | | |
| | | In: function (k) { |
| | | |
| | | if (k === 0) { |
| | | return 0; |
| | | } |
| | | |
| | | if (k === 1) { |
| | | return 1; |
| | | } |
| | | |
| | | return -Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI); |
| | | |
| | | }, |
| | | |
| | | Out: function (k) { |
| | | |
| | | if (k === 0) { |
| | | return 0; |
| | | } |
| | | |
| | | if (k === 1) { |
| | | return 1; |
| | | } |
| | | |
| | | return Math.pow(2, -10 * k) * Math.sin((k - 0.1) * 5 * Math.PI) + 1; |
| | | |
| | | }, |
| | | |
| | | InOut: function (k) { |
| | | |
| | | if (k === 0) { |
| | | return 0; |
| | | } |
| | | |
| | | if (k === 1) { |
| | | return 1; |
| | | } |
| | | |
| | | k *= 2; |
| | | |
| | | if (k < 1) { |
| | | return -0.5 * Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI); |
| | | } |
| | | |
| | | return 0.5 * Math.pow(2, -10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI) + 1; |
| | | |
| | | } |
| | | |
| | | }, |
| | | |
| | | Back: { |
| | | |
| | | In: function (k) { |
| | | |
| | | var s = 1.70158; |
| | | |
| | | return k * k * ((s + 1) * k - s); |
| | | |
| | | }, |
| | | |
| | | Out: function (k) { |
| | | |
| | | var s = 1.70158; |
| | | |
| | | return --k * k * ((s + 1) * k + s) + 1; |
| | | |
| | | }, |
| | | |
| | | InOut: function (k) { |
| | | |
| | | var s = 1.70158 * 1.525; |
| | | |
| | | if ((k *= 2) < 1) { |
| | | return 0.5 * (k * k * ((s + 1) * k - s)); |
| | | } |
| | | |
| | | return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2); |
| | | |
| | | } |
| | | |
| | | }, |
| | | |
| | | Bounce: { |
| | | |
| | | In: function (k) { |
| | | |
| | | return 1 - TWEEN.Easing.Bounce.Out(1 - k); |
| | | |
| | | }, |
| | | |
| | | Out: function (k) { |
| | | |
| | | if (k < (1 / 2.75)) { |
| | | return 7.5625 * k * k; |
| | | } else if (k < (2 / 2.75)) { |
| | | return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75; |
| | | } else if (k < (2.5 / 2.75)) { |
| | | return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375; |
| | | } else { |
| | | return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375; |
| | | } |
| | | |
| | | }, |
| | | |
| | | InOut: function (k) { |
| | | |
| | | if (k < 0.5) { |
| | | return TWEEN.Easing.Bounce.In(k * 2) * 0.5; |
| | | } |
| | | |
| | | return TWEEN.Easing.Bounce.Out(k * 2 - 1) * 0.5 + 0.5; |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | }; |
| | | |
| | | TWEEN.Interpolation = { |
| | | |
| | | Linear: function (v, k) { |
| | | |
| | | var m = v.length - 1; |
| | | var f = m * k; |
| | | var i = Math.floor(f); |
| | | var fn = TWEEN.Interpolation.Utils.Linear; |
| | | |
| | | if (k < 0) { |
| | | return fn(v[0], v[1], f); |
| | | } |
| | | |
| | | if (k > 1) { |
| | | return fn(v[m], v[m - 1], m - f); |
| | | } |
| | | |
| | | return fn(v[i], v[i + 1 > m ? m : i + 1], f - i); |
| | | |
| | | }, |
| | | |
| | | Bezier: function (v, k) { |
| | | |
| | | var b = 0; |
| | | var n = v.length - 1; |
| | | var pw = Math.pow; |
| | | var bn = TWEEN.Interpolation.Utils.Bernstein; |
| | | |
| | | for (var i = 0; i <= n; i++) { |
| | | b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i); |
| | | } |
| | | |
| | | return b; |
| | | |
| | | }, |
| | | |
| | | CatmullRom: function (v, k) { |
| | | |
| | | var m = v.length - 1; |
| | | var f = m * k; |
| | | var i = Math.floor(f); |
| | | var fn = TWEEN.Interpolation.Utils.CatmullRom; |
| | | |
| | | if (v[0] === v[m]) { |
| | | |
| | | if (k < 0) { |
| | | i = Math.floor(f = m * (1 + k)); |
| | | } |
| | | |
| | | return fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i); |
| | | |
| | | } else { |
| | | |
| | | if (k < 0) { |
| | | return v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0]); |
| | | } |
| | | |
| | | if (k > 1) { |
| | | return v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]); |
| | | } |
| | | |
| | | return fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i); |
| | | |
| | | } |
| | | |
| | | }, |
| | | |
| | | Utils: { |
| | | |
| | | Linear: function (p0, p1, t) { |
| | | |
| | | return (p1 - p0) * t + p0; |
| | | |
| | | }, |
| | | |
| | | Bernstein: function (n, i) { |
| | | |
| | | var fc = TWEEN.Interpolation.Utils.Factorial; |
| | | |
| | | return fc(n) / fc(i) / fc(n - i); |
| | | |
| | | }, |
| | | |
| | | Factorial: (function () { |
| | | |
| | | var a = [1]; |
| | | |
| | | return function (n) { |
| | | |
| | | var s = 1; |
| | | |
| | | if (a[n]) { |
| | | return a[n]; |
| | | } |
| | | |
| | | for (var i = n; i > 1; i--) { |
| | | s *= i; |
| | | } |
| | | |
| | | a[n] = s; |
| | | return s; |
| | | |
| | | }; |
| | | |
| | | })(), |
| | | |
| | | CatmullRom: function (p0, p1, p2, p3, t) { |
| | | |
| | | var v0 = (p2 - p0) * 0.5; |
| | | var v1 = (p3 - p1) * 0.5; |
| | | var t2 = t * t; |
| | | var t3 = t * t2; |
| | | |
| | | return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1; |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | }; |
| | | |
| | | // UMD (Universal Module Definition) |
| | | (function (root) { |
| | | |
| | | if (typeof define === 'function' && define.amd) { |
| | | |
| | | // AMD |
| | | define([], function () { |
| | | return TWEEN; |
| | | }); |
| | | |
| | | } else if (typeof module !== 'undefined' && typeof exports === 'object') { |
| | | |
| | | // Node.js |
| | | module.exports = TWEEN; |
| | | |
| | | } else if (root !== undefined) { |
| | | |
| | | // Global variable |
| | | root.TWEEN = TWEEN; |
| | | |
| | | } |
| | | |
| | | })(this); |
| | |
| | | src: "topoGraph", |
| | | }, |
| | | { |
| | | label: "3D机房", |
| | | icon: "el-icon-s-platform", |
| | | name: "room3D", |
| | | src: "room3D", |
| | | }, |
| | | { |
| | | label: "UPS状态监控", |
| | | icon: "el-icon-s-platform", |
| | | name: "UPSStateMonitor", |
| | |
| | | import router from './router' |
| | | import store from './store' |
| | | |
| | | import * as THREE from 'three' |
| | | window.THREE = THREE |
| | | |
| | | import ElementUI from 'element-ui' |
| | | import 'element-ui/lib/theme-chalk/index.css' |
| | | import './assets/css/basic.css' |
New file |
| | |
| | | <template> |
| | | <div class="contentBox threeRoom"> |
| | | <div id="remap"></div> |
| | | </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"; |
| | | let threeBuild; |
| | | export default { |
| | | data() { |
| | | return { |
| | | initOption: { |
| | | cameraPosition: [0, 800, -1500], //初始化相机视角位置 |
| | | showAxisHelper: true, |
| | | }, |
| | | }; |
| | | }, |
| | | mounted() { |
| | | this.$nextTick(() => { |
| | | this.initThreeEvent(); |
| | | threeBuild = new InitThree(); |
| | | threeBuild.initmsj3D("remap", this.initOption, Aobjects); |
| | | threeBuild.start(); |
| | | }); |
| | | }, |
| | | methods: { |
| | | //初始化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("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); |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | | //打开机柜门 |
| | | 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); |
| | | } |
| | | _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 + "电池!"); |
| | | } |
| | | }, |
| | | destroyed() { |
| | | threeBuild.stop(); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .threeRoom { |
| | | width: 100%; |
| | | height: 100%; |
| | | position: relative; |
| | | padding: 20px; |
| | | } |
| | | |
| | | #remap { |
| | | width: 100%; |
| | | height: 100%; |
| | | overflow: hidden; |
| | | transition: 0.3s; |
| | | } |
| | | </style> |
| | |
| | | name: 'topoGraph', |
| | | meta: {}, |
| | | component: (resolve) => require(['@/pages/home/topoGraph.vue'], resolve), |
| | | }, { //3D机房 |
| | | path: 'room3D', |
| | | name: 'room3D', |
| | | meta: {}, |
| | | component: (resolve) => require(['@/pages/room.vue'], resolve), |
| | | }, { //UPS状态监控 |
| | | path: 'UPSStateMonitor', |
| | | name: 'UPSStateMonitor', |