|
|
@@ -11,6 +11,7 @@ var _DEFAULT_CAMERA = new THREE.PerspectiveCamera( 50, 1, 0.001, 1e10 );
|
|
|
_DEFAULT_CAMERA.name = 'Camera';
|
|
|
_DEFAULT_CAMERA.position.set( 0, 5, 10 );
|
|
|
_DEFAULT_CAMERA.lookAt( new THREE.Vector3() );
|
|
|
+const _ORTHOGRAPHIC_FRUSTUM_SIZE = 100;
|
|
|
|
|
|
function Editor() {
|
|
|
|
|
|
@@ -551,6 +552,68 @@ Editor.prototype = {
|
|
|
|
|
|
},
|
|
|
|
|
|
+ setCameraType: function ( type ) {
|
|
|
+
|
|
|
+ const oldCamera = this.camera;
|
|
|
+
|
|
|
+ const isOrthographic = oldCamera.isOrthographicCamera === true;
|
|
|
+
|
|
|
+ if ( ( type === 'orthographic' && isOrthographic ) || ( type === 'perspective' && ! isOrthographic ) ) return;
|
|
|
+
|
|
|
+ // the orbit point the framing should be preserved around
|
|
|
+
|
|
|
+ const center = this.controls ? this.controls.center : new THREE.Vector3();
|
|
|
+ const distance = oldCamera.position.distanceTo( center );
|
|
|
+
|
|
|
+ let newCamera;
|
|
|
+
|
|
|
+ if ( type === 'orthographic' ) {
|
|
|
+
|
|
|
+ const halfSize = _ORTHOGRAPHIC_FRUSTUM_SIZE / 2;
|
|
|
+ newCamera = new THREE.OrthographicCamera( - halfSize, halfSize, halfSize, - halfSize, 0, 10000 );
|
|
|
+ newCamera.position.copy( oldCamera.position );
|
|
|
+ newCamera.quaternion.copy( oldCamera.quaternion );
|
|
|
+
|
|
|
+ // derive the zoom so the orthographic framing matches the perspective view at the orbit center
|
|
|
+
|
|
|
+ const halfFOV = THREE.MathUtils.DEG2RAD * oldCamera.fov / 2;
|
|
|
+ newCamera.zoom = ( newCamera.top - newCamera.bottom ) / ( 2 * Math.max( distance, 0.0001 ) * Math.tan( halfFOV ) );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ newCamera = new THREE.PerspectiveCamera( 50, 1, 0.001, 1e10 );
|
|
|
+ newCamera.quaternion.copy( oldCamera.quaternion );
|
|
|
+
|
|
|
+ // reposition along the view direction so the perspective framing matches the orthographic view
|
|
|
+
|
|
|
+ const halfFOV = THREE.MathUtils.DEG2RAD * newCamera.fov / 2;
|
|
|
+ const targetDistance = ( oldCamera.top - oldCamera.bottom ) / ( 2 * oldCamera.zoom * Math.tan( halfFOV ) );
|
|
|
+
|
|
|
+ const offset = new THREE.Vector3().subVectors( oldCamera.position, center );
|
|
|
+ if ( offset.lengthSq() === 0 ) offset.set( 0, 0, 1 ).applyQuaternion( oldCamera.quaternion );
|
|
|
+ offset.normalize().multiplyScalar( targetDistance );
|
|
|
+
|
|
|
+ newCamera.position.copy( center ).add( offset );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ newCamera.name = oldCamera.name;
|
|
|
+ newCamera.uuid = oldCamera.uuid;
|
|
|
+ newCamera.updateProjectionMatrix();
|
|
|
+
|
|
|
+ this.camera = newCamera;
|
|
|
+ this.cameras[ newCamera.uuid ] = newCamera;
|
|
|
+
|
|
|
+ if ( this.viewportCamera === oldCamera ) this.viewportCamera = newCamera;
|
|
|
+
|
|
|
+ this.signals.cameraResetted.dispatch();
|
|
|
+
|
|
|
+ // keep the selection (and thus the sidebar) in sync with the new camera instance
|
|
|
+
|
|
|
+ if ( this.selected === oldCamera ) this.select( newCamera );
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
setViewportCamera: function ( uuid ) {
|
|
|
|
|
|
this.viewportCamera = this.cameras[ uuid ] || this.camera;
|
|
|
@@ -629,6 +692,7 @@ Editor.prototype = {
|
|
|
this.history.clear();
|
|
|
this.storage.clear();
|
|
|
|
|
|
+ this.setCameraType( 'perspective' );
|
|
|
this.camera.copy( _DEFAULT_CAMERA );
|
|
|
this.signals.cameraResetted.dispatch();
|
|
|
|
|
|
@@ -676,6 +740,8 @@ Editor.prototype = {
|
|
|
var loader = new THREE.ObjectLoader();
|
|
|
var camera = await loader.parseAsync( json.camera );
|
|
|
|
|
|
+ this.setCameraType( camera.isOrthographicCamera ? 'orthographic' : 'perspective' );
|
|
|
+
|
|
|
const existingUuid = this.camera.uuid;
|
|
|
const incomingUuid = camera.uuid;
|
|
|
|