Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move a rotated SCNNode in SceneKit?

The image below shows a rotated box that should be moved horizontally on the X and Z axes. Y should stay unaffected to simplify the scenario. The box could also be the SCNNode of the camera, so I guess a projection does not make sense at this point.

So lets say we want to move the box in the direction of the red arrow. How to achieve this using SceneKit?

The red arrow indicates -Z direction of the box. It also shows us it is not parallel to the camera's projection or to the global axes that are shown as dark grey lines of the grid.

My last approach is the product of a translation matrix and a rotation matrix that results in a new transformation matrix. Do I have to add the current transform to the new transform then?

If yes, where is the SceneKit function for the addition of matrices like SCNMatrix4Mult for multiplication or do I have to write it myself using Metal?

If no, what I'm missing out with the matrix calculations?

I don't want to make use of GLKit.

enter image description here

like image 896
Marc Avatar asked Apr 05 '17 17:04

Marc


1 Answers

So my understanding is that you want to move the Box Node along its own X axis (not it's parents X axis). And because the Box Node is rotated, its X axis is not aligned with its parent's one, so you have the problem to convert the translation between the two coordinate systems.

The node hierarchy is

parentNode
    |
    |----boxNode // rotated around Y (vertical) axis

Using Transformation Matrices

To move boxNode along its own X axis

// First let's get the current boxNode transformation matrix
SCNMatrix4 boxTransform = boxNode.transform;

// Let's make a new matrix for translation +2 along X axis
SCNMatrix4 xTranslation = SCNMatrix4MakeTranslation(2, 0, 0);

// Combine the two matrices, THE ORDER MATTERS !
// if you swap the parameters you will move it in parent's coord system
SCNMatrix4 newTransform = SCNMatrix4Mult(xTranslation, boxTransform);

// Allply the newly generated transform
boxNode.transform = newTransform;

Please Note: The order matters when multiplying matrices

Another option:

Using SCNNode coordinate conversion functions, looks more straight forward to me

// Get the boxNode current position in parent's coord system
SCNVector3 positionInParent = boxNode.position;

// Convert that coordinate to boxNode's own coord system
SCNVector3 positionInSelf = [boxNode convertPosition:positionInParent fromNode:parentNode];

// Translate along own X axis by +2 points
positionInSelf = SCNVector3Make(positionInSelf.x + 2,
                                positionInSelf.y,
                                positionInSelf.z);

// Convert that back to parent's coord system
positionInParent = [parentNode convertPosition: positionInSelf fromNode:boxNode];

// Apply the new position
boxNode.position = positionInParent;
like image 191
Sulevus Avatar answered Dec 09 '22 00:12

Sulevus