@ssafy-mhk/e-ver 1.0.3 → 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.
Files changed (63) hide show
  1. package/README.md +175 -120
  2. package/dist/api/EverClient.d.ts +12 -1
  3. package/dist/avatar/VRMCompat.d.ts +8 -0
  4. package/dist/avatar/avatarLoader.d.ts +12 -0
  5. package/dist/avatar/humanoidBindings.d.ts +7 -0
  6. package/dist/bodyPreset/presetSelection.d.ts +31 -0
  7. package/dist/components/CameraView.d.ts +5 -0
  8. package/dist/components/EverCanvas.d.ts +2 -0
  9. package/dist/components/EverFittingScene.d.ts +18 -0
  10. package/dist/components/EverFittingScene.test.d.ts +1 -0
  11. package/dist/components/EverTrackedGarment.d.ts +15 -0
  12. package/dist/components/TrackedGarmentPoseDriver.d.ts +13 -0
  13. package/dist/components/WebcamPlaneBackground.d.ts +7 -0
  14. package/dist/compositing/videoCover.d.ts +14 -0
  15. package/dist/fitting/bodyFirstFitting.d.ts +14 -0
  16. package/dist/fitting/bodyFirstFitting.test.d.ts +1 -0
  17. package/dist/garment/constants.d.ts +1 -0
  18. package/dist/garment/fitMotion.d.ts +18 -0
  19. package/dist/garment/garmentFitProfile.d.ts +24 -0
  20. package/dist/garment/poseApplication.d.ts +18 -0
  21. package/dist/garment/trackedGarmentMotion.d.ts +32 -0
  22. package/dist/garment/trackedModelTransform.d.ts +40 -0
  23. package/dist/hooks/useAvatarVariant.d.ts +12 -0
  24. package/dist/hooks/useBodyMeasurer.d.ts +13 -4
  25. package/dist/hooks/useBodyPresetSelection.d.ts +3 -0
  26. package/dist/hooks/useEverFitting.d.ts +51 -0
  27. package/dist/hooks/useEverFitting.test.d.ts +1 -0
  28. package/dist/hooks/useEverGeneration.d.ts +4 -5
  29. package/dist/hooks/useMeasurement.d.ts +19 -0
  30. package/dist/hooks/usePoseMapper.d.ts +2 -7
  31. package/dist/hooks/usePoseTracker.d.ts +24 -6
  32. package/dist/hooks/useWebcam.d.ts +19 -0
  33. package/dist/hooks/useWebcam.test.d.ts +1 -0
  34. package/dist/index.d.ts +44 -0
  35. package/dist/index.es.js +3119 -40592
  36. package/dist/index.umd.js +1 -4415
  37. package/dist/measurement/garmentScaler.d.ts +19 -0
  38. package/dist/measurement/scaleCalculator.d.ts +5 -0
  39. package/dist/measurement/scaleCalculator.test.d.ts +1 -0
  40. package/dist/measurement/silhouetteExtractor.d.ts +3 -0
  41. package/dist/measurement/sizeRecommender.d.ts +2 -0
  42. package/dist/pose/boneMapping.d.ts +14 -0
  43. package/dist/pose/coordinateTransform.d.ts +9 -0
  44. package/dist/pose/facingDetector.d.ts +35 -0
  45. package/dist/pose/interpolation.d.ts +16 -0
  46. package/dist/pose/landmarkPoseSolver.d.ts +9 -0
  47. package/dist/pose/landmarkerFactory.d.ts +13 -0
  48. package/dist/pose/poseSolver.d.ts +2 -0
  49. package/dist/pose/segmentation.d.ts +9 -0
  50. package/dist/pose/smoothing.d.ts +12 -0
  51. package/dist/pose/yawDirectionStabilizer.d.ts +20 -0
  52. package/dist/pose/yawFreezeController.d.ts +11 -0
  53. package/dist/publicApi.test.d.ts +1 -0
  54. package/dist/store/useEverStore.d.ts +2 -4
  55. package/dist/tracking/personLock.d.ts +39 -0
  56. package/dist/tracking/trackingStability.d.ts +6 -0
  57. package/dist/tracking/trackingState.d.ts +18 -0
  58. package/dist/types/bodyPreset.d.ts +65 -0
  59. package/dist/types/fitting.d.ts +15 -0
  60. package/dist/types/measurement.d.ts +42 -0
  61. package/dist/types/pose.d.ts +81 -0
  62. package/dist/types/tracking.d.ts +13 -0
  63. package/package.json +8 -5
