@ssafy-mhk/e-ver 1.0.2 → 1.0.4
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/README.md +183 -114
- package/dist/api/EverClient.d.ts +12 -1
- package/dist/api/EverClient.test.d.ts +1 -0
- package/dist/avatar/VRMCompat.d.ts +8 -0
- package/dist/avatar/avatarLoader.d.ts +12 -0
- package/dist/avatar/humanoidBindings.d.ts +7 -0
- package/dist/bodyPreset/presetSelection.d.ts +31 -0
- package/dist/components/CameraView.d.ts +5 -0
- package/dist/components/EverCanvas.d.ts +2 -0
- package/dist/components/EverFittingScene.d.ts +18 -0
- package/dist/components/EverFittingScene.test.d.ts +1 -0
- package/dist/components/EverProvider.d.ts +0 -8
- package/dist/components/EverTrackedGarment.d.ts +15 -0
- package/dist/components/TrackedGarmentPoseDriver.d.ts +13 -0
- package/dist/components/WebcamPlaneBackground.d.ts +7 -0
- package/dist/components/ever-context.d.ts +9 -0
- package/dist/compositing/videoCover.d.ts +14 -0
- package/dist/fitting/bodyFirstFitting.d.ts +14 -0
- package/dist/fitting/bodyFirstFitting.test.d.ts +1 -0
- package/dist/garment/constants.d.ts +1 -0
- package/dist/garment/fitMotion.d.ts +18 -0
- package/dist/garment/garmentFitProfile.d.ts +24 -0
- package/dist/garment/poseApplication.d.ts +18 -0
- package/dist/garment/trackedGarmentMotion.d.ts +32 -0
- package/dist/garment/trackedModelTransform.d.ts +40 -0
- package/dist/hooks/useAvatarVariant.d.ts +12 -0
- package/dist/hooks/useBodyMeasurer.d.ts +13 -4
- package/dist/hooks/useBodyMeasurer.test.d.ts +1 -0
- package/dist/hooks/useBodyPresetSelection.d.ts +3 -0
- package/dist/hooks/useEverFitting.d.ts +51 -0
- package/dist/hooks/useEverFitting.test.d.ts +1 -0
- package/dist/hooks/useEverGeneration.d.ts +4 -5
- package/dist/hooks/useEverGeneration.test.d.ts +1 -0
- package/dist/hooks/useMeasurement.d.ts +19 -0
- package/dist/hooks/usePoseMapper.d.ts +2 -1
- package/dist/hooks/usePoseTracker.d.ts +24 -6
- package/dist/hooks/usePoseTracker.test.d.ts +1 -0
- package/dist/hooks/useWebcam.d.ts +19 -0
- package/dist/hooks/useWebcam.test.d.ts +1 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.es.js +3119 -40588
- package/dist/index.umd.js +1 -4415
- package/dist/measurement/garmentScaler.d.ts +19 -0
- package/dist/measurement/scaleCalculator.d.ts +5 -0
- package/dist/measurement/scaleCalculator.test.d.ts +1 -0
- package/dist/measurement/silhouetteExtractor.d.ts +3 -0
- package/dist/measurement/sizeRecommender.d.ts +2 -0
- package/dist/pose/boneMapping.d.ts +14 -0
- package/dist/pose/coordinateTransform.d.ts +9 -0
- package/dist/pose/facingDetector.d.ts +35 -0
- package/dist/pose/interpolation.d.ts +16 -0
- package/dist/pose/landmarkPoseSolver.d.ts +9 -0
- package/dist/pose/landmarkerFactory.d.ts +13 -0
- package/dist/pose/poseSolver.d.ts +2 -0
- package/dist/pose/segmentation.d.ts +9 -0
- package/dist/pose/smoothing.d.ts +12 -0
- package/dist/pose/yawDirectionStabilizer.d.ts +20 -0
- package/dist/pose/yawFreezeController.d.ts +11 -0
- package/dist/publicApi.test.d.ts +1 -0
- package/dist/store/useEverStore.d.ts +10 -5
- package/dist/tracking/personLock.d.ts +39 -0
- package/dist/tracking/trackingStability.d.ts +6 -0
- package/dist/tracking/trackingState.d.ts +18 -0
- package/dist/types/bodyPreset.d.ts +65 -0
- package/dist/types/fitting.d.ts +15 -0
- package/dist/types/measurement.d.ts +42 -0
- package/dist/types/pose.d.ts +81 -0
- package/dist/types/tracking.d.ts +13 -0
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -1,175 +1,244 @@
|
|
|
1
|
-
# `@ssafy-mhk/e-ver`
|
|
1
|
+
# `@ssafy-mhk/e-ver`
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
복잡한 Three.js 카메라 및 조명 설정, MediaPipe AI 바디 트래킹 연동, SkinnedMesh 기반 의류 렌더링 로직을 추상화하여, **단순한 React 컴포넌트와 Hook**으로 증강현실(AR) 가상 피팅 기능을 빠르게 구현할 수 있도록 지원합니다.
|
|
3
|
+
React 기반 가상 피팅 SDK입니다. `generate-3d`로 생성한 의류 GLB를 불러오고, 웹캠과 MediaPipe Pose 추적을 이용해 body preset 기반 가상 피팅 씬을 구성할 수 있습니다.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
현재 SDK가 책임지는 범위는 다음입니다.
|
|
7
6
|
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
7
|
+
- 의류 생성 API client와 생성 플로우
|
|
8
|
+
- webcam, pose tracking, body measurement, body preset selection
|
|
9
|
+
- tracked garment 렌더링
|
|
10
|
+
- 최종 보정이 반영된 `finalGarmentScale` 계산
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
현재 SDK가 책임지지 않는 범위는 다음입니다.
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
- 패널 UI, 디버그 UI, overlay
|
|
15
|
+
- foreground occlusion 같은 앱 전용 시각 효과
|
|
16
|
+
- 사진 기반 개인 avatar 생성
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
## 설치
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add @ssafy-mhk/e-ver
|
|
22
|
+
```
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
필수 peer dependency:
|
|
22
25
|
|
|
23
26
|
```bash
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
pnpm add react react-dom three @react-three/fiber @react-three/drei @mediapipe/tasks-vision zustand
|
|
28
|
+
```
|
|
26
29
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
이 레포에서 `ever/frontend`로 로컬 검증할 때는:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm run sdk:use-tarball
|
|
30
34
|
```
|
|
31
35
|
|
|
32
|
-
|
|
36
|
+
퍼블리시된 버전으로 되돌릴 때는:
|
|
33
37
|
|
|
34
|
-
|
|
38
|
+
```bash
|
|
39
|
+
pnpm run sdk:use-version -- 1.0.4
|
|
40
|
+
```
|
|
35
41
|
|
|
36
|
-
##
|
|
42
|
+
## 서버와 인증
|
|
37
43
|
|
|
38
|
-
|
|
44
|
+
기본 API 서버는 `http://localhost:8000/api/v1`입니다.
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
```tsx
|
|
47
|
+
import { EverClient } from "@ssafy-mhk/e-ver";
|
|
48
|
+
|
|
49
|
+
const client = new EverClient();
|
|
50
|
+
|
|
51
|
+
const publicClient = new EverClient({
|
|
52
|
+
apiKey: "ever_live_xxxxxxxx",
|
|
53
|
+
});
|
|
54
|
+
```
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
- 기본 생성자: 쿠키 인증 또는 같은 오리진 환경에서 사용
|
|
57
|
+
- `apiKey` 지정 시: `/sdk/public/*` 경로를 사용하는 공개 SDK 모드
|
|
51
58
|
|
|
52
|
-
|
|
59
|
+
`useEverGeneration`도 동일하게 `apiKey`를 받을 수 있습니다.
|
|
53
60
|
|
|
54
|
-
|
|
61
|
+
## 권장 사용 흐름
|
|
55
62
|
|
|
56
|
-
|
|
63
|
+
가장 권장되는 경로는 아래입니다.
|
|
57
64
|
|
|
58
|
-
|
|
65
|
+
1. `useEverGeneration`으로 의류 생성
|
|
66
|
+
2. 생성이 끝나면 `resultUrl` 확보
|
|
67
|
+
3. `EverFittingScene`에 `garmentUrl={resultUrl}` 전달
|
|
68
|
+
4. `onRuntimeStateChange`에서 `measurements`, `bodyPresetSelection`, `finalGarmentScale` 소비
|
|
69
|
+
|
|
70
|
+
## 핵심 API
|
|
71
|
+
|
|
72
|
+
| 분류 | 모듈 | 역할 |
|
|
73
|
+
| --- | --- | --- |
|
|
74
|
+
| Client | `EverClient` | body preset 조회/매칭, garment 생성, 이미지 업로드, `generate-3d`, polling |
|
|
75
|
+
| Hook | `useEverGeneration` | 의류 생성 플로우를 훅으로 제공 |
|
|
76
|
+
| Scene | `EverFittingScene` | webcam, tracking, measurement, body preset selection, garment 렌더링 통합 |
|
|
77
|
+
| Scene | `EverTrackedGarment` | 준비된 의류 GLB를 추적 렌더링 |
|
|
78
|
+
| Hook | `useEverFitting` | 고수준 fitting runtime 상태 제공 |
|
|
79
|
+
| Hook | `useBodyPresetSelection` | 측정값 기반 body preset 자동 선택 |
|
|
80
|
+
| Renderer | `EverCanvas` | 저수준 R3F canvas wrapper |
|
|
81
|
+
|
|
82
|
+
## Quick Start
|
|
59
83
|
|
|
60
84
|
```tsx
|
|
61
|
-
|
|
62
|
-
"use client";
|
|
85
|
+
import { EverFittingScene, useEverGeneration } from "@ssafy-mhk/e-ver";
|
|
63
86
|
|
|
64
|
-
|
|
87
|
+
function Demo() {
|
|
88
|
+
const { createGarment, resultUrl, status } = useEverGeneration({
|
|
89
|
+
apiKey: process.env.NEXT_PUBLIC_EVER_API_KEY,
|
|
90
|
+
});
|
|
65
91
|
|
|
66
|
-
|
|
67
|
-
|
|
92
|
+
const handleGenerate = async () => {
|
|
93
|
+
await createGarment(
|
|
94
|
+
{ name: "오버핏 셔츠", category: "top" },
|
|
95
|
+
frontImageBlob,
|
|
96
|
+
backImageBlob,
|
|
97
|
+
);
|
|
98
|
+
};
|
|
68
99
|
|
|
69
100
|
return (
|
|
70
|
-
<div className="
|
|
71
|
-
<button onClick={
|
|
72
|
-
|
|
73
|
-
새로운 옷 입어보기 👕
|
|
101
|
+
<div className="relative h-screen w-full">
|
|
102
|
+
<button onClick={handleGenerate} disabled={status !== "idle"}>
|
|
103
|
+
3D 생성
|
|
74
104
|
</button>
|
|
75
105
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
106
|
+
<EverFittingScene
|
|
107
|
+
garmentUrl={resultUrl}
|
|
108
|
+
enabled
|
|
109
|
+
measurementEnabled
|
|
110
|
+
autoStartMeasurement
|
|
111
|
+
fitType="regular"
|
|
112
|
+
onRuntimeStateChange={(runtime) => {
|
|
113
|
+
console.log(runtime.measurements);
|
|
114
|
+
console.log(runtime.bodyPresetSelection);
|
|
115
|
+
console.log(runtime.finalGarmentScale);
|
|
116
|
+
}}
|
|
117
|
+
/>
|
|
81
118
|
</div>
|
|
82
119
|
);
|
|
83
120
|
}
|
|
84
121
|
```
|
|
85
122
|
|
|
86
|
-
|
|
123
|
+
## 생성 API
|
|
87
124
|
|
|
88
|
-
|
|
125
|
+
### `useEverGeneration`
|
|
89
126
|
|
|
90
|
-
|
|
91
|
-
// components/VirtualFittingScene.tsx
|
|
92
|
-
"use client";
|
|
127
|
+
`createGarment`는 아래 순서를 묶습니다.
|
|
93
128
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
GarmentModel,
|
|
99
|
-
useEverStore,
|
|
100
|
-
} from "@ssafy-mhk/e-ver";
|
|
129
|
+
1. garment 생성
|
|
130
|
+
2. front/back 이미지 업로드
|
|
131
|
+
3. `generate-3d` 요청
|
|
132
|
+
4. 의류 모델 준비 완료까지 polling
|
|
101
133
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const { activeGarmentUrl } = useEverStore();
|
|
134
|
+
```tsx
|
|
135
|
+
import { useEverGeneration } from "@ssafy-mhk/e-ver";
|
|
105
136
|
|
|
106
|
-
|
|
107
|
-
const
|
|
137
|
+
function Generator() {
|
|
138
|
+
const { createGarment, resultUrl, status, error } = useEverGeneration();
|
|
108
139
|
|
|
109
140
|
return (
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
</EverCanvas>
|
|
127
|
-
</div>
|
|
141
|
+
<>
|
|
142
|
+
<button
|
|
143
|
+
onClick={() =>
|
|
144
|
+
createGarment(
|
|
145
|
+
{ name: "니트", category: "top" },
|
|
146
|
+
frontImageBlob,
|
|
147
|
+
backImageBlob,
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
>
|
|
151
|
+
생성
|
|
152
|
+
</button>
|
|
153
|
+
<p>{status}</p>
|
|
154
|
+
{error ? <p>{error}</p> : null}
|
|
155
|
+
{resultUrl ? <p>{resultUrl}</p> : null}
|
|
156
|
+
</>
|
|
128
157
|
);
|
|
129
158
|
}
|
|
130
159
|
```
|
|
131
160
|
|
|
132
|
-
|
|
161
|
+
## 고수준 Scene
|
|
133
162
|
|
|
134
|
-
|
|
163
|
+
### `EverFittingScene`
|
|
135
164
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
165
|
+
가장 권장되는 엔트리입니다. 내부에서 다음을 수행합니다.
|
|
166
|
+
|
|
167
|
+
- webcam 준비
|
|
168
|
+
- MediaPipe Pose tracking
|
|
169
|
+
- 측정값 계산
|
|
170
|
+
- body preset 선택
|
|
171
|
+
- tracked garment 렌더링
|
|
172
|
+
- 최종 보정 scale 계산
|
|
173
|
+
|
|
174
|
+
주요 props:
|
|
175
|
+
|
|
176
|
+
- `garmentUrl: string | null`
|
|
177
|
+
- `enabled?: boolean`
|
|
178
|
+
- `measurementEnabled?: boolean`
|
|
179
|
+
- `autoStartMeasurement?: boolean`
|
|
180
|
+
- `fitType?: "slim" | "regular" | "oversize"`
|
|
181
|
+
- `garmentScaleHint?: number | null`
|
|
182
|
+
- `onRuntimeStateChange?: (runtime) => void`
|
|
183
|
+
- `onGarmentLoadStateChange?: (state) => void`
|
|
184
|
+
|
|
185
|
+
`runtime`에서 특히 많이 쓰는 값:
|
|
139
186
|
|
|
140
|
-
|
|
141
|
-
|
|
187
|
+
- `measurements`
|
|
188
|
+
- `bodyPresetSelection`
|
|
189
|
+
- `sizeRecommendation`
|
|
190
|
+
- `garmentScale`
|
|
191
|
+
- `finalGarmentScale`
|
|
192
|
+
- `bodyMorphResult`
|
|
193
|
+
- `isTracking`
|
|
194
|
+
- `webcamError`
|
|
142
195
|
|
|
143
|
-
|
|
144
|
-
const videoRef = useRef<HTMLVideoElement>(null);
|
|
196
|
+
## 저수준 조립
|
|
145
197
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
198
|
+
직접 조립이 필요하면 `useEverFitting`과 `EverTrackedGarment`를 사용할 수 있습니다.
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
import { EverCanvas, EverTrackedGarment, useEverFitting } from "@ssafy-mhk/e-ver";
|
|
202
|
+
|
|
203
|
+
function CustomScene({ garmentUrl }: { garmentUrl: string }) {
|
|
204
|
+
const fitting = useEverFitting({
|
|
205
|
+
enabled: true,
|
|
206
|
+
fitType: "oversize",
|
|
207
|
+
garmentScaleHint: 1.04,
|
|
208
|
+
});
|
|
149
209
|
|
|
150
210
|
return (
|
|
151
|
-
<
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
style={{ display: isWebcamActive ? "block" : "none" }}
|
|
211
|
+
<EverCanvas showEnvironment={false}>
|
|
212
|
+
<EverTrackedGarment
|
|
213
|
+
url={garmentUrl}
|
|
214
|
+
landmarks={fitting.landmarks}
|
|
215
|
+
worldLandmarks={fitting.worldLandmarks}
|
|
216
|
+
poseFrameWidth={fitting.poseFrameWidth}
|
|
217
|
+
poseFrameHeight={fitting.poseFrameHeight}
|
|
159
218
|
/>
|
|
160
|
-
|
|
161
|
-
{!isTrackerReady && isWebcamActive && <p>AI 모델 로딩 중...</p>}
|
|
162
|
-
</div>
|
|
219
|
+
</EverCanvas>
|
|
163
220
|
);
|
|
164
221
|
}
|
|
165
222
|
```
|
|
166
223
|
|
|
167
|
-
|
|
224
|
+
## fitting 결과
|
|
225
|
+
|
|
226
|
+
`finalGarmentScale`은 아래 요소를 합성한 최종 결과입니다.
|
|
227
|
+
|
|
228
|
+
- body measurement 기반 scale
|
|
229
|
+
- body preset selection
|
|
230
|
+
- `fitType`
|
|
231
|
+
- `garmentScaleHint`
|
|
232
|
+
|
|
233
|
+
showcase와 동일한 fitting 결과가 필요하면 소비 앱에서 별도 보정하지 말고 `runtime.finalGarmentScale`을 그대로 사용하면 됩니다.
|
|
234
|
+
|
|
235
|
+
## 주의 사항
|
|
168
236
|
|
|
169
|
-
|
|
237
|
+
**`generateAvatar`는 사진 기반 개인 avatar 생성이 아닙니다.**
|
|
238
|
+
현재 버전에서는 body preset 매칭을 통해 기본 아바타 모델 URL을 찾습니다.
|
|
170
239
|
|
|
171
|
-
**
|
|
172
|
-
|
|
240
|
+
**SDK는 UI kit이 아닙니다.**
|
|
241
|
+
측정 패널, 디버그 패널, overlay는 소비 앱에서 조립해야 합니다.
|
|
173
242
|
|
|
174
|
-
**
|
|
175
|
-
|
|
243
|
+
**SDK 범위는 body preset 기반 fitting입니다.**
|
|
244
|
+
개인 사진 기반 avatar 생성이나 앱 전용 시각 효과는 현재 범위 밖입니다.
|
package/dist/api/EverClient.d.ts
CHANGED
|
@@ -138,13 +138,24 @@ export interface WaitForGarmentModelOptions {
|
|
|
138
138
|
intervalMs?: number;
|
|
139
139
|
timeoutMs?: number;
|
|
140
140
|
}
|
|
141
|
+
export interface EverClientOptions {
|
|
142
|
+
baseUrl?: string;
|
|
143
|
+
apiKey?: string;
|
|
144
|
+
}
|
|
145
|
+
export declare const DEFAULT_EVER_API_BASE_URL = "http://localhost:8000/api/v1";
|
|
141
146
|
/**
|
|
142
147
|
* EverClient provides methods to interact with the e-ver backend API.
|
|
148
|
+
*
|
|
149
|
+
* Supports two authentication modes:
|
|
150
|
+
* - **Cookie (default)**: browser session credentials (no apiKey).
|
|
151
|
+
* - **API Key**: pass `apiKey` in the constructor to use `X-API-Key` header
|
|
152
|
+
* and route requests through `/sdk/public/*` endpoints.
|
|
143
153
|
*/
|
|
144
154
|
export declare class EverClient {
|
|
145
155
|
private readonly baseUrl;
|
|
146
156
|
private readonly apiOrigin;
|
|
147
|
-
|
|
157
|
+
private readonly apiKey;
|
|
158
|
+
constructor(config?: string | EverClientOptions);
|
|
148
159
|
resolveAssetUrl(assetUrl: string | null): string | null;
|
|
149
160
|
listBodyPresets(gender?: string): Promise<BodyPreset[]>;
|
|
150
161
|
matchBodyPreset(body: BodyPresetMatchRequest): Promise<BodyPreset>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { VRM } from "@pixiv/three-vrm";
|
|
2
|
+
import * as THREE from "three";
|
|
3
|
+
export interface VRMCompatHumanoid {
|
|
4
|
+
getNormalizedBoneNode(boneName: string): THREE.Object3D | null;
|
|
5
|
+
update(delta: number): void;
|
|
6
|
+
vrm: VRM | null;
|
|
7
|
+
}
|
|
8
|
+
export declare function createVRMCompat(scene: THREE.Object3D, vrm: VRM | null | undefined): VRMCompatHumanoid;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { VRM } from "@pixiv/three-vrm";
|
|
2
|
+
import * as THREE from "three";
|
|
3
|
+
type UseGLTFSignature = typeof import("@react-three/drei")["useGLTF"];
|
|
4
|
+
type AvatarLoader = Parameters<NonNullable<Parameters<UseGLTFSignature>[3]>>[0];
|
|
5
|
+
export type AvatarAssetKind = "vrm" | "gltf";
|
|
6
|
+
export declare function isVRMAssetUrl(url: string): boolean;
|
|
7
|
+
export declare function getAvatarAssetKind(url: string): AvatarAssetKind;
|
|
8
|
+
export declare function configureAvatarLoader(loader: AvatarLoader, url: string): void;
|
|
9
|
+
export declare function createAvatarLoaderExtension(url: string): ((loader: AvatarLoader) => void) | undefined;
|
|
10
|
+
export declare function prepareAvatarScene(scene: THREE.Object3D): void;
|
|
11
|
+
export declare function prepareNativeVRM(vrm: VRM): void;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
import { type GarmentBoneBindingMap } from "../garment/garmentFitProfile";
|
|
3
|
+
interface HumanoidBoneSource {
|
|
4
|
+
getNormalizedBoneNode(name: string): THREE.Object3D | null;
|
|
5
|
+
}
|
|
6
|
+
export declare function createHumanoidBoneBindings(humanoid: HumanoidBoneSource): GarmentBoneBindingMap;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { EverClient } from "../api/EverClient";
|
|
2
|
+
import type { BodyPreset } from "../api/EverClient";
|
|
3
|
+
import type { BodyMeasurements } from "../types/measurement";
|
|
4
|
+
import type { BodyPresetGender, BodyPresetMatchRequest, BodyPresetSelection, BodyPresetSummary } from "../types/bodyPreset";
|
|
5
|
+
export declare const DEFAULT_MALE_BODY_PRESET_ID = "male-m-balanced-balanced";
|
|
6
|
+
export declare const DEFAULT_FEMALE_BODY_PRESET_ID = "female-m-balanced-balanced";
|
|
7
|
+
export declare const LEGACY_RIGGED_BODY_PRESET_ID = "rigged_avatar";
|
|
8
|
+
export declare function normalizeBodyPresetGender(value?: string | null): BodyPresetGender;
|
|
9
|
+
export declare function buildBodyPresetAssetUrl(presetId: string, options?: {
|
|
10
|
+
renderMode?: "rigged_avatar" | "preset-native";
|
|
11
|
+
legacyPresetId?: string;
|
|
12
|
+
}): string;
|
|
13
|
+
export declare function getDefaultBodyPresetId(gender: BodyPresetGender): string;
|
|
14
|
+
export declare function toBodyPresetSummary(preset: BodyPreset, client: EverClient): BodyPresetSummary;
|
|
15
|
+
export declare function ensureBodyPresetModelUrl(preset: BodyPresetSummary, options?: {
|
|
16
|
+
renderMode?: "rigged_avatar" | "preset-native";
|
|
17
|
+
legacyPresetId?: string;
|
|
18
|
+
}): BodyPresetSummary;
|
|
19
|
+
export declare function pickDefaultBodyPreset(presets: BodyPresetSummary[], options?: {
|
|
20
|
+
renderMode?: "rigged_avatar" | "preset-native";
|
|
21
|
+
legacyPresetId?: string;
|
|
22
|
+
}): BodyPresetSummary | null;
|
|
23
|
+
export declare function createFallbackBodyPresetSelection(gender: BodyPresetGender, options?: {
|
|
24
|
+
renderMode?: "rigged_avatar" | "preset-native";
|
|
25
|
+
legacyPresetId?: string;
|
|
26
|
+
}): BodyPresetSelection;
|
|
27
|
+
export declare function toBodyPresetSelection(preset: BodyPresetSummary, source: BodyPresetSelection["source"], options?: {
|
|
28
|
+
renderMode?: "rigged_avatar" | "preset-native";
|
|
29
|
+
legacyPresetId?: string;
|
|
30
|
+
}): BodyPresetSelection;
|
|
31
|
+
export declare function buildBodyPresetMatchRequest(measurements: BodyMeasurements, gender: BodyPresetGender): BodyPresetMatchRequest;
|
|
@@ -2,6 +2,11 @@ import React from "react";
|
|
|
2
2
|
export interface CameraViewProps {
|
|
3
3
|
className?: string;
|
|
4
4
|
style?: React.CSSProperties;
|
|
5
|
+
width?: number;
|
|
6
|
+
height?: number;
|
|
7
|
+
facingMode?: "user" | "environment";
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
mockMode?: boolean;
|
|
5
10
|
}
|
|
6
11
|
/**
|
|
7
12
|
* CameraView handles the rendering of the user's webcam feed.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type CSSProperties } from "react";
|
|
2
|
+
import type { UseBodyPresetSelectionOptions } from "../types/bodyPreset";
|
|
3
|
+
import { type EverFittingOptions, type EverFittingRuntimeState } from "../hooks/useEverFitting";
|
|
4
|
+
import { type GarmentLoadState } from "./EverTrackedGarment";
|
|
5
|
+
export interface EverFittingSceneProps extends Pick<EverFittingOptions, "enabled" | "width" | "height" | "facingMode" | "mockMode" | "viewportWidth" | "viewportHeight" | "measurementEnabled" | "autoStartMeasurement" | "measurementConfig" | "fitType" | "garmentScaleHint"> {
|
|
6
|
+
garmentUrl: string | null;
|
|
7
|
+
bodyPresetOptions?: UseBodyPresetSelectionOptions;
|
|
8
|
+
className?: string;
|
|
9
|
+
style?: CSSProperties;
|
|
10
|
+
debugMaterials?: boolean;
|
|
11
|
+
showEnvironment?: boolean;
|
|
12
|
+
showStats?: boolean;
|
|
13
|
+
showWebcamBackground?: boolean;
|
|
14
|
+
onCanvasReadyChange?: (ready: boolean) => void;
|
|
15
|
+
onRuntimeStateChange?: (state: EverFittingRuntimeState) => void;
|
|
16
|
+
onGarmentLoadStateChange?: (state: GarmentLoadState) => void;
|
|
17
|
+
}
|
|
18
|
+
export declare function EverFittingScene({ garmentUrl, enabled, width, height, facingMode, mockMode, viewportWidth, viewportHeight, measurementEnabled, autoStartMeasurement, measurementConfig, fitType, garmentScaleHint, bodyPresetOptions, className, style, debugMaterials, showEnvironment, showStats, showWebcamBackground, onCanvasReadyChange, onRuntimeStateChange, onGarmentLoadStateChange, }: EverFittingSceneProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import * as THREE from "three";
|
|
3
|
-
export interface EverContextType {
|
|
4
|
-
videoRef: React.RefObject<HTMLVideoElement | null>;
|
|
5
|
-
avatarBones: Record<string, THREE.Bone> | null;
|
|
6
|
-
setAvatarBones: (bones: Record<string, THREE.Bone> | null) => void;
|
|
7
|
-
isProviderReady: boolean;
|
|
8
|
-
}
|
|
9
|
-
export declare const useEver: () => EverContextType;
|
|
10
2
|
export interface EverProviderProps {
|
|
11
3
|
children: React.ReactNode;
|
|
12
4
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PoseLandmarkLike } from "../types/pose";
|
|
2
|
+
export interface GarmentLoadState {
|
|
3
|
+
loaded: boolean;
|
|
4
|
+
error: string | null;
|
|
5
|
+
}
|
|
6
|
+
export interface EverTrackedGarmentProps {
|
|
7
|
+
url: string;
|
|
8
|
+
landmarks: PoseLandmarkLike[] | null;
|
|
9
|
+
worldLandmarks: PoseLandmarkLike[] | null;
|
|
10
|
+
poseFrameWidth: number;
|
|
11
|
+
poseFrameHeight: number;
|
|
12
|
+
debugMaterials?: boolean;
|
|
13
|
+
onLoadStateChange?: (state: GarmentLoadState) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare function EverTrackedGarment({ url, landmarks, worldLandmarks, poseFrameWidth, poseFrameHeight, debugMaterials, onLoadStateChange, }: EverTrackedGarmentProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { NormalizedLandmark } from "@mediapipe/tasks-vision";
|
|
2
|
+
import * as THREE from "three";
|
|
3
|
+
import type { GarmentBoneBindingMap, GarmentFitProfile } from "../garment/garmentFitProfile";
|
|
4
|
+
export interface TrackedGarmentPoseDriverProps {
|
|
5
|
+
garmentRootRef: React.RefObject<THREE.Group | null>;
|
|
6
|
+
boneBindingMap: GarmentBoneBindingMap;
|
|
7
|
+
fitProfile: GarmentFitProfile | null;
|
|
8
|
+
landmarks: NormalizedLandmark[] | null;
|
|
9
|
+
worldLandmarks: NormalizedLandmark[] | null;
|
|
10
|
+
poseFrameWidth: number;
|
|
11
|
+
poseFrameHeight: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function TrackedGarmentPoseDriver({ garmentRootRef, boneBindingMap, fitProfile, landmarks, worldLandmarks, poseFrameWidth, poseFrameHeight, }: TrackedGarmentPoseDriverProps): null;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
2
|
+
interface WebcamPlaneBackgroundProps {
|
|
3
|
+
videoRef: RefObject<HTMLVideoElement | null>;
|
|
4
|
+
webcamReady: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function WebcamPlaneBackground({ videoRef, webcamReady, }: WebcamPlaneBackgroundProps): import("react/jsx-runtime").JSX.Element | null;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
export interface EverContextType {
|
|
3
|
+
videoRef: React.RefObject<HTMLVideoElement | null>;
|
|
4
|
+
avatarBones: Record<string, THREE.Bone> | null;
|
|
5
|
+
setAvatarBones: (bones: Record<string, THREE.Bone> | null) => void;
|
|
6
|
+
isProviderReady: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare const EverContext: import("react").Context<EverContextType | undefined>;
|
|
9
|
+
export declare function useEver(): EverContextType;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface VisibleNormalizedRegion {
|
|
2
|
+
xMin: number;
|
|
3
|
+
xMax: number;
|
|
4
|
+
yMin: number;
|
|
5
|
+
yMax: number;
|
|
6
|
+
}
|
|
7
|
+
export interface CoverRect {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function computeCoverRect(viewportWidth: number, viewportHeight: number, sourceWidth: number, sourceHeight: number): CoverRect;
|
|
14
|
+
export declare function computeVisibleNormalizedRegion(viewportWidth: number, viewportHeight: number, sourceWidth: number, sourceHeight: number): VisibleNormalizedRegion;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type GarmentSpec } from "../measurement/garmentScaler";
|
|
2
|
+
import type { BodyPresetSelection } from "../types/bodyPreset";
|
|
3
|
+
import type { BodyFirstFittingResult, BodyMorphResult, FitType } from "../types/fitting";
|
|
4
|
+
import type { BodyMeasurements, GarmentScaleParams } from "../types/measurement";
|
|
5
|
+
export interface BodyFirstFittingParams {
|
|
6
|
+
measurements: BodyMeasurements | null;
|
|
7
|
+
measurementScale: GarmentScaleParams | null;
|
|
8
|
+
presetSelection: BodyPresetSelection | null;
|
|
9
|
+
fitType?: FitType;
|
|
10
|
+
garmentScaleHint?: number | null;
|
|
11
|
+
spec?: GarmentSpec;
|
|
12
|
+
}
|
|
13
|
+
export declare function deriveBodyMorphResult(measurements: BodyMeasurements, presetSelection: BodyPresetSelection): BodyMorphResult;
|
|
14
|
+
export declare function computeBodyFirstFitting({ measurements, measurementScale, presetSelection, fitType, garmentScaleHint, spec, }: BodyFirstFittingParams): BodyFirstFittingResult;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const BONE_VISIBILITY_MAP: Record<string, readonly number[]>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { NormalizedLandmark } from "@mediapipe/tasks-vision";
|
|
2
|
+
import * as THREE from "three";
|
|
3
|
+
interface StableShoulderWidthInput {
|
|
4
|
+
projectedShoulderWidth: number;
|
|
5
|
+
projectedTorsoHeight: number;
|
|
6
|
+
bodyYaw: number;
|
|
7
|
+
worldLandmarks?: NormalizedLandmark[] | null;
|
|
8
|
+
}
|
|
9
|
+
interface GarmentRootOrientationInput {
|
|
10
|
+
leftShoulder: THREE.Vector3;
|
|
11
|
+
rightShoulder: THREE.Vector3;
|
|
12
|
+
leftHip: THREE.Vector3;
|
|
13
|
+
rightHip: THREE.Vector3;
|
|
14
|
+
}
|
|
15
|
+
export declare function computeFacingAwareShoulderWidth(shoulderWidth: number, torsoHeight: number, bodyYaw: number): number;
|
|
16
|
+
export declare function computeStableShoulderWidth({ projectedShoulderWidth, projectedTorsoHeight, bodyYaw, worldLandmarks, }: StableShoulderWidthInput): number;
|
|
17
|
+
export declare function computeGarmentRootQuaternion({ leftShoulder, rightShoulder, leftHip, rightHip, }: GarmentRootOrientationInput, target?: THREE.Quaternion): THREE.Quaternion | null;
|
|
18
|
+
export {};
|