ARKit - How to set the position of a manipulator with a center node in the SceneKit editor

I downloaded two different 3D models from Sketchfab. I imported both models into an ARKit 3D object placement. When placing 3D models, the node is not correctly aligned with the manipulator for one of the models. I have a screenshot. enter image description here

The left side is where the selected node (viewport) and manipulator are correctly aligned. But on the right side, the selected node (viewport) and manipulator are incorrectly aligned. How to make the node and manipulator align in the center, like a left three-dimensional model. please guide me. thank you

@ Josh Robbins

I tried your code, but still I have the same problem.

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) 

enter image description here

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 
+5
source share
2 answers

Looking at your model, it seems that the axis of rotation is set to the left for the tree.

You can change the reference point of your programmatically using the pivot property for SCNNode, which is SCNMatrix4MakeTranslation.

Assuming your model is called a tree, you can change it like this:

 tree.pivot = SCNMatrix4MakeTranslation(0,0,0) 

Or you can try the following:

 //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 can also create "EMPTY NODE". Then center the tree. This is probably the best option if the above does not work.

+1
source

This seems to be a popular question. A few minutes ago I answered a similar question. See if this function helps center the axis of the node below without moving its position.

set the SCNNode axis to the bounding center of the volume without changing the position of the node

  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 } 

use the above function:

  centerPivotWithOutMoving(for: treenode) 

Edit: Ive realized that my approach above was not the most efficient way to solve the centerPivotWithOutMoving center for all cases , because in some cases the local axis of your child node trying to center the rotation axis cannot be coplanar (the local axis and the parent axis sharing the same same plane) with the ParentNode axis. It is best to place a wrapper around each node for which you want to center the axis.

something like this will wrap each node fixing this potential problem when the axis is 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 have done this for now to call CenerPivotWithOutMoving in all child Nodes while clicking on 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 a modified centerPivotWithOutMoving, with some code added to test the local axis against the parent to show that they are now 1,1,1 for all shell nodes. Without 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 } 
+1
source

Source: https://habr.com/ru/post/1275733/


All Articles