@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,323 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Instructions"
|
|
3
|
+
description: "Prompts that ask for a gesture, an expression or a pose with a 3D hint and your copy — ready-made presets, and every layer underneath open for your own vocabulary, detection, look and layout."
|
|
4
|
+
sidebarTitle: "Instructions"
|
|
5
|
+
icon: "person-chalkboard"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
An instruction asks the person to do something and waits until they do. It shows a 3D hint, puts
|
|
9
|
+
your copy under it, and completes once the pose has been held for `holdMs`. Everything lives in one door:
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import { … } from "@vincentt-xr/sdk/instructions";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
There are three ready-made presets:
|
|
16
|
+
|
|
17
|
+
- [Hand Instructions](/api/hand-instructions)
|
|
18
|
+
- [Face Instructions](/api/face-instructions)
|
|
19
|
+
- [Body Instructions](/api/body-instructions)
|
|
20
|
+
|
|
21
|
+
Each preset is built from four open layers, and you can use any layer on its own from outside the SDK.
|
|
22
|
+
|
|
23
|
+
| Layer | What you get |
|
|
24
|
+
| -------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
25
|
+
| **Vocabulary** | The built-in gestures, expressions and poses; `defineHandGesture` / `defineFaceExpression` / `defineBodyPose` for your own. |
|
|
26
|
+
| **Detection** | `useHandGesture`, `useFaceExpression`, `useBodyPose`, and `useInstructionHold` for any condition. |
|
|
27
|
+
| **Hint** | `HandGestureHint`, `FaceExpressionHint`, `BodyPoseHint` with `look` and `loop`, and the kit to build a hint on any model. |
|
|
28
|
+
| **Layout** | `<Instruction>`: any detector, any symbol, your text style, motion and proportions. |
|
|
29
|
+
|
|
30
|
+
The rest of this page goes from small changes to a fully custom prompt.
|
|
31
|
+
|
|
32
|
+
## 1. Restyle a preset
|
|
33
|
+
|
|
34
|
+
Every preset takes the same layout and text options, plus `look` and `loop` for its hint. Each is
|
|
35
|
+
merged over that preset's default, so you only write what you change.
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
<HandInstruction
|
|
39
|
+
gesture="peace"
|
|
40
|
+
model={hand.scene}
|
|
41
|
+
poses={hand.animations}
|
|
42
|
+
size={0.2} // a fraction of the screen height, or "sm" | "md" | "lg"
|
|
43
|
+
look={{
|
|
44
|
+
ghost: { color: "#7dd3fc", core: 0.35 }, // tint, opacity facing you, at the rim (`rim`), rim whitening
|
|
45
|
+
halo: false, // turn a layer off
|
|
46
|
+
glow: { color: "#38bdf8", full: 1 },
|
|
47
|
+
highlight: { opacity: 1 },
|
|
48
|
+
}}
|
|
49
|
+
loop={{ seconds: 1.6, stagger: 0 }} // timing, hold share, start, easing, finger stagger (hand)
|
|
50
|
+
textStyle={{ fontFamily: "Georgia, serif", strokeColor: "#0c4a6e", strokeWidth: 6 }}
|
|
51
|
+
motion={{ ring: { color: "#38bdf8" }, pop: 0.2, bob: 0 }}
|
|
52
|
+
layout={{ gap: 0.2, textHeight: 0.35 }}
|
|
53
|
+
/>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**`look`** (`HintLook`) controls how the hint is drawn:
|
|
57
|
+
|
|
58
|
+
- `ghost` (`GhostOptions`): `color`, `core` (opacity facing you), `rim` (opacity at the silhouette),
|
|
59
|
+
`whiten`.
|
|
60
|
+
- `parts`: overrides per model material name, e.g. `{ iris: { color: "#2a2732" } }`; `null` removes
|
|
61
|
+
a default tint.
|
|
62
|
+
- `halo`: `width` in model units, `color`, `opacity`.
|
|
63
|
+
- `glow`: `color`, `size`, `idle` and `full` opacity.
|
|
64
|
+
- `highlight`: `opacity`, `whiten`, and `idle` (the share shown while relaxed).
|
|
65
|
+
- `matcap`: your own shading texture.
|
|
66
|
+
- `material`: any three.js material, replacing the ghost.
|
|
67
|
+
|
|
68
|
+
Any layer can be `false` to turn it off. The defaults are exported:
|
|
69
|
+
|
|
70
|
+
- `HAND_HINT_LOOK` and `HAND_HINT_LOOP`
|
|
71
|
+
- `FACE_HINT_LOOK` and `FACE_HINT_LOOP`
|
|
72
|
+
- `BODY_HINT_LOOK` and `BODY_HINT_LOOP`
|
|
73
|
+
|
|
74
|
+
`mergeHintLook(base, over)` merges two looks the same way the presets do.
|
|
75
|
+
|
|
76
|
+
**`loop`** (`HintLoop`) controls how the hint animates:
|
|
77
|
+
|
|
78
|
+
- `seconds` per cycle; `0` holds the pose.
|
|
79
|
+
- `hold`: the share of the cycle held at the full pose.
|
|
80
|
+
- `from`: where each cycle starts, 0 = the model's rest.
|
|
81
|
+
- `easing`.
|
|
82
|
+
- The hand also takes `stagger`, how far apart the fingers move; `0` moves them together.
|
|
83
|
+
|
|
84
|
+
**Text and layout** apply to every preset and to `<Instruction>`:
|
|
85
|
+
|
|
86
|
+
- `textStyle` / `nudgeTextStyle`: any `TextLabel` style (font, weight, stroke, shadow, background),
|
|
87
|
+
merged over `INSTRUCTION_TEXT_STYLE`.
|
|
88
|
+
- `color`: a shortcut for the text colour.
|
|
89
|
+
- `motion` (`InstructionMotion`):
|
|
90
|
+
- `fadeIn` and `fadeOut`, in seconds;
|
|
91
|
+
- `rise`, `bob`, `pop`, `popSeconds` and `nudgePulse`;
|
|
92
|
+
- `ring`: `{ color, seconds, opacity, from, to }`, or `false`.
|
|
93
|
+
- `layout` (`InstructionLayout`): `textHeight`, `gap`, `nudgeHeight`, `textWidth` and `edgeMargin`.
|
|
94
|
+
Each is relative to the size, except `edgeMargin`, which is a fraction of the screen height.
|
|
95
|
+
- `renderText(slot)`: draw each line yourself. You get `{ text, role, width, height, renderOrder,
|
|
96
|
+
style }`. Use transparent materials, because the layout fades every mesh under it.
|
|
97
|
+
|
|
98
|
+
## 2. Your own gesture, expression or pose
|
|
99
|
+
|
|
100
|
+
A definition holds three things:
|
|
101
|
+
|
|
102
|
+
- its default copy (`label`);
|
|
103
|
+
- how it is detected: a `rule`, a `match` function, or both, in which case both must pass;
|
|
104
|
+
- how the hint shows it (`hint`).
|
|
105
|
+
|
|
106
|
+
Pass a definition anywhere a built-in name goes: the presets, the hooks, the hints and the pure
|
|
107
|
+
`match*` functions.
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
const hangLoose = defineHandGesture({
|
|
111
|
+
label: "Hang loose",
|
|
112
|
+
rule: { digits: { thumb: true, index: false, middle: false, ring: false, pinky: true } },
|
|
113
|
+
match: (shape) => shape.curl.pinky < 0.35, // and the pinky really straight
|
|
114
|
+
hint: { clip: "callMe", roll: 103, highlight: ["thumb", "pinky"] },
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const yawn = defineFaceExpression({
|
|
118
|
+
label: "Big yawn",
|
|
119
|
+
rule: { atLeast: { jawOpen: 0.7 } },
|
|
120
|
+
hint: { targets: { surprised: 1, smile: 0.3 } }, // a weighted mix of morph targets
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const flex = defineBodyPose({
|
|
124
|
+
label: "Show your muscles",
|
|
125
|
+
match: (shape) =>
|
|
126
|
+
shape.arms.left.bend > 70 && shape.arms.right.bend > 70 && shape.arms.left.up > 0,
|
|
127
|
+
hint: { clip: "flex", arms: ["left", "right"] }, // a clip in your own figure
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
<HandInstruction gesture={hangLoose} model={hand.scene} poses={hand.animations} />;
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The hint can name a clip in your own model:
|
|
134
|
+
|
|
135
|
+
- **Hand:** a `HandHintPose`: an authored `clip`, or a procedural pose (`curl`, `spread`,
|
|
136
|
+
`thumbTuck`, `thumbTo`), plus the view (`yaw`, `roll`, `aimThumb`) and `highlight`.
|
|
137
|
+
- **Face:** `{ target }` or `{ targets }`.
|
|
138
|
+
- **Body:** `{ clip, arms }`.
|
|
139
|
+
|
|
140
|
+
`resolveHandGesture`, `resolveFaceExpression` and `resolveBodyPose` turn a name or definition into
|
|
141
|
+
the full definition.
|
|
142
|
+
|
|
143
|
+
## 3. Tune detection
|
|
144
|
+
|
|
145
|
+
Every hook takes the same kinds of input:
|
|
146
|
+
|
|
147
|
+
- a built-in name;
|
|
148
|
+
- a rule;
|
|
149
|
+
- a match function:
|
|
150
|
+
- hand: `(shape, side) => boolean`;
|
|
151
|
+
- face: `(blendshapes, face) => boolean`;
|
|
152
|
+
- body: `(shape) => boolean`;
|
|
153
|
+
- a definition.
|
|
154
|
+
|
|
155
|
+
They also take `holdMs`, `graceMs`, `onComplete` and `active`.
|
|
156
|
+
|
|
157
|
+
The hand and body hooks take `limits`: thresholds overridden for that detector only. The defaults,
|
|
158
|
+
`HAND_SHAPE_LIMITS` and `BODY_SHAPE_LIMITS`, are frozen. The pure classifiers take them too:
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
const thumb = useHandGesture("thumbUp", { limits: { thumbVertical: 0.5 }, holdMs: 800 });
|
|
162
|
+
const shape = analyzeBodyShape(landmarks, { mirrored, limits: { raisedAboveShoulder: 1 } });
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Every hook returns an **`InstructionDetector`** plus its own readout (`shapesRef`, `faceRef`,
|
|
166
|
+
`shapeRef`):
|
|
167
|
+
|
|
168
|
+
- `status`: re-renders only when it changes;
|
|
169
|
+
- `holdRef`: `progress` 0..1;
|
|
170
|
+
- `matchedRef`: matched on this frame;
|
|
171
|
+
- `isInView()`;
|
|
172
|
+
- `reset()`.
|
|
173
|
+
|
|
174
|
+
**Any condition.** `useInstructionHold(match, options)` holds any test you write; `match` runs every
|
|
175
|
+
frame. To combine detectors, read their `matchedRef`s, and call those hooks first in the same
|
|
176
|
+
component:
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
const hand = useHandGesture("palm");
|
|
180
|
+
const face = useFaceExpression("smile");
|
|
181
|
+
const both = useInstructionHold(() => hand.matchedRef.current && face.matchedRef.current, {
|
|
182
|
+
isInView: () => hand.isInView() && face.isInView(),
|
|
183
|
+
holdMs: 600,
|
|
184
|
+
onComplete: start,
|
|
185
|
+
});
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
A new name, rule or definition value starts a new prompt. A match function is read live and doesn't
|
|
189
|
+
restart the hold. For a new prompt with the same function, call `reset()` or change the component's
|
|
190
|
+
React `key`.
|
|
191
|
+
|
|
192
|
+
## 4. A fully custom prompt: `<Instruction>`
|
|
193
|
+
|
|
194
|
+
The layout on its own: any detector, any symbol.
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
<Instruction
|
|
198
|
+
detector={both} // any hook result, or your own { status, isInView }
|
|
199
|
+
text="Wave and smile"
|
|
200
|
+
nudgeText="Show your hand and your face" // default null (no nudge) here
|
|
201
|
+
symbol={(height, renderOrder) => (
|
|
202
|
+
<TextLabel
|
|
203
|
+
text="🖐️😊"
|
|
204
|
+
bgColor="transparent"
|
|
205
|
+
aspect={2}
|
|
206
|
+
scale={[height * 2, height, 1]}
|
|
207
|
+
renderOrder={renderOrder}
|
|
208
|
+
/>
|
|
209
|
+
)}
|
|
210
|
+
renderText={({ text, width, height, renderOrder }) => (
|
|
211
|
+
<TextLabel
|
|
212
|
+
text={text}
|
|
213
|
+
bgColor="#fde68a"
|
|
214
|
+
color="#0f172a"
|
|
215
|
+
borderRadius={60}
|
|
216
|
+
bgFit="text"
|
|
217
|
+
aspect={width / height}
|
|
218
|
+
scale={[width, height, 1]}
|
|
219
|
+
renderOrder={renderOrder}
|
|
220
|
+
/>
|
|
221
|
+
)}
|
|
222
|
+
/>
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
It takes every option from section 1, plus `symbolAspect` (a taller slot, e.g. 2.1 for a standing
|
|
226
|
+
figure) and `active`. Mount it inside `XRScene`; it draws in its own `ScreenSpaceUI`, above the AR
|
|
227
|
+
content (`INSTRUCTION_RENDER_ORDER`, 2000 and up). The symbol can be:
|
|
228
|
+
|
|
229
|
+
- a preset hint, e.g. `HandGestureHint` with your definition and `look`;
|
|
230
|
+
- an image (`ScreenImage`), a `SpriteAnimation` or an emoji;
|
|
231
|
+
- your own 3D model.
|
|
232
|
+
|
|
233
|
+
## 5. A hint on your own model
|
|
234
|
+
|
|
235
|
+
The presets' hints are built from a small kit you can use on any model:
|
|
236
|
+
|
|
237
|
+
- **`useGhostModel(model, look, { base, renderOrder })`** makes a ghost copy of the model.
|
|
238
|
+
- It applies a matcap per part, a depth pre-pass, the halo and the glow, all from one `look`.
|
|
239
|
+
- It returns `object` to render, and `meshes` (each with its twins, which need the same morph
|
|
240
|
+
weights).
|
|
241
|
+
- `setHighlight(bone => 0..1)` lights up bones; call `setStrength(amount)` every frame.
|
|
242
|
+
- **`HintStage`** handles the staging. It fits `span` to `height`, mirrors the model, draws the glow
|
|
243
|
+
disc behind it and runs the auto orbit.
|
|
244
|
+
- **`sampleHintLoop(time, loop)`** samples the loop: rest → pose (held) → rest. It returns `{ amount,
|
|
245
|
+
drive, phase, closing }`.
|
|
246
|
+
- **`createClipBlend(root, fromClip, toClip)`** and **`createMorphBlend(meshes, targets)`** pose the
|
|
247
|
+
model; `apply(amount)` each frame.
|
|
248
|
+
- **`orbitSpan(points, middle, amplitude)`** fits the model over the whole orbit.
|
|
249
|
+
|
|
250
|
+
```tsx
|
|
251
|
+
const MyHint = ({ height, renderOrder }: { height: number; renderOrder: number }) => {
|
|
252
|
+
const ghost = useGhostModel(
|
|
253
|
+
face.scene,
|
|
254
|
+
{ ghost: { color: "#fde68a" } },
|
|
255
|
+
{ base: FACE_HINT_LOOK, renderOrder },
|
|
256
|
+
);
|
|
257
|
+
const blend = useMemo(
|
|
258
|
+
() =>
|
|
259
|
+
createMorphBlend(
|
|
260
|
+
ghost.meshes.flatMap(({ mesh, twins }) => [mesh, ...twins]),
|
|
261
|
+
{ surprised: 1, wink: 1 },
|
|
262
|
+
),
|
|
263
|
+
[ghost.meshes],
|
|
264
|
+
);
|
|
265
|
+
const frame = useMemo(() => {
|
|
266
|
+
const box = new THREE.Box3().setFromObject(ghost.object);
|
|
267
|
+
const size = box.getSize(new THREE.Vector3());
|
|
268
|
+
return {
|
|
269
|
+
offset: box.getCenter(new THREE.Vector3()).negate(),
|
|
270
|
+
span: Math.max(size.x, size.y) * 1.2,
|
|
271
|
+
};
|
|
272
|
+
}, [ghost.object]);
|
|
273
|
+
useFrame(({ clock }) => {
|
|
274
|
+
const { amount } = sampleHintLoop(clock.elapsedTime, { seconds: 2 });
|
|
275
|
+
blend.apply(amount);
|
|
276
|
+
ghost.setStrength(amount);
|
|
277
|
+
});
|
|
278
|
+
return (
|
|
279
|
+
<HintStage
|
|
280
|
+
height={height}
|
|
281
|
+
span={frame.span}
|
|
282
|
+
orbit={20}
|
|
283
|
+
glow={ghost.glowMaterial}
|
|
284
|
+
renderOrder={renderOrder}
|
|
285
|
+
>
|
|
286
|
+
<group position={frame.offset}>
|
|
287
|
+
<primitive object={ghost.object} />
|
|
288
|
+
</group>
|
|
289
|
+
</HintStage>
|
|
290
|
+
);
|
|
291
|
+
};
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
The material factories are exported for full control: `createGhostMaterial`, `createHaloMaterial`,
|
|
295
|
+
`createGlowMaterial`, `createDepthPrepassMaterial`, `createHintMatcap`, `addHintTwins` and
|
|
296
|
+
`assignHintMaterials`. Their opacities, colours and widths are uniforms (`userData.ghost`,
|
|
297
|
+
`userData.halo`). The hold timing is pure too: `createGestureHoldState`, `stepGestureHold`,
|
|
298
|
+
`GESTURE_HOLD_DEFAULT_MS` (400) and `GESTURE_HOLD_GRACE_MS` (150).
|
|
299
|
+
|
|
300
|
+
## Example
|
|
301
|
+
|
|
302
|
+
`/custom-instruction` has three demos, built only from this door:
|
|
303
|
+
|
|
304
|
+
1. **Hang loose:** a custom gesture on the hand preset, with a restyled look, loop, text style and
|
|
305
|
+
ring.
|
|
306
|
+
2. **Palm and smile:** an open palm and a smile held together. It uses an emoji symbol and a pill
|
|
307
|
+
text component.
|
|
308
|
+
3. **Surprised wink:** your own hint, mixing two morph targets, for an expression with a match
|
|
309
|
+
function.
|
|
310
|
+
|
|
311
|
+
## Manual visual test plan
|
|
312
|
+
|
|
313
|
+
Open `/custom-instruction`.
|
|
314
|
+
|
|
315
|
+
1. **Restyled preset**: the hang-loose hand is cyan with no halo and a blue glow. The thumb and
|
|
316
|
+
pinky are brighter, the fingers move together, and the text is a serif with a dark stroke. On the
|
|
317
|
+
webcam, do the gesture: a large cyan ring plays, and "Nice!" replaces the copy.
|
|
318
|
+
2. **Any condition**: the emoji pair stands over a yellow pill. Show an open palm only: it stays
|
|
319
|
+
`detected`. Then smile with the palm up: it holds, then completes.
|
|
320
|
+
3. **Own hint**: the gold face loops into a surprised wink with a dark-gold halo. A plain wink or a
|
|
321
|
+
plain open mouth doesn't complete it; both together do.
|
|
322
|
+
4. **Presets unchanged**: `/hand-instructions`, `/face-instructions` and `/body-instructions` look
|
|
323
|
+
and behave as before. The exception is peace, point and the counts, which now show the palm.
|
|
@@ -28,15 +28,19 @@ useFrame(() => {
|
|
|
28
28
|
|
|
29
29
|
## Landmarks and sides
|
|
30
30
|
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
| `left`
|
|
34
|
-
| `right`
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
| MediaPipe side | Center | Ring (outer, top, inner, bottom) | Inner / outer corner | Upper / lower lid |
|
|
32
|
+
| -------------- | ------ | -------------------------------- | -------------------- | ----------------- |
|
|
33
|
+
| `left` | 473 | 474, 475, 476, 477 | 362 / 263 | 386 / 374 |
|
|
34
|
+
| `right` | 468 | 469, 470, 471, 472 | 133 / 33 | 159 / 145 |
|
|
35
|
+
|
|
36
|
+
`result.left` / `result.right` are the person's own eyes on every source
|
|
37
|
+
(GROUNDING "Left and right"). The table lists MediaPipe's sides
|
|
38
|
+
(`IRIS_LANDMARKS`): its left eye sits on the image's right of the analysed
|
|
39
|
+
frame, which is the person's left eye on a straight video, image or rear
|
|
40
|
+
camera, and their RIGHT eye on the mirrored webcam. The SDK reads the mesh
|
|
41
|
+
eye for the feed (`IRIS_LANDMARKS[personSide(side, mirrored)]`), so app code
|
|
42
|
+
never swaps. The data needs the refined mesh (478 points); with fewer
|
|
43
|
+
landmarks each eye reports `detected: false`. The
|
|
40
44
|
allocation-free helpers behind the hook (`createIrisResult`,
|
|
41
45
|
`updateIrisResult`, `computeIrisEye`, `IrisLead`) live on
|
|
42
46
|
`@vincentt-xr/sdk/low-level` for pipelines that already hold their own
|
|
@@ -230,13 +234,14 @@ the example does.
|
|
|
230
234
|
|
|
231
235
|
Run `/iris-tracking`:
|
|
232
236
|
|
|
233
|
-
| Case | Steps | Expect
|
|
234
|
-
| -------------------- | --------------------------------------- |
|
|
235
|
-
| Shader material | default, change color / scale / opacity | Both irises recoloured live; pupil follows the iris offset
|
|
236
|
-
| Image material | mode `image`, presets or a URL | Image covers each iris, tinted by color; mirror flips it
|
|
237
|
-
| Custom material | "custom shader (ring)" | Pulsing ring from the shared uniforms
|
|
238
|
-
| Tracking loss | cover the face / "Person Shaking Head" | Effect holds ~250 ms then disappears; no stale eyes
|
|
239
|
-
| Multi-face | "Two People Smiling", face index 0 / 1 | Effect moves to the selected face
|
|
240
|
-
| Mirrored camera | webcam
|
|
241
|
-
|
|
|
242
|
-
|
|
|
237
|
+
| Case | Steps | Expect |
|
|
238
|
+
| -------------------- | --------------------------------------- | ------------------------------------------------------------- |
|
|
239
|
+
| Shader material | default, change color / scale / opacity | Both irises recoloured live; pupil follows the iris offset |
|
|
240
|
+
| Image material | mode `image`, presets or a URL | Image covers each iris, tinted by color; mirror flips it |
|
|
241
|
+
| Custom material | "custom shader (ring)" | Pulsing ring from the shared uniforms |
|
|
242
|
+
| Tracking loss | cover the face / "Person Shaking Head" | Effect holds ~250 ms then disappears; no stale eyes |
|
|
243
|
+
| Multi-face | "Two People Smiling", face index 0 / 1 | Effect moves to the selected face |
|
|
244
|
+
| Mirrored camera | webcam, `eye` left | Only your real left eye; on screen it is the eye on the left |
|
|
245
|
+
| Straight video | a clip, `eye` left | Only the person's real left eye; on screen it is on the right |
|
|
246
|
+
| Portrait / landscape | resize the pane | Quads stay centred on the irises at the right size |
|
|
247
|
+
| Closed eyes | blink | Effect fades with confidence |
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Made-up Camera"
|
|
3
|
+
description: "Give face insets, face textures and face swap the camera image with the makeup on it: one shared, opt-in, feed-size render of camera plus makeup."
|
|
4
|
+
sidebarTitle: "Made-up Camera"
|
|
5
|
+
icon: "wand-magic-sparkles"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Makeup is drawn over the live face in the main render. A component that samples the camera image
|
|
9
|
+
itself (a face inset, a face texture, a face swap's live source) therefore shows the bare face.
|
|
10
|
+
`<MadeUpCamera>` gives the components inside it the camera image with the makeup on it.
|
|
11
|
+
|
|
12
|
+
It is off unless mounted. While mounted it renders one feed-size texture of camera plus makeup per
|
|
13
|
+
frame, shared by every `<MadeUpCamera>`. Import from `@vincentt-xr/sdk/face-effects`.
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { Blush, FaceInset, LipEffect, MadeUpCamera } from "@vincentt-xr/sdk/face-effects";
|
|
19
|
+
import { FaceTracker } from "@vincentt-xr/sdk/tracking";
|
|
20
|
+
|
|
21
|
+
<FaceTracker>
|
|
22
|
+
<Blush />
|
|
23
|
+
<LipEffect preset="lipstick" shade="classicRed" />
|
|
24
|
+
<MadeUpCamera>
|
|
25
|
+
{/* The giant mouth wears the lipstick */}
|
|
26
|
+
<FaceInset part="mouth" magnify={1.8} />
|
|
27
|
+
</MadeUpCamera>
|
|
28
|
+
</FaceTracker>;
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## What follows it
|
|
32
|
+
|
|
33
|
+
Inside a `<MadeUpCamera>`:
|
|
34
|
+
|
|
35
|
+
| Component | What shows the makeup |
|
|
36
|
+
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| `FaceInset`, `useFaceInsetTexture` | The cut-out part |
|
|
38
|
+
| `FaceMorph`, `FaceReprojection` | The camera-face texture they wear |
|
|
39
|
+
| Face swap live faces | The face map. A face's map is shared: one consumer inside a `<MadeUpCamera>` decides for all of that face's consumers |
|
|
40
|
+
|
|
41
|
+
Components outside it keep the plain camera.
|
|
42
|
+
|
|
43
|
+
`FaceWarp3D` always keeps the plain camera. Nest the makeup in the warp instead: it already rides it.
|
|
44
|
+
|
|
45
|
+
The skin probe, the face swap's colour statistics and the makeup's own camera sampling always read the
|
|
46
|
+
plain camera, so makeup never feeds back into itself.
|
|
47
|
+
|
|
48
|
+
## What it holds
|
|
49
|
+
|
|
50
|
+
- Every face-atlas layer drawn between `MAKEUP_RENDER_ORDER.prepass` and `.restore`, on every face:
|
|
51
|
+
makeup regions, `LipEffect`, `MakeupDesign`, custom `FaceAtlasLayer`s at makeup orders, and the
|
|
52
|
+
self-occlusion passes.
|
|
53
|
+
- `HandCutout`, so hands stay bare.
|
|
54
|
+
- Anything you add with `object.layers.enable(MADE_UP_CAMERA_LAYER)` (layer 30; 31 is the external background layer).
|
|
55
|
+
|
|
56
|
+
Faces riding a `FaceWarp3D` or `FaceMorph` are drawn unwarped, where the camera sees them, with the
|
|
57
|
+
unwarped face's normals.
|
|
58
|
+
|
|
59
|
+
The pass is lit by the lights the main camera sees and writes and blends sRGB colour exactly as the
|
|
60
|
+
canvas does, with the same shader programs, so the makeup's pixels match the screen. It does not hold:
|
|
61
|
+
|
|
62
|
+
- `FaceRetouch`, face swaps or other face effects;
|
|
63
|
+
- face-atlas layers outside the makeup orders;
|
|
64
|
+
- the canvas's multisampling (antialiasing) or any post-processing.
|
|
65
|
+
|
|
66
|
+
## Double makeup
|
|
67
|
+
|
|
68
|
+
Makeup drawn on the same face again on top shows twice:
|
|
69
|
+
|
|
70
|
+
- makeup nested in a `FaceMorph` that is wrapped in `<MadeUpCamera>`;
|
|
71
|
+
- a wrapped face swap that lands on a face wearing makeup of its own (that makeup draws over the
|
|
72
|
+
swapped face).
|
|
73
|
+
|
|
74
|
+
Wrap only the components that should show the makeup.
|
|
75
|
+
|
|
76
|
+
## Your own materials
|
|
77
|
+
|
|
78
|
+
`useMadeUpCamera()` holds the shared target and returns a handle, or `null` before mount:
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { useMadeUpCamera } from "@vincentt-xr/sdk/face-effects";
|
|
82
|
+
|
|
83
|
+
const madeUp = useMadeUpCamera();
|
|
84
|
+
<mesh>
|
|
85
|
+
<planeGeometry />
|
|
86
|
+
<meshBasicMaterial map={madeUp?.ready ? madeUp.texture : null} toneMapped={false} />
|
|
87
|
+
</mesh>;
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
| Handle | Meaning |
|
|
91
|
+
| ----------------- | ---------------------------------------------------------------------------------------------------- |
|
|
92
|
+
| `texture` | Camera plus makeup. Same layout as the camera texture (uv, aspect, image top at v = 1), sRGB |
|
|
93
|
+
| `ready` | The texture holds the current camera image: false before the first pass and while the camera is gone |
|
|
94
|
+
| `frame` | Passes rendered so far |
|
|
95
|
+
| `width`, `height` | The texture's size: the camera image's |
|
|
96
|
+
|
|
97
|
+
- `useMadeUpCameraTexture()` returns the nearest `<MadeUpCamera>`'s texture while it is ready, else
|
|
98
|
+
the session camera texture (null without a camera, never a stale made-up frame). The SDK
|
|
99
|
+
components use it.
|
|
100
|
+
- `feedTextureVersion(texture)` returns a feed texture's content version: the pass count for the
|
|
101
|
+
made-up texture (its `version` never changes), `texture.version` for the camera. Compare it between
|
|
102
|
+
frames to skip work when the image did not change.
|
|
103
|
+
|
|
104
|
+
## Cost
|
|
105
|
+
|
|
106
|
+
Every frame while any holder is mounted:
|
|
107
|
+
|
|
108
|
+
- the makeup is drawn a second time;
|
|
109
|
+
- two feed-size passes: the camera copied under the makeup, then a copy into the sRGB texture;
|
|
110
|
+
- a second walk of the scene graph.
|
|
111
|
+
|
|
112
|
+
GPU memory: three 4-byte-per-pixel buffers at the camera image's size (colour, depth-stencil, output).
|
|
113
|
+
That is about 4 MB for a 390 × 844 feed and 25 MB at 1080 × 1920.
|
|
114
|
+
|
|
115
|
+
The pass runs at frame priority -0.3, after the face surfaces update. Frame callbacks at the default
|
|
116
|
+
priority read this frame's image. The face swap's live map (priority -0.75) reads the previous
|
|
117
|
+
frame's. Shadow maps are not re-rendered for the pass.
|
|
118
|
+
|
|
119
|
+
## Manual visual test plan
|
|
120
|
+
|
|
121
|
+
On the webcam, with blush and a red lipstick:
|
|
122
|
+
|
|
123
|
+
1. **Inset**: a mouth inset inside `<MadeUpCamera>` shows the lipstick, with the same colour and edge
|
|
124
|
+
as on the face. Outside it, the inset shows bare lips.
|
|
125
|
+
2. **Match**: put a `FaceInset part="face" magnify={1}` inside it. The face looks the same as without
|
|
126
|
+
the inset.
|
|
127
|
+
3. **Hands**: a hand over the cheek (with `HandCutout`) stays bare in the inset.
|
|
128
|
+
4. **Turned head**: the far cheek's blush stops at the nose in the inset, as on screen.
|
|
129
|
+
5. **Face swap**: with makeup on face 0 only, a two-person swap inside it shows that makeup where
|
|
130
|
+
face 1 is.
|
|
131
|
+
6. **Off**: unmount the `<MadeUpCamera>`. The frame time returns to its earlier value.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Makeup Skin Tone"
|
|
3
|
+
description: "Read the person's skin depth, undertone, lip and brow colours from the skin probe, and get the curated palette shades that suit them, for shade-finder UIs."
|
|
4
|
+
sidebarTitle: "Makeup Skin Tone"
|
|
5
|
+
icon: "swatchbook"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
`useMakeupSkinTone` reads the face's skin probe back from the GPU a few times a second and returns
|
|
9
|
+
what a shade finder needs:
|
|
10
|
+
|
|
11
|
+
- **Skin depth**: `fair`, `light`, `medium`, `tan`, `deep` or `rich`.
|
|
12
|
+
- **Undertone**: `cool`, `neutral` or `warm`.
|
|
13
|
+
- **The person's own colours**: settled skin, lips and brow hair, as sRGB hex.
|
|
14
|
+
- **Recommendations**: for every makeup region, the curated palette shades (`MAKEUP_SHADES`) nearest
|
|
15
|
+
what that region would paint on this person, best first.
|
|
16
|
+
|
|
17
|
+
The SDK draws no labels. Makeup does not need this readout: `shade: "auto"` already adapts on the
|
|
18
|
+
GPU. Import from `@vincentt-xr/sdk/face-effects`.
|
|
19
|
+
|
|
20
|
+
## Quick start
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { Blush, Contour, useMakeupSkinTone } from "@vincentt-xr/sdk/face-effects";
|
|
24
|
+
|
|
25
|
+
const tone = useMakeupSkinTone(); // null until the skin probe has settled
|
|
26
|
+
<Contour shade={tone?.recommendations.contour[0] ?? "medium"} />;
|
|
27
|
+
<Blush shade={tone?.recommendations.blush[0] ?? "rose"} />;
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Call it inside the canvas. It works alone: it starts the face model when no `FaceTracker` is above
|
|
31
|
+
it, and starts the face's skin probe when no makeup runs one.
|
|
32
|
+
|
|
33
|
+
## Options
|
|
34
|
+
|
|
35
|
+
| Option | Default | Meaning |
|
|
36
|
+
| ------------ | --------------- | -------------------------------------------------------------- |
|
|
37
|
+
| `faceIndex` | rig / tracker | Which face: the enclosing `FaceRig` or `FaceTracker`'s, else 0 |
|
|
38
|
+
| `numFaces` | `faceIndex + 1` | Faces to start the face model with, when this hook starts it |
|
|
39
|
+
| `intervalMs` | 500 | Milliseconds between reads, at least 200 |
|
|
40
|
+
| `count` | 3 | Shades recommended per region |
|
|
41
|
+
| `quality` | `"auto"` | The skin probe's quality (`useFaceSkin`) |
|
|
42
|
+
| `enabled` | `true` | `false` stops reading and releases the probe |
|
|
43
|
+
|
|
44
|
+
## The readout
|
|
45
|
+
|
|
46
|
+
| Field | Meaning |
|
|
47
|
+
| ----------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
48
|
+
| `skin` | The settled skin colour as the camera shows it, sRGB hex |
|
|
49
|
+
| `lab` | Its CIELAB (D65) `[L*, a*, b*]` |
|
|
50
|
+
| `depth`, `ita` | Depth from the Individual Typology Angle, `atan((L* − 50) / b*)` in degrees |
|
|
51
|
+
| `undertone` | From the CIELAB hue angle |
|
|
52
|
+
| `hue`, `chroma` | The skin's CIELAB hue (degrees) and chroma, for your own thresholds |
|
|
53
|
+
| `lips`, `brows` | The person's lip and brow-hair colours, or `null` while under a quarter of them was seen |
|
|
54
|
+
| `recommendations` | Palette shade names per region: `lips`, `contour`, `blush`, `highlighter`, `eyeshadow`, `eyeliner`, `brows` |
|
|
55
|
+
|
|
56
|
+
| Depth | ITA |
|
|
57
|
+
| -------- | ----------- |
|
|
58
|
+
| `fair` | over 55° |
|
|
59
|
+
| `light` | 41° to 55° |
|
|
60
|
+
| `medium` | 28° to 41° |
|
|
61
|
+
| `tan` | 10° to 28° |
|
|
62
|
+
| `deep` | −30° to 10° |
|
|
63
|
+
| `rich` | under −30° |
|
|
64
|
+
|
|
65
|
+
Undertone: hue under 50° is `cool`, over 60° is `warm`, between is `neutral`. Deeper skin has a lower
|
|
66
|
+
hue whatever its undertone, so below `L*` 50 both cuts drop 0.25° per unit: at `L*` 20 they are 42.5°
|
|
67
|
+
and 52.5°. A skin with chroma under 6 (a grey or washed-out image) is always `neutral`. The thresholds
|
|
68
|
+
are `MAKEUP_SKIN_TONE`.
|
|
69
|
+
|
|
70
|
+
## How shades are chosen
|
|
71
|
+
|
|
72
|
+
Each region gets a target colour: what `shade: "auto"` paints on this person.
|
|
73
|
+
|
|
74
|
+
- **Lips**: their own lips, deepened.
|
|
75
|
+
- **Blush**: their skin moved toward rose.
|
|
76
|
+
- **Contour**: their skin, deepened.
|
|
77
|
+
- **Highlighter**: their skin, lifted.
|
|
78
|
+
- **Brows**: their brow hair.
|
|
79
|
+
- **Eyeshadow**: a transition shade, the skin deepened.
|
|
80
|
+
- **Eyeliner**: the brow hair, darkened.
|
|
81
|
+
|
|
82
|
+
Warm skin leans blush, highlighter and eyeshadow toward peach, gold and bronze; cool skin toward rose,
|
|
83
|
+
pearl and taupe. The recommendations are the palette shades nearest each target (CIELAB ΔE). Unseen
|
|
84
|
+
lips or brows fall back to colours derived from the skin.
|
|
85
|
+
|
|
86
|
+
## Camera light
|
|
87
|
+
|
|
88
|
+
The readout measures the image, not the person:
|
|
89
|
+
|
|
90
|
+
- **White balance** moves the undertone. A warm room reads warm; a cool screen glow reads cool.
|
|
91
|
+
- **Exposure** moves the depth. A backlit face reads deeper.
|
|
92
|
+
|
|
93
|
+
Present the result as a suggestion the user can change, never as a label. Ask for even, neutral
|
|
94
|
+
light when it matters.
|
|
95
|
+
|
|
96
|
+
## Cost
|
|
97
|
+
|
|
98
|
+
No per-frame allocation. Each read is one 24 × 1 packing draw and an asynchronous copy to the CPU
|
|
99
|
+
(`FaceSkinProbe.readStatsAsync`), with one read in flight at a time. The hook re-renders only when the
|
|
100
|
+
readout changes.
|
|
101
|
+
|
|
102
|
+
## Photos
|
|
103
|
+
|
|
104
|
+
`computeMakeupSkinTone(stats)` takes any `FaceSkinStats`:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import {
|
|
108
|
+
FaceSkinProbe,
|
|
109
|
+
computeMakeupSkinTone,
|
|
110
|
+
readFaceSkinStats,
|
|
111
|
+
} from "@vincentt-xr/sdk/face-effects";
|
|
112
|
+
|
|
113
|
+
const probe = new FaceSkinProbe({ renderer: gl });
|
|
114
|
+
probe.renderStill(gl, photoTexture, photoLandmarks);
|
|
115
|
+
const data = await probe.readStatsAsync(gl);
|
|
116
|
+
const tone = data ? computeMakeupSkinTone(readFaceSkinStats(data)) : null;
|
|
117
|
+
probe.dispose();
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Also exported: `classifyMakeupSkinDepth`, `classifyMakeupUndertone`, `nearestMakeupShades`,
|
|
121
|
+
`MAKEUP_SKIN_DEPTHS`, `MAKEUP_UNDERTONES`.
|
|
122
|
+
|
|
123
|
+
## Manual visual test plan
|
|
124
|
+
|
|
125
|
+
Show `tone.depth`, `tone.undertone`, `tone.skin` and the first blush, contour and lip shade in a
|
|
126
|
+
debug readout on the webcam.
|
|
127
|
+
|
|
128
|
+
1. **Settles**: the readout appears within a second of the face showing, and stays steady while you
|
|
129
|
+
hold still.
|
|
130
|
+
2. **Light**: switch from daylight to a warm lamp. The undertone moves toward warm (the documented
|
|
131
|
+
caveat); the shades follow.
|
|
132
|
+
3. **Turn away**: past about 35° the readout holds its last value.
|
|
133
|
+
4. **Lips**: wear a strong lipstick. The lip recommendations move toward it within a few seconds.
|
|
134
|
+
5. **Two faces**: `faceIndex: 1` reads the second person.
|
|
135
|
+
6. **Cost**: the frame time does not change with the hook mounted.
|