Untitled
unknown
plain_text
5 months ago
9.0 kB
4
Indexable
@Composable fun ARSceneContent(sourceLatLng: LatLng,destinationLatLng: LatLng?) { Box(modifier = Modifier.fillMaxSize()) { 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) } var destinationAnchor: Anchor? = null var previousDestination: LatLng? = 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 config.geospatialMode = Config.GeospatialMode.ENABLED }, cameraNode = cameraNode, planeRenderer = planeRenderer, onTrackingFailureChanged = { trackingFailureReason = it }, onSessionUpdated = { session, updatedFrame -> frame = updatedFrame // if(session.isGeospatialModeSupported(Config.GeospatialMode.ENABLED)){ //// Log.d("tg", "ARSceneContent:enabled ") // } // 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 // ) // } // } val earth = session.earth if (earth?.earthState == Earth.EarthState.ENABLED) { // Check if destination anchor needs to be recreated if (destinationAnchor == null || previousDestination != destinationLatLng) { previousDestination = destinationLatLng // Detach old anchor if it exists destinationAnchor?.detach() destinationAnchor = createDestinationAnchor(earth, destinationLatLng!!)?.also { anchor -> childNodes += createAnchorNode( engine = engine, modelLoader = modelLoader, materialLoader = materialLoader, anchor = anchor ) } } } else{ Log.d("tag", "null: "+earth) } }, 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 createDestinationAnchor(earth: Earth?, destinationLatLng: LatLng): Anchor? { if (earth?.earthState != Earth.EarthState.ENABLED) { Log.e("Anchor", "Earth is not enabled") return null } val latitude = destinationLatLng.latitude val longitude = destinationLatLng.longitude val altitude = earth.cameraGeospatialPose.altitude - 1.5 return earth.createAnchor( longitude, altitude, latitude, 0.0f, 0.0f, 0.0f, 1.0f ).also { Log.d("Anchor", "Created anchor at Lat=$latitude, Lng=$longitude, Alt=$altitude") } } 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 } fun generatePathPoints(start: LatLng, end: LatLng, spacing: Double): List<LatLng> { val pathPoints = mutableListOf<LatLng>() val distance = calculateDistance(start, end) val steps = (distance / spacing).toInt() Log.d("", "distance: "+distance) for (i in 0..steps) { val fraction = i.toDouble() / steps val lat = start.latitude + fraction * (end.latitude - start.latitude) val lng = start.longitude + fraction * (end.longitude - start.longitude) pathPoints.add(LatLng(lat, lng)) } Log.d("", "pathPoints: "+pathPoints) return pathPoints } fun calculateBearing(start: LatLng, end: LatLng): Float { val startLat = Math.toRadians(start.latitude) val startLng = Math.toRadians(start.longitude) val endLat = Math.toRadians(end.latitude) val endLng = Math.toRadians(end.longitude) val dLng = endLng - startLng val x = Math.sin(dLng) * Math.cos(endLat) val y = Math.cos(startLat) * Math.sin(endLat) - Math.sin(startLat) * Math.cos(endLat) * Math.cos(dLng) return ((Math.toDegrees(Math.atan2(x, y)) + 360) % 360).toFloat() } // Calculate distance between two LatLng points private fun calculateDistance(start: LatLng, end: LatLng): Double { val results = FloatArray(1) Location.distanceBetween( start.latitude, start.longitude, end.latitude, end.longitude, results ) return results[0].toDouble() }
Editor is loading...
Leave a Comment