Model rotation completely unreliable

All of my models and my scene are oriented as follows:


z+ toward the camera, z- away from it. x- to the left, x+ to the right y+ up and y - down


However when I used this:

- (CGFloat) pointPairToBearingDegrees:(CGPoint)startingPoint secondPoint:(CGPoint) endingPoint
{
    CGPoint originPoint = CGPointMake(endingPoint.x - startingPoint.x, endingPoint.y - startingPoint.y); /
    float bearingRadians = atan2f(originPoint.y, originPoint.x); /
    float bearingDegrees = bearingRadians * (180.0 / M_PI); /
    bearingDegrees = (bearingDegrees > 0.0 ? bearingDegrees : (360.0 + bearingDegrees)); /
    return degreesToRadian(bearingDegrees);
}


or this:

CGFloat angleBetweenPoints(CGPoint first, CGPoint second) {
    CGFloat height = second.y - first.y;
    CGFloat width = first.x - second.x;
    CGFloat rads = atan2(width, height);
    return rads;
}


to try to get an angle between two points (given as the nodes x position and z position) and then rotate the model I get wildly unpredictable rotations which are usually +- 45 degree or +- 90 degree, however, if I attempt to correct this, the result remains unpredictable.

I don't know if I simply don't understand how 3d works in scene kit or what.

What is the best orientation for objects? I'll rearrange the scene and models any way I need too if it means I can have slghtly more realistic looking movement.

Replies

Well, your problem has more to do with a lack of knowledge of Trigonometry than with Scene Kit.

For instance, your second function is called angleBetweenPoints(). It does not make sense. You may have an angle between vectors, but not between points.


Try to think about triangles. If you have a point A and want to rotate it to position B, around the origin O, then you have a AOB triangle. Usually the most interesting angles are the ones formed by OA or OB with the +x axis, as it gives you the original angle, and the one you want to reach. Since they are rectangle triangles, our usual friends atan2(), asin() and acos() do the trick.


As a side remark: you should generally work in radians, as Scene Kit and trigonometric functions expect them.

I know degrees have more meaning to us human, but try to only use them when showing an angle to the user.

It's common for newcomers to 3D to want to represent orientation in terms of angles.

After all, in 2D, angles are a pretty good way of dealing with the problem.


In 3D, angles can cause a lot of problems. If we try to represent an orientation in terms of yaw, pitch and roll, for instance, the resulting outcome can be different depending on the order in which these are applied. And we also tend to encounter the "gimbal lock" problem. This can occur when small changes to the angual representation go past 90degree point. Which sounds like what you seem to be experiencing. Even interpolating angles is harder than it looks. (What is the average of 359 degrees and 1 degree?)


A better solution is to directly represent orientations in terms of either matrices or quaternions.

And represent directions in terms of vectors.


Quaternions have the benefit of being compact and easy to interpolate.

A matrix has the benefit of being able to transform geometry, and can be concatenated.


A good starting point for a games project is a really comprehensive 3d vector & matrix library.