Skip to content

SceneView

Overview

SceneView is a powerful 3D and AR rendering library for Android, Flutter, and React Native applications. Built on top of ARCore and Google's Filament Engine, it provides a robust foundation for creating immersive 3D and augmented reality experiences with high-performance rendering capabilities.

Integration Context

In the MINE Indoor Navigation Engine, SceneView serves as the primary rendering engine for displaying 3D maps, visualizing navigation paths, and providing real-time AR wayfinding experiences.


Platform Support

SceneView is available across multiple platforms with consistent APIs:

  • Android


    Native Android library with full ARCore support

    Android Repository

  • :material-flutter: Flutter


    Cross-platform Flutter plugin for iOS and Android

    Flutter Plugin

  • React Native


    React Native module for mobile AR experiences

    RN Module


Core Features

๐ŸŽจ Advanced Rendering

  • Filament-Powered: Leverages Google's physically-based rendering engine
  • PBR Materials: Support for physically-based materials and lighting
  • HDR Environment: High dynamic range image-based lighting
  • Post-Processing: Bloom, depth-of-field, and other effects

๐ŸŒ AR Capabilities

  • ARCore Integration: Native support for Google ARCore
  • Plane Detection: Automatic detection of horizontal and vertical surfaces
  • Light Estimation: Real-world lighting integration
  • Anchors: Persistent AR content placement

๐Ÿ“ฆ 3D Model Support

  • glTF/GLB: Industry-standard 3D model formats
  • Animations: Skeletal and keyframe animations
  • LOD Support: Level-of-detail optimization
  • Custom Shaders: GLSL shader customization

๐ŸŽฎ Interactive Controls

  • Gesture Recognition: Pan, zoom, rotate, and tap gestures
  • Camera Controls: Orbit, first-person, and follow modes
  • Hit Testing: Ray-casting for object selection
  • Custom Interactions: Extensible gesture system

Use Cases in MINE

1. 3D Map Visualization

SceneView renders interactive 3D representations of indoor environments, allowing users to:

  • View building layouts from multiple angles
  • Interact with floor plans in real-time
  • Zoom and rotate the map intuitively
// Example: Loading a 3D indoor map
val sceneView = findViewById<SceneView>(R.id.sceneView)

sceneView.apply {
    // Load the building model
    loadModel("models/building.glb") { model ->
        // Position and scale the model
        model.position = Position(0f, 0f, 0f)
        model.scale = Scale(1f)

        // Add to scene
        addChild(model)
    }

    // Configure camera
    camera.setPosition(x = 0f, y = 5f, z = 10f)
    camera.lookAt(0f, 0f, 0f)
}

2. Navigation Path Rendering

Displays real-time navigation routes with visual clarity:

// Example: Rendering navigation path
fun renderNavigationPath(pathPoints: List<Vector3>) {
    val pathMaterial = MaterialInstance(
        material = MaterialLoader.load(context, "materials/path.mat"),
        color = Color(0xFF4CAF50)
    )

    val pathLine = LineNode(
        points = pathPoints,
        thickness = 0.05f,
        material = pathMaterial
    )

    sceneView.addChild(pathLine)

    // Add animated indicator
    val indicator = createPathIndicator()
    animateAlongPath(indicator, pathPoints)
}

3. AR Wayfinding

Provides augmented reality overlays for enhanced navigation:

// Example: AR navigation overlay
sceneView.apply {
    // Enable AR mode
    arMode = true

    // Place AR navigation arrows
    onTapAr { hitResult ->
        val anchor = hitResult.createAnchor()
        val arrowNode = createNavigationArrow()

        arrowNode.anchor = anchor
        addChild(arrowNode)

        // Animate the arrow
        animateArrow(arrowNode)
    }
}

4. Point of Interest (POI) Markers

Display interactive markers for locations of interest:

// Example: Adding POI markers
fun addPOIMarker(location: Vector3, info: POIInfo) {
    val markerNode = Node().apply {
        position = location

        // Add 3D icon
        loadModel("models/poi_marker.glb") { model ->
            addChild(model)
        }

        // Add text label
        val textNode = TextNode(
            text = info.name,
            fontSize = 0.2f,
            color = Color.WHITE
        )
        addChild(textNode)

        // Handle interactions
        onTap { 
            showPOIDetails(info)
        }
    }

    sceneView.addChild(markerNode)
}

