Przeglądaj źródła

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 7 lat temu
rodzic
commit
3c37371c87
1 zmienionych plików z 102 dodań i 47 usunięć
  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();
 
 						}