Skip to content

API Cheatsheet

A quick reference for SceneView's most-used APIs. Print it, pin it, keep it next to your keyboard.


Setup

// build.gradle
implementation("io.github.sceneview:sceneview:3.2.0")     // 3D
implementation("io.github.sceneview:arsceneview:3.2.0")    // AR + 3D

Core Remember Hooks

val engine = rememberEngine()
val modelLoader = rememberModelLoader(engine)
val materialLoader = rememberMaterialLoader(engine)
val environmentLoader = rememberEnvironmentLoader(engine)

val model = rememberModelInstance(modelLoader, "models/file.glb")  // null while loading
val env = rememberEnvironment(environmentLoader) {
    createHDREnvironment("environments/sky.hdr")!!
}

val cameraManipulator = rememberCameraManipulator()
val mainLight = rememberMainLightNode(engine) { intensity = 100_000f }
val cameraNode = rememberCameraNode(engine) { position = Position(0f, 2f, 5f) }
val viewNodeManager = rememberViewNodeManager()

Scene

Scene(
    modifier = Modifier.fillMaxSize(),
    engine = engine,
    modelLoader = modelLoader,
    cameraManipulator = cameraManipulator,    // orbit/pan/zoom
    cameraNode = cameraNode,                  // OR fixed camera
    environment = env,
    mainLightNode = mainLight,
    surfaceType = SurfaceType.Surface,        // or TextureSurface
    isOpaque = true,
    viewNodeWindowManager = viewNodeManager,  // for ViewNode
    onGestureListener = rememberOnGestureListener(
        onSingleTapConfirmed = { event, node -> },
        onDoubleTap = { event, node -> },
        onLongPress = { event, node -> }
    ),
    onTouchEvent = { event, hitResult -> false },
    onFrame = { frameTimeNanos -> }
) {
    // SceneScope — declare nodes here
}

ARScene

ARScene(
    modifier = Modifier.fillMaxSize(),
    engine = engine,
    modelLoader = modelLoader,
    planeRenderer = true,
    sessionConfiguration = { session, config ->
        config.depthMode = Config.DepthMode.AUTOMATIC
        config.lightEstimationMode = Config.LightEstimationMode.ENVIRONMENTAL_HDR
    },
    sessionFeatures = setOf(),  // e.g., Session.Feature.FRONT_CAMERA
    onSessionUpdated = { session, frame -> },
    onTouchEvent = { event, hitResult -> true }
) {
    // ARSceneScope — declare AR nodes here
}

Node Types — 3D

Node Key Parameters
ModelNode modelInstance, scaleToUnits, centerOrigin, position, rotation, isEditable, autoAnimate, animationName, animationLoop
CubeNode size: Size, materialInstance
SphereNode radius: Float, materialInstance
CylinderNode radius, height, materialInstance
PlaneNode size: Size, materialInstance
LightNode type: LightManager.Type, apply = { intensity(); color(); castShadows() }
ImageNode imageFileLocation / imageResId / bitmap, size
VideoNode player: MediaPlayer, chromaKeyColor, size
ViewNode windowManager, content = @Composable
TextNode text, fontSize, textColor, backgroundColor, widthMeters
BillboardNode bitmap, widthMeters, heightMeters
LineNode start, end, materialInstance
PathNode points: List<Position>, closed, materialInstance
DynamicSkyNode timeOfDay (0-24), turbidity, sunIntensity
FogNode view, density, height, color, enabled
ReflectionProbeNode filamentScene, environment, position, radius, cameraPosition
PhysicsNode node, mass, restitution, linearVelocity, floorY, radius
MeshNode primitiveType, vertexBuffer, indexBuffer, materialInstance
Node position, rotation, scale + child content
CameraNode (via rememberCameraNode)

Node Types — AR

Node Key Parameters
AnchorNode anchor: Anchor + child content
HitResultNode xPx, yPx + child content (reticle)
AugmentedImageNode augmentedImage + child content
AugmentedFaceNode augmentedFace, meshMaterialInstance
CloudAnchorNode anchor, cloudAnchorId, onHosted + child content

Common Node Properties

node.position = Position(x, y, z)      // meters
node.rotation = Rotation(x, y, z)      // degrees
node.scale = Scale(x, y, z)            // multiplier
node.isVisible = true
node.isEditable = true                 // pinch-scale, drag-move, rotate
node.isTouchable = true
node.onSingleTapConfirmed = { event -> true }
node.onFrame = { frameTimeNanos -> }

// Smooth movement
node.transform(position = Position(2f, 0f, 0f), smooth = true, smoothSpeed = 5f)
node.lookAt(targetNode)

// Animation
node.animateRotations(Rotation(0f), Rotation(y = 360f)).also {
    it.duration = 2000
    it.repeatCount = ValueAnimator.INFINITE
}.start()

Math Types

import io.github.sceneview.math.*

Position(x = 0f, y = 1f, z = -2f)     // Float3, meters
Rotation(x = 0f, y = 90f, z = 0f)     // Float3, degrees
Scale(1.5f)                             // uniform
Scale(x = 2f, y = 1f, z = 2f)         // non-uniform
Direction(x = 0f, y = 1f, z = 0f)     // unit vector
Size(width = 1f, height = 0.5f)       // Float2

Resource Loading

// Composable (preferred)
val model = rememberModelInstance(modelLoader, "models/file.glb")

// Imperative
val model = modelLoader.loadModelInstance("models/file.glb")
modelLoader.loadModelInstanceAsync("models/file.glb") { instance -> }

// Environment
environmentLoader.createHDREnvironment("environments/sky.hdr")
environmentLoader.createKtxEnvironment("environments/studio.ktx")

// Material
materialLoader.createColorInstance(Color.Red)

Threading Rules

Safe Unsafe
rememberModelInstance(...) modelLoader.createModelInstance(...) on IO
loadModelInstanceAsync(...) materialLoader.createMaterial(...) on IO
Any composable in Scene { } Direct Filament API on background thread

Rule: Filament JNI = main thread only. remember* hooks handle this for you.