fix hand tracking glove fallback and loading
This commit is contained in:
Binary file not shown.
@@ -13,19 +13,28 @@ import { useLoggedGLTF } from "@/hooks/three/useLoggedGLTF";
|
|||||||
import type { HandTrackingLandmark } from "@/types/handTracking/handTracking";
|
import type { HandTrackingLandmark } from "@/types/handTracking/handTracking";
|
||||||
import { logModelLoadError } from "@/utils/three/modelLoadLogger";
|
import { logModelLoadError } from "@/utils/three/modelLoadLogger";
|
||||||
|
|
||||||
const GLOVE_MODEL_PATHS: Record<HandTrackingGloveHandedness, string> = {
|
const GLOVE_CONFIGS: Record<
|
||||||
left: "/models/gant_l/model.gltf",
|
HandTrackingGloveHandedness,
|
||||||
right: "/models/gant_r/model.gltf",
|
{
|
||||||
};
|
modelPath: string;
|
||||||
|
rootNodeName: string;
|
||||||
const GLOVE_ROOT_NODE_NAMES: Record<HandTrackingGloveHandedness, string> = {
|
scale: number;
|
||||||
left: "Hand_l",
|
}
|
||||||
right: "Hand_r",
|
> = {
|
||||||
|
left: {
|
||||||
|
modelPath: "/models/gant_l/model.gltf",
|
||||||
|
rootNodeName: "Armature",
|
||||||
|
scale: 0.17,
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
modelPath: "/models/gant_r/model.gltf",
|
||||||
|
rootNodeName: "Hand_r",
|
||||||
|
scale: 0.04,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const HAND_SPACE_DISTANCE = 2.4;
|
const HAND_SPACE_DISTANCE = 2.4;
|
||||||
const HAND_DEPTH_SCALE = 0.45;
|
const HAND_DEPTH_SCALE = 0.45;
|
||||||
const GLOVE_SCALE = 0.17;
|
|
||||||
|
|
||||||
const _cameraPosition = new THREE.Vector3();
|
const _cameraPosition = new THREE.Vector3();
|
||||||
const _direction = new THREE.Vector3();
|
const _direction = new THREE.Vector3();
|
||||||
@@ -73,7 +82,7 @@ class HandTrackingGloveErrorBoundary extends Component<
|
|||||||
{
|
{
|
||||||
modelPath: this.props.modelPath,
|
modelPath: this.props.modelPath,
|
||||||
scope: `HandTrackingGlove.${this.props.handedness}`,
|
scope: `HandTrackingGlove.${this.props.handedness}`,
|
||||||
scale: GLOVE_SCALE,
|
scale: GLOVE_CONFIGS[this.props.handedness].scale,
|
||||||
},
|
},
|
||||||
error,
|
error,
|
||||||
);
|
);
|
||||||
@@ -122,24 +131,21 @@ function HandTrackingGloveModel({
|
|||||||
const setGloveStatus = useHandTrackingGloveStatus(
|
const setGloveStatus = useHandTrackingGloveStatus(
|
||||||
(state) => state.setGloveStatus,
|
(state) => state.setGloveStatus,
|
||||||
);
|
);
|
||||||
const modelPath = GLOVE_MODEL_PATHS[handedness];
|
const config = GLOVE_CONFIGS[handedness];
|
||||||
|
const modelPath = config.modelPath;
|
||||||
const gltf = useLoggedGLTF(modelPath, {
|
const gltf = useLoggedGLTF(modelPath, {
|
||||||
scope: `HandTrackingGlove.${handedness}`,
|
scope: `HandTrackingGlove.${handedness}`,
|
||||||
scale: GLOVE_SCALE,
|
scale: config.scale,
|
||||||
});
|
});
|
||||||
const gloveScene = useMemo(() => {
|
const gloveScene = useMemo(() => {
|
||||||
const rootNode = gltf.scene.getObjectByName(
|
const rootNode = gltf.scene.getObjectByName(config.rootNodeName);
|
||||||
GLOVE_ROOT_NODE_NAMES[handedness],
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!rootNode) {
|
if (!rootNode) {
|
||||||
throw new Error(
|
throw new Error(`Missing glove root node ${config.rootNodeName}`);
|
||||||
`Missing glove root node ${GLOVE_ROOT_NODE_NAMES[handedness]}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return clone(rootNode);
|
return clone(rootNode);
|
||||||
}, [gltf.scene, handedness]);
|
}, [config.rootNodeName, gltf.scene]);
|
||||||
|
|
||||||
const hand = hands.find((candidate) =>
|
const hand = hands.find((candidate) =>
|
||||||
matchesHandedness(candidate.handedness, handedness),
|
matchesHandedness(candidate.handedness, handedness),
|
||||||
@@ -207,7 +213,7 @@ function HandTrackingGloveModel({
|
|||||||
group.quaternion.slerp(_targetQuaternion, Math.min(1, delta * 18));
|
group.quaternion.slerp(_targetQuaternion, Math.min(1, delta * 18));
|
||||||
|
|
||||||
const palmLength = _wristPosition.distanceTo(_middlePosition);
|
const palmLength = _wristPosition.distanceTo(_middlePosition);
|
||||||
const scale = palmLength * GLOVE_SCALE;
|
const scale = palmLength * config.scale;
|
||||||
group.scale.setScalar(scale);
|
group.scale.setScalar(scale);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -219,7 +225,7 @@ function HandTrackingGloveModel({
|
|||||||
export function HandTrackingGlove({
|
export function HandTrackingGlove({
|
||||||
handedness,
|
handedness,
|
||||||
}: HandTrackingGloveProps): React.JSX.Element {
|
}: HandTrackingGloveProps): React.JSX.Element {
|
||||||
const modelPath = GLOVE_MODEL_PATHS[handedness];
|
const modelPath = GLOVE_CONFIGS[handedness].modelPath;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HandTrackingGloveErrorBoundary
|
<HandTrackingGloveErrorBoundary
|
||||||
@@ -231,5 +237,5 @@ export function HandTrackingGlove({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
useGLTF.preload(GLOVE_MODEL_PATHS.left);
|
useGLTF.preload(GLOVE_CONFIGS.left.modelPath);
|
||||||
useGLTF.preload(GLOVE_MODEL_PATHS.right);
|
useGLTF.preload(GLOVE_CONFIGS.right.modelPath);
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ const HAND_CONNECTIONS: Array<[number, number]> = [
|
|||||||
export function HandTrackingVisualizer(): React.JSX.Element | null {
|
export function HandTrackingVisualizer(): React.JSX.Element | null {
|
||||||
const { hands, status } = useHandTrackingSnapshot();
|
const { hands, status } = useHandTrackingSnapshot();
|
||||||
const gloves = useHandTrackingGloveStatus((state) => state.gloves);
|
const gloves = useHandTrackingGloveStatus((state) => state.gloves);
|
||||||
const shouldShowSvgFallback = Object.values(gloves).some(
|
const hasLoadedGlove = Object.values(gloves).some(
|
||||||
(gloveStatus) => gloveStatus === "error" || gloveStatus === "idle",
|
(gloveStatus) => gloveStatus === "loaded",
|
||||||
);
|
);
|
||||||
|
|
||||||
if (status === "idle" || hands.length === 0 || !shouldShowSvgFallback) {
|
if (status === "idle" || hands.length === 0 || hasLoadedGlove) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ export function HandTrackingDebugPanel(): React.JSX.Element | null {
|
|||||||
]
|
]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(", ") || "none";
|
.join(", ") || "none";
|
||||||
const modelFallback = Object.values(gloves).some(
|
const modelFallback = !Object.values(gloves).some(
|
||||||
(gloveStatus) => gloveStatus === "error",
|
(gloveStatus) => gloveStatus === "loaded",
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user