@vincentt-xr/sdk 2.0.0-alpha.4 → 2.0.0-alpha.6
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 +11 -4
- package/README.md +85 -52
- package/dist/{DebuggerUI-DhKTXTY2.js → DebuggerUI-C_rbLdkh.js} +1 -1
- package/dist/{DebuggerUI-bnGHSSOb.cjs → DebuggerUI-DYT_dk1E.cjs} +1 -1
- package/dist/FaceMeshRenderer-D1WsrTLA.cjs +155 -0
- package/dist/FaceMeshRenderer-DSCd1H55.js +1264 -0
- package/dist/{FaceRetouch-Bg-OBU4n.js → FaceRetouch-CMJbGThL.js} +30 -30
- package/dist/{FaceRetouch-TZeBGIqW.cjs → FaceRetouch-DsE0Dbw-.cjs} +1 -1
- package/dist/components/FaceMesh/canonical/CanonicalFaceMeshRenderer.d.ts +11 -1
- package/dist/components/FaceMesh/canonical/geometryGroups.d.ts +1 -1
- package/dist/components/FaceMesh/canonical/parseCanonicalFaceModel.d.ts +1 -0
- package/dist/components/LipEffect/LipEffect.d.ts +2 -0
- package/dist/components/LipEffect/LipEffectMaterial.d.ts +10 -0
- package/dist/components/LipEffect/defaults.d.ts +9 -0
- package/dist/components/LipEffect/index.d.ts +4 -0
- package/dist/components/LipEffect/types.d.ts +22 -0
- package/dist/{contexts-B2_NsTnk.js → contexts-DvQI4PqI.js} +6 -3
- package/dist/contexts-h-9TRH0r.cjs +1 -0
- package/dist/debug-ui/media-source.cjs +1 -1
- package/dist/debug-ui/media-source.js +1 -1
- package/dist/debug-ui.cjs +1 -1
- package/dist/debug-ui.js +10 -10
- package/dist/entries/face-effects.d.ts +2 -0
- package/dist/face-effects.cjs +1 -1
- package/dist/face-effects.js +621 -508
- package/dist/{getFaceInfo-4DhcPZDJ.js → getFaceInfo-B43Cwq4n.js} +1 -1
- package/dist/{getFaceInfo-QOQ_dc-W.cjs → getFaceInfo-DEzcL_Ub.cjs} +1 -1
- package/dist/{index-D1kj6uc-.js → index-B-s4YbWu.js} +1 -1
- package/dist/index-C0-fg1Hk.cjs +1 -0
- package/dist/{index-C9yQVzAh.cjs → index-CY7Z8cHV.cjs} +1 -1
- package/dist/{index-ZaDEzDtR.cjs → index-CxMEeCRP.cjs} +1 -1
- package/dist/{index-WPPnlFO1.cjs → index-D67hHm44.cjs} +1 -1
- package/dist/{index-CNGzE49z.cjs → index-DPPpU5By.cjs} +1 -1
- package/dist/{index-g250Tqme.js → index-DYfY9ljy.js} +1 -1
- package/dist/{index-Cj3fGDtZ.js → index-G_5h_FJQ.js} +8 -8
- package/dist/{index-BMeBJ0dV.js → index-I4eF5TKT.js} +227 -191
- package/dist/{index-72Wb15Ca.js → index-uE3sKczj.js} +1 -1
- package/dist/{internal-Dtvo4WYo.cjs → internal-MvKrz0Nt.cjs} +1 -1
- package/dist/{internal-34pb7djs.js → internal-ldPYiUF0.js} +3 -3
- package/dist/internal.cjs +1 -1
- package/dist/internal.js +1 -1
- package/dist/low-level.cjs +1 -1
- package/dist/low-level.js +11 -11
- package/dist/main.cjs +1 -1
- package/dist/main.js +12 -12
- package/dist/{renderGroups-jSUOY1Oq.cjs → renderGroups-BJsx32q5.cjs} +1 -1
- package/dist/{renderGroups-CPWUX6z9.js → renderGroups-CFt1yYLB.js} +1 -1
- package/dist/{renderPasses-CLlYRdMk.js → renderPasses-C72MbZ-a.js} +4 -4
- package/dist/{renderPasses-KUJUSevp.cjs → renderPasses-D-Krl6D0.cjs} +1 -1
- package/dist/scene-object.cjs +1 -1
- package/dist/scene-object.js +2 -2
- package/dist/{selectors-DLxL8Q66.js → selectors-ByKNTXeA.js} +1 -1
- package/dist/{selectors-S8g25ke9.cjs → selectors-CAwmL9VW.cjs} +1 -1
- package/dist/{session-DP8AF7Rg.cjs → session-CANvoLD6.cjs} +1 -1
- package/dist/{session-CbtvwiaD.js → session-Dhi0OqZo.js} +1 -1
- package/dist/tracking.cjs +1 -1
- package/dist/tracking.js +9 -9
- package/dist/{useFaceInfo-BvZeUBsL.cjs → useFaceInfo-BSZq7AO1.cjs} +1 -1
- package/dist/{useFaceInfo-C06EyScd.js → useFaceInfo-FVQBBNdY.js} +3 -3
- package/dist/{useFaceResults-CCNiH7VZ.cjs → useFaceResults-C3oZkn2Z.cjs} +1 -1
- package/dist/{useFaceResults-C1Ppc8rS.js → useFaceResults-D62STzT1.js} +1 -1
- package/dist/utils/visionWasm.d.ts +18 -0
- package/package.json +2 -2
- package/dist/FaceMeshRenderer-B2i2NW71.js +0 -1195
- package/dist/FaceMeshRenderer-BSOq1OnG.cjs +0 -155
- package/dist/contexts-BgWfyxre.cjs +0 -1
- package/dist/index-Da7uycur.cjs +0 -1
package/GROUNDING.md
CHANGED
|
@@ -20,10 +20,11 @@ Trackers (`<FaceTracker>`, `<GestureTracker>`, `<HandTracker>`, `<BodyTracker>`)
|
|
|
20
20
|
**self-register** when mounted — no explicit `registerXRPipeline` call. Per-frame
|
|
21
21
|
logic is R3F `useFrame`; per-mount setup is `useEffect`.
|
|
22
22
|
|
|
23
|
-
> This file ships inside the SDK tarball
|
|
24
|
-
>
|
|
25
|
-
>
|
|
26
|
-
>
|
|
23
|
+
> This file ships inside the SDK tarball, and that is how it reaches a project:
|
|
24
|
+
> on disk at `node_modules/@vincentt-xr/sdk/GROUNDING.md`. Nothing merges it into
|
|
25
|
+
> the project's own `GROUNDING.md` — a v2-template project has two grounding
|
|
26
|
+
> files, this one for the SDK API and the template's for its local helpers, and
|
|
27
|
+
> an agent reads both. Edit the SDK API here, in the repo that owns the API.
|
|
27
28
|
|
|
28
29
|
### Internal source layout
|
|
29
30
|
|
|
@@ -945,6 +946,12 @@ Fix: mount trackers that more than one scene needs **once**, above the phase swi
|
|
|
945
946
|
|
|
946
947
|
Scope a tracker to a single scene only when just that scene uses it (e.g. a `<FaceTracker>` catcher that exists only during gameplay).
|
|
947
948
|
|
|
949
|
+
### First load: each tracker you mount is a download
|
|
950
|
+
|
|
951
|
+
Before a tracker reports anything, the viewer's phone downloads its model and the shared MediaPipe engine (`vision_wasm_internal.wasm`, served gzip-compressed, ~2.9 MB). The SDK fetches the two in parallel, and trackers mounted together share one engine download. Model sizes: face 3.8 MB, hand 7.8 MB, gesture 8.4 MB, body 5.8 MB. All are cached by the browser for a year, so a returning viewer downloads nothing.
|
|
952
|
+
|
|
953
|
+
So every extra tracker costs a first-time viewer its full model on mobile data. Mount only the trackers the experience actually reads; a face-only effect should not also mount `<HandTracker>`.
|
|
954
|
+
|
|
948
955
|
### `active` — pause an off-scene tracker without unmounting it
|
|
949
956
|
|
|
950
957
|
The "mount once" rule keeps a model alive across scenes, but a persistent tracker then runs its MediaPipe pipeline **every frame for the whole session** — even in scenes that don't use it. Each running model does a GPU→CPU readback per inference, and that readback is often the single largest cost in the app; two persistent trackers (e.g. gesture on the menus, face in gameplay) stack two readbacks the whole time when only one is ever needed at once.
|
package/README.md
CHANGED
|
@@ -1,85 +1,118 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Vincentt XR SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@vincentt-xr/sdk` is the AR runtime for Vincentt projects. It gives a React +
|
|
4
|
+
react-three-fiber app a camera session, face/hand/body tracking, and the
|
|
5
|
+
screen-space layout primitives that most AR effects are built from.
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
Your JSX renders directly — in local preview and in the published bundle at
|
|
8
|
+
`<slug>.vincentt.app`.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
The SDK is installed for you when you scaffold a project from the Vincentt
|
|
13
|
+
template, which pins a known-good version alongside its peers:
|
|
7
14
|
|
|
8
15
|
```
|
|
9
|
-
|
|
16
|
+
vincentt create my-app
|
|
10
17
|
```
|
|
11
18
|
|
|
12
|
-
|
|
19
|
+
To add it to an existing project:
|
|
13
20
|
|
|
14
21
|
```
|
|
15
|
-
|
|
22
|
+
pnpm add @vincentt-xr/sdk
|
|
16
23
|
```
|
|
17
24
|
|
|
18
|
-
|
|
19
|
-
|
|
25
|
+
It expects `react`, `react-dom`, `three`, `@react-three/fiber`,
|
|
26
|
+
`@react-three/drei`, and `@mediapipe/tasks-vision` as peers. The template
|
|
27
|
+
already pins compatible versions of all of them; mismatched copies of React or
|
|
28
|
+
three.js are the most common source of runtime errors.
|
|
20
29
|
|
|
21
|
-
|
|
22
|
-
Initialize the SDK by attaching the `@rangoon/track`'s `Webcam` component to your React Project.
|
|
23
|
-
The `Webcam` component will start a video stream which will be used for tracking.
|
|
30
|
+
## Quick start
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
import { useRef } from "react"
|
|
32
|
+
Wrap your app in `XRProvider`, mount an `XRScene`, and add content. Trackers
|
|
33
|
+
self-register when mounted — there is no pipeline to wire up by hand.
|
|
28
34
|
|
|
29
|
-
|
|
35
|
+
```tsx
|
|
36
|
+
import { ScreenSpaceUI, ScreenText, XRProvider, XRScene } from "@vincentt-xr/sdk";
|
|
37
|
+
import { useFaceDetection } from "@vincentt-xr/sdk/tracking";
|
|
30
38
|
|
|
31
|
-
|
|
39
|
+
function Effect() {
|
|
40
|
+
const detection = useFaceDetection({ numFaces: 1 });
|
|
41
|
+
|
|
42
|
+
if (detection.face) return null;
|
|
32
43
|
|
|
33
44
|
return (
|
|
34
|
-
<
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
45
|
+
<ScreenSpaceUI>
|
|
46
|
+
<ScreenText
|
|
47
|
+
text="SHOW A FACE TO THE CAMERA"
|
|
48
|
+
screenTransform={{ position: { x: 0, y: 0 }, size: { width: 400, height: 52 } }}
|
|
49
|
+
fontSize={24}
|
|
50
|
+
/>
|
|
51
|
+
</ScreenSpaceUI>
|
|
52
|
+
);
|
|
38
53
|
}
|
|
39
54
|
|
|
40
|
-
export default App
|
|
41
|
-
|
|
55
|
+
export default function App() {
|
|
56
|
+
return (
|
|
57
|
+
<XRProvider>
|
|
58
|
+
<XRScene>
|
|
59
|
+
<Effect />
|
|
60
|
+
</XRScene>
|
|
61
|
+
</XRProvider>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
42
64
|
```
|
|
43
65
|
|
|
44
|
-
|
|
66
|
+
## Import doors
|
|
45
67
|
|
|
46
|
-
|
|
47
|
-
* Hand Tracking (Landmarks)
|
|
48
|
-
* Hand Gesture Tracking (Landmarks + Gestures)
|
|
49
|
-
* Face Tracking
|
|
68
|
+
The API is split by task domain. Import each symbol from the door that owns it.
|
|
50
69
|
|
|
51
|
-
|
|
70
|
+
| Entry point | What lives there |
|
|
71
|
+
| -------------------------------- | ------------------------------------------------------------------------------- |
|
|
72
|
+
| `@vincentt-xr/sdk` | Providers, scene root, screen-space layout, renderers, text, capture, audio |
|
|
73
|
+
| `@vincentt-xr/sdk/tracking` | Face / hand / gesture / body / segmentation trackers, anchors, triggers |
|
|
74
|
+
| `@vincentt-xr/sdk/face-effects` | Face mesh materials, retouch, canonical mesh, head binding |
|
|
75
|
+
| `@vincentt-xr/sdk/scene-object` | Scene-object types, factories, selectors, immutable store operations |
|
|
76
|
+
| `@vincentt-xr/sdk/low-level` | Raw model-node reads and custom-tracker plumbing — the escape hatch |
|
|
77
|
+
| `@vincentt-xr/sdk/debug-ui` | Dev-only inspector panels; not for shipping surfaces |
|
|
52
78
|
|
|
53
|
-
|
|
54
|
-
```ts
|
|
55
|
-
import { Webcam, useHandTracking } from "@rangoon/track"
|
|
56
|
-
import { useEffect, useRef } from "react"
|
|
79
|
+
## Documentation
|
|
57
80
|
|
|
58
|
-
|
|
81
|
+
**[`GROUNDING.md`](./GROUNDING.md) is the authoritative API reference** — every
|
|
82
|
+
component, hook, and prop, plus the composition conventions. Read it before
|
|
83
|
+
reaching into `node_modules` or inventing props. It ships inside the package, so
|
|
84
|
+
it travels with the version you actually installed.
|
|
59
85
|
|
|
60
|
-
|
|
86
|
+
Longer-form guides live in [`docs/`](./docs):
|
|
61
87
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
88
|
+
- [`docs/introduction.mdx`](./docs/introduction.mdx) — the scene-object authoring model
|
|
89
|
+
- [`docs/guides/`](./docs/guides) — task guides
|
|
90
|
+
- [`docs/api/`](./docs/api) — API pages
|
|
91
|
+
- [`docs/MIGRATION_GUIDE.md`](./docs/MIGRATION_GUIDE.md) — upgrading from 1.x
|
|
66
92
|
|
|
67
|
-
|
|
68
|
-
useEffect(() => {
|
|
69
|
-
console.log(handData)
|
|
70
|
-
}, [handData])
|
|
93
|
+
## Local development
|
|
71
94
|
|
|
72
|
-
return (
|
|
73
|
-
<div>
|
|
74
|
-
<Webcam videoReference={videoRef}/>
|
|
75
|
-
</div>
|
|
76
|
-
)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export default App
|
|
80
95
|
```
|
|
96
|
+
pnpm install
|
|
97
|
+
pnpm dev # example app
|
|
98
|
+
pnpm preview:tunnel # example app, reachable on a phone
|
|
99
|
+
pnpm build
|
|
100
|
+
pnpm test
|
|
101
|
+
pnpm typecheck
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The example app under `example/` is the development surface for the SDK itself.
|
|
105
|
+
Experiments start there; once one becomes a real app it graduates to its own
|
|
106
|
+
repo built against the packaged SDK.
|
|
107
|
+
|
|
108
|
+
Release steps are in [`RELEASING.md`](./RELEASING.md).
|
|
109
|
+
|
|
110
|
+
## License
|
|
81
111
|
|
|
112
|
+
Proprietary. See [`LICENSE`](./LICENSE) — the published package is for use with
|
|
113
|
+
the Vincentt platform only.
|
|
82
114
|
|
|
83
115
|
## Feedback
|
|
84
116
|
|
|
85
|
-
|
|
117
|
+
Report friction and bugs to the Vincentt team through the beta reporting flow,
|
|
118
|
+
or open an issue on this repository.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as e, jsxs as r, Fragment as f } from "react/jsx-runtime";
|
|
2
2
|
import { useState as P, useEffect as M } from "react";
|
|
3
3
|
import { createPortal as F } from "react-dom";
|
|
4
|
-
import { f as i } from "./internal-
|
|
4
|
+
import { f as i } from "./internal-ldPYiUF0.js";
|
|
5
5
|
const z = {
|
|
6
6
|
position: "fixed",
|
|
7
7
|
top: "10px",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),x=require("react"),C=require("react-dom"),s=require("./internal-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),x=require("react"),C=require("react-dom"),s=require("./internal-MvKrz0Nt.cjs"),P={position:"fixed",top:"10px",left:"10px",zIndex:9999,fontFamily:"'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace",fontSize:"12px",color:"#fff",pointerEvents:"auto",userSelect:"none"},h={background:"rgba(0, 0, 0, 0.85)",borderRadius:"6px",padding:"12px 16px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.5)",backdropFilter:"blur(10px)",border:"1px solid rgba(255, 255, 255, 0.1)",minWidth:"240px"},k={...h,padding:"8px 12px",minWidth:"auto"},F={display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"12px",paddingBottom:"8px",borderBottom:"1px solid rgba(255, 255, 255, 0.2)"},M={fontSize:"13px",fontWeight:"bold",color:"#00ff9f",letterSpacing:"0.5px",textTransform:"uppercase"},z={display:"flex",gap:"6px"},f={background:"rgba(255, 255, 255, 0.1)",border:"1px solid rgba(255, 255, 255, 0.2)",borderRadius:"4px",color:"#fff",padding:"4px 8px",fontSize:"11px",cursor:"pointer",transition:"all 0.2s"},R={display:"grid",gridTemplateColumns:"1fr 1fr",gap:"10px"},i={display:"flex",flexDirection:"column",gap:"4px"},o={fontSize:"10px",color:"rgba(255, 255, 255, 0.6)",textTransform:"uppercase",letterSpacing:"0.5px"},d={fontSize:"16px",fontWeight:"bold",color:"#fff"},u={...d,color:"#00ff9f"},g={...d,color:"#ffaa00"},m={...d,color:"#ff4444"},l={fontSize:"11px",color:"rgba(255, 255, 255, 0.5)",marginLeft:"4px"},N={width:"100%",height:"4px",background:"rgba(255, 255, 255, 0.2)",borderRadius:"2px",overflow:"hidden",marginTop:"4px"},w=t=>({width:`${t}%`,height:"100%",background:t>90?"#ff4444":t>70?"#ffaa00":"#00ff9f",transition:"width 0.3s ease, background 0.3s ease"}),B={fontSize:"9px",color:"rgba(255, 255, 255, 0.4)",marginTop:"8px",textAlign:"center",fontStyle:"italic"};function a(t,n){return n==="fps"?t>=30?u:t>=20?g:m:t<=40?u:t<=60?g:m}function D({metrics:t,collapsed:n,onCollapse:y,onClose:b,position:c="top-left",keyboardShortcut:j="ctrl+shift+d"}){const[p,v]=x.useState(null);if(x.useEffect(()=>{const r=document.createElement("div");return r.id="xr-debugger-overlay",document.body.appendChild(r),v(r),()=>{document.body.removeChild(r)}},[]),!p)return null;const S={...P,...c==="top-right"&&{left:"auto",right:"10px"},...c==="bottom-left"&&{top:"auto",bottom:"10px"},...c==="bottom-right"&&{top:"auto",bottom:"10px",left:"auto",right:"10px"}};return C.createPortal(e.jsx("div",{style:S,children:e.jsxs("div",{style:n?k:h,children:[e.jsxs("div",{style:F,children:[e.jsx("div",{style:M,children:n?"AR Debugger":"AR Performance"}),e.jsxs("div",{style:z,children:[e.jsx("button",{style:f,onClick:()=>y(!n),onMouseEnter:r=>{r.currentTarget.style.background="rgba(255, 255, 255, 0.2)"},onMouseLeave:r=>{r.currentTarget.style.background="rgba(255, 255, 255, 0.1)"},children:n?"+":"−"}),e.jsx("button",{style:f,onClick:b,onMouseEnter:r=>{r.currentTarget.style.background="rgba(255, 255, 255, 0.2)"},onMouseLeave:r=>{r.currentTarget.style.background="rgba(255, 255, 255, 0.1)"},children:"✕"})]})]}),!n&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:R,children:[e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Camera FPS"}),e.jsxs("div",{children:[e.jsx("span",{style:a(t.cameraFPS,"fps"),children:s.formatNumber(t.cameraFPS,0)}),e.jsx("span",{style:l,children:"fps"})]})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Resolution"}),e.jsx("span",{style:d,children:t.resolution})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Detection"}),e.jsxs("div",{children:[e.jsx("span",{style:a(t.detectionTime,"time"),children:s.formatNumber(t.detectionTime,1)}),e.jsx("span",{style:l,children:"ms"})]})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Rendering"}),e.jsxs("div",{children:[e.jsx("span",{style:a(t.renderTime,"time"),children:s.formatNumber(t.renderTime,1)}),e.jsx("span",{style:l,children:"ms"})]})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Effective FPS"}),e.jsxs("div",{children:[e.jsx("span",{style:a(t.effectiveFPS,"fps"),children:s.formatNumber(t.effectiveFPS,0)}),e.jsx("span",{style:l,children:"fps"})]})]}),e.jsxs("div",{style:i,children:[e.jsx("div",{style:o,children:"Memory"}),t.memory?e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("span",{style:d,children:s.formatNumber(t.memory.used,0)}),e.jsxs("span",{style:l,children:["/ ",s.formatNumber(t.memory.total,0)," MB"]})]}),e.jsx("div",{style:N,children:e.jsx("div",{style:w(t.memory.percentage)})})]}):e.jsx("span",{style:d,children:"N/A"})]})]}),t.modelPerformance.length>0&&e.jsx(e.Fragment,{children:e.jsxs("div",{style:{borderTop:"1px solid rgba(255, 255, 255, 0.15)",marginTop:"12px",paddingTop:"12px"},children:[e.jsx("div",{style:o,children:"Model Performance"}),e.jsx("div",{style:{marginTop:"8px",display:"flex",flexDirection:"column",gap:"6px"},children:t.modelPerformance.map((r,T)=>e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",fontSize:"11px"},children:[e.jsx("span",{style:{color:"rgba(255, 255, 255, 0.7)"},children:r.name}),e.jsxs("div",{children:[e.jsx("span",{style:a(r.processingTime,"time"),children:s.formatNumber(r.processingTime,1)}),e.jsx("span",{style:l,children:"ms"})]})]},T))})]})}),e.jsxs("div",{style:B,children:["Press ",j.toUpperCase()," to toggle"]})]})]})}),p)}exports.DebuggerUI=D;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";const u=require("react/jsx-runtime"),te=require("@react-three/fiber"),c=require("react"),ee=require("three"),Q=require("./index-C0-fg1Hk.cjs"),Ve=require("./selectors-CAwmL9VW.cjs"),Fe=require("./index-CxMEeCRP.cjs"),Qt=require("@react-three/drei");function Zt(e){const n=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const t in e)if(t!=="default"){const r=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(n,t,r.get?r:{enumerable:!0,get:()=>e[t]})}}return n.default=e,Object.freeze(n)}const p=Zt(ee),he=8,Y={type:"linear",stops:[{offset:0,color:"#38bdf8"},{offset:1,color:"#a78bfa"}],angle:0,center:{x:.5,y:.5},radius:.5},Jt=e=>{const n=e.slice(0,he).map(t=>({...t,offset:ee.MathUtils.clamp(t.offset,0,1)})).sort((t,r)=>t.offset-r.offset);return n.length>=2?n:Y.stops.map(t=>({...t}))},Ye=e=>({...Y,...e,center:{...Y.center,...e==null?void 0:e.center},radius:Math.max(.01,(e==null?void 0:e.radius)??Y.radius),stops:Jt((e==null?void 0:e.stops)??Y.stops)}),en=`
|
|
2
|
+
varying vec2 vPosition;
|
|
3
|
+
void main() {
|
|
4
|
+
vPosition = position.xy;
|
|
5
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
6
|
+
}
|
|
7
|
+
`,tn=`
|
|
8
|
+
#define MAX_STOPS 8
|
|
9
|
+
uniform vec3 stopColors[MAX_STOPS];
|
|
10
|
+
uniform float stopOffsets[MAX_STOPS];
|
|
11
|
+
uniform int stopCount;
|
|
12
|
+
uniform int gradientType;
|
|
13
|
+
uniform vec2 direction;
|
|
14
|
+
uniform vec2 center;
|
|
15
|
+
uniform float radius;
|
|
16
|
+
uniform float angleOffset;
|
|
17
|
+
uniform float opacity;
|
|
18
|
+
varying vec2 vPosition;
|
|
19
|
+
|
|
20
|
+
vec3 sampleGradient(float amount) {
|
|
21
|
+
vec3 color = stopColors[0];
|
|
22
|
+
for (int index = 1; index < MAX_STOPS; index++) {
|
|
23
|
+
if (index >= stopCount) break;
|
|
24
|
+
if (amount <= stopOffsets[index]) {
|
|
25
|
+
float width = max(0.0001, stopOffsets[index] - stopOffsets[index - 1]);
|
|
26
|
+
return mix(stopColors[index - 1], stopColors[index], clamp((amount - stopOffsets[index - 1]) / width, 0.0, 1.0));
|
|
27
|
+
}
|
|
28
|
+
color = stopColors[index];
|
|
29
|
+
}
|
|
30
|
+
return color;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
void main() {
|
|
34
|
+
vec2 delta = vPosition - center;
|
|
35
|
+
float amount;
|
|
36
|
+
if (gradientType == 1) {
|
|
37
|
+
amount = clamp(length(delta) / radius, 0.0, 1.0);
|
|
38
|
+
} else if (gradientType == 2) {
|
|
39
|
+
amount = fract(atan(delta.y, delta.x) / 6.28318530718 + 0.5 + angleOffset);
|
|
40
|
+
} else {
|
|
41
|
+
amount = clamp(dot(delta, direction) + 0.5, 0.0, 1.0);
|
|
42
|
+
}
|
|
43
|
+
gl_FragColor = vec4(sampleGradient(amount), opacity);
|
|
44
|
+
}
|
|
45
|
+
`,nn={linear:0,radial:1,angular:2},$e=({opacity:e=1,value:n})=>{const t=c.useMemo(()=>{const r=Ye(n),o=ee.MathUtils.degToRad(r.angle),a=r.stops.map(s=>new ee.Color(s.color)),i=r.stops.map(s=>s.offset);for(;a.length<he;)a.push(a[a.length-1]);for(;i.length<he;)i.push(1);return{stopColors:{value:a},stopOffsets:{value:i},stopCount:{value:r.stops.length},gradientType:{value:nn[r.type]},direction:{value:new ee.Vector2(Math.cos(o),Math.sin(o))},center:{value:new ee.Vector2(r.center.x-.5,.5-r.center.y)},radius:{value:r.radius},angleOffset:{value:r.angle/360},opacity:{value:e}}},[e,n]);return u.jsx("shaderMaterial",{uniforms:t,vertexShader:en,fragmentShader:tn,transparent:e<1,depthTest:!1,depthWrite:!1,toneMapped:!1})},rn="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO2YpZcAAAAASUVORK5CYII=",on={source:"solid",color:"#ffffff",opacity:1,textureUrl:"",gradient:Y},we=e=>({...Y,stops:[{offset:0,color:"#ffffff"},{offset:1,color:e}]}),an=({depthTest:e,depthWrite:n,settings:t,side:r,toneMapped:o})=>{const a=te.useLoader(p.TextureLoader,t.textureUrl||rn);return u.jsx("meshBasicMaterial",{color:t.color,map:a,transparent:!0,opacity:t.opacity,side:r,depthWrite:n,depthTest:e,toneMapped:o})},Ke=({depthTest:e=!1,depthWrite:n=!1,settings:t,side:r,toneMapped:o=!1})=>{const a=c.useMemo(()=>t.gradient??we(t.color),[t.color,t.gradient]);return t.source==="gradient"?u.jsx($e,{value:a,opacity:t.opacity}):t.source==="texture"?u.jsx(an,{settings:t,side:r,depthTest:e,depthWrite:n,toneMapped:o}):u.jsx("meshBasicMaterial",{color:t.color,transparent:!0,opacity:t.opacity,side:r,depthWrite:n,depthTest:e,toneMapped:o})},Re=Math.PI/180,Se=180/Math.PI,B=e=>Number(e.toFixed(6)),ke={enabled:!0,linked:{position:!1,rotation:!1,scale:!1},showTransformControls:!1,transformControlMode:"translate",transformControlSpace:"local",position:{x:0,y:0,z:0},rotation:{x:0,y:0,z:0},scale:{x:1,y:1,z:1},visible:!0},sn=({children:e,objectRef:n,onChange:t,value:r})=>{const o=c.useRef(null),a=c.useRef(n);a.current=n;const[i,s]=c.useState(null),d=c.useCallback(l=>{var x;o.current=l,s(l),(x=a.current)==null||x.call(a,l)},[]),h=c.useCallback(()=>{const l=o.current;!l||!t||t({...r,position:{x:B(l.position.x),y:B(l.position.y),z:B(l.position.z)},rotation:{x:B(l.rotation.x*Se),y:B(l.rotation.y*Se),z:B(l.rotation.z*Se)},scale:{x:B(l.scale.x),y:B(l.scale.y),z:B(l.scale.z)}})},[t,r]);return r.enabled?u.jsxs(u.Fragment,{children:[u.jsx("group",{ref:d,position:[r.position.x,r.position.y,r.position.z],rotation:[r.rotation.x*Re,r.rotation.y*Re,r.rotation.z*Re],scale:[r.scale.x,r.scale.y,r.scale.z],visible:r.visible,children:e}),i&&r.showTransformControls&&u.jsx(Qt.TransformControls,{object:i,mode:r.transformControlMode,space:r.transformControlSpace,size:.85,onMouseUp:h,onObjectChange:h})]}):null},ae=e=>Math.min(1,Math.max(0,e)),O=(e,n,t)=>ae(1-Math.abs(e-n)/t),cn=e=>{let n=1/0,t=-1/0,r=1/0,o=-1/0;for(const s of e)n=Math.min(n,s.x),t=Math.max(t,s.x),r=Math.min(r,s.y),o=Math.max(o,s.y);const a=Math.max(t-n,.001),i=Math.max(o-r,.001);return{centerX:n+a*.5,centerY:r+i*.5,width:a,height:i}},ln=e=>e!=null&&e.enabled?(e.strength??1)!==0&&Object.entries(e).some(([n,t])=>n!=="enabled"&&n!=="strength"&&typeof t=="number"&&t!==0):!1,un=(e,n,t,r)=>{const o=t.enabled?t.strength??1:0;if(o===0)return r.x=e.x,r.y=e.y,r.z=e.z,r;const a=(e.x-n.centerX)/n.width,i=(e.y-n.centerY)/n.height,s=Math.abs(a),d=ae((-i+.42)/.55),h=O(i,-.02,.34),l=O(i,-.24,.16)*ae((s-.05)/.28),x=O(i,.02,.26)*O(s,0,.18),_=O(i,.29,.18)*O(s,0,.36),D=ae((i-.16)/.36),C=h*O(s,.34,.22),k=d*O(s,0,.48),S=O(i,-.19,.1)*ae((s-.05)/.3),$=O(i,.48,.2)*O(s,0,.26);let A=e.x,y=e.y,w=e.z;const E=(v,m=1)=>{A+=a*n.width*v*o*m},f=(v,m=1)=>{y+=i*n.height*v*o*m};E(t.faceWidth??0),f(t.faceHeight??0),E(t.faceRoundness??0,h*(1-s)),y-=n.height*(t.midfaceHeight??0)*o*h*.25,f(-(t.foreheadHeight??0),k),E(t.foreheadWidth??0,k),E(t.cheekboneWidth??0,O(i,-.06,.16)*O(s,.34,.2)),E(t.cheekWidth??0,C),E(t.jawWidth??0,D),f(t.chinHeight??0,$),y-=n.height*(t.scalpHeight??0)*o*d*.3,w-=(t.midfaceDepth??0)*o*h*.08,w+=(t.cheekHollowness??0)*o*C*.06,w-=(t.browDepth??0)*o*S*.05,y-=n.height*(t.browHeight??0)*o*S*.2,A+=Math.sign(a||1)*n.width*(t.browDistance??0)*o*S*.16;const F=(t.headCurve??0)*o*(i+.1);w-=F*F*.04*Math.sign(t.headCurve??0),A+=n.width*(t.faceTwist??0)*o*i*.18;const H=(t.faceSwirl??0)*o*.22;A+=-i*n.width*H,y+=a*n.height*H;const I=a<0?t.leftEyeSize??0:t.rightEyeSize??0,b=((t.eyeSize??0)+I)*o*l;A+=a*n.width*b*.45,y+=(i+.24)*n.height*b*.7,A+=Math.sign(a||1)*n.width*(t.eyeDistance??0)*o*l*.2,A+=n.width*(a<0?t.leftEyeX??0:t.rightEyeX??0)*o*l*.15,y+=n.height*(a<0?t.leftEyeY??0:t.rightEyeY??0)*o*l*.15;const R=(t.noseSize??0)*o*x;return A+=a*n.width*R*.7,y+=(i-.02)*n.height*R*.5,y+=n.height*(t.noseLength??0)*o*x*Math.max(i+.08,0)*.4,w-=(t.noseSize??0)*o*x*.08,A+=a*n.width*(t.mouthWidth??0)*o*_,y+=(i-.29)*n.height*(t.mouthHeight??0)*o*_,r.x=A,r.y=y,r.z=w,r},ve=new Set([61,146,91,181,84,17,314,405,321,375,291,78,95,88,178,87,14,317,402,318,324,308,191,80,81,82,13,312,311,310,415]),Xe=[61,146,91,181,84,17,314,405,321,375,291,409,270,269,267,0,37,39,40,185],Te=new Set([33,7,163,144,145,153,154,155,133,173,157,158,159,160,161,246]),_e=new Set([362,382,381,380,374,373,390,249,263,466,388,387,386,385,384,398]),fn=new Set([814,815,816,817,818,819,830,831,832,833]),dn=(e,n,t)=>{const r=ve.has(e)&&ve.has(n)&&ve.has(t),o=Te.has(e)&&Te.has(n)&&Te.has(t),a=_e.has(e)&&_e.has(n)&&_e.has(t);return r?"mouth":o?"leftEye":a?"rightEye":"base"},hn=e=>{const n=new Map;for(let s=0;s<e.length;s+=3){const d=[e[s],e[s+1],e[s+2]];for(let h=0;h<3;h+=1){const l=d[h],x=d[(h+1)%3],_=l<x?`${l}:${x}`:`${x}:${l}`,D=n.get(_);D?D.count+=1:n.set(_,{a:l,b:x,count:1})}}const t=new Map;n.forEach(({a:s,b:d,count:h})=>{h===1&&(t.set(s,[...t.get(s)??[],d]),t.set(d,[...t.get(d)??[],s]))});const r=[...t.keys()].sort((s,d)=>s-d)[0];if(r===void 0)return[];const o=[r];let a=-1,i=r;for(;o.length<=t.size+1;){const s=(t.get(i)??[]).find(d=>d!==a);if(s===void 0||s===r)break;o.push(s),a=i,i=s}return o},qe=e=>{const n=[],t=[],r=[],o=[],a=[],i=[],s=[],d=[];let h=0,l=0;e.split(`
|
|
46
|
+
`).forEach(E=>{const f=E.trim();if(!f)return;if(f.startsWith("v ")){const[,b,R,v]=f.split(/\s+/);s.push([Number(b),Number(R),Number(v)]),h+=1;return}if(f.startsWith("vt ")){const[,b,R]=f.split(/\s+/);i.push([Number(b),Number(R)]);return}if(!f.startsWith("f "))return;const F=l;l+=1;const[,...H]=f.split(/\s+/),I=H.map(b=>{const[R,v]=b.split("/"),m=Number(R)-1,G=Number(v)-1;return G>=0&&i[G]&&!d[m]&&(d[m]=i[G]),m});if(!(I.length<3))for(let b=1;b<I.length-1;b+=1){const R=I[0],v=I[b],m=I[b+1],G=dn(R,v,m);fn.has(F)?a.push(R,v,m):G==="mouth"?t.push(R,v,m):G==="leftEye"?r.push(R,v,m):G==="rightEye"?o.push(R,v,m):n.push(R,v,m)}});const x=[];for(let E=0;E<h;E+=1){const[f,F]=d[E]??[0,0];x.push(f,F)}const _=new Uint16Array(r),D=new Uint16Array(o),C=new Uint16Array(r.length+o.length);C.set(_),C.set(D,_.length);const k=Xe.map(E=>{const[f,F]=s[E]??[0,0];return new p.Vector2(f,F)}),S=hn(t),$=S.map(E=>{const[f,F]=s[E]??[0,0];return new p.Vector2(f,F)}),A=p.ShapeUtils.triangulateShape(k,[$]),y=[...Xe,...S],w=new Uint16Array(S.length>2?A.flatMap(E=>E.map(f=>y[f])):[]);return{baseIndices:new Uint16Array(n),mouthIndices:new Uint16Array(t),lipIndices:w,leftEyeIndices:_,rightEyeIndices:D,eyeIndices:C,noseIndices:new Uint16Array(a),uvs:new Float32Array(x),vertexCount:h}},mn="canonical_face_model.obj",pn=new TextDecoder("utf-8"),Ce=new Map,yn=e=>{const n=Ce.get(e);if(n)return n;const t=Q.fetchAndVerify(e).then(r=>qe(pn.decode(r))).catch(r=>{throw Ce.delete(e),r});return Ce.set(e,t),t},Qe=e=>{const{mesh:n,url:t}=e??{},r=t??`${Q.libConfig.sdkAssetsBaseUrl}/${mn}`,[o,a]=c.useState(n??null);return c.useEffect(()=>{if(n){a(n);return}let i=!1;return yn(r).then(s=>{i||a(s)}).catch(s=>{i||console.error(`${Q.libConfig.loggerPrefix} canonical face mesh load failed`,s)}),()=>{i=!0}},[n,r]),o},T={basic:"basic",standard:"standard",physical:"physical",toon:"toon",normal:"normal",matcap:"matcap",wireframe:"wireframe",shader:"shader"},V={originalFace:"originalFace",composite:"composite"},X={none:"none",canonical:"canonical",style2:"style2"},q={none:"none",canonical:"canonical"},oe={solid:"solid",gradient:"gradient",imageUrl:"imageUrl",mediaUrl:"mediaUrl"},ne={front:"front",back:"back",double:"double"},Ie={normal:"normal",add:"add",subtract:"subtract",multiply:"multiply",screen:"screen",overlay:"overlay",softLight:"softLight",hardLight:"hardLight",lighten:"lighten",darken:"darken",difference:"difference",exclusion:"exclusion"},En={textureMap:X.canonical,alphaMap:q.canonical,alphaOpacity:1},We={...En,blendMode:Ie.hardLight,blendOpacity:.85,baseColor:"#ffffff",opacity:1,compositeShading:!0},N={materialType:T.basic,shaderPreset:V.originalFace,textureMap:X.none,alphaMap:q.none,alphaOpacity:1,side:ne.front,blendMode:Ie.normal,blendOpacity:1,baseColor:"#38bdf8",opacity:.45,compositeShading:!1};T.shader,V.composite,ne.front;const fe={mouth:!0,eyes:!0,nose:!0},re={textureSource:oe.solid,color:"#111111",opacity:.5},Mn=24,Ze=10,Le=(e,n,t)=>e!==T.shader?"none":n===V.originalFace?"originalFace":n===V.composite?t===X.none?"originalFace":"composite":"none",An=(e,n)=>e===T.basic||e===T.standard||e===T.physical||e===T.toon||e===T.shader&&n===V.composite,bn=(e,n,t=X.canonical)=>Le(e,n,t)==="composite",gn=(e,n,t)=>Le(e,n,t)==="originalFace",me=e=>e===oe.imageUrl||e===oe.mediaUrl,Je=e=>e===oe.solid||e===oe.gradient,Ue={normal:0,add:1,subtract:2,multiply:3,screen:4,overlay:5,softLight:6,hardLight:7,lighten:8,darken:9,difference:10,exclusion:11},de="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO2YpZcAAAAASUVORK5CYII=",xn=()=>{const e=new Uint8Array([32,32,32,255,96,96,96,255,176,176,176,255,255,255,255,255]),n=new p.DataTexture(e,4,1,p.RGBAFormat);return n.minFilter=p.NearestFilter,n.magFilter=p.NearestFilter,n.generateMipmaps=!1,n.needsUpdate=!0,n},Rn=()=>{const e=document.createElement("canvas");e.width=256,e.height=256;const n=e.getContext("2d");if(!n)return new p.CanvasTexture(e);const t=n.createRadialGradient(96,80,10,128,128,128);t.addColorStop(0,"#ffffff"),t.addColorStop(.18,"#f7d794"),t.addColorStop(.45,"#d97706"),t.addColorStop(.72,"#78350f"),t.addColorStop(1,"#120701"),n.fillStyle=t,n.fillRect(0,0,e.width,e.height);const r=new p.CanvasTexture(e);return r.needsUpdate=!0,r},Sn=`
|
|
47
|
+
attribute vec2 faceUv;
|
|
48
|
+
varying vec2 vUv;
|
|
49
|
+
varying vec2 vFaceUv;
|
|
50
|
+
varying vec3 vNormal;
|
|
51
|
+
|
|
52
|
+
void main() {
|
|
53
|
+
vUv = uv;
|
|
54
|
+
vFaceUv = faceUv;
|
|
55
|
+
vNormal = normalize(normalMatrix * normal);
|
|
56
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
57
|
+
}
|
|
58
|
+
`,vn=`
|
|
59
|
+
uniform sampler2D cameraTexture;
|
|
60
|
+
uniform sampler2D canonicalTexture;
|
|
61
|
+
uniform sampler2D alphaMask;
|
|
62
|
+
uniform vec3 textureTint;
|
|
63
|
+
uniform float opacity;
|
|
64
|
+
uniform int blendMode;
|
|
65
|
+
uniform float blendOpacity;
|
|
66
|
+
uniform float useCanonicalTexture;
|
|
67
|
+
uniform float useAlphaMask;
|
|
68
|
+
uniform float alphaOpacity;
|
|
69
|
+
uniform float compositeShading;
|
|
70
|
+
uniform vec3 lightDirection;
|
|
71
|
+
uniform float ambientStrength;
|
|
72
|
+
uniform float directionalStrength;
|
|
73
|
+
varying vec2 vUv;
|
|
74
|
+
varying vec2 vFaceUv;
|
|
75
|
+
varying vec3 vNormal;
|
|
76
|
+
|
|
77
|
+
vec3 linearToSrgb(vec3 value) {
|
|
78
|
+
vec3 low = value * 12.92;
|
|
79
|
+
vec3 high = 1.055 * pow(max(value, vec3(0.0)), vec3(1.0 / 2.4)) - 0.055;
|
|
80
|
+
return mix(high, low, step(value, vec3(0.0031308)));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
vec3 srgbToLinear(vec3 value) {
|
|
84
|
+
vec3 low = value / 12.92;
|
|
85
|
+
vec3 high = pow(max((value + 0.055) / 1.055, vec3(0.0)), vec3(2.4));
|
|
86
|
+
return mix(high, low, step(value, vec3(0.04045)));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
float overlayChannel(float base, float blend) {
|
|
90
|
+
return base < 0.5 ? 2.0 * base * blend : 1.0 - 2.0 * (1.0 - base) * (1.0 - blend);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
float hardLightChannel(float base, float blend) {
|
|
94
|
+
return blend < 0.5 ? 2.0 * base * blend : 1.0 - 2.0 * (1.0 - base) * (1.0 - blend);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
float softLightChannel(float base, float blend) {
|
|
98
|
+
if (blend <= 0.5) {
|
|
99
|
+
return base - (1.0 - 2.0 * blend) * base * (1.0 - base);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
float d = base <= 0.25
|
|
103
|
+
? ((16.0 * base - 12.0) * base + 4.0) * base
|
|
104
|
+
: sqrt(base);
|
|
105
|
+
|
|
106
|
+
return base + (2.0 * blend - 1.0) * (d - base);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
vec3 applyBlendMode(vec3 base, vec3 blend, int mode) {
|
|
110
|
+
if (mode == 0) return blend;
|
|
111
|
+
if (mode == 1) return min(base + blend, 1.0);
|
|
112
|
+
if (mode == 2) return max(base - blend, 0.0);
|
|
113
|
+
if (mode == 3) return base * blend;
|
|
114
|
+
if (mode == 4) return 1.0 - (1.0 - base) * (1.0 - blend);
|
|
115
|
+
if (mode == 5) {
|
|
116
|
+
return vec3(
|
|
117
|
+
overlayChannel(base.r, blend.r),
|
|
118
|
+
overlayChannel(base.g, blend.g),
|
|
119
|
+
overlayChannel(base.b, blend.b)
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
if (mode == 6) {
|
|
123
|
+
return vec3(
|
|
124
|
+
softLightChannel(base.r, blend.r),
|
|
125
|
+
softLightChannel(base.g, blend.g),
|
|
126
|
+
softLightChannel(base.b, blend.b)
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
if (mode == 7) {
|
|
130
|
+
return vec3(
|
|
131
|
+
hardLightChannel(base.r, blend.r),
|
|
132
|
+
hardLightChannel(base.g, blend.g),
|
|
133
|
+
hardLightChannel(base.b, blend.b)
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
if (mode == 8) return max(base, blend);
|
|
137
|
+
if (mode == 9) return min(base, blend);
|
|
138
|
+
if (mode == 10) return abs(base - blend);
|
|
139
|
+
return base + blend - 2.0 * base * blend;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
void main() {
|
|
143
|
+
vec3 base = linearToSrgb(texture2D(cameraTexture, vFaceUv).rgb);
|
|
144
|
+
vec4 textureSample = texture2D(canonicalTexture, vUv);
|
|
145
|
+
vec3 blend = linearToSrgb(textureSample.rgb) * textureTint;
|
|
146
|
+
float light = ambientStrength + max(dot(normalize(vNormal), normalize(lightDirection)), 0.0) * directionalStrength;
|
|
147
|
+
blend *= mix(1.0, clamp(light, 0.35, 1.35), compositeShading);
|
|
148
|
+
float maskSample = texture2D(alphaMask, vUv).r;
|
|
149
|
+
float mask = useAlphaMask > 0.5 ? mix(1.0, maskSample, alphaOpacity) : 1.0;
|
|
150
|
+
float textureAlpha = useCanonicalTexture > 0.5 ? textureSample.a : 1.0;
|
|
151
|
+
vec3 blended = applyBlendMode(base, blend, blendMode);
|
|
152
|
+
vec3 color = useCanonicalTexture > 0.5 ? mix(base, blended, blendOpacity) : base;
|
|
153
|
+
gl_FragColor = vec4(srgbToLinear(color), opacity * mask * textureAlpha);
|
|
154
|
+
}
|
|
155
|
+
`,et=({alphaMap:e,alphaOpacity:n,blendMode:t,blendOpacity:r,cameraTexture:o,color:a,compositeShading:i,faceAlphaMaskUrl:s,faceTextureStyle2Url:d,faceTextureUrl:h,masked:l=!1,maskColor:x,maskOpacity:_,maskSourceUrl:D,maskTextureSource:C,materialType:k,opacity:S,shaderPreset:$,side:A,textureMap:y})=>{const w=te.useLoader(p.TextureLoader,h||de),E=te.useLoader(p.TextureLoader,d||h||de),f=te.useLoader(p.TextureLoader,s||de),F=c.useMemo(()=>xn(),[]),H=c.useMemo(()=>Rn(),[]);c.useEffect(()=>()=>{F.dispose(),H.dispose()},[H,F]);const I=y===X.style2?E:w,b=y!==X.none,R=Le(k,$,y),v=["composite-material",y,e,n,t,r,i?"lit":"flat",a,S,h,d,s].join("|"),m={side:A,transparent:!0,opacity:S,wireframe:!1},G=c.useMemo(()=>({source:me(C)?"texture":C,color:Je(C)?x:"#ffffff",opacity:_,textureUrl:me(C)?D:"",gradient:we(x)}),[x,_,D,C]),U=c.useMemo(()=>({cameraTexture:{value:null},canonicalTexture:{value:null},alphaMask:{value:null},textureTint:{value:new p.Color(a)},opacity:{value:S},blendMode:{value:Ue[t]},blendOpacity:{value:r},useCanonicalTexture:{value:b?1:0},useAlphaMask:{value:e===q.canonical?1:0},alphaOpacity:{value:n},compositeShading:{value:i?1:0},lightDirection:{value:new p.Vector3(.3,.65,.7).normalize()},ambientStrength:{value:.78},directionalStrength:{value:.38}}),[e,n,t,r,a,i,b,S]);if(c.useEffect(()=>{U.cameraTexture.value=o??w,U.canonicalTexture.value=I,U.alphaMask.value=f,U.textureTint.value.set(a),U.opacity.value=S,U.blendMode.value=Ue[t],U.blendOpacity.value=r,U.useCanonicalTexture.value=b?1:0,U.useAlphaMask.value=e===q.canonical?1:0,U.alphaOpacity.value=n,U.compositeShading.value=i?1:0},[e,f,n,t,r,o,a,i,U,w,b,S,I]),l)return u.jsx(Ke,{settings:G,side:A},`masked-${C}-material`);if(k===T.wireframe)return u.jsx("meshBasicMaterial",{color:a,transparent:!0,opacity:S,side:A,depthWrite:!1,depthTest:!1,wireframe:!0,toneMapped:!1},"wireframe-material");if(R==="originalFace"&&o)return u.jsx("meshBasicMaterial",{map:o,alphaMap:f,transparent:!0,opacity:S,side:A,depthWrite:!1,depthTest:!0,toneMapped:!1},"use-original-face-material");if(R==="composite"&&o)return u.jsx("shaderMaterial",{uniforms:U,vertexShader:Sn,fragmentShader:vn,transparent:!0,side:A,depthWrite:!1,depthTest:!0,toneMapped:!1},v);const Z=b?I:null,K=e===q.canonical&&n>0?f:null,W=`${k}-${y}-${e}-${n>0?"alpha-on":"alpha-off"}`;return k===T.standard?u.jsx("meshStandardMaterial",{...m,color:a,map:Z??void 0,alphaMap:K??void 0,depthWrite:!0,depthTest:!0,metalness:.05,roughness:.72},W):k===T.physical?u.jsx("meshPhysicalMaterial",{...m,color:a,map:Z??void 0,alphaMap:K??void 0,depthWrite:!0,depthTest:!0,roughness:.58,metalness:.08,clearcoat:.35,clearcoatRoughness:.4},W):k===T.toon?u.jsx("meshToonMaterial",{...m,color:a,map:Z??void 0,alphaMap:K??void 0,gradientMap:F,depthWrite:!0,depthTest:!0},W):k===T.normal?u.jsx("meshNormalMaterial",{...m,depthWrite:!0,depthTest:!0,flatShading:!1},"normal-material"):k===T.matcap?u.jsx("meshMatcapMaterial",{...m,color:a,matcap:H,depthWrite:!0,depthTest:!0},"matcap-material"):u.jsx("meshBasicMaterial",{...m,color:a,map:Z??void 0,alphaMap:K??void 0,depthWrite:!1,depthTest:y!==X.none||e!==q.none,toneMapped:!1},W)},tt=[{key:"base",getIndices:e=>e.baseIndices,masked:!1,renderOrderOffset:0},{key:"mouth",getIndices:e=>e.mouthIndices,masked:!1,renderOrderOffset:2},{key:"lips",getIndices:e=>e.lipIndices,masked:!1,renderOrderOffset:3},{key:"left-eye",getIndices:e=>e.leftEyeIndices,masked:!1,renderOrderOffset:2},{key:"right-eye",getIndices:e=>e.rightEyeIndices,masked:!1,renderOrderOffset:2},{key:"nose",getIndices:e=>e.noseIndices,masked:!1,renderOrderOffset:2},{key:"mouth-mask",getIndices:e=>e.mouthIndices,masked:!0,renderOrderOffset:3},{key:"left-eye-mask",getIndices:e=>e.leftEyeIndices,masked:!0,renderOrderOffset:3},{key:"right-eye-mask",getIndices:e=>e.rightEyeIndices,masked:!0,renderOrderOffset:3},{key:"nose-mask",getIndices:e=>e.noseIndices,masked:!0,renderOrderOffset:3}],Tn={[ne.front]:p.FrontSide,[ne.back]:p.BackSide,[ne.double]:p.DoubleSide},_n=(e,n,t)=>{e.setAttribute("position",n.position),e.setAttribute("uv",n.uv),e.setAttribute("faceUv",n.faceUv),e.setIndex(new p.BufferAttribute(t,1))},nt=({faceIndex:e=0,baseColor:n,color:t=N.baseColor,opacity:r=N.opacity,materialType:o=N.materialType,shaderPreset:a=N.shaderPreset,textureMap:i=N.textureMap,alphaMap:s=N.alphaMap,alphaOpacity:d=N.alphaOpacity,side:h=N.side,blendMode:l=N.blendMode,blendOpacity:x=N.blendOpacity,showOverlayMask:_=!1,showMouthMask:D=fe.mouth,showEyeMask:C=fe.eyes,showLeftEyeMask:k,showRightEyeMask:S,showNoseMask:$=fe.nose,showEyeGeometry:A=!0,showLeftEyeGeometry:y,showRightEyeGeometry:w,showMouthGeometry:E=!0,showLipsGeometry:f=!0,showBaseGeometry:F=!0,showNoseGeometry:H=!0,maskTextureSource:I=re.textureSource,maskSourceUrl:b="",maskColor:R=re.color,maskOpacity:v=re.opacity,faceTextureUrl:m="",faceTextureStyle2Url:G="",faceAlphaMaskUrl:U="",compositeShading:Z=!1,faceWarp3D:K,transform:W,renderOrder:ct=Ze,externalScale:pe=1,mesh:lt,meshUrl:ut,materialOverride:se})=>{const ye=Ve.useXRModelNode(Q.XRModel.FACE_TRACKER),Oe=Ve.useXRCameraTexture(),{camera:ft}=te.useThree(),j=Qe({mesh:lt,url:ut}),De=c.useRef(null),dt=c.useRef(null),ht=c.useRef(null),mt=c.useRef(null),pt=c.useRef(null),yt=c.useRef(null),Et=c.useRef(null),Mt=c.useRef(null),At=c.useRef(null),bt=c.useRef(null),gt=c.useRef(null),xt=c.useRef(null),Rt=c.useRef(null),St=c.useRef(null),vt=c.useRef(null),Tt=c.useRef(null),_t=c.useRef(null),Ct=c.useRef(null),Ft=c.useRef(null),kt=c.useRef(null),Ee=c.useRef(null),Me=c.useRef(null),Ae=c.useRef(null),Pe=c.useRef(null),Ut=c.useRef(new p.Vector3),wt=c.useRef({x:0,y:0,z:0}),It=c.useRef({x:0,y:0,z:0}),Lt=c.useRef({x:0,y:0,z:0}),ie=c.useRef(!1),Ot=Tn[h],Dt=n??t,Pt=y??A,Nt=w??A,Gt=_||(k??C),Ht=_||(S??C),jt=_||D,zt=_||$,Bt={base:De,mouth:dt,lips:ht,"left-eye":mt,"right-eye":pt,nose:yt,"mouth-mask":Et,"left-eye-mask":Mt,"right-eye-mask":At,"nose-mask":bt},Vt={base:gt,mouth:xt,lips:Rt,"left-eye":St,"right-eye":vt,nose:Tt,"mouth-mask":_t,"left-eye-mask":Ct,"right-eye-mask":Ft,"nose-mask":kt},Xt={base:F,mouth:E,lips:f,"left-eye":Pt,"right-eye":Nt,nose:H,"mouth-mask":jt,"left-eye-mask":Gt,"right-eye-mask":Ht,"nose-mask":zt},Wt=g=>u.jsx(et,{alphaMap:s,alphaOpacity:d,blendMode:l,blendOpacity:x,cameraTexture:Oe,color:Dt,compositeShading:Z,faceAlphaMaskUrl:U,faceTextureStyle2Url:G,faceTextureUrl:m,masked:g,maskColor:R,maskOpacity:v,maskSourceUrl:b,maskTextureSource:I,materialType:o,opacity:r,shaderPreset:a,side:Ot,textureMap:i}),J=tt.map(g=>({...g,geometryRef:Bt[g.key],meshRef:Vt[g.key],visible:Xt[g.key]})),Yt=g=>Fe.projectLandmarkWithDepth(g,ft,Ut.current);return te.useFrame(()=>{var je,ze;const g=De.current,z=(ze=(je=ye==null?void 0:ye.detectionResults)==null?void 0:je.faceLandmarks)==null?void 0:ze[e],$t=J.every(M=>M.geometryRef.current&&M.meshRef.current);if(!j||!g||!$t)return;if(!z||z.length<j.vertexCount){J.forEach(M=>{M.meshRef.current.visible=!1});return}if(Pe.current!==j){Ee.current=new Float32Array(j.vertexCount*3),Me.current=new Float32Array(j.uvs),Ae.current=new Float32Array(j.vertexCount*2);const M={position:new p.BufferAttribute(Ee.current,3),uv:new p.BufferAttribute(Me.current,2),faceUv:new p.BufferAttribute(Ae.current,2)};J.forEach(L=>{_n(L.geometryRef.current,M,L.getIndices(j))}),M.uv.needsUpdate=!0,Pe.current=j,ie.current=!1}const ce=Ee.current,be=Ae.current,le=Me.current;if(!ce||!be||!le)return;const Ne=gn(o,a,i),Ge=ln(K),He=Ge?cn(z):null,P=W?Lt.current:null;if(P){P.x=0,P.y=0,P.z=0;for(let M=0;M<z.length;M++){const L=z[M];P.x+=L.x,P.y+=L.y,P.z+=L.z}P.x/=z.length,P.y/=z.length,P.z/=z.length}const Kt=Math.min(z.length,j.vertexCount);for(let M=0;M<Kt;M++){const L=z[M],Be=Ge&&He?un(L,He,K,wt.current):L,qt=W&&P?Fe.transformFaceMeshLandmark(Be,P,W,It.current):Be,ge=M*3,ue=M*2,xe=Yt(qt);ce[ge]=xe.x,ce[ge+1]=xe.y,ce[ge+2]=xe.z,be[ue]=L.x,be[ue+1]=1-L.y,Ne&&(le[ue]=L.x,le[ue+1]=1-L.y)}Ne?(g.attributes.uv.needsUpdate=!0,ie.current=!0):ie.current&&(le.set(j.uvs),g.attributes.uv.needsUpdate=!0,ie.current=!1),J.forEach(M=>{M.meshRef.current.visible=M.visible}),g.attributes.position.needsUpdate=!0,g.attributes.faceUv.needsUpdate=!0,J.forEach(M=>{M.geometryRef.current.computeVertexNormals()})}),u.jsx("group",{scale:[pe,pe,pe],children:J.map(g=>u.jsxs("mesh",{ref:g.meshRef,renderOrder:ct+g.renderOrderOffset,frustumCulled:!1,children:[u.jsx("bufferGeometry",{ref:g.geometryRef}),se?typeof se=="function"?se({cameraTexture:Oe??null,geometryKey:g.key}):se:Wt(g.masked)]},g.key))})},rt=`${Q.libConfig.sdkAssetsBaseUrl}/Canonical_Face_Color.png`,ot=`${Q.libConfig.sdkAssetsBaseUrl}/Canonical_Face_Color_style_2.png`,at=`${Q.libConfig.sdkAssetsBaseUrl}/Canonical_Face_Color_Mask.png`,st={...ke,position:{...ke.position,y:.001}},Cn={enabled:!0,faceIndex:0,targetFps:Mn,...N,showLeftEyeGeometry:!0,showRightEyeGeometry:!0,showMouthGeometry:!0,showNoseGeometry:!0,externalScale:1,showOverlayMask:!1,showMouthMask:!1,showLeftEyeMask:!1,showRightEyeMask:!1,showNoseMask:!1,maskTextureSource:re.textureSource,maskSourceUrl:"",maskColor:re.color,maskOpacity:re.opacity,faceTextureUrl:rt,faceTextureStyle2Url:ot,faceAlphaMaskUrl:at,renderOrder:Ze},it=e=>{const{externalMeshUrl:n,...t}=e;return{...t,color:t.baseColor,meshUrl:n}},Fn=(e,n)=>{const t={...e,...n};return n.maskTextureSource&&!me(n.maskTextureSource)&&(t.maskSourceUrl=""),t.materialType===T.shader&&n.shaderPreset===V.composite?{...t,...We,materialType:T.shader,shaderPreset:V.composite}:t.materialType===T.shader&&t.shaderPreset===V.composite&&t.textureMap===X.none?{...t,textureMap:We.textureMap}:t},kn=({transform:e,value:n})=>n.enabled?u.jsxs(u.Fragment,{children:[u.jsx(Fe.FaceTracker,{active:n.enabled,faceIndex:n.faceIndex,numFaces:n.faceIndex+1,targetFps:n.targetFps}),u.jsx(nt,{...it(n),transform:e??st})]}):null;exports.CANONICAL_FACE_MESH_GEOMETRY_SPECS=tt;exports.CanonicalFaceMeshRenderer=nt;exports.DEFAULT_APPEARANCE=N;exports.DEFAULT_FACE_MESH_RENDERER=Cn;exports.DEFAULT_FACE_MESH_TRANSFORM=st;exports.DEFAULT_MASKING=fe;exports.DEFAULT_MATERIAL_FILL=on;exports.DEFAULT_SCREEN_GRADIENT=Y;exports.DEFAULT_TRANSFORM_3D=ke;exports.FACE_MESH_ALPHA_MAPS=q;exports.FACE_MESH_BLEND_MODES=Ie;exports.FACE_MESH_MASK_TEXTURE_SOURCES=oe;exports.FACE_MESH_MATERIAL_TYPES=T;exports.FACE_MESH_SHADER_PRESETS=V;exports.FACE_MESH_SIDES=ne;exports.FACE_MESH_TEXTURE_MAPS=X;exports.FaceMeshMaterial=et;exports.FaceMeshRenderer=kn;exports.MAX_SCREEN_GRADIENT_STOPS=he;exports.MaterialFill=Ke;exports.ScreenGradientMaterial=$e;exports.TRANSPARENT_TEXTURE_DATA_URL=de;exports.Transform3D=sn;exports.blendModeIndices=Ue;exports.canonicalFaceAlphaMaskUrl=at;exports.canonicalFaceTextureStyle2Url=ot;exports.canonicalFaceTextureUrl=rt;exports.createTwoStopGradient=we;exports.mapFaceMeshRendererSettingsToProps=it;exports.normalizeScreenGradient=Ye;exports.parseCanonicalFaceModel=qe;exports.resolveFaceMeshRendererSettings=Fn;exports.supportsBlendMode=bn;exports.supportsTexturePanel=An;exports.useCanonicalFaceMesh=Qe;exports.usesMaskColor=Je;exports.usesMaskSourceUrl=me;
|