@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,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Face Reprojection"
|
|
3
|
+
description: "The live camera face, worn by a face model in the model's own UV layout: the whole face, or only the eyes and mouth on a character."
|
|
4
|
+
sidebarTitle: "Face Reprojection"
|
|
5
|
+
icon: "masks-theater"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
`FaceReprojection` puts the person's real face from the camera onto a face model
|
|
9
|
+
([`ExternalFaceMesh`](/api/external-face-mesh)). The model can use any UV atlas.
|
|
10
|
+
|
|
11
|
+
- **The whole face:** the person's face on the character's head.
|
|
12
|
+
- **Only the eyes and / or mouth:** the classic talking-character effect.
|
|
13
|
+
- **The eyes on the eyeballs** as well, if you choose.
|
|
14
|
+
|
|
15
|
+
It is part of the face-character pipeline ([#194](https://github.com/vincentt-xr/sdk/issues/194),
|
|
16
|
+
#199). Import from `@vincentt-xr/sdk/face-effects`.
|
|
17
|
+
|
|
18
|
+
## Quick start
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { ExternalFaceMesh, FaceReprojection } from "@vincentt-xr/sdk/face-effects";
|
|
22
|
+
import { FaceTracker } from "@vincentt-xr/sdk/tracking";
|
|
23
|
+
|
|
24
|
+
<FaceTracker>
|
|
25
|
+
<ExternalFaceMesh model={gltf.scene}>
|
|
26
|
+
<FaceReprojection region="eyesAndMouth" />
|
|
27
|
+
</ExternalFaceMesh>
|
|
28
|
+
</FaceTracker>;
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## How it works
|
|
32
|
+
|
|
33
|
+
Two offscreen passes run per camera frame (at most `fps` a second):
|
|
34
|
+
|
|
35
|
+
1. **Unwrap.** The camera face is laid out in the canonical face UV layout.
|
|
36
|
+
- Every landmark samples the camera image where it was tracked.
|
|
37
|
+
- The eye and mouth openings, which are holes in the canonical surface, are filled. So the eyes
|
|
38
|
+
and the inside of the mouth come along.
|
|
39
|
+
- Skin seen edge-on (a cheek in a profile view) fades out instead of smearing, and so does the
|
|
40
|
+
outer edge of the face.
|
|
41
|
+
2. **Remap.** Every vertex of the model is bound once to its closest point on that filled canonical
|
|
42
|
+
face. The model is drawn in its own UV layout and reads the unwrap there. A few pixels of edge
|
|
43
|
+
padding stop seams at the edges of UV islands.
|
|
44
|
+
|
|
45
|
+
The result is applied to the model's meshes through a patched clone of each material:
|
|
46
|
+
|
|
47
|
+
- **unlit** (default): as the camera saw it;
|
|
48
|
+
- **lit**: as the base colour, shaded by the scene lights.
|
|
49
|
+
|
|
50
|
+
**Mirroring, aspect and resize** need nothing. The camera image and the landmarks share one space (a
|
|
51
|
+
mirrored webcam is mirrored before tracking), and the unwrap follows the anatomy rather than the
|
|
52
|
+
screen.
|
|
53
|
+
|
|
54
|
+
## Props
|
|
55
|
+
|
|
56
|
+
| Prop | Default | What it does |
|
|
57
|
+
| ------------------ | ------------- | -------------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| `meshes` | skin parts | Which meshes wear it, by object name. They must share one atlas. Add the eyeballs for real eyes. |
|
|
59
|
+
| `region` | `"face"` | `"face"`, `"eyes"`, `"mouth"` or `"eyesAndMouth"` (soft areas around the openings, lids and lips in). |
|
|
60
|
+
| `amount` | `1` | How much of the camera face shows, 0..1. |
|
|
61
|
+
| `shading` | `"unlit"` | `"unlit"`: the camera's colours. `"lit"`: shaded by the scene lights. |
|
|
62
|
+
| `mask` | — | Red channel, in the model's UV layout (load it like the model's map; glTF textures use `flipY = false`). |
|
|
63
|
+
| `canonicalMask` | — | Red channel, in the canonical face UV layout. |
|
|
64
|
+
| `resolution` | `1024` | Output texture size, px (mipmapped). |
|
|
65
|
+
| `unwrapResolution` | `512` | Canonical-layout texture size, px. |
|
|
66
|
+
| `padding` | `2` | Edge padding around UV islands, px (0–4). |
|
|
67
|
+
| `fps` | `30` | The most updates a second (`0` = every new camera frame). |
|
|
68
|
+
| `facing` | `[0.05, 0.3]` | Cosines: skin turned further than the first is hidden, fully kept from the second. |
|
|
69
|
+
| `falloff` | `[1, 3]` | Distance from the canonical face (cm) over which a vertex stops taking the face. |
|
|
70
|
+
| `apply` | `true` | Patch the meshes' materials. With `false`, only render; use `onTexture` with your own material. |
|
|
71
|
+
| `onTexture` | — | Receives `{ texture, unwrap }` once they exist. |
|
|
72
|
+
|
|
73
|
+
**Eyes and lids.** Eyeballs (parts named `eye…`) read the eye openings. Skin and teeth read the face
|
|
74
|
+
and the mouth opening, never the eyes. A lid's edge sits in the eye opening, and wearing the eye there
|
|
75
|
+
would show when a blink morph closes the lid.
|
|
76
|
+
|
|
77
|
+
**Face index and tracking.**
|
|
78
|
+
|
|
79
|
+
- It uses the enclosing rig's face (`FaceRigState.faceIndex`, from `FaceRig` / `ExternalFaceMesh`
|
|
80
|
+
`faceIndex`).
|
|
81
|
+
- It updates only on frames where that face is tracked, and keeps the last texture through a
|
|
82
|
+
dropout.
|
|
83
|
+
- Both textures are freed on unmount.
|
|
84
|
+
|
|
85
|
+
## Your own material or pipeline
|
|
86
|
+
|
|
87
|
+
- **Your own material.** Pass `apply={false}` and use `onTexture`, or patch any built-in material
|
|
88
|
+
with `patchFaceReprojectionMaterial(material, createFaceReprojectionUniforms())`. The textures
|
|
89
|
+
hold premultiplied alpha.
|
|
90
|
+
- **Without React.** `FaceReprojector` is the GPU engine:
|
|
91
|
+
|
|
92
|
+
- `setTargets([{ geometry, canonical, openings }])`;
|
|
93
|
+
- `render(renderer, cameraTexture, landmarks)` once per frame;
|
|
94
|
+
- read `texture` / `unwrapTexture`;
|
|
95
|
+
- `dispose()` when done.
|
|
96
|
+
|
|
97
|
+
It takes five more options for the unwrap, all off by default:
|
|
98
|
+
|
|
99
|
+
| Option | Default | Meaning |
|
|
100
|
+
| --------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
101
|
+
| `uvs` | `CANONICAL_FACE_UVS` | The unwrap's layout, one `[u, v]` per landmark. `FACE_ATLAS_UVS` unwraps into the face atlas; a `canonicalMask` must then be in that layout. |
|
|
102
|
+
| `unwrapMipmaps` | `false` | Mipmap the unwrap, for reading it smaller than it is. |
|
|
103
|
+
| `mirrorFill` | `false` | Fill the far side of a turned face from the other side, once per unwrap; only where the mirror twin was seen clearly better. Points outside the image are filled from their twin too. |
|
|
104
|
+
| `inFrame` | on with `mirrorFill` | Drop the parts of the face outside the image instead of stretching the edge pixels over them. |
|
|
105
|
+
| `unwrapPadding` | `0` | Padding of the unwrap, px (0–16). It pads alpha too: coverage grows at the face's edge and into unseen holes, so padded texels count as seen. |
|
|
106
|
+
|
|
107
|
+
With `uvs`, `texture` (the remap into `setTargets`' own atlas) follows the layout, but the
|
|
108
|
+
canonical paths do not: `bindFaceReprojection(...).canonicalUv`, a `faceUv` attribute and
|
|
109
|
+
`patchFaceReprojectionMaterial(..., { attributes: true })` read the unwrap in the canonical
|
|
110
|
+
layout and would wear a scrambled face. Convert the binding first:
|
|
111
|
+
`writeFaceReprojectionLayoutUv(binding, FACE_ATLAS_UVS)` is the `faceUv` for that unwrap.
|
|
112
|
+
|
|
113
|
+
- **Pure helpers.** `getFaceUnwrapMesh`, `getFaceUnwrapUvs` (the unwrap's UVs in a layout),
|
|
114
|
+
`writeFaceUnwrapFrame`, `writeFaceFacing` (how squarely each of the 471 unwrap vertices faces
|
|
115
|
+
the camera), `bindFaceReprojection`, `writeFaceReprojectionLayoutUv` and the region helpers.
|
|
116
|
+
|
|
117
|
+
## Face swap and mirror
|
|
118
|
+
|
|
119
|
+
To put a face on another live face instead of on a model, use [Face Swap](/api/face-swap):
|
|
120
|
+
`FaceSwap` swaps two people's faces or puts a photo or painted face on every face, and
|
|
121
|
+
`FaceMirror` mirrors your own face. They unwrap the face with the same `FaceReprojector`, into the
|
|
122
|
+
face atlas (`FACE_ATLAS_UVS`) rather than the canonical layout, and draw it back on the tracked face
|
|
123
|
+
in screen space. `/face-reprojection?mode=swap` and `?mode=mirror` show them.
|
|
124
|
+
|
|
125
|
+
## Example
|
|
126
|
+
|
|
127
|
+
`/face-reprojection` runs on the local facecap character (see
|
|
128
|
+
[External Face Mesh](/api/external-face-mesh#example)). It has controls for region, shading,
|
|
129
|
+
amount, facing, fps, resolution and face index, and an option to put your eyes on the eyeballs. It
|
|
130
|
+
previews both textures in the top-right corner: the remap in the model's atlas, and the unwrap. Without the
|
|
131
|
+
local model, only the unwrap shows.
|
|
132
|
+
|
|
133
|
+
## Manual visual test plan
|
|
134
|
+
|
|
135
|
+
Open `/face-reprojection` on the webcam with the local facecap model.
|
|
136
|
+
|
|
137
|
+
1. **Whole face**: your face is on the character's skin, sharp and aligned, with no seam at the
|
|
138
|
+
edge. The ears, the scalp and the back of the head keep the character's own skin, and the edge
|
|
139
|
+
fades softly.
|
|
140
|
+
2. **Head turn**: turn your head. The cheek turning away fades to the character's skin instead of
|
|
141
|
+
smearing. The near side stays sharp.
|
|
142
|
+
3. **Expressions**: open your mouth (your teeth and tongue show in the character's mouth), smile and
|
|
143
|
+
raise your brows. Blink: the character blinks (its own morph) and the lids show your lids.
|
|
144
|
+
4. **Eyes + mouth**: switch region to "eyes + mouth". Only your eyes and lips show, with soft edges,
|
|
145
|
+
on the character's grey skin. Tick "your eyes on the eyeballs" and your eyes move with your gaze.
|
|
146
|
+
5. **Shading**: switch to "lit". The face takes the scene lighting. The amount slider fades it.
|
|
147
|
+
6. **Mirror and source**: switch between the webcam and the sample videos and image. Each real eye
|
|
148
|
+
lands on the character's eye in front of it, on every source (mesh to mesh; GROUNDING "Left and
|
|
149
|
+
right").
|
|
150
|
+
7. **Resolution / fps**: change the resolution (the previews resize) and the fps (lower updates
|
|
151
|
+
less often). Nothing leaks: switching back and forth keeps the frame rate.
|
|
152
|
+
8. **Dropout**: cover the camera briefly. The face holds, then the character hides and comes back
|
|
153
|
+
with a fresh face.
|
|
154
|
+
9. **Second face**: with two people, "second face" puts the second person's face on the character.
|
|
@@ -52,22 +52,30 @@ space. They default to the full frame. The legacy compare demo uses
|
|
|
52
52
|
|
|
53
53
|
For multiple people, render one `FaceRetouch` per person and pass `faceIndex`.
|
|
54
54
|
`numFaces` defaults to `faceIndex + 1`, so `<FaceRetouch faceIndex={1} />`
|
|
55
|
-
requests tracking for at least two faces.
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
requests tracking for at least two faces. Each pass is see-through outside
|
|
56
|
+
its own face mask, so they stack over the same camera background at the same
|
|
57
|
+
draw order.
|
|
58
58
|
|
|
59
59
|
```tsx
|
|
60
60
|
const faceCount = 2;
|
|
61
61
|
|
|
62
62
|
{
|
|
63
63
|
Array.from({ length: faceCount }, (_, faceIndex) => (
|
|
64
|
-
<FaceRetouch
|
|
65
|
-
key={faceIndex}
|
|
66
|
-
{...controls}
|
|
67
|
-
faceIndex={faceIndex}
|
|
68
|
-
numFaces={faceCount}
|
|
69
|
-
renderOrder={-1000 + faceIndex}
|
|
70
|
-
/>
|
|
64
|
+
<FaceRetouch key={faceIndex} {...controls} faceIndex={faceIndex} numFaces={faceCount} />
|
|
71
65
|
));
|
|
72
66
|
}
|
|
73
67
|
```
|
|
68
|
+
|
|
69
|
+
## Draw order
|
|
70
|
+
|
|
71
|
+
`FaceRetouch` draws in the opaque face layer at `FACE_RETOUCH_RENDER_ORDER`
|
|
72
|
+
(-2.5, from `@vincentt-xr/sdk/face-effects`), with depth testing:
|
|
73
|
+
|
|
74
|
+
- after the camera background (-1000) and `HandCutout` (-900), so a hand in
|
|
75
|
+
front of the face stays sharp instead of being smoothed;
|
|
76
|
+
- before the face effects (`FaceWarp3D`, `FaceMorph`, characters at -2) and
|
|
77
|
+
makeup (-1.99 to -1.55), which draw over the retouched skin.
|
|
78
|
+
|
|
79
|
+
Mount it at the top of the scene, not inside a tracker group (a group's
|
|
80
|
+
render order would move it). Override `renderOrder` only to place a custom
|
|
81
|
+
effect between the retouch and the face.
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Face Swap"
|
|
3
|
+
description: "Two people swap faces, a photo or a painted face goes on every face, or your own face is mirrored, live on the camera, in the wearer's skin tone and light."
|
|
4
|
+
sidebarTitle: "Face Swap"
|
|
5
|
+
icon: "people-arrows"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
`FaceSwap` and `FaceMirror` draw a face on a tracked face, live on the camera:
|
|
9
|
+
|
|
10
|
+
- **Two people swap faces.** It starts by itself when two faces are in view.
|
|
11
|
+
- **A photo or a painted face** goes on every face (or only one).
|
|
12
|
+
- **Your own face, mirrored:** one half doubled, the halves swapped, or the eyes and mouth upside
|
|
13
|
+
down.
|
|
14
|
+
|
|
15
|
+
The drawn face moves with the wearer's expression, takes the wearer's skin tone and light, and
|
|
16
|
+
fades in centimetres inside the face edge. Both components start the face model themselves.
|
|
17
|
+
Import from `@vincentt-xr/sdk/face-effects` ([#275](https://github.com/vincentt-xr/sdk/issues/275)).
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { VideoBackground, XRProvider, XRScene } from "@vincentt-xr/sdk";
|
|
23
|
+
import { FaceMirror, FaceSwap } from "@vincentt-xr/sdk/face-effects";
|
|
24
|
+
|
|
25
|
+
<XRProvider>
|
|
26
|
+
<XRScene>
|
|
27
|
+
<VideoBackground />
|
|
28
|
+
{/* Two people swap faces automatically; with one face the camera shows as is */}
|
|
29
|
+
<FaceSwap onStatus={(s) => setSwapping(s.active)} />
|
|
30
|
+
</XRScene>
|
|
31
|
+
</XRProvider>;
|
|
32
|
+
|
|
33
|
+
// Any photo: File, Blob, URL, <img>, canvas or ImageBitmap
|
|
34
|
+
<FaceSwap source={{ kind: "photo", src: file }} onStatus={(s) => setWarnings(s.warnings)} />;
|
|
35
|
+
// A face painted in the face atlas: keeps its paint, takes the room's light
|
|
36
|
+
<FaceSwap source={{ kind: "canonicalTexture", src: paintedUrl }} />;
|
|
37
|
+
// Your own face, the left half twice
|
|
38
|
+
<FaceMirror variant="leftLeft" />;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Which component
|
|
42
|
+
|
|
43
|
+
| Goal | Use |
|
|
44
|
+
| -------------------------------------------------------------- | ------------------------------------------------------------------------ |
|
|
45
|
+
| Two people swap faces, or a photo / painted face on every face | `FaceSwap` |
|
|
46
|
+
| Your own face mirrored | `FaceMirror variant` |
|
|
47
|
+
| Your own face texture on a live face (a custom effect) | `FaceTextureLayer face`, fed by `useFaceTexture` or `useLiveFaceTexture` |
|
|
48
|
+
| A face drawn into a picture or a render target, or no React | `FaceTransfer` with `createFaceTexture` |
|
|
49
|
+
|
|
50
|
+
**Mounting.** Mount them anywhere in `<XRScene>`, also inside a `<FaceTracker>`. They draw in
|
|
51
|
+
screen space and need no `FaceRig`. With no `FaceTracker` above, they start the face model
|
|
52
|
+
themselves: `FaceSwap` with two faces for a two-person swap, otherwise one. The first component to
|
|
53
|
+
start the model sets its face count, so anything else that may start it first needs the same
|
|
54
|
+
`numFaces`. A console warning names the fix when a face the component needs can never be tracked.
|
|
55
|
+
Keep hands in front with `<HandTracker><HandCutout /></HandTracker>`.
|
|
56
|
+
|
|
57
|
+
## FaceSwap
|
|
58
|
+
|
|
59
|
+
### Sources
|
|
60
|
+
|
|
61
|
+
| `source` | What is drawn |
|
|
62
|
+
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
63
|
+
| `{ kind: "eachOther" }` (default) | Faces 0 and 1 swap. |
|
|
64
|
+
| `{ kind: "photo", src, mirrored?, pick?, maxSize? }` | The face found in a photo, on every tracked face. `pick`: `"largest"` (default) or the n-th face from the left. |
|
|
65
|
+
| `{ kind: "canonicalTexture", src, mirrored? }` | A face painted in the face atlas (a URL or a `THREE.Texture`), on every tracked face. |
|
|
66
|
+
| `{ kind: "faceTexture", face }` | A `FaceTexture` you made (`useFaceTexture`, `createFaceTexture`, `useLiveFaceTexture`); it stays yours to dispose. |
|
|
67
|
+
|
|
68
|
+
`mirrored` says the image itself is mirrored (some phones save selfies mirrored). A mirrored selfie
|
|
69
|
+
cannot be detected from the pixels, so it is your app's toggle.
|
|
70
|
+
|
|
71
|
+
### Props
|
|
72
|
+
|
|
73
|
+
Every setting below is also a prop, flat (`<FaceSwap matchLighting={0.5} />`), plus:
|
|
74
|
+
|
|
75
|
+
| Prop | Default | What it does |
|
|
76
|
+
| ----------- | ------------------------ | ----------------------------------------------------------------------------------- |
|
|
77
|
+
| `source` | `{ kind: "eachOther" }` | The face drawn (above). |
|
|
78
|
+
| `amount` | `1` | 0..1, or a ref read every frame, so it can fade without re-rendering. |
|
|
79
|
+
| `faceIndex` | every tracked face | Photo, painted and `faceTexture` sources: only this face. Ignored for two people. |
|
|
80
|
+
| `numFaces` | 2 for two people, else 1 | Faces to start the face model with. |
|
|
81
|
+
| `quality` | `"auto"` | `"auto"` follows the session's quality tier; or `"high"`, `"medium"`, `"low"`. |
|
|
82
|
+
| `active` | `true` | `false` hides it and stops its passes and its face model, but keeps a loaded photo. |
|
|
83
|
+
| `onStatus` | | Called whenever the status changes (not every frame). |
|
|
84
|
+
|
|
85
|
+
The status is `{ active, faces, source, warnings, error }`:
|
|
86
|
+
|
|
87
|
+
- `active`: drawn now (fading in, shown or fading out);
|
|
88
|
+
- `faces`: faces in the newest face result;
|
|
89
|
+
- `source`: `"waiting"` (no source yet, or fewer than two ready faces for a two-person swap),
|
|
90
|
+
`"loading"`, `"ready"` or `"error"`;
|
|
91
|
+
- `warnings`: for photos, any of `turned` (head turned more than 25°), `eyesClosed`, `mouthOpen`,
|
|
92
|
+
`small` (eyes less than 60 px apart) and `severalFaces`;
|
|
93
|
+
- `error`: `{ code, message }` with code `noFace`, `decode`, `cors`, `model` or `aborted`.
|
|
94
|
+
|
|
95
|
+
### Behaviour
|
|
96
|
+
|
|
97
|
+
- **Two people.** The swap starts once both faces have been tracked for 5 face results and fades
|
|
98
|
+
in over 200 ms. It holds through a dropout of up to 250 ms, then fades back to the plain camera
|
|
99
|
+
(also after 1 s with no face results at all). MediaPipe reordering the faces changes nothing.
|
|
100
|
+
Where the faces overlap, the larger face draws on top. With three or more faces, only faces 0 and
|
|
101
|
+
1 swap.
|
|
102
|
+
- **Photos and painted faces.** Each tracked face fades in with its first result and out 250 ms
|
|
103
|
+
after it is lost.
|
|
104
|
+
- **Own eyes and mouth.** By default the wearer keeps their own live eyes and mouth inside the drawn
|
|
105
|
+
face (`ownEyes`, `ownMouth`), so blinks, gaze, teeth and tongue stay real. Turn them off for the
|
|
106
|
+
source's own eyes and mouth: a photo's or painting's stay still.
|
|
107
|
+
- **Expression.** The wearer's expression moves the drawn face. A still face has a neutral, closed
|
|
108
|
+
mouth, so its lips stretch when the wearer talks.
|
|
109
|
+
|
|
110
|
+
## Settings and presets
|
|
111
|
+
|
|
112
|
+
| Field | Range | Default | What it does |
|
|
113
|
+
| ----------------- | -------- | --------- | ----------------------------------------------------------------------------------------- |
|
|
114
|
+
| `preset` | | `natural` | `natural`, `keepColors`, `raw`, or `"custom"`. |
|
|
115
|
+
| `matchSkinTone` | 0..1 | 1 | The drawn face takes the wearer's skin tone, exposure and white balance. |
|
|
116
|
+
| `matchLighting` | 0..1 | 1 | The wearer's light and shadow fall on the drawn face. |
|
|
117
|
+
| `edgeMatch` | 0..1 | 1 | The band inside the face edge always takes the wearer's tone and light, so no seam shows. |
|
|
118
|
+
| `edgeSoftness` | 0.3..3 | 1.2 | Width of the fade inside the face edge, cm. |
|
|
119
|
+
| `edgeInset` | 0..1.5 | 0.3 | Pulls the edge inside the tracked outline, cm. |
|
|
120
|
+
| `ownEyes` | boolean | true | The wearer keeps their live eyes. |
|
|
121
|
+
| `ownMouth` | boolean | true | The wearer keeps their live mouth interior. |
|
|
122
|
+
| `featureSoftness` | 0.1..0.6 | 0.25 | Soft rim around the kept eyes and mouth, cm (0.1 for painted faces). |
|
|
123
|
+
| `detail` | 0..1 | 1 | Sharpness of the drawn face; lower softens it to match a soft camera. |
|
|
124
|
+
| `smoothing` | 0..1 | 0.35 | Landmark smoothing. Shared per face: the most any component asks for wins. |
|
|
125
|
+
| `amount` | 0..1 | 1 | Overall strength. |
|
|
126
|
+
|
|
127
|
+
| Preset | For | Sets |
|
|
128
|
+
| ------------ | ------------------------- | ---------------------------------------------------------------------------- |
|
|
129
|
+
| `natural` | photos and two people | Full skin-tone and light match, 1.2 cm edge, own eyes and mouth. |
|
|
130
|
+
| `keepColors` | painted or stylised faces | No skin-tone match, 0.7 light match, 1 cm edge: the paint keeps its colours. |
|
|
131
|
+
| `raw` | a mask look, or debugging | No matching, a short 0.4 cm edge: the face as captured. |
|
|
132
|
+
|
|
133
|
+
- Without `preset`, a painted face starts from `keepColors` with a 0.1 cm feature rim; photos and
|
|
134
|
+
two people start from `natural`.
|
|
135
|
+
- A named preset always means its values: an explicit value that moves a field the preset sets
|
|
136
|
+
makes it `"custom"`. Smoothing, inset, feature softness and amount are never set by a preset.
|
|
137
|
+
- `resolveFaceSwapSettings(input, { source })` resolves props (defaults, then the preset, then your
|
|
138
|
+
values, clamped). `patchFaceSwapSettings(prev, patch)` applies a panel edit: choosing a preset
|
|
139
|
+
applies it, editing a field it sets makes it `"custom"`. `FACE_SWAP_SETTINGS_FIELDS` drives a
|
|
140
|
+
settings panel; `FaceSwapSettingsPanel` from `@vincentt-xr/sdk/debug-ui` is a ready one.
|
|
141
|
+
|
|
142
|
+
## Colour and edges
|
|
143
|
+
|
|
144
|
+
**Colour.** The drawn face is multiplied by a gain per colour channel, in linear light, computed per
|
|
145
|
+
vertex:
|
|
146
|
+
|
|
147
|
+
- **Skin tone** (`matchSkinTone`): the ratio of the wearer's mean skin colour to the source's. It
|
|
148
|
+
carries skin tone, exposure and white balance.
|
|
149
|
+
- **Light** (`matchLighting`): the ratio of the wearer's local, low-frequency skin colour to the
|
|
150
|
+
source's, relative to their means. It is applied at full strength for brightness and half
|
|
151
|
+
strength for colour, so coloured light does not tint the skin. A painted face only takes the
|
|
152
|
+
wearer's light: its own painted shading keeps its contrast.
|
|
153
|
+
- The gain is clamped to 0.25–4.
|
|
154
|
+
|
|
155
|
+
The statistics are skin only: brows, eyes, lips and nostrils are masked out, and outliers
|
|
156
|
+
(speculars, beard, glasses frames) are rejected. They are blurred to 64² and smoothed over 250 ms,
|
|
157
|
+
so a flicker in one frame never shows.
|
|
158
|
+
|
|
159
|
+
**Edges.** Every distance is in cm on the face, measured from a smoothed face outline, so the fade
|
|
160
|
+
lines are smooth curves. The alpha is the product of:
|
|
161
|
+
|
|
162
|
+
- the edge fade: from `edgeInset` inside the outline, over `edgeSoftness`;
|
|
163
|
+
- how squarely the wearer's face points at the camera there;
|
|
164
|
+
- how much of the source was seen there (a photo's turned-away cheek is filled from the other side
|
|
165
|
+
when it is baked);
|
|
166
|
+
- soft rims of `featureSoftness` around the kept eyes and mouth.
|
|
167
|
+
|
|
168
|
+
Inside the fade, a band twice as wide always takes the wearer's tone and light (`edgeMatch`), so
|
|
169
|
+
the drawn face meets the real skin with no seam even when `matchSkinTone` is 0.
|
|
170
|
+
|
|
171
|
+
## FaceMirror
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
<FaceMirror variant="leftLeft" /> // both halves are your own LEFT half
|
|
175
|
+
<FaceMirror variant="rightRight" /> // both halves are your own RIGHT half
|
|
176
|
+
<FaceMirror variant="flip" /> // left and right swapped: a left wink shows on the right
|
|
177
|
+
<FaceMirror variant="upsideDown" /> // each eye and the mouth flipped top to bottom in place
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
| Prop | Default | What it does |
|
|
181
|
+
| --------------- | ------------------ | ---------------------------------------------------------------------------- |
|
|
182
|
+
| `variant` | required | `leftLeft`, `rightRight`, `flip` or `upsideDown`. |
|
|
183
|
+
| `matchLighting` | `1` | The real side light stays where it falls; `0` shows the raw mirrored pixels. |
|
|
184
|
+
| `edgeSoftness` | `1.2` | Width of the fade inside the face edge, cm. |
|
|
185
|
+
| `smoothing` | `0.35` | Landmark smoothing. |
|
|
186
|
+
| `amount` | `1` | 0..1, or a ref. |
|
|
187
|
+
| `faceIndex` | every tracked face | Only this face. |
|
|
188
|
+
| `numFaces` | `1` | Faces to start the face model with. |
|
|
189
|
+
| `quality` | `"auto"` | As for `FaceSwap`. |
|
|
190
|
+
| `active` | `true` | `false` hides it and stops its passes. |
|
|
191
|
+
|
|
192
|
+
- Left and right are the person's own sides on the mirrored webcam, the rear camera and videos
|
|
193
|
+
alike.
|
|
194
|
+
- The eyes and mouth are part of every variant: they always come from the mirrored face, so a left
|
|
195
|
+
wink in `leftLeft` winks both eyes.
|
|
196
|
+
- Where the far side of a turned face was not seen, the real face shows.
|
|
197
|
+
|
|
198
|
+
## Sides
|
|
199
|
+
|
|
200
|
+
Left and right always mean the person's own side. A face texture's `mirrored` flag says which side
|
|
201
|
+
of the canonical face is the person's left: `true` for a live face on the mirrored webcam or a
|
|
202
|
+
selfie saved mirrored, `false` for a photo as stored, a painted face, and a live face on the rear
|
|
203
|
+
camera or a video. When a face is drawn on another, the sides are matched through that flag and the
|
|
204
|
+
exact landmark mirror map (`FACE_UNWRAP_MIRROR`, `resolveFaceSourceMirror`), never by flipping the
|
|
205
|
+
texture. A photo's left cheek lands on the wearer's left cheek on every feed.
|
|
206
|
+
|
|
207
|
+
## Face textures and FaceTextureLayer
|
|
208
|
+
|
|
209
|
+
A `FaceTexture` is one face laid flat in the face atlas (`FACE_ATLAS_UVS`): its `map`, its skin
|
|
210
|
+
statistics `low` and `mean`, `mirrored`, and for photos the detected `landmarks`.
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
import {
|
|
214
|
+
FaceTextureLayer,
|
|
215
|
+
useFaceTexture,
|
|
216
|
+
useLiveFaceTexture,
|
|
217
|
+
} from "@vincentt-xr/sdk/face-effects";
|
|
218
|
+
|
|
219
|
+
// Inside <XRScene>: these need the renderer.
|
|
220
|
+
const photo = useFaceTexture({ kind: "photo", src: file }); // { face, status, warnings, error, faceCount }
|
|
221
|
+
const second = useLiveFaceTexture(1); // stable, updated in place; null until made
|
|
222
|
+
|
|
223
|
+
<FaceTextureLayer face={photo.face} />;
|
|
224
|
+
<FaceTextureLayer face={second} faceIndex={0} />;
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
- `useFaceTexture(source)` bakes a photo or painted face once per URL or object, aborts a stale load
|
|
228
|
+
and disposes the face on change or unmount.
|
|
229
|
+
- `useLiveFaceTexture(faceIndex)` is shared and refcounted per face: every component asking for the
|
|
230
|
+
same face shares one unwrap and one set of statistics. It updates only when a new face result
|
|
231
|
+
arrives, from smoothed landmarks, so it never swims.
|
|
232
|
+
- `FaceTextureLayer` draws any face texture on a tracked face with the same settings as `FaceSwap`,
|
|
233
|
+
plus `layout` (`asIs`, `flip`, `leftLeft`, `rightRight`, `upsideDown`) and `targetStats`. It starts
|
|
234
|
+
the face model one commit after it mounts, so `useLiveFaceTexture(1)` above it starts the model
|
|
235
|
+
with two faces.
|
|
236
|
+
- Without React: `createFaceTexture(renderer, source)` bakes a face (you dispose it), and
|
|
237
|
+
`FaceTransfer` draws it: `setTarget(landmarks, aspect)` or a live map, `setSource`,
|
|
238
|
+
`setTargetStats`, `setLayout`, `setSettings`, `setAmount`, then render its `mesh` into the scene or
|
|
239
|
+
into a picture-sized render target.
|
|
240
|
+
- `detectFaceImage(image)` finds the faces in a still image (the same face model, run in image mode
|
|
241
|
+
on the CPU).
|
|
242
|
+
|
|
243
|
+
## Painting a face
|
|
244
|
+
|
|
245
|
+
A painted face is one image in the face atlas layout:
|
|
246
|
+
|
|
247
|
+
- **Layout.** Upright, chin at the bottom, image left = the character's own RIGHT, as on an
|
|
248
|
+
unmirrored photo. The template labels both halves.
|
|
249
|
+
- **Coverage.** Opaque about 5 mm past the face outline; the fade sits inside it. Straight alpha.
|
|
250
|
+
- **Look.** A neutral face, eyes open, lips closed, in flat even light: `matchLighting` adds the
|
|
251
|
+
room's light.
|
|
252
|
+
- **Eyes and mouth.** Paint the eye and mouth fills too: they show when `ownEyes` or `ownMouth` is
|
|
253
|
+
off. Keep liner and lip lines outside the dashed feature rims in the template, or the wearer's own
|
|
254
|
+
lid and lips show through them.
|
|
255
|
+
- **Size.** 1024², WebP or PNG.
|
|
256
|
+
|
|
257
|
+
Template: [`docs/guides/face-texture-template.svg`](/guides/face-texture-template.svg), or in your
|
|
258
|
+
app `createFaceTextureGuideSvg()` / `createFaceTextureGuidePngBlob()`, which draw the outline, the
|
|
259
|
+
edge fade lines of a preset, the feature rims, the skin-statistics area and the side labels.
|
|
260
|
+
`createFaceTextureSideTestSvg()` draws a test face with an "L" on the character's own left cheek:
|
|
261
|
+
worn as a source, it reads like a sticker on the wearer's left cheek. The Blender pipeline used for
|
|
262
|
+
the two example faces is in `assets-src/face-swap/README.md`.
|
|
263
|
+
|
|
264
|
+
## Layering
|
|
265
|
+
|
|
266
|
+
The swap, the mirror and `FaceTextureLayer` _are_ the face (render order −2):
|
|
267
|
+
|
|
268
|
+
| Layer | Order | With the swap |
|
|
269
|
+
| -------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------ |
|
|
270
|
+
| Camera background | −1000 | Under it. |
|
|
271
|
+
| `HandCutout` | −900 | Hands stay in front. |
|
|
272
|
+
| `FaceRetouch` | −2.5 | Covered where the swap draws; do not combine. |
|
|
273
|
+
| `FaceSwap`, `FaceMirror`, `FaceTextureLayer` | −2 | The face. One face effect per face: not with `FaceWarp3D`, `FaceMorph` or an `ExternalFaceMesh`. |
|
|
274
|
+
| Makeup, `LipEffect` | −1.99 … −1.55 | Paint on top, shaded from the raw camera. |
|
|
275
|
+
| `FaceInset` | −1.5 | Shows the raw camera part. |
|
|
276
|
+
| Head occluder | −1 | Unchanged. |
|
|
277
|
+
| Accessories | 0+ | Draw on top. |
|
|
278
|
+
|
|
279
|
+
## Performance
|
|
280
|
+
|
|
281
|
+
Targets: about 30 fps on a mid-range phone with one feature on. The numbers below are estimates
|
|
282
|
+
until they are measured on devices.
|
|
283
|
+
|
|
284
|
+
| Mode | GPU per frame | Per face result | One-time |
|
|
285
|
+
| --------------------- | ------------------------ | -------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
286
|
+
| Photo or painted face | 1 draw, about 0.3–0.5 ms | skin statistics at 6–15 Hz, under 0.1 ms | Photo: decode 20–60 ms; detector start 0.3–1.5 s (first photo); detection 30–100 ms; bake under 5 ms |
|
|
287
|
+
| Mirror | 1 draw | one unwrap, 512–1024², about 0.2–0.5 ms | none |
|
|
288
|
+
| Two people | 2 draws, about 0.6–1 ms | two unwraps with mirror fill, about 0.6–1 ms | none |
|
|
289
|
+
|
|
290
|
+
- **Two people cost most in inference:** two-face tracking runs on a larger analysis image and
|
|
291
|
+
re-runs face detection while fewer than two faces are tracked. Expect 1.6–2.5× the one-face
|
|
292
|
+
inference time; `FaceSwap` cannot reduce it.
|
|
293
|
+
- **Quality tiers** (`quality: "auto"` follows the session tier):
|
|
294
|
+
|
|
295
|
+
| Tier | Mesh | Live map max | Mirror fill (two people) | Statistics |
|
|
296
|
+
| ------ | ------------------------ | ------------ | ------------------------ | ---------- |
|
|
297
|
+
| high | level 2, 14.5k triangles | 1024 | on | 15 Hz |
|
|
298
|
+
| medium | level 2 | 768 | on | 10 Hz |
|
|
299
|
+
| low | level 1, 3.6k triangles | 512 | off | 6 Hz |
|
|
300
|
+
|
|
301
|
+
The live map is also capped by the face's size on screen.
|
|
302
|
+
|
|
303
|
+
- **Memory:** a photo or painted face is about 5.6 MB of GPU memory; a live map 1.4–5.6 MB per face.
|
|
304
|
+
The photo detector is a second MediaPipe instance (20–40 MB, with its own small WebGL context); it
|
|
305
|
+
closes after 30 s idle or with `disposeFaceImageLandmarker()`.
|
|
306
|
+
|
|
307
|
+
Device results (device, browser, tier, fps, date) are recorded here once measured.
|
|
308
|
+
|
|
309
|
+
## Privacy
|
|
310
|
+
|
|
311
|
+
The SDK accepts any photo, so a real person's face can be swapped. Photos are decoded in memory
|
|
312
|
+
only: nothing is uploaded, stored or put in the URL, and a baked face is disposed when it is
|
|
313
|
+
replaced. No real person's face ships with the SDK. Ask for consent before using someone's photo;
|
|
314
|
+
whether captures that contain a swap carry a disclosure is your product's decision.
|
|
315
|
+
|
|
316
|
+
## Example
|
|
317
|
+
|
|
318
|
+
`/face-reprojection` has `?mode=swap` and `?mode=mirror` (with `?mode=character` for the face
|
|
319
|
+
character):
|
|
320
|
+
|
|
321
|
+
- `?mode=swap&with=eachOther&source=sdk-video-5`: two people swap on the two-person clip;
|
|
322
|
+
- `?mode=swap&with=painted-female&preset=keepColors`: a painted face on yours;
|
|
323
|
+
- `?mode=swap&with=sideTest`: the side test;
|
|
324
|
+
- `?mode=mirror&variant=upsideDown&matchLighting=0`: the Thatcher effect, raw.
|
|
325
|
+
|
|
326
|
+
## Manual visual test plan
|
|
327
|
+
|
|
328
|
+
Record each run with the device and the date.
|
|
329
|
+
|
|
330
|
+
1. **Sides.** `?mode=swap&with=sideTest` on the webcam, the rear camera and a clip: the "L" lands on
|
|
331
|
+
the person's own left cheek every time. With a sticker on your real left cheek: `leftLeft` shows
|
|
332
|
+
it on both cheeks, `rightRight` on neither, `flip` on the right. A left wink in `leftLeft` winks
|
|
333
|
+
both eyes.
|
|
334
|
+
2. **Registration.** `<FaceTextureLayer face={useLiveFaceTexture(0)} layout="asIs" />` looks like the
|
|
335
|
+
plain camera while talking and turning: no shift, no swimming.
|
|
336
|
+
3. **Turned head.** At about 30° of yaw in a two-person swap, the nose covers the far cheek and no
|
|
337
|
+
cheek is painted over the nose.
|
|
338
|
+
4. **Two people.** On `sdk-video-5` and with two real people: when one leaves, the camera is back to
|
|
339
|
+
normal within about 0.5 s; when they return, the swap comes back after a few frames and the fade;
|
|
340
|
+
when the faces reorder, there is no colour flash.
|
|
341
|
+
5. **Photos.** Local photos only, never committed: an EXIF-rotated portrait, a 12 MP image, a face
|
|
342
|
+
turned 30° (the far cheek is filled; `turned` warning), closed eyes (warning), a group photo (the
|
|
343
|
+
largest face is used).
|
|
344
|
+
6. **Colour.** Several skin tones, side light, warm and cool white balance, and a dark-skin /
|
|
345
|
+
light-skin pair: no seam with `natural` at `edgeSoftness` 0.5, 1.2 and 3. `raw` shows the raw
|
|
346
|
+
difference. A painted face with `keepColors` keeps its paint and blends at the edge.
|
|
347
|
+
7. **Occluders.** A hand over the face (`HandCutout`), glasses and earrings drawing on top, bangs.
|
|
348
|
+
8. **Mirror variants.** Each one, including `upsideDown` with the mouth open.
|
|
349
|
+
9. **Performance.** Every tier on a Pixel 6a, a Galaxy A54 and an iPhone 12, with
|
|
350
|
+
`useXRDiagnostics`. Memory stays flat after 10 photo re-picks.
|