Key Components

SceneView

The main view component that hosts the 3D/AR scene:

<io.github.sceneview.SceneView
    android:id="@+id/sceneView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:arEnabled="true"
    app:antialiasingMode="fxaa"
    app:msaaSampleCount="4" />

Node Hierarchy

SceneView uses a node-based scene graph:

// Creating a node hierarchy
val rootNode = Node()

val buildingNode = ModelNode().apply {
    loadModel("building.glb")
}

val navigationNode = Node().apply {
    // Add navigation path
}

rootNode.addChild(buildingNode)
rootNode.addChild(navigationNode)
sceneView.addChild(rootNode)

Camera Control

Flexible camera positioning and movement:

// Camera configuration
sceneView.cameraNode.apply {
    // Set position
    worldPosition = Position(x = 0f, y = 2f, z = 5f)

    // Look at target
    lookAt(targetPosition = Position(0f, 0f, 0f))

    // Animate camera
    smooth(
        position = newPosition,
        rotation = newRotation,
        duration = 1.5f
    )
}

Lighting

Configure scene lighting for optimal visualization:

// Setup lighting
sceneView.apply {
    // Add directional light (sun)
    val sunLight = LightNode(
        type = LightType.DIRECTIONAL,
        intensity = 100000f,
        color = Color.WHITE
    )
    sunLight.worldRotation = Rotation(x = 45f, y = 0f, z = 0f)
    addChild(sunLight)

    // Set environment (HDR image)
    environment = HDREnvironment(
        asset = "environments/indoor.hdr",
        intensity = 30000f
    )

    // Configure skybox
    skybox = Skybox(environment = environment)
}

Performance Optimization

Level of Detail (LOD)

Optimize rendering performance with LOD models:

val modelNode = ModelNode().apply {
    // Load multiple LOD levels
    loadModelLOD(
        high = "models/building_high.glb",
        medium = "models/building_medium.glb",
        low = "models/building_low.glb"
    )

    // Configure LOD distances
    lodDistances = listOf(10f, 50f, 100f)
}

Culling

Implement frustum culling for large scenes:

sceneView.apply {
    // Enable frustum culling
    isFrustumCullingEnabled = true

    // Set culling distance
    farClipPlane = 100f
}

Texture Compression

Use compressed textures for better performance:

// Use KTX2 format with Basis compression
val material = MaterialLoader.load(
    context = context,
    assetFileLocation = "materials/compressed.ktx2"
)

Best Practices

Recommended Practices

1. Memory Management

override fun onDestroy() {
    super.onDestroy()
    sceneView.destroy()
}

2. Async Loading

// Load models asynchronously
lifecycleScope.launch {
    val model = sceneView.loadModelAsync("model.glb")
    sceneView.addChild(model)
}

3. Error Handling

sceneView.loadModel("model.glb",
    onError = { exception ->
        Log.e("SceneView", "Failed to load model", exception)
        showErrorToUser()
    }
)

Common Pitfalls

  • Avoid loading large models on the main thread
  • Always destroy SceneView in onDestroy()
  • Check ARCore availability before enabling AR mode
  • Optimize textures and models for mobile devices

Resources


Version & Compatibility

Component Minimum Version Recommended
Android SDK API 24 (7.0) API 33+
ARCore 1.20.0 Latest
Filament 1.28.0 Latest
Kotlin 1.8.0 1.9.0+

Documentation Status

As of December 2025, SceneView continues to evolve rapidly. For the latest features and updates, check the official GitHub repository and release notes.


Quick Start Integration

To integrate SceneView into your MINE implementation:

  1. Add Dependencies

    dependencies {
        implementation 'io.github.sceneview:sceneview:2.0.0'
    }
    

  2. Add to Layout

    <io.github.sceneview.SceneView
        android:id="@+id/sceneView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    

  3. Initialize in Activity

    val sceneView = findViewById<SceneView>(R.id.sceneView)
    sceneView.loadModel("model.glb")
    

For detailed integration steps, see the Quick Start Guide.