sceneview-mcp 3.5.1 → 3.5.2
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 +159 -12
- package/dist/extra-guides.js +539 -0
- package/dist/generate-scene.js +178 -36
- package/dist/guides.js +9 -9
- package/dist/index.js +15 -15
- package/dist/issues.js +132 -1
- package/dist/migrate-code.js +73 -5
- package/dist/migration.js +66 -2
- package/dist/platform-setup.js +49 -19
- package/dist/samples.js +683 -124
- package/dist/validator.js +97 -0
- package/llms.txt +1 -1
- package/package.json +2 -1
package/dist/samples.js
CHANGED
|
@@ -4,8 +4,8 @@ export const SAMPLES = {
|
|
|
4
4
|
title: "3D Model Viewer",
|
|
5
5
|
description: "Full-screen 3D scene with a GLB model, HDR environment, orbit camera, and animation controls",
|
|
6
6
|
tags: ["3d", "model", "environment", "camera", "animation"],
|
|
7
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
8
|
-
prompt: "Create an Android Compose screen that loads a GLB model and displays it with HDR lighting, orbit camera, and animation playback. Use SceneView `io.github.sceneview:sceneview:3.
|
|
7
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
8
|
+
prompt: "Create an Android Compose screen that loads a GLB model and displays it with HDR lighting, orbit camera, and animation playback. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
9
9
|
code: `@Composable
|
|
10
10
|
fun ModelViewerScreen() {
|
|
11
11
|
val engine = rememberEngine()
|
|
@@ -38,8 +38,8 @@ fun ModelViewerScreen() {
|
|
|
38
38
|
title: "AR Tap-to-Place Model Viewer",
|
|
39
39
|
description: "AR scene with plane detection. Tap a surface to place a 3D model with pinch-to-scale and drag-to-rotate gestures.",
|
|
40
40
|
tags: ["ar", "model", "anchor", "plane-detection", "placement", "gestures"],
|
|
41
|
-
dependency: "io.github.sceneview:arsceneview:3.
|
|
42
|
-
prompt: "Create an AR screen that detects surfaces and lets the user tap to place a GLB model. Support pinch-to-scale and drag-to-rotate. Use SceneView `io.github.sceneview:arsceneview:3.
|
|
41
|
+
dependency: "io.github.sceneview:arsceneview:3.4.7",
|
|
42
|
+
prompt: "Create an AR screen that detects surfaces and lets the user tap to place a GLB model. Support pinch-to-scale and drag-to-rotate. Use SceneView `io.github.sceneview:arsceneview:3.4.7`.",
|
|
43
43
|
code: `@Composable
|
|
44
44
|
fun ARModelViewerScreen() {
|
|
45
45
|
val engine = rememberEngine()
|
|
@@ -83,8 +83,8 @@ fun ARModelViewerScreen() {
|
|
|
83
83
|
title: "AR Augmented Image",
|
|
84
84
|
description: "Detects reference images in the camera feed and overlays 3D models or video above them.",
|
|
85
85
|
tags: ["ar", "model", "image-tracking"],
|
|
86
|
-
dependency: "io.github.sceneview:arsceneview:3.
|
|
87
|
-
prompt: "Create an AR screen that detects a printed reference image and places a 3D model above it. Use SceneView `io.github.sceneview:arsceneview:3.
|
|
86
|
+
dependency: "io.github.sceneview:arsceneview:3.4.7",
|
|
87
|
+
prompt: "Create an AR screen that detects a printed reference image and places a 3D model above it. Use SceneView `io.github.sceneview:arsceneview:3.4.7`.",
|
|
88
88
|
code: `@Composable
|
|
89
89
|
fun AugmentedImageScreen() {
|
|
90
90
|
val engine = rememberEngine()
|
|
@@ -125,8 +125,8 @@ fun AugmentedImageScreen() {
|
|
|
125
125
|
title: "AR Cloud Anchor",
|
|
126
126
|
description: "Host and resolve persistent cross-device anchors using ARCore Cloud Anchors.",
|
|
127
127
|
tags: ["ar", "anchor", "cloud-anchor"],
|
|
128
|
-
dependency: "io.github.sceneview:arsceneview:3.
|
|
129
|
-
prompt: "Create an AR screen that can host a cloud anchor (saving its ID) and resolve it later on another device. Use SceneView `io.github.sceneview:arsceneview:3.
|
|
128
|
+
dependency: "io.github.sceneview:arsceneview:3.4.7",
|
|
129
|
+
prompt: "Create an AR screen that can host a cloud anchor (saving its ID) and resolve it later on another device. Use SceneView `io.github.sceneview:arsceneview:3.4.7`.",
|
|
130
130
|
code: `@Composable
|
|
131
131
|
fun CloudAnchorScreen() {
|
|
132
132
|
val engine = rememberEngine()
|
|
@@ -156,8 +156,8 @@ fun CloudAnchorScreen() {
|
|
|
156
156
|
title: "AR Point Cloud",
|
|
157
157
|
description: "Visualizes ARCore feature points as 3D spheres with confidence-based filtering.",
|
|
158
158
|
tags: ["ar", "point-cloud"],
|
|
159
|
-
dependency: "io.github.sceneview:arsceneview:3.
|
|
160
|
-
prompt: "Create an AR screen that visualizes ARCore feature points as small 3D spheres, filtered by confidence. Use SceneView `io.github.sceneview:arsceneview:3.
|
|
159
|
+
dependency: "io.github.sceneview:arsceneview:3.4.7",
|
|
160
|
+
prompt: "Create an AR screen that visualizes ARCore feature points as small 3D spheres, filtered by confidence. Use SceneView `io.github.sceneview:arsceneview:3.4.7`.",
|
|
161
161
|
code: `@Composable
|
|
162
162
|
fun PointCloudScreen() {
|
|
163
163
|
val engine = rememberEngine()
|
|
@@ -188,8 +188,8 @@ fun PointCloudScreen() {
|
|
|
188
188
|
title: "AR Face Mesh",
|
|
189
189
|
description: "AR face tracking with AugmentedFaceNode — applies a textured mesh overlay to detected faces using the front camera.",
|
|
190
190
|
tags: ["ar", "face-tracking", "model"],
|
|
191
|
-
dependency: "io.github.sceneview:arsceneview:3.
|
|
192
|
-
prompt: "Create an AR screen that uses the front camera to detect faces and overlay a 3D mesh on them. Use SceneView `io.github.sceneview:arsceneview:3.
|
|
191
|
+
dependency: "io.github.sceneview:arsceneview:3.4.7",
|
|
192
|
+
prompt: "Create an AR screen that uses the front camera to detect faces and overlay a 3D mesh on them. Use SceneView `io.github.sceneview:arsceneview:3.4.7`.",
|
|
193
193
|
code: `@Composable
|
|
194
194
|
fun ARFaceMeshScreen() {
|
|
195
195
|
val engine = rememberEngine()
|
|
@@ -232,8 +232,8 @@ fun ARFaceMeshScreen() {
|
|
|
232
232
|
title: "glTF Camera",
|
|
233
233
|
description: "Extracts and uses camera definitions embedded in a glTF file for cinematic viewpoints.",
|
|
234
234
|
tags: ["3d", "model", "camera"],
|
|
235
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
236
|
-
prompt: "Create a 3D scene that loads a GLB file containing embedded camera definitions, then uses those cameras for cinematic viewpoints. Use SceneView `io.github.sceneview:sceneview:3.
|
|
235
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
236
|
+
prompt: "Create a 3D scene that loads a GLB file containing embedded camera definitions, then uses those cameras for cinematic viewpoints. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
237
237
|
code: `@Composable
|
|
238
238
|
fun GltfCameraScreen() {
|
|
239
239
|
val engine = rememberEngine()
|
|
@@ -262,8 +262,8 @@ fun GltfCameraScreen() {
|
|
|
262
262
|
title: "Camera Manipulator",
|
|
263
263
|
description: "Orbit, pan, and zoom camera with customizable sensitivity and bounds.",
|
|
264
264
|
tags: ["3d", "camera", "gestures"],
|
|
265
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
266
|
-
prompt: "Create a 3D scene with a fully configurable orbit camera — drag to rotate, two-finger pan, pinch to zoom. Use SceneView `io.github.sceneview:sceneview:3.
|
|
265
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
266
|
+
prompt: "Create a 3D scene with a fully configurable orbit camera — drag to rotate, two-finger pan, pinch to zoom. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
267
267
|
code: `@Composable
|
|
268
268
|
fun CameraManipulatorScreen() {
|
|
269
269
|
val engine = rememberEngine()
|
|
@@ -293,8 +293,8 @@ fun CameraManipulatorScreen() {
|
|
|
293
293
|
title: "Camera Animation",
|
|
294
294
|
description: "Animated camera flythrough around a 3D model — smooth orbit using LaunchedEffect and trigonometric interpolation.",
|
|
295
295
|
tags: ["3d", "camera", "animation", "model"],
|
|
296
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
297
|
-
prompt: "Create a 3D scene with a camera that automatically orbits around a model in a smooth circle. Include a play/pause button. Use SceneView `io.github.sceneview:sceneview:3.
|
|
296
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
297
|
+
prompt: "Create a 3D scene with a camera that automatically orbits around a model in a smooth circle. Include a play/pause button. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
298
298
|
code: `@Composable
|
|
299
299
|
fun CameraAnimationScreen() {
|
|
300
300
|
val engine = rememberEngine()
|
|
@@ -352,108 +352,256 @@ fun CameraAnimationScreen() {
|
|
|
352
352
|
"autopilot-demo": {
|
|
353
353
|
id: "autopilot-demo",
|
|
354
354
|
title: "Autopilot Demo",
|
|
355
|
-
description: "
|
|
355
|
+
description: "Autonomous driving HUD with animated car, road geometry, and real-time telemetry overlay.",
|
|
356
356
|
tags: ["3d", "model", "animation", "geometry"],
|
|
357
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
358
|
-
prompt: "Create
|
|
357
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
358
|
+
prompt: "Create an autopilot-style visualization with a 3D car on a road and a HUD overlay showing speed, distance, and status. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
359
359
|
code: `@Composable
|
|
360
360
|
fun AutopilotScreen() {
|
|
361
361
|
val engine = rememberEngine()
|
|
362
362
|
val modelLoader = rememberModelLoader(engine)
|
|
363
|
+
val materialLoader = rememberMaterialLoader(engine)
|
|
364
|
+
var speed by remember { mutableFloatStateOf(60f) }
|
|
363
365
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
366
|
+
Box(modifier = Modifier.fillMaxSize()) {
|
|
367
|
+
Scene(
|
|
368
|
+
modifier = Modifier.fillMaxSize(),
|
|
369
|
+
engine = engine,
|
|
370
|
+
modelLoader = modelLoader,
|
|
371
|
+
cameraNode = rememberCameraNode(engine) {
|
|
372
|
+
position = Position(x = 0f, y = 2f, z = 5f)
|
|
373
|
+
lookAt(Position(0f, 0f, -2f))
|
|
374
|
+
},
|
|
375
|
+
mainLightNode = rememberMainLightNode(engine) { intensity = 110_000f }
|
|
376
|
+
) {
|
|
377
|
+
// Road surface
|
|
378
|
+
val roadMat = remember(materialLoader) {
|
|
379
|
+
materialLoader.createColorInstance(Color.DarkGray, roughness = 0.95f)
|
|
380
|
+
}
|
|
381
|
+
PlaneNode(size = Size(6f, 50f), materialInstance = roadMat, position = Position(y = -0.01f))
|
|
382
|
+
|
|
383
|
+
// Lane markings (white lines)
|
|
384
|
+
val whiteMat = remember(materialLoader) {
|
|
385
|
+
materialLoader.createColorInstance(Color.White)
|
|
386
|
+
}
|
|
387
|
+
for (z in -20..20 step 4) {
|
|
388
|
+
CubeNode(
|
|
389
|
+
size = Size(0.1f, 0.01f, 2f),
|
|
390
|
+
materialInstance = whiteMat,
|
|
391
|
+
position = Position(x = 0f, y = 0f, z = z.toFloat())
|
|
392
|
+
)
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Ego car
|
|
396
|
+
rememberModelInstance(modelLoader, "models/car.glb")?.let { instance ->
|
|
397
|
+
ModelNode(modelInstance = instance, scaleToUnits = 2f)
|
|
398
|
+
}
|
|
372
399
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
400
|
+
// Traffic light post
|
|
401
|
+
val greenMat = remember(materialLoader) {
|
|
402
|
+
materialLoader.createColorInstance(Color.Green, metallic = 0f, roughness = 0.3f)
|
|
403
|
+
}
|
|
404
|
+
SphereNode(radius = 0.1f, materialInstance = greenMat, position = Position(x = 2f, y = 3f, z = -8f))
|
|
376
405
|
}
|
|
377
406
|
|
|
378
|
-
//
|
|
379
|
-
|
|
407
|
+
// HUD overlay
|
|
408
|
+
Column(
|
|
409
|
+
modifier = Modifier.align(Alignment.TopStart).padding(24.dp)
|
|
410
|
+
.background(Color.Black.copy(alpha = 0.7f), RoundedCornerShape(12.dp))
|
|
411
|
+
.padding(16.dp)
|
|
412
|
+
) {
|
|
413
|
+
Text("\${speed.toInt()} km/h", color = Color.White, fontSize = 32.sp, fontWeight = FontWeight.Bold)
|
|
414
|
+
Text("AUTOPILOT ACTIVE", color = Color.Green, fontSize = 14.sp)
|
|
415
|
+
Spacer(Modifier.height(8.dp))
|
|
416
|
+
Text("Next turn: 2.3 km", color = Color.LightGray, fontSize = 12.sp)
|
|
417
|
+
}
|
|
380
418
|
}
|
|
381
419
|
}`,
|
|
382
420
|
},
|
|
383
421
|
"physics-demo": {
|
|
384
422
|
id: "physics-demo",
|
|
385
|
-
title: "Physics
|
|
386
|
-
description: "
|
|
423
|
+
title: "Physics Simulation",
|
|
424
|
+
description: "Animated physics simulation with spheres falling under gravity and bouncing off a floor, using onFrame for per-frame updates.",
|
|
387
425
|
tags: ["3d", "physics", "geometry", "animation"],
|
|
388
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
389
|
-
prompt: "Create a 3D scene
|
|
426
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
427
|
+
prompt: "Create a 3D scene with spheres that fall under gravity and bounce on a floor using per-frame animation. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
390
428
|
code: `@Composable
|
|
391
429
|
fun PhysicsDemoScreen() {
|
|
392
430
|
val engine = rememberEngine()
|
|
393
431
|
val materialLoader = rememberMaterialLoader(engine)
|
|
432
|
+
val environmentLoader = rememberEnvironmentLoader(engine)
|
|
394
433
|
var restitution by remember { mutableFloatStateOf(0.7f) }
|
|
395
434
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
435
|
+
// Simple physics state: y-positions and velocities for 5 spheres
|
|
436
|
+
data class Ball(var y: Float, var vy: Float, val x: Float, val color: Color)
|
|
437
|
+
val balls = remember {
|
|
438
|
+
mutableStateListOf(
|
|
439
|
+
Ball(3.0f, 0f, -1.0f, Color.Red),
|
|
440
|
+
Ball(4.0f, 0f, -0.5f, Color.Blue),
|
|
441
|
+
Ball(3.5f, 0f, 0.0f, Color.Green),
|
|
442
|
+
Ball(4.5f, 0f, 0.5f, Color.Yellow),
|
|
443
|
+
Ball(5.0f, 0f, 1.0f, Color.Cyan)
|
|
444
|
+
)
|
|
445
|
+
}
|
|
404
446
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
447
|
+
// Per-frame gravity + bounce
|
|
448
|
+
LaunchedEffect(restitution) {
|
|
449
|
+
while (true) {
|
|
450
|
+
withFrameNanos { _ ->
|
|
451
|
+
val dt = 0.016f
|
|
452
|
+
val gravity = -9.8f
|
|
453
|
+
val floorY = 0.15f
|
|
454
|
+
for (ball in balls) {
|
|
455
|
+
ball.vy += gravity * dt
|
|
456
|
+
ball.y += ball.vy * dt
|
|
457
|
+
if (ball.y < floorY) {
|
|
458
|
+
ball.y = floorY
|
|
459
|
+
ball.vy = -ball.vy * restitution
|
|
460
|
+
}
|
|
461
|
+
}
|
|
409
462
|
}
|
|
410
463
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
Column {
|
|
467
|
+
Scene(
|
|
468
|
+
modifier = Modifier.weight(1f).fillMaxWidth(),
|
|
469
|
+
engine = engine,
|
|
470
|
+
cameraManipulator = rememberCameraManipulator(
|
|
471
|
+
orbitHomePosition = Position(x = 0f, y = 3f, z = 6f),
|
|
472
|
+
targetPosition = Position(0f, 1f, 0f)
|
|
473
|
+
),
|
|
474
|
+
environment = rememberEnvironment(environmentLoader) {
|
|
475
|
+
environmentLoader.createHDREnvironment("environments/sky_2k.hdr")
|
|
476
|
+
?: createEnvironment(environmentLoader)
|
|
477
|
+
},
|
|
478
|
+
mainLightNode = rememberMainLightNode(engine) { intensity = 100_000f }
|
|
479
|
+
) {
|
|
480
|
+
// Floor
|
|
481
|
+
val floorMat = remember(materialLoader) {
|
|
482
|
+
materialLoader.createColorInstance(Color.DarkGray, roughness = 0.9f)
|
|
483
|
+
}
|
|
484
|
+
PlaneNode(size = Size(6f, 6f), materialInstance = floorMat)
|
|
485
|
+
|
|
486
|
+
// Bouncing spheres
|
|
487
|
+
for (ball in balls) {
|
|
488
|
+
val mat = remember(materialLoader, ball.color) {
|
|
489
|
+
materialLoader.createColorInstance(ball.color, roughness = 0.4f)
|
|
490
|
+
}
|
|
491
|
+
SphereNode(
|
|
492
|
+
radius = 0.15f,
|
|
493
|
+
materialInstance = mat,
|
|
494
|
+
position = Position(x = ball.x, y = ball.y, z = 0f)
|
|
495
|
+
)
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
// Bounciness slider
|
|
499
|
+
Row(
|
|
500
|
+
modifier = Modifier.fillMaxWidth().padding(16.dp),
|
|
501
|
+
verticalAlignment = Alignment.CenterVertically
|
|
502
|
+
) {
|
|
503
|
+
Text("Bounciness: \${String.format("%.1f", restitution)}")
|
|
504
|
+
Slider(
|
|
505
|
+
value = restitution,
|
|
506
|
+
onValueChange = { restitution = it },
|
|
507
|
+
valueRange = 0f..1f,
|
|
508
|
+
modifier = Modifier.weight(1f).padding(start = 8.dp)
|
|
509
|
+
)
|
|
510
|
+
}
|
|
416
511
|
}
|
|
417
512
|
}`,
|
|
418
513
|
},
|
|
419
514
|
"dynamic-sky": {
|
|
420
515
|
id: "dynamic-sky",
|
|
421
|
-
title: "Dynamic Sky",
|
|
422
|
-
description: "Time-of-day sun cycle with
|
|
423
|
-
tags: ["3d", "sky", "
|
|
424
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
425
|
-
prompt: "Create a 3D scene with a time-of-day sun that moves from sunrise through noon to sunset, with
|
|
516
|
+
title: "Dynamic Sky & Lighting",
|
|
517
|
+
description: "Time-of-day sun cycle with animated LightNode direction, intensity, and color to simulate sunrise through sunset.",
|
|
518
|
+
tags: ["3d", "sky", "environment", "animation", "lighting"],
|
|
519
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
520
|
+
prompt: "Create a 3D scene with a time-of-day sun that moves from sunrise through noon to sunset, with animated light color and intensity. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
426
521
|
code: `@Composable
|
|
427
522
|
fun DynamicSkyScreen() {
|
|
428
523
|
val engine = rememberEngine()
|
|
429
524
|
val modelLoader = rememberModelLoader(engine)
|
|
525
|
+
val materialLoader = rememberMaterialLoader(engine)
|
|
526
|
+
val environmentLoader = rememberEnvironmentLoader(engine)
|
|
430
527
|
var timeOfDay by remember { mutableFloatStateOf(12f) }
|
|
431
528
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
529
|
+
// Compute sun angle and color from time of day
|
|
530
|
+
val sunAngle = remember(timeOfDay) {
|
|
531
|
+
val normalized = (timeOfDay - 6f) / 12f // 6am=0, 18pm=1
|
|
532
|
+
normalized.coerceIn(0f, 1f) * Math.PI.toFloat()
|
|
533
|
+
}
|
|
534
|
+
val sunIntensity = remember(timeOfDay) {
|
|
535
|
+
val noon = 1f - abs(timeOfDay - 12f) / 6f
|
|
536
|
+
(noon.coerceIn(0.1f, 1f) * 110_000f)
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
Column {
|
|
540
|
+
Scene(
|
|
541
|
+
modifier = Modifier.weight(1f).fillMaxWidth(),
|
|
542
|
+
engine = engine,
|
|
543
|
+
modelLoader = modelLoader,
|
|
544
|
+
cameraManipulator = rememberCameraManipulator(
|
|
545
|
+
orbitHomePosition = Position(x = 0f, y = 2f, z = 6f),
|
|
546
|
+
targetPosition = Position(0f, 0f, 0f)
|
|
547
|
+
),
|
|
548
|
+
environment = rememberEnvironment(environmentLoader) {
|
|
549
|
+
environmentLoader.createHDREnvironment("environments/sky_2k.hdr")
|
|
550
|
+
?: createEnvironment(environmentLoader)
|
|
551
|
+
}
|
|
552
|
+
) {
|
|
553
|
+
// Animated sun light — position and color change with time
|
|
554
|
+
LightNode(
|
|
555
|
+
type = LightManager.Type.SUN,
|
|
556
|
+
apply = {
|
|
557
|
+
// Warm at sunrise/sunset, neutral at noon
|
|
558
|
+
val warmth = abs(timeOfDay - 12f) / 6f
|
|
559
|
+
color(1.0f, 1.0f - warmth * 0.3f, 1.0f - warmth * 0.5f)
|
|
560
|
+
intensity(sunIntensity)
|
|
561
|
+
castShadows(true)
|
|
562
|
+
},
|
|
563
|
+
position = Position(
|
|
564
|
+
x = cos(sunAngle) * 5f,
|
|
565
|
+
y = sin(sunAngle) * 5f,
|
|
566
|
+
z = 0f
|
|
567
|
+
)
|
|
568
|
+
)
|
|
442
569
|
|
|
443
|
-
|
|
444
|
-
|
|
570
|
+
// Ground
|
|
571
|
+
val floorMat = remember(materialLoader) {
|
|
572
|
+
materialLoader.createColorInstance(Color(0.3f, 0.5f, 0.2f), roughness = 0.9f)
|
|
573
|
+
}
|
|
574
|
+
PlaneNode(size = Size(20f, 20f), materialInstance = floorMat)
|
|
575
|
+
|
|
576
|
+
// Scene model
|
|
577
|
+
rememberModelInstance(modelLoader, "models/scene.glb")?.let { instance ->
|
|
578
|
+
ModelNode(modelInstance = instance, scaleToUnits = 2f)
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// Time of day slider
|
|
583
|
+
Row(
|
|
584
|
+
modifier = Modifier.fillMaxWidth().padding(16.dp),
|
|
585
|
+
verticalAlignment = Alignment.CenterVertically
|
|
586
|
+
) {
|
|
587
|
+
Text("Time: \${String.format("%02d:%02d", timeOfDay.toInt(), ((timeOfDay % 1) * 60).toInt())}")
|
|
588
|
+
Slider(
|
|
589
|
+
value = timeOfDay,
|
|
590
|
+
onValueChange = { timeOfDay = it },
|
|
591
|
+
valueRange = 5f..19f,
|
|
592
|
+
modifier = Modifier.weight(1f).padding(start = 8.dp)
|
|
593
|
+
)
|
|
445
594
|
}
|
|
446
595
|
}
|
|
447
|
-
// Add a Slider to control timeOfDay from 0 to 24
|
|
448
596
|
}`,
|
|
449
597
|
},
|
|
450
598
|
"line-path": {
|
|
451
599
|
id: "line-path",
|
|
452
600
|
title: "Line & Path",
|
|
453
|
-
description: "Animated 3D line art with sine waves
|
|
601
|
+
description: "Animated 3D line art with sine waves and Lissajous curves using PathNode and LineNode, with parameter sliders.",
|
|
454
602
|
tags: ["3d", "lines", "geometry", "animation"],
|
|
455
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
456
|
-
prompt: "Create a 3D scene that draws animated parametric curves (sine wave, Lissajous) using PathNode with amplitude and frequency sliders. Use SceneView `io.github.sceneview:sceneview:3.
|
|
603
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
604
|
+
prompt: "Create a 3D scene that draws animated parametric curves (sine wave, Lissajous) using PathNode with amplitude and frequency sliders. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
457
605
|
code: `@Composable
|
|
458
606
|
fun LinePathScreen() {
|
|
459
607
|
val engine = rememberEngine()
|
|
@@ -461,51 +609,124 @@ fun LinePathScreen() {
|
|
|
461
609
|
var amplitude by remember { mutableFloatStateOf(1f) }
|
|
462
610
|
var frequency by remember { mutableFloatStateOf(2f) }
|
|
463
611
|
|
|
464
|
-
val
|
|
612
|
+
val sinePoints = remember(amplitude, frequency) {
|
|
465
613
|
(0..200).map { i ->
|
|
466
614
|
val t = i / 200f * Math.PI.toFloat() * 4
|
|
467
615
|
Position(x = t * 0.5f - 3f, y = sin(t * frequency) * amplitude, z = 0f)
|
|
468
616
|
}
|
|
469
617
|
}
|
|
618
|
+
val lissajousPoints = remember(amplitude, frequency) {
|
|
619
|
+
(0..300).map { i ->
|
|
620
|
+
val t = i / 300f * Math.PI.toFloat() * 2
|
|
621
|
+
Position(
|
|
622
|
+
x = sin(t * 3f) * amplitude,
|
|
623
|
+
y = sin(t * frequency) * amplitude,
|
|
624
|
+
z = cos(t * 2f) * 0.5f
|
|
625
|
+
)
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
Column {
|
|
630
|
+
Scene(
|
|
631
|
+
modifier = Modifier.weight(1f).fillMaxWidth(),
|
|
632
|
+
engine = engine,
|
|
633
|
+
cameraManipulator = rememberCameraManipulator(
|
|
634
|
+
orbitHomePosition = Position(x = 0f, y = 1f, z = 5f),
|
|
635
|
+
targetPosition = Position(0f, 0f, 0f)
|
|
636
|
+
)
|
|
637
|
+
) {
|
|
638
|
+
// Sine wave path (cyan)
|
|
639
|
+
val cyanMat = remember(materialLoader) {
|
|
640
|
+
materialLoader.createColorInstance(Color.Cyan)
|
|
641
|
+
}
|
|
642
|
+
PathNode(
|
|
643
|
+
points = sinePoints,
|
|
644
|
+
materialInstance = cyanMat
|
|
645
|
+
)
|
|
646
|
+
|
|
647
|
+
// Lissajous curve (magenta)
|
|
648
|
+
val magentaMat = remember(materialLoader) {
|
|
649
|
+
materialLoader.createColorInstance(Color.Magenta)
|
|
650
|
+
}
|
|
651
|
+
PathNode(
|
|
652
|
+
points = lissajousPoints,
|
|
653
|
+
closed = true,
|
|
654
|
+
materialInstance = magentaMat
|
|
655
|
+
)
|
|
656
|
+
|
|
657
|
+
// Axis lines
|
|
658
|
+
val grayMat = remember(materialLoader) {
|
|
659
|
+
materialLoader.createColorInstance(Color.Gray)
|
|
660
|
+
}
|
|
661
|
+
LineNode(start = Position(-3f, 0f, 0f), end = Position(3f, 0f, 0f), materialInstance = grayMat)
|
|
662
|
+
LineNode(start = Position(0f, -2f, 0f), end = Position(0f, 2f, 0f), materialInstance = grayMat)
|
|
663
|
+
}
|
|
470
664
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
665
|
+
// Parameter sliders
|
|
666
|
+
Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) {
|
|
667
|
+
Text("Amplitude: \${String.format("%.1f", amplitude)}")
|
|
668
|
+
Slider(value = amplitude, onValueChange = { amplitude = it }, valueRange = 0.1f..3f)
|
|
669
|
+
Text("Frequency: \${String.format("%.1f", frequency)}")
|
|
670
|
+
Slider(value = frequency, onValueChange = { frequency = it }, valueRange = 0.5f..5f)
|
|
474
671
|
}
|
|
475
|
-
Node(node = path)
|
|
476
672
|
}
|
|
477
|
-
// Add Sliders for amplitude and frequency
|
|
478
673
|
}`,
|
|
479
674
|
},
|
|
480
675
|
"text-labels": {
|
|
481
676
|
id: "text-labels",
|
|
482
677
|
title: "Text Labels",
|
|
483
|
-
description: "Camera-facing 3D text labels
|
|
678
|
+
description: "Camera-facing 3D text labels using TextNode — floating labels above geometry spheres representing planets.",
|
|
484
679
|
tags: ["3d", "text", "geometry"],
|
|
485
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
486
|
-
prompt: "Create a 3D scene with floating text labels
|
|
680
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
681
|
+
prompt: "Create a 3D scene with floating text labels above colored spheres representing planets. Use TextNode for the labels. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
487
682
|
code: `@Composable
|
|
488
683
|
fun TextLabelsScreen() {
|
|
489
684
|
val engine = rememberEngine()
|
|
490
685
|
val materialLoader = rememberMaterialLoader(engine)
|
|
491
|
-
|
|
686
|
+
val environmentLoader = rememberEnvironmentLoader(engine)
|
|
687
|
+
|
|
688
|
+
data class Planet(val name: String, val color: Color, val x: Float)
|
|
689
|
+
val planets = listOf(
|
|
690
|
+
Planet("Earth", Color.Blue, -1.5f),
|
|
691
|
+
Planet("Mars", Color.Red, 0f),
|
|
692
|
+
Planet("Venus", Color(1f, 0.8f, 0.3f), 1.5f)
|
|
693
|
+
)
|
|
492
694
|
|
|
493
695
|
Scene(
|
|
494
696
|
modifier = Modifier.fillMaxSize(),
|
|
495
697
|
engine = engine,
|
|
496
|
-
|
|
497
|
-
|
|
698
|
+
cameraManipulator = rememberCameraManipulator(
|
|
699
|
+
orbitHomePosition = Position(x = 0f, y = 1.5f, z = 5f),
|
|
700
|
+
targetPosition = Position(0f, 0.5f, 0f)
|
|
701
|
+
),
|
|
702
|
+
environment = rememberEnvironment(environmentLoader) {
|
|
703
|
+
environmentLoader.createHDREnvironment("environments/sky_2k.hdr")
|
|
704
|
+
?: createEnvironment(environmentLoader)
|
|
705
|
+
},
|
|
706
|
+
mainLightNode = rememberMainLightNode(engine) { intensity = 100_000f }
|
|
498
707
|
) {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
708
|
+
for (planet in planets) {
|
|
709
|
+
// Planet sphere
|
|
710
|
+
val mat = remember(materialLoader, planet.color) {
|
|
711
|
+
materialLoader.createColorInstance(planet.color, roughness = 0.6f)
|
|
712
|
+
}
|
|
713
|
+
SphereNode(
|
|
714
|
+
radius = 0.3f,
|
|
715
|
+
materialInstance = mat,
|
|
716
|
+
position = Position(x = planet.x, y = 0.3f, z = 0f)
|
|
717
|
+
)
|
|
718
|
+
|
|
719
|
+
// Text label above the planet
|
|
720
|
+
TextNode(
|
|
721
|
+
text = planet.name,
|
|
722
|
+
fontSize = 48f,
|
|
723
|
+
textColor = android.graphics.Color.WHITE,
|
|
724
|
+
backgroundColor = 0xCC000000.toInt(),
|
|
725
|
+
widthMeters = 0.6f,
|
|
726
|
+
heightMeters = 0.2f,
|
|
727
|
+
position = Position(x = planet.x, y = 0.9f, z = 0f)
|
|
728
|
+
)
|
|
729
|
+
}
|
|
509
730
|
}
|
|
510
731
|
}`,
|
|
511
732
|
},
|
|
@@ -514,8 +735,8 @@ fun TextLabelsScreen() {
|
|
|
514
735
|
title: "Reflection Probe",
|
|
515
736
|
description: "Zone-based IBL overrides with material picker (Chrome, Gold, Copper, Rough) and probe toggle.",
|
|
516
737
|
tags: ["3d", "reflection", "environment", "model"],
|
|
517
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
518
|
-
prompt: "Create a 3D scene with a metallic sphere and a ReflectionProbeNode that overrides the IBL. Add a material picker to switch between Chrome, Gold, Copper, and Rough. Use SceneView `io.github.sceneview:sceneview:3.
|
|
738
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
739
|
+
prompt: "Create a 3D scene with a metallic sphere and a ReflectionProbeNode that overrides the IBL. Add a material picker to switch between Chrome, Gold, Copper, and Rough. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
519
740
|
code: `@Composable
|
|
520
741
|
fun ReflectionProbeScreen() {
|
|
521
742
|
val engine = rememberEngine()
|
|
@@ -550,8 +771,8 @@ fun ReflectionProbeScreen() {
|
|
|
550
771
|
title: "Post-Processing",
|
|
551
772
|
description: "Real-time post-processing effects: bloom, vignette, tone mapping, FXAA, and SSAO controls.",
|
|
552
773
|
tags: ["3d", "post-processing", "environment"],
|
|
553
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
554
|
-
prompt: "Create a 3D scene with interactive post-processing controls for bloom, vignette, tone mapping, FXAA, and SSAO. Use SceneView `io.github.sceneview:sceneview:3.
|
|
774
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
775
|
+
prompt: "Create a 3D scene with interactive post-processing controls for bloom, vignette, tone mapping, FXAA, and SSAO. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
555
776
|
code: `@Composable
|
|
556
777
|
fun PostProcessingScreen() {
|
|
557
778
|
val engine = rememberEngine()
|
|
@@ -578,8 +799,8 @@ fun PostProcessingScreen() {
|
|
|
578
799
|
title: "Video Texture",
|
|
579
800
|
description: "Video playback on a 3D plane using VideoNode with MediaPlayer — supports looping, chroma-key, and auto-sizing.",
|
|
580
801
|
tags: ["3d", "video", "model"],
|
|
581
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
582
|
-
prompt: "Create a 3D scene with a video playing on a floating 3D plane. Include play/pause controls and chroma-key support. Use SceneView `io.github.sceneview:sceneview:3.
|
|
802
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
803
|
+
prompt: "Create a 3D scene with a video playing on a floating 3D plane. Include play/pause controls and chroma-key support. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
583
804
|
code: `@Composable
|
|
584
805
|
fun VideoTextureScreen() {
|
|
585
806
|
val context = LocalContext.current
|
|
@@ -628,8 +849,8 @@ fun VideoTextureScreen() {
|
|
|
628
849
|
title: "Multi-Model Scene",
|
|
629
850
|
description: "Scene with multiple 3D models loaded independently, positioned and scaled to create a complete environment.",
|
|
630
851
|
tags: ["3d", "model", "multi-model", "environment"],
|
|
631
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
632
|
-
prompt: "Create a 3D scene that loads multiple GLB models (a car, a building, and trees) and positions them to form a street scene. Use SceneView `io.github.sceneview:sceneview:3.
|
|
852
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
853
|
+
prompt: "Create a 3D scene that loads multiple GLB models (a car, a building, and trees) and positions them to form a street scene. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
633
854
|
code: `@Composable
|
|
634
855
|
fun MultiModelScreen() {
|
|
635
856
|
val engine = rememberEngine()
|
|
@@ -694,8 +915,8 @@ fun MultiModelScreen() {
|
|
|
694
915
|
title: "Gesture Interaction",
|
|
695
916
|
description: "Full gesture handling — tap to select, double-tap to scale, long-press for info, pinch-to-scale, drag-to-move on editable nodes.",
|
|
696
917
|
tags: ["3d", "gestures", "model"],
|
|
697
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
698
|
-
prompt: "Create a 3D scene with a model that responds to tap (select), double-tap (scale up), long-press (show info), and supports pinch-to-scale and drag-to-move. Use SceneView `io.github.sceneview:sceneview:3.
|
|
918
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
919
|
+
prompt: "Create a 3D scene with a model that responds to tap (select), double-tap (scale up), long-press (show info), and supports pinch-to-scale and drag-to-move. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
699
920
|
code: `@Composable
|
|
700
921
|
fun GestureInteractionScreen() {
|
|
701
922
|
val engine = rememberEngine()
|
|
@@ -758,8 +979,8 @@ fun GestureInteractionScreen() {
|
|
|
758
979
|
title: "Environment & Lighting",
|
|
759
980
|
description: "Complete lighting setup — HDR environment (IBL + skybox), main directional light, point light, and spot light with LightNode.",
|
|
760
981
|
tags: ["3d", "environment", "lighting", "model"],
|
|
761
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
762
|
-
prompt: "Create a 3D scene with full HDR environment lighting (IBL + skybox), a directional sun light, a red point light, and a blue spot light. Use SceneView `io.github.sceneview:sceneview:3.
|
|
982
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
983
|
+
prompt: "Create a 3D scene with full HDR environment lighting (IBL + skybox), a directional sun light, a red point light, and a blue spot light. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
763
984
|
code: `@Composable
|
|
764
985
|
fun EnvironmentLightingScreen() {
|
|
765
986
|
val engine = rememberEngine()
|
|
@@ -827,8 +1048,8 @@ fun EnvironmentLightingScreen() {
|
|
|
827
1048
|
title: "Procedural Geometry",
|
|
828
1049
|
description: "Procedural shapes — CubeNode, SphereNode, CylinderNode, PlaneNode — with PBR materials (metallic, roughness, color).",
|
|
829
1050
|
tags: ["3d", "geometry", "model"],
|
|
830
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
831
|
-
prompt: "Create a 3D scene showing procedural geometry shapes (cube, sphere, cylinder, plane) with different PBR materials. No model files needed. Use SceneView `io.github.sceneview:sceneview:3.
|
|
1051
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
1052
|
+
prompt: "Create a 3D scene showing procedural geometry shapes (cube, sphere, cylinder, plane) with different PBR materials. No model files needed. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
832
1053
|
code: `@Composable
|
|
833
1054
|
fun ProceduralGeometryScreen() {
|
|
834
1055
|
val engine = rememberEngine()
|
|
@@ -907,8 +1128,8 @@ fun ProceduralGeometryScreen() {
|
|
|
907
1128
|
title: "Compose UI in 3D",
|
|
908
1129
|
description: "Embed interactive Jetpack Compose UI (Cards, Buttons, Text) inside 3D space using ViewNode.",
|
|
909
1130
|
tags: ["3d", "compose-ui", "text"],
|
|
910
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
911
|
-
prompt: "Create a 3D scene with interactive Compose UI elements (Card with text and a button) floating in 3D space using ViewNode. Use SceneView `io.github.sceneview:sceneview:3.
|
|
1131
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
1132
|
+
prompt: "Create a 3D scene with interactive Compose UI elements (Card with text and a button) floating in 3D space using ViewNode. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
912
1133
|
code: `@Composable
|
|
913
1134
|
fun ComposeUI3DScreen() {
|
|
914
1135
|
val engine = rememberEngine()
|
|
@@ -957,8 +1178,8 @@ fun ComposeUI3DScreen() {
|
|
|
957
1178
|
title: "Node Hierarchy",
|
|
958
1179
|
description: "Parent-child node relationships — a spinning solar system with planet groups orbiting a central sun.",
|
|
959
1180
|
tags: ["3d", "hierarchy", "geometry", "animation"],
|
|
960
|
-
dependency: "io.github.sceneview:sceneview:3.
|
|
961
|
-
prompt: "Create a 3D solar system where planets orbit a sun using parent-child node hierarchies. Each planet group rotates independently. Use SceneView `io.github.sceneview:sceneview:3.
|
|
1181
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
1182
|
+
prompt: "Create a 3D solar system where planets orbit a sun using parent-child node hierarchies. Each planet group rotates independently. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
962
1183
|
code: `@Composable
|
|
963
1184
|
fun NodeHierarchyScreen() {
|
|
964
1185
|
val engine = rememberEngine()
|
|
@@ -1038,7 +1259,7 @@ fun NodeHierarchyScreen() {
|
|
|
1038
1259
|
title: "iOS 3D Model Viewer",
|
|
1039
1260
|
description: "SwiftUI 3D scene with a USDZ model, IBL environment, orbit camera, and animation playback.",
|
|
1040
1261
|
tags: ["3d", "model", "environment", "camera", "animation", "ios", "swift"],
|
|
1041
|
-
dependency: "https://github.com/sceneview/sceneview — from: \"3.
|
|
1262
|
+
dependency: "https://github.com/sceneview/sceneview — from: \"3.4.7\"",
|
|
1042
1263
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1043
1264
|
prompt: "Create a SwiftUI screen that loads a USDZ model and displays it with IBL lighting, orbit camera, and animation playback. Use SceneViewSwift.",
|
|
1044
1265
|
language: "swift",
|
|
@@ -1077,7 +1298,7 @@ struct ModelViewerScreen: View {
|
|
|
1077
1298
|
title: "iOS AR Tap-to-Place Model Viewer",
|
|
1078
1299
|
description: "AR scene with plane detection. Tap a surface to place a 3D model using ARKit + RealityKit.",
|
|
1079
1300
|
tags: ["ar", "model", "anchor", "plane-detection", "placement", "ios", "swift"],
|
|
1080
|
-
dependency: "https://github.com/sceneview/sceneview — from: \"3.
|
|
1301
|
+
dependency: "https://github.com/sceneview/sceneview — from: \"3.4.7\"",
|
|
1081
1302
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1082
1303
|
prompt: "Create an iOS AR screen that detects surfaces and lets the user tap to place a USDZ model. Use SceneViewSwift.",
|
|
1083
1304
|
language: "swift",
|
|
@@ -1117,7 +1338,7 @@ struct ARModelViewerScreen: View {
|
|
|
1117
1338
|
title: "iOS AR Augmented Image",
|
|
1118
1339
|
description: "Detects reference images in the camera feed and overlays 3D content above them using ARKit.",
|
|
1119
1340
|
tags: ["ar", "model", "image-tracking", "ios", "swift"],
|
|
1120
|
-
dependency: "https://github.com/sceneview/sceneview — from: \"3.
|
|
1341
|
+
dependency: "https://github.com/sceneview/sceneview — from: \"3.4.7\"",
|
|
1121
1342
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1122
1343
|
prompt: "Create an iOS AR screen that detects a printed reference image and places a 3D model above it. Use SceneViewSwift.",
|
|
1123
1344
|
language: "swift",
|
|
@@ -1155,7 +1376,7 @@ struct AugmentedImageScreen: View {
|
|
|
1155
1376
|
title: "iOS Procedural Geometry",
|
|
1156
1377
|
description: "Procedural geometry shapes — cube, sphere, cylinder, cone, and plane — with PBR materials.",
|
|
1157
1378
|
tags: ["3d", "geometry", "ios", "swift"],
|
|
1158
|
-
dependency: "https://github.com/sceneview/sceneview — from: \"3.
|
|
1379
|
+
dependency: "https://github.com/sceneview/sceneview — from: \"3.4.7\"",
|
|
1159
1380
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1160
1381
|
prompt: "Create a SwiftUI scene showing procedural geometry shapes (cube, sphere, cylinder, cone, plane) with different materials. Use SceneViewSwift.",
|
|
1161
1382
|
language: "swift",
|
|
@@ -1209,7 +1430,7 @@ struct GeometryShapesScreen: View {
|
|
|
1209
1430
|
title: "iOS Lighting",
|
|
1210
1431
|
description: "Directional, point, and spot lights with configurable intensity, color, and shadows.",
|
|
1211
1432
|
tags: ["3d", "lighting", "environment", "ios", "swift"],
|
|
1212
|
-
dependency: "https://github.com/sceneview/sceneview — from: \"3.
|
|
1433
|
+
dependency: "https://github.com/sceneview/sceneview — from: \"3.4.7\"",
|
|
1213
1434
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1214
1435
|
prompt: "Create a SwiftUI 3D scene with directional, point, and spot lights illuminating geometry. Use SceneViewSwift.",
|
|
1215
1436
|
language: "swift",
|
|
@@ -1273,7 +1494,7 @@ struct LightingScreen: View {
|
|
|
1273
1494
|
title: "iOS Physics Demo",
|
|
1274
1495
|
description: "Interactive physics simulation with bouncing spheres, gravity, and configurable restitution.",
|
|
1275
1496
|
tags: ["3d", "physics", "geometry", "ios", "swift"],
|
|
1276
|
-
dependency: "https://github.com/sceneview/sceneview — from: \"3.
|
|
1497
|
+
dependency: "https://github.com/sceneview/sceneview — from: \"3.4.7\"",
|
|
1277
1498
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1278
1499
|
prompt: "Create a SwiftUI 3D scene where tapping spawns coloured spheres that fall under gravity and bounce off a floor. Use SceneViewSwift.",
|
|
1279
1500
|
language: "swift",
|
|
@@ -1337,7 +1558,7 @@ struct PhysicsDemoScreen: View {
|
|
|
1337
1558
|
title: "iOS 3D Text Labels",
|
|
1338
1559
|
description: "Camera-facing 3D text labels using TextNode and BillboardNode for always-facing-camera behavior.",
|
|
1339
1560
|
tags: ["3d", "text", "geometry", "ios", "swift"],
|
|
1340
|
-
dependency: "https://github.com/sceneview/sceneview — from: \"3.
|
|
1561
|
+
dependency: "https://github.com/sceneview/sceneview — from: \"3.4.7\"",
|
|
1341
1562
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1342
1563
|
prompt: "Create a SwiftUI 3D scene with floating text labels that always face the camera, showing planet names. Use SceneViewSwift.",
|
|
1343
1564
|
language: "swift",
|
|
@@ -1385,7 +1606,7 @@ struct TextLabelsScreen: View {
|
|
|
1385
1606
|
title: "iOS Video on 3D Surface",
|
|
1386
1607
|
description: "Video playback on a 3D plane using VideoNode with play/pause controls.",
|
|
1387
1608
|
tags: ["3d", "video", "ios", "swift"],
|
|
1388
|
-
dependency: "https://github.com/sceneview/sceneview — from: \"3.
|
|
1609
|
+
dependency: "https://github.com/sceneview/sceneview — from: \"3.4.7\"",
|
|
1389
1610
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1390
1611
|
prompt: "Create a SwiftUI 3D scene with a video playing on a floating 3D plane. Include play/pause controls. Use SceneViewSwift.",
|
|
1391
1612
|
language: "swift",
|
|
@@ -1448,6 +1669,344 @@ struct VideoPlayerScreen: View {
|
|
|
1448
1669
|
}
|
|
1449
1670
|
}
|
|
1450
1671
|
}
|
|
1672
|
+
}`,
|
|
1673
|
+
},
|
|
1674
|
+
// ─── New Android Samples ──────────────────────────────────────────────
|
|
1675
|
+
"image-node": {
|
|
1676
|
+
id: "image-node",
|
|
1677
|
+
title: "Image Node",
|
|
1678
|
+
description: "Display images on 3D planes using ImageNode — from assets, resources, or Bitmaps.",
|
|
1679
|
+
tags: ["3d", "image", "geometry"],
|
|
1680
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
1681
|
+
prompt: "Create a 3D scene with images displayed on floating planes using ImageNode. Show examples from file, resource, and Bitmap. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
1682
|
+
code: `@Composable
|
|
1683
|
+
fun ImageNodeScreen() {
|
|
1684
|
+
val engine = rememberEngine()
|
|
1685
|
+
val environmentLoader = rememberEnvironmentLoader(engine)
|
|
1686
|
+
|
|
1687
|
+
Scene(
|
|
1688
|
+
modifier = Modifier.fillMaxSize(),
|
|
1689
|
+
engine = engine,
|
|
1690
|
+
cameraManipulator = rememberCameraManipulator(
|
|
1691
|
+
orbitHomePosition = Position(x = 0f, y = 1f, z = 4f),
|
|
1692
|
+
targetPosition = Position(0f, 0.5f, 0f)
|
|
1693
|
+
),
|
|
1694
|
+
environment = rememberEnvironment(environmentLoader) {
|
|
1695
|
+
environmentLoader.createHDREnvironment("environments/sky_2k.hdr")
|
|
1696
|
+
?: createEnvironment(environmentLoader)
|
|
1697
|
+
},
|
|
1698
|
+
mainLightNode = rememberMainLightNode(engine) { intensity = 100_000f }
|
|
1699
|
+
) {
|
|
1700
|
+
// Image from assets file
|
|
1701
|
+
ImageNode(
|
|
1702
|
+
imageFileLocation = "images/logo.png",
|
|
1703
|
+
size = Size(1f, 1f),
|
|
1704
|
+
position = Position(x = -1.2f, y = 0.5f, z = 0f)
|
|
1705
|
+
)
|
|
1706
|
+
|
|
1707
|
+
// Image from drawable resource
|
|
1708
|
+
ImageNode(
|
|
1709
|
+
imageResId = R.drawable.my_image,
|
|
1710
|
+
position = Position(x = 0f, y = 0.5f, z = 0f)
|
|
1711
|
+
)
|
|
1712
|
+
|
|
1713
|
+
// Image from Bitmap (e.g., dynamically generated)
|
|
1714
|
+
val bitmap = remember {
|
|
1715
|
+
Bitmap.createBitmap(256, 256, Bitmap.Config.ARGB_8888).apply {
|
|
1716
|
+
val canvas = android.graphics.Canvas(this)
|
|
1717
|
+
canvas.drawColor(android.graphics.Color.WHITE)
|
|
1718
|
+
val paint = Paint().apply {
|
|
1719
|
+
color = android.graphics.Color.BLUE
|
|
1720
|
+
textSize = 48f
|
|
1721
|
+
textAlign = Paint.Align.CENTER
|
|
1722
|
+
}
|
|
1723
|
+
canvas.drawText("SceneView", 128f, 140f, paint)
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
ImageNode(
|
|
1727
|
+
bitmap = bitmap,
|
|
1728
|
+
size = Size(1f, 1f),
|
|
1729
|
+
position = Position(x = 1.2f, y = 0.5f, z = 0f)
|
|
1730
|
+
)
|
|
1731
|
+
}
|
|
1732
|
+
}`,
|
|
1733
|
+
},
|
|
1734
|
+
"billboard-sprite": {
|
|
1735
|
+
id: "billboard-sprite",
|
|
1736
|
+
title: "Billboard Sprite",
|
|
1737
|
+
description: "Always-facing-camera sprites using BillboardNode — useful for markers, icons, and info overlays in 3D space.",
|
|
1738
|
+
tags: ["3d", "billboard", "image"],
|
|
1739
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
1740
|
+
prompt: "Create a 3D scene with billboard sprites that always face the camera, useful for markers and info overlays. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
1741
|
+
code: `@Composable
|
|
1742
|
+
fun BillboardSpriteScreen() {
|
|
1743
|
+
val engine = rememberEngine()
|
|
1744
|
+
val modelLoader = rememberModelLoader(engine)
|
|
1745
|
+
val materialLoader = rememberMaterialLoader(engine)
|
|
1746
|
+
val environmentLoader = rememberEnvironmentLoader(engine)
|
|
1747
|
+
val context = LocalContext.current
|
|
1748
|
+
|
|
1749
|
+
// Create marker bitmaps
|
|
1750
|
+
val markerBitmap = remember {
|
|
1751
|
+
Bitmap.createBitmap(64, 64, Bitmap.Config.ARGB_8888).apply {
|
|
1752
|
+
val canvas = android.graphics.Canvas(this)
|
|
1753
|
+
val paint = Paint(Paint.ANTI_ALIAS_FLAG)
|
|
1754
|
+
paint.color = android.graphics.Color.RED
|
|
1755
|
+
canvas.drawCircle(32f, 32f, 28f, paint)
|
|
1756
|
+
paint.color = android.graphics.Color.WHITE
|
|
1757
|
+
paint.textSize = 32f
|
|
1758
|
+
paint.textAlign = Paint.Align.CENTER
|
|
1759
|
+
canvas.drawText("!", 32f, 44f, paint)
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
Scene(
|
|
1764
|
+
modifier = Modifier.fillMaxSize(),
|
|
1765
|
+
engine = engine,
|
|
1766
|
+
modelLoader = modelLoader,
|
|
1767
|
+
cameraManipulator = rememberCameraManipulator(
|
|
1768
|
+
orbitHomePosition = Position(x = 0f, y = 2f, z = 5f),
|
|
1769
|
+
targetPosition = Position(0f, 0.5f, 0f)
|
|
1770
|
+
),
|
|
1771
|
+
environment = rememberEnvironment(environmentLoader) {
|
|
1772
|
+
environmentLoader.createHDREnvironment("environments/sky_2k.hdr")
|
|
1773
|
+
?: createEnvironment(environmentLoader)
|
|
1774
|
+
},
|
|
1775
|
+
mainLightNode = rememberMainLightNode(engine) { intensity = 100_000f }
|
|
1776
|
+
) {
|
|
1777
|
+
// A model with billboard markers above it
|
|
1778
|
+
rememberModelInstance(modelLoader, "models/damaged_helmet.glb")?.let { instance ->
|
|
1779
|
+
ModelNode(modelInstance = instance, scaleToUnits = 1.0f)
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
// Billboard markers that always face the camera
|
|
1783
|
+
BillboardNode(
|
|
1784
|
+
bitmap = markerBitmap,
|
|
1785
|
+
widthMeters = 0.3f,
|
|
1786
|
+
heightMeters = 0.3f,
|
|
1787
|
+
position = Position(x = 0.5f, y = 1.2f, z = 0f)
|
|
1788
|
+
)
|
|
1789
|
+
|
|
1790
|
+
BillboardNode(
|
|
1791
|
+
bitmap = markerBitmap,
|
|
1792
|
+
widthMeters = 0.3f,
|
|
1793
|
+
heightMeters = 0.3f,
|
|
1794
|
+
position = Position(x = -0.5f, y = 0.8f, z = 0.3f)
|
|
1795
|
+
)
|
|
1796
|
+
}
|
|
1797
|
+
}`,
|
|
1798
|
+
},
|
|
1799
|
+
"animation-state": {
|
|
1800
|
+
id: "animation-state",
|
|
1801
|
+
title: "Animation State Machine",
|
|
1802
|
+
description: "Reactive animation driven by Compose state — switch between Idle, Walk, and Run animations on a character model.",
|
|
1803
|
+
tags: ["3d", "model", "animation"],
|
|
1804
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
1805
|
+
prompt: "Create a 3D scene with a character model that switches between Idle, Walk, and Run animations based on button clicks. Use animationName for state-driven animation. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
1806
|
+
code: `@Composable
|
|
1807
|
+
fun AnimationStateScreen() {
|
|
1808
|
+
val engine = rememberEngine()
|
|
1809
|
+
val modelLoader = rememberModelLoader(engine)
|
|
1810
|
+
val environmentLoader = rememberEnvironmentLoader(engine)
|
|
1811
|
+
var currentAnim by remember { mutableStateOf("Idle") }
|
|
1812
|
+
|
|
1813
|
+
Column {
|
|
1814
|
+
Scene(
|
|
1815
|
+
modifier = Modifier.weight(1f).fillMaxWidth(),
|
|
1816
|
+
engine = engine,
|
|
1817
|
+
modelLoader = modelLoader,
|
|
1818
|
+
cameraManipulator = rememberCameraManipulator(
|
|
1819
|
+
orbitHomePosition = Position(x = 0f, y = 1f, z = 3f),
|
|
1820
|
+
targetPosition = Position(0f, 0.8f, 0f)
|
|
1821
|
+
),
|
|
1822
|
+
environment = rememberEnvironment(environmentLoader) {
|
|
1823
|
+
environmentLoader.createHDREnvironment("environments/sky_2k.hdr")
|
|
1824
|
+
?: createEnvironment(environmentLoader)
|
|
1825
|
+
},
|
|
1826
|
+
mainLightNode = rememberMainLightNode(engine) { intensity = 100_000f }
|
|
1827
|
+
) {
|
|
1828
|
+
rememberModelInstance(modelLoader, "models/character.glb")?.let { instance ->
|
|
1829
|
+
ModelNode(
|
|
1830
|
+
modelInstance = instance,
|
|
1831
|
+
scaleToUnits = 1.5f,
|
|
1832
|
+
centerOrigin = Position(y = -1f),
|
|
1833
|
+
autoAnimate = false,
|
|
1834
|
+
animationName = currentAnim,
|
|
1835
|
+
animationLoop = true,
|
|
1836
|
+
animationSpeed = if (currentAnim == "Run") 1.5f else 1f
|
|
1837
|
+
)
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
// Animation controls
|
|
1842
|
+
Row(
|
|
1843
|
+
modifier = Modifier.fillMaxWidth().padding(16.dp),
|
|
1844
|
+
horizontalArrangement = Arrangement.SpaceEvenly
|
|
1845
|
+
) {
|
|
1846
|
+
listOf("Idle", "Walk", "Run").forEach { anim ->
|
|
1847
|
+
Button(
|
|
1848
|
+
onClick = { currentAnim = anim },
|
|
1849
|
+
colors = ButtonDefaults.buttonColors(
|
|
1850
|
+
containerColor = if (currentAnim == anim)
|
|
1851
|
+
MaterialTheme.colorScheme.primary
|
|
1852
|
+
else
|
|
1853
|
+
MaterialTheme.colorScheme.surfaceVariant
|
|
1854
|
+
)
|
|
1855
|
+
) {
|
|
1856
|
+
Text(anim)
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
}`,
|
|
1862
|
+
},
|
|
1863
|
+
"spring-animation": {
|
|
1864
|
+
id: "spring-animation",
|
|
1865
|
+
title: "Spring Animation",
|
|
1866
|
+
description: "Smooth spring-based node animations using Compose animateFloatAsState with spring spec for natural motion.",
|
|
1867
|
+
tags: ["3d", "animation", "spring", "geometry"],
|
|
1868
|
+
dependency: "io.github.sceneview:sceneview:3.4.7",
|
|
1869
|
+
prompt: "Create a 3D scene with geometry nodes that animate position using spring physics via Compose's animateFloatAsState. Tap to toggle positions with springy motion. Use SceneView `io.github.sceneview:sceneview:3.4.7`.",
|
|
1870
|
+
code: `@Composable
|
|
1871
|
+
fun SpringAnimationScreen() {
|
|
1872
|
+
val engine = rememberEngine()
|
|
1873
|
+
val materialLoader = rememberMaterialLoader(engine)
|
|
1874
|
+
val environmentLoader = rememberEnvironmentLoader(engine)
|
|
1875
|
+
var expanded by remember { mutableStateOf(false) }
|
|
1876
|
+
|
|
1877
|
+
// Spring-animated positions
|
|
1878
|
+
val cubeX by animateFloatAsState(
|
|
1879
|
+
targetValue = if (expanded) -2f else -0.5f,
|
|
1880
|
+
animationSpec = spring(dampingRatio = 0.4f, stiffness = 200f)
|
|
1881
|
+
)
|
|
1882
|
+
val sphereY by animateFloatAsState(
|
|
1883
|
+
targetValue = if (expanded) 2f else 0.5f,
|
|
1884
|
+
animationSpec = spring(dampingRatio = 0.3f, stiffness = 150f)
|
|
1885
|
+
)
|
|
1886
|
+
val cylinderX by animateFloatAsState(
|
|
1887
|
+
targetValue = if (expanded) 2f else 0.5f,
|
|
1888
|
+
animationSpec = spring(dampingRatio = 0.5f, stiffness = 300f)
|
|
1889
|
+
)
|
|
1890
|
+
val uniformScale by animateFloatAsState(
|
|
1891
|
+
targetValue = if (expanded) 1.5f else 1f,
|
|
1892
|
+
animationSpec = spring(dampingRatio = 0.6f, stiffness = 250f)
|
|
1893
|
+
)
|
|
1894
|
+
|
|
1895
|
+
Column {
|
|
1896
|
+
Scene(
|
|
1897
|
+
modifier = Modifier.weight(1f).fillMaxWidth(),
|
|
1898
|
+
engine = engine,
|
|
1899
|
+
cameraManipulator = rememberCameraManipulator(
|
|
1900
|
+
orbitHomePosition = Position(x = 0f, y = 2f, z = 6f),
|
|
1901
|
+
targetPosition = Position(0f, 0.5f, 0f)
|
|
1902
|
+
),
|
|
1903
|
+
environment = rememberEnvironment(environmentLoader) {
|
|
1904
|
+
environmentLoader.createHDREnvironment("environments/sky_2k.hdr")
|
|
1905
|
+
?: createEnvironment(environmentLoader)
|
|
1906
|
+
},
|
|
1907
|
+
mainLightNode = rememberMainLightNode(engine) { intensity = 100_000f }
|
|
1908
|
+
) {
|
|
1909
|
+
// Floor
|
|
1910
|
+
val floorMat = remember(materialLoader) {
|
|
1911
|
+
materialLoader.createColorInstance(Color.DarkGray, roughness = 0.9f)
|
|
1912
|
+
}
|
|
1913
|
+
PlaneNode(size = Size(8f, 8f), materialInstance = floorMat)
|
|
1914
|
+
|
|
1915
|
+
// Spring-animated cube
|
|
1916
|
+
val redMat = remember(materialLoader) {
|
|
1917
|
+
materialLoader.createColorInstance(Color.Red, metallic = 0.2f, roughness = 0.4f)
|
|
1918
|
+
}
|
|
1919
|
+
CubeNode(
|
|
1920
|
+
size = Size(0.4f * uniformScale),
|
|
1921
|
+
materialInstance = redMat,
|
|
1922
|
+
position = Position(x = cubeX, y = 0.3f * uniformScale, z = 0f)
|
|
1923
|
+
)
|
|
1924
|
+
|
|
1925
|
+
// Spring-animated sphere
|
|
1926
|
+
val blueMat = remember(materialLoader) {
|
|
1927
|
+
materialLoader.createColorInstance(Color.Blue, metallic = 0.8f, roughness = 0.1f)
|
|
1928
|
+
}
|
|
1929
|
+
SphereNode(
|
|
1930
|
+
radius = 0.3f * uniformScale,
|
|
1931
|
+
materialInstance = blueMat,
|
|
1932
|
+
position = Position(x = 0f, y = sphereY, z = 0f)
|
|
1933
|
+
)
|
|
1934
|
+
|
|
1935
|
+
// Spring-animated cylinder
|
|
1936
|
+
val greenMat = remember(materialLoader) {
|
|
1937
|
+
materialLoader.createColorInstance(Color.Green, metallic = 0.3f, roughness = 0.5f)
|
|
1938
|
+
}
|
|
1939
|
+
CylinderNode(
|
|
1940
|
+
radius = 0.2f * uniformScale,
|
|
1941
|
+
height = 0.6f * uniformScale,
|
|
1942
|
+
materialInstance = greenMat,
|
|
1943
|
+
position = Position(x = cylinderX, y = 0.3f * uniformScale, z = 0f)
|
|
1944
|
+
)
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
Button(
|
|
1948
|
+
onClick = { expanded = !expanded },
|
|
1949
|
+
modifier = Modifier.align(Alignment.CenterHorizontally).padding(16.dp)
|
|
1950
|
+
) {
|
|
1951
|
+
Text(if (expanded) "Contract" else "Expand")
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
}`,
|
|
1955
|
+
},
|
|
1956
|
+
"ar-surface-cursor": {
|
|
1957
|
+
id: "ar-surface-cursor",
|
|
1958
|
+
title: "AR Surface Cursor",
|
|
1959
|
+
description: "AR scene with a center-screen reticle using HitResultNode that follows the detected surface.",
|
|
1960
|
+
tags: ["ar", "cursor", "plane-detection", "placement"],
|
|
1961
|
+
dependency: "io.github.sceneview:arsceneview:3.4.7",
|
|
1962
|
+
prompt: "Create an AR screen with a surface cursor (reticle) in the center of the screen that follows detected surfaces, using HitResultNode. Tap to place a model at the cursor position. Use SceneView `io.github.sceneview:arsceneview:3.4.7`.",
|
|
1963
|
+
code: `@Composable
|
|
1964
|
+
fun ARSurfaceCursorScreen() {
|
|
1965
|
+
val engine = rememberEngine()
|
|
1966
|
+
val modelLoader = rememberModelLoader(engine)
|
|
1967
|
+
val materialLoader = rememberMaterialLoader(engine)
|
|
1968
|
+
val view = LocalView.current
|
|
1969
|
+
val modelInstance = rememberModelInstance(modelLoader, "models/chair.glb")
|
|
1970
|
+
var placedAnchors by remember { mutableStateOf(listOf<Anchor>()) }
|
|
1971
|
+
|
|
1972
|
+
ARScene(
|
|
1973
|
+
modifier = Modifier.fillMaxSize(),
|
|
1974
|
+
engine = engine,
|
|
1975
|
+
modelLoader = modelLoader,
|
|
1976
|
+
planeRenderer = true,
|
|
1977
|
+
sessionConfiguration = { session, config ->
|
|
1978
|
+
config.depthMode = if (session.isDepthModeSupported(Config.DepthMode.AUTOMATIC))
|
|
1979
|
+
Config.DepthMode.AUTOMATIC else Config.DepthMode.DISABLED
|
|
1980
|
+
config.lightEstimationMode = Config.LightEstimationMode.ENVIRONMENTAL_HDR
|
|
1981
|
+
},
|
|
1982
|
+
onTouchEvent = { event, hitResult ->
|
|
1983
|
+
if (event.action == MotionEvent.ACTION_UP && hitResult != null) {
|
|
1984
|
+
placedAnchors = placedAnchors + hitResult.createAnchor()
|
|
1985
|
+
}
|
|
1986
|
+
true
|
|
1987
|
+
}
|
|
1988
|
+
) {
|
|
1989
|
+
// Surface cursor — follows the center of the screen
|
|
1990
|
+
val cursorMat = remember(materialLoader) {
|
|
1991
|
+
materialLoader.createColorInstance(Color.White.copy(alpha = 0.6f))
|
|
1992
|
+
}
|
|
1993
|
+
HitResultNode(xPx = view.width / 2f, yPx = view.height / 2f) {
|
|
1994
|
+
CylinderNode(radius = 0.03f, height = 0.005f, materialInstance = cursorMat)
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
// Placed models
|
|
1998
|
+
for (anchor in placedAnchors) {
|
|
1999
|
+
AnchorNode(anchor = anchor) {
|
|
2000
|
+
modelInstance?.let { instance ->
|
|
2001
|
+
ModelNode(
|
|
2002
|
+
modelInstance = instance,
|
|
2003
|
+
scaleToUnits = 0.5f,
|
|
2004
|
+
isEditable = true
|
|
2005
|
+
)
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
1451
2010
|
}`,
|
|
1452
2011
|
},
|
|
1453
2012
|
// ── Web Samples (Kotlin/JS + Filament.js) ──────────────────────────────
|