Browse Source

ExtrudeGeometry using TubeGeometry internally for TNB frames. Added webgl_geometry_extrudePath.html to test ExtrudeGeometry

zz85 13 years ago
parent
commit
155fca7b04
2 changed files with 399 additions and 24 deletions
  1. 362 0
      examples/webgl_geometry_extrudePath.html
  2. 37 24
      src/extras/geometries/ExtrudeGeometry.js

+ 362 - 0
examples/webgl_geometry_extrudePath.html

@@ -0,0 +1,362 @@
+
+<!doctype html>
+<html lang="en">
+  <head>
+    <title>three.js webgl - geometry - extrude splines</title>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+    <style>
+      body {
+        font-family: Monospace;
+        background-color: #f0f0f0;
+        margin: 0px;
+        overflow: hidden;
+      }
+    </style>
+  </head>
+  <body>
+    <canvas id="debug" style="position:absolute; left:100px"></canvas>
+
+    <script src="../build/Three.js"></script>
+    <script src="../src/extras/core/Curve.js"></script>
+    <script src="../src/extras/geometries/TubeGeometry.js"></script>
+    <script src="../src/extras/geometries/ExtrudeGeometry.js"></script>
+    <script src="js/Stats.js"></script>
+
+
+    <script>
+
+      var container, stats;
+
+      var camera, scene, renderer;
+
+      var text, plane;
+
+      var targetRotation = 0;
+      var targetRotationOnMouseDown = 0;
+
+      var mouseX = 0;
+      var mouseXOnMouseDown = 0;
+
+      var windowHalfX = window.innerWidth / 2;
+      var windowHalfY = window.innerHeight / 2;
+
+      init();
+      animate();
+
+      function init() {
+
+        container = document.createElement( 'div' );
+        document.body.appendChild( container );
+
+        var info = document.createElement( 'div' );
+        info.style.position = 'absolute';
+        info.style.top = '10px';
+        info.style.width = '100%';
+        info.style.textAlign = 'center';
+        info.innerHTML = 'Simple procedurally generated 3D shapes example by <a href="http://www.lab4games.net/zz85/blog">zz85</a><br/>Drag to spin';
+        container.appendChild( info );
+
+        scene = new THREE.Scene();
+
+        camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
+        camera.position.set( 0, 150, 500 );
+        scene.add( camera );
+
+        var light = new THREE.DirectionalLight( 0xffffff );
+        light.position.set( 0, 0, 1 );
+        scene.add( light );
+
+        parent = new THREE.Object3D();
+        parent.position.y = 50;
+        scene.add( parent );
+
+        function addGeometry( geometry, points, spacedPoints, color, x, y, z, rx, ry, rz, s ) {
+
+          // 3d shape
+
+          var mesh = THREE.SceneUtils.createMultiMaterialObject( geometry, [ new THREE.MeshLambertMaterial( { color: color } ), new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, transparent: true } ) ] );
+          mesh.position.set( x, y, z - 75 );
+          mesh.rotation.set( rx, ry, rz );
+          mesh.scale.set( s, s, s );
+          parent.add( mesh );
+
+          // solid line
+
+          var line = new THREE.Line( points, new THREE.LineBasicMaterial( { color: color, linewidth: 2 } ) );
+          line.position.set( x, y, z + 25 );
+          line.rotation.set( rx, ry, rz );
+          line.scale.set( s, s, s );
+          parent.add( line );
+
+          // transparent line from real points
+
+          var line = new THREE.Line( points, new THREE.LineBasicMaterial( { color: color, opacity: 0.5 } ) );
+          line.position.set( x, y, z + 75 );
+          line.rotation.set( rx, ry, rz );
+          line.scale.set( s, s, s );
+          parent.add( line );
+
+          // vertices from real points
+
+          var pgeo = THREE.GeometryUtils.clone( points );
+          var particles = new THREE.ParticleSystem( pgeo, new THREE.ParticleBasicMaterial( { color: color, size: 2, opacity: 0.75 } ) );
+          particles.position.set( x, y, z + 75 );
+          particles.rotation.set( rx, ry, rz );
+          particles.scale.set( s, s, s );
+          parent.add( particles );
+
+          // transparent line from equidistance sampled points
+
+          var line = new THREE.Line( spacedPoints, new THREE.LineBasicMaterial( { color: color, opacity: 0.2 } ) );
+          line.position.set( x, y, z + 100 );
+          line.rotation.set( rx, ry, rz );
+          line.scale.set( s, s, s );
+          parent.add( line );
+
+          // equidistance sampled points
+
+          var pgeo = THREE.GeometryUtils.clone( spacedPoints );
+          var particles2 = new THREE.ParticleSystem( pgeo, new THREE.ParticleBasicMaterial( { color: color, size: 2, opacity: 0.5 } ) );
+          particles2.position.set( x, y, z + 100 );
+          particles2.rotation.set( rx, ry, rz );
+          particles2.scale.set( s, s, s );
+          parent.add( particles2 );
+
+        }
+
+        var extrudeSettings = { amount: 200,  bevelEnabled: true, bevelSegments: 2, steps: 150 }; // bevelSegments: 2, steps: 2 , bevelSegments: 5, bevelSize: 8, bevelThickness:5,
+
+        // var extrudePath = new THREE.Path();
+
+        // extrudePath.moveTo( 0, 0 );
+        // extrudePath.lineTo( 10, 10 );
+        // extrudePath.quadraticCurveTo( 80, 60, 160, 10 );
+        // extrudePath.quadraticCurveTo( 240, -40, 320, 10 );
+
+        
+        extrudeSettings.bevelEnabled = false;
+
+        var extrudeBend = new THREE.SplineCurve3( //Closed
+        [
+
+          new THREE.Vector3( 30, 12, 83),
+          new THREE.Vector3( 40, 20, 67),
+          new THREE.Vector3( 60, 40, 99),
+          new THREE.Vector3( 10, 60, 49),
+          new THREE.Vector3( 25, 80, 40)
+
+          // new THREE.Vector3( 0, 12, 83),
+          // new THREE.Vector3( 0, 20, 67),
+          // new THREE.Vector3( 0, 40, 99),
+          // new THREE.Vector3( 0, 60, 49),
+          // new THREE.Vector3( 0, 80, 40)
+
+          // new THREE.Vector3( 12, 83, 0 ),
+          // new THREE.Vector3( 20, 67, 0 ),
+          // new THREE.Vector3( 40, 99, 0 ),
+          // new THREE.Vector3( 60, 49, 0 ),
+          // new THREE.Vector3( 80, 40, 0 )
+          ]);
+
+            var pipeSpline = new THREE.SplineCurve3([
+        new THREE.Vector3(0, 10, -10), new THREE.Vector3(10, 0, -10), new THREE.Vector3(20, 0, 0), new THREE.Vector3(30, 0, 10), new THREE.Vector3(30, 0, 20), new THREE.Vector3(20, 0, 30), new THREE.Vector3(10, 0, 30), new THREE.Vector3(0, 0, 30), new THREE.Vector3(-10, 10, 30), new THREE.Vector3(-10, 20, 30), new THREE.Vector3(0, 30, 30), new THREE.Vector3(10, 30, 30), new THREE.Vector3(20, 30, 15), new THREE.Vector3(10, 30, 10), new THREE.Vector3(0, 30, 10), new THREE.Vector3(-10, 20, 10), new THREE.Vector3(-10, 10, 10), new THREE.Vector3(0, 0, 10), new THREE.Vector3(10, -10, 10), new THREE.Vector3(20, -15, 10), new THREE.Vector3(30, -15, 10), new THREE.Vector3(40, -15, 10), new THREE.Vector3(50, -15, 10), new THREE.Vector3(60, 0, 10), new THREE.Vector3(70, 0, 0), new THREE.Vector3(80, 0, 0), new THREE.Vector3(90, 0, 0), new THREE.Vector3(100, 0, 0)]);
+
+        var sampleClosedSpline = new THREE.ClosedSplineCurve3([
+          new THREE.Vector3(0, -40, -40),
+          new THREE.Vector3(0, 40, -40),
+          new THREE.Vector3(0, 140, -40),
+          new THREE.Vector3(0, 40, 40),
+          new THREE.Vector3(0, -40, 40),
+        ]);
+
+        var randomPoints = [];
+
+        for (var i=0; i<10;i++) {
+          randomPoints.push(
+            new THREE.Vector3(Math.random() * 200,Math.random() * 200,Math.random() * 200 )
+            );
+        }
+
+        var randomSpline =  new THREE.SplineCurve3(randomPoints);
+
+        extrudeSettings.extrudePath = randomSpline; // extrudeBend sampleClosedSpline pipeSpline
+
+        // Circle
+
+        var circleRadius = 4;
+        var circleShape = new THREE.Shape();
+        circleShape.moveTo( 0, circleRadius );
+        circleShape.quadraticCurveTo( circleRadius, circleRadius, circleRadius, 0 );
+        circleShape.quadraticCurveTo( circleRadius, -circleRadius, 0, -circleRadius );
+        circleShape.quadraticCurveTo( -circleRadius, -circleRadius, -circleRadius, 0 );
+        circleShape.quadraticCurveTo( -circleRadius, circleRadius, 0, circleRadius);
+
+        var rectLength = 12, rectWidth = 4;
+
+        var rectShape = new THREE.Shape();
+        // rectShape.moveTo( 0,0 );
+        // rectShape.lineTo( 0, rectWidth );
+        // rectShape.lineTo( rectLength, rectWidth );
+        // rectShape.lineTo( rectLength, 0 );
+        // rectShape.lineTo( 0, 0 );
+
+        rectShape.moveTo( -rectLength/2, -rectWidth/2 );
+        rectShape.lineTo( -rectLength/2, rectWidth/2 );
+        rectShape.lineTo( rectLength/2, rectWidth/2 );
+        rectShape.lineTo( rectLength/2, -rectLength/2 );
+        rectShape.lineTo( -rectLength/2, -rectLength/2 );
+
+
+        // Smiley
+
+        var smileyShape = new THREE.Shape();
+        smileyShape.moveTo( 80, 40 );
+        smileyShape.arc( 40, 40, 40, 0, Math.PI*2, false );
+
+        var smileyEye1Path = new THREE.Path();
+        smileyEye1Path.moveTo( 35, 20 );
+        smileyEye1Path.arc( 25, 20, 10, 0, Math.PI*2, true );
+        smileyShape.holes.push( smileyEye1Path );
+
+        var smileyEye2Path = new THREE.Path();
+        smileyEye2Path.moveTo( 65, 20 );
+        smileyEye2Path.arc( 55, 20, 10, 0, Math.PI*2, true );
+        smileyShape.holes.push( smileyEye2Path );
+
+        var smileyMouthPath = new THREE.Path();
+        // ugly box mouth
+        // smileyMouthPath.moveTo( 20, 40 );
+        // smileyMouthPath.lineTo( 60, 40 );
+        // smileyMouthPath.lineTo( 60, 60 );
+        // smileyMouthPath.lineTo( 20, 60 );
+        // smileyMouthPath.lineTo( 20, 40 );
+
+        smileyMouthPath.moveTo( 20, 40 );
+        smileyMouthPath.quadraticCurveTo( 40, 60, 60, 40 );
+        smileyMouthPath.bezierCurveTo( 70, 45, 70, 50, 60, 60 );
+        smileyMouthPath.quadraticCurveTo( 40, 80, 20, 60 );
+        smileyMouthPath.quadraticCurveTo( 5, 50, 20, 40 );
+
+        smileyShape.holes.push( smileyMouthPath );
+
+
+
+
+        var circle3d = rectShape.extrude( extrudeSettings ); //circleShape rectShape smileyShape
+        // var circle3d = new THREE.ExtrudeGeometry(circleShape, extrudeBend, extrudeSettings );
+        
+        var circlePoints = circleShape.createPointsGeometry();
+        var circleSpacedPoints = circleShape.createSpacedPointsGeometry();
+
+
+        addGeometry( circle3d, circlePoints, circleSpacedPoints,        0x00ff11,  0,  0, 0,     0, 0, 0, 1 );
+
+
+  
+
+        //
+
+        renderer = new THREE.WebGLRenderer( { antialias: true } );
+        renderer.setSize( window.innerWidth, window.innerHeight );
+
+        container.appendChild( renderer.domElement );
+
+        stats = new Stats();
+        stats.domElement.style.position = 'absolute';
+        stats.domElement.style.top = '0px';
+        container.appendChild( stats.domElement );
+
+        document.addEventListener( 'mousedown', onDocumentMouseDown, false );
+        document.addEventListener( 'touchstart', onDocumentTouchStart, false );
+        document.addEventListener( 'touchmove', onDocumentTouchMove, false );
+
+      }
+
+      //
+
+      function onDocumentMouseDown( event ) {
+
+        event.preventDefault();
+
+        document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+        document.addEventListener( 'mouseup', onDocumentMouseUp, false );
+        document.addEventListener( 'mouseout', onDocumentMouseOut, false );
+
+        mouseXOnMouseDown = event.clientX - windowHalfX;
+        targetRotationOnMouseDown = targetRotation;
+
+      }
+
+      function onDocumentMouseMove( event ) {
+
+        mouseX = event.clientX - windowHalfX;
+
+        targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
+
+      }
+
+      function onDocumentMouseUp( event ) {
+
+        document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
+        document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
+        document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
+
+      }
+
+      function onDocumentMouseOut( event ) {
+
+        document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
+        document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
+        document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
+
+      }
+
+      function onDocumentTouchStart( event ) {
+
+        if ( event.touches.length == 1 ) {
+
+          event.preventDefault();
+
+          mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
+          targetRotationOnMouseDown = targetRotation;
+
+        }
+
+      }
+
+      function onDocumentTouchMove( event ) {
+
+        if ( event.touches.length == 1 ) {
+
+          event.preventDefault();
+
+          mouseX = event.touches[ 0 ].pageX - windowHalfX;
+          targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
+
+        }
+
+      }
+
+      //
+
+      function animate() {
+
+        requestAnimationFrame( animate );
+
+        render();
+        stats.update();
+
+      }
+
+      function render() {
+
+        parent.rotation.y += ( targetRotation - parent.rotation.y ) * 0.05;
+        renderer.render( scene, camera );
+
+      }
+
+    </script>
+
+  </body>
+</html>

