@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,234 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Body Triggers"
|
|
3
|
+
description: "Fire on full-body poses (T-pose, hands up, squat) and moves over time (jump, squat reps, wave, clap, punch, arm flap, kick, step, march) with begin / end events."
|
|
4
|
+
sidebarTitle: "Body Triggers"
|
|
5
|
+
icon: "person-running"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
`BodyTrigger` fires when the person holds a body pose or performs a body move. It reads the body
|
|
9
|
+
model's 33 pose landmarks (it acquires the model itself; no `BodyTracker` needed) and runs the same
|
|
10
|
+
lifecycle as [`useGesture`](/api/gestures): begin / end events, hold, cooldown, loss grace and a
|
|
11
|
+
count.
|
|
12
|
+
|
|
13
|
+
Import from `@vincentt-xr/sdk/tracking`.
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { BodyTrigger, useBodyTrigger } from "@vincentt-xr/sdk/tracking";
|
|
17
|
+
|
|
18
|
+
// Declarative: mount inside the scene, act on the events.
|
|
19
|
+
<BodyTrigger pose="tPose" onBegin={() => takeOff()} onEnd={() => land()} />;
|
|
20
|
+
<BodyTrigger move="jump" onBegin={() => hop()} />;
|
|
21
|
+
<BodyTrigger move="punch" side="right" onBegin={(state) => hit(state.side)} />;
|
|
22
|
+
|
|
23
|
+
// Hook: React state that changes only when the trigger's state changes.
|
|
24
|
+
const squats = useBodyTrigger({ move: "squat" });
|
|
25
|
+
// squats.count = reps so far; squats.active = at the bottom of a rep.
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Pass exactly one of `pose` or `move`. Left / right are the person's own sides on every camera.
|
|
29
|
+
|
|
30
|
+
## Poses
|
|
31
|
+
|
|
32
|
+
`pose` takes BodyInstruction's vocabulary (`BODY_POSES` from `@vincentt-xr/sdk/instructions`) and
|
|
33
|
+
its classifier (`analyzeBodyShape` + `matchBodyPose`), so a pose that completes a
|
|
34
|
+
[`BodyInstruction`](/api/body-instructions) also fires a `BodyTrigger`.
|
|
35
|
+
|
|
36
|
+
| You want | `pose` | Needs |
|
|
37
|
+
| -------------------------------- | ---------------------------------------------------------- | ---------- |
|
|
38
|
+
| T-pose | `"tPose"` | upper body |
|
|
39
|
+
| Hands up | `"handsUp"` (alias of `"hooray"`) | upper body |
|
|
40
|
+
| Hands on hips | `"handsOnHips"` | upper body |
|
|
41
|
+
| Arms crossed | `"armsCrossed"` | upper body |
|
|
42
|
+
| Squat position | `"squat"` | whole body |
|
|
43
|
+
| Raise one arm | `"raiseLeft"` / `"raiseRight"` | upper body |
|
|
44
|
+
| Hands on head, thumbs up, salute | `"handsOnHead"`, `"thumbUp"`, `"bothThumbsUp"`, `"salute"` | upper body |
|
|
45
|
+
| Lean, one leg, star | `"leanLeft"` / `"leanRight"`, `"oneLeg"`, `"star"` | whole body |
|
|
46
|
+
|
|
47
|
+
`pose` also takes a rule, a match function or a `defineBodyPose` definition:
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
<BodyTrigger pose={{ arms: { left: "raised", right: "out" } }} onBegin={point} />
|
|
51
|
+
<BodyTrigger pose={(shape) => shape.arms.left.up > 1.2} onBegin={reach} />
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
A pose begins once it has been held (the match is smoothed over about 80 ms, then `holdMs`, 150 by
|
|
55
|
+
default) and ends when it is released. A one-frame flicker of the classifier neither ends nor
|
|
56
|
+
restarts it. Pose defaults: `BODY_POSE_TRIGGER_DEFAULTS` (enter 0.6, exit 0.25, hold 150 ms, loss
|
|
57
|
+
grace 250 ms).
|
|
58
|
+
|
|
59
|
+
Poses read the same on portrait, landscape and square feeds. Tracker x and y each span the frame,
|
|
60
|
+
so on a 9:16 portrait feed a horizontal distance reads 1.78 times too long next to a vertical one;
|
|
61
|
+
the trigger multiplies x by the frame's aspect ratio (`useXRFeedAspect()`) before classifying.
|
|
62
|
+
`handsUp` and `hooray` are the same pose: each answers the other.
|
|
63
|
+
|
|
64
|
+
## Moves
|
|
65
|
+
|
|
66
|
+
`move` takes a `BODY_MOVES` name (`BODY_MOVE_NAMES`) or your own `defineBodyMove` definition.
|
|
67
|
+
|
|
68
|
+
| `move` | Begins | Ends | Needs | `side` | Cooldown |
|
|
69
|
+
| ---------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------ | ---------- | ------ | -------- |
|
|
70
|
+
| `"jump"` | shoulders, hips and both feet rise together above the standing level (take-off) | on landing | whole body | – | 150 ms |
|
|
71
|
+
| `"squat"` | from standing, both thighs drop toward level (bottom of a rep) | back up standing | whole body | – | 200 ms |
|
|
72
|
+
| `"wave"` | a raised forearm swings side to side (three turning points within 1.5 s) | when the swinging stops | the arm | yes | 600 ms |
|
|
73
|
+
| `"clap"` | the hands meet fast (apart to touching within 0.25 s) | when they part | both arms | – | 100 ms |
|
|
74
|
+
| `"punch"` | an arm snaps from bent to straight (within 0.2 s) at shoulder height, to the camera or the side | when it bends back | the arm | yes | 150 ms |
|
|
75
|
+
| `"armFlap"` | both arms, out like wings, beat down together | when the arms rise again | both arms | – | 100 ms |
|
|
76
|
+
| `"kick"` | one foot swings up fast with the knee lifted and the lower leg raised | when the foot is down | whole body | yes | 300 ms |
|
|
77
|
+
| `"stepLeft"` / `"stepRight"` | hips and both feet move to the person's own left / right by half a shoulder width within 0.7 s | when the body settles | whole body | – | 300 ms |
|
|
78
|
+
| `"march"` | each alternating knee (or foot) lift; the first lift only starts the count | when that foot is down | whole body | – | 0 |
|
|
79
|
+
|
|
80
|
+
Every move counts: `state.count` goes up on each begin (jumps, reps, claps, punches, flaps, kicks,
|
|
81
|
+
steps, march steps). `onEnd` with `endReason: "released"` means the move completed. `state.side` is the
|
|
82
|
+
limb behind the begin (`wave`, `punch`, `kick`, `march`) or the step direction.
|
|
83
|
+
|
|
84
|
+
`side` (`"left"`, `"right"`, default `"either"`) picks the limb a `wave`, `punch` or `kick` watches.
|
|
85
|
+
|
|
86
|
+
### Telling moves apart
|
|
87
|
+
|
|
88
|
+
The moves are built not to answer each other: a squat is not a jump (the feet stay down), a march
|
|
89
|
+
step is not a kick (the foot hangs under the knee), a heel kick is not a kick (the knee stays down),
|
|
90
|
+
lowering the arms from the front is not a flap, dropping or raising a bent arm is not a punch, a slow
|
|
91
|
+
reach is not a punch, hands brought together slowly are not a clap, walking toward the camera is not
|
|
92
|
+
a step, and a single knee raise is not marching.
|
|
93
|
+
|
|
94
|
+
Moves read body motion in the frame, so a camera that moves fast reads as motion too: a jerked
|
|
95
|
+
handheld phone can look like a jump or a step. Slow drift never does. For leg moves, prop the phone up.
|
|
96
|
+
|
|
97
|
+
## Whole body in view
|
|
98
|
+
|
|
99
|
+
Leg moves need shoulders, hips, knees and ankles in view. A joint counts when MediaPipe's visibility
|
|
100
|
+
is at least 0.2 and it sits no more than 0.12 past the frame edge (`BODY_MOVE_VIEW_LIMITS`; the
|
|
101
|
+
frame spans −1..1). Both bars are deliberate: MediaPipe often reports 0.2 to 0.5 for ankles that are
|
|
102
|
+
in frame, and an ankle can sit just past the edge when the feet are partly cropped. Legs cut off by a
|
|
103
|
+
front camera held close sit far past the edge with visibility near 0, so leg moves never fire.
|
|
104
|
+
Tune per trigger with `view`:
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
<BodyTrigger move="jump" view={{ visible: 0.3, edge: 0.05 }} onBegin={hop} />
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The leg poses (`squat`, `leanLeft`, `leanRight`, `oneLeg`, `star`) use BodyInstruction's own check
|
|
111
|
+
(visibility at least `BODY_SHAPE_LIMITS.visible`, 0.5). The trigger reports what it needs:
|
|
112
|
+
|
|
113
|
+
- `state.view`: `"full"` (needs the whole body) or `"upper"`.
|
|
114
|
+
- `state.inView`: whether what it needs is in view now.
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
const jump = useBodyTrigger({ move: "jump", onBegin: hop });
|
|
118
|
+
// Show "Step back so your whole body is in view" while this is true.
|
|
119
|
+
const needsStepBack = jump.view === "full" && !jump.inView;
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Leaving view while a move is active is tracking loss: after `lostGraceMs` it ends with
|
|
123
|
+
`endReason: "lost"`, and the move's memory starts fresh when the body is back.
|
|
124
|
+
|
|
125
|
+
## Thresholds
|
|
126
|
+
|
|
127
|
+
Arm moves measure in shoulder widths (like BodyInstruction's classifier). Leg moves measure vertical
|
|
128
|
+
against vertical (torso length, the standing shin), so distance from the camera and the frame's aspect
|
|
129
|
+
ratio cancel. Defaults are in `BODY_MOVE_LIMITS`; each move lists the keys it reads in
|
|
130
|
+
`BODY_MOVES[name].limitKeys`. Override per trigger:
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
<BodyTrigger move="jump" limits={{ jumpRise: 0.2 }} onBegin={hop} />
|
|
134
|
+
<BodyTrigger move="squat" limits={{ squatDown: 0.75 }} onBegin={rep} /> {/* shallower squats count */}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
| Key | Default | Meaning |
|
|
138
|
+
| ----------------------------------------------------------------- | -------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
139
|
+
| `jumpRise` / `jumpLand` | 0.12 / 0.06 | take-off rise and landing tolerance, torso lengths |
|
|
140
|
+
| `jumpMaxAirMs` / `jumpLevelMs` | 900 / 300 | longest air time; how fast the standing level follows slow drift |
|
|
141
|
+
| `squatDown` / `squatUp` | 0.6 / 0.85 | thigh height ÷ shin height at the bottom / back up (standing ≈ 1) |
|
|
142
|
+
| `waveForearmUp`, `waveAmplitude`, `waveReversals`, `waveWindowMs` | 0.25, 0.3, 3, 1500 | forearm raised; swing between turning points; turning points within the window |
|
|
143
|
+
| `clapApart`, `clapTogether`, `clapWithinMs`, `clapRelease` | 0.6, 0.3, 250, 0.45 | hands apart, then together within the time; parted again |
|
|
144
|
+
| `punchBent`, `punchStraight`, `punchWithinMs`, `punchBand` | 0.75, 0.93, 200, 0.9 | arm straightness (shoulder → wrist ÷ arm length, in 3D) from bent to straight; wrist near shoulder height |
|
|
145
|
+
| `flapStroke`, `flapWithinMs`, `flapTop`, `flapOut` | 0.7, 500, −0.4, 0.3 | both wrists drop this far, from a top near shoulder level, out to the sides |
|
|
146
|
+
| `kickLift`, `kickKnee`, `kickShin`, `kickWithinMs` | 0.35, 0.15, 0.6, 600 | foot and knee above the standing ones; the foot not hanging under the knee |
|
|
147
|
+
| `stepShift`, `stepWithinMs` | 0.5, 700 | sideways travel of hips and feet, shoulder widths |
|
|
148
|
+
| `marchLift`, `marchDrop`, `marchWithinMs` | 0.2, 0.08, 1200 | knee or foot above the other one; alternation window |
|
|
149
|
+
|
|
150
|
+
For poses, `limits` also takes BodyInstruction's classifier thresholds (`BODY_SHAPE_LIMITS` keys).
|
|
151
|
+
The lifecycle options are the gesture engine's (`enterThreshold`, `exitThreshold`, `holdMs`,
|
|
152
|
+
`cooldownMs`, `minConfidence`, `lostGraceMs`), per trigger.
|
|
153
|
+
|
|
154
|
+
## Options
|
|
155
|
+
|
|
156
|
+
`useBodyTrigger({ pose | move, … })` and `<BodyTrigger … />` take:
|
|
157
|
+
|
|
158
|
+
- `pose` or `move` (exactly one).
|
|
159
|
+
- `side`: `"either"` (default), `"left"`, `"right"`.
|
|
160
|
+
- `limits`: `Partial<BodyMoveLimits & BodyShapeLimits>`.
|
|
161
|
+
- `view`: `Partial<BodyMoveViewLimits>` (`{ visible, edge }`, the leg moves' view gate).
|
|
162
|
+
- The lifecycle options above.
|
|
163
|
+
- `bodyIndex` (default 0), `active` (default `true`; `false` pauses and releases the body model),
|
|
164
|
+
`targetFps`.
|
|
165
|
+
- `onBegin`, `onEnd`, `onChange`: called from the frame loop with that frame's `BodyTriggerState`.
|
|
166
|
+
|
|
167
|
+
`BodyTriggerState` is `GestureState` (`active`, `value`, `confidence`, `tracked`, `phase`,
|
|
168
|
+
`justBegan`, `justEnded`, `endReason`, `startedAtMs`, `durationMs`, `count`) plus `kind`
|
|
169
|
+
(`"pose"` | `"move"`), `view`, `inView` and `side`.
|
|
170
|
+
|
|
171
|
+
## Custom moves
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import { defineBodyMove } from "@vincentt-xr/sdk/tracking";
|
|
175
|
+
|
|
176
|
+
// Both wrists above the head, then down below the hips within a second: a "touch the floor".
|
|
177
|
+
const touchFloor = defineBodyMove({
|
|
178
|
+
name: "touchFloor",
|
|
179
|
+
label: "Touch the floor",
|
|
180
|
+
description: "Hands from overhead to below the knees within 1 s.",
|
|
181
|
+
view: "full",
|
|
182
|
+
createMemory: () => ({ upAt: -Infinity }),
|
|
183
|
+
measure: (frame, memory, nowMs) => {
|
|
184
|
+
const { joints: j } = frame;
|
|
185
|
+
if (j.leftWrist.y > j.nose.y && j.rightWrist.y > j.nose.y) memory.upAt = nowMs;
|
|
186
|
+
const down = j.leftWrist.y < j.leftKnee.y && j.rightWrist.y < j.rightKnee.y;
|
|
187
|
+
return { value: down && nowMs - memory.upAt < 1000 ? 1 : 0 };
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
<BodyTrigger move={touchFloor} onBegin={celebrate} />;
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
`measure(frame, memory, nowMs, { side, limits })` runs once per new tracker sample of a body in
|
|
195
|
+
view and returns `{ value, side? }` (`value` ≥ 0.5 while the move is happening, for the default
|
|
196
|
+
thresholds). `frame` (`BodyMoveFrame`) carries BodyInstruction's `shape`, the person's own `joints`
|
|
197
|
+
(`joints.leftWrist` is their left wrist) in square units (x multiplied by the frame's aspect, so x and
|
|
198
|
+
y compare), `visibility` and `seen` per joint (the view gate above), `shoulderWidth`, `torso`
|
|
199
|
+
(vertical shoulder-to-hip length), `leftward` (the tracker-x direction of the person's left),
|
|
200
|
+
`upperInView`, `fullInView` and `aspect`. Memory is recreated whenever the body is lost or leaves
|
|
201
|
+
view. Define moves at module scope: a definition is keyed by its `name`.
|
|
202
|
+
|
|
203
|
+
The pure layer is on `@vincentt-xr/sdk/low-level` for tests and custom runners:
|
|
204
|
+
`createBodyMoveFrame(landmarks, { mirrored, visibility, aspect, view })`, `createBodyTrigger(target, options)`,
|
|
205
|
+
`stepBodyTrigger(machine, frame | null, nowMs, fresh?)`, `snapshotBodyTriggerState`,
|
|
206
|
+
`bodyTriggerStatesEqual`, `setBodyTriggerOptions`, `resolveBodyTriggerOptions`,
|
|
207
|
+
`resolveBodyMoveLimits`, `BODY_POSE_TRIGGER_DEFAULTS`, `sideJoint` and `TimedSeries` (windowed
|
|
208
|
+
min / max over a fixed ring, for custom moves).
|
|
209
|
+
|
|
210
|
+
## Performance
|
|
211
|
+
|
|
212
|
+
All body triggers read one shared body model; each tracker sample is analysed once and shared by
|
|
213
|
+
every trigger reading it. Moves keep a short fixed-size history and measure only new tracker samples,
|
|
214
|
+
not every rendered frame.
|
|
215
|
+
|
|
216
|
+
## Manual validation
|
|
217
|
+
|
|
218
|
+
Run `/gestures` (webcam by default; the fallback clip shows a full body). The body triggers section
|
|
219
|
+
lists every pose and move with a light and, for moves, a count.
|
|
220
|
+
|
|
221
|
+
| Case | Steps | Expect |
|
|
222
|
+
| ---------------- | ----------------------------------------------------------- | -------------------------------------------------------------- |
|
|
223
|
+
| Poses | hold a T-pose, hands up, hands on hips, arms crossed, squat | That row lights while held, off when released |
|
|
224
|
+
| Jump | stand back (whole body in view), jump three times | `jump` ×3; no `squat`, `march` or `step` |
|
|
225
|
+
| Squat reps | three squats | `squat` ×3, counted at the bottom |
|
|
226
|
+
| Wave | wave with your left hand, `side` = right | No count; set `side` = left, it counts with side `left` |
|
|
227
|
+
| Clap | clap four times | `clap` ×4; slowly pressing the palms together: no count |
|
|
228
|
+
| Punch | jab at the camera with each hand | `punch` counts with the right side |
|
|
229
|
+
| Arm flap | flap both arms like wings | `armFlap` counts each downstroke |
|
|
230
|
+
| Kick, march | kick once; then march in place | `kick` ×1; `march` counts steps, `kick` stays still |
|
|
231
|
+
| Steps | step to your left, then to your right | `stepLeft` then `stepRight`, on the webcam and rear camera |
|
|
232
|
+
| Legs out of view | come close so only the upper body shows | Leg rows turn amber ("needs full body") and never count |
|
|
233
|
+
| Fallback clip | "Person Fullbody" (portrait, standing still) | No pose lit (not `squat`); leg rows in view, counts at 0 |
|
|
234
|
+
| Feed shape | switch the stage between portrait and landscape | The same poses light; the "leg view gate" readout says in view |
|
|
@@ -128,7 +128,7 @@ next to `XRErrorReason`, for callers that classify their own
|
|
|
128
128
|
|
|
129
129
|
## Manual validation
|
|
130
130
|
|
|
131
|
-
Run `/camera
|
|
131
|
+
Run `/camera`:
|
|
132
132
|
|
|
133
133
|
| Case | Steps | Expect |
|
|
134
134
|
| ------------ | ----------------------------------------- | ----------------------------------------------------------------- |
|
|
@@ -80,10 +80,13 @@ less than the frame (zoom > 1 never does; a contain-shaped source does);
|
|
|
80
80
|
|
|
81
81
|
- Positions never need a flip: landmarks already live in the (possibly
|
|
82
82
|
mirrored) feed, and the feed is what you see.
|
|
83
|
-
- **Direction signs** do.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
- **Direction signs and side names** do. Every SDK left / right is the
|
|
84
|
+
person's own side on every source (GROUNDING "Left and right"); MediaPipe's
|
|
85
|
+
own sides (landmark indices, labels, blendshape names) are swapped on the
|
|
86
|
+
mirrored webcam. The SDK corrects them with `isMirroredSourceKind(sourceKind)`
|
|
87
|
+
/ `useXRMirrored()`; for your own reads use `personSide(side, mirrored)`,
|
|
88
|
+
`feedSidedName(name, mirrored)` and `personLeftSign(mirrored)` from
|
|
89
|
+
`@vincentt-xr/sdk`, never `sourceKind === "webcam"` inline.
|
|
87
90
|
- `mirrorFeedX` flips a feed point's x (for a direction vector, or to compare
|
|
88
91
|
a selfie feed with a straight recording).
|
|
89
92
|
|
|
@@ -50,7 +50,8 @@ unprojected to the scene lands where the preview shows it on every camera.
|
|
|
50
50
|
Consumers never flip positions; `useXRMirrored()` (low-level, the same
|
|
51
51
|
answer as `isMirroredSourceKind(sourceKind)`) is for _direction_ semantics
|
|
52
52
|
only, such as which hand is the person's left. Every tracker and the
|
|
53
|
-
coordinate toolkit already key off the kind
|
|
53
|
+
coordinate toolkit already key off the kind, so every SDK left / right is the
|
|
54
|
+
person's own side on every camera (GROUNDING "Left and right").
|
|
54
55
|
|
|
55
56
|
## Orientation
|
|
56
57
|
|
|
@@ -76,7 +77,7 @@ on the face through a rotation and a camera switch. Use
|
|
|
76
77
|
|
|
77
78
|
## Manual validation
|
|
78
79
|
|
|
79
|
-
Run `/camera
|
|
80
|
+
Run `/camera` on a phone:
|
|
80
81
|
|
|
81
82
|
| Case | Steps | Expect |
|
|
82
83
|
| ------------------- | ----------------------------------- | ---------------------------------------------------------------------- |
|
|
@@ -32,11 +32,10 @@ from final preview/runtime surfaces.
|
|
|
32
32
|
|
|
33
33
|
## In-repo examples
|
|
34
34
|
|
|
35
|
-
- `/viewport-editor`: general 3D scene-object editor.
|
|
36
35
|
- `/unified-architecture`: unified face-tracking scene using
|
|
37
36
|
`XRSceneEditorProvider`, `XRSceneViewport`, hierarchy, inspector, toolbar, and
|
|
38
37
|
media switching.
|
|
39
|
-
- `/
|
|
38
|
+
- `/face-mesh?faces=two`: multi-face face mesh setup backed by the same reusable
|
|
40
39
|
editor primitives.
|
|
41
40
|
- `/debugger`: debugger overlay mounted beside a minimal tracked scene.
|
|
42
41
|
|
|
@@ -129,6 +128,28 @@ It renders sections for components present on the selected object:
|
|
|
129
128
|
|
|
130
129
|
All edits route through `onComponentChange` or `onObjectChange`.
|
|
131
130
|
|
|
131
|
+
## Docked windows
|
|
132
|
+
|
|
133
|
+
The hierarchy and inspector float by default: draggable glass cards over the
|
|
134
|
+
page. To put them in your own layout — a side panel or a settings drawer — pass
|
|
135
|
+
`docked`. A docked window renders in place: no portal, no fixed position, no
|
|
136
|
+
dragging. It takes the container's width, grows with its content, and drops the
|
|
137
|
+
glass card so it blends into the host.
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
<XRSceneEditorProvider defaultStore={store}>
|
|
141
|
+
<aside className="my-side-panel">
|
|
142
|
+
<SceneHierarchyPanel docked />
|
|
143
|
+
<SceneInspectorPanel docked />
|
|
144
|
+
</aside>
|
|
145
|
+
<XRSceneViewport />
|
|
146
|
+
</XRSceneEditorProvider>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The provider must wrap the layout that hosts the docked panels. `docked` also
|
|
150
|
+
works on `HierarchyPanel`, `ObjectInspectorPanel`, `ScreenImageSettingsPanel`,
|
|
151
|
+
`ScreenTextSettingsPanel`, `ProductHotspotPanel` and `XRDiagnosticsPanel`.
|
|
152
|
+
|
|
132
153
|
## `ViewportToolbar`
|
|
133
154
|
|
|
134
155
|
Small optional toolbar for transient viewport controls.
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "External Face Mesh"
|
|
3
|
+
description: "Wear your own head or face model on the tracked face: it follows the head pose and the face's expression, with any topology and UV layout."
|
|
4
|
+
sidebarTitle: "External Face Mesh"
|
|
5
|
+
icon: "masks-theater"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
`ExternalFaceMesh` puts your own face model on the tracked face. It follows the head pose and the
|
|
9
|
+
face's expression in two ways at once:
|
|
10
|
+
|
|
11
|
+
- **Landmarks:** the tracked landmarks bend the mesh, so the jaw opens and the lips and cheeks move.
|
|
12
|
+
- **Morphs:** the model's own ARKit-named morph targets play the face's blendshapes. That gives an
|
|
13
|
+
authored blink and raised brows, and the eyeballs turn with the gaze.
|
|
14
|
+
|
|
15
|
+
It is the foundation of the face-character pipeline
|
|
16
|
+
([#194](https://github.com/vincentt-xr/sdk/issues/194)). Expression controllers, pinned accessories
|
|
17
|
+
and face reprojection build on the same `FaceRig`.
|
|
18
|
+
|
|
19
|
+
Import from `@vincentt-xr/sdk/face-effects`.
|
|
20
|
+
|
|
21
|
+
## Quick start
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { useLoader } from "@react-three/fiber";
|
|
25
|
+
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
26
|
+
import { FaceTracker } from "@vincentt-xr/sdk/tracking";
|
|
27
|
+
import { ExternalFaceMesh } from "@vincentt-xr/sdk/face-effects";
|
|
28
|
+
|
|
29
|
+
const Character = () => {
|
|
30
|
+
const head = useLoader(GLTFLoader, headUrl); // authored in canonical centimetres
|
|
31
|
+
return (
|
|
32
|
+
<FaceTracker>
|
|
33
|
+
<ExternalFaceMesh model={head.scene} />
|
|
34
|
+
</FaceTracker>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
It reads the parent `FaceTracker`'s face (or a `HeadBinding`'s) and never acquires the face model
|
|
40
|
+
itself. The model is cloned with its geometry, so one loaded model can back several faces.
|
|
41
|
+
|
|
42
|
+
## Authoring the model
|
|
43
|
+
|
|
44
|
+
Author the model in the **canonical head frame**, the same frame as `CanonicalHeadFrame` and the v3
|
|
45
|
+
head occluder `.blend` in `assets-src/head-occluder/`:
|
|
46
|
+
|
|
47
|
+
- **Units and axes:** centimetres, +Y up, +Z out of the face toward the camera.
|
|
48
|
+
- **Origin:** landmark 4, just above the nose tip, sits at `(0, -0.46, 7.59)`.
|
|
49
|
+
|
|
50
|
+
The easiest way is to open the occluder `.blend` and fit your head over it. Its first 468 vertices
|
|
51
|
+
are the tracked face landmarks, so the eyes, nose and mouth line up when your model sits on them.
|
|
52
|
+
|
|
53
|
+
Any topology and any UV layout works. The face area should lie close to the canonical face surface:
|
|
54
|
+
the closer it is, the more of the face follows the expression. The rest (skull, ears, neck,
|
|
55
|
+
accessories) can go anywhere and stays rigid.
|
|
56
|
+
|
|
57
|
+
## How it follows the face
|
|
58
|
+
|
|
59
|
+
**What drives it** is set by `drive`:
|
|
60
|
+
|
|
61
|
+
| `drive` | What moves it |
|
|
62
|
+
| ------------------ | ---------------------------------------------------------------------------------------------------------------- |
|
|
63
|
+
| `"auto"` (default) | `"morphs"` for a full ARKit set (mouth morphs too), `"hybrid"` with only eye or brow morphs, else `"landmarks"`. |
|
|
64
|
+
| `"hybrid"` | Landmarks for the jaw, lips and cheeks; the model's morphs for the eyes and brows. |
|
|
65
|
+
| `"morphs"` | Only the model's morph targets, driven by the blendshapes; otherwise just the head pose. |
|
|
66
|
+
| `"landmarks"` | Only the landmarks bend the mesh. |
|
|
67
|
+
| `"none"` | The head pose only. |
|
|
68
|
+
|
|
69
|
+
For a model with a full ARKit set, such as Face Cap's, the authored morphs look best, so `"auto"`
|
|
70
|
+
picks `"morphs"`. Binding then plays no part, because nothing is bent.
|
|
71
|
+
|
|
72
|
+
Why hybrid for eye and brow morphs: MediaPipe only tracks the edge of each eyelid, 16 points around each eye. Bending a
|
|
73
|
+
sculpted lid with those points drags its edge down without rolling the lid over the eyeball. That
|
|
74
|
+
leaves slits at the corners and creases the lid. An authored `eyeBlink` morph closes it cleanly, so
|
|
75
|
+
hybrid masks the eye and brow landmarks (`FACE_REGION_MASKS`) and lets the morphs move those parts.
|
|
76
|
+
|
|
77
|
+
**Morph names** map to MediaPipe's 51 blendshape channels (`FACE_MORPH_NAMES`, ARKit names). The
|
|
78
|
+
match accepts:
|
|
79
|
+
|
|
80
|
+
- ARKit names, e.g. `eyeBlinkLeft`;
|
|
81
|
+
- Face Cap and Blender styles, e.g. `eyeBlink_L`, `eyeBlink.L`, `eyeBlink_left`;
|
|
82
|
+
- any case;
|
|
83
|
+
- exporter prefixes such as `blendShape1.`.
|
|
84
|
+
|
|
85
|
+
`Left` is the model's own left (landmark 263's side, MediaPipe's left), as in ARKit. It is driven
|
|
86
|
+
mesh to mesh, so the model's eye in front of the person's blinking eye blinks on every feed (on the
|
|
87
|
+
mirrored webcam that is MediaPipe's right channel for the person's real left eye; GROUNDING "Left
|
|
88
|
+
and right"). MediaPipe has no `tongueOut`.
|
|
89
|
+
Morphs that no channel drives are left alone, so your own animation keeps them. The model's rest pose
|
|
90
|
+
must have every morph at 0.
|
|
91
|
+
|
|
92
|
+
**Binding** happens once, at load. Each vertex is bound to a point on the canonical face surface,
|
|
93
|
+
which is MediaPipe's 853 face triangles. The mouth and eye openings are holes, so a lip never binds
|
|
94
|
+
across the mouth. `binding` picks how:
|
|
95
|
+
|
|
96
|
+
| `binding` | Binds by |
|
|
97
|
+
| ------------------ | ------------------------------------------------------------------------------------ |
|
|
98
|
+
| `"auto"` (default) | UV when the mesh's UVs are a canonical layout (most UV hits agree with 3D), else 3D. |
|
|
99
|
+
| `"uv"` | UV only, for a mesh whose face UVs follow `CANONICAL_FACE_UVS` (either v direction). |
|
|
100
|
+
| `"surface"` | The closest point in 3D. Any topology and layout. |
|
|
101
|
+
|
|
102
|
+
**Influence** depends on how far a vertex sits from the face surface. Within `falloff[0]` (0.8 cm)
|
|
103
|
+
it follows fully; it fades to rigid at `falloff[1]` (2.5 cm). The back of the head, the ears and the
|
|
104
|
+
neck therefore stay rigid.
|
|
105
|
+
|
|
106
|
+
**Parts:** each mesh of the model follows in one of three ways (`parts`, by object name):
|
|
107
|
+
|
|
108
|
+
- `"surface"`: every vertex follows its own point. Use it for skin.
|
|
109
|
+
- `"follow"`: the whole mesh moves as one with the point under its centre, keeping its shape. Use
|
|
110
|
+
it for eyeballs, teeth or a nose ring. A follow part named like an eye (`eye…`) also turns with
|
|
111
|
+
the gaze (`eyeLookIn/Out/Up/Down`, up to `gazeDegrees` = `[25, 20]`).
|
|
112
|
+
- `"rigid"`: head pose only. Use it for a helmet or hair.
|
|
113
|
+
|
|
114
|
+
By default, a mesh whose median vertex sits more than 0.3 cm behind the face (eyeballs, teeth) is
|
|
115
|
+
`"follow"`, and everything else is `"surface"`.
|
|
116
|
+
|
|
117
|
+
**Neutral.** Only the expression moves the model, not the person's own face shape or resting
|
|
118
|
+
expression. With `neutral: "auto"` (default), the rig averages the landmarks and the blendshape
|
|
119
|
+
scores over the first `neutralMs` (600 ms) after the face is found, and subtracts that rest face. The
|
|
120
|
+
blendshapes are rescaled, so a resting 0.1 reads 0 and a full blink still reads 1. It recaptures every time the face is found again, and when
|
|
121
|
+
`neutralKey` changes: bind it to a "Recalibrate" button and ask the person to relax and look at the
|
|
122
|
+
camera. With `neutral: "none"` the model also takes on the person's face shape (wider eyes, a longer
|
|
123
|
+
jaw).
|
|
124
|
+
|
|
125
|
+
## `ExternalFaceMesh`
|
|
126
|
+
|
|
127
|
+
| Prop | Default | What it does |
|
|
128
|
+
| --------------------- | ------------- | ------------------------------------------------------------------------------------------- |
|
|
129
|
+
| `model` | — | The face model (e.g. a GLTF scene) in the canonical head frame. |
|
|
130
|
+
| `drive` | `"auto"` | What moves it: `"auto"`, `"hybrid"`, `"morphs"`, `"landmarks"` or `"none"`. |
|
|
131
|
+
| `binding` | `"auto"` | `"auto"`, `"uv"` or `"surface"`. |
|
|
132
|
+
| `falloff` | `[0.8, 2.5]` | Full influence up to the first distance (cm), rigid beyond the second. |
|
|
133
|
+
| `parts` | auto | Per mesh name: `"surface"`, `"follow"` or `"rigid"`. |
|
|
134
|
+
| `expression` | `1` | 0 = rigid, 1 = the tracked face, > 1 exaggerates. |
|
|
135
|
+
| `morphGain` | — | A gain per channel on its morph, e.g. `{ eyeBlinkLeft: 1.2 }`. |
|
|
136
|
+
| `gazeDegrees` | `[25, 20]` | How far a full look turns an eyeball: sideways, up/down (degrees). |
|
|
137
|
+
| `onBind` | — | Called once per model with every mesh's binding (readouts, debug views). |
|
|
138
|
+
| `faceIndex` | the tracker's | Which tracked face (when not inside a `FaceRig`; likewise the rows below). |
|
|
139
|
+
| `smoothing` | `0.5` | Head pose EMA while still (`1` = none). Fast turns follow at once, so a shake never trails. |
|
|
140
|
+
| `expressionSmoothing` | `0.6` | Expression EMA, `1` = none. MediaPipe's depth is noisy; a little keeps the mesh calm. |
|
|
141
|
+
| `holdMs` | `250` | Keep the last pose and expression through shorter dropouts. |
|
|
142
|
+
| `neutral` | `"auto"` | `"auto"` subtracts the captured rest face; `"none"` keeps the person's face shape. |
|
|
143
|
+
| `neutralMs` | `600` | How long the neutral capture averages. |
|
|
144
|
+
| `neutralKey` | — | A new value captures the neutral again. |
|
|
145
|
+
| `leadMs` | `0` | Landmark lead between inferences (One Euro + velocity, at most this long). 0 = raw. |
|
|
146
|
+
| `onTrackingChange` | — | Called once on found (`true`) and once on lost (`false`). |
|
|
147
|
+
| `children` | — | More content in the canonical head frame. |
|
|
148
|
+
|
|
149
|
+
## `FaceRig`
|
|
150
|
+
|
|
151
|
+
`FaceRig` is the engine underneath, and every face-character component shares one. It is a group in
|
|
152
|
+
the canonical head frame, like `CanonicalHeadFrame`, that also publishes the face's expression. Put
|
|
153
|
+
several components inside one `FaceRig` to share it:
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
<FaceTracker>
|
|
157
|
+
<FaceRig neutralKey={recalibrations}>
|
|
158
|
+
<ExternalFaceMesh model={head.scene} />
|
|
159
|
+
<ExternalFaceMesh model={beard.scene} />
|
|
160
|
+
</FaceRig>
|
|
161
|
+
</FaceTracker>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`useFaceRig()` returns a ref to the live `FaceRigState`. Read it inside `useFrame`:
|
|
165
|
+
|
|
166
|
+
- `tracking`: `"tracked"`, `"held"` or `"lost"`.
|
|
167
|
+
- `pose`: `{ position, quaternion, scale }`, canonical cm → world.
|
|
168
|
+
- `local`: the 468 landmarks in the head frame (cm).
|
|
169
|
+
- `residual`: the expression, as each landmark's offset from the rest face (cm, 468 × 3).
|
|
170
|
+
- `morphs`: the 51 blendshape channels (0..1, neutral removed).
|
|
171
|
+
- `neutral`, `morphNeutral` and `neutralState`.
|
|
172
|
+
|
|
173
|
+
The rig holds its last state through dropouts shorter than `holdMs`, hides when the face is lost,
|
|
174
|
+
and snaps on reacquire.
|
|
175
|
+
|
|
176
|
+
The pure pieces are exported for custom renderers:
|
|
177
|
+
|
|
178
|
+
- `stepFaceRig(state, worldLandmarks, nowMs, options, scores)`, `createFaceRigState()` and
|
|
179
|
+
`recalibrateFaceRig(state)`.
|
|
180
|
+
- `bindFaceMesh(positionsCm, uvs, { mode, falloff, uvTolerance })` and
|
|
181
|
+
`deformFaceMesh(binding, rest, residual, out, amount, toLocal)`.
|
|
182
|
+
- `bindFaceModel(root, options)`, `planFaceDrive(meshes, mode)` and
|
|
183
|
+
`driveFaceModel(meshes, plan, rig, options)`.
|
|
184
|
+
- `faceMorphChannel(name)`, `faceMorphRegion`, `FACE_GAZE_CHANNELS` and `FACE_REGION_MASKS`.
|
|
185
|
+
- The canonical data: `CANONICAL_FACE_POSITIONS`, `CANONICAL_FACE_TRIANGLES` and
|
|
186
|
+
`CANONICAL_FACE_UVS`.
|
|
187
|
+
|
|
188
|
+
## Example
|
|
189
|
+
|
|
190
|
+
`/external-face-mesh` wears the three.js "facecap" head when it is present. The file goes in the
|
|
191
|
+
git-ignored `example/src/assets/models/local/facecap-canonical.glb`; it has no redistribution
|
|
192
|
+
licence, so it is never committed. That copy is prepared as follows:
|
|
193
|
+
|
|
194
|
+
- aligned to the canonical frame;
|
|
195
|
+
- ears raised to the anatomical height (brow to nose base);
|
|
196
|
+
- every morph zeroed at rest (the original kept a frame of its animation).
|
|
197
|
+
|
|
198
|
+
It carries all 52 ARKit morphs, of which 51 are tracked. Without it, the page uses the canonical
|
|
199
|
+
head.
|
|
200
|
+
|
|
201
|
+
The page has controls for:
|
|
202
|
+
|
|
203
|
+
- drive, binding, expression and falloff;
|
|
204
|
+
- a binding heat map (red follows, blue rigid);
|
|
205
|
+
- keeping the face shape;
|
|
206
|
+
- recalibrating the neutral;
|
|
207
|
+
- the head occluder and two faces.
|
|
208
|
+
|
|
209
|
+
## Manual visual test plan
|
|
210
|
+
|
|
211
|
+
Open `/external-face-mesh` on the webcam.
|
|
212
|
+
|
|
213
|
+
1. **Placement**: the model sits on your head, with its eyes, nose and mouth on yours, and stays
|
|
214
|
+
there as you turn and tilt.
|
|
215
|
+
2. **Neutral**: look at the camera relaxed when it appears. At rest it keeps its own shape: eyes
|
|
216
|
+
not stretched, jaw not lengthened. Tick "keep the person's face shape" and it conforms to yours;
|
|
217
|
+
untick it.
|
|
218
|
+
3. **Expression**: open your mouth (the jaw drops and the lips part, never stretching across), smile
|
|
219
|
+
(the mouth corners and cheeks move), raise your brows. With drive "none", nothing moves but the
|
|
220
|
+
pose.
|
|
221
|
+
4. **Blink and gaze** (facecap, drive "auto" = morphs): blink one eye, then both. The lid rolls down over the
|
|
222
|
+
eye and closes, with no slit at the corners and no crease. Look left, right, up and down: the
|
|
223
|
+
eyeballs turn with you. Open your mouth and smile: facecap's own jawOpen and smile shapes play.
|
|
224
|
+
Switch drive to "landmarks" to see the difference.
|
|
225
|
+
5. **Parts**: the eyes and teeth move as whole pieces, never squashed. The back of the head and the
|
|
226
|
+
ears stay rigid; the heat map shows red on the face fading to blue.
|
|
227
|
+
6. **Recalibrate**: start with your mouth open, then relax and press Recalibrate. The rest pose is
|
|
228
|
+
corrected.
|
|
229
|
+
7. **Dropouts**: a brief cover of the camera holds the head. Longer, and it hides, then snaps back
|
|
230
|
+
on reacquire.
|
|
231
|
+
8. **Two faces**: on the two-people image, each face wears its own copy.
|
|
@@ -37,21 +37,23 @@ const isPouting = hasFaceAction(face, "mouthPout");
|
|
|
37
37
|
|
|
38
38
|
## Actions
|
|
39
39
|
|
|
40
|
-
| Name | Meaning
|
|
41
|
-
| ------------------------------- |
|
|
42
|
-
| `browRaise` | Either brow is raised
|
|
43
|
-
| `eyeBlink` | Both eyes blink
|
|
44
|
-
| `eyeBlinkEither` | Either eye blinks
|
|
45
|
-
| `eyeBlinkLeft`, `eyeBlinkRight` |
|
|
46
|
-
| `mouthOpen` | Jaw opens
|
|
47
|
-
| `mouthPout` | Lips pucker
|
|
48
|
-
| `headUp`, `headDown` | Pitch from neutral
|
|
49
|
-
| `headTurnLeft`, `headTurnRight` | Yaw from neutral
|
|
50
|
-
| `headTiltLeft`, `headTiltRight` | Roll from neutral
|
|
40
|
+
| Name | Meaning |
|
|
41
|
+
| ------------------------------- | ---------------------------------------------------------------- |
|
|
42
|
+
| `browRaise` | Either brow is raised |
|
|
43
|
+
| `eyeBlink` | Both eyes blink |
|
|
44
|
+
| `eyeBlinkEither` | Either eye blinks |
|
|
45
|
+
| `eyeBlinkLeft`, `eyeBlinkRight` | The person's own left / right eye blinks |
|
|
46
|
+
| `mouthOpen` | Jaw opens |
|
|
47
|
+
| `mouthPout` | Lips pucker |
|
|
48
|
+
| `headUp`, `headDown` | Pitch from neutral |
|
|
49
|
+
| `headTurnLeft`, `headTurnRight` | Yaw from neutral, toward the person's own left / right |
|
|
50
|
+
| `headTiltLeft`, `headTiltRight` | Roll from neutral, toward the person's own left / right shoulder |
|
|
51
51
|
|
|
52
52
|
Blendshape values are in `[0, 1]`. Head values are non-negative radians. Up and
|
|
53
|
-
left follow the SDK convention and are positive before they
|
|
54
|
-
action magnitude.
|
|
53
|
+
the person's own left follow the SDK convention and are positive before they
|
|
54
|
+
are converted to an action magnitude. Left and right are the person's own side
|
|
55
|
+
on every feed: the mirrored webcam, the rear camera, images and video
|
|
56
|
+
(GROUNDING "Left and right").
|
|
55
57
|
|
|
56
58
|
## Neutral head pose
|
|
57
59
|
|
|
@@ -89,15 +91,17 @@ left, right, both, and either-eye movement cases. Use `mouthOpen`, `mouthPout`,
|
|
|
89
91
|
and `browRaise` for the matching physical movements. These actions report
|
|
90
92
|
observable pose/blendshape movement; they do not infer emotion.
|
|
91
93
|
|
|
92
|
-
Left/right blink names
|
|
93
|
-
|
|
94
|
+
Left/right blink names are the person's own eyes on every feed. Raw
|
|
95
|
+
`FaceInfo.blendshapes` keep MediaPipe's names (`eyeBlinkLeft` = MediaPipe's left
|
|
96
|
+
eye: the person's own left on an unmirrored feed, their right on the mirrored
|
|
97
|
+
webcam); the actions read the right one for `face.mirrored`.
|
|
94
98
|
The lifecycle guarantees one `stay` frame between `begin` and `end`, including
|
|
95
99
|
for a blink that drops below its release threshold on the next input frame.
|
|
96
100
|
|
|
97
101
|
For image-based happy, sad, angry, fear, disgust, surprise, neutral, and unknown
|
|
98
102
|
classification, use the separate `useFaceAttributeExpression` hook. The SDK
|
|
99
103
|
does not fabricate these labels from movement thresholds. The verified
|
|
100
|
-
`/
|
|
104
|
+
`/face-actions` page exposes both independent surfaces.
|
|
101
105
|
|
|
102
106
|
Use `/face-actions` to view every value, calibrate neutral pose, adjust the
|
|
103
107
|
selected action, and repeat the live verification checklist. All actions and
|
|
@@ -82,6 +82,6 @@ Without those headers, ONNX Runtime falls back to single-threaded WASM.
|
|
|
82
82
|
Treat classifications as model estimates of visible facial expression—not
|
|
83
83
|
ground-truth emotion, intent, identity, or mental state.
|
|
84
84
|
|
|
85
|
-
Use the verified `/
|
|
85
|
+
Use the verified `/face-actions` page to inspect the live winning
|
|
86
86
|
class and all seven probabilities. Its real-camera model flow, including every
|
|
87
87
|
expression class, was verified on 26 July 2026.
|
|
@@ -7,7 +7,9 @@ icon: "locate-fixed"
|
|
|
7
7
|
|
|
8
8
|
Use `TrackingAnchor` to attach content to semantic face locations. Build editor
|
|
9
9
|
dropdowns from `FACE_TARGETS`; do not copy landmark indices or invent target
|
|
10
|
-
strings. Left and right
|
|
10
|
+
strings. Left and right are the tracked person's own side on every feed (GROUNDING "Left and
|
|
11
|
+
right"): `face.leftEarlobe` is their real left ear lobe on the mirrored webcam (the screen's left)
|
|
12
|
+
and on a video (the screen's right).
|
|
11
13
|
|
|
12
14
|
## Presets
|
|
13
15
|
|
|
@@ -33,7 +35,7 @@ does not provide anatomical earlobe points.
|
|
|
33
35
|
## Custom points
|
|
34
36
|
|
|
35
37
|
For `face.custom`, pass `customAnchorPoint`. X and Y are clamped to `[-1, 1]`;
|
|
36
|
-
the origin is face center, X runs from the person's left to right, Y runs from
|
|
38
|
+
the origin is face center, X runs from the person's own left to right on every feed, Y runs from
|
|
37
39
|
chin to forehead, and positive Z points toward the camera.
|
|
38
40
|
|
|
39
41
|
```tsx
|