There is a GLTF file with animated camera and some moving parts and it works fine when the default camera is reassigned by glft.cameras[0] at GLTFLoader.load() and the initial model and camera positions are absolutely as it was designed in Blender.
camera = gltf.cameras[0].clone();
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
camera.needsUpdate = true;
However, the task it to have an interactive OrbitControls mode allowing users to freely rotate/scale and move the platform while holding SHIFT key. And to do this, I’m re-initializing controls by this line at keydown event listener.
controls = new OrbitControls(camera, renderer.domElement);
And the model jumps to another position.
I have tried to play with camera.lookAt vector as well as controls.target, but it doesn’t help me. It seems that this issue occurs due to the difference between the origin coordinates in the GLTF and ThreeJS scene.
The working code is available here.
const URL = {
name: '3non-sliding',
prefix: 'assets/models/'
};
import * as THREE from 'three';
import { AnimationMixer } from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { DebugEnvironment } from 'three/addons/environments/DebugEnvironment.js';
let container, renderer, scene, camera, controls, group, gltf, mixer, freeMode = false, verify = true, clock = new THREE.Clock();
inits();
function inits() {
container = document.createElement('div');
document.body.appendChild(container);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 64);
scene = new THREE.Scene();
const loader = new THREE.TextureLoader();
scene.background = loader.load('assets/checkboxGrey4x4.png');
const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileCubemapShader();
const generativeEnvironment = new DebugEnvironment(new THREE.Color(0xDDDDDD));
scene.environment = pmremGenerator.fromScene(generativeEnvironment).texture;
controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.1;
controls.enabled = false;
const geometry = new THREE.SphereGeometry(0.25, 8, 8);
const material = new THREE.MeshBasicMaterial({
color: 0xFF00FF
});
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
const onProgress = function(xhr_) {
if (xhr_.lengthComputable) {
const percentComplete = xhr_.loaded / xhr_.total * 100;
console.log(`${URL.name}.glb : ${percentComplete.toFixed( 2 )}%`);
}
};
new GLTFLoader().setPath(URL.prefix).load(new URLSearchParams(window.location.search).get('id') != null ? `${new URLSearchParams(window.location.search).get('id')}.glb` : `${URL.name}.glb`, function(gltf_) {
gltf = gltf_;
mixer = new THREE.AnimationMixer(gltf.scene);
scene.add(gltf.scene);
camera = gltf.cameras[0].clone();
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
camera.needsUpdate = true;
}, onProgress);
window.addEventListener('resize', onWindowResize);
document.addEventListener('keydown', (event_) => {
if (event_.keyCode == 16 && verify) {
freeMode = true;
verify = false;
controls.enabled = true;
console.log('OrbitControls mode enabled');
controls = new OrbitControls(camera, renderer.domElement);
}
});
document.addEventListener('keyup', (event_) => {
freeMode = false;
verify = true;
controls.enabled = false;
console.log('OrbitControls mode disabled');
});
render();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
Any ideas why it's jumping and how to solve it?