+ 37 - 24
src/extras/geometries/ExtrudeGeometry.js

@@ -8,14 +8,15 @@
  *  size: 			<float>, 	// size of the text
  *  size: 			<float>, 	// size of the text
  *  height: 		<float>, 	// thickness to extrude text
  *  height: 		<float>, 	// thickness to extrude text
  *  curveSegments: 	<int>,		// number of points on the curves
  *  curveSegments: 	<int>,		// number of points on the curves
- *  steps: 			<int>,		// number of points for z-side extrusions / used for subdivding extrude spline too
+ *  steps: 			<int>,		// number of points for z-side extrusions / used for subdividing segements of extrude spline too
+ 	amount: <int>,	// Amount 
  *
  *
  *  bevelEnabled:	<bool>,			// turn on bevel
  *  bevelEnabled:	<bool>,			// turn on bevel
  *  bevelThickness: <float>, 		// how deep into text bevel goes
  *  bevelThickness: <float>, 		// how deep into text bevel goes
  *  bevelSize:		<float>, 		// how far from text outline is bevel
  *  bevelSize:		<float>, 		// how far from text outline is bevel
  *  bevelSegments:	<int>, 			// number of bevel layers
  *  bevelSegments:	<int>, 			// number of bevel layers
  *
  *
- *  extrudePath:	<THREE.CurvePath>	// 2d/3d spline path to extrude shape orthoganly to
+ *  extrudePath:	<THREE.CurvePath>	// 2d/3d spline path to extrude shape orthogonality to
  *  bendPath:		<THREE.CurvePath> 	// 2d path for bend the shape around x/y plane
  *  bendPath:		<THREE.CurvePath> 	// 2d path for bend the shape around x/y plane
  *
  *
  *  material:		 <int>	// material index for front and back faces
  *  material:		 <int>	// material index for front and back faces
