Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ androidx-test-junit = "1.3.0"
androidx-window = "1.5.0-beta02"
androidx-window-core = "1.5.0-beta02"
androidx-window-java = "1.5.0-beta02"
androidx-xr-arcore = "1.0.0-alpha05"
androidx-xr-compose = "1.0.0-alpha06"
androidx-xr-scenecore = "1.0.0-alpha06"
androidx-xr-arcore = "1.0.0-alpha06"
androidx-xr-compose = "1.0.0-alpha07"
androidx-xr-scenecore = "1.0.0-alpha07"
androidxHiltNavigationCompose = "1.2.0"
appcompat = "1.7.1"
coil = "2.7.0"
Expand Down
5 changes: 1 addition & 4 deletions xr/src/main/java/com/example/xr/arcore/Anchors.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import androidx.xr.arcore.AnchorCreateSuccess
import androidx.xr.arcore.Trackable
import androidx.xr.runtime.Config
import androidx.xr.runtime.Session
import androidx.xr.runtime.SessionConfigureConfigurationNotSupported
import androidx.xr.runtime.SessionConfigureSuccess
import androidx.xr.runtime.math.Pose
import androidx.xr.scenecore.AnchorEntity
Expand All @@ -34,11 +33,9 @@ fun configureAnchoring(session: Session) {
anchorPersistence = Config.AnchorPersistenceMode.LOCAL,
)
when (val result = session.configure(newConfig)) {
is SessionConfigureConfigurationNotSupported ->
TODO(/* Some combinations of configurations are not valid. Handle this failure case. */)
is SessionConfigureSuccess -> TODO(/* Success! */)
else ->
TODO(/* A different unhandled exception was thrown. */)
TODO(/* The session could not be configured. See SessionConfigureResult for possible causes. */)
}
// [END androidxr_arcore_anchoring_configure]
}
Expand Down
21 changes: 9 additions & 12 deletions xr/src/main/java/com/example/xr/arcore/Hands.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ import android.app.Activity
import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope
import androidx.xr.arcore.Hand
import androidx.xr.arcore.HandJointType
import androidx.xr.runtime.Config
import androidx.xr.runtime.HandJointType
import androidx.xr.runtime.Session
import androidx.xr.runtime.SessionConfigureConfigurationNotSupported
import androidx.xr.runtime.SessionConfigureSuccess
import androidx.xr.runtime.math.Pose
import androidx.xr.runtime.math.Quaternion
Expand All @@ -40,11 +39,9 @@ fun ComponentActivity.configureSession(session: Session) {
handTracking = Config.HandTrackingMode.BOTH
)
when (val result = session.configure(newConfig)) {
is SessionConfigureConfigurationNotSupported ->
TODO(/* Some combinations of configurations are not valid. Handle this failure case. */)
is SessionConfigureSuccess -> TODO(/* Success! */)
else ->
TODO(/* A different unhandled exception was thrown. */)
TODO(/* The session could not be configured. See SessionConfigureResult for possible causes. */)
}
// [END androidxr_arcore_hand_configure]
}
Expand Down Expand Up @@ -80,7 +77,7 @@ fun ComponentActivity.renderPlanetAtHandPalm(leftHandState: Hand.State) {
val session: Session = null!!
val palmEntity: GltfModelEntity = null!!
// [START androidxr_arcore_hand_entityAtHandPalm]
val palmPose = leftHandState.handJoints[HandJointType.PALM] ?: return
val palmPose = leftHandState.handJoints[HandJointType.HAND_JOINT_TYPE_PALM] ?: return

// the down direction points in the same direction as the palm
val angle = Vector3.angleBetween(palmPose.rotation * Vector3.Down, Vector3.Up)
Expand All @@ -101,7 +98,7 @@ fun ComponentActivity.renderPlanetAtFingerTip(rightHandState: Hand.State) {
val indexFingerEntity: GltfModelEntity = null!!

// [START androidxr_arcore_hand_entityAtIndexFingerTip]
val tipPose = rightHandState.handJoints[HandJointType.INDEX_TIP] ?: return
val tipPose = rightHandState.handJoints[HandJointType.HAND_JOINT_TYPE_INDEX_TIP] ?: return

// the forward direction points towards the finger tip.
val angle = Vector3.angleBetween(tipPose.rotation * Vector3.Forward, Vector3.Up)
Expand All @@ -120,9 +117,9 @@ fun ComponentActivity.renderPlanetAtFingerTip(rightHandState: Hand.State) {

private fun detectPinch(session: Session, handState: Hand.State): Boolean {
// [START androidxr_arcore_hand_pinch_gesture]
val thumbTip = handState.handJoints[HandJointType.THUMB_TIP] ?: return false
val thumbTip = handState.handJoints[HandJointType.HAND_JOINT_TYPE_THUMB_TIP] ?: return false
val thumbTipPose = session.scene.perceptionSpace.transformPoseTo(thumbTip, session.scene.activitySpace)
val indexTip = handState.handJoints[HandJointType.INDEX_TIP] ?: return false
val indexTip = handState.handJoints[HandJointType.HAND_JOINT_TYPE_INDEX_TIP] ?: return false
val indexTipPose = session.scene.perceptionSpace.transformPoseTo(indexTip, session.scene.activitySpace)
return Vector3.distance(thumbTipPose.translation, indexTipPose.translation) < 0.05
// [END androidxr_arcore_hand_pinch_gesture]
Expand All @@ -136,8 +133,8 @@ private fun detectStop(session: Session, handState: Hand.State): Boolean {
val forward2 = handState.handJoints[joint2]?.forward ?: return false
return Vector3.angleBetween(forward1, forward2) < threshold
}
return pointingInSameDirection(HandJointType.INDEX_PROXIMAL, HandJointType.INDEX_TIP) &&
pointingInSameDirection(HandJointType.MIDDLE_PROXIMAL, HandJointType.MIDDLE_TIP) &&
pointingInSameDirection(HandJointType.RING_PROXIMAL, HandJointType.RING_TIP)
return pointingInSameDirection(HandJointType.HAND_JOINT_TYPE_INDEX_PROXIMAL, HandJointType.HAND_JOINT_TYPE_INDEX_TIP) &&
pointingInSameDirection(HandJointType.HAND_JOINT_TYPE_MIDDLE_PROXIMAL, HandJointType.HAND_JOINT_TYPE_MIDDLE_TIP) &&
pointingInSameDirection(HandJointType.HAND_JOINT_TYPE_RING_PROXIMAL, HandJointType.HAND_JOINT_TYPE_RING_TIP)
// [END androidxr_arcore_hand_stop_gesture]
}
5 changes: 1 addition & 4 deletions xr/src/main/java/com/example/xr/arcore/Planes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package com.example.xr.arcore
import androidx.xr.arcore.Plane
import androidx.xr.runtime.Config
import androidx.xr.runtime.Session
import androidx.xr.runtime.SessionConfigureConfigurationNotSupported
import androidx.xr.runtime.SessionConfigureSuccess
import androidx.xr.runtime.math.Pose
import androidx.xr.runtime.math.Ray
Expand All @@ -31,11 +30,9 @@ fun configurePlaneTracking(session: Session) {
planeTracking = Config.PlaneTrackingMode.HORIZONTAL_AND_VERTICAL,
)
when (val result = session.configure(newConfig)) {
is SessionConfigureConfigurationNotSupported ->
TODO(/* Some combinations of configurations are not valid. Handle this failure case. */)
is SessionConfigureSuccess -> TODO(/* Success! */)
else ->
TODO(/* A different unhandled exception was thrown. */)
TODO(/* The session could not be configured. See SessionConfigureResult for possible causes. */)
}
// [END androidxr_arcore_planetracking_configure]
}
Expand Down
10 changes: 5 additions & 5 deletions xr/src/main/java/com/example/xr/compose/Orbiter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ import androidx.xr.compose.spatial.ContentEdge
import androidx.xr.compose.spatial.Orbiter
import androidx.xr.compose.spatial.OrbiterOffsetType
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.MovePolicy
import androidx.xr.compose.subspace.ResizePolicy
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.SpatialRow
import androidx.xr.compose.subspace.layout.SpatialRoundedCornerShape
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.movable
import androidx.xr.compose.subspace.layout.resizable
import androidx.xr.compose.subspace.layout.width
import com.example.xr.R

Expand All @@ -57,9 +57,9 @@ private fun OrbiterExampleSubspace() {
SpatialPanel(
SubspaceModifier
.height(824.dp)
.width(1400.dp)
.movable()
.resizable()
.width(1400.dp),
dragPolicy = MovePolicy(),
resizePolicy = ResizePolicy(),
) {
SpatialPanelContent()
OrbiterExample()
Expand Down
15 changes: 7 additions & 8 deletions xr/src/main/java/com/example/xr/compose/SpatialPanel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.xr.compose.platform.LocalSpatialCapabilities
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.MovePolicy
import androidx.xr.compose.subspace.ResizePolicy
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.movable
import androidx.xr.compose.subspace.layout.resizable
import androidx.xr.compose.subspace.layout.width

@Composable
Expand All @@ -43,9 +43,9 @@ private fun SpatialPanelExample() {
SpatialPanel(
SubspaceModifier
.height(824.dp)
.width(1400.dp)
.movable()
.resizable()
.width(1400.dp),
dragPolicy = MovePolicy(),
resizePolicy = ResizePolicy(),
) {
SpatialPanelContent()
}
Expand Down Expand Up @@ -81,9 +81,8 @@ private fun ContentInSpatialPanel() {
if (LocalSpatialCapabilities.current.isSpatialUiEnabled) {
Subspace {
SpatialPanel(
SubspaceModifier
.resizable(true)
.movable(true)
dragPolicy = MovePolicy(),
resizePolicy = ResizePolicy(),
) {
AppContent()
}
Expand Down
9 changes: 5 additions & 4 deletions xr/src/main/java/com/example/xr/compose/Volume.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ import androidx.compose.ui.unit.sp
import androidx.xr.compose.platform.LocalSession
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.ExperimentalSubspaceVolumeApi
import androidx.xr.compose.subspace.MovePolicy
import androidx.xr.compose.subspace.ResizePolicy
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.Volume
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.movable
import androidx.xr.compose.subspace.layout.offset
import androidx.xr.compose.subspace.layout.resizable
import androidx.xr.compose.subspace.layout.scale
import androidx.xr.compose.subspace.layout.width
import kotlinx.coroutines.launch
Expand All @@ -44,8 +44,9 @@ private fun VolumeExample() {
// [START androidxr_compose_Volume]
Subspace {
SpatialPanel(
SubspaceModifier.height(1500.dp).width(1500.dp)
.resizable().movable()
SubspaceModifier.height(1500.dp).width(1500.dp),
dragPolicy = MovePolicy(),
resizePolicy = ResizePolicy(),
) {
ObjectInAVolume(true)
Box(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.example.xr.scenecore

import androidx.xr.runtime.Session
import androidx.xr.runtime.math.FloatSize2d
import androidx.xr.runtime.math.FloatSize3d
import androidx.xr.scenecore.ResizableComponent
import androidx.xr.scenecore.ResizeEvent
Expand All @@ -32,11 +33,11 @@ private fun resizableComponentExample(
val resizableComponent = ResizableComponent.create(session) { event ->
if (event.resizeState == ResizeEvent.ResizeState.RESIZE_STATE_END) {
// update the Entity to reflect the new size
surfaceEntity.canvasShape = SurfaceEntity.CanvasShape.Quad(event.newSize.width, event.newSize.height)
surfaceEntity.shape = SurfaceEntity.Shape.Quad(FloatSize2d(event.newSize.width, event.newSize.height))
}
}
resizableComponent.minimumEntitySize = FloatSize3d(177f, 100f, 1f)
resizableComponent.fixedAspectRatio = 16f / 9f // Specify a 16:9 aspect ratio
resizableComponent.isFixedAspectRatioEnabled = true // Maintain a fixed aspect ratio when resizing

surfaceEntity.addComponent(resizableComponent)
// [END androidxr_scenecore_resizableComponentExample]
Expand Down
59 changes: 29 additions & 30 deletions xr/src/main/java/com/example/xr/scenecore/SpatialVideo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,22 @@ import androidx.media3.common.C
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer
import androidx.xr.runtime.Session
import androidx.xr.runtime.math.FloatSize2d
import androidx.xr.runtime.math.Pose
import androidx.xr.runtime.math.Vector3
import androidx.xr.scenecore.SurfaceEntity
import androidx.xr.scenecore.Texture
import androidx.xr.scenecore.TextureSampler
import androidx.xr.scenecore.scene
import java.nio.file.Paths
import kotlinx.coroutines.launch

private fun ComponentActivity.surfaceEntityCreate(xrSession: Session) {
// [START androidxr_scenecore_surfaceEntityCreate]
val stereoSurfaceEntity = SurfaceEntity.create(
xrSession,
SurfaceEntity.StereoMode.SIDE_BY_SIDE,
Pose(Vector3(0.0f, 0.0f, -1.5f)),
SurfaceEntity.CanvasShape.Quad(1.0f, 1.0f)
session = xrSession,
stereoMode = SurfaceEntity.StereoMode.STEREO_MODE_SIDE_BY_SIDE,
pose = Pose(Vector3(0.0f, 0.0f, -1.5f)),
shape = SurfaceEntity.Shape.Quad(FloatSize2d(1.0f, 1.0f))
)
val videoUri = Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
Expand All @@ -60,13 +60,13 @@ private fun ComponentActivity.surfaceEntityCreateSbs(xrSession: Session) {
// Set up the surface for playing a 180° video on a hemisphere.
val hemisphereStereoSurfaceEntity =
SurfaceEntity.create(
xrSession,
SurfaceEntity.StereoMode.SIDE_BY_SIDE,
xrSession.scene.spatialUser.head?.transformPoseTo(
session = xrSession,
stereoMode = SurfaceEntity.StereoMode.STEREO_MODE_SIDE_BY_SIDE,
pose = xrSession.scene.spatialUser.head?.transformPoseTo(
Pose.Identity,
xrSession.scene.activitySpace
)!!,
SurfaceEntity.CanvasShape.Vr180Hemisphere(1.0f),
shape = SurfaceEntity.Shape.Hemisphere(1.0f),
)
// ... and use the surface for playing the media.
// [END androidxr_scenecore_surfaceEntityCreateSbs]
Expand All @@ -77,13 +77,13 @@ private fun ComponentActivity.surfaceEntityCreateTb(xrSession: Session) {
// Set up the surface for playing a 360° video on a sphere.
val sphereStereoSurfaceEntity =
SurfaceEntity.create(
xrSession,
SurfaceEntity.StereoMode.TOP_BOTTOM,
xrSession.scene.spatialUser.head?.transformPoseTo(
session = xrSession,
stereoMode = SurfaceEntity.StereoMode.STEREO_MODE_TOP_BOTTOM,
pose = xrSession.scene.spatialUser.head?.transformPoseTo(
Pose.Identity,
xrSession.scene.activitySpace
)!!,
SurfaceEntity.CanvasShape.Vr360Sphere(1.0f),
shape = SurfaceEntity.Shape.Sphere(1.0f),
)
// ... and use the surface for playing the media.
// [END androidxr_scenecore_surfaceEntityCreateTb]
Expand All @@ -93,10 +93,10 @@ private fun ComponentActivity.surfaceEntityCreateMVHEVC(xrSession: Session) {
// [START androidxr_scenecore_surfaceEntityCreateMVHEVC]
// Create the SurfaceEntity with the StereoMode corresponding to the MV-HEVC content
val stereoSurfaceEntity = SurfaceEntity.create(
xrSession,
SurfaceEntity.StereoMode.MULTIVIEW_LEFT_PRIMARY,
Pose(Vector3(0.0f, 0.0f, -1.5f)),
SurfaceEntity.CanvasShape.Quad(1.0f, 1.0f)
session = xrSession,
stereoMode = SurfaceEntity.StereoMode.STEREO_MODE_MULTIVIEW_LEFT_PRIMARY,
pose = Pose(Vector3(0.0f, 0.0f, -1.5f)),
shape = SurfaceEntity.Shape.Quad(FloatSize2d(1.0f, 1.0f))
)
val videoUri = Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
Expand All @@ -123,10 +123,10 @@ private fun ComponentActivity.surfaceEntityCreateDRM(xrSession: Session) {
// Create the SurfaceEntity with the PROTECTED content security level.
val protectedSurfaceEntity = SurfaceEntity.create(
session = xrSession,
stereoMode = SurfaceEntity.StereoMode.SIDE_BY_SIDE,
stereoMode = SurfaceEntity.StereoMode.STEREO_MODE_SIDE_BY_SIDE,
pose = Pose(Vector3(0.0f, 0.0f, -1.5f)),
canvasShape = SurfaceEntity.CanvasShape.Quad(1.0f, 1.0f),
contentSecurityLevel = SurfaceEntity.ContentSecurityLevel.PROTECTED
shape = SurfaceEntity.Shape.Quad(FloatSize2d(1.0f, 1.0f)),
surfaceProtection = SurfaceEntity.SurfaceProtection.SURFACE_PROTECTION_PROTECTED
)

// Build a MediaItem with the necessary DRM configuration.
Expand Down Expand Up @@ -156,20 +156,20 @@ private fun ComponentActivity.surfaceEntityHDR(xrSession: Session) {
// Define the color properties for your HDR video. These values should be specific
// to your content.
val hdrMetadata = SurfaceEntity.ContentColorMetadata(
colorSpace = SurfaceEntity.ContentColorMetadata.ColorSpace.BT2020,
colorTransfer = SurfaceEntity.ContentColorMetadata.ColorTransfer.ST2084, // PQ
colorRange = SurfaceEntity.ContentColorMetadata.ColorRange.LIMITED,
maxCLL = 1000 // Example: 1000 nits
colorSpace = SurfaceEntity.ContentColorMetadata.ColorSpace.COLOR_SPACE_BT2020,
colorTransfer = SurfaceEntity.ContentColorMetadata.ColorTransfer.COLOR_TRANSFER_ST2084, // PQ
colorRange = SurfaceEntity.ContentColorMetadata.ColorRange.COLOR_RANGE_LIMITED,
maxContentLightLevel = 1000 // Example: 1000 nits
)

// Create a SurfaceEntity, passing the HDR metadata at creation time.
val hdrSurfaceEntity = SurfaceEntity.create(
session = xrSession,
stereoMode = SurfaceEntity.StereoMode.MONO,
stereoMode = SurfaceEntity.StereoMode.STEREO_MODE_MONO,
pose = Pose(Vector3(0.0f, 0.0f, -1.5f)),
canvasShape = SurfaceEntity.CanvasShape.Quad(1.0f, 1.0f),
contentColorMetadata = hdrMetadata
shape = SurfaceEntity.Shape.Quad(FloatSize2d(1.0f, 1.0f)),
)
hdrSurfaceEntity.contentColorMetadata = hdrMetadata

// Initialize ExoPlayer and set the surface.
val exoPlayer = ExoPlayer.Builder(this).build()
Expand All @@ -195,8 +195,8 @@ private fun surfaceEntityEdgeFeathering(xrSession: Session) {
)

// Feather the edges of the surface.
surfaceEntity.edgeFeather =
SurfaceEntity.EdgeFeatheringParams.SmoothFeather(0.1f, 0.1f)
surfaceEntity.edgeFeatheringParams =
SurfaceEntity.EdgeFeatheringParams.RectangleFeather(0.1f, 0.1f)
// [END androidxr_scenecore_surfaceEntityEdgeFeathering]
}

Expand All @@ -214,7 +214,6 @@ private fun surfaceEntityAlphaMasking(xrSession: Session, activity: ComponentAct
Texture.create(
xrSession,
Paths.get("textures", "alpha_mask.png"),
TextureSampler.create()
)

// Apply the alpha mask.
Expand Down