FirstPersonControls class
class FirstPersonControls { THREE.Object3D object; Vector3 target = new Vector3.zero(); Element domElement; num movementSpeed = 1.0; num lookSpeed = 0.005; bool lookVertical = true; bool autoForward = false; // bool invertVertical = false; bool activeLook = true; bool heightSpeed = false; num heightCoef = 1.0; num heightMin = 0.0; num heightMax = 1.0; bool constrainVertical = false; num verticalMin = 0; num verticalMax = Math.PI; num autoSpeedFactor = 0.0; num mouseX = 0; num mouseY = 0; num lat = 0; num lon = 0; num phi = 0; num theta = 0; bool moveForward = false; bool moveBackward = false; bool moveLeft = false; bool moveRight = false; bool moveUp = false; bool moveDown = false; bool freeze = false; bool mouseDragOn = false; num viewHalfX = 0; num viewHalfY = 0; FirstPersonControls(this.object, [Element domElement]) { this.domElement = (domElement != null) ? domElement : document.body; if ( this.domElement != document.body ) { this.domElement.tabIndex = -1; } this.domElement.onContextMenu.listen((event) => event.preventDefault()); this.domElement.onMouseMove.listen(this.onMouseMove); this.domElement.onMouseDown.listen(this.onMouseDown); this.domElement.onMouseUp.listen(this.onMouseUp); this.domElement.onKeyDown.listen(this.onKeyDown); this.domElement.onKeyUp.listen(this.onKeyUp); this.handleResize(); } void handleResize() { if ( this.domElement == document.body ) { this.viewHalfX = window.innerWidth / 2; this.viewHalfY = window.innerHeight / 2; } else { this.viewHalfX = this.domElement.offsetWidth / 2; this.viewHalfY = this.domElement.offsetHeight / 2; } } void onMouseDown(event) { if ( this.domElement != document.body ) { this.domElement.focus(); } event.preventDefault(); event.stopPropagation(); if ( this.activeLook ) { switch ( event.button ) { case 0: this.moveForward = true; break; case 2: this.moveBackward = true; break; } } this.mouseDragOn = true; } void onMouseUp(event) { event.preventDefault(); event.stopPropagation(); if ( this.activeLook ) { switch ( event.button ) { case 0: this.moveForward = false; break; case 2: this.moveBackward = false; break; } } this.mouseDragOn = false; } void onMouseMove(event) { if ( this.domElement == document.body ) { this.mouseX = event.page.x - this.viewHalfX; this.mouseY = event.page.y - this.viewHalfY; } else { this.mouseX = event.page.x - this.domElement.offsetLeft - this.viewHalfX; this.mouseY = event.page.y - this.domElement.offsetTop - this.viewHalfY; } } void onKeyDown(event) { //event.preventDefault(); switch ( event.keyCode ) { case 38: /*up*/ case 87: /*W*/ this.moveForward = true; break; case 37: /*left*/ case 65: /*A*/ this.moveLeft = true; break; case 40: /*down*/ case 83: /*S*/ this.moveBackward = true; break; case 39: /*right*/ case 68: /*D*/ this.moveRight = true; break; case 82: /*R*/ this.moveUp = true; break; case 70: /*F*/ this.moveDown = true; break; case 81: /*Q*/ this.freeze = !this.freeze; break; } } void onKeyUp(event) { switch( event.keyCode ) { case 38: /*up*/ case 87: /*W*/ this.moveForward = false; break; case 37: /*left*/ case 65: /*A*/ this.moveLeft = false; break; case 40: /*down*/ case 83: /*S*/ this.moveBackward = false; break; case 39: /*right*/ case 68: /*D*/ this.moveRight = false; break; case 82: /*R*/ this.moveUp = false; break; case 70: /*F*/ this.moveDown = false; break; } } void update(delta) { var actualMoveSpeed = 0; var actualLookSpeed = 0; if ( this.freeze ) { return; } else { if ( this.heightSpeed ) { var y = THREEMath.clamp( this.object.position.y, this.heightMin, this.heightMax ); var heightDelta = y - this.heightMin; this.autoSpeedFactor = delta * ( heightDelta * this.heightCoef ); } else { this.autoSpeedFactor = 0.0; } actualMoveSpeed = delta * this.movementSpeed; if ( this.moveForward || ( this.autoForward && !this.moveBackward ) ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) ); if ( this.moveBackward ) this.object.translateZ( actualMoveSpeed ); if ( this.moveLeft ) this.object.translateX( - actualMoveSpeed ); if ( this.moveRight ) this.object.translateX( actualMoveSpeed ); if ( this.moveUp ) this.object.translateY( actualMoveSpeed ); if ( this.moveDown ) this.object.translateY( - actualMoveSpeed ); var actualLookSpeed = delta * this.lookSpeed; if ( !this.activeLook ) { actualLookSpeed = 0; } this.lon += this.mouseX * actualLookSpeed; if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed; // * this.invertVertical?-1:1; this.lat = Math.max( - 85, Math.min( 85, this.lat ) ); this.phi = ( 90 - this.lat ) * Math.PI / 180; this.theta = this.lon * Math.PI / 180; var targetPosition = this.target, position = this.object.position; targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta ); targetPosition.y = position.y + 100 * Math.cos( this.phi ); targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta ); } var verticalLookRatio = 1; if ( this.constrainVertical ) { verticalLookRatio = Math.PI / ( this.verticalMax - this.verticalMin ); } this.lon += this.mouseX * actualLookSpeed; if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio; this.lat = Math.max( - 85, Math.min( 85, this.lat ) ); this.phi = ( 90 - this.lat ) * Math.PI / 180; this.theta = this.lon * Math.PI / 180; if ( this.constrainVertical ) { this.phi = THREEMath.mapLinear( this.phi, 0, Math.PI, this.verticalMin, this.verticalMax ); } var targetPosition = this.target, position = this.object.position; targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta ); targetPosition.y = position.y + 100 * Math.cos( this.phi ); targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta ); this.object.lookAt( targetPosition ); } }
Constructors
new FirstPersonControls(Object3D object, [Element domElement]) #
Creates a new Object instance.
Object instances have no meaningful state, and are only useful through their identity. An Object instance is equal to itself only.
docs inherited from Object
FirstPersonControls(this.object, [Element domElement]) { this.domElement = (domElement != null) ? domElement : document.body; if ( this.domElement != document.body ) { this.domElement.tabIndex = -1; } this.domElement.onContextMenu.listen((event) => event.preventDefault()); this.domElement.onMouseMove.listen(this.onMouseMove); this.domElement.onMouseDown.listen(this.onMouseDown); this.domElement.onMouseUp.listen(this.onMouseUp); this.domElement.onKeyDown.listen(this.onKeyDown); this.domElement.onKeyUp.listen(this.onKeyUp); this.handleResize(); }
Properties
Methods
void handleResize() #
void handleResize() { if ( this.domElement == document.body ) { this.viewHalfX = window.innerWidth / 2; this.viewHalfY = window.innerHeight / 2; } else { this.viewHalfX = this.domElement.offsetWidth / 2; this.viewHalfY = this.domElement.offsetHeight / 2; } }
void onKeyDown(event) #
void onKeyDown(event) { //event.preventDefault(); switch ( event.keyCode ) { case 38: /*up*/ case 87: /*W*/ this.moveForward = true; break; case 37: /*left*/ case 65: /*A*/ this.moveLeft = true; break; case 40: /*down*/ case 83: /*S*/ this.moveBackward = true; break; case 39: /*right*/ case 68: /*D*/ this.moveRight = true; break; case 82: /*R*/ this.moveUp = true; break; case 70: /*F*/ this.moveDown = true; break; case 81: /*Q*/ this.freeze = !this.freeze; break; } }
void onKeyUp(event) #
void onKeyUp(event) { switch( event.keyCode ) { case 38: /*up*/ case 87: /*W*/ this.moveForward = false; break; case 37: /*left*/ case 65: /*A*/ this.moveLeft = false; break; case 40: /*down*/ case 83: /*S*/ this.moveBackward = false; break; case 39: /*right*/ case 68: /*D*/ this.moveRight = false; break; case 82: /*R*/ this.moveUp = false; break; case 70: /*F*/ this.moveDown = false; break; } }
void onMouseDown(event) #
void onMouseDown(event) { if ( this.domElement != document.body ) { this.domElement.focus(); } event.preventDefault(); event.stopPropagation(); if ( this.activeLook ) { switch ( event.button ) { case 0: this.moveForward = true; break; case 2: this.moveBackward = true; break; } } this.mouseDragOn = true; }
void onMouseMove(event) #
void onMouseMove(event) { if ( this.domElement == document.body ) { this.mouseX = event.page.x - this.viewHalfX; this.mouseY = event.page.y - this.viewHalfY; } else { this.mouseX = event.page.x - this.domElement.offsetLeft - this.viewHalfX; this.mouseY = event.page.y - this.domElement.offsetTop - this.viewHalfY; } }
void onMouseUp(event) #
void onMouseUp(event) { event.preventDefault(); event.stopPropagation(); if ( this.activeLook ) { switch ( event.button ) { case 0: this.moveForward = false; break; case 2: this.moveBackward = false; break; } } this.mouseDragOn = false; }
void update(delta) #
void update(delta) { var actualMoveSpeed = 0; var actualLookSpeed = 0; if ( this.freeze ) { return; } else { if ( this.heightSpeed ) { var y = THREEMath.clamp( this.object.position.y, this.heightMin, this.heightMax ); var heightDelta = y - this.heightMin; this.autoSpeedFactor = delta * ( heightDelta * this.heightCoef ); } else { this.autoSpeedFactor = 0.0; } actualMoveSpeed = delta * this.movementSpeed; if ( this.moveForward || ( this.autoForward && !this.moveBackward ) ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) ); if ( this.moveBackward ) this.object.translateZ( actualMoveSpeed ); if ( this.moveLeft ) this.object.translateX( - actualMoveSpeed ); if ( this.moveRight ) this.object.translateX( actualMoveSpeed ); if ( this.moveUp ) this.object.translateY( actualMoveSpeed ); if ( this.moveDown ) this.object.translateY( - actualMoveSpeed ); var actualLookSpeed = delta * this.lookSpeed; if ( !this.activeLook ) { actualLookSpeed = 0; } this.lon += this.mouseX * actualLookSpeed; if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed; // * this.invertVertical?-1:1; this.lat = Math.max( - 85, Math.min( 85, this.lat ) ); this.phi = ( 90 - this.lat ) * Math.PI / 180; this.theta = this.lon * Math.PI / 180; var targetPosition = this.target, position = this.object.position; targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta ); targetPosition.y = position.y + 100 * Math.cos( this.phi ); targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta ); } var verticalLookRatio = 1; if ( this.constrainVertical ) { verticalLookRatio = Math.PI / ( this.verticalMax - this.verticalMin ); } this.lon += this.mouseX * actualLookSpeed; if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio; this.lat = Math.max( - 85, Math.min( 85, this.lat ) ); this.phi = ( 90 - this.lat ) * Math.PI / 180; this.theta = this.lon * Math.PI / 180; if ( this.constrainVertical ) { this.phi = THREEMath.mapLinear( this.phi, 0, Math.PI, this.verticalMin, this.verticalMax ); } var targetPosition = this.target, position = this.object.position; targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta ); targetPosition.y = position.y + 100 * Math.cos( this.phi ); targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta ); this.object.lookAt( targetPosition ); }