提交 ed26738c 编写于 作者: K Kyle Larson

Possible support for multiple animations?

上级 0ad977c2
......@@ -14,7 +14,7 @@
* - morph
*/
( function() {
( function () {
THREE.FBXLoader = function ( manager ) {
......@@ -29,7 +29,9 @@
THREE.FBXLoader.prototype.constructor = THREE.FBXLoader;
THREE.FBXLoader.prototype.load = function ( url, onLoad, onProgress, onError ) {
Object.assign( THREE.FBXLoader.prototype, {
load: function ( url, onLoad, onProgress, onError ) {
var scope = this;
......@@ -54,15 +56,15 @@
}, onProgress, onError );
};
},
THREE.FBXLoader.prototype.setCrossOrigin = function ( value ) {
setCrossOrigin: function ( value ) {
this.crossOrigin = value;
};
},
THREE.FBXLoader.prototype.isFbxFormatASCII = function ( body ) {
isFbxFormatASCII: function ( body ) {
var CORRECT = [ 'K', 'a', 'y', 'd', 'a', 'r', 'a', '\\', 'F', 'B', 'X', '\\', 'B', 'i', 'n', 'a', 'r', 'y', '\\', '\\' ];
......@@ -89,9 +91,9 @@
return true;
};
},
THREE.FBXLoader.prototype.isFbxVersionSupported = function ( body ) {
isFbxVersionSupported: function ( body ) {
var versionExp = /FBXVersion: (\d+)/;
var match = body.match( versionExp );
......@@ -104,9 +106,9 @@
}
return false;
};
},
THREE.FBXLoader.prototype.parse = function ( text ) {
parse: function ( text ) {
var scope = this;
......@@ -121,6 +123,8 @@
scope.weights = ( new Weights() ).parse( nodes, scope.hierarchy );
scope.animations = ( new Animation() ).parse( nodes, scope.hierarchy );
scope.textures = ( new Textures() ).parse( nodes, scope.hierarchy );
//scope.materials = ( new Materials() ).parse( nodes, scope.hierarchy );
//scope.geometries = ( new Geometries() ).parse( nodes, scope.hierarchy );
console.timeEnd( 'FBXLoader: ObjectParser' );
console.time( 'FBXLoader: GeometryParser' );
......@@ -155,9 +159,9 @@
console.timeEnd( 'FBXLoader' );
return container;
};
},
THREE.FBXLoader.prototype.parseGeometries = function ( node ) {
parseGeometries: function ( node ) {
// has not geo, return []
if ( ! ( 'Geometry' in node.Objects.subNodes ) ) {
......@@ -199,9 +203,9 @@
return res;
};
},
THREE.FBXLoader.prototype.parseGeometry = function ( node, nodes ) {
parseGeometry: function ( node, nodes ) {
var geo = ( new Geometry() ).parse( node );
geo.addBones( this.hierarchy.hierarchy );
......@@ -282,21 +286,28 @@
return mesh;
};
},
THREE.FBXLoader.prototype.addAnimation = function ( mesh, matrices, animations ) {
addAnimation: function ( mesh, matrices, animations ) {
var animationdata = { "name": 'animationtest', "fps": 30, "length": animations.length, "hierarchy": [] };
for ( var key in animations.stacks ) {
var animationData = {
name: animations.stacks[ key ].name,
fps: 30,
length: animations.length,
hierarchy: []
};
for ( var i = 0; i < mesh.geometry.bones.length; ++ i ) {
var name = mesh.geometry.bones[ i ].name;
name = name.replace( /.*:/, '' );
animationdata.hierarchy.push( { parent: mesh.geometry.bones[ i ].parent, name: name, keys: [] } );
animationData.hierarchy.push( { parent: mesh.geometry.bones[ i ].parent, name: name, keys: [] } );
}
var hasCurve = function ( animNode, attr ) {
function hasCurve( animNode, attr ) {
if ( animNode === undefined ) {
......@@ -308,7 +319,7 @@
switch ( attr ) {
case 'S':
if ( animNode.S === undefined ) {
if ( ! ( animNode.S ) ) {
return false;
......@@ -317,7 +328,7 @@
break;
case 'R':
if ( animNode.R === undefined ) {
if ( ! ( animNode.R ) ) {
return false;
......@@ -326,13 +337,14 @@
break;
case 'T':
if ( animNode.T === undefined ) {
if ( ! ( animNode.T ) ) {
return false;
}
attrNode = animNode.T;
break;
}
if ( attrNode.curves.x === undefined ) {
......@@ -355,9 +367,9 @@
return true;
};
}
var hasKeyOnFrame = function ( attrNode, frame ) {
function hasKeyOnFrame( attrNode, frame ) {
var x = isKeyExistOnFrame( attrNode.curves.x, frame );
var y = isKeyExistOnFrame( attrNode.curves.y, frame );
......@@ -365,17 +377,16 @@
return x && y && z;
};
}
var isKeyExistOnFrame = function ( curve, frame ) {
function isKeyExistOnFrame( curve, frame ) {
var value = curve.values[ frame ];
return value !== undefined;
};
}
var genKey = function ( animNode, bone ) {
function genKey( animNode, bone ) {
// key initialize with its bone's bind pose at first
var key = {};
......@@ -400,10 +411,6 @@
animNode.T.curves.z.values[ frame ] );
key.pos = [ pos.x, pos.y, pos.z ];
} else {
delete key.pos;
}
if ( hasCurve( animNode, 'R' ) && hasKeyOnFrame( animNode.R, frame ) ) {
......@@ -415,10 +422,6 @@
var rot = quatFromVec( eul.x, eul.y, eul.z );
key.rot = [ rot.x, rot.y, rot.z, rot.w ];
} else {
delete key.rot;
}
if ( hasCurve( animNode, 'S' ) && hasKeyOnFrame( animNode.S, frame ) ) {
......@@ -429,10 +432,6 @@
animNode.S.curves.z.values[ frame ] );
key.scl = [ scl.x, scl.y, scl.z ];
} else {
delete key.scl;
}
} catch ( e ) {
......@@ -445,7 +444,7 @@
return key;
};
}
var bones = mesh.geometry.bones;
for ( var frame = 0; frame < animations.frames; frame ++ ) {
......@@ -454,13 +453,13 @@
for ( i = 0; i < bones.length; i ++ ) {
var bone = bones[ i ];
var animNode = animations.curves[ i ];
var animNode = animations.stacks[ key ].layers[ 0 ][ i ];
for ( var j = 0; j < animationdata.hierarchy.length; j ++ ) {
for ( var j = 0; j < animationData.hierarchy.length; j ++ ) {
if ( animationdata.hierarchy[ j ].name === bone.name ) {
if ( animationData.hierarchy[ j ].name === bone.name ) {
animationdata.hierarchy[ j ].keys.push( genKey( animNode, bone ) );
animationData.hierarchy[ j ].keys.push( genKey( animNode, bone ) );
}
......@@ -476,96 +475,51 @@
}
mesh.geometry.animations.push( THREE.AnimationClip.parseAnimation( animationdata, mesh.geometry.bones ) );
};
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 ++;
mesh.geometry.animations.push( THREE.AnimationClip.parseAnimation( animationData, mesh.geometry.bones ) );
}
}
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 ) {
loadFile: function ( url, onLoad, onProgress, onError, responseType ) {
var loader = new THREE.FileLoader( this.manager );
loader.setResponseType( responseType );
var request = loader.load( url, function ( result ) {
onLoad( result );
}, onProgress, onError );
var request = loader.load( url, onLoad, onProgress, onError );
return request;
};
},
THREE.FBXLoader.prototype.loadFileAsBuffer = function ( url, onload, onProgress, onError ) {
loadFileAsBuffer: function ( url, onLoad, onProgress, onError ) {
this.loadFile( url, onLoad, onProgress, onError, 'arraybuffer' );
};
},
THREE.FBXLoader.prototype.loadFileAsText = function ( url, onLoad, onProgress, onError ) {
loadFileAsText: function ( url, onLoad, onProgress, onError ) {
this.loadFile( url, onLoad, onProgress, onError, 'text' );
};
}
} );
/* ----------------------------------------------------------------- */
function FBXNodes() {}
FBXNodes.prototype.add = function ( key, val ) {
Object.assign( FBXNodes.prototype, {
add: function ( key, val ) {
this[ key ] = val;
};
},
FBXNodes.prototype.searchConnectionParent = function ( id ) {
searchConnectionParent: function ( id ) {
if ( this.__cache_search_connection_parent === undefined ) {
......@@ -610,9 +564,9 @@
}
};
},
FBXNodes.prototype.searchConnectionChildren = function ( id ) {
searchConnectionChildren: function ( id ) {
if ( this.__cache_search_connection_children === undefined ) {
......@@ -652,14 +606,14 @@
} else {
this.__cache_search_connection_children[ id ] = [ - 1 ];
return [ - 1 ];
this.__cache_search_connection_children[ id ] = [ ];
return [ ];
}
};
},
FBXNodes.prototype.searchConnectionType = function ( id, to ) {
searchConnectionType: function ( id, to ) {
var key = id + ',' + to; // TODO: to hash
if ( this.__cache_search_connection_type === undefined ) {
......@@ -695,15 +649,13 @@
this.__cache_search_connection_type[ id ] = null;
return null;
};
function FBXParser() {}
}
FBXParser.prototype = {
} );
// constructor: FBXParser,
function FBXParser() {}
// ------------ node stack manipulations ----------------------------------
Object.assign( FBXParser.prototype, {
getPrevNode: function () {
......@@ -879,6 +831,11 @@
}
} else if ( typeof attrs.id === 'number' || attrs.id.match( /^\d+$/ ) ) {
currentNode.subNodes[ nodeName ] = {};
currentNode.subNodes[ nodeName ][ attrs.id ] = node;
} else {
currentNode.subNodes[ nodeName ] = node;
......@@ -1077,7 +1034,7 @@
},
nodeEnd: function ( line ) {
nodeEnd: function () {
this.popStack();
......@@ -1091,13 +1048,7 @@
}
};
function FBXAnalyzer() {}
FBXAnalyzer.prototype = {
};
} );
// generate skinIndices, skinWeights
......@@ -1117,10 +1068,10 @@
Weights.prototype.parseCluster = function ( node, id, entry ) {
var _p = node.searchConnectionParent( id );
var _indices = toInt( entry.subNodes.Indexes.properties.a.split( ',' ) );
var _weights = toFloat( entry.subNodes.Weights.properties.a.split( ',' ) );
var _transform = toMat44( toFloat( entry.subNodes.Transform.properties.a.split( ',' ) ) );
var _link = toMat44( toFloat( entry.subNodes.TransformLink.properties.a.split( ',' ) ) );
var _indices = parseArrayToInt( entry.subNodes.Indexes.properties.a );
var _weights = parseArrayToFloat( entry.subNodes.Weights.properties.a );
var _transform = parseArrayToMatrix( entry.subNodes.Transform.properties.a );
var _link = parseArrayToMatrix( entry.subNodes.TransformLink.properties.a );
return {
......@@ -1215,6 +1166,14 @@
// TODO - this might be a good place to choose greatest 4 weights
for ( var i = 0; i < weights.length; i ++ ) {
if ( weights[ i ] === undefined ) {
this.skinIndices.push( new THREE.Vector4( 0, 0, 0, 0 ) );
this.skinWeights.push( new THREE.Vector4( 0, 0, 0, 0 ) );
continue;
}
var indicies = new THREE.Vector4(
weights[ i ].joint[ 0 ] ? weights[ i ].joint[ 0 ] : 0,
weights[ i ].joint[ 1 ] ? weights[ i ].joint[ 1 ] : 0,
......@@ -1318,13 +1277,13 @@
if ( 'Lcl_Translation' in bone.properties ) {
t = toFloat( bone.properties.Lcl_Translation.value.split( ',' ) );
t = parseArrayToFloat( bone.properties.Lcl_Translation.value );
}
if ( 'Lcl_Rotation' in bone.properties ) {
r = toRad( toFloat( bone.properties.Lcl_Rotation.value.split( ',' ) ) );
r = parseArrayToRadians( bone.properties.Lcl_Rotation.value );
var q = new THREE.Quaternion();
q.setFromEuler( new THREE.Euler( r[ 0 ], r[ 1 ], r[ 2 ], 'ZYX' ) );
r = [ q.x, q.y, q.z, q.w ];
......@@ -1333,7 +1292,7 @@
if ( 'Lcl_Scaling' in bone.properties ) {
s = toFloat( bone.properties.Lcl_Scaling.value.split( ',' ) );
s = parseArrayToFloat( bone.properties.Lcl_Scaling.value );
}
......@@ -1382,14 +1341,25 @@
}
for ( var key in bindPoseNode ) {
if ( bindPoseNode[ key ].attrType === 'BindPose' ) {
bindPoseNode = bindPoseNode[ key ];
break;
}
}
var poseNode = bindPoseNode.subNodes.PoseNode;
var localMatrices = {}; // store local matrices, modified later( initialy world space )
var worldMatrices = {}; // store world matrices
for ( var i = 0; i < poseNode.length; ++ i ) {
var rawMatLcl = toMat44( poseNode[ i ].subNodes.Matrix.properties.a.split( ',' ) );
var rawMatWrd = toMat44( poseNode[ i ].subNodes.Matrix.properties.a.split( ',' ) );
var rawMatLcl = parseArrayToMatrix( poseNode[ i ].subNodes.Matrix.properties.a );
var rawMatWrd = parseArrayToMatrix( poseNode[ i ].subNodes.Matrix.properties.a );
localMatrices[ poseNode[ i ].id ] = rawMatLcl;
worldMatrices[ poseNode[ i ].id ] = rawMatWrd;
......@@ -1831,7 +1801,7 @@
UV.prototype._parseText = function ( node ) {
var uvNode = this.getNode( node );
var uvNode = this.getNode( node )[ 0 ];
if ( uvNode === undefined ) {
// console.log( node.attrName + "(" + node.id + ")" + " has no LayerElementUV." );
......@@ -1865,8 +1835,8 @@
var uvRef = uvNode.properties.ReferenceInformationType;
this.uv = toFloat( uvs.split( ',' ) );
this.index = toInt( uvIndex.split( ',' ) );
this.uv = parseArrayToFloat( uvs );
this.index = parseArrayToInt( uvIndex );
this.map = uvMap; // TODO: normalize notation shaking... FOR BLENDER
this.ref = uvRef;
......@@ -1877,6 +1847,12 @@
UV.prototype.parse = function ( node, geo ) {
if ( ! ( 'LayerElementUV' in node.subNodes ) ) {
return;
}
this.uvNode = this.getNode( node );
this.uv = this.getUV( node );
......@@ -1935,6 +1911,7 @@
}
break;
}
return this.uv;
......@@ -2056,7 +2033,7 @@
Normal.prototype._parseText = function ( node ) {
var normalNode = this.getNode( node );
var normalNode = this.getNode( node )[ 0 ];
if ( normalNode === undefined ) {
......@@ -2069,7 +2046,7 @@
var refType = normalNode.properties.ReferenceInformationType;
var rawTextNormals = normalNode.subNodes.Normals.properties.a;
this.normal = toFloat( rawTextNormals.split( ',' ) );
this.normal = parseArrayToFloat( rawTextNormals );
// TODO: normalize notation shaking, vertex / vertice... blender...
this.map = mappingType;
......@@ -2197,10 +2174,10 @@
this.attrFlag = curveNode.subNodes.KeyAttrFlags.properties.a;
this.attrData = curveNode.subNodes.KeyAttrDataFloat.properties.a;
this.times = toFloat( this.times.split( ',' ) );
this.values = toFloat( this.values.split( ',' ) );
this.attrData = toFloat( this.attrData.split( ',' ) );
this.attrFlag = toInt( this.attrFlag.split( ',' ) );
this.times = parseArrayToFloat( this.times );
this.values = parseArrayToFloat( this.values );
this.attrData = parseArrayToFloat( this.attrData );
this.attrFlag = parseArrayToInt( this.attrFlag );
this.times = this.times.map( function ( element ) {
......@@ -2229,7 +2206,7 @@
this.containerInternalId = null; // bone, null etc Id
this.containerBoneId = null; // bone, null etc Id
this.curveIdx = null; // AnimationCurve's indices
this.curves = []; // AnimationCurve refs
this.curves = {}; // AnimationCurve refs
}
......@@ -2313,6 +2290,8 @@
var rawNodes = node.Objects.subNodes.AnimationCurveNode;
var rawCurves = node.Objects.subNodes.AnimationCurve;
var rawLayers = node.Objects.subNodes.AnimationLayer;
var rawStacks = node.Objects.subNodes.AnimationStack;
// first: expand AnimationCurveNode into curve nodes
var curveNodes = [];
......@@ -2383,7 +2362,11 @@
var id = tmp[ t ].containerBoneId;
if ( this.curves[ id ] === undefined ) {
this.curves[ id ] = {};
this.curves[ id ] = {
T: null,
R: null,
S: null
};
}
......@@ -2391,6 +2374,58 @@
}
//Layers
this.layers = {};
for ( var key in rawLayers ) {
var layer = [];
var children = node.searchConnectionChildren( key );
for ( var i = 0; i < children.length; ++ i ) {
if ( layer[ tmp[ children[ i ] ].containerBoneId ] === undefined ) {
layer[ tmp[ children[ i ] ].containerBoneId ] = {
T: null,
R: null,
S: null
};
}
layer[ tmp[ children[ i ] ].containerBoneId ][ tmp[ children[ i ] ].attr ] = tmp[ children[ i ] ];
}
this.layers[ key ] = layer;
}
//Takes
this.stacks = {};
for ( var key in rawStacks ) {
var layers = [];
var children = node.searchConnectionChildren( key );
for ( var i = 0; i < children.length; ++ i ) {
if ( children[ i ] in this.layers ) {
layers.push( this.layers[ children[ i ] ] );
}
}
this.stacks[ key ] = {
name: rawStacks[ key ].attrName,
layers: layers
};
}
this.length = max;
this.frames = this.length * this.fps;
......@@ -2509,40 +2544,6 @@
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
function loadTextureImage( texture, url ) {
var loader = new THREE.ImageLoader();
loader.load( url, function ( image ) {
} );
loader.load( url, function ( image ) {
texture.image = image;
texture.needUpdate = true;
console.log( 'tex load done' );
},
// Function called when download progresses
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
// Function called when download errors
function ( xhr ) {
console.log( 'An error happened' );
}
);
}
// LayerElementUV: 0 {
// Version: 101
// Name: "Texture_Projection"
......@@ -2678,25 +2679,19 @@
}
// AUTODESK uses broken clock. i guess
var FBXTimeToSeconds = function ( adskTime ) {
function FBXTimeToSeconds( adskTime ) {
return adskTime / 46186158000;
};
}
var degToRad = function ( degrees ) {
function degToRad( degrees ) {
return degrees * Math.PI / 180;
};
var radToDeg = function ( radians ) {
return radians * 180 / Math.PI;
};
}
var quatFromVec = function ( x, y, z ) {
function quatFromVec( x, y, z ) {
var euler = new THREE.Euler( x, y, z, 'ZYX' );
var quat = new THREE.Quaternion();
......@@ -2704,61 +2699,43 @@
return quat;
};
}
// extend Array.prototype ? ....uuuh
var toInt = function ( arr ) {
function parseArrayToInt( string ) {
return arr.map( function ( element ) {
return string.split( ',' ).map( function ( element ) {
return parseInt( element );
} );
};
}
var toFloat = function ( arr ) {
function parseArrayToFloat( string ) {
return arr.map( function ( element ) {
return string.split( ',' ).map( function ( element ) {
return parseFloat( element );
} );
};
}
var toRad = function ( arr ) {
function parseArrayToRadians( string ) {
return arr.map( function ( element ) {
return string.split( ',' ).map( function ( element ) {
return degToRad( element );
return degToRad( parseFloat( element ) );
} );
};
var toMat44 = function ( arr ) {
var mat = new THREE.Matrix4();
mat.set(
arr[ 0 ], arr[ 4 ], arr[ 8 ], arr[ 12 ],
arr[ 1 ], arr[ 5 ], arr[ 9 ], arr[ 13 ],
arr[ 2 ], arr[ 6 ], arr[ 10 ], arr[ 14 ],
arr[ 3 ], arr[ 7 ], arr[ 11 ], arr[ 15 ]
);
}
/*
mat.set(
arr[ 0], arr[ 1], arr[ 2], arr[ 3],
arr[ 4], arr[ 5], arr[ 6], arr[ 7],
arr[ 8], arr[ 9], arr[10], arr[11],
arr[12], arr[13], arr[14], arr[15]
);
// */
function parseArrayToMatrix( string ) {
return mat;
var arr = parseArrayToFloat( string );
return new THREE.Matrix4().fromArray( arr );
};
}
} )();
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册