@vincentt-xr/sdk 2.0.0-alpha.8 → 2.0.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/GROUNDING.md +4643 -170
- package/README.md +1 -0
- package/dist/CanonicalHeadFrame-BHcWyaiK.js +1506 -0
- package/dist/CanonicalHeadFrame-D-_T1OMU.cjs +1 -0
- package/dist/DebuggerUI-7ngnJsBe.js +275 -0
- package/dist/DebuggerUI-CoglgKdO.cjs +1 -0
- package/dist/FaceRetouch-CLoTfrcs.js +1071 -0
- package/dist/FaceRetouch-J1lC1WbS.cjs +134 -0
- package/dist/FaceSurface-CHAMEeG1.cjs +1 -0
- package/dist/FaceSurface-DmP9AEeC.js +27 -0
- package/dist/SegmentationOverlay-D_FWkcyP.cjs +35 -0
- package/dist/SegmentationOverlay-vn5x_knv.js +6237 -0
- package/dist/SkeletonUtils-C2r90MtN.js +21 -0
- package/dist/SkeletonUtils-CddIup1F.cjs +1 -0
- package/dist/TextLabel-XE0rQSDn.cjs +2 -0
- package/dist/TextLabel-c9BCucOI.js +961 -0
- package/dist/assets/gltfLoader.d.ts +16 -0
- package/dist/assets/loaders.d.ts +16 -1
- package/dist/body-pose/index.d.ts +521 -0
- package/dist/body-trigger/__fixtures__/syntheticBody.d.ts +83 -0
- package/dist/body-trigger/frame.d.ts +88 -0
- package/dist/body-trigger/index.d.ts +6 -0
- package/dist/body-trigger/moves.d.ts +235 -0
- package/dist/body-trigger/trigger.d.ts +75 -0
- package/dist/calibration/calibration.d.ts +11 -6
- package/dist/canonicalFace-BHwyCx1c.js +9 -0
- package/dist/canonicalFace-C83I225R.cjs +1 -0
- package/dist/components/BodyInstruction/BodyPoseHint.d.ts +63 -0
- package/dist/components/BodyInstruction/index.d.ts +69 -0
- package/dist/components/BodyInstruction/useBodyPose.d.ts +23 -0
- package/dist/components/BodyTracker/index.d.ts +10 -2
- package/dist/components/BodyTrigger/index.d.ts +49 -0
- package/dist/components/Debugger/DebuggerProvider.d.ts +14 -1
- package/dist/components/Debugger/DebuggerUI.d.ts +3 -1
- package/dist/components/FaceAtlas/FaceAtlasLayer.d.ts +114 -0
- package/dist/components/FaceAtlas/MadeUpCamera.d.ts +80 -0
- package/dist/components/FaceAtlas/constants.d.ts +8 -0
- package/dist/components/FaceAtlas/index.d.ts +7 -0
- package/dist/components/FaceAtlas/useFaceAtlasSurface.d.ts +84 -0
- package/dist/components/FaceAtlas/useFaceSkin.d.ts +84 -0
- package/dist/components/FaceCharacter/ExternalFaceMesh.d.ts +109 -0
- package/dist/components/FaceCharacter/FaceExpressionController.d.ts +53 -0
- package/dist/components/FaceCharacter/FaceMorph.d.ts +71 -0
- package/dist/components/FaceCharacter/FacePiercing.d.ts +65 -0
- package/dist/components/FaceCharacter/FaceReprojection.d.ts +85 -0
- package/dist/components/FaceCharacter/FaceRig.d.ts +38 -0
- package/dist/components/FaceCharacter/FaceSurface.d.ts +49 -0
- package/dist/components/FaceCharacter/FaceSurfaceOccluder.d.ts +39 -0
- package/dist/components/FaceCharacter/PinToFaceMesh.d.ts +68 -0
- package/dist/components/FaceCharacter/index.d.ts +18 -0
- package/dist/components/FaceCharacter/useFaceReprojector.d.ts +10 -0
- package/dist/components/FaceInset/FaceInset.d.ts +68 -0
- package/dist/components/FaceInset/frame.d.ts +94 -0
- package/dist/components/FaceInset/index.d.ts +6 -0
- package/dist/components/FaceInset/material.d.ts +40 -0
- package/dist/components/FaceInset/useFaceInsetTexture.d.ts +37 -0
- package/dist/components/FaceInstruction/FaceExpressionHint.d.ts +43 -0
- package/dist/components/FaceInstruction/index.d.ts +56 -0
- package/dist/components/FaceInstruction/useFaceExpression.d.ts +20 -0
- package/dist/components/FaceLiquify/FaceLiquify.d.ts +49 -0
- package/dist/components/FaceLiquify/debug.d.ts +37 -0
- package/dist/components/FaceLiquify/frame.d.ts +55 -0
- package/dist/components/FaceLiquify/index.d.ts +10 -0
- package/dist/components/FaceLiquify/material.d.ts +39 -0
- package/dist/components/FaceLiquify/pass.d.ts +49 -0
- package/dist/components/FaceLiquify/presence.d.ts +25 -0
- package/dist/components/FaceLiquify/presets.d.ts +82 -0
- package/dist/components/FaceLiquify/selfTest.d.ts +66 -0
- package/dist/components/FaceLiquify/target.d.ts +85 -0
- package/dist/components/FaceLiquify/warp.d.ts +72 -0
- package/dist/components/FaceMesh/canonical/CanonicalFaceMeshRenderer.d.ts +5 -3
- package/dist/components/FaceMesh/canonical/geometryGroups.d.ts +21 -0
- package/dist/components/FaceMesh/canonical/parseCanonicalFaceModel.d.ts +9 -0
- package/dist/components/FaceMesh/index.d.ts +1 -1
- package/dist/components/FaceRetouch/Background.d.ts +3 -1
- package/dist/components/FaceRetouch/FaceRetouch.d.ts +5 -0
- package/dist/components/FaceRetouch/renderState.d.ts +19 -0
- package/dist/components/FaceSwap/FaceMirror.d.ts +46 -0
- package/dist/components/FaceSwap/FaceSwap.d.ts +58 -0
- package/dist/components/FaceSwap/FaceTextureLayer.d.ts +72 -0
- package/dist/components/FaceSwap/faceSwapPlan.d.ts +91 -0
- package/dist/components/FaceSwap/index.d.ts +13 -0
- package/dist/components/FaceSwap/settings.d.ts +300 -0
- package/dist/components/FaceSwap/useFaceTexture.d.ts +35 -0
- package/dist/components/FaceSwap/useLiveFace.d.ts +38 -0
- package/dist/components/FaceSwap/useLiveFaceTexture.d.ts +31 -0
- package/dist/components/FaceWarp3D/FaceWarp3D.d.ts +50 -0
- package/dist/components/FaceWarp3D/index.d.ts +2 -3
- package/dist/components/Faceless/Faceless.d.ts +51 -0
- package/dist/components/Faceless/index.d.ts +2 -0
- package/dist/components/HairLock/HairLock.d.ts +39 -0
- package/dist/components/HairLock/index.d.ts +2 -0
- package/dist/components/HairLock/lockGeometry.d.ts +15 -0
- package/dist/components/HandCutout/index.d.ts +35 -0
- package/dist/components/HandInstruction/HandGestureHint.d.ts +70 -0
- package/dist/components/HandInstruction/index.d.ts +74 -0
- package/dist/components/HandInstruction/useHandGesture.d.ts +22 -0
- package/dist/components/HandRig/ForearmOccluder.d.ts +29 -0
- package/dist/components/HandRig/HandAttachment.d.ts +34 -0
- package/dist/components/HandRig/HandOccluder.d.ts +55 -0
- package/dist/components/HandRig/HandTattoo.d.ts +61 -0
- package/dist/components/HandRig/WristAttachment.d.ts +34 -0
- package/dist/components/HandRig/index.d.ts +101 -0
- package/dist/components/HandRig/useArmMask.d.ts +29 -0
- package/dist/components/HandRig/wristSolve.d.ts +69 -0
- package/dist/components/HandTouch/HandTouch.d.ts +62 -0
- package/dist/components/HandTouch/Touchable.d.ts +36 -0
- package/dist/components/HandTouch/index.d.ts +2 -0
- package/dist/components/HeadBinding/index.d.ts +14 -0
- package/dist/components/HeadOccluder/CanonicalHeadFrame.d.ts +22 -0
- package/dist/components/HeadOccluder/Earrings.d.ts +55 -0
- package/dist/components/HeadOccluder/HeadAttachment.d.ts +38 -0
- package/dist/components/HeadOccluder/NeckOccluder.d.ts +64 -0
- package/dist/components/HeadOccluder/earringPlacement.d.ts +31 -0
- package/dist/components/HeadOccluder/headAttachmentPoints.d.ts +69 -0
- package/dist/components/HeadOccluder/index.d.ts +57 -3
- package/dist/components/HeadOccluder/useCanonicalHeadFit.d.ts +36 -0
- package/dist/components/HeadOccluder/useLandmarkPoseFit.d.ts +80 -0
- package/dist/components/Instruction/HintStage.d.ts +29 -0
- package/dist/components/Instruction/InstructionCue.d.ts +126 -0
- package/dist/components/Instruction/gestureHold.d.ts +20 -0
- package/dist/components/Instruction/ghost.d.ts +129 -0
- package/dist/components/Instruction/hintBlend.d.ts +19 -0
- package/dist/components/Instruction/hintLook.d.ts +81 -0
- package/dist/components/Instruction/hintLoop.d.ts +36 -0
- package/dist/components/Instruction/index.d.ts +41 -0
- package/dist/components/Instruction/useGhostModel.d.ts +33 -0
- package/dist/components/Instruction/useInstructionHold.d.ts +72 -0
- package/dist/components/LipEffect/LipEffect.d.ts +22 -2
- package/dist/components/LipEffect/LipEffectMaterial.d.ts +62 -10
- package/dist/components/LipEffect/LipEffects.d.ts +5 -2
- package/dist/components/LipEffect/defaults.d.ts +21 -2
- package/dist/components/LipEffect/index.d.ts +1 -1
- package/dist/components/LipEffect/lipShading.d.ts +73 -0
- package/dist/components/LipEffect/settings.d.ts +117 -13
- package/dist/components/LipEffect/shader.d.ts +39 -0
- package/dist/components/LipEffect/types.d.ts +82 -10
- package/dist/components/LipEffect/useLipDesignTextures.d.ts +6 -0
- package/dist/components/LipEffect/uvGuide.d.ts +31 -16
- package/dist/components/Makeup/Blush.d.ts +18 -0
- package/dist/components/Makeup/Brows.d.ts +20 -0
- package/dist/components/Makeup/Contour.d.ts +17 -0
- package/dist/components/Makeup/Eyeliner.d.ts +20 -0
- package/dist/components/Makeup/Eyeshadow.d.ts +20 -0
- package/dist/components/Makeup/Highlighter.d.ts +18 -0
- package/dist/components/Makeup/MakeupDesign.d.ts +37 -0
- package/dist/components/Makeup/MakeupRegion.d.ts +132 -0
- package/dist/components/Makeup/constants.d.ts +44 -0
- package/dist/components/Makeup/design.d.ts +106 -0
- package/dist/components/Makeup/designSamples.d.ts +42 -0
- package/dist/components/Makeup/eyes.d.ts +114 -0
- package/dist/components/Makeup/fields.d.ts +10 -0
- package/dist/components/Makeup/geometry.d.ts +106 -0
- package/dist/components/Makeup/index.d.ts +26 -0
- package/dist/components/Makeup/looks.d.ts +28 -0
- package/dist/components/Makeup/material.d.ts +239 -0
- package/dist/components/Makeup/settings.d.ts +54 -0
- package/dist/components/Makeup/shades.d.ts +143 -0
- package/dist/components/Makeup/shapes.d.ts +27 -0
- package/dist/components/Makeup/skinTone.d.ts +135 -0
- package/dist/components/Makeup/types.d.ts +110 -0
- package/dist/components/Makeup/useMakeupSkinTone.d.ts +40 -0
- package/dist/components/Necklace/Necklace.d.ts +44 -0
- package/dist/components/Necklace/index.d.ts +1 -0
- package/dist/components/ParticleEmitter/ParticleEmitter.d.ts +69 -0
- package/dist/components/ParticleEmitter/index.d.ts +1 -0
- package/dist/components/ShoulderOccluder/index.d.ts +43 -0
- package/dist/components/ShoulderOccluder/useCanonicalTorsoFit.d.ts +24 -0
- package/dist/components/SpringSwing/SpringSwing.d.ts +22 -0
- package/dist/components/SpringSwing/index.d.ts +1 -0
- package/dist/components/XRScene/renderOutputTarget.d.ts +12 -0
- package/dist/components/index.d.ts +8 -0
- package/dist/config/index.d.ts +0 -1
- package/dist/context-DTxSQvp4.js +13 -0
- package/dist/context-hA0Rb2Xa.cjs +1 -0
- package/dist/contexts-BH7PdKFS.cjs +1 -0
- package/dist/contexts-jak8-tND.js +667 -0
- package/dist/coordinates/index.d.ts +2 -0
- package/dist/coordinates/side.d.ts +40 -0
- package/dist/debug-ui/default-setting.cjs +2 -2
- package/dist/debug-ui/face-swap-settings/index.d.ts +22 -0
- package/dist/debug-ui/hierarchy-panel/index.d.ts +3 -2
- package/dist/debug-ui/index.d.ts +4 -3
- package/dist/debug-ui/media-source/index.d.ts +1 -1
- package/dist/debug-ui/media-source/session.d.ts +30 -2
- package/dist/debug-ui/media-source.cjs +1 -1
- package/dist/debug-ui/media-source.js +1 -1
- package/dist/debug-ui/object-inspector-panel/index.d.ts +3 -2
- package/dist/debug-ui/product-hotspots/index.d.ts +3 -2
- package/dist/debug-ui/scene-editor/hierarchy-panel.d.ts +3 -1
- package/dist/debug-ui/scene-editor/inspector-panel.d.ts +3 -1
- package/dist/debug-ui/screen-image-settings/index.d.ts +3 -1
- package/dist/debug-ui/screen-text-settings/ScreenTextSettingsPanel.d.ts +1 -1
- package/dist/debug-ui/screen-text-settings/types.d.ts +2 -0
- package/dist/debug-ui/settings-panel/index.d.ts +6 -1
- package/dist/debug-ui/shared/debugWindow.d.ts +51 -0
- package/dist/debug-ui/xr-diagnostics/index.d.ts +3 -2
- package/dist/debug-ui.cjs +3 -3
- package/dist/debug-ui.js +2250 -2472
- package/dist/entries/all.d.ts +3 -1
- package/dist/entries/core.d.ts +3 -2
- package/dist/entries/face-effects.d.ts +114 -8
- package/dist/entries/instructions.d.ts +48 -0
- package/dist/entries/internal.d.ts +2 -1
- package/dist/entries/low-level.d.ts +28 -1
- package/dist/entries/particles.d.ts +11 -0
- package/dist/entries/tracking.d.ts +37 -2
- package/dist/face-atlas/attributes.d.ts +30 -0
- package/dist/face-atlas/eyes.d.ts +272 -0
- package/dist/face-atlas/faceAtlas.generated.d.ts +46 -0
- package/dist/face-atlas/glsl/atlasVertex.d.ts +46 -0
- package/dist/face-atlas/glsl/common.d.ts +55 -0
- package/dist/face-atlas/glsl/design.d.ts +49 -0
- package/dist/face-atlas/glsl/eyes.d.ts +73 -0
- package/dist/face-atlas/glsl/finish.d.ts +24 -0
- package/dist/face-atlas/glsl/format.d.ts +4 -0
- package/dist/face-atlas/glsl/index.d.ts +59 -0
- package/dist/face-atlas/glsl/shading.d.ts +15 -0
- package/dist/face-atlas/glsl/shapes.d.ts +66 -0
- package/dist/face-atlas/glsl/sparkle.d.ts +19 -0
- package/dist/face-atlas/glsl/uniforms.d.ts +106 -0
- package/dist/face-atlas/guide.d.ts +51 -0
- package/dist/face-atlas/index.d.ts +25 -0
- package/dist/face-atlas/lead.d.ts +117 -0
- package/dist/face-atlas/madeUpCamera.d.ts +125 -0
- package/dist/face-atlas/masks.d.ts +53 -0
- package/dist/face-atlas/obj.d.ts +69 -0
- package/dist/face-atlas/polylines.d.ts +63 -0
- package/dist/face-atlas/probe/FaceSkinProbe.d.ts +208 -0
- package/dist/face-atlas/probe/__fixtures__/emulate.d.ts +9 -0
- package/dist/face-atlas/probe/__fixtures__/face.d.ts +24 -0
- package/dist/face-atlas/probe/constants.d.ts +137 -0
- package/dist/face-atlas/probe/glsl.d.ts +43 -0
- package/dist/face-atlas/probe/lightFit.d.ts +108 -0
- package/dist/face-atlas/probe/schedule.d.ts +44 -0
- package/dist/face-atlas/probe/selfTest.d.ts +87 -0
- package/dist/face-atlas/probe/stats.d.ts +143 -0
- package/dist/face-atlas/probe/targets.d.ts +70 -0
- package/dist/face-atlas/probe/unwrap.d.ts +76 -0
- package/dist/face-atlas/quality.d.ts +28 -0
- package/dist/face-atlas/regions.d.ts +31 -0
- package/dist/face-atlas/registry.d.ts +252 -0
- package/dist/face-atlas/renderState.d.ts +86 -0
- package/dist/face-atlas/selfOcclusion.d.ts +62 -0
- package/dist/face-atlas/shading.d.ts +406 -0
- package/dist/face-atlas/shapes.d.ts +86 -0
- package/dist/face-atlas/sides.d.ts +41 -0
- package/dist/face-atlas/skinMask.d.ts +35 -0
- package/dist/face-atlas/surface.d.ts +155 -0
- package/dist/face-atlas/topology.d.ts +44 -0
- package/dist/face-character/__fixtures__/faceImageDetections.d.ts +25 -0
- package/dist/face-character/__fixtures__/faceNode.d.ts +22 -0
- package/dist/face-character/bindFaceModel.d.ts +106 -0
- package/dist/face-character/canonicalFace.d.ts +17 -0
- package/dist/face-character/canonicalFaceGeometry.d.ts +11 -0
- package/dist/face-character/canonicalFacePositions.d.ts +7 -0
- package/dist/face-character/driveFaceModel.d.ts +57 -0
- package/dist/face-character/expressionOutputs.d.ts +45 -0
- package/dist/face-character/faceExpressions.d.ts +104 -0
- package/dist/face-character/faceImageLandmarker.d.ts +93 -0
- package/dist/face-character/faceMeshBinding.d.ts +62 -0
- package/dist/face-character/faceMorph.d.ts +77 -0
- package/dist/face-character/faceMorphs.d.ts +46 -0
- package/dist/face-character/facePhoto.d.ts +138 -0
- package/dist/face-character/facePiercings.d.ts +116 -0
- package/dist/face-character/facePin.d.ts +131 -0
- package/dist/face-character/faceReprojection.d.ts +273 -0
- package/dist/face-character/faceReprojector.d.ts +171 -0
- package/dist/face-character/faceRig.d.ts +176 -0
- package/dist/face-character/faceSwapPresence.d.ts +85 -0
- package/dist/face-character/faceTexture.d.ts +169 -0
- package/dist/face-character/faceTextureBaker.d.ts +86 -0
- package/dist/face-character/faceTextureGuide.d.ts +106 -0
- package/dist/face-character/faceTextureStats.d.ts +298 -0
- package/dist/face-character/faceTransfer.d.ts +396 -0
- package/dist/face-character/faceTransferGeometry.d.ts +109 -0
- package/dist/face-character/faceTransferSelfTest.d.ts +94 -0
- package/dist/face-character/faceWarp3D.d.ts +101 -0
- package/dist/face-character/faceless.d.ts +79 -0
- package/dist/face-character/featureWarp.d.ts +28 -0
- package/dist/face-character/liveFaceRegistry.d.ts +370 -0
- package/dist/face-character/liveValue.d.ts +12 -0
- package/dist/face-character/memo.d.ts +15 -0
- package/dist/face-effects.cjs +2252 -83
- package/dist/face-effects.js +14234 -1231
- package/dist/face-expression/index.d.ts +182 -0
- package/dist/face-info/landmarks.d.ts +17 -3
- package/dist/face-info/types.d.ts +20 -3
- package/dist/gestures/definitions.d.ts +15 -2
- package/dist/gestures/index.d.ts +1 -1
- package/dist/gestures/measures.d.ts +21 -8
- package/dist/getFaceInfo-B1otSDMX.cjs +1 -0
- package/dist/getFaceInfo-Cu4xDWiL.js +62 -0
- package/dist/hand/armFit.d.ts +46 -0
- package/dist/hand/armMask.d.ts +178 -0
- package/dist/hand/handCutout.d.ts +23 -0
- package/dist/hand/handCutoutRegistry.d.ts +7 -0
- package/dist/hand/handGestures.d.ts +524 -0
- package/dist/hand/handPose.d.ts +98 -0
- package/dist/hand/handRigSolver.d.ts +159 -0
- package/dist/hand/handTattoo.d.ts +81 -0
- package/dist/hand/handTouch.d.ts +240 -0
- package/dist/hand/wrist.d.ts +44 -0
- package/dist/hand/wristFilter.d.ts +44 -0
- package/dist/hooks/selectors.d.ts +8 -0
- package/dist/hooks/useFaceModelAcquisition.d.ts +38 -0
- package/dist/hooks/useTrackerContext.d.ts +6 -0
- package/dist/index-B1_TzJaI.js +1104 -0
- package/dist/index-BavF06C6.js +190 -0
- package/dist/index-BfFmpddl.cjs +21 -0
- package/dist/index-BuBzneeW.cjs +46 -0
- package/dist/index-CGsQWodV.cjs +1 -0
- package/dist/index-CIe7eCMH.js +3200 -0
- package/dist/index-CfSF8LXa.cjs +1 -0
- package/dist/index-D5GTzOzD.cjs +1 -0
- package/dist/index-DBhQzvVa.js +314 -0
- package/dist/index-DE17y0ZI.cjs +1 -0
- package/dist/index-JII7huPk.js +442 -0
- package/dist/index-tpCr9CLj.cjs +1 -0
- package/dist/{renderPasses-NnKZVfBy.js → index-w1S7fI2B.js} +219 -247
- package/dist/index-zGaqrz_K.js +188 -0
- package/dist/instructions.cjs +30 -0
- package/dist/instructions.js +1507 -0
- package/dist/{internal-vsfNQycj.js → internal-B90P-clC.js} +138 -118
- package/dist/internal-Cjinca64.cjs +1 -0
- package/dist/internal.cjs +1 -1
- package/dist/internal.js +15 -10
- package/dist/iris/compute.d.ts +7 -5
- package/dist/iris/types.d.ts +6 -4
- package/dist/{landmarkMask-CbTFzBYG.js → landmarkMask-BFDyBnKM.js} +6 -6
- package/dist/landmarks-BlUqf5MZ.cjs +1 -0
- package/dist/landmarks-bftdwq6Z.js +76 -0
- package/dist/loaders-BGAUACsd.js +363 -0
- package/dist/loaders-BJ1_QCHt.cjs +1 -0
- package/dist/low-level.cjs +1 -1
- package/dist/low-level.js +666 -602
- package/dist/main.cjs +1 -1
- package/dist/main.js +866 -1182
- package/dist/models/Body/index.d.ts +2 -0
- package/dist/models/Face/constants.d.ts +8 -0
- package/dist/models/Face/index.d.ts +3 -11
- package/dist/models/Face/rotation.d.ts +18 -3
- package/dist/models/Hand/HandTracking.d.ts +17 -1
- package/dist/models/Segmentation/index.d.ts +2 -0
- package/dist/models/nodeSource.d.ts +9 -0
- package/dist/particles/emission.d.ts +24 -0
- package/dist/particles/eyes.d.ts +24 -0
- package/dist/particles/glsl.d.ts +14 -0
- package/dist/particles/index.d.ts +10 -0
- package/dist/particles/motion.d.ts +42 -0
- package/dist/particles/presets.d.ts +12 -0
- package/dist/particles/ring.d.ts +58 -0
- package/dist/particles/selfTest.d.ts +53 -0
- package/dist/particles/settings.d.ts +127 -0
- package/dist/particles/shapes.d.ts +29 -0
- package/dist/particles/spawner.d.ts +60 -0
- package/dist/particles/system.d.ts +64 -0
- package/dist/particles.cjs +122 -0
- package/dist/particles.js +774 -0
- package/dist/product.cjs +1 -1
- package/dist/product.js +29 -29
- package/dist/{providers-C0Dlhh9Z.js → providers-C8rE26Uf.js} +127 -126
- package/dist/providers-DHsrhDI2.cjs +62 -0
- package/dist/render/renderPasses.d.ts +8 -0
- package/dist/render/sceneBeforeRender.d.ts +12 -0
- package/dist/{renderGroups-CN1cGFUo.js → renderGroups-B38pUaX2.js} +1 -1
- package/dist/{renderGroups-O4KmaMl9.cjs → renderGroups-Cb_4Ar1Q.cjs} +1 -1
- package/dist/renderPasses-B6l8IpJv.js +1290 -0
- package/dist/renderPasses-dqmkft4P.cjs +158 -0
- package/dist/renderState-CJNmj5jz.js +39 -0
- package/dist/renderState-apSfg4eR.cjs +1 -0
- package/dist/scene-object.cjs +1 -1
- package/dist/scene-object.js +2 -2
- package/dist/segmentation-Cb3ouK6Z.js +1758 -0
- package/dist/segmentation-D9pYO6aR.cjs +1 -0
- package/dist/segmentation2d/types.d.ts +6 -0
- package/dist/select-Ck5LGz-J.cjs +1 -0
- package/dist/select-pYRo_win.js +233 -0
- package/dist/selectors-C4X71aoD.cjs +1 -0
- package/dist/selectors-DmNaKIwE.js +196 -0
- package/dist/session-BrH8G7iJ.cjs +31 -0
- package/dist/session-DgA_z6O1.js +418 -0
- package/dist/{settings-aQk845NJ.js → settings-BJ7FMBsO.js} +53 -15
- package/dist/settings-C63FMBlF.cjs +1 -0
- package/dist/similarityFit-BFqHND2e.cjs +1 -0
- package/dist/similarityFit-Bbz-R8AY.js +91 -0
- package/dist/spring/index.d.ts +2 -0
- package/dist/spring/spring.d.ts +69 -0
- package/dist/spring/swing.d.ts +54 -0
- package/dist/tracking.cjs +10 -1
- package/dist/tracking.js +1002 -855
- package/dist/trigger-D0Pm9noT.cjs +49 -0
- package/dist/trigger-IQeys0oS.js +2128 -0
- package/dist/types/face.d.ts +20 -1
- package/dist/types/hand-tracking.d.ts +9 -0
- package/dist/types/nodes.d.ts +20 -1
- package/dist/types/segmentation.d.ts +5 -0
- package/dist/updateThrottle-BseecYag.js +4 -0
- package/dist/updateThrottle-Of5Y4SVa.cjs +1 -0
- package/dist/useFaceInfo-BHDNCvsJ.cjs +1 -0
- package/dist/useFaceInfo-J4x7LsqL.js +76 -0
- package/dist/useFaceResultReader-BvEo5REG.js +61 -0
- package/dist/useFaceResultReader-DuaL1KJG.cjs +1 -0
- package/dist/useInstructionHold-DOu-RpCM.js +53 -0
- package/dist/useInstructionHold-DwJY1Alr.cjs +1 -0
- package/dist/useLandmarkPoseFit-Bg-h9BPb.cjs +1 -0
- package/dist/useLandmarkPoseFit-Bmb3h6Mw.js +87 -0
- package/dist/{useXRCapabilities-B1R2ghy-.cjs → useXRCapabilities-Cr3RzuAW.cjs} +1 -1
- package/dist/{useXRCapabilities-C68v__wB.js → useXRCapabilities-Cxmlmpbd.js} +1 -1
- package/dist/utils/canonicalRigidLandmarks.d.ts +8 -0
- package/dist/utils/headOccluderFit.d.ts +42 -0
- package/dist/utils/integrity.d.ts +17 -0
- package/dist/utils/resolveNumFaces.d.ts +13 -0
- package/dist/utils/shoulderOccluderFit.d.ts +38 -0
- package/dist/utils/similarityFit.d.ts +23 -0
- package/dist/uv-BMFt19bg.cjs +1 -0
- package/dist/{index-CsUdQ-pn.js → uv-DJU_XfmN.js} +15 -249
- package/docs/SDK_DOCUMENTATION.md +1 -2
- package/docs/api/adaptive-quality.mdx +1 -1
- package/docs/api/body-instructions.mdx +285 -0
- package/docs/api/body-triggers.mdx +234 -0
- package/docs/api/camera-permission.mdx +1 -1
- package/docs/api/coordinate-spaces.mdx +7 -4
- package/docs/api/cross-camera.mdx +3 -2
- package/docs/api/debug-ui-scene-editor.mdx +23 -2
- package/docs/api/external-face-mesh.mdx +231 -0
- package/docs/api/face-actions.mdx +20 -16
- package/docs/api/face-attribute-expression.mdx +1 -1
- package/docs/api/face-binding-anchors.mdx +4 -2
- package/docs/api/face-character.mdx +157 -0
- package/docs/api/face-effects.mdx +3 -0
- package/docs/api/face-expression-controller.mdx +153 -0
- package/docs/api/face-info.mdx +17 -11
- package/docs/api/face-inset.mdx +204 -0
- package/docs/api/face-instructions.mdx +183 -0
- package/docs/api/face-liquify.mdx +196 -0
- package/docs/api/face-mesh.mdx +4 -7
- package/docs/api/face-morph.mdx +117 -0
- package/docs/api/face-painting.mdx +7 -0
- package/docs/api/face-reprojection.mdx +154 -0
- package/docs/api/face-retouching.mdx +18 -10
- package/docs/api/face-swap.mdx +350 -0
- package/docs/api/face-warp-3d.mdx +166 -0
- package/docs/api/faceless.mdx +143 -0
- package/docs/api/gestures.mdx +68 -32
- package/docs/api/hair.mdx +97 -0
- package/docs/api/hand-instructions.mdx +222 -0
- package/docs/api/hand-rig.mdx +535 -0
- package/docs/api/hand-touch.mdx +162 -0
- package/docs/api/head-occluder.mdx +563 -0
- package/docs/api/holistic-tracker.mdx +6 -1
- package/docs/api/instructions.mdx +323 -0
- package/docs/api/iris-tracking.mdx +24 -19
- package/docs/api/made-up-camera.mdx +131 -0
- package/docs/api/makeup-skin-tone.mdx +135 -0
- package/docs/api/makeup.mdx +353 -0
- package/docs/api/multi-subject.mdx +4 -1
- package/docs/api/particles.mdx +155 -0
- package/docs/api/person-cutout.mdx +1 -1
- package/docs/api/pin-to-face-mesh.mdx +274 -0
- package/docs/api/product-ar.mdx +5 -2
- package/docs/api/segmentation-overlay.mdx +1 -1
- package/docs/docs.json +29 -1
- package/docs/examples/lip-shaders.mdx +82 -33
- package/docs/guides/face-atlas-template.svg +1 -0
- package/docs/guides/face-atlas-textures.mdx +186 -0
- package/docs/guides/face-texture-template.svg +1 -0
- package/docs/guides/harness-debug-ui.mdx +4 -4
- package/docs/guides/lip-effect-textures.mdx +178 -102
- package/docs/guides/lip-uv-template.png +0 -0
- package/docs/guides/lip-uv-template.svg +1 -1
- package/docs/guides/makeup-design-textures.mdx +109 -0
- package/docs/introduction.mdx +1 -2
- package/package.json +11 -1
- package/dist/DebuggerUI-C-ldiozL.js +0 -269
- package/dist/DebuggerUI-CWX5EtQv.cjs +0 -1
- package/dist/FaceMeshRenderer-BEEXZwS6.cjs +0 -158
- package/dist/FaceMeshRenderer-UuH5sTXG.js +0 -1322
- package/dist/FaceRetouch-C7h7x9kd.js +0 -683
- package/dist/FaceRetouch-DqftT26Y.cjs +0 -134
- package/dist/GLTFLoader-C5q63sKO.js +0 -1633
- package/dist/GLTFLoader-Cb_CRwmG.cjs +0 -1
- package/dist/SegmentationOverlay-DQuW3dsc.js +0 -133
- package/dist/SegmentationOverlay-aWVod8Kl.cjs +0 -1
- package/dist/components/FaceWarp3D/FaceWarp3DHead.d.ts +0 -15
- package/dist/components/FaceWarp3D/defaults.d.ts +0 -37
- package/dist/components/FaceWarp3D/warp.d.ts +0 -13
- package/dist/contexts-CO0sd4JQ.cjs +0 -1
- package/dist/contexts-FzlnnMYD.js +0 -669
- package/dist/debug-ui/face-warp-3d/index.d.ts +0 -6
- package/dist/getFaceInfo-BkZfaQs-.js +0 -118
- package/dist/getFaceInfo-ahPxQFGu.cjs +0 -1
- package/dist/index--RgGzZ6X.cjs +0 -47
- package/dist/index-CHVbH0hz.js +0 -214
- package/dist/index-CeVkgsag.cjs +0 -1
- package/dist/index-CnGox6Xr.js +0 -3054
- package/dist/index-DKBAh6hV.cjs +0 -1
- package/dist/index-DsZwTfG0.cjs +0 -1
- package/dist/index-Dw6tj2Mi.js +0 -144
- package/dist/index-OCPjOaeP.cjs +0 -1
- package/dist/index-s9pF4zkG.js +0 -2053
- package/dist/internal-BYza1h8_.cjs +0 -1
- package/dist/measures-9dQPdw96.js +0 -154
- package/dist/measures-KfJzpvod.cjs +0 -1
- package/dist/providers-YNwkmNeK.cjs +0 -62
- package/dist/renderPasses-Cg-zqmEz.cjs +0 -21
- package/dist/screenTransform-BenfCtZt.js +0 -44
- package/dist/screenTransform-BiXdpVf0.cjs +0 -1
- package/dist/segmentation-9PhSvc-R.cjs +0 -1
- package/dist/segmentation-CeOTKemr.js +0 -5
- package/dist/selectors-C5G1PMYL.js +0 -195
- package/dist/selectors-Du_PsVnW.cjs +0 -1
- package/dist/session-BBr0yN8h.cjs +0 -31
- package/dist/session-Cy0m7l7-.js +0 -363
- package/dist/settings-DRR7-snV.cjs +0 -1
- package/dist/useFaceInfo-Blf7FCu3.js +0 -303
- package/dist/useFaceInfo-C5mO8NQY.cjs +0 -1
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Hand Rig"
|
|
3
|
+
description: "Both tracked hands as world-space poses, a driver that animates a skinned 3D hand model (or a glove) from them, hand occlusion for rings, and hand tattoos."
|
|
4
|
+
sidebarTitle: "Hand Rig"
|
|
5
|
+
icon: "hand"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
The hand tracker detects up to two hands. `HandRig` drives a skinned 3D hand model from either of
|
|
9
|
+
them: the model's palm is fitted to the tracked palm (position, rotation, size) and every finger bone
|
|
10
|
+
swings toward its tracked joint. Underneath, the hand model publishes both hands as **world-space
|
|
11
|
+
poses** with a stable left / right identity.
|
|
12
|
+
|
|
13
|
+
Import from `@vincentt-xr/sdk/tracking`.
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { useLoader } from "@react-three/fiber";
|
|
19
|
+
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
20
|
+
import { HandRig } from "@vincentt-xr/sdk/tracking";
|
|
21
|
+
|
|
22
|
+
const Hands = () => {
|
|
23
|
+
const gltf = useLoader(GLTFLoader, handUrl); // a model following the rig contract
|
|
24
|
+
return (
|
|
25
|
+
<>
|
|
26
|
+
<HandRig hand="left" model={gltf.scene} />
|
|
27
|
+
<HandRig hand="right" model={gltf.scene} />
|
|
28
|
+
</>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Mount `HandRig` anywhere in the scene, not inside a tracker. It acquires the shared hand model
|
|
34
|
+
itself. One loaded model can drive both hands: each rig clones it, skeleton included. Example:
|
|
35
|
+
`/hand-rig`.
|
|
36
|
+
|
|
37
|
+
## Hand poses (`HandPose`)
|
|
38
|
+
|
|
39
|
+
`node.poses` / `node.getHandPose(hand)` on the hand model node
|
|
40
|
+
(`useXRModelNode(XRModel.HAND_TRACKER)`, `/low-level`) give each hand by its **anatomical** side:
|
|
41
|
+
|
|
42
|
+
| field | meaning |
|
|
43
|
+
| ------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
44
|
+
| `handedness` | the person's own hand, on every source (mirrored webcam or not) |
|
|
45
|
+
| `score` | MediaPipe's handedness confidence, 0..1 |
|
|
46
|
+
| `world` | 21 joints, **centimetres**, origin at the hand centre, three.js axes: +X screen right, +Y up, +Z toward the viewer |
|
|
47
|
+
| `image` | the same 21 joints in tracker space (centre origin, ±1, Y up) — what `HandTracker` publishes as `coordinates` |
|
|
48
|
+
| `timestampMs` | `performance.now()` of the detection |
|
|
49
|
+
| `held` | `true` while a lost hand is being held (see below) |
|
|
50
|
+
|
|
51
|
+
Joint order and names: `HAND_JOINT_NAMES` (`wrist`, `thumbCmc`, `thumbMcp`, `thumbIp`, `thumbTip`,
|
|
52
|
+
`indexMcp` … `pinkyTip`) = MediaPipe landmark order; `HAND_JOINT_INDEX[name]` is the index.
|
|
53
|
+
`world` is the true 3D shape of the hand (finger bend, which way the palm faces), independent of its
|
|
54
|
+
distance. `image` is where it is on screen. `handPoseToScene(pose, camera)` (`/tracking`) combines the two into scene
|
|
55
|
+
positions: the world shape, scaled and turned in the image plane onto the tracked image points (weak
|
|
56
|
+
perspective; the hand's centre sits on the `z = 0` tracking plane).
|
|
57
|
+
|
|
58
|
+
`node.hands[i]` also carries `worldCoordinates` and `handednessScore` per raw detection.
|
|
59
|
+
|
|
60
|
+
### Handedness is anatomical
|
|
61
|
+
|
|
62
|
+
MediaPipe labels a hand as it appears in the frame it is given. The SDK analyzes the feed as
|
|
63
|
+
displayed, which is mirrored for the front webcam, so its raw labels were swapped there. The SDK now
|
|
64
|
+
corrects them (`anatomicalHandedness`). `HandTracker hand="left"`, `node.handedness` and the poses all
|
|
65
|
+
mean the person's left hand on the webcam, the rear camera, images and video.
|
|
66
|
+
|
|
67
|
+
### Stable identity (`assignHandPoses`, `/low-level`)
|
|
68
|
+
|
|
69
|
+
MediaPipe labels each hand independently, so a hand can be called the wrong side for a frame (edge-on)
|
|
70
|
+
or both hands the same side. The rules, in order:
|
|
71
|
+
|
|
72
|
+
1. Two hands with different, confident labels take their labels.
|
|
73
|
+
2. Otherwise, while both sides were seen in the last 500 ms, the pairing that keeps each wrist nearest
|
|
74
|
+
to where that side's wrist was wins.
|
|
75
|
+
3. Two hands with the same label and no history: the higher score keeps it.
|
|
76
|
+
4. One hand with a low-confidence label sitting where the OTHER hand just was is that hand, mislabeled.
|
|
77
|
+
|
|
78
|
+
A lost hand is held for `HAND_POSE_DEFAULT_HOLD_MS` (200 ms, marked `held`), then becomes `null`. When
|
|
79
|
+
it comes back it lands on the same side, never the other rig.
|
|
80
|
+
|
|
81
|
+
## `HandRig`
|
|
82
|
+
|
|
83
|
+
| prop | default | meaning |
|
|
84
|
+
| ------------------ | ----------- | --------------------------------------------------------------------------------------- |
|
|
85
|
+
| `hand` | — | `"left"` / `"right"`, the person's hand to follow |
|
|
86
|
+
| `model` | — | the loaded model (e.g. `gltf.scene`); cloned per rig |
|
|
87
|
+
| `modelHand` | `"right"` | the chirality the model is authored as |
|
|
88
|
+
| `smoothing` | `0.5` | EMA factor for the hand and finger poses, `1` = none |
|
|
89
|
+
| `fingerLengths` | `"tracked"` | `"tracked"`: segments take the tracked lengths; `"model"`: keep the model's proportions |
|
|
90
|
+
| `showHeld` | `true` | keep drawing a hand during the short hold |
|
|
91
|
+
| `material` | — | replaces every mesh material of this rig (caller-owned) |
|
|
92
|
+
| `onModel` | — | called once with the rig's clone (shadows, render order …) |
|
|
93
|
+
| `onTrackingChange` | — | fires once on found (`true`) and once on lost (`false`) |
|
|
94
|
+
| `active` | `true` | `false` pauses the hand model's inference |
|
|
95
|
+
|
|
96
|
+
**Mirroring.** A right hand seen in a mirror looks like a left hand. On the mirrored webcam, the
|
|
97
|
+
person's right hand therefore has a LEFT hand's shape on screen, and a right-hand model is mirrored
|
|
98
|
+
onto it (`screenChirality`). One model serves both hands on every source.
|
|
99
|
+
|
|
100
|
+
**Tracking.** While a hand is lost the rig hides. On reacquire it snaps to the new pose rather than
|
|
101
|
+
sliding in. A jump of more than `HAND_RIG_SNAP_PALMS` (2.5) palm lengths in one frame also snaps
|
|
102
|
+
(about 22 cm on an average hand). It's measured in the model's own units (`handRigSnapDistance`), so
|
|
103
|
+
models authored in metres, centimetres or millimetres behave the same. Same contract as the head fits.
|
|
104
|
+
|
|
105
|
+
**Finger lengths.** The model is scaled as a whole by the palm fit. With `fingerLengths="tracked"`
|
|
106
|
+
each segment then takes the tracked hand's length, ratio clamped to `HAND_RIG_LENGTH_RANGE`
|
|
107
|
+
(0.75–1.35). Segments are lengthened **along the bone only**, so fingers keep the model's thickness:
|
|
108
|
+
the next joint moves out, and the last segment stretches along its own axis.
|
|
109
|
+
|
|
110
|
+
## Rings and other finger jewellery: `HandOccluder` + `HandAttachment`
|
|
111
|
+
|
|
112
|
+
`HandOccluder` is a `HandRig` whose hand writes depth but no colour and draws first
|
|
113
|
+
(`HAND_OCCLUDER_RENDER_ORDER` = −1). The camera shows the real hand, and anything behind it (the
|
|
114
|
+
back half of a ring, the far side of a watch strap) fails the depth test and disappears.
|
|
115
|
+
`HandAttachment` puts content on a finger bone of the enclosing rig, so it rides on the same fit:
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
import { HandAttachment, HandOccluder } from "@vincentt-xr/sdk/tracking";
|
|
119
|
+
|
|
120
|
+
<HandOccluder hand="right" model={handGltf.scene} inflate={-0.1}>
|
|
121
|
+
<HandAttachment joint="ringMcp" along={0.6}>
|
|
122
|
+
<primitive object={gemRing} />
|
|
123
|
+
</HandAttachment>
|
|
124
|
+
<HandAttachment joint="middlePip" along={0.5}>
|
|
125
|
+
<primitive object={midiRing} />
|
|
126
|
+
</HandAttachment>
|
|
127
|
+
</HandOccluder>;
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**`HandAttachment` props**
|
|
131
|
+
|
|
132
|
+
| prop | default | meaning |
|
|
133
|
+
| -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
134
|
+
| `joint` | — | the finger bone, named by the joint it starts at: `indexMcp` = base segment, `indexPip` middle, `indexDip` last; thumb `thumbCmc` / `thumbMcp` / `thumbIp` |
|
|
135
|
+
| `along` | `0.5` | where along that segment: 0 = at the joint, 1 = at the next |
|
|
136
|
+
| `offset` | — | `{ position, rotation, scale }` in the attachment frame (model units, radians, multiplier) |
|
|
137
|
+
|
|
138
|
+
**The attachment frame.** +Y runs along the finger toward the tip, +Z points out of the palm, so −Z
|
|
139
|
+
is the back of the hand. Units are the model's (cm for the SDK hand). Author a ring around +Y with
|
|
140
|
+
its stone at −Z and it sits on the back of the finger, whatever the rig's own bone axes are
|
|
141
|
+
(`handAttachmentLocal`, `/low-level`). Attachments follow the bone, its tracked length and the
|
|
142
|
+
knuckle offsets, the hand's visibility and its mirroring. On the other chirality the content is
|
|
143
|
+
mirrored too; symmetric pieces like rings are unaffected. Use it inside a `HandRig` as well (e.g.
|
|
144
|
+
nails on a visible skinned hand).
|
|
145
|
+
|
|
146
|
+
**`HandOccluder` props**: everything `HandRig` takes except `material`, plus:
|
|
147
|
+
|
|
148
|
+
- `inflate` (model units, default `0`) pushes the occluder along its normals after skinning. Use
|
|
149
|
+
it negative to shrink.
|
|
150
|
+
- `showDebugMaterial`: draw the occluder as translucent grey.
|
|
151
|
+
- `opacity` (0.5) for that debug view.
|
|
152
|
+
|
|
153
|
+
**Sizing rule.** A ring must stay **outside** the occluder, or the occluder hides its front as
|
|
154
|
+
well. Real fingers vary and the SDK hand's low-poly fingers are wider than they are tall. The
|
|
155
|
+
example places base rings past the webbing (`along={0.6}`), uses a 1.0 cm inner radius (0.85 cm for
|
|
156
|
+
a midi ring), and shrinks the occluder by 1 mm (`inflate={-0.1}`). If a ring's front disappears,
|
|
157
|
+
lower `inflate`. If its back shows through the finger, raise it.
|
|
158
|
+
|
|
159
|
+
**Knuckles.** The palm fit is rigid, so a hand whose knuckles are spread wider or narrower than the
|
|
160
|
+
model's would start its fingers a few millimetres off, enough to put a ring beside the finger. With
|
|
161
|
+
`fingerLengths="tracked"` (the default) each digit's first bone also moves to its tracked knuckle
|
|
162
|
+
(`HandRigSolution.knuckles`, clamped to `HAND_RIG_KNUCKLE_SHIFT`, 0.2 palm lengths), eased like the
|
|
163
|
+
lengths.
|
|
164
|
+
|
|
165
|
+
**Render order.**
|
|
166
|
+
|
|
167
|
+
- The occluder draws at −1, only on the hand model's own meshes (flagged
|
|
168
|
+
`userData[HAND_RIG_MODEL_MESH]`).
|
|
169
|
+
- Attachments keep their own order (0) and depth-test against the occluder.
|
|
170
|
+
- The occluder ends 1.2 cm past the wrist, like the hand model, so a watch on the wrist bone's
|
|
171
|
+
neighbour isn't occluded below that point.
|
|
172
|
+
|
|
173
|
+
Example: `/hand-rig?rings=1`, with three rings from `assets-src/accessories/rings-v1.blend` (gold band,
|
|
174
|
+
gem ring, rose-gold midi). It has:
|
|
175
|
+
|
|
176
|
+
- a ring picker per finger
|
|
177
|
+
- occluder on/off
|
|
178
|
+
- the debug view
|
|
179
|
+
- an inflate slider
|
|
180
|
+
- a found/lost log
|
|
181
|
+
- a hide-able panel
|
|
182
|
+
|
|
183
|
+
## Watches and bracelets (experimental): `WristAttachment`, the forearm bone and the arm mask
|
|
184
|
+
|
|
185
|
+
Experimental: the props and the behaviour may change in a later alpha. Known gaps are tracked in
|
|
186
|
+
vincentt-xr/sdk#319.
|
|
187
|
+
|
|
188
|
+
`WristAttachment` puts content on the wrist of the enclosing `HandRig` / `HandOccluder`. A function
|
|
189
|
+
child gets the wrist's size, so a strap or a bangle fits the tracked hand. `forearm` on the occluder
|
|
190
|
+
adds an arm behind it, so the back of the strap disappears behind the real arm. `armMask` makes the
|
|
191
|
+
wristwear follow the real arm:
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
import { HandOccluder, WristAttachment } from "@vincentt-xr/sdk/tracking";
|
|
195
|
+
|
|
196
|
+
<HandOccluder hand="right" model={handGltf.scene} inflate={-0.1} forearm armMask="skin">
|
|
197
|
+
<WristAttachment along={1.6}>
|
|
198
|
+
{(wrist) => <Watch rx={wrist.width / 2 + 0.25} rz={wrist.depth / 2 + 0.25} />}
|
|
199
|
+
</WristAttachment>
|
|
200
|
+
</HandOccluder>;
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**`WristAttachment` props**
|
|
204
|
+
|
|
205
|
+
| prop | default | meaning |
|
|
206
|
+
| ---------- | ------- | ------------------------------------------------------------------------------------------ |
|
|
207
|
+
| `along` | `1` | how far up the forearm from the wrist joint, in model units (cm for the SDK hand) |
|
|
208
|
+
| `offset` | — | `{ position, rotation, scale }` in the wrist frame (model units, radians, multiplier) |
|
|
209
|
+
| `children` | — | content in the wrist frame, or `(wrist: WristSize) => ReactNode` to size it from the wrist |
|
|
210
|
+
|
|
211
|
+
**The forearm bone.** Wristwear rides on the rig's `forearm` bone: a child of `wrist` that starts at
|
|
212
|
+
the tracked wrist point and runs up the arm. The SDK hand has it (`assets-src/hands/build_forearm.py`
|
|
213
|
+
adds it in Blender). For other models, `HandRig` makes one in code (`ensureForearmBone`). Author
|
|
214
|
+
wristwear in Blender by parenting it to `forearm`.
|
|
215
|
+
|
|
216
|
+
**The wrist frame.** +Y runs toward the fingers (so −Y goes up the arm), +Z points out of the palm
|
|
217
|
+
(−Z is the back of the wrist, where a watch face goes), +X runs across the wrist. Its origin is the
|
|
218
|
+
wrist joint. It is built from the rig's rest pose, so it is the same whatever the model's own bone
|
|
219
|
+
axes are (`wristFrameLocal`, `/low-level`).
|
|
220
|
+
|
|
221
|
+
**The wrist's size** (`WristSize`, from `wristSizeOf`, measured on the rig at rest, model units):
|
|
222
|
+
|
|
223
|
+
- `palmWidth`: index knuckle to pinky knuckle.
|
|
224
|
+
- `palmLength`: wrist to middle knuckle.
|
|
225
|
+
- `width`: `WRIST_WIDTH_OF_PALM` (0.9) × `palmWidth`.
|
|
226
|
+
- `depth`, back to palm: `WRIST_DEPTH_OF_WIDTH` (0.7) × `width`.
|
|
227
|
+
|
|
228
|
+
Make a strap's inner ellipse a little larger than `width / 2` by `depth / 2`. The example adds
|
|
229
|
+
0.25 cm, so the strap stays outside the arm occluder and its front never hides.
|
|
230
|
+
|
|
231
|
+
**How the forearm is aimed.** Before every render the rig aims the forearm bone once, for everything
|
|
232
|
+
on that wrist (`HandRigWrist`):
|
|
233
|
+
|
|
234
|
+
1. **Steadied.** When a hand turns edge-on, one camera can't tell which side of the palm faces it,
|
|
235
|
+
and the tracked hand can flip for a few frames. A turn of more than 35° is only taken once it
|
|
236
|
+
lasts 200 ms and 4 hand detections (`WristRotationFilter`), so flips don't spin the watch.
|
|
237
|
+
2. **Aligned with the arm** (`armMask` on `HandRig` / `HandOccluder`). From the wrist it scans
|
|
238
|
+
across the arm in a segmentation mask: first an arc around the wrist, then cross-sections 2–8 cm
|
|
239
|
+
up the arm, then a line through their middles. That gives the arm's direction (bends up to
|
|
240
|
+
95°), its middle and its width. The forearm then:
|
|
241
|
+
- lines up with the arm in full once the mask is sure;
|
|
242
|
+
- moves onto the arm's middle (at most 2 cm);
|
|
243
|
+
- keeps its way while the hand points at the camera;
|
|
244
|
+
- eases back to the hand's own axis when the arm is lost.
|
|
245
|
+
3. **Fitted to the width,** gently: a scale across the arm of 0.85 to 1.2 on what rides on the bone.
|
|
246
|
+
|
|
247
|
+
| `armMask` | the arm is |
|
|
248
|
+
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
249
|
+
| `"skin"` | the multiclass segmenter's bare skin (`body_skin`), apart from the face and the clothes |
|
|
250
|
+
| `"portrait"` | the person mask: cheaper, but has no edges where the arm is in front of the body |
|
|
251
|
+
| `{ … }` | options: `kind`, `turn`, `fitWidth`, the easing (`smoothing`, `holdMs`, `fadeMs`, `maxSkewMs`, `maxShift`) and the measure (`along`, `widthAt`, `maxWidth`, `minWidth`, `maxTurn`) |
|
|
252
|
+
|
|
253
|
+
Masks arrive later than hand poses, so each mask is measured against the hand pose from the same
|
|
254
|
+
moment (`ArmTracker`; both segmenters stamp their masks with `timestampMs`). `"skin"` runs the
|
|
255
|
+
multiclass segmenter, which shares `XRModel.SEMANTIC_SEGMENTATION` with the hair mask: the first
|
|
256
|
+
acquirer in a session picks the preset.
|
|
257
|
+
|
|
258
|
+
**The forearm occluder.** `forearm` on `HandOccluder` (`true`, or `{ length, scale }`) adds a
|
|
259
|
+
depth-only `ForearmOccluder` on the forearm bone: a tapered elliptic tube from the wrist up the arm.
|
|
260
|
+
|
|
261
|
+
- `length` is in palm lengths (`FOREARM_OCCLUDER_LENGTH`, 2.5).
|
|
262
|
+
- It widens by `FOREARM_OCCLUDER_FLARE` (1.25) toward the elbow; `scale` makes it wider (> 1) or
|
|
263
|
+
narrower.
|
|
264
|
+
- It reaches `FOREARM_OCCLUDER_OVERLAP` (0.15 palm lengths) into the hand, so there is no gap at the
|
|
265
|
+
wrist.
|
|
266
|
+
- It shares the occluder's debug view.
|
|
267
|
+
|
|
268
|
+
Mount it on its own inside a `HandRig` (`<ForearmOccluder length scale showDebugMaterial opacity />`),
|
|
269
|
+
or build the mesh yourself with `createForearmGeometry(wrist, { length, scale })`.
|
|
270
|
+
|
|
271
|
+
**Known gaps** (vincentt-xr/sdk#319):
|
|
272
|
+
|
|
273
|
+
- The hand tracker misses some poses: a fist pressed on the face, a hand bent toward the camera.
|
|
274
|
+
- With the hand pointing at the camera, the bone can't yet lie along an arm seen side-on.
|
|
275
|
+
- Width readings differ between the two masks.
|
|
276
|
+
|
|
277
|
+
Example: `/hand-rig?rings=1&wrist=watch&armMask=skin` (also `wrist=bracelet` / `both`,
|
|
278
|
+
`armMask=portrait`). The watch and the bead bracelet are built in code, and the watch hands show the
|
|
279
|
+
real time. `debug=1` draws the mask, the hand's axis, the cross-sections across the arm and the arm's
|
|
280
|
+
axis; `forearm=0` turns the arm occluder off to compare.
|
|
281
|
+
|
|
282
|
+
## Gloves: a model that wears `HandRig`
|
|
283
|
+
|
|
284
|
+
A glove is a hand model. Build it on the same rig and `HandRig` wears it, fitted to the person's
|
|
285
|
+
palm and finger lengths. There is no glove component: the rig contract below is the whole
|
|
286
|
+
interface.
|
|
287
|
+
|
|
288
|
+
```tsx
|
|
289
|
+
import { useLoader } from "@react-three/fiber";
|
|
290
|
+
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
291
|
+
import { HandRig } from "@vincentt-xr/sdk/tracking";
|
|
292
|
+
|
|
293
|
+
const Gloves = () => {
|
|
294
|
+
const glove = useLoader(GLTFLoader, gloveUrl); // e.g. the example's glove-v1.glb
|
|
295
|
+
return (
|
|
296
|
+
<>
|
|
297
|
+
<HandRig hand="left" model={glove.scene} />
|
|
298
|
+
<HandRig hand="right" model={glove.scene} />
|
|
299
|
+
</>
|
|
300
|
+
);
|
|
301
|
+
};
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
The glove's materials are lit (`MeshPhysicalMaterial` from the GLB), so the scene needs lights or an
|
|
305
|
+
environment.
|
|
306
|
+
|
|
307
|
+
**Recipe for your own glove** (or a gauntlet, a mitten, a robot hand):
|
|
308
|
+
|
|
309
|
+
1. Start from a rigged hand's skin (`assets-src/hands/hand-v1.blend`). Keep its armature, weights,
|
|
310
|
+
joint names and rest positions.
|
|
311
|
+
2. Make it slightly thicker than the hand: push the surface out along its normals (the example uses
|
|
312
|
+
2.8 mm). The real fingers then stay hidden under it in every pose. The thickness scales with the
|
|
313
|
+
hand, because the whole rig does.
|
|
314
|
+
3. Weight anything past the wrist (a cuff) to `wrist` only. The tracker has no forearm landmark, so
|
|
315
|
+
a cuff follows the palm's direction: keep it short.
|
|
316
|
+
4. Add UVs and textures as for any model, then export a GLB with skinning, deform bones only and
|
|
317
|
+
+Y up. No animation is needed.
|
|
318
|
+
|
|
319
|
+
**The example glove** (`glove-v1.glb`, ~195 KB) is a winter knit glove: a deep red `knit` body and
|
|
320
|
+
a cream ribbed `rib` cuff, with knit textures generated procedurally in Blender. It sits 2.8 mm
|
|
321
|
+
outside `hand-v1` everywhere, is quantised (`KHR_mesh_quantization`, which a plain `GLTFLoader`
|
|
322
|
+
reads) and uses `KHR_materials_sheen` for the soft fuzz. To recolour it, set `material.color` on the
|
|
323
|
+
material named `knit` or `rib`; clone the material first to change one hand only. It's built by
|
|
324
|
+
`assets-src/hands/build_glove.py` from `hand-v1.blend`, so the hand's CC BY 4.0 credit applies.
|
|
325
|
+
Example: `/hand-rig?glove=1` (`&gloveHands=left` gloves one hand only).
|
|
326
|
+
|
|
327
|
+
## Tattoos: `HandTattoo`
|
|
328
|
+
|
|
329
|
+
`HandTattoo` puts art on the skin of the enclosing `HandRig` / `HandOccluder`, on the back of the hand
|
|
330
|
+
or the palm. The art is projected onto the model's surface in its **rest pose**, so it bends,
|
|
331
|
+
stretches and turns with the fingers and the palm. Inside a `HandOccluder` it inks the real hand in
|
|
332
|
+
the camera image:
|
|
333
|
+
|
|
334
|
+
```tsx
|
|
335
|
+
import { HandOccluder, HandTattoo } from "@vincentt-xr/sdk/tracking";
|
|
336
|
+
|
|
337
|
+
<HandOccluder hand="right" model={handGltf.scene} inflate={-0.1}>
|
|
338
|
+
<HandTattoo src={roseUrl} placement="back" size={5} opacity={0.85} />
|
|
339
|
+
</HandOccluder>;
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
- **Blending.** `blend="multiply"` (the default) multiplies the camera image by the art, so skin
|
|
343
|
+
shading and texture show through the ink, and white or transparent parts leave the skin as it
|
|
344
|
+
is. `blend="normal"` lays the art's own colours over the skin, for stickers or light ink on dark
|
|
345
|
+
skin.
|
|
346
|
+
- **Occlusion.** The `HandOccluder` draws the hand's depth first, so the art disappears where the
|
|
347
|
+
hand covers itself (curled fingers over a palm tattoo). Keep the occluder's `inflate` at or below
|
|
348
|
+
0: the art is drawn on the model's own surface, and a grown occluder covers it.
|
|
349
|
+
- **On a visible model** (inside a `HandRig` with a skin or a glove) the art prints on that model.
|
|
350
|
+
- **No UVs needed.** The placement is measured from the rig's joints, so any model on the rig
|
|
351
|
+
contract works, `hand-v1` included (it ships without UVs).
|
|
352
|
+
|
|
353
|
+
**`HandTattoo` props**
|
|
354
|
+
|
|
355
|
+
| prop | default | meaning |
|
|
356
|
+
| ------------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
357
|
+
| `src` | — | an image URL (loaded as sRGB) or a `THREE.Texture` you own (set `colorSpace = SRGBColorSpace`) |
|
|
358
|
+
| `placement` | `"back"` | `"back"` of the hand or `"palm"` |
|
|
359
|
+
| `size` | 0.55 palm lengths (4.8 cm) | the art's width in model units (cm for the SDK hand). Its height follows the image's aspect |
|
|
360
|
+
| `offset` | `[0, 0]` | `[towardThumb, towardFingers]` from the centre of that side, model units |
|
|
361
|
+
| `rotation` | `0` | radians, counter-clockwise as seen looking at that side with the fingers up |
|
|
362
|
+
| `opacity` | `0.9` | 0..1 |
|
|
363
|
+
| `blend` | `"multiply"` | `"multiply"` (ink) or `"normal"` (the art's own colours) |
|
|
364
|
+
| `renderOrder` | `1` | `HAND_TATTOO_RENDER_ORDER`: after the hand model (transparent pass), so it blends over the camera image or the model |
|
|
365
|
+
|
|
366
|
+
**Where it lands.** The centre of each side is half-way from the wrist to the knuckles. The art is
|
|
367
|
+
projected straight onto that side and fades out where the surface turns more than ~65° away (the
|
|
368
|
+
edges of the hand), so it never wraps onto the other side. For a piece that wraps round the hand,
|
|
369
|
+
mount two `HandTattoo`s. Several tattoos per hand are fine: each one is one more draw of the hand
|
|
370
|
+
mesh.
|
|
371
|
+
|
|
372
|
+
**Mirroring.** On the other chirality (a right-hand model drawn as a left hand) the placement mirrors
|
|
373
|
+
with the hand: `offset[0]` stays toward the thumb. The art itself is flipped back, so it never reads
|
|
374
|
+
mirrored, and `rotation` still turns it counter-clockwise on screen.
|
|
375
|
+
|
|
376
|
+
**Art.** Dark line art on a transparent PNG works best with `multiply` (a white background works
|
|
377
|
+
too), at 512–1024 px. The example draws placeholder art in code (`tattooArt.ts`: a nautical star and
|
|
378
|
+
a swallow).
|
|
379
|
+
|
|
380
|
+
**Why a component, not a UV texture.** The SDK hand ships without UVs, and every model would unwrap
|
|
381
|
+
differently. Projecting from the rig's rest joints gives the same placement on any compatible model,
|
|
382
|
+
in physical units, and keeps the art where an artist expects it: on the back or the palm, upright
|
|
383
|
+
with the fingers up.
|
|
384
|
+
|
|
385
|
+
**Pure pieces** (`/low-level`): `handTattooFrame(binding, placement)` (the projector's frame in rig
|
|
386
|
+
space), `handGeometryToRoot(binding, mesh)` (geometry to rest space, quantised meshes included),
|
|
387
|
+
`handTattooMatrix(frame, geometryToRoot, { size, offset })` (the shader's matrix), `handTattooUv`
|
|
388
|
+
(the shader's math in JS), `createHandTattooMaterial`, `setHandTattooBlend`,
|
|
389
|
+
`HAND_TATTOO_FACING_FADE`. `HAND_TATTOO_DEFAULT_SIZE` and `HAND_TATTOO_RENDER_ORDER` are in
|
|
390
|
+
`/tracking`.
|
|
391
|
+
|
|
392
|
+
Example: `/hand-rig?tattoo=1`. It has back / palm placement, two placeholder arts, opacity, size,
|
|
393
|
+
rotation, offsets and blend. With `glove=1` the art prints on the glove.
|
|
394
|
+
|
|
395
|
+
## The rig contract (for your own hand model)
|
|
396
|
+
|
|
397
|
+
A compatible model has a node named after each joint it rotates, placed **at** that joint:
|
|
398
|
+
|
|
399
|
+
```
|
|
400
|
+
wrist ─┬ thumbCmc → thumbMcp → thumbIp → (thumbTip)
|
|
401
|
+
├ indexMcp → indexPip → indexDip → (indexTip)
|
|
402
|
+
├ middleMcp → middlePip → middleDip → (middleTip)
|
|
403
|
+
├ ringMcp → ringPip → ringDip → (ringTip)
|
|
404
|
+
├ pinkyMcp → pinkyPip → pinkyDip → (pinkyTip)
|
|
405
|
+
└ (forearm)
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
- `HAND_RIG_REQUIRED_JOINTS` (the 16 non-tip nodes) must exist. Missing ones throw with their names.
|
|
409
|
+
The `…Tip` nodes are optional; without them the tip is extrapolated from the last bone.
|
|
410
|
+
- **Any rest pose, units, bone roll and authoring axes work.** The driver measures every rotation
|
|
411
|
+
from the model's own rest pose, so a relaxed, curled rest hand is fine.
|
|
412
|
+
- One chirality per model (`modelHand`). Draw the other by mirroring; don't ship two meshes.
|
|
413
|
+
- `forearm` is optional (experimental): a bone from the wrist joint up the arm. The rig aims it
|
|
414
|
+
(steadied, and along the arm in the mask with `armMask`), and wristwear rides on it. Without it,
|
|
415
|
+
`HandRig` makes one in code. Weight forearm geometry (a sleeve, a glove's cuff) to it so it follows
|
|
416
|
+
the arm rather than the palm. The example model ends at the wrist with an alpha fade and carries
|
|
417
|
+
the bone only.
|
|
418
|
+
- Keep the deforming bones' children on their local axis (Blender's +Y does this) so the last
|
|
419
|
+
segment can stretch along it.
|
|
420
|
+
|
|
421
|
+
**How it solves**, per frame (`solveHandRig`, pure):
|
|
422
|
+
|
|
423
|
+
1. `handPoseToScene` maps the tracked hand into the scene.
|
|
424
|
+
2. If the hand's on-screen chirality differs from `modelHand`, the live points are mirrored in X and
|
|
425
|
+
the mirror goes on the root.
|
|
426
|
+
3. Root: the Umeyama similarity from the rig's rest palm (`HAND_RIG_PALM_JOINTS`: wrist, thumb CMC,
|
|
427
|
+
four MCPs) onto the live palm.
|
|
428
|
+
4. Fingers: each bone (`HAND_RIG_BONES`, parents first) follows its parent rigidly, then swings by the
|
|
429
|
+
shortest arc so it points at its live child joint.
|
|
430
|
+
5. Lengths: tracked segment length over rest length per bone (`solution.lengths`).
|
|
431
|
+
|
|
432
|
+
`bindHandRig`, `solveHandRig`, `applyHandRigSolution`, `applyHandRigLengths`, `handRigRootMatrix`,
|
|
433
|
+
`handRigSnapDistance`, `screenChirality`, the `HAND_RIG_*` tables and the identity pieces
|
|
434
|
+
(`assignHandPoses`, `anatomicalHandedness`, `handWorldLandmarkToJoint`) are exported from
|
|
435
|
+
**`@vincentt-xr/sdk/low-level`**, for apps that animate a rig outside React or record poses.
|
|
436
|
+
`/tracking` keeps `HandRig`, the pose contract (`HAND_JOINT_NAMES`, `HAND_JOINT_INDEX`, `HandPose`,
|
|
437
|
+
`HandPoses`, `HandJointName`, `HAND_POSE_DEFAULT_HOLD_MS`), `handPoseToScene` (the blessed way to
|
|
438
|
+
place a pose in the scene, e.g. for a joint overlay) and `HAND_RIG_REQUIRED_JOINTS`.
|
|
439
|
+
|
|
440
|
+
## The example model
|
|
441
|
+
|
|
442
|
+
`assets-src/hands/hand-v1.blend` (README beside it): "Hand (low poly)" by scribbletoad, CC BY 4.0. It
|
|
443
|
+
was rigged for the SDK by running MediaPipe on renders of the mesh to place the joints, with knuckle
|
|
444
|
+
edge rings, 21 joint nodes, a 17 cm right hand and a wrist alpha fade. The 1 k-triangle cage is
|
|
445
|
+
subdivided once on export (5.6 k triangles, ~230 KB). The GLB also carries 11 gesture poses as
|
|
446
|
+
animations, used by [Hand Instructions](/api/hand-instructions).
|
|
447
|
+
|
|
448
|
+
GLTFLoader turns depth writes off for alpha-blended materials. The example turns them back on for the
|
|
449
|
+
hand so curled fingers don't show through the palm, because only the wrist edge is see-through. A
|
|
450
|
+
replacement material keeps the wrist fade with `vertexColors: true, transparent: true`.
|
|
451
|
+
|
|
452
|
+
## Manual visual test plan
|
|
453
|
+
|
|
454
|
+
Open `/hand-rig` with the tracked joints overlay on.
|
|
455
|
+
|
|
456
|
+
1. **Webcam (mirrored)**: raise your right hand. The panel says `right` and the rig is a mirrored
|
|
457
|
+
right-hand model. Raise the left: `left`. Both together: two rigs, thumbs on the correct sides.
|
|
458
|
+
2. **Unmirrored source** (a video preset or a local clip): the person's right hand reads `right`
|
|
459
|
+
(on screen-left when they face the camera).
|
|
460
|
+
3. **Rotation**: palm to camera, back to camera, palm sideways, wrist bent. The rig turns with the
|
|
461
|
+
hand, the fingertips sit on the tip dots, and the hand ends at the wrist without a stub.
|
|
462
|
+
4. **Fingers**: fist, point, peace sign, OK sign, spread. Each finger bends at its knuckles, nothing
|
|
463
|
+
tears.
|
|
464
|
+
5. **Lengths**: switch fingers to "model proportions" and back. Tracked lengths reach the tip dots;
|
|
465
|
+
finger thickness does not change.
|
|
466
|
+
6. **Loss and reacquisition**: hide one hand. Its rig vanishes after a moment, the panel logs `lost`.
|
|
467
|
+
Bring it back: the same rig returns (`found`), snapped, without sliding in from elsewhere. Cross
|
|
468
|
+
your hands and uncross: the rigs stay with their hands.
|
|
469
|
+
7. **Partial occlusion**: cover some fingers with the other hand or an object. MediaPipe still
|
|
470
|
+
estimates all 21 joints, so the covered fingers follow its guess (expect some wobble). The rig
|
|
471
|
+
hides only when the hand itself is lost.
|
|
472
|
+
8. **Materials**: switch the look to gloves and ghost. Each rig gets its own material and the wrist
|
|
473
|
+
still fades.
|
|
474
|
+
|
|
475
|
+
### Hand occluder (`/hand-rig?rings=1`)
|
|
476
|
+
|
|
477
|
+
1. **Palm to camera**: each ring shows only its front arc. The back arc and the gem (on the back of
|
|
478
|
+
the hand) are hidden behind the finger.
|
|
479
|
+
2. **Back of the hand to camera**: the gem faces you, and the band's palm side is hidden.
|
|
480
|
+
3. **Turn the hand edge-on**: the near half of each ring shows, the far half hides, with no
|
|
481
|
+
flicker at the finger's silhouette.
|
|
482
|
+
4. **Occluder off**: the whole ring draws over the finger, which is the failure case.
|
|
483
|
+
5. **Debug**: the grey occluder hand sits on the real one and each ring wraps its occluder finger.
|
|
484
|
+
6. **Inflate**: lower it until a ring's front stays whole at every angle. Raise it until the back
|
|
485
|
+
no longer shows through.
|
|
486
|
+
7. **Placement**: rings sit on the right fingers past the webbing. Bend the fingers and the rings
|
|
487
|
+
ride along. Spread and close the fingers and each ring stays centred on its finger.
|
|
488
|
+
8. **Both hands, both cameras**: the left and right hands each wear their rings. On the mirrored
|
|
489
|
+
webcam the gem still sits on the back of the hand.
|
|
490
|
+
|
|
491
|
+
### Wristwear, experimental (`/hand-rig?rings=1&wrist=both&armMask=skin`)
|
|
492
|
+
|
|
493
|
+
1. **Back of the hand to camera**: the watch case sits on the strap on the back of the wrist, 12
|
|
494
|
+
toward the thumb and 3 toward the fingers, showing the real time. The strap wraps the wrist to
|
|
495
|
+
its edges. The bracelet sits above the watch, up the arm.
|
|
496
|
+
2. **Palm to camera**: the watch case is hidden behind the arm and the strap's palm side shows. The
|
|
497
|
+
bracelet's far beads hide and the near ones show.
|
|
498
|
+
3. **Turn the wrist edge-on and back** a few times: the watch does not flip or spin round the arm.
|
|
499
|
+
A real turn is taken after a moment.
|
|
500
|
+
4. **Bend the wrist** (a fist hanging from a level arm), with `debug=1`: the yellow arm axis and the
|
|
501
|
+
grey forearm run along the real forearm, not along the hand, and the watch stays across the arm.
|
|
502
|
+
5. **Arm in front of the shirt**: with `armMask=skin` the arm is still found. With
|
|
503
|
+
`armMask=portrait` it isn't, and the forearm follows the hand.
|
|
504
|
+
6. **Forearm occluder off** (`forearm=0`): the whole strap and every bead draw over the arm, which is
|
|
505
|
+
the failure case.
|
|
506
|
+
7. **Both hands, both cameras**: each hand wears its watch and bracelet. On the mirrored webcam the
|
|
507
|
+
face still sits on the back of the wrist.
|
|
508
|
+
|
|
509
|
+
### Glove (`/hand-rig?glove=1`)
|
|
510
|
+
|
|
511
|
+
1. **Cover**: open hand, palm and back to the camera. No skin shows at the fingertips, the finger
|
|
512
|
+
sides or the knuckles; the cuff ends just past the wrist.
|
|
513
|
+
2. **Fit**: spread, fist, point, OK sign. Each glove finger bends at the real knuckles and ends at
|
|
514
|
+
the real fingertip (tracked lengths). Switch fingers to "model proportions": the glove keeps its
|
|
515
|
+
own lengths.
|
|
516
|
+
3. **Knit**: the stitch columns run along each finger and up the palm; the cuff is ribbed and
|
|
517
|
+
cream. Turn the hand: the knit catches the light softly (sheen).
|
|
518
|
+
4. **Both hands**: each hand wears a glove (the left one mirrored). `gloveHands=left` gloves only
|
|
519
|
+
the left hand; the right shows the look material (or the rings when they are on).
|
|
520
|
+
5. **Loss**: hide a gloved hand and bring it back. The glove returns on the same hand, snapped.
|
|
521
|
+
|
|
522
|
+
### Tattoo (`/hand-rig?tattoo=1`)
|
|
523
|
+
|
|
524
|
+
1. **Back of the hand to the camera**: the star sits between the wrist and the knuckles, upright
|
|
525
|
+
with the fingers up. The skin's shading and creases show through the ink.
|
|
526
|
+
2. **Bend and spread**: make a fist, spread the fingers, bend the wrist. The art stays on the same
|
|
527
|
+
patch of skin and stretches with it, without sliding.
|
|
528
|
+
3. **Turn the hand**: palm to the camera hides a back tattoo; edge-on, it fades out at the side of
|
|
529
|
+
the hand rather than smearing.
|
|
530
|
+
4. **Palm** (`tattooAt=palm`): the art is on the palm. Curl the fingers over it: they cover it.
|
|
531
|
+
5. **Mirroring** (`tattooArt=swallow`): show both hands, backs to the camera. The swallow faces the
|
|
532
|
+
same way on both and never reads mirrored. `tattooX` moves it toward the thumb on both hands.
|
|
533
|
+
6. **Controls**: opacity, size, rotation (counter-clockwise), offsets and blend each change the art
|
|
534
|
+
live. `blend=normal` shows the art's own colours (the swallow's cream belly appears).
|
|
535
|
+
7. **With the glove** (`glove=1&tattoo=1`): the art prints on the knit.
|