adds key controls, star info and more stars

This commit is contained in:
Norman Köhring 2023-01-22 21:49:34 +01:00
parent d2b31f895a
commit 3bac2bd865
5 changed files with 86 additions and 26 deletions

View file

@ -33,7 +33,7 @@
</style>
</head>
<body>
<div id="info"></div>
<div id="info">Click a star to get options.</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View file

@ -9,13 +9,13 @@ import {
} from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { planeGeometry } from './plane'
import { renderStars } from './stars'
import { renderStars, Star } from './stars'
function init() {
const w = window.innerWidth
const h = window.innerHeight
const radius = 50
const infoEl = document.getElementById('info')!
const renderer = new WebGLRenderer({ antialias: true })
renderer.setSize(w, h)
@ -29,9 +29,10 @@ function init() {
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableZoom = true
controls.enableRotate = true
controls.enablePan = false
controls.enablePan = true
controls.maxDistance = radius * 2.5
controls.minDistance = 0.1
controls.listenToKeyEvents(window)
const plane = planeGeometry(radius)
const stars = renderStars(radius)
@ -41,6 +42,7 @@ function init() {
const pointer = new Vector2()
const raycaster = new Raycaster()
const intersections: Intersection<Object3D<Event>>[] = []
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight
@ -52,15 +54,27 @@ function init() {
pointer.x = (event.clientX / window.innerWidth) * 2 - 1
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1
})
document.addEventListener('click', () => {
infoEl.innerText = 'Click a star to get options.'
for (let star of stars.children) {
;(star as Star).highlighted = false
}
const intersections: Intersection<Object3D<Event>>[] = []
for (let i of intersections) {
const star = i.object.parent as Star
if (star.isStar) {
star.highlighted = true
infoEl.innerText = JSON.stringify(star.starData)
}
}
})
renderer.setAnimationLoop(() => {
raycaster.setFromCamera(pointer, camera)
intersections.length = 0
raycaster.intersectObject(stars, false, intersections)
if (intersections.length) console.log(intersections)
raycaster.intersectObject(stars, true, intersections)
renderer.render(scene, camera)
})
document.body.appendChild(renderer.domElement)

View file

@ -2,7 +2,7 @@ import { BufferGeometry, Group, Line, LineBasicMaterial, Shape, Vector3 } from '
export function planeGeometry(radius: number, n = 5) {
const material = new LineBasicMaterial({
color: 0xa0a0a0,
color: 0x303030,
})
const plane = new Group()

View file

@ -21,13 +21,20 @@ export interface StarData {
theta: number
}
class Star extends Group {
export class Star extends Group {
public isStar = true
public starData: StarData
private tangentialCoords = new Vector3()
private cartesianCoords = new Vector3()
private sphericalCoords = new Spherical()
private isHighlighted = false
private normalPointSize = 2
private highlightedPointSize = 3
private lineMaterial = new LineBasicMaterial({ color: 0xffffff })
private pointMaterial = new PointsMaterial({ size: 1, vertexColors: true })
private pointMaterial = new PointsMaterial({ size: this.normalPointSize, vertexColors: true })
private pointGeometry = new BufferGeometry()
private whiteColor = new Float32BufferAttribute([255, 255, 255], 3)
@ -35,10 +42,11 @@ class Star extends Group {
private poleLine = new Line(new BufferGeometry(), this.lineMaterial)
constructor(star: StarData) {
constructor(starData: StarData) {
super()
const { radius, phi, theta } = star
const { radius, phi, theta } = starData
this.starData = starData
this.sphericalCoords.set(radius, phi, theta)
this.cartesianCoords.setFromSpherical(this.sphericalCoords)
@ -58,30 +66,36 @@ class Star extends Group {
this.add(point)
}
setHighlight(isHighlight = true) {
this.pointGeometry.setAttribute('color', isHighlight ? this.yellowColor : this.whiteColor)
private setHighlight(isHighlight = true) {
const color = isHighlight ? this.yellowColor : this.whiteColor
this.pointGeometry.setAttribute('color', color)
this.pointMaterial.setValues({
size: isHighlight ? this.highlightedPointSize : this.normalPointSize,
})
}
public get highlighted() {
return this.isHighlighted
}
public set highlighted(isHighlighted) {
this.isHighlighted = isHighlighted
this.setHighlight(isHighlighted)
}
public toggleHighlight() {
this.isHighlighted = !this.isHighlighted
this.setHighlight(this.isHighlighted)
}
}
export function renderStars(maxRadius: number) {
const group = new Group()
const infoEl = document.getElementById('info')!
data.forEach((starData) => {
if (starData.radius > maxRadius) return
const star = new Star(starData)
group.add(star)
let highlighted = false
const btnEl = document.createElement('button')
btnEl.addEventListener('click', () => {
highlighted = !highlighted
star.setHighlight(highlighted)
btnEl.classList.toggle('highlighted', highlighted)
})
btnEl.innerText = starData.name
infoEl.appendChild(btnEl)
})
return group

View file

@ -38,5 +38,37 @@
"phi": -13.0693645782006,
"spectral": "M4.0Ve",
"radius": 5.0515
},
{
"name": "Proxima Centauri",
"type": "Eruptive Variable",
"theta": 313.9398620493784,
"phi": -1.9271491330428,
"spectral": "M5.5Ve",
"radius": 1.3019
},
{
"name": "Teegarden's Star",
"type": "Low-mass Star",
"theta": 160.2632765789228,
"phi": -37.0261176452823,
"spectral": "dM6",
"radius": 3.8315
},
{
"name": "Barnard's star",
"type": "BY Dra Variable",
"theta": 31.0087027177046,
"phi": 14.0626510150033,
"spectral": "M4V",
"radius": 1.8282
},
{
"name": "Wolf 359",
"type": "Eruptive Variable",
"theta": 244.0543969618636,
"phi": 56.1197323657577,
"spectral": "dM6",
"radius": 2.4086
}
]