提交 3fcc3930 编写于 作者: E Eberhard Gräther

restructured TrackballCamera, final static moving version

上级 b71b063f
......@@ -9,6 +9,7 @@
* target: <THREE.Object3D>,
* radius: <float>,
* screen: { width : <float>, height : <float>, offsetLeft : <float>, offsetTop : <float> },
* zoomSpeed: <float>,
* panSpeed: <float>,
......@@ -16,307 +17,286 @@
* noZoom: <bool>,
* noPan: <bool>,
* keys: <Array>, // [ rotateKey, zoomKey, panKey ]
* keys: <Array>, // [ rotateKey, zoomKey, panKey ],
* domElement: <HTMLElement>,
* }
*/
// TODO: onWindowResize();
THREE.TrackballCamera = function ( parameters ) {
THREE.Camera.call( this, parameters.fov, parameters.aspect, parameters.near, parameters.far, parameters.target );
// target.position is modified when panning
this.radius = ( window.innerWidth + window.innerHeight ) / 4;
parameters = parameters || {};
this.zoomSpeed = 1.0;
this.panSpeed = 1.0;
THREE.Camera.call( this, parameters.fov, parameters.aspect, parameters.near, parameters.far, parameters.target );
this.noZoom = false;
this.noPan = false;
this.domElement = parameters.domElement || document;
this.keys = [ 65, 83, 68 ];
this.keyPressed = false;
this.screen = parameters.screen || { width : window.innerWidth, height : window.innerHeight, offsetLeft : 0, offsetTop : 0 };
this.radius = parameters.radius || ( this.screen.width + this.screen.height ) / 4;
this.domElement = document;
this.zoomSpeed = parameters.zoomSpeed || 1.5;
this.panSpeed = parameters.panSpeed || 0.3;
if ( parameters ) {
this.noZoom = parameters.noZoom || false;
this.noPan = parameters.noPan || false;
if ( parameters.radius !== undefined ) this.radius = parameters.radius;
this.keys = parameters.keys || [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
if ( parameters.zoomSpeed !== undefined ) this.zoomSpeed = parameters.zoomSpeed;
if ( parameters.panSpeed !== undefined ) this.panSpeed = parameters.panSpeed;
this.useTarget = true;
if ( parameters.noZoom !== undefined ) this.noZoom = parameters.noZoom;
if ( parameters.noPan !== undefined ) this.noPan = parameters.noPan;
if ( parameters.keys !== undefined ) this.keys = parameters.keys;
//internals
if ( parameters.domElement !== undefined ) this.domElement = parameters.domElement;
var _keyPressed = false,
}
_state = this.STATE.NONE,
this.useTarget = true;
_mouse = new THREE.Vector2(),
this.state = this.STATE.NONE;
this.screen = this.getScreenDimensions();
_start = new THREE.Vector3(),
_end = new THREE.Vector3();
this.mouse = new THREE.Vector2();
this.start = new THREE.Vector3();
this.end = new THREE.Vector3();
// methods
function bind( scope, fn ) {
this.handleEvent = function ( event ) {
return function () {
if ( typeof this[ event.type ] == 'function' ) {
fn.apply( scope, arguments );
this[ event.type ]( event );
};
}
};
this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
this.getMouseOnScreen = function( clientX, clientY ) {
this.domElement.addEventListener( 'mousemove', bind( this, this.mousemove ), false );
this.domElement.addEventListener( 'mousedown', bind( this, this.mousedown ), false );
this.domElement.addEventListener( 'mouseup', bind( this, this.mouseup ), false );
return new THREE.Vector2(
( clientX - this.screen.offsetLeft ) / this.radius * 0.5,
( clientY - this.screen.offsetTop ) / this.radius * 0.5
);
window.addEventListener( 'keydown', bind( this, this.keydown ), false );
window.addEventListener( 'keyup', bind( this, this.keyup ), false );
};
};
this.getMouseProjectionOnBall = function( clientX, clientY ) {
THREE.TrackballCamera.prototype = new THREE.Camera();
THREE.TrackballCamera.prototype.constructor = THREE.TrackballCamera;
THREE.TrackballCamera.prototype.supr = THREE.Camera.prototype;
var mouseOnBall = new THREE.Vector3(
( clientX - this.screen.width * 0.5 - this.screen.offsetLeft ) / this.radius,
( this.screen.height * 0.5 + this.screen.offsetTop - clientY ) / this.radius,
0.0
);
THREE.TrackballCamera.prototype.STATE = {
NONE : -1,
ROTATE : 0,
ZOOM : 1,
PAN : 2
};
var length = mouseOnBall.length();
if ( length > 1.0 ) {
THREE.TrackballCamera.prototype.handleEvent = function ( event ) {
mouseOnBall.normalize();
if ( typeof this[ event.type ] == 'function' ) {
} else {
this[ event.type ]( event );
mouseOnBall.z = Math.sqrt( 1.0 - length * length );
}
};
var projection = this.up.clone().setLength( mouseOnBall.y );
projection.addSelf( this.up.clone().crossSelf( this.position ).setLength( mouseOnBall.x ) );
projection.addSelf( this.position.clone().setLength( mouseOnBall.z ) );
THREE.TrackballCamera.prototype.keydown = function( event ) {
return projection;
if ( this.state !== this.STATE.NONE ) {
};
return;
this.rotateCamera = function( clientX, clientY ) {
} else if ( event.keyCode === this.keys[ this.STATE.ROTATE ] ) {
_end = this.getMouseProjectionOnBall( clientX, clientY );
this.state = this.STATE.ROTATE;
this.keyPressed = true;
var angle = Math.acos( _start.dot( _end ) / _start.length() / _end.length() );
} else if ( event.keyCode === this.keys[ this.STATE.ZOOM ] ) {
if ( angle ) {
this.state = this.STATE.ZOOM;
this.keyPressed = true;
var axis = (new THREE.Vector3()).cross( _end, _start ).normalize(),
quaternion = new THREE.Quaternion();
} else if ( event.keyCode === this.keys[ this.STATE.PAN ] ) {
quaternion.setFromAxisAngle( axis, angle );
quaternion.multiplyVector3( this.position );
quaternion.multiplyVector3( this.up );
this.state = this.STATE.PAN;
this.keyPressed = true;
// quaternion.setFromAxisAngle( axis, angle * -0.1 );
// quaternion.multiplyVector3( _start );
}
};
};
THREE.TrackballCamera.prototype.keyup = function( event ) {
this.zoomCamera = function( clientX, clientY ) {
if ( this.state !== this.STATE.NONE ) {
var newMouse = this.getMouseOnScreen( clientX, clientY ),
eye = this.position.clone().subSelf( this.target.position ),
factor = 1.0 + ( newMouse.y - _mouse.y ) * this.zoomSpeed;
this.state = this.STATE.NONE;
if ( factor > 0.0 ) {
}
this.position.add( this.target.position, eye.multiplyScalar( factor ) );
_mouse = newMouse;
};
}
THREE.TrackballCamera.prototype.mousedown = function(event) {
};
event.preventDefault();
event.stopPropagation();
this.panCamera = function( clientX, clientY ) {
if ( this.state === this.STATE.NONE ) {
var newMouse = this.getMouseOnScreen( clientX, clientY ),
mouseChange = newMouse.clone().subSelf( _mouse ),
factor = this.position.distanceTo( this.target.position ) * this.panSpeed;
this.state = event.button;
mouseChange.multiplyScalar( factor );
if ( this.state === this.STATE.ROTATE ) {
var pan = this.position.clone().crossSelf( this.up ).setLength( mouseChange.x );
pan.addSelf( this.up.clone().setLength( mouseChange.y ) );
this.start = this.getMouseProjectionOnBall( event.clientX, event.clientY );
this.position.addSelf( pan );
this.target.position.addSelf( pan );
} else {
_mouse = newMouse;
this.mouse = this.getMouseOnScreen( event.clientX, event.clientY );
};
}
// this.update = function( parentMatrixWorld, forceUpdate, camera ) {
//
// this.rotateCamera();
//
// this.supr.update.call( this, parentMatrixWorld, forceUpdate, camera );
//
// };
}
// listeners
};
function keydown( event ) {
THREE.TrackballCamera.prototype.mousemove = function( event ) {
if ( _state !== this.STATE.NONE ) {
if ( this.keyPressed ) {
return;
this.start = this.getMouseProjectionOnBall( event.clientX, event.clientY );
this.mouse = this.getMouseOnScreen( event.clientX, event.clientY );
} else if ( event.keyCode === this.keys[ this.STATE.ROTATE ] ) {
this.keyPressed = false;
_state = this.STATE.ROTATE;
_keyPressed = true;
}
} else if ( event.keyCode === this.keys[ this.STATE.ZOOM ] ) {
if ( this.state === this.STATE.NONE ) {
_state = this.STATE.ZOOM;
_keyPressed = true;
return;
} else if ( event.keyCode === this.keys[ this.STATE.PAN ] ) {
} else if ( this.state === this.STATE.ROTATE ) {
_state = this.STATE.PAN;
_keyPressed = true;
this.rotateCamera( event.clientX, event.clientY );
}
} else if ( this.state === this.STATE.ZOOM && !this.noZoom ) {
};
this.zoomCamera( event.clientX, event.clientY );
function keyup( event ) {
} else if ( this.state === this.STATE.PAN && !this.noPan ) {
if ( _state !== this.STATE.NONE ) {
this.panCamera( event.clientX, event.clientY );
_state = this.STATE.NONE;
}
};
};
THREE.TrackballCamera.prototype.mouseup = function( event ) {
function mousedown(event) {
event.preventDefault();
event.stopPropagation();
this.state = this.STATE.NONE;
};
if ( _state === this.STATE.NONE ) {
THREE.TrackballCamera.prototype.getScreenDimensions = function() {
_state = event.button;
if ( this.domElement != document ) {
if ( _state === this.STATE.ROTATE ) {
return {
width : this.domElement.offsetWidth,
height : this.domElement.offsetHeight,
offsetLeft : this.domElement.offsetLeft,
offsetTop : this.domElement.offsetTop
};
_start = this.getMouseProjectionOnBall( event.clientX, event.clientY );
} else {
return {
width : window.innerWidth,
height : window.innerHeight,
offsetLeft : 0,
offsetTop : 0
};
_mouse = this.getMouseOnScreen( event.clientX, event.clientY );
}
};
THREE.TrackballCamera.prototype.getMouseOnScreen = function( clientX, clientY ) {
return new THREE.Vector2(
( clientX - this.screen.offsetLeft ) / this.radius * 0.5,
( clientY - this.screen.offsetTop ) / this.radius * 0.5
);
};
THREE.TrackballCamera.prototype.getMouseProjectionOnBall = function( clientX, clientY ) {
var mouseOnBall = new THREE.Vector3(
( clientX - this.screen.width * 0.5 - this.screen.offsetLeft ) / this.radius,
( this.screen.height * 0.5 + this.screen.offsetTop - clientY ) / this.radius,
0.0
);
}
var length = mouseOnBall.length();
};
if ( length > 1.0 ) {
function mousemove( event ) {
mouseOnBall.normalize();
if ( _keyPressed ) {
} else {
_start = this.getMouseProjectionOnBall( event.clientX, event.clientY );
_mouse = this.getMouseOnScreen( event.clientX, event.clientY );
mouseOnBall.z = Math.sqrt( 1.0 - length * length );
_keyPressed = false;
}
var projection = this.up.clone().setLength( mouseOnBall.y );
projection.addSelf( this.up.clone().crossSelf( this.position ).setLength( mouseOnBall.x ) );
projection.addSelf( this.position.clone().setLength( mouseOnBall.z ) );
return projection;
if ( _state === this.STATE.NONE ) {
};
return;
THREE.TrackballCamera.prototype.rotateCamera = function( clientX, clientY ) {
} else if ( _state === this.STATE.ROTATE ) {
this.end = this.getMouseProjectionOnBall( clientX, clientY );
// _end = this.getMouseProjectionOnBall( event.clientX, event.clientY );
var angle = Math.acos( this.start.dot( this.end ) / this.start.length() / this.end.length() );
this.rotateCamera( event.clientX, event.clientY );
if ( angle ) {
} else if ( _state === this.STATE.ZOOM && !this.noZoom ) {
var axis = (new THREE.Vector3()).cross( this.end, this.start ).normalize(),
quaternion = new THREE.Quaternion();
this.zoomCamera( event.clientX, event.clientY );
quaternion.setFromAxisAngle( axis, angle );
} else if ( _state === this.STATE.PAN && !this.noPan ) {
quaternion.multiplyVector3( this.position );
quaternion.multiplyVector3( this.up );
this.panCamera( event.clientX, event.clientY );
}
};
};
THREE.TrackballCamera.prototype.zoomCamera = function( clientX, clientY ) {
function mouseup( event ) {
var newMouse = this.getMouseOnScreen( clientX, clientY ),
eye = this.position.clone().subSelf( this.target.position ),
factor = 1.0 + ( newMouse.y - this.mouse.y ) * this.zoomSpeed;
event.preventDefault();
event.stopPropagation();
if ( factor > 0.0 ) {
_state = this.STATE.NONE;
this.position.add( this.target.position, eye.multiplyScalar( factor ) );
this.mouse = newMouse;
};
}
function bind( scope, fn ) {
};
return function () {
THREE.TrackballCamera.prototype.panCamera = function( clientX, clientY ) {
fn.apply( scope, arguments );
var newMouse = this.getMouseOnScreen( clientX, clientY ),
mouseChange = newMouse.clone().subSelf(this.mouse),
factor = this.position.distanceTo( this.target.position ) * this.panSpeed;
};
mouseChange.multiplyScalar( factor );
};
var pan = this.position.clone().crossSelf( this.up ).setLength( mouseChange.x );
pan.addSelf( this.up.clone().setLength( mouseChange.y ) );
this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
this.position.addSelf( pan );
this.target.position.addSelf( pan );
this.domElement.addEventListener( 'mousemove', bind( this, mousemove ), false );
this.domElement.addEventListener( 'mousedown', bind( this, mousedown ), false );
this.domElement.addEventListener( 'mouseup', bind( this, mouseup ), false );
this.mouse = newMouse;
window.addEventListener( 'keydown', bind( this, keydown ), false );
window.addEventListener( 'keyup', bind( this, keyup ), false );
};
THREE.TrackballCamera.prototype = new THREE.Camera();
THREE.TrackballCamera.prototype.constructor = THREE.TrackballCamera;
THREE.TrackballCamera.prototype.supr = THREE.Camera.prototype;
THREE.TrackballCamera.prototype.STATE = { NONE : -1, ROTATE : 0, ZOOM : 1, PAN : 2 };
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册