获取放置的 SCNNode 的世界 x、y 和 z - Swift
Getting the world x, y, and z of placed SCNNode - Swift
我的objective是在另一个包含SCNPlane的SCNNode中间生成一个SCNNode
SCNPlane 是在这样的渲染器函数中生成的:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
let width = CGFloat(planeAnchor.extent.x)
let height = CGFloat(planeAnchor.extent.z)
let plane = SCNPlane(width: width, height: height)
plane.materials.first?.diffuse.contents = UIColor.orange
let planeNode = SCNNode(geometry: plane)
let x = CGFloat(planeAnchor.center.x)
let y = CGFloat(planeAnchor.center.y)
let z = CGFloat(planeAnchor.center.z)
planeNode.position = SCNVector3(x,y,z)
planeNode.eulerAngles.x = -.pi / 2
node.addChildNode(planeNode)
node.name = "plane"
loadSphere(x:x, y:y, z:z)
我正试图将球体放在平面的中间:
func loadSphere (x:CGFloat, y:CGFloat, z:CGFloat) {
let idleScene = SCNScene(named: "art.scnassets/bounceFixed.dae")!
// This node will be parent of all the animation models
let node = SCNNode()
for child in idleScene.rootNode.childNodes {
node.addChildNode(child)
}
// Set up some properties
node.name = "Sphere"
node.position = SCNVector3(x, y, z)
node.scale = SCNVector3(0.001, 0.001, 0.001)
...
但问题是,每当我 运行 时,x、y、z 最终都为零。我试过 sceneView.scene.rootNode.childNodes[3].worldPosition
或 node.worldPosition
之类的东西,但最终总是在相机的视野中而不是在平面的中间生成球体。
我在这里附上了一张图片,向您展示我所说的 "middle" 的意思。
请告诉我如何解决这个问题。
编辑:我的目标 post 是尝试获取平面节点的 x、y、z(中心)而不附加球体作为子节点。
最佳。
在没有真正看到您的模型或您添加 Sphere 的确切方式的情况下,我会冒险猜测,要么您没有将模型添加到正确的 SCNNode
,要么 [=16] =] 你的模型没有居中。
如果你想在你的 SCNNode 中央放置一些东西,你可以将它的位置设置在 SCNVector3Zero
或者完全忽略它,例如
/// Loads An SCNSphere On A Generated SCNNode
///
/// - Parameter plane: SCNNode
func loadSphereOnPlane(_ plane: SCNNode) {
let sphereNode = SCNNode()
let sphereNodeGeometry = SCNSphere(radius: 0.01)
sphereNodeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
sphereNode.geometry = sphereNodeGeometry
plane.addChildNode(sphereNode)
}
您可以在 rendererDidAddNode
委托回调结束时调用它,例如:
loadSphereOnPlane(planeNode)
如果您的模型的枢轴没有居中,您可以使用类似这样的东西来改变它:
/// Changes The Pivot To The Center Of The Model
///
/// - Parameter model: SCNNode
func createCentralPivotFor(_ model: SCNNode){
let (min, max) = model.boundingBox
let dx = min.x + 0.5 * (max.x - min.x)
let dy = min.y + 0.5 * (max.y - min.y)
let dz = min.z + 0.5 * (max.z - min.z)
model.pivot = SCNMatrix4MakeTranslation(dx, dy, dz)
}
一个示例用法可能是这样的:
/// Loads Our Little Scatterbug
func loadScatterBugOnPlane(_ node: SCNNode) {
let modelPath = "ARModels.scnassets/Scatterbug.scn"
//1. Get The Reference To Our SCNScene & Get The Model Root Node
guard let model = SCNScene(named: modelPath),
let pokemonModel = model.rootNode.childNode(withName: "RootNode", recursively: false) else { return }
let scatterBug = pokemonModel
//2. Scale The Scatterbug
scatterBug.scale = SCNVector3(0.002, 0.002, 0.002)
//3. Set The Pivot
createCentralPivotFor(scatterBug)
//4. Add It To The Plane
node.addChildNode(scatterBug)
}
您也可以在 rendererDidAddNode 委托回调结束时调用,例如:
两种方法的结果如下:
更新:
既然你现在已经改变了你的问题,你可以尝试这样的事情:
/// Loads An SCNSphere At The Position Of An ARAnchor
///
/// - Parameter plane: SCNNode
func loadSphereAtAnchorPosition(_ anchor: ARPlaneAnchor) {
let sphereNode = SCNNode()
let sphereNodeGeometry = SCNSphere(radius: 0.01)
sphereNodeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
sphereNode.geometry = sphereNodeGeometry
sphereNode.position = SCNVector3(anchor.transform.columns.3.x,
anchor.transform.columns.3.y,
anchor.transform.columns.3.z)
augmentedRealityView?.scene.rootNode.addChildNode(sphereNode)
}
希望对您有所帮助...
我的objective是在另一个包含SCNPlane的SCNNode中间生成一个SCNNode
SCNPlane 是在这样的渲染器函数中生成的:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
let width = CGFloat(planeAnchor.extent.x)
let height = CGFloat(planeAnchor.extent.z)
let plane = SCNPlane(width: width, height: height)
plane.materials.first?.diffuse.contents = UIColor.orange
let planeNode = SCNNode(geometry: plane)
let x = CGFloat(planeAnchor.center.x)
let y = CGFloat(planeAnchor.center.y)
let z = CGFloat(planeAnchor.center.z)
planeNode.position = SCNVector3(x,y,z)
planeNode.eulerAngles.x = -.pi / 2
node.addChildNode(planeNode)
node.name = "plane"
loadSphere(x:x, y:y, z:z)
我正试图将球体放在平面的中间:
func loadSphere (x:CGFloat, y:CGFloat, z:CGFloat) {
let idleScene = SCNScene(named: "art.scnassets/bounceFixed.dae")!
// This node will be parent of all the animation models
let node = SCNNode()
for child in idleScene.rootNode.childNodes {
node.addChildNode(child)
}
// Set up some properties
node.name = "Sphere"
node.position = SCNVector3(x, y, z)
node.scale = SCNVector3(0.001, 0.001, 0.001)
...
但问题是,每当我 运行 时,x、y、z 最终都为零。我试过 sceneView.scene.rootNode.childNodes[3].worldPosition
或 node.worldPosition
之类的东西,但最终总是在相机的视野中而不是在平面的中间生成球体。
我在这里附上了一张图片,向您展示我所说的 "middle" 的意思。
请告诉我如何解决这个问题。
编辑:我的目标 post 是尝试获取平面节点的 x、y、z(中心)而不附加球体作为子节点。
最佳。
在没有真正看到您的模型或您添加 Sphere 的确切方式的情况下,我会冒险猜测,要么您没有将模型添加到正确的 SCNNode
,要么 [=16] =] 你的模型没有居中。
如果你想在你的 SCNNode 中央放置一些东西,你可以将它的位置设置在 SCNVector3Zero
或者完全忽略它,例如
/// Loads An SCNSphere On A Generated SCNNode
///
/// - Parameter plane: SCNNode
func loadSphereOnPlane(_ plane: SCNNode) {
let sphereNode = SCNNode()
let sphereNodeGeometry = SCNSphere(radius: 0.01)
sphereNodeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
sphereNode.geometry = sphereNodeGeometry
plane.addChildNode(sphereNode)
}
您可以在 rendererDidAddNode
委托回调结束时调用它,例如:
loadSphereOnPlane(planeNode)
如果您的模型的枢轴没有居中,您可以使用类似这样的东西来改变它:
/// Changes The Pivot To The Center Of The Model
///
/// - Parameter model: SCNNode
func createCentralPivotFor(_ model: SCNNode){
let (min, max) = model.boundingBox
let dx = min.x + 0.5 * (max.x - min.x)
let dy = min.y + 0.5 * (max.y - min.y)
let dz = min.z + 0.5 * (max.z - min.z)
model.pivot = SCNMatrix4MakeTranslation(dx, dy, dz)
}
一个示例用法可能是这样的:
/// Loads Our Little Scatterbug
func loadScatterBugOnPlane(_ node: SCNNode) {
let modelPath = "ARModels.scnassets/Scatterbug.scn"
//1. Get The Reference To Our SCNScene & Get The Model Root Node
guard let model = SCNScene(named: modelPath),
let pokemonModel = model.rootNode.childNode(withName: "RootNode", recursively: false) else { return }
let scatterBug = pokemonModel
//2. Scale The Scatterbug
scatterBug.scale = SCNVector3(0.002, 0.002, 0.002)
//3. Set The Pivot
createCentralPivotFor(scatterBug)
//4. Add It To The Plane
node.addChildNode(scatterBug)
}
您也可以在 rendererDidAddNode 委托回调结束时调用,例如:
两种方法的结果如下:
更新:
既然你现在已经改变了你的问题,你可以尝试这样的事情:
/// Loads An SCNSphere At The Position Of An ARAnchor
///
/// - Parameter plane: SCNNode
func loadSphereAtAnchorPosition(_ anchor: ARPlaneAnchor) {
let sphereNode = SCNNode()
let sphereNodeGeometry = SCNSphere(radius: 0.01)
sphereNodeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
sphereNode.geometry = sphereNodeGeometry
sphereNode.position = SCNVector3(anchor.transform.columns.3.x,
anchor.transform.columns.3.y,
anchor.transform.columns.3.z)
augmentedRealityView?.scene.rootNode.addChildNode(sphereNode)
}
希望对您有所帮助...