@@ -405,12 +406,20 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) {
 
 
 	bs = bevelSize;
 	bs = bevelSize;
 
 
-	// SETUP TNB variables 
+	// SETUP TNB variables
+
+	// Reuse TNB from TubeGeomtry for now.
+	// TODO1 - have a .isClosed in spline?
+	// TODO2 - have have TNBs calculation refactored from TubeGeometry?
+	var splineTube = new THREE.TubeGeometry(extrudePath, steps, 1, 1, true, false);
+	
+	console.log(splineTube);
+
     var tangent;
     var tangent;
     var binormal = new THREE.Vector3();
     var binormal = new THREE.Vector3();
     var normal = new THREE.Vector3();
     var normal = new THREE.Vector3();
     var position2 = new THREE.Vector3();
     var position2 = new THREE.Vector3();
-    var lastBinormal = new THREE.Vector3(1, 0, 0);
+
     var cx, cy;
     var cx, cy;
 
 
 	// Back facing vertices
 	// Back facing vertices
@@ -429,19 +438,23 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) {
 
 
 			var splinePt = extrudePts[ 0 ];
 			var splinePt = extrudePts[ 0 ];
 
 
-			tangent = extrudePath.getTangentAt(0);
 
 
-            normal.cross(lastBinormal, tangent).normalize();
-            binormal.cross(tangent, normal).normalize();
-            lastBinormal = binormal;
+			normal.copy(splineTube.normals[0]);
+			binormal.copy(splineTube.binormals[0]);
+
+			// normal.copy(binormal).crossSelf(splineTube.tangents[0]);
 
 
-            cx = vert.x;
-            cy = vert.y;
+			cx = vert.x;
+			cy = vert.y;
+			normal.multiplyScalar(vert.x);
+			binormal.multiplyScalar(vert.y);
+
+			position2.copy(splinePt);
+            position2.addSelf(normal);
+            position2.addSelf(binormal);
+
+            
 
 
-            position2.copy(splinePt);
-            position2.x += cx * normal.x + cy * binormal.x;
-            position2.y += cx * normal.y + cy * binormal.y;
-            position2.z += cx * normal.z + cy * binormal.z;
             v( position2.x, position2.y, position2.z );
             v( position2.x, position2.y, position2.z );
 
 
 		}
 		}
