@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.
Files changed (69) hide show
  1. package/README.md +183 -114
  2. package/dist/api/EverClient.d.ts +12 -1
  3. package/dist/api/EverClient.test.d.ts +1 -0
  4. package/dist/avatar/VRMCompat.d.ts +8 -0
  5. package/dist/avatar/avatarLoader.d.ts +12 -0
  6. package/dist/avatar/humanoidBindings.d.ts +7 -0
  7. package/dist/bodyPreset/presetSelection.d.ts +31 -0
  8. package/dist/components/CameraView.d.ts +5 -0
  9. package/dist/components/EverCanvas.d.ts +2 -0
  10. package/dist/components/EverFittingScene.d.ts +18 -0
  11. package/dist/components/EverFittingScene.test.d.ts +1 -0
  12. package/dist/components/EverProvider.d.ts +0 -8
  13. package/dist/components/EverTrackedGarment.d.ts +15 -0
  14. package/dist/components/TrackedGarmentPoseDriver.d.ts +13 -0
  15. package/dist/components/WebcamPlaneBackground.d.ts +7 -0
  16. package/dist/components/ever-context.d.ts +9 -0
  17. package/dist/compositing/videoCover.d.ts +14 -0
  18. package/dist/fitting/bodyFirstFitting.d.ts +14 -0
  19. package/dist/fitting/bodyFirstFitting.test.d.ts +1 -0
  20. package/dist/garment/constants.d.ts +1 -0
  21. package/dist/garment/fitMotion.d.ts +18 -0
  22. package/dist/garment/garmentFitProfile.d.ts +24 -0
  23. package/dist/garment/poseApplication.d.ts +18 -0
  24. package/dist/garment/trackedGarmentMotion.d.ts +32 -0
  25. package/dist/garment/trackedModelTransform.d.ts +40 -0
  26. package/dist/hooks/useAvatarVariant.d.ts +12 -0
  27. package/dist/hooks/useBodyMeasurer.d.ts +13 -4
  28. package/dist/hooks/useBodyMeasurer.test.d.ts +1 -0
  29. package/dist/hooks/useBodyPresetSelection.d.ts +3 -0
  30. package/dist/hooks/useEverFitting.d.ts +51 -0
  31. package/dist/hooks/useEverFitting.test.d.ts +1 -0
  32. package/dist/hooks/useEverGeneration.d.ts +4 -5
  33. package/dist/hooks/useEverGeneration.test.d.ts +1 -0
  34. package/dist/hooks/useMeasurement.d.ts +19 -0
  35. package/dist/hooks/usePoseMapper.d.ts +2 -1
  36. package/dist/hooks/usePoseTracker.d.ts +24 -6
  37. package/dist/hooks/usePoseTracker.test.d.ts +1 -0
  38. package/dist/hooks/useWebcam.d.ts +19 -0
  39. package/dist/hooks/useWebcam.test.d.ts +1 -0
  40. package/dist/index.d.ts +45 -0
  41. package/dist/index.es.js +3119 -40588
  42. package/dist/index.umd.js +1 -4415
  43. package/dist/measurement/garmentScaler.d.ts +19 -0
  44. package/dist/measurement/scaleCalculator.d.ts +5 -0
  45. package/dist/measurement/scaleCalculator.test.d.ts +1 -0
  46. package/dist/measurement/silhouetteExtractor.d.ts +3 -0
  47. package/dist/measurement/sizeRecommender.d.ts +2 -0
  48. package/dist/pose/boneMapping.d.ts +14 -0
  49. package/dist/pose/coordinateTransform.d.ts +9 -0
  50. package/dist/pose/facingDetector.d.ts +35 -0
  51. package/dist/pose/interpolation.d.ts +16 -0
  52. package/dist/pose/landmarkPoseSolver.d.ts +9 -0
  53. package/dist/pose/landmarkerFactory.d.ts +13 -0
  54. package/dist/pose/poseSolver.d.ts +2 -0
  55. package/dist/pose/segmentation.d.ts +9 -0
  56. package/dist/pose/smoothing.d.ts +12 -0
  57. package/dist/pose/yawDirectionStabilizer.d.ts +20 -0
  58. package/dist/pose/yawFreezeController.d.ts +11 -0
  59. package/dist/publicApi.test.d.ts +1 -0
  60. package/dist/store/useEverStore.d.ts +10 -5
  61. package/dist/tracking/personLock.d.ts +39 -0
  62. package/dist/tracking/trackingStability.d.ts +6 -0
  63. package/dist/tracking/trackingState.d.ts +18 -0
  64. package/dist/types/bodyPreset.d.ts +65 -0
  65. package/dist/types/fitting.d.ts +15 -0
  66. package/dist/types/measurement.d.ts +42 -0
  67. package/dist/types/pose.d.ts +81 -0
  68. package/dist/types/tracking.d.ts +13 -0
  69. package/package.json +11 -6
