Проблема масштабирования при обнаружении контакта с физикой в ​​iOS ARKit + SceneKit

У меня есть простая трехмерная область, содержащая 4 стены, каждая из которых представляет собой SCNNode с простой геометрией SCNBox, прямоугольной формы и соответствующим прикрепленным SCNPhysicsBody. SCNPhysicsBody использует SCNPhysicsShape.ShapeType.boundingBox и имеет статический тип. Вот фрагмент кода:

        let size = (self.levelNode.boundingBox.max - self.levelNode.boundingBox.min) * self.levelNode.scale

        //x //z
        let geometryA = SCNBox(width: CGFloat(size.x), height: CGFloat(1 * self.levelNode.scale.x), length: 0.01, chamferRadius: 0)
        let geometryB = SCNBox(width: CGFloat(size.z), height: CGFloat(1 * self.levelNode.scale.x), length: 0.01, chamferRadius: 0)

        geometryA.firstMaterial?.diffuse.contents = UIColor(red: 0.0, green: 0.2, blue: 1.0, alpha: 0.65)
        geometryB.firstMaterial?.diffuse.contents = UIColor(red: 0.0, green: 0.2, blue: 1.0, alpha: 0.65)


        let nodeA = SCNNode(geometry: geometryA)
        nodeA.position += self.levelNode.position
        nodeA.position += SCNVector3(0, 0.25 * self.levelNode.scale.y, -size.z/2)
        nodeA.name = "Boundary-01"

        let nodeB = SCNNode(geometry: geometryA)
        nodeB.position += self.levelNode.position
        nodeB.position += SCNVector3(0, 0.25 * self.levelNode.scale.y, size.z/2)
        nodeB.name = "Boundary-03"

        let nodeC = SCNNode(geometry: geometryB)
        nodeC.position += self.levelNode.position
        nodeC.position += SCNVector3(-size.x/2, 0.25 * self.levelNode.scale.y, 0)
        nodeC.eulerAngles = SCNVector3(0, -Float.pi/2, 0)
        nodeC.name = "Boundary-02"

        let nodeD = SCNNode(geometry: geometryB)
        nodeD.position += self.levelNode.position
        nodeD.position += SCNVector3(size.x/2, 0.25 * self.levelNode.scale.y, 0)
        nodeD.eulerAngles = SCNVector3(0, Float.pi/2, 0)
        nodeD.name = "Boundary-04"

        let nodes = [nodeA, nodeB, nodeC, nodeD]

        for node in nodes {
            //
            let shape = SCNPhysicsShape(geometry: node.geometry!, options: [
                SCNPhysicsShape.Option.type : SCNPhysicsShape.ShapeType.boundingBox])
            let body = SCNPhysicsBody(type: .static, shape: shape)
            node.physicsBody = body
            node.physicsBody?.isAffectedByGravity = false
            node.physicsBody?.categoryBitMask = Bitmask.boundary.rawValue
            node.physicsBody?.contactTestBitMask = Bitmask.edge.rawValue
            node.physicsBody?.collisionBitMask = 0

            scene.rootNode.addChildNode(node)
            node.physicsBody?.resetTransform()
        }

Внутри этой области я периодически порождаю сущности. У каждого также есть геометрия SCNBox, которая на этот раз имеет форму куба, меньшего размера, чем стены, и те же параметры для физического тела, что и выше.

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

Я использую контактный делегат SCNPhysicsWorld, чтобы определять, когда объект достигает одной из граничных стен. Затем я вычисляю для него случайную траекторию от этой стены в другом направлении, очищаю его действия и применяю новое движение SCNAction.

Вот тут и становится интересно ...

Когда этот «мир» в масштабе 1: 1. Контакты обнаруживаются как нормальные как в стандартной SCNScene, так и в сцене, спроецированной с помощью ARKit. Видимый контакт, то есть видимое изменение направления объекта, кажется, близко к границе, как и ожидалось. Когда я проверяю contact.penetrationDistance каждого контакта, их значения, например, 0,00294602662324905.

НО, когда я изменяю масштаб этого «мира» на что-то меньшее, скажем, эквивалент 10 см ширины в ARKit, симуляция разваливается.

Контакты между объектом и граничным узлом имеют сравнительно большой видимый зазор между ними при обнаружении контакта. Тем не менее, contact.penetrationDistance имеет ту же величину, что и раньше.

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

Как видно из приведенного выше примера кода, граничные узлы создаются после того, как я масштабировал уровень во время настройки пользователя AR. Они добавляются к корневому узлу сцены, а не как дочерний узел узла уровня. Тот же код используется для создания сущностей.

Раньше я пробовал использовать функцию resetTransform () для физических тел, но это не давало надежного масштабирования физических тел после того, как я масштабировал уровень, поэтому я решил сгенерировать узлы для границ и объектов после того, как уровень были масштабированы.

В документации Apple говорится, что если SCNPhysicsBody не является настраиваемой формой, он будет принимать масштаб геометрии узла, примененной к нему. На меня это не влияет, поскольку я генерирую геометрию и соответствующие узлы после того, как масштабирование было применено к уровню.

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

Есть ли более подходящий способ масштабирования мира физики?

Или я обнаружил ошибку в SCNPhysicsWorld, это что-то вне моего контроля в данный момент.

Одно из решений, о котором я подумал, заключалось в том, чтобы запустить всю симуляцию в масштабе 1: 1, но скрыто, а затем применить эти движения к более мелким объектам. Как вы понимаете, это повлияет на производительность всей сцены ...

Вы имеете в виду, что вы изменяете масштаб узла после того, как он был создан и к нему был прикреплен SCNPhysicsBody?

drewster 16.04.2018 03:22

@drewster Я создаю узлы в нужном мне масштабе, затем применяю к ним физические тела, а затем добавляю их на сцену. В приведенном выше коде для моих границ я вычисляю размер уровня, используя его ограничивающую рамку min и max, и применяю его масштаб, как в сцене.

nightbird 16.04.2018 13:29
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
460
1

Ответы 1

Расстояние проникновения первого контакта отрицательное, что указывает на наличие зазора. Этот промежуток не увеличивается при уменьшении размера моделирования.

Чтобы устранить вышеупомянутый избыток, я реализовал дополнительную проверку контактов в Contact Delegate, чтобы не принимать первый обнаруженный контакт для определенной категории, а вместо этого обеспечивать положительное значение протяженности проникновения, таким образом обеспечивая перекрытие между два объекта, прежде чем инициировать изменение направления объекта, связанного с границей.

Другие вопросы по теме