Bläddra i källkod

Update VRMLLoader to use or create an indexed geometry.

With this, VRMLLoader imports any existing indexes, balances all attributes after the main index array, and converts the geometry to a non-indexed triangle soup with hard edges if no normals are defined in the file.
Victor Glindås 6 år sedan
förälder
incheckning
3c37371c87
1 ändrade filer med 102 tillägg och 47 borttagningar
  1. 102 47
      examples/js/loaders/VRMLLoader.js

+ 102 - 47
examples/js/loaders/VRMLLoader.js

@@ -912,91 +912,144 @@ THREE.VRMLLoader.prototype = {
 
 						}
 
-						var skip = 0;
-
 						// some shapes only have vertices for use in other shapes
 
 						if ( data.coordIndex ) {
 
+							function triangulateIndexArray( indexArray ) {
+
+								var triangulatedIndexArray = [];
+								var ccw = data.ccw === undefined ? true : data.ccw; // ccw is true by default
+								var skip = 0;
+
+								for ( i = 0, il = indexArray.length; i < il; i ++ ) {
+
+									var indexedFace = data.coordIndex[ i ];
+	
+									// VRML support multipoint indexed face sets (more then 3 vertices). You must calculate the composing triangles here
+	
+									skip = 0;
+	
+									while ( indexedFace.length >= 3 && skip < ( indexedFace.length - 2 ) ) {
+
+										var i1 = indexedFace[ 0 ];
+										var i2 = indexedFace[ skip + ( ccw ? 1 : 2 ) ];
+										var i3 = indexedFace[ skip + ( ccw ? 2 : 1 ) ];
+	
+										triangulatedIndexArray.push( i1, i2, i3 );
+	
+										skip ++;
+	
+									}
+	
+								}
+
+								return triangulatedIndexArray;
+
+							}
+
+							var positionIndexes = data.coordIndex ? triangulateIndexArray( data.coordIndex ) : [];
+							var normalIndexes = data.normalIndex ? triangulateIndexArray( data.normalIndex ) : positionIndexes;
+							var colorIndexes = data.colorIndex ? triangulateIndexArray( data.colorIndex ) : positionIndexes;
+							var uvIndexes = data.texCoordIndex ? triangulateIndexArray( data.texCoordIndex ) : positionIndexes;
+
+							var newIndexes = [];
 							var newPositions = [];
-							var newColors = [];
 							var newNormals = [];
+							var newColors = [];
 							var newUvs = [];
 
-							position = new THREE.Vector3();
-							color = new THREE.Color();
-							normal = new THREE.Vector3();
-							uv = new THREE.Vector2();
+							// if any other index array does not match the coordinate indexes, split any points that differ
 
-							for ( i = 0, il = data.coordIndex.length; i < il; i ++ ) {
+							var pointMap = Object.create( null );
 
-								var indexes = data.coordIndex[ i ];
+							for ( i = 0; i < positionIndexes.length; i ++ ) {
 
-								// VRML support multipoint indexed face sets (more then 3 vertices). You must calculate the composing triangles here
+								var pointAttributes = [];
 
-								skip = 0;
+								var positionIndex = positionIndexes[ i ];
+								var normalIndex = normalIndexes[ i ];
+								var colorIndex = colorIndexes[ i ];
+								var uvIndex = uvIndexes[ i ];
 
-								while ( indexes.length >= 3 && skip < ( indexes.length - 2 ) ) {
+								var base = 10; // which base to use to represent each value
 
-									if ( data.ccw === undefined ) data.ccw = true; // ccw is true by default
+								pointAttributes.push( positionIndex.toString( base ) );
 
-									var i1 = indexes[ 0 ];
-									var i2 = indexes[ skip + ( data.ccw ? 1 : 2 ) ];
-									var i3 = indexes[ skip + ( data.ccw ? 2 : 1 ) ];
+								if ( normalIndex !== undefined ) {
 
-									// create non indexed geometry, necessary for face normal generation
+									pointAttributes.push( normalIndex.toString( base ) );
 
-									position.fromArray( positions, i1 * 3 );
-									newPositions.push( position.x, position.y, position.z );
-									position.fromArray( positions, i2 * 3 );
-									newPositions.push( position.x, position.y, position.z );
-									position.fromArray( positions, i3 * 3 );
-									newPositions.push( position.x, position.y, position.z );
+								}
 
-									if ( colors.length > 0 ) {
+								if ( colorIndex !== undefined ) { 
 
-										color.fromArray( colors, i1 * 3 );
-										newColors.push( color.r, color.g, color.b );
-										color.fromArray( colors, i2 * 3 );
-										newColors.push( color.r, color.g, color.b );
-										color.fromArray( colors, i3 * 3 );
-										newColors.push( color.r, color.g, color.b );
+									pointAttributes.push( colorIndex.toString( base ) );
 
-									}
+								}
 
-									if ( uvs.length > 0 ) {
+								if ( uvIndex !== undefined ) {
 
-										uv.fromArray( uvs, i1 * 2 );
-										newUvs.push( uv.x, uv.y );
-										uv.fromArray( uvs, i2 * 2 );
-										newUvs.push( uv.x, uv.y );
-										uv.fromArray( uvs, i3 * 2 );
-										newUvs.push( uv.x, uv.y );
+									pointAttributes.push( uvIndex.toString( base ) );
+
+								}
+
+								var pointId = pointAttributes.join( ',' );
+								var newIndex = pointMap[ pointId ];
+
+								if ( newIndex === undefined ) {
+
+									newIndex = newPositions.length / 3;
+									pointMap[ pointId ] = newIndex;
+
+									newPositions.push(
+										positions[ positionIndex * 3 ],
+										positions[ positionIndex * 3 + 1 ],
+										positions[ positionIndex * 3 + 2 ]
+									);
+
+									if ( normalIndex !== undefined && normals.length > 0 ) {
+
+										newNormals.push(
+											normals[ normalIndex * 3 ],
+											normals[ normalIndex * 3 + 1 ],
+											normals[ normalIndex * 3 + 2 ]
+										);
 
 									}
 
-									if ( normals.length > 0 ) {
+									if ( colorIndex !== undefined && colors.length > 0 ) {
 
-										normal.fromArray( normals, i1 * 3 );
-										newNormals.push( normal.x, normal.y, normal.z );
-										normal.fromArray( normals, i2 * 3 );
-										newNormals.push( normal.x, normal.y, normal.z );
-										normal.fromArray( normals, i3 * 3 );
-										newNormals.push( normal.x, normal.y, normal.z );
+										newColors.push(
+											colors[ colorIndex * 3 ],
+											colors[ colorIndex * 3 + 1 ],
+											colors[ colorIndex * 3 + 2 ]
+										);
 
 									}
 
-									skip ++;
+									if ( uvIndex !== undefined && uvs.length > 0 ) {
+
+										newUvs.push(
+											uvs[ uvIndex * 2 ],
+											uvs[ uvIndex * 2 + 1 ]
+										);
+
+									}
 
 								}
 
+								newIndexes.push( newIndex );
+
 							}
 
 							positions = newPositions;
-							colors = newColors;
 							normals = newNormals;
+							color = newColors;
 							uvs = newUvs;
 
+							geometry.setIndex( newIndexes );
+
 						} else {
 
 							// do not add dummy mesh to the scene
@@ -1034,6 +1087,8 @@ THREE.VRMLLoader.prototype = {
 
 						} else {
 
+							// convert geometry to non-indexed to get sharp normals 
+							geometry = geometry.toNonIndexed();
 							geometry.computeVertexNormals();
 
 						}