package/README.md CHANGED
@@ -1,189 +1,244 @@
1
- # `@ssafy-mhk/e-ver` - Virtual Fitting React SDK 👗👕
1
+ # `@ssafy-mhk/e-ver`
2
2
 
3
- S14P21M104 가상 피팅(WebAR) 프로젝트를 위한 공식 프론트엔드 React SDK입니다.
4
- 복잡한 Three.js 카메라 및 조명 설정, MediaPipe AI 바디 트래킹 연동, SkinnedMesh 기반 의류 렌더링 로직을 추상화하여, **단순한 React 컴포넌트와 Hook**으로 증강현실(AR) 가상 피팅 기능을 빠르게 구현할 수 있도록 지원합니다.
3
+ React 기반 가상 피팅 SDK입니다. `generate-3d`로 생성한 의류 GLB를 불러오고, 웹캠과 MediaPipe Pose 추적을 이용해 body preset 기반 가상 피팅 씬을 구성할 수 있습니다.
5
4
 
6
- ## 개발 스택 (Technology Stack)
5
+ 현재 SDK가 책임지는 범위는 다음입니다.
7
6
 
8
- - **Framework**: React / Next.js 호환
9
- - **3D & AR Rendering**: Three.js, React Three Fiber (R3F), Drei, three-vrm
10
- - **AI Tracking**: MediaPipe Pose Landmarker (Lite)
11
- - **State Management**: Zustand
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
- ## 🛠 설치 방법 (Installation)
14
+ - 패널 UI, 디버그 UI, overlay
15
+ - foreground occlusion 같은 앱 전용 시각 효과
16
+ - 사진 기반 개인 avatar 생성
16
17
 
17
- 패키지는 배포 전 로컬 검증 시 tarball로 패키징한 뒤 소비 애플리케이션에 설치해서 확인하는 방식을 권장합니다.
18
-
19
- ### 배포된 패키지 설치
20
-
21
- 여러분의 Next.js 프로젝트 최상위 폴더에서 아래 명령어를 실행하세요.
18
+ ## 설치
22
19
 
23
20
  ```bash
24
- # pnpm 사용 시
25
21
  pnpm add @ssafy-mhk/e-ver
26
-
27
- # 또는 패키지 매니저에 따라
28
- npm install @ssafy-mhk/e-ver
29
- yarn add @ssafy-mhk/e-ver
30
22
  ```
31
23
 
32
- _(의존성 설치가 잘 되었는지 꼭 `package.json` 코드를 확인하세요.)_
24
+ 필수 peer dependency:
33
25
 
34
- ### 이 레포에서 `frontend`로 로컬 검증할 경우
26
+ ```bash
27
+ pnpm add react react-dom three @react-three/fiber @react-three/drei @mediapipe/tasks-vision zustand
28
+ ```
35
29
 
36
- `/ever/frontend`에서 아래 명령어를 실행하면 `/ever/sdk`를 빌드하고 tarball로 패키징한 뒤 현재 프론트엔드에 설치합니다.
30
+ 레포에서 `ever/frontend`로 로컬 검증할 때는:
37
31
 
38
32
  ```bash
39
33
  pnpm run sdk:use-tarball
40
34
  ```
41
35
 
42
- 검증 후 퍼블리시된 버전으로 되돌릴 때는 아래 명령어를 사용합니다.
36
+ 퍼블리시된 버전으로 되돌릴 때는:
43
37
 
44
38
  ```bash
45
- pnpm run sdk:use-version -- 1.0.3
39
+ pnpm run sdk:use-version -- 1.0.4
46
40
  ```
47
41
 
48
- ---
42
+ ## 서버와 인증
43
+
44
+ 기본 API 서버는 `http://localhost:8000/api/v1`입니다.
49
45
 
