|
@@ -1,5 +1,6 @@
|
|
/**
|
|
/**
|
|
* @author yamahigashi https://github.com/yamahigashi
|
|
* @author yamahigashi https://github.com/yamahigashi
|
|
|
|
+ * @author Kyle-Larson https://github.com/Kyle-Larson
|
|
*
|
|
*
|
|
* This loader loads FBX file in *ASCII and version 7 format*.
|
|
* This loader loads FBX file in *ASCII and version 7 format*.
|
|
*
|
|
*
|
|
@@ -121,6 +122,7 @@
|
|
scope.weights = ( new Weights() ).parse( nodes, scope.hierarchy );
|
|
scope.weights = ( new Weights() ).parse( nodes, scope.hierarchy );
|
|
scope.animations = ( new Animation() ).parse( nodes, scope.hierarchy );
|
|
scope.animations = ( new Animation() ).parse( nodes, scope.hierarchy );
|
|
scope.textures = ( new Textures() ).parse( nodes, scope.hierarchy );
|
|
scope.textures = ( new Textures() ).parse( nodes, scope.hierarchy );
|
|
|
|
+ scope.materials = ( new Materials() ).parse( nodes, scope.hierarchy );
|
|
console.timeEnd( 'FBXLoader: ObjectParser' );
|
|
console.timeEnd( 'FBXLoader: ObjectParser' );
|
|
|
|
|
|
console.time( 'FBXLoader: GeometryParser' );
|
|
console.time( 'FBXLoader: GeometryParser' );
|
|
@@ -237,7 +239,6 @@
|
|
geometry.computeBoundingSphere();
|
|
geometry.computeBoundingSphere();
|
|
geometry.computeBoundingBox();
|
|
geometry.computeBoundingBox();
|
|
|
|
|
|
- // TODO: texture & material support
|
|
|
|
var texture;
|
|
var texture;
|
|
var texs = this.textures.getById( nodes.searchConnectionParent( geo.id ) );
|
|
var texs = this.textures.getById( nodes.searchConnectionParent( geo.id ) );
|
|
if ( texs !== undefined && texs.length > 0 ) {
|
|
if ( texs !== undefined && texs.length > 0 ) {
|
|
@@ -251,15 +252,68 @@
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ var materials = [];
|
|
var material;
|
|
var material;
|
|
- if ( texture !== undefined ) {
|
|
|
|
|
|
+ var mats = this.materials.getById( nodes.searchConnectionParent( geo.id ) );
|
|
|
|
+ if ( mats !== undefined && mats.length > 0) {
|
|
|
|
+ for(var i = 0; i < mats.length; ++i) {
|
|
|
|
+ var mat_data = mats[i];
|
|
|
|
+ var tmpMat;
|
|
|
|
+
|
|
|
|
+ // TODO:
|
|
|
|
+ // Cannot find a list of possible ShadingModel values.
|
|
|
|
+ // If someone finds a list, please add additional cases
|
|
|
|
+ // and map to appropriate materials.
|
|
|
|
+ switch(mat_data.type) {
|
|
|
|
+ case "phong":
|
|
|
|
+ tmpMat = new THREE.MeshPhongMaterial();
|
|
|
|
+ break;
|
|
|
|
+ case "Lambert":
|
|
|
|
+ tmpMat = new THREE.MeshLambertMaterial();
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ console.warn("No implementation given for material type " + mat_data.type + " in FBXLoader.js. Defaulting to basic material")
|
|
|
|
+ tmpMat = new THREE.MeshBasicMaterial({ color: 0x3300ff });
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ if (texture !== undefined) {
|
|
|
|
+ mat_data.parameters.map = texture;
|
|
|
|
+ }
|
|
|
|
+ tmpMat.setValues(mat_data.parameters);
|
|
|
|
+
|
|
|
|
+ materials.push(tmpMat);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(materials.length === 1) {
|
|
|
|
+ material = materials[0];
|
|
|
|
+ } else {
|
|
|
|
+ //Set up for multi-material
|
|
|
|
+ material = new THREE.MultiMaterial(materials);
|
|
|
|
+ var material_groupings = [];
|
|
|
|
+ var last_material_group = -1;
|
|
|
|
+ var material_index_list = toInt(node.subNodes.LayerElementMaterial.subNodes.Materials.properties.a.split( ',' ));
|
|
|
|
+ for(var i = 0; i < geo.polyIndices.length; ++i) {
|
|
|
|
+ if(last_material_group !== material_index_list[geo.polyIndices[i]]) {
|
|
|
|
+ material_groupings.push({start: i * 3, count: 0, materialIndex: material_index_list[geo.polyIndices[i]]});
|
|
|
|
+ last_material_group = material_index_list[geo.polyIndices[i]];
|
|
|
|
+ }
|
|
|
|
+ material_groupings[material_groupings.length - 1].count += 3;
|
|
|
|
+ }
|
|
|
|
+ geometry.groups = material_groupings;
|
|
|
|
+ }
|
|
|
|
|
|
- material = new THREE.MeshBasicMaterial( { map: texture } );
|
|
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
|
+ //No material found for this geometry, create default
|
|
|
|
+ if (texture !== undefined) {
|
|
|
|
+
|
|
|
|
+ material = new THREE.MeshBasicMaterial({ map: texture });
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
|
|
- material = new THREE.MeshBasicMaterial( { color: 0x3300ff } );
|
|
|
|
|
|
+ material = new THREE.MeshBasicMaterial({ color: 0x3300ff });
|
|
|
|
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
geometry = new THREE.Geometry().fromBufferGeometry( geometry );
|
|
geometry = new THREE.Geometry().fromBufferGeometry( geometry );
|
|
@@ -480,51 +534,6 @@
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
- THREE.FBXLoader.prototype.parseMaterials = function ( node ) {
|
|
|
|
-
|
|
|
|
- // has not mat, return []
|
|
|
|
- if ( ! ( 'Material' in node.subNodes ) ) {
|
|
|
|
-
|
|
|
|
- return [];
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // has many
|
|
|
|
- var matCount = 0;
|
|
|
|
- for ( var mat in node.subNodes.Materials ) {
|
|
|
|
-
|
|
|
|
- if ( mat.match( /^\d+$/ ) ) {
|
|
|
|
-
|
|
|
|
- matCount ++;
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- var res = [];
|
|
|
|
- if ( matCount > 0 ) {
|
|
|
|
-
|
|
|
|
- for ( mat in node.subNodes.Material ) {
|
|
|
|
-
|
|
|
|
- res.push( parseMaterial( node.subNodes.Material[ mat ] ) );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- } else {
|
|
|
|
-
|
|
|
|
- res.push( parseMaterial( node.subNodes.Material ) );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return res;
|
|
|
|
-
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // TODO
|
|
|
|
- THREE.FBXLoader.prototype.parseMaterial = function ( node ) {
|
|
|
|
-
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
|
|
|
|
THREE.FBXLoader.prototype.loadFile = function ( url, onLoad, onProgress, onError, responseType ) {
|
|
THREE.FBXLoader.prototype.loadFile = function ( url, onLoad, onProgress, onError, responseType ) {
|
|
|
|
|
|
@@ -1564,8 +1573,10 @@
|
|
|
|
|
|
if ( this.getPolygonTopologyMax() > 3 ) {
|
|
if ( this.getPolygonTopologyMax() > 3 ) {
|
|
|
|
|
|
- this.indices = this.convertPolyIndicesToTri(
|
|
|
|
|
|
+ var indexInfo = this.convertPolyIndicesToTri(
|
|
this.indices, this.getPolygonTopologyArray() );
|
|
this.indices, this.getPolygonTopologyArray() );
|
|
|
|
+ this.indices = indexInfo.res;
|
|
|
|
+ this.polyIndices = indexInfo.polyIndices;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1709,14 +1720,16 @@
|
|
//
|
|
//
|
|
// [( a, b, c, d ) ...........
|
|
// [( a, b, c, d ) ...........
|
|
// [( a, b, c ), (a, c, d )....
|
|
// [( a, b, c ), (a, c, d )....
|
|
|
|
+
|
|
|
|
+ // Also keep track of original poly index.
|
|
Geometry.prototype.convertPolyIndicesToTri = function ( indices, strides ) {
|
|
Geometry.prototype.convertPolyIndicesToTri = function ( indices, strides ) {
|
|
|
|
|
|
var res = [];
|
|
var res = [];
|
|
|
|
|
|
var i = 0;
|
|
var i = 0;
|
|
- var tmp = [];
|
|
|
|
var currentPolyNum = 0;
|
|
var currentPolyNum = 0;
|
|
var currentStride = 0;
|
|
var currentStride = 0;
|
|
|
|
+ var polyIndices = [];
|
|
|
|
|
|
while ( i < indices.length ) {
|
|
while ( i < indices.length ) {
|
|
|
|
|
|
@@ -1729,14 +1742,14 @@
|
|
res.push( indices[ i + ( currentStride - 2 - j ) ] );
|
|
res.push( indices[ i + ( currentStride - 2 - j ) ] );
|
|
res.push( indices[ i + ( currentStride - 1 - j ) ] );
|
|
res.push( indices[ i + ( currentStride - 1 - j ) ] );
|
|
|
|
|
|
|
|
+ polyIndices.push(currentPolyNum);
|
|
}
|
|
}
|
|
|
|
|
|
currentPolyNum ++;
|
|
currentPolyNum ++;
|
|
i += currentStride;
|
|
i += currentStride;
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- return res;
|
|
|
|
|
|
+ return {res: res, polyIndices: polyIndices};
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
@@ -2503,6 +2516,114 @@
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ function Materials() {
|
|
|
|
+ this.materials = [];
|
|
|
|
+ this.perGeoMap = {};
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Materials.prototype.add = function ( mat ) {
|
|
|
|
+
|
|
|
|
+ if ( this.materials === undefined ) {
|
|
|
|
+
|
|
|
|
+ this.materials = [];
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.materials.push( mat );
|
|
|
|
+
|
|
|
|
+ for ( var i = 0; i < mat.parentIds.length; ++ i ) {
|
|
|
|
+
|
|
|
|
+ if ( this.perGeoMap[ mat.parentIds[ i ] ] === undefined ) {
|
|
|
|
+
|
|
|
|
+ this.perGeoMap[ mat.parentIds[ i ] ] = [];
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.perGeoMap[ mat.parentIds[ i ] ].push( this.materials[ this.materials.length - 1 ] );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ Materials.prototype.parse = function ( node, bones ) {
|
|
|
|
+
|
|
|
|
+ var rawNodes = node.Objects.subNodes.Material;
|
|
|
|
+
|
|
|
|
+ for ( var n in rawNodes ) {
|
|
|
|
+
|
|
|
|
+ var mat = ( new Material() ).parse( rawNodes[ n ], node );
|
|
|
|
+ this.add( mat );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return this;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ Materials.prototype.getById = function ( id ) {
|
|
|
|
+
|
|
|
|
+ return this.perGeoMap[ id ];
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ function Material() {
|
|
|
|
+
|
|
|
|
+ this.fileName = "";
|
|
|
|
+ this.name = "";
|
|
|
|
+ this.id = null;
|
|
|
|
+ this.parentIds = [];
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Material.prototype.parse = function ( node, nodes ) {
|
|
|
|
+
|
|
|
|
+ this.id = node.id;
|
|
|
|
+ this.name = node.attrName;
|
|
|
|
+ this.type = node.properties.ShadingModel;
|
|
|
|
+
|
|
|
|
+ this.parameters = this.getParameters( node.properties );
|
|
|
|
+
|
|
|
|
+ this.parentIds = this.searchParents( this.id, nodes );
|
|
|
|
+
|
|
|
|
+ return this;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ Material.prototype.getParameters = function( properties ) {
|
|
|
|
+ var parameters = {};
|
|
|
|
+
|
|
|
|
+ //TODO: Missing parameters:
|
|
|
|
+ // - Ambient
|
|
|
|
+ // - AmbientColor
|
|
|
|
+ // - (Diffuse?) Using DiffuseColor, which has same value, so I dunno.
|
|
|
|
+ // - (Emissive?) Same as above)
|
|
|
|
+ // - MultiLayer
|
|
|
|
+ // - ShininessExponent (Same vals as Shininess)
|
|
|
|
+ // - Specular (Same vals as SpecularColor)
|
|
|
|
+ // - TransparencyFactor (Maybe same as Opacity?).
|
|
|
|
+
|
|
|
|
+ parameters.color = new THREE.Color().fromArray(toFloat([properties.DiffuseColor.value.x, properties.DiffuseColor.value.y, properties.DiffuseColor.value.z]));
|
|
|
|
+ parameters.specular = new THREE.Color().fromArray(toFloat([properties.SpecularColor.value.x, properties.SpecularColor.value.y, properties.SpecularColor.value.z]));
|
|
|
|
+ parameters.shininess = properties.Shininess.value;
|
|
|
|
+ parameters.emissive = new THREE.Color().fromArray(toFloat([properties.EmissiveColor.value.x, properties.EmissiveColor.value.y, properties.EmissiveColor.value.z]));
|
|
|
|
+ parameters.emissiveIntensity = properties.EmissiveFactor.value;
|
|
|
|
+ parameters.reflectivity = properties.Reflectivity.value;
|
|
|
|
+ parameters.opacity = properties.Opacity.value;
|
|
|
|
+ if(parameters.opacity < 1.0) {
|
|
|
|
+ parameters.transparent = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return parameters;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ Material.prototype.searchParents = function ( id, nodes ) {
|
|
|
|
+
|
|
|
|
+ var p = nodes.searchConnectionParent( id );
|
|
|
|
+
|
|
|
|
+ return p;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
/* --------------------------------------------------------------------- */
|
|
/* --------------------------------------------------------------------- */
|
|
/* --------------------------------------------------------------------- */
|