修复播放完动画,嘴角下垂的问题

This commit is contained in:
yinsx
2025-12-24 15:52:06 +08:00
parent de7c26da35
commit 48d587c1ff
3 changed files with 51 additions and 7 deletions

View File

@ -3,6 +3,7 @@ class BlendShapeAnimator {
constructor(config = {}) {
this.morphTargetAdapter = null;
this.animationFrames = [];
this.animationShapeNames = [];
this.isPlaying = false;
this.currentFrameIndex = 0;
this.animationStartTime = 0;
@ -58,7 +59,8 @@ class BlendShapeAnimator {
// 加载动画帧数据
loadAnimationFrames(frames) {
this.animationFrames = frames;
this.animationFrames = frames || [];
this.animationShapeNames = this._collectAnimationShapeNames(this.animationFrames);
}
// 播放动画
@ -78,7 +80,7 @@ class BlendShapeAnimator {
window.ExpressionLibrary.randomPlayer.stop();
}
this.stopAnimation();
this.stopAnimation(false);
this.isPlaying = true;
this.currentFrameIndex = 0;
this.animationStartTime = performance.now();
@ -88,17 +90,41 @@ class BlendShapeAnimator {
}
// 停止动画
stopAnimation() {
stopAnimation(resumeExpressions = true) {
this.isPlaying = false;
this._resetAnimationInfluences();
// 恢复随机表情
if (this.isExpressionEnabled && window.ExpressionLibrary) {
if (resumeExpressions && this.isExpressionEnabled && window.ExpressionLibrary) {
window.ExpressionLibrary.randomPlayer.start();
}
this.onStatusChange('info', '已停止');
}
_collectAnimationShapeNames(frames) {
const names = new Set();
frames.forEach(frame => {
const blendShapes = frame?.blendShapes;
if (!blendShapes) return;
Object.keys(blendShapes).forEach(name => names.add(name));
});
return Array.from(names);
}
_resetAnimationInfluences() {
if (!this.morphTargetAdapter || this.animationShapeNames.length === 0) {
return;
}
this.animationShapeNames.forEach(name => {
this.morphTargetAdapter.setInfluence(name, 0);
});
}
// 内部动画帧处理
_animateFrame() {
if (!this.isPlaying) return;
@ -116,12 +142,18 @@ class BlendShapeAnimator {
const currentFrame = this.animationFrames[targetFrameIndex];
const nextFrame = this.animationFrames[Math.min(targetFrameIndex + 1, this.animationFrames.length - 1)];
const currentBlendShapes = currentFrame?.blendShapes || {};
const nextBlendShapes = nextFrame?.blendShapes || {};
const frameProgress = exactFrame - targetFrameIndex;
const smoothProgress = this._easeOutQuad(frameProgress);
for (const key in currentFrame.blendShapes) {
const currentValue = currentFrame.blendShapes[key] || 0;
const nextValue = nextFrame.blendShapes[key] || 0;
const shapeNames = this.animationShapeNames.length > 0
? this.animationShapeNames
: Object.keys(currentBlendShapes);
for (const key of shapeNames) {
const currentValue = currentBlendShapes[key] || 0;
const nextValue = nextBlendShapes[key] || 0;
const interpolatedValue = this._lerp(currentValue, nextValue, smoothProgress);
const scaledValue = interpolatedValue * this.blendShapeScale;