Подтвердить что ты не робот

Как обнаружить столкновение в three.js?

Я использую three.js.

У меня две геометрии сетки в моей сцене.

Если эти геометрии пересекаются (или пересекаются, если они переведены), я хочу обнаружить это как столкновение.

Как я могу выполнить обнаружение столкновений с помощью трёх .js? Если у three.js нет средств обнаружения столкновений, есть ли другие библиотеки, которые я мог бы использовать в сочетании с тр .js?

4b9b3361

Ответ 1

В файле Three.js утилиты CollisionUtils.js и Collisions.js больше не поддерживаются, и mrdoob (создатель three.js) сам рекомендует обновить до последней версии three.js и использовать класс Ray вместо этого. Ниже следует один способ сделать это.

Идея такова: пусть говорят, что мы хотим проверить, пересекает ли какой-либо сет, называемый "Player", какие-либо сетки, содержащиеся в массиве, называемом "collidableMeshList". Мы можем создать набор лучей, которые начинаются с координат сетки Player (Player.position) и распространяются по каждой вершине в геометрии сетки Player. Каждый луч имеет метод под названием "intersectObjects", который возвращает массив объектов, с которыми пересекался луч, и расстояние до каждого из этих объектов (измеренное от начала луча). Если расстояние до пересечения меньше расстояния между позицией игрока и вершиной геометрии, то столкновение происходит во внутренней части игровой сетки - что мы, вероятно, будем называть "фактическим" столкновением.

Я опубликовал рабочий пример:

http://stemkoski.github.io/Three.js/Collision-Detection.html

Вы можете переместить красный кубик каркаса с помощью клавиш со стрелками и повернуть его с помощью W/A/S/D. Когда он пересекает один из синих кубов, слово "Хит" будет отображаться в верхней части экрана один раз для каждого пересечения, как описано выше. Важная часть кода приведена ниже.

for (var vertexIndex = 0; vertexIndex < Player.geometry.vertices.length; vertexIndex++)
{       
    var localVertex = Player.geometry.vertices[vertexIndex].clone();
    var globalVertex = Player.matrix.multiplyVector3(localVertex);
    var directionVector = globalVertex.subSelf( Player.position );

    var ray = new THREE.Ray( Player.position, directionVector.clone().normalize() );
    var collisionResults = ray.intersectObjects( collidableMeshList );
    if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() ) 
    {
        // a collision occurred... do something...
    }
}

Есть две потенциальные проблемы с этим конкретным подходом.

(1) Когда начало луча находится внутри сетки M, результаты столкновения между лучом и M не будут возвращены.

(2) Возможно, что маленький объект (по отношению к сетке Игрока) может "скользить" между различными лучами, и, таким образом, никакое столкновение не будет зарегистрировано. Два возможных подхода, чтобы уменьшить вероятность этой проблемы, - это написать код, чтобы мелкие объекты создавали лучи и выполняли усилия по обнаружению столкновения с их точки зрения или включали больше вершин в сетке (например, используя CubeGeometry (100, 100, 100, 20, 20, 20), а не CubeGeometry (100, 100, 100, 1, 1, 1).) Последний подход, вероятно, приведет к поражению производительности, поэтому я рекомендую использовать его экономно.

Я надеюсь, что другие будут способствовать этому вопросу своими решениями по этому вопросу. Я боролся с этим довольно долго, прежде чем разрабатывать описанное здесь решение.

Ответ 2

Это действительно слишком широкая тема для рассмотрения в вопросе SO, но ради смазывания SEO сайта немного, вот пара простых отправных точек:

Если вы хотите действительно простое обнаружение столкновения, а не полный физический движок, посмотрите Three.js: Простое обнаружение конфликтов

Если, с другой стороны, вам нужен какой-то ответ на столкновение, а не просто "сделал A и B bump?", взгляните на Physijs, который представляет собой суперпростую в использовании оболочку Ammo.js, построенную вокруг Three.js