|
@@ -0,0 +1,652 @@
|
|
|
+
|
|
|
+import * as THREE from "../../libs/three.js/build/three.module.js";
|
|
|
+import {EventDispatcher} from "../EventDispatcher.js";
|
|
|
+import { XRControllerModelFactory } from '../../libs/three.js/webxr/XRControllerModelFactory.js';
|
|
|
+import {Line2} from "../../libs/three.js/lines/Line2.js";
|
|
|
+import {LineGeometry} from "../../libs/three.js/lines/LineGeometry.js";
|
|
|
+import {LineMaterial} from "../../libs/three.js/lines/LineMaterial.js";
|
|
|
+
|
|
|
+import {GLTFLoader} from "../../libs/three.js/loaders/GLTFLoader.js";
|
|
|
+
|
|
|
+
|
|
|
+let fakeCam = new THREE.PerspectiveCamera();
|
|
|
+
|
|
|
+function toScene(vec, ref){
|
|
|
+ let node = ref.clone();
|
|
|
+ node.updateMatrix();
|
|
|
+ node.updateMatrixWorld();
|
|
|
+
|
|
|
+ let result = vec.clone().applyMatrix4(node.matrix);
|
|
|
+ result.z -= 0.8 * node.scale.x;
|
|
|
+
|
|
|
+ return result;
|
|
|
+};
|
|
|
+
|
|
|
+function computeMove(vrControls, controller){
|
|
|
+
|
|
|
+ if(!controller || !controller.inputSource || !controller.inputSource.gamepad){
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ let pad = controller.inputSource.gamepad;
|
|
|
+
|
|
|
+ let axes = pad.axes;
|
|
|
+ // [0,1] are for touchpad, [2,3] for thumbsticks?
|
|
|
+ let y = 0;
|
|
|
+ if(axes.length === 2){
|
|
|
+ y = axes[1];
|
|
|
+ }else if(axes.length === 4){
|
|
|
+ y = axes[3];
|
|
|
+ }
|
|
|
+
|
|
|
+ y = Math.sign(y) * (2 * y) ** 2;
|
|
|
+
|
|
|
+ let maxSize = 0;
|
|
|
+ for(let pc of viewer.scene.pointclouds){
|
|
|
+ let size = pc.boundingBox.min.distanceTo(pc.boundingBox.max);
|
|
|
+ maxSize = Math.max(maxSize, size);
|
|
|
+ }
|
|
|
+ let multiplicator = Math.pow(maxSize, 0.5) / 2;
|
|
|
+
|
|
|
+ let scale = vrControls.node.scale.x;
|
|
|
+ let moveSpeed = viewer.getMoveSpeed();
|
|
|
+ let amount = multiplicator * y * (moveSpeed ** 0.5) / scale;
|
|
|
+
|
|
|
+
|
|
|
+ let rotation = new THREE.Quaternion().setFromEuler(controller.rotation);
|
|
|
+ let dir = new THREE.Vector3(0, 0, -1);
|
|
|
+ dir.applyQuaternion(rotation);
|
|
|
+
|
|
|
+ let move = dir.clone().multiplyScalar(amount);
|
|
|
+
|
|
|
+ let p1 = vrControls.toScene(controller.position);
|
|
|
+ let p2 = vrControls.toScene(controller.position.clone().add(move));
|
|
|
+
|
|
|
+ move = p2.clone().sub(p1);
|
|
|
+
|
|
|
+ return move;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+class FlyMode{
|
|
|
+
|
|
|
+ constructor(vrControls){
|
|
|
+ this.moveFactor = 1;
|
|
|
+ this.dbgLabel = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ start(vrControls){
|
|
|
+ if(!this.dbgLabel){
|
|
|
+ debugger;
|
|
|
+ /* this.dbgLabel = new Potree.TextSprite("abc");
|
|
|
+ this.dbgLabel.name = "debug label";
|
|
|
+ vrControls.viewer.sceneVR.add(this.dbgLabel);
|
|
|
+ this.dbgLabel.visible = false; */
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ end(){
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ update(vrControls, delta){
|
|
|
+
|
|
|
+ let primary = vrControls.cPrimary;
|
|
|
+ let secondary = vrControls.cSecondary;
|
|
|
+
|
|
|
+ let move1 = computeMove(vrControls, primary);
|
|
|
+ let move2 = computeMove(vrControls, secondary);
|
|
|
+
|
|
|
+
|
|
|
+ if(!move1){
|
|
|
+ move1 = new THREE.Vector3();
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!move2){
|
|
|
+ move2 = new THREE.Vector3();
|
|
|
+ }
|
|
|
+
|
|
|
+ let move = move1.clone().add(move2);
|
|
|
+
|
|
|
+ move.multiplyScalar(-delta * this.moveFactor);
|
|
|
+ vrControls.node.position.add(move);
|
|
|
+
|
|
|
+
|
|
|
+ let scale = vrControls.node.scale.x;
|
|
|
+
|
|
|
+ let camVR = vrControls.viewer.renderer.xr.getCamera(fakeCam);
|
|
|
+
|
|
|
+ let vrPos = camVR.getWorldPosition(new THREE.Vector3());
|
|
|
+ let vrDir = camVR.getWorldDirection(new THREE.Vector3());
|
|
|
+ let vrTarget = vrPos.clone().add(vrDir.multiplyScalar(scale));
|
|
|
+
|
|
|
+ let scenePos = toScene(vrPos, vrControls.node);
|
|
|
+ let sceneDir = toScene(vrPos.clone().add(vrDir), vrControls.node).sub(scenePos);
|
|
|
+ sceneDir.normalize().multiplyScalar(scale);
|
|
|
+ let sceneTarget = scenePos.clone().add(sceneDir);
|
|
|
+
|
|
|
+ vrControls.viewer.scene.view.setView({target:sceneTarget, position:scenePos})
|
|
|
+
|
|
|
+
|
|
|
+ if(Potree.debug.message){
|
|
|
+ this.dbgLabel.visible = true;
|
|
|
+ this.dbgLabel.setText(Potree.debug.message);
|
|
|
+ this.dbgLabel.scale.set(0.1, 0.1, 0.1);
|
|
|
+ this.dbgLabel.position.copy(primary.position);
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+class TranslationMode{
|
|
|
+
|
|
|
+ constructor(){
|
|
|
+ this.controller = null;
|
|
|
+ this.startPos = null;
|
|
|
+ this.debugLine = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ start(vrControls){
|
|
|
+ this.controller = vrControls.triggered.values().next().value;
|
|
|
+ this.startPos = vrControls.node.position.clone();
|
|
|
+ }
|
|
|
+
|
|
|
+ end(vrControls){
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ update(vrControls, delta){
|
|
|
+
|
|
|
+ let start = this.controller.start.position;
|
|
|
+ let end = this.controller.position;
|
|
|
+
|
|
|
+ start = vrControls.toScene(start);
|
|
|
+ end = vrControls.toScene(end);
|
|
|
+
|
|
|
+ let diff = end.clone().sub(start);
|
|
|
+ diff.set(-diff.x, -diff.y, -diff.z);
|
|
|
+
|
|
|
+ let pos = new THREE.Vector3().addVectors(this.startPos, diff);
|
|
|
+
|
|
|
+ vrControls.node.position.copy(pos);
|
|
|
+ }
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+class RotScaleMode{
|
|
|
+
|
|
|
+ constructor(){
|
|
|
+ this.line = null;
|
|
|
+ this.startState = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ start(vrControls){
|
|
|
+ if(!this.line){
|
|
|
+ this.line = Potree.Utils.debugLine(
|
|
|
+ vrControls.viewer.sceneVR,
|
|
|
+ new THREE.Vector3(0, 0, 0),
|
|
|
+ new THREE.Vector3(0, 0, 0),
|
|
|
+ 0xffff00,
|
|
|
+ );
|
|
|
+
|
|
|
+ this.dbgLabel = new Potree.TextSprite("abc");
|
|
|
+ this.dbgLabel.scale.set(0.1, 0.1, 0.1);
|
|
|
+ vrControls.viewer.sceneVR.add(this.dbgLabel);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.line.node.visible = true;
|
|
|
+
|
|
|
+ this.startState = vrControls.node.clone();
|
|
|
+ }
|
|
|
+
|
|
|
+ end(vrControls){
|
|
|
+ this.line.node.visible = false;
|
|
|
+ this.dbgLabel.visible = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ update(vrControls, delta){
|
|
|
+
|
|
|
+ let start_c1 = vrControls.cPrimary.start.position.clone();
|
|
|
+ let start_c2 = vrControls.cSecondary.start.position.clone();
|
|
|
+ let start_center = start_c1.clone().add(start_c2).multiplyScalar(0.5);
|
|
|
+ let start_c1_c2 = start_c2.clone().sub(start_c1);
|
|
|
+ let end_c1 = vrControls.cPrimary.position.clone();
|
|
|
+ let end_c2 = vrControls.cSecondary.position.clone();
|
|
|
+ let end_center = end_c1.clone().add(end_c2).multiplyScalar(0.5);
|
|
|
+ let end_c1_c2 = end_c2.clone().sub(end_c1);
|
|
|
+
|
|
|
+ let d1 = start_c1_c2.length();
|
|
|
+ let d2 = end_c1_c2.length();
|
|
|
+
|
|
|
+ let angleStart = new THREE.Vector2(start_c1_c2.x, start_c1_c2.z).angle();
|
|
|
+ let angleEnd = new THREE.Vector2(end_c1_c2.x, end_c1_c2.z).angle();
|
|
|
+ let angleDiff = angleEnd - angleStart;
|
|
|
+
|
|
|
+ let scale = d2 / d1;
|
|
|
+
|
|
|
+ let node = this.startState.clone();
|
|
|
+ node.updateMatrix();
|
|
|
+ node.matrixAutoUpdate = false;
|
|
|
+
|
|
|
+ let mToOrigin = new THREE.Matrix4().makeTranslation(...toScene(start_center, this.startState).multiplyScalar(-1).toArray());
|
|
|
+ let mToStart = new THREE.Matrix4().makeTranslation(...toScene(start_center, this.startState).toArray());
|
|
|
+ let mRotate = new THREE.Matrix4().makeRotationZ(angleDiff);
|
|
|
+ let mScale = new THREE.Matrix4().makeScale(1 / scale, 1 / scale, 1 / scale);
|
|
|
+
|
|
|
+ node.applyMatrix4(mToOrigin);
|
|
|
+ node.applyMatrix4(mRotate);
|
|
|
+ node.applyMatrix4(mScale);
|
|
|
+ node.applyMatrix4(mToStart);
|
|
|
+
|
|
|
+ let oldScenePos = toScene(start_center, this.startState);
|
|
|
+ let newScenePos = toScene(end_center, node);
|
|
|
+ let toNew = oldScenePos.clone().sub(newScenePos);
|
|
|
+ let mToNew = new THREE.Matrix4().makeTranslation(...toNew.toArray());
|
|
|
+ node.applyMatrix4(mToNew);
|
|
|
+
|
|
|
+ node.matrix.decompose(node.position, node.quaternion, node.scale );
|
|
|
+
|
|
|
+ vrControls.node.position.copy(node.position);
|
|
|
+ vrControls.node.quaternion.copy(node.quaternion);
|
|
|
+ vrControls.node.scale.copy(node.scale);
|
|
|
+ vrControls.node.updateMatrix();
|
|
|
+
|
|
|
+ {
|
|
|
+ let scale = vrControls.node.scale.x;
|
|
|
+ let camVR = vrControls.viewer.renderer.xr.getCamera(fakeCam);
|
|
|
+
|
|
|
+ let vrPos = camVR.getWorldPosition(new THREE.Vector3());
|
|
|
+ let vrDir = camVR.getWorldDirection(new THREE.Vector3());
|
|
|
+ let vrTarget = vrPos.clone().add(vrDir.multiplyScalar(scale));
|
|
|
+
|
|
|
+ let scenePos = toScene(vrPos, this.startState);
|
|
|
+ let sceneDir = toScene(vrPos.clone().add(vrDir), this.startState).sub(scenePos);
|
|
|
+ sceneDir.normalize().multiplyScalar(scale);
|
|
|
+ let sceneTarget = scenePos.clone().add(sceneDir);
|
|
|
+
|
|
|
+ vrControls.viewer.scene.view.setView(scenePos, sceneTarget);
|
|
|
+ vrControls.viewer.setMoveSpeed(scale);
|
|
|
+ }
|
|
|
+
|
|
|
+ { // update "GUI"
|
|
|
+ this.line.set(end_c1, end_c2);
|
|
|
+
|
|
|
+ let scale = vrControls.node.scale.x;
|
|
|
+ this.dbgLabel.visible = true;
|
|
|
+ this.dbgLabel.position.copy(end_center);
|
|
|
+ this.dbgLabel.setText(`scale: 1 : ${scale.toFixed(2)}`);
|
|
|
+ this.dbgLabel.scale.set(0.05, 0.05, 0.05);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+export class VRControls extends EventDispatcher{
|
|
|
+
|
|
|
+ constructor(viewer){
|
|
|
+ super(viewer);
|
|
|
+
|
|
|
+ this.viewer = viewer;
|
|
|
+
|
|
|
+ viewer.addEventListener("vr_start", this.onStart.bind(this));
|
|
|
+ viewer.addEventListener("vr_end", this.onEnd.bind(this));
|
|
|
+
|
|
|
+ this.node = new THREE.Object3D();
|
|
|
+ this.node.up.set(0, 0, 1);
|
|
|
+ this.triggered = new Set();
|
|
|
+
|
|
|
+ let xr = viewer.renderer.xr;
|
|
|
+
|
|
|
+ { // lights
|
|
|
+
|
|
|
+ const light = new THREE.PointLight( 0xffffff, 5, 0, 1 );
|
|
|
+ light.position.set(0, 2, 0);
|
|
|
+ this.viewer.sceneVR.add(light)
|
|
|
+ }
|
|
|
+
|
|
|
+ this.menu = null;
|
|
|
+
|
|
|
+ const controllerModelFactory = new XRControllerModelFactory(new GLTFLoader(undefined, viewer.renderer, Potree.settings.libsUrl ));
|
|
|
+
|
|
|
+ let sg = new THREE.SphereGeometry(1, 32, 32);
|
|
|
+ let sm = new THREE.MeshNormalMaterial();
|
|
|
+
|
|
|
+ { // setup primary controller
|
|
|
+ let controller = xr.getController(0);
|
|
|
+
|
|
|
+ let grip = xr.getControllerGrip(0);
|
|
|
+ grip.name = "grip(0)";
|
|
|
+
|
|
|
+ // ADD CONTROLLERMODEL
|
|
|
+ grip.add( controllerModelFactory.createControllerModel( grip ) );
|
|
|
+ this.viewer.sceneVR.add(grip);
|
|
|
+
|
|
|
+ // ADD SPHERE
|
|
|
+ let sphere = new THREE.Mesh(sg, sm);
|
|
|
+ sphere.scale.set(0.005, 0.005, 0.005);
|
|
|
+
|
|
|
+ controller.add(sphere);
|
|
|
+ controller.visible = true;
|
|
|
+ this.viewer.sceneVR.add(controller);
|
|
|
+
|
|
|
+ { // ADD LINE
|
|
|
+
|
|
|
+ let lineGeometry = new LineGeometry();
|
|
|
+
|
|
|
+ lineGeometry.setPositions([
|
|
|
+ 0, 0, -0.15,
|
|
|
+ 0, 0, 0.05,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ let lineMaterial = new LineMaterial({
|
|
|
+ color: 0xff0000,
|
|
|
+ linewidth: 2,
|
|
|
+ resolution: new THREE.Vector2(1000, 1000),
|
|
|
+ });
|
|
|
+
|
|
|
+ const line = new Line2(lineGeometry, lineMaterial);
|
|
|
+
|
|
|
+ controller.add(line);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ controller.addEventListener( 'connected', function ( event ) {
|
|
|
+ const xrInputSource = event.data;
|
|
|
+ controller.inputSource = xrInputSource;
|
|
|
+ // initInfo(controller);
|
|
|
+ });
|
|
|
+
|
|
|
+ controller.addEventListener( 'selectstart', () => {this.onTriggerStart(controller)});
|
|
|
+ controller.addEventListener( 'selectend', () => {this.onTriggerEnd(controller)});
|
|
|
+
|
|
|
+ this.cPrimary = controller;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ { // setup secondary controller
|
|
|
+ let controller = xr.getController(1);
|
|
|
+
|
|
|
+ let grip = xr.getControllerGrip(1);
|
|
|
+
|
|
|
+ // ADD CONTROLLER MODEL
|
|
|
+ let model = controllerModelFactory.createControllerModel( grip );
|
|
|
+ grip.add(model);
|
|
|
+ this.viewer.sceneVR.add( grip );
|
|
|
+
|
|
|
+ // ADD SPHERE
|
|
|
+ let sphere = new THREE.Mesh(sg, sm);
|
|
|
+ sphere.scale.set(0.005, 0.005, 0.005);
|
|
|
+ controller.add(sphere);
|
|
|
+ controller.visible = true;
|
|
|
+ this.viewer.sceneVR.add(controller);
|
|
|
+
|
|
|
+ { // ADD LINE
|
|
|
+
|
|
|
+ let lineGeometry = new LineGeometry();
|
|
|
+
|
|
|
+ lineGeometry.setPositions([
|
|
|
+ 0, 0, -0.15,
|
|
|
+ 0, 0, 0.05,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ let lineMaterial = new LineMaterial({
|
|
|
+ color: 0xff0000,
|
|
|
+ linewidth: 2,
|
|
|
+ resolution: new THREE.Vector2(1000, 1000),
|
|
|
+ });
|
|
|
+
|
|
|
+ const line = new Line2(lineGeometry, lineMaterial);
|
|
|
+
|
|
|
+ controller.add(line);
|
|
|
+ }
|
|
|
+
|
|
|
+ controller.addEventListener( 'connected', (event) => {
|
|
|
+ const xrInputSource = event.data;
|
|
|
+ controller.inputSource = xrInputSource;
|
|
|
+ this.initMenu(controller);
|
|
|
+ });
|
|
|
+
|
|
|
+ controller.addEventListener( 'selectstart', () => {this.onTriggerStart(controller)});
|
|
|
+ controller.addEventListener( 'selectend', () => {this.onTriggerEnd(controller)});
|
|
|
+
|
|
|
+ this.cSecondary = controller;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.mode_fly = new FlyMode();
|
|
|
+ this.mode_translate = new TranslationMode();
|
|
|
+ this.mode_rotScale = new RotScaleMode();
|
|
|
+ this.setMode(this.mode_fly);
|
|
|
+ }
|
|
|
+
|
|
|
+ createSlider(label, min, max){
|
|
|
+
|
|
|
+ let sg = new THREE.SphereGeometry(1, 8, 8);
|
|
|
+ let cg = new THREE.CylinderGeometry(1, 1, 1, 8);
|
|
|
+ let matHandle = new THREE.MeshBasicMaterial({color: 0xff0000});
|
|
|
+ let matScale = new THREE.MeshBasicMaterial({color: 0xff4444});
|
|
|
+ let matValue = new THREE.MeshNormalMaterial();
|
|
|
+
|
|
|
+ let node = new THREE.Object3D("slider");
|
|
|
+ let nLabel = new Potree.TextSprite(`${label}: 0`);
|
|
|
+ let nMax = new THREE.Mesh(sg, matHandle);
|
|
|
+ let nMin = new THREE.Mesh(sg, matHandle);
|
|
|
+ let nValue = new THREE.Mesh(sg, matValue);
|
|
|
+ let nScale = new THREE.Mesh(cg, matScale);
|
|
|
+
|
|
|
+ nLabel.scale.set(0.2, 0.2, 0.2);
|
|
|
+ nLabel.position.set(0, 0.35, 0);
|
|
|
+
|
|
|
+ nMax.scale.set(0.02, 0.02, 0.02);
|
|
|
+ nMax.position.set(0, 0.25, 0);
|
|
|
+
|
|
|
+ nMin.scale.set(0.02, 0.02, 0.02);
|
|
|
+ nMin.position.set(0, -0.25, 0);
|
|
|
+
|
|
|
+ nValue.scale.set(0.02, 0.02, 0.02);
|
|
|
+ nValue.position.set(0, 0, 0);
|
|
|
+
|
|
|
+ nScale.scale.set(0.005, 0.5, 0.005);
|
|
|
+
|
|
|
+ node.add(nLabel);
|
|
|
+ node.add(nMax);
|
|
|
+ node.add(nMin);
|
|
|
+ node.add(nValue);
|
|
|
+ node.add(nScale);
|
|
|
+
|
|
|
+ return node;
|
|
|
+ }
|
|
|
+
|
|
|
+ createInfo(){
|
|
|
+
|
|
|
+ let texture = new THREE.TextureLoader().load(`${Potree.resourcePath}/images/vr_controller_help.jpg`);
|
|
|
+ let plane = new THREE.PlaneBufferGeometry(1, 1, 1, 1);
|
|
|
+ let infoMaterial = new THREE.MeshBasicMaterial({map: texture});
|
|
|
+ let infoNode = new THREE.Mesh(plane, infoMaterial);
|
|
|
+
|
|
|
+ return infoNode;
|
|
|
+ }
|
|
|
+
|
|
|
+ initMenu(controller){
|
|
|
+
|
|
|
+ if(this.menu){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let node = new THREE.Object3D("vr menu");
|
|
|
+
|
|
|
+ // let nSlider = this.createSlider("speed", 0, 1);
|
|
|
+ // let nInfo = this.createInfo();
|
|
|
+
|
|
|
+ // // node.add(nSlider);
|
|
|
+ // node.add(nInfo);
|
|
|
+
|
|
|
+ // {
|
|
|
+ // node.rotation.set(-1.5, 0, 0)
|
|
|
+ // node.scale.set(0.3, 0.3, 0.3);
|
|
|
+ // node.position.set(-0.2, -0.002, -0.1)
|
|
|
+
|
|
|
+ // // nInfo.position.set(0.5, 0, 0);
|
|
|
+ // nInfo.scale.set(0.8, 0.6, 0);
|
|
|
+
|
|
|
+ // // controller.add(node);
|
|
|
+ // }
|
|
|
+
|
|
|
+ // node.position.set(-0.3, 1.2, 0.2);
|
|
|
+ // node.scale.set(0.3, 0.2, 0.3);
|
|
|
+ // node.lookAt(new THREE.Vector3(0, 1.5, 0.1));
|
|
|
+
|
|
|
+ // this.viewer.sceneVR.add(node);
|
|
|
+
|
|
|
+ this.menu = node;
|
|
|
+
|
|
|
+ // window.vrSlider = nSlider;
|
|
|
+ window.vrMenu = node;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ toScene(vec){
|
|
|
+ let camVR = this.getCamera();
|
|
|
+
|
|
|
+ let mat = camVR.matrixWorld;
|
|
|
+ let result = vec.clone().applyMatrix4(mat);
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ toVR(vec){
|
|
|
+ let camVR = this.getCamera();
|
|
|
+
|
|
|
+ let mat = camVR.matrixWorld.clone();
|
|
|
+ mat.invert();
|
|
|
+ let result = vec.clone().applyMatrix4(mat);
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ setMode(mode){
|
|
|
+
|
|
|
+ if(this.mode === mode){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(this.mode){
|
|
|
+ this.mode.end(this);
|
|
|
+ }
|
|
|
+
|
|
|
+ for(let controller of [this.cPrimary, this.cSecondary]){
|
|
|
+
|
|
|
+ let start = {
|
|
|
+ position: controller.position.clone(),
|
|
|
+ rotation: controller.rotation.clone(),
|
|
|
+ };
|
|
|
+
|
|
|
+ controller.start = start;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.mode = mode;
|
|
|
+ this.mode.start(this);
|
|
|
+ }
|
|
|
+
|
|
|
+ onTriggerStart(controller){
|
|
|
+ this.triggered.add(controller);
|
|
|
+
|
|
|
+ if(this.triggered.size === 0){
|
|
|
+ this.setMode(this.mode_fly);
|
|
|
+ }else if(this.triggered.size === 1){
|
|
|
+ this.setMode(this.mode_translate);
|
|
|
+ }else if(this.triggered.size === 2){
|
|
|
+ this.setMode(this.mode_rotScale);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onTriggerEnd(controller){
|
|
|
+ this.triggered.delete(controller);
|
|
|
+
|
|
|
+ if(this.triggered.size === 0){
|
|
|
+ this.setMode(this.mode_fly);
|
|
|
+ }else if(this.triggered.size === 1){
|
|
|
+ this.setMode(this.mode_translate);
|
|
|
+ }else if(this.triggered.size === 2){
|
|
|
+ this.setMode(this.mode_rotScale);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onStart(){
|
|
|
+
|
|
|
+ let position = this.viewer.scene.view.position.clone();
|
|
|
+ let direction = this.viewer.scene.view.direction;
|
|
|
+ direction.multiplyScalar(-1);
|
|
|
+
|
|
|
+ let target = position.clone().add(direction);
|
|
|
+ target.z = position.z;
|
|
|
+
|
|
|
+ let scale = this.viewer.getMoveSpeed();
|
|
|
+
|
|
|
+ this.node.position.copy(position);
|
|
|
+ this.node.lookAt(target);
|
|
|
+ this.node.scale.set(scale, scale, scale);
|
|
|
+ this.node.updateMatrix();
|
|
|
+ this.node.updateMatrixWorld();
|
|
|
+ }
|
|
|
+
|
|
|
+ onEnd(){
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ setScene(scene){
|
|
|
+ this.scene = scene;
|
|
|
+ }
|
|
|
+
|
|
|
+ getCamera(){
|
|
|
+ let reference = this.viewer.scene.getActiveCamera();
|
|
|
+ let camera = new THREE.PerspectiveCamera();
|
|
|
+
|
|
|
+ // let scale = this.node.scale.x;
|
|
|
+ let scale = this.viewer.getMoveSpeed();
|
|
|
+ //camera.near = 0.01 / scale;
|
|
|
+ camera.near = 0.1;
|
|
|
+ camera.far = 1000;
|
|
|
+ // camera.near = reference.near / scale;
|
|
|
+ // camera.far = reference.far / scale;
|
|
|
+ camera.up.set(0, 0, 1);
|
|
|
+ camera.lookAt(new THREE.Vector3(0, -1, 0));
|
|
|
+ camera.updateMatrix();
|
|
|
+ camera.updateMatrixWorld();
|
|
|
+
|
|
|
+ camera.position.copy(this.node.position);
|
|
|
+ camera.rotation.copy(this.node.rotation);
|
|
|
+ camera.scale.set(scale, scale, scale);
|
|
|
+ camera.updateMatrix();
|
|
|
+ camera.updateMatrixWorld();
|
|
|
+ camera.matrixAutoUpdate = false;
|
|
|
+ camera.parent = camera;
|
|
|
+
|
|
|
+ return camera;
|
|
|
+ }
|
|
|
+
|
|
|
+ update(delta){
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // if(this.mode === this.mode_fly){
|
|
|
+ // let ray = new THREE.Ray(origin, direction);
|
|
|
+
|
|
|
+ // for(let object of this.selectables){
|
|
|
+
|
|
|
+ // if(object.intersectsRay(ray)){
|
|
|
+ // object.onHit(ray);
|
|
|
+ // }
|
|
|
+
|
|
|
+ // }
|
|
|
+
|
|
|
+ // }
|
|
|
+
|
|
|
+ this.mode.update(this, delta);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+};
|