【发布时间】:2014-12-21 15:15:22
【问题描述】:
使用 Three.js r68+ 我需要稍微修改源代码才能让我的动画正常工作。未经修改的每种类型的模型只有一个被动画化(每种类型的模型有多个生成)。
这是第 29407 行的修改后的源代码(发布的代码从 29389 开始):
THREE.AnimationHandler = {
LINEAR: 0,
CATMULLROM: 1,
CATMULLROM_FORWARD: 2,
//
add: function () { console.warn( 'THREE.AnimationHandler.add() has been deprecated.' ); },
get: function () { console.warn( 'THREE.AnimationHandler.get() has been deprecated.' ); },
remove: function () { console.warn( 'THREE.AnimationHandler.remove() has been deprecated.' ); },
//
animations: [],
init: function ( data ) {
// original -> if ( data.initialized === true ) return;
if ( data.initialized === true ) return data; //<-- modified
如果已初始化,该函数现在返回动画数据。我假设它不会因为缓存而这样做。我的问题是动画具有相同动画名称的多个模型的最佳实践是什么?我尝试根据模型名称对它们进行唯一命名,即:“Death_MaleWarrior”,但这没有效果。
目前我的模型和动画是这样处理的:
var modelArray = [];
var geoCache = [];
var loader = new THREE.JSONLoader(true);
var _MODEL = function(data){
this.data = data;
this.mesh = null;
this.animations = {};
this.canAnimate = false;
this.parseAnimations = function () {
var len,i,anim;
if (this.mesh) {
if( this.mesh.geometry.animations ){
this.canAnimate = true;
len = this.mesh.geometry.animations.length;
if( len ){
for(i=0;i<len;i++){
anim = this.mesh.geometry.animations[i];
if( anim ){
this.animations[anim.name] = new THREE.Animation( this.mesh, anim );
}
}
}
}
}
};
this.playAnimation = function(label){
if (this.canAnimate) {
if( this.animations[label] ){
//if( this.animations[label].data ){
this.animations[label].play(0,1);
//}
}
}
return false;
};
this.load = function(geo){
var mat;
mat = new THREE.MeshPhongMaterial({color:somecolor, skinning:true})
this.mesh = new THREE.SkinnedMesh(geo,mat);
this.mesh.position.x = this.data.position[0];
this.mesh.position.y = this.data.position[1];
this.mesh.position.z = this.data.position[2];
this.parseAnimations();
scene.add(this.mesh);
this.playAnimation('Idle');
};
this.init = function(){
var geo;
if( geoCache[this.data.name] ){
geo = geoCache[this.data.name];
this.load(geo);
}else{
geo = loader.parse(JSON.parse(this.data.json)).geometry;
geoCache[this.data.name] = geo;
this.load(geo);
}
};
this.init();
};
var dataArray = [{name:'MaleWarrior',json:'json_data',position:[x,y,z]},{name:'FemaleWarrior',json:'json_data',position:[x,y,z]},{name:'MaleWarrior',json:'json_data',position:[x,y,z]}];
for(var i=0, len=objectArray.length; i<len; i++){
modelArray.push(new _MODEL(dataArray[i]) );
}
在此示例中,第一个 MaleWarrior 将设置动画,但第二个则不会。如果有第二个女性,她也不会被动画化,因为动画(即使它是一个新的 THREE.Animation() )将被视为已初始化并且不会返回任何数据。如果我不检查 playAnimation 中是否存在 animations.data,我会在第 29665 行收到错误““Uncaught TypeError: Cannot read property 'name' of undefined”。
我正在做什么绕过动画缓存并损害性能?我觉得我错过了什么。没有数据的动画怎么播放?
每个模型“空闲”、“运行”、“攻击”等的所有动画名称都相同。
任何帮助将不胜感激。如果我不够清楚,请告诉我。我添加了更多细节。
【问题讨论】:
-
没有必要修改代码。如果您使用 JSON 加载器,也许您应该检查导出模型的方式?此外,对于您创建的每个 THREE.SkinnedMesh 以及您希望为其播放动画,您必须创建一个 THREE.Animation 对象,并调用其 .play 方法。也许您认为您只需为所有 THREE.SkinnedMesh 创建一个 THREE.Animation?很可能您必须检查您的 JSON 及其加载,因为 geometry.animations 可能没有加载。否则,我认为您的代码没有理由不工作。也许还有那个 Animationhandler 修改的行。
-
另外,通常定义了animation.data。它在您调用 THREE.Animation 构造函数时设置。如果您发布指向其余代码和正在加载的 JSON 文件的链接,我们可以为您提供更多帮助。
-
每个蒙皮网格都有自己的 THREE.Animation 对象数组。为每个单独的网格运行 parseAnimations 函数。 AnimationHandler (pre r68) 行被注释掉。 JSONLoader 没有问题。 r68 之前一切正常。
-
另外,您正在该代码中创建一个名为“animation”的全局,因为您忘记使用“var”指定本地范围,应该是“var animation = new THREE.Animation...” .
-
我相信你有一个更大的对象,它具有那些 .animations 和 .mesh 属性,看到这一点会很有用,因为你的问题可能存在,而不是在你引用的这段代码中在这里。