From b4241d454667fa82c4980b68aeeb9deb5719d002 Mon Sep 17 00:00:00 2001 From: Thomas FORGIONE Date: Tue, 26 May 2015 11:49:24 +0200 Subject: [PATCH] Added begining of tutorial --- controllers/prototype/index.js | 9 + controllers/prototype/urls.js | 3 +- controllers/prototype/views/tutorial.jade | 8 + js/Logger.js | 35 ++- js/Makefile | 7 +- js/PointerCamera.js | 13 +- js/prototype/ArrowCamera.js | 31 +++ js/prototype/initScene.js | 14 ++ js/prototype/tutorial.js | 285 ++++++++++++++++++++++ urls.js | 1 + views/main.jade | 3 + 11 files changed, 389 insertions(+), 20 deletions(-) create mode 100644 controllers/prototype/views/tutorial.jade create mode 100644 js/prototype/tutorial.js diff --git a/controllers/prototype/index.js b/controllers/prototype/index.js index e13cff5..fe64c88 100644 --- a/controllers/prototype/index.js +++ b/controllers/prototype/index.js @@ -68,3 +68,12 @@ module.exports.replay_index = function(req, res, next) { }); }); } + +module.exports.tutorial = function(req, res) { + + + res.setHeader('Content-Type', 'text/html'); + res.render('tutorial.jade', res.lcals, function(err, result) { + res.send(result); + }); +} diff --git a/controllers/prototype/urls.js b/controllers/prototype/urls.js index 45b8113..25f84df 100644 --- a/controllers/prototype/urls.js +++ b/controllers/prototype/urls.js @@ -5,5 +5,6 @@ module.exports = { '/prototype/reverse': 'reverse', '/prototype/replay': 'replay_index', '/prototype/replay/:id': 'replay', - '/prototype/replay_info/:id': 'replay_info' + '/prototype/replay_info/:id': 'replay_info', + '/prototype/tutorial': 'tutorial' } diff --git a/controllers/prototype/views/tutorial.jade b/controllers/prototype/views/tutorial.jade new file mode 100644 index 0000000..53a8272 --- /dev/null +++ b/controllers/prototype/views/tutorial.jade @@ -0,0 +1,8 @@ +extends ./prototype + +block title + title #{title} - Prototype - Tutorial + +block configjs + script RecommendedCamera = FixedCamera; + script(src="/static/js/tutorial.min.js") diff --git a/js/Logger.js b/js/Logger.js index 44e5cc3..b3825ef 100644 --- a/js/Logger.js +++ b/js/Logger.js @@ -1,21 +1,34 @@ var BD = {}; BD.Private = {}; + BD.Private.sendData = function(url, data) { - // Append time to data - data.time = Date.now() / 1000; + if (BD.Private.enabled) { + // Append time to data + data.time = Date.now() / 1000; - var xhr = new XMLHttpRequest(); - xhr.open("POST", url, true); - xhr.setRequestHeader("Content-type", "application/json;charset=UTF-8"); + var xhr = new XMLHttpRequest(); + xhr.open("POST", url, true); + xhr.setRequestHeader("Content-type", "application/json;charset=UTF-8"); - // xhr.onreadystatechange = function() { - // if(xhr.readyState == 4 && xhr.status == 200) { - // console.log(xhr.responseText); - // } - // } + // xhr.onreadystatechange = function() { + // if(xhr.readyState == 4 && xhr.status == 200) { + // console.log(xhr.responseText); + // } + // } - xhr.send(JSON.stringify(data)); + xhr.send(JSON.stringify(data)); + } +} + +BD.Private.enabled = true; + +BD.enable = function() { + BD.Private.enabled = true; +} + +BD.disable = function() { + BD.Private.enabled = false; } BD.Private.compactCamera = function(camera) { diff --git a/js/Makefile b/js/Makefile index 111bfff..e71f582 100644 --- a/js/Makefile +++ b/js/Makefile @@ -1,7 +1,7 @@ OPT=--compilation_level SIMPLE_OPTIMIZATIONS CLOSURE=java -jar /usr/share/java/closure-compiler/closure-compiler.jar -all: Three Stats ThreeTools Bouncing Multisphere StreamingSimulator PrototypeTools PrototypeReplay PrototypeInteractive +all: Three Stats ThreeTools Bouncing Multisphere StreamingSimulator PrototypeTools PrototypeReplay PrototypeInteractive Tutorial Three: cp three/three.min.js ../static/js/ @@ -74,5 +74,10 @@ PrototypeReplay: --js prototype/replay.js \ --js_output_file ../static/js/replay.min.js +Tutorial: + $(CLOSURE) $(OPT) \ + --js prototype/tutorial.js \ + --js_output_file ../static/js/tutorial.min.js + clean: rm -rf ../static/js/* diff --git a/js/PointerCamera.js b/js/PointerCamera.js index d6d4fce..8678eb2 100644 --- a/js/PointerCamera.js +++ b/js/PointerCamera.js @@ -54,6 +54,8 @@ var PointerCamera = function() { // listenerTarget.addEventListener('mouseout', onMouseUp, false); this.collisions = true; + + this.resetElements = resetBobombElements(); } PointerCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype); PointerCamera.prototype.constructor = PointerCamera; @@ -152,18 +154,15 @@ PointerCamera.prototype.normalMotion = function(time) { } PointerCamera.prototype.reset = function() { - this.resetBobomb(); + this.resetPosition(); this.moving = false; this.movingHermite = false; (new BD.Event.ResetClicked()).send(); - // this.position.copy(new THREE.Vector3(-8.849933489419644, 9.050627639459208, 0.6192960680432451)); - // this.target.copy(new THREE.Vector3(17.945323228767702, -15.156828589982375, -16.585740412769756)); - // this.anglesFromVectors(); } -PointerCamera.prototype.resetBobomb = function() { - this.position.copy(new THREE.Vector3(34.51854618261728,10.038879540840306,-21.772598201888613)); - this.target.copy(new THREE.Vector3(-2.593404107644737,8.039712770013185,-6.983870133675925)); +PointerCamera.prototype.resetPosition = function() { + this.position.copy(this.resetElements.position); + this.target.copy(this.resetElements.target); this.anglesFromVectors(); } diff --git a/js/prototype/ArrowCamera.js b/js/prototype/ArrowCamera.js index 5ffb592..ab57f28 100644 --- a/js/prototype/ArrowCamera.js +++ b/js/prototype/ArrowCamera.js @@ -92,6 +92,37 @@ ArrowCamera.prototype.initExtremity = function() { return this.mesh; } +ArrowCamera.prototype.updateExtremity = function() { + var direction = this.target.clone(); + direction.sub(this.position); + direction.normalize(); + + var left = Tools.cross(direction, this.up); + var other = Tools.cross(direction, left); + + left.normalize(); + other.normalize(); + left = Tools.mul(left, this.size); + other = Tools.mul(other, this.size); + + this.mesh.geometry.vertices = [ + Tools.sum( Tools.sum( this.position, left), other), + Tools.diff(Tools.sum( this.position, other), left), + Tools.diff(Tools.diff(this.position, left), other), + Tools.sum( Tools.diff(this.position, other), left), + Tools.sum(this.position, direction) + ]; + + this.mesh.geometry.computeFaceNormals(); + this.mesh.geometry.verticesNeedUpdate = true; + +} + +ArrowCamera.prototype.setSize = function(size) { + this.size = size; + this.updateExtremity(); +} + // Update function ArrowCamera.prototype.update = function(mainCamera) { // Compute distance between center of camera and position diff --git a/js/prototype/initScene.js b/js/prototype/initScene.js index b09003f..c463ba6 100644 --- a/js/prototype/initScene.js +++ b/js/prototype/initScene.js @@ -63,6 +63,13 @@ function initPeachCastle(scene, collidableObjects, loader, static_path) { ); } +function resetPeachElements() { + return { + position: new THREE.Vector3(-0.18679773265763222,0.20096245470188506,0.19015771599529685), + target: new THREE.Vector3(-0.18679773265767263,0.20096245470190005,-39.8098422840047) + }; +} + function initZeldaScene(scene, collidableObjects, loader, static_path) { // Create loader if not already done if (loader === undefined) { @@ -253,6 +260,13 @@ function initBobombScene(scene, collidableObjects, loader, static_path) { //); } +function resetBobombElements() { + return { + position: new THREE.Vector3(-8.849933489419644, 9.050627639459208, 0.6192960680432451), + target: new THREE.Vector3(17.945323228767702, -15.156828589982375, -16.585740412769756) + }; +} + function createBobombCoins() { var coins = []; diff --git a/js/prototype/tutorial.js b/js/prototype/tutorial.js new file mode 100644 index 0000000..abdfc9a --- /dev/null +++ b/js/prototype/tutorial.js @@ -0,0 +1,285 @@ +// Disable scrolling +window.onscroll = function () { window.scrollTo(0, 0); }; + +var mesh_number = 25; +var renderer, scene, controls, cube, container, plane, mouse= {x:0, y:0}; +var bigmesh; +var raycaster; +var objects = []; +var cameras, cameraSelecter; +var spheres = new Array(mesh_number); +var visible = 0; +var stats; +var previewer; + +var loader; +var coins; +var beenFullscreen = false; +var isFullscreen = false; +var previousTime; + +var main_section = document.getElementById('main-section'); +var offset = function() { + return + document.getElementById('nav').offsetHeight + + document.getElementById('main-div').offsetHeight; +} + +console.log(document.getElementById('main-div').offsetHeight); +var container_size = { + width: function() { if (!isFullscreen) return main_section.clientWidth; else return screen.width;}, + height: function() { + if (!isFullscreen) + return main_section.clientHeight + - document.getElementById('nav').offsetHeight + - document.getElementById('main-div').offsetHeight; + else + return screen.height; + } +}; + +console.log(container_size.width(), container_size.height()); + +init(); +animate(); + +function init() { + // Disable log for this time + BD.disable(); + + // Collidable objects to prevent camera from traversing objects + var collidableObjects = new Array(); + + // Initialize renderer + container = document.getElementById('container'); + container.style.height = container_size.height() + 'px'; + container.style.width = container_size.width() + 'px'; + renderer = new THREE.WebGLRenderer({alpha:true, antialias:true}); + renderer.setSize(container_size.width(), container_size.height()); + // renderer.setSize(container_size.width(), container_size.height()); + renderer.shadowMapEnabled = true; + renderer.setClearColor(0x87ceeb); + + // Initialize previewer + previewer = new Previewer(renderer); + previewer.domElement.style.position ="absolute"; + previewer.domElement.style.cssFloat = 'top-left'; + previewer.domElement.width = container_size.width(); + previewer.domElement.height = container_size.height(); + + // Initialize scene + scene = new THREE.Scene(); + + // Initialize stats counter + stats = new Stats(); + stats.setMode(0); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.cssFloat = "top-left"; + + // Add elements to page + container.appendChild( stats.domElement ); + container.appendChild(previewer.domElement); + container.appendChild(renderer.domElement); + + // init light + var directional_light = new THREE.DirectionalLight(0xdddddd); + directional_light.position.set(1, 2.5, 1).normalize(); + directional_light.castShadow = false; + scene.add(directional_light); + + var ambient_light = new THREE.AmbientLight(0x555555); + scene.add(ambient_light); + + // Initialize pointer camera + var camera1 = new PointerCamera(50, container_size.width() / container_size.height(), 0.01, 100000, container); + camera1.speed = 0.001; + camera1.resetElements = resetPeachElements(); + camera1.reset(); + camera1.save(); + scene.add(camera1); + + // Collisions + camera1.collidableObjects = collidableObjects; + + + // Initialize recommendations + // var otherCams = createBobombCameras(container_size.width(), container_size.height()); + var otherCams = []; // createPeachCameras(container_size.width(), container_size.height()); + cameras = new CameraContainer(camera1, otherCams); + otherCams.forEach(function(cam) {cam.setSize(0.2); cam.addToScene(scene);}); + + // Initalize loader + var loader = new THREE.OBJMTLLoader(); + + // Load scene + initPeachCastle(scene, collidableObjects, loader, static_path); + // initBobombScene(scene, collidableObjects, loader, static_path); + + coins = []; + // coins = createBobombCoins(); + // setTimeout(function() {coins.forEach(function(coin) { coin.addToScene(scene);})}, 1000); + + // Add listeners + initListeners(); +} + +function initListeners() { + window.addEventListener('resize', onWindowResize, false); + + // Transmit click event to camera selecter + container.addEventListener('mousedown', function(event) { + if (event.which == 1) + cameraSelecter.click(event); + }, false + ); + + // Update camera selecter when mouse moved + container.addEventListener('mousemove', function(event) { + cameraSelecter.update(event); + }, false + ); + + // Escape key to exit fullscreen mode + document.addEventListener('keydown', function(event) { if (event.keyCode == 27) { stopFullscreen();} }, false); + + // HTML Bootstrap buttons + buttonManager = new ButtonManager(cameras, previewer); + + // Camera selecter for hover and clicking recommendations + cameraSelecter = new CameraSelecter(renderer, cameras, buttonManager); +} + +function fullscreen() { + isFullscreen = true; + + if (!beenFullscreen) { + beenFullscreen = true; + alert('To quit fullscren mode, type ESC key'); + } + + container.style.position = "absolute"; + container.style.cssFloat = "top-left"; + container.style.top = "50px"; + container.style.bottom = "0px"; + container.style.left = "0px"; + container.style.right = "0px"; + container.style.width=""; + container.style.height=""; + container.style.overflow = "hidden"; + + // canvas.style.position = "absolute"; + // canvas.style.cssFloat = "top-left"; + // canvas.style.top = "0px"; + // canvas.style.bottom = "0px"; + // canvas.style.left = "0px"; + // canvas.style.right = "0px"; + // canvas.width=window.innerWidth; + // canvas.height=window.innerHeight; + // canvas.style.overflow = "hidden"; + + onWindowResize(); +} + +function stopFullscreen() { + isFullscreen = false; + + container.style.position = ""; + container.style.cssFloat = ""; + container.style.top = ""; + container.style.bottom = ""; + container.style.left = ""; + container.style.right = ""; + container.style.width = container_size.width() + "px"; + container.style.height = container_size.height() + "px"; + + // canvas.style.position = ""; + // canvas.style.cssFloat = ""; + // canvas.style.top = ""; + // canvas.style.bottom = ""; + // canvas.style.left = ""; + // canvas.style.right = ""; + // canvas.width = container_size.width(); + // canvas.height = container_size.height(); + // canvas.style.overflow = ""; + + onWindowResize(); +} + +function render() { + cameraSelecter.update(); + + // Update recommendations (set raycastable if shown) + var transform = buttonManager.showArrows ? show : hide; + cameras.map(function(camera) { + if (camera instanceof RecommendedCamera) { + transform(camera); + + camera.traverse(function(elt) { + elt.raycastable = buttonManager.showArrows; + }); + } + }); + + // Update coins + // coins.forEach(function(coin) { coin.update(); }); + + // Update main camera + var currentTime = Date.now() - previousTime; + cameras.updateMainCamera(isNaN(currentTime) ? 20 : currentTime); + previousTime = Date.now(); + + // Update the recommendations + cameras.update(cameras.mainCamera()); + + + // Set current position of camera + cameras.look(); + + var left = 0, bottom = 0, width = container_size.width(), height = container_size.height(); + renderer.setScissor(left, bottom, width, height); + renderer.enableScissorTest(true); + renderer.setViewport(left, bottom, width, height); + renderer.render(scene, cameras.mainCamera()); + + // Remove borders of preview + previewer.clear(); + + // Hide arrows in recommendation + cameras.map(function(camera) { if (camera instanceof RecommendedCamera) hide(camera); }); + + // Render preview + previewer.render(cameraSelecter.prev, container_size.width(), container_size.height()); +} + +function animate() { + // Render each frame + requestAnimationFrame(animate); + + // stats count the number of frames per second + stats.begin(); + render(); + stats.end(); +} + +function onWindowResize() { + + container.style.width = container_size.width() + "px"; + container.style.height = container_size.height() + "px"; + + previewer.domElement.width = container_size.width(); + previewer.domElement.height = container_size.height(); + + renderer.setSize(container_size.width(), container_size.height()); + cameras.forEach(function(camera) {camera.aspect = container_size.width() / container_size.height();}); + cameras.forEach(function(camera) {camera.updateProjectionMatrix();}); + render(); +} + +function hide(object) { + object.traverse(function(object) {object.visible = false;}); +} + +function show(object) { + object.traverse(function(object) {object.visible = true;}); +} + diff --git a/urls.js b/urls.js index 291822e..cc2a839 100644 --- a/urls.js +++ b/urls.js @@ -7,3 +7,4 @@ module.exports.viewports = '/prototype/viewports/'; module.exports.stream = '/stream/'; module.exports.reverse = '/prototype/reverse/'; module.exports.replay_index = '/prototype/replay/'; +module.exports.tutorial = '/prototype/tutorial'; diff --git a/views/main.jade b/views/main.jade index 19a84e2..db564a2 100644 --- a/views/main.jade +++ b/views/main.jade @@ -40,6 +40,9 @@ html(lang='fr') li.divider li a(href="#{urls.replay_index}") Replays + li.divider + li + a(href="#{urls.tutorial}") Tutorial li a(href="#{urls.stream}") Streaming simulator