├── README.md
├── basic-example
├── Cakefile
├── code.coffee
└── index.html
├── edit-in-webpage
└── index.html
└── multiple-views
├── Cakefile
├── code.coffee
└── index.html
/README.md:
--------------------------------------------------------------------------------
1 | threejs-examples
2 | ================
3 |
4 | Collection of small Three.js examples relevant to math visualization
5 |
--------------------------------------------------------------------------------
/basic-example/Cakefile:
--------------------------------------------------------------------------------
1 | fs = require 'fs'
2 | {print} = require 'util'
3 | {spawn, exec} = require 'child_process'
4 |
5 | log = (message, explanation) ->
6 | console.log message + ' ' + (explanation or '')
7 |
8 | build = (watch, callback) ->
9 | if typeof watch is 'function'
10 | callback = watch
11 | watch = false
12 | options = ['-c','-m','code.coffee']
13 | options.unshift '-w' if watch
14 |
15 | coffee = spawn 'coffee', options
16 | coffee.stdout.on 'data', (data) -> print data.toString()
17 | coffee.stderr.on 'data', (data) -> log data.toString()
18 | coffee.on 'exit', (status) -> callback?() if status is 0
19 |
20 | task 'sbuild', 'generate javascript files.', ->
21 | build -> log "Done building."
--------------------------------------------------------------------------------
/basic-example/code.coffee:
--------------------------------------------------------------------------------
1 |
2 | # The Mathematics
3 |
4 | gcd = (a,b,depth=0) ->
5 | switch
6 | when a > b then gcd(a-b,b,depth+1)
7 | when a < b then gcd(a,b-a,depth+1)
8 | when a == b then [a, depth]
9 | else "error"
10 |
11 | canonicalize = (a,b) ->
12 | [g,d] = gcd(a,b)
13 | [a/g, b/g]
14 |
15 |
16 | # Helper Functions for Creating Three.js Objects
17 |
18 | remove_duplicates = (arr) ->
19 | output = {}
20 | output[arr[key]] = arr[key] for key in [0...arr.length]
21 | value for key, value of output
22 |
23 | gcd_geometry = (boxsize=10) ->
24 | M = boxsize
25 | S = []
26 | for a in [1..M]
27 | for b in [1..M]
28 | S.push(canonicalize(a,b))
29 | S = remove_duplicates(S)
30 | console.log(S)
31 | pair2line = (p,q) ->
32 | l = Math.min(M/p,M/q)
33 | [g,depth] = gcd(p,q)
34 | { from: [p,q,1], to: [l*p,l*q,l], color: depth/M }
35 | ( pair2line(p,q) for [p,q] in S )
36 |
37 | drawline = (from,to,material) ->
38 | geometry = new THREE.Geometry()
39 | geometry.vertices[0] = new THREE.Vector3( from[0], from[1], from[2] )
40 | geometry.vertices[1] = new THREE.Vector3( to[0], to[1], to[2] )
41 | new THREE.Line(geometry, material, THREE.LineStrip)
42 |
43 | drawcube = (M,material) ->
44 | group = new THREE.Object3D()
45 | group.add(drawline(a,b,material)) for [a,b] in [
46 | [[0,0,0], [M,0,0]],
47 | [[0,0,0], [0,M,0]],
48 | [[0,0,0], [0,0,M]],
49 | [[M,0,0], [M,0,M]],
50 | [[M,0,0], [M,M,0]],
51 | [[0,M,0], [0,M,M]],
52 | [[0,M,0], [M,M,0]],
53 | [[0,0,M], [M,0,M]],
54 | [[0,0,M], [0,M,M]],
55 | [[M,M,0], [M,M,M]],
56 | [[0,M,M], [M,M,M]],
57 | [[M,0,M], [M,M,M]] ]
58 | group
59 |
60 |
61 | # Setup Three.js
62 |
63 | init = (boxsize) ->
64 | renderer = new THREE.SVGRenderer()
65 | renderer.setSize( window.innerWidth, window.innerHeight )
66 | document.body.appendChild( renderer.domElement )
67 |
68 | alpha = 1
69 | aspect = window.innerWidth / window.innerHeight
70 |
71 | camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 1, 1000 )
72 | #camera = new THREE.OrthographicCamera( -alpha*boxsize*aspect, alpha*boxsize*aspect, alpha*boxsize, -alpha*boxsize, 1, 1000 );
73 |
74 | camera.position.z = 50
75 |
76 | scene = new THREE.Scene()
77 |
78 | group = new THREE.Object3D()
79 |
80 | group.add(drawcube(boxsize, new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 2} )))
81 |
82 | for line in gcd_geometry(boxsize)
83 | color = new THREE.Color()
84 | color.setHSL(line.color, 0.8, 0.4)
85 | material = new THREE.LineBasicMaterial( { color: color, dashSize: 3, gapSize: 1, linewidth: 2} )
86 | group.add(drawline(line.from,line.to,material))
87 |
88 | scene.add(group)
89 |
90 | group.rotation.x = 3.1415 * (- 0.5 )
91 | group.position.x = -5
92 | group.position.y = -5
93 |
94 | render = () ->
95 | renderer.render( scene, camera )
96 |
97 | controls = new THREE.OrbitControls( camera )
98 | controls.addEventListener( 'change', render )
99 |
100 | render
101 |
102 |
103 | # Main
104 |
105 | render = init(10)
106 |
107 | render()
--------------------------------------------------------------------------------
/basic-example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/edit-in-webpage/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Interactive SVG Snapshot from Three.js Visualization
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
30 |
31 |
32 |
33 |
37 |
38 |
39 |
40 |
41 |
42 | Visualization
43 |
44 |
45 | Snap!
46 |
47 | Snapshot
48 |
49 |
53 |
54 |
58 |
59 |
68 |
69 | Editor
70 |
188 |
189 | Run!
190 |
191 |
208 |
209 |
210 |
247 |
248 |
--------------------------------------------------------------------------------
/multiple-views/Cakefile:
--------------------------------------------------------------------------------
1 | fs = require 'fs'
2 | {print} = require 'util'
3 | {spawn, exec} = require 'child_process'
4 |
5 | log = (message, explanation) ->
6 | console.log message + ' ' + (explanation or '')
7 |
8 | build = (watch, callback) ->
9 | if typeof watch is 'function'
10 | callback = watch
11 | watch = false
12 | options = ['-c','-m','code.coffee']
13 | options.unshift '-w' if watch
14 |
15 | coffee = spawn 'coffee', options
16 | coffee.stdout.on 'data', (data) -> print data.toString()
17 | coffee.stderr.on 'data', (data) -> log data.toString()
18 | coffee.on 'exit', (status) -> callback?() if status is 0
19 |
20 | task 'sbuild', 'generate javascript files.', ->
21 | build -> log "Done building."
--------------------------------------------------------------------------------
/multiple-views/code.coffee:
--------------------------------------------------------------------------------
1 |
2 | # The Mathematics
3 |
4 | gcd = (a,b,depth=0) ->
5 | switch
6 | when a > b then gcd(a-b,b,depth+1)
7 | when a < b then gcd(a,b-a,depth+1)
8 | when a == b then [a, depth]
9 | else "error"
10 |
11 | canonicalize = (a,b) ->
12 | [g,d] = gcd(a,b)
13 | [a/g, b/g]
14 |
15 |
16 | # Helper Functions for Creating Three.js Objects
17 |
18 | remove_duplicates = (arr) ->
19 | output = {}
20 | output[arr[key]] = arr[key] for key in [0...arr.length]
21 | value for key, value of output
22 |
23 | gcd_geometry = (boxsize=10) ->
24 | M = boxsize
25 | S = []
26 | for a in [1..M]
27 | for b in [1..M]
28 | S.push(canonicalize(a,b))
29 | S = remove_duplicates(S)
30 | console.log(S)
31 | pair2line = (p,q) ->
32 | l = Math.min(M/p,M/q)
33 | [g,depth] = gcd(p,q)
34 | { from: [p,q,1], to: [l*p,l*q,l], color: depth/M }
35 | ( pair2line(p,q) for [p,q] in S )
36 |
37 | drawline = (from,to,material) ->
38 | geometry = new THREE.Geometry()
39 | geometry.vertices[0] = new THREE.Vector3( from[0], from[1], from[2] )
40 | geometry.vertices[1] = new THREE.Vector3( to[0], to[1], to[2] )
41 | new THREE.Line(geometry, material, THREE.LineStrip)
42 |
43 | drawcube = (M,material) ->
44 | group = new THREE.Object3D()
45 | group.add(drawline(a,b,material)) for [a,b] in [
46 | [[0,0,0], [M,0,0]],
47 | [[0,0,0], [0,M,0]],
48 | [[0,0,0], [0,0,M]],
49 | [[M,0,0], [M,0,M]],
50 | [[M,0,0], [M,M,0]],
51 | [[0,M,0], [0,M,M]],
52 | [[0,M,0], [M,M,0]],
53 | [[0,0,M], [M,0,M]],
54 | [[0,0,M], [0,M,M]],
55 | [[M,M,0], [M,M,M]],
56 | [[0,M,M], [M,M,M]],
57 | [[M,0,M], [M,M,M]] ]
58 | group
59 |
60 |
61 | from_rgb = (triple) ->
62 | new THREE.Color().setRGB( triple[0], triple[1], triple[2] )
63 |
64 | # Setup Three.js
65 |
66 | init = (boxsize) ->
67 | renderer = new THREE.WebGLRenderer()
68 | renderer.setSize( window.innerWidth, window.innerHeight )
69 | document.body.appendChild( renderer.domElement )
70 |
71 | alpha = 1
72 | aspect = window.innerWidth / window.innerHeight
73 |
74 | camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 1, 1000 )
75 | #camera = new THREE.OrthographicCamera( -alpha*boxsize*aspect, alpha*boxsize*aspect, alpha*boxsize, -alpha*boxsize, 1, 1000 );
76 |
77 | camera.position.z = 50
78 |
79 | scene = new THREE.Scene()
80 |
81 | group = new THREE.Object3D()
82 |
83 | group.add(drawcube(boxsize, new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 2} )))
84 |
85 | for line in gcd_geometry(boxsize)
86 | color = new THREE.Color()
87 | color.setHSL(line.color, 0.8, 0.4)
88 | material = new THREE.LineBasicMaterial( { color: color, dashSize: 3, gapSize: 1, linewidth: 2} )
89 | group.add(drawline(line.from,line.to,material))
90 |
91 | scene.add(group)
92 |
93 | group.rotation.x = 3.1415 * (- 0.5 )
94 | group.position.x = -5
95 | group.position.y = -5
96 |
97 | render = () ->
98 | views = { left: {
99 | left: 0,
100 | bottom: 0,
101 | width: 0.67,
102 | height: 1,
103 | background: [0.5, 0.5, 0.7]
104 | }, bottom_right: {
105 | left: 0.67,
106 | bottom: 0,
107 | width: 0.33,
108 | height: 0.5,
109 | background: [0.5, 0.7, 0.5]
110 | }, top_right: {
111 | left: 0.67,
112 | bottom: 0.5,
113 | width: 0.33,
114 | height: 0.5,
115 | background: [0.7, 0.5, 0.5]
116 | }
117 | }
118 |
119 | render_view = (view, scene, camera) ->
120 | left = Math.floor( window.innerWidth * view.left )
121 | bottom = Math.floor( window.innerHeight * view.bottom )
122 | width = Math.floor( window.innerWidth * view.width )
123 | height = Math.floor( window.innerHeight * view.height )
124 |
125 | renderer.setSize(window.innerWidth, window.innerHeight)
126 | renderer.setViewport(left,bottom,width,height)
127 | renderer.setScissor(left,bottom,width,height)
128 | renderer.enableScissorTest(true)
129 | renderer.setClearColor(from_rgb(view.background))
130 |
131 | camera.aspect = width / height
132 | camera.updateProjectionMatrix()
133 |
134 | renderer.render( scene, camera )
135 |
136 | render_view(views.left, scene, camera)
137 | render_view(views.top_right, scene, camera)
138 | render_view(views.bottom_right, scene, camera)
139 |
140 | controls = new THREE.OrbitControls( camera )
141 | controls.addEventListener( 'change', render )
142 |
143 | render
144 |
145 |
146 | # Main
147 |
148 | render = init(10)
149 |
150 | render()
--------------------------------------------------------------------------------
/multiple-views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------