Как применить OrbitControls к загруженной камере из файла gltf?

Я использую three.js для загрузки сцены gltf с камерой. Камера и модель выглядят хорошо, но когда я пытаюсь применить OrbitControls.js к загруженной камере, это не сработает. Он работает только с камерами, созданными непосредственно в three.js с помощью new THREE.PerspectiveCamera(). Я оставляю код ниже, я прокомментировал функцию 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;

person AlvaroMerino    schedule 19.10.2018    source источник
comment
Попробуйте это: camera = result.cameras[ 0 ]; scene.add( camera ). Это переназначит родителя камеры.   -  person WestLangley    schedule 19.10.2018
comment
Спасибо, попробовал, но не вышло. Я решил это с помощью обходного пути (Edit1)   -  person AlvaroMerino    schedule 23.10.2018


Ответы (1)


Похоже, что экспортер GLTF для Blender любит создавать родительский объект для экспортируемых камер, как вы заметили в своем обходном пути.

Понятно, что определение поведения орбитальной камеры, которая работает согласованно и имеет смысл, когда эта камера потенциально одновременно перемещается по сцене путем преобразования ее родительского элемента, является трудным, как и крайним случаем, поэтому похоже, что OrbitControls просто не работает при применении к камера с родительским объектом.


Попробуйте отсоединить камеру от родительского объекта:

scene.attach(blenderCamera)

Это приведет к удалению родительского атрибута импортированной камеры, а также к применению матриц обратного преобразования ее родителей, чтобы ее положение и ориентация в сцене остались прежними. Вы также сможете проверить blenderCamera.parent == null после этого, что аналогично жестко запрограммированным камерам, которые работали раньше.


Примечание. Похоже, что scene.attach в настоящее время является каноническим способом удаления родительского объекта с объекта. Очевидно, раньше это было SceneUtils.detach, которое теперь помечено как устаревшее в исходном коде. Вы также можете попробовать напрямую установить .parent = null, но тогда вы, вероятно, потеряете преобразование от родителя в лучшем случае. Имея только один родительский элемент и нулевое преобразование родительского пространства, вы можете обойти это, вручную скопировав координаты, но вам, возможно, придется начать применять матрицы преобразования самостоятельно для чего-либо более сложного или надежного.

person Will Chen    schedule 25.06.2020