mirror of
https://github.com/open-webui/open-webui.git
synced 2026-10-14 04:08:46 +00:00
fix: VRM 0.x voice avatars rest with their arms down (#32270)
This commit is contained in:
parent
e4cd58f19e
commit
80ae7f620a
1 changed files with 15 additions and 10 deletions
|
|
@ -57,6 +57,7 @@ export async function createAvatarRenderer(
|
|||
const camera = new THREE.PerspectiveCamera(30, 1, 0.01, 100);
|
||||
const bone = (name: Parameters<typeof vrm.humanoid.getNormalizedBoneNode>[0]) =>
|
||||
vrm.humanoid.getNormalizedBoneNode(name);
|
||||
const mirror = vrm.meta.metaVersion === '0' ? -1 : 1;
|
||||
const head = bone('head');
|
||||
const spine = bone('spine');
|
||||
const chest = bone('chest') ?? bone('upperChest');
|
||||
|
|
@ -82,7 +83,6 @@ export async function createAvatarRenderer(
|
|||
];
|
||||
});
|
||||
// Start all built-in states from a relaxed, slightly asymmetric stance.
|
||||
// Normalized VRM bones share T-pose axes across VRM 0 and 1.
|
||||
const restingRotations: Partial<Record<Parameters<typeof bone>[0], [number, number, number]>> = {
|
||||
hips: [0, 0, 0.025],
|
||||
spine: [0.025, 0.015, -0.035],
|
||||
|
|
@ -104,7 +104,11 @@ export async function createAvatarRenderer(
|
|||
rightFoot: [-0.045, -0.035, 0.025]
|
||||
};
|
||||
for (const [name, rotation] of Object.entries(restingRotations))
|
||||
bone(name as Parameters<typeof bone>[0])?.rotation.set(...rotation);
|
||||
bone(name as Parameters<typeof bone>[0])?.rotation.set(
|
||||
rotation[0] * mirror,
|
||||
rotation[1],
|
||||
rotation[2] * mirror
|
||||
);
|
||||
// Resting fingers curl mainly at the first two joints, with a softer index finger.
|
||||
for (const side of ['left', 'right'] as const) {
|
||||
const sign = side === 'left' ? -1 : 1;
|
||||
|
|
@ -116,7 +120,7 @@ export async function createAvatarRenderer(
|
|||
['Distal', 0.04]
|
||||
] as const) {
|
||||
const node = bone(`${side}${finger}${joint}`);
|
||||
if (node) node.rotation.z = sign * amount;
|
||||
if (node) node.rotation.z = sign * amount * mirror;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -326,25 +330,26 @@ export async function createAvatarRenderer(
|
|||
const breath = Math.sin(elapsed * 1.1) * 0.9 + Math.sin(elapsed * 0.47) * 0.1;
|
||||
const sway = amount * (0.01 * Math.sin(elapsed * 0.43) + 0.003 * Math.sin(elapsed * 0.71));
|
||||
if (spine) {
|
||||
spine.rotation.x += amount * (0.006 * breath + 0.015 * listening);
|
||||
spine.rotation.x += mirror * amount * (0.006 * breath + 0.015 * listening);
|
||||
spine.rotation.y += amount * speaking * 0.008 * Math.sin(elapsed * 0.6);
|
||||
spine.rotation.z += sway;
|
||||
spine.rotation.z += mirror * sway;
|
||||
}
|
||||
if (chest) {
|
||||
chest.rotation.x -= amount * 0.008 * breath;
|
||||
chest.rotation.z -= sway * 0.35;
|
||||
chest.rotation.x -= mirror * amount * 0.008 * breath;
|
||||
chest.rotation.z -= mirror * sway * 0.35;
|
||||
}
|
||||
if (head) {
|
||||
head.rotation.x +=
|
||||
mirror *
|
||||
amount *
|
||||
(0.006 * breath + speaking * 0.012 * Math.sin(elapsed * 0.85) + listening * 0.025);
|
||||
head.rotation.y +=
|
||||
amount * (0.012 * Math.sin(elapsed * 0.32) + speaking * 0.008 * Math.sin(elapsed * 0.6));
|
||||
head.rotation.z +=
|
||||
amount * (0.006 * Math.sin(elapsed * 0.27) + listening * 0.025) - sway * 0.5;
|
||||
mirror * (amount * (0.006 * Math.sin(elapsed * 0.27) + listening * 0.025) - sway * 0.5);
|
||||
}
|
||||
if (leftArm) leftArm.rotation.z += amount * 0.004 * breath;
|
||||
if (rightArm) rightArm.rotation.z -= amount * 0.003 * Math.sin(elapsed * 1.1 - 0.2);
|
||||
if (leftArm) leftArm.rotation.z += mirror * amount * 0.004 * breath;
|
||||
if (rightArm) rightArm.rotation.z -= mirror * amount * 0.003 * Math.sin(elapsed * 1.1 - 0.2);
|
||||
if (leftElbow) leftElbow.rotation.y -= amount * 0.006 * Math.sin(elapsed * 1.1 - 0.3);
|
||||
if (rightElbow) rightElbow.rotation.y += amount * 0.004 * Math.sin(elapsed * 1.1 - 0.5);
|
||||
if (current && (bodyWeight > 0 || authored)) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue