I'm developing an Android app for recognizing augmented images and displaying videos directly over them. I have implemented everything and it's working well but the only issue is that the anchorNode model that gets attached to the augmented image anchor isn't very stable and doesn't remain exactly in the image's frame. I tried to follow some best practices for improving tracking and got better results but there is only one point that I'm not understanding which is "If your image will never move from its initial position (for example, a poster affixed to a wall), you can attach a global anchor to the image to increase tracking stability.", could someone help explain how to that , please? and It would be great if I can get some tips for improving tracking evermore. Thanks in advance. Here is the code I'm using for tracking and creating video anchors.
override fun onSessionConfiguration(session: Session?, config: Config?) {
Log.d("ttt","onSessionConfiguration")
this.session = session
// Disable plane detection
config!!.planeFindingMode = Config.PlaneFindingMode.DISABLED
Thread().run {
database = AugmentedImageDatabase(session).also {
for(fileName in requireContext().fileList().filter { it.contains("image.jpg") }){
val file = File(requireContext().filesDir,fileName)
if(file.exists()){
it.addImage(fileName.toString().split("-")[0],BitmapFactory.decodeFile(file.absolutePath),0.25f)
}
}
}
config.setAugmentedImageDatabase(database)
}
arFragment?.setOnAugmentedImageUpdateListener { it->
run {
onAugmentedImageTrackingUpdate(it)
}
}
}
private fun onAugmentedImageTrackingUpdate(augmentedImage: AugmentedImage) {
attachVideo(augmentedImage)
}
private fun attachVideo(augmentedImage: AugmentedImage){
if (augmentedImage.trackingState == TrackingState.TRACKING
&& augmentedImage.trackingMethod == AugmentedImage.TrackingMethod.FULL_TRACKING){
if (!matrixDetected) {
matrixDetected = true
lastTracketedImageName = augmentedImage.name
anchorNode = AnchorNode(augmentedImage.createAnchor(augmentedImage.centerPose))
anchorNode!!.isSmoothed = true
texture = ExternalTexture().also {
it.surfaceTexture.setOnFrameAvailableListener {
texture!!.surfaceTexture.setOnFrameAvailableListener(null)
val model = ShapeFactory.makeCube(
Vector3(augmentedImage.extentX,0f,augmentedImage.extentZ),
Vector3(0f,0f,0f),
plainVideoMaterial
)
model.isShadowReceiver = false
model.isShadowCaster = false
val renderable = anchorNode!!.setRenderable(model)
renderable.material!!.setExternalTexture("videoTexture",texture)
fadeInVideo(renderable.material)
}
}
val videoFile = File(requireContext().filesDir,"${augmentedImage.name}-video.mp4")
mediaPlayer = MediaPlayer.create(requireContext(),Uri.fromFile(videoFile)).also {
it.isLooping = true
it.setSurface(texture!!.surface)
it.start()
}
arFragment!!.arSceneView.scene.addChild(anchorNode)
}
}else{
if(matrixDetected){
if(anchorNode != null){
arFragment!!.arSceneView.scene.removeChild(anchorNode!!)
anchorNode = null
}
viewLifecycleOwner.lifecycleScope.launch {
val result = viewModel.endArVideo(deviceID,augmentedImage.name)
if(result.isSuccessful){
Log.d("ttt","stop ar request success")
}else{
Log.d("ttt","stop ar request failed ${result.errorBody()}")
}
}
matrixDetected = false
}
mediaPlayer?.let {
it.setSurface(null)
it.stop()
it.release()
mediaPlayer = null
}
}
}
private fun fadeInVideo(material: Material) {
ValueAnimator.ofFloat(0f, 1f).apply {
duration = 500L
interpolator = LinearInterpolator()
addUpdateListener { v ->
material.setFloat("videoAlpha", v.animatedValue as Float)
}
}.start()
}