All pages
Powered by GitBook
1 of 5

Loading...

Loading...

Loading...

Loading...

Loading...

How to enable VR?

There are few changes we need to make to turn our experience into a VR experience.

import { VRButton } from "/jsm/webxr/VRButton";
renderer.xr.enabled = true;
document.body.appendChild(VRButton.createButton(renderer));

Run the VR experience on your phone

If you are on an iOS

Project

Create your first AR & VR applications on the Web

In this section, we will turn our 3D experience from the last section into an immersive experience. We will develop on our local device, laptop or desktop and run the code locally.

Prerequisites

You can follow along the tutorial using an online editor. If you want to learn how to develop on your local environment, please follow the below checklist.

How to enable AR and Hit-test?

Similar to VR experience, you can add AR Button to enable AR experiences. Additionally, you can specify the required and optional AR features your experience will use.

import { ARButton } from "/jsm/webxr/ARButton";

document.body.appendChild(ARButton.createButton(renderer, { requiredFeatures: ["hit-test"] }));

Add a controller: Returns a Group representing the so called target ray space of the controller. Use this space for visualizing 3D objects that support the user in pointing tasks like UI interaction.

	controller = renderer.xr.getController(0);
	controller.addEventListener("select", onSelect);
	scene.add(controller);

When we are hitting a surface, to indicate the surface, we will create a reticle to our scene.

	//Hit-test indicator
	reticle = new Mesh(new RingBufferGeometry(0.15, 0.2, 32).rotateX(-Math.PI / 2), new MeshBasicMaterial());
	reticle.matrixAutoUpdate = false;
	reticle.visible = false;
	scene.add(reticle);

Let's define the onSelect event that we attached to controller. When the select event happen, meaning user decides to place the object and we create it on the chosen location.

function onSelect() {
	if (reticle.visible) {
		const mesh = new Mesh(geometry, phongMaterial);
		mesh.position.setFromMatrixPosition(reticle.matrix);
		mesh.scale.y = Math.random() * 2 + 1;
		scene.add(mesh);
	}
}

Finally in our render function, we will check in every XRFrame if we have an hit-test source to display the reticle on the surface.

function render(timestamp: number, frame: any) {
	if (frame) {
		earth.visible = false;
		const referenceSpace = renderer.xr.getReferenceSpace();
		const session = renderer.xr.getSession();
		if (hitTestSourceRequested === false) {
			session.requestReferenceSpace("viewer").then((referenceSpace) => {
				session.requestHitTestSource({ space: referenceSpace }).then((source) => {
					hitTestSource = source;
				});
			});

			session.addEventListener("end", () => {
				hitTestSourceRequested = false;
				hitTestSource = null;
			});
			hitTestSourceRequested = true;
		}
		if (hitTestSource) {
			const hitTestResults = frame.getHitTestResults(hitTestSource);
			if (hitTestResults.length) {
				const hit = hitTestResults[0];
				reticle.visible = true;
				reticle.matrix.fromArray(hit.getPose(referenceSpace).transform.matrix);
			} else {
				reticle.visible = false;
			}
		}
	}
	renderer.render(scene, camera);
}

To run the code on your device, you have to give access to your camera when prompted.

How to load a 3D Model

Only a few loaders (e.g. ObjectLoader) are included by default with three.js — others should be added to your app individually.

import { GLTFLoader } from '/jsm/loaders/GLTFLoader.js';

//Model loader
const manager = new LoadingManager();
const loader = new GLTFLoader(manager).setPath("/assets/models/AyaSofia/");
let modelLoaded = false;

Once you've imported a loader, you're ready to add a model to your scene. Syntax varies among different loaders — when using another format, check the examples and documentation for that loader. For glTF, usage with global scripts would be:

Change the onSelect function to load and place the model, instead of the Sphere mesh we were placing previously.

function onSelect() {
	if (reticle.visible && !modelLoaded) {
		loader.load(
			"GM_poly.gltf",
			function (gltf) {
				gltf.scene.children[0].position.setFromMatrixPosition(reticle.matrix);
				scene.add(gltf.scene);
				modelLoaded = true;
			},
			undefined,
			function (error) {
				console.error(error);
			}
		);
	}
}

We can add event callbacks for loading manager.

manager.onStart = function (url, itemsLoaded, itemsTotal) {
	console.log("Started loading file: " + url + ".\nLoaded " + itemsLoaded + " of " + itemsTotal + " files.");
};

manager.onLoad = function () {
	console.log("Loading complete!");
};

manager.onProgress = function (url, itemsLoaded, itemsTotal) {
	console.log("Loading file: " + url + ".\nLoaded " + itemsLoaded + " of " + itemsTotal + " files.");
};

manager.onError = function (url) {
	console.log("There was an error loading " + url);
};

See GLTFLoader documentation for further details.

Exercise

Troubleshooting

You've spent hours modeling an artisanal masterpiece, you load it into the webpage, and — oh no! 😭 It's distorted, miscolored, or missing entirely. Start with these troubleshooting steps:

  1. Check the JavaScript console for errors, and make sure you've used an onError callback when calling .load() to log the result.

  2. View the model in another application. For glTF, drag-and-drop viewers are available for three.js and babylon.js. If the model appears correctly in one or more applications, file a bug against three.js. If the model cannot be shown in any application, we strongly encourage filing a bug with the application used to create the model.

  3. Try scaling the model up or down by a factor of 1000. Many models are scaled differently, and large models may not appear if the camera is inside the model.

  4. Try to add and position a light source. The model may be hidden in the dark.

  5. Look for failed texture requests in the network tab, like C:\\Path\To\Model\texture.jpg. Use paths relative to your model instead, such as images/texture.jpg — this may require editing the model file in a text editor.

How to debug and test your WebXR Application with Chrome Dev Tools?

three.js examplesthreejs.org
ThreeJS gltf loader demo
Logo
Chrome Dev Tools Debugging an AR app