|
@@ -328,8 +328,7 @@
|
|
|
|
|
|
fileName = imageMap.get( children[ 0 ].ID );
|
|
|
|
|
|
- } else if ( relativeFilePath !== undefined && relativeFilePath[ 0 ] !== '/' &&
|
|
|
- relativeFilePath.match( /^[a-zA-Z]:/ ) === null ) {
|
|
|
+ } else if ( relativeFilePath !== undefined && relativeFilePath[ 0 ] !== '/' && relativeFilePath.match( /^[a-zA-Z]:/ ) === null ) {
|
|
|
|
|
|
// use textureNode.properties.RelativeFilename
|
|
|
// if it exists and it doesn't seem an absolute path
|
|
@@ -657,15 +656,15 @@
|
|
|
index: i,
|
|
|
indices: [],
|
|
|
weights: [],
|
|
|
- transform: parseMatrixArray( subDeformerNode.subNodes.Transform.properties.a ),
|
|
|
- transformLink: parseMatrixArray( subDeformerNode.subNodes.TransformLink.properties.a ),
|
|
|
+ transform: new THREE.Matrix4().fromArray( subDeformerNode.subNodes.Transform.properties.a ),
|
|
|
+ transformLink: new THREE.Matrix4().fromArray( subDeformerNode.subNodes.TransformLink.properties.a ),
|
|
|
linkMode: subDeformerNode.properties.Mode
|
|
|
};
|
|
|
|
|
|
if ( 'Indexes' in subDeformerNode.subNodes ) {
|
|
|
|
|
|
- subDeformer.indices = parseIntArray( subDeformerNode.subNodes.Indexes.properties.a );
|
|
|
- subDeformer.weights = parseFloatArray( subDeformerNode.subNodes.Weights.properties.a );
|
|
|
+ subDeformer.indices = subDeformerNode.subNodes.Indexes.properties.a;
|
|
|
+ subDeformer.weights = subDeformerNode.subNodes.Weights.properties.a;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -764,8 +763,8 @@
|
|
|
|
|
|
// First, each index is going to be its own vertex.
|
|
|
|
|
|
- var vertexBuffer = parseFloatArray( subNodes.Vertices.properties.a );
|
|
|
- var indexBuffer = parseIntArray( subNodes.PolygonVertexIndex.properties.a );
|
|
|
+ var vertexBuffer = subNodes.Vertices.properties.a;
|
|
|
+ var indexBuffer = subNodes.PolygonVertexIndex.properties.a;
|
|
|
|
|
|
if ( subNodes.LayerElementNormal ) {
|
|
|
|
|
@@ -1017,43 +1016,47 @@
|
|
|
|
|
|
}
|
|
|
|
|
|
- // Convert the material indices of each vertex into rendering groups on the geometry.
|
|
|
+ if ( materialInfo && materialInfo.mappingType !== 'AllSame' ) {
|
|
|
|
|
|
- var materialIndexBuffer = bufferInfo.materialIndexBuffer;
|
|
|
- var prevMaterialIndex = materialIndexBuffer[ 0 ];
|
|
|
- var startIndex = 0;
|
|
|
+ // Convert the material indices of each vertex into rendering groups on the geometry.
|
|
|
+ var materialIndexBuffer = bufferInfo.materialIndexBuffer;
|
|
|
+ var prevMaterialIndex = materialIndexBuffer[ 0 ];
|
|
|
+ var startIndex = 0;
|
|
|
|
|
|
- for ( var i = 0; i < materialIndexBuffer.length; ++ i ) {
|
|
|
+ for ( var i = 0; i < materialIndexBuffer.length; ++ i ) {
|
|
|
|
|
|
- if ( materialIndexBuffer[ i ] !== prevMaterialIndex ) {
|
|
|
+ if ( materialIndexBuffer[ i ] !== prevMaterialIndex ) {
|
|
|
|
|
|
- geo.addGroup( startIndex, i - startIndex, prevMaterialIndex );
|
|
|
+ geo.addGroup( startIndex, i - startIndex, prevMaterialIndex );
|
|
|
|
|
|
- prevMaterialIndex = materialIndexBuffer[ i ];
|
|
|
- startIndex = i;
|
|
|
+ prevMaterialIndex = materialIndexBuffer[ i ];
|
|
|
+ startIndex = i;
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ // the loop above doesn't add the last group, do that here.
|
|
|
+ if ( geo.groups.length > 0 ) {
|
|
|
|
|
|
- // the loop above doesn't add the last group, do that here.
|
|
|
- if ( geo.groups.length > 0 ) {
|
|
|
+ var lastGroup = geo.groups[ geo.groups.length - 1 ];
|
|
|
+ var lastIndex = lastGroup.start + lastGroup.count;
|
|
|
|
|
|
- var lastGroup = geo.groups[ geo.groups.length - 1 ];
|
|
|
- var lastIndex = lastGroup.start + lastGroup.count;
|
|
|
+ if ( lastIndex !== materialIndexBuffer.length ) {
|
|
|
|
|
|
- if ( lastIndex !== materialIndexBuffer.length ) {
|
|
|
+ geo.addGroup( lastIndex, materialIndexBuffer.length - lastIndex, prevMaterialIndex );
|
|
|
|
|
|
- geo.addGroup( lastIndex, materialIndexBuffer.length - lastIndex, prevMaterialIndex );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ // case where there are multiple materials but the whole geometry is only
|
|
|
+ // using one of them
|
|
|
+ if ( geo.groups.length === 0 ) {
|
|
|
|
|
|
- // catch case where the whole geometry has a single non-zero index
|
|
|
- if ( geo.groups.length === 0 && materialIndexBuffer[ 0 ] !== 0 ) {
|
|
|
+ geo.addGroup( 0, materialIndexBuffer.length, materialIndexBuffer[ 0 ] );
|
|
|
|
|
|
- geo.addGroup( 0, materialIndexBuffer.length, materialIndexBuffer[ 0 ] );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
@@ -1070,17 +1073,17 @@
|
|
|
|
|
|
var mappingType = NormalNode.properties.MappingInformationType;
|
|
|
var referenceType = NormalNode.properties.ReferenceInformationType;
|
|
|
- var buffer = parseFloatArray( NormalNode.subNodes.Normals.properties.a );
|
|
|
+ var buffer = NormalNode.subNodes.Normals.properties.a;
|
|
|
var indexBuffer = [];
|
|
|
if ( referenceType === 'IndexToDirect' ) {
|
|
|
|
|
|
if ( 'NormalIndex' in NormalNode.subNodes ) {
|
|
|
|
|
|
- indexBuffer = parseIntArray( NormalNode.subNodes.NormalIndex.properties.a );
|
|
|
+ indexBuffer = NormalNode.subNodes.NormalIndex.properties.a;
|
|
|
|
|
|
} else if ( 'NormalsIndex' in NormalNode.subNodes ) {
|
|
|
|
|
|
- indexBuffer = parseIntArray( NormalNode.subNodes.NormalsIndex.properties.a );
|
|
|
+ indexBuffer = NormalNode.subNodes.NormalsIndex.properties.a;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -1105,11 +1108,11 @@
|
|
|
|
|
|
var mappingType = UVNode.properties.MappingInformationType;
|
|
|
var referenceType = UVNode.properties.ReferenceInformationType;
|
|
|
- var buffer = parseFloatArray( UVNode.subNodes.UV.properties.a );
|
|
|
+ var buffer = UVNode.subNodes.UV.properties.a;
|
|
|
var indexBuffer = [];
|
|
|
if ( referenceType === 'IndexToDirect' ) {
|
|
|
|
|
|
- indexBuffer = parseIntArray( UVNode.subNodes.UVIndex.properties.a );
|
|
|
+ indexBuffer = UVNode.subNodes.UVIndex.properties.a;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -1132,11 +1135,11 @@
|
|
|
|
|
|
var mappingType = ColorNode.properties.MappingInformationType;
|
|
|
var referenceType = ColorNode.properties.ReferenceInformationType;
|
|
|
- var buffer = parseFloatArray( ColorNode.subNodes.Colors.properties.a );
|
|
|
+ var buffer = ColorNode.subNodes.Colors.properties.a;
|
|
|
var indexBuffer = [];
|
|
|
if ( referenceType === 'IndexToDirect' ) {
|
|
|
|
|
|
- indexBuffer = parseFloatArray( ColorNode.subNodes.ColorIndex.properties.a );
|
|
|
+ indexBuffer = ColorNode.subNodes.ColorIndex.properties.a;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -1172,7 +1175,7 @@
|
|
|
|
|
|
}
|
|
|
|
|
|
- var materialIndexBuffer = parseIntArray( MaterialNode.subNodes.Materials.properties.a );
|
|
|
+ var materialIndexBuffer = MaterialNode.subNodes.Materials.properties.a;
|
|
|
|
|
|
// Since materials are stored as indices, there's a bit of a mismatch between FBX and what
|
|
|
// we expect. So we create an intermediate buffer that points to the index in the buffer,
|
|
@@ -1360,9 +1363,9 @@
|
|
|
|
|
|
var degree = order - 1;
|
|
|
|
|
|
- var knots = parseFloatArray( geometryNode.subNodes.KnotVector.properties.a );
|
|
|
+ var knots = geometryNode.subNodes.KnotVector.properties.a;
|
|
|
var controlPoints = [];
|
|
|
- var pointsValues = parseFloatArray( geometryNode.subNodes.Points.properties.a );
|
|
|
+ var pointsValues = geometryNode.subNodes.Points.properties.a;
|
|
|
|
|
|
for ( var i = 0, l = pointsValues.length; i < l; i += 4 ) {
|
|
|
|
|
@@ -1808,7 +1811,7 @@
|
|
|
|
|
|
if ( 'Lcl_Rotation' in node.properties ) {
|
|
|
|
|
|
- var rotation = node.properties.Lcl_Rotation.value.map( degreeToRadian );
|
|
|
+ var rotation = node.properties.Lcl_Rotation.value.map( THREE.Math.degToRad );
|
|
|
rotation.push( 'ZYX' );
|
|
|
model.rotation.fromArray( rotation );
|
|
|
|
|
@@ -1822,7 +1825,7 @@
|
|
|
|
|
|
if ( 'PreRotation' in node.properties ) {
|
|
|
|
|
|
- var preRotations = new THREE.Euler().setFromVector3( parseVector3( node.properties.PreRotation ).multiplyScalar( DEG2RAD ), 'ZYX' );
|
|
|
+ var preRotations = new THREE.Euler().fromArray( node.properties.PreRotation.value.map( THREE.Math.degToRad ), 'ZYX' );
|
|
|
preRotations = new THREE.Quaternion().setFromEuler( preRotations );
|
|
|
var currentRotation = new THREE.Quaternion().setFromEuler( model.rotation );
|
|
|
preRotations.multiply( currentRotation );
|
|
@@ -1935,7 +1938,7 @@
|
|
|
|
|
|
var node = PoseNode[ PoseNodeIndex ];
|
|
|
|
|
|
- var rawMatWrd = parseMatrixArray( node.subNodes.Matrix.properties.a );
|
|
|
+ var rawMatWrd = new THREE.Matrix4().fromArray( node.subNodes.Matrix.properties.a );
|
|
|
|
|
|
worldMatrices.set( parseInt( node.id ), rawMatWrd );
|
|
|
|
|
@@ -2616,6 +2619,7 @@
|
|
|
|
|
|
}
|
|
|
returnObject.curves.get( id )[ curveNode.attr ] = curveNode;
|
|
|
+
|
|
|
if ( curveNode.attr === 'R' ) {
|
|
|
|
|
|
var curves = curveNode.curves;
|
|
@@ -2654,9 +2658,9 @@
|
|
|
|
|
|
}
|
|
|
|
|
|
- curves.x.values = curves.x.values.map( degreeToRadian );
|
|
|
- curves.y.values = curves.y.values.map( degreeToRadian );
|
|
|
- curves.z.values = curves.z.values.map( degreeToRadian );
|
|
|
+ curves.x.values = curves.x.values.map( THREE.Math.degToRad );
|
|
|
+ curves.y.values = curves.y.values.map( THREE.Math.degToRad );
|
|
|
+ curves.z.values = curves.z.values.map( THREE.Math.degToRad );
|
|
|
|
|
|
if ( curveNode.preRotations !== null ) {
|
|
|
|
|
@@ -3012,11 +3016,11 @@
|
|
|
version: null,
|
|
|
id: animationCurve.id,
|
|
|
internalID: animationCurve.id,
|
|
|
- times: parseFloatArray( animationCurve.subNodes.KeyTime.properties.a ).map( convertFBXTimeToSeconds ),
|
|
|
- values: parseFloatArray( animationCurve.subNodes.KeyValueFloat.properties.a ),
|
|
|
+ times: animationCurve.subNodes.KeyTime.properties.a.map( convertFBXTimeToSeconds ),
|
|
|
+ values: animationCurve.subNodes.KeyValueFloat.properties.a,
|
|
|
|
|
|
- attrFlag: parseIntArray( animationCurve.subNodes.KeyAttrFlags.properties.a ),
|
|
|
- attrData: parseFloatArray( animationCurve.subNodes.KeyAttrDataFloat.properties.a )
|
|
|
+ attrFlag: animationCurve.subNodes.KeyAttrFlags.properties.a,
|
|
|
+ attrData: animationCurve.subNodes.KeyAttrDataFloat.properties.a,
|
|
|
};
|
|
|
|
|
|
}
|
|
@@ -4069,7 +4073,7 @@
|
|
|
|
|
|
} );
|
|
|
|
|
|
- function TextParser() { }
|
|
|
+ function TextParser() {}
|
|
|
|
|
|
Object.assign( TextParser.prototype, {
|
|
|
|
|
@@ -4194,15 +4198,8 @@
|
|
|
|
|
|
}
|
|
|
|
|
|
- // for special case,
|
|
|
- //
|
|
|
- // Vertices: *8670 {
|
|
|
- // a: 0.0356229953467846,13.9599733352661,-0.399196773.....(snip)
|
|
|
- // -0.0612030513584614,13.960485458374,-0.409748703241348,-0.10.....
|
|
|
- // 0.12490539252758,13.7450733184814,-0.454119384288788,0.09272.....
|
|
|
- // 0.0836158767342567,13.5432004928589,-0.435397416353226,0.028.....
|
|
|
- //
|
|
|
- // in these case the lines must continue from the previous line
|
|
|
+ // large arrays are split over multiple lines terminated with a ',' character
|
|
|
+ // if this is encountered the line needs to be joined to the previous line
|
|
|
if ( l.match( /^[^\s\t}]/ ) ) {
|
|
|
|
|
|
this.parseNodePropertyContinued( l );
|
|
@@ -4377,7 +4374,6 @@
|
|
|
// already exists in properties, then append this
|
|
|
if ( propName in currentNode.properties ) {
|
|
|
|
|
|
- // console.log( "duped entry found\nkey: " + propName + "\nvalue: " + propValue );
|
|
|
if ( Array.isArray( currentNode.properties[ propName ] ) ) {
|
|
|
|
|
|
currentNode.properties[ propName ].push( propValue );
|
|
@@ -4404,13 +4400,28 @@
|
|
|
|
|
|
this.setCurrentProp( currentNode.properties, propName );
|
|
|
|
|
|
+ // convert string to array, unless it ends in ',' in which case more will be added to it
|
|
|
+ if ( propName === 'a' && propValue.slice( - 1 ) !== ',' ) {
|
|
|
+
|
|
|
+ currentNode.properties.a = parseNumberArray( propValue );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
},
|
|
|
|
|
|
- // TODO:
|
|
|
parseNodePropertyContinued: function ( line ) {
|
|
|
|
|
|
this.currentProp[ this.currentPropName ] += line;
|
|
|
|
|
|
+ // if the line doesn't end in ',' we have reached the end of the property value
|
|
|
+ // so convert the string to an array
|
|
|
+ if ( line.slice( - 1 ) !== ',' ) {
|
|
|
+
|
|
|
+ var currentNode = this.getCurrentNode();
|
|
|
+ currentNode.properties.a = parseNumberArray( currentNode.properties.a );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
},
|
|
|
|
|
|
parseNodeSpecialProperty: function ( line, propName, propValue ) {
|
|
@@ -4460,7 +4471,7 @@
|
|
|
case 'Lcl_Translation':
|
|
|
case 'Lcl_Rotation':
|
|
|
case 'Lcl_Scaling':
|
|
|
- innerPropValue = parseFloatArray( innerPropValue );
|
|
|
+ innerPropValue = parseNumberArray( innerPropValue );
|
|
|
break;
|
|
|
|
|
|
}
|
|
@@ -4498,7 +4509,7 @@
|
|
|
// Binary format specification:
|
|
|
// https://code.blender.org/2013/08/fbx-binary-file-format-specification/
|
|
|
// https://wiki.rogiken.org/specifications/file-format/fbx/ (more detail but Japanese)
|
|
|
- function BinaryParser() { }
|
|
|
+ function BinaryParser() {}
|
|
|
|
|
|
Object.assign( BinaryParser.prototype, {
|
|
|
|
|
@@ -4614,18 +4625,10 @@
|
|
|
|
|
|
if ( Array.isArray( value ) ) {
|
|
|
|
|
|
- // node represents
|
|
|
- // Vertices: *3 {
|
|
|
- // a: 0.01, 0.02, 0.03
|
|
|
- // }
|
|
|
- // of text format here.
|
|
|
-
|
|
|
node.properties[ node.name ] = node.propertyList[ 0 ];
|
|
|
subNodes[ node.name ] = node;
|
|
|
|
|
|
- // Later phase expects single property array is in node.properties.a as String.
|
|
|
- // TODO: optimize
|
|
|
- node.properties.a = value.toString();
|
|
|
+ node.properties.a = value;
|
|
|
|
|
|
} else {
|
|
|
|
|
@@ -4696,8 +4699,7 @@
|
|
|
if ( innerPropName.indexOf( 'Lcl ' ) === 0 ) innerPropName = innerPropName.replace( 'Lcl ', 'Lcl_' );
|
|
|
if ( innerPropType1.indexOf( 'Lcl ' ) === 0 ) innerPropType1 = innerPropType1.replace( 'Lcl ', 'Lcl_' );
|
|
|
|
|
|
- if ( innerPropType1 === 'ColorRGB' || innerPropType1 === 'Vector' ||
|
|
|
- innerPropType1 === 'Vector3D' || innerPropType1.indexOf( 'Lcl_' ) === 0 ) {
|
|
|
+ if ( innerPropType1 === 'ColorRGB' || innerPropType1 === 'Vector' || innerPropType1 === 'Vector3D' || innerPropType1.indexOf( 'Lcl_' ) === 0 ) {
|
|
|
|
|
|
innerPropValue = [
|
|
|
node.propertyList[ 4 ],
|
|
@@ -5256,7 +5258,7 @@
|
|
|
} );
|
|
|
|
|
|
|
|
|
- function FBXTree() { }
|
|
|
+ function FBXTree() {}
|
|
|
|
|
|
Object.assign( FBXTree.prototype, {
|
|
|
|
|
@@ -5353,8 +5355,8 @@
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- this.__cache_search_connection_children[ id ] = [];
|
|
|
- return [];
|
|
|
+ this.__cache_search_connection_children[ id ] = [ ];
|
|
|
+ return [ ];
|
|
|
|
|
|
}
|
|
|
|
|
@@ -5476,15 +5478,18 @@
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Parses comma separated list of float numbers and returns them in an array.
|
|
|
+ * Parses comma separated list of numbers and returns them in an array.
|
|
|
+ * If an array is passed just return it - this is because the TextParser sometimes
|
|
|
+ * returns strings instead of arrays, while the BinaryParser always returns arrays
|
|
|
+ * TODO: this function should only need to be called from inside the TextParser
|
|
|
* @example
|
|
|
* // Returns [ 5.6, 9.4, 2.5, 1.4 ]
|
|
|
- * parseFloatArray( "5.6,9.4,2.5,1.4" )
|
|
|
+ * parseNumberArray( "5.6,9.4,2.5,1.4" )
|
|
|
* @returns {number[]}
|
|
|
*/
|
|
|
- function parseFloatArray( string ) {
|
|
|
+ function parseNumberArray( value ) {
|
|
|
|
|
|
- var array = string.split( ',' );
|
|
|
+ var array = value.split( ',' );
|
|
|
|
|
|
for ( var i = 0, l = array.length; i < l; i ++ ) {
|
|
|
|
|
@@ -5496,27 +5501,6 @@
|
|
|
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Parses comma separated list of int numbers and returns them in an array.
|
|
|
- * @example
|
|
|
- * // Returns [ 5, 8, 2, 3 ]
|
|
|
- * parseFloatArray( "5,8,2,3" )
|
|
|
- * @returns {number[]}
|
|
|
- */
|
|
|
- function parseIntArray( string ) {
|
|
|
-
|
|
|
- var array = string.split( ',' );
|
|
|
-
|
|
|
- for ( var i = 0, l = array.length; i < l; i ++ ) {
|
|
|
-
|
|
|
- array[ i ] = parseInt( array[ i ] );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return array;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* Parses Vector3 property from FBXTree. Property is given as .value.x, .value.y, etc.
|
|
|
* @param {FBXVector3} property - Property to parse as Vector3.
|
|
@@ -5539,12 +5523,6 @@
|
|
|
|
|
|
}
|
|
|
|
|
|
- function parseMatrixArray( floatString ) {
|
|
|
-
|
|
|
- return new THREE.Matrix4().fromArray( parseFloatArray( floatString ) );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* Converts ArrayBuffer to String.
|
|
|
* @param {ArrayBuffer} buffer
|
|
@@ -5577,21 +5555,6 @@
|
|
|
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Converts number from degrees into radians.
|
|
|
- * @param {number} value
|
|
|
- * @returns {number}
|
|
|
- */
|
|
|
- function degreeToRadian( value ) {
|
|
|
-
|
|
|
- return value * DEG2RAD;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- var DEG2RAD = Math.PI / 180;
|
|
|
-
|
|
|
- //
|
|
|
-
|
|
|
function findIndex( array, func ) {
|
|
|
|
|
|
for ( var i = 0, l = array.length; i < l; i ++ ) {
|