Untitled
unknown
plain_text
a year ago
6.1 kB
8
Indexable
private const val kModelFile = "models/arrow.glb"
class ArCore : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// A surface container using the 'background' color from the theme
Box(
modifier = Modifier.fillMaxSize(),
) {
// The destroy calls are automatically made when their disposable effect leaves
// the composition or its key changes.
val engine = rememberEngine()
val modelLoader = rememberModelLoader(engine)
val materialLoader = rememberMaterialLoader(engine)
val cameraNode = rememberARCameraNode(engine)
val childNodes = rememberNodes()
val view = rememberView(engine)
val collisionSystem = rememberCollisionSystem(view)
var planeRenderer by remember { mutableStateOf(true) }
var trackingFailureReason by remember {
mutableStateOf<TrackingFailureReason?>(null)
}
var frame by remember { mutableStateOf<Frame?>(null) }
ARScene(
modifier = Modifier.fillMaxSize(),
childNodes = childNodes,
engine = engine,
view = view,
modelLoader = modelLoader,
collisionSystem = collisionSystem,
sessionConfiguration = { session, config ->
config.depthMode =
when (session.isDepthModeSupported(Config.DepthMode.AUTOMATIC)) {
true -> Config.DepthMode.AUTOMATIC
else -> Config.DepthMode.DISABLED
}
config.instantPlacementMode = Config.InstantPlacementMode.LOCAL_Y_UP
config.lightEstimationMode =
Config.LightEstimationMode.ENVIRONMENTAL_HDR
},
cameraNode = cameraNode,
planeRenderer = planeRenderer,
onTrackingFailureChanged = {
trackingFailureReason = it
},
onSessionUpdated = { session, updatedFrame ->
frame = updatedFrame
if (childNodes.isEmpty()) {
updatedFrame.getUpdatedPlanes()
.firstOrNull { it.type == Plane.Type.HORIZONTAL_UPWARD_FACING }
?.let { it.createAnchorOrNull(it.centerPose) }?.let { anchor ->
childNodes += createAnchorNode(
engine = engine,
modelLoader = modelLoader,
materialLoader = materialLoader,
anchor = anchor
)
}
}
},
onGestureListener = rememberOnGestureListener(
onSingleTapConfirmed = { motionEvent, node ->
if (node == null) {
val hitResults = frame?.hitTest(motionEvent.x, motionEvent.y)
hitResults?.firstOrNull {
it.isValid(
depthPoint = false,
point = false
)
}?.createAnchorOrNull()
?.let { anchor ->
planeRenderer = false
childNodes += createAnchorNode(
engine = engine,
modelLoader = modelLoader,
materialLoader = materialLoader,
anchor = anchor
)
}
}
})
)
}
}
}
fun createAnchorNode(
engine: Engine,
modelLoader: ModelLoader,
materialLoader: MaterialLoader,
anchor: Anchor
): AnchorNode {
val anchorNode = AnchorNode(engine = engine, anchor = anchor)
val modelNode = ModelNode(
modelInstance = modelLoader.createModelInstance(kModelFile),
// Scale to fit in a 0.5 meters cube
scaleToUnits = 0.5f
).apply {
// Model Node needs to be editable for independent rotation from the anchor rotation
isEditable = true
editableScaleRange = 0.2f..0.75f
}
val boundingBoxNode = CubeNode(
engine,
size = modelNode.extents,
center = modelNode.center,
materialInstance = materialLoader.createColorInstance(Color.White.copy(alpha = 0.5f))
).apply {
isVisible = false
}
modelNode.addChildNode(boundingBoxNode)
anchorNode.addChildNode(modelNode)
listOf(modelNode, anchorNode).forEach {
it.onEditingChanged = { editingTransforms ->
boundingBoxNode.isVisible = editingTransforms.isNotEmpty()
}
}
return anchorNode
}
}Editor is loading...
Leave a Comment