solaris-js
Version:
A reusable component for interactive visualization of the Solar System
122 lines (88 loc) • 3.15 kB
text/coffeescript
import publicize from './helpers/publicizer'
import {
Group, SphereGeometry, MeshPhongMaterial, MeshBasicMaterial, MeshLambertMaterial
TextureLoader, Mesh, PointLight, Sprite, SpriteMaterial, AdditiveBlending, Vector3
} from 'three'
import Label from './label/Label'
import Ring from './Ring'
import Orbit from './Orbit'
degreesToRadians = (v) -> v * (Math.PI / 180)
class $CelestialBody
constructor: (, , , ) ->
= .styles.compute(.key, .type)
= if not then .scene
else $CelestialBody.privateInstances.get().group
= new Group
.add()
=
.add()
if .ring
= new Ring(.ring, .key, .root, .scale)
.add(.mesh)
if .elements
= new Orbit(.getOrbitPath(), .orbit, .scale)
.add(.line)
#
= new Label , .orbit, .el
.onClick => .center(this)
#
update: ->
if .elements
.position.fromArray(.scale.convert(.position))
if isnt .model.time
= .model.time
.update(.getOrbitPath()) if
labelPosition =
if isnt labelPosition
= labelPosition
.setPosition(labelPosition)
createSphere: (radius) ->
radius = .scale.convert(radius)
{color, light, texture} =
geometry = new SphereGeometry(radius, 32, 32) # radius, segments, rings
material = if texture
new MeshPhongMaterial {map: new TextureLoader().load(texture)}
else if light
new MeshBasicMaterial {color}
else if color
new MeshLambertMaterial {color}
sphere = new Mesh(geometry, material)
if light
sphere.add(new PointLight(light))
sphere.add( radius, light)
sphere.position.set(0, 0, 0)
if .tilt
sphere.rotation.x = (Math.PI / 2) - degreesToRadians(.tilt)
sphere
createCorona: (radius, color) ->
material = new SpriteMaterial
map: new TextureLoader().load("#{@solaris.root}/img/corona.jpg")
color: color
transparent: no
blending: AdditiveBlending
mesh = new Sprite(material)
mesh.scale.multiplyScalar(radius * 4.4)
mesh
#
getAbsolutePosition: ->
pos = new Vector3
pos.setFromMatrixPosition(.matrixWorld)
pos
getScreenPosition: ->
pos =
pos.project(.camera)
w = .offsetWidth
hw = w / 2
h = .offsetHeight
hh = h / 2
pos.x = (pos.x * hw) + hw
pos.y = -(pos.y * hh) + hh
if 0 < pos.z <= 1 and
0 < pos.x < w and
0 < pos.y < h
pos
else # out of screen
null
export default class CelestialBody extends publicize $CelestialBody,
methods: ['update', 'getAbsolutePosition']
properties: ['label']