基于Android的hello_ar_java项目:如何让3D物体处于AR Core相机中心?
Hey there! I’ve tinkered with the hello_ar_java sample quite a bit, so let me walk you through exactly how to place a 3D object right at the camera’s center using Android Java—no Unity required, just straight native AR Core code.
First, a quick primer: AR Core’s Camera class gives you the pose (position + orientation) of the device’s camera in the real world. To place an object at the camera’s center, we’ll use this pose, but we’ll nudge it slightly forward—because placing an object exactly at the camera’s lens position means it’ll be invisible to the user.
The default hello_ar_java sample uses tap-to-place on detected planes. We’ll replace that logic with code that grabs the camera’s pose and spawns the object there. Here are two common implementations:
Option 1: Place Object on Button Tap
Add a UI button to your layout, then hook up this click listener in your HelloArActivity:
Button placeBtn = findViewById(R.id.place_at_camera_btn); placeBtn.setOnClickListener(v -> { ArSceneView arSceneView = arFragment.getArSceneView(); ARSession session = arSceneView.getSession(); // Make sure session is valid and camera is tracking if (session == null || session.getCamera().getTrackingState() != TrackingState.TRACKING) { Toast.makeText(this, "Wait for AR tracking to stabilize!", Toast.LENGTH_SHORT).show(); return; } // Get current camera pose Pose cameraPose = session.getCamera().getPose(); // Nudge the object 50cm in front of the camera (z-axis controls forward/backward) // Adjust the -0.5f value to move it closer or farther away Pose objectSpawnPose = cameraPose.compose(Pose.makeTranslation(0f, 0f, -0.5f)); // Create an anchor to fix the object in the real world Anchor anchor = session.createAnchor(objectSpawnPose); AnchorNode anchorNode = new AnchorNode(anchor); anchorNode.setParent(arSceneView.getScene()); // Load your 3D model (use the sample's default model or your own .sfb file) Renderable.builder() .setSource(this, Uri.parse("models/andy.sfb")) // Replace with your model path .build() .thenAccept(renderable -> { TransformableNode transformableNode = new TransformableNode(arFragment.getTransformationSystem()); transformableNode.setParent(anchorNode); transformableNode.setRenderable(renderable); transformableNode.select(); // Let users scale/rotate the object post-placement }) .exceptionally(throwable -> { Toast.makeText(this, "Failed to load model: " + throwable.getMessage(), Toast.LENGTH_LONG).show(); return null; }); });
Option 2: Auto-Place Object When Tracking is Stable
If you want the object to spawn automatically once AR Core locks onto the environment, add this to your onCreate method:
// Flag to prevent spawning duplicate objects private boolean isObjectPlaced = false; // ... arFragment.getArSceneView().getScene().addOnUpdateListener(frameTime -> { if (isObjectPlaced) return; ARSession session = arFragment.getArSceneView().getSession(); if (session == null) return; Camera camera = session.getCamera(); // Only spawn when the camera is actively tracking the environment if (camera.getTrackingState() != TrackingState.TRACKING) return; // Reuse the same spawn logic as the button tap option Pose cameraPose = camera.getPose(); Pose objectSpawnPose = cameraPose.compose(Pose.makeTranslation(0f, 0f, -0.5f)); Anchor anchor = session.createAnchor(objectSpawnPose); AnchorNode anchorNode = new AnchorNode(anchor); anchorNode.setParent(arFragment.getArSceneView().getScene()); Renderable.builder() .setSource(this, Uri.parse("models/andy.sfb")) .build() .thenAccept(renderable -> { TransformableNode transformableNode = new TransformableNode(arFragment.getTransformationSystem()); transformableNode.setParent(anchorNode); transformableNode.setRenderable(renderable); transformableNode.select(); isObjectPlaced = true; // Mark as placed to stop repeated spawning }) .exceptionally(throwable -> { Toast.makeText(this, "Model load failed", Toast.LENGTH_SHORT).show(); return null; }); });
- Tracking State Check: Always verify the camera is in
TrackingState.TRACKINGbefore spawning—if it’s inPAUSEDorSTOPPED, the pose data will be inaccurate. - Z-Axis Adjustment: The
-0.5finPose.makeTranslationmoves the object 50cm forward. Tweak this value based on your model’s size (e.g.,-1.0ffor 1 meter away). - Model Format: Use
.sfb(Sceneform Binary) models, just like the sample. You can convert GLB/GLTF models to SFB using the Sceneform SDK’s converter tool.
Run your modified hello_ar_java app:
- Wait for AR Core to initialize and start tracking your surroundings.
- Tap your button (or wait for auto-spawn) and the object should appear right in front of your camera.
- Use the sample’s built-in transformation controls to move, scale, or rotate the object after placement.
内容的提问来源于stack exchange,提问作者Arigarasuthan

