libassimp
0.1.0

Open USDZ in Apple Quick Look

Convert a model to USDZ, detect Apple AR Quick Look, and launch the result from a browser.

Open Markdown

Apple Quick Look opens a USDZ file as a rotatable model and, on supported iPhones and iPads, can place it in the room through AR. The conversion below runs locally; open this page on a compatible device to see Open in AR.

1. Produce one USDZ file

import { convert } from 'libassimp';const response = await fetch('/cube.obj');const bytes = new Uint8Array(await response.arrayBuffer());const {  files: [usdz],} = await convert({ name: 'cube.obj', bytes }, { to: 'usdz' });

Input

objcube.obj136 B

Output

Preparing artifact…

Convert
Output
Files
WASM load

Quick Look expects one USDZ archive served as model/vnd.usdz+zip. A browser that cannot launch AR can still download the same output.

2. Detect support before showing the action

Apple exposes Quick Look through an anchor whose relList supports ar. Check the host as well: desktop Safari can understand the relationship without providing the iPhone or iPad AR experience.

const anchor = document.createElement('a');
const appleMobile =
  /iPad|iPhone|iPod/.test(navigator.userAgent) ||
  (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
const canOpenAr = appleMobile && anchor.relList.supports('ar');

Other iOS browsers also delegate USDZ links to Quick Look. If your product supports them, include their iOS user-agent tokens as a fallback after the Apple-device check; libassimp's demo follows the same rule as Tau's viewer.

3. Launch from the user's click

Create the object URL after conversion, retain it while the action is visible, and revoke it when replacing the result or unmounting the view.

const openInAr = (bytes: Uint8Array<ArrayBuffer>): string => {
  const url = URL.createObjectURL(new Blob([bytes], { type: 'model/vnd.usdz+zip' }));
  const anchor = document.createElement('a');
  anchor.rel = 'ar';
  anchor.href = url;
  anchor.append(document.createElement('img'));
  anchor.hidden = true;
  document.body.append(anchor);
  anchor.click();
  anchor.remove();
  return url;
};

declare const usdz: { readonly bytes: Uint8Array<ArrayBuffer> }; // Result from step 1.
let arUrl: string | undefined;

const launch = (): void => {
  if (arUrl !== undefined) URL.revokeObjectURL(arUrl);
  arUrl = openInAr(usdz.bytes);
};

// Call when replacing this result or unmounting its owner, not immediately after launch.
const release = (): void => {
  if (arUrl !== undefined) URL.revokeObjectURL(arUrl);
  arUrl = undefined;
};

Call openInAr directly from the button's click handler. Browsers may block a launch detached from a user gesture. The empty image child is required by the Quick Look link contract.

Variations

Desktop and Android. Keep a normal USDZ download visible; do not show a button that promises AR when the host cannot honour it.

A hosted USDZ. A regular <a rel="ar" href="model.usdz"> works when the file is already on a URL. The Blob route is only for bytes produced in memory.

On this page