SCNNode clone() 在克隆节点时为场景添加更多光线
SCNNode clone() adds more light to the scene as nodes are cloned
我正在尝试在我的 ARKit 代码中添加多个带阴影的 3d 对象。
我这样创建节点
func loadNodaA()
{
isObjectCoordinatesAtCentre = false
let scaleFactor = 0.005
let dragonScene = SCNScene(named:"art.scnassets/Lowpoly_tree_sample.dae")!
let queenNode = dragonScene.rootNode.childNode(withName: "Tree_lp_11", recursively: true)
let geometry : SCNGeometry = (queenNode?.geometry)!
geometry.materials = [self.CreateMaterialWithName("streakedmetal")];
nodeA = dragonScene.rootNode
nodeA.position = SCNVector3Zero
nodeA.scale = SCNVector3(x: Float(scaleFactor), y: Float(scaleFactor), z: Float(scaleFactor))
nodeA.position = SCNVector3Make(0,0,0)
}
一旦 ARKIT 检测到飞机,我就会创建一个这样的飞机:
func createPlaneNode(anchor: ARPlaneAnchor) -> SCNNode {
let floatwidth = anchor.extent.x
let floatlength = anchor.extent.z
let floatPlaneHeight : Float = 0.001
let planeGeometry = SCNBox(width: CGFloat(floatwidth), height: CGFloat(floatPlaneHeight), length: CGFloat(floatlength), chamferRadius:0)
planesGeometries[anchor.identifier] = planeGeometry
let planeNode = SCNNode(geometry: planeGeometry)
let transparentMaterial : SCNMaterial = SCNMaterial()
//transparentMaterial.diffuse.contents = UIImage.init(named: "art.scnassets/GridtextureGrayLines.png")
transparentMaterial.diffuse.contents = UIImage.init(named: "art.scnassets/sunmica.png")
//planeGeometry.materials = [transparentMaterial, transparentMaterial, transparentMaterial, transparentMaterial,self.CreateMaterialWithName("redbricks"), transparentMaterial];
//planeGeometry.materials = [transparentMaterial]
planeGeometry.firstMaterial = transparentMaterial
transparentMaterial.diffuse.contentsTransform = SCNMatrix4MakeScale(2,2, 0)
planeNode.geometry?.firstMaterial?.diffuse.wrapS = .repeat
planeNode.geometry?.firstMaterial?.diffuse.wrapT = .repeat
planeNode.position = SCNVector3Make(0, -(floatPlaneHeight/2), 0)
planeNode.physicsBody = SCNPhysicsBody(type: .kinematic, shape: SCNPhysicsShape(geometry: planeGeometry, options: nil))
//planeNode.castsShadow = true
self.setTextureScale(plane: planeNode, planeGeometry: planeGeometry)
return planeNode
}
然后在点击平面时,我正在向其添加带有阴影的树对象。但问题是当我一次又一次地克隆这些对象时,树下的平面变得更亮我认为我正在添加的光节点不断为每个节点添加,尽管我试图按名称删除它。
func insertGeometry(_ anchor : ARHitTestResult ) {
let h = CGFloat(selectedNode.boundingBox.max.y - selectedNode.boundingBox.min.y)
var insertionYOffset: Float = Float(h)/2.0;
if isObjectCoordinatesAtCentre == false
{
insertionYOffset = 0
}
let hitPointPosition = SCNVector3Make(
anchor.worldTransform.columns.3.x,
anchor.worldTransform.columns.3.y + insertionYOffset,
anchor.worldTransform.columns.3.z
);
var nodeClone = SCNNode.init()
if CurrentNodeChoise == 1
{
//This means draw tree
nodeClone = nodeA.clone()
}
nodeClone.position = hitPointPosition
sceneView.scene.rootNode.addChildNode(nodeClone)
guard let spotlightNode : SCNNode = (sceneView.scene.rootNode.childNode(withName: "LightForShadows", recursively: true)) else {
let spot = SCNLight()
spot.type = .spot
spot.castsShadow = true
spot.color = UIColor.darkGray
spot.shadowMode = .forward
spot.intensity = 2000
spot.shadowRadius = 5;
spot.shadowSampleCount = 20;
spot.shadowMapSize = CGSize(width: 4000, height: 4000)
spot.orthographicScale=50;
spot.zNear=1;
spot.zFar=1000;
spot.name = "myLight"
let spotNode = SCNNode()
spotNode.light = spot
spotNode.position = SCNVector3(x:4, y: 6, z: 0)
let lookAt = SCNLookAtConstraint.init(target: nodeClone)
constraintsArray.append(lookAt)
spotNode.constraints = constraintsArray
spotNode.name = "LightForShadows"
sceneView.scene.rootNode.addChildNode(spotNode)
return
}
let lookAt = SCNLookAtConstraint.init(target: nodeClone)
constraintsArray.append(lookAt)
spotlightNode.constraints = constraintsArray
}
我还尝试仅将光添加到第一个节点,然后通过仅更新第一个光节点来为其余节点添加光。但这也行不通。我希望树木在其下方的平面保持不变的情况下添加阴影。阴影也不是完美的,有没有办法让它们变得更好?
查看屏幕截图,树下的平面如何随着一棵树的添加而变化。
每添加一棵树,您都会添加一盏灯,这当然会让您的平面更亮。
坚持使用您在场景设置中创建的一盏灯,并将其约束更新为指向平面。当您添加其他节点时,您不需要对闪电做任何事情。当你的场景有一个产生阴影的光时,这将影响你添加的每个节点。
要制作阴影 "look better" - 不管是什么意思 - 您需要尝试使用不同的闪电模式和灯光参数。我建议在 Xcode 编辑器中创建一个场景并使用这些属性。
我正在尝试在我的 ARKit 代码中添加多个带阴影的 3d 对象。
我这样创建节点
func loadNodaA()
{
isObjectCoordinatesAtCentre = false
let scaleFactor = 0.005
let dragonScene = SCNScene(named:"art.scnassets/Lowpoly_tree_sample.dae")!
let queenNode = dragonScene.rootNode.childNode(withName: "Tree_lp_11", recursively: true)
let geometry : SCNGeometry = (queenNode?.geometry)!
geometry.materials = [self.CreateMaterialWithName("streakedmetal")];
nodeA = dragonScene.rootNode
nodeA.position = SCNVector3Zero
nodeA.scale = SCNVector3(x: Float(scaleFactor), y: Float(scaleFactor), z: Float(scaleFactor))
nodeA.position = SCNVector3Make(0,0,0)
}
一旦 ARKIT 检测到飞机,我就会创建一个这样的飞机:
func createPlaneNode(anchor: ARPlaneAnchor) -> SCNNode {
let floatwidth = anchor.extent.x
let floatlength = anchor.extent.z
let floatPlaneHeight : Float = 0.001
let planeGeometry = SCNBox(width: CGFloat(floatwidth), height: CGFloat(floatPlaneHeight), length: CGFloat(floatlength), chamferRadius:0)
planesGeometries[anchor.identifier] = planeGeometry
let planeNode = SCNNode(geometry: planeGeometry)
let transparentMaterial : SCNMaterial = SCNMaterial()
//transparentMaterial.diffuse.contents = UIImage.init(named: "art.scnassets/GridtextureGrayLines.png")
transparentMaterial.diffuse.contents = UIImage.init(named: "art.scnassets/sunmica.png")
//planeGeometry.materials = [transparentMaterial, transparentMaterial, transparentMaterial, transparentMaterial,self.CreateMaterialWithName("redbricks"), transparentMaterial];
//planeGeometry.materials = [transparentMaterial]
planeGeometry.firstMaterial = transparentMaterial
transparentMaterial.diffuse.contentsTransform = SCNMatrix4MakeScale(2,2, 0)
planeNode.geometry?.firstMaterial?.diffuse.wrapS = .repeat
planeNode.geometry?.firstMaterial?.diffuse.wrapT = .repeat
planeNode.position = SCNVector3Make(0, -(floatPlaneHeight/2), 0)
planeNode.physicsBody = SCNPhysicsBody(type: .kinematic, shape: SCNPhysicsShape(geometry: planeGeometry, options: nil))
//planeNode.castsShadow = true
self.setTextureScale(plane: planeNode, planeGeometry: planeGeometry)
return planeNode
}
然后在点击平面时,我正在向其添加带有阴影的树对象。但问题是当我一次又一次地克隆这些对象时,树下的平面变得更亮我认为我正在添加的光节点不断为每个节点添加,尽管我试图按名称删除它。
func insertGeometry(_ anchor : ARHitTestResult ) {
let h = CGFloat(selectedNode.boundingBox.max.y - selectedNode.boundingBox.min.y)
var insertionYOffset: Float = Float(h)/2.0;
if isObjectCoordinatesAtCentre == false
{
insertionYOffset = 0
}
let hitPointPosition = SCNVector3Make(
anchor.worldTransform.columns.3.x,
anchor.worldTransform.columns.3.y + insertionYOffset,
anchor.worldTransform.columns.3.z
);
var nodeClone = SCNNode.init()
if CurrentNodeChoise == 1
{
//This means draw tree
nodeClone = nodeA.clone()
}
nodeClone.position = hitPointPosition
sceneView.scene.rootNode.addChildNode(nodeClone)
guard let spotlightNode : SCNNode = (sceneView.scene.rootNode.childNode(withName: "LightForShadows", recursively: true)) else {
let spot = SCNLight()
spot.type = .spot
spot.castsShadow = true
spot.color = UIColor.darkGray
spot.shadowMode = .forward
spot.intensity = 2000
spot.shadowRadius = 5;
spot.shadowSampleCount = 20;
spot.shadowMapSize = CGSize(width: 4000, height: 4000)
spot.orthographicScale=50;
spot.zNear=1;
spot.zFar=1000;
spot.name = "myLight"
let spotNode = SCNNode()
spotNode.light = spot
spotNode.position = SCNVector3(x:4, y: 6, z: 0)
let lookAt = SCNLookAtConstraint.init(target: nodeClone)
constraintsArray.append(lookAt)
spotNode.constraints = constraintsArray
spotNode.name = "LightForShadows"
sceneView.scene.rootNode.addChildNode(spotNode)
return
}
let lookAt = SCNLookAtConstraint.init(target: nodeClone)
constraintsArray.append(lookAt)
spotlightNode.constraints = constraintsArray
}
我还尝试仅将光添加到第一个节点,然后通过仅更新第一个光节点来为其余节点添加光。但这也行不通。我希望树木在其下方的平面保持不变的情况下添加阴影。阴影也不是完美的,有没有办法让它们变得更好?
查看屏幕截图,树下的平面如何随着一棵树的添加而变化。
每添加一棵树,您都会添加一盏灯,这当然会让您的平面更亮。
坚持使用您在场景设置中创建的一盏灯,并将其约束更新为指向平面。当您添加其他节点时,您不需要对闪电做任何事情。当你的场景有一个产生阴影的光时,这将影响你添加的每个节点。
要制作阴影 "look better" - 不管是什么意思 - 您需要尝试使用不同的闪电模式和灯光参数。我建议在 Xcode 编辑器中创建一个场景并使用这些属性。