@cympotek/3d-transfer-sdk 1.0.0 → 1.0.1
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 +128 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ TypeScript SDK for Mobius 3D Transfer API - Convert images to 3D models using AI
|
|
|
8
8
|
- Support for multiple frameworks (Vite, Next.js, Expo, Node.js)
|
|
9
9
|
- Environment variable based configuration
|
|
10
10
|
- Axios-based HTTP client
|
|
11
|
+
- **React ModelViewer component** for displaying 3D GLB models
|
|
11
12
|
|
|
12
13
|
## Installation
|
|
13
14
|
|
|
@@ -117,11 +118,17 @@ async function convertImageTo3D(imageFile: File) {
|
|
|
117
118
|
path: { requestId },
|
|
118
119
|
});
|
|
119
120
|
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
const data = statusResponse.data.data;
|
|
122
|
+
status = data.status;
|
|
123
|
+
console.log('Status:', status, 'Phase:', data.phase, 'Progress:', data.progress);
|
|
124
|
+
|
|
125
|
+
// 2D preview is available when phase changes to 3d_generation
|
|
126
|
+
if (data.result?.preview_2d_url) {
|
|
127
|
+
console.log('2D Preview ready:', data.result.preview_2d_url);
|
|
128
|
+
}
|
|
122
129
|
|
|
123
130
|
if (status === 'COMPLETED') {
|
|
124
|
-
result =
|
|
131
|
+
result = data.result;
|
|
125
132
|
}
|
|
126
133
|
}
|
|
127
134
|
|
|
@@ -135,20 +142,63 @@ async function convertImageTo3D(imageFile: File) {
|
|
|
135
142
|
}
|
|
136
143
|
```
|
|
137
144
|
|
|
138
|
-
|
|
145
|
+
## React Components
|
|
146
|
+
|
|
147
|
+
### ModelViewer
|
|
148
|
+
|
|
149
|
+
The SDK includes a React component for displaying 3D GLB/GLTF models using Google's [model-viewer](https://modelviewer.dev/) web component.
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
import { ModelViewer } from '@cympotek/3d-transfer-sdk/react';
|
|
153
|
+
|
|
154
|
+
function My3DViewer() {
|
|
155
|
+
return (
|
|
156
|
+
<ModelViewer
|
|
157
|
+
src="https://example.com/model.glb"
|
|
158
|
+
alt="3D Model"
|
|
159
|
+
cameraControls
|
|
160
|
+
autoRotate
|
|
161
|
+
style={{ width: '100%', height: '400px' }}
|
|
162
|
+
/>
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### ModelViewer Props
|
|
168
|
+
|
|
169
|
+
| Prop | Type | Default | Description |
|
|
170
|
+
|------|------|---------|-------------|
|
|
171
|
+
| `src` | `string` | *required* | URL to the GLB/GLTF model file |
|
|
172
|
+
| `alt` | `string` | `'3D Model'` | Alt text for accessibility |
|
|
173
|
+
| `cameraControls` | `boolean` | `true` | Enable camera controls (pan, zoom, rotate) |
|
|
174
|
+
| `autoRotate` | `boolean` | `true` | Enable auto rotation |
|
|
175
|
+
| `shadowIntensity` | `number` | `1` | Shadow intensity (0-1) |
|
|
176
|
+
| `poster` | `string` | - | Poster image URL to show while loading |
|
|
177
|
+
| `className` | `string` | - | CSS class name |
|
|
178
|
+
| `style` | `CSSProperties` | - | Inline styles |
|
|
179
|
+
| `loading` | `'auto' \| 'lazy' \| 'eager'` | `'auto'` | Loading strategy |
|
|
180
|
+
| `reveal` | `'auto' \| 'manual'` | `'auto'` | Reveal strategy |
|
|
181
|
+
| `onLoad` | `() => void` | - | Callback when model is loaded |
|
|
182
|
+
| `onError` | `(error: Error) => void` | - | Callback when error occurs |
|
|
183
|
+
|
|
184
|
+
#### Complete React Example with ModelViewer
|
|
139
185
|
|
|
140
186
|
```tsx
|
|
141
|
-
import { useState } from 'react';
|
|
187
|
+
import { useState, useEffect } from 'react';
|
|
142
188
|
import {
|
|
143
189
|
createTransfer3DClient,
|
|
144
190
|
getTransfer3dStyles,
|
|
145
191
|
initiateTransfer3dConversion,
|
|
146
192
|
getTransfer3dStatus,
|
|
147
193
|
} from '@cympotek/3d-transfer-sdk';
|
|
194
|
+
import { ModelViewer } from '@cympotek/3d-transfer-sdk/react';
|
|
148
195
|
|
|
149
196
|
export function ImageTo3DConverter() {
|
|
150
197
|
const [status, setStatus] = useState<string>('idle');
|
|
151
|
-
const [
|
|
198
|
+
const [progress, setProgress] = useState(0);
|
|
199
|
+
const [preview2dUrl, setPreview2dUrl] = useState<string | null>(null);
|
|
200
|
+
const [glbUrl, setGlbUrl] = useState<string | null>(null);
|
|
201
|
+
const [webViewUrl, setWebViewUrl] = useState<string | null>(null);
|
|
152
202
|
|
|
153
203
|
const handleConvert = async (file: File, style: string) => {
|
|
154
204
|
const client = createTransfer3DClient();
|
|
@@ -169,10 +219,23 @@ export function ImageTo3DConverter() {
|
|
|
169
219
|
path: { requestId },
|
|
170
220
|
});
|
|
171
221
|
|
|
172
|
-
|
|
173
|
-
|
|
222
|
+
const result = statusData.data;
|
|
223
|
+
setProgress(result.progress || 0);
|
|
224
|
+
|
|
225
|
+
// Web view URL for viewing on main site
|
|
226
|
+
if (result.web_view_url) {
|
|
227
|
+
setWebViewUrl(result.web_view_url);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// 2D preview becomes available during 3D generation phase
|
|
231
|
+
if (result.result?.preview_2d_url) {
|
|
232
|
+
setPreview2dUrl(result.result.preview_2d_url);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (result.status === 'COMPLETED') {
|
|
236
|
+
setGlbUrl(result.result.glb_url);
|
|
174
237
|
setStatus('completed');
|
|
175
|
-
} else if (
|
|
238
|
+
} else if (result.status === 'FAILED') {
|
|
176
239
|
setStatus('failed');
|
|
177
240
|
} else {
|
|
178
241
|
setTimeout(pollStatus, 2000);
|
|
@@ -184,8 +247,36 @@ export function ImageTo3DConverter() {
|
|
|
184
247
|
|
|
185
248
|
return (
|
|
186
249
|
<div>
|
|
187
|
-
<p>Status: {status}</p>
|
|
188
|
-
|
|
250
|
+
<p>Status: {status} ({progress}%)</p>
|
|
251
|
+
|
|
252
|
+
{/* Link to view progress on main site */}
|
|
253
|
+
{webViewUrl && (
|
|
254
|
+
<a href={webViewUrl} target="_blank" rel="noopener noreferrer">
|
|
255
|
+
View on main site
|
|
256
|
+
</a>
|
|
257
|
+
)}
|
|
258
|
+
|
|
259
|
+
{/* 2D styled preview */}
|
|
260
|
+
{preview2dUrl && (
|
|
261
|
+
<div>
|
|
262
|
+
<h3>2D Style Preview</h3>
|
|
263
|
+
<img src={preview2dUrl} alt="2D Preview" />
|
|
264
|
+
</div>
|
|
265
|
+
)}
|
|
266
|
+
|
|
267
|
+
{/* 3D Model Viewer */}
|
|
268
|
+
{glbUrl && (
|
|
269
|
+
<div>
|
|
270
|
+
<h3>3D Model</h3>
|
|
271
|
+
<ModelViewer
|
|
272
|
+
src={glbUrl}
|
|
273
|
+
alt="Generated 3D Model"
|
|
274
|
+
cameraControls
|
|
275
|
+
autoRotate
|
|
276
|
+
style={{ width: '100%', height: '400px' }}
|
|
277
|
+
/>
|
|
278
|
+
</div>
|
|
279
|
+
)}
|
|
189
280
|
</div>
|
|
190
281
|
);
|
|
191
282
|
}
|
|
@@ -261,18 +352,29 @@ Get the status of a conversion request.
|
|
|
261
352
|
data: {
|
|
262
353
|
request_id: string;
|
|
263
354
|
status: 'PENDING' | 'IN_PROGRESS' | 'COMPLETED' | 'FAILED';
|
|
264
|
-
phase: '2d_style_transfer' | '3d_generation';
|
|
355
|
+
phase: '2d_style_transfer' | '3d_generation_pending' | '3d_generation';
|
|
265
356
|
progress: number; // 0-100
|
|
357
|
+
web_view_url: string; // URL to view progress on main site
|
|
266
358
|
result?: {
|
|
267
|
-
preview_2d_url: string;
|
|
268
|
-
model_3d_url: string;
|
|
269
|
-
glb_url: string;
|
|
359
|
+
preview_2d_url: string; // Available when 2D transfer completes
|
|
360
|
+
model_3d_url: string; // Available when fully completed
|
|
361
|
+
glb_url: string; // GLB file URL (same as model_3d_url)
|
|
270
362
|
};
|
|
271
363
|
error?: string; // Present if status is FAILED
|
|
272
364
|
}
|
|
273
365
|
}
|
|
274
366
|
```
|
|
275
367
|
|
|
368
|
+
## Conversion Phases
|
|
369
|
+
|
|
370
|
+
| Phase | Progress | Description |
|
|
371
|
+
|-------|----------|-------------|
|
|
372
|
+
| `2d_style_transfer` | 0-50% | Image is being styled with AI |
|
|
373
|
+
| `3d_generation_pending` | 50% | 2D complete, waiting for 3D to start |
|
|
374
|
+
| `3d_generation` | 50-100% | 3D model is being generated |
|
|
375
|
+
|
|
376
|
+
**Note:** The `preview_2d_url` becomes available when the phase changes to `3d_generation_pending` or `3d_generation`, allowing you to show the styled image while the 3D model is still being generated.
|
|
377
|
+
|
|
276
378
|
## Status Values
|
|
277
379
|
|
|
278
380
|
| Status | Description |
|
|
@@ -293,6 +395,9 @@ import type {
|
|
|
293
395
|
GetTransfer3dStatusData,
|
|
294
396
|
GetTransfer3dStatusResponse,
|
|
295
397
|
} from '@cympotek/3d-transfer-sdk';
|
|
398
|
+
|
|
399
|
+
// React component types
|
|
400
|
+
import type { ModelViewerProps } from '@cympotek/3d-transfer-sdk/react';
|
|
296
401
|
```
|
|
297
402
|
|
|
298
403
|
## Error Handling
|
|
@@ -319,25 +424,21 @@ try {
|
|
|
319
424
|
}
|
|
320
425
|
```
|
|
321
426
|
|
|
322
|
-
##
|
|
427
|
+
## Demo Application
|
|
323
428
|
|
|
324
|
-
|
|
429
|
+
A complete React demo application is available in the [examples/react-demo](https://github.com/cympotek/mobius-frontier/tree/main/builds/3d-transfer-sdk/examples/react-demo) directory.
|
|
430
|
+
|
|
431
|
+
To run the demo:
|
|
325
432
|
|
|
326
433
|
```bash
|
|
327
|
-
|
|
328
|
-
|
|
434
|
+
cd examples/react-demo
|
|
435
|
+
pnpm install
|
|
436
|
+
cp .env.example .env # Configure your API URL and token
|
|
437
|
+
pnpm dev
|
|
329
438
|
```
|
|
330
439
|
|
|
331
|
-
## OpenAPI Specification
|
|
332
|
-
|
|
333
|
-
The OpenAPI spec is included in this package at `openapi.json`. You can use it to:
|
|
334
|
-
- Generate clients for other languages
|
|
335
|
-
- Import into API testing tools (Postman, Insomnia)
|
|
336
|
-
- Generate documentation
|
|
337
|
-
|
|
338
440
|
## Support
|
|
339
441
|
|
|
340
|
-
- [API Documentation](https://api.localhost/docs/api)
|
|
341
442
|
- [GitHub Issues](https://github.com/cympotek/mobius-frontier/issues)
|
|
342
443
|
|
|
343
444
|
---
|