sceneview-mcp 3.4.12 → 3.4.13
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/dist/debug-issue.js +551 -0
- package/dist/generate-scene.js +325 -0
- package/dist/index.js +133 -1
- package/dist/migrate-code.js +203 -0
- package/dist/platform-setup.js +787 -0
- package/package.json +8 -1
|
@@ -0,0 +1,787 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* platform-setup.ts
|
|
3
|
+
*
|
|
4
|
+
* Setup guides for every supported SceneView platform.
|
|
5
|
+
* Consolidates Android, iOS, Web, Flutter, React Native, Desktop, and TV.
|
|
6
|
+
*/
|
|
7
|
+
export const PLATFORM_IDS = ["android", "ios", "web", "flutter", "react-native", "desktop", "tv"];
|
|
8
|
+
const ANDROID_3D = `## SceneView Android — 3D Setup
|
|
9
|
+
|
|
10
|
+
### 1. Gradle Dependencies
|
|
11
|
+
|
|
12
|
+
\`\`\`kotlin
|
|
13
|
+
// build.gradle.kts (app module)
|
|
14
|
+
dependencies {
|
|
15
|
+
implementation("io.github.sceneview:sceneview:3.3.0")
|
|
16
|
+
}
|
|
17
|
+
\`\`\`
|
|
18
|
+
|
|
19
|
+
### 2. Minimum SDK
|
|
20
|
+
|
|
21
|
+
\`\`\`kotlin
|
|
22
|
+
android {
|
|
23
|
+
defaultConfig {
|
|
24
|
+
minSdk = 24
|
|
25
|
+
}
|
|
26
|
+
compileOptions {
|
|
27
|
+
sourceCompatibility = JavaVersion.VERSION_17
|
|
28
|
+
targetCompatibility = JavaVersion.VERSION_17
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
\`\`\`
|
|
32
|
+
|
|
33
|
+
### 3. Basic 3D Scene
|
|
34
|
+
|
|
35
|
+
\`\`\`kotlin
|
|
36
|
+
@Composable
|
|
37
|
+
fun My3DScreen() {
|
|
38
|
+
val engine = rememberEngine()
|
|
39
|
+
val modelLoader = rememberModelLoader(engine)
|
|
40
|
+
val environmentLoader = rememberEnvironmentLoader(engine)
|
|
41
|
+
|
|
42
|
+
Scene(
|
|
43
|
+
modifier = Modifier.fillMaxSize(),
|
|
44
|
+
engine = engine,
|
|
45
|
+
modelLoader = modelLoader,
|
|
46
|
+
environment = rememberEnvironment(environmentLoader) {
|
|
47
|
+
environmentLoader.createHDREnvironment("environments/sky_2k.hdr")
|
|
48
|
+
?: createEnvironment(environmentLoader)
|
|
49
|
+
}
|
|
50
|
+
) {
|
|
51
|
+
rememberModelInstance(modelLoader, "models/chair.glb")?.let { instance ->
|
|
52
|
+
ModelNode(
|
|
53
|
+
modelInstance = instance,
|
|
54
|
+
scaleToUnits = 1.0f,
|
|
55
|
+
centerOrigin = Position(0f, 0f, 0f)
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
LightNode(
|
|
60
|
+
engine = engine,
|
|
61
|
+
type = LightManager.Type.DIRECTIONAL,
|
|
62
|
+
apply = {
|
|
63
|
+
intensity(100_000f)
|
|
64
|
+
castShadows(true)
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
\`\`\`
|
|
70
|
+
|
|
71
|
+
### 4. Asset Location
|
|
72
|
+
|
|
73
|
+
Place 3D assets in \`src/main/assets/\`:
|
|
74
|
+
\`\`\`
|
|
75
|
+
app/src/main/assets/
|
|
76
|
+
models/ # GLB/glTF files
|
|
77
|
+
environments/ # HDR environment maps
|
|
78
|
+
materials/ # Custom .filamat materials
|
|
79
|
+
\`\`\`
|
|
80
|
+
|
|
81
|
+
### 5. No Manifest Changes Required
|
|
82
|
+
|
|
83
|
+
3D-only scenes need no special permissions or manifest entries.`;
|
|
84
|
+
const ANDROID_AR = `## SceneView Android — AR Setup
|
|
85
|
+
|
|
86
|
+
### 1. Gradle Dependencies
|
|
87
|
+
|
|
88
|
+
\`\`\`kotlin
|
|
89
|
+
// build.gradle.kts (app module)
|
|
90
|
+
dependencies {
|
|
91
|
+
implementation("io.github.sceneview:arsceneview:3.3.0")
|
|
92
|
+
// arsceneview includes sceneview transitively
|
|
93
|
+
}
|
|
94
|
+
\`\`\`
|
|
95
|
+
|
|
96
|
+
### 2. AndroidManifest.xml
|
|
97
|
+
|
|
98
|
+
\`\`\`xml
|
|
99
|
+
<uses-permission android:name="android.permission.CAMERA" />
|
|
100
|
+
<uses-feature android:name="android.hardware.camera.ar" android:required="true" />
|
|
101
|
+
|
|
102
|
+
<application>
|
|
103
|
+
<meta-data android:name="com.google.ar.core" android:value="required" />
|
|
104
|
+
</application>
|
|
105
|
+
\`\`\`
|
|
106
|
+
|
|
107
|
+
### 3. Camera Permission at Runtime
|
|
108
|
+
|
|
109
|
+
\`\`\`kotlin
|
|
110
|
+
val cameraPermission = rememberLauncherForActivityResult(
|
|
111
|
+
ActivityResultContracts.RequestPermission()
|
|
112
|
+
) { granted -> if (granted) showAR = true }
|
|
113
|
+
|
|
114
|
+
LaunchedEffect(Unit) {
|
|
115
|
+
cameraPermission.launch(Manifest.permission.CAMERA)
|
|
116
|
+
}
|
|
117
|
+
\`\`\`
|
|
118
|
+
|
|
119
|
+
### 4. Basic AR Scene
|
|
120
|
+
|
|
121
|
+
\`\`\`kotlin
|
|
122
|
+
@Composable
|
|
123
|
+
fun MyARScreen() {
|
|
124
|
+
val engine = rememberEngine()
|
|
125
|
+
val modelLoader = rememberModelLoader(engine)
|
|
126
|
+
var anchor by remember { mutableStateOf<Anchor?>(null) }
|
|
127
|
+
|
|
128
|
+
val modelInstance = rememberModelInstance(modelLoader, "models/robot.glb")
|
|
129
|
+
|
|
130
|
+
ARScene(
|
|
131
|
+
modifier = Modifier.fillMaxSize(),
|
|
132
|
+
engine = engine,
|
|
133
|
+
modelLoader = modelLoader,
|
|
134
|
+
planeRenderer = true,
|
|
135
|
+
sessionConfiguration = { session, config ->
|
|
136
|
+
config.depthMode =
|
|
137
|
+
if (session.isDepthModeSupported(Config.DepthMode.AUTOMATIC))
|
|
138
|
+
Config.DepthMode.AUTOMATIC else Config.DepthMode.DISABLED
|
|
139
|
+
config.lightEstimationMode = Config.LightEstimationMode.ENVIRONMENTAL_HDR
|
|
140
|
+
config.planeFindingMode = Config.PlaneFindingMode.HORIZONTAL_AND_VERTICAL
|
|
141
|
+
},
|
|
142
|
+
onTouchEvent = { event, hitResult ->
|
|
143
|
+
if (event.action == MotionEvent.ACTION_UP && hitResult != null) {
|
|
144
|
+
anchor = hitResult.createAnchor()
|
|
145
|
+
}
|
|
146
|
+
true
|
|
147
|
+
}
|
|
148
|
+
) {
|
|
149
|
+
anchor?.let { a ->
|
|
150
|
+
AnchorNode(anchor = a) {
|
|
151
|
+
modelInstance?.let { instance ->
|
|
152
|
+
ModelNode(
|
|
153
|
+
modelInstance = instance,
|
|
154
|
+
scaleToUnits = 0.5f,
|
|
155
|
+
isEditable = true
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
\`\`\`
|
|
163
|
+
|
|
164
|
+
### 5. Session Configuration Options
|
|
165
|
+
|
|
166
|
+
| Option | Values | Default |
|
|
167
|
+
|--------|--------|---------|
|
|
168
|
+
| \`depthMode\` | \`DISABLED\`, \`AUTOMATIC\` | \`DISABLED\` |
|
|
169
|
+
| \`lightEstimationMode\` | \`DISABLED\`, \`AMBIENT_INTENSITY\`, \`ENVIRONMENTAL_HDR\` | \`ENVIRONMENTAL_HDR\` |
|
|
170
|
+
| \`planeFindingMode\` | \`DISABLED\`, \`HORIZONTAL\`, \`VERTICAL\`, \`HORIZONTAL_AND_VERTICAL\` | \`HORIZONTAL_AND_VERTICAL\` |
|
|
171
|
+
| \`instantPlacementMode\` | \`DISABLED\`, \`LOCAL_Y_UP\` | \`DISABLED\` |
|
|
172
|
+
| \`cloudAnchorMode\` | \`DISABLED\`, \`ENABLED\` | \`DISABLED\` |`;
|
|
173
|
+
const IOS_3D = `## SceneViewSwift — iOS/macOS/visionOS 3D Setup
|
|
174
|
+
|
|
175
|
+
### 1. SPM Dependency
|
|
176
|
+
|
|
177
|
+
In Xcode: **File > Add Package Dependencies** > paste:
|
|
178
|
+
\`\`\`
|
|
179
|
+
https://github.com/SceneView/sceneview
|
|
180
|
+
\`\`\`
|
|
181
|
+
Set version rule to **"from: 3.3.0"**.
|
|
182
|
+
|
|
183
|
+
Or in Package.swift:
|
|
184
|
+
\`\`\`swift
|
|
185
|
+
// swift-tools-version: 5.10
|
|
186
|
+
import PackageDescription
|
|
187
|
+
|
|
188
|
+
let package = Package(
|
|
189
|
+
name: "MyApp",
|
|
190
|
+
platforms: [.iOS(.v17), .macOS(.v14), .visionOS(.v1)],
|
|
191
|
+
dependencies: [
|
|
192
|
+
.package(url: "https://github.com/SceneView/sceneview", from: "3.3.0")
|
|
193
|
+
],
|
|
194
|
+
targets: [
|
|
195
|
+
.executableTarget(
|
|
196
|
+
name: "MyApp",
|
|
197
|
+
dependencies: [
|
|
198
|
+
.product(name: "SceneViewSwift", package: "sceneview")
|
|
199
|
+
]
|
|
200
|
+
)
|
|
201
|
+
]
|
|
202
|
+
)
|
|
203
|
+
\`\`\`
|
|
204
|
+
|
|
205
|
+
### 2. Minimum Platform Versions
|
|
206
|
+
|
|
207
|
+
| Platform | Minimum |
|
|
208
|
+
|----------|---------|
|
|
209
|
+
| iOS | 17.0 |
|
|
210
|
+
| macOS | 14.0 |
|
|
211
|
+
| visionOS | 1.0 |
|
|
212
|
+
|
|
213
|
+
### 3. Basic SwiftUI Integration
|
|
214
|
+
|
|
215
|
+
\`\`\`swift
|
|
216
|
+
import SwiftUI
|
|
217
|
+
import SceneViewSwift
|
|
218
|
+
import RealityKit
|
|
219
|
+
|
|
220
|
+
struct ContentView: View {
|
|
221
|
+
@State private var model: ModelNode?
|
|
222
|
+
|
|
223
|
+
var body: some View {
|
|
224
|
+
SceneView { root in
|
|
225
|
+
if let model {
|
|
226
|
+
root.addChild(model.entity)
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
.cameraControls(.orbit)
|
|
230
|
+
.task {
|
|
231
|
+
do {
|
|
232
|
+
model = try await ModelNode.load("models/car.usdz")
|
|
233
|
+
model?.scaleToUnits(1.0)
|
|
234
|
+
} catch {
|
|
235
|
+
print("Failed to load model: \\(error)")
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
\`\`\`
|
|
241
|
+
|
|
242
|
+
### 4. Model Formats
|
|
243
|
+
|
|
244
|
+
| Format | Support |
|
|
245
|
+
|--------|---------|
|
|
246
|
+
| USDZ | Native — recommended for iOS |
|
|
247
|
+
| .reality | Native — RealityKit format |
|
|
248
|
+
| glTF/GLB | Not natively supported (use Android/Web) |`;
|
|
249
|
+
const IOS_AR = `## SceneViewSwift — iOS AR Setup
|
|
250
|
+
|
|
251
|
+
### 1. SPM Dependency
|
|
252
|
+
|
|
253
|
+
\`\`\`swift
|
|
254
|
+
.package(url: "https://github.com/SceneView/sceneview", from: "3.3.0")
|
|
255
|
+
\`\`\`
|
|
256
|
+
|
|
257
|
+
### 2. Info.plist — Camera Permission (Required)
|
|
258
|
+
|
|
259
|
+
\`\`\`xml
|
|
260
|
+
<key>NSCameraUsageDescription</key>
|
|
261
|
+
<string>This app uses the camera for augmented reality.</string>
|
|
262
|
+
\`\`\`
|
|
263
|
+
|
|
264
|
+
### 3. Minimum Platform
|
|
265
|
+
|
|
266
|
+
AR requires **iOS 17.0+**. Not available on macOS or visionOS via \`ARSceneView\`.
|
|
267
|
+
|
|
268
|
+
### 4. Basic AR Integration
|
|
269
|
+
|
|
270
|
+
\`\`\`swift
|
|
271
|
+
import SwiftUI
|
|
272
|
+
import SceneViewSwift
|
|
273
|
+
import RealityKit
|
|
274
|
+
|
|
275
|
+
struct ARContentView: View {
|
|
276
|
+
@State private var model: ModelNode?
|
|
277
|
+
|
|
278
|
+
var body: some View {
|
|
279
|
+
ARSceneView(
|
|
280
|
+
planeDetection: .horizontal,
|
|
281
|
+
showCoachingOverlay: true,
|
|
282
|
+
onTapOnPlane: { position, arView in
|
|
283
|
+
guard let model else { return }
|
|
284
|
+
let anchor = AnchorNode.world(position: position)
|
|
285
|
+
let clone = model.entity.clone(recursive: true)
|
|
286
|
+
clone.scale = .init(repeating: 0.3)
|
|
287
|
+
anchor.add(clone)
|
|
288
|
+
arView.scene.addAnchor(anchor.entity)
|
|
289
|
+
}
|
|
290
|
+
)
|
|
291
|
+
.edgesIgnoringSafeArea(.all)
|
|
292
|
+
.task {
|
|
293
|
+
model = try? await ModelNode.load("models/robot.usdz")
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
\`\`\`
|
|
298
|
+
|
|
299
|
+
### 5. AR Configuration
|
|
300
|
+
|
|
301
|
+
| Parameter | Options | Default |
|
|
302
|
+
|-----------|---------|---------|
|
|
303
|
+
| \`planeDetection\` | \`.none\`, \`.horizontal\`, \`.vertical\`, \`.both\` | \`.horizontal\` |
|
|
304
|
+
| \`showPlaneOverlay\` | \`true\` / \`false\` | \`true\` |
|
|
305
|
+
| \`showCoachingOverlay\` | \`true\` / \`false\` | \`true\` |`;
|
|
306
|
+
const WEB_3D = `## SceneView Web — Browser 3D Setup
|
|
307
|
+
|
|
308
|
+
SceneView Web uses **Filament.js** — the same rendering engine as Android, compiled to WebAssembly (WebGL2).
|
|
309
|
+
|
|
310
|
+
### 1. Install
|
|
311
|
+
|
|
312
|
+
\`\`\`bash
|
|
313
|
+
npm install @sceneview/sceneview-web
|
|
314
|
+
\`\`\`
|
|
315
|
+
|
|
316
|
+
Or in a Kotlin/JS Gradle project:
|
|
317
|
+
\`\`\`kotlin
|
|
318
|
+
kotlin {
|
|
319
|
+
js(IR) { browser(); binaries.executable() }
|
|
320
|
+
sourceSets {
|
|
321
|
+
jsMain.dependencies {
|
|
322
|
+
implementation("@sceneview/sceneview-web")
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
\`\`\`
|
|
327
|
+
|
|
328
|
+
### 2. HTML
|
|
329
|
+
|
|
330
|
+
\`\`\`html
|
|
331
|
+
<canvas id="scene-canvas" style="width:100%;height:100vh"></canvas>
|
|
332
|
+
<script src="your-app.js"></script>
|
|
333
|
+
\`\`\`
|
|
334
|
+
|
|
335
|
+
### 3. Kotlin/JS Code
|
|
336
|
+
|
|
337
|
+
\`\`\`kotlin
|
|
338
|
+
import io.github.sceneview.web.SceneView
|
|
339
|
+
import kotlinx.browser.document
|
|
340
|
+
import org.w3c.dom.HTMLCanvasElement
|
|
341
|
+
|
|
342
|
+
fun main() {
|
|
343
|
+
val canvas = document.getElementById("scene-canvas") as HTMLCanvasElement
|
|
344
|
+
canvas.width = canvas.clientWidth
|
|
345
|
+
canvas.height = canvas.clientHeight
|
|
346
|
+
|
|
347
|
+
SceneView.create(
|
|
348
|
+
canvas = canvas,
|
|
349
|
+
configure = {
|
|
350
|
+
camera {
|
|
351
|
+
eye(0.0, 1.5, 5.0)
|
|
352
|
+
target(0.0, 0.0, 0.0)
|
|
353
|
+
fov(45.0)
|
|
354
|
+
}
|
|
355
|
+
light {
|
|
356
|
+
directional()
|
|
357
|
+
intensity(100_000.0)
|
|
358
|
+
}
|
|
359
|
+
model("models/DamagedHelmet.glb")
|
|
360
|
+
autoRotate()
|
|
361
|
+
},
|
|
362
|
+
onReady = { sceneView ->
|
|
363
|
+
sceneView.startRendering()
|
|
364
|
+
}
|
|
365
|
+
)
|
|
366
|
+
}
|
|
367
|
+
\`\`\`
|
|
368
|
+
|
|
369
|
+
### 4. Supported Features
|
|
370
|
+
|
|
371
|
+
- Same Filament PBR renderer as Android (WASM)
|
|
372
|
+
- glTF 2.0 / GLB model loading
|
|
373
|
+
- IBL environment lighting (KTX)
|
|
374
|
+
- Orbit camera with mouse/touch/pinch
|
|
375
|
+
- Auto-rotation, directional/point/spot lights
|
|
376
|
+
|
|
377
|
+
### 5. Limitations
|
|
378
|
+
|
|
379
|
+
- No AR (requires native sensors)
|
|
380
|
+
- WebGL2 required (~95% of browsers)
|
|
381
|
+
- glTF/GLB format only`;
|
|
382
|
+
const FLUTTER_3D = `## SceneView Flutter — 3D Setup
|
|
383
|
+
|
|
384
|
+
SceneView Flutter uses **PlatformView** to embed native SceneView (Android: Filament, iOS: RealityKit).
|
|
385
|
+
|
|
386
|
+
### 1. Dependencies
|
|
387
|
+
|
|
388
|
+
\`\`\`yaml
|
|
389
|
+
# pubspec.yaml
|
|
390
|
+
dependencies:
|
|
391
|
+
sceneview_flutter: ^3.3.0
|
|
392
|
+
\`\`\`
|
|
393
|
+
|
|
394
|
+
### 2. Android Setup
|
|
395
|
+
|
|
396
|
+
Add to \`android/app/build.gradle\`:
|
|
397
|
+
\`\`\`groovy
|
|
398
|
+
android {
|
|
399
|
+
defaultConfig {
|
|
400
|
+
minSdkVersion 24
|
|
401
|
+
}
|
|
402
|
+
compileOptions {
|
|
403
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
404
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
\`\`\`
|
|
408
|
+
|
|
409
|
+
### 3. iOS Setup
|
|
410
|
+
|
|
411
|
+
In \`ios/Podfile\`:
|
|
412
|
+
\`\`\`ruby
|
|
413
|
+
platform :ios, '17.0'
|
|
414
|
+
\`\`\`
|
|
415
|
+
|
|
416
|
+
### 4. Basic 3D Scene
|
|
417
|
+
|
|
418
|
+
\`\`\`dart
|
|
419
|
+
import 'package:sceneview_flutter/sceneview_flutter.dart';
|
|
420
|
+
|
|
421
|
+
class My3DScreen extends StatelessWidget {
|
|
422
|
+
@override
|
|
423
|
+
Widget build(BuildContext context) {
|
|
424
|
+
return SceneView(
|
|
425
|
+
modelUrl: 'assets/models/chair.glb', // Android: GLB, iOS: USDZ
|
|
426
|
+
environment: 'assets/environments/sky_2k.hdr',
|
|
427
|
+
cameraOrbit: true,
|
|
428
|
+
scaleToUnits: 1.0,
|
|
429
|
+
onModelLoaded: (controller) {
|
|
430
|
+
print('Model loaded');
|
|
431
|
+
},
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
\`\`\`
|
|
436
|
+
|
|
437
|
+
### 5. Platform Differences
|
|
438
|
+
|
|
439
|
+
| Feature | Android | iOS |
|
|
440
|
+
|---------|---------|-----|
|
|
441
|
+
| Renderer | Filament | RealityKit |
|
|
442
|
+
| Model format | GLB/glTF | USDZ/.reality |
|
|
443
|
+
| Environment | HDR | Built-in IBL |`;
|
|
444
|
+
const FLUTTER_AR = `## SceneView Flutter — AR Setup
|
|
445
|
+
|
|
446
|
+
### 1. Dependencies
|
|
447
|
+
|
|
448
|
+
\`\`\`yaml
|
|
449
|
+
dependencies:
|
|
450
|
+
sceneview_flutter: ^3.3.0
|
|
451
|
+
\`\`\`
|
|
452
|
+
|
|
453
|
+
### 2. Android Manifest
|
|
454
|
+
|
|
455
|
+
\`\`\`xml
|
|
456
|
+
<uses-permission android:name="android.permission.CAMERA" />
|
|
457
|
+
<uses-feature android:name="android.hardware.camera.ar" android:required="true" />
|
|
458
|
+
<application>
|
|
459
|
+
<meta-data android:name="com.google.ar.core" android:value="required" />
|
|
460
|
+
</application>
|
|
461
|
+
\`\`\`
|
|
462
|
+
|
|
463
|
+
### 3. iOS Info.plist
|
|
464
|
+
|
|
465
|
+
\`\`\`xml
|
|
466
|
+
<key>NSCameraUsageDescription</key>
|
|
467
|
+
<string>This app uses the camera for augmented reality.</string>
|
|
468
|
+
\`\`\`
|
|
469
|
+
|
|
470
|
+
### 4. Basic AR Scene
|
|
471
|
+
|
|
472
|
+
\`\`\`dart
|
|
473
|
+
import 'package:sceneview_flutter/sceneview_flutter.dart';
|
|
474
|
+
|
|
475
|
+
class MyARScreen extends StatelessWidget {
|
|
476
|
+
@override
|
|
477
|
+
Widget build(BuildContext context) {
|
|
478
|
+
return ARSceneView(
|
|
479
|
+
modelUrl: 'assets/models/robot.glb',
|
|
480
|
+
planeDetection: PlaneDetection.horizontal,
|
|
481
|
+
tapToPlace: true,
|
|
482
|
+
scaleToUnits: 0.5,
|
|
483
|
+
onAnchorCreated: (anchor) {
|
|
484
|
+
print('Object placed at: \${anchor.position}');
|
|
485
|
+
},
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
\`\`\``;
|
|
490
|
+
const REACT_NATIVE_3D = `## SceneView React Native — 3D Setup
|
|
491
|
+
|
|
492
|
+
SceneView React Native uses **Fabric/Turbo** to bridge to native SceneView.
|
|
493
|
+
|
|
494
|
+
### 1. Install
|
|
495
|
+
|
|
496
|
+
\`\`\`bash
|
|
497
|
+
npm install @sceneview/react-native
|
|
498
|
+
cd ios && pod install
|
|
499
|
+
\`\`\`
|
|
500
|
+
|
|
501
|
+
### 2. Android Setup
|
|
502
|
+
|
|
503
|
+
In \`android/app/build.gradle\`:
|
|
504
|
+
\`\`\`groovy
|
|
505
|
+
android {
|
|
506
|
+
defaultConfig {
|
|
507
|
+
minSdkVersion 24
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
\`\`\`
|
|
511
|
+
|
|
512
|
+
### 3. iOS Setup
|
|
513
|
+
|
|
514
|
+
In \`ios/Podfile\`:
|
|
515
|
+
\`\`\`ruby
|
|
516
|
+
platform :ios, '17.0'
|
|
517
|
+
\`\`\`
|
|
518
|
+
|
|
519
|
+
### 4. Basic 3D Scene
|
|
520
|
+
|
|
521
|
+
\`\`\`tsx
|
|
522
|
+
import { SceneView } from '@sceneview/react-native';
|
|
523
|
+
|
|
524
|
+
export default function My3DScreen() {
|
|
525
|
+
return (
|
|
526
|
+
<SceneView
|
|
527
|
+
style={{ flex: 1 }}
|
|
528
|
+
modelUrl={require('./assets/models/chair.glb')}
|
|
529
|
+
environment={require('./assets/environments/sky_2k.hdr')}
|
|
530
|
+
cameraOrbit={true}
|
|
531
|
+
scaleToUnits={1.0}
|
|
532
|
+
onModelLoaded={() => console.log('Model loaded')}
|
|
533
|
+
/>
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
\`\`\`
|
|
537
|
+
|
|
538
|
+
### 5. Platform Differences
|
|
539
|
+
|
|
540
|
+
| Feature | Android | iOS |
|
|
541
|
+
|---------|---------|-----|
|
|
542
|
+
| Renderer | Filament | RealityKit |
|
|
543
|
+
| Model format | GLB/glTF | USDZ/.reality |
|
|
544
|
+
| Bridge | Fabric component | Fabric component |`;
|
|
545
|
+
const REACT_NATIVE_AR = `## SceneView React Native — AR Setup
|
|
546
|
+
|
|
547
|
+
### 1. Install
|
|
548
|
+
|
|
549
|
+
\`\`\`bash
|
|
550
|
+
npm install @sceneview/react-native
|
|
551
|
+
cd ios && pod install
|
|
552
|
+
\`\`\`
|
|
553
|
+
|
|
554
|
+
### 2. Android Permissions
|
|
555
|
+
|
|
556
|
+
Add to \`AndroidManifest.xml\`:
|
|
557
|
+
\`\`\`xml
|
|
558
|
+
<uses-permission android:name="android.permission.CAMERA" />
|
|
559
|
+
<uses-feature android:name="android.hardware.camera.ar" android:required="true" />
|
|
560
|
+
<application>
|
|
561
|
+
<meta-data android:name="com.google.ar.core" android:value="required" />
|
|
562
|
+
</application>
|
|
563
|
+
\`\`\`
|
|
564
|
+
|
|
565
|
+
### 3. iOS Permissions
|
|
566
|
+
|
|
567
|
+
Add to \`Info.plist\`:
|
|
568
|
+
\`\`\`xml
|
|
569
|
+
<key>NSCameraUsageDescription</key>
|
|
570
|
+
<string>This app uses the camera for augmented reality.</string>
|
|
571
|
+
\`\`\`
|
|
572
|
+
|
|
573
|
+
### 4. Basic AR Scene
|
|
574
|
+
|
|
575
|
+
\`\`\`tsx
|
|
576
|
+
import { ARSceneView } from '@sceneview/react-native';
|
|
577
|
+
|
|
578
|
+
export default function MyARScreen() {
|
|
579
|
+
return (
|
|
580
|
+
<ARSceneView
|
|
581
|
+
style={{ flex: 1 }}
|
|
582
|
+
modelUrl={require('./assets/models/robot.glb')}
|
|
583
|
+
planeDetection="horizontal"
|
|
584
|
+
tapToPlace={true}
|
|
585
|
+
scaleToUnits={0.5}
|
|
586
|
+
onAnchorCreated={(anchor) => console.log('Placed:', anchor)}
|
|
587
|
+
/>
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
\`\`\``;
|
|
591
|
+
const DESKTOP_3D = `## SceneView Desktop — Setup
|
|
592
|
+
|
|
593
|
+
SceneView Desktop uses **Compose Desktop** with a software 3D renderer (wireframe). A Filament JNI backend is planned for full PBR rendering.
|
|
594
|
+
|
|
595
|
+
### 1. Gradle Dependencies
|
|
596
|
+
|
|
597
|
+
\`\`\`kotlin
|
|
598
|
+
// build.gradle.kts
|
|
599
|
+
plugins {
|
|
600
|
+
kotlin("jvm")
|
|
601
|
+
id("org.jetbrains.compose")
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
dependencies {
|
|
605
|
+
implementation(compose.desktop.currentOs)
|
|
606
|
+
implementation("io.github.sceneview:sceneview-desktop:3.3.0") // when published
|
|
607
|
+
}
|
|
608
|
+
\`\`\`
|
|
609
|
+
|
|
610
|
+
### 2. Basic Desktop Scene
|
|
611
|
+
|
|
612
|
+
\`\`\`kotlin
|
|
613
|
+
import androidx.compose.ui.window.Window
|
|
614
|
+
import androidx.compose.ui.window.application
|
|
615
|
+
|
|
616
|
+
fun main() = application {
|
|
617
|
+
Window(
|
|
618
|
+
onCloseRequest = ::exitApplication,
|
|
619
|
+
title = "SceneView Desktop"
|
|
620
|
+
) {
|
|
621
|
+
// Current: software wireframe renderer
|
|
622
|
+
DesktopScene(
|
|
623
|
+
modifier = Modifier.fillMaxSize(),
|
|
624
|
+
shapes = listOf(
|
|
625
|
+
WireframeCube(position = Float3(0f, 0f, 0f), size = 1f),
|
|
626
|
+
WireframeSphere(position = Float3(2f, 0f, 0f), radius = 0.5f)
|
|
627
|
+
),
|
|
628
|
+
cameraOrbit = true,
|
|
629
|
+
backgroundColor = Color(0xFF1A1A2E)
|
|
630
|
+
)
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
\`\`\`
|
|
634
|
+
|
|
635
|
+
### 3. Current Status
|
|
636
|
+
|
|
637
|
+
| Feature | Status |
|
|
638
|
+
|---------|--------|
|
|
639
|
+
| Software wireframe renderer | Alpha |
|
|
640
|
+
| Filament JNI (full PBR) | Planned (18-29 day effort) |
|
|
641
|
+
| GLB/glTF loading | Planned (needs Filament JNI) |
|
|
642
|
+
| Windows / macOS / Linux | Alpha |
|
|
643
|
+
|
|
644
|
+
### 4. Limitations
|
|
645
|
+
|
|
646
|
+
- Currently wireframe only (no PBR, no textures)
|
|
647
|
+
- No AR support (desktop has no camera/sensor API)
|
|
648
|
+
- Model loading requires Filament JNI (not yet available)`;
|
|
649
|
+
const TV_3D = `## SceneView Android TV — Setup
|
|
650
|
+
|
|
651
|
+
SceneView on Android TV uses the same Filament renderer as mobile Android, with D-pad navigation support.
|
|
652
|
+
|
|
653
|
+
### 1. Gradle Dependencies
|
|
654
|
+
|
|
655
|
+
\`\`\`kotlin
|
|
656
|
+
dependencies {
|
|
657
|
+
implementation("io.github.sceneview:sceneview:3.3.0")
|
|
658
|
+
implementation("androidx.leanback:leanback:1.0.0")
|
|
659
|
+
implementation("androidx.tv:tv-foundation:1.0.0-alpha10")
|
|
660
|
+
}
|
|
661
|
+
\`\`\`
|
|
662
|
+
|
|
663
|
+
### 2. Manifest
|
|
664
|
+
|
|
665
|
+
\`\`\`xml
|
|
666
|
+
<uses-feature android:name="android.software.leanback" android:required="true" />
|
|
667
|
+
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
|
668
|
+
\`\`\`
|
|
669
|
+
|
|
670
|
+
### 3. Basic TV Scene with D-pad Controls
|
|
671
|
+
|
|
672
|
+
\`\`\`kotlin
|
|
673
|
+
@Composable
|
|
674
|
+
fun TVModelViewer() {
|
|
675
|
+
val engine = rememberEngine()
|
|
676
|
+
val modelLoader = rememberModelLoader(engine)
|
|
677
|
+
var rotation by remember { mutableFloatStateOf(0f) }
|
|
678
|
+
|
|
679
|
+
// D-pad rotation control
|
|
680
|
+
val focusRequester = remember { FocusRequester() }
|
|
681
|
+
LaunchedEffect(Unit) { focusRequester.requestFocus() }
|
|
682
|
+
|
|
683
|
+
Box(
|
|
684
|
+
modifier = Modifier
|
|
685
|
+
.fillMaxSize()
|
|
686
|
+
.focusRequester(focusRequester)
|
|
687
|
+
.focusable()
|
|
688
|
+
.onKeyEvent { event ->
|
|
689
|
+
when (event.key) {
|
|
690
|
+
Key.DirectionLeft -> { rotation -= 15f; true }
|
|
691
|
+
Key.DirectionRight -> { rotation += 15f; true }
|
|
692
|
+
else -> false
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
) {
|
|
696
|
+
Scene(
|
|
697
|
+
modifier = Modifier.fillMaxSize(),
|
|
698
|
+
engine = engine,
|
|
699
|
+
modelLoader = modelLoader
|
|
700
|
+
) {
|
|
701
|
+
rememberModelInstance(modelLoader, "models/car.glb")?.let { instance ->
|
|
702
|
+
ModelNode(
|
|
703
|
+
modelInstance = instance,
|
|
704
|
+
scaleToUnits = 2.0f
|
|
705
|
+
)
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
\`\`\`
|
|
711
|
+
|
|
712
|
+
### 4. TV-Specific Considerations
|
|
713
|
+
|
|
714
|
+
- **No touch** — use D-pad for rotation, Select for actions
|
|
715
|
+
- **10-foot UI** — larger models, simpler scenes, bolder text
|
|
716
|
+
- **No AR** — Android TV has no camera/sensors for AR
|
|
717
|
+
- **Performance** — TV SoCs are weaker than phones; limit to <50K triangles`;
|
|
718
|
+
const SETUPS = {
|
|
719
|
+
android: {
|
|
720
|
+
name: "Android (Jetpack Compose)",
|
|
721
|
+
renderer: "Filament (OpenGL ES / Vulkan)",
|
|
722
|
+
status: "Stable (v3.3.0)",
|
|
723
|
+
guide3d: ANDROID_3D,
|
|
724
|
+
guideAr: ANDROID_AR,
|
|
725
|
+
},
|
|
726
|
+
ios: {
|
|
727
|
+
name: "iOS / macOS / visionOS (SwiftUI)",
|
|
728
|
+
renderer: "RealityKit (Metal)",
|
|
729
|
+
status: "Alpha (v3.3.0)",
|
|
730
|
+
guide3d: IOS_3D,
|
|
731
|
+
guideAr: IOS_AR,
|
|
732
|
+
},
|
|
733
|
+
web: {
|
|
734
|
+
name: "Web (Kotlin/JS + Filament.js)",
|
|
735
|
+
renderer: "Filament.js (WebGL2 / WASM)",
|
|
736
|
+
status: "Alpha",
|
|
737
|
+
guide3d: WEB_3D,
|
|
738
|
+
guideAr: null,
|
|
739
|
+
},
|
|
740
|
+
flutter: {
|
|
741
|
+
name: "Flutter (PlatformView bridge)",
|
|
742
|
+
renderer: "Filament (Android) / RealityKit (iOS)",
|
|
743
|
+
status: "Alpha",
|
|
744
|
+
guide3d: FLUTTER_3D,
|
|
745
|
+
guideAr: FLUTTER_AR,
|
|
746
|
+
},
|
|
747
|
+
"react-native": {
|
|
748
|
+
name: "React Native (Fabric bridge)",
|
|
749
|
+
renderer: "Filament (Android) / RealityKit (iOS)",
|
|
750
|
+
status: "Alpha",
|
|
751
|
+
guide3d: REACT_NATIVE_3D,
|
|
752
|
+
guideAr: REACT_NATIVE_AR,
|
|
753
|
+
},
|
|
754
|
+
desktop: {
|
|
755
|
+
name: "Desktop (Compose Desktop)",
|
|
756
|
+
renderer: "Software wireframe (Filament JNI planned)",
|
|
757
|
+
status: "Alpha",
|
|
758
|
+
guide3d: DESKTOP_3D,
|
|
759
|
+
guideAr: null,
|
|
760
|
+
},
|
|
761
|
+
tv: {
|
|
762
|
+
name: "Android TV",
|
|
763
|
+
renderer: "Filament (OpenGL ES)",
|
|
764
|
+
status: "Alpha",
|
|
765
|
+
guide3d: TV_3D,
|
|
766
|
+
guideAr: null,
|
|
767
|
+
},
|
|
768
|
+
};
|
|
769
|
+
export function getPlatformSetup(platform, type) {
|
|
770
|
+
const setup = SETUPS[platform];
|
|
771
|
+
if (!setup) {
|
|
772
|
+
return `Unknown platform "${platform}". Available: ${PLATFORM_IDS.join(", ")}`;
|
|
773
|
+
}
|
|
774
|
+
if (type === "ar" && !setup.guideAr) {
|
|
775
|
+
return `# ${setup.name}\n\n**Status:** ${setup.status}\n**Renderer:** ${setup.renderer}\n\n> AR is not supported on ${setup.name}. Only 3D scenes are available on this platform.\n\nUse \`get_platform_setup\` with \`type: "3d"\` for 3D setup instructions.`;
|
|
776
|
+
}
|
|
777
|
+
const guide = type === "ar" ? setup.guideAr : setup.guide3d;
|
|
778
|
+
return `# ${setup.name}\n\n**Status:** ${setup.status} | **Renderer:** ${setup.renderer}\n\n${guide}`;
|
|
779
|
+
}
|
|
780
|
+
export function listPlatforms() {
|
|
781
|
+
const header = `## SceneView — Supported Platforms\n\n| Platform | Renderer | Status | 3D | AR |\n|----------|----------|--------|-----|-----|\n`;
|
|
782
|
+
const rows = PLATFORM_IDS.map((id) => {
|
|
783
|
+
const s = SETUPS[id];
|
|
784
|
+
return `| ${s.name} | ${s.renderer} | ${s.status} | Yes | ${s.guideAr ? "Yes" : "No"} |`;
|
|
785
|
+
}).join("\n");
|
|
786
|
+
return header + rows + "\n\nUse `get_platform_setup` with a specific platform for full setup instructions.";
|
|
787
|
+
}
|