How to move a rotated SCNNode in SceneKit?
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;
Rotate SCNNode then move relative to rotation?
Assuming I have understood you correctly, once you have rotated your SCNNode
, you want to move it forward it in that direction.
This can be done by using the worldFront
value which is simply:
The local unit -Z axis (0,0,-1) in world space.
As such this may be the answer you are looking for:
//1. Create A Node Holder
let nodeToAdd = SCNNode()
//2. Create An SCNBox Geometry
let nodeGeometry = SCNBox(width: 0.2, height: 0.2, length: 0.2, chamferRadius: 0)
nodeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
nodeGeometry.firstMaterial?.lightingModel = .constant
nodeToAdd.geometry = nodeGeometry
//3. Position It 1.5m Away From The Camera
nodeToAdd.position = SCNVector3(0, 0, -1.5)
//4. Rotate The Node By 90 Degrees On It's Y Axis
nodeToAdd.rotation = SCNVector4Make(0, 1, 0, .pi / 2)
//5. Add The Node To The ARSCNView
augmentedRealityView.scene.rootNode.addChildNode(nodeToAdd)
//6. Use The World Front To Move The Node Forward e.g
/*
nodeToAdd.simdPosition += nodeToAdd.simdWorldFront * 1.2
*/
nodeToAdd.simdPosition += nodeToAdd.simdWorldFront
//7. Print The Position
print(nodeToAdd.position)
/*
SCNVector3(x: -0.999999881, y: 0.0, z: -1.50000024)
*/
How to move a SCNNode in the direction it is pointing at after an rotation is applied
I've found that the easiest way to do this is to grab the third row of the node's worldTransform
property, which corresponds to its z-forward axis.
func getZForward(node: SCNNode) -> SCNVector3 {
return SCNVector3(node.worldTransform.m31, node.worldTransform.m32, node.worldTransform.m33)
}
ship.position += getZForward(ship) * speed // nb scalar multiply requires overload of * func
// if node has a physics body, you might need to use the presentationNode, eg:
// getZForward(ship.presentationNode)
// though you probably don't want to be directly modifying the position of a node with a physics body
See the discussion here Getting direction that SCNNode is facing
iOS 11 update
iOS 11 adds handy convenience functions for getting the orientation of a node. In this case the worldForward
property is the one you want. Also, all of the properties on SCNNode
that return SCNVector
and matrix types now have versions that return simd types. Because simd already has overloads for the arithmetic operators, you no longer need to add sets of arithmetic overrides for the SCNVector
and SCNMatrix
types.
So we can get rid of out getZForward
method above, and just have the line:
ship.simdPosition += ship.simdWorldFront * speed
Scenekit - multiple rotation of SCNNode and direction of axes
After further research i realised i chose completely wrong approach. The way to achieve what i want was to rotate the node using the axes of the rootNode - this way i don't need to worry about local axes of my node.
EDIT: updated code based on Xartec's suggestions
let rotation = SCNMatrix4MakeRotation(angle, x, y, Float(0))
let newTransform = SCNMatrix4Mult(bricksNode.transform, rotation)
let animation = CABasicAnimation(keyPath: "transform")
animation.fromValue = bricksNode.transform
animation.toValue = scnScene.rootNode.convertTransform(newTransform,from: nil)
animation.duration = 0.5
bricksNode.addAnimation(animation, forKey: nil)
How do I rotate a SCNNode to look at another node, whilst keeping its roll and pitch level with the camera?
Have you tried setting isGimbalLockEnabled
to true
to constrain the roll rotation? In the documentation Apple mentions: "For example, when constraining a camera to follow a moving object, setting this property to true ensures that the horizon remains level from the camera’s point of view."
If that still isn't what you're looking for, you may need to write a custom constraint using the class function SCNTransformConstraint.orientationConstraint
. You could write the constraint as a secondary constraint that basically restricts rotations on the X and Z axes, or you could write your own look-at constraint with more restrictions (in which case I'd recommend looking at the simd.look(at:)
function and then restricting the orientation axes from there).
This should get you most of the way there, or I can add some code in later if it doesn't seem to be working. Good luck!
Related Topics
How to Make List with Single Selection with Swiftui
Difference Between Awakefromnib() and Viewdidload() in Swift
Swift: Popover Dismiss Callback
Swift Codable Decode Manually Optional Variable
What Is the Meaning of "" in Swift
Swiftui Swizzling Disabled by Default, Phone Auth Not Working
Cannot Use Mutating Member on Immutable Value of Type
Result Values in '? :' Expression Have Mismatching Types 'Some View' and '...'
Datepicker Using Time-Interval in Swiftui
How to Build a Workout App on Watchos with Audio Feedback
Swift Uipasteboard Not Copying Png
Cannot Assign to Value: 'Word' Is a 'Let' Constant
Swift Extension for Selected Class Instance
Alamofire, Objectmapper, Realm: Nested Objects
Detecting If Wifi or Bluetooth Is Turned on or Off by the User
How to Reload a UI View's Content Swift
How to Cast an _Nsmallocblock_ to Its Underlying Type in Swift 3