interstellar / src /Simulation.js
Pim Schreurs
Fix orientation controls for iOS13
aa14f68
import {
Vector3,
Vector4,
Clock
} from 'three'
import Ui from './Ui'
import Player from './Player'
import KeyboardControls from './controls/KeyboardControls'
import MobileDeviceControls from './controls/MobileDeviceControls'
import ControlsManager from './controls/ControlsManager'
import SimulationRenderer from './SimulationRenderer'
import Teleporter from './Teleporter'
class Simulation {
init () {
this.config = {
wormhole: {
position: new Vector3(10, 0.0, -32),
radius: 0.8,
gravityRatio: 0.25
},
blackhole: {
position: new Vector3(0.0, -250.0, 250.0),
radius: 12.5,
// Ring definition - xyz is normal going through ring. Its magnitude determines inner radius.
// w component determines outer radius
disk: new Vector4(-12, 12, 6, 150.0),
diskTexture: 'assets/accretion_disk.png'
},
saturn: {
position: new Vector3(-14, 5, -40),
radius: 8.0,
// Ring definition - xyz is normal going through ring. Its magnitude determines inner radius.
// w component determines outer radius
rings: new Vector4(0, 9.22, 0, 17.1),
texture: 'assets/saturn.jpg',
ringsTexture: 'assets/saturnrings.png',
lightDirection: (new Vector3(-4, 2, 3)).normalize()
},
planet: {
position: new Vector3(7.6, -188.0, 200),
radius: 0.08,
diffuse: new Vector3(0.58, 0.85, 0.96),
specular: new Vector3(0.1, 0.1, 0.1)
},
galaxy1: { texture: 'assets/galaxy1.png' },
galaxy2: { texture: 'assets/galaxy2.png' }
}
this.teleportTargets = [
{ position: new Vector3(10, -307, 454), lookAt: this.config.blackhole.position, galaxy: 1 },
{ position: new Vector3(7.2, -188, 199.6), lookAt: this.config.planet.position, galaxy: 1 },
{ position: new Vector3(12.4, 3.3, -35.1), lookAt: this.config.wormhole.position, galaxy: 1 },
{ position: new Vector3(9.8, -4.6, -3.1), lookAt: this.config.wormhole.position, galaxy: 0 }
]
this.initPlayer()
this.initTeleporter()
this.initRenderer()
this.initControls()
}
initRenderer () {
this.renderer = new SimulationRenderer(this.config, this.player)
this.renderer.onTexturesLoaded = () => {
Ui.removeLoadingScreen()
this.inited = true
}
this.container = document.getElementById('container')
this.container.appendChild(this.renderer.domElement)
Ui.onPixelSizeChange = pixelSize => {
this.renderer.setPixelSize(pixelSize)
}
window.addEventListener(
'resize', e => {
this.renderer.setSize(window.innerWidth, window.innerHeight)
},
false
)
let pixelSize = Ui.getSelectedPixelSize()
if (!pixelSize) {
pixelSize = this.getSuggestedPixelSize()
Ui.setPixelSize(pixelSize)
}
this.renderer.setSize(window.innerWidth, window.innerHeight, pixelSize)
window.addEventListener('wheel', e => {
e.preventDefault()
const delta = e.delta || (e.deltaX + e.deltaY + e.deltaZ)
if (delta < 0) {
this.renderer.setZoom(this.renderer.zoom * 1.06)
}
else {
this.renderer.setZoom(this.renderer.zoom / 1.06)
}
}, false)
}
initPlayer () {
this.player = new Player()
this.player.lookAt(this.config.wormhole.position)
}
initControls () {
// Add keyboard controls to the player
this.keyboardControls = new KeyboardControls(this.player, this.container)
this.keyboardControls.movementSpeed = 1
this.keyboardControls.rollSpeed = Math.PI / 3
this.keyboardControls.autoForward = false
this.keyboardControls.dragToLook = false
// Add mobile device controls (touch + accelerometer) to the player
this.mobileDeviceControls = new MobileDeviceControls(this.player, this.container)
this.controlsManager = new ControlsManager(this.keyboardControls, this.mobileDeviceControls)
this.controlsManager.onChange = device => {
if (device !== 'mobile') {
return
}
// The player will probably not be looking with their device in the right direction, so fix that
requestAnimationFrame(() => {
this.player.object.quaternion.multiply(this.player.eyes.quaternion.clone().inverse())
})
}
this.controlsManager.start()
this.player.addController(this.keyboardControls)
this.player.addController(this.mobileDeviceControls)
}
initTeleporter () {
this.teleporter = new Teleporter(this.player)
this.teleportTargets.forEach(target => {
this.teleporter.addTarget(target)
})
Ui.onTeleportClick = () => {
this.teleporter.teleportNext()
}
document.addEventListener('keydown', e => {
if (e.keyCode === 84) {
e.preventDefault()
this.teleporter.teleportNext()
}
})
}
step () {
if (this.inited) {
this.update()
}
this.render()
}
start () {
this.clock = new Clock()
const animate = () => {
requestAnimationFrame(animate)
this.step()
}
animate()
}
update () {
const delta = Math.max(0.001, this.clock.getDelta())
this.player.update(delta)
}
render () {
this.renderer.render()
}
getSuggestedPixelSize () {
const pixelCount = window.innerWidth * window.innerHeight
let pixelSize = 4
while (pixelSize > 1) {
if (pixelCount / (pixelSize * pixelSize) < 512 * 512) {
pixelSize /= 2
}
else {
break
}
}
return pixelSize
}
}
export default new Simulation()