summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJules Laplace <jules@okfoc.us>2015-02-04 13:30:39 -0500
committerJules Laplace <jules@okfoc.us>2015-02-04 13:30:39 -0500
commit4c7cad2ebfc44244ba845c1574271e48b9f2b740 (patch)
treea676d31abcb141a2a52a1351c0271ccc5099cc64
parenteb1f73bd8be4ba8909ec5c7cd83c37269fbff31b (diff)
orbit camera
-rw-r--r--public/assets/javascripts/mx/extensions/mx.orbitCamera.js80
-rw-r--r--public/assets/javascripts/rectangles/util/mouse.js8
-rw-r--r--public/assets/test/orbit.html140
-rw-r--r--public/assets/test/ortho.html50
4 files changed, 235 insertions, 43 deletions
diff --git a/public/assets/javascripts/mx/extensions/mx.orbitCamera.js b/public/assets/javascripts/mx/extensions/mx.orbitCamera.js
new file mode 100644
index 0000000..b3dcc43
--- /dev/null
+++ b/public/assets/javascripts/mx/extensions/mx.orbitCamera.js
@@ -0,0 +1,80 @@
+MX.OrbitCamera = function(opt){
+ var exports = {}, bound = false
+ exports.opt = opt = defaults(opt, {
+ el: window, // object to bind events on
+ camera: scene.camera, // camera object we'll be moving
+ radius: 100,
+ radiusRange: [ 10, 1000 ],
+ rotationX: PI/2,
+ rotationY: 0,
+ center: { x: 0, y: 0, z: 0 },
+ sensitivity: 10, // moving 1 pixel is like moving N radians
+ ease: 10,
+ })
+ var rx, ry, px, py, epsilon = 1e-10, dragging = false
+ exports.init = function(){
+ ry = opt.rotationY
+ rx = opt.rotationX
+ exports.bind()
+ }
+ exports.toggle = function(state){
+ if (state) exports.bind()
+ else exports.unbind()
+ }
+ exports.bind = function(){
+ if (bound) return;
+ bound = true
+ opt.el.addEventListener("mousedown", down)
+ opt.el.addEventListener("mousemove", move)
+ opt.el.addEventListener("mouseup", up)
+ }
+ exports.unbind = function(){
+ if (! bound) return;
+ bound = false
+ opt.el.removeEventListener("mousedown", down)
+ opt.el.removeEventListener("mousemove", move)
+ opt.el.removeEventListener("mouseup", up)
+ }
+ function down (e) {
+ px = e.pageX
+ py = e.pageY
+ dragging = true
+ }
+ function move (e) {
+ if (! dragging) return
+ exports.delta(px- e.pageX, py - e.pageY)
+ px = e.pageX
+ py = e.pageY
+ }
+ function up (e) {
+ dragging = false
+ }
+ exports.delta = function(x,y){
+ opt.rotationY += x/window.innerWidth * opt.sensitivity
+ opt.rotationX = clamp( opt.rotationX + y/window.innerHeight * opt.sensitivity, 0, PI)
+ }
+ exports.move = function(y, x){
+ opt.rotationY = y
+ if (typeof x == "number") { opt.rotationX = x }
+ }
+ exports.update = function(){
+ if (abs(ry - opt.rotationY) > epsilon) {
+ ry = avg(ry, opt.rotationY, opt.ease)
+ }
+ else {
+ ry = opt.rotationY
+ }
+ if (abs(rx - opt.rotationX) > epsilon) {
+ rx = avg(rx, opt.rotationX, opt.ease)
+ }
+ else {
+ rx = opt.rotationX
+ }
+ opt.camera.x = opt.center.x + opt.radius * sin(rx) * cos(ry)
+ opt.camera.z = opt.center.y + opt.radius * sin(rx) * sin(ry)
+ opt.camera.y = opt.center.z + opt.radius * cos(rx)
+ opt.camera.rotationX = PI/2 - rx
+ opt.camera.rotationY = ry + PI/2
+ }
+ return exports
+}
diff --git a/public/assets/javascripts/rectangles/util/mouse.js b/public/assets/javascripts/rectangles/util/mouse.js
index cb36038..86edf6c 100644
--- a/public/assets/javascripts/rectangles/util/mouse.js
+++ b/public/assets/javascripts/rectangles/util/mouse.js
@@ -76,6 +76,14 @@ function mouse (opt) {
window.addEventListener("mousemove", base.mousemove)
window.addEventListener("mouseup", base.mouseup)
}
+ base.unbind = function(){
+ if (opt.el) {
+ opt.el.removeEventListener("mousedown", base.mousedown)
+ opt.el.removeEventListener("contextmenu", base.contextmenu)
+ }
+ window.removeEventListener("mousemove", base.mousemove)
+ window.removeEventListener("mouseup", base.mouseup)
+ }
base.bind_el = function(el){
el.addEventListener("mousedown", base.mousedown)
diff --git a/public/assets/test/orbit.html b/public/assets/test/orbit.html
new file mode 100644
index 0000000..8b45de6
--- /dev/null
+++ b/public/assets/test/orbit.html
@@ -0,0 +1,140 @@
+<style type="text/css">
+html,body{width:100%;height:100%;margin:0;padding:0;}
+body {
+ font-family: Menlo, monospace;
+ overflow: hidden;
+}
+#perspective {
+ position: absolute;
+ left:0%;
+ top:0px
+}
+#orthographic {
+ position: absolute;
+ left:50%;
+ top:0px
+}
+#hud {
+ white-space: pre;
+}
+</style>
+
+<div id="perspective"></div>
+<div id="orthographic"></div>
+
+<div id="hud"></div>
+
+<script src="/assets/javascripts/util.js"></script>
+<script src="/assets/javascripts/vendor/bower_components/jquery/dist/jquery.min.js"></script>
+<script src="/assets/javascripts/vendor/bower_components/lodash/lodash.min.js"></script>
+<script src="/assets/javascripts/vendor/bower_components/hidpi-canvas/dist/hidpi-canvas.js"></script>
+<script src="/assets/javascripts/vendor/polyfill.js"></script>
+<script src="/assets/javascripts/vendor/tube.js"></script>
+<script src="/assets/javascripts/mx/mx.js"></script>
+<script src="/assets/javascripts/mx/extensions/mx.scene.js"></script>
+<script src="/assets/javascripts/mx/extensions/mx.orbitCamera.js"></script>
+<script src="/assets/javascripts/rectangles/util/constants.js"></script>
+<script src="/assets/javascripts/rectangles/util/mouse.js"></script>
+<script src="/assets/javascripts/rectangles/models/vec2.js"></script>
+<script src="/assets/javascripts/rectangles/models/rect.js"></script>
+<script src="/assets/javascripts/rectangles/models/rect.js"></script>
+<script src="/assets/javascripts/rectangles/engine/map/_map.js"></script>
+<script src="/assets/javascripts/rectangles/engine/map/draw.js"></script>
+
+<script>
+
+Map.UI = Map.UI || {}
+Map.UI.Ortho = function(map){
+
+ var base = this
+
+ base.creating = base.dragging = base.resizing = false
+
+ base.mouse = new mouse({
+ el: map.el,
+ move: function(e, cursor){
+ cursor.x.div(map.dimensions.a).add(0.5).mul(map.dimensions.a / map.zoom).add(map.center.a)
+ cursor.y.div(map.dimensions.b).sub(0.5).mul(map.dimensions.b / map.zoom).sub(map.center.b)
+ },
+ })
+}
+
+var scene, map, controls
+
+map = new Map ({
+ type: "ortho",
+ el: document.querySelector("#orthographic"),
+ width: window.innerWidth/2,
+ height: window.innerHeight,
+})
+
+var ctx = map.draw.ctx
+
+document.addEventListener('DOMContentLoaded', build_circle)
+function add_mx_point (p, theta, i) {
+ var mx = new MX.Object3D()
+ mx.updateChildren = false
+ mx.move({
+ x: p.a,
+ y: i/4,
+ z: p.b,
+ rotationY: -theta,
+ width: 1,
+ height: i/2,
+ })
+ mx.el.style.backgroundColor = 'rgb(' + [abs(floor(p.a*30)), 0, abs(floor(p.b*30))] + ')'
+ mx.el.style.backfaceVisibility = "visible"
+ scene.add(mx)
+ mx.update()
+}
+function build_circle () {
+ scene = new MX.Scene().addTo("#perspective")
+ scene.camera.move({
+ "x": 0,
+ "y": 0,
+ "z": 0,
+ "rotationX": 0, // PI/2,
+ "rotationY": PI/2, // PI
+ })
+ scene.camera.radius = 20
+
+ scene.width = window.innerWidth/2
+ scene.height = window.innerHeight
+ scene.perspective = window.innerHeight
+
+ var theta, rad = 10;
+ for (var i = 0; i < 100; i++) {
+ theta = (i/100 * TWO_PI)
+ add_mx_point({
+ a: sin(theta) * rad,
+ b: cos(theta) * rad,
+ }, theta, i)
+ }
+
+ scene.update()
+
+ controls = new MX.OrbitCamera()
+ controls.init()
+
+ console.log("ready..perhaps")
+ animate(0)
+}
+function animate(time){
+ requestAnimationFrame(animate)
+ map.update(time)
+
+ controls.update()
+ hud.innerHTML = scene.camera.toString()
+ scene.update()
+
+ map.draw.ctx.save()
+ map.draw.translate()
+
+ map.draw.coords()
+ map.draw.mouse(map.ui.mouse.cursor)
+ map.draw.camera(scene.camera)
+
+ map.draw.ctx.restore()
+}
+
+</script> \ No newline at end of file
diff --git a/public/assets/test/ortho.html b/public/assets/test/ortho.html
index bd94a51..57e050c 100644
--- a/public/assets/test/ortho.html
+++ b/public/assets/test/ortho.html
@@ -32,6 +32,7 @@ body {
<script src="/assets/javascripts/vendor/tube.js"></script>
<script src="/assets/javascripts/mx/mx.js"></script>
<script src="/assets/javascripts/mx/extensions/mx.scene.js"></script>
+<script src="/assets/javascripts/mx/extensions/mx.orbitCamera.js"></script>
<script src="/assets/javascripts/rectangles/util/constants.js"></script>
<script src="/assets/javascripts/rectangles/util/mouse.js"></script>
<script src="/assets/javascripts/rectangles/models/vec2.js"></script>
@@ -94,43 +95,6 @@ Map.UI.Ortho = function(map){
}
})
}
-MX.OrbitCamera = function(opt){
- var exports = {}, bound = false
- exports.opt = opt = defaults(opt, {
- el: window, // object to bind events on
- camera: scene.camera, // camera object we'll be moving
- radius: 100,
- radiusRange: [ 10, 1000 ],
- rotationX: 0,
- rotationY: 0,
- center: { x: 0, y: 0, z: 0 },
- })
- exports.init = function(){
- exports.bind()
- }
- exports.toggle = function(state){
- if (state) exports.bind()
- else exports.unbind()
- }
- exports.bind = function(){
- if (bound) return;
- bound = true
- }
- exports.unbind = function(){
- if (! bound) return;
- bound = false
- }
- exports.update = function(){
- opt.camera.x = opt.radius * sin(opt.rotationY) * cos(opt.rotationX)
- opt.camera.y = opt.radius * sin(opt.rotationY) * sin(opt.rotationX)
- opt.camera.z = opt.radius * cos(opt.rotationY)
- opt.camera.rotationX = opt.rotationX
- opt.camera.rotationY = PI-opt.rotationY
- hud.innerHTML = opt.camera.toString()
- }
-
- return exports
-}
var scene, map, controls
@@ -167,17 +131,17 @@ function polyline (time) {
}
}
document.addEventListener('DOMContentLoaded', build_circle)
-function add_mx_point (p) {
+function add_mx_point (p, i) {
var mx = new MX.Object3D()
mx.updateChildren = false
mx.move({
x: p.a,
- y: 0,
+ y: i/4,
z: p.b,
width: 1,
- height: 1,
+ height: i/2,
})
- mx.el.style.backgroundColor = "#f80"
+ mx.el.style.backgroundColor = 'rgb(' + [abs(floor(p.a*30)), 0, abs(floor(p.b*30))] + ')'
mx.el.style.backfaceVisibility = "visible"
scene.add(mx)
mx.update()
@@ -200,11 +164,11 @@ function build_circle () {
var theta, rad = 10;
for (var i = 0; i < 100; i++) {
- theta = (i/TWO_PI)
+ theta = (i/100 * TWO_PI)
add_mx_point({
a: sin(theta) * rad,
b: cos(theta) * rad,
- })
+ }, i)
}
scene.update()