停止以编程方式与其克隆共享节点的几何图形
Stop sharing node's geometry with its clone programmatically
当您创建对象的副本时,几何体及其属性 (materials...) 将与该对象共享。
在 Xcode 场景编辑器中,您可以通过将 Geometry Sharing
(在 Attributes Inspector
下)设置为 Unshare
可以轻松禁用它。
我想以编程方式实现相同的功能,但在 SceneKit
文档中找不到任何类似的属性。
我找到了一个类似的 post,其中有人建议复制对象,它的几何形状和它的 material。我尝试这样做但没有成功。
这是我代码的相关部分:
let randomColors: [UIColor] = [UIColor.blue, UIColor.red, UIColor.yellow, UIColor.gray]
let obstacleScene = SCNScene(named: "art.scnassets/Scenes/obstacleNormal.scn")
let obstacle = obstacleScene?.rootNode.childNode(withName: "obstacle", recursively: true)
for i in 1...15 {
let randomPosition = SCNVector3(x: Float(i) * 3.5, y: 0.15, z: sign * Float(arc4random_uniform(UInt32(Int(playgroundZ/2 - 2.0))) + 1))
let randomColor = randomColors[Int(arc4random_uniform(UInt32(3)))]
let obstacleCopy = obstacle?.clone()
obstacleCopy?.position = randomPosition
obstacleCopy?.geometry?.materials.first?.diffuse.contents = randomColor
obstacleCopy?.eulerAngles = SCNVector3(x: 10.0 * Float(i), y: Float(30 - i), z: 5.0 * Float(i) * sign) //malo na random
obstacleCopy?.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
obstacleCopy?.physicsBody?.isAffectedByGravity = false
obstacleCopy?.physicsBody?.categoryBitMask = PhysicsCategory.obstacle
obstacleCopy?.physicsBody?.collisionBitMask = PhysicsCategory.none
obstacleCopy?.physicsBody?.contactTestBitMask = PhysicsCategory.car1 | PhysicsCategory.car2 | PhysicsCategory.barrier
obstacleArray.append(obstacleCopy!)
raceScene!.rootNode.addChildNode(obstacleCopy!)
}
我想在这些对象上设置不同的属性但不能,因为它们的几何形状是共享的。
我尝试通过复制对象并克隆它来实现这一点,但我看不出有任何区别复制或克隆它。
有没有属性可以实现几何体取消共享,类似于场景编辑器中的选项,或者应该也是复制对象几何体的方法及其 material 的工作?
根据clone()
API reference,您可以在克隆后复制几何体,这将为您的节点创建一个新的非共享几何体。
let newNode = node.clone()
newNode.geometry = node.geometry?.copy() as? SCNGeometry
附加到复制几何体的 material 与原始几何体上使用的相同,因此任何更改仍会影响两者。
要么创建一个新的 material,要么制作一个副本。
if let newMaterial = newNode.geometry?.materials.first.copy() as? SCNMaterial {
//make changes to material
newNode.geometry?.materials = [newMaterial]
}
您可以深度克隆一个 SCNNode
,它会创建一个与原始对象不共享的几何体和不共享的材质。
fileprivate func deepCopyNode(node: SCNNode) -> SCNNode {
let clone = node.clone()
clone.geometry = node.geometry?.copy() as? SCNGeometry
if let g = node.geometry {
clone.geometry?.materials = g.materials.map{ [=10=].copy() as! SCNMaterial }
}
return clone
}
当您创建对象的副本时,几何体及其属性 (materials...) 将与该对象共享。
在 Xcode 场景编辑器中,您可以通过将 Geometry Sharing
(在 Attributes Inspector
下)设置为 Unshare
可以轻松禁用它。
我想以编程方式实现相同的功能,但在 SceneKit
文档中找不到任何类似的属性。
我找到了一个类似的 post,其中有人建议复制对象,它的几何形状和它的 material。我尝试这样做但没有成功。
这是我代码的相关部分:
let randomColors: [UIColor] = [UIColor.blue, UIColor.red, UIColor.yellow, UIColor.gray]
let obstacleScene = SCNScene(named: "art.scnassets/Scenes/obstacleNormal.scn")
let obstacle = obstacleScene?.rootNode.childNode(withName: "obstacle", recursively: true)
for i in 1...15 {
let randomPosition = SCNVector3(x: Float(i) * 3.5, y: 0.15, z: sign * Float(arc4random_uniform(UInt32(Int(playgroundZ/2 - 2.0))) + 1))
let randomColor = randomColors[Int(arc4random_uniform(UInt32(3)))]
let obstacleCopy = obstacle?.clone()
obstacleCopy?.position = randomPosition
obstacleCopy?.geometry?.materials.first?.diffuse.contents = randomColor
obstacleCopy?.eulerAngles = SCNVector3(x: 10.0 * Float(i), y: Float(30 - i), z: 5.0 * Float(i) * sign) //malo na random
obstacleCopy?.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
obstacleCopy?.physicsBody?.isAffectedByGravity = false
obstacleCopy?.physicsBody?.categoryBitMask = PhysicsCategory.obstacle
obstacleCopy?.physicsBody?.collisionBitMask = PhysicsCategory.none
obstacleCopy?.physicsBody?.contactTestBitMask = PhysicsCategory.car1 | PhysicsCategory.car2 | PhysicsCategory.barrier
obstacleArray.append(obstacleCopy!)
raceScene!.rootNode.addChildNode(obstacleCopy!)
}
我想在这些对象上设置不同的属性但不能,因为它们的几何形状是共享的。
我尝试通过复制对象并克隆它来实现这一点,但我看不出有任何区别复制或克隆它。
有没有属性可以实现几何体取消共享,类似于场景编辑器中的选项,或者应该也是复制对象几何体的方法及其 material 的工作?
根据clone()
API reference,您可以在克隆后复制几何体,这将为您的节点创建一个新的非共享几何体。
let newNode = node.clone()
newNode.geometry = node.geometry?.copy() as? SCNGeometry
附加到复制几何体的 material 与原始几何体上使用的相同,因此任何更改仍会影响两者。 要么创建一个新的 material,要么制作一个副本。
if let newMaterial = newNode.geometry?.materials.first.copy() as? SCNMaterial {
//make changes to material
newNode.geometry?.materials = [newMaterial]
}
您可以深度克隆一个 SCNNode
,它会创建一个与原始对象不共享的几何体和不共享的材质。
fileprivate func deepCopyNode(node: SCNNode) -> SCNNode {
let clone = node.clone()
clone.geometry = node.geometry?.copy() as? SCNGeometry
if let g = node.geometry {
clone.geometry?.materials = g.materials.map{ [=10=].copy() as! SCNMaterial }
}
return clone
}