Overview

QuickLook Vertical Image Tracker

In cases in which you are using QuickLook Image Tracker and Vertical Imagery you will need to correct the orientation of the model. As noted on the Detecting Images in an AR Experienceopen in new window page:

SCNPlane is vertically oriented in its local coordinate space, but ARImageAnchor assumes the image is horizontal in its local space, so rotate the plane to match.

import { Behaviour, GameObject, serializable, USDZExporter } from "@needle-tools/engine";
import { Object3D, Euler } from "three";

export class QuickLookObjectsToFix extends Behaviour {

    @serializable(Object3D)
    objectToFix!: Object3D;

    private usdzExporter!: USDZExporter;
    private startRot: Euler = new Euler();

    onEnable() {
        this.usdzExporter = GameObject.findObjectOfType(USDZExporter)!;
        this.startRot = this.objectToFix.rotation;
        this.subscribeToBeforeExportEvent();
    }

    onDisable() {
        this.unsubscribeFromBeforeExportEvent();
    }

    private subscribeToBeforeExportEvent() {
        this.usdzExporter.addEventListener("before-export", this.onBeforeExport);
        this.usdzExporter.addEventListener("after-export", this.onAfterExport);
    }

    private unsubscribeFromBeforeExportEvent() {
        this.usdzExporter.removeEventListener("before-export", this.onBeforeExport);
        this.usdzExporter.removeEventListener("after-export", this.onAfterExport);
    }

    private onBeforeExport = () => {
        this.objectToFix.updateMatrixWorld();
        this.objectToFix.rotation.x = -Math.PI / 2;
        this.objectToFix.updateMatrixWorld();
    }

    private onAfterExport = () => {
        this.objectToFix.updateMatrixWorld();
        this.objectToFix.setRotationFromEuler(this.startRot);
        this.objectToFix.updateMatrixWorld();
    }
}

Thanks to llllkatjallllopen in new window as their Set fallback material for USDZ exporteropen in new window solution helped me come up with a working solution for this.

EDIT: Code cleanup and fixes.