import * as THREE from "../../libs/three.js/build/three.module.js"; import {transitions, easing, lerp} from '../utils/transitions.js' import Common from '../utils/Common' export class View{ constructor () { this.position = new THREE.Vector3(0, 0, 0); this.yaw = 0//Math.PI / 4; // = 4dkk lon + 90 this._pitch = 0//-Math.PI / 4; //上下旋转 = 4dkk lat this.radius = 1; this.maxPitch = Math.PI / 2; this.minPitch = -Math.PI / 2; this.zoom = 1 } applyToCamera(camera){//add camera.position.copy(this.position); camera.rotation.order = "ZXY"; camera.rotation.x = Math.PI / 2 + this.pitch; camera.rotation.z = this.yaw; camera.updateMatrix(); camera.updateMatrixWorld(); camera.matrixWorldInverse.copy(camera.matrixWorld).invert(); } copy(a){ Common.CopyClassObject(this, a) } clone () { /* let c = new View(); c.yaw = this.yaw; c._pitch = this.pitch; c.radius = this.radius; c.maxPitch = this.maxPitch; c.minPitch = this.minPitch; return c; */ return Common.CloneClassObject(this) } get pitch () { return this._pitch; } set pitch (angle) { this._pitch = Math.max(Math.min(angle, this.maxPitch), this.minPitch); } get direction () { let dir = new THREE.Vector3(0, 1, 0); dir.applyAxisAngle(new THREE.Vector3(1, 0, 0), this.pitch); dir.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw); return dir; } set direction (dir) { //if(dir.x === dir.y){ if(dir.x === 0 && dir.y === 0){ this.pitch = Math.PI / 2 * Math.sign(dir.z); }else{ let yaw = Math.atan2(dir.y, dir.x) - Math.PI / 2; let pitch = Math.atan2(dir.z, Math.sqrt(dir.x * dir.x + dir.y * dir.y)); this.yaw = yaw; this.pitch = pitch; } } lookAt(t){ let V; if(arguments.length === 1){ V = new THREE.Vector3().subVectors(t, this.position); }else if(arguments.length === 3){ V = new THREE.Vector3().subVectors(new THREE.Vector3(...arguments), this.position); } let radius = V.length(); let dir = V.normalize(); this.radius = radius; this.direction = dir; } getPivot () { return new THREE.Vector3().addVectors(this.position, this.direction.multiplyScalar(this.radius)); } getSide () { let side = new THREE.Vector3(1, 0, 0); side.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw); return side; } pan (x, y) { let dir = new THREE.Vector3(0, 1, 0); dir.applyAxisAngle(new THREE.Vector3(1, 0, 0), this.pitch); dir.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw); // let side = new THREE.Vector3(1, 0, 0); // side.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw); let side = this.getSide(); let up = side.clone().cross(dir); let pan = side.multiplyScalar(x).add(up.multiplyScalar(y)); this.position = this.position.add(pan); // this.target = this.target.add(pan); } translate (x, y, z) { let dir = new THREE.Vector3(0, 1, 0); dir.applyAxisAngle(new THREE.Vector3(1, 0, 0), this.pitch); dir.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw); let side = new THREE.Vector3(1, 0, 0); side.applyAxisAngle(new THREE.Vector3(0, 0, 1), this.yaw); let up = side.clone().cross(dir); let t = side.multiplyScalar(x) .add(dir.multiplyScalar(y)) .add(up.multiplyScalar(z)); this.position = this.position.add(t); this.restrictPos() } translateWorld (x, y, z) { this.position.x += x; this.position.y += y; this.position.z += z; this.restrictPos() } /* setView(position, target, duration = 0, callback = null, onUpdate = null, Easing=''){ let endPosition = null; if(position instanceof Array){ endPosition = new THREE.Vector3(...position); }else if(position.x != null){ endPosition = position.clone(); } let endTarget = null; if(target instanceof Array){ endTarget = new THREE.Vector3(...target); }else if(target.x != null){ endTarget = target.clone(); } const startPosition = this.position.clone(); const startTarget = this.getPivot(); //const endPosition = position.clone(); //const endTarget = target.clone(); let easing = Easing ? TWEEN.Easing.Quartic[Easing] : TWEEN.Easing.Quartic.Out ; if(duration === 0){ this.position.copy(endPosition); this.lookAt(endTarget); }else{ let value = {x: 0}; let tween = new TWEEN.Tween(value).to({x: 1}, duration); tween.easing(easing); //this.tweens.push(tween); tween.onUpdate(() => { let t = value.x; //console.log(t); const pos = new THREE.Vector3( (1 - t) * startPosition.x + t * endPosition.x, (1 - t) * startPosition.y + t * endPosition.y, (1 - t) * startPosition.z + t * endPosition.z, ); const target = new THREE.Vector3( (1 - t) * startTarget.x + t * endTarget.x, (1 - t) * startTarget.y + t * endTarget.y, (1 - t) * startTarget.z + t * endTarget.z, ); this.position.copy(pos); this.lookAt(target); onUpdate && onUpdate(t)//add }); tween.start(); tween.onComplete(() => { if(callback){ callback(); } }); } } */ restrictPos(){//add if(this.limitBound){ this.position.clamp(this.limitBound.min, this.limitBound.max) } } setCubeView(dir) { switch(dir) { case "Front": this.yaw = 0; this.pitch = 0; break; case "Back": this.yaw = Math.PI; this.pitch = 0; break; case "Left": this.yaw = -Math.PI / 2; this.pitch = 0; break; case "Right": this.yaw = Math.PI / 2; this.pitch = 0; break; case "Top": this.yaw = 0; this.pitch = -Math.PI / 2; break; case "Bottom": this.yaw = -Math.PI; this.pitch = Math.PI / 2; break; } } setView(position, target, duration = 0, callback = null, onUpdate = null, Easing=''){ //待改成quater渐变 let endPosition = null; /* if(position instanceof Array){ endPosition = new THREE.Vector3(...position); }else */if(position.x != null){ endPosition = new THREE.Vector3().copy(position) } let endTarget = null; /* if(target instanceof Array){ endTarget = new THREE.Vector3(...target); }else */if(target && target.x != null){ endTarget = new THREE.Vector3().copy(target) } const startPosition = this.position.clone(); const startTarget = this.getPivot(); if(duration === 0){ this.position.copy(endPosition); this.restrictPos() endTarget && this.lookAt(endTarget); onUpdate && onUpdate(1) callback && callback() }else{ transitions.start(lerp.vector(this.position, endPosition, (pos, progress)=>{ let t = progress //console.log(t); if(endTarget){ const target = new THREE.Vector3( (1 - t) * startTarget.x + t * endTarget.x, (1 - t) * startTarget.y + t * endTarget.y, (1 - t) * startTarget.z + t * endTarget.z, ); this.lookAt(target); } this.restrictPos() onUpdate && onUpdate(t)//add }), duration, callback, 0, Easing ? easing[Easing] : easing.easeInOutQuad ); } } };