Full orbit control within After Effects extension preview panel

Hello!
I’m using a THREE.GLTFLoader and THREE.OrbitControls inside a preview panel in a After Effects extension.
When a .glb is loaded to the preview window it automatically rotates, and I’m able to use the scroll wheel on the mouse to zoom in and out of the scene, but all the orbit controls/pan controls do not work at all. Below is my current code:

// OrbitControls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // Smooth motion
controls.dampingFactor = 0.05;
controls.enableZoom = true; // Allow zooming
controls.enablePan = true; // Allow panning
controls.enableRotate = true; // Allow rotation

// Allow full vertical orbit: from directly above (0) to directly below (PI)
controls.minPolarAngle = 0;
controls.maxPolarAngle = Math.PI;

// Remove explicit azimuth restrictions so that horizontal rotation is fully free
// (If you need to set limits, try using numeric values, e.g., -Math.PI and Math.PI)

// GLTFLoader
gltfLoader = new THREE.GLTFLoader();

I have been using Chatgpt to help with the coding because I’m not familiar with it yet.

Is this even possible in After Effects? I kind assume that if zooming in and out on the model works full orbit control would work? right?

It’s possible that AE is stealing some events…
A random thing to try is passing window or body instead of renderer.domElement, to try to catch the events higher up…

controls.enableZoom = true; // Allow zooming
controls.enablePan = true; // Allow panning
controls.enableRotate = true; // Allow rotation

shouled be enabled by default, so you don’t need to set those.

@manthrax
Do you mean adding these:
controls.enablePan = true; // Allow panning
controls.enableRotate = true; // Allow rotation

above:
controls = new THREE.OrbitControls(camera, renderer.domElement);

Sorry, Im unsure of “passing window or body instead of renderer.domElement”

Try:

controls = new THREE.OrbitControls(camera, document.body );

Thank you @manthrax I tried:
controls = new THREE.OrbitControls(camera, document.body );

but I still only have the zoom in and zoom out capability with the scroll wheel.

Below is the full code for the preview.js that I’m using for the Orbit Controls and loader.

// Assumes global THREE, THREE.OrbitControls, and THREE.GLTFLoader are available

(function() {
let renderer, scene, camera, controls;
let gltfLoader, model;

function init3DPreview() {
const canvas = document.getElementById(‘previewCanvas’);
// Ensure the canvas can receive focus (if needed)
canvas.setAttribute(‘tabindex’, ‘0’);

renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true });
renderer.setSize(canvas.clientWidth, canvas.clientHeight);

scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000);

camera = new THREE.PerspectiveCamera(45, canvas.clientWidth / canvas.clientHeight, 0.1, 1000);
camera.position.set(0, 0, 3);

// Basic lighting
const light = new THREE.DirectionalLight(0xffffff, 5);
light.position.set(0, 5, 5);
scene.add(light);

// OrbitControls
controls = new THREE.OrbitControls(camera, document.body );

controls.enableDamping = true; // Smooth motion
controls.dampingFactor = 0.05;
controls.enableZoom = true; // Allow zooming
controls.enablePan = true; // Allow panning
controls.enableRotate = true; // Allow rotation

// Allow full vertical orbit: from directly above (0) to directly below (PI)
controls.minPolarAngle = 0;
controls.maxPolarAngle = Math.PI;

// Remove explicit azimuth restrictions so that horizontal rotation is fully free
// (If you need to set limits, try using numeric values, e.g., -Math.PI and Math.PI)

// GLTFLoader
gltfLoader = new THREE.GLTFLoader();

animate();

}

function animate() {
requestAnimationFrame(animate);
if (model) {
model.rotation.y += 0.01; // Optional automatic rotation
}
controls.update();
renderer.render(scene, camera);
}

function loadGLBModel(glbUrl) {
if (model) {
scene.remove(model);
model = null;
}
gltfLoader.load(glbUrl, (gltf) => {
model = gltf.scene;
scene.add(model);
controls.target.copy(model.position); // Center controls on the model
}, undefined, (error) => {
console.error(“Error loading GLB model:”, error);
});
}

// New function: Clears the preview by removing any loaded model.
function clearPreview() {
if (model) {
scene.remove(model);
model = null;
}
}

document.addEventListener(‘DOMContentLoaded’, init3DPreview);

// Expose functions globally for use by other scripts
window.loadGLBModel = loadGLBModel;
window.clearPreview = clearPreview;
})();

Here is my full javascript file.
This file was created with chatgpt.
I still cannot fully orbit around the .glb in the preview window.
If anyone one who has experience with preview windows has the time to check it out, this would be very appreciated!
preview.js (2.8 KB)