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).
This commit is contained in:
Dean Jackson
2011-11-30 08:40:27 +11:00
parent d9f055c989
commit 5965061ca1
2 changed files with 227 additions and 10 deletions
+217
View File
@@ -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
View File
@@ -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( [