将物理添加到SCNGeometryElement原语

时间:2016-05-16 16:33:18

标签: scenekit scnnode

我是SceneKit的新手,所以我完全可能/可能我尝试做的事情甚至不是正确的做法。所以这是我的一般意图:

我正在建造一条隧道"玩家通过它旅行。这是一个程序生成隧道。我确定代表我的隧道网格的点的位置,然后将点与三角形连接起来以对其进行蒙皮。我使用以下方法生成三角形:

func addTriangleFromPositions(scene: SCNScene, point1: SCNVector3, point2: SCNVector3, point3: SCNVector3)
{   
    let vector12 = GLKVector3Make(point1.x - point2.x, point1.y - point2.y, point1.z - point2.z)
    let vector32 = GLKVector3Make(point3.x - point2.x, point3.y - point2.y, point3.z - point2.z)
    let normalVector = SCNVector3FromGLKVector3(GLKVector3CrossProduct(vector12, vector32))


    let positions: [SCNVector3] = [point1, point2, point3]
    let normals: [SCNVector3] = [normalVector, normalVector, normalVector]
    let indices: [Int32] = [0, 2, 1]
    let vertexSource = SCNGeometrySource(vertices: positions, count: positions.count)
    let normalSource = SCNGeometrySource(normals: normals, count: normals.count)
    let indexData = NSData(bytes: indices, length: sizeof(Int32) * indices.count)

    let element = SCNGeometryElement(data: indexData, primitiveType: .Triangles, primitiveCount: indices.count, bytesPerIndex: sizeof(Int32))
    let geometry = SCNGeometry(sources: [vertexSource, normalSource], elements: [element])

    let material = SCNMaterial()
    material.diffuse.contents = UIColor(red: 41.0 / 256.0, green: 16.0 / 256.0, blue: 0, alpha: 1 )

    geometry.materials = [material]
    let node = SCNNode(geometry: geometry)
    scene.rootNode.addChildNode( node )
}

这很好用,我的隧道看起来像隧道。但是,当我开始尝试将PhysicsBody添加到我的节点以使其成为静态主体(事情应该能够撞到隧道,但隧道墙不会移动)时,我的应用程序开始崩溃与EXC_BAD_ADDRESS。在我添加了前几个三角形之后,它实际上崩溃了,所以我怀疑在以这种方式添加几个三角形时会出现一些问题。

因此,为了测试这一点,我创建了一个测试项目并添加了一个三角形,并将其PhysicsBody设置为静态体。它并没有崩溃,但是物理体看起来是原点上的一个点,而不是我的三角形。

所以,有些问题:

  1. 一般来说,生成自定义几何图形是一种不好的方法吗?如果我真的想要一个有点不规则的形状,并且我希望它有一个PhysicsBody,还有另一种方法,而不是创建三角形来连接这些点吗?
  2. 为什么为我的三角形创建物理主体的任何想法都没有用?
  3. 感谢。

1 个答案:

答案 0 :(得分:4)

注意SceneKit会为您的自定义几何体创建physics shape,这一点非常重要。此物理形状与您创建的网格具有相同的几何形状,而是默认为在网格外部构建凸包。我的猜测是,凸包算法可能不适用于法线面向内(?)的隧道网格。但是,即使它确实有效,你最终也会在隧道外围设置网状物,防止你飞过它。

一种可能的解决方案可能是在创建SCNPhysicsShape时使用SCNPhysicsShapeTypeKey来指定SCNPhysicsShapeTypeConcavePolyhedron。如果采用这种方法,我还建议将隧道绕其圆周及其长度分段。

Tube segmentation

这有很多原因;它应该有助于渲染性能,因为当在视锥体外面时,SceneKit将剔除整个片段(节点),它应该有助于碰撞检测性能(SceneKit可能会在检查基于网格的碰撞之前进行边界框检查),最后是物理形状生成算法应该有效。

另一种方法是生成表示隧道的多个几何图元(SCNSphereSCNBox等),并创建一个由多个形状组成的SCNPhysicsShape。这是我在程序生成的岛屿周围构建形状的方法,每个灰色框都是SCNBox

enter image description here

SceneKit将通过打开相应的调试选项(可能仅限金属)来帮助显示所有物理形状。例如; scenekitView.debugOptions = SCNDebugOptions.ShowPhysicsShapes

我应该补充一点,生成SCNGeometry的方式并没有错。您需要记住一些注意事项,尤其是当网格具有大量三角形时。

希望它有所帮助。