From 647843d51b87ce18267354bfe2bc14a81ab1bd50 Mon Sep 17 00:00:00 2001 From: Thomas FORGIONE Date: Mon, 11 May 2015 08:45:13 +0200 Subject: [PATCH] Added reverse camera (arrow with camera at the end) --- controllers/prototype/index.js | 10 + controllers/prototype/urls.js | 3 +- controllers/prototype/views/prototype.jade | 2 + static/js/CameraContainer.js | 2 +- static/js/ReverseCamera.js | 215 +++++++++++++++++++++ static/js/prototype/Previewer.js | 8 +- static/js/prototype/raycasterTools.js | 3 +- urls.js | 1 + views/main.jade | 2 + views/withjs.jade | 1 + 10 files changed, 239 insertions(+), 8 deletions(-) create mode 100644 static/js/ReverseCamera.js diff --git a/controllers/prototype/index.js b/controllers/prototype/index.js index 647b8f7..2190458 100644 --- a/controllers/prototype/index.js +++ b/controllers/prototype/index.js @@ -25,3 +25,13 @@ module.exports.viewports = function(req, res) { res.send(result); }); } + +module.exports.reverse = function(req, res) { + res.setHeader('Content-Type', 'text/html'); + + res.locals.cameraStyle = 'reverse'; + + res.render('prototype.jade', res.locals, function(err, result) { + res.send(result); + }); +} diff --git a/controllers/prototype/urls.js b/controllers/prototype/urls.js index 49b2c93..8c9ecbd 100644 --- a/controllers/prototype/urls.js +++ b/controllers/prototype/urls.js @@ -1,5 +1,6 @@ module.exports = { '/prototype': 'index', '/prototype/arrows': 'arrows', - '/prototype/viewports': 'viewports' + '/prototype/viewports': 'viewports', + '/prototype/reverse': 'reverse' } diff --git a/controllers/prototype/views/prototype.jade b/controllers/prototype/views/prototype.jade index f49ae4c..56dd14d 100644 --- a/controllers/prototype/views/prototype.jade +++ b/controllers/prototype/views/prototype.jade @@ -12,6 +12,8 @@ block extrajs script Recommendation = FixedCamera; else if cameraStyle == 'viewports' script Recommendation = OldFixedCamera; + else if cameraStyle == 'reverse' + script Recommendation = ReverseCamera script(src="/static/js/prototype/main.js") block extrahead diff --git a/static/js/CameraContainer.js b/static/js/CameraContainer.js index 95c371c..c2b35db 100644 --- a/static/js/CameraContainer.js +++ b/static/js/CameraContainer.js @@ -52,7 +52,7 @@ CameraContainer.prototype.get = function(i) { CameraContainer.prototype.getById = function(id) { for (var i in this.cameras) { - if (this.cameras[i] instanceof FixedCamera) { + if (this.cameras[i] instanceof FixedCamera || this.cameras[i] instanceof ReverseCamera) { if (this.cameras[i].object3D !== undefined) { if (this.cameras[i].object3D.id == id) { return this.get(i); diff --git a/static/js/ReverseCamera.js b/static/js/ReverseCamera.js new file mode 100644 index 0000000..81a8191 --- /dev/null +++ b/static/js/ReverseCamera.js @@ -0,0 +1,215 @@ +// Initialization + +// class camera extends THREE.PerspectiveCamera +var ReverseCamera = function(arg1, arg2, arg3, arg4, position, target) { + THREE.PerspectiveCamera.apply(this, arguments); + + // Set Position + if (position === undefined) { + this.position = new THREE.Vector3(0,0,5); + } else { + this.position.x = position.x; + this.position.y = position.y; + this.position.z = position.z; + } + + if (target === undefined) + target = new THREE.Vector3(0,0,0); + + var direction = target.clone(); + direction.sub(this.position); + direction.normalize(); + + this.target = this.position.clone(); + this.target.add(Tools.mul(direction,20)); + + var geometry = new THREE.Geometry(); + + this.center = this.position.clone(); + var left = Tools.cross(direction, this.up); + var other = Tools.cross(direction, left); + + this.center.sub(direction); + + left.normalize(); + other.normalize(); + left = Tools.mul(left, 0.1); + other = Tools.mul(other, 0.1); + + var pyramidCenter = Tools.diff(this.position, Tools.mul(direction,0.25)) + geometry.vertices.push( + 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( 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.diff(this.position, direction) + ); + + var lambda = 0.6; + for (var i = 0; i < 4; i++) + geometry.vertices[i] = Tools.mul(Tools.diff(geometry.vertices[i], Tools.mul(pyramidCenter,lambda)), 1/(1-lambda)); + + + geometry.faces.push(new THREE.Face3(2,0,1), // new THREE.Face3(0,2,1), + new THREE.Face3(3,0,2), // new THREE.Face3(0,3,2) + + new THREE.Face3(1,0,4), + new THREE.Face3(1,4,5), + + new THREE.Face3(2,1,5), + new THREE.Face3(2,5,6), + + new THREE.Face3(7,2,6), + new THREE.Face3(7,3,2), + + new THREE.Face3(3,7,4), + new THREE.Face3(3,4,0) + + ); + + geometry.computeFaceNormals(); + + var material = new THREE.MeshLambertMaterial({ + color : 0xff0000, + transparent : true, + opacity : 0.5, + side: THREE.FrontSide + }); + + this.mesh = new THREE.Mesh(geometry, material); + this.arrow = new THREE.Mesh(new THREE.Geometry(), new THREE.MeshLambertMaterial({color: 0xff0000, side:THREE.BackSide})); + + this.object3D = new THREE.Object3D(); + this.object3D.add(this.mesh); + this.object3D.add(this.arrow); + + this.fullArrow = false; +} +ReverseCamera.prototype = Object.create(THREE.PerspectiveCamera.prototype); +ReverseCamera.prototype.constructor = ReverseCamera; + +// Update function +ReverseCamera.prototype.update = function(mainCamera) { + // Compute distance between center of camera and position + dist = Tools.norm2(Tools.diff(mainCamera.position, this.center)); + + var low_bound = 1; + var high_bound = 5; + var new_value; + + if (dist < low_bound) { + new_value = 0; + } + else if (dist > high_bound) { + new_value = 1; + } + else { + new_value = (dist - low_bound)/(high_bound - low_bound); + } + + // Update opacity + this.object3D.traverse(function(elt) { + if (elt instanceof THREE.Mesh) { + elt.material.transparent = new_value < 0.9; + elt.material.opacity = new_value; + + if (new_value < 0.1) + elt.material.transparent = elt.visible = false; + } + }); + + this.regenerateArrow(mainCamera); +} + +ReverseCamera.prototype.regenerateArrow = function(mainCamera) { + var vertices = new Array(); + var t = [0,1]; + var f0 = mainCamera.position.clone(); + f0.add(Tools.sum(Tools.mul(this.up,-1), Tools.diff(this.target, this.position).normalize())); + var f = [Tools.sum(mainCamera.position, Tools.diff(this.target, this.position)).normalize(), this.position.clone()]; + + var first = Tools.diff(mainCamera.target, mainCamera.position); + first.normalize(); + + var fp = [Tools.mul(first,40), Tools.diff(this.target, this.position)]; + fp[1].normalize(); + fp[1].multiplyScalar(4); + var hermite = new Hermite.special.Polynom(f0, f[1], fp[1]); + + var up = this.up.clone(); + var point; + var deriv; + var limit = this.fullArrow ? 0.1 : 0.3; + + // for (var i = this.fullArrow ? 0 : 0.5; i <= 1.001; i += 0.05) { + for (var i = 1; i > limit; i -= 0.025) { + point = hermite.eval(i); + deriv = hermite.prime(i); + up.cross(deriv); + up.cross(deriv); + up.multiplyScalar(-1); + up.normalize(); + + var coeff = 0.1; + var left = Tools.cross(up, deriv); left.normalize(); left.multiplyScalar(coeff); + var other = Tools.cross(deriv, left); other.normalize(); other.multiplyScalar(coeff); + + vertices.push( + Tools.sum(Tools.sum(point, left), other), + Tools.sum(Tools.diff(point, left), other), + Tools.diff(point, Tools.sum(other,left)), + Tools.sum(Tools.diff(point, other), left) + ); + } + + var faces = new Array(); + + for (var i = 0; i < vertices.length - 4; i+= 4) { + faces.push(new THREE.Face3(i,i+1,i+5),new THREE.Face3(i,i+5,i+4), + new THREE.Face3(i+1,i+2,i+6),new THREE.Face3(i+1,i+6,i+5), + new THREE.Face3(i+2,i+3,i+7),new THREE.Face3(i+2,i+7,i+6), + new THREE.Face3(i,i+7,i+3), new THREE.Face3(i,i+4,i+7)); + } + + var len = vertices.length; + faces.push(new THREE.Face3(len-4,len-3,len-2), new THREE.Face3(len-4,len-2,len-1)); + + + this.arrow.geometry.vertices = vertices; + this.arrow.geometry.faces = faces; + + // this.arrow.geometry.mergeVertices(); + this.arrow.geometry.computeFaceNormals(); + // this.arrow.geometry.computeVertexNormals(); + this.arrow.geometry.computeBoundingSphere(); + + // this.arrow.geometry.vertices[0] = new THREE.Vector3(); // mainCamera.position.clone(); + // this.arrow.geometry.vertices[1] = this.position.clone(); + + this.arrow.geometry.dynamic = true; + this.arrow.geometry.verticesNeedUpdate = true; + this.arrow.geometry.elementsNeedUpdate = true; + this.arrow.geometry.groupsNeedUpdate = true; + this.arrow.geometry.normalsNeedUpdate = true; + // this.arrow.geometry.facesNeedUpdate = true; + +} + +// Look function +ReverseCamera.prototype.look = function() { + this.lookAt(this.target); +} + +ReverseCamera.prototype.addToScene = function(scene) { + scene.add(this); + scene.add(this.object3D); +} + +ReverseCamera.prototype.traverse = function(callback) { + this.object3D.traverse(callback); +} diff --git a/static/js/prototype/Previewer.js b/static/js/prototype/Previewer.js index 114f00f..8625328 100644 --- a/static/js/prototype/Previewer.js +++ b/static/js/prototype/Previewer.js @@ -39,10 +39,10 @@ Previewer.prototype.render = function(prev, container_width, container_height) { // Do render in previsualization prev.camera.look(); - renderer.setScissor(left, bottom, width, height); - renderer.enableScissorTest (true); - renderer.setViewport(left, bottom, width, height); - renderer.render(scene, prev.camera); + this.renderer.setScissor(left, bottom, width, height); + this.renderer.enableScissorTest (true); + this.renderer.setViewport(left, bottom, width, height); + this.renderer.render(scene, prev.camera); } } diff --git a/static/js/prototype/raycasterTools.js b/static/js/prototype/raycasterTools.js index 3c7f79b..7c5a835 100644 --- a/static/js/prototype/raycasterTools.js +++ b/static/js/prototype/raycasterTools.js @@ -41,11 +41,10 @@ CameraSelecter.prototype.pointedCamera = function() { if (bestIndex !== undefined) { // if (this.cameras.getById(intersects[bestIndex].object.parent.id) !== undefined) { var obj = intersects[bestIndex].object; - if (Recommendation === FixedCamera) { + if (Recommendation === FixedCamera || Recommendation === ReverseCamera) { return this.cameras.getById(intersects[bestIndex].object.parent.id); } else { return this.cameras.getById(intersects[bestIndex].object.id); - console.log('tata'); } // } } diff --git a/urls.js b/urls.js index ed177cb..13c1628 100644 --- a/urls.js +++ b/urls.js @@ -5,3 +5,4 @@ module.exports.prototype = '/prototype/'; module.exports.arrows = '/prototype/arrows/'; module.exports.viewports = '/prototype/viewports/'; module.exports.stream = '/stream/'; +module.exports.reverse = '/prototype/reverse/'; diff --git a/views/main.jade b/views/main.jade index 6d0aa5a..31cfeec 100644 --- a/views/main.jade +++ b/views/main.jade @@ -33,6 +33,8 @@ html(lang='fr') ul.dropdown-menu(role="menu") li a(href="#{urls.arrows}") Arrows + li + a(href="#{urls.reverse}") Reverse arrows li a(href="#{urls.viewports}") Viewports li diff --git a/views/withjs.jade b/views/withjs.jade index 2e71372..c68bd41 100644 --- a/views/withjs.jade +++ b/views/withjs.jade @@ -14,6 +14,7 @@ block js script(src="/static/js/Camera.js") script(src="/static/js/FixedCamera.js") script(src="/static/js/OldFixedCamera.js") + script(src="/static/js/ReverseCamera.js") script(src="/static/js/BouncingCube.js") script(src="/static/js/BufferGeometryToGeometry.js") script(src="/static/js/PointerCamera.js")