diff --git a/.github/workflows/build-apks.yml b/.github/workflows/build-apks.yml index bafa40eb5..7c9895091 100644 --- a/.github/workflows/build-apks.yml +++ b/.github/workflows/build-apks.yml @@ -2,13 +2,55 @@ name: Build sample APKs on: push: + branches: [main] tags: - 'v[0-9]+.[0-9]+.[0-9]+' + pull_request: + branches: [main] workflow_dispatch: jobs: + build-demo: + name: Build demo APK (quick — always available) + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: gradle + + - run: chmod +x ./gradlew + + - name: Build SceneView Demo APK + run: ./gradlew :samples:sceneview-demo:assembleDebug --console=plain + + - name: Collect demo APK + run: | + mkdir -p dist + apk=$(find samples/sceneview-demo/build/outputs/apk/debug -name "*.apk" | head -1) + cp "$apk" dist/sceneview-demo.apk + + - name: Upload demo APK + uses: actions/upload-artifact@v4 + with: + name: sceneview-demo-apk + path: dist/sceneview-demo.apk + retention-days: 90 + + - name: Attach demo APK to GitHub Release + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + uses: softprops/action-gh-release@v2 + with: + files: dist/sceneview-demo.apk + build-samples: - name: Build sample APKs + name: Build all sample APKs runs-on: ubuntu-latest permissions: contents: write @@ -28,6 +70,7 @@ jobs: - name: Build all sample APKs run: | ./gradlew \ + :samples:sceneview-demo:assembleDebug \ :samples:model-viewer:assembleDebug \ :samples:camera-manipulator:assembleDebug \ :samples:gltf-camera:assembleDebug \ @@ -47,9 +90,9 @@ jobs: - name: Collect APKs run: | mkdir -p dist - for sample in model-viewer camera-manipulator gltf-camera autopilot-demo \ - physics-demo post-processing dynamic-sky line-path \ - text-labels reflection-probe \ + for sample in sceneview-demo model-viewer camera-manipulator gltf-camera \ + autopilot-demo physics-demo post-processing dynamic-sky \ + line-path text-labels reflection-probe \ ar-model-viewer ar-augmented-image ar-cloud-anchor ar-point-cloud; do apk=$(find "samples/$sample/build/outputs/apk/debug" -name "*.apk" | head -1) if [ -n "$apk" ]; then diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6fd235f08..867a63e04 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -11,6 +11,10 @@ on: - 'CONTRIBUTING.md' - 'ROADMAP.md' - 'llms.txt' + - 'sceneview/Module.md' + - 'arsceneview/Module.md' + release: + types: [published] workflow_dispatch: jobs: diff --git a/.gitignore b/.gitignore index cc7569f99..bc43fac99 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,5 @@ samples/*/build/ # MCP compiled test artifacts mcp/dist/*.test.js mcp/llms.txt - -# MkDocs build output +sceneview-core/build/ docs/site/ diff --git a/docs/docs/architecture.md b/docs/docs/architecture.md index d4d6b8462..775c9039d 100644 --- a/docs/docs/architecture.md +++ b/docs/docs/architecture.md @@ -10,7 +10,7 @@ from your Kotlin code all the way down to the GPU. SceneView is a stack of five layers. Each layer only talks to the one directly below it, keeping responsibilities clean and dependencies one-directional. -``` +```text ┌──────────────────────────────────────────────────┐ │ Your Android App (Kotlin/Compose) │ ├──────────────────────────────────────────────────┤ @@ -124,7 +124,7 @@ maintains an idempotent `managedNodes` set to prevent double-add/remove. ### How the threading works in practice -``` +```text ┌────────────────────┐ ┌──────────────────────┐ │ Dispatchers.IO │ │ Main Thread │ │ │ │ │ @@ -190,7 +190,7 @@ LaunchedEffect(engine, renderer, view, scene) { SceneView ties every Filament resource to Compose's lifecycle through `remember` + `DisposableEffect`, following a consistent pattern: -``` +```text remember { create resource } → DisposableEffect { onDispose { destroy resource } } ``` @@ -228,7 +228,7 @@ registered models when the loader itself is disposed. Every frame follows this sequence: -``` +```text 1. Compose recomposition └─ SideEffect pushes updated node properties to Filament entities @@ -261,7 +261,7 @@ For AR scenes (`ARScene`), step 2 additionally: SceneView is split into two Gradle modules with a strict dependency direction: -``` +```text ┌─────────────────────┐ ┌─────────────────────────┐ │ sceneview/ │◀────────│ arsceneview/ │ │ │ depends │ │ diff --git a/docs/docs/assets/images/auto-companion.svg b/docs/docs/assets/images/auto-companion.svg new file mode 100644 index 000000000..365f000fa --- /dev/null +++ b/docs/docs/assets/images/auto-companion.svg @@ -0,0 +1,344 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + My Vehicle + + + + + + + + + + + + + + + + + + + + + + Locked + 2 min ago + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2.3 + + + + + + 2.3 + + + + + + 2.2 + + + + + + 2.1 + + + + + + + + + + 286 km + Battery: 72% + + + + + + + + + + + + + + + + + + 21°C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/docs/assets/images/auto-hud-wide.svg b/docs/docs/assets/images/auto-hud-wide.svg new file mode 100644 index 000000000..9188b90a4 --- /dev/null +++ b/docs/docs/assets/images/auto-hud-wide.svg @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 22°C + + + 14:32 + + + + + + + + 78% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 98m + + + + + + 56m + + + + + + + + + 24m + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 112 + + km/h + + + + + + + + + + + + + + + + + + + Turn right in 200m + + + Hauptstraße + + + + + + + + + + + + + + + Range: 342km + | + ADAS: Active + | + Music: Now Playing + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/docs/assets/images/badge-made-with-sceneview.svg b/docs/docs/assets/images/badge-made-with-sceneview.svg new file mode 100644 index 000000000..3087fe4c5 --- /dev/null +++ b/docs/docs/assets/images/badge-made-with-sceneview.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + Made with SceneView + diff --git a/docs/docs/assets/images/comparison-chart.svg b/docs/docs/assets/images/comparison-chart.svg new file mode 100644 index 000000000..d58009b56 --- /dev/null +++ b/docs/docs/assets/images/comparison-chart.svg @@ -0,0 +1,90 @@ + + + + + + + + + + + + + Lines of code to display a 3D model + + + + + + ~15 lines + SceneView + + Compose + + 0 XML + + Auto lifecycle + + + + + + ~80 lines + Sceneform + + Archived + + XML + Views + + + + + + ~200+ lines + Raw ARCore + + No UI layer + + + + + + ~50 lines + engine overhead + Unity + + +50MB APK + + C# / IL2CPP + + + + + Why developers choose SceneView: + + + + + Compose-native + + + + + Zero boilerplate + + + + + ~5MB APK size + + + + + Apache 2.0 + + + + + Active + AI-ready + + + diff --git a/docs/docs/assets/images/device-ios-preview.svg b/docs/docs/assets/images/device-ios-preview.svg new file mode 100644 index 000000000..3f7e36639 --- /dev/null +++ b/docs/docs/assets/images/device-ios-preview.svg @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 9:41 + + + + + + + + + + + + + + + + + + + + + + + + + Product View + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AIR + + + + + + + + + + + + + + + + + + + Air Runner Pro + + $189 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + View in AR + + + + + + + + + + + Home + + + + + + Search + + + + + Saved + + + + + + Profile + + + + + + + + + v4.1 + + + + + diff --git a/docs/docs/assets/images/device-tv-preview.svg b/docs/docs/assets/images/device-tv-preview.svg new file mode 100644 index 000000000..efdfe0a3a --- /dev/null +++ b/docs/docs/assets/images/device-tv-preview.svg @@ -0,0 +1,345 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Living Room + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Compose Desktop + + \ No newline at end of file diff --git a/docs/docs/assets/images/device-xr-preview.svg b/docs/docs/assets/images/device-xr-preview.svg new file mode 100644 index 000000000..771702b2b --- /dev/null +++ b/docs/docs/assets/images/device-xr-preview.svg @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tap to customize + + + + + + COLOR + + + + + + + + + + + + SIZE + + + S + + M + + L + + + $299 + In Stock + + + + + + + + + + Material + + + + + + + + + + + Oak + + + + Fabric + + + + + + + + + + Leather + + + + + + + Chrome + + + + + + + + + + + + + + + + + + + + + + + + + XRScene { } + + + + + + + + + + + + + + + + diff --git a/docs/docs/assets/images/hero-banner.svg b/docs/docs/assets/images/hero-banner.svg index 6061ab18b..10e13a43e 100644 --- a/docs/docs/assets/images/hero-banner.svg +++ b/docs/docs/assets/images/hero-banner.svg @@ -1,125 +1,281 @@ - + - - - - - + + + + + - - - - + + - - - + + - - - + + + + + + + + + + + + + + + + + - - + + + + + + - + - - - - - - - + + + + + + + + Nike Air Max + + + + + + + + + + + + + + + + + + + + Size + + 8 + + 9 + + 10 + + + + + View in AR + + Add to Cart + + $189 + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + 72 + km/h + + + + + + + 82% + Range + 342 km + + + + + + + + + + + + + + + Green 12s + + + + + Lane Assist · ACC 80 · Autopilot - - - - - - - - - - - - - - - - - + + + + + + + + + 3D Anatomy Lab + + + + + Heart + + Lungs + + Brain + + + + + + + + + + + + + Right Ventricle + + + + + Properties + Opacity + + + + Cross Section + + + + + - - - - - - - ModelViewerScreen.kt + + + + + + + + + + + + + + + + + + + Virtual Tour — Living Room + - - - @Composable - fun ModelViewerScreen() { - // 3D scene — same pattern as Column { } - Scene( - modifier = Modifier.fillMaxSize() - ) { - // Model loads async — null until ready - rememberModelInstance( - modelLoader, "models/helmet.glb" - )?.let { instance -> - ModelNode( - modelInstance = instance, - scaleToUnits = 1.0f - ) + + + + + + + + + + + + + + + + + + + Tap to customize + + + + + + + + + + Spatial preview + + + + + - - - SCENEVIEW - 3D is just - Compose UI. - Filament + ARCore + Jetpack Compose + + + + Android Auto + + + + 60fps + + + + Compose UI + + + + ARCore + + + + Filament - - - - - - - - - - - - - + + Phone + Car Dashboard + Tablet + TV + XR Headset diff --git a/docs/docs/assets/images/hero-devices.svg b/docs/docs/assets/images/hero-devices.svg new file mode 100644 index 000000000..2deba6f34 --- /dev/null +++ b/docs/docs/assets/images/hero-devices.svg @@ -0,0 +1,269 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Android + + + + + + + + + + + + + + + + + + + + + iOS v4.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tablet + + + + + + + + + + + + + + + + + + + + + + + + XR + + + + + + + + + + + + + + + + + + + + + + + + + + + + Automotive + + + + + + + + + + + + + + + + + + + + + + + + + + + TV · Desktop + + + + + + + + + + + + + React Native + + + + + + + + + Flutter + + + \ No newline at end of file diff --git a/docs/docs/assets/images/industry-automotive.svg b/docs/docs/assets/images/industry-automotive.svg new file mode 100644 index 000000000..6e35e45e3 --- /dev/null +++ b/docs/docs/assets/images/industry-automotive.svg @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 300m + Turn right on Main St + + + + + 72 + km/h + + + + + + 82% + Range + 342 km + Outside + 18°C + + + + + + + + + + + + + + Green 12s + + + + Lane Assist · ACC 80 km/h · Autopilot + + + + + + + + + + 9:41 + + + + + 3 min + to destination + + Via Highway 101 + + + + + + + + + + + + Live vehicle model + + + + + Night Drive + Synthwave FM + + + + + + + + + + + Built with SceneView + + Built with SceneView + Android Automotive · Head-Up Display · Companion App + diff --git a/docs/docs/assets/images/industry-ecommerce.svg b/docs/docs/assets/images/industry-ecommerce.svg new file mode 100644 index 000000000..df7974436 --- /dev/null +++ b/docs/docs/assets/images/industry-ecommerce.svg @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 9:41 + 100% + + Nike Air Max 90 + $189 + + + + + + + + + + + + + + + + + Drag to rotate + + + + + + + + + + Size + + 8 + + 9 + + 10 + + 11 + + + View in AR + + Add to Cart + + + + + Built with SceneView + + + + + + + 60fps rendering + + + + + 3D + PBR materials + + + + + AR + Try before buy + + + + + + +32% conversion + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AR Mode + Plane detected + + 2.1m wide + + + + Colors + + + + Built with SceneView + diff --git a/docs/docs/assets/images/industry-education.svg b/docs/docs/assets/images/industry-education.svg new file mode 100644 index 000000000..1ad843967 --- /dev/null +++ b/docs/docs/assets/images/industry-education.svg @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 9:41 + + + World Geography + + + + + + + + + + + + + + + + + + + + + + + + + + + + ! + Paris, France + Pop. 2.1M · Eiffel Tower + + + + Start Quiz + + Explore + + Drag to rotate globe + + + + + Built with SceneView + + + + + 🌍 + Interactive globes + + + + 🧪 + Lab simulations + + + + 📐 + 3D math visualizer + + + + 🎯 + Quiz gamification + + + + + + + + + + + + + + + + + + + + + + Solar System Explorer + + AR Mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + 🌍 + Earth + 12,742 km · 365 days · 1 moon + Tap to explore surface + + + + + Mercury + + Venus + + Earth + + Mars + + Jupiter + + Saturn + + + + + Built with SceneView + + Geography · Solar System · Lab Simulations · STEM Visualization + diff --git a/docs/docs/assets/images/industry-gaming.svg b/docs/docs/assets/images/industry-gaming.svg new file mode 100644 index 000000000..e715cd068 --- /dev/null +++ b/docs/docs/assets/images/industry-gaming.svg @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 75% + + + + Score: 2,450 + + + + + + + + + + + + + + + + + + + + + A + + B + + + + + Built with SceneView + + + + + PhysicsNode collisions + + + + Dynamic lighting + + + + Compose UI overlays + + + + 60fps rendering + + + + + + + + + + + + Level Editor — World 3 + + Saved + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Block + + Lava + + Item + + Enemy + + Spawn + + + + + Play · Undo · Redo · Grid · Camera + + + + + Built with SceneView + + 3D Games · Level Editors · Interactive Worlds · No Game Engine Needed + diff --git a/docs/docs/assets/images/industry-medical.svg b/docs/docs/assets/images/industry-medical.svg new file mode 100644 index 000000000..f3db5607c --- /dev/null +++ b/docs/docs/assets/images/industry-medical.svg @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3D Anatomy Lab + + Share + + + + Heart + + Lungs + + Brain + + Skeleton + + Muscles + + + + + + + + + + + + + + Right Ventricle + + + Left Atrium + + + + + + X + Y + Z + + + + Properties + Opacity + + + + Cross Section + + + + Animation + + Play Heartbeat + Labels + + + + + + + Built with SceneView + + + + + + + + + + 9:41 + + Caffeine — C8H10N4O2 + + + + + + + + + + + + + + + + + + + + + + + C + C + C + N + N + O + O + + + Legend + Carbon + Nitrogen + Oxygen + + + + Rotate + + VR + + Quiz + + + + + Built with SceneView + + + + + 🫀 + Heart + + + + 🧬 + DNA + + + + 🦴 + Skeleton + + + Medical Training · Molecular Science · Interactive 3D Education + diff --git a/docs/docs/assets/images/industry-realestate.svg b/docs/docs/assets/images/industry-realestate.svg new file mode 100644 index 000000000..0798d3756 --- /dev/null +++ b/docs/docs/assets/images/industry-realestate.svg @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AR Staging + + 3 items + + + Pinch to resize · Rotate to turn + Tap floor to place furniture + + + + + Table + Chair + Sofa + Lamp + + + + + Built with SceneView + + + + + 🏠 + 3D Floor Plans + + + + 🚪 + Portal walkthrough + + + + ☀️ + Lighting conditions + + + + 📐 + AR Measuring + + + + + + + + + + + 123 Oak Ave — Floor Plan + + 3D View + + + + + + + + + + + + Living Room + 24 m2 + + + + + Living + + Kitchen + + Bedroom + + Bathroom + + Balcony + + + Total: 85 m2 · 3 rooms · 2nd floor + + + + Built with SceneView + + + + + + + + + + Open House 2pm + + + + + + + + + + + + + + + + Virtual Tour — Living Room + + + Virtual Tours · AR Staging · 3D Floor Plans · PortalNode Walkthroughs + diff --git a/docs/docs/assets/images/infographic-composable-tree.svg b/docs/docs/assets/images/infographic-composable-tree.svg new file mode 100644 index 000000000..53050631e --- /dev/null +++ b/docs/docs/assets/images/infographic-composable-tree.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + Scene { } + + + + ModelNode + + + + LightNode + + + + AnchorNode + + + + ModelNode + + + + ViewNode + \ No newline at end of file diff --git a/docs/docs/assets/images/infographic-how-it-works.svg b/docs/docs/assets/images/infographic-how-it-works.svg new file mode 100644 index 000000000..937b179b8 --- /dev/null +++ b/docs/docs/assets/images/infographic-how-it-works.svg @@ -0,0 +1,27 @@ + + + + + + + + + + 1 + { } + Write Compose + + + + 2 + + + + Add nodes + + + + 3 + + Ship + \ No newline at end of file diff --git a/docs/docs/assets/images/screenshot-autopilot.png b/docs/docs/assets/images/screenshot-autopilot.png new file mode 100644 index 000000000..c130c17c2 Binary files /dev/null and b/docs/docs/assets/images/screenshot-autopilot.png differ diff --git a/docs/docs/assets/images/screenshot-camera-manipulator.png b/docs/docs/assets/images/screenshot-camera-manipulator.png new file mode 100644 index 000000000..a9eb01a26 Binary files /dev/null and b/docs/docs/assets/images/screenshot-camera-manipulator.png differ diff --git a/docs/docs/assets/images/screenshot-gltf-camera.png b/docs/docs/assets/images/screenshot-gltf-camera.png new file mode 100644 index 000000000..7d944f87e Binary files /dev/null and b/docs/docs/assets/images/screenshot-gltf-camera.png differ diff --git a/docs/docs/assets/images/showcase-ar-placement.svg b/docs/docs/assets/images/showcase-ar-placement.svg new file mode 100644 index 000000000..1809f648d --- /dev/null +++ b/docs/docs/assets/images/showcase-ar-placement.svg @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tap to place + + + + + + + AR Placement + + Tracking + + + + + + 1:1 + + + + Pinch to scale · Drag to move + + + diff --git a/docs/docs/assets/images/showcase-ar-pointcloud.svg b/docs/docs/assets/images/showcase-ar-pointcloud.svg new file mode 100644 index 000000000..bfd43408f --- /dev/null +++ b/docs/docs/assets/images/showcase-ar-pointcloud.svg @@ -0,0 +1,271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Floor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AR Point Cloud + TRACKING + + + + Points: 847 + Planes: 3 + FPS: 60 + + + + + High + + Med + + Low + \ No newline at end of file diff --git a/docs/docs/assets/images/showcase-autopilot.svg b/docs/docs/assets/images/showcase-autopilot.svg index 34d2f1bcb..9381d3757 100644 --- a/docs/docs/assets/images/showcase-autopilot.svg +++ b/docs/docs/assets/images/showcase-autopilot.svg @@ -1,115 +1,210 @@ - + - - - + + + + - - - + + + + + + - - - + + + + + + - + + + - + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 42m - - - - - - - - - - - - - - - AUTOPILOT - FOLLOWING DIST - SceneView FSD - COMFORTABLE - - - - ACTIVE - - - - - - - 120 - - - 108 - km/h - - - - - - DETECTED - - Cars 3 - Bus 1 - Truck 1 - Bikes 2 - - - - - Powered by SceneView + Jetpack Compose + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 120m + + + + + + + + + + + 68m + + + + + + + + + + + + 32m + + + + + + + + + + + + 87 + + km/h + + + + + + + + + + Lane Assist + + + + + + + Autopilot Active + + 3 objects detected + + + + + + + + + + + + Next turn: 1.2km + | + ETA: 12min - + + diff --git a/docs/docs/assets/images/showcase-camera.svg b/docs/docs/assets/images/showcase-camera.svg new file mode 100644 index 000000000..5ec234903 --- /dev/null +++ b/docs/docs/assets/images/showcase-camera.svg @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Camera Controls + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + X + + + Y + + + Z + + + + + + + + + + + + + + + + 1 finger + Orbit + + + + + + + + + + + + + + 2 fingers + Pan + + + + + + + + + + + + + + + + Pinch + Zoom + + + + + + diff --git a/docs/docs/assets/images/showcase-dynamic-sky.svg b/docs/docs/assets/images/showcase-dynamic-sky.svg new file mode 100644 index 000000000..c82b0598c --- /dev/null +++ b/docs/docs/assets/images/showcase-dynamic-sky.svg @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dynamic Sky + + + + + TIME OF DAY + + + + + + + + + + + + + + + + Turbidity: 4 + + + Elevation: 15° + + + + + + + diff --git a/docs/docs/assets/images/showcase-line-paths.svg b/docs/docs/assets/images/showcase-line-paths.svg new file mode 100644 index 000000000..3139bbcbb --- /dev/null +++ b/docs/docs/assets/images/showcase-line-paths.svg @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Line Paths + + + + + A:3 B:2 δ:π/2 + + + + + + + + Lissajous + + + + Sine + + + + Spiral + + \ No newline at end of file diff --git a/docs/docs/assets/images/showcase-model-viewer.svg b/docs/docs/assets/images/showcase-model-viewer.svg new file mode 100644 index 000000000..5f2c88017 --- /dev/null +++ b/docs/docs/assets/images/showcase-model-viewer.svg @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Model Viewer + + + + + + + + + + + Animation: Rotate + + + + + + + + + + + EV + + \ No newline at end of file diff --git a/docs/docs/assets/images/showcase-physics.svg b/docs/docs/assets/images/showcase-physics.svg new file mode 100644 index 000000000..d55e0245d --- /dev/null +++ b/docs/docs/assets/images/showcase-physics.svg @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Physics + + + + Gravity: 9.8 + | + Restitution: 0.7 + | + Bodies: 5 + + + + + Tap to throw + diff --git a/docs/docs/assets/images/showcase-post-processing.svg b/docs/docs/assets/images/showcase-post-processing.svg new file mode 100644 index 000000000..4fb2b1aff --- /dev/null +++ b/docs/docs/assets/images/showcase-post-processing.svg @@ -0,0 +1,223 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Post-Processing + + + SSAO + + + + + + ✓ Bloom + + + + ✓ Vignette + + + + ✓ ACES + + + + ✓ FXAA + + \ No newline at end of file diff --git a/docs/docs/assets/images/showcase-reflection.svg b/docs/docs/assets/images/showcase-reflection.svg new file mode 100644 index 000000000..5d0b82bae --- /dev/null +++ b/docs/docs/assets/images/showcase-reflection.svg @@ -0,0 +1,298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Chrome + Matte + Glass + Gold + + + + Materials + + + PBR Material Showcase + + + + + + + Metal: 1.0 Rgh: 0.0 + + + + + Metal: 0.0 Rgh: 0.9 + + + + + Metal: 0.0 Rgh: 0.0 + + + + + Metal: 1.0 Rgh: 0.3 + + \ No newline at end of file diff --git a/docs/docs/assets/images/showcase-text-labels.svg b/docs/docs/assets/images/showcase-text-labels.svg new file mode 100644 index 000000000..76b0db079 --- /dev/null +++ b/docs/docs/assets/images/showcase-text-labels.svg @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Text Labels + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Red Cube + + + + + + + + + + + + + + + + + + + + + + Planet Earth + + + + + + + + + + + + + + + + + + + + + + + + + Gold Cylinder + + + + + + + + + Hello! + Hello! + Hello! + + Hello! + + Hello! + + + + + + + + + + + + + + + + + + + + faces camera + + + + + + + + Billboard: ON + + + + + \ No newline at end of file diff --git a/docs/docs/assets/images/tablet-anatomy.svg b/docs/docs/assets/images/tablet-anatomy.svg new file mode 100644 index 000000000..c8e35310f --- /dev/null +++ b/docs/docs/assets/images/tablet-anatomy.svg @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3D Anatomy Lab + Heart — Cardiovascular System + + + + + + + + + + + + + + Rotate + + + + + + + + + Slice + + + + + + + + + Labels + + + + + + + + + Opacity + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Aorta + + + + + + Left Ventricle + + + + + + Pulmonary Artery + + + + + + Opacity: 80% + + + + + + 24,831 vertices · 49,204 triangles + \ No newline at end of file diff --git a/docs/docs/assets/images/tablet-floorplan.svg b/docs/docs/assets/images/tablet-floorplan.svg new file mode 100644 index 000000000..833aa4797 --- /dev/null +++ b/docs/docs/assets/images/tablet-floorplan.svg @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Living + Kitchen + Bed + Bath + + + + + + + + + + + + + 4.2m + + + + + + + + + 3.1m + + + + + + + + + + N + + + + + + + + + + All + + + + Living + + + + Kitchen + + + + Bed + + + + + + + + + AR View + + + \ No newline at end of file diff --git a/docs/docs/assets/images/tablet-leveleditor.svg b/docs/docs/assets/images/tablet-leveleditor.svg new file mode 100644 index 000000000..1db7146c2 --- /dev/null +++ b/docs/docs/assets/images/tablet-leveleditor.svg @@ -0,0 +1,322 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level Editor + — World 1-3 + + + + + + + + + + + + + Play + + + + Save + + Test + + + + + + Blocks + + + + + + + + + + Grass + + + + + + + + + Water + + + + + + + + + Brick + + + + + + + + + Sand + + + + Items + + + + + + + + + + + + + + + + + + + + + + $ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ + + + + + + + + + + + + + + + + + + + Grid: 8x8 · Blocks: 9 · Items: 4 + + + + Layer: + + 1 + + 2 + + 3 + + + + + + - + + + + + + SceneView 3D + \ No newline at end of file diff --git a/docs/docs/assets/images/tablet-solar.svg b/docs/docs/assets/images/tablet-solar.svg new file mode 100644 index 000000000..e0edce43d --- /dev/null +++ b/docs/docs/assets/images/tablet-solar.svg @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Earth + Terrestrial Planet + + + + Radius + 6,371 km + Distance + 1.0 AU + Moons + 1 + + + + Mercury + Venus + Mars + + + + Solar System Explorer + + + + + + + S + + + + + + + + + Zoom + + + + + + Speed + + + 1x + + 5x + + 10x + + + + + + + + + + + + + + + + + + + + + + SceneView 3D + \ No newline at end of file diff --git a/docs/docs/assets/images/v4-architecture.svg b/docs/docs/assets/images/v4-architecture.svg new file mode 100644 index 000000000..a501ac1a2 --- /dev/null +++ b/docs/docs/assets/images/v4-architecture.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + SceneView 4.0 — Multi-Platform Architecture + + + + Your App — Jetpack Compose / SwiftUI + + + + + + + + SceneView API — Scene { } · ARScene { } · XRScene { } + + + + + + + + + sceneview-core (KMP) + Math · Collision · Physics + Animation · Geometry · Scene + + + + sceneview (Android) + 26+ Nodes · Compose · Gestures + Loaders · Materials · Camera + + + + arsceneview (AR) + ARCore · Anchors · Planes + Images · Faces · Cloud + + + + + + + + + + + + kotlin-math + + + Filament + + + Compose UI + + + Metal / OpenGL + + + ARCore + + + + + Android + + iOS + + XR + + TV + + Auto + + Desktop + + diff --git a/docs/docs/assets/images/visual-node-types.svg b/docs/docs/assets/images/visual-node-types.svg new file mode 100644 index 000000000..01e93db9c --- /dev/null +++ b/docs/docs/assets/images/visual-node-types.svg @@ -0,0 +1,64 @@ + + + + + + + + + ModelNode + + + + + + + + + + LightNode + + + + + + CubeNode + + + + + + + AnchorNode + + + + + + + + + VideoNode + + + + + A + TextNode + + + + + + PathNode + + + + + + + ViewNode + + \ No newline at end of file diff --git a/docs/docs/codelabs/codelab-3d-compose.md b/docs/docs/codelabs/codelab-3d-compose.md index 575f9dd65..70c3655a2 100644 --- a/docs/docs/codelabs/codelab-3d-compose.md +++ b/docs/docs/codelabs/codelab-3d-compose.md @@ -1,5 +1,7 @@ # CodeLab: Your first 3D scene with SceneView 3.0 +What you'll build: a 3D model viewer + **Time:** ~25 minutes **Level:** Beginner (requires Kotlin + Jetpack Compose basics) **What you'll build:** A 3D model viewer with orbit camera, HDR lighting, and a double-tap-to-scale gesture @@ -312,4 +314,4 @@ That's ~35 lines. A production-quality 3D model viewer with orbit camera, HDR li - **Add geometry** → Try `CubeNode`, `SphereNode`, `CylinderNode` in the scene block - **Embed in a screen** → Replace any `Image()` in your app with this `Box` wrapping a `Scene` - **Explore samples** → The [model-viewer](/samples/model-viewer), [gltf-camera](/samples/gltf-camera), and [camera-manipulator](/samples/camera-manipulator) samples show more patterns -- **Read the API docs** → [sceneview.github.io/api/sceneview-android/sceneview](https://sceneview.github.io/api/sceneview-android/sceneview/) +- **Read the API docs** → [sceneview.github.io/api/sceneview/sceneview](https://sceneview.github.io/api/sceneview/sceneview/) diff --git a/docs/docs/codelabs/codelab-ar-compose.md b/docs/docs/codelabs/codelab-ar-compose.md index 4d3175a64..f7bf905f3 100644 --- a/docs/docs/codelabs/codelab-ar-compose.md +++ b/docs/docs/codelabs/codelab-ar-compose.md @@ -1,5 +1,7 @@ # CodeLab: AR with Jetpack Compose — SceneView 3.0 +What you'll build: AR model placement + **Time:** ~20 minutes **Prerequisites:** Complete the [3D CodeLab](codelab-3d-compose.md) first, or have basic SceneView knowledge **What you'll build:** An AR scene that detects horizontal planes and places a 3D model anchored to the physical world diff --git a/docs/docs/comparison.md b/docs/docs/comparison.md index 986091545..fb3a1efde 100644 --- a/docs/docs/comparison.md +++ b/docs/docs/comparison.md @@ -2,6 +2,10 @@ An honest comparison for developers evaluating 3D and AR options. +
+Lines of code comparison: SceneView vs alternatives +
+ --- ## The landscape diff --git a/docs/docs/index.md b/docs/docs/index.md index fc16511fa..596764586 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -1,57 +1,184 @@ # SceneView -

3D and AR as Compose UI — on Android, XR headsets, and soon iOS

- - -
- - -
Loading 3D model...
-
-

Drag to rotate · Scroll to zoom · This is what SceneView renders natively on Android

-
- -## Scenes are composables. +

3D & AR for every platform — native Android, native iOS, React Native, Flutter, and beyond.

+ +
+Android Native +iOS Native v4.1 +XR Headsets +React Native +Flutter +TV · Auto · Desktop +
+ +[:octicons-arrow-right-24: Start building](#get-started){ .md-button .md-button--primary } +[:octicons-download-24: Try the demo](try.md){ .md-button .md-button--primary } +[:octicons-mark-github-24: View on GitHub](https://github.com/SceneView/sceneview-android){ .md-button } + + +
+SceneView runs on Android phones, tablets, iOS, XR headsets, automotive, TV, React Native, and Flutter +
+ +--- + + +
+ + + + + + + +
+ + +
+26+ built-in nodes +60fps on mid-range devices +6 platforms supported +Apache 2.0 open source +
+ +--- + +## See what you can build + +SceneView powers production apps in e-commerce, automotive, healthcare, and more. Same composable API — from a 5" phone to a 65" TV to XR headsets. + + +
+ +
+3D product viewer with AR try-on +
Made with SceneView
+

E-commerce

+

3D product viewers with 360° rotation and AR try-on. Drop a Scene {} where you'd use an Image().

+
+ +
+Interactive 3D education with globe and solar system +
Made with SceneView
+

Education & STEM

+

Interactive 3D globes, solar systems, molecular viewers, anatomy labs — bring learning to life with Scene {}.

+
+ +
+Automotive HUD with 3D navigation +
Made with SceneView
+

Automotive HUD

+

Heads-up displays, 3D navigation arrows, speed overlays on Android Automotive. Multiple Scene {} on one screen.

+
+ +
+XR spatial computing showroom +
Made with SceneView
+

XR spatial computing

+

Floating 3D models with Compose UI panels in spatial space. XRScene {} + ViewNode for cards, buttons, pickers.

+
+ +
+ + +
+ +
+Medical training app with interactive 3D anatomy +
+

Healthcare & education

+

Interactive 3D anatomy models, molecular structures, and mechanical assemblies. Students control everything with standard Compose UI — sliders, buttons, toggles.

+
+
+ +
+Real estate AR furniture placement +
+

Real estate

+

Walk through 3D floor plans, preview renovations in AR, compare lighting conditions. PortalNode lets users peek through doors into furnished rooms.

+
+
+ +
+3D mobile game with physics and level editor +
+

Gaming & entertainment

+

Build 3D mobile games without a game engine. PhysicsNode for collisions, dynamic lighting, Compose UI overlays for HUD — all at 60fps on mid-range devices.

+
+
+ + +
+ +--- + +## How it works Write a `Scene { }` the same way you write a `Column { }`. Nodes are composables. -State drives the scene. Lifecycle is automatic. One API — every platform. +State drives the scene. Lifecycle is automatic. -=== "3D Model Viewer" + +
+3 steps: Write Compose, Add 3D Nodes, Ship everywhere +
+ + +
+Scene tree: Scene contains ModelNode, LightNode, AnchorNode — same pattern as Column/Row +
+ +=== "Product viewer" ```kotlin - Scene(modifier = Modifier.fillMaxSize()) { - rememberModelInstance(modelLoader, "models/helmet.glb")?.let { instance -> - ModelNode(modelInstance = instance, scaleToUnits = 1.0f, autoAnimate = true) + @Composable + fun ProductViewer() { + val engine = rememberEngine() + val modelLoader = rememberModelLoader(engine) + val shoe = rememberModelInstance(modelLoader, "models/shoe.glb") + + Scene( + modifier = Modifier.fillMaxWidth().height(300.dp), + engine = engine, + cameraManipulator = rememberCameraManipulator() + ) { + shoe?.let { + ModelNode(modelInstance = it, scaleToUnits = 1.0f, autoAnimate = true) + } + LightNode(type = LightManager.Type.SUN, apply = { intensity(100_000.0f) }) } - LightNode(type = LightManager.Type.SUN, apply = { intensity(100_000.0f) }) } ``` - Five lines. Production-quality 3D. Same Kotlin you write every day. + Ten lines. Your users can rotate, zoom, and inspect a product in 3D — inside your existing Compose layout. -=== "AR Placement" +=== "AR placement" ```kotlin - ARScene(planeRenderer = true, onSessionUpdated = { _, frame -> - anchor = frame.getUpdatedPlanes() - .firstOrNull { it.type == Plane.Type.HORIZONTAL_UPWARD_FACING } - ?.let { frame.createAnchorOrNull(it.centerPose) } - }) { - anchor?.let { a -> - AnchorNode(anchor = a) { - ModelNode(modelInstance = sofa, scaleToUnits = 0.5f, isEditable = true) + @Composable + fun FurniturePlacement() { + var anchor by remember { mutableStateOf(null) } + val engine = rememberEngine() + val modelLoader = rememberModelLoader(engine) + val sofa = rememberModelInstance(modelLoader, "models/sofa.glb") + + ARScene( + modifier = Modifier.fillMaxSize(), + engine = engine, + planeRenderer = true, + onSessionUpdated = { _, frame -> + if (anchor == null) { + anchor = frame.getUpdatedPlanes() + .firstOrNull { it.type == Plane.Type.HORIZONTAL_UPWARD_FACING } + ?.let { frame.createAnchorOrNull(it.centerPose) } + } + } + ) { + anchor?.let { a -> + AnchorNode(anchor = a) { + sofa?.let { + ModelNode(modelInstance = it, scaleToUnits = 0.5f, isEditable = true) + } + } } } } @@ -59,18 +186,21 @@ State drives the scene. Lifecycle is automatic. One API — every platform. Tap to place. Pinch to scale. Two-finger rotate. All built in. -=== "XR Spatial" +=== "XR spatial" ```kotlin - XRScene(modifier = Modifier.fillMaxSize()) { - ModelNode( - modelInstance = furniture, - position = Position(0f, 0f, -2f) - ) - ViewNode(position = Position(0.5f, 1.5f, -1.5f)) { - Card { - Text("Tap to customize") - ColorPicker(onColorSelected = { /* update material */ }) + @Composable + fun SpatialShowroom() { + XRScene(modifier = Modifier.fillMaxSize()) { + ModelNode( + modelInstance = furniture, + position = Position(0f, 0f, -2f) + ) + ViewNode(position = Position(0.5f, 1.5f, -1.5f)) { + Card { + Text("Tap to customize") + ColorPicker(onColorSelected = { /* update material */ }) + } } } } @@ -78,55 +208,70 @@ State drives the scene. Lifecycle is automatic. One API — every platform. Same composable API — now in spatial computing headsets. -=== "Physics" +=== "iOS (v4.0)" - ```kotlin - Scene(modifier = Modifier.fillMaxSize()) { - val ball = rememberModelInstance(modelLoader, "models/ball.glb") - ball?.let { - val node = ModelNode(modelInstance = it, scaleToUnits = 0.1f) - PhysicsNode(node = node, mass = 1f, restitution = 0.6f, - linearVelocity = Position(0f, 5f, -3f), floorY = 0f) + ```swift + struct ProductViewer: View { + var body: some View { + SceneView { + ModelNode("models/shoe.usdz", scaleToUnits: 1.0) + .playAllAnimations() + LightNode(.directional) + } + .cameraControls(.orbit) } } ``` - Rigid body simulation. Gravity, bounce, collision — no game engine needed. + Same mental model — SwiftUI + RealityKit under the hood. Share your scene graph via Kotlin Multiplatform. -[:octicons-rocket-24: Get started](#get-started){ .md-button .md-button--primary } -[:octicons-book-24: Why SceneView](showcase.md){ .md-button } +[:octicons-arrow-right-24: v4.0 multi-platform roadmap](v4-preview.md){ .md-button } --- -## One API, every surface - -
- -- :octicons-device-mobile-24: **Android** - - --- - - `Scene {}` and `ARScene {}` — Jetpack Compose composables backed by Google Filament and ARCore. Production-ready today. - -- :octicons-device-desktop-24: **XR headsets** +## Ask AI, get a 3D scene - --- - - `XRScene {}` brings the same composable patterns to spatial computing. Your existing code and skills transfer directly. - -- :octicons-globe-24: **Kotlin Multiplatform** - - --- +The most AI-friendly 3D library. Ships with an MCP server and `llms.txt` API reference — so Claude, Cursor, and Copilot always have the current API. - iOS via Filament's Metal backend. Share scene definitions across Android and iOS from one Kotlin codebase. +
+
💬 You describe it → AI writes the code → SceneView renders it
+
+"Add a 3D product viewer to my shopping app. Users should rotate the sneaker model and tap a button to see it in AR in their room." +
+
+
-- :octicons-cpu-24: **Rendering engine** +```kotlin +@Composable +fun ProductDetail(modelPath: String) { + var showAR by remember { mutableStateOf(false) } + val engine = rememberEngine() + val modelLoader = rememberModelLoader(engine) + val model = rememberModelInstance(modelLoader, modelPath) + + if (showAR) { + ARScene(modifier = Modifier.fillMaxSize(), engine = engine, planeRenderer = true, + onSessionUpdated = { _, frame -> /* anchor placement */ } + ) { /* AR content */ } + } else { + Scene(modifier = Modifier.fillMaxWidth().height(350.dp), engine = engine, + cameraManipulator = rememberCameraManipulator() + ) { + model?.let { ModelNode(modelInstance = it, scaleToUnits = 1.0f) } + } + } + Button(onClick = { showAR = !showAR }) { Text(if (showAR) "Back to 3D" else "View in AR") } +} +``` - --- +
+
- Google Filament — physically-based rendering, HDR environment lighting, post-processing. 60fps on mid-range devices. +MCP server included +llms.txt API reference +Works with Claude · Cursor · Copilot -
+[:octicons-arrow-right-24: AI-assisted development](ai-development.md){ .md-button } --- @@ -163,7 +308,12 @@ State drives the scene. Lifecycle is automatic. One API — every platform. ## What you get -### 26+ composable node types +### 26+ composable node types — visual overview + + +
+8 node types: ModelNode, LightNode, CubeNode, AnchorNode, VideoNode, TextNode, PathNode, ViewNode +
@@ -174,6 +324,8 @@ State drives the scene. Lifecycle is automatic. One API — every platform. `ModelNode` loads glTF/GLB with animations, gestures, and automatic scaling. Geometry primitives — `CubeNode`, `SphereNode`, `CylinderNode`, `PlaneNode` — need no asset files. + [:octicons-arrow-right-24: Model loading guide](recipes.md#loading-display) + - :octicons-sun-24: **Lighting & Atmosphere** --- @@ -181,6 +333,8 @@ State drives the scene. Lifecycle is automatic. One API — every platform. `LightNode` (sun, point, spot, directional), `DynamicSkyNode` (time-of-day), `FogNode`, `ReflectionProbeNode`. All driven by Compose state. + [:octicons-arrow-right-24: Lighting recipes](recipes.md#lighting-environment) + - :octicons-image-24: **Media & UI in 3D** --- @@ -188,6 +342,8 @@ State drives the scene. Lifecycle is automatic. One API — every platform. `ImageNode`, `VideoNode` (with chromakey), and `ViewNode` — render **any Composable** directly inside 3D space. Text, buttons, cards — floating in your scene. + [:octicons-arrow-right-24: ViewNode recipes](recipes.md#viewnode-compose-inside-3d-space) + - :octicons-zap-24: **Physics** --- @@ -195,6 +351,8 @@ State drives the scene. Lifecycle is automatic. One API — every platform. `PhysicsNode` — rigid body simulation with gravity, collision, and tap-to-throw. Interactive 3D worlds without a game engine. + [:octicons-arrow-right-24: Physics guide](codelabs/guide-physics.md) + - :octicons-paintbrush-24: **Drawing & Text** --- @@ -202,6 +360,8 @@ State drives the scene. Lifecycle is automatic. One API — every platform. `LineNode`, `PathNode` for 3D polylines and animated paths. `TextNode`, `BillboardNode` for camera-facing labels. + [:octicons-arrow-right-24: Lines & text guide](codelabs/guide-lines-text.md) + - :octicons-eye-24: **AR & spatial** --- @@ -209,55 +369,232 @@ State drives the scene. Lifecycle is automatic. One API — every platform. `AnchorNode`, `AugmentedImageNode`, `AugmentedFaceNode`, `CloudAnchorNode`, `StreetscapeGeometryNode`. Plane detection, geospatial, environmental HDR. -
- -[:octicons-arrow-right-24: Full feature showcase](showcase.md) - ---- - -### Production rendering + [:octicons-arrow-right-24: AR codelab](codelabs/codelab-ar-compose.md) -Built on [Google Filament](https://github.com/google/filament) — the same physically-based -rendering engine used inside Google Search and Google Play Store. - -- **PBR** with metallic/roughness workflow -- **HDR environment lighting** from `.hdr` and `.ktx` files -- **Post-processing**: bloom, depth-of-field, SSAO, fog -- **60fps** on mid-range devices - ---- +- :octicons-cpu-24: **Production rendering — Filament** -### v4.0 — what's next + --- -
+ Built on [Google Filament](https://github.com/google/filament) — PBR, HDR environment lighting, + bloom, depth-of-field, SSAO. 60fps on mid-range devices. -- :octicons-stack-24: **Multiple scenes** + [:octicons-arrow-right-24: Performance guide](performance.md) - --- - - Multiple independent `Scene {}` on one screen — dashboards, feeds, product cards — each with its own camera and environment. +
-- :octicons-mirror-24: **Portal rendering** +[:octicons-arrow-right-24: Full feature showcase](showcase.md) - --- +--- - `PortalNode` — a window into another scene. AR portals, product showcases with custom lighting, level transitions. +### See it in action -- :octicons-iterations-24: **Particles & animation** + +
+
+📱 +Android Phone +Shipping today +
- --- +

Real app screenshots

+ - `ParticleNode` for GPU particles (fire, smoke, sparkles). `AnimationController` for blending, cross-fading, and layering. +

Feature previews

+ +
-- :octicons-plug-24: **Collision detection** + +
+
+📋 +Android Tablet +Shipping today +
+ +
- --- + +
+
+🚗 +Android Automotive +Shipping today +
+ +
- `CollisionNode` — declarative collision detection between scene nodes. No manual raycasting. + +
+ +
+🥽 +XR Headsets +v4.0 +:octicons-arrow-right-24: +
+
+

Same composable API — XRScene { } for spatial computing. Floating Compose UI via ViewNode.

+ +
+ +
+ +
+🍎 +iOS +v4.1 +:octicons-arrow-right-24: +
+
+

Kotlin Multiplatform + Filament Metal backend. Share your scene graph across Android and iOS.

+
-[:octicons-arrow-right-24: v4.0 preview](v4-preview.md) + +
+ +
+🖥️ +TV · Desktop +v4.0 +:octicons-arrow-right-24: +
+
+

Compose Multiplatform opens the door to Android TV, Desktop JVM, and every screen Kotlin reaches.

+ +
--- @@ -289,36 +626,6 @@ rendering engine used inside Google Search and Google Play Store. --- -## Key concepts - -### Nodes are composables - -Every 3D object — models, lights, geometry, cameras — is a `@Composable` function inside `Scene { }`. No manual `addChildNode()` or `destroy()` calls. Nodes enter the scene on composition and are cleaned up when they leave. - -### State drives the scene - -Pass Compose state into node parameters. The scene updates on the next frame. Toggle a `Boolean` to show/hide a node. Animate a `Float` for smooth transitions. Update a `mutableStateOf` to place content in AR. - -### Everything is `remember` - -The Filament engine, model loaders, environment, camera — all are `remember`-ed values with automatic cleanup: - -```kotlin -val engine = rememberEngine() -val modelLoader = rememberModelLoader(engine) -val model = rememberModelInstance(modelLoader, "models/product.glb") -val environment = rememberEnvironment(rememberEnvironmentLoader(engine)) { - createHDREnvironment("environments/sky_2k.hdr")!! -} -// All resources destroyed automatically when composable leaves the tree -``` - -### Thread safety by default - -Filament requires JNI calls on the main thread. `rememberModelInstance` handles the IO-to-main-thread transition automatically. You never think about it. - ---- - ## Samples 15 working sample apps ship with the repository: @@ -328,17 +635,18 @@ Filament requires JNI calls on the main thread. `rememberModelInstance` handles | `model-viewer` | 3D model, HDR environment, orbit camera, animation playback | | `ar-model-viewer` | Tap-to-place, plane detection, pinch/rotate gestures | | `camera-manipulator` | Orbit / pan / zoom camera with gesture hints | -| `gltf-camera` | Cameras imported from a glTF file | | `dynamic-sky` | Time-of-day sun, turbidity, fog controls | -| `reflection-probe` | Metallic surfaces with cubemap reflections | | `physics-demo` | Tap-to-throw balls, collision, gravity | | `post-processing` | Bloom, depth-of-field, SSAO, fog toggles | -| `line-path` | 3D line drawing, gizmos, spirals, animated paths | -| `text-labels` | Camera-facing text labels on 3D objects | | `ar-augmented-image` | Real-world image detection + overlay | | `ar-cloud-anchor` | Persistent cross-device anchors | -| `ar-point-cloud` | ARCore feature point visualization | -| `autopilot-demo` | Autonomous AR demo | +| `ar-point-cloud` | ARCore feature point visualisation | +| `autopilot-demo` | Autonomous driving HUD | +| `gltf-camera` | Cameras imported from a glTF file | +| `line-path` | Animated sine/Lissajous curves with PathNode | +| `text-labels` | Camera-facing 3D text labels (TextNode) | +| `reflection-probe` | Zone-based IBL overrides + material picker | +| `sceneview-demo` | Full showcase: Explore, Showcase, Gallery tabs | --- @@ -366,9 +674,17 @@ Filament requires JNI calls on the main thread. `rememberModelInstance` handles --- -## Community + +
+ +## Start building in 5 minutes + +One Gradle line. No XML. No OpenGL. Just Compose. -[:octicons-comment-discussion-24: Discord](https://discord.gg/UbNDDBTNqb){ .md-button } -[:octicons-mark-github-24: GitHub](https://github.com/SceneView/sceneview-android){ .md-button .md-button--primary } +[:octicons-arrow-right-24: Start building now](quickstart.md){ .md-button .md-button--primary } +[:octicons-comment-discussion-24: Join Discord](https://discord.gg/UbNDDBTNqb){ .md-button } +[:octicons-mark-github-24: Star on GitHub](https://github.com/SceneView/sceneview-android){ .md-button } + +
- + diff --git a/docs/docs/samples.md b/docs/docs/samples.md index 72fdc7561..ed114686b 100644 --- a/docs/docs/samples.md +++ b/docs/docs/samples.md @@ -56,6 +56,8 @@ Use cameras defined inside a glTF file. The scene animates between camera viewpo ### Dynamic Sky +Dynamic Sky sample + Time-of-day sun positioning with turbidity and fog controls. Sunrise, noon, sunset — all driven by a Compose slider. **Demonstrates:** `DynamicSkyNode`, `FogNode`, reactive lighting from Compose state @@ -64,6 +66,8 @@ Time-of-day sun positioning with turbidity and fog controls. Sunrise, noon, suns ### Reflection Probe +Reflection Probe sample + Metallic surfaces with local cubemap reflections that override the global environment. **Demonstrates:** `ReflectionProbeNode`, IBL override, metallic materials @@ -72,6 +76,8 @@ Metallic surfaces with local cubemap reflections that override the global enviro ### Physics Demo +Physics Demo sample + Tap the screen to throw balls. They bounce off the floor and each other with rigid body physics. **Demonstrates:** `PhysicsNode`, gravity, collision detection, tap-to-throw interaction @@ -80,6 +86,8 @@ Tap the screen to throw balls. They bounce off the floor and each other with rig ### Post-Processing +Post-Processing sample + Toggle visual effects: bloom, depth-of-field, SSAO, and fog. See the difference each makes. **Demonstrates:** Filament post-processing pipeline, `View` options, composable toggles @@ -88,6 +96,8 @@ Toggle visual effects: bloom, depth-of-field, SSAO, and fog. See the difference ### Line & Path +Line & Path sample + 3D line drawing, axis gizmos, spiral curves, and animated sine-wave paths. **Demonstrates:** `LineNode`, `PathNode`, `updateGeometry()`, GPU line primitives @@ -96,6 +106,8 @@ Toggle visual effects: bloom, depth-of-field, SSAO, and fog. See the difference ### Text Labels +Text Labels sample + Camera-facing text labels floating above 3D spheres. Tap to cycle text. **Demonstrates:** `TextNode`, `BillboardNode`, Canvas-rendered text in 3D space @@ -151,6 +163,8 @@ Detect a real-world image and overlay 3D content on it. ### AR Cloud Anchor +AR Cloud Anchor sample + Host an anchor to Google Cloud and resolve it on another device. Cross-device AR persistence. **Demonstrates:** `CloudAnchorNode`, anchor hosting/resolving, `CloudAnchorState` @@ -159,7 +173,7 @@ Host an anchor to Google Cloud and resolve it on another device. Cross-device AR ### AR Point Cloud -![AR Point Cloud](screenshots/ar-point-cloud.png){ width=320 } +AR Point Cloud sample Visualize ARCore's feature points as a real-time point cloud. diff --git a/docs/docs/showcase.md b/docs/docs/showcase.md index be391c1b8..ebda9cc24 100644 --- a/docs/docs/showcase.md +++ b/docs/docs/showcase.md @@ -5,6 +5,60 @@ It delivers Filament's physically-based rendering and ARCore's full AR capabilit a declarative API that developers already understand — and v4.0 extends that to XR headsets and iOS via Kotlin Multiplatform. + + --- ## The pitch in 10 seconds @@ -132,6 +186,40 @@ ARScene( ## Real-world use cases + + ### E-commerce: product viewer in 10 lines Replace a static `Image()` with a `Scene {}` on your product detail page: diff --git a/docs/docs/stylesheets/extra.css b/docs/docs/stylesheets/extra.css index b36976fbf..42abcac9b 100644 --- a/docs/docs/stylesheets/extra.css +++ b/docs/docs/stylesheets/extra.css @@ -1,13 +1,477 @@ -/* SceneView docs — custom styles */ +/* ============================================================ + SceneView docs — Material 3 Expressive theme + Ultra-round, bubbly, warm — inspired by M3 Expressive shape language. + Ref: https://m3.material.io/styles/shape/corner-radius-scale + ============================================================ */ +/* --- M3 Expressive Design Tokens --- */ :root { - --md-primary-fg-color: #6c35aa; - --md-primary-fg-color--light: #9c65da; - --md-primary-fg-color--dark: #4a1d8a; - --md-accent-fg-color: #9c27b0; + /* Primary — M3 tonal purple palette */ + --md-primary-fg-color: #6750A4; + --md-primary-fg-color--light: #D0BCFF; + --md-primary-fg-color--dark: #4F378B; + --md-accent-fg-color: #6750A4; + + /* M3 tonal palette — pastel, clean, Google-like */ + --sv-primary: #6750A4; + --sv-on-primary: #FFFFFF; + --sv-primary-container: #EADDFF; + --sv-secondary: #625B71; + --sv-secondary-container: #E8DEF8; + --sv-tertiary: #7D5260; + --sv-tertiary-container: #FFD8E4; + --sv-warm: #625B71; + --sv-warm-container: #F4EFF4; + --sv-surface: #FFFBFE; + --sv-surface-container: #F4EFF4; + --sv-surface-container-high: #E6E1E5; + --sv-on-surface: #1C1B1F; + --sv-on-surface-variant: #49454F; + --sv-outline: #CAC4D0; + --sv-outline-variant: #CAC4D0; + + /* M3 Expressive shape scale — bumped up for maximum roundness + None: 0, XS: 8, S: 16, M: 24, L: 32, XL: 48, Full: 9999 */ + --sv-shape-xs: 12px; + --sv-shape-sm: 20px; + --sv-shape-md: 28px; + --sv-shape-lg: 36px; + --sv-shape-xl: 48px; + --sv-shape-xxl: 56px; + --sv-shape-full: 9999px; + + /* Gradients — M3 tonal, clean */ + --sv-gradient-hero: linear-gradient(135deg, #FFFBFE 0%, #F6F2FF 40%, #FFFBFE 100%); + --sv-gradient-primary: linear-gradient(135deg, #6750A4 0%, #7F67BE 100%); + --sv-gradient-warm: linear-gradient(135deg, #6750A4 0%, #7D5260 100%); + --sv-gradient-cool: linear-gradient(135deg, #6750A4 0%, #006B5E 100%); +} + +/* Dark mode adjustments */ +[data-md-color-scheme="slate"] { + --sv-primary: #A78BFA; + --sv-primary-container: #2E1065; + --sv-secondary: #F9A8D4; + --sv-secondary-container: #831843; + --sv-tertiary: #67E8F9; + --sv-tertiary-container: #164E63; + --sv-warm: #FB923C; + --sv-warm-container: #431407; + --sv-surface: #1C1B1F; + --sv-surface-container: #242220; + --sv-surface-container-high: #2E2B28; + --sv-on-surface: #E6E1E5; + --sv-on-surface-variant: #CAC4D0; + --sv-outline: #49454F; + --sv-outline-variant: #332D2A; + --sv-gradient-hero: linear-gradient(135deg, #2A1F1A 0%, #2D1B2E 40%, #1A2030 100%); +} + +/* ---- Typography — M3 Expressive uses bolder, more playful type ---- */ + +.md-typeset h1 { + font-weight: 800; + letter-spacing: -0.02em; + line-height: 1.15; +} + +.md-typeset h2 { + font-weight: 700; + letter-spacing: -0.01em; +} + +/* ================================================================ + GLOBAL M3 EXPRESSIVE ROUNDNESS — override MkDocs Material defaults + ================================================================ */ + +/* Header — rounded bottom edge */ +.md-header { + border-radius: 0 0 var(--sv-shape-md) var(--sv-shape-md); +} + +/* Search bar — fully rounded pill */ +.md-search__form { + border-radius: var(--sv-shape-full) !important; +} + +.md-search__input { + border-radius: var(--sv-shape-full) !important; +} + +/* Search results dropdown */ +.md-search__output { + border-radius: var(--sv-shape-lg) !important; + overflow: hidden; +} + +/* Navigation tabs — pill-shaped */ +.md-tabs { + border-radius: 0 0 var(--sv-shape-sm) var(--sv-shape-sm); +} + +.md-tabs__link { + border-radius: var(--sv-shape-full) !important; + margin: 4px 2px; + transition: background 0.2s ease, transform 0.15s ease; +} + +.md-tabs__link:hover { + background: rgba(103, 80, 164, 0.08); +} + +.md-tabs__link--active { + background: var(--sv-primary-container) !important; + border-bottom: none; +} + +[data-md-color-scheme="slate"] .md-tabs__link--active { + background: rgba(103, 80, 164, 0.15) !important; +} + +/* Sidebar navigation items — rounded */ +.md-nav__link { + border-radius: var(--sv-shape-full) !important; + padding-left: 12px !important; + padding-right: 12px !important; + transition: background 0.2s ease; +} + +.md-nav__link:hover { + background: rgba(103, 80, 164, 0.06); +} + +.md-nav__link--active { + background: var(--sv-primary-container) !important; + color: var(--sv-primary) !important; + font-weight: 600; +} + +[data-md-color-scheme="slate"] .md-nav__link--active { + background: rgba(103, 80, 164, 0.15) !important; + color: var(--sv-primary) !important; +} + +/* Content area — soft rounded container */ +.md-content { + border-radius: var(--sv-shape-lg); +} + +/* Tables — rounded */ +.md-typeset table:not([class]) { + font-size: 0.88rem; + border-radius: var(--sv-shape-md) !important; + overflow: hidden; + border: 1px solid var(--sv-outline-variant); +} + +.md-typeset table:not([class]) th { + background: var(--sv-surface-container); +} + +/* Source/edit button — pill */ +.md-content__button { + border-radius: var(--sv-shape-full) !important; +} + +/* Tag/label chips — pill */ +.md-typeset .md-tag { + border-radius: var(--sv-shape-full) !important; +} + +/* Footer — rounded top */ +.md-footer { + border-radius: var(--sv-shape-md) var(--sv-shape-md) 0 0; +} + +/* Back-to-top button — fully round */ +.md-top { + border-radius: var(--sv-shape-full) !important; +} + +/* Dialog/tooltip — rounded */ +.md-dialog { + border-radius: var(--sv-shape-lg) !important; +} + +/* Clipboard button — rounded */ +.md-clipboard { + border-radius: var(--sv-shape-sm) !important; +} + +/* Version selector — pill */ +.md-version__current { + border-radius: var(--sv-shape-full) !important; +} + +/* ---- Hero section ---- */ + +.hero-tagline { + font-size: 1.3rem; + font-weight: 400; + color: var(--sv-on-surface-variant); + margin-top: -0.25rem; + margin-bottom: 1.5rem; + line-height: 1.6; + animation: spring-in 0.4s ease both; + animation-delay: 0.1s; +} + +/* Platform badges row */ +.platform-badges { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin: 1rem 0 1.5rem; + justify-content: center; + animation: spring-in 0.4s ease both; + animation-delay: 0.15s; +} + +.platform-badge { + display: inline-flex; + align-items: center; + gap: 0.4rem; + padding: 0.45rem 1.1rem; + border-radius: var(--sv-shape-full); + font-size: 0.82rem; + font-weight: 600; + border: none; + color: var(--sv-on-surface); + background: var(--sv-surface-container); + border: 1.5px solid var(--sv-outline); + transition: background 0.2s ease, border-color 0.2s ease; +} + +.platform-badge:hover { + background: var(--sv-primary-container); + border-color: var(--sv-primary); +} + +.platform-badge small { + font-size: 0.7rem; + font-weight: 500; + color: var(--sv-primary); + opacity: 0.8; +} + +.platform-badge--android { background: #EADDFF; color: #21005D; border-color: #D0BCFF; } +.platform-badge--ios { background: #FFD8E4; color: #31111D; border-color: #EFB8C8; } +.platform-badge--xr { background: #D0E8FF; color: #001D36; border-color: #A8C8E8; } +.platform-badge--react { background: #DDFAFF; color: #003544; border-color: #B0E0F0; } +.platform-badge--flutter { background: #D0F0FF; color: #002F49; border-color: #A4D4F0; } +.platform-badge--desktop { background: #D0F0D0; color: #002200; border-color: #A4D4A4; } + +/* "Made with SceneView" callout */ +.made-with-sv { + display: inline-flex; + align-items: center; + gap: 0.5rem; + background: var(--sv-primary-container); + color: var(--sv-primary); + font-size: 0.8rem; + font-weight: 600; + padding: 0.4rem 1.1rem; + border-radius: var(--sv-shape-full); + margin-top: 0.5rem; + letter-spacing: 0.02em; +} + +[data-md-color-scheme="slate"] .made-with-sv { + background: var(--sv-primary-container); + color: var(--sv-primary); +} + +/* ---- Interactive demo container ---- */ + +.demo-container { + background: var(--sv-gradient-hero); + border-radius: var(--sv-shape-xxl); + padding: 2.5rem; + margin: 1.5rem 0 2rem; + text-align: center; + position: relative; + overflow: hidden; +} + +[data-md-color-scheme="slate"] .demo-container { + background: var(--sv-gradient-hero); +} + +.demo-container model-viewer { + border-radius: var(--sv-shape-xl) !important; + background: transparent !important; +} + +/* ---- LLM Prompt Showcase ---- */ + +.prompt-showcase { + background: var(--sv-gradient-hero); + border-radius: var(--sv-shape-xxl); + padding: 2.5rem; + margin: 1.5rem 0; + position: relative; + border: 1px solid var(--sv-outline-variant); +} + +.prompt-showcase__header { + display: flex; + align-items: center; + gap: 0.75rem; + margin-bottom: 1rem; + font-weight: 700; + font-size: 0.9rem; + color: var(--sv-primary); +} + +.prompt-showcase__prompt { + background: var(--sv-surface); + border: 1px solid var(--sv-outline-variant); + border-radius: var(--sv-shape-xl); + padding: 1.25rem 1.5rem; + font-size: 0.92rem; + color: var(--sv-on-surface); + margin-bottom: 1rem; + line-height: 1.6; + font-style: italic; +} + +.prompt-showcase__arrow { + text-align: center; + font-size: 1.5rem; + color: var(--sv-primary); + margin: 0.5rem 0; +} + +.prompt-showcase__result { + background: var(--sv-surface); + border: 1px solid var(--sv-outline-variant); + border-radius: var(--sv-shape-xl); + padding: 0; + overflow: hidden; +} + +.prompt-showcase__result pre { + margin: 0 !important; + border-radius: var(--sv-shape-xl) !important; +} + +/* ---- Grid cards — M3 Expressive with XXL radius, bubbly ---- */ + +.grid.cards > ul { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 1.25rem; + list-style: none; + padding: 0; +} + +.grid.cards > ul > li { + background: var(--sv-surface-container); + border: 1px solid var(--sv-outline-variant); + border-radius: var(--sv-shape-xl); + padding: 2rem; + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +.grid.cards > ul > li:hover { + border-color: var(--sv-primary); + box-shadow: 0 2px 12px rgba(103, 80, 164, 0.08); +} + +/* Card icons — colorful, not monochrome */ +.grid.cards .twemoji svg { + fill: var(--sv-primary); + width: 2rem; + height: 2rem; +} + +/* ---- Buttons — M3 Expressive, fully rounded pill ---- */ + +.md-typeset .md-button { + border-radius: var(--sv-shape-full) !important; + padding: 0.65rem 2rem; + font-weight: 600; + letter-spacing: 0.01em; + transition: background 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease; +} + +.md-typeset .md-button:hover { + box-shadow: 0 1px 6px rgba(103, 80, 164, 0.12); +} + +.md-typeset .md-button--primary { + background: var(--sv-primary) !important; + border-color: transparent !important; + color: white !important; +} + +.md-typeset .md-button--primary:hover { + background: #7F67BE !important; + box-shadow: 0 1px 8px rgba(103, 80, 164, 0.2); +} + +/* ---- Feature highlight chips ---- */ + +.feature-chip { + display: inline-flex; + align-items: center; + gap: 0.3rem; + padding: 0.35rem 1rem; + border-radius: var(--sv-shape-full); + font-size: 0.78rem; + font-weight: 600; + margin: 0.2rem; +} + +.feature-chip--primary { + background: var(--sv-primary-container); + color: var(--sv-primary); +} + +.feature-chip--secondary { + background: var(--sv-secondary-container); + color: var(--sv-secondary); +} + +.feature-chip--tertiary { + background: var(--sv-tertiary-container); + color: var(--sv-tertiary); +} + +.feature-chip--warm { + background: var(--sv-warm-container); + color: var(--sv-warm); +} + +/* ---- "What you see" banner ---- */ + +.live-badge { + display: inline-flex; + align-items: center; + gap: 0.4rem; + background: linear-gradient(135deg, #10B981 0%, #059669 100%); + color: white; + font-size: 0.75rem; + font-weight: 700; + padding: 0.35rem 1rem; + border-radius: var(--sv-shape-full); + text-transform: uppercase; + letter-spacing: 0.05em; + animation: pulse-badge 2s ease-in-out infinite; +} + +@keyframes pulse-badge { + 0%, 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.3); } + 50% { box-shadow: 0 0 0 8px rgba(16, 185, 129, 0); } +} + +/* ---- Section dividers — softer ---- */ + +.md-typeset hr { + border-color: var(--sv-outline-variant); } -/* Force all inline emoji/icons to monochrome tinted with theme color */ +/* ---- Force all inline emoji/icons to monochrome tinted with theme color ---- */ .md-typeset .twemoji svg, .md-typeset .gemoji img, .md-typeset .emojione svg, @@ -16,40 +480,24 @@ filter: none; } -/* Grid card icons — tinted with theme primary */ -.grid.cards .twemoji svg { - fill: var(--md-primary-fg-color); - width: 2rem; - height: 2rem; -} - /* Buttons — icon inherits button text color */ .md-button .twemoji svg { fill: currentColor; } -/* Hero tagline on homepage */ -.hero-tagline { - font-size: 1.25rem; - color: var(--md-default-fg-color--light); - margin-top: -0.5rem; - margin-bottom: 1.5rem; -} - -/* Footer note */ +/* ---- Footer note ---- */ .footer-note { font-size: 0.85rem; - color: var(--md-default-fg-color--lighter); + color: var(--sv-on-surface-variant); text-align: center; margin-top: 2rem; } -/* Step numbers for codelab-style headers */ +/* ---- Codelab step counters ---- */ .md-content h2 { counter-increment: step; } -/* Only show step counters on codelab pages */ .md-content[data-page="codelabs"] h2 { display: flex; align-items: center; @@ -58,13 +506,13 @@ .md-content[data-page="codelabs"] h2::before { content: counter(step); - background: var(--md-primary-fg-color); + background: var(--sv-gradient-primary); color: white; font-size: 0.9rem; font-weight: 700; - min-width: 32px; - height: 32px; - border-radius: 50%; + min-width: 40px; + height: 40px; + border-radius: var(--sv-shape-full); display: flex; align-items: center; justify-content: center; @@ -75,54 +523,809 @@ counter-reset: step; } -/* Code blocks */ +/* ---- Code blocks — GitHub / VS Code-inspired, ultra-rounded ---- */ .highlight code { font-size: 0.85rem; } -/* Card grid */ -.grid.cards > ul { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); - gap: 1rem; - list-style: none; - padding: 0; +.md-typeset pre > code { + border-radius: var(--sv-shape-lg) !important; } -.grid.cards > ul > li { - border: 1px solid var(--md-default-fg-color--lightest); - border-radius: 8px; - padding: 1.5rem; - transition: box-shadow 0.2s; +/* Light mode: GitHub Light — slightly warmed */ +:root { + --sv-code-bg: #FAF8F6; + --sv-code-fg: #24292F; + --sv-code-comment: #6E7781; + --sv-code-keyword: #CF222E; + --sv-code-string: #0A3069; + --sv-code-function: #8250DF; + --sv-code-type: #953800; + --sv-code-number: #0550AE; + --sv-code-operator: #CF222E; + --sv-code-property: #0550AE; + --sv-code-annotation: #8250DF; } -.grid.cards > ul > li:hover { - box-shadow: 0 4px 16px rgba(108, 53, 170, 0.15); +/* Dark mode: VS Code Dark+ */ +[data-md-color-scheme="slate"] { + --sv-code-bg: #1E1E1E; + --sv-code-fg: #D4D4D4; + --sv-code-comment: #6A9955; + --sv-code-keyword: #569CD6; + --sv-code-string: #CE9178; + --sv-code-function: #DCDCAA; + --sv-code-type: #4EC9B0; + --sv-code-number: #B5CEA8; + --sv-code-operator: #D4D4D4; + --sv-code-property: #9CDCFE; + --sv-code-annotation: #DCDCAA; +} + +/* Apply the code theme */ +.highlight pre, +.highlight code, +.md-typeset pre { + background: var(--sv-code-bg) !important; + color: var(--sv-code-fg) !important; +} + +/* Code block container — ultra-rounded with soft border */ +.md-typeset .highlight { + border-radius: var(--sv-shape-lg); + overflow: hidden; + border: 1px solid var(--sv-outline-variant); } -/* Hero image centering */ +/* Pygments token overrides */ +.highlight .k, .highlight .kd, .highlight .kn, +.highlight .kp, .highlight .kr, .highlight .kt, +.highlight .kc { color: var(--sv-code-keyword) !important; } + +.highlight .s, .highlight .s1, .highlight .s2, +.highlight .sb, .highlight .sc, .highlight .sd, +.highlight .sh, .highlight .sx { color: var(--sv-code-string) !important; } + +.highlight .nf, .highlight .fm, .highlight .nb { color: var(--sv-code-function) !important; } + +.highlight .nc, .highlight .nn, .highlight .no { color: var(--sv-code-type) !important; } + +.highlight .mi, .highlight .mf, .highlight .mh, +.highlight .mo, .highlight .il { color: var(--sv-code-number) !important; } + +.highlight .o, .highlight .ow { color: var(--sv-code-operator) !important; } + +.highlight .c, .highlight .c1, .highlight .cm, +.highlight .cs, .highlight .cp, .highlight .ch { color: var(--sv-code-comment) !important; font-style: italic; } + +.highlight .na, .highlight .py { color: var(--sv-code-property) !important; } + +.highlight .nd, .highlight .ni { color: var(--sv-code-annotation) !important; } + +.highlight .p { color: var(--sv-code-fg) !important; } + +/* Line numbers — subtle */ +.highlight .linenos { + color: var(--sv-code-comment) !important; + opacity: 0.6; +} + +/* ---- Hero image centering ---- */ .md-content img[width] { display: block; margin: 0 auto 2rem; } -/* Feature matrix — highlight SceneView column */ +/* ---- Admonitions — bubbly, very round ---- */ +.md-typeset .admonition, +.md-typeset details { + border-radius: var(--sv-shape-lg) !important; + overflow: hidden; +} + +.md-typeset .admonition-title, +.md-typeset summary { + border-radius: var(--sv-shape-lg) var(--sv-shape-lg) 0 0 !important; +} + +.md-typeset .admonition.question { + border-color: var(--sv-primary); +} + +/* ---- Tabs — M3 Expressive pill-style ---- */ +.md-typeset .tabbed-labels { + border-radius: var(--sv-shape-full); + background: var(--sv-surface-container); + padding: 4px; + display: inline-flex; + gap: 4px; + border: 1px solid var(--sv-outline-variant); +} + +.md-typeset .tabbed-labels > label { + border-radius: var(--sv-shape-full) !important; + font-weight: 600; + padding: 0.4rem 1.2rem; + transition: background 0.2s ease, color 0.2s ease; +} + +.md-typeset .tabbed-labels > label:hover { + background: rgba(103, 80, 164, 0.08); +} + +.md-typeset .tabbed-labels > .tabbed-label--active, +.md-typeset input:checked + .tabbed-labels > label[for] { + background: var(--sv-primary) !important; + color: white !important; +} + +/* Tab content panel */ +.md-typeset .tabbed-content { + border-radius: 0 0 var(--sv-shape-lg) var(--sv-shape-lg); +} + +/* ---- Navigation tab active indicator ---- */ +.md-tabs__link--active { + border-bottom: none; +} + +/* ---- Feature matrix — highlight SceneView column ---- */ table th:nth-child(2), table td:nth-child(2) { font-weight: 500; } -/* Admonition question style for FAQ */ -.md-typeset .admonition.question { - border-color: var(--md-primary-fg-color); +/* ---- Platform grid — larger, more visual, ultra-round ---- */ + +.platform-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 1.25rem; + margin: 1.5rem 0; } -/* Cheatsheet — compact tables */ -.md-typeset table:not([class]) { +.platform-card { + background: var(--sv-surface-container); + border: 1px solid var(--sv-outline-variant); + border-radius: var(--sv-shape-xxl); + padding: 2rem; + text-align: center; + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +.platform-card:hover { + border-color: var(--sv-primary); + box-shadow: 0 2px 12px rgba(103, 80, 164, 0.08); +} + +.platform-card__icon { + font-size: 2.75rem; + margin-bottom: 0.75rem; +} + +.platform-card__title { + font-weight: 700; + font-size: 1.1rem; + margin-bottom: 0.4rem; + color: var(--sv-on-surface); +} + +.platform-card__status { + font-size: 0.78rem; + font-weight: 600; + padding: 0.25rem 0.8rem; + border-radius: var(--sv-shape-full); + display: inline-block; + margin-bottom: 0.5rem; +} + +.platform-card__status--ready { + background: #DCFCE7; + color: #166534; +} + +.platform-card__status--coming { + background: var(--sv-primary-container); + color: var(--sv-primary); +} + +[data-md-color-scheme="slate"] .platform-card__status--ready { + background: #052E16; + color: #86EFAC; +} + +[data-md-color-scheme="slate"] .platform-card__status--coming { + background: var(--sv-primary-container); + color: var(--sv-primary); +} + +.platform-card__desc { font-size: 0.88rem; + color: var(--sv-on-surface-variant); + line-height: 1.5; +} + +/* ---- Stat pills row ---- */ + +.stat-row { + display: flex; + flex-wrap: wrap; + gap: 0.75rem; + justify-content: center; + margin: 1.5rem 0; + animation: spring-in 0.4s ease both; + animation-delay: 0.2s; +} + +.stat-pill { + display: inline-flex; + align-items: center; + gap: 0.4rem; + background: var(--sv-surface-container); + border: 1px solid var(--sv-outline-variant); + border-radius: var(--sv-shape-full); + padding: 0.55rem 1.4rem; + font-size: 0.85rem; + color: var(--sv-on-surface); +} + +.stat-pill strong { + color: var(--sv-primary); +} + +/* Color-coded stat pills */ +.stat-pill:nth-child(1) { border-left: 4px solid var(--sv-primary); } +.stat-pill:nth-child(2) { border-left: 4px solid var(--sv-secondary); } +.stat-pill:nth-child(3) { border-left: 4px solid var(--sv-warm); } +.stat-pill:nth-child(4) { border-left: 4px solid #10B981; } + +.stat-pill:nth-child(1) strong { color: var(--sv-primary); } +.stat-pill:nth-child(2) strong { color: var(--sv-secondary); } +.stat-pill:nth-child(3) strong { color: var(--sv-warm); } +.stat-pill:nth-child(4) strong { color: #10B981; } + +/* ---- Tech ecosystem logo bar ---- */ + +.tech-logos { + display: flex; + flex-wrap: wrap; + gap: 0.75rem; + justify-content: center; + align-items: center; + margin: 1rem 0 0.5rem; + padding: 1rem 0; +} + +.tech-logo { + display: inline-flex; + align-items: center; + gap: 0.35rem; + font-size: 0.82rem; + font-weight: 600; + color: var(--sv-on-surface-variant); + padding: 0.4rem 1rem; + border-radius: var(--sv-shape-full); + background: var(--sv-surface-container); + border: 1px solid var(--sv-outline-variant); + letter-spacing: 0.01em; + transition: color 0.2s ease, border-color 0.2s ease, transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1); +} + +.tech-logo:hover { + color: var(--sv-primary); + border-color: var(--sv-primary); +} + +/* ---- Industry cards — visual-first, ultra-round ---- */ + +.industry-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 1.5rem; + margin: 2rem 0; +} + +.industry-card { + background: var(--sv-surface); + border: 1px solid var(--sv-outline-variant); + border-radius: var(--sv-shape-xxl); + overflow: hidden; + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +.industry-card:hover { + border-color: var(--sv-primary); + box-shadow: 0 2px 12px rgba(103, 80, 164, 0.08); +} + +.industry-card__img { + width: 100%; + height: auto; + display: block; +} + +.industry-card__content { + padding: 1.5rem 1.75rem 1.75rem; +} + +.industry-card__content h3 { + font-weight: 700; + font-size: 1.1rem; + margin: 0 0 0.5rem; + color: var(--sv-on-surface); +} + +.industry-card__content p { + font-size: 0.9rem; + color: var(--sv-on-surface-variant); + line-height: 1.6; + margin: 0; +} + +.industry-card__content code { + font-size: 0.82rem; + background: var(--sv-surface-container); + padding: 0.15em 0.4em; + border-radius: var(--sv-shape-xs); +} + +/* ---- Bottom CTA — strong, visually distinct, ultra-round ---- */ + +.bottom-cta { + background: var(--sv-gradient-hero); + border-radius: var(--sv-shape-xxl); + padding: 3.5rem 2.5rem; + text-align: center; + margin: 2rem 0; + border: 1px solid var(--sv-outline-variant); +} + +[data-md-color-scheme="slate"] .bottom-cta { + background: var(--sv-gradient-hero); + border-color: var(--sv-outline); +} + +.bottom-cta h2 { + margin-top: 0 !important; + font-size: 1.8rem; + font-weight: 800; +} + +.bottom-cta p { + color: var(--sv-on-surface-variant); + font-size: 1.05rem; + margin-bottom: 1.5rem; +} + +/* ---- Tooltips — rounded ---- */ +.md-typeset .md-tooltip { + border-radius: var(--sv-shape-md) !important; +} + +/* ---- Annotation popups — rounded ---- */ +.md-typeset .md-annotation__index { + border-radius: var(--sv-shape-full) !important; +} + +/* ---- Better inline code readability — rounded pill ---- */ +.md-typeset code:not(.highlight code) { + padding: 0.2em 0.5em; + border-radius: var(--sv-shape-sm); + background: var(--sv-surface-container); +} + +/* ---- Device sections — grouped by OS/form-factor ---- */ + +.device-section { + margin: 1.5rem 0 2rem; + padding: 1.5rem; + background: var(--sv-surface-container); + border-radius: var(--sv-shape-xxl); + border: 1px solid var(--sv-outline-variant); +} + +[data-md-color-scheme="slate"] .device-section { + background: var(--sv-surface-container); +} + +.device-section__header { + display: flex; + align-items: center; + gap: 0.6rem; + margin-bottom: 0.75rem; +} + +.device-section__icon { + font-size: 1.5rem; + line-height: 1; +} + +.device-section__title { + font-size: 1.1rem; + font-weight: 700; + color: var(--sv-on-surface); +} + +.device-section__badge { + font-size: 0.72rem; + font-weight: 600; + padding: 0.2rem 0.7rem; + border-radius: var(--sv-shape-full); + margin-left: 0.25rem; +} + +.device-section__badge--ready { + background: #DCFCE7; + color: #166534; +} + +.device-section__badge--coming { + background: var(--sv-primary-container); + color: var(--sv-primary); +} + +[data-md-color-scheme="slate"] .device-section__badge--ready { + background: #052E16; + color: #86EFAC; +} + +[data-md-color-scheme="slate"] .device-section__badge--coming { + background: var(--sv-primary-container); + color: var(--sv-primary); +} + +.device-section__desc { + font-size: 0.9rem; + color: var(--sv-on-surface-variant); + line-height: 1.6; + margin: 0; +} + +.device-section__desc code { + font-size: 0.82rem; + background: var(--sv-surface); + padding: 0.15em 0.4em; + border-radius: var(--sv-shape-xs); +} + +/* Clickable device sections */ +.device-section--clickable { + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +.device-section--clickable:hover { + border-color: var(--sv-primary); + box-shadow: 0 4px 20px rgba(103, 80, 164, 0.1); +} + +.device-section__link { + text-decoration: none !important; + color: inherit !important; + display: block; +} + +.device-section__arrow { + margin-left: auto; + opacity: 0; + transition: opacity 0.2s ease, transform 0.2s ease; + color: var(--sv-primary); +} + +.device-section--clickable:hover .device-section__arrow { + opacity: 1; + transform: translateX(4px); +} + +/* Nested showcase gallery inside device section */ +.device-section .showcase-gallery { + margin: 0.5rem -0.5rem 0; + padding-bottom: 0.5rem; +} + +/* Device section subtitles */ +.device-section__subtitle { + font-size: 0.78rem; + font-weight: 600; + color: var(--sv-on-surface-variant); + text-transform: uppercase; + letter-spacing: 0.05em; + margin: 0.75rem 0 0; +} + +/* Real screenshot images (PNG, need object-fit) */ +.showcase-item__img--screenshot { + object-fit: cover; + object-position: top; + height: 340px; +} + +/* Wide showcase items (landscape tablets, automotive HUDs) */ +.showcase-item--wide { + flex: 0 0 340px; +} + +.showcase-item__img--landscape { + border-radius: var(--sv-shape-xl) !important; + aspect-ratio: 4 / 3; + object-fit: cover; +} + +/* ---- Showcase gallery — ultra-round device screenshots ---- */ + +.showcase-gallery { + display: flex; + gap: 1.25rem; + overflow-x: auto; + scroll-snap-type: x mandatory; + padding: 1rem 0 1.5rem; + margin: 1.5rem -0.5rem; + -webkit-overflow-scrolling: touch; + scrollbar-width: thin; + scrollbar-color: var(--sv-outline-variant) transparent; +} + +.showcase-gallery::-webkit-scrollbar { + height: 6px; +} + +.showcase-gallery::-webkit-scrollbar-thumb { + background: var(--sv-outline-variant); + border-radius: var(--sv-shape-full); +} + +.showcase-item { + flex: 0 0 220px; + scroll-snap-align: center; + text-align: center; + transition: transform 0.2s ease; +} + +.showcase-item:hover { + transform: translateY(-2px); +} + +.showcase-item__img { + width: 100%; + height: auto; + border-radius: var(--sv-shape-xxl); + box-shadow: 0 12px 40px rgba(103, 80, 164, 0.12); + transition: box-shadow 0.3s ease; + border: 1px solid var(--sv-outline-variant); } -/* Mobile: full-width code blocks */ +.showcase-item:hover .showcase-item__img { + box-shadow: 0 20px 56px rgba(103, 80, 164, 0.2); +} + +[data-md-color-scheme="slate"] .showcase-item__img { + box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3); + border-color: var(--sv-outline); +} + +[data-md-color-scheme="slate"] .showcase-item:hover .showcase-item__img { + box-shadow: 0 20px 56px rgba(103, 80, 164, 0.25); +} + +.showcase-item__label { + margin-top: 0.75rem; + font-weight: 700; + font-size: 0.9rem; + color: var(--sv-on-surface); +} + +.showcase-item__desc { + font-size: 0.78rem; + color: var(--sv-on-surface-variant); + line-height: 1.4; + margin-top: 0.2rem; +} + +/* ---- Smooth scrolling ---- */ +html { + scroll-behavior: smooth; +} + +/* ---- Visual showcase wall — large illustration cards ---- */ + +.visual-wall { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1.5rem; + margin: 2rem 0; +} + +.visual-card { + background: var(--sv-surface); + border: 1px solid var(--sv-outline); + border-radius: var(--sv-shape-xxl); + overflow: hidden; + position: relative; + transition: border-color 0.2s ease; +} + +.visual-card:hover { + border-color: var(--sv-primary); +} + +.visual-card__img { + width: 100%; + height: auto; + display: block; +} + +.visual-card__badge { + position: absolute; + top: 12px; + right: 12px; + background: rgba(28, 27, 31, 0.82); + color: white; + font-size: 0.68rem; + font-weight: 600; + padding: 0.25rem 0.7rem; + border-radius: var(--sv-shape-full); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + border: 1px solid rgba(255, 255, 255, 0.12); + letter-spacing: 0.02em; +} + +.visual-card h3 { + font-weight: 700; + font-size: 1rem; + margin: 0.75rem 1.25rem 0.25rem; + color: var(--sv-on-surface); +} + +.visual-card p { + font-size: 0.85rem; + color: var(--sv-on-surface-variant); + line-height: 1.5; + margin: 0 1.25rem 1.25rem; +} + +.visual-card p code { + font-size: 0.78rem; + background: var(--sv-surface-container); + padding: 0.12em 0.4em; + border-radius: var(--sv-shape-xs); +} + +/* "Made with SceneView" badge on screenshot items */ +.showcase-item__wrapper { + position: relative; + display: inline-block; +} + +.showcase-item__wrapper .showcase-item__img { + display: block; +} + +.showcase-item__made-badge { + position: absolute; + bottom: 10px; + left: 50%; + transform: translateX(-50%); + background: rgba(28, 27, 31, 0.82); + color: white; + font-size: 0.62rem; + font-weight: 600; + padding: 0.2rem 0.6rem; + border-radius: var(--sv-shape-full); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + border: 1px solid rgba(255, 255, 255, 0.12); + white-space: nowrap; + letter-spacing: 0.02em; +} + +/* ---- Infographic banners ---- */ +.infographic { + text-align: center; + margin: 2rem 0; +} + +.infographic img { + width: 100%; + max-width: 800px; + height: auto; + border-radius: var(--sv-shape-xl); +} + +.infographic--small img { + max-width: 480px; +} + +/* ---- M3-style entrance animations ---- */ +@keyframes spring-in { + 0% { transform: translateY(12px); opacity: 0; } + 100% { transform: translateY(0); opacity: 1; } +} + +@keyframes fade-in { + 0% { opacity: 0; } + 100% { opacity: 1; } +} + +/* Staggered entrance for device sections */ +.device-section { + animation: spring-in 0.4s ease both; +} +.device-section:nth-child(1) { animation-delay: 0s; } +.device-section:nth-child(2) { animation-delay: 0.08s; } +.device-section:nth-child(3) { animation-delay: 0.16s; } +.device-section:nth-child(4) { animation-delay: 0.24s; } +.device-section:nth-child(5) { animation-delay: 0.32s; } +.device-section:nth-child(6) { animation-delay: 0.4s; } + +/* Staggered entrance for visual wall */ +.visual-card { + animation: spring-in 0.4s ease both; +} +.visual-card:nth-child(1) { animation-delay: 0s; } +.visual-card:nth-child(2) { animation-delay: 0.06s; } +.visual-card:nth-child(3) { animation-delay: 0.12s; } +.visual-card:nth-child(4) { animation-delay: 0.18s; } + +/* Entrance for showcase items */ +.showcase-item { + animation: spring-in 0.3s ease both; +} + +/* Infographic entrance */ +.infographic { + animation: fade-in 0.5s ease both; +} + +/* ---- Try Demo page ---- */ + +.try-download-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1.5rem; + margin: 1.5rem 0; +} + +.try-download-card { + background: var(--sv-surface); + border: 1px solid var(--sv-outline-variant); + border-radius: var(--sv-shape-xxl); + padding: 2rem; + text-align: center; +} + +.try-download-card h3 { + margin-top: 0; + font-weight: 700; +} + +.try-download-note { + font-size: 0.78rem; + color: var(--sv-on-surface-variant); + margin-top: 0.75rem; +} + +.try-demo-features { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 1rem; + margin: 1.5rem 0; +} + +.try-feature { + background: var(--sv-surface-container); + border-radius: var(--sv-shape-xl); + padding: 1.25rem; + text-align: center; + font-size: 0.85rem; + line-height: 1.5; +} + +.try-feature strong { + color: var(--sv-primary); + font-size: 1rem; +} + +/* ---- Mobile responsive ---- */ @media screen and (max-width: 76.1875em) { .md-content .highlight pre { margin-left: -0.8rem; @@ -130,24 +1333,70 @@ table td:nth-child(2) { border-radius: 0; } - /* Stack grid cards on small screens */ .grid.cards > ul { grid-template-columns: 1fr; } -} -/* Smooth scrolling */ -html { - scroll-behavior: smooth; -} + .platform-badges { + justify-content: center; + } -/* Better inline code readability */ -.md-typeset code:not(.highlight code) { - padding: 0.1em 0.35em; - border-radius: 3px; + .demo-container { + padding: 1.25rem; + border-radius: var(--sv-shape-xl); + } + + .industry-grid { + grid-template-columns: 1fr; + } + + .visual-wall { + grid-template-columns: 1fr; + } + + .try-download-grid { + grid-template-columns: 1fr; + } + + .try-demo-features { + grid-template-columns: repeat(2, 1fr); + } + + .platform-grid { + grid-template-columns: 1fr 1fr; + } + + .bottom-cta { + padding: 2rem 1.5rem; + border-radius: var(--sv-shape-xl); + } + + .prompt-showcase { + border-radius: var(--sv-shape-xl); + padding: 1.5rem; + } + + /* Don't round header/footer on mobile — full-width */ + .md-header { + border-radius: 0; + } + + .md-footer { + border-radius: 0; + } } -/* Navigation tab active indicator */ -.md-tabs__link--active { - border-bottom: 2px solid var(--md-accent-fg-color); +@media screen and (max-width: 36em) { + .platform-grid { + grid-template-columns: 1fr; + } + + .stat-row { + gap: 0.5rem; + } + + .stat-pill { + font-size: 0.78rem; + padding: 0.4rem 0.8rem; + } } diff --git a/docs/docs/try.md b/docs/docs/try.md new file mode 100644 index 000000000..1385a2e71 --- /dev/null +++ b/docs/docs/try.md @@ -0,0 +1,139 @@ +# Try SceneView + +Get the demo app running on your device in under a minute. + +--- + +## Option 1 — One command (recommended) + +Clone the repo and run: + +```bash +git clone https://github.com/SceneView/sceneview-android.git +cd sceneview-android +./try-demo +``` + +That's it. The script builds the demo app and installs it on your connected Android device. + +!!! tip "Requirements" + - Android device with **USB debugging** enabled + - **Java 17+** installed + - **adb** on your PATH (comes with Android Studio) + +### Try a specific sample + +```bash +./try-demo --sample ar-model-viewer # AR tap-to-place +./try-demo --sample physics-demo # Bouncing spheres +./try-demo --sample autopilot-demo # Automotive HUD +./try-demo --sample dynamic-sky # Day/night cycle +./try-demo --sample post-processing # Bloom, SSAO, vignette +``` + +All 15 samples are available. Run `./try-demo --help` for the full list. + +--- + +## Option 2 — Download the APK + +
+ +
+

