Browse Source

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 years ago
parent
commit
3c37371c87
1 changed files with 102 additions and 47 deletions
  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
 						// some shapes only have vertices for use in other shapes
 
 
 						if ( data.coordIndex ) {
 						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 newPositions = [];
-							var newColors = [];
 							var newNormals = [];
 							var newNormals = [];
+							var newColors = [];
 							var newUvs = [];
 							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;
 							positions = newPositions;
-							colors = newColors;
 							normals = newNormals;
 							normals = newNormals;
+							color = newColors;
 							uvs = newUvs;
 							uvs = newUvs;
 
 
+							geometry.setIndex( newIndexes );
+
 						} else {
 						} else {
 
 
 							// do not add dummy mesh to the scene
 							// do not add dummy mesh to the scene
@@ -1034,6 +1087,8 @@ THREE.VRMLLoader.prototype = {
 
 
 						} else {
 						} else {
 
 
+							// convert geometry to non-indexed to get sharp normals 
+							geometry = geometry.toNonIndexed();
 							geometry.computeVertexNormals();
 							geometry.computeVertexNormals();
 
 
 						}
 						}