Created
June 10, 2014 18:11
-
-
Save benjaminjackman/e9832bb44c5a59026f69 to your computer and use it in GitHub Desktop.
Example of using three js in scala
This file contains 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
package cgta.viz | |
package learn.threejs | |
import scala.scalajs.js | |
import scala.scalajs.js.annotation.JSExport | |
import cgta.oscala.wraps.tween.{Tween, TWEENJS} | |
import org.scalajs.dom | |
@JSExport | |
object PeriodicTable { | |
case class Element(symbol: String, name: String, weight: String, col: Int, row: Int) | |
val rawElements = IVec( | |
Element("H", "Hydrogen", "1.00794", 1, 1), | |
Element("He", "Helium", "4.002602", 18, 1), | |
Element("Li", "Lithium", "6.941", 1, 2), | |
Element("Be", "Beryllium", "9.012182", 2, 2), | |
Element("B", "Boron", "10.811", 13, 2), | |
Element("C", "Carbon", "12.0107", 14, 2), | |
Element("N", "Nitrogen", "14.0067", 15, 2), | |
Element("O", "Oxygen", "15.9994", 16, 2), | |
Element("F", "Fluorine", "18.9984032", 17, 2), | |
Element("Ne", "Neon", "20.1797", 18, 2), | |
Element("Na", "Sodium", "22.98976...", 1, 3), | |
Element("Mg", "Magnesium", "24.305", 2, 3), | |
Element("Al", "Aluminium", "26.9815386", 13, 3), | |
Element("Si", "Silicon", "28.0855", 14, 3), | |
Element("P", "Phosphorus", "30.973762", 15, 3), | |
Element("S", "Sulfur", "32.065", 16, 3), | |
Element("Cl", "Chlorine", "35.453", 17, 3), | |
Element("Ar", "Argon", "39.948", 18, 3), | |
Element("K", "Potassium", "39.948", 1, 4), | |
Element("Ca", "Calcium", "40.078", 2, 4), | |
Element("Sc", "Scandium", "44.955912", 3, 4), | |
Element("Ti", "Titanium", "47.867", 4, 4), | |
Element("V", "Vanadium", "50.9415", 5, 4), | |
Element("Cr", "Chromium", "51.9961", 6, 4), | |
Element("Mn", "Manganese", "54.938045", 7, 4), | |
Element("Fe", "Iron", "55.845", 8, 4), | |
Element("Co", "Cobalt", "58.933195", 9, 4), | |
Element("Ni", "Nickel", "58.6934", 10, 4), | |
Element("Cu", "Copper", "63.546", 11, 4), | |
Element("Zn", "Zinc", "65.38", 12, 4), | |
Element("Ga", "Gallium", "69.723", 13, 4), | |
Element("Ge", "Germanium", "72.63", 14, 4), | |
Element("As", "Arsenic", "74.9216", 15, 4), | |
Element("Se", "Selenium", "78.96", 16, 4), | |
Element("Br", "Bromine", "79.904", 17, 4), | |
Element("Kr", "Krypton", "83.798", 18, 4), | |
Element("Rb", "Rubidium", "85.4678", 1, 5), | |
Element("Sr", "Strontium", "87.62", 2, 5), | |
Element("Y", "Yttrium", "88.90585", 3, 5), | |
Element("Zr", "Zirconium", "91.224", 4, 5), | |
Element("Nb", "Niobium", "92.90628", 5, 5), | |
Element("Mo", "Molybdenum", "95.96", 6, 5), | |
Element("Tc", "Technetium", "(98)", 7, 5), | |
Element("Ru", "Ruthenium", "101.07", 8, 5), | |
Element("Rh", "Rhodium", "102.9055", 9, 5), | |
Element("Pd", "Palladium", "106.42", 10, 5), | |
Element("Ag", "Silver", "107.8682", 11, 5), | |
Element("Cd", "Cadmium", "112.411", 12, 5), | |
Element("In", "Indium", "114.818", 13, 5), | |
Element("Sn", "Tin", "118.71", 14, 5), | |
Element("Sb", "Antimony", "121.76", 15, 5), | |
Element("Te", "Tellurium", "127.6", 16, 5), | |
Element("I", "Iodine", "126.90447", 17, 5), | |
Element("Xe", "Xenon", "131.293", 18, 5), | |
Element("Cs", "Caesium", "132.9054", 1, 6), | |
Element("Ba", "Barium", "132.9054", 2, 6), | |
Element("La", "Lanthanum", "138.90547", 4, 9), | |
Element("Ce", "Cerium", "140.116", 5, 9), | |
Element("Pr", "Praseodymium", "140.90765", 6, 9), | |
Element("Nd", "Neodymium", "144.242", 7, 9), | |
Element("Pm", "Promethium", "(145)", 8, 9), | |
Element("Sm", "Samarium", "150.36", 9, 9), | |
Element("Eu", "Europium", "151.964", 10, 9), | |
Element("Gd", "Gadolinium", "157.25", 11, 9), | |
Element("Tb", "Terbium", "158.92535", 12, 9), | |
Element("Dy", "Dysprosium", "162.5", 13, 9), | |
Element("Ho", "Holmium", "164.93032", 14, 9), | |
Element("Er", "Erbium", "167.259", 15, 9), | |
Element("Tm", "Thulium", "168.93421", 16, 9), | |
Element("Yb", "Ytterbium", "173.054", 17, 9), | |
Element("Lu", "Lutetium", "174.9668", 18, 9), | |
Element("Hf", "Hafnium", "178.49", 4, 6), | |
Element("Ta", "Tantalum", "180.94788", 5, 6), | |
Element("W", "Tungsten", "183.84", 6, 6), | |
Element("Re", "Rhenium", "186.207", 7, 6), | |
Element("Os", "Osmium", "190.23", 8, 6), | |
Element("Ir", "Iridium", "192.217", 9, 6), | |
Element("Pt", "Platinum", "195.084", 10, 6), | |
Element("Au", "Gold", "196.966569", 11, 6), | |
Element("Hg", "Mercury", "200.59", 12, 6), | |
Element("Tl", "Thallium", "204.3833", 13, 6), | |
Element("Pb", "Lead", "207.2", 14, 6), | |
Element("Bi", "Bismuth", "208.9804", 15, 6), | |
Element("Po", "Polonium", "(209)", 16, 6), | |
Element("At", "Astatine", "(210)", 17, 6), | |
Element("Rn", "Radon", "(222)", 18, 6), | |
Element("Fr", "Francium", "(223)", 1, 7), | |
Element("Ra", "Radium", "(226)", 2, 7), | |
Element("Ac", "Actinium", "(227)", 4, 10), | |
Element("Th", "Thorium", "232.03806", 5, 10), | |
Element("Pa", "Protactinium", "231.0588", 6, 10), | |
Element("U", "Uranium", "238.02891", 7, 10), | |
Element("Np", "Neptunium", "(237)", 8, 10), | |
Element("Pu", "Plutonium", "(244)", 9, 10), | |
Element("Am", "Americium", "(243)", 10, 10), | |
Element("Cm", "Curium", "(247)", 11, 10), | |
Element("Bk", "Berkelium", "(247)", 12, 10), | |
Element("Cf", "Californium", "(251)", 13, 10), | |
Element("Es", "Einstenium", "(252)", 14, 10), | |
Element("Fm", "Fermium", "(257)", 15, 10), | |
Element("Md", "Mendelevium", "(258)", 16, 10), | |
Element("No", "Nobelium", "(259)", 17, 10), | |
Element("Lr", "Lawrencium", "(262)", 18, 10), | |
Element("Rf", "Rutherfordium", "(267)", 4, 7), | |
Element("Db", "Dubnium", "(268)", 5, 7), | |
Element("Sg", "Seaborgium", "(271)", 6, 7), | |
Element("Bh", "Bohrium", "(272)", 7, 7), | |
Element("Hs", "Hassium", "(270)", 8, 7), | |
Element("Mt", "Meitnerium", "(276)", 9, 7), | |
Element("Ds", "Darmstadium", "(281)", 10, 7), | |
Element("Rg", "Roentgenium", "(280)", 11, 7), | |
Element("Cn", "Copernicium", "(285)", 12, 7), | |
Element("Uut", "Unutrium", "(284)", 13, 7), | |
Element("Fl", "Flerovium", "(289)", 14, 7), | |
Element("Uup", "Ununpentium", "(288)", 15, 7), | |
Element("Lv", "Livermorium", "(293)", 16, 7), | |
Element("Uus", "Ununseptium", "(294)", 17, 7), | |
Element("Uuo", "Ununoctium", "(294)", 18, 7)) | |
val elements = rawElements | |
//++ rawElements ++ rawElements ++ rawElements | |
case class Targets( | |
table: js.Array[*] = js.Array(), | |
sphere: js.Array[*] = js.Array(), | |
helix: js.Array[*] = js.Array(), | |
grid: js.Array[*] = js.Array() | |
) | |
@JSExport | |
def start() { | |
console.log("Periodic Table Start") | |
var camera: * = null | |
var scene: * = null | |
var renderer: * = null | |
var controls: * = null | |
var objects = js.Array[*]() | |
val THREE = global.THREE | |
val targets = Targets() | |
// | |
init() | |
animate() | |
// | |
def init() { | |
camera = js.Dynamic.newInstance(THREE.PerspectiveCamera)(40, window.innerWidth / window.innerHeight, 1, 10000) | |
camera.position.z = 3000 | |
scene = js.Dynamic.newInstance(THREE.Scene)() | |
// table | |
jfor[Int](0, _ < elements.size, _ + 1) { i: Int => | |
var element = document.createElement("div") | |
element.className = "element" | |
element.style.backgroundColor = "rgba(0, 127, 127, " + (js.Math.random() * 0.5 + 0.25) + ")" | |
var number = document.createElement("div") | |
number.className = "number" | |
number.textContent = (i + 1).toString | |
element.appendChild(number) | |
var symbol = document.createElement("div") | |
symbol.className = "symbol" | |
symbol.textContent = elements(i).symbol | |
element.appendChild(symbol) | |
var details = document.createElement("div") | |
details.className = "details" | |
details.innerHTML = elements(i).name + "<br> " + elements(i).weight | |
element.appendChild(details) | |
var obj = js.Dynamic.newInstance(THREE.CSS3DObject)(element) | |
obj.position.x = js.Math.random() * 4000 - 2000 | |
obj.position.y = js.Math.random() * 4000 - 2000 | |
obj.position.z = js.Math.random() * 4000 - 2000 | |
scene.add(obj) | |
objects.push(obj) | |
// | |
var obj2 = js.Dynamic.newInstance(THREE.Object3D)() | |
obj2.position.x = (elements(i).col * 140) - 1330 | |
obj2.position.y = -(elements(i).row * 180) + 990 | |
targets.table.push(obj2) | |
} | |
// sphere | |
locally { | |
val l = objects.length.toDouble | |
var vector = js.Dynamic.newInstance(THREE.Vector3)() | |
jfor[Int](0, _ < l, _ + 1) { i: Int => | |
var phi = js.Math.acos(-1 + (2 * i) / l) | |
var theta = js.Math.sqrt(l * js.Math.PI) * phi | |
var obj = js.Dynamic.newInstance(THREE.Object3D)() | |
obj.position.x = 800 * js.Math.cos(theta) * js.Math.sin(phi) | |
obj.position.y = 800 * js.Math.sin(theta) * js.Math.sin(phi) | |
obj.position.z = 800 * js.Math.cos(phi) | |
vector.copy(obj.position).multiplyScalar(2) | |
obj.lookAt(vector) | |
targets.sphere.push(obj) | |
} | |
} | |
// helix | |
locally { | |
var vector = js.Dynamic.newInstance(THREE.Vector3)() | |
jfor[Int](0, _ < objects.length, _ + 1) { i: Int => | |
var phi = i * 0.175 + js.Math.PI | |
var obj = js.Dynamic.newInstance(THREE.Object3D)() | |
obj.position.x = 900 * js.Math.sin(phi) | |
obj.position.y = -(i * 8) + 450 | |
obj.position.z = 900 * js.Math.cos(phi) | |
vector.x = obj.position.x * 2 | |
vector.y = obj.position.y | |
vector.z = obj.position.z * 2 | |
obj.lookAt(vector) | |
targets.helix.push(obj) | |
} | |
} | |
// grid | |
jfor[Int](0, _ < objects.length, _ + 1) { i: Int => | |
var obj = js.Dynamic.newInstance(THREE.Object3D)() | |
obj.position.x = ((i % 5) * 400) - 800 | |
obj.position.y = (-(js.Math.floor(i / 5) % 5) * 400) + 800 | |
obj.position.z = js.Math.floor(i / 25) * 1000 - 2000 | |
targets.grid.push(obj) | |
} | |
// | |
renderer = js.Dynamic.newInstance(THREE.CSS3DRenderer)() | |
renderer.setSize(window.innerWidth, window.innerHeight) | |
renderer.domElement.style.position = "absolute" | |
document.getElementById("container").appendChild(renderer.domElement.asInstanceOf[dom.Node]) | |
// | |
controls = js.Dynamic.newInstance(THREE.TrackballControls)(camera, renderer.domElement) | |
controls.rotateSpeed = 0.5 | |
controls.minDistance = 500 | |
controls.maxDistance = 6000 | |
controls.addEventListener("change", () => render()) | |
document.getElementById("table").addEventListener("click", (x: dom.Event) => transform(targets.table, 2000), false) | |
document.getElementById("sphere").addEventListener("click", (x: dom.Event) => transform(targets.sphere, 2000), false) | |
document.getElementById("helix").addEventListener("click", (x: dom.Event) => transform(targets.helix, 2000), false) | |
document.getElementById("grid").addEventListener("click", (x: dom.Event) => transform(targets.grid, 2000), false) | |
transform(targets.table, 1000) | |
// | |
window.addEventListener("resize", () => onWindowResize(), false) | |
} | |
def transform(targets: js.Array[*], durMs: js.Number) { | |
console.log("transforming to", targets(0)) | |
TWEENJS.removeAll() | |
var i = 0 | |
while (i < objects.length) { | |
val obj = objects(i) | |
val target = targets(i) | |
new Tween(obj.position) | |
.to(*(x = target.position.x, y = target.position.y, z = target.position.z), js.Math.random() * durMs + durMs) | |
.easing(TWEENJS.Easing.Bounce.Out _) | |
.start() | |
new Tween(obj.rotation) | |
.to(*(x = target.rotation.x, y = target.rotation.y, z = target.rotation.z), js.Math.random() * durMs + durMs) | |
.easing(TWEENJS.Easing.Bounce.Out _) | |
.start() | |
i += 1 | |
} | |
new Tween(window).to(*(), durMs * 2).onUpdate(() => render()).start() | |
} | |
def onWindowResize() { | |
camera.aspect = window.innerWidth / window.innerHeight | |
camera.updateProjectionMatrix() | |
renderer.setSize(window.innerWidth, window.innerHeight) | |
render() | |
} | |
def animate() { | |
window.requestAnimationFrame(() => animate()) | |
TWEENJS.update() | |
controls.update() | |
} | |
def render() { | |
renderer.render(scene, camera) | |
} | |
} | |
} |
This file contains 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
package cgta.oscala | |
package wraps.tween | |
import scala.scalajs.js | |
import scala.scalajs.js.annotation.JSName | |
@JSName("TWEEN") | |
object TWEENJS extends js.Object { | |
// Type definitions for tween.js r12 | |
// Project: https://github.com/sole/tween.js/ | |
// Definitions by: sunetos <https://github.com/sunetos>, jzarnikov <https://github.com/jzarnikov> | |
// Definitions: https://github.com/borisyankov/DefinitelyTyped | |
val REVISION: js.String = ??? | |
def getAll(): js.Array[Tween] = ??? | |
def removeAll(): Unit = ??? | |
def add(tween: Tween): Unit = ??? | |
def remove(tween: Tween): Unit = ??? | |
def update(time: js.Number = ???): js.Boolean = ??? | |
val Easing : Tween.Easing = ??? | |
val Interpolation: Tween.Interpolation = ??? | |
} | |
@JSName("TWEEN.Tween") | |
class Tween(obj: js.Any = ???) extends js.Object { | |
def to(properties: js.Any, duration: js.Number): Tween = ??? | |
def start(time: js.Number = ???): Tween = ??? | |
def stop(): Tween = ??? | |
def delay(amount: js.Number): Tween = ??? | |
def easing(easing: js.Function1[js.Number, js.Number]): Tween = ??? | |
def interpolation(interpolation: js.Function2[js.Array[js.Number], js.Number, js.Number]): Tween = ??? | |
def chain(tweens: Tween*): Tween = ??? | |
def onStart(callback: js.Function1[js.Any, Unit]): Tween = ??? | |
def onUpdate(callback: js.Function1[js.Any, Unit]): Tween = ??? | |
def onComplete(callback: js.Function1[js.Any, Unit]): Tween = ??? | |
def onStart(callback: js.Function0[Unit]): Tween = ??? | |
def onUpdate(callback: js.Function0[Unit]): Tween = ??? | |
def onComplete(callback: js.Function0[Unit]): Tween = ??? | |
def update(time: js.Number): js.Boolean = ??? | |
def repeat(times: js.Number): Tween = ??? | |
def yoyo(enable: js.Boolean): Tween = ??? | |
} | |
object Tween { | |
trait InOutEasingFns extends js.Object { | |
def In(x: js.Number): js.Number = ??? | |
def Out(x: js.Number): js.Number = ??? | |
def InOut(x: js.Number): js.Number = ??? | |
} | |
trait LinearEasingFns extends js.Object { | |
def None(x: js.Number): js.Number | |
} | |
trait Easing extends js.Object { | |
val Linear : LinearEasingFns = ??? | |
val Quadratic : InOutEasingFns = ??? | |
val Cubic : InOutEasingFns = ??? | |
val Quartic : InOutEasingFns = ??? | |
val Quintic : InOutEasingFns = ??? | |
val Sinusoidal : InOutEasingFns = ??? | |
val Exponential: InOutEasingFns = ??? | |
val Circular : InOutEasingFns = ??? | |
val Elastic : InOutEasingFns = ??? | |
val Back : InOutEasingFns = ??? | |
val Bounce : InOutEasingFns = ??? | |
} | |
trait InterpolationUtils extends js.Object { | |
def Linear(p0: js.Number, p1: js.Number, t: js.Number): js.Number = ??? | |
def Bernstein(n: js.Number, i: js.Number): js.Number = ??? | |
def Factorial(n: js.Number): js.Number = ??? | |
} | |
trait Interpolation extends js.Object { | |
def Linear(v: js.Array[js.Number], k: js.Number): js.Number = ??? | |
def Bezier(v: js.Array[js.Number], k: js.Number): js.Number = ??? | |
def CatmullRom(v: js.Array[js.Number], k: js.Number): js.Number = ??? | |
val Utils: InterpolationUtils = ??? | |
} | |
} |
This file contains 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
package cgta.oscala | |
package sjs | |
import scala.scalajs.js | |
import cgta.oscala.sjs.lang.JsConsole | |
object OScalaSjsExports extends OScalaSjsExports | |
trait OScalaSjsExports { | |
val global = js.Dynamic.global | |
val console = global.console.asInstanceOf[JsConsole] | |
val JSON = global.JSON | |
val undefined = global.undefined | |
val window = global.window | |
val document = org.scalajs.dom.document | |
def newObject = js.Object().asInstanceOf[js.Dynamic] | |
// def new_*(clazz: js.Dynamic)(): js.Dynamic = js.Dynamic.newInstance(clazz)() | |
// def new_*(clazz: js.Dynamic)(a0: js.Any): js.Dynamic = js.Dynamic.newInstance(clazz)(a0) | |
// def new_*(clazz: js.Dynamic)(a0: js.Any, a1: js.Any): js.Dynamic = js.Dynamic.newInstance(clazz)(a0, a1) | |
// def new_*(clazz: js.Dynamic)(a0: js.Any, a1: js.Any, a2: js.Any): js.Dynamic = js.Dynamic.newInstance(clazz)(a0, a1, a2) | |
// def new_*(clazz: js.Dynamic)(args: js.Any*): js.Dynamic = js.Dynamic.newInstance(clazz)(args: _*) | |
// def new_*(clazz: js.Dynamic)(args: js.Any*): js.Dynamic = js.Dynamic.newInstance(clazz)(args: _*) | |
val * = js.Dynamic.literal | |
type * = js.Dynamic | |
type ** = js.Object with js.Dynamic | |
def log(args: js.Any*) = console.log(args: _*) | |
def jfor[A](init: A, p: A => Boolean, inc: A => A)(f: A => Unit) { | |
var x = init | |
while (p(x)) { | |
f(x) | |
x = inc(x) | |
} | |
} | |
// implicit object QueueExecutionContext extends ExecutionContext { | |
// | |
// def execute(runnable: Runnable) = { | |
// val lambda: js.Function = () => | |
// try {runnable.run()} catch {case t: Throwable => reportFailure(t)} | |
// js.Dynamic.global.setTimeout(lambda, 0) | |
// } | |
// | |
// def reportFailure(t: Throwable) = | |
// Console.err.println("Failure in async execution: " + t) | |
// | |
// } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment