[英]How do I add a node to my SceneKit/ARKit scene, retaining its position but resetting its orientation/rotation
[英]ARKit - How to set manipulator position with center of the node in SceneKit editor
我從Sketchfab下載了兩個不同的3D模型。 我在ARKit 3D對象放置中導入了兩個模型。 在放置3D模型時,節點沒有與其中一個模型的操縱器正確對齊..我已附上截圖。
左側是所選節點(視口)和操縱器正確對齊的位置。 但右側所選節點(視口)和操縱器未正確對齊。 如何使節點和操縱器像左側3D模型一樣對齊中心。 請指導我。 謝謝
@Josh羅賓斯
我已經嘗試過你的代碼,但我仍然遇到同樣的問題。
box.firstMaterial?.emission.contents = UIColor.green
box.firstMaterial?.shaderModifiers = [SCNShaderModifierEntryPoint.surface: sm]
box.firstMaterial?.isDoubleSided = true
let boxNode = SCNNode(geometry: box)
boxNode.position = SCNVector3(node.position.x,(node.position.y + Float((proheights * 0.0234)/2)),node.position.z)
let minimum = float3(treenode.boundingBox.min)
let maximum = float3(treenode.boundingBox.max)
let translation = (maximum - minimum) * 0.5
//3. Set The Pivot
treenode.pivot = SCNMatrix4MakeTranslation(translation.x, translation.y, translation.z)
boxNode.pivot = SCNMatrix4MakeTranslation(translation.x, translation.y, translation.z)
self.addChildNode(boxNode)
更新的代碼
let treenode = SCNNode()
let box = SCNBox(width: (prowidths * 0.0234), height: (proheights * 0.0234), length: (prolenght * 0.0234), chamferRadius: 0)
box.firstMaterial?.emission.contents = UIColor.green
box.firstMaterial?.shaderModifiers = [SCNShaderModifierEntryPoint.surface: sm]
box.firstMaterial?.isDoubleSided = true
let boxNode = SCNNode(geometry: box)
boxNode.position = SCNVector3(treenode.position.x,(treenode.position.y + Float((proheights * 0.0234)/2)),treenode.position.z)
let minimum = float3(treenode.boundingBox.min)
let maximum = float3(treenode.boundingBox.max)
let translation = (maximum - minimum) * 0.5
//3. Set The Pivot
treenode.pivot = SCNMatrix4MakeTranslation(translation.x, translation.y, translation.z)
boxNode.pivot = SCNMatrix4MakeTranslation(translation.x, translation.y, translation.z)
self.addChildNode(boxNode)
self.addChildNode(treenode)
return treenode
這似乎是一個受歡迎的問題。 幾分鍾前我剛剛回答了類似的問題。 看看下面的這個功能是否有助於在不移動其位置的情況下使節點的樞軸居中。
func centerPivotWithOutMoving(for node: SCNNode) -> SCNNode {
let initialPos = treenode.presentation.position
var min = SCNVector3Zero
var max = SCNVector3Zero
node.__getBoundingBoxMin(&min, max: &max)
node.pivot = SCNMatrix4MakeTranslation(
min.x + (max.x - min.x)/2,
min.y + (max.y - min.y)/2,
min.z + (max.z - min.z)/2
)
let correctX = Float(min.x + (max.x - min.x)/2)
let correctY = Float(min.y + (max.y - min.y)/2)
let correctZ = Float(min.z + (max.z - min.z)/2)
if node.convertVector(SCNVector3(0,0,1), from: parentNode).z < 0 {
// if blue local z-axis is pointing downwards
node.position = SCNVector3(initialPos.x - correctX, initialPos.y - correctY, initialPos.z - correctZ)
} else {
// if blue local z-axis is pointing upwards
node.position = SCNVector3(initialPos.x + correctX, initialPos.y + correctY, initialPos.z + correctZ)
}
return node
}
使用上面的函數執行此操作:
centerPivotWithOutMoving(for: treenode)
編輯: 我已經意識到我的方法不是解決所有情況下解決centerPivotWithOutMoving的最有效方法,因為在某些情況下,您嘗試將樞軸居中的子節點的局部軸可能不共面(局部軸和父軸與ParentNode軸共享相同的平面。 更好的方法是在每個要將樞軸居中的節點周圍放置一個wrapperNode。
當軸不共面時,類似這樣的東西將包裝每個節點來修復潛在的問題。
for child in (self.parentNode?.childNodes)! {
let wrapperNode = SCNNode()
child.geometry?.firstMaterial?.lightingModel = .physicallyBased
wrapperNode.addChildNode(child)
wrapperNode.name = child.name! + "_wrapper"
self.parentNode.addChildNode(wrapperNode)
}
我這樣做暫時在點擊場景時在所有childNodes上調用CenerPivotWithOutMoving。
for child in parentNode.childNodes {
let delayInSeconds = Double(0.1)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delayInSeconds) {
self.centerPivotWithOutMoving(for: child)
}
}
這里是修改后的centerPivotWithOutMoving,其中添加了一些用於測試本地軸對父節點的代碼,只是為了顯示所有封裝節點的1,1,1。 沒有包裝節點,這些數字在大多數情況下從不是1,1,1。
func centerPivot(for node: SCNNode) -> SCNNode {
var min = SCNVector3Zero
var max = SCNVector3Zero
node.__getBoundingBoxMin(&min, max: &max)
node.pivot = SCNMatrix4MakeTranslation(
min.x + (max.x - min.x)/2,
min.y + (max.y - min.y)/2,
min.z + (max.z - min.z)/2
)
return node
}
func centerPivotWithOutMoving(for node: SCNNode) -> SCNNode {
let initialPos = node.presentation.position
var min = SCNVector3Zero
var max = SCNVector3Zero
node.__getBoundingBoxMin(&min, max: &max)
// corrective factor for each axis
let correctX = Float(min.x + (max.x - min.x)/2)
let correctY = Float(min.y + (max.y - min.y)/2)
let correctZ = Float(min.z + (max.z - min.z)/2)
var xAxis = node.convertVector(SCNVector3(1,0,0), from: parentNode).x
var yAxis = node.convertVector(SCNVector3(0,1,0), from: parentNode).y
var zAxis = node.convertVector(SCNVector3(0,0,1), from: parentNode).z
// check the local axis is coplanar with parentNode axis
if (xAxis == 1) && (yAxis == 1) && (zAxis == 1) {
print(node.name)
centerPivot(for: node)
node.position = SCNVector3(initialPos.x + correctX, initialPos.y + correctY, initialPos.z + correctZ)
} else {
print("node axis is not coplanar with parent")
}
return node
}
看看你的模型,看起來你的樹的樞軸設置在左側。
您可以使用`SCNNode的pivot屬性更改編程的軸,這是SCNMatrix4MakeTranslation。
假設您的模型被稱為樹,您可以像這樣更改它:
tree.pivot = SCNMatrix4MakeTranslation(0,0,0)
或者你可以嘗試這個:
//1. Get The Bounding Box Of The Tree
let minimum = float3(tree.boundingBox.min)
let maximum = float3(tree.boundingBox.max)
//2. Set The Translation To Be Half Way Between The Vector
let translation = (maximum - minimum) * 0.5
//3. Set The Pivot
tree.pivot = SCNMatrix4MakeTranslation(translation.x, translation.y, translation.z)
更新:在Scenekit編輯器中,您還可以創建一個“EMPTY NODE”。 然后將樹集中放置在其中。 如果前面提到的不起作用,這可能是你最好的選擇。
我用node.position = SCNVector3(0, 0, 0)
解決了這個問題
在我的代碼中看起來像這樣:
func placeObject(with objectPath: String) {
// Create a new scene
guard let virtualObjectScene = SCNScene(named: objectPath)
else {
print("Unable to Generate " + objectPath)
return
}
let wrapperNode = SCNNode()
for child in virtualObjectScene.rootNode.childNodes {
child.geometry?.firstMaterial?.lightingModel = .constant
wrapperNode.addChildNode(child)
}
// Rotate the node
let rotationAction = SCNAction.rotateBy(x: 0, y: 0.5, z: 0, duration: 1)
let inifiniteAction = SCNAction.repeatForever(rotationAction)
wrapperNode.runAction(inifiniteAction)
// 0.08 from placed plane
wrapperNode.position = SCNVector3(0, 0.08, 0)
node.addChildNode(wrapperNode)
}
我希望它對你有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.