2

I am looking for a way to set the pivot of SCNNodes (obtained from importing Collada files) to their centroid (or the center of their bounding box. I get the center with

 SCNVector3 center;
CGFloat radius;
[node getBoundingSphereCenter:&center radius:&radius];

However, when I try to set the node's pivot (which is a 4D vector as opposed to the 3D vector of the center) to the center, the node's position also changes.

node.pivot = SCNMatrix4MakeTranslation(center.x,center.y,center.z);

How can I offset this movement - resp. how can I only change the node's pivot without affecting its position in space? Or is there even a way (without using additional empty nodes) to do it in Interface Builder?

Ekta Padaliya
  • 5,743
  • 3
  • 39
  • 51
user1612877
  • 391
  • 1
  • 5
  • 19
  • Did the answer below work for you or did you find another solution? – bpedit Jul 22 '16 at 14:42
  • Hi I tried below answer - however I still had some nodes in the wrong places. The solution I had to stick to was changing the pivot of each model part in the external 3D editor (Blender) and export the DAE file again. – user1612877 Jul 23 '16 at 08:40

2 Answers2

4

The same question was also asked here Is it normal for an SCNNode pivot to change the nodes position? ... but after searching online for hours I couldn't find any coded solution to this problem. Which is how does one center the pivot of a node without moving the node.

So in the end I spend most of today working on this coded answer below. What I found was that the orientation of the local axis determines whether you subtract or do an addition for the correction factor.

Take this bike below. The right-hand pedal crank pivot z-axis (blue) is pointing upwards, whilst in the other photo, left-hand pedal crank pivot z-axis (blue) is pointing downwards. That reason these axis is different is when the person was drawing the bike model in SketchUp, they just copied and flipped the first pedal crank to the opposite side. So unfortunately, its very common to get imported DAE models with ad-hoc pivot orientation and positions!

enter image description here

enter image description here

 func centerPivotWithOutMoving(for node: SCNNode) -> SCNNode {

    let initialPos = activeNode.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
}

I've only tested the code above on the two different z-axis orientations shown above, the complete code would also have to deal with x, y axis using these two conditions.

  node.convertVector(SCNVector3(0,1,0), from: parentNode).z < 0

  node.convertVector(SCNVector3(1,0,0), from: parentNode).z < 0   

If there is a better way to do this... please share?

Clay
  • 1,721
  • 2
  • 10
  • 18
3

The pivot is not only the center of rotation, it is the node's reference point for position. When you reset the pivot, the position of the pivot relative to the parent object remains fixed. You are, in effect, moving the geometry relative to the object's current position.

The simple fix is to reposition the node using the negative values of those used to reset the pivot. If, for some reason, you need a specific value that doesn't allow this, put your node in a container node and use the container node for position and your re-pivoted node for rotation.

bpedit
  • 1,176
  • 8
  • 22