From 6f51ce7e8d39c66b3fc2d8ff5a29ad50abe14df5 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Sat, 30 Oct 2010 01:39:08 +0100 Subject: [PATCH] * Trying to make the interaction stuff work... --- examples/geometry/primitives/ClickCube.js | 14 +- examples/geometry/primitives/Sphere.js | 55 +++--- examples/geometry_earth.html | 6 +- examples/geometry_terrain.html | 83 +--------- examples/interactive_spheres.html | 193 ++++++++++++++++++++++ examples/js/ImprovedNoise.js | 71 ++++++++ src/core/Geometry.js | 3 +- src/hci/ClickResolver.js | 156 ++++++++--------- src/scenes/Scene.js | 29 ++-- 9 files changed, 409 insertions(+), 201 deletions(-) create mode 100644 examples/interactive_spheres.html create mode 100644 examples/js/ImprovedNoise.js diff --git a/examples/geometry/primitives/ClickCube.js b/examples/geometry/primitives/ClickCube.js index acb7af1e..e90c325d 100644 --- a/examples/geometry/primitives/ClickCube.js +++ b/examples/geometry/primitives/ClickCube.js @@ -2,9 +2,9 @@ * @author mr.doob / http://mrdoob.com/ */ -var ClickCube = function (width, height, depth, onSelect) { +var ClickCube = function ( width, height, depth, onSelect ) { - THREE.Geometry.call(this); + THREE.Geometry.call( this ); var scope = this, width_half = width / 2, @@ -21,21 +21,23 @@ var ClickCube = function (width, height, depth, onSelect) { v( -width_half, height_half, depth_half ); f4( 0, 1, 2, 3 ); - + f4( 4, 7, 6, 5 ); f4( 0, 4, 5, 1 ); f4( 2, 6, 7, 3 ); f4( 1, 5, 6, 2 ); f4( 4, 0, 3, 7 ); - function v(x, y, z) { + function v( x, y, z ) { scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) ); } - function f4(a, b, c, d) { + function f4( a, b, c, d ) { + var f = new THREE.SelectableFace4( a, b, c, d, onSelect ); - scope.faces.push(f); + scope.faces.push( f ); + } this.computeCentroids(); diff --git a/examples/geometry/primitives/Sphere.js b/examples/geometry/primitives/Sphere.js index b311342a..2df17179 100644 --- a/examples/geometry/primitives/Sphere.js +++ b/examples/geometry/primitives/Sphere.js @@ -70,36 +70,47 @@ var Sphere = function ( radius, segments_width, segments_height, smooth ) { var aP4uv = new THREE.UV( 1 - fI0, fJ1 ); if ( j < ( aVtc.length - 1 ) ) { - n1 = this.vertices[aP1].position.clone(); - n2 = this.vertices[aP2].position.clone(); - n3 = this.vertices[aP3].position.clone(); - n1.normalize(); - n2.normalize(); - n3.normalize(); - if ( smooth ) - this.faces.push( new THREE.Face3( aP1, aP2, aP3, [new THREE.Vector3(n1.x,n1.y,n1.z), new THREE.Vector3(n2.x,n2.y,n2.z), new THREE.Vector3(n3.x,n3.y,n3.z)] ) ); - else - this.faces.push( new THREE.Face3( aP1, aP2, aP3 ) ); - + n1 = this.vertices[ aP1 ].position.clone(); + n2 = this.vertices[ aP2 ].position.clone(); + n3 = this.vertices[ aP3 ].position.clone(); + n1.normalize(); + n2.normalize(); + n3.normalize(); + + if ( smooth ) { + + this.faces.push( new THREE.Face3( aP1, aP2, aP3, [ new THREE.Vector3( n1.x, n1.y, n1.z ), new THREE.Vector3( n2.x, n2.y, n2.z ), new THREE.Vector3( n3.x, n3.y, n3.z ) ] ) ); + + } else { + + this.faces.push( new THREE.Face3( aP1, aP2, aP3 ) ); + + } + this.uvs.push( [ aP1uv, aP2uv, aP3uv ] ); } if ( j > 1 ) { - n1 = this.vertices[aP1].position.clone(); - n2 = this.vertices[aP3].position.clone(); - n3 = this.vertices[aP4].position.clone(); - n1.normalize(); - n2.normalize(); - n3.normalize(); + n1 = this.vertices[aP1].position.clone(); + n2 = this.vertices[aP3].position.clone(); + n3 = this.vertices[aP4].position.clone(); + n1.normalize(); + n2.normalize(); + n3.normalize(); + + if ( smooth ) { + + this.faces.push( new THREE.Face3( aP1, aP3, aP4, [ new THREE.Vector3( n1.x, n1.y, n1.z ), new THREE.Vector3( n2.x, n2.y, n2.z ), new THREE.Vector3( n3.x, n3.y, n3.z ) ] ) ); + + } else { + + this.faces.push( new THREE.Face3( aP1, aP3, aP4 ) ); + + } - if ( smooth ) - this.faces.push( new THREE.Face3( aP1, aP3, aP4, [new THREE.Vector3(n1.x,n1.y,n1.z), new THREE.Vector3(n2.x,n2.y,n2.z), new THREE.Vector3(n3.x,n3.y,n3.z)] ) ); - else - this.faces.push( new THREE.Face3( aP1, aP3, aP4 ) ); - this.uvs.push( [ aP1uv, aP3uv, aP4uv ] ); } diff --git a/examples/geometry_earth.html b/examples/geometry_earth.html index 90b31b50..6baac7c7 100644 --- a/examples/geometry_earth.html +++ b/examples/geometry_earth.html @@ -65,7 +65,7 @@ container = document.getElementById( 'container' ); - camera = new THREE.Camera( 60, SCREEN_WIDTH / SCREEN_HEIGHT, 0.0001, 10000 ); + camera = new THREE.Camera( 60, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 ); camera.position.z = 500; scene = new THREE.Scene(); @@ -81,12 +81,12 @@ renderer = new THREE.CanvasRenderer(); renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); - container.appendChild(renderer.domElement); + container.appendChild( renderer.domElement ); stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.top = '0px'; - container.appendChild(stats.domElement); + container.appendChild( stats.domElement ); document.addEventListener('mousemove', onDocumentMouseMove, false); diff --git a/examples/geometry_terrain.html b/examples/geometry_terrain.html index 1dd44541..160d7033 100644 --- a/examples/geometry_terrain.html +++ b/examples/geometry_terrain.html @@ -34,6 +34,7 @@
three.js - terrain demo. generate another
+ @@ -41,80 +42,6 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/js/ImprovedNoise.js b/examples/js/ImprovedNoise.js new file mode 100644 index 00000000..17ff9f13 --- /dev/null +++ b/examples/js/ImprovedNoise.js @@ -0,0 +1,71 @@ +// http://mrl.nyu.edu/~perlin/noise/ + +var ImprovedNoise = function () { + + var p = [151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10, + 23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87, + 174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211, + 133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208, + 89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5, + 202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119, + 248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232, + 178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249, + 14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205, + 93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]; + + for (var i=0; i < 256 ; i++) { + + p[256+i] = p[i]; + + } + + function fade(t) { + + return t * t * t * (t * (t * 6 - 15) + 10); + + } + + function lerp(t, a, b) { + + return a + t * (b - a); + + } + + function grad(hash, x, y, z) { + + var h = hash & 15; + var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z; + return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v); + + } + + return { + + noise: function (x, y, z) { + + var floorX = Math.floor(x), floorY = Math.floor(y), floorZ = Math.floor(z); + + var X = floorX & 255, Y = floorY & 255, Z = floorZ & 255; + + x -= floorX; + y -= floorY; + z -= floorZ; + + var xMinus1 = x -1, yMinus1 = y - 1, zMinus1 = z - 1; + + var u = fade(x), v = fade(y), w = fade(z); + + var A = p[X]+Y, AA = p[A]+Z, AB = p[A+1]+Z, B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z; + + return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z), + grad(p[BA], xMinus1, y, z)), + lerp(u, grad(p[AB], x, yMinus1, z), + grad(p[BB], xMinus1, yMinus1, z))), + lerp(v, lerp(u, grad(p[AA+1], x, y, zMinus1), + grad(p[BA+1], xMinus1, y, z-1)), + lerp(u, grad(p[AB+1], x, yMinus1, zMinus1), + grad(p[BB+1], xMinus1, yMinus1, zMinus1)))); + + } + } +} diff --git a/src/core/Geometry.js b/src/core/Geometry.js index 2dc2f28a..67f14b72 100644 --- a/src/core/Geometry.js +++ b/src/core/Geometry.js @@ -45,7 +45,8 @@ THREE.Geometry.prototype = { computeNormals: function ( useVertexNormals ) { - var n, nl, v, vl, vertex, f, fl, face, vA, vB, vC, cb = new THREE.Vector3(), ab = new THREE.Vector3(); + var n, nl, v, vl, vertex, f, fl, face, vA, vB, vC, + cb = new THREE.Vector3(), ab = new THREE.Vector3(); for ( v = 0, vl = this.vertices.length; v < vl; v++ ) { diff --git a/src/hci/ClickResolver.js b/src/hci/ClickResolver.js index a7529433..624e804f 100644 --- a/src/hci/ClickResolver.js +++ b/src/hci/ClickResolver.js @@ -3,51 +3,56 @@ THREE.ClickResolver = function( camera, scene ) { this.camera = camera; this.scene = scene; - this._debug = false; + this._debug = true; }; THREE.ClickResolver.prototype = { - + findIntersectInScene : function ( xPercent, yPercent ) { - + var objects = this.scene.objects; var intersects = []; - + var mouseRayStart = this.translateScreenCoordsToZIndex( xPercent, yPercent, 300 ); var mouseRayEnd = this.translateScreenCoordsToZIndex( xPercent, yPercent, 800 ); - + var mouseRayDir = new THREE.Vector3().sub( mouseRayEnd, mouseRayStart ); - + var closestIntersect = null; - - for ( var i = 0; i < objects.length; i++ ) { - - var o = objects[i]; - var intersect = this.getIntersectingFaces( this.scene, camera, o, mouseRayStart, mouseRayDir ); - - if ( intersect.face != null && - (closestIntersect == null || - closestIntersect.distance > intersect.distance) - ) { - - closestIntersect = intersect; + + for ( var i = 0, l = objects.length; i < l; i++ ) { + + var object = objects[i]; + + if ( object instanceof THREE.Mesh ) { + + var intersect = this.getIntersectingFaces( this.scene, camera, object, mouseRayStart, mouseRayDir ); + + if ( intersect.face != null && (closestIntersect == null || closestIntersect.distance > intersect.distance) ) { + + closestIntersect = intersect; + + } + } + } - + if ( closestIntersect != null && closestIntersect.face.onSelect ) { - - closestIntersect.face.onSelect( scene, camera, o, closestIntersect.face, closestIntersect.point ); + + closestIntersect.face.onSelect( scene, camera, object, closestIntersect.face, closestIntersect.point ); + } + }, - - - translateScreenCoordsToZIndex : function ( xPercent, yPercent, targetZIndex ) { + + translateScreenCoordsToZIndex: function ( xPercent, yPercent, targetZIndex ) { var maxVisibleXatZIndex, maxVisibleYatZIndex; - var rayToZIndex = new THREE.Vector3(); - var left = new THREE.Vector3(); - var up = new THREE.Vector3(); + var rayToZIndex = new THREE.Vector3(); + var left = new THREE.Vector3(); + var up = new THREE.Vector3(); var coordAtZIndex = new THREE.Vector3(); rayToZIndex.sub( this.camera.target.position, this.camera.position ).setLength( targetZIndex ); @@ -68,12 +73,11 @@ THREE.ClickResolver.prototype = { if ( this._debug ) { - var vg = new THREE.Geometry(); + var p = new THREE.Particle( new THREE.ParticleCircleMaterial( hex, 0.5 ) ); + p.position = v.clone(); + p.scale.x = p.scale.y = p.scale.z = 5; - vg.vertices[ 0 ] = new THREE.Vertex( v ); - vg.vertices[ 1 ] = new THREE.Vertex( v ); - - scene.addObject( new THREE.Line( vg, new THREE.LineColorMaterial( hex, 1, 10 ))); + scene.addObject( p ); } }, @@ -89,7 +93,7 @@ THREE.ClickResolver.prototype = { lg.vertices[0] = new THREE.Vertex( s.clone() ); lg.vertices[1] = new THREE.Vertex( e.clone() ); - scene.addObject(new THREE.Line( lg, new THREE.LineColorMaterial( hex, 1, 4 ) )); + scene.addObject( new THREE.Line( lg, new THREE.LineColorMaterial( hex, 0.5 ) ) ); } }, @@ -103,24 +107,19 @@ THREE.ClickResolver.prototype = { distance : Number.MAX_VALUE }; - var geo = object3d.geometry; + var geometry = object3d.geometry; var matrix = object3d.matrix; - for ( f = 0; f < geo.faces.length; f++ ) { + for ( f = 0; f < geometry.faces.length; f++ ) { - var face = geo.faces[ f ]; + var face = geometry.faces[ f ]; - if ( !face.selectable ) continue; + // if ( !face.selectable ) continue; - var a = matrix.transform( geo.vertices[ face.a ].position.clone() ); - var b = matrix.transform( geo.vertices[ face.b ].position.clone() ); - var c = matrix.transform( geo.vertices[ face.c ].position.clone() ); - var d = null; - - if ( face.d ) { - - d = matrix.transform( geo.vertices[ face.d ].position.clone() ); - } + var a = matrix.transform( geometry.vertices[ face.a ].position.clone() ); + var b = matrix.transform( geometry.vertices[ face.b ].position.clone() ); + var c = matrix.transform( geometry.vertices[ face.c ].position.clone() ); + var d = face.d ? matrix.transform( geometry.vertices[ face.d ].position.clone() ) : null; var lineStart = linePoint.clone(); var lineDirection = lineDir.clone(); @@ -128,73 +127,80 @@ THREE.ClickResolver.prototype = { if ( this._debug ) { - this.logLine( scene, a, new THREE.Vector3().add( a, new THREE.Vector3().addSelf( face.normal ).multiplyScalar( 100 )), 0x0000FF ); - this.logLine( scene, lineStart, lineStart.clone().addSelf(lineDirection), 0x55FF88 ); + /* + this.logLine( scene, a, new THREE.Vector3().add( a, new THREE.Vector3().addSelf( face.normal ).multiplyScalar( 100 ) ), 0x0000FF ); + this.logLine( scene, lineStart, lineStart.clone().addSelf( lineDirection ), 0x55FF88 ); this.logPoint( scene, a, 0xFF0000 ); // r this.logPoint( scene, b, 0x00FF00 ); // g this.logPoint( scene, c, 0x0000FF ); // b - this.logPoint( scene, d, 0xFFFF00 ); // y + if ( d ) this.logPoint( scene, d, 0xFFFF00 ); // y + */ } - - if ( Math.abs(dot) > .0001 ) { - + + if ( dot < 0 ) { // Math.abs( dot ) > 0.0001 + var s = face.normal.dot( new THREE.Vector3().sub( a, lineStart ) ) / dot; var planeIntersect = lineStart.addSelf( lineDirection.multiplyScalar( s ) ); - - if ( this._debug ) this.logPoint( scene, planeIntersect, 0xFFCCAA ); - + + // if ( this._debug ) this.logPoint( scene, planeIntersect, 0x808080 ); + if ( d == null ) { - + var ab = isInsideBoundary( planeIntersect, a, b, c ); var bc = isInsideBoundary( planeIntersect, b, c, a ); var ca = isInsideBoundary( planeIntersect, c, a, b ); - + if ( ab && bc && ca ) { - - if ( this._debug ) this.logPoint( scene, planeIntersect, 0xFF0000 ); + + if ( this._debug ) this.logPoint( scene, planeIntersect, 0x0000ff ); logIntersect( planeIntersect, face ); - + } + } else { - + var ab = isInsideBoundary( planeIntersect, a, b, c ); var bc = isInsideBoundary( planeIntersect, b, c, d ); var cd = isInsideBoundary( planeIntersect, c, d, a ); var da = isInsideBoundary( planeIntersect, d, a, b ); - + if ( ab && bc && cd && da ) { - - if ( this._debug ) this.logPoint( scene, planeIntersect, 0xFF0000 ); + + if ( this._debug ) this.logPoint( scene, planeIntersect, 0x000000 ); logIntersect( planeIntersect, face ); - + } + } + } + } - + function logIntersect( planeIntersect, face ) { - + var distance = camera.position.distanceTo( planeIntersect ); - + if ( distance < intersect.distance ) { - + intersect.distance = distance; intersect.face = face; intersect.point = planeIntersect; + } + } - + function isInsideBoundary( pointOnPlaneToCheck, pointInside, boundaryPointA, boundaryPointB ) { - + var toB = boundaryPointB.clone().subSelf( boundaryPointA ); var toI = pointInside.clone().subSelf( boundaryPointA ); var pointMid = toB.setLength( toI.dot( toB ) ).addSelf( boundaryPointA ); var pointMirror = pointMid.subSelf( pointInside ).multiplyScalar( 2 ).addSelf( pointInside ); - - return pointOnPlaneToCheck.distanceToSquared( pointInside ) < - pointOnPlaneToCheck.distanceToSquared( pointMirror ); + + return pointOnPlaneToCheck.distanceToSquared( pointInside ) < pointOnPlaneToCheck.distanceToSquared( pointMirror ); }; - + return intersect; } diff --git a/src/scenes/Scene.js b/src/scenes/Scene.js index 02d31932..235a0078 100644 --- a/src/scenes/Scene.js +++ b/src/scenes/Scene.js @@ -9,7 +9,7 @@ THREE.Scene = function () { this.addObject = function ( object ) { - this.objects.push(object); + this.objects.push( object ); }; @@ -23,32 +23,29 @@ THREE.Scene = function () { return; } + } + }; - this.addLight = function ( light ) { + this.addLight = function ( light ) { - this.lights.push(light); + this.lights.push( light ); - }; + }; - this.removeLight = function ( light ) { + this.removeLight = function ( light ) { - for ( var i = 0, l = this.lights.length; i < l; i++ ) { + for ( var i = 0, l = this.lights.length; i < l; i++ ) { - if ( light == this.lights[ i ] ) { + if ( light == this.lights[ i ] ) { - this.lights.splice( i, 1 ); - return; + this.lights.splice( i, 1 ); + return; - } - } - }; + } - // Deprecated - this.add = function ( object ) { - - this.addObject( object ); + } };