Я думаю, вам нужен Google ARCore Дополненные изображения подход.
Вот как выглядит рабочий код Котлина для дополненных изображений:
class MyArFragment : ArFragment() {
private val trackableMap = mutableMapOf<String, AugmentedImageAnchorNode>()
var setOnStarted: (() -> Unit)? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = super.onCreateView(inflater, container, savedInstanceState)
view!!.visibility = View.GONE
planeDiscoveryController.hide()
planeDiscoveryController.setInstructionView(null)
arSceneView.planeRenderer.isEnabled = false
arSceneView.scene.setOnTouchListener { _, motionEvent ->
swipeAnGestureDetector.onTouchEvent(motionEvent)
}
arSceneView.scene.addOnUpdateListener(::onUpdateFrame)
ArResources.init(this.context!!).handle { _, _ ->
setOnStarted?.invoke()
view.visibility = View.VISIBLE
}
return view
}
override fun onPause() {
super.onPause()
trackableMap.forEach {
arSceneView.scene.removeChild(it.value)
}
trackableMap.clear()
}
override fun getSessionConfiguration(session: Session): Config {
val config = super.getSessionConfiguration(session)
config.focusMode = Config.FocusMode.AUTO
config.augmentedImageDatabase = AugmentedImageDatabase.deserialize(session, context!!.resources.assets.open("yourAR.imgdb"))
return config
}
private fun createArNode(image: AugmentedImage) {
Logger.d("create : ${image.name}(${image.index}), pose: ${image.centerPose}, ex: ${image.extentX}, ez: ${image.extentZ}")
when (image.name) {
"object" -> {
val node = MyAnchorNode().init(image)
trackableMap[image.name] = node
arSceneView.scene.addChild(node)
Toast.makeText(context, "add object", Toast.LENGTH_LONG).show()
}
}
}
private fun onUpdateFrame(@Suppress("UNUSED_PARAMETER") frameTime: FrameTime?) {
val frame = arSceneView.arFrame
if (frame == null || frame.camera.trackingState != TrackingState.TRACKING) {
return
}
frame.getUpdatedTrackables(AugmentedImage::class.java).forEach { image ->
when (image.trackingState) {
TrackingState.TRACKING -> if (trackableMap.contains(image.name)) {
if (trackableMap[image.name]?.update(image) == true) {
Logger.d("update node: ${image.name}(${image.index}), pose: ${image.centerPose}, ex: ${image.extentX}, ez: ${image.extentZ}")
}
} else {
createArNode(image)
}
TrackingState.STOPPED -> {
Logger.d("remove note: ${image.name}(${image.index})")
trackableMap.remove(image.name)
}
else -> {
}
}
}
}
private val swipeAnGestureDetector = GestureDetector(null, object : GestureDetector.SimpleOnGestureListener() {
private val SWIPE_DISTANCE_THRESHOLD = 150
private val SWIPE_VELOCITY_THRESHOLD = 150
override fun onDown(e: MotionEvent?): Boolean {
return true
}
override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
val objectAN = trackableMap["object"] as? MyAnchorNode
if (objectAN != null && objectAN.isActive) {
val distanceX = e2.x - e1.x
val distanceY = e2.y - e1.y
if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (distanceX > 0) {
objectAN.forwardScene()
} else {
objectAN.backwardScene()
}
return true
}
}
return false
}
})
}