SceneKit - 自定义几何体不显示
SceneKit – Custom geometry does not show up
我应该看到 2 个黄色三角形,但我什么也没看到。
class Terrain {
private class func createGeometry () -> SCNGeometry {
let sources = [
SCNGeometrySource(vertices:[
SCNVector3(x: -1.0, y: -1.0, z: 0.0),
SCNVector3(x: -1.0, y: 1.0, z: 0.0),
SCNVector3(x: 1.0, y: 1.0, z: 0.0),
SCNVector3(x: 1.0, y: -1.0, z: 0.0)], count:4),
SCNGeometrySource(normals:[
SCNVector3(x: 0.0, y: 0.0, z: -1.0),
SCNVector3(x: 0.0, y: 0.0, z: -1.0),
SCNVector3(x: 0.0, y: 0.0, z: -1.0),
SCNVector3(x: 0.0, y: 0.0, z: -1.0)], count:4)
]
let elements = [
SCNGeometryElement(indices: [0, 2, 3, 0, 1, 2], primitiveType: .Triangles)
]
let geo = SCNGeometry(sources:sources, elements:elements)
let mat = SCNMaterial()
mat.diffuse.contents = UIColor.yellowColor()
mat.doubleSided = true
geo.materials = [mat]
return geo
}
class func createNode () -> SCNNode {
let node = SCNNode(geometry: createGeometry())
node.name = "Terrain"
node.position = SCNVector3()
return node
}
}
我是这样使用的:
let terrain = Terrain.createNode()
sceneView.scene?.rootNode.addChildNode(terrain)
let camera = SCNCamera()
camera.zFar = 10000
self.camera = SCNNode()
self.camera.camera = camera
self.camera.position = SCNVector3(x: -20, y: 15, z: 30)
let constraint = SCNLookAtConstraint(target: terrain)
constraint.gimbalLockEnabled = true
self.camera.constraints = [constraint]
sceneView.scene?.rootNode.addChildNode(self.camera)
我看到其他具有非自定义几何形状的节点。怎么了?
注意:请参阅 Ash 的回答,对于现代 Swift 来说,这是比这个更好的方法。
您的索引数组包含错误大小的元素。它被推断为 [Int]
。你需要 [CInt]
.
我将你的 elements
设置分解为:
let indices = [0, 2, 3, 0, 1, 2] // [Int]
print(sizeof(Int)) // 8
print(sizeof(CInt)) // 4
let elements = [
SCNGeometryElement(indices: indices, primitiveType: .Triangles)
]
要使索引像预期的 C 数组一样打包,请显式声明类型:
let indices: [CInt] = [0, 2, 3, 0, 1, 2]
Custom SceneKit Geometry in Swift on iOS not working but equivalent Objective C code does说的比较详细,不过是针对Swift1写的,所以你得做一些翻译。
SCNGeometryElement(indices:, primitiveType:)
似乎没有在任何地方记录,尽管它确实出现在 headers.
中
Hal Mueller 说得非常正确,所涉及的索引必须是指定类型,但需要注意的是,此功能在 Swift 语言的最新版本中发生了显着变化。值得注意的是,SCNGeometryElement(indices:, primitiveType:)
现在在 Swift 4 中运行良好,我建议不要使用对我不起作用的 CInt
。而是使用符合 FixedWidthInteger
协议的标准整数类型之一,即 Int32
。如果您知道网格中涉及的顶点数量有上限,请使用可以包含所有顶点的最小位大小。
示例:
let vertices = [
SCNVector3(x: 5, y: 4, z: 0),
SCNVector3(x: -5 , y: 4, z: 0),
SCNVector3(x: -5, y: -5, z: 0),
SCNVector3(x: 5, y: -5, z: 0)
]
let allPrimitives: [Int32] = [0, 1, 2, 0, 2, 3]
let vertexSource = SCNGeometrySource(vertices: vertices)
let element = SCNGeometryElement(indices: allPrimitives, primitiveType: .triangles)
let geometry = SCNGeometry(sources: [vertexSource], elements: [element])
SCNNode(geometry: geometry)
这里发生了什么?
首先我们创建一个 vertices
数组来描述三维 space 中的点。 allPrimitives
数组描述了那些顶点如何 link 向上。每个元素都是 vertices
数组中的一个索引。由于我们使用的是三角形,因此应将它们分成三个一组,每个角一个。为了简单起见,我在这里做了一个简单的平面正方形。然后我们使用所有顶点的原始数组创建一个语义类型为 vertices
的几何源,并使用 allPrimitives
数组创建一个几何元素,同时通知它它们是三角形,因此它知道将它们分组三人一组。这些可以用来创建 SCNGeometry
对象,我们用它来初始化我们的 SCNNode
.
一种简单的思考方式是,顶点源的存在只是为了列出对象中的所有顶点。几何元素的存在只是为了描述这些顶点是如何 link 起来的。正是 SCNGeometry
将这两个对象组合在一起以创建最终的物理表示。
我应该看到 2 个黄色三角形,但我什么也没看到。
class Terrain {
private class func createGeometry () -> SCNGeometry {
let sources = [
SCNGeometrySource(vertices:[
SCNVector3(x: -1.0, y: -1.0, z: 0.0),
SCNVector3(x: -1.0, y: 1.0, z: 0.0),
SCNVector3(x: 1.0, y: 1.0, z: 0.0),
SCNVector3(x: 1.0, y: -1.0, z: 0.0)], count:4),
SCNGeometrySource(normals:[
SCNVector3(x: 0.0, y: 0.0, z: -1.0),
SCNVector3(x: 0.0, y: 0.0, z: -1.0),
SCNVector3(x: 0.0, y: 0.0, z: -1.0),
SCNVector3(x: 0.0, y: 0.0, z: -1.0)], count:4)
]
let elements = [
SCNGeometryElement(indices: [0, 2, 3, 0, 1, 2], primitiveType: .Triangles)
]
let geo = SCNGeometry(sources:sources, elements:elements)
let mat = SCNMaterial()
mat.diffuse.contents = UIColor.yellowColor()
mat.doubleSided = true
geo.materials = [mat]
return geo
}
class func createNode () -> SCNNode {
let node = SCNNode(geometry: createGeometry())
node.name = "Terrain"
node.position = SCNVector3()
return node
}
}
我是这样使用的:
let terrain = Terrain.createNode()
sceneView.scene?.rootNode.addChildNode(terrain)
let camera = SCNCamera()
camera.zFar = 10000
self.camera = SCNNode()
self.camera.camera = camera
self.camera.position = SCNVector3(x: -20, y: 15, z: 30)
let constraint = SCNLookAtConstraint(target: terrain)
constraint.gimbalLockEnabled = true
self.camera.constraints = [constraint]
sceneView.scene?.rootNode.addChildNode(self.camera)
我看到其他具有非自定义几何形状的节点。怎么了?
注意:请参阅 Ash 的回答,对于现代 Swift 来说,这是比这个更好的方法。
您的索引数组包含错误大小的元素。它被推断为 [Int]
。你需要 [CInt]
.
我将你的 elements
设置分解为:
let indices = [0, 2, 3, 0, 1, 2] // [Int]
print(sizeof(Int)) // 8
print(sizeof(CInt)) // 4
let elements = [
SCNGeometryElement(indices: indices, primitiveType: .Triangles)
]
要使索引像预期的 C 数组一样打包,请显式声明类型:
let indices: [CInt] = [0, 2, 3, 0, 1, 2]
Custom SceneKit Geometry in Swift on iOS not working but equivalent Objective C code does说的比较详细,不过是针对Swift1写的,所以你得做一些翻译。
SCNGeometryElement(indices:, primitiveType:)
似乎没有在任何地方记录,尽管它确实出现在 headers.
Hal Mueller 说得非常正确,所涉及的索引必须是指定类型,但需要注意的是,此功能在 Swift 语言的最新版本中发生了显着变化。值得注意的是,SCNGeometryElement(indices:, primitiveType:)
现在在 Swift 4 中运行良好,我建议不要使用对我不起作用的 CInt
。而是使用符合 FixedWidthInteger
协议的标准整数类型之一,即 Int32
。如果您知道网格中涉及的顶点数量有上限,请使用可以包含所有顶点的最小位大小。
示例:
let vertices = [
SCNVector3(x: 5, y: 4, z: 0),
SCNVector3(x: -5 , y: 4, z: 0),
SCNVector3(x: -5, y: -5, z: 0),
SCNVector3(x: 5, y: -5, z: 0)
]
let allPrimitives: [Int32] = [0, 1, 2, 0, 2, 3]
let vertexSource = SCNGeometrySource(vertices: vertices)
let element = SCNGeometryElement(indices: allPrimitives, primitiveType: .triangles)
let geometry = SCNGeometry(sources: [vertexSource], elements: [element])
SCNNode(geometry: geometry)
这里发生了什么?
首先我们创建一个 vertices
数组来描述三维 space 中的点。 allPrimitives
数组描述了那些顶点如何 link 向上。每个元素都是 vertices
数组中的一个索引。由于我们使用的是三角形,因此应将它们分成三个一组,每个角一个。为了简单起见,我在这里做了一个简单的平面正方形。然后我们使用所有顶点的原始数组创建一个语义类型为 vertices
的几何源,并使用 allPrimitives
数组创建一个几何元素,同时通知它它们是三角形,因此它知道将它们分组三人一组。这些可以用来创建 SCNGeometry
对象,我们用它来初始化我们的 SCNNode
.
一种简单的思考方式是,顶点源的存在只是为了列出对象中的所有顶点。几何元素的存在只是为了描述这些顶点是如何 link 起来的。正是 SCNGeometry
将这两个对象组合在一起以创建最终的物理表示。