50
- ## 🚀 코어로직 한눈에 보기 (SDK 핵심 요소)
46
+ ```tsx
47
+ import { EverClient } from "@ssafy-mhk/e-ver";
51
48
 
52
- SDK는 크게 **State(상태 관리)**, **Renderer(렌더링 UI)**, **Tracker(추적/측정 Hook)** 이렇게 3가지 핵심 축으로 구성됩니다.
49
+ const client = new EverClient();
53
50
 
54
- | 분류 | 모듈명 | 역할 |
55
- | ------------ | ----------------- | ------------------------------------------------------------------------------------ |
56
- | **State** | `useEverStore` | 웹캠 활성화 여부, 렌더링 중인 옷/아바타 주소, 최종 핏 결과(체형 측정) 관리 |
57
- | **Renderer** | `EverCanvas` | AR/3D 환경에 최적화된 조명과 카메라 세팅을 내장한 R3F 캔버스 래퍼 |
58
- | **Renderer** | `AvatarModel` | 사용자의 AI 기반 생성 3D 아바타(GLB)를 로딩하고, 뼈대(Bone) 구조를 추출 |
59
- | **Renderer** | `GarmentModel` | 사용자가 선택한 옷(GLB)을 로딩하고, 옷의 SkinnedMesh를 대상 아바타에 입힘 |
60
- | **Tracker** | `usePoseTracker` | 브라우저 내에서 MediaPipe를 가동시켜 실시간 30-60Hz 웹캠 추적 |
61
- | **Tracker** | `usePoseMapper` | 웹캠에서 얻은 2D/3D 점(Landmarks)을 필수 13본(Bone)의 회전값(Quaternion)으로 변환 |
62
- | **Tracker** | `useBodyMeasurer` | AR 카메라 상에서 사용자 실루엣 기반 사이즈(어깨, 가슴, 허리)를 연산하여 옷의 핏 평가 |
51
+ const publicClient = new EverClient({
52
+ apiKey: "ever_live_xxxxxxxx",
53
+ });
54
+ ```
63
55
 
64
- ---
56
+ - 기본 생성자: 쿠키 인증 또는 같은 오리진 환경에서 사용
57
+ - `apiKey` 지정 시: `/sdk/public/*` 경로를 사용하는 공개 SDK 모드
65
58
 
66
- ## 📖 사용 가이드 (Usage Guide)
59
+ `useEverGeneration`도 동일하게 `apiKey`를 받을 있습니다.
67
60
 
68
- 아래는 Next.js(App Router) 환경에서 가상 피팅 서비스를 구축하는 기본 예제 코드입니다.
61
+ ## 권장 사용 흐름
69
62
 
70
- ### Step 1. Zustand로 글로벌 상태 세팅하기
63
+ 가장 권장되는 경로는 아래입니다.
71
64
 
72
- 우선, 애플리케이션 외부 버튼 조작을 위해 스토어를 호출할 수 있습니다.
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
73
83
 
74
84
  ```tsx
75
- // app/fitting/page.tsx
76
- "use client";
85
+ import { EverFittingScene, useEverGeneration } from "@ssafy-mhk/e-ver";
77
86
 
78
- import { useEverStore } from "@ssafy-mhk/e-ver";
87
+ function Demo() {
88
+ const { createGarment, resultUrl, status } = useEverGeneration({
89
+ apiKey: process.env.NEXT_PUBLIC_EVER_API_KEY,
90
+ });
79
91
 
80
- export default function FittingControls() {
81
- const { setWebcamActive, setActiveGarmentUrl, fitResult } = useEverStore();
92
+ const handleGenerate = async () => {
93
+ await createGarment(
94
+ { name: "오버핏 셔츠", category: "top" },
95
+ frontImageBlob,
96
+ backImageBlob,
97
+ );
98
+ };
82
99
 
83
100
  return (
84
- <div className="absolute top-4 left-4 z-10 flex flex-col gap-2">
85
- <button onClick={() => setWebcamActive(true)}>웹캠 가동 시작 🎥</button>
86
- <button onClick={() => setActiveGarmentUrl("/path/to/clothes.glb")}>
87
- 새로운 옷 입어보기 👕
101
+ <div className="relative h-screen w-full">
102
+ <button onClick={handleGenerate} disabled={status !== "idle"}>
103
+ 3D 생성
88
104
  </button>
89
105
 
90
- {fitResult && (
91
- <div className="bg-white/80 p-2 rounded">
92
- 핏 타입: {fitResult.type} (적합도 {fitResult.suitability}%)
93
- </div>
94
- )}
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
+ />
95
118
  </div>
96
119
  );
97
120
  }
98
121
  ```
99
122
 
100
- ### Step 2. 3D AR 캔버스 및 모델 구축하기
123
+ ## 생성 API
101
124
 
102
- SDK에서 제공하는 `EverCanvas`, `AvatarModel`, `GarmentModel`을 활용하여 화면을 그립니다.
125
+ ### `useEverGeneration`
103
126
 
104
- ```tsx
105
- // components/VirtualFittingScene.tsx
106
- "use client";
127
+ `createGarment`는 아래 순서를 묶습니다.
107
128
 
108
- import { useState } from "react";
109
- import {
110
- EverCanvas,
111
- AvatarModel,
112
- GarmentModel,
113
- useEverStore,
114
- } from "@ssafy-mhk/e-ver";
129
+ 1. garment 생성
130
+ 2. front/back 이미지 업로드
131
+ 3. `generate-3d` 요청
132
+ 4. 의류 모델 준비 완료까지 polling
115
133
 
116
- export default function VirtualFittingScene() {
117
- const [avatarBones, setAvatarBones] = useState<Record<string, THREE.Bone>>();
118
- const { activeGarmentUrl } = useEverStore();
134
+ ```tsx
135
+ import { useEverGeneration } from "@ssafy-mhk/e-ver";
119
136
 
120
- // 계정의 3D 아바타 파일 경로
121
- const AVATAR_URL = "/models/my-avatar.glb";
137
+ function Generator() {
138
+ const { createGarment, resultUrl, status, error } = useEverGeneration();
122
139
 
123
140
  return (
124
- <div className="w-full h-screen bg-transparent relative">
125
- {/* 1. 기본 AR 조명이 세팅된 캔버스 호출 */}
126
- <EverCanvas showEnvironment={true}>
127
- {/* 2. 사용자의 베이스 아바타 불러오기 */}
128
- <AvatarModel
129
- url={AVATAR_URL}
130
- onBonesReady={(bones) => setAvatarBones(bones)}
131
- />
132
-
133
- {/* 3. 활성화된 옷이 있다면 아바타 위에 덧입히기 */}
134
- {activeGarmentUrl && avatarBones && (
135
- <GarmentModel
136
- url={activeGarmentUrl}
137
- targetAvatarBones={avatarBones}
138
- />
139
- )}
140
- </EverCanvas>
141
- </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
+ </>
142
157
  );
143
158
  }
144
159
  ```
145
160
 
146
- ### Step 3. AI 바디 트래킹 연동하기
161
+ ## 고수준 Scene
147
162
 
148
- 웹캠 화면과 R3F 화면을 겹쳐주려면 `<video>` 태그를 `usePoseTracker`에 넘겨 연결해 주어야 합니다.
163
+ ### `EverFittingScene`
149
164
 
150
- ```tsx
151
- // components/ArCameraView.tsx
152
- "use client";
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`에서 특히 많이 쓰는 값:
186
+
187
+ - `measurements`
188
+ - `bodyPresetSelection`
189
+ - `sizeRecommendation`
190
+ - `garmentScale`
191
+ - `finalGarmentScale`
192
+ - `bodyMorphResult`
193
+ - `isTracking`
194
+ - `webcamError`
153
195
 
154
- import { useRef } from "react";
155
- import { usePoseTracker, useEverStore } from "@ssafy-mhk/e-ver";
196
+ ## 저수준 조립
156
197
 
157
- export default function ArCameraView() {
158
- const videoRef = useRef<HTMLVideoElement>(null);
198
+ 직접 조립이 필요하면 `useEverFitting`과 `EverTrackedGarment`를 사용할 수 있습니다.
159
199
 
160
- // SDK 내부의 로직을 통해 실시간으로 프레임을 MediaPipe에 전송
161
- const { isTrackerReady } = usePoseTracker(videoRef);
162
- const { isWebcamActive } = useEverStore();
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
+ });
163
209
 
164
210
  return (
165
- <div className="absolute inset-0 z-0">
166
- <video
167
- ref={videoRef}
168
- autoPlay
169
- playsInline
170
- muted
171
- className="w-full h-full object-cover"
172
- 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}
173
218
  />
174
- {/* Tracker가 로딩 중일 때 로딩 오버레이 표시 가능 */}
175
- {!isTrackerReady && isWebcamActive && <p>AI 모델 로딩 중...</p>}
176
- </div>
219
+ </EverCanvas>
177
220
  );
178
221
  }
179
222
  ```
180
223
 
181
- ---
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
+ ## 주의 사항
182
236
 
183
- ## 🙋‍♂️ Q&A (추가 기능 문의)
237
+ **`generateAvatar`는 사진 기반 개인 avatar 생성이 아닙니다.**
238
+ 현재 버전에서는 body preset 매칭을 통해 기본 아바타 모델 URL을 찾습니다.
184
239
 
185
- **Q. 평가는 어떻게 동작하나요?**
186
- -> 내부에 구축된 `useBodyMeasurer` 훅이 1초 단위(1Hz)로 캔버스의 실루엣을 통해 [어깨, 가슴, 허리] 사이즈를 분석하여 `useEverStore`의 `fitResult`에 자동 업데이트합니다.
240
+ **SDK는 UI kit이 아닙니다.**
241
+ 측정 패널, 디버그 패널, overlay는 소비 앱에서 조립해야 합니다.
187
242
 
188
- **Q. 물리 엔진(Rapier.js)이 적용되어 있나요?**
189
- -> 현재 MVP 스코프에서 무거운 런타임 물리 물리엔진은 제외되었으며, 대신 **SkinnedMesh 본 바인딩(P0)**과 **Normal Map 애니메이션(P1)**을 통하여 주름과 디테일을 시뮬레이션합니다.
243
+ **SDK 범위는 body preset 기반 fitting입니다.**
244
+ 개인 사진 기반 avatar 생성이나 전용 시각 효과는 현재 범위 밖입니다.
@@ -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
- constructor(baseUrl?: string);
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,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.
@@ -2,6 +2,8 @@ import React from "react";
2
2
  export interface EverCanvasProps {
3
3
  children: React.ReactNode;
4
4
  showEnvironment?: boolean;
5
+ useDefaultLights?: boolean;
6
+ enableOrbitControls?: boolean;
5
7
  }
6
8
  /**
7
9
  * A wrapper around R3F <Canvas> specifically configured for optimal
@@ -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 {};
@@ -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,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 {};
@@ -0,0 +1,24 @@
1
+ import * as THREE from "three";
2
+ export interface GarmentBoneBinding {
3
+ bone: THREE.Bone;
4
+ restQuaternion: THREE.Quaternion;
5
+ restScale: THREE.Vector3;
6
+ restWorldPosition?: THREE.Vector3;
7
+ restWorldQuaternion?: THREE.Quaternion;
8
+ restParentWorldQuaternion?: THREE.Quaternion;
9
+ }
10
+ export type GarmentBoneBindingMap = Map<string, GarmentBoneBinding[]>;
11
+ export interface GarmentFitProfile {
12
+ anchor: THREE.Vector3;
13
+ shoulderCenter: THREE.Vector3;
14
+ hipCenter: THREE.Vector3;
15
+ referenceWidth: number;
16
+ referenceTorsoHeight: number;
17
+ trackingHeight: number;
18
+ boundsCenter: THREE.Vector3;
19
+ boundsSize: THREE.Vector3;
20
+ hasBoneAnchors: boolean;
21
+ }
22
+ export declare function captureBoneBinding(bone: THREE.Bone): GarmentBoneBinding;
23
+ export declare function computeGarmentFitProfile(scene: THREE.Group, bones: GarmentBoneBindingMap, fallbackWidth?: number): GarmentFitProfile;
24
+ export declare function resetBoneRotations(bones: GarmentBoneBindingMap): void;
@@ -0,0 +1,18 @@
1
+ import type { NormalizedLandmark } from "@mediapipe/tasks-vision";
2
+ import { type MutableRefObject } from "react";
3
+ import * as THREE from "three";
4
+ import { type LandmarkCoordinateSpace } from "../pose/landmarkPoseSolver";
5
+ import { type GarmentBoneBindingMap } from "./garmentFitProfile";
6
+ export interface PoseApplicationRefs {
7
+ clockRef: MutableRefObject<THREE.Timer>;
8
+ prevRotationsRef: MutableRefObject<Map<string, THREE.Quaternion>>;
9
+ }
10
+ interface ApplyLandmarkPoseOptions {
11
+ coordinateSpace?: LandmarkCoordinateSpace;
12
+ excludeBones?: Set<string>;
13
+ }
14
+ export declare function usePoseApplicationRefs(): PoseApplicationRefs;
15
+ export declare function applyLandmarkPoseToGarment(landmarks: NormalizedLandmark[], bones: GarmentBoneBindingMap, refs: PoseApplicationRefs, options?: ApplyLandmarkPoseOptions): void;
16
+ export declare function resetPoseState(bones: GarmentBoneBindingMap, refs: PoseApplicationRefs): void;
17
+ export declare function blendBonesToRest(bones: GarmentBoneBindingMap, factor: number, delta: number, onlyBones?: Set<string>): void;
18
+ export {};