feat(handtracking): restyle svg visualizer and add silhouette fallback
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import type {
|
||||
HandTrackingHand,
|
||||
HandTrackingLandmark,
|
||||
} from "@/types/handTracking/handTracking";
|
||||
|
||||
function lerp(previous: number, next: number, factor: number): number {
|
||||
return previous * (1 - factor) + next * factor;
|
||||
}
|
||||
|
||||
function smoothLandmark(
|
||||
previous: HandTrackingLandmark,
|
||||
next: HandTrackingLandmark,
|
||||
factor: number,
|
||||
): HandTrackingLandmark {
|
||||
return {
|
||||
x: lerp(previous.x, next.x, factor),
|
||||
y: lerp(previous.y, next.y, factor),
|
||||
z: lerp(previous.z, next.z, factor),
|
||||
};
|
||||
}
|
||||
|
||||
function smoothHand(
|
||||
previous: HandTrackingHand,
|
||||
next: HandTrackingHand,
|
||||
factor: number,
|
||||
): HandTrackingHand {
|
||||
return {
|
||||
...next,
|
||||
x: lerp(previous.x, next.x, factor),
|
||||
y: lerp(previous.y, next.y, factor),
|
||||
z: lerp(previous.z, next.z, factor),
|
||||
landmarks: next.landmarks.map((landmark, index) => {
|
||||
const previousLandmark = previous.landmarks[index];
|
||||
if (!previousLandmark) return landmark;
|
||||
return smoothLandmark(previousLandmark, landmark, factor);
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply an exponential moving average to the landmark positions of each
|
||||
* detected hand. MediaPipe lands per-frame positions with noticeable
|
||||
* jitter (especially at ~10fps), and feeding those raw values into the
|
||||
* scene makes both the glove rig and any grabbed object tremble.
|
||||
*
|
||||
* `factor` is the weight given to the latest sample (0 = previous frame
|
||||
* only, 1 = no smoothing). Hands are matched between frames by
|
||||
* handedness so left/right don't bleed into each other.
|
||||
*/
|
||||
export function smoothHands(
|
||||
previousHands: HandTrackingHand[],
|
||||
nextHands: HandTrackingHand[],
|
||||
factor: number,
|
||||
): HandTrackingHand[] {
|
||||
if (factor >= 1) return nextHands;
|
||||
|
||||
return nextHands.map((next) => {
|
||||
const previous = previousHands.find(
|
||||
(candidate) => candidate.handedness === next.handedness,
|
||||
);
|
||||
if (!previous) return next;
|
||||
return smoothHand(previous, next, factor);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user