2016-05-16 73 views
1

我是SceneKit的新手,所以完全有可能/我可能试图做的事情甚至都不是正确的方法。所以这里是我的一般意图:将物理添加到SCNGeometryElement原始码

我正在建立一个玩家旅行的“隧道”。这是一个程序化的隧道。我确定代表隧道网格的点的位置,然后用三角形将点连接在一起以对其进行蒙皮处理。我使用下面的方法来生成我的三角形:

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. 关于为什么为我的三角形创建物理体的任何想法都不起作用?

谢谢。

回答

4

请务必注意,SceneKit将为您的自定义几何创建一个physics shape。这个物理形状而不是与您创建的网格具有相同的几何形状,相反,它默认在网格外围创建凸包。我的猜测是,凸包算法可能不适用于法线向内(?)的隧道网格。但是,即使它确实起作用,你的最终结果也会是在隧道外面有一个网状结构,防止你从中穿过。

一个可能的解决方案可能是在创建SCNPhysicsShape以指定SCNPhysicsShapeTypeConcavePolyhedron时使用SCNPhysicsShapeTypeKey。如果采取这种方法,我还建议把你的隧道在其周围和沿其长度方向上分段。

Tube segmentation

有许多的可能的原因:它应该有助于渲染性能,因为SceneKit在视域外观时会捕捉整个片段(节点),它应该有助于碰撞检测性能(SceneKit在检查基于网格的碰撞之前可能会执行边界框检查),最后物理形状生成算法应该工作。

另一种方法是生成一些代表隧道的几何图元(SCNSphere,SCNBox等),并创建由多个形状组成的SCNPhysicsShape。这是我采取的方法来建立我的程序生成的岛屿周围的形状,每个灰色框是一个SCNBox

enter image description here

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

我应该补充一点,您生成SCNGeometry的方式没有任何问题。只需要记住一些注意事项,特别是当网格有大量三角形时。

希望它有帮助。

+0

谢谢,锁定。你的岛屿看起来很棒。我设想我的隧道与概念上的隧道相似。假设你的目标是让一个角色在你的岛上四处走动,就好像每个多边形都是一个硬表面让他们走路。也许为每个多边形创建一个物理主体在计算上太昂贵了,这正是我试图接近它的原因。相反,您是否会创建一堆SCNPhysicsShapeTypeConcavePolyhedron物体,大致与您的岛屿的某个部分的曲率匹配,以便多边形本身只能近似地逼近物理体? – Dan

+0

TBH我会*非常喜欢将自己的网格提供给'SCNPhysicsShape'的方法,就像您最初提出的那样。我猜SceneKit开发者想要减少由于太多多边形而导致接触检测速度减慢的可能性。每个多边形创建一个物理形状可能会导致物理形状的接触多边形比您想要表示的多边形多。走过去很困难,因为你需要相当准确的结果。我认为'SCNPhysicsShapeTypeConcavePolyhedron'是你最好的选择,记住你几乎不能控制它的几何形状。 – lock