Система микшера была введена в r73, и с тех пор я пытаюсь обновить свою игру в этой новой системе.
Я ПОЧТИ, кроме одного. Перекрестное замирание некоторых анимаций с определенными геометриями имеет небольшую задержку, которой не было в r72. Я взломал функции r72 BlendCharacter и Animation, чтобы разрешить обратные вызовы, и он отлично работает. В 73 это не было необходимо, если бы эта функция была встроена через триггер события.
В следующей скрипте все работает по назначению (r72).
http://jsfiddle.net/titansoftime/a93w5hw0/
<script src="http://www.titansoftime.com/webgl/Three72.full.js"></script>
<script src="http://www.titansoftime.com/webgl/BlendCharacter2.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/DDSLoader.js"></script>
var scene, camera, renderer, ambient, directional;
var mesh, geoCache={};
var clock, jsLoader, ddsLoader;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 20;
camera.position.y = 10;
ambient = new THREE.AmbientLight(0xffffff);
scene.add(ambient);
directional = new THREE.DirectionalLight(0xffffff,1);
directional.position.set(1,1,0);
scene.add(directional);
clock = new THREE.Clock();
jsLoader = new THREE.JSONLoader(true);
ddsLoader = new THREE.DDSLoader();
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xffffff, 1 );
document.getElementById('idle').onclick = function(e){
play('Idle',true);
};
document.getElementById('run').onclick = function(e){
play('Run',true);
};
document.getElementById('melee').onclick = function(e){
play('MelleAttack');
};
document.getElementById('magic').onclick = function(e){
play('MagicAttack');
};
document.body.appendChild( renderer.domElement );
loadFloor();
loadModel();
}
function createModel(json){
var geo, geo2;
if( geoCache[json.name] ){
geo = geoCache[json.name];
}else{
geo2 = jsLoader.parse(json).geometry;
var m = new THREE.SkinnedMesh( geo2 );
m.normalizeSkinWeights();
geo2 = m.geometry;
geo = new THREE.BufferGeometry().fromGeometry(geo2);
geo.bones = geo2.bones;
geo.animations = geo2.animations;
geoCache[json.name] = geo;
}
var tex = ddsLoader.load('http://www.titansoftime.com/utils.php?task=getTexture&id=16');
var mat = new THREE.MeshPhongMaterial({map:tex,skinning:true,side:THREE.DoubleSide});
mesh = new THREE.BlendCharacter();
mesh.load(geo,mat);
//mesh.scale.set(10,10,10);
//mesh.mixer = new THREE.AnimationMixer( mesh );
//parseAnimations();
scene.add(mesh);
play('Idle',true);
camera.lookAt(new THREE.Vector3(mesh.position.x,7,mesh.position.z));
}
function loadModel(){
$.ajax({
url: 'http://www.titansoftime.com/utils.php',
data: 'task=getModel&id=16',
crossDomain: true,
type: 'POST',
success: function(response){
createModel(JSON.parse(response));
}
});
}
function loadFloor(){
var geo = new THREE.PlaneBufferGeometry(50,50);
geo.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
var mat = new THREE.MeshBasicMaterial({color:0x0000ff});
var mesh = new THREE.Mesh(geo,mat);
scene.add(mesh);
}
function play(name,loop){
loop = loop || false;
var anim = mesh.animations[name];
anim.loop = loop;
if( mesh.currentAnimation ){
var cur = mesh.animations[mesh.currentAnimation];
var theTime = 0.175;
if( !cur.loop ){
var diff = cur.data.length - cur.currentTime;
theTime = Math.max(0,Math.min(theTime,diff));
}
console.log('blending: '+name);
mesh.crossfade(name,theTime,function(){
play('Idle',true)
});
}else{
console.log('playing: '+name);
mesh.play(name,loop);
}
}
function animate() {
requestAnimationFrame( animate );
var delta = clock.getDelta();
if( mesh ){
mesh.update( delta );
}
THREE.AnimationHandler.update(delta);
renderer.render( scene, camera );
}
Этот (r78) работает почти отлично, за исключением одной анимации (Magic Attack) имеет небольшую, но заметную задержку перед возвратом в анимацию Idle. На других моделях это анимация ближнего боя, на некоторых нет проблем вообще. Супер путают, поскольку все они работают правильно в 72.
http://jsfiddle.net/titansoftime/2sh95etj/
<script src="https://rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/master/examples/js/loaders/DDSLoader.js"></script>
var scene, camera, renderer, ambient, directional;
var mesh, geoCache={};
var clock, jsLoader, ddsLoader;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 20;
camera.position.y = 10;
ambient = new THREE.AmbientLight(0xffffff);
scene.add(ambient);
directional = new THREE.DirectionalLight(0xffffff,1);
directional.position.set(1,1,0);
scene.add(directional);
clock = new THREE.Clock();
jsLoader = new THREE.JSONLoader(true);
ddsLoader = new THREE.DDSLoader();
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xffffff, 1 );
document.getElementById('idle').onclick = function(e){
play('Idle',true);
};
document.getElementById('run').onclick = function(e){
play('Run',true);
};
document.getElementById('melee').onclick = function(e){
play('MelleAttack');
};
document.getElementById('magic').onclick = function(e){
play('MagicAttack');
};
document.body.appendChild( renderer.domElement );
loadFloor();
loadModel();
}
function createModel(json){
var geo, geo2;
if( geoCache[json.name] ){
geo = geoCache[json.name];
}else{
geo2 = jsLoader.parse(json).geometry;
var m = new THREE.SkinnedMesh( geo2 );
m.normalizeSkinWeights();
geo2 = m.geometry;
geo = new THREE.BufferGeometry().fromGeometry(geo2);
geo.bones = geo2.bones;
geo.animations = geo2.animations;
geoCache[json.name] = geo;
}
var tex = ddsLoader.load('http://www.titansoftime.com/utils.php?task=getTexture&id=16');
var mat = new THREE.MeshPhongMaterial({map:tex,skinning:true,side:THREE.DoubleSide});
mesh = new THREE.SkinnedMesh(geo,mat);
//mesh.scale.set(10,10,10);
mesh.mixer = new THREE.AnimationMixer( mesh );
parseAnimations();
play('Idle',true);
scene.add(mesh);
camera.lookAt(new THREE.Vector3(mesh.position.x,7,mesh.position.z));
}
function loadModel(){
$.ajax({
url: 'http://www.titansoftime.com/utils.php',
data: 'task=getModel&id=16',
crossDomain: true,
type: 'POST',
success: function(response){
createModel(JSON.parse(response));
}
});
}
function loadFloor(){
var geo = new THREE.PlaneBufferGeometry(50,50);
geo.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
var mat = new THREE.MeshBasicMaterial({color:0x0000ff});
var mesh = new THREE.Mesh(geo,mat);
scene.add(mesh);
}
function play(name,loop){
var to = mesh.animations[ name ];
if( mesh.currentAnimation ){
var from = mesh.animations[ mesh.currentAnimation ];
to.reset();
if( loop ){
to.setLoop(THREE.LoopRepeat);
to.clampWhenFinished = false;
}else{
to.setLoop(THREE.LoopOnce, 0);
to.clampWhenFinished = true;
mesh.mixer.addEventListener('finished',function(e){
play('Idle',true);
});
}
from.play();
to.play();
from.enabled = true;
to.enabled = true;
from.crossFadeTo( to, 0.3 );
}else{
to.play();
}
mesh.currentAnimation = name;
}
function parseAnimations(){
var o, anim, anims = {};
console.log(mesh);
for( var i=0,len=mesh.geometry.animations.length;i<len;i++){
o = mesh.geometry.animations[i];
if( o ){
anim = mesh.mixer.clipAction(o,mesh);
anim.setEffectiveWeight(1);
anims[o.name] = anim;
}
}
mesh.animations = anims;
}
function animate() {
requestAnimationFrame( animate );
var delta = clock.getDelta();
if( mesh ){
if( mesh.mixer ){
mesh.mixer.update( delta );
}
}
renderer.render( scene, camera );
}
Почему это происходит?
ОБНОВЛЕНИЕ: Я заметил, что это проблема не ограничивается смешением между анимациями. Одна из моих анимаций, только что зацикливающая, теперь имеет задержку!
72: http://jsfiddle.net/titansoftime/8v0pasp5/
78: http://jsfiddle.net/titansoftime/n6apnj3z/
Что происходит!? Было ли какое-то автокорректирующее поведение или что-то в этом роде в 72, которое было удалено?