I've been playing with the SCNNode object for a while now and I'm lost with the Pivot. How can I change the pivot of a SCNNode (SCNBox as a bar) and place the pivot on one of the edge of the bar?
2 Answers
A node's pivot
is a transformation matrix, the inverse of which is applied to the node before its transform
property takes effect. For example, take a look at this bit from the default SceneKit Game template in Xcode:
let boxNode = SCNNode()
boxNode.geometry = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0.02)
If you set the boxNode
's position
, that point corresponds to the center of the cube, and if you rotate it (as the template does in an animation), it spins around its center.
To change the anchor point, set the pivot
to a translation transform:
boxNode.pivot = SCNMatrix4MakeTranslation(0.5, 0.5, 0.5)
Now, when you set the position
that point corresponds to the top-right-front corner of the cube, and when you rotate the cube it spins around that corner.
More generally, a pivot transforms the contents of a node relative to the node's own transform. Suppose you wanted to model the precession of the Earth's axis of rotation. You could do this by creating two animations: one that animates pivot
to spin the node around its own Y axis, and another that animates rotation
to move that axis relative to the space containing the node.

- 124,678
- 26
- 272
- 326
-
Thank you ! that was fast and smart ! – hciaravolo Jul 15 '14 at 06:20
-
Where did you see documentation on changing the pivot? For instance, we want to change the pivot, such that increasing the length makes a SCNBox grow only in the positive-z direction. However, the documentation for the pivot property is sparse on the SCNNode page and there is nothing on the SCNBox page. – Crashalot Mar 03 '17 at 00:14
-
@rickster I used your method in a **pinch gesture** to grow the node from its **upper left hand corner**. During the **state.changed** I changed the pivot point to: **node.pivot = SCNMatrix4MakeTranslation(0, 1, 0)**. I used a TSI, contacted apple, and they said: *"This is not moving the pivot to the upper left hand corner, it translating it one meter in the y-direction. To find the “upper left hand corner” you would need to calculate it based on the bounds of the geometry of your node via node.geometry.boundingBox."* https://developer.apple.com/documentation/scenekit/scnnode/1408044-pivot – Lance Samaria Jul 29 '20 at 13:26
-
I didn't have enough room to finish what I was saying, the method didn't work, and that's why I went to apple. They didn't give much help other then what you see there. How come you was able to change the pivot point to the top right but I wasn't able to change it to the top left? Why did apple say to do it another way? – Lance Samaria Jul 29 '20 at 14:51
On the pivot topic:
Just in case you do not have dimensions for your geometry/node something like this might help (especially for SCNText).
var minVec = SCNVector3Zero
var maxVec = SCNVector3Zero
if node.getBoundingBoxMin(&minVec, max: &maxVec) {
let bound = SCNVector3(x: maxVec.x + minVec.x,
y: maxVec.y + minVec.y,
z: maxVec.z + minVec.z)
node.pivot = SCNMatrix4MakeTranslation(bound.x / 2,
bound.y / 2,
bound.z / 2)
}

- 2,664
- 14
- 22
-
The `alloc(0)` and `dealloc(0)` are not correct. That's asking to allocate no memory at all (and then you promptly read from the memory it didn't allocate). You should be using `alloc(1)` and `dealloc(1)` for both pointers. – Lily Ballard Feb 05 '15 at 05:50
-
1Although I don't understand why you're even allocating anything. You should really just be using two stack variables, `var minVec = SCNVector3Zero; var maxVec = SCNVector3Zero`. Then to get the bounding box you say `node.getBoundingBoxMin(&minVec, max: &maxVec)`. – Lily Ballard Feb 05 '15 at 05:52
-
You are absolutly right Kevin. I copied the code directly from one of my projects. I wrote it early during the Swift Beta. Not sure if I needed that for some Beta reasons, or if it was simply too late in the night. :) I have updated the answer. – Mikael Hellman May 29 '15 at 07:00
-
1I think math is incorrect and you should use `(max + min) / 2` to calculate central point instead of `(max - min) / 2`. – kelin Oct 27 '21 at 10:40
-
Hmm, yes you are right. What a silly misstake, that must have worked because the minVec was always zero when I used it :) – Mikael Hellman Oct 28 '21 at 12:43