如何在不点击屏幕的情况下放置对象 [英] How to place a object without tapping on the screen
问题描述
我正在尝试使用 ARCore 在不点击屏幕的情况下显示对象.在谷歌提供的ARCore Sceneform基础示例中,检测到表面后需要点击屏幕.
I am trying to show an object without tapping on the screen using ARCore. In the basic sample of ARCore Sceneform provided by Google, you need to tap on the screen after it detects the surface.
我想实现这一点,AR 无需点击屏幕即可显示对象.
I want to implement that, AR shows the object without tapping on the screen.
Anchor newAnchor;
for (Plane plane : mSession.getAllTrackables(Plane.class)) {
if (plane.getType() == Plane.Type.HORIZONTAL_UPWARD_FACING
&& plane.getTrackingState() == TrackingState.TRACKING)
{
newAnchor = plane.createAnchor(plane.getCenterPose());
break;
}
}
我试过这个是为了在不点击屏幕的情况下显示.
I tried this for displaying without tapping on the screen.
如果有人知道如何做到这一点,请帮助我.提前致谢
if Anyone know how to do this please help me. Thanks in Advance
推荐答案
尽管我建议您在用户点击 & 时放置对象他/她在屏幕上点击的地方,可以像这样实现您的要求.(这个例子是在 Kotlin 中)
Although I suggest you place the object when a user taps & where s/he taps on the screen, what you're asking can be achieved like so. (this example is in Kotlin)
在开始放置对象之前,您需要创建一个 ModelRenderable
.全局声明一个 @Nullable
.
Before you begin placing an object, you need to create a ModelRenderable
. Declare one @Nullable
globally.
private var modelRenderable: ModelRenderable? = null
//Create the football renderable
ModelRenderable.builder()
//get the context of the ARFragment and pass the name of your .sfb file
.setSource(fragment.context, Uri.parse("FootBall.sfb"))
.build()
//I accepted the CompletableFuture using Async since I created my model on creation of the activity. You could simply use .thenAccept too.
//Use the returned modelRenderable and save it to a global variable of the same name
.thenAcceptAsync { modelRenderable -> this@MainActivity.modelRenderable = modelRenderable }
编程的主要部分必须在框架的 onUpdate
方法上完成.因此,您可以像这样附加一个用于帧更新的侦听器
The major chunk of the programming has to be done on the frame's onUpdate
method. So you attach a listener for frame updates like so
fragment.arSceneView.scene.addOnUpdateListener(this@MainActivity) //You can do this anywhere. I do it on activity creation post inflating the fragment
现在您处理在侦听器上添加对象.
now you handle adding an object on the listener.
override fun onUpdate(frameTime: FrameTime?) {
//get the frame from the scene for shorthand
val frame = fragment.arSceneView.arFrame
if (frame != null) {
//get the trackables to ensure planes are detected
val var3 = frame.getUpdatedTrackables(Plane::class.java).iterator()
while(var3.hasNext()) {
val plane = var3.next() as Plane
//If a plane has been detected & is being tracked by ARCore
if (plane.trackingState == TrackingState.TRACKING) {
//Hide the plane discovery helper animation
fragment.planeDiscoveryController.hide()
//Get all added anchors to the frame
val iterableAnchor = frame.updatedAnchors.iterator()
//place the first object only if no previous anchors were added
if(!iterableAnchor.hasNext()) {
//Perform a hit test at the center of the screen to place an object without tapping
val hitTest = frame.hitTest(frame.screenCenter().x, frame.screenCenter().y)
//iterate through all hits
val hitTestIterator = hitTest.iterator()
while(hitTestIterator.hasNext()) {
val hitResult = hitTestIterator.next()
//Create an anchor at the plane hit
val modelAnchor = plane.createAnchor(hitResult.hitPose)
//Attach a node to this anchor with the scene as the parent
val anchorNode = AnchorNode(modelAnchor)
anchorNode.setParent(fragment.arSceneView.scene)
//create a new TranformableNode that will carry our object
val transformableNode = TransformableNode(fragment.transformationSystem)
transformableNode.setParent(anchorNode)
transformableNode.renderable = this@MainActivity.modelRenderable
//Alter the real world position to ensure object renders on the table top. Not somewhere inside.
transformableNode.worldPosition = Vector3(modelAnchor.pose.tx(),
modelAnchor.pose.compose(Pose.makeTranslation(0f, 0.05f, 0f)).ty(),
modelAnchor.pose.tz())
}
}
}
}
}
}
我使用了一种扩展方法
//A method to find the screen center. This is used while placing objects in the scene
private fun Frame.screenCenter(): Vector3 {
val vw = findViewById<View>(android.R.id.content)
return Vector3(vw.width / 2f, vw.height / 2f, 0f)
}
这是最终结果
这篇关于如何在不点击屏幕的情况下放置对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!