I have downloaded two different 3D models from Sketchfab. i imported both model in ARKit 3D object placing. While placing the 3D models the node is not properly aligning with the manipulator for one of the models.. i have attached screenshot.
Left side is where the selected node(viewport) and manipulator are properly aligned. But Right side the selected node(viewport) and manipulator are not properly aligned. How do i make the node and manipulator align to the center like left side 3D model. please guide me. Thank you
@Josh Robbins
i have tried your code but still i am getting same issue.
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)
updated code
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
This seems to be a popular question. I just answered a similar question a few minutes ago. See if this function below helps centering your node's pivot without moving its position.
set pivot of SCNNode to bounding volume center without changing the node's position
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
}
to use the function above do this:
centerPivotWithOutMoving(for: treenode)
Edit: I’ve realised my approach above wasn’t the most efficient way to go about solving centerPivotWithOutMoving for all cases, because in some cases the local axis of the childnode you are trying to center the pivot for may not coplanar (local axis & parent axis sharing the same planes) with the ParentNode axis. A better way to go is to put a wrapperNode around each node you want to centre the pivot for.
something like this will wrap each node fixing that potential issue when the axis are not coplanar.
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)
}
I did this for the time being to call CenerPivotWithOutMoving on all the childNodes at time of tapping into the scene.
for child in parentNode.childNodes {
let delayInSeconds = Double(0.1)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delayInSeconds) {
self.centerPivotWithOutMoving(for: child)
}
}
here is the modified centerPivotWithOutMoving, with some added code for testing the local axis against the parent just to show they are all now 1,1,1 for all wrapper nodes. Without the wrapper nodes these numbers were in most cases never 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
}
Looking at your model, it seems like the pivot is set to the left hand side for you tree.
You can change the pivot of your programatically by using the pivot property of the `SCNNode, which is an SCNMatrix4MakeTranslation.
Assuming your model is called tree you could change it like so:
tree.pivot = SCNMatrix4MakeTranslation(0,0,0)
Or you can try this:
//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)
Update: In Scenekit Editor, you could also create an `EMPTY NODE'. Thenposition the tree centrally within that. This is probably your best bet if the aforementioned doesn't work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With