Mixamo animation support (#37)

This PR adds support for Mixamo FBX imports (via backend conversion to
glTF/glB) and some miscellaneous improvements to the animation systems.

### User-facing improvements
* Retargeting math has been fixed to eliminate jittering issues
* Retargeter can now handle animated bone translations when present
  (generally this is only used for root motion)

### Housekeeping / Code improvements

* Animation-related components and system logic have been moved to a
  dedicated `anim` module and `AnimPlugin`
* Retargeting stuff has been moved from the `bvh` module to
  `anim::retargeting`
* Component-based solution for marking an entity as an animation
  retargeting source makes it easy to extend the retargeting functionality
  to new types of source animations

### Limitations

Currently the code assumes that there will be at most one animation
source at a time. That single animation (if present) will be retargeted
to all other skeletons in the scene. A component-based solution for
directing a specific target skeleton to use a specific source animation
is possible, but will require some additional consideration around the
implementation design for the read-only "viewer" modes.

### Test animations:

* Hip-Hop Dancing (Mixamo): ?mode=viewer&mixamo=mocap/hip-hop-dancing.gltf
* Shuffle (MocapNET): ?mode=viewer&bvh=mocap/shuffle.bvh
* Scott (MocapNET): ?mode=viewer&bvh=mocap/scott.bvh
* Scott 1 (MocapNET): ?mode=viewer&bvh=mocap/scott1.bvh
This commit is contained in:
Danny McGee
2024-02-09 13:21:16 -05:00
committed by GitHub
parent d1b4aab8ca
commit a5aeff7a3a
13 changed files with 4109 additions and 299 deletions
@@ -0,0 +1,34 @@
import * as studio from "@storyteller/studio";
import { ViewportSize } from "@storyteller/studio";
import { PropertyValues } from "lit";
import { customElement, property } from "lit/decorators.js";
import { StudioBaseElement } from "./studio-base.element";
@customElement("sts-mixamo-viewer")
export class MixamoViewerElement extends StudioBaseElement {
@property() mixamoPath?: string;
@property() skyboxId?: string;
onStart(viewportSize: ViewportSize): void {
if (!this.mixamoPath) return;
if (!this.skyboxId) return;
studio.startMixamoViewer(
this.mixamoPath,
this.skyboxId,
`#${this._canvasProvider!.canvasId}`,
"Storyteller Studio",
viewportSize,
);
}
onChanges(changes: PropertyValues<this>): void {
if (changes.has("mixamoPath") && !!this.mixamoPath) {
// TODO
}
if (changes.has("skyboxId") && !!this.skyboxId)
studio.setSkybox(this.skyboxId);
}
}