package/README.md CHANGED
@@ -1,175 +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
- 패키지는 사내 또는 외부 NPM에 직접 배포되기 전 로컬 저장소를 통한 심볼릭 링크(Symbolic Link) 방식으로 연결하거나 파일 디렉토리를 참조하여 사용할 수 있습니다.
18
+ ## 설치
18
19
 
19
- ### 로컬 프로젝트에서 참조하여 설치할 경우:
20
+ ```bash
21
+ pnpm add @ssafy-mhk/e-ver
22
+ ```
20
23
 
21
- 여러분의 Next.js 프로젝트 최상위 폴더(`frontend`)에서 아래 명령어를 실행하세요.
24
+ 필수 peer dependency:
22
25
 
23
26
  ```bash
24
- # pnpm 사용
25
- pnpm add @ssafy-mhk/e-ver
27
+ pnpm add react react-dom three @react-three/fiber @react-three/drei @mediapipe/tasks-vision zustand
28
+ ```
26
29
 
27
- # 또는 패키지 매니저에 따라
28
- npm install @ssafy-mhk/e-ver
29
- yarn add @ssafy-mhk/e-ver
30
+ 레포에서 `ever/frontend`로 로컬 검증할 때는:
31
+
32
+ ```bash
33
+ pnpm run sdk:use-tarball
30
34
  ```
31
35
 
32
- _(의존성 설치가 되었는지 꼭 `package.json` 코드를 확인하세요.)_
36
+ 퍼블리시된 버전으로 되돌릴 때는:
33
37
 
34
- ---
38
+ ```bash
39
+ pnpm run sdk:use-version -- 1.0.4
40
+ ```
35
41
 
36
- ## 🚀 코어로직 한눈에 보기 (SDK 핵심 요소)
42
+ ## 서버와 인증
37
43
 
38
- SDK는 크게 **State(상태 관리)**, **Renderer(렌더링 UI)**, **Tracker(추적/측정 Hook)** 이렇게 3가지 핵심 축으로 구성됩니다.
44
+ 기본 API 서버는 `http://localhost:8000/api/v1`입니다.
39
45
 
40
- | 분류 | 모듈명 | 역할 |
41
- | ------------ | ----------------- | ------------------------------------------------------------------------------------ |
42
- | **State** | `useEverStore` | 웹캠 활성화 여부, 렌더링 중인 옷/아바타 주소, 최종 핏 결과(체형 측정) 관리 |
43
- | **Renderer** | `EverCanvas` | AR/3D 환경에 최적화된 조명과 카메라 세팅을 내장한 R3F 캔버스 래퍼 |
44
- | **Renderer** | `AvatarModel` | 사용자의 AI 기반 생성 3D 아바타(GLB)를 로딩하고, 뼈대(Bone) 구조를 추출 |
45
- | **Renderer** | `GarmentModel` | 사용자가 선택한 옷(GLB)을 로딩하고, 옷의 SkinnedMesh를 대상 아바타에 입힘 |
46
- | **Tracker** | `usePoseTracker` | 브라우저 내에서 MediaPipe를 가동시켜 실시간 30-60Hz 웹캠 추적 |
47
- | **Tracker** | `usePoseMapper` | 웹캠에서 얻은 2D/3D 점(Landmarks)을 필수 13본(Bone)의 회전값(Quaternion)으로 변환 |
48
- | **Tracker** | `useBodyMeasurer` | AR 카메라 상에서 사용자 실루엣 기반 사이즈(어깨, 가슴, 허리)를 연산하여 옷의 핏 평가 |
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
- ## 📖 사용 가이드 (Usage Guide)
59
+ `useEverGeneration`도 동일하게 `apiKey`를 받을 있습니다.
53
60
 
54
- 아래는 Next.js(App Router) 환경에서 가상 피팅 서비스를 구축하는 기본 예제 코드입니다.
61
+ ## 권장 사용 흐름
55
62
 
56
- ### Step 1. Zustand로 글로벌 상태 세팅하기
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
- // app/fitting/page.tsx
62
- "use client";
85
+ import { EverFittingScene, useEverGeneration } from "@ssafy-mhk/e-ver";
63
86
 
64
- 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
+ });
65
91
 
