diff --git a/src/jlmap3d/jl3dstationmanager/component/jl3dactionmanager.js b/src/jlmap3d/jl3dstationmanager/component/jl3dactionmanager.js new file mode 100644 index 000000000..c85646d4e --- /dev/null +++ b/src/jlmap3d/jl3dstationmanager/component/jl3dactionmanager.js @@ -0,0 +1,438 @@ +import { Staticmodel } from '@/jlmap3d/jl3dtrafficplan/loader/stationconfig.js'; +//静态资源文件路劲 +import { JL3D_LOCAL_STATIC } from '@/api/jlmap3d/assets3d.js'; +//loader +import { FBXLoader } from '@/jlmap3d/main/loaders/FBXLoader'; +//轨道视角控制 +import { StationManagerControls } from '@/jlmap3d/jl3dstationmanager/controls/stationManagerControls'; +//模型管理器 +import { ModelManager } from '@/jlmap3d/jl3dstationmanager/loader/loader.js'; +//骨骼动画模型辅助工具 +import { SkeletonUtils } from '@/jlmap3d/main/utils/SkeletonUtils.js'; +//获取信息接口 +import { getPublishMapVersion, getPublishMapDetail,getPublish3dMapDetail} from '@/api/jlmap3d/load3ddata'; +//cctv站台对象 +import { PasserStation } from '@/jlmap3d/jl3dtrafficplan/model/passerstation.js'; +//cctv检票机对象 +import { PasserCheckDoor } from '@/jlmap3d/jl3dtrafficplan/model/passercheckdoor.js'; +//cctv列车对象 +import { PasserTrain } from '@/jlmap3d/jl3dtrafficplan/model/passertrain.js'; +//cctv行人对象 +import { PasserHuman } from '@/jlmap3d/jl3dtrafficplan/model/passerhuman.js'; +//cctv渲染器 +import { PasserRender } from '@/jlmap3d/jl3dpassflow/passerrender/passerrender.js'; +//cctv行人ai +import { PasserAi } from '@/jlmap3d/jl3dtrafficplan/passerai/passerai.js'; +//行人寻路相关工具 +import { ZoneManager } from '@/jlmap3d/jl3dtrafficplan/model/zonemanager.js'; +import { PathFinder } from '@/jlmap3d/jl3dtrafficplan/passerai/pathfinder.js'; +//cctv通信工具 +import { PassflowConnect } from '@/jlmap3d/jl3dtrafficplan/connect/stationconnect.js'; + +import StompClient from '@/utils/sock'; +import store from '@/store/index'; +// import { Loading } from 'element-ui'; +import {Stats} from '@/jlmap3d/main/lib/stats.min.js'; + +//动画播放相关 +let clock = new THREE.Clock(); +let delta; + +let scene,camerass,renderer; + +let aiswitch = 0; +//动画组 +let mixers = []; +//车站摄像机模型 +let monitor; + +//寻路相关对象 +let passerZone = new ZoneManager(); +let pathFinder = new PathFinder(); +let path; + +//设备动画action组 +let deviceaction = []; +//控制帧率的webworker线程 +let passerWebWork = new Worker(JL3D_LOCAL_STATIC+"/workertest/trafficplan/trafficstation.js"); + +//老版本临时ai控制 +let olddataai = false; + +export function Jl3dStationManager(dom,skinCode,routegroup,viewMap,initCode) { + + // let stats = new Stats(); + // dom.appendChild( stats.dom ); + + let scope = this; + + this.dom = dom; + this.nowcode = null; + this.animateswitch = false; + this.signallights = []; + this.mixers = []; + this.showmodel = null; + + this.allStationData = []; + this.humanWaitTop = 0; + this.humanWaitDown = 0; + this.humanInSpeed = 0; + this.humanOutSpeed = 0; + let waitForCreatIn = []; + let waitForCreatOutTop = []; + let waitForCreatOutDown = []; + //定义相机 + camerass = new THREE.PerspectiveCamera(70, dom.offsetWidth / dom.offsetHeight, 0.01, 10000); + camerass.position.set(0,200,0); + camerass.aspect = dom.offsetWidth / dom.offsetHeight; + camerass.updateProjectionMatrix(); + + //定义场景(渲染容器) + scene = new THREE.Scene(); + // scene.background = new THREE.Color(0xa0a0a0); + + + var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 1000, 1000 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) ); + mesh.rotation.x = - Math.PI / 2; + mesh.receiveShadow = true; + scene.add( mesh ); + + var grid = new THREE.GridHelper( 1000, 100, 0x000000, 0x000000 ); + grid.material.opacity = 0.2; + grid.material.transparent = true; + scene.add( grid ); + + let passerRender = new PasserRender(viewMap); + passerRender.initView(dom,scene,camerass); + passerRender.reSize(scope.dom.offsetWidth,scope.dom.offsetHeight); + //定义全局光 + let ambientLight = new THREE.AmbientLight(0xffffff, 1.3); + scene.add(ambientLight); + var light = new THREE.HemisphereLight( 0xffffff, 0x444444 ); + light.position.set( 0, 4000, 0 ); + scene.add( light ); + + let controls = new THREE.StationManagerControls(camerass, dom,camerass,scene,mesh); + // controls.maxPolarAngle = Math.PI / 2; + // controls.minPolarangle = Math.PI / 5; + // controls.maxDistance = 800; + controls.screenSpacePanning = true; + + controls.target.set( 1, 0, 0 ); + controls.controlMode = "Draw"; + controls.update(); + this.selectmodel = null; + + // let mouse = new THREE.Vector2(); + let raycaster = new THREE.Raycaster(); + + //进站运动中乘客 + let humanlist = new THREE.Group(); + //上行等待上车乘客 + let topWaitPassers = new THREE.Group(); + //下行等待上车乘客 + let downWaitPassers = new THREE.Group(); + //出站乘客 + let outStationPassers = new THREE.Group(); + + let passerHuman = new PasserHuman(); + + let passerAi = new PasserAi(passerZone,pathFinder); + + this.anime = null; + + this.modelmanager = new ModelManager(); + // let loadingInstance = Loading.service({ fullscreen: true }); + + let stationlist = []; + let socktest = null; + let passerStation = new PasserStation(); + let passerCheckDoor = new PasserCheckDoor(); + let passerTrain = new PasserTrain(); + + // document.addEventListener( "mousedown", onselect, false ); + + this.modelmanager.loadpromise(Staticmodel, scope.mixers,"2").then(function (data) { + // console.log(scope.modelmanager.station.mesh.getObjectByName("top")); + // let testtop = scope.modelmanager.station.mesh.getObjectByName("down"); + // for(let i=0;i=0;an--){ + passerTrain.toptrain.action.top[an].reset(); + passerTrain.toptrain.action.top[an].time = passerTrain.toptrain.action.top[an]._clip.duration; + passerTrain.toptrain.action.top[an].timeScale = -1; + passerTrain.toptrain.action.top[an].play(); + } + for(let an=passerTrain.toptrain.action.down.length-1;an>=0;an--){ + passerTrain.toptrain.action.down[an].reset(); + passerTrain.toptrain.action.down[an].time = passerTrain.toptrain.action.down[an]._clip.duration; + passerTrain.toptrain.action.down[an].timeScale = -1; + passerTrain.toptrain.action.down[an].play(); + } + // for(let an=actions.length-1;an>=0;an--){ + // actions[an].reset(); + // actions[an].time = actions[an]._clip.duration; + // actions[an].timeScale = -1; + // actions[an].play(); + // } + setTimeout(function(){ + passerAi.initPasser(humanlist,topWaitPassers,downWaitPassers,passerHuman,scope); + aiswitch = 0; + }, 2000); + + } + + function startWorker(){ + + let updateaianimate = setInterval( + function(){ + // console.log("?"); + if(aiswitch == 0){ + updatePasserData(humanlist.children.length,topWaitPassers.children.length,downWaitPassers.children.length,outStationPassers.children.length,passerHuman.speed); + + passerHuman.moveAnimateUpdate(humanlist,topWaitPassers,downWaitPassers,outStationPassers,passerHuman); + passerAi.aiUpdate(humanlist,topWaitPassers,downWaitPassers,outStationPassers,passerHuman,passerCheckDoor,deviceaction); + // passerZone.zoneActionCheck(humanlist,passerHuman,passerCheckDoor,deviceaction); + delta = clock.getDelta(); + + for(let i=mixers.length-1;i>=0;i--){ + if(mixers[i]._actions[0].isRunning()){ + mixers[i].update( delta ); + } + } + // for(let i=topWaitPassers.children.length-1;i>=0;i--){ + // if(topWaitPassers.children[i].mixer._actions[0].isRunning()){ + // topWaitPassers.children[i].mixer.update( delta ); + // } + // } + // for(let i=downWaitPassers.children.length-1;i>=0;i--){ + // if(downWaitPassers.children[i].mixer._actions[0].isRunning()){ + // downWaitPassers.children[i].mixer.update( delta ); + // } + // } + // for(let i=outStationPassers.children.length-1;i>=0;i--){ + // if(outStationPassers.children[i].mixer._actions[0].isRunning()){ + // outStationPassers.children[i].mixer.update( delta ); + // } + // } + // for(let i=humanlist.children.length-1;i>=0;i--){ + // if(humanlist.children[i].mixer._actions[0].isRunning()){ + // humanlist.children[i].mixer.update( delta ); + // } + // } + } + } + , 100); + + passerWebWork.onmessage = function (event) { + if(aiswitch == 0){ + // console.log(humanlist.children.length); + + this.allStationData = []; + if(waitForCreatIn.length>0){ + let direct = Math.floor(Math.random()*(3-1+1))+1; + //1--top + //2-- down + if(direct == 1){ + passerHuman.newHumanCreate(humanlist,passerZone.getzoneposition("enter1"),0,waitForCreatIn[0].overGoal); + }else{ + passerHuman.newHumanCreate(humanlist,passerZone.getzoneposition("enter2"),0,waitForCreatIn[0].overGoal); + } + waitForCreatIn.shift(); + } + } + }; + } + // + // function onselect(event){ + // if(event.button == '0'){ + // + // //定义光线 + // let raycaster = new THREE.Raycaster(); + // //定义平面鼠标点击坐标 + // let mouse = new THREE.Vector2(); + // mouse.x = (event.clientX / scope.dom.offsetWidth) * 2 - 1; + // mouse.y = -(event.clientY / scope.dom.offsetHeight) * 2 + 1; + // + // raycaster.setFromCamera( mouse, camerass ); + // + // let intersects = raycaster.intersectObject(scope.modelmanager.station.mesh,true); + // console.log(intersects[0].point); + // } + // } + + + //循环渲染函数 + function animate() { + passerRender.update(); + // console.log(passerRender); + // console.log("ss"); + // if(passerRender.state == "freeview"){ + controls.update(); + // } + // delta = clock.getDelta(); + + requestAnimationFrame(animate); + + } + + window.onresize = function () { + passerRender.reSize(scope.dom.offsetWidth,scope.dom.offsetHeight); + } + + this.switchviews = function(viewmode){ + passerRender.changeRenderMode(viewmode); + } + + + function getnum(num,pnum){ + let re = []; + let base = Math.floor(num/pnum); + let reset = num%pnum; + for(let i=0;i2){ + atobject.railpoint[1] = { + x:cube2.matrixWorld.elements[12], + y:cube2.matrixWorld.elements[13], + z:cube2.matrixWorld.elements[14], + }; + atobject.railpoint[2] = { + x:cube3.matrixWorld.elements[12], + y:cube3.matrixWorld.elements[13], + z:cube3.matrixWorld.elements[14], + }; + }else{ + atobject.railpoint[1] = { + x:cube3.matrixWorld.elements[12], + y:cube3.matrixWorld.elements[13], + z:cube3.matrixWorld.elements[14], + }; + } + }else{ + object.position.copy( offset ).add( positionStart ); + } + + + + // Apply translation snap + if ( this.translationSnap ) { + if ( space === 'local' ) { + + object.position.applyQuaternion(_tempQuaternion.copy( quaternionStart ).inverse() ); + + if ( axis.search( 'X' ) !== -1 ) { + object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap; + } + + if ( axis.search( 'Y' ) !== -1 ) { + object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap; + } + + if ( axis.search( 'Z' ) !== -1 ) { + object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap; + } + + object.position.applyQuaternion( quaternionStart ); + + } + + if ( space === 'world' ) { + + if ( object.parent ) { + object.position.add( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) ); + } + + if ( axis.search( 'X' ) !== -1 ) { + object.position.x = Math.round( object.position.x / this.translationSnap ) * this.translationSnap; + } + + if ( axis.search( 'Y' ) !== -1 ) { + object.position.y = Math.round( object.position.y / this.translationSnap ) * this.translationSnap; + } + + if ( axis.search( 'Z' ) !== -1 ) { + object.position.z = Math.round( object.position.z / this.translationSnap ) * this.translationSnap; + } + + if ( object.parent ) { + object.position.sub( _tempVector.setFromMatrixPosition( object.parent.matrixWorld ) ); + } + + } + + } + + } else if ( mode === 'scale' ) { + + if ( axis.search( 'XYZ' ) !== -1 ) { + + var d = pointEnd.length() / pointStart.length(); + + if ( pointEnd.dot( pointStart ) < 0 ) d *= -1; + + _tempVector.set( d, d, d ); + + } else { + + _tempVector.copy( pointEnd ).divide( pointStart ); + + if ( axis.search( 'X' ) === -1 ) { + _tempVector.x = 1; + } + if ( axis.search( 'Y' ) === -1 ) { + _tempVector.y = 1; + } + if ( axis.search( 'Z' ) === -1 ) { + _tempVector.z = 1; + } + + } + + // Apply scale + + object.scale.copy( scaleStart ).multiply( _tempVector ); + + } else if ( mode === 'rotate' ) { + + offset.copy( pointEnd ).sub( pointStart ); + + var ROTATION_SPEED = 20 / worldPosition.distanceTo( _tempVector.setFromMatrixPosition( this.camera.matrixWorld ) ); + + if ( axis === 'E' ) { + + rotationAxis.copy( eye ); + rotationAngle = pointEnd.angleTo( pointStart ); + + startNorm.copy( pointStart ).normalize(); + endNorm.copy( pointEnd ).normalize(); + + rotationAngle *= ( endNorm.cross( startNorm ).dot( eye ) < 0 ? 1 : -1); + + } else if ( axis === 'XYZE' ) { + + rotationAxis.copy( offset ).cross( eye ).normalize( ); + rotationAngle = offset.dot( _tempVector.copy( rotationAxis ).cross( this.eye ) ) * ROTATION_SPEED; + + } else if ( axis === 'X' || axis === 'Y' || axis === 'Z' ) { + + rotationAxis.copy( _unit[ axis ] ); + + _tempVector.copy( _unit[ axis ] ); + + if ( space === 'local' ) { + _tempVector.applyQuaternion( worldQuaternion ); + } + + rotationAngle = offset.dot( _tempVector.cross( eye ).normalize() ) * ROTATION_SPEED; + + } + + // Apply rotation snap + + if ( this.rotationSnap ) rotationAngle = Math.round( rotationAngle / this.rotationSnap ) * this.rotationSnap; + + this.rotationAngle = rotationAngle; + + // Apply rotate + if ( space === 'local' && axis !== 'E' && axis !== 'XYZE' ) { + + object.quaternion.copy( quaternionStart ); + object.quaternion.multiply( _tempQuaternion.setFromAxisAngle( rotationAxis, rotationAngle ) ).normalize(); + + } else { + + rotationAxis.applyQuaternion( parentQuaternionInv ); + object.quaternion.copy( _tempQuaternion.setFromAxisAngle( rotationAxis, rotationAngle ) ); + object.quaternion.multiply( quaternionStart ).normalize(); + + } + + } + + this.dispatchEvent( changeEvent ); + this.dispatchEvent( objectChangeEvent ); + + }; + + this.pointerUp = function( pointer ) { + + if ( pointer.button !== undefined && pointer.button !== 0 ) return; + + if ( this.dragging && ( this.axis !== null ) ) { + + mouseUpEvent.mode = this.mode; + this.dispatchEvent( mouseUpEvent ); + + } + + this.dragging = false; + + if ( pointer.button === undefined ) this.axis = null; + + }; + + // normalize mouse / touch pointer and remap {x,y} to view space. + + function getPointer( event ) { + + var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event; + + var rect = domElement.getBoundingClientRect(); + + return { + x: ( pointer.clientX - rect.left ) / rect.width * 2 - 1, + y: - ( pointer.clientY - rect.top ) / rect.height * 2 + 1, + button: event.button + }; + + } + + // mouse / touch event handlers + + function onPointerHover( event ) { + + if ( !scope.enabled ) return; + + scope.pointerHover( getPointer( event ) ); + + } + + function onPointerDown( event ) { + + if ( !scope.enabled ) return; + + document.addEventListener( "mousemove", onPointerMove, false ); + + scope.pointerHover( getPointer( event ) ); + scope.pointerDown( getPointer( event ) ); + + } + + function onPointerMove( event ) { + + if ( !scope.enabled ) return; + + scope.pointerMove( getPointer( event ) ); + + } + + function onPointerUp( event ) { + + if ( !scope.enabled ) return; + + document.removeEventListener( "mousemove", onPointerMove, false ); + + scope.pointerUp( getPointer( event ) ); + + } + + // TODO: depricate + + this.getMode = function () { + + return scope.mode; + + }; + + this.setMode = function ( mode ) { + + scope.mode = mode; + + }; + + this.setTranslationSnap = function ( translationSnap ) { + + scope.translationSnap = translationSnap; + + }; + + this.setRotationSnap = function ( rotationSnap ) { + + scope.rotationSnap = rotationSnap; + + }; + + this.setSize = function ( size ) { + + scope.size = size; + + }; + + this.setSpace = function ( space ) { + + scope.space = space; + + }; + + this.update = function () { + + console.warn( 'THREE.TransformControls: update function has been depricated.' ); + + }; + +}; + +THREE.TransformControls.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), { + + constructor: THREE.TransformControls, + + isTransformControls: true + +} ); + + +THREE.TransformControlsGizmo = function () { + + 'use strict'; + + THREE.Object3D.call( this ); + + this.type = 'TransformControlsGizmo'; + + // shared materials + + var gizmoMaterial = new THREE.MeshBasicMaterial({ + depthTest: false, + depthWrite: false, + transparent: true, + side: THREE.DoubleSide, + fog: false + }); + + var gizmoLineMaterial = new THREE.LineBasicMaterial({ + depthTest: false, + depthWrite: false, + transparent: true, + linewidth: 1, + fog: false + }); + + // Make unique material for each axis/color + + var matInvisible = gizmoMaterial.clone(); + matInvisible.opacity = 0.15; + + var matHelper = gizmoMaterial.clone(); + matHelper.opacity = 0.33; + + var matRed = gizmoMaterial.clone(); + matRed.color.set( 0xff0000 ); + + var matGreen = gizmoMaterial.clone(); + matGreen.color.set( 0x00ff00 ); + + var matBlue = gizmoMaterial.clone(); + matBlue.color.set( 0x0000ff ); + + var matWhiteTransperent = gizmoMaterial.clone(); + matWhiteTransperent.opacity = 0.25; + + var matYellowTransparent = matWhiteTransperent.clone(); + matYellowTransparent.color.set( 0xffff00 ); + + var matCyanTransparent = matWhiteTransperent.clone(); + matCyanTransparent.color.set( 0x00ffff ); + + var matMagentaTransparent = matWhiteTransperent.clone(); + matMagentaTransparent.color.set( 0xff00ff ); + + var matYellow = gizmoMaterial.clone(); + matYellow.color.set( 0xffff00 ); + + var matLineRed = gizmoLineMaterial.clone(); + matLineRed.color.set( 0xff0000 ); + + var matLineGreen = gizmoLineMaterial.clone(); + matLineGreen.color.set( 0x00ff00 ); + + var matLineBlue = gizmoLineMaterial.clone(); + matLineBlue.color.set( 0x0000ff ); + + var matLineCyan = gizmoLineMaterial.clone(); + matLineCyan.color.set( 0x00ffff ); + + var matLineMagenta = gizmoLineMaterial.clone(); + matLineMagenta.color.set( 0xff00ff ); + + var matLineYellow = gizmoLineMaterial.clone(); + matLineYellow.color.set( 0xffff00 ); + + var matLineGray = gizmoLineMaterial.clone(); + matLineGray.color.set( 0x787878); + + var matLineYellowTransparent = matLineYellow.clone(); + matLineYellowTransparent.opacity = 0.25; + + // reusable geometry + + var arrowGeometry = new THREE.CylinderBufferGeometry( 0, 0.05, 0.2, 12, 1, false); + + var scaleHandleGeometry = new THREE.BoxBufferGeometry( 0.125, 0.125, 0.125); + + var lineGeometry = new THREE.BufferGeometry( ); + lineGeometry.addAttribute('position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0 ], 3 ) ); + + var CircleGeometry = function( radius, arc ) { + + var geometry = new THREE.BufferGeometry( ); + var vertices = []; + + for ( var i = 0; i <= 64 * arc; ++i ) { + + vertices.push( 0, Math.cos( i / 32 * Math.PI ) * radius, Math.sin( i / 32 * Math.PI ) * radius ); + + } + + geometry.addAttribute('position', new THREE.Float32BufferAttribute( vertices, 3 ) ); + + return geometry; + + }; + + // Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position + + var TranslateHelperGeometry = function( radius, arc ) { + + var geometry = new THREE.BufferGeometry() + + geometry.addAttribute('position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 1, 1 ], 3 ) ); + + return geometry; + + }; + + // Gizmo definitions - custom hierarchy definitions for setupGizmo() function + + var gizmoTranslate = { + X: [ + [ new THREE.Mesh( arrowGeometry, matRed ), [ 1, 0, 0 ], [ 0, 0, -Math.PI / 2 ], null, 'fwd' ], + [ new THREE.Mesh( arrowGeometry, matRed ), [ 1, 0, 0 ], [ 0, 0, Math.PI / 2 ], null, 'bwd' ], + [ new THREE.Line( lineGeometry, matLineRed ) ] + ], + Y: [ + [ new THREE.Mesh( arrowGeometry, matGreen ), [ 0, 1, 0 ], null, null, 'fwd' ], + [ new THREE.Mesh( arrowGeometry, matGreen ), [ 0, 1, 0 ], [ Math.PI, 0, 0 ], null, 'bwd' ], + [ new THREE.Line( lineGeometry, matLineGreen ), null, [ 0, 0, Math.PI / 2 ] ] + ], + Z: [ + [ new THREE.Mesh( arrowGeometry, matBlue ), [ 0, 0, 1 ], [ Math.PI / 2, 0, 0 ], null, 'fwd' ], + [ new THREE.Mesh( arrowGeometry, matBlue ), [ 0, 0, 1 ], [ -Math.PI / 2, 0, 0 ], null, 'bwd' ], + [ new THREE.Line( lineGeometry, matLineBlue ), null, [ 0, -Math.PI / 2, 0 ] ] + ], + XYZ: [ + [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.1, 0 ), matWhiteTransperent ), [ 0, 0, 0 ], [ 0, 0, 0 ] ] + ], + XY: [ + [ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.295, 0.295 ), matYellowTransparent ), [ 0.15, 0.15, 0 ] ], + [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.18, 0.3, 0 ], null, [ 0.125, 1, 1 ] ], + [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.3, 0.18, 0 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ] ] + ], + YZ: [ + [ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.295, 0.295 ), matCyanTransparent ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ] ], + [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.18, 0.3 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ] ], + [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.3, 0.18 ], [ 0, -Math.PI / 2, 0 ], [ 0.125, 1, 1 ] ] + ], + XZ: [ + [ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.295, 0.295 ), matMagentaTransparent ), [ 0.15, 0, 0.15 ], [ -Math.PI / 2, 0, 0 ] ], + [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.18, 0, 0.3 ], null, [ 0.125, 1, 1 ] ], + [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.3, 0, 0.18 ], [ 0, -Math.PI / 2, 0 ], [ 0.125, 1, 1 ] ] + ] + }; + + var pickerTranslate = { + X: [ + [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0.6, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ] + ], + Y: [ + [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0, 0.6, 0 ] ] + ], + Z: [ + [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), matInvisible ), [ 0, 0, 0.6 ], [ Math.PI / 2, 0, 0 ] ] + ], + XYZ: [ + [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.2, 0 ), matInvisible ) ] + ], + XY: [ + [ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), matInvisible ), [ 0.2, 0.2, 0 ] ] + ], + YZ: [ + [ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), matInvisible ), [ 0, 0.2, 0.2 ], [ 0, Math.PI / 2, 0 ] ] + ], + XZ: [ + [ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), matInvisible ), [ 0.2, 0, 0.2 ], [ -Math.PI / 2, 0, 0 ] ] + ] + }; + + var helperTranslate = { + START: [ + [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ] + ], + END: [ + [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.01, 2 ), matHelper ), null, null, null, 'helper' ] + ], + DELTA: [ + [ new THREE.Line( TranslateHelperGeometry(), matHelper ), null, null, null, 'helper' ] + ], + X: [ + [ new THREE.Line( lineGeometry, matHelper.clone() ), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ] + ], + Y: [ + [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, -1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ] + ], + Z: [ + [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, 0, -1e3 ], [ 0, -Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ] + ] + }; + + var gizmoRotate = { + X: [ + [ new THREE.Line( CircleGeometry( 1, 0.5 ), matLineRed ) ], + [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.04, 0 ), matRed ), [ 0, 0, 0.99 ], null, [ 1, 3, 1 ] ], + ], + Y: [ + [ new THREE.Line( CircleGeometry( 1, 0.5 ), matLineGreen ), null, [ 0, 0, -Math.PI / 2 ] ], + [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.04, 0 ), matGreen ), [ 0, 0, 0.99 ], null, [ 3, 1, 1 ] ], + ], + Z: [ + [ new THREE.Line( CircleGeometry( 1, 0.5 ), matLineBlue ), null, [ 0, Math.PI / 2, 0 ] ], + [ new THREE.Mesh( new THREE.OctahedronBufferGeometry( 0.04, 0 ), matBlue ), [ 0.99, 0, 0 ], null, [ 1, 3, 1 ] ], + ], + E: [ + [ new THREE.Line( CircleGeometry( 1.25, 1 ), matLineYellowTransparent ), null, [ 0, Math.PI / 2, 0 ] ], + [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 1.17, 0, 0 ], [ 0, 0, -Math.PI / 2 ], [ 1, 1, 0.001 ]], + [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ -1.17, 0, 0 ], [ 0, 0, Math.PI / 2 ], [ 1, 1, 0.001 ]], + [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 0, -1.17, 0 ], [ Math.PI, 0, 0 ], [ 1, 1, 0.001 ]], + [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.03, 0, 0.15, 4, 1, false ), matLineYellowTransparent ), [ 0, 1.17, 0 ], [ 0, 0, 0 ], [ 1, 1, 0.001 ]], + ], + XYZE: [ + [ new THREE.Line( CircleGeometry( 1, 1 ), matLineGray ), null, [ 0, Math.PI / 2, 0 ] ] + ] + }; + + var helperRotate = { + AXIS: [ + [ new THREE.Line( lineGeometry, matHelper.clone() ), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ] + ] + }; + + var pickerRotate = { + X: [ + [ new THREE.Mesh( new THREE.TorusBufferGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, -Math.PI / 2, -Math.PI / 2 ] ], + ], + Y: [ + [ new THREE.Mesh( new THREE.TorusBufferGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ] ], + ], + Z: [ + [ new THREE.Mesh( new THREE.TorusBufferGeometry( 1, 0.1, 4, 24 ), matInvisible ), [ 0, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], + ], + E: [ + [ new THREE.Mesh( new THREE.TorusBufferGeometry( 1.25, 0.1, 2, 24 ), matInvisible ) ] + ], + XYZE: [ + [ new THREE.Mesh( new THREE.SphereBufferGeometry( 0.7, 10, 8 ), matInvisible ) ] + ] + }; + + var gizmoScale = { + X: [ + [ new THREE.Mesh( scaleHandleGeometry, matRed ), [ 0.8, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], + [ new THREE.Line( lineGeometry, matLineRed ), null, null, [ 0.8, 1, 1 ] ] + ], + Y: [ + [ new THREE.Mesh( scaleHandleGeometry, matGreen ), [ 0, 0.8, 0 ] ], + [ new THREE.Line( lineGeometry, matLineGreen ), null, [ 0, 0, Math.PI / 2 ], [ 0.8, 1, 1 ] ] + ], + Z: [ + [ new THREE.Mesh( scaleHandleGeometry, matBlue ), [ 0, 0, 0.8 ], [ Math.PI / 2, 0, 0 ] ], + [ new THREE.Line( lineGeometry, matLineBlue ), null, [ 0, -Math.PI / 2, 0 ], [ 0.8, 1, 1 ] ] + ], + XY: [ + [ new THREE.Mesh( scaleHandleGeometry, matYellowTransparent ), [ 0.85, 0.85, 0 ], null, [ 2, 2, 0.2 ] ], + [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.855, 0.98, 0 ], null, [ 0.125, 1, 1 ] ], + [ new THREE.Line( lineGeometry, matLineYellow ), [ 0.98, 0.855, 0 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ] ] + ], + YZ: [ + [ new THREE.Mesh( scaleHandleGeometry, matCyanTransparent ), [ 0, 0.85, 0.85 ], null, [ 0.2, 2, 2 ] ], + [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.855, 0.98 ], [ 0, 0, Math.PI / 2 ], [ 0.125, 1, 1 ] ], + [ new THREE.Line( lineGeometry, matLineCyan ), [ 0, 0.98, 0.855 ], [ 0, -Math.PI / 2, 0 ], [ 0.125, 1, 1 ] ] + ], + XZ: [ + [ new THREE.Mesh( scaleHandleGeometry, matMagentaTransparent ), [ 0.85, 0, 0.85 ], null, [ 2, 0.2, 2 ] ], + [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.855, 0, 0.98 ], null, [ 0.125, 1, 1 ] ], + [ new THREE.Line( lineGeometry, matLineMagenta ), [ 0.98, 0, 0.855 ], [ 0, -Math.PI / 2, 0 ], [ 0.125, 1, 1 ] ] + ], + XYZX: [ + [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.125, 0.125, 0.125 ), matWhiteTransperent ), [ 1.1, 0, 0 ] ], + ], + XYZY: [ + [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.125, 0.125, 0.125 ), matWhiteTransperent ), [ 0, 1.1, 0 ] ], + ], + XYZZ: [ + [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.125, 0.125, 0.125 ), matWhiteTransperent ), [ 0, 0, 1.1 ] ], + ] + }; + + var pickerScale = { + X: [ + [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0.5, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ] + ], + Y: [ + [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0, 0.5, 0 ] ] + ], + Z: [ + [ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 0.8, 4, 1, false ), matInvisible ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ] ] + ], + XY: [ + [ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0.85, 0.85, 0 ], null, [ 3, 3, 0.2 ] ], + ], + YZ: [ + [ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0, 0.85, 0.85 ], null, [ 0.2, 3, 3 ] ], + ], + XZ: [ + [ new THREE.Mesh( scaleHandleGeometry, matInvisible ), [ 0.85, 0, 0.85 ], null, [ 3, 0.2, 3 ] ], + ], + XYZX: [ + [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 1.1, 0, 0 ] ], + ], + XYZY: [ + [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 1.1, 0 ] ], + ], + XYZZ: [ + [ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.2, 0.2, 0.2 ), matInvisible ), [ 0, 0, 1.1 ] ], + ] + }; + + var helperScale = { + X: [ + [ new THREE.Line( lineGeometry, matHelper.clone() ), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], 'helper' ] + ], + Y: [ + [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, -1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], 'helper' ] + ], + Z: [ + [ new THREE.Line( lineGeometry, matHelper.clone() ), [ 0, 0, -1e3 ], [ 0, -Math.PI / 2, 0 ], [ 1e6, 1, 1 ], 'helper' ] + ] + }; + + // Creates an Object3D with gizmos described in custom hierarchy definition. + + var setupGizmo = function( gizmoMap ) { + + var gizmo = new THREE.Object3D(); + + for ( var name in gizmoMap ) { + + for ( var i = gizmoMap[ name ].length; i --; ) { + + var object = gizmoMap[ name ][ i ][ 0 ].clone(); + var position = gizmoMap[ name ][ i ][ 1 ]; + var rotation = gizmoMap[ name ][ i ][ 2 ]; + var scale = gizmoMap[ name ][ i ][ 3 ]; + var tag = gizmoMap[ name ][ i ][ 4 ]; + + // name and tag properties are essential for picking and updating logic. + object.name = name; + object.tag = tag; + + if (position) { + object.position.set(position[ 0 ], position[ 1 ], position[ 2 ]); + } + if (rotation) { + object.rotation.set(rotation[ 0 ], rotation[ 1 ], rotation[ 2 ]); + } + if (scale) { + object.scale.set(scale[ 0 ], scale[ 1 ], scale[ 2 ]); + } + + object.updateMatrix(); + + var tempGeometry = object.geometry.clone(); + tempGeometry.applyMatrix(object.matrix); + object.geometry = tempGeometry; + + object.position.set( 0, 0, 0 ); + object.rotation.set( 0, 0, 0 ); + object.scale.set(1, 1, 1); + + gizmo.add(object); + + } + + } + + return gizmo; + + }; + + // Reusable utility variables + + var tempVector = new THREE.Vector3( 0, 0, 0 ); + var tempEuler = new THREE.Euler(); + var alignVector = new THREE.Vector3( 0, 1, 0 ); + var zeroVector = new THREE.Vector3( 0, 0, 0 ); + var lookAtMatrix = new THREE.Matrix4(); + var tempQuaternion = new THREE.Quaternion(); + var tempQuaternion2 = new THREE.Quaternion(); + var identityQuaternion = new THREE.Quaternion(); + + var unitX = new THREE.Vector3( 1, 0, 0 ); + var unitY = new THREE.Vector3( 0, 1, 0 ); + var unitZ = new THREE.Vector3( 0, 0, 1 ); + + // Gizmo creation + + this.gizmo = {}; + this.picker = {}; + this.helper = {}; + + this.add( this.gizmo[ "translate" ] = setupGizmo( gizmoTranslate ) ); + this.add( this.gizmo[ "rotate" ] = setupGizmo( gizmoRotate ) ); + this.add( this.gizmo[ "scale" ] = setupGizmo( gizmoScale ) ); + this.add( this.picker[ "translate" ] = setupGizmo( pickerTranslate ) ); + this.add( this.picker[ "rotate" ] = setupGizmo( pickerRotate ) ); + this.add( this.picker[ "scale" ] = setupGizmo( pickerScale ) ); + this.add( this.helper[ "translate" ] = setupGizmo( helperTranslate ) ); + this.add( this.helper[ "rotate" ] = setupGizmo( helperRotate ) ); + this.add( this.helper[ "scale" ] = setupGizmo( helperScale ) ); + + // Pickers should be hidden always + + this.picker[ "translate" ].visible = false; + this.picker[ "rotate" ].visible = false; + this.picker[ "scale" ].visible = false; + + // updateMatrixWorld will update transformations and appearance of individual handles + + this.updateMatrixWorld = function () { + + var space = this.space; + + if ( this.mode === 'scale' ) space = 'local'; // scale always oriented to local rotation + + var quaternion = space === "local" ? this.worldQuaternion : identityQuaternion; + + // Show only gizmos for current transform mode + + this.gizmo[ "translate" ].visible = this.mode === "translate"; + this.gizmo[ "rotate" ].visible = this.mode === "rotate"; + this.gizmo[ "scale" ].visible = this.mode === "scale"; + + this.helper[ "translate" ].visible = this.mode === "translate"; + this.helper[ "rotate" ].visible = this.mode === "rotate"; + this.helper[ "scale" ].visible = this.mode === "scale"; + + + var handles = []; + handles = handles.concat( this.picker[ this.mode ].children ); + handles = handles.concat( this.gizmo[ this.mode ].children ); + handles = handles.concat( this.helper[ this.mode ].children ); + + for ( var i = 0; i < handles.length; i++ ) { + + var handle = handles[i]; + + // hide aligned to camera + + handle.visible = true; + handle.rotation.set( 0, 0, 0 ); + handle.position.copy( this.worldPosition ); + + var eyeDistance = this.worldPosition.distanceTo( this.cameraPosition); + handle.scale.set( 1, 1, 1 ).multiplyScalar( eyeDistance * this.size / 7 ); + + // TODO: simplify helpers and consider decoupling from gizmo + + if ( handle.tag === 'helper' ) { + + handle.visible = false; + + if ( handle.name === 'AXIS' ) { + + handle.position.copy( this.worldPositionStart ); + handle.visible = !!this.axis; + + if ( this.axis === 'X' ) { + + tempQuaternion.setFromEuler( tempEuler.set( 0, 0, 0 ) ); + handle.quaternion.copy( quaternion ).multiply( tempQuaternion ); + + if ( Math.abs( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) { + handle.visible = false; + } + + } + + if ( this.axis === 'Y' ) { + + tempQuaternion.setFromEuler( tempEuler.set( 0, 0, Math.PI / 2 ) ); + handle.quaternion.copy( quaternion ).multiply( tempQuaternion ); + + if ( Math.abs( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) { + handle.visible = false; + } + + } + + if ( this.axis === 'Z' ) { + + tempQuaternion.setFromEuler( tempEuler.set( 0, Math.PI / 2, 0 ) ); + handle.quaternion.copy( quaternion ).multiply( tempQuaternion ); + + if ( Math.abs( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > 0.9 ) { + handle.visible = false; + } + + } + + if ( this.axis === 'XYZE' ) { + + tempQuaternion.setFromEuler( tempEuler.set( 0, Math.PI / 2, 0 ) ); + alignVector.copy( this.rotationAxis ); + handle.quaternion.setFromRotationMatrix( lookAtMatrix.lookAt( zeroVector, alignVector, unitY ) ); + handle.quaternion.multiply( tempQuaternion ); + handle.visible = this.dragging; + + } + + if ( this.axis === 'E' ) { + + handle.visible = false; + + } + + + } else if ( handle.name === 'START' ) { + + handle.position.copy( this.worldPositionStart ); + handle.visible = this.dragging; + + } else if ( handle.name === 'END' ) { + + handle.position.copy( this.worldPosition ); + handle.visible = this.dragging; + + } else if ( handle.name === 'DELTA' ) { + + handle.position.copy( this.worldPositionStart ); + handle.quaternion.copy( this.worldQuaternionStart ); + tempVector.set( 1e-10, 1e-10, 1e-10 ).add( this.worldPositionStart ).sub( this.worldPosition ).multiplyScalar( -1 ); + tempVector.applyQuaternion( this.worldQuaternionStart.clone().inverse() ); + handle.scale.copy( tempVector ); + handle.visible = this.dragging; + + } else { + + handle.quaternion.copy( quaternion ); + + if ( this.dragging ) { + + handle.position.copy( this.worldPositionStart ); + + } else { + + handle.position.copy( this.worldPosition ); + + } + + if ( this.axis ) { + + handle.visible = this.axis.search( handle.name ) !== -1; + + } + + } + + // If updating helper, skip rest of the loop + continue; + + } + + // Align handles to current local or world rotation + + handle.quaternion.copy( quaternion ); + + if ( this.mode === 'translate' || this.mode === 'scale' ) { + + // Hide translate and scale axis facing the camera + + var AXIS_HIDE_TRESHOLD = 0.99; + var PLANE_HIDE_TRESHOLD = 0.2; + var AXIS_FLIP_TRESHOLD = -0.4; + + + if ( handle.name === 'X' || handle.name === 'XYZX' ) { + if ( Math.abs( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) { + handle.scale.set( 1e-10, 1e-10, 1e-10 ); + handle.visible = false; + } + } + if ( handle.name === 'Y' || handle.name === 'XYZY' ) { + if ( Math.abs( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) { + handle.scale.set( 1e-10, 1e-10, 1e-10 ); + handle.visible = false; + } + } + if ( handle.name === 'Z' || handle.name === 'XYZZ' ) { + if ( Math.abs( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) { + handle.scale.set( 1e-10, 1e-10, 1e-10 ); + handle.visible = false; + } + } + if ( handle.name === 'XY' ) { + if ( Math.abs( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) { + handle.scale.set( 1e-10, 1e-10, 1e-10 ); + handle.visible = false; + } + } + if ( handle.name === 'YZ' ) { + if ( Math.abs( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) { + handle.scale.set( 1e-10, 1e-10, 1e-10 ); + handle.visible = false; + } + } + if ( handle.name === 'XZ' ) { + if ( Math.abs( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) { + handle.scale.set( 1e-10, 1e-10, 1e-10 ); + handle.visible = false; + } + } + + // Flip translate and scale axis ocluded behind another axis + + if ( handle.name.search( 'X' ) !== -1 ) { + if ( alignVector.copy( unitX ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) { + if ( handle.tag === 'fwd' ) { + handle.visible = false; + } else { + handle.scale.x *= -1; + } + } else if ( handle.tag === 'bwd' ) { + handle.visible = false; + } + } + + if ( handle.name.search( 'Y' ) !== -1 ) { + if ( alignVector.copy( unitY ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) { + if ( handle.tag === 'fwd' ) { + handle.visible = false; + } else { + handle.scale.y *= -1; + } + } else if ( handle.tag === 'bwd' ) { + handle.visible = false; + } + } + + if ( handle.name.search( 'Z' ) !== -1 ) { + if ( alignVector.copy( unitZ ).applyQuaternion( quaternion ).dot( this.eye ) < AXIS_FLIP_TRESHOLD ) { + if ( handle.tag === 'fwd' ) { + handle.visible = false; + } else { + handle.scale.z *= -1; + } + } else if ( handle.tag === 'bwd' ) { + handle.visible = false; + } + } + + } else if ( this.mode === 'rotate' ) { + + // Align handles to current local or world rotation + + tempQuaternion2.copy( quaternion ); + alignVector.copy( this.eye ).applyQuaternion( tempQuaternion.copy( quaternion ).inverse() ); + + if ( handle.name.search( "E" ) !== - 1 ) { + + handle.quaternion.setFromRotationMatrix( lookAtMatrix.lookAt( this.eye, zeroVector, unitY ) ); + + } + + if ( handle.name === 'X' ) { + + tempQuaternion.setFromAxisAngle( unitX, Math.atan2( -alignVector.y, alignVector.z ) ); + tempQuaternion.multiplyQuaternions( tempQuaternion2, tempQuaternion ); + handle.quaternion.copy( tempQuaternion ); + + } + + if ( handle.name === 'Y' ) { + + tempQuaternion.setFromAxisAngle( unitY, Math.atan2( alignVector.x, alignVector.z ) ); + tempQuaternion.multiplyQuaternions( tempQuaternion2, tempQuaternion ); + handle.quaternion.copy( tempQuaternion ); + + } + + if ( handle.name === 'Z' ) { + + tempQuaternion.setFromAxisAngle( unitZ, Math.atan2( alignVector.y, alignVector.x ) ); + tempQuaternion.multiplyQuaternions( tempQuaternion2, tempQuaternion ); + handle.quaternion.copy( tempQuaternion ); + + } + + } + + // Hide disabled axes + handle.visible = handle.visible && ( handle.name.indexOf( "X" ) === -1 || this.showX ); + handle.visible = handle.visible && ( handle.name.indexOf( "Y" ) === -1 || this.showY ); + handle.visible = handle.visible && ( handle.name.indexOf( "Z" ) === -1 || this.showZ ); + handle.visible = handle.visible && ( handle.name.indexOf( "E" ) === -1 || ( this.showX && this.showY && this.showZ ) ); + + // highlight selected axis + + handle.material._opacity = handle.material._opacity || handle.material.opacity; + handle.material._color = handle.material._color || handle.material.color.clone(); + + handle.material.color.copy( handle.material._color ); + handle.material.opacity = handle.material._opacity; + + if ( !this.enabled ) { + + handle.material.opacity *= 0.5; + handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 ); + + } else if ( this.axis ) { + + if ( handle.name === this.axis ) { + + handle.material.opacity = 1.0; + handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 ); + + } else if ( this.axis.split('').some( function( a ) { return handle.name === a; } ) ) { + + handle.material.opacity = 1.0; + handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 ); + + } else { + + handle.material.opacity *= 0.25; + handle.material.color.lerp( new THREE.Color( 1, 1, 1 ), 0.5 ); + + } + + } + + } + + THREE.Object3D.prototype.updateMatrixWorld.call( this ); + + }; + +}; + +THREE.TransformControlsGizmo.prototype = Object.assign( Object.create( THREE.Object3D.prototype ), { + + constructor: THREE.TransformControlsGizmo, + + isTransformControlsGizmo: true + +} ); + + +THREE.TransformControlsPlane = function () { + + 'use strict'; + + THREE.Mesh.call( this, + new THREE.PlaneBufferGeometry( 100000, 100000, 2, 2 ), + new THREE.MeshBasicMaterial( { visible: false, wireframe: true, side: THREE.DoubleSide, transparent: true, opacity: 0.1 } ) + ); + + this.type = 'TransformControlsPlane'; + + var unitX = new THREE.Vector3( 1, 0, 0 ); + var unitY = new THREE.Vector3( 0, 1, 0 ); + var unitZ = new THREE.Vector3( 0, 0, 1 ); + + var tempVector = new THREE.Vector3(); + var dirVector = new THREE.Vector3(); + var alignVector = new THREE.Vector3(); + var tempMatrix = new THREE.Matrix4(); + var identityQuaternion = new THREE.Quaternion(); + + this.updateMatrixWorld = function() { + + var space = this.space; + + this.position.copy( this.worldPosition ); + + if ( this.mode === 'scale' ) space = 'local'; // scale always oriented to local rotation + + unitX.set( 1, 0, 0 ).applyQuaternion( space === "local" ? this.worldQuaternion : identityQuaternion ); + unitY.set( 0, 1, 0 ).applyQuaternion( space === "local" ? this.worldQuaternion : identityQuaternion ); + unitZ.set( 0, 0, 1 ).applyQuaternion( space === "local" ? this.worldQuaternion : identityQuaternion ); + + // Align the plane for current transform mode, axis and space. + + alignVector.copy( unitY ); + + switch ( this.mode ) { + case 'translate': + case 'scale': + switch ( this.axis ) { + case 'X': + alignVector.copy( this.eye ).cross( unitX ); + dirVector.copy( unitX ).cross( alignVector ); + break; + case 'Y': + alignVector.copy( this.eye ).cross( unitY ); + dirVector.copy( unitY ).cross( alignVector ); + break; + case 'Z': + alignVector.copy( this.eye ).cross( unitZ ); + dirVector.copy( unitZ ).cross( alignVector ); + break; + case 'XY': + dirVector.copy( unitZ ); + break; + case 'YZ': + dirVector.copy( unitX ); + break; + case 'XZ': + alignVector.copy( unitZ ); + dirVector.copy( unitY ); + break; + case 'XYZ': + case 'E': + dirVector.set( 0, 0, 0 ); + break; + } + break; + case 'rotate': + default: + // special case for rotate + dirVector.set( 0, 0, 0 ); + } + + if ( dirVector.length() === 0 ) { + + // If in rotate mode, make the plane parallel to camera + this.quaternion.copy( this.cameraQuaternion ); + + } else { + + tempMatrix.lookAt( tempVector.set( 0, 0, 0 ), dirVector, alignVector ); + + this.quaternion.setFromRotationMatrix( tempMatrix ); + + } + + THREE.Object3D.prototype.updateMatrixWorld.call( this ); + + }; + +}; + +THREE.TransformControlsPlane.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), { + + constructor: THREE.TransformControlsPlane, + + isTransformControlsPlane: true + +} ); diff --git a/src/jlmap3d/jl3dstationmanager/controls/stationManagerControls.js b/src/jlmap3d/jl3dstationmanager/controls/stationManagerControls.js index 334ffa01f..634c14ad1 100644 --- a/src/jlmap3d/jl3dstationmanager/controls/stationManagerControls.js +++ b/src/jlmap3d/jl3dstationmanager/controls/stationManagerControls.js @@ -13,20 +13,33 @@ // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish // Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move -THREE.StationManagerControls = function ( object, domElement ) { +THREE.StationManagerControls = function ( object, domElement ,camera,scene) { this.object = object; - + this.planeMesh = []; this.data = { stationstandlist : null, trainlisttest : null }; + + this.animateswitch = null; this.scene = null; //控制模式切换 //画线:Orbit 绘图:Draw this.controlMode = "Orbit"; + this.drawColor = 0x2894FF; + this.drawSwitch = false; + this.drawGroup = new THREE.Group(); + scene.add(this.drawGroup); + + let drawMesh = null; + let mouse = new THREE.Vector2(); + let raycaster = new THREE.Raycaster(); + let intersects = null; + let drawStartPoint = null; + let drawEndPoint = null; this.domElement = ( domElement !== undefined ) ? domElement : document; @@ -96,6 +109,10 @@ THREE.StationManagerControls = function ( object, domElement ) { // // public methods // + this.initPlaneMesh = function (planeMesh){ + scope.planeMesh["1floor"] = planeMesh.topfloor; + scope.planeMesh["2floor"] = planeMesh.downfloor; + }; this.getPolarAngle = function () { @@ -729,7 +746,7 @@ THREE.StationManagerControls = function ( object, domElement ) { // prevents the browser from setting it automatically. scope.domElement.focus ? scope.domElement.focus() : window.focus(); - if(scope.controlMode == "orbit"){ + if(scope.controlMode == "Orbit"){ switch ( event.button ) { case scope.mouseButtons.RIGHT: @@ -779,11 +796,29 @@ THREE.StationManagerControls = function ( object, domElement ) { } if(scope.controlMode == "Draw"){ - var geometry = new THREE.PlaneGeometry( 20, 20, 1 ); - var material = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} ); - var plane = new THREE.Mesh( geometry, material ); - scene.add( plane ); - plane.position.x = 200; + if(scope.drawSwitch == true){ + var geometry = new THREE.PlaneGeometry( 1, 1, 1 ); + var material = new THREE.MeshBasicMaterial( {color: scope.drawColor, side: THREE.DoubleSide} ); + drawMesh = new THREE.Mesh( geometry, material ); + drawMesh.renderOrder = 8; + // drawMesh.rotation.x = Math.PI/2; + scope.drawGroup.add( drawMesh ); + // let edges = new THREE.EdgesHelper( drawMesh, 0x0000C6 );//设置边框,可以旋转 + + // drawMesh.add( edges ); + + mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; + mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; + raycaster.setFromCamera( mouse, camera ); + for(let k in scope.planeMesh){ + intersects = raycaster.intersectObject( scope.planeMesh[k] ); + if(intersects[0]){ + drawMesh.underFloor = k; + drawStartPoint = intersects[0].point; + state = "Draw"; + } + } + } } if ( state !== STATE.NONE ) { @@ -833,15 +868,39 @@ THREE.StationManagerControls = function ( object, domElement ) { } } - if(scope.controlMode == "Draw"){ - let points = [ - {x:-10,y:0,z:10}, - {x:10,y:0,z:10}, - {x:-10,y:0,z:-10}, - {x:10,y:0,z:-10} - ]; - plane.geometry.setFromPoints(points); + + mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; + mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; + raycaster.setFromCamera( mouse, camera ); + for(let k in scope.planeMesh){ + intersects = raycaster.intersectObject( scope.planeMesh[k] ); + if(intersects[0]){ + drawEndPoint = intersects[0].point; + let points = [ + + new THREE.Vector3(drawStartPoint.x,drawStartPoint.y+0.1,drawStartPoint.z), + new THREE.Vector3(drawEndPoint.x,drawStartPoint.y+0.1,drawStartPoint.z), + new THREE.Vector3(drawStartPoint.x,drawStartPoint.y+0.1,drawEndPoint.z), + new THREE.Vector3(drawEndPoint.x,drawStartPoint.y+0.1,drawEndPoint.z) + ]; + for(let i=0;i0){ + let stationobject = { + code : list[k][0].stationCode, + name : k, + toppsd:null, + downpsd:null, + topsection:null, + downsection:null, + }; + if(list[k][0].position.y0){ + for(let i=0;i0){ + for(let i=0;i + + + + + + + + 入口区域 + + + 安检区域 + + + 闸机区域 + + + 站台区域 + + + + + + 售票区域 + + + 电梯区域 + + + 楼梯区域 + + + 扶梯区域 + + + 禁行区域 + + + + + + + + + + + + + + diff --git a/src/views/jlmap3d/stationmanager/component/manager.vue b/src/views/jlmap3d/stationmanager/component/manager.vue new file mode 100644 index 000000000..d75a23888 --- /dev/null +++ b/src/views/jlmap3d/stationmanager/component/manager.vue @@ -0,0 +1,74 @@ + + + diff --git a/src/views/jlmap3d/stationmanager/component/property.vue b/src/views/jlmap3d/stationmanager/component/property.vue new file mode 100644 index 000000000..9848e3076 --- /dev/null +++ b/src/views/jlmap3d/stationmanager/component/property.vue @@ -0,0 +1,115 @@ + + + + + + diff --git a/src/views/jlmap3d/stationmanager/jl3dstationmanager.vue b/src/views/jlmap3d/stationmanager/jl3dstationmanager.vue index c4c81de37..667ce42b5 100644 --- a/src/views/jlmap3d/stationmanager/jl3dstationmanager.vue +++ b/src/views/jlmap3d/stationmanager/jl3dstationmanager.vue @@ -1,6 +1,23 @@ @@ -10,14 +27,20 @@ import { Jl3dStationManager } from '@/jlmap3d/jl3dstationmanager/jl3dstationmanager.js'; + import DrawType from '@/views/jlmap3d/stationmanager/component/drawtype'; + import ProPerty from '@/views/jlmap3d/stationmanager/component/property'; export default { name: 'jl3devacuation', components: { + DrawType, + ProPerty, }, data() { return { localStatic:JL3D_LOCAL_STATIC, jl3d: null, + switchButtonName:'仿真视角', + viewStatus:false, } }, watch: { @@ -39,13 +62,34 @@ let dom = document.getElementById('jl3d'); this.jl3d = new Jl3dStationManager(dom); }, + changeDrawType(drawTypeName){ + // console.log(drawTypeName); + this.jl3d.changeDrawType(drawTypeName); + }, + switchViews(){ + + if(this.viewStatus == false){ + this.switchButtonName = '绘制视角', + this.viewStatus = true; + this.jl3d.changeControlMode(true); + }else if(this.viewStatus == true){ + this.switchButtonName = '仿真视角 ', + this.viewStatus = false; + this.jl3d.changeControlMode(false); + } + }, } }