Skip to content

Commit 3c37371

Browse files
authored
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.
1 parent 951f5ec commit 3c37371

File tree

1 file changed

+102
-47
lines changed

1 file changed

+102
-47
lines changed

examples/js/loaders/VRMLLoader.js

Lines changed: 102 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -912,91 +912,144 @@ THREE.VRMLLoader.prototype = {
912912

913913
}
914914

915-
var skip = 0;
916-
917915
// some shapes only have vertices for use in other shapes
918916

919917
if ( data.coordIndex ) {
920918

919+
function triangulateIndexArray( indexArray ) {
920+
921+
var triangulatedIndexArray = [];
922+
var ccw = data.ccw === undefined ? true : data.ccw; // ccw is true by default
923+
var skip = 0;
924+
925+
for ( i = 0, il = indexArray.length; i < il; i ++ ) {
926+
927+
var indexedFace = data.coordIndex[ i ];
928+
929+
// VRML support multipoint indexed face sets (more then 3 vertices). You must calculate the composing triangles here
930+
931+
skip = 0;
932+
933+
while ( indexedFace.length >= 3 && skip < ( indexedFace.length - 2 ) ) {
934+
935+
var i1 = indexedFace[ 0 ];
936+
var i2 = indexedFace[ skip + ( ccw ? 1 : 2 ) ];
937+
var i3 = indexedFace[ skip + ( ccw ? 2 : 1 ) ];
938+
939+
triangulatedIndexArray.push( i1, i2, i3 );
940+
941+
skip ++;
942+
943+
}
944+
945+
}
946+
947+
return triangulatedIndexArray;
948+
949+
}
950+
951+
var positionIndexes = data.coordIndex ? triangulateIndexArray( data.coordIndex ) : [];
952+
var normalIndexes = data.normalIndex ? triangulateIndexArray( data.normalIndex ) : positionIndexes;
953+
var colorIndexes = data.colorIndex ? triangulateIndexArray( data.colorIndex ) : positionIndexes;
954+
var uvIndexes = data.texCoordIndex ? triangulateIndexArray( data.texCoordIndex ) : positionIndexes;
955+
956+
var newIndexes = [];
921957
var newPositions = [];
922-
var newColors = [];
923958
var newNormals = [];
959+
var newColors = [];
924960
var newUvs = [];
925961

926-
position = new THREE.Vector3();
927-
color = new THREE.Color();
928-
normal = new THREE.Vector3();
929-
uv = new THREE.Vector2();
962+
// if any other index array does not match the coordinate indexes, split any points that differ
930963

931-
for ( i = 0, il = data.coordIndex.length; i < il; i ++ ) {
964+
var pointMap = Object.create( null );
932965

933-
var indexes = data.coordIndex[ i ];
966+
for ( i = 0; i < positionIndexes.length; i ++ ) {
934967

935-
// VRML support multipoint indexed face sets (more then 3 vertices). You must calculate the composing triangles here
968+
var pointAttributes = [];
936969

937-
skip = 0;
970+
var positionIndex = positionIndexes[ i ];
971+
var normalIndex = normalIndexes[ i ];
972+
var colorIndex = colorIndexes[ i ];
973+
var uvIndex = uvIndexes[ i ];
938974

939-
while ( indexes.length >= 3 && skip < ( indexes.length - 2 ) ) {
975+
var base = 10; // which base to use to represent each value
940976

941-
if ( data.ccw === undefined ) data.ccw = true; // ccw is true by default
977+
pointAttributes.push( positionIndex.toString( base ) );
942978

943-
var i1 = indexes[ 0 ];
944-
var i2 = indexes[ skip + ( data.ccw ? 1 : 2 ) ];
945-
var i3 = indexes[ skip + ( data.ccw ? 2 : 1 ) ];
979+
if ( normalIndex !== undefined ) {
946980

947-
// create non indexed geometry, necessary for face normal generation
981+
pointAttributes.push( normalIndex.toString( base ) );
948982

949-
position.fromArray( positions, i1 * 3 );
950-
newPositions.push( position.x, position.y, position.z );
951-
position.fromArray( positions, i2 * 3 );
952-
newPositions.push( position.x, position.y, position.z );
953-
position.fromArray( positions, i3 * 3 );
954-
newPositions.push( position.x, position.y, position.z );
983+
}
955984

956-
if ( colors.length > 0 ) {
985+
if ( colorIndex !== undefined ) {
957986

958-
color.fromArray( colors, i1 * 3 );
959-
newColors.push( color.r, color.g, color.b );
960-
color.fromArray( colors, i2 * 3 );
961-
newColors.push( color.r, color.g, color.b );
962-
color.fromArray( colors, i3 * 3 );
963-
newColors.push( color.r, color.g, color.b );
987+
pointAttributes.push( colorIndex.toString( base ) );
964988

965-
}
989+
}
966990

967-
if ( uvs.length > 0 ) {
991+
if ( uvIndex !== undefined ) {
968992

969-
uv.fromArray( uvs, i1 * 2 );
970-
newUvs.push( uv.x, uv.y );
971-
uv.fromArray( uvs, i2 * 2 );
972-
newUvs.push( uv.x, uv.y );
973-
uv.fromArray( uvs, i3 * 2 );
974-
newUvs.push( uv.x, uv.y );
993+
pointAttributes.push( uvIndex.toString( base ) );
994+
995+
}
996+
997+
var pointId = pointAttributes.join( ',' );
998+
var newIndex = pointMap[ pointId ];
999+
1000+
if ( newIndex === undefined ) {
1001+
1002+
newIndex = newPositions.length / 3;
1003+
pointMap[ pointId ] = newIndex;
1004+
1005+
newPositions.push(
1006+
positions[ positionIndex * 3 ],
1007+
positions[ positionIndex * 3 + 1 ],
1008+
positions[ positionIndex * 3 + 2 ]
1009+
);
1010+
1011+
if ( normalIndex !== undefined && normals.length > 0 ) {
1012+
1013+
newNormals.push(
1014+
normals[ normalIndex * 3 ],
1015+
normals[ normalIndex * 3 + 1 ],
1016+
normals[ normalIndex * 3 + 2 ]
1017+
);
9751018

9761019
}
9771020

978-
if ( normals.length > 0 ) {
1021+
if ( colorIndex !== undefined && colors.length > 0 ) {
9791022

980-
normal.fromArray( normals, i1 * 3 );
981-
newNormals.push( normal.x, normal.y, normal.z );
982-
normal.fromArray( normals, i2 * 3 );
983-
newNormals.push( normal.x, normal.y, normal.z );
984-
normal.fromArray( normals, i3 * 3 );
985-
newNormals.push( normal.x, normal.y, normal.z );
1023+
newColors.push(
1024+
colors[ colorIndex * 3 ],
1025+
colors[ colorIndex * 3 + 1 ],
1026+
colors[ colorIndex * 3 + 2 ]
1027+
);
9861028

9871029
}
9881030

989-
skip ++;
1031+
if ( uvIndex !== undefined && uvs.length > 0 ) {
1032+
1033+
newUvs.push(
1034+
uvs[ uvIndex * 2 ],
1035+
uvs[ uvIndex * 2 + 1 ]
1036+
);
1037+
1038+
}
9901039

9911040
}
9921041

1042+
newIndexes.push( newIndex );
1043+
9931044
}
9941045

9951046
positions = newPositions;
996-
colors = newColors;
9971047
normals = newNormals;
1048+
color = newColors;
9981049
uvs = newUvs;
9991050

1051+
geometry.setIndex( newIndexes );
1052+
10001053
} else {
10011054

10021055
// do not add dummy mesh to the scene
@@ -1034,6 +1087,8 @@ THREE.VRMLLoader.prototype = {
10341087

10351088
} else {
10361089

1090+
// convert geometry to non-indexed to get sharp normals
1091+
geometry = geometry.toNonIndexed();
10371092
geometry.computeVertexNormals();
10381093

10391094
}

0 commit comments

Comments
 (0)