How to Parent 3D Model to Three.js AR Marker
To successfully display a dynamically loaded 3D model on a tracking marker in a WebXR or Three.js augmented reality application, you must load the asset asynchronously and attach it directly to the anchor group associated with your tracking marker. This article provides a concise, step-by-step guide and code implementation for loading a GLTF model and properly parenting it to an AR marker so that it tracks accurately in physical space.
1. Create the Marker Group
In Three.js AR frameworks (such as AR.js or MindAR), tracking markers
are represented as THREE.Group objects. The tracking
library automatically updates the position and rotation of this group
based on the camera’s view of the physical marker.
First, initialize your scene, camera, renderer, and the marker group:
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
// Setup basic Three.js scene
const scene = new THREE.Scene();
// Create a group that will act as the marker anchor
const markerGroup = new THREE.Group();
scene.add(markerGroup);
// Note: Your AR tracking library (e.g., AR.js) must be configured
// to update this markerGroup's matrix.2. Load the 3D Model Dynamically
Use the GLTFLoader to load your 3D model. Because
loading is asynchronous, you must handle the parenting inside the
loader’s success callback function.
const loader = new GLTFLoader();
loader.load(
'path/to/your/model.gltf',
(gltf) => {
const model = gltf.scene;
// Parent the model to the marker group
parentModelToMarker(model, markerGroup);
},
(xhr) => {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
},
(error) => {
console.error('An error happened while loading the model', error);
}
);3. Position and Parent the Model
When you add the model as a child of the markerGroup, it
inherits the marker’s local coordinate system. You must reset or adjust
the model’s local position, rotation, and scale to ensure it sits
correctly on top of the physical marker.
function parentModelToMarker(model, marker) {
// 1. Clear any previous models attached to the marker
while (marker.children.length > 0) {
marker.remove(marker.children[0]);
}
// 2. Adjust local scale to fit the physical marker
// (AR coordinates are typically in meters)
model.scale.set(0.5, 0.5, 0.5);
// 3. Align the model to the center of the marker
model.position.set(0, 0, 0);
// 4. Rotate the model if necessary (e.g., to stand upright)
model.rotation.set(0, 0, 0);
// 5. Parent the model to the marker group
marker.add(model);
}Key Considerations for AR Alignment
- Coordinate Systems: In AR.js, the positive Y-axis usually points up out of the marker, while the X and Z axes represent the flat surface of the marker.
- Model Pivot Point: Ensure your 3D model’s origin (pivot point) is set to its bottom-center in your 3D modeling software (like Blender) before exporting. This ensures the model sits directly on top of the marker surface instead of floating or being partially buried.
- Matrix Updates: Ensure
renderer.xr.enabledis set totrueif using native WebXR, or that your custom tracking loop continuously callsrenderer.render(scene, camera)to apply the tracking matrix transformations to the marker group.