demo.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. 'use strict'
  2. var now = require('right-now')
  3. var bunny = require('bunny')
  4. var perspective = require('gl-mat4/perspective')
  5. var fit = require('canvas-fit')
  6. var createContext = require('gl-context')
  7. var createAxes = require('gl-axes')
  8. var createMesh = require('gl-simplicial-complex')
  9. var createCamera = require('../view')
  10. //Set up WebGL
  11. var canvas = document.createElement('canvas')
  12. document.body.appendChild(canvas)
  13. window.addEventListener('resize', fit(canvas), false)
  14. var gl = createContext(canvas, {}, render)
  15. var controlDiv = document.createElement('div')
  16. controlDiv.style.position = 'absolute'
  17. controlDiv.style['z-index'] = 10
  18. controlDiv.style.left = '10px'
  19. controlDiv.style.top = '10px'
  20. document.body.appendChild(controlDiv)
  21. var commandList = [
  22. 'Rotate - Hold left mouse',
  23. 'Roll - Hold shift + left mouse',
  24. 'Pan - Hold right mouse',
  25. 'Zoom - Mouse wheel',
  26. 'Translate - Hold control + left mouse'
  27. ]
  28. var commandContainer = document.createElement('div')
  29. commandContainer.style['font-size'] = '75%'
  30. controlDiv.appendChild(commandContainer)
  31. commandList.forEach(function(str) {
  32. var container = document.createElement('p')
  33. container.appendChild(document.createTextNode(str))
  34. commandContainer.appendChild(container)
  35. })
  36. function appendItem(label, item) {
  37. var container = document.createElement('p')
  38. container.appendChild(document.createTextNode(label))
  39. container.appendChild(item)
  40. controlDiv.appendChild(container)
  41. }
  42. var delayControl = document.createElement('input')
  43. delayControl.type = 'range'
  44. delayControl.min = 0
  45. delayControl.max = 200
  46. delayControl.value = 30
  47. appendItem('Delay:', delayControl)
  48. var zoomControl = document.createElement('input')
  49. zoomControl.type = 'range'
  50. zoomControl.min = 1
  51. zoomControl.max = 1000
  52. zoomControl.value = 50
  53. appendItem('Distance:', zoomControl)
  54. var rotateSensitivity = document.createElement('input')
  55. rotateSensitivity.type = 'range'
  56. rotateSensitivity.min = -10
  57. rotateSensitivity.max = 10
  58. rotateSensitivity.value = 0
  59. appendItem('Rotation Sensitivity:', rotateSensitivity)
  60. var zoomSensitivity = document.createElement('input')
  61. zoomSensitivity.type = 'range'
  62. zoomSensitivity.min = -10
  63. zoomSensitivity.max = 10
  64. zoomSensitivity.value = 0
  65. appendItem('Zoom Sensitivity:', zoomSensitivity)
  66. var flipXControl = document.createElement('input')
  67. flipXControl.type = 'checkbox'
  68. appendItem('Flip X:', flipXControl)
  69. var flipYControl = document.createElement('input')
  70. flipYControl.type = 'checkbox'
  71. appendItem('Flip Y:', flipYControl)
  72. var modes = ['turntable', 'orbit', 'matrix']
  73. var modeSelect = document.createElement('select')
  74. for(var i=0; i<modes.length; ++i) {
  75. var option = document.createElement('option')
  76. option.text = modes[i]
  77. option.value = modes[i]
  78. modeSelect.add(option)
  79. }
  80. appendItem('Mode:', modeSelect)
  81. var lookAtButton = document.createElement('input')
  82. lookAtButton.type = 'submit'
  83. lookAtButton.value = 'Reset'
  84. controlDiv.appendChild(lookAtButton)
  85. var statusElement = document.createElement('p')
  86. statusElement.style['font-size'] = '30%'
  87. controlDiv.appendChild(statusElement)
  88. //Create objects for rendering
  89. var bounds = [[-10,-10,-10], [10,10,10]]
  90. var mesh = createMesh(gl, {
  91. cells: bunny.cells,
  92. positions: bunny.positions,
  93. colormap: 'jet'
  94. })
  95. var axes = createAxes(gl, {
  96. bounds: bounds,
  97. tickSpacing: [1,1,1],
  98. textSize: 0.05
  99. })
  100. //Set up camera
  101. var projectionMatrix = new Array(16)
  102. var camera = createCamera({
  103. center: [
  104. 0.5*(bounds[0][0]+bounds[1][0]),
  105. 0.5*(bounds[0][1]+bounds[1][1]),
  106. 0.5*(bounds[0][2]+bounds[1][2]) ],
  107. eye: [0, 0, bounds[1][2]],
  108. distanceLimits: [1, 1000]
  109. })
  110. //Hook event listeners
  111. var lastX = 0, lastY = 0
  112. document.oncontextmenu = function(e) {
  113. e.preventDefault()
  114. e.stopPropagation()
  115. return false
  116. }
  117. modeSelect.addEventListener('change', function(ev) {
  118. camera.setMode(modeSelect.value)
  119. })
  120. canvas.addEventListener('mousemove', function(ev) {
  121. var dx = (ev.clientX - lastX) / gl.drawingBufferWidth
  122. var dy = -(ev.clientY - lastY) / gl.drawingBufferHeight
  123. var w = Math.exp(+rotateSensitivity.value)
  124. var flipX = flipXControl.checked
  125. var flipY = flipYControl.checked
  126. if(ev.which === 1) {
  127. if(ev.shiftKey) {
  128. camera.rotate(now(), 0, 0, w*dx)
  129. } else if(ev.ctrlKey) {
  130. camera.translate(now(), dx, dy, 0)
  131. } else {
  132. if(flipX) { dx = -dx }
  133. if(flipY) { dy = -dy }
  134. camera.rotate(now(), w*dx, w*dy)
  135. }
  136. }
  137. if(ev.which === 3) {
  138. camera.pan(now(), dx, dy)
  139. }
  140. lastX = ev.clientX
  141. lastY = ev.clientY
  142. })
  143. canvas.addEventListener('wheel', function(e) {
  144. var w = +zoomSensitivity.value
  145. camera.pan(now(), 0, 0, Math.exp(w) * e.deltaY)
  146. })
  147. lookAtButton.addEventListener('click', function() {
  148. camera.lookAt(now(),
  149. [ 0, 0, -50 ],
  150. [ 0.5*(bounds[0][0]+bounds[1][0]),
  151. 0.5*(bounds[0][1]+bounds[1][1]),
  152. 0.5*(bounds[0][2]+bounds[1][2]) ],
  153. [ 0, 1, 0 ])
  154. })
  155. zoomControl.addEventListener('change', function() {
  156. camera.setDistance(now(), +zoomControl.value)
  157. })
  158. //Redraw frame
  159. function render() {
  160. //Update camera parameters
  161. var t = now()
  162. var delay = +delayControl.value
  163. camera.idle(t - delay)
  164. camera.flush(t - 100 * (delay + 1))
  165. //Compute parameters
  166. var cameraParams = {
  167. view: camera.getMatrix(t - 2*delay),
  168. projection: perspective(
  169. [],
  170. Math.PI/4.0,
  171. gl.drawingBufferWidth/gl.drawingBufferHeight,
  172. 0.1,
  173. 1000.0)
  174. }
  175. //Draw everything
  176. gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight)
  177. gl.enable(gl.DEPTH_TEST)
  178. axes.draw(cameraParams)
  179. mesh.draw(cameraParams)
  180. var d = camera.getDistance(t)
  181. if(d !== +zoomControl.value) {
  182. zoomControl.value = d
  183. }
  184. //Write out status stuff
  185. statusElement.innerHTML =
  186. '<p>Distance=' + camera.getDistance(t-2*delay) +
  187. '</p><p>Up=[' + camera.getUp(t-2*delay).join() +
  188. ']</p><p>Eye=[' + camera.getEye(t-2*delay).join() +
  189. ']</p><p>Matrix=</p><table><tr><td>' + cameraParams.view.slice(0,4).join('</td><td>') +
  190. '</td></tr><tr><td>' + cameraParams.view.slice(4,8).join('</td><td>') +
  191. '</td></tr><tr><td>' + cameraParams.view.slice(8,12).join('</td><td>') +
  192. '</td></tr><tr><td>' + cameraParams.view.slice(12,16).join('</td><td>') +
  193. '</td></tr></table><p>Rotate sensitivity:' + Math.exp(rotateSensitivity.value) +
  194. '</p><p>Zoom sensitivity:' + Math.exp(zoomSensitivity.value) + '</p>'
  195. }