Browse Source

Removed unnecessary vertex hashing which caused bugs if geometry was small enough for the hash function's rounding to cause loss of precision. Added support for faces with vcount greater than 4 by subdividing. Fixed texture bugs: V for UV was inverted, UVs not set for Face4s, offset and repeat and wrap options not set properly.

Work by: Erik Kitson and Khang Duong
Erik Kitson 13 years ago
parent
commit
05b6489520
1 changed files with 132 additions and 101 deletions
  1. 132 101
      src/extras/loaders/ColladaLoader.js

+ 132 - 101
src/extras/loaders/ColladaLoader.js

@@ -1809,30 +1809,13 @@ THREE.ColladaLoader = function () {
 
 
 		}
 		}
 
 
-		var vertex_store = {};
-
-		function get_vertex ( v, index )  {
-
-			var hash = _hash_vector3( v.position );
-
-			if ( vertex_store[ hash ] === undefined ) {
-
-				vertex_store[ hash ] = { v: v, index: index };
-
-			}
-
-			return vertex_store[ hash ];
-
-		}
-
 		this.geometry3js = new THREE.Geometry();
 		this.geometry3js = new THREE.Geometry();
 
 
 		var vertexData = sources[ this.vertices.input['POSITION'].source ].data;
 		var vertexData = sources[ this.vertices.input['POSITION'].source ].data;
 
 
-		for ( i = 0, j = 0; i < vertexData.length; i += 3, j ++ ) {
+		for ( i = 0; i < vertexData.length; i += 3 ) {
 
 
 			var v = new THREE.Vertex( new THREE.Vector3( vertexData[ i ], vertexData[ i + 1 ], vertexData[ i + 2 ] ) );
 			var v = new THREE.Vertex( new THREE.Vector3( vertexData[ i ], vertexData[ i + 1 ], vertexData[ i + 2 ] ) );
-			get_vertex( v, j );
 			this.geometry3js.vertices.push( v );
 			this.geometry3js.vertices.push( v );
 
 
 		}
 		}
@@ -1841,7 +1824,7 @@ THREE.ColladaLoader = function () {
 
 
 			var primitive = this.primitives[ i ];
 			var primitive = this.primitives[ i ];
 			primitive.setVertices( this.vertices );
 			primitive.setVertices( this.vertices );
-			this.handlePrimitive( primitive, this.geometry3js, vertex_store );
+			this.handlePrimitive( primitive, this.geometry3js );
 
 
 		}
 		}
 
 
@@ -1854,7 +1837,7 @@ THREE.ColladaLoader = function () {
 
 
 	};
 	};
 
 
