Skip to content

Tabletop AR: scene placement #602

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8bb7966
merge `Feature branches/forms` into v.next (#566)
kaushikrw Sep 16, 2024
a9d7ef7
Remove unnecessary creating the viewmodel in the main activity (#571)
puneet-pdx Sep 19, 2024
70803cc
Set up Tabletop AR project (#545)
hud10837 Sep 16, 2024
7190e71
Hud10837/import render code (#580)
hud10837 Sep 24, 2024
cb66965
Tabletop AR: Add ArSurfaceView (#590)
hud10837 Sep 27, 2024
83f8749
Hud10837/session init and permissions (#595)
hud10837 Oct 4, 2024
bda3d32
add new DetectingPlanes status
hud10837 Oct 4, 2024
8443903
create callback and set status for first plane detected
hud10837 Oct 4, 2024
16cba8e
add in scene placement logic
hud10837 Oct 4, 2024
4a41f66
add translation factor, anchor point, clipping distance
hud10837 Oct 4, 2024
3b220e2
rm initial viewpoint on scene
hud10837 Oct 4, 2024
42150aa
Merge branch 'feature-branches/tabletop-ar' of https://github.com/Esr…
hud10837 Oct 4, 2024
d57ca1f
display simple helper text while detecting planes
hud10837 Oct 4, 2024
a1c97fe
use string res
hud10837 Oct 4, 2024
9532c2e
use string res for lat lon callout content
hud10837 Oct 7, 2024
4a9e5ce
enhance microapp with status messages
hud10837 Oct 7, 2024
74b0f37
use better data for microapp
hud10837 Oct 7, 2024
47b60bb
rm debug code
hud10837 Oct 7, 2024
8fe8cac
use val instead of var for status
hud10837 Oct 8, 2024
d419076
cleanup
hud10837 Oct 8, 2024
ebb360a
use display rotation for lens intrinsics
hud10837 Oct 8, 2024
8ca8790
checkout unexpected files from feature branch
hud10837 Oct 8, 2024
9dc2fc8
checkout unexpected files from feature branch
hud10837 Oct 8, 2024
f65e0ca
add doc to TextWithScrim
hud10837 Oct 8, 2024
5a86032
use when statements and be exhaustive
hud10837 Oct 10, 2024
ab43931
mv declarations of cameraController and arCoreAnchor
hud10837 Oct 10, 2024
752331e
add doc Pose.transformationMatrix
hud10837 Oct 10, 2024
c7fa7e8
use when (val status = ...
hud10837 Oct 11, 2024
eb465ee
use explicit api mode
hud10837 Oct 11, 2024
aa65730
fix build warnings
gunt0001 Oct 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,32 @@

package com.arcgismaps.toolkit.artabletopapp.screens

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.arcgismaps.LoadStatus
import com.arcgismaps.geometry.Point
import com.arcgismaps.mapping.ArcGISScene
import com.arcgismaps.mapping.BasemapStyle
import com.arcgismaps.mapping.Viewpoint
import com.arcgismaps.mapping.ElevationSource
import com.arcgismaps.mapping.Surface
import com.arcgismaps.mapping.layers.ArcGISMapImageLayer
import com.arcgismaps.mapping.layers.ArcGISSceneLayer
import com.arcgismaps.toolkit.ar.TableTopSceneView
import com.arcgismaps.toolkit.ar.TableTopSceneViewProxy
import com.arcgismaps.toolkit.ar.TableTopSceneViewStatus
Expand All @@ -47,7 +55,23 @@ import kotlin.math.roundToInt
fun MainScreen() {
val arcGISScene = remember {
ArcGISScene(BasemapStyle.ArcGISImagery).apply {
initialViewpoint = Viewpoint(34.056295, -117.195800, 10000000.0)
operationalLayers.addAll(
listOf(
// New York Transit Frequency
ArcGISMapImageLayer("https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/UrbanObservatory_NYC_TransitFrequency/MapServer"),
// New York Industrial Area
ArcGISMapImageLayer("https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/New_York_Industrial/MapServer"),
// New York Population Density
ArcGISMapImageLayer("https://tiles.arcgis.com/tiles/4yjifSiIG17X0gW4/arcgis/rest/services/NewYorkCity_PopDensity/MapServer"),
// New York Buildings
ArcGISSceneLayer("https://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/Buildings_NewYork_17/SceneServer")
)
)
baseSurface = Surface().apply {
elevationSources.add(
ElevationSource.fromTerrain3dService()
)
}
}
}
val tableTopSceneViewProxy = remember { TableTopSceneViewProxy() }
Expand All @@ -56,6 +80,9 @@ fun MainScreen() {
Box(modifier = Modifier.fillMaxSize()) {
TableTopSceneView(
arcGISScene = arcGISScene,
arcGISSceneAnchor = Point(-74.0, 40.72, 0.0, arcGISScene.spatialReference),
translationFactor = 2000.0,
clippingDistance = 750.0,
modifier = Modifier.fillMaxSize(),
tableTopSceneViewProxy = tableTopSceneViewProxy,
onInitializationStatusChanged = {
Expand All @@ -70,14 +97,71 @@ fun MainScreen() {
) {
tappedLocation?.let {
Callout(location = it, modifier = Modifier.wrapContentSize()) {
Text("Lat: ${it.y.roundToInt()}, Lon: ${it.x.roundToInt()}")
Text(stringResource(R.string.lat_lon, it.y.roundToInt(), it.x.roundToInt()))
}
}
}
Text(
text = stringResource(R.string.initialization_status, initializationStatus),
modifier = Modifier.height(200.dp),
color = Color.Red
)
when (val status = initializationStatus) {
is TableTopSceneViewStatus.Initializing -> TextWithScrim(text = stringResource(R.string.initializing_overlay))
is TableTopSceneViewStatus.DetectingPlanes -> TextWithScrim(text = stringResource(R.string.detect_planes_overlay))
is TableTopSceneViewStatus.Initialized -> {
val sceneLoadStatus = arcGISScene.loadStatus.collectAsStateWithLifecycle().value
when (sceneLoadStatus) {
is LoadStatus.NotLoaded -> {
// Tell the user to tap the screen if the scene has not started loading
TextWithScrim(text = stringResource(R.string.tap_scene_overlay))
}

is LoadStatus.Loading -> {
// The scene may take a while to load, so show a progress indicator
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
CircularProgressIndicator()
}
}

This comment was marked as resolved.


is LoadStatus.FailedToLoad -> {
TextWithScrim(
text = stringResource(
R.string.failed_to_load_scene,
sceneLoadStatus.error
)
)
}

LoadStatus.Loaded -> {} // Do nothing
}
}

is TableTopSceneViewStatus.FailedToInitialize -> {
TextWithScrim(
text = stringResource(
R.string.failed_to_initialize_overlay,
status.error.message ?: status.error
)
)
}
}
}
}

/**
* Displays the provided [text] on top of a half-transparent gray background.
*
* @since 200.6.0
*/
@Composable
fun TextWithScrim(text: String) {
Column(
modifier = Modifier
.background(Color.Gray.copy(alpha = 0.5f))
.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = text)
}
}
6 changes: 6 additions & 0 deletions microapps/ArTabletopApp/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,10 @@
<string name="app_name">ArTabletopApp</string>
<string name="arcore_not_installed_screen_message">Google Play Services for AR must be installed to run this app.</string>
<string name="initialization_status">Initialization status: %1$s</string>
<string name="detect_planes_overlay">Move your phone around to detect planes...</string>
<string name="lat_lon">Lat: %1$s, Lon: %2$s</string>
<string name="tap_scene_overlay">Tap on a plane to place the scene</string>
<string name="initializing_overlay">Setting up AR...</string>
<string name="failed_to_initialize_overlay">Failed to initialize: %1$s</string>
<string name="failed_to_load_scene">Failed to load scene: %1$s</string>
</resources>
13 changes: 13 additions & 0 deletions toolkit/ar/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,22 @@ android {
kotlinOptions {
jvmTarget = "1.8"
}
@Suppress("UnstableApiUsage")
buildFeatures {
compose = true
}
packagingOptions {
exclude("META-INF/LICENSE-notice.md")
exclude("META-INF/LICENSE.md")
}
// If this were not an android project, we would just write `explicitApi()` in the Kotlin scope.
// but as an android project could write `freeCompilerArgs = listOf("-Xexplicit-api=strict")`
// in the kotlinOptions above, but that would enforce api rules on the test code, which we don't want.
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
if ("Test" !in name) {
kotlinOptions.freeCompilerArgs += "-Xexplicit-api=strict"
}
}

/**
* Configures the test report for connected (instrumented) tests to be copied to a central
Expand Down
Loading