gpt4 book ai didi

iOS ARKit + SceneKit 物理接触检测缩放问题

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:03:35 25 4
gpt4 key购买 nike

我有一个简单的 3d 区域,其中包含 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 接触委托(delegate)来检测实体何时到达边界墙之一。然后,我从该墙向另一个方向计算它的随机轨迹,清除它的 Action ,并应用新的移动 SCNAction。

这就是有趣的地方......

当这个“世界”比例为 1:1 时。在标准 SCNScene 和使用 ARKit 投影的场景中,接触被检测为正常。可见接触,即实体方向的可见变化,似乎如预期的那样接近边界。当我检查每个联系人的 contact.penetrationDistance 时,它​​们的值是例如0.00294602662324905。

但是当我在 ARKit 中将这个“世界”的比例更改为更小的尺寸时,比如说相当于 10 厘米宽度,模拟就会崩溃。

当检测到接触时,实体和边界节点之间的接触在它们之间具有相对较大的可见间隙。然而,contact.penetrationDistance 与之前的大小相同。

我打开 ARSCNView 调试选项以在渲染中显示物理形状,它们看起来都是正确的比例,匹配它们节点的边界框。

正如您从上面的代码示例中看到的,边界节点是在我的 AR 用户设置期间缩放关卡后生成的。它们被添加到场景的根节点,而不是作为关卡节点的子节点。相同的代码用于生成实体。

之前我曾尝试在物理体上使用 resetTransform() 函数,但这并没有产生可靠的物理体缩放,在我缩放关卡之后,所以我决定在之后为边界和实体生成节点级别已缩放。

在 Apple 的文档中,它确实声明如果 SCNPhysicsBody 不是自定义形状,它将采用应用于它的节点几何体的比例。在将缩放应用于关卡后,我正在生成几何图形及其各自的节点,因此我不受此影响。

目前的假设之一是物理模拟会在如此小的范围内崩溃。但是我不是靠模拟力来移动 body 的……

是否有更合适的方法来缩放物理世界?

或者,我是在盯着 SCNPhysicsWorld 中的一个错误,那是我目前无法控制的事情。

我确实考虑过的一个解决方案是以 1:1 的比例运行整个模拟但隐藏,然后将这些运动应用于较小的实体。可以想象,那会影响整个场景的表现……

最佳答案

第一个接触点的穿透距离为负值,说明存在间隙。当您缩小模拟的大小时,此差距似乎不会缩小。

作为解决上述多余问题的一种方法,我对 Contact Delegate 中的接触进行了额外检查,不采用针对特定类别检测到的第一个接触,而是确保 penetrationDistance 值为正,从而确保有是两个对象之间的重叠,然后触发与边界相连的实体的方向改变。

关于iOS ARKit + SceneKit 物理接触检测缩放问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49771646/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com