Sfoglia il codice sorgente

Updated Normals Helpers to Support BufferGeometry and Output BufferGeometry

WestLangley 10 anni fa
parent
commit
60612f1991

+ 10 - 3
examples/webgl_helpers.html

@@ -19,6 +19,7 @@
 
 			var scene, renderer;
 			var camera, light;
+			var fnh, vnh;
 
 			init();
 			animate();
@@ -60,10 +61,13 @@
 					var mesh = new THREE.Mesh( geometry, material );
 					group.add( mesh );
 
-					group.add( new THREE.FaceNormalsHelper( mesh, 0.1 ) );
-					group.add( new THREE.VertexNormalsHelper( mesh, 0.1 ) );
+					fnh = new THREE.FaceNormalsHelper( mesh, 5 );
+					scene.add( fnh );
 
-					group.add( new THREE.BoxHelper( mesh ) );
+					vnh = new THREE.VertexNormalsHelper( mesh, 5 );
+					scene.add( vnh );
+
+					scene.add( new THREE.BoxHelper( mesh ) );
 
 					var wireframe = new THREE.WireframeGeometry( geometry );
 					var line = new THREE.LineSegments( wireframe );
@@ -112,6 +116,9 @@
 				light.position.y = Math.cos( time * 1.5 ) * 400;
 				light.position.z = Math.cos( time * 1.3 ) * 300;
 
+				if ( fnh ) fnh.update();
+				if ( vnh ) vnh.update();
+
 				renderer.render( scene, camera );
 
 			}

+ 66 - 28
src/extras/helpers/FaceNormalsHelper.js

