[英]How to apply OrbitControls to a loaded camera from a gltf file?
我正在使用 Three.js 加载一个带有相机的 gltf 场景。 相机和模型显示良好,但是当我尝试将 OrbitControls.js 应用于该加载的相机时,它不起作用。 它仅适用于使用new THREE.PerspectiveCamera()
在 Three.js 中直接创建的相机。 我把代码留在下面,我已经评论了play()
函数只是为了先尝试这个。
var container, stats, clock, controls;
var camera, scene, renderer, mixer;
init();
animate();
controls.update();
function init() {
container = document.getElementById( 'container' );
scene = new THREE.Scene();
clock = new THREE.Clock();
var loader = new THREE.GLTFLoader();
var ruta = 'file.gltf';
loader.load( ruta, function ( data ) {
handleSceneLoaded(data);
var animations = data.animations;
var avatar = data.scene;
mixer = new THREE.AnimationMixer( avatar );
NumberOfAnimations = animations.length;
for ( var i=0; i<NumberOfAnimations; i++){
//mixer.clipAction( animations[ i ] ).play();
}
scene.add( avatar );
} );
//
scene.background = new THREE.Color( 0xefe3a7 );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
}
function handleSceneLoaded(data){
scene.add(data.scene);
var result={};
data.scene.traverse(function(n){traverseScene(n,result);});
if (result.cameras && result.cameras.length){
camera = result.cameras[0];
controls = new THREE.OrbitControls(camera);
controls.screenSpacePanning = true;
}else{
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set( 15, 10, - 15 );
}
if(result.lights && result.lights.length){
for (i=0;i<result.lights.length;i++){
var lamp = result.lights[i];
scene.add(lamp);
}
}else {
var ambientLight = new THREE.AmbientLight( 0xffffff, 0.2 );
scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff, .8 );
directionalLight.position.set( 1, 1, - 1 );
scene.add( directionalLight );
var directionalLight2 = new THREE.DirectionalLight( 0xffffff, .8 );
directionalLight2.position.set( -5, -5, 10 );
scene.add( directionalLight2 );
}
}
function traverseScene(n, result){
if (n instanceof THREE.Camera){
if(!result.cameras)
result.cameras = [];
result.cameras.push(n);
}
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
var delta = clock.getDelta();
if ( mixer !== undefined ) {
mixer.update( delta );
}
renderer.render( scene, camera );
}
Edit1:我最终通过将加载的相机分配给变量 blenderCamera 然后创建真正的相机并从加载的相机及其父级复制值来解决它:
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
blenderCamera = result.cameras[0];
camera.position.x = blenderCamera.parent.position.x;
camera.position.y = blenderCamera.parent.position.y;
camera.position.z = blenderCamera.parent.position.z;
camera.aspect = blenderCamera.aspect;
camera.fov = blenderCamera.fov;
camera.far = blenderCamera.far;
camera.near = blenderCamera.near;
正如您在解决方法中所注意到的,Blender 的 GLTF 导出器似乎喜欢为导出的相机创建父对象。
定义一个轨道相机的行为,该相机在通过其父项的变换可能同时在场景中移动时,始终如一地工作且有意义,这是可以理解的困难 - 以及边缘情况 - 因此看起来OrbitControls
在应用于带有父对象的相机。
scene.attach(blenderCamera)
这将删除导入相机的父属性,同时还应用其父的逆变换矩阵,使其在场景中的位置和方向保持不变。 之后您也应该能够检查blenderCamera.parent == null
,这与之前工作的硬编码相机相同。
注意:看起来scene.attach
是当前去父对象的规范方法。 它显然曾经是SceneUtils.detach
,现在在源代码中被标记为已弃用。 您也可以尝试直接设置.parent = null
,但在最好的情况下,您可能会丢失来自父级的转换。 只有一个父级和零父级空间变换,您可以通过手动复制坐标来规避这种情况,但您可能必须开始自己应用变换矩阵来处理任何更复杂或更健壮的事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.