SceneView Demo

+

Full showcase: 11 models, 6 HDR environments, 26+ node types, animations, physics, post-processing.

+ +Download APK + +

Debug-signed — works on any device, no Play Store needed.

+
+ +
+

All 15 samples

+

Individual APKs for each sample: model viewer, AR, physics, camera, sky, path, text, effects.

+ +Browse all APKs + +
+ +
+ +### Install from terminal + +```bash +# Download and install in one line +curl -fSL -o /tmp/sceneview-demo.apk \ + https://github.com/SceneView/sceneview-android/releases/latest/download/sceneview-demo.apk \ + && adb install -r /tmp/sceneview-demo.apk +``` + +Or use the script's download mode (no build required): + +```bash +./try-demo --download +``` + +--- + +## Option 3 — Android Studio + +1. Open the project in Android Studio +2. Select the **`samples:sceneview-demo`** run configuration +3. Click **Run** + +--- + +## What's in the demo + +| Tab | What it shows | +|---|---| +| **Explore** | Full-screen 3D viewer — orbit camera, 8 models, 6 HDR environments | +| **Showcase** | Live previews of every node type with code snippets | +| **Gallery** | 14 curated cards — realistic models, animated characters, procedural geometry | +| **Effects** | Post-processing: bloom, vignette, tone mapping, FXAA, SSAO | +| **QA** | Stress tests, spring animations, edge cases | + +
+ +
+11 models
+Khronos PBR demos, Sketchfab realistic & animated characters +
+ +
+6 HDR environments
+Night, studio, warm, sunset, outdoor, autumn +
+ +
+26+ node types
+Model, Light, Cube, Sphere, Text, Path, Video, View... +
+ +
+60fps on mid-range
+Filament rendering engine, optimized for mobile +
+ +
+ +--- + +## Build from source + +```bash +# Clone +git clone https://github.com/SceneView/sceneview-android.git +cd sceneview-android + +# Build just the demo +./gradlew :samples:sceneview-demo:assembleDebug + +# Build all samples +./gradlew assembleDebug + +# Run lint +./gradlew :samples:sceneview-demo:lint +``` + +The APK lands in `samples/sceneview-demo/build/outputs/apk/debug/`. diff --git a/docs/docs/use-cases.md b/docs/docs/use-cases.md index 9e5f440fd..6979a00cf 100644 --- a/docs/docs/use-cases.md +++ b/docs/docs/use-cases.md @@ -2,6 +2,40 @@ Real-world applications of SceneView across industries. Each example includes the key composables used and approximate line counts. + + --- ## E-commerce: 3D product viewer diff --git a/docs/docs/v4-preview.md b/docs/docs/v4-preview.md index 2b7ec036d..3b7271649 100644 --- a/docs/docs/v4-preview.md +++ b/docs/docs/v4-preview.md @@ -1,10 +1,10 @@ ---- -title: v4 Preview — Multi-Platform ---- +# SceneView 4.0 preview -# SceneView v4 Preview — Multi-Platform +The next major release takes SceneView beyond Android — multi-platform, spatial computing, and a more powerful scene graph. -> **Status**: Design phase. The v4 milestone is about expanding SceneView beyond Android while maintaining the Compose-first philosophy. +
+SceneView 4.0 multi-platform architecture +
!!! info "v3.2.0 is production-ready today" You don't need to wait for 4.0. Everything below adds capabilities on top — it doesn't @@ -24,38 +24,6 @@ title: v4 Preview — Multi-Platform --- -## What's Coming - -### Kotlin Multiplatform Core - -SceneView v4 will extract the platform-independent layers (scene graph, math, asset loading, physics) into a Kotlin Multiplatform module. This means: - -- **Shared scene graph** across Android, iOS, Desktop, and Web -- **Shared asset pipeline** for glTF/GLB loading -- **Shared math library** already based on kotlin-math -- **Platform-specific renderers** using Filament's native backends - -### Android XR Support - -With Android XR launching, SceneView v4 will add: - -- `XRScene { }` composable for immersive 6DoF experiences -- Spatial anchors and hand tracking -- Eye tracking-aware rendering -- Passthrough AR on XR headsets - -### New Platforms - -| Platform | Composable | Renderer | -|---|---|---| -| Android | `Scene { }` | Filament (OpenGL ES / Vulkan) | -| Android XR | `XRScene { }` | Filament (Vulkan) | -| iOS | `SceneView { }` (SwiftUI) | Filament (Metal) | -| Desktop | `Scene { }` (Compose Desktop) | Filament (OpenGL / Vulkan) | -| Web | `Scene { }` (Compose HTML) | Filament (WebGPU) | - ---- - ## Multiple `Scene {}` on one screen Today, you get one `Scene` per screen. In 4.0, multiple independent scenes share a single @@ -167,19 +135,6 @@ fun ProductViewer(modelPath: String) { Write once, render natively on both platforms. -### API Evolution - -The v4 API will be backwards-compatible with v3 for Android. New platforms will use the same node DSL: - -```kotlin -// Same code works on Android, Desktop, and Web via KMP -Scene(modifier = Modifier.fillMaxSize()) { - rememberModelInstance(modelLoader, "models/helmet.glb")?.let { instance -> - ModelNode(modelInstance = instance, scaleToUnits = 1.0f) - } -} -``` - --- ## Also in 4.0 @@ -191,18 +146,6 @@ Scene(modifier = Modifier.fillMaxSize()) { --- -## Timeline - -| Milestone | Target | Scope | -|---|---|---| -| v3.3 | Q2 2026 | Collision system rewrite, performance optimizations | -| v3.4 | Q3 2026 | Android XR preview, API stabilization | -| v4.0-alpha | Q4 2026 | KMP core extraction, Desktop preview | -| v4.0-beta | Q1 2027 | iOS preview, Web preview | -| v4.0 | Q2 2027 | Stable multi-platform release | - ---- - ## Who should care about 4.0
@@ -241,15 +184,7 @@ Scene(modifier = Modifier.fillMaxSize()) { |---|---| | One Scene per screen | Multiple independent Scenes | | Flat scene graph | `PortalNode` — scenes within scenes | -| Android only | Kotlin Multiplatform (iOS, Desktop, Web) | +| Android only | Kotlin Multiplatform (iOS) | | Phone/tablet only | `SceneView-XR` for spatial computing | ---- - -## How to Get Involved - -- **Join the discussion**: [Discord #v4-planning](https://discord.gg/UbNDDBTNqb) -- **Contribute**: Check [CONTRIBUTING.md](../contributing/) for guidelines -- **Sponsor**: Help fund multi-platform development on [Open Collective](https://opencollective.com/sceneview) - [:octicons-arrow-right-24: Full roadmap on GitHub](https://github.com/SceneView/sceneview-android/blob/main/ROADMAP.md) diff --git a/docs/ios-swift-package-design.md b/docs/ios-swift-package-design.md new file mode 100644 index 000000000..7e6b7038c --- /dev/null +++ b/docs/ios-swift-package-design.md @@ -0,0 +1,161 @@ +# SceneView for iOS — Swift Package Design + +## Overview + +Native SwiftUI framework for 3D and AR, mirroring SceneView Android's API philosophy. +Two distribution paths: +1. **SceneViewSwift** — Native Swift Package using RealityKit (pure iOS) +2. **SceneViewKMP** — Kotlin/Native framework via sceneview-core (cross-platform) + +## Why RealityKit over SceneKit? + +- **SceneKit is officially deprecated** (WWDC 2025) — Apple published migration guide +- Apple published "Bring your SceneKit project to RealityKit" (WWDC25 session 288) +- visionOS/Vision Pro native support (SceneKit does not support visionOS) +- Built-in AR anchoring via ARKit integration +- PBR materials, physics, animation out of the box +- `RealityView` in SwiftUI (iOS 18+) — no UIViewRepresentable needed +- Future-proof: Apple's only actively developed 3D framework + +## API Design — SwiftUI Declarative + +### 3D Scene (mirrors `Scene { }`) + +```swift +import SceneViewSwift + +struct ModelViewer: View { + @State private var model: ModelEntity? + + var body: some View { + SceneView { + if let model { + ModelNode(model) + .position(.init(x: 0, y: 0, z: -2)) + .scale(.init(repeating: 0.5)) + } + + LightNode(.directional) + .direction(.init(x: 0, y: -1, z: -1)) + .intensity(1000) + + CameraNode() + .position(.init(x: 0, y: 1, z: 3)) + .lookAt(.zero) + } + .environment(.studio) + .cameraControls(.orbit) + .task { + model = try? await ModelLoader.load("models/car.usdz") + } + } +} +``` + +### AR Scene (mirrors `ARScene { }`) + +```swift +struct ARModelViewer: View { + @State private var model: ModelEntity? + + var body: some View { + ARSceneView(planeDetection: .horizontal) { anchor in + if let model { + AnchorNode(anchor) { + ModelNode(model) + .scale(.init(repeating: 0.1)) + } + .onTapGesture { node in + // Handle tap on placed model + } + } + } + .task { + model = try? await ModelLoader.load("models/robot.usdz") + } + } +} +``` + +## Module Structure + +``` +SceneViewSwift/ +├── Package.swift +├── Sources/ +│ ├── SceneViewSwift/ +│ │ ├── SceneView.swift — Main RealityView wrapper +│ │ ├── ARSceneView.swift — AR RealityView wrapper +│ │ ├── Nodes/ +│ │ │ ├── ModelNode.swift — 3D model entity +│ │ │ ├── LightNode.swift — Light entity +│ │ │ ├── CameraNode.swift — Camera entity +│ │ │ ├── ShapeNode.swift — Primitive geometry +│ │ │ └── AnchorNode.swift — AR anchor entity +│ │ ├── Modifiers/ +│ │ │ ├── TransformModifiers.swift — .position(), .rotation(), .scale() +│ │ │ ├── MaterialModifiers.swift — .color(), .metallic(), .roughness() +│ │ │ └── GestureModifiers.swift — .onTapGesture(), .draggable() +│ │ ├── Environment/ +│ │ │ ├── Environment.swift — IBL + skybox loading +│ │ │ └── EnvironmentPresets.swift — .studio, .outdoor, .sunset +│ │ ├── Loaders/ +│ │ │ ├── ModelLoader.swift — USDZ/glTF async loading +│ │ │ └── EnvironmentLoader.swift — HDR/EXR loading +│ │ └── Camera/ +│ │ ├── CameraControls.swift — Orbit/pan/zoom gestures +│ │ └── CameraManipulator.swift — Camera transform math +│ └── SceneViewAR/ +│ ├── ARSceneView.swift — ARKit + RealityKit +│ ├── PlaneDetection.swift — Plane anchoring +│ └── ImageTracking.swift — Image detection +└── Tests/ +``` + +## glTF Support + +RealityKit natively supports USDZ. For glTF: +- Use **GLTFKit2** (MIT license) for runtime glTF→Entity conversion +- Or pre-convert glTF→USDZ at build time via Apple's `reality-converter` CLI +- Accept both `.glb` and `.usdz` in ModelLoader + +## Shared Code with sceneview-core (KMP) + +The `sceneview-core` KMP module exports a Kotlin/Native framework: +- Collision detection (ray-sphere, ray-box, etc.) +- Math utilities (type aliases, transforms, comparisons) +- Triangulation (Earcut, Delaunator) + +Swift can consume this via: +```swift +import SceneViewCore // KMP framework + +let ray = Ray(origin: Vector3(0, 0, -5), direction: Vector3(0, 0, 1)) +let sphere = Sphere(center: Vector3.zero, radius: 1.0) +let hit = RayHit() +if sphere.rayIntersection(ray, hit) { + print("Hit at distance: \(hit.getDistance())") +} +``` + +## Estimated Effort + +| Component | Lines | Complexity | +|-----------|-------|------------| +| SceneView (RealityView wrapper) | ~200 | Low | +| Node modifiers (position, rotation, etc.) | ~300 | Low | +| ModelLoader (USDZ + glTF) | ~400 | Medium | +| Environment/IBL loading | ~200 | Medium | +| Camera controls (orbit/pan/zoom) | ~500 | Medium | +| ARSceneView + anchoring | ~400 | High | +| Gesture system | ~300 | Medium | +| **Total** | **~2,300** | Medium | + +## AI-First Design Checklist + +- [ ] Every public API has DocC documentation +- [ ] Parameter names match Android SceneView (position, rotation, scale) +- [ ] Default values make basic usage zero-config +- [ ] Loading is always async/await (no callback hell) +- [ ] Errors are typed Swift errors, not crashes +- [ ] `llms-swift.txt` with complete API reference for AI assistants diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 254409cef..633c1cdb3 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -9,19 +9,19 @@ theme: name: material palette: - scheme: default - primary: deep purple - accent: purple + primary: custom + accent: custom toggle: icon: material/brightness-7 name: Switch to dark mode - scheme: slate - primary: deep purple - accent: purple + primary: custom + accent: custom toggle: icon: material/brightness-4 name: Switch to light mode font: - text: Roboto + text: Google Sans code: JetBrains Mono icon: logo: material/cube-outline @@ -41,6 +41,7 @@ theme: nav: - Home: index.md + - Try the Demo: try.md - Get Started: - Quickstart: quickstart.md - API Cheatsheet: cheatsheet.md @@ -62,6 +63,10 @@ nav: - codelabs/index.md - 3D with Compose: codelabs/codelab-3d-compose.md - AR with Compose: codelabs/codelab-ar-compose.md + - Dynamic Sky: codelabs/guide-dynamic-sky.md + - Lines & Text: codelabs/guide-lines-text.md + - Physics: codelabs/guide-physics.md + - Reflection Probes: codelabs/guide-reflection-probes.md - API: - API (3D — sceneview): https://sceneview.github.io/api/sceneview-android/sceneview/ - API (AR — arsceneview): https://sceneview.github.io/api/sceneview-android/arsceneview/ diff --git a/docs/research/3d-models-capabilities.md b/docs/research/3d-models-capabilities.md new file mode 100644 index 000000000..4b6109c28 --- /dev/null +++ b/docs/research/3d-models-capabilities.md @@ -0,0 +1,182 @@ +# 3D Models for SceneView Capability Demos — Research + +> Research compiled for SceneView demo app expansion. +> Models selected to showcase specific SceneView features. + +## Top 10 Picks (covers the most features with fewest downloads) + +| # | Model | Feature | License | ~Size | +|---|-------|---------|---------|-------| +| 1 | **DamagedHelmet** (Khronos) | PBR, emissive, lighting, tone mapping, SSAO | CC-BY | ~3.7 MB | +| 2 | **Fox** (Khronos) | Skeletal animation (3 clips), AR placement | CC-BY | ~1 MB | +| 3 | **ABeautifulGame** (Khronos) | Transmission, volume, SSAO, complex scene | CC-BY | ~8-12 MB | +| 4 | **SheenChair** (Khronos/Wayfair) | Sheen extension, AR furniture | CC-BY | ~4 MB | +| 5 | **SunglassesKhronos** | Iridescence + transmission | CC-BY | ~2-4 MB | +| 6 | **EmissiveStrengthTest** (Khronos) | Bloom post-processing | CC-BY | ~0.1 MB | +| 7 | **AnimatedMorphSphere** (Khronos) | Morph targets | CC0 | ~50 KB | +| 8 | **Kenney Physics Assets** | 215 physics-ready shapes | CC0 | ~5 MB pack | +| 9 | **CC0 Chair 8 + Table + Plant Pot** (plaggy) | AR furniture trio | CC0 | ~1.5 MB | +| 10 | **Brain with Labeled Parts** | TextNode annotation | CC-BY | ~5-10 MB | + +--- + +## 1. PBR Materials (ModelNode) + +### Metallic / Roughness Extremes +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **DamagedHelmet** (Khronos) | CC-BY | ~3.7 MB | Mixed metallic/roughness, emissive visor, normal maps | +| **FlightHelmet** (Khronos) | CC-BY | ~5 MB | Multiple materials: leather, glass, metal, rubber | +| **AnisotropyBarnLamp** (Khronos) | CC-BY | ~8.4 MB | Brushed copper with anisotropic reflections, 6 extensions | + +### Iridescence / Sheen / Clearcoat +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **SunglassesKhronos** | CC-BY | ~2-4 MB | `KHR_materials_iridescence` + `KHR_materials_transmission` | +| **IridescenceLamp** (Wayfair) | CC-BY | ~3-5 MB | Iridescence with thickness texture | +| **SheenChair** (Wayfair) | CC-BY | ~4 MB | `KHR_materials_sheen` — damask fabric | +| **ClearCoatCarPaint** | CC0 | ~1-2 MB | `KHR_materials_clearcoat` — automotive paint | + +### Transmission / Volume (Glass, Gems) +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **ABeautifulGame** (ASWF) | CC-BY | ~8-12 MB | Chess set with glass pawn tops | +| **GlassVaseFlowers** (Wayfair) | CC-BY | ~5-8 MB | Alpha blend vs. transmission comparison | +| **CommercialRefrigerator** | CC-BY | ~5-10 MB | Glass doors + animated door | + +--- + +## 2. Animations + +### Skeletal Animation +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **Fox** (Khronos) | CC-BY | ~1 MB | 3 animations (Survey, Walk, Run) — `playAnimation(index)` | +| **CesiumMan** (Khronos) | CC-BY | ~0.5 MB | Textured walking man | +| **Soldier.glb** (three.js) | MIT | ~1 MB | Walk/run/idle — human-scale for AR | +| **Quaternius Platformer Character** | CC0 | ~0.5-1 MB | 18 animations per character | + +### Morph Targets +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **AnimatedMorphSphere** (Khronos) | CC0 | ~50 KB | Smooth morph transitions | +| **AnimatedMorphCube** (Khronos) | CC0 | ~10 KB | Two morph targets, minimal | +| **MorphStressTest** (Khronos) | CC-BY | ~1-2 MB | High morph-target count stress test | + +### Animated Machinery +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **CesiumMilkTruck** (Khronos) | CC-BY | ~0.5 MB | Spinning wheels (rigid body) | +| **CC0 - Gear** (plaggy) | CC0 | ~0.3 MB | 384 polys, PBR metallic | + +--- + +## 3. Lighting (LightNode) + +### Dramatic Lighting Demos +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **BoomBox** (Khronos) | CC0 | ~10 MB | Emissive panel + reflective metal | +| **Corset** (Khronos) | CC0 | ~5 MB | Fine detail needing good lighting | +| **FlightHelmet** (Khronos) | CC-BY | ~5 MB | Glass reflects, leather absorbs | + +### Emissive Materials +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **EmissiveStrengthTest** (Khronos) | CC-BY | ~0.1 MB | Progressive brightness cubes | +| **CC0 - Neon Sign Open** (plaggy) | CC0 | ~1 MB | Neon "OPEN" sign, 974 polys | + +--- + +## 4. Physics (PhysicsNode) + +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **Kenney Physics Assets** | CC0 | ~5 MB | 215 shapes: balls, cubes, planks, ramps | +| **Avocado** (Khronos) | CC0 | ~0.1 MB | Simple convex shape for drop/bounce | +| **Box** (Khronos) | CC-BY | ~1 KB | Minimal stacking primitive | +| **Low Poly Bowling Pins** (Sketchfab) | CC-BY | ~0.5 MB | 3 damage levels per pin | +| **Quaternius Platformer Pack** | CC0 | ~15 MB | Platforms, hazards, stackable shapes | + +--- + +## 5. Text & Labels (TextNode) + +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **Brain with Labeled Parts** (Sketchfab) | CC-BY | ~5-10 MB | Pre-labeled anatomical regions | +| **Male Skeleton** (Sketchfab) | CC-BY | ~5-10 MB | Labeled bones | +| **Anatomy of a Flower** (Sketchfab) | CC-BY | ~1-3 MB | Named parts (stamen, pistil) | + +--- + +## 6. Path & Line Drawing (PathNode) + +Best demonstrated procedurally (sine waves, Lissajous, helices). Context models: + +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **DNA Helix** (Sketchfab) | CC-BY | ~1-3 MB | Extract path coords for helix demo | +| **Klein Bottle** (Sketchfab) | CC-BY | ~0.5-1 MB | Mathematical surface | + +--- + +## 7. Post-Processing + +### Bloom +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **EmissiveStrengthTest** (Khronos) | CC-BY | ~0.1 MB | Bloom makes flat white → glowing | +| **CC0 - Neon Sign Open** (plaggy) | CC0 | ~1 MB | Neon tubes glow with bloom | +| **BoomBox** (Khronos) | CC0 | ~10 MB | Emissive panel + bloom | + +### SSAO +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **ABeautifulGame** (Khronos) | CC-BY | ~8-12 MB | Contact shadows between chess pieces | +| **FlightHelmet** (Khronos) | CC-BY | ~5 MB | Depth in goggle cavities | +| **Corset** (Khronos) | CC0 | ~5 MB | Rich AO in fabric folds | + +### Tone Mapping +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **DamagedHelmet** (Khronos) | CC-BY | ~3.7 MB | Wide dynamic range: ACES vs Filmic vs Linear | +| **AnisotropyBarnLamp** (Khronos) | CC-BY | ~8.4 MB | Highlight rolloff on copper | + +--- + +## 8. AR Placement (AnchorNode) + +### Furniture (room scale) +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **CC0 - Chair 8** (plaggy) | CC0 | ~0.5 MB | 324 polys, PBR, glTF + USDZ | +| **CC0 - Table** (plaggy) | CC0 | ~0.5 MB | Pairs with Chair 8 | +| **SheenChair** (Khronos/Wayfair) | CC-BY | ~4 MB | Premium AR furniture preview | + +### Plants / Decorative +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **CC0 - Plant Pot** (plaggy) | CC0 | ~0.5 MB | Tabletop-scale | +| **Avocado** (Khronos) | CC0 | ~0.1 MB | Tiny object, demonstrates scaleToUnits | + +### Characters (human scale) +| Model | License | ~Size | Feature | +|-------|---------|-------|---------| +| **Fox** (Khronos) | CC-BY | ~1 MB | Animated walk, floor-scale placement | +| **CesiumMan** (Khronos) | CC-BY | ~0.5 MB | Walking human figure | +| **PS1 Character Walk Cycle** (Sketchfab) | CC0 | ~0.5 MB | Retro-style, CC0, walk loop | + +--- + +## Key Repositories + +| Repository | License | Description | +|---|---|---| +| [Khronos glTF-Sample-Assets](https://github.com/KhronosGroup/glTF-Sample-Assets) | CC0/CC-BY | Official reference models for all glTF extensions | +| [Poly Haven](https://polyhaven.com/models) | CC0 | 1700+ photoscanned assets, up to 8K textures | +| [Kenney 3D](https://kenney.nl/assets/category:3D) | CC0 | 40k+ game-ready GLB assets | +| [Quaternius](https://quaternius.com/) | CC0 | Themed packs with animated characters | +| [three.js models](https://github.com/mrdoob/three.js/tree/dev/examples/models/gltf) | MIT | Soldier, Horse, Flamingo, Parrot — lightweight animated GLBs | +| [plaggy CC0 collection](https://sketchfab.com/plaggy/models) | CC0 | Furniture, signs, gears, plants with PBR + glTF/USDZ | +| [awesome-cc0](https://github.com/madjin/awesome-cc0) | N/A | Master list of all CC0 3D asset sources | diff --git a/docs/research/3d-models-industry.md b/docs/research/3d-models-industry.md new file mode 100644 index 000000000..195f2d8f8 --- /dev/null +++ b/docs/research/3d-models-industry.md @@ -0,0 +1,140 @@ +# 3D Models for Industry Use Cases — Research + +> Research compiled for SceneView demo app expansion. +> Priority: CC0/CC-BY, GLB format, < 10 MB, high visual quality. + +## Key Sources + +| Source | License | Notes | +|--------|---------|-------| +| [Khronos glTF-Sample-Assets](https://github.com/KhronosGroup/glTF-Sample-Assets) | Permissive | Official PBR reference models | +| [Sketchfab CC0](https://sketchfab.com/tags/cc0) | CC0 | 800k+ downloadable, auto-converts to GLB | +| [Poly Haven](https://polyhaven.com/models) | CC0 | Photoscanned, 4K-8K PBR | +| [Quaternius](https://quaternius.com/) | CC0 | Thousands of game-ready assets, many animated | +| [Kenney.nl](https://kenney.nl/assets) | CC0 | 40k+ low-poly assets | +| [plaggy CC0 Collection](https://sketchfab.com/plaggy/collections/cc0-public-domain-free-models-c1af6539a9ee49f4b3d51fabd6c25a85) | CC0 | 193 models with 4K PBR | + +--- + +## Top 10 Picks (highest confidence — CC0 or Khronos-licensed) + +| # | Model | Industry | License | ~Size | Why | +|---|-------|----------|---------|-------|-----| +| 1 | **Khronos ToyCar** | Automotive | Khronos | ~3 MB | Clearcoat PBR, already in demo | +| 2 | **Khronos SheenChair** | Furniture | Khronos | ~3 MB | Fabric sheen extension, already in demo | +| 3 | **Khronos MaterialsVariantsShoe** | E-commerce | Khronos | ~5 MB | Color configurator (KHR_materials_variants) | +| 4 | **Khronos Sunglasses** | AR try-on | Khronos | ~3 MB | Iridescence + transmission | +| 5 | **Khronos FlightHelmet** | Materials | Khronos | ~5 MB | Multi-material worn textures | +| 6 | **CC0 Chair 8** (plaggy) | AR placement | CC0 | ~2 MB | 4K PBR, 324 polys | +| 7 | **Animated Triceratops** (Smithsonian) | Education | CC0 | ~10 MB | Walking animation, museum scan | +| 8 | **Concept Car 025** (Unity Fan) | Automotive | CC0 | ~5-10 MB | Sleek design, no attribution needed | +| 9 | **4K Antique Ceramic Vase** | Museum | CC0 | ~5-10 MB | Historical artifact | +| 10 | **Earth 3D Globe** (Jeremy Faivre) | Education | CC-BY | ~5-10 MB | Recognizable, educational | + +--- + +## Per-Industry Breakdown + +### 1. E-commerce / Retail + +**Sneaker / Shoe:** +- Khronos **MaterialsVariantsShoe** — color configurator demo (KHR_materials_variants) +- Sketchfab "Shoe Model - Realistic 3D Sneaker" (Taohid Animation) — CC-BY, ~5-10 MB + +**Watch / Jewelry:** +- Khronos **IridescenceAbalone** / **IridescenceLamp** — iridescence for jewelry reflections +- Khronos **AntiqueCamera** — metallic materials showcase + +**Furniture:** +- Sketchfab **CC0 - Chair 8** (plaggy) — CC0, 4K PBR, ~2 MB +- Khronos **SheenChair** — velvet/fabric with KHR_materials_sheen + +**Sunglasses (AR try-on):** +- Khronos **Sunglasses** — iridescence + transmission +- Sketchfab "3D Glasses - Optimized for Virtual Try-on" (IceyTape) — built for AR VTO + +### 2. Automotive + +**Car exterior:** +- Sketchfab "FREE Concept Car 025" (Unity Fan) — **CC0**, ~5-10 MB +- Sketchfab "FREE Concept Car 003/006" (Unity Fan) — **CC0** variants +- Khronos **ToyCar** — clearcoat PBR, ~3 MB +- Khronos **ClearCoatCarPaint** — automotive paint finish + +**Wheels:** +- Sketchfab "Rims_N_Tyres_kit_1.0" (britdawgmasterfunk) — **CC0**, configurator + +**Mechanical parts:** +- Sketchfab **CC0 - Gear** (plaggy) — **CC0**, 4K PBR metallic +- Khronos **CarbonFibre** — anisotropy on carbon fiber + +### 3. Healthcare / Medical + +**Anatomy:** +- Sketchfab "Human Skeleton" (Terrie Simmons-Ehrhardt) — CC-BY, NIH source, CT-derived +- Sketchfab "Human Skull: Colored Bone Anatomy" (SGU BioMedViz) — color-coded bones + +**Medical devices:** +- Sketchfab "MRI Machine" (Phillip Stephens) — recognizable equipment +- Sketchfab "Surgical Instruments Collection" (Digital Surgery) — accurate tools + +**Molecular:** +- Sketchfab "DNA by Holoxica" — clean double helix +- Sketchfab "16-base-pair B-DNA" (S.Duce) — from Protein Data Bank X-ray data + +### 4. Real Estate / Architecture + +**Houses:** +- Sketchfab "American House" (AleixoAlonso) — CC-BY, PBR, exterior + kitchen +- Sketchfab "Buildings_kit_1.0" (britdawgmasterfunk) — **CC0**, domestic housing kit + +**Interiors:** +- Poly Haven indoor models — **CC0**, photoscanned furniture/props, 4K-8K PBR + +### 5. Education / STEM + +**Solar system:** +- Sketchfab "Earth 3D Globe" (Jeremy Faivre) — CC-BY +- Sketchfab "Solar System" (dannzjs) + +**Dinosaurs:** +- Sketchfab "Animated Triceratops Skeleton" (Zacxophone) — **CC0**, Smithsonian scan, animated walk +- Sketchfab "T. rex / Triceratops" (Thomas Flynn / Smithsonian DPO) — **CC0**, museum quality + +**Artifacts:** +- Sketchfab "4k Antique Ceramic Vase" (mohamedhussien) — **CC0** +- Sketchfab "CC0 Museum Artifacts Collection" (danielpett) — all **CC0** + +### 6. Gaming / Entertainment + +**Characters:** +- Quaternius "Ultimate Platformer Pack" — **CC0**, 100+ models, 18 character animations +- Sketchfab "The Forgotten Knight" (dark_igorek) — CC-BY, rigged fantasy knight + +**Robots:** +- Sketchfab "Futuristic Flying Animated Robot" (Shayan) — 5.7K polys, animated +- Sketchfab "MechaVolt MK-II" (DevPoly3D) — PBR, optimized for VR/AR + +**Weapons:** +- OpenGameArt "CC0 - 3D Weapons" — **CC0**, shields, swords, fantasy weapons + +**Landscapes:** +- Quaternius "Ultimate Space Kit" — **CC0**, 90+ models +- Kenney Nature Assets — **CC0**, consistent low-poly style + +--- + +## Khronos Models — Feature Demo Matrix + +| Model | Extension / Feature | Best For | +|-------|-------------------|----------| +| ToyCar | clearcoat | Automotive paint | +| SheenChair | sheen | Fabric/velvet | +| MaterialsVariantsShoe | variants | Color configurator | +| Sunglasses | iridescence + transmission | AR try-on | +| FlightHelmet | multi-material | Material showcase | +| DragonAttenuation | transmission + volume | Glass/transparency | +| CarbonFibre | anisotropy | Sports/automotive | +| DiffuseTransmissionPlant | diffuse transmission | Nature/foliage | +| AnisotropyBarnLamp | 6 extensions combined | Advanced materials | +| CommercialRefrigerator | glass + animation | Retail/appliance | diff --git a/try-demo b/try-demo new file mode 100755 index 000000000..f698f1739 --- /dev/null +++ b/try-demo @@ -0,0 +1,201 @@ +#!/usr/bin/env bash +# ───────────────────────────────────────────────────────────────────── +# SceneView Demo — one-click installer +# +# Usage: +# ./try-demo # Build & install the demo app +# ./try-demo --download # Download latest APK from GitHub Releases +# ./try-demo --sample ar-model-viewer # Build & install a specific sample +# +# Requirements: +# - Android device connected via USB/Wi-Fi with USB debugging ON +# - Java 17+ (for local build) +# - adb on PATH (comes with Android SDK) +# ───────────────────────────────────────────────────────────────────── +set -euo pipefail + +RED='\033[0;31m' +GREEN='\033[0;32m' +CYAN='\033[0;36m' +BOLD='\033[1m' +RESET='\033[0m' + +REPO_ROOT="$(cd "$(dirname "$0")" && pwd)" +DEMO_MODULE=":samples:sceneview-demo" +DEMO_PKG="io.github.sceneview.demo" +GITHUB_REPO="SceneView/sceneview-android" + +banner() { + echo "" + echo -e "${CYAN}${BOLD}╔══════════════════════════════════════════╗${RESET}" + echo -e "${CYAN}${BOLD}║ SceneView Demo Installer ║${RESET}" + echo -e "${CYAN}${BOLD}║ 3D & AR for Jetpack Compose — try it ║${RESET}" + echo -e "${CYAN}${BOLD}╚══════════════════════════════════════════╝${RESET}" + echo "" +} + +check_device() { + if ! command -v adb &>/dev/null; then + echo -e "${RED}Error: adb not found. Install Android SDK platform-tools.${RESET}" + echo " brew install android-platform-tools # macOS" + echo " sudo apt install adb # Linux" + exit 1 + fi + + local devices + devices=$(adb devices | grep -c 'device$' || true) + if [[ "$devices" -eq 0 ]]; then + echo -e "${RED}No Android device detected.${RESET}" + echo "" + echo " 1. Connect your phone via USB" + echo " 2. Enable USB debugging in Developer Options" + echo " 3. Accept the USB debugging prompt on your phone" + echo "" + echo -e " Or use Wi-Fi: ${CYAN}adb connect :5555${RESET}" + exit 1 + fi + echo -e "${GREEN}✓${RESET} Device connected ($devices device(s))" +} + +download_and_install() { + echo -e "${CYAN}Downloading latest demo APK from GitHub Releases...${RESET}" + + local url + if command -v gh &>/dev/null; then + url=$(gh release view --repo "$GITHUB_REPO" --json assets \ + --jq '.assets[] | select(.name == "sceneview-demo.apk") | .url' 2>/dev/null || true) + fi + + if [[ -z "${url:-}" ]]; then + url="https://github.com/$GITHUB_REPO/releases/latest/download/sceneview-demo.apk" + fi + + local tmp_apk="/tmp/sceneview-demo.apk" + curl -fSL --progress-bar -o "$tmp_apk" "$url" + echo -e "${GREEN}✓${RESET} Downloaded" + + echo -e "${CYAN}Installing on device...${RESET}" + adb install -r "$tmp_apk" + echo -e "${GREEN}✓${RESET} Installed" + + launch_app +} + +build_and_install() { + local module="${1:-$DEMO_MODULE}" + local pkg="${2:-$DEMO_PKG}" + + echo -e "${CYAN}Building ${BOLD}${module}${RESET}${CYAN}...${RESET}" + cd "$REPO_ROOT" + + if [[ ! -f gradlew ]]; then + echo -e "${RED}Error: gradlew not found. Are you in the SceneView repo root?${RESET}" + exit 1 + fi + + chmod +x gradlew + ./gradlew "${module}:assembleDebug" --console=plain -q + + local apk + apk=$(find "$REPO_ROOT" -path "*${module##*:}*/build/outputs/apk/debug/*.apk" | head -1) + if [[ -z "$apk" ]]; then + # Fallback: search by module name converted to path + local module_path="${module//:///}" + apk=$(find "$REPO_ROOT${module_path}/build/outputs/apk/debug" -name "*.apk" 2>/dev/null | head -1) + fi + + if [[ -z "$apk" ]]; then + echo -e "${RED}Error: APK not found after build.${RESET}" + exit 1 + fi + + echo -e "${GREEN}✓${RESET} Built: $(basename "$apk")" + echo -e "${CYAN}Installing on device...${RESET}" + adb install -r "$apk" + echo -e "${GREEN}✓${RESET} Installed" + + launch_app "$pkg" +} + +launch_app() { + local pkg="${1:-$DEMO_PKG}" + echo -e "${CYAN}Launching...${RESET}" + adb shell am start -n "${pkg}/.MainActivity" 2>/dev/null \ + || adb shell monkey -p "$pkg" -c android.intent.category.LAUNCHER 1 2>/dev/null \ + || true + echo "" + echo -e "${GREEN}${BOLD}🎉 SceneView Demo is running on your device!${RESET}" + echo -e " Explore 3D models, switch environments, try animations." + echo "" +} + +# ── Sample name → Gradle module mapping ── +sample_to_module() { + local sample="$1" + case "$sample" in + demo|sceneview-demo) echo ":samples:sceneview-demo" ;; + model-viewer) echo ":samples:model-viewer" ;; + ar-model-viewer) echo ":samples:ar-model-viewer" ;; + ar-augmented-image) echo ":samples:ar-augmented-image" ;; + ar-cloud-anchor) echo ":samples:ar-cloud-anchor" ;; + ar-point-cloud) echo ":samples:ar-point-cloud" ;; + camera-manipulator) echo ":samples:camera-manipulator" ;; + gltf-camera) echo ":samples:gltf-camera" ;; + autopilot-demo) echo ":samples:autopilot-demo" ;; + physics-demo) echo ":samples:physics-demo" ;; + dynamic-sky) echo ":samples:dynamic-sky" ;; + line-path) echo ":samples:line-path" ;; + text-labels) echo ":samples:text-labels" ;; + reflection-probe) echo ":samples:reflection-probe" ;; + post-processing) echo ":samples:post-processing" ;; + *) + echo -e "${RED}Unknown sample: $sample${RESET}" >&2 + echo "Available: demo, model-viewer, ar-model-viewer, camera-manipulator," >&2 + echo " gltf-camera, autopilot-demo, physics-demo, dynamic-sky, line-path," >&2 + echo " text-labels, reflection-probe, post-processing, ar-augmented-image," >&2 + echo " ar-cloud-anchor, ar-point-cloud" >&2 + exit 1 + ;; + esac +} + +# ── Main ── +banner + +MODE="build" +SAMPLE="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --download|-d) MODE="download"; shift ;; + --sample|-s) SAMPLE="$2"; shift 2 ;; + --help|-h) + echo "Usage: ./try-demo [OPTIONS]" + echo "" + echo "Options:" + echo " --download, -d Download latest APK from GitHub Releases" + echo " --sample, -s NAME Build a specific sample (e.g. ar-model-viewer)" + echo " --help, -h Show this help" + echo "" + echo "Examples:" + echo " ./try-demo # Build & install the demo app" + echo " ./try-demo --download # Download pre-built APK" + echo " ./try-demo --sample physics-demo # Try the physics sample" + exit 0 + ;; + *) echo -e "${RED}Unknown option: $1${RESET}"; exit 1 ;; + esac +done + +check_device + +if [[ "$MODE" == "download" ]]; then + download_and_install +elif [[ -n "$SAMPLE" ]]; then + module=$(sample_to_module "$SAMPLE") + # Derive package from sample name + sample_pkg="io.github.sceneview.sample.${SAMPLE//-/.}" + build_and_install "$module" "$sample_pkg" +else + build_and_install +fi