Use augmented reality (AR) to pin a scene to a table or desk for easy exploration.
Use case
Tabletop scenes allow you to use your device to interact with scenes as if they are 3D-printed model models sitting on your desk. You could use this to virtually explore a proposed development without needing to create a physical model.
How to use the sample
Once the scene loads, you'll see a feed from the camera. Wait for ArCore to highlight a plane and tap on one to place the scene. With the scene placed, you can move the camera around the scene to explore.
NOTE: Google Play Services for AR must be installed to run this app and the application code will prompt the user to install it if it is not already installed.
How it works
- Create a
TableTopSceneView
witharcGISSceneAnchor
,translationFactor
,clippingDistance
, and anarcGISScene
. - For this sample, the
arcGISSceneAnchor
sets coordinates at the center of the buildings in theArcGSISceneLayer
to give the impression that the scene is centered on the location the user tapped. - Set the
translationFactor
such that the user can view the entire scene by moving the device around it. The translation factor defines how far the virtual camera moves through the scene when the physical camera moves. -A good formula for determining translation factor to use in a tabletop map experience is translationFactor = sceneWidth / tableTopWidth. The scene width is the width/length of the scene content you wish to display in meters. The tabletop width is the length of the area on the physical surface that you want the scene content to fill. For simplicity, the sample assumes a scene width of 800 meters. - Set the
clippingDistance
to clip the scene to the area you want to show.
Relevant API
- ArcGISScene
- TableTopSceneView
About the data
This sample uses the Philadelphia Mobile Scene Package. It was chosen because it is a compact scene ideal for tabletop use. Note that tabletop mapping experiences work best with small, focused scenes. The small, focused area with basemap tiles defines a clear boundary for the scene.
Additional information
This sample requires a device that is compatible with ARCore on Android.
This sample uses AR from the Maps SDK Toolkit.
Tags
augmented reality, drop, mixed reality, model, pin, place, table-top, tabletop
Sample Code
/* Copyright 2025 Esri
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.esri.arcgismaps.sample.augmentrealitytoshowtabletopscene.components
import android.app.Application
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.arcgismaps.mapping.ArcGISScene
import com.arcgismaps.mapping.MobileScenePackage
import com.arcgismaps.mapping.NavigationConstraint
import com.esri.arcgismaps.sample.augmentrealitytoshowtabletopscene.R
import com.esri.arcgismaps.sample.sampleslib.components.MessageDialogViewModel
import kotlinx.coroutines.launch
import java.io.File
class AugmentRealityToShowTabletopSceneViewModel(application: Application) : AndroidViewModel(application) {
private val provisionPath: String by lazy {
application.getExternalFilesDir(null)?.path.toString() + File.separator + application.getString(R.string.augment_reality_to_show_tabletop_scene_app_name)
}
// Get the folder path containing the mobile scene package (.mspk) file
private val filePath = "$provisionPath/philadelphia.mspk"
// Create a mobile scene package
private val scenePackage = MobileScenePackage(filePath)
// Create a mutable state variable to hold the scene. Later loaded from the scene package
var scene: ArcGISScene? by mutableStateOf(null)
// Create a message dialog view model for handling error messages
val messageDialogVM = MessageDialogViewModel()
init {
viewModelScope.launch {
// Load the mobile scene package
scenePackage.load().onSuccess {
// Get the first scene from the package
scene = scenePackage.scenes.first().apply {
// Set the navigation constraint to allow you to look at the scene from below
baseSurface.navigationConstraint = NavigationConstraint.None
}
}.onFailure {
messageDialogVM.showMessageDialog(
"Error loading mobile scene package", it.message.toString()
)
}
}
}
}