Перемещайте камеру в кадре с помощью физического движка

Я использую физический движок в моем приложении aframe, и я хочу, чтобы камера двигалась, когда пользователь нажимает кнопку.

Я хочу сохранить свойства физического движка, поэтому использую applyImpulse в качестве метода движения.

Вот мой пример сцены:

<script src="https://aframe.io/releases/0.3.0/aframe.min.js"></script>
<script src="//cdn.rawgit.com/donmccurdy/aframe-extras/v2.3.0/dist/aframe-extras.min.js"></script>
<a-scene physics>
<!-- Camera -->
<a-entity id="cameraWrapper" geometry="box" dynamic-body="mass:1" position="0 1 0" width="2" height="1" depth="2" listener>
<a-entity id="camera" camera universal-controls position="0 1 0" rotation="0 0 0">
</a-entity>
</a-entity>
<a-grid static-body position="0 0 0"></a-grid>
</a-scene>
<div>
<a id="impulseButton">Move</a>
</div>

Метод javascript, который должен перемещать камеру, выглядит так:

$(document).ready(function(){
  $("#impulseButton").on("click",function(){
    applyImpulse();
  });

function applyImpulse(){
    var x = 0;
    var y = 0;
    var z = 1;
    var el = $('#cameraWrapper')[0];
    el.body.applyImpulse(
       new CANNON.Vec3(x,y,z),
       new CANNON.Vec3().copy(el.body.position)
    );
  }
});

Однако движение кажется не очень плавным, и когда пользователи используют элементы управления WASD, объект cameraWrapper остается в старом месте. Как плавно перемещать камеру с помощью applyImpulse?


person bear    schedule 19.04.2017    source источник


Ответы (2)


Компонент universal-controls заменяет wasd-controls и look-controls, которые "из коробки" совместим с aframe-Physics-системой. Ключевым случаем, когда это полезно, является предотвращение прохождения камерой препятствий, которые Я не рекомендую в VR, но по-прежнему полезен для настольных приложений, не относящихся к VR.

Использование:

<a-entity camera universal-controls kinematic-body></a-entity>

Добавлен компонент kinematic-body для обнаружения столкновений на плеере. Вот более полный пример.


ПРИМЕЧАНИЕ. В будущих версиях aframe-extras, вероятно, не будет поддержки kinematic-body и коллизий камеры, поэтому вы можете быть заблокированы в версии 3.X.X. К сожалению, это необходимо для лучшей поддержки ключевых случаев виртуальной реальности, таких как наличие физики для многопользовательской игры и запуск физики в веб-воркере для повышения производительности.

person Don McCurdy    schedule 20.04.2017
comment
Это работает, живая демонстрация здесь. Исходный код этой демонстрации указан в ответе. - person Don McCurdy; 20.04.2017
comment
Я понимаю, что kinematic-body обнаруживает столкновения, но я не понимаю, как это можно комбинировать с applyImpulse или любым другим методом, который перемещает камеру для обнаружения столкновений при программном перемещении камеры. извините, если это было непонятно в моем вопросе. - person bear; 20.04.2017
comment
kinematic-body не работает с applyImpulse(), но в сочетании с universal-controls он автоматически обнаруживает столкновения и предотвращает прохождение камерой static-body или dynamic-body объектов. - person Don McCurdy; 20.04.2017
comment
Другими словами, вы можете либо использовать kinematic-body с universal-controls, либо вы можете использовать dynamic-body с applyImpulse(). Для последнего, вероятно, потребуется более 100 строк кода. - person Don McCurdy; 20.04.2017

Я думаю, что это просто вопрос движения, поэтому js / aframe будет всем, что вам нужно. Должно получиться вот так. Это просто быстрый и грязный подход, но он должен дать вам представление. Вы можете поискать информацию о перемещениях игроков и найти много способов сделать это. Просто измените функции клавиш на функции кнопок, и все будет в порядке.

Так что для всех типов сущностей (камера, свет, игрок ...) это было бы больше:

this.camMove = function(){
        // delta = change in time since last call (seconds)
            delta = clock.getDelta(); 
            var mDir = 100 * delta;
            moves = false;

            var mButtons = ["button1", "button2", "button3"];
            for (var i = 0; i < mButtons.length; i++)
            {
                if ( mButtons >= 0 )
                    moves = true;
            }

            if ( mButtons === button1 )
                cam.translateX( mDir );
            if ( mButtons === button2 )
                cam.translateX( -mDir );
            if ( mButtons === button3 )
                cam.translateY( -mDir );
                ................
                ............
                ........
}

Часы должны быть функцией в вашем кадре, но я не уверен в этом, потому что я использую three.js для таких вещей.

person Roland    schedule 20.04.2017
comment
Проблема с translateX и анимациями в том, что они не распознаются физическим движком, а распознаются только элементы управления внешним видом. Есть ли способ использовать applyImpulse, чтобы сделать то, что вы предложили? - person bear; 20.04.2017
comment
Чтобы это работало с физическим движком (например, для столкновений), вы можете заменить cam.translateX на cameraEl.body.applyImpulse(..., ...). См. документацию по CANNON.Body.applyImpulse () . - person Don McCurdy; 20.04.2017
comment
@DonMcCurdy, похоже, это работает только с примерами динамического тела. Не могли бы вы привести пример, который перемещает объект кинематической камеры, например, с вектором 0,0,1, как в моем вопросе? - person bear; 20.04.2017
comment
@bear Правильно, к кинематическому телу нельзя прикладывать импульсы. Вместо этого вы можете прикрепить к камере динамическое тело с el.body.fixedRotation = true для предотвращения перекатывания. Но для полной реализации этого, вероятно, потребуются сотни строк кода, поэтому я не могу написать это для вас, извините. - person Don McCurdy; 20.04.2017