问题
I am using the below code to rotate a node using the pan gesture. I like to rotate my node only in the y-axis.
let translation = gestureRecognize.translation(in: gestureRecognize.view!)
let x = Float(translation.x)
let y = Float(-translation.y)
let anglePan = (sqrt(pow(x,2)+pow(y,2)))*(Float)(Double.pi)/180.0
var rotationVector = SCNVector4()
rotationVector.x = 0.0
rotationVector.y = x
rotationVector.z = 0.0
rotationVector.w = anglePan
node.rotation = rotationVector
if(gestureRecognize.state == UIGestureRecognizerState.ended) {
let currentPivot = node.pivot
let changePivot = SCNMatrix4Invert( node.transform)
node.pivot = SCNMatrix4Mult(changePivot, currentPivot)
node.transform = SCNMatrix4Identity
}
This works for nodes with Euler set to (x: 0, y: 0, z: 0). But my node has Euler (x: -90, y: 0, z: 0). For my Euler values above code rotates the object in the wrong angle. How can I rotate a node with my/different Euler values?
回答1:
I think you might be overcomplicating what you need to do here.
In my example, I have created an SCNNode
with an SCNBox
Geometry and set it's Euler Angles
as per your example: (x: -90, y: 0, z: 0).
The 1st thing you need to do, is create a variable to store the rotationAngle around the YAxis:
var currentAngleY: Float = 0.0
Then try this function in order to rotate your node around the YAxis (which works fine by the way):
/// Rotates An Object On It's YAxis
///
/// - Parameter gesture: UIPanGestureRecognizer
@objc func rotateObject(_ gesture: UIPanGestureRecognizer) {
guard let nodeToRotate = currentNode else { return }
let translation = gesture.translation(in: gesture.view!)
var newAngleY = (Float)(translation.x)*(Float)(Double.pi)/180.0
newAngleY += currentAngleY
nodeToRotate.eulerAngles.y = newAngleY
if(gesture.state == .ended) { currentAngleY = newAngleY }
print(nodeToRotate.eulerAngles)
}
Hope it helps...
回答2:
The rotation vector should look like this;
rotation = SCNVector4(x: 0, y: 1, z: 0, w: some_angle_in_radians)
x,y,z is a normalized unit vector w is in radians
check your math
let anglePan = (sqrt(pow(x,2)+pow(y,2)))*(Float)(Double.pi)/180.0
probably check values of x,y, should be something like
let anglePan = (sqrt(pow(x*deg2rd,2)+pow(y*deg2rad,2)))
回答3:
Here's how to do what you want, which happens to be the only way to do it:
BOOL shouldRotateCube;
- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan)
{
shouldRotateCube = TRUE;
} else if (sender.state == UIGestureRecognizerStateChanged && shouldRotateCube
&& fabs([sender translationInView:sender.view].y) > 10.0)
{
shouldRotateCube = FALSE;
[SCNTransaction begin];
[SCNTransaction setCompletionBlock:^{
[SCNTransaction begin];
[SCNTransaction setAnimationDuration:0.15];
SCNVector3 nodeAngles = [node eulerAngles];
[node setEulerAngles:SCNVector3Make(nodeAngles.x + (([sender translationInView:sender.view].y > 0.0) ? degreesToRadians(90) : degreesToRadians(-90)), nodes[i].rotation.y, nodes[i].rotation.z)];
}
[SCNTransaction commit];
}];
[SCNTransaction commit];
}
}
Here's how it works: a BOOL
is used to prevent the multiplicity of pan gesture calls that results from swiping your finger up and down on your device's screen, since this particular code rotates a cube 90° at a time. When you begin a new gesture, then it will allow you to run the rotation-related code again.
The translationInView
method is used twice: once to make sure you intend to rotate the cube by requiring a distance of at least 10 in either direction before rotating the cube, and a second time to determine whether you are swiping up or down (by evaluating whether the translation value is positive or negative).
Since my cube is only being rotated up and down, I either added or subtracted 90° to/from the (x) value of the eulerAngles
vector; I placed the remaining eulerAngles
values in their respective positions.
Everything was placed inside an SCNTransaction to animate the rotation, and to control the duration of the rotation animation.
I've literally tried every other kind of rotation method available, even those in Core Animation, etc .—this is all that allows you to rotate a cube, etc., back and forth without weird things happening. I have an app that uses this very code, and it works fine. If you have trouble integrating it into your own app, I will gladly forward the code for my app to you at anytime.
来源:https://stackoverflow.com/questions/44781184/rotate-a-node-using-pan-gesture-in-scenekit-ios