Browse Source

Extruded geometry was treating materials as objects rather than indices and
UV mapping of extruded geometry was miscalculated.

- ExtrudeGeometry was documented to take a Three.Material for the
"material" and "extrudeMaterial" parameters, but the examples and
usage in TextGeometry showed that these were in fact indices into
the materials array. This meant that the tests such as "if (material)"
would evaluate to false if the index passed in was 0 (a very typical
index to choose :). Simply have the tests check against undefined and
update the documentation.

- Also, the code that converted a shape into a set of triangles was
miscalculating the UV offsets. It was correctly dividing the UV by
the bounding box of the old shape, but was forgetting to offset the
value from the minimum (which potentially led to negative UVs).

Dean Jackson 13 years ago
parent
commit
5965061ca1
2 changed files with 227 additions and 10 deletions
  1. 217 0
      examples/webgl_extrude_material.html
  2. 10 10
      src/extras/geometries/ExtrudeGeometry.js

+ 217 - 0
examples/webgl_extrude_material.html

@@ -0,0 +1,217 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <title>three.js webgl - geometry - extrusion materials</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="js/RequestAnimationFrame.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 loadTexture( path ) {
+
+        var image = new Image();
+        image.onload = function () { texture.needsUpdate = true; };
+        image.src = path;
+
+        var texture  = new THREE.Texture( image, new THREE.UVMapping(), THREE.ClampToEdgeWrapping, THREE.ClampToEdgeWrapping, THREE.NearestFilter, THREE.LinearMipMapLinearFilter );
+
+        return new THREE.MeshBasicMaterial( { map: texture } );
+
+      }
+
+      function init() {
+
+        container = document.createElement( 'div' );
+        document.body.appendChild( container );
+
+        var grass = loadTexture( 'textures/minecraft/grass.png' );
+
+        var info = document.createElement( 'div' );
+        info.style.position = 'absolute';
+        info.style.top = '10px';
+        info.style.width = '100%';
+        info.style.textAlign = 'center';
+        info.innerHTML = 'Procedurally generated 3D shapes with different materials on extrusions<br/>Drag to spin';
+        container.appendChild( info );
+
+        camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
+        camera.position.y = 150;
+        camera.position.z = 500;
+
+        scene = new THREE.Scene();
+        scene.add( camera );
+
+        parent = new THREE.Object3D();
+        parent.position.y = 150;
+        scene.add( parent );
+
+        var extrudeSettings = { amount: 20, bevelEnabled: true, bevelSegments: 2, steps: 2, material: 0, extrudeMaterial: 1 };
+
+        var colorMaterials = [ new THREE.MeshBasicMaterial({ color: 0x006ed5 }), new THREE.MeshBasicMaterial({ color: 0x6ed500 }) ];
+
+        var imageAndColorMaterials = [ grass, new THREE.MeshBasicMaterial({ color: 0x6ed500 }) ];
+        
+        var pillShape1 = new THREE.Shape();
+        pillShape1.moveTo(  30, 10 );
+        pillShape1.lineTo(  100, 10 );
+        pillShape1.quadraticCurveTo( 120, 20, 100, 30 );
+        pillShape1.lineTo( 30, 30 );
+        pillShape1.quadraticCurveTo( 10, 20, 30, 10 );
+
+        var pillGeometry1 = pillShape1.extrude( extrudeSettings );
+        pillGeometry1.materials = colorMaterials;
+        var pillMesh1 = new THREE.Mesh( pillGeometry1, new THREE.MeshFaceMaterial() );
+
+        parent.add ( pillMesh1 );
+
+        var pillShape2 = new THREE.Shape();
+        pillShape2.moveTo(  30, 80 );
+        pillShape2.lineTo(  100, 80 );
+        pillShape2.quadraticCurveTo( 120, 90, 100, 100 );
+        pillShape2.lineTo( 30, 100 );
+        pillShape2.quadraticCurveTo( 10, 90, 30, 80 );
+
+        var pillGeometry2 = pillShape2.extrude( extrudeSettings );
+        pillGeometry2.materials = imageAndColorMaterials;
+        var pillMesh2 = new THREE.Mesh( pillGeometry2, new THREE.MeshFaceMaterial() );
+
+        parent.add ( pillMesh2 );
+
+
+        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>

+ 10 - 10
src/extras/geometries/ExtrudeGeometry.js

@@ -22,8 +22,8 @@
  *  extrudePath:	<THREE.CurvePath>	// path to extrude shape along
  *  bendPath:		<THREE.CurvePath> 	// path to bend the geometry around
  *
- *  material:		 <THREE.Material>	// material for front and back faces
- *  extrudeMaterial: <THREE.Material>	// material for extrusion and beveled faces
+ *  material:		 <int>	// material index for front and back faces
+ *  extrudeMaterial: <int>	// material index for extrusion and beveled faces
  *
  *  }
   **/
@@ -621,7 +621,7 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) {
 
 				f4( a, b, c, d );
 
-				if ( extrudeMaterial ) {
+				if ( extrudeMaterial !== undefined ) {
 
 					var v1 = s / sl;
 					var v2 = ( s + 1 ) / sl;
@@ -664,21 +664,21 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) {
 		scope.faces.push( new THREE.Face3( a, b, c, null, null, material ) );
 		//normal, color, materials
 
-		if ( material ) {
+		if ( material !== undefined ) {
 
 			var mx = shapebb.minX, my = shapebb.minY;
 
 			var uy = shapebb.maxY; // - shapebb.minY;
 			var ux = shapebb.maxX; // - shapebb.minX;
 
-			var ax = scope.vertices[ a ].position.x,
-				ay = scope.vertices[ a ].position.y,
+			var ax = scope.vertices[ a ].position.x - mx,
+				ay = scope.vertices[ a ].position.y - my,
 
-				bx = scope.vertices[ b ].position.x,
-				by = scope.vertices[ b ].position.y,
+				bx = scope.vertices[ b ].position.x - mx,
+				by = scope.vertices[ b ].position.y - my,
 
-				cx = scope.vertices[ c ].position.x,
-				cy = scope.vertices[ c ].position.y;
+				cx = scope.vertices[ c ].position.x - mx,
+				cy = scope.vertices[ c ].position.y - my;
 
 			scope.faceVertexUvs[ 0 ].push( [