-	Mesh.prototype.handlePrimitive = function( primitive, geom, vertex_store ) {
+	Mesh.prototype.handlePrimitive = function( primitive, geom ) {
 
 
 		var i = 0, j, k, p = primitive.p, inputs = primitive.inputs;
 		var i = 0, j, k, p = primitive.p, inputs = primitive.inputs;
 		var input, index, idx32;
 		var input, index, idx32;
@@ -1904,8 +1887,7 @@ THREE.ColladaLoader = function () {
 
 
 						case 'VERTEX':
 						case 'VERTEX':
 
 
-							var hash = _hash_vector3( geom.vertices[ index ].position );
-							vs.push( vertex_store[ hash ].index );
+							vs.push( index );
 
 
 							break;
 							break;
 
 
@@ -1918,7 +1900,8 @@ THREE.ColladaLoader = function () {
 						case 'TEXCOORD':
 						case 'TEXCOORD':
 
 
 							if ( ts[ input.set ] === undefined ) ts[ input.set ] = [];
 							if ( ts[ input.set ] === undefined ) ts[ input.set ] = [];
-							ts[ input.set ].push( new THREE.UV( source.data[ idx32 ], source.data[ idx32 + 1 ] ) );
+							// invert the V
+							ts[ input.set ].push( new THREE.UV( source.data[ idx32 ], 1.0 - source.data[ idx32 + 1 ] ) );
 
 
 							break;
 							break;
 
 
@@ -1938,25 +1921,73 @@ THREE.ColladaLoader = function () {
 			}
 			}
 
 
 
 
-			var face, uv;
+			var face = null, faces = [], uv, uvArr;
+
+			if ( vcount === 3 ) {
+
+				faces.push( new THREE.Face3( vs[0], vs[1], vs[2], [ ns[0], ns[1], ns[2] ], cs.length ? cs : new THREE.Color() ) );
+
+			} else if ( vcount === 4 ) {
+
+				faces.push( new THREE.Face4( vs[0], vs[1], vs[2], vs[3], [ ns[0], ns[1], ns[2], ns[3] ], cs.length ? cs : new THREE.Color() ) );
 
 
-			if ( vcount == 3 ) {
+			} else if ( vcount > 4 ) {
 
 
-				face = new THREE.Face3( vs[0], vs[1], vs[2], [ ns[0], ns[1], ns[2] ], cs.length ? cs : new THREE.Color() );
+				var clr = cs.length ? cs : new THREE.Color(),
+					vec1, vec2, vec3, v1, v2, norm;
 
 
-			} else if ( vcount == 4 ) {
+				// subdivide into multiple Face3s
+				for ( k = 1; k < vcount-1; ) {
 
 
-				face = new THREE.Face4( vs[0], vs[1], vs[2], vs[3], [ ns[0], ns[1], ns[2], ns[3] ], cs.length ? cs : new THREE.Color() );
+					// FIXME: normals don't seem to be quite right
+					faces.push( new THREE.Face3( vs[0], vs[k], vs[k+1], [ ns[0], ns[k++], ns[k] ],  clr ) );
+
+				}
 
 
 			}
 			}
 
 
-			face.daeMaterial = primitive.material;
-			geom.faces.push( face );
+			if ( faces.length ) {
+
+				for (var ndx = 0, len = faces.length; ndx < len; ndx++) {
+
+					face = faces[ndx];
+					face.daeMaterial = primitive.material;
+					geom.faces.push( face );
+
+					for ( k = 0; k < texture_sets.length; k++ ) {
+
+						uv = ts[ texture_sets[k] ];
+
+						if ( vcount > 4 ) {
 
 
-			for ( k = 0; k < texture_sets.length; k ++ ) {
+							// Grab the right UVs for the vertices in this face
+							uvArr = [ uv[0], uv[ndx+1], uv[ndx+2] ];
+
+						} else if ( vcount === 4 ) {
+
+							uvArr = [ uv[0], uv[1], uv[2], uv[3] ];
+
+						} else {
+
+							uvArr = [ uv[0], uv[1], uv[2] ];
+
+						}
 
 
-				uv = ts[ texture_sets[ k ] ];
-				geom.faceVertexUvs[ k ].push( [ uv[0], uv[1], uv[2] ] );
+						if ( !geom.faceVertexUvs[k] ) {
+
+							geom.faceVertexUvs[k] = [];
+
+						}
+
+						geom.faceVertexUvs[k].push( uvArr );
+
+					}
+
+				}
+
+			} else {
+
+				console.log( 'dropped face with vcount ' + vcount + ' for geometry with id: ' + geom.id );
 
 
 			}
 			}
 
 
@@ -2273,6 +2304,7 @@ THREE.ColladaLoader = function () {
 
 
 		this.texture = null;
 		this.texture = null;
 		this.texcoord = null;
 		this.texcoord = null;
+		this.texOpts = null;
 
 
 	};
 	};
 
 
@@ -2309,6 +2341,17 @@ THREE.ColladaLoader = function () {
 
 
 					this.texture = child.getAttribute('texture');
 					this.texture = child.getAttribute('texture');
 					this.texcoord = child.getAttribute('texcoord');
 					this.texcoord = child.getAttribute('texcoord');
+					// Defaults from:
+					// https://collada.org/mediawiki/index.php/Maya_texture_placement_MAYA_extension
+					this.texOpts = {
+						offsetU: 0,
+						offsetV: 0,
+						repeatU: 1,
+						repeatV: 1,
+						wrapU: 1,
+						wrapV: 1,
+					};
+					this.parseTexture( child );
 					break;
 					break;
 
 
 				default:
 				default:
@@ -2322,6 +2365,54 @@ THREE.ColladaLoader = function () {
 
 
 	};
 	};
 
 
+	ColorOrTexture.prototype.parseTexture = function ( element ) {
+
+		// This should be supported by Maya, 3dsMax, and MotionBuilder
+
+		if ( element.children[0] && element.children[0].nodeName === 'extra' ) {
+
+			element = element.children[0];
+
+			if ( element.children[0] && element.children[0].nodeName === 'technique' ) {
+
+				element = element.children[0];
+
+			}
+
+		}
+
+		for ( var i = 0; i < element.children.length; i ++ ) {
+
+			var child = element.children[ i ];
+
+			switch ( child.nodeName ) {
+
+				case 'offsetU':
+				case 'offsetV':
+				case 'repeatU':
+				case 'repeatV':
+
+					this.texOpts[ child.nodeName ] = parseFloat( child.textContent );
+					break;
+
+				case 'wrapU':
+				case 'wrapV':
+
+					this.texOpts[ child.nodeName ] = parseInt( child.textContent );
+					break;
+
+				default:
+					this.texOpts[ child.nodeName ] = child.textContent;
+					break;
+
+			}
+
+		}
+
+		return this;
+
+	};
+
 	function Shader ( type, effect ) {
 	function Shader ( type, effect ) {
 
 
 		this.type = type;
 		this.type = type;
@@ -2399,11 +2490,14 @@ THREE.ColladaLoader = function () {
 
 
 									if ( image ) {
 									if ( image ) {
 
 
-										props['map'] = THREE.ImageUtils.loadTexture(baseUrl + image.init_from);
-										props['map'].wrapS = THREE.RepeatWrapping;
-										props['map'].wrapT = THREE.RepeatWrapping;
-										props['map'].repeat.x = 1;
-										props['map'].repeat.y = -1;
+										var texture = THREE.ImageUtils.loadTexture(baseUrl + image.init_from);
+										texture.wrapS = cot.texOpts.wrapU;
+										texture.wrapT = cot.texOpts.wrapV;
+										texture.offset.x = cot.texOpts.offsetU;
+										texture.offset.y = cot.texOpts.offsetV;
+										texture.repeat.x = cot.texOpts.repeatU;
+										texture.repeat.y = cot.texOpts.repeatV;
+										props['map'] = texture;
 
 
 									}
 									}
 
 
@@ -3127,69 +3221,6 @@ THREE.ColladaLoader = function () {
 
 
 	};
 	};
 
 
-	function _hash_vertex ( v, n, t0, t1, precision ) {
-
-		precision = precision || 2;
-
-		var s = v instanceof THREE.Vertex ? _hash_vector3( v.position, precision ) : _hash_vector3( v, precision );
-
-		if ( n === undefined ) {
-
-			s += '_0.00,0.00,0.00';
-
-		} else {
-
-			s += '_' + _hash_vector3( n, precision );
-
-		}
-
-		if ( t0 === undefined ) {
-
-			s += '_0.00,0.00';
-
-		} else {
-
-			s += '_' + _hash_uv( t0, precision );
-
-		}
-
-		if ( t1 === undefined ) {
-
-			s += '_0.00,0.00';
-
-		} else {
-
-			s += '_' + _hash_uv( t1, precision );
-
-		}
-
-		return s;
-
-	};
-
-	function _hash_uv ( uv, num ) {
-
-		var s = '';
-
-		s += _format_float( uv.u, num ) + ',';
-		s += _format_float( uv.v, num );
-
-		return s;
-
-	};
-
-	function _hash_vector3 ( vec, num ) {
-
-		var s = '';
-
-		s += _format_float( vec.x, num ) + ',';
-		s += _format_float( vec.y, num ) + ',';
-		s += _format_float( vec.z, num );
-
-		return s;
-
-	};
-
 	function evaluateXPath ( node, query ) {
 	function evaluateXPath ( node, query ) {
 
 
 		var instances = COLLADA.evaluate(query,
 		var instances = COLLADA.evaluate(query,