Last active
October 30, 2016 18:56
-
-
Save mathdoodle/a6f87439affbaa7d2edc68e81b8a1cc0 to your computer and use it in GitHub Desktop.
three.js textures
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export interface Renderer { | |
setSize: (width: number, height: number) => any; | |
} | |
export interface Camera { | |
aspect: number; | |
updateProjectionMatrix: () => any; | |
} | |
/** | |
* Update renderer and camera when the window is resized | |
* | |
* renderer -- the renderer to update | |
* camera -- the camera to update | |
*/ | |
export default function bindResize(renderer: Renderer, camera: Camera) { | |
/** | |
* | |
*/ | |
const listener = function() { | |
// Notify the renderer of the size change. | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
// Update the camera. | |
camera.aspect = window.innerWidth / window.innerHeight; | |
camera.updateProjectionMatrix(); | |
} | |
const useCapture = false; | |
window.addEventListener('resize', listener, useCapture); | |
// return .stop() the function to stop watching window resize | |
return { | |
/** | |
* Stop watching window resize | |
*/ | |
stop : function(){ | |
window.removeEventListener('resize', listener, useCapture); | |
} | |
}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @author alteredq / http://alteredqualia.com/ | |
* @author mr.doob / http://mrdoob.com/ | |
*/ | |
const Detector = { | |
canvas: !! window['CanvasRenderingContext2D'], | |
webgl: ( function () { try { return !! window['WebGLRenderingContext'] && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(), | |
workers: !! window['Worker'], | |
fileapi: window['File'] && window['FileReader'] && window['FileList'] && window['Blob'], | |
getWebGLErrorMessage: function () { | |
var element = document.createElement( 'div' ); | |
element.id = 'webgl-error-message'; | |
element.style.fontFamily = 'monospace'; | |
element.style.fontSize = '13px'; | |
element.style.fontWeight = 'normal'; | |
element.style.textAlign = 'center'; | |
element.style.background = '#fff'; | |
element.style.color = '#000'; | |
element.style.padding = '1.5em'; | |
element.style.width = '400px'; | |
element.style.margin = '5em auto 0'; | |
if ( ! this.webgl ) { | |
element.innerHTML = window['WebGLRenderingContext'] ? [ | |
'Your graphics card does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#000">WebGL</a>.<br />', | |
'Find out how to get it <a href="http://get.webgl.org/" style="color:#000">here</a>.' | |
].join( '\n' ) : [ | |
'Your browser does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#000">WebGL</a>.<br/>', | |
'Find out how to get it <a href="http://get.webgl.org/" style="color:#000">here</a>.' | |
].join( '\n' ); | |
} | |
return element; | |
}, | |
addGetWebGLMessage: function ( parameters ) { | |
var parent, id, element; | |
parameters = parameters || {}; | |
parent = parameters.parent !== undefined ? parameters.parent : document.body; | |
id = parameters.id !== undefined ? parameters.id : 'oldie'; | |
element = Detector.getWebGLErrorMessage(); | |
element.id = id; | |
parent.appendChild( element ); | |
} | |
}; | |
export default Detector; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This THREEx helper makes it easy to handle the fullscreen API | |
// * it hides the prefix for each browser | |
// * it hides the little discrepencies of the various vendor API | |
// * at the time of this writing (nov 2011) it is available in | |
// [firefox nightly](http://blog.pearce.org.nz/2011/11/firefoxs-html-full-screen-api-enabled.html), | |
// [webkit nightly](http://peter.sh/2011/01/javascript-full-screen-api-navigation-timing-and-repeating-css-gradients/) and | |
// [chrome stable](http://updates.html5rocks.com/2011/10/Let-Your-Content-Do-the-Talking-Fullscreen-API). | |
// internal constants to know which fullscreen API implementation is available | |
function cancelFullScreen(el) { | |
var requestMethod = el.cancelFullScreen || el.webkitCancelFullScreen || el.mozCancelFullScreen || el.exitFullscreen; | |
if (requestMethod) { // cancel full screen. | |
requestMethod.call(el); | |
} | |
else if (typeof window['ActiveXObject'] !== "undefined") { // Older IE. | |
var wscript = new ActiveXObject("WScript.Shell"); | |
if (wscript !== null) { | |
wscript.SendKeys("{F11}"); | |
} | |
} | |
} | |
function requestFullScreen(el) { | |
// Supports most browsers and their versions. | |
var requestMethod = el.requestFullScreen || el.webkitRequestFullScreen(el.ALLOW_KEYBOARD_INPUT) || el.mozRequestFullScreen || el.msRequestFullScreen; | |
if (requestMethod) { // Native full screen. | |
requestMethod.call(el); | |
} | |
else if (typeof window['ActiveXObject'] !== "undefined") { // Older IE. | |
var wscript = new ActiveXObject("WScript.Shell"); | |
if (wscript !== null) { | |
wscript.SendKeys("{F11}"); | |
} | |
} | |
return false | |
} | |
function toggleFull() { | |
var elem = document.body; // Make the body go full screen. | |
var isInFullScreen = (document['fullScreenElement'] && document['fullScreenElement'] !== null) || (document['mozFullScreen'] || document['webkitIsFullScreen']); | |
if (isInFullScreen) { | |
cancelFullScreen(document); | |
} else { | |
requestFullScreen(elem); | |
} | |
return false; | |
} | |
const hasWebkitFullScreen = 'webkitCancelFullScreen' in document ? true : false; | |
// console.log(`hasWebkitFullScreen => ${hasWebkitFullScreen}`); | |
const hasMozFullScreen = 'mozCancelFullScreen' in document ? true : false; | |
// console.log(`hasMozFullScreen => ${hasMozFullScreen}`); | |
const FullScreen = { | |
/** | |
* test if it is possible to have fullscreen | |
* | |
* @returns {Boolean} true if fullscreen API is available, false otherwise | |
*/ | |
available: function() { | |
return hasWebkitFullScreen || hasMozFullScreen; | |
}, | |
/** | |
* test if fullscreen is currently activated | |
* | |
* @returns {Boolean} true if fullscreen is currently activated, false otherwise | |
*/ | |
activated: function(): boolean { | |
if( hasWebkitFullScreen ) { | |
return document['webkitIsFullScreen']; | |
} | |
else if( hasMozFullScreen ) { | |
return document['mozFullScreen']; | |
} | |
else { | |
console.assert(false); | |
} | |
}, | |
/** | |
* Request fullscreen on a given element | |
* @param {DomElement} element to make fullscreen. optional. default to document.body | |
*/ | |
request: function(element: HTMLElement) { | |
element = element || document.body; | |
if( hasWebkitFullScreen ) { | |
element['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']); | |
} | |
else if( this._hasMozFullScreen ) { | |
element['mozRequestFullScreen'](); | |
} | |
else { | |
console.assert(false); | |
} | |
}, | |
/** | |
* Cancel fullscreen | |
*/ | |
cancel: function() { | |
if( hasWebkitFullScreen ) { | |
document['webkitCancelFullScreen'](); | |
} | |
else if( this._hasMozFullScreen ) { | |
document['mozCancelFullScreen'](); | |
} | |
else { | |
console.assert(false); | |
} | |
}, | |
/** | |
* Bind a key to renderer screenshot | |
* usage: THREEx.FullScreen.bindKey({ charCode : 'a'.charCodeAt(0) }); | |
*/ | |
bindKey: function(opts){ | |
opts = opts || {}; | |
var charCode = opts.charCode || 'f'.charCodeAt(0); | |
var dblclick = opts.dblclick !== undefined ? opts.dblclick : false; | |
var element = opts.element | |
var toggle = function() { | |
console.log("toggle") | |
if( FullScreen.activated() ) { | |
FullScreen.cancel(); | |
} | |
else { | |
FullScreen.request(element); | |
} | |
} | |
var onKeyPress = function(event){ | |
if( event.which !== charCode ) return; | |
toggle(); | |
}.bind(this); | |
document.addEventListener('keypress', onKeyPress, false); | |
dblclick && document.addEventListener('dblclick', toggle, false); | |
return { | |
unbind : function(){ | |
document.removeEventListener('keypress', onKeyPress, false); | |
dblclick && document.removeEventListener('dblclick', toggle, false); | |
} | |
}; | |
} | |
}; | |
export default FullScreen; | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<style> | |
/* STYLE-MARKER */ | |
</style> | |
<!-- SCRIPTS-MARKER --> | |
<script src="https://jspm.io/system.js"></script> | |
</head> | |
<body> | |
<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div> | |
<script> | |
// CODE-MARKER | |
</script> | |
<script>System.import('./index.js')</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Detector from './Detector'; | |
import FullScreen from './FullScreen'; | |
import KeyboardState from './KeyboardState'; | |
import OrbitControls from './OrbitControls'; | |
import bindResize from './bindResize'; | |
let scene: THREE.Scene; | |
let camera: THREE.PerspectiveCamera; | |
let renderer: THREE.WebGLRenderer; | |
let container: HTMLElement; | |
let stats: Stats; | |
let controls: OrbitControls; | |
const keyboard = new KeyboardState(); | |
DomReady.ready(function() { | |
init(); | |
animate(); | |
}); | |
function init() | |
{ | |
scene = new THREE.Scene(); | |
const SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight; | |
const VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000; | |
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR); | |
scene.add(camera); | |
camera.position.set(0,150,400); | |
camera.lookAt(scene.position); | |
if (Detector.webgl) { | |
renderer = new THREE.WebGLRenderer( {antialias:true} ); | |
} | |
else { | |
throw new Error("WeBGL is not supported"); | |
} | |
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT); | |
container = document.getElementById( 'ThreeJS' ); | |
container.appendChild( renderer.domElement ); | |
bindResize(renderer, camera); | |
FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) }); | |
controls = new OrbitControls( camera, renderer.domElement ); | |
stats = new Stats(); | |
stats.domElement.style.position = 'absolute'; | |
stats.domElement.style.left = '0px'; | |
stats.domElement.style.top = '0px'; | |
stats.domElement.style.zIndex = '100'; | |
container.appendChild( stats.domElement ); | |
const light = new THREE.PointLight(0xffffff); | |
light.position.set(100,250,100); | |
scene.add(light); | |
const loader = new THREE.TextureLoader(); | |
loader.load('img/textures/checkerboard.jpg', | |
function (texture: THREE.Texture) { | |
texture.wrapS = THREE.RepeatWrapping | |
texture.wrapT = THREE.RepeatWrapping | |
texture.repeat.set(2, 2); | |
texture.flipY = false | |
const floorMaterial = new THREE.MeshBasicMaterial({map: texture, side: THREE.DoubleSide}); | |
const floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10); | |
const floor = new THREE.Mesh(floorGeometry, floorMaterial); | |
floor.position.y = -0.5; | |
floor.rotation.x = Math.PI / 2; | |
scene.add(floor); | |
}, | |
function(progress) { | |
// console.log((progress.loaded / progress.total * 100) + '% loaded' ); | |
}, | |
function(e) { | |
console.log( `An error happened ${JSON.stringify(e)}` ); | |
} | |
); | |
const skyBoxGeometry = new THREE.CubeGeometry(10000, 10000, 10000 ); | |
const side: THREE.Side = THREE.BackSide | |
const skyBoxMaterial: THREE.MeshBasicMaterial = new THREE.MeshBasicMaterial({color: 0x9999ff, side: THREE.BackSide}); | |
skyBoxMaterial.color = new THREE.Color(0x9999ff); | |
const skyBox = new THREE.Mesh( skyBoxGeometry, skyBoxMaterial ); | |
scene.add(skyBox); | |
loader.load('img/textures/earth-day.jpg', function(texture) { | |
const geometry = new THREE.SphereGeometry(60, 32, 16); | |
const material = new THREE.MeshLambertMaterial(); | |
const mesh = new THREE.Mesh(geometry, material); | |
mesh.position.set(0, 40, 0); | |
// Apparently, we don't need to set needsUpdate | |
material.map = texture | |
material.needsUpdate = false | |
scene.add(mesh); | |
}) | |
// How to create a different material for each face... | |
// It will now be harder to load all the textures. | |
// The solution is to either uses Promise and Promise.all, | |
// or it could be interesting to use bacon.js to create an event stream. | |
const materials: THREE.Material[] = [] | |
const faceMaterial = new THREE.MeshFaceMaterial(materials) | |
} | |
function animate() { | |
update(); | |
render(); | |
requestAnimationFrame(animate); | |
} | |
function update() { | |
if ( keyboard.pressed("z") ) { | |
// do something | |
} | |
controls.update(); | |
stats.update(); | |
} | |
function render() { | |
renderer.render( scene, camera ); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @author Lee Stemkoski | |
* @author David Geo Holmes (TypeScript migration) | |
* | |
* Usage: | |
* (1) create a global variable: | |
* var keyboard = new KeyboardState(); | |
* (2) during main loop: | |
* keyboard.update(); | |
* (3) check state of keys: | |
* keyboard.down("A") -- true for one update cycle after key is pressed | |
* keyboard.pressed("A") -- true as long as key is being pressed | |
* keyboard.up("A") -- true for one update cycle after key is released | |
* | |
* See KeyboardState.k object data below for names of keys whose state can be polled | |
*/ | |
export default class KeyboardState { | |
constructor() { | |
// bind keyEvents | |
document.addEventListener("keydown", KeyboardState.onKeyDown, false); | |
document.addEventListener("keyup", KeyboardState.onKeyUp, false); | |
} | |
update() | |
{ | |
for (var key in KeyboardState.status) | |
{ | |
// ensure that every keypress has "down" status exactly once | |
if (!KeyboardState.status[key].updatedPreviously) | |
{ | |
KeyboardState.status[key].down = true; | |
KeyboardState.status[key].pressed = true; | |
KeyboardState.status[key].updatedPreviously = true; | |
} | |
else // updated previously | |
{ | |
KeyboardState.status[key].down = false; | |
} | |
// key has been flagged as "up" since last update | |
if ( KeyboardState.status[key].up ) | |
{ | |
delete KeyboardState.status[key]; | |
continue; // move on to next key | |
} | |
if ( !KeyboardState.status[key].pressed ) // key released | |
KeyboardState.status[key].up = true; | |
} | |
} | |
down(keyName: string): boolean { | |
return (KeyboardState.status[keyName] && KeyboardState.status[keyName].down); | |
} | |
pressed(keyName: string): boolean { | |
return (KeyboardState.status[keyName] && KeyboardState.status[keyName].pressed); | |
} | |
up(keyName: string): boolean { | |
return (KeyboardState.status[keyName] && KeyboardState.status[keyName].up); | |
} | |
debug() { | |
var list = "Keys active: "; | |
for (var arg in KeyboardState.status) | |
list += " " + arg | |
console.log(list); | |
} | |
static k: {[keyCode: number]: string} = { | |
8: "backspace", 9: "tab", 13: "enter", 16: "shift", | |
17: "ctrl", 18: "alt", 27: "esc", 32: "space", | |
33: "pageup", 34: "pagedown", 35: "end", 36: "home", | |
37: "left", 38: "up", 39: "right", 40: "down", | |
45: "insert", 46: "delete", 186: ";", 187: "=", | |
188: ",", 189: "-", 190: ".", 191: "/", | |
219: "[", 220: "\\", 221: "]", 222: "'" | |
}; | |
static status: {[key: string]: {down: boolean; pressed: boolean; up: boolean; updatedPreviously: boolean}} = {}; | |
static keyName(keyCode: number): string { | |
return ( KeyboardState.k[keyCode] != null ) ? KeyboardState.k[keyCode] : String.fromCharCode(keyCode); | |
} | |
static onKeyUp(event: KeyboardEvent) { | |
const key = KeyboardState.keyName(event.keyCode); | |
if ( KeyboardState.status[key] ) | |
KeyboardState.status[key].pressed = false; | |
} | |
static onKeyDown(event: KeyboardEvent) { | |
const key = KeyboardState.keyName(event.keyCode); | |
if (!KeyboardState.status[key]) { | |
KeyboardState.status[key] = { down: false, pressed: false, up: false, updatedPreviously: false }; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @author qiao / https://github.com/qiao | |
* @author mrdoob / http://mrdoob.com | |
* @author alteredq / http://alteredqualia.com/ | |
* @author WestLangley / http://github.com/WestLangley | |
* @author David Geo Holmes (TypeScript migration) | |
*/ | |
const EPS = 0.000001; | |
// 65 /*A*/, 83 /*S*/, 68 /*D*/ | |
const keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40, ROTATE: 65, ZOOM: 83, PAN: 68 }; | |
export default class OrbitControls { | |
private object: THREE.Object3D; | |
private domElement; | |
public enabled = true; | |
public center = new THREE.Vector3(); | |
public userZoom = true; | |
public userZoomSpeed = 1.0; | |
public userRotate = true; | |
public userRotateSpeed = 1.0; | |
public userPan = true; | |
public userPanSpeed = 2.0; | |
public autoRotate = false; | |
public autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 | |
public minPolarAngle = 0; // radians | |
public maxPolarAngle = Math.PI; // radians | |
public minDistance = 0; | |
public maxDistance = Infinity; | |
private phiDelta = 0; | |
private thetaDelta = 0; | |
private scale = 1; | |
private lastPosition = new THREE.Vector3(); | |
constructor( object: THREE.Object3D , domElement: HTMLCanvasElement ) { | |
this.object = object; | |
this.domElement = ( domElement !== undefined ) ? domElement : document; | |
var PIXELS_PER_ROUND = 1800; | |
var rotateStart = new THREE.Vector2(); | |
var rotateEnd = new THREE.Vector2(); | |
var rotateDelta = new THREE.Vector2(); | |
var zoomStart = new THREE.Vector2(); | |
var zoomEnd = new THREE.Vector2(); | |
var zoomDelta = new THREE.Vector2(); | |
var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 }; | |
var state = STATE.NONE; | |
// events | |
var changeEvent = { type: 'change' }; | |
this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); | |
const onMouseDown = (event: MouseEvent) => { | |
if (this.enabled === false ) return; | |
if (this.userRotate === false ) return; | |
event.preventDefault(); | |
if ( state === STATE.NONE ) | |
{ | |
if ( event.button === 0 ) | |
state = STATE.ROTATE; | |
if ( event.button === 1 ) | |
state = STATE.ZOOM; | |
if ( event.button === 2 ) | |
state = STATE.PAN; | |
} | |
if ( state === STATE.ROTATE ) { | |
//state = STATE.ROTATE; | |
rotateStart.set( event.clientX, event.clientY ); | |
} | |
else if ( state === STATE.ZOOM ) { | |
//state = STATE.ZOOM; | |
zoomStart.set( event.clientX, event.clientY ); | |
} | |
else if ( state === STATE.PAN ) { | |
//state = STATE.PAN; | |
} | |
document.addEventListener( 'mousemove', onMouseMove, false ); | |
document.addEventListener( 'mouseup', onMouseUp, false ); | |
} | |
this.domElement.addEventListener( 'mousedown', onMouseDown, false ); | |
const onMouseMove = (event: MouseEvent) => { | |
if (this.enabled === false ) return; | |
event.preventDefault(); | |
if ( state === STATE.ROTATE ) { | |
rotateEnd.set( event.clientX, event.clientY ); | |
rotateDelta.subVectors( rotateEnd, rotateStart ); | |
this.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * this.userRotateSpeed ); | |
this.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * this.userRotateSpeed ); | |
rotateStart.copy( rotateEnd ); | |
} | |
else if ( state === STATE.ZOOM ) { | |
zoomEnd.set( event.clientX, event.clientY ); | |
zoomDelta.subVectors( zoomEnd, zoomStart ); | |
if ( zoomDelta.y > 0 ) { | |
this.zoomIn(); | |
} | |
else { | |
this.zoomOut(); | |
} | |
zoomStart.copy( zoomEnd ); | |
} else if ( state === STATE.PAN ) { | |
const movementX: number = event['movementX'] || event['mozMovementX'] || event['webkitMovementX'] || 0; | |
const movementY = event['movementY'] || event['mozMovementY'] || event['webkitMovementY'] || 0; | |
this.pan( new THREE.Vector3( - movementX, movementY, 0 ) ); | |
} | |
} | |
const onMouseUp = (event: MouseEvent) => { | |
if (this.enabled === false) return; | |
if (this.userRotate === false) return; | |
document.removeEventListener( 'mousemove', onMouseMove, false ); | |
document.removeEventListener( 'mouseup', onMouseUp, false ); | |
state = STATE.NONE; | |
} | |
const onMouseWheel = (event: MouseWheelEvent) => { | |
if (this.enabled === false ) return; | |
if (this.userZoom === false ) return; | |
let delta = 0; | |
if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 | |
delta = event.wheelDelta; | |
} | |
else if ( event.detail ) { // Firefox | |
delta = - event.detail; | |
} | |
if ( delta > 0 ) { | |
this.zoomOut(); | |
} | |
else { | |
this.zoomIn(); | |
} | |
} | |
this.domElement.addEventListener( 'mousewheel', onMouseWheel, false ); | |
this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox | |
const onKeyDown = (event: KeyboardEvent) => { | |
if (this.enabled === false) return; | |
if (this.userPan === false) return; | |
switch ( event.keyCode ) { | |
/*case scope.keys.UP: | |
scope.pan( new THREE.Vector3( 0, 1, 0 ) ); | |
break; | |
case scope.keys.BOTTOM: | |
scope.pan( new THREE.Vector3( 0, - 1, 0 ) ); | |
break; | |
case scope.keys.LEFT: | |
scope.pan( new THREE.Vector3( - 1, 0, 0 ) ); | |
break; | |
case scope.keys.RIGHT: | |
scope.pan( new THREE.Vector3( 1, 0, 0 ) ); | |
break; | |
*/ | |
case keys.ROTATE: | |
state = STATE.ROTATE; | |
break; | |
case keys.ZOOM: | |
state = STATE.ZOOM; | |
break; | |
case keys.PAN: | |
state = STATE.PAN; | |
break; | |
} | |
} | |
const onKeyUp = (event: KeyboardEvent) => { | |
switch (event.keyCode) { | |
case keys.ROTATE: | |
case keys.ZOOM: | |
case keys.PAN: | |
state = STATE.NONE; | |
break; | |
} | |
} | |
window.addEventListener( 'keydown', onKeyDown, false ); | |
window.addEventListener( 'keyup', onKeyUp, false ); | |
} | |
private getAutoRotationAngle(): number { | |
return 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; | |
} | |
private getZoomScale(): number { | |
return Math.pow( 0.95, this.userZoomSpeed ); | |
} | |
rotateLeft(angle?: number): void { | |
if ( angle === undefined ) { | |
angle = this.getAutoRotationAngle(); | |
} | |
this.thetaDelta -= angle; | |
} | |
rotateRight(angle?: number): void { | |
if ( angle === undefined ) { | |
angle = this.getAutoRotationAngle(); | |
} | |
this.thetaDelta += angle; | |
} | |
rotateUp(angle?: number) { | |
if ( angle === undefined ) { | |
angle = this.getAutoRotationAngle(); | |
} | |
this.phiDelta -= angle; | |
} | |
rotateDown(angle?: number) { | |
if ( angle === undefined ) { | |
angle = this.getAutoRotationAngle(); | |
} | |
this.phiDelta += angle; | |
} | |
zoomIn(zoomScale?: number): void { | |
if ( zoomScale === undefined ) { | |
zoomScale = this.getZoomScale(); | |
} | |
this.scale /= zoomScale; | |
} | |
zoomOut(zoomScale?: number): void { | |
if (zoomScale === undefined) { | |
zoomScale = this.getZoomScale(); | |
} | |
this.scale *= zoomScale; | |
} | |
pan( distance: THREE.Vector3 ) { | |
distance.transformDirection( this.object.matrix ); | |
distance.multiplyScalar( this.userPanSpeed ); | |
this.object.position.add( distance ); | |
this.center.add( distance ); | |
} | |
update() { | |
const position = this.object.position; | |
const offset = position.clone().sub( this.center ); | |
// angle from z-axis around y-axis | |
let theta = Math.atan2( offset.x, offset.z ); | |
// angle from y-axis | |
let phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y ); | |
if (this.autoRotate) { | |
this.rotateLeft(this.getAutoRotationAngle()); | |
} | |
theta += this.thetaDelta; | |
phi += this.phiDelta; | |
// restrict phi to be between desired limits | |
phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) ); | |
// restrict phi to be betwee EPS and PI-EPS | |
phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) ); | |
var radius = offset.length() * this.scale; | |
// restrict radius to be between desired limits | |
radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) ); | |
offset.x = radius * Math.sin( phi ) * Math.sin( theta ); | |
offset.y = radius * Math.cos( phi ); | |
offset.z = radius * Math.sin( phi ) * Math.cos( theta ); | |
position.copy( this.center ).add( offset ); | |
this.object.lookAt( this.center ); | |
this.thetaDelta = 0; | |
this.phiDelta = 0; | |
this.scale = 1; | |
if ( this.lastPosition.distanceTo( this.object.position ) > 0 ) { | |
// this.dispatchEvent( changeEvent ); | |
this.lastPosition.copy( this.object.position ); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"description": "three.js textures", | |
"name": "copy-of-copy-of-", | |
"version": "0.1.0", | |
"dependencies": { | |
"DomReady": "1.0.0", | |
"three.js": "0.82.0", | |
"stats.js": "0.16.0" | |
}, | |
"keywords": [ | |
"THREE", | |
"three.js", | |
"Texture" | |
], | |
"author": "David Geo Holmes" | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment