J'essaie de montrer un objet sans taper sur l'écran en utilisant ARCore. Dans l'exemple de base d'ARCore Sceneform fourni par Google, vous devez appuyer sur l'écran après qu'il ait détecté la surface.
Je veux implémenter cela, AR montre l'objet sans taper sur l'écran.
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;
}
}
J'ai essayé cela pour afficher sans taper sur l'écran.
si quelqu'un sait comment le faire, veuillez m'aider. Merci d'avance
Bien que je vous suggère de placer l'objet lorsqu'un utilisateur tape et où il tape sur l'écran, ce que vous demandez peut être réalisé de la sorte. (cet exemple est dans Kotlin)
Avant de commencer à placer un objet, vous devez créer un ModelRenderable
. Déclarez un @Nullable
globalement.
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 -> [email protected] = modelRenderable }
La majeure partie de la programmation doit être effectuée sur la méthode onUpdate
du cadre. Vous attachez donc un écouteur pour les mises à jour de trames comme ça
fragment.arSceneView.scene.addOnUpdateListener(this@MainActivity) //You can do this anywhere. I do it on activity creation post inflating the fragment
vous gérez maintenant l'ajout d'un objet sur l'écouteur.
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 = [email protected]
//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())
}
}
}
}
}
}
J'ai utilisé une méthode d'extension
//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)
}
Si vous ne souhaitez pas utiliser hit-testing
ou button's action
méthodes pour placer un objet dans un environnement réel, vous pouvez utiliser, par exemple, la pose d'une caméra pour le placement automatique (rappelez-vous, vous devez ajouter un ARAnchor
, son Node
correspondant et un Renderable
devant l'ARCamera c'est-à-dire le long de -Z
direction):
if (this.anchorNode == null) {
Session session = arFragment.getArSceneView().getSession();
float[] position = { 0, 0, -0.75 }; // 75 cm away from camera
float[] rotation = { 0, 0, 0, 1 };
Anchor anchor = session.createAnchor(new Pose(position, rotation));
anchorNode = new AnchorNode(anchor);
anchorNode.setRenderable(yourModelRenderable);
anchorNode.setParent(arFragment.getArSceneView().getScene());
}
J'espère que cela t'aides.
Voici l'extrait de code si vous souhaitez placer un seul objet. Merci @clinkz
override fun onUpdate(frameTime: FrameTime?) {
arFragment?.let { fragment ->
fragment.arSceneView?.let { sceneView ->
sceneView.arFrame?.let { frame ->
if (!placed) {
val trackable = frame.getUpdatedTrackables(Plane::class.Java).iterator()
if (trackable.hasNext()) {
val plane = trackable.next() as Plane
if (plane.trackingState == TrackingState.TRACKING) {
fragment.planeDiscoveryController?.hide()
val hitTest =
frame.hitTest(frame.screenCenter().x, frame.screenCenter().y)
val hitTestIterator = hitTest.iterator()
if (hitTestIterator.hasNext()) {
val hitResult = hitTestIterator.next()
val modelAnchor = plane.createAnchor(hitResult.hitPose)
val anchorNode = AnchorNode(modelAnchor)
anchorNode.setParent(sceneView.scene)
val transformableNode =
TransformableNode(fragment.transformationSystem)
transformableNode.setParent(anchorNode)
transformableNode.renderable = [email protected]
transformableNode.worldPosition = Vector3(
modelAnchor.pose.tx(),
modelAnchor.pose.compose(
Pose.makeTranslation(
0f,
0.05f,
0f
)
).ty(),
modelAnchor.pose.tz()
)
placed = true
}
}
}
}
}
}
}
}
private fun Frame.screenCenter(): Vector3 {
val vw = findViewById<View>(Android.R.id.content)
return Vector3(vw.width / 2f, vw.height / 2f, 0f)
}