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/debug-issue.js
CHANGED
|
@@ -14,6 +14,8 @@ export const DEBUG_CATEGORIES = [
|
|
|
14
14
|
"lighting",
|
|
15
15
|
"gestures",
|
|
16
16
|
"ios",
|
|
17
|
+
"material",
|
|
18
|
+
"animation",
|
|
17
19
|
];
|
|
18
20
|
const DEBUG_GUIDES = {
|
|
19
21
|
"model-not-showing": {
|
|
@@ -199,6 +201,15 @@ fun DebugModelViewer() {
|
|
|
199
201
|
- Large models (>100K triangles) on old devices → reduce poly count.
|
|
200
202
|
- Multiple 4K HDR environments → use 2K or smaller.
|
|
201
203
|
|
|
204
|
+
### Threading Crashes (most common)
|
|
205
|
+
|
|
206
|
+
| Symptom | Cause | Fix |
|
|
207
|
+
|---------|-------|-----|
|
|
208
|
+
| SIGABRT on model load | \`modelLoader.createModel*\` on IO thread | Use \`rememberModelInstance\` or wrap in \`Dispatchers.Main\` |
|
|
209
|
+
| SIGABRT on texture create | \`Texture.Builder\` on background thread | Move to main thread |
|
|
210
|
+
| SIGABRT on material load | \`materialLoader.*\` on coroutine | Use \`Dispatchers.Main\` |
|
|
211
|
+
| Crash in LaunchedEffect | Filament call inside \`launch(Dispatchers.IO)\` | Remove the dispatcher or use \`Dispatchers.Main\` |
|
|
212
|
+
|
|
202
213
|
### Diagnostic Steps
|
|
203
214
|
|
|
204
215
|
1. Enable Filament debug logging:
|
|
@@ -212,7 +223,17 @@ fun DebugModelViewer() {
|
|
|
212
223
|
adb logcat -s Filament
|
|
213
224
|
\`\`\`
|
|
214
225
|
|
|
215
|
-
3.
|
|
226
|
+
3. Check for threading violations:
|
|
227
|
+
\`\`\`
|
|
228
|
+
adb logcat | grep -i "wrong thread\\|filament\\|SIGABRT"
|
|
229
|
+
\`\`\`
|
|
230
|
+
|
|
231
|
+
4. Run with Android Studio memory profiler to detect leaks.
|
|
232
|
+
|
|
233
|
+
5. Common stack traces and what they mean:
|
|
234
|
+
- \`Filament::FEngine::assertThread\` → wrong thread (not main)
|
|
235
|
+
- \`Filament::FTexture::terminate\` → texture destroyed while material still using it
|
|
236
|
+
- \`Filament::FEngine::terminate\` → engine double-destroyed or destroyed before children`,
|
|
216
237
|
},
|
|
217
238
|
performance: {
|
|
218
239
|
title: "Performance Problems",
|
|
@@ -273,7 +294,7 @@ fun DebugModelViewer() {
|
|
|
273
294
|
title: "Build / Gradle Errors",
|
|
274
295
|
guide: `## Debugging: Build Errors
|
|
275
296
|
|
|
276
|
-
### "Cannot resolve io.github.sceneview:sceneview:3.
|
|
297
|
+
### "Cannot resolve io.github.sceneview:sceneview:3.4.7"
|
|
277
298
|
|
|
278
299
|
1. Check repositories in \`settings.gradle.kts\`:
|
|
279
300
|
\`\`\`kotlin
|
|
@@ -316,7 +337,7 @@ SceneView bundles Filament. If you also depend on Filament directly:
|
|
|
316
337
|
\`\`\`kotlin
|
|
317
338
|
// Remove direct Filament dependency — SceneView includes it
|
|
318
339
|
// implementation("com.google.android.filament:filament-android:1.x.x") // REMOVE
|
|
319
|
-
implementation("io.github.sceneview:sceneview:3.
|
|
340
|
+
implementation("io.github.sceneview:sceneview:3.4.7") // This includes Filament
|
|
320
341
|
\`\`\`
|
|
321
342
|
|
|
322
343
|
### "Cannot find Filament material"
|
|
@@ -510,6 +531,122 @@ Scene(
|
|
|
510
531
|
- Always load models in \`.task { }\` (inherits @MainActor) or annotate functions with \`@MainActor\`.
|
|
511
532
|
- SceneViewSwift nodes are \`@unchecked Sendable\` — the warning is expected.`,
|
|
512
533
|
},
|
|
534
|
+
material: {
|
|
535
|
+
title: "Material / Texture Issues",
|
|
536
|
+
guide: `## Debugging: Material / Texture Issues
|
|
537
|
+
|
|
538
|
+
### Model Appears White or Untextured
|
|
539
|
+
|
|
540
|
+
1. **Missing textures in GLB** — the GLB file may reference external textures.
|
|
541
|
+
- Use \`.glb\` (binary) not \`.gltf\` (multi-file) to bundle textures.
|
|
542
|
+
- Validate in https://gltf-viewer.donmccurdy.com/
|
|
543
|
+
|
|
544
|
+
2. **Material compatibility** — SceneView uses Filament 1.70.0+ materials.
|
|
545
|
+
- Filament only supports metallic-roughness PBR (not spec-gloss).
|
|
546
|
+
- Convert spec-gloss models in Blender before export.
|
|
547
|
+
|
|
548
|
+
3. **Custom material files (.filamat)** — must match your Filament version.
|
|
549
|
+
- Recompile \`.mat\` files with matching \`matc\` version.
|
|
550
|
+
- Pre-compiled materials in \`src/main/assets/materials/\`.
|
|
551
|
+
|
|
552
|
+
### Material Loading Crashes
|
|
553
|
+
|
|
554
|
+
1. **Wrong thread** — \`materialLoader.createMaterial()\` must run on the main thread.
|
|
555
|
+
\`\`\`kotlin
|
|
556
|
+
// WRONG — crashes
|
|
557
|
+
launch(Dispatchers.IO) { materialLoader.createMaterial(...) }
|
|
558
|
+
|
|
559
|
+
// CORRECT
|
|
560
|
+
val material = rememberMaterial(materialLoader) { ... }
|
|
561
|
+
\`\`\`
|
|
562
|
+
|
|
563
|
+
2. **Destroy order** — materials must be destroyed BEFORE textures.
|
|
564
|
+
\`\`\`kotlin
|
|
565
|
+
// CORRECT order
|
|
566
|
+
materialLoader.destroyMaterialInstance(instance)
|
|
567
|
+
engine.safeDestroyTexture(texture)
|
|
568
|
+
\`\`\`
|
|
569
|
+
|
|
570
|
+
### Transparent Materials
|
|
571
|
+
|
|
572
|
+
- Set \`transparencyMode = MaterialInstance.TransparencyMode.DEFAULT\` for alpha blending.
|
|
573
|
+
- Double-sided rendering: set \`doubleSided = true\` in your material.
|
|
574
|
+
- For cutout transparency (e.g., leaves), use alpha masking not blending.
|
|
575
|
+
|
|
576
|
+
### Common Material Issues
|
|
577
|
+
|
|
578
|
+
| Symptom | Cause | Fix |
|
|
579
|
+
|---------|-------|-----|
|
|
580
|
+
| White/grey model | Missing textures or wrong format | Use .glb, check textures embedded |
|
|
581
|
+
| Pink model | Material compilation error | Recompile .filamat for current Filament version |
|
|
582
|
+
| Crash on material load | Wrong thread | Use main thread or \`rememberMaterial\` |
|
|
583
|
+
| SIGABRT on cleanup | Wrong destroy order | Destroy materials before textures |
|
|
584
|
+
| Transparent parts solid | TransparencyMode not set | Set transparencyMode on MaterialInstance |`,
|
|
585
|
+
},
|
|
586
|
+
animation: {
|
|
587
|
+
title: "Animation Issues",
|
|
588
|
+
guide: `## Debugging: Animation Issues
|
|
589
|
+
|
|
590
|
+
### Animation Not Playing
|
|
591
|
+
|
|
592
|
+
1. **Model has no animations** — check in a 3D viewer (Blender, gltf-viewer).
|
|
593
|
+
\`\`\`kotlin
|
|
594
|
+
// Log available animations
|
|
595
|
+
modelInstance?.let { instance ->
|
|
596
|
+
instance.animator?.let { animator ->
|
|
597
|
+
Log.d("SV", "Animation count: \${animator.animationCount}")
|
|
598
|
+
for (i in 0 until animator.animationCount) {
|
|
599
|
+
Log.d("SV", "Animation \$i: \${animator.getAnimationName(i)}")
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
\`\`\`
|
|
604
|
+
|
|
605
|
+
2. **Animator not being updated** — animations require frame-by-frame updates.
|
|
606
|
+
\`\`\`kotlin
|
|
607
|
+
Scene(
|
|
608
|
+
onFrame = { frameTimeNanos ->
|
|
609
|
+
modelInstance?.animator?.let { animator ->
|
|
610
|
+
if (animator.animationCount > 0) {
|
|
611
|
+
animator.applyAnimation(0, elapsedTime)
|
|
612
|
+
animator.updateBoneMatrices()
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
)
|
|
617
|
+
\`\`\`
|
|
618
|
+
|
|
619
|
+
3. **Animation index out of bounds** — always check \`animationCount\` before \`applyAnimation\`.
|
|
620
|
+
|
|
621
|
+
### Animation Looks Wrong
|
|
622
|
+
|
|
623
|
+
- **Wrong scale** — if model was scaled with \`scaleToUnits\`, bone positions may look off on very small/large models.
|
|
624
|
+
- **Missing morph targets** — blend shapes require morph target support in the model.
|
|
625
|
+
- **Frame rate** — animations interpolate between keyframes. Low FPS = choppy animation.
|
|
626
|
+
|
|
627
|
+
### Smooth Object Movement
|
|
628
|
+
|
|
629
|
+
For smooth node transforms (not skeletal animation):
|
|
630
|
+
\`\`\`kotlin
|
|
631
|
+
// Use SmoothTransform from sceneview-core
|
|
632
|
+
ModelNode(
|
|
633
|
+
modelInstance = instance,
|
|
634
|
+
// Position changes are smoothly interpolated
|
|
635
|
+
position = targetPosition,
|
|
636
|
+
smoothSpeed = 5.0f
|
|
637
|
+
)
|
|
638
|
+
\`\`\`
|
|
639
|
+
|
|
640
|
+
### Common Animation Issues
|
|
641
|
+
|
|
642
|
+
| Symptom | Cause | Fix |
|
|
643
|
+
|---------|-------|-----|
|
|
644
|
+
| No animation plays | Animator not updated in onFrame | Call \`applyAnimation\` + \`updateBoneMatrices\` each frame |
|
|
645
|
+
| Animation freezes | \`elapsedTime\` not advancing | Track time with \`System.nanoTime()\` delta |
|
|
646
|
+
| Wrong animation | Wrong index | Log animation names, use correct index |
|
|
647
|
+
| Bones don't move | \`updateBoneMatrices()\` missing | Always call after \`applyAnimation\` |
|
|
648
|
+
| Morph targets broken | Model export issue | Re-export from Blender with morph targets enabled |`,
|
|
649
|
+
},
|
|
513
650
|
};
|
|
514
651
|
export function getDebugGuide(category) {
|
|
515
652
|
const entry = DEBUG_GUIDES[category];
|
|
@@ -520,31 +657,41 @@ export function getDebugGuide(category) {
|
|
|
520
657
|
}
|
|
521
658
|
export function autoDetectIssue(description) {
|
|
522
659
|
const lower = description.toLowerCase();
|
|
523
|
-
|
|
660
|
+
// Threading issues → crash category (very common, check early)
|
|
661
|
+
if (lower.includes("wrong thread") || lower.includes("off main thread") || lower.includes("dispatchers.io") || lower.includes("background thread")) {
|
|
662
|
+
return "crash";
|
|
663
|
+
}
|
|
664
|
+
if (lower.includes("not showing") || lower.includes("invisible") || lower.includes("can't see") || lower.includes("model doesn't appear") || lower.includes("model not visible") || lower.includes("nothing shows up") || lower.includes("model is null") || lower.includes("remembermodelinstance returns null")) {
|
|
524
665
|
return "model-not-showing";
|
|
525
666
|
}
|
|
526
|
-
if (lower.includes("ar not") || lower.includes("ar doesn't") || lower.includes("arcore") || lower.includes("plane") || lower.includes("anchor")) {
|
|
667
|
+
if (lower.includes("ar not") || lower.includes("ar doesn't") || lower.includes("arcore") || lower.includes("plane") || lower.includes("anchor") || lower.includes("camera permission") || lower.includes("augmented reality") || lower.includes("hit test") || lower.includes("hitresult")) {
|
|
527
668
|
return "ar-not-working";
|
|
528
669
|
}
|
|
529
|
-
if (lower.includes("crash") || lower.includes("sigabrt") || lower.includes("native") || lower.includes("fatal") || lower.includes("exception")) {
|
|
670
|
+
if (lower.includes("crash") || lower.includes("sigabrt") || lower.includes("native crash") || lower.includes("fatal") || lower.includes("exception") || lower.includes("destroy") || lower.includes("double free") || lower.includes("segfault") || (lower.includes("oom") && !lower.includes("zoom")) || lower.includes("out of memory") || lower.includes("nullpointerexception") || lower.includes("npe")) {
|
|
530
671
|
return "crash";
|
|
531
672
|
}
|
|
532
|
-
if (lower.includes("slow") || lower.includes("fps") || lower.includes("lag") || lower.includes("jank") || lower.includes("performance") || lower.includes("memory")) {
|
|
673
|
+
if (lower.includes("slow") || lower.includes("fps") || lower.includes("lag") || lower.includes("jank") || lower.includes("performance") || lower.includes("memory") || lower.includes("stuttering") || lower.includes("frame drop") || lower.includes("choppy") || lower.includes("battery drain")) {
|
|
533
674
|
return "performance";
|
|
534
675
|
}
|
|
535
|
-
if (lower.includes("build") || lower.includes("gradle") || lower.includes("compile") || lower.includes("dependency") || lower.includes("cannot resolve")) {
|
|
676
|
+
if (lower.includes("build") || lower.includes("gradle") || lower.includes("compile") || lower.includes("dependency") || lower.includes("cannot resolve") || lower.includes("duplicate class") || lower.includes("java version") || lower.includes("agp") || lower.includes("version mismatch") || lower.includes("unresolved reference")) {
|
|
536
677
|
return "build-error";
|
|
537
678
|
}
|
|
538
|
-
if (lower.includes("black screen") || lower.includes("blank") || lower.includes("nothing renders")) {
|
|
679
|
+
if (lower.includes("black screen") || lower.includes("blank") || lower.includes("nothing renders") || lower.includes("no rendering") || lower.includes("screen is black") || lower.includes("empty screen")) {
|
|
539
680
|
return "black-screen";
|
|
540
681
|
}
|
|
541
|
-
if (lower.includes("
|
|
682
|
+
if (lower.includes("material") || lower.includes("texture") || lower.includes("white model") || lower.includes("untextured") || lower.includes("pink model") || lower.includes("filamat") || lower.includes("transparent") || lower.includes("alpha")) {
|
|
683
|
+
return "material";
|
|
684
|
+
}
|
|
685
|
+
if (lower.includes("animation") || lower.includes("animate") || lower.includes("morph") || lower.includes("bone") || lower.includes("skeleton") || lower.includes("keyframe") || lower.includes("animator")) {
|
|
686
|
+
return "animation";
|
|
687
|
+
}
|
|
688
|
+
if (lower.includes("dark") || lower.includes("bright") || lower.includes("light") || lower.includes("shadow") || lower.includes("overexposed") || lower.includes("hdr") || lower.includes("environment") || lower.includes("ibl")) {
|
|
542
689
|
return "lighting";
|
|
543
690
|
}
|
|
544
|
-
if (lower.includes("touch") || lower.includes("gesture") || lower.includes("tap") || lower.includes("drag") || lower.includes("rotate") || lower.includes("interact")) {
|
|
691
|
+
if (lower.includes("touch") || lower.includes("gesture") || lower.includes("tap") || lower.includes("drag") || lower.includes("rotate") || lower.includes("interact") || lower.includes("click") || lower.includes("select") || lower.includes("pinch") || lower.includes("zoom")) {
|
|
545
692
|
return "gestures";
|
|
546
693
|
}
|
|
547
|
-
if (lower.includes("ios") || lower.includes("swift") || lower.includes("xcode") || lower.includes("spm") || lower.includes("realitykit") || lower.includes("usdz")) {
|
|
694
|
+
if (lower.includes("ios") || lower.includes("swift") || lower.includes("xcode") || lower.includes("spm") || lower.includes("realitykit") || lower.includes("usdz") || lower.includes("visionos") || lower.includes("macos") || lower.includes("apple")) {
|
|
548
695
|
return "ios";
|
|
549
696
|
}
|
|
550
697
|
return null;
|