@@ -466,21 +479,21 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) {
 			} else {
 			} else {
 
 
 				// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
 				// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
-				var splinePt = extrudePts[ (s - 1) ];
+				var splinePt = extrudePts[ (s-1) ];
 
 
-				tangent = extrudePath.getTangentAt((s - 1)/steps );
+				normal.copy(splineTube.normals[s-1]);
+				binormal.copy(splineTube.binormals[s-1]);
 
 
-				normal.cross(lastBinormal, tangent).normalize();
-				binormal.cross(tangent, normal).normalize();
-				lastBinormal = binormal;
+				// normal.copy(binormal).crossSelf(splineTube.tangents[s - 1]);
 
 
-				cx = vert.x;
-				cy = vert.y;
+				normal.multiplyScalar(vert.x);
+				binormal.multiplyScalar(vert.y);
 
 
 				position2.copy(splinePt);
 				position2.copy(splinePt);
-				position2.x += cx * normal.x + cy * binormal.x;
-				position2.y += cx * normal.y + cy * binormal.y;
-				position2.z += cx * normal.z + cy * binormal.z;
+	            position2.addSelf(normal);
+	            position2.addSelf(binormal);
+
+
 				v( position2.x, position2.y, position2.z );
 				v( position2.x, position2.y, position2.z );
 
 
 			}
 			}