Skip to content

Commit

Permalink
Add a sun to show night lights. (#77)
Browse files Browse the repository at this point in the history
Some issues: satellites are not really clear in the night:
I cannot add an ambient light because of this:
mrdoob/three.js#5180
  • Loading branch information
Thiesjoo authored Jun 19, 2024
1 parent d8d91aa commit ce72345
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 22 deletions.
8 changes: 4 additions & 4 deletions frontend-vue/src/Satellite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from './common/constants'
import { Orbit } from './Orbit'

function polar2Cartesian(lat: number, lng: number, relAltitude: number, globeRadius: number) {
export function polar2Cartesian(lat: number, lng: number, relAltitude: number, globeRadius: number) {
const phi = ((90 - lat) * Math.PI) / 180
const theta = ((90 - lng) * Math.PI) / 180
const r = globeRadius * (1 + relAltitude)
Expand All @@ -35,12 +35,12 @@ export function constructSatelliteMesh(globeRadius: number): SatelliteMeshes {
0
)

const satMaterial = new THREE.MeshLambertMaterial({
const satMaterial = new THREE.MeshBasicMaterial({
transparent: true,
opacity: 0.7
opacity: 0.7,
})

const satClickMaterial = new THREE.MeshLambertMaterial({
const satClickMaterial = new THREE.MeshBasicMaterial({
opacity: 0,
transparent: true
})
Expand Down
68 changes: 61 additions & 7 deletions frontend-vue/src/Sim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import ThreeGlobe from 'three-globe'

import Earth from './assets/earth-blue-marble.jpg'
import Gaia from './assets/Gaia.png'
import { constructSatelliteMesh, SatelliteMeshes, type Satellite } from './Satellite'
import { loadTexture, shiftLeft, geoCoords } from './common/utils'
import NightLights from "./assets/night_lights_modified.png"

import { constructSatelliteMesh, SatelliteMeshes, type Satellite, polar2Cartesian } from './Satellite'
import { geoCoords, loadTexture, shiftLeft } from './common/utils'

Check warning on line 12 in frontend-vue/src/Sim.ts

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

frontend-vue/src/Sim.ts#L12

[@typescript-eslint/no-unused-vars] 'shiftLeft' is defined but never used.
import {
EARTH_RADIUS_KM,
LINE_SIZE,

Check warning on line 15 in frontend-vue/src/Sim.ts

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

frontend-vue/src/Sim.ts#L15

[@typescript-eslint/no-unused-vars] 'LINE_SIZE' is defined but never used.
Expand All @@ -32,6 +34,7 @@ export class ThreeSimulation {
private tweeningStatus: number = 0
private escapedFollow = false

private sun!: THREE.DirectionalLight;
private renderer!: THREE.WebGLRenderer
public scene!: THREE.Scene //TODO: private maken
private camera!: THREE.PerspectiveCamera
Expand Down Expand Up @@ -90,6 +93,32 @@ export class ThreeSimulation {
document.body.appendChild(this.stats.dom)
}

private getSunPosition() {
// Calculate the position of the sun in our scene
// This is used for the night lights on the Earth. solar ephemeris
const time = this.time.time;
const copy = new Date(time.getTime());
// get time in GMT
const hours = copy.getUTCHours();
const minutes = copy.getUTCMinutes();
const seconds = copy.getUTCSeconds();

// progress in day
const progress = (hours * 60 * 60 + minutes * 60 + seconds) / (24 * 60 * 60);

// at 0.00 the sun is at lat0, lon0, 4 hours later at lat
const lat = 0;
const lng = progress * 360 - 180;
const cartesianPosition = polar2Cartesian(
lat,
lng,
EARTH_RADIUS_KM * 3,
this.globe.getGlobeRadius()
)

return new THREE.Vector3(cartesianPosition.x, cartesianPosition.y, cartesianPosition.z)
}

private async initScene(canvas: HTMLCanvasElement) {
this.scene = new THREE.Scene()

Expand Down Expand Up @@ -118,22 +147,47 @@ export class ThreeSimulation {
}

// Add lights
this.scene.add(new THREE.DirectionalLight(0xffffff, 0.6 * Math.PI))
this.scene.add(new THREE.AmbientLight(0xcccccc, Math.PI))
this.sun = new THREE.DirectionalLight(0xffffff, 0.6 * Math.PI)
this.scene.add(this.sun)

const nightLights = await loadTexture(NightLights)

// Add background
const envMap = await loadTexture(Gaia)
envMap.mapping = THREE.EquirectangularReflectionMapping
this.scene.background = envMap

const earth = await loadTexture(Earth)
earth.colorSpace = THREE.SRGBColorSpace;

const material = new THREE.MeshPhongMaterial({
map: earth,
emissiveMap: nightLights,
emissive: new THREE.Color(0xffff88),
})


// Code from: https://github.com/franky-adl/threejs-earth
material.onBeforeCompile = function( shader ) {
shader.fragmentShader = shader.fragmentShader.replace('#include <emissivemap_fragment>', `
vec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );
emissiveColor *= 1.0 - smoothstep(-0.2, 0.2, dot(normal, directionalLights[0].direction));
totalEmissiveRadiance *= emissiveColor.rgb;
`)
}

// Add the Earth
this.globe = new ThreeGlobe()
.globeImageUrl(Earth)
.objectLat('lat')
.objectLng('lng')
.objectAltitude('alt')
.objectFacesSurface(false)
.atmosphereAltitude(0)
.globeMaterial(material)
this.sun.position.copy(this.getSunPosition())

const axialTiltInRadians = 23.5 * (Math.PI / 180)
this.globe.rotation.x = axialTiltInRadians

this.globe.userData = {name: "globe"};

Expand Down Expand Up @@ -198,10 +252,10 @@ export class ThreeSimulation {
this.globe.rotation.y += 0.001
}

this.sun.position.copy(this.getSunPosition())
if (this.workerManager.finishPropagate(this.time.time, satellite.gstime(this.time.time))) {
this.updatePositionsOfMeshes()
}

this.time.step()
this.updateOrbits()
this.satelliteLinks?.render()
Expand All @@ -216,7 +270,6 @@ export class ThreeSimulation {
// Update the picking ray with the camera and pointer position
this.raycaster.setFromCamera(this.pointer, this.camera)
const intersects = this.raycaster.intersectObjects(this.scene.children)

if (intersects.length > 0 && 'satellite' in intersects[0].object.userData) {
this.dehover()

Expand Down Expand Up @@ -531,6 +584,7 @@ export class ThreeSimulation {

// Emits:
// select(sat | undefined )

addEventListener(event: 'select', callback: (sat: Satellite | undefined) => void): void
addEventListener(event: 'earthClicked', callback: (sat: geoCoords | undefined) => void): void
addEventListener(event: 'select' | 'earthClicked', callback: ((sat: Satellite | undefined) => void) | ((sat: geoCoords | undefined) => void)): void {
Expand Down
Binary file added frontend-vue/src/assets/Bump.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend-vue/src/assets/night_lights_modified.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion frontend-vue/src/common/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const EARTH_RADIUS_KM = 6371 // km
export const SAT_SIZE = 75 // km
export const SAT_SIZE_CLICK = 2.5 * SAT_SIZE // km
export const SAT_COLOR = 'palegreen'
export const SAT_COLOR = 'white'
export const SAT_COLOR_HOVER = '#FFD700'
export const SAT_COLOR_SELECTED = '#FF4500'
export const LINE_SIZE = 12_000
Expand Down
33 changes: 23 additions & 10 deletions frontend-vue/src/components/SpeedButtons.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,29 @@ const time = props.simulation.getTime()
const currentTimeString = ref('')
const dateFormatEN = new Intl.DateTimeFormat('en', {
hour: '2-digit',
minute: '2-digit',
weekday: 'short',
day: '2-digit',
month: 'short',
year: 'numeric',
timeZone: "Europe/Amsterdam"
})
const dateFormatNL = new Intl.DateTimeFormat('nl', {
hour: '2-digit',
minute: '2-digit',
weekday: 'short',
day: '2-digit',
month: 'short',
year: 'numeric',
timeZone: "Europe/Amsterdam"
})
const updateCurrentTimeString = () => {
const localeCode = locale.value === 'nl' ? 'nl-NL' : 'en-US'
currentTimeString.value = time.time.toLocaleTimeString(localeCode, {
hour: '2-digit',
minute: '2-digit',
weekday: 'short',
day: '2-digit',
month: 'short',
year: 'numeric'
})
currentTimeString.value = locale.value === 'en' ? dateFormatEN.format(time.time) : dateFormatNL.format(time.time)
}
onMounted(() => {
Expand All @@ -36,7 +49,7 @@ const resetTime = () => {
time.setSpeed(1)
}
const intervals = [1, 10, 100, 1000]
const intervals = [1, 10, 100, 1000, 10000]
</script>

<template>
Expand Down

0 comments on commit ce72345

Please sign in to comment.