You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
i have three models moveleft, moveright and movefoward. am rendering a model directly in front of camera. this model muct change dynamically based of values that getting changed in
if (step1Details != null && step2Details != null) {
val currentDistance = step1Details.distance
val nextManeuver = step2Details.maneuver
// Determine the instruction based on the current distance and next maneuver
instructionMessage = when {
currentDistance.contains("m") && nextManeuver.equals("turn-left", ignoreCase = true) -> {
"Take Left turn in $currentDistance"
}
currentDistance.contains("m") && nextManeuver.equals("turn-right", ignoreCase = true) -> {
"Take Right turn in $currentDistance"
}
else -> {
"Go Straight!"
}
}
// Log the instruction to console (optional)
Log.d("NavigationInstruction", instructionMessage)
}
moveForward , moveRight , moveLeft these values will changes in this method dynamically at that time I need to replace my gib model that's being rendered. my question is that I need to delete the model node or can I update the exsn g nod itself. The complete source code is given below
private const val kAperture = 16f
private const val kShutterSpeed = 1f / 125f
private const val kSensitivity = 100f
private const val moveForward = "models/map_way.glb"
private const val moveLeft = "models/left_arrow.glb"
private const val moveRight = "models/right_arrow.glb"
var currentModel = moveForward
var isObjectRendered = false
class MainActivity : ComponentActivity() {
private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var locationCallback: LocationCallback
private var locationRequired: Boolean = false
private val permissions = arrayOf(
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
)
override fun onResume() {
super.onResume()
if (locationRequired) {
startLocationUpdates()
}
}
override fun onPause() {
super.onPause()
locationCallback?.let {
fusedLocationClient?.removeLocationUpdates(it)
}
}
@SuppressLint("MissingPermission")
private fun startLocationUpdates() {
locationCallback?.let {
val locationRequest = LocationRequest.Builder(
Priority.PRIORITY_HIGH_ACCURACY, 100
)
.setWaitForAccurateLocation(false)
.setMinUpdateIntervalMillis(3000)
.setMaxUpdateDelayMillis(100)
.build()
fusedLocationClient?.requestLocationUpdates(
locationRequest,
it,
Looper.getMainLooper()
)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
MapsInitializer.initialize(this, MapsInitializer.Renderer.LATEST) {
}
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
setContent {
var currentLocation by remember { mutableStateOf(LatLng(0.toDouble(), 0.toDouble())) }
val cameraPosition = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(
currentLocation, 10f
)
}
val origin = LatLng(
8.4999486,76.6122943
)//You can add your area location it's for camera position
val cameraPositionStateNew = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(origin, 10f)
}
var cameraPositionState by remember {
mutableStateOf(cameraPosition)
}
locationCallback = object : LocationCallback() {
override fun onLocationResult(p0: LocationResult) {
super.onLocationResult(p0)
for (location in p0.locations) {
currentLocation = LatLng(location.latitude, location.longitude)
// Get the accuracy radius from the location object
cameraPositionState = CameraPositionState(
position = CameraPosition.fromLatLngZoom(
currentLocation, 20f
)
)
}
}
}
GoogleNavigationAppTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
LocationScreen(this@MainActivity, currentLocation, cameraPositionStateNew)
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun LocationScreen(
context: Context,
currentLocation: LatLng,
cameraPositionState: CameraPositionState,
viewModel: LocationViewModel = viewModel()
) {
val latLngList = remember { mutableStateOf<List<LatLng>>(emptyList()) }
val destination = remember { mutableStateOf(LatLng(8.4814699,76.941563)) }
val circlePoints = viewModel.generateCirclePoints(currentLocation, 20.00)
val routeSteps = remember { mutableStateOf<List<RouteStep>>(emptyList()) }
val transparentSkyBlue = Color(0x3F00BFFF)
var orientationAngle by remember { mutableStateOf(0f) } // Initial orientation angle
var azimuthDegrees by remember { mutableStateOf(0f) }
val sensorManager = remember { context.getSystemService(Context.SENSOR_SERVICE) as SensorManager }
val accelerometerSensor = remember { sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) }
val magnetometerSensor = remember { sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) }
val originalBitmap: Bitmap = remember { BitmapFactory.decodeResource(context.resources, R.drawable.navigation) }
val desiredWidth = 150 // Specify the desired width in pixels
val desiredHeight = 150 // Specify the desired height in pixels
val resizedBitmap: Bitmap = remember { Bitmap.createScaledBitmap(originalBitmap, desiredWidth, desiredHeight, true) }
val rotatedBitmap: Bitmap = remember(orientationAngle) { viewModel.rotateBitmap(resizedBitmap, orientationAngle) }
val bitmapDescriptor: BitmapDescriptor = remember(rotatedBitmap) { BitmapDescriptorFactory.fromBitmap(rotatedBitmap) }
val step1Details = routeSteps.value.getOrNull(0)
val step2Details = routeSteps.value.getOrNull(1)
val sensorEventListener = remember {
object : SensorEventListener {
private val gravity = FloatArray(3)
private val geomagnetic = FloatArray(3)
private var lastUpdateTime = 0L
override fun onSensorChanged(event: SensorEvent) {
val currentTime = System.currentTimeMillis()
if (currentTime - lastUpdateTime < 100) { // Throttle updates to occur every 100 milliseconds
return
}
lastUpdateTime = currentTime
when (event.sensor.type) {
Sensor.TYPE_ACCELEROMETER -> gravity.apply { event.values.copyInto(this) }
Sensor.TYPE_MAGNETIC_FIELD -> geomagnetic.apply { event.values.copyInto(this) }
}
val rotationMatrix = FloatArray(9)
val success = SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)
if (success) {
val orientation = FloatArray(3)
SensorManager.getOrientation(rotationMatrix, orientation)
val azimuthRadians = orientation[0].toDouble()
azimuthDegrees = Math.toDegrees(azimuthRadians).toFloat()
orientationAngle = azimuthDegrees // Update the orientation angle
}
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
}
}
val launchMultiplePermissions =
rememberLauncherForActivityResult(ActivityResultContracts.RequestMultiplePermissions())
{ permissionMaps ->
val areGranted = permissionMaps.values.reduce { acc, next -> acc && next }
if (areGranted) {
locationRequired = true
startLocationUpdates()
Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
}
}
// Define a function to calculate and display the route to the clicked marker
suspend fun showRouteToMarker(markerLocation: LatLng) {
startLocationUpdates()
// Fetch route from current location to clicked marker's location
latLngList.value = viewModel.fetchRoute(
"${currentLocation.latitude},${currentLocation.longitude}",
"${markerLocation.latitude},${markerLocation.longitude}"
)!!
//get steps
routeSteps.value= viewModel.fetchSteps(
"${currentLocation.latitude},${currentLocation.longitude}",
"${destination.value.latitude},${destination.value.longitude}"
)!!
}
LaunchedEffect(currentLocation) {
if (permissions.all {
ContextCompat.checkSelfPermission(
context,
it
) == PackageManager.PERMISSION_GRANTED
}) {
//get location
startLocationUpdates()
//get route
latLngList.value=viewModel.fetchRoute(
"${currentLocation.latitude},${currentLocation.longitude}",
"${destination.value.latitude},${destination.value.longitude}"
)!!
//get steps
routeSteps.value= viewModel.fetchSteps(
"${currentLocation.latitude},${currentLocation.longitude}",
"${destination.value.latitude},${destination.value.longitude}"
)!!
} else {
launchMultiplePermissions.launch(permissions)
}
}
LaunchedEffect(destination.value) {
destination.value?.let { markerLocation ->
showRouteToMarker(markerLocation)
}
}
LaunchedEffect(orientationAngle) {
orientationAngle = azimuthDegrees // Update the orientation angle
// Delay to throttle updates
delay(100) // Adjust the delay time as needed
}
DisposableEffect(Unit) {
// Register sensor listeners with optimized sampling rate
sensorManager.registerListener(sensorEventListener, accelerometerSensor, SensorManager.SENSOR_DELAY_UI)
sensorManager.registerListener(sensorEventListener, magnetometerSensor, SensorManager.SENSOR_DELAY_UI)
onDispose {
// Unregister sensor listeners
sensorManager.unregisterListener(sensorEventListener)
}
}
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) }
// Variable to hold the navigation instruction
var instructionMessage by remember { mutableStateOf("") }
if (step1Details != null && step2Details != null) {
val currentDistance = step1Details.distance
val nextManeuver = step2Details.maneuver
// Determine the instruction based on the current distance and next maneuver
instructionMessage = when {
currentDistance.contains("m") && nextManeuver.equals("turn-left", ignoreCase = true) -> {
"Take Left turn in $currentDistance"
}
currentDistance.contains("m") && nextManeuver.equals("turn-right", ignoreCase = true) -> {
"Take Right turn in $currentDistance"
}
else -> {
"Go Straight!"
}
}
// Log the instruction to console (optional)
Log.d("NavigationInstruction", instructionMessage)
}
Box(modifier = Modifier.fillMaxSize()) {
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 = false,
onTrackingFailureChanged = {
trackingFailureReason = it
},
onSessionUpdated = { session, updatedFrame ->
frame = updatedFrame
if (updatedFrame.camera.trackingState == TrackingState.TRACKING && !isObjectRendered) {
// Create the pose for placing the object
val cameraPose = updatedFrame.camera.pose
val translation = FloatArray(3).apply { cameraPose.getTranslation(this, 0) }
val rotation = FloatArray(4).apply { cameraPose.getRotationQuaternion(this, 0) }
translation[2] -= 1.0f // Place 1 meter in front of the camera
val anchorPose = Pose(translation, rotation)
val anchor = session.createAnchor(anchorPose)
childNodes += createAnchorNode(
engine = engine,
modelLoader = modelLoader,
materialLoader = materialLoader,
anchor = anchor
)
isObjectRendered = true
} else {
Log.w("ARScene", "Camera is not tracking. Unable to place object.")
}
},
)
androidx.compose.material.Text(
modifier = Modifier
.systemBarsPadding()
.fillMaxWidth()
.align(Alignment.TopCenter)
.padding(top = 16.dp, start = 32.dp, end = 32.dp),
textAlign = TextAlign.Center,
fontSize = 28.sp,
color = Color.White,
text = if (instructionMessage.isNotEmpty()) {
instructionMessage // Display navigation instruction here
} else {
trackingFailureReason?.let {
it.getDescription(LocalContext.current)
} ?: if (childNodes.isEmpty()) {
stringResource(R.string.point_your_phone_down)
} else {
stringResource(R.string.tap_anywhere_to_add_model)
}
}
)
}
}
}
fun createAnchorNode(
engine: Engine,
modelLoader: ModelLoader,
materialLoader: MaterialLoader,
anchor: Anchor
): AnchorNode {
val anchorNode = AnchorNode(engine = engine, anchor = anchor)
val modelNode = ModelNode(
modelInstance = modelLoader.createModelInstance(currentModel),
// 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
}
modelNode.rotation = Rotation(x = 0.0f, y = 0.0f, z = -90.0f) // Adjust as needed
anchorNode.addChildNode(modelNode)
return anchorNode
}
@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class)
@Composable
fun BoxScope.ChipsGroup(labels: List<String>, onSelected: (index: Int) -> Unit) {
var selectedIndex by remember { mutableIntStateOf(0) }
FlowRow(
modifier = Modifier
.fillMaxWidth()
.align(Alignment.BottomEnd)
.background(MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.5f))
.navigationBarsPadding()
.padding(8.dp)
) {
labels.forEachIndexed { index, label ->
val selected = selectedIndex == index
FilterChip(
label = {
Text(
style = MaterialTheme.typography.bodyLarge.copy(),
text = label
)
},
modifier = Modifier.padding(4.dp),
selected = selected,
onClick = {
selectedIndex = index
onSelected(index)
},
leadingIcon = if (selected) {
{
Icon(
imageVector = Icons.Filled.Done,
contentDescription = "Done icon",
modifier = Modifier.size(FilterChipDefaults.IconSize)
)
}
} else {
null
}
)
}
}
}
The text was updated successfully, but these errors were encountered:
i have three models moveleft, moveright and movefoward. am rendering a model directly in front of camera. this model muct change dynamically based of values that getting changed in
if (step1Details != null && step2Details != null) {
val currentDistance = step1Details.distance
val nextManeuver = step2Details.maneuver
moveForward , moveRight , moveLeft these values will changes in this method dynamically at that time I need to replace my gib model that's being rendered. my question is that I need to delete the model node or can I update the exsn g nod itself. The complete source code is given below
The text was updated successfully, but these errors were encountered: