|
@@ -18,7 +18,7 @@ if ( THREE.LoaderSupport === undefined ) console.error( '"THREE.LoaderSupport" i
|
|
|
*/
|
|
|
THREE.OBJLoader2 = (function () {
|
|
|
|
|
|
- var OBJLOADER2_VERSION = '2.2.0';
|
|
|
+ var OBJLOADER2_VERSION = '2.2.1';
|
|
|
var LoaderBase = THREE.LoaderSupport.LoaderBase;
|
|
|
var Validator = THREE.LoaderSupport.Validator;
|
|
|
var ConsoleLogger = THREE.LoaderSupport.ConsoleLogger;
|
|
@@ -297,8 +297,7 @@ THREE.OBJLoader2 = (function () {
|
|
|
input: content,
|
|
|
options: null
|
|
|
}
|
|
|
- },
|
|
|
- [ content.buffer ]
|
|
|
+ }
|
|
|
);
|
|
|
};
|
|
|
|
|
@@ -354,7 +353,6 @@ THREE.OBJLoader2 = (function () {
|
|
|
};
|
|
|
this.logger = new ConsoleLogger();
|
|
|
this.totalBytes = 0;
|
|
|
- this.reachedFaces = false;
|
|
|
};
|
|
|
|
|
|
Parser.prototype.setUseAsync = function ( useAsync ) {
|
|
@@ -560,28 +558,7 @@ THREE.OBJLoader2 = (function () {
|
|
|
|
|
|
switch ( buffer[ 0 ] ) {
|
|
|
case Consts.LINE_V:
|
|
|
- // object complete instance required if reached faces already (= reached next block of v)
|
|
|
- if ( this.reachedFaces ) {
|
|
|
-
|
|
|
- if ( this.rawMesh.colors.length > 0 && this.rawMesh.colors.length !== this.rawMesh.vertices.length ) {
|
|
|
-
|
|
|
- throw 'Vertex Colors were detected, but vertex count and color count do not match!';
|
|
|
-
|
|
|
- }
|
|
|
- // only when new vertices after faces are detected complete new mesh is prepared (reset offsets, etc)
|
|
|
- this.processCompletedMesh( this.rawMesh.objectName, this.rawMesh.groupName, currentByte, true );
|
|
|
- this.reachedFaces = false;
|
|
|
-
|
|
|
- }
|
|
|
- if ( bufferPointer === 4 ) {
|
|
|
-
|
|
|
- this.rawMesh.pushVertex( buffer )
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- this.rawMesh.pushVertexAndVertextColors( buffer );
|
|
|
-
|
|
|
- }
|
|
|
+ this.rawMesh.pushVertex( buffer, bufferPointer > 4 );
|
|
|
break;
|
|
|
|
|
|
case Consts.LINE_VT:
|
|
@@ -593,7 +570,6 @@ THREE.OBJLoader2 = (function () {
|
|
|
break;
|
|
|
|
|
|
case Consts.LINE_F:
|
|
|
- this.reachedFaces = true;
|
|
|
this.rawMesh.processFaces( buffer, bufferPointer, countSlashes( slashSpacePattern, slashSpacePatternPointer ) );
|
|
|
break;
|
|
|
|
|
@@ -607,12 +583,15 @@ THREE.OBJLoader2 = (function () {
|
|
|
break;
|
|
|
|
|
|
case Consts.LINE_G:
|
|
|
- this.processCompletedMesh( this.rawMesh.objectName, concatStringBuffer( buffer, bufferPointer, slashSpacePattern ), currentByte, false );
|
|
|
+ // 'g' leads to creation of mesh if valid data (faces declaration was done before), otherwise only groupName gets set
|
|
|
+ this.processCompletedMesh( currentByte );
|
|
|
+ this.rawMesh.pushGroup( concatStringBuffer( buffer, bufferPointer, slashSpacePattern ) );
|
|
|
flushStringBuffer( buffer, bufferPointer );
|
|
|
break;
|
|
|
|
|
|
case Consts.LINE_O:
|
|
|
- this.processCompletedMesh( concatStringBuffer( buffer, bufferPointer, slashSpacePattern ), this.rawMesh.groupName, currentByte, false );
|
|
|
+ // 'o' is pure meta-information and does not result in creation of new meshes
|
|
|
+ this.rawMesh.pushObject( concatStringBuffer( buffer, bufferPointer, slashSpacePattern ) );
|
|
|
flushStringBuffer( buffer, bufferPointer );
|
|
|
break;
|
|
|
|
|
@@ -645,43 +624,40 @@ THREE.OBJLoader2 = (function () {
|
|
|
'\n\tReal RawMeshSubGroup count: ' + report.subGroups;
|
|
|
};
|
|
|
|
|
|
- Parser.prototype.processCompletedMesh = function ( objectName, groupName, currentByte, beginNewObject ) {
|
|
|
+ Parser.prototype.processCompletedMesh = function ( currentByte ) {
|
|
|
var result = this.rawMesh.finalize();
|
|
|
if ( Validator.isValid( result ) ) {
|
|
|
|
|
|
- this.inputObjectCount++;
|
|
|
+ if ( this.rawMesh.colors.length > 0 && this.rawMesh.colors.length !== this.rawMesh.vertices.length ) {
|
|
|
+
|
|
|
+ throw 'Vertex Colors were detected, but vertex count and color count do not match!';
|
|
|
+
|
|
|
+ }
|
|
|
if ( this.logger.isDebug() ) this.logger.logDebug( this.createRawMeshReport( this.rawMesh, this.inputObjectCount ) );
|
|
|
+ this.inputObjectCount++;
|
|
|
+
|
|
|
this.buildMesh( result, currentByte );
|
|
|
var progressBytesPercent = currentByte / this.totalBytes;
|
|
|
this.callbackProgress( 'Completed [o: ' + this.rawMesh.objectName + ' g:' + this.rawMesh.groupName + '] Total progress: ' + ( progressBytesPercent * 100 ).toFixed( 2 ) + '%', progressBytesPercent );
|
|
|
- this.rawMesh = beginNewObject ? this.rawMesh.newInstanceResetOffsets() : this.rawMesh.newInstanceKeepOffsets();
|
|
|
+ this.rawMesh.reset( this.rawMesh.smoothingGroup.splitMaterials );
|
|
|
|
|
|
+ return true;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ return false;
|
|
|
}
|
|
|
- // Always update group an object name in case they have changed and are valid
|
|
|
- if ( this.rawMesh.objectName !== objectName && Validator.isValid( objectName ) ) this.rawMesh.pushObject( objectName );
|
|
|
- if ( this.rawMesh.groupName !== groupName && Validator.isValid( groupName ) ) this.rawMesh.pushGroup( groupName );
|
|
|
};
|
|
|
|
|
|
Parser.prototype.finalize = function ( currentByte ) {
|
|
|
this.logger.logInfo( 'Global output object count: ' + this.outputObjectCount );
|
|
|
- var result = Validator.isValid( this.rawMesh ) ? this.rawMesh.finalize() : null;
|
|
|
- if ( Validator.isValid( result ) ) {
|
|
|
-
|
|
|
- this.inputObjectCount++;
|
|
|
- if ( this.logger.isDebug() ) this.logger.logDebug( this.createRawMeshReport( this.rawMesh, this.inputObjectCount ) );
|
|
|
- this.buildMesh( result, currentByte );
|
|
|
-
|
|
|
- if ( this.logger.isEnabled() ) {
|
|
|
-
|
|
|
- var parserFinalReport = 'Overall counts: ' +
|
|
|
- '\n\tVertices: ' + this.counts.vertices +
|
|
|
- '\n\tFaces: ' + this.counts.faces +
|
|
|
- '\n\tMultiple definitions: ' + this.counts.doubleIndicesCount;
|
|
|
- this.logger.logInfo( parserFinalReport );
|
|
|
+ if ( this.processCompletedMesh( currentByte ) && this.logger.isEnabled() ) {
|
|
|
|
|
|
- }
|
|
|
- var progressBytesPercent = currentByte / this.totalBytes;
|
|
|
- this.callbackProgress( 'Completed Parsing: 100.00%', progressBytesPercent );
|
|
|
+ var parserFinalReport = 'Overall counts: ' +
|
|
|
+ '\n\tVertices: ' + this.counts.vertices +
|
|
|
+ '\n\tFaces: ' + this.counts.faces +
|
|
|
+ '\n\tMultiple definitions: ' + this.counts.doubleIndicesCount;
|
|
|
+ this.logger.logInfo( parserFinalReport );
|
|
|
|
|
|
}
|
|
|
};
|
|
@@ -836,11 +812,11 @@ THREE.OBJLoader2 = (function () {
|
|
|
if ( this.logger.isDebug() ) {
|
|
|
var materialIndexLine = Validator.isValid( selectedMaterialIndex ) ? '\n\t\tmaterialIndex: ' + selectedMaterialIndex : '';
|
|
|
var createdReport = 'Output Object no.: ' + this.outputObjectCount +
|
|
|
- '\n\t\tobjectName: ' + rawObjectDescription.objectName +
|
|
|
'\n\t\tgroupName: ' + rawObjectDescription.groupName +
|
|
|
- '\n\t\tmaterialName: ' + rawObjectDescription.materialName +
|
|
|
materialIndexLine +
|
|
|
+ '\n\t\tmaterialName: ' + rawObjectDescription.materialName +
|
|
|
'\n\t\tsmoothingGroup: ' + rawObjectDescription.smoothingGroup +
|
|
|
+ '\n\t\tobjectName: ' + rawObjectDescription.objectName +
|
|
|
'\n\t\t#vertices: ' + rawObjectDescription.vertices.length / 3 +
|
|
|
'\n\t\t#indices: ' + rawObjectDescription.indices.length +
|
|
|
'\n\t\t#colors: ' + rawObjectDescription.colors.length / 3 +
|
|
@@ -892,82 +868,51 @@ THREE.OBJLoader2 = (function () {
|
|
|
*/
|
|
|
var RawMesh = (function () {
|
|
|
|
|
|
- function RawMesh( materialPerSmoothingGroup, useIndices, disregardNormals, activeMtlName ) {
|
|
|
- this.globalVertexOffset = 1;
|
|
|
- this.globalUvOffset = 1;
|
|
|
- this.globalNormalOffset = 1;
|
|
|
-
|
|
|
+ function RawMesh( materialPerSmoothingGroup, useIndices, disregardNormals ) {
|
|
|
this.vertices = [];
|
|
|
this.colors = [];
|
|
|
this.normals = [];
|
|
|
this.uvs = [];
|
|
|
|
|
|
- // faces are stored according combined index of group, material and smoothingGroup (0 or not)
|
|
|
- this.activeMtlName = Validator.verifyInput( activeMtlName, '' );
|
|
|
+ this.useIndices = useIndices === true;
|
|
|
+ this.disregardNormals = disregardNormals === true;
|
|
|
+
|
|
|
this.objectName = '';
|
|
|
this.groupName = '';
|
|
|
+ this.activeMtlName = '';
|
|
|
this.mtllibName = '';
|
|
|
+ this.reset( materialPerSmoothingGroup );
|
|
|
+ }
|
|
|
+
|
|
|
+ RawMesh.prototype.reset = function ( materialPerSmoothingGroup ) {
|
|
|
+ // faces are stored according combined index of group, material and smoothingGroup (0 or not)
|
|
|
+ this.subGroups = [];
|
|
|
+ this.subGroupInUse = null;
|
|
|
this.smoothingGroup = {
|
|
|
splitMaterials: materialPerSmoothingGroup === true,
|
|
|
normalized: -1,
|
|
|
real: -1
|
|
|
};
|
|
|
- this.useIndices = useIndices === true;
|
|
|
- this.disregardNormals = disregardNormals === true;
|
|
|
-
|
|
|
- this.mtlCount = 0;
|
|
|
- this.smoothingGroupCount = 0;
|
|
|
-
|
|
|
- this.subGroups = [];
|
|
|
- this.subGroupInUse = null;
|
|
|
// this default index is required as it is possible to define faces without 'g' or 'usemtl'
|
|
|
this.pushSmoothingGroup( 1 );
|
|
|
|
|
|
this.doubleIndicesCount = 0;
|
|
|
this.faceCount = 0;
|
|
|
- }
|
|
|
-
|
|
|
- RawMesh.prototype.newInstanceResetOffsets = function () {
|
|
|
- var newRawObject = new RawMesh( this.smoothingGroup.splitMaterials, this.useIndices, this.disregardNormals, this.activeMtlName );
|
|
|
-
|
|
|
- // move indices forward
|
|
|
- newRawObject.globalVertexOffset = this.globalVertexOffset + this.vertices.length / 3;
|
|
|
- newRawObject.globalUvOffset = this.globalUvOffset + this.uvs.length / 2;
|
|
|
- newRawObject.globalNormalOffset = this.globalNormalOffset + this.normals.length / 3;
|
|
|
-
|
|
|
- return newRawObject;
|
|
|
- };
|
|
|
-
|
|
|
- RawMesh.prototype.newInstanceKeepOffsets = function () {
|
|
|
- var newRawObject = new RawMesh( this.smoothingGroup.splitMaterials, this.useIndices, this.disregardNormals, this.activeMtlName );
|
|
|
- // keep objectName
|
|
|
- newRawObject.pushObject( this.objectName );
|
|
|
-
|
|
|
- // keep current buffers and indices forward
|
|
|
- newRawObject.vertices = this.vertices;
|
|
|
- newRawObject.colors = this.colors;
|
|
|
- newRawObject.uvs = this.uvs;
|
|
|
- newRawObject.normals = this.normals;
|
|
|
- newRawObject.globalVertexOffset = this.globalVertexOffset;
|
|
|
- newRawObject.globalUvOffset = this.globalUvOffset;
|
|
|
- newRawObject.globalNormalOffset = this.globalNormalOffset;
|
|
|
-
|
|
|
- return newRawObject;
|
|
|
+ this.mtlCount = 0;
|
|
|
+ this.smoothingGroupCount = 0;
|
|
|
};
|
|
|
|
|
|
- RawMesh.prototype.pushVertex = function ( buffer ) {
|
|
|
+ RawMesh.prototype.pushVertex = function ( buffer, haveVertexColors ) {
|
|
|
this.vertices.push( parseFloat( buffer[ 1 ] ) );
|
|
|
this.vertices.push( parseFloat( buffer[ 2 ] ) );
|
|
|
this.vertices.push( parseFloat( buffer[ 3 ] ) );
|
|
|
- };
|
|
|
+ if ( haveVertexColors ) {
|
|
|
|
|
|
- RawMesh.prototype.pushVertexAndVertextColors = function ( buffer ) {
|
|
|
- this.vertices.push( parseFloat( buffer[ 1 ] ) );
|
|
|
- this.vertices.push( parseFloat( buffer[ 2 ] ) );
|
|
|
- this.vertices.push( parseFloat( buffer[ 3 ] ) );
|
|
|
- this.colors.push( parseFloat( buffer[ 4 ] ) );
|
|
|
- this.colors.push( parseFloat( buffer[ 5 ] ) );
|
|
|
- this.colors.push( parseFloat( buffer[ 6 ] ) );
|
|
|
+ this.colors.push( parseFloat( buffer[ 4 ] ) );
|
|
|
+ this.colors.push( parseFloat( buffer[ 5 ] ) );
|
|
|
+ this.colors.push( parseFloat( buffer[ 6 ] ) );
|
|
|
+
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
RawMesh.prototype.pushUv = function ( buffer ) {
|
|
@@ -981,6 +926,10 @@ THREE.OBJLoader2 = (function () {
|
|
|
this.normals.push( parseFloat( buffer[ 3 ] ) );
|
|
|
};
|
|
|
|
|
|
+ RawMesh.prototype.pushGroup = function ( groupName ) {
|
|
|
+ this.groupName = Validator.verifyInput( groupName, '' );
|
|
|
+ };
|
|
|
+
|
|
|
RawMesh.prototype.pushObject = function ( objectName ) {
|
|
|
this.objectName = Validator.verifyInput( objectName, '' );
|
|
|
};
|
|
@@ -989,10 +938,6 @@ THREE.OBJLoader2 = (function () {
|
|
|
this.mtllibName = Validator.verifyInput( mtllibName, '' );
|
|
|
};
|
|
|
|
|
|
- RawMesh.prototype.pushGroup = function ( groupName ) {
|
|
|
- this.groupName = Validator.verifyInput( groupName, '' );
|
|
|
- };
|
|
|
-
|
|
|
RawMesh.prototype.pushUsemtl = function ( mtlName ) {
|
|
|
if ( this.activeMtlName === mtlName || ! Validator.isValid( mtlName ) ) return;
|
|
|
this.activeMtlName = mtlName;
|
|
@@ -1037,7 +982,7 @@ THREE.OBJLoader2 = (function () {
|
|
|
// "f vertex ..."
|
|
|
if ( slashesCount === 0 ) {
|
|
|
|
|
|
- for ( i = 2, length = bufferLength - 1; i < length; i ++ ) {
|
|
|
+ for ( i = 2, length = bufferLength; i < length; i ++ ) {
|
|
|
|
|
|
this.buildFace( buffer[ 1 ] );
|
|
|
this.buildFace( buffer[ i ] );
|
|
@@ -1081,20 +1026,22 @@ THREE.OBJLoader2 = (function () {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+
|
|
|
RawMesh.prototype.buildFace = function ( faceIndexV, faceIndexU, faceIndexN ) {
|
|
|
var sgiu = this.subGroupInUse;
|
|
|
if ( this.disregardNormals ) faceIndexN = undefined;
|
|
|
var scope = this;
|
|
|
var updateRawObjectDescriptionInUse = function () {
|
|
|
|
|
|
- var indexPointerV = ( parseInt( faceIndexV ) - scope.globalVertexOffset ) * 3;
|
|
|
- var indexPointerC = scope.colors.length > 0 ? indexPointerV : null;
|
|
|
+ var faceIndexVi = parseInt( faceIndexV );
|
|
|
+ var indexPointerV = 3 * ( faceIndexVi > 0 ? faceIndexVi - 1 : faceIndexVi + scope.vertices.length / 3 );
|
|
|
|
|
|
var vertices = sgiu.vertices;
|
|
|
vertices.push( scope.vertices[ indexPointerV++ ] );
|
|
|
vertices.push( scope.vertices[ indexPointerV++ ] );
|
|
|
vertices.push( scope.vertices[ indexPointerV ] );
|
|
|
|
|
|
+ var indexPointerC = scope.colors.length > 0 ? indexPointerV : null;
|
|
|
if ( indexPointerC !== null ) {
|
|
|
|
|
|
var colors = sgiu.colors;
|
|
@@ -1106,7 +1053,8 @@ THREE.OBJLoader2 = (function () {
|
|
|
|
|
|
if ( faceIndexU ) {
|
|
|
|
|
|
- var indexPointerU = ( parseInt( faceIndexU ) - scope.globalUvOffset ) * 2;
|
|
|
+ var faceIndexUi = parseInt( faceIndexU );
|
|
|
+ var indexPointerU = 2 * ( faceIndexUi > 0 ? faceIndexUi - 1 : faceIndexUi + scope.uvs.length / 2 );
|
|
|
var uvs = sgiu.uvs;
|
|
|
uvs.push( scope.uvs[ indexPointerU++ ] );
|
|
|
uvs.push( scope.uvs[ indexPointerU ] );
|
|
@@ -1114,7 +1062,8 @@ THREE.OBJLoader2 = (function () {
|
|
|
}
|
|
|
if ( faceIndexN ) {
|
|
|
|
|
|
- var indexPointerN = ( parseInt( faceIndexN ) - scope.globalNormalOffset ) * 3;
|
|
|
+ var faceIndexNi = parseInt( faceIndexN );
|
|
|
+ var indexPointerN = 3 * ( faceIndexNi > 0 ? faceIndexNi - 1 : faceIndexNi + scope.normals.length / 3 );
|
|
|
var normals = sgiu.normals;
|
|
|
normals.push( scope.normals[ indexPointerN++ ] );
|
|
|
normals.push( scope.normals[ indexPointerN++ ] );
|
|
@@ -1348,12 +1297,11 @@ THREE.OBJLoader2 = (function () {
|
|
|
* @memberOf THREE.OBJLoader2
|
|
|
*
|
|
|
* @param {string} url URL to the file
|
|
|
- * @param {string} name The name of the object
|
|
|
* @param {Object} content The file content as arraybuffer or text
|
|
|
* @param {function} callbackOnLoad
|
|
|
* @param {string} [crossOrigin] CORS value
|
|
|
*/
|
|
|
- OBJLoader2.prototype.loadMtl = function ( url, name, content, callbackOnLoad, crossOrigin ) {
|
|
|
+ OBJLoader2.prototype.loadMtl = function ( url, content, callbackOnLoad, crossOrigin ) {
|
|
|
var resource = new THREE.LoaderSupport.ResourceDescriptor( url, 'MTL' );
|
|
|
resource.setContent( content );
|
|
|
this._loadMtl( resource, callbackOnLoad, crossOrigin );
|