@@ -5,6 +5,8 @@
 
 THREE.FaceNormalsHelper = function ( object, size, hex, linewidth ) {
 
+	// FaceNormalsHelper only supports THREE.Geometry
+
 	this.object = object;
 
 	this.size = ( size !== undefined ) ? size : 1;
@@ -13,18 +15,34 @@ THREE.FaceNormalsHelper = function ( object, size, hex, linewidth ) {
 
 	var width = ( linewidth !== undefined ) ? linewidth : 1;
 
-	var geometry = new THREE.Geometry();
+	//
+
+	var nNormals = 0;
+
+	var objGeometry = this.object.geometry;
+
+	if ( objGeometry instanceof THREE.Geometry ) {
 
-	var faces = this.object.geometry.faces;
+		nNormals = objGeometry.faces.length;
 
-	for ( var i = 0, l = faces.length; i < l; i ++ ) {
+	} else {
 
-		geometry.vertices.push( new THREE.Vector3(), new THREE.Vector3() );
+		console.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' );
 
 	}
 
+	//
+
+	var geometry = new THREE.BufferGeometry();
+
+	var positions = new THREE.Float32Attribute( nNormals * 2 * 3, 3 );
+
+	geometry.addAttribute( 'position', positions );
+
 	THREE.LineSegments.call( this, geometry, new THREE.LineBasicMaterial( { color: color, linewidth: width } ) );
 
+	//
+
 	this.matrixAutoUpdate = false;
 
 	this.normalMatrix = new THREE.Matrix3();
@@ -36,39 +54,59 @@ THREE.FaceNormalsHelper = function ( object, size, hex, linewidth ) {
 THREE.FaceNormalsHelper.prototype = Object.create( THREE.LineSegments.prototype );
 THREE.FaceNormalsHelper.prototype.constructor = THREE.FaceNormalsHelper;
 
-THREE.FaceNormalsHelper.prototype.update = function () {
+THREE.FaceNormalsHelper.prototype.update = ( function () {
 
-	var vertices = this.geometry.vertices;
+	var v1 = new THREE.Vector3();
+	var v2 = new THREE.Vector3();
 
-	var object = this.object;
-	var objectVertices = object.geometry.vertices;
-	var objectFaces = object.geometry.faces;
-	var objectWorldMatrix = object.matrixWorld;
+	return function() {
 
-	object.updateMatrixWorld( true );
+		this.object.updateMatrixWorld( true );
 
-	this.normalMatrix.getNormalMatrix( objectWorldMatrix );
+		this.normalMatrix.getNormalMatrix( this.object.matrixWorld );
 
-	for ( var i = 0, i2 = 0, l = objectFaces.length; i < l; i ++, i2 += 2 ) {
+		var matrixWorld = this.object.matrixWorld;
 
-		var face = objectFaces[ i ];
+		var position = this.geometry.attributes.position;
 
-		vertices[ i2 ].copy( objectVertices[ face.a ] )
-			.add( objectVertices[ face.b ] )
-			.add( objectVertices[ face.c ] )
-			.divideScalar( 3 )
-			.applyMatrix4( objectWorldMatrix );
+		//
 
-		vertices[ i2 + 1 ].copy( face.normal )
-			.applyMatrix3( this.normalMatrix )
-			.normalize()
-			.multiplyScalar( this.size )
-			.add( vertices[ i2 ] );
+		var objGeometry = this.object.geometry;
 
-	}
+		var vertices = objGeometry.vertices;
 
-	this.geometry.verticesNeedUpdate = true;
+		var faces = objGeometry.faces;
 
-	return this;
+		var idx = 0;
 
-};
+		for ( var i = 0, l = faces.length; i < l; i ++ ) {
+
+			var face = faces[ i ];
+
+			var normal = face.normal;
+
+			v1.copy( vertices[ face.a ] )
+				.add( vertices[ face.b ] )
+				.add( vertices[ face.c ] )
+				.divideScalar( 3 )
+				.applyMatrix4( matrixWorld );
+
+			v2.copy( normal ).applyMatrix3( this.normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
+
+			position.setXYZ( idx, v1.x, v1.y, v1.z );
+
+			idx = idx + 1;
+
+			position.setXYZ( idx, v2.x, v2.y, v2.z );
+
+			idx = idx + 1;
+
+		}
+
+		position.needsUpdate = true;
+
+		return this;
+
+	}
+
+}());

+ 74 - 26
src/extras/helpers/VertexNormalsHelper.js

@@ -13,24 +13,34 @@ THREE.VertexNormalsHelper = function ( object, size, hex, linewidth ) {
 
 	var width = ( linewidth !== undefined ) ? linewidth : 1;
 
-	var geometry = new THREE.Geometry();
+	//
 
-	var faces = object.geometry.faces;
+	var nNormals = 0;
 
-	for ( var i = 0, l = faces.length; i < l; i ++ ) {
+	var objGeometry = this.object.geometry;
 
-		var face = faces[ i ];
+	if ( objGeometry instanceof THREE.Geometry ) {
 
-		for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
+		nNormals = objGeometry.faces.length * 3;
 
-			geometry.vertices.push( new THREE.Vector3(), new THREE.Vector3() );
+	} else if ( objGeometry instanceof THREE.BufferGeometry ) {
 
-		}
+		nNormals = objGeometry.attributes.normal.count
 
 	}
 
+	//
+
+	var geometry = new THREE.BufferGeometry();
+
+	var positions = new THREE.Float32Attribute( nNormals * 2 * 3, 3 );
+
+	geometry.addAttribute( 'position', positions );
+
 	THREE.LineSegments.call( this, geometry, new THREE.LineBasicMaterial( { color: color, linewidth: width } ) );
 
+	//
+
 	this.matrixAutoUpdate = false;
 
 	this.normalMatrix = new THREE.Matrix3();
@@ -42,54 +52,92 @@ THREE.VertexNormalsHelper = function ( object, size, hex, linewidth ) {
 THREE.VertexNormalsHelper.prototype = Object.create( THREE.LineSegments.prototype );
 THREE.VertexNormalsHelper.prototype.constructor = THREE.VertexNormalsHelper;
 
-THREE.VertexNormalsHelper.prototype.update = ( function ( object ) {
+THREE.VertexNormalsHelper.prototype.update = ( function () {
 
 	var v1 = new THREE.Vector3();
+	var v2 = new THREE.Vector3();
 
-	return function( object ) {
+	return function() {
 
-		var keys = [ 'a', 'b', 'c', 'd' ];
+		var keys = [ 'a', 'b', 'c' ];
 
 		this.object.updateMatrixWorld( true );
 
 		this.normalMatrix.getNormalMatrix( this.object.matrixWorld );
 
-		var vertices = this.geometry.vertices;
+		var matrixWorld = this.object.matrixWorld;
+
+		var position = this.geometry.attributes.position;
+
+		//
+
+		var objGeometry = this.object.geometry;
+
+		if ( objGeometry instanceof THREE.Geometry ) {
+
+			var vertices = objGeometry.vertices;
+
+			var faces = objGeometry.faces;
+
+			var idx = 0;
+
+			for ( var i = 0, l = faces.length; i < l; i ++ ) {
 
-		var verts = this.object.geometry.vertices;
+				var face = faces[ i ];
 
-		var faces = this.object.geometry.faces;
+				for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
 
-		var worldMatrix = this.object.matrixWorld;
+					var vertex = vertices[ face[ keys[ j ] ] ];
 
-		var idx = 0;
+					var normal = face.vertexNormals[ j ];
 
-		for ( var i = 0, l = faces.length; i < l; i ++ ) {
+					v1.copy( vertex ).applyMatrix4( matrixWorld );
 
-			var face = faces[ i ];
+					v2.copy( normal ).applyMatrix3( this.normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
 
-			for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
+					position.setXYZ( idx, v1.x, v1.y, v1.z );
 
-				var vertexId = face[ keys[ j ] ];
-				var vertex = verts[ vertexId ];
+					idx = idx + 1;
 
-				var normal = face.vertexNormals[ j ];
+					position.setXYZ( idx, v2.x, v2.y, v2.z );
 
-				vertices[ idx ].copy( vertex ).applyMatrix4( worldMatrix );
+					idx = idx + 1;
 
-				v1.copy( normal ).applyMatrix3( this.normalMatrix ).normalize().multiplyScalar( this.size );
+				}
+
+			}
+
+		} else if ( objGeometry instanceof THREE.BufferGeometry ) {
+
+			var objPos = objGeometry.attributes.position;
+
+			var objNorm = objGeometry.attributes.normal;
+
+			var idx = 0;
+
+			// for simplicity, ignore index and drawcalls, and render every normal
+
+			for ( var j = 0, jl = objPos.count; j < jl; j ++ ) {
+
+				v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );
+
+				v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) );
+
+				v2.applyMatrix3( this.normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
+
+				position.setXYZ( idx, v1.x, v1.y, v1.z );
 
-				v1.add( vertices[ idx ] );
 				idx = idx + 1;
 
-				vertices[ idx ].copy( v1 );
+				position.setXYZ( idx, v2.x, v2.y, v2.z );
+
 				idx = idx + 1;
 
 			}
 
 		}
 
-		this.geometry.verticesNeedUpdate = true;
+		position.needsUpdate = true;
 
 		return this;
 

+ 75 - 26
src/extras/helpers/VertexTangentsHelper.js

@@ -13,25 +13,34 @@ THREE.VertexTangentsHelper = function ( object, size, hex, linewidth ) {
 
 	var width = ( linewidth !== undefined ) ? linewidth : 1;
 
-	var geometry = new THREE.Geometry();
+	//
 
-	var faces = object.geometry.faces;
+	var nTangents = 0;
 
-	for ( var i = 0, l = faces.length; i < l; i ++ ) {
+	var objGeometry = this.object.geometry;
 
-		var face = faces[ i ];
+	if ( objGeometry instanceof THREE.Geometry ) {
 
-		for ( var j = 0, jl = face.vertexTangents.length; j < jl; j ++ ) {
+		nTangents = objGeometry.faces.length * 3;
 
-			geometry.vertices.push( new THREE.Vector3() );
-			geometry.vertices.push( new THREE.Vector3() );
+	} else if ( objGeometry instanceof THREE.BufferGeometry ) {
 
-		}
+		nTangents = objGeometry.attributes.tangent.count
 
 	}
 
+	//
+
+	var geometry = new THREE.BufferGeometry();
+
+	var positions = new THREE.Float32Attribute( nTangents * 2 * 3, 3 );
+
+	geometry.addAttribute( 'position', positions );
+
 	THREE.LineSegments.call( this, geometry, new THREE.LineBasicMaterial( { color: color, linewidth: width } ) );
 
+	//
+
 	this.matrixAutoUpdate = false;
 
 	this.update();
@@ -44,49 +53,89 @@ THREE.VertexTangentsHelper.prototype.constructor = THREE.VertexTangentsHelper;
 THREE.VertexTangentsHelper.prototype.update = ( function ( object ) {
 
 	var v1 = new THREE.Vector3();
+	var v2 = new THREE.Vector3();
 
-	return function( object ) {
+	return function() {
 
-		var keys = [ 'a', 'b', 'c', 'd' ];
+		var keys = [ 'a', 'b', 'c' ];
 
 		this.object.updateMatrixWorld( true );
 
-		var vertices = this.geometry.vertices;
+		var matrixWorld = this.object.matrixWorld;
+
+		var position = this.geometry.attributes.position;
+
+		//
+
+		var objGeometry = this.object.geometry;
+
+		if ( objGeometry instanceof THREE.Geometry ) {
+
+			var vertices = objGeometry.vertices;
+
+			var faces = objGeometry.faces;
+
+			var idx = 0;
+
+			for ( var i = 0, l = faces.length; i < l; i ++ ) {
 
-		var verts = this.object.geometry.vertices;
+				var face = faces[ i ];
 
-		var faces = this.object.geometry.faces;
+				for ( var j = 0, jl = face.vertexTangents.length; j < jl; j ++ ) {
 
-		var worldMatrix = this.object.matrixWorld;
+					var vertex = vertices[ face[ keys[ j ] ] ];
 
-		var idx = 0;
+					var tangent = face.vertexTangents[ j ];
 
-		for ( var i = 0, l = faces.length; i < l; i ++ ) {
+					v1.copy( vertex ).applyMatrix4( matrixWorld );
 
-			var face = faces[ i ];
+					v2.set( tangent.x, tangent.y, tangent.z ); // tangent.w used for bitangents only
 
-			for ( var j = 0, jl = face.vertexTangents.length; j < jl; j ++ ) {
+					v2.transformDirection( matrixWorld ).multiplyScalar( this.size ).add( v1 );
 
-				var vertexId = face[ keys[ j ] ];
-				var vertex = verts[ vertexId ];
+					position.setXYZ( idx, v1.x, v1.y, v1.z );
 
-				var tangent = face.vertexTangents[ j ];
+					idx = idx + 1;
 
-				vertices[ idx ].copy( vertex ).applyMatrix4( worldMatrix );
+					position.setXYZ( idx, v2.x, v2.y, v2.z );
 
-				v1.copy( tangent ).transformDirection( worldMatrix ).multiplyScalar( this.size );
+					idx = idx + 1;
+
+				}
+
+			}
+
+		} else if ( objGeometry instanceof THREE.BufferGeometry ) {
+
+			var objPos = objGeometry.attributes.position;
+
+			var objTan = objGeometry.attributes.tangent;
+
+			var idx = 0;
+
+			// for simplicity, ignore index and drawcalls, and render every tangent
+
+			for ( var j = 0, jl = objPos.count; j < jl; j ++ ) {
+
+				v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );
+
+				v2.set( objTan.getX( j ), objTan.getY( j ), objTan.getZ( j ) ); // tangent.w used for bitangents only
+
+				v2.transformDirection( matrixWorld ).multiplyScalar( this.size ).add( v1 );
+
+				position.setXYZ( idx, v1.x, v1.y, v1.z );
 
-				v1.add( vertices[ idx ] );
 				idx = idx + 1;
 
-				vertices[ idx ].copy( v1 );
+				position.setXYZ( idx, v2.x, v2.y, v2.z );
+
 				idx = idx + 1;
 
 			}
 
 		}
 
-		this.geometry.verticesNeedUpdate = true;
+		position.needsUpdate = true;
 
 		return this;