66
- export default function FittingControls() {
67
- const { setWebcamActive, setActiveGarmentUrl, fitResult } = useEverStore();
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="absolute top-4 left-4 z-10 flex flex-col gap-2">
71
- <button onClick={() => setWebcamActive(true)}>웹캠 가동 시작 🎥</button>
72
- <button onClick={() => setActiveGarmentUrl("/path/to/clothes.glb")}>
73
- 새로운 옷 입어보기 👕
101
+ <div className="relative h-screen w-full">
102
+ <button onClick={handleGenerate} disabled={status !== "idle"}>
103
+ 3D 생성
74
104
  </button>
75
105
 
76
- {fitResult && (
77
- <div className="bg-white/80 p-2 rounded">
78
- 핏 타입: {fitResult.type} (적합도 {fitResult.suitability}%)
79
- </div>
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
- ### Step 2. 3D AR 캔버스 및 모델 구축하기
123
+ ## 생성 API
87
124
 
88
- SDK에서 제공하는 `EverCanvas`, `AvatarModel`, `GarmentModel`을 활용하여 화면을 그립니다.
125
+ ### `useEverGeneration`
89
126
 
90
- ```tsx
91
- // components/VirtualFittingScene.tsx
92
- "use client";
127
+ `createGarment`는 아래 순서를 묶습니다.
93
128
 
94
- import { useState } from "react";
95
- import {
96
- EverCanvas,
97
- AvatarModel,
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
- export default function VirtualFittingScene() {
103
- const [avatarBones, setAvatarBones] = useState<Record<string, THREE.Bone>>();
104
- const { activeGarmentUrl } = useEverStore();
134
+ ```tsx
135
+ import { useEverGeneration } from "@ssafy-mhk/e-ver";
105
136
 
106
- // 계정의 3D 아바타 파일 경로
107
- const AVATAR_URL = "/models/my-avatar.glb";
137
+ function Generator() {
138
+ const { createGarment, resultUrl, status, error } = useEverGeneration();
108
139
 
109
140
  return (
110
- <div className="w-full h-screen bg-transparent relative">
111
- {/* 1. 기본 AR 조명이 세팅된 캔버스 호출 */}
112
- <EverCanvas showEnvironment={true}>
113
- {/* 2. 사용자의 베이스 아바타 불러오기 */}
114
- <AvatarModel
115
- url={AVATAR_URL}
116
- onBonesReady={(bones) => setAvatarBones(bones)}
117
- />
118
-
119
- {/* 3. 활성화된 옷이 있다면 아바타 위에 덧입히기 */}
120
- {activeGarmentUrl && avatarBones && (
121
- <GarmentModel
122
- url={activeGarmentUrl}
123
- targetAvatarBones={avatarBones}
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
- ### Step 3. AI 바디 트래킹 연동하기
161
+ ## 고수준 Scene
133
162
 
134
- 웹캠 화면과 R3F 화면을 겹쳐주려면 `<video>` 태그를 `usePoseTracker`에 넘겨 연결해 주어야 합니다.
163
+ ### `EverFittingScene`
135
164
 
136
- ```tsx
137
- // components/ArCameraView.tsx
138
- "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`에서 특히 많이 쓰는 값:
139
186
 
140
- import { useRef } from "react";
141
- import { usePoseTracker, useEverStore } from "@ssafy-mhk/e-ver";
187
+ - `measurements`
188
+ - `bodyPresetSelection`
189
+ - `sizeRecommendation`
190
+ - `garmentScale`
191
+ - `finalGarmentScale`
192
+ - `bodyMorphResult`
193
+ - `isTracking`
194
+ - `webcamError`
142
195
 
143
- export default function ArCameraView() {
144
- const videoRef = useRef<HTMLVideoElement>(null);
196
+ ## 저수준 조립
145
197
 
146
- // SDK 내부의 로직을 통해 실시간으로 프레임을 MediaPipe에 전송
147
- const { isTrackerReady } = usePoseTracker(videoRef);
148
- const { isWebcamActive } = useEverStore();
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
- <div className="absolute inset-0 z-0">
152
- <video
153
- ref={videoRef}
154
- autoPlay
155
- playsInline
156
- muted
157
- className="w-full h-full object-cover"
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
- {/* Tracker가 로딩 중일 때 로딩 오버레이 표시 가능 */}
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
- ## 🙋‍♂️ Q&A (추가 기능 문의)
237
+ **`generateAvatar`는 사진 기반 개인 avatar 생성이 아닙니다.**
238
+ 현재 버전에서는 body preset 매칭을 통해 기본 아바타 모델 URL을 찾습니다.
170
239
 
171
- **Q. 평가는 어떻게 동작하나요?**
172
- -> 내부에 구축된 `useBodyMeasurer` 훅이 1초 단위(1Hz)로 캔버스의 실루엣을 통해 [어깨, 가슴, 허리] 사이즈를 분석하여 `useEverStore`의 `fitResult`에 자동 업데이트합니다.
240
+ **SDK는 UI kit이 아닙니다.**
241
+ 측정 패널, 디버그 패널, overlay는 소비 앱에서 조립해야 합니다.
173
242
 
174
- **Q. 물리 엔진(Rapier.js)이 적용되어 있나요?**
175
- -> 현재 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 @@
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.
@@ -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 {};
@@ -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 {};