修复播放完动画,嘴角下垂的问题
This commit is contained in:
@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user