PhilBot
PhilBot

Reputation: 50

iOS OpenGL ES 2.0 Rotate 1 Point Cartesian X Radians about Origin

I need to rotate a single point expressed in cartesian XYZ coordinates about the Z axis. The following 2 attempts are not working properly - I believe the first one is more correct..

I tried to rotate the points using the math on this website: http://farside.ph.utexas.edu/teaching/336k/newton/node153.html

// Rotate the XYZ coordinate for the pin image
if ( [satName isEqualToString:@"pin"] ) {
    double x = xyz.x;
    double y = xyz.y;
    double radians = self.timeSinceOpenGlStarted;
    x = x * cos(radians) + y * sin(radians);
    y = -x * sin(radians) + y * cos(radians);
    xyz.x = x;
    xyz.z = y;
}

I also tried this function by extracting the points after GLKMatrix4Rotate:

// This function rotates XYZ a certain of radians about the origin and gives back XYZ
- (GLKVector4)rotateXYZCoordinates:(XYZ*)coords {

    // Get the current modelview matrix
    GLKMatrix4 currMat = self.effect.transform.modelviewMatrix;

    // Print the coords before
    NSLog(@"Before: %f %f %f",coords->x,coords->y,coords->z);
    NSLog(@"Rotation Before: %f %f %f",currMat.m00,currMat.m10,currMat.m20);

    // Construct the rows in the new matrix
    float d = sqrt( pow(currMat.m00,2) + pow(currMat.m10,2) + pow(currMat.m20,2) );
    GLKVector4 columnToInsert0 = GLKVector4Make(d, 0, 0, coords->x);
    GLKVector4 columnToInsert1 = GLKVector4Make(0, d, 0, coords->y);
    GLKVector4 columnToInsert2 = GLKVector4Make(0, 0, d, coords->z);
    GLKVector4 columnToInsert3 = GLKVector4Make(0, 0, 0, 1);

    // Build the new Matrix
    GLKMatrix4 noTranslationInfo = GLKMatrix4SetRow(currMat, 0, columnToInsert0);
    noTranslationInfo = GLKMatrix4SetRow(noTranslationInfo, 1, columnToInsert1);
    noTranslationInfo = GLKMatrix4SetRow(noTranslationInfo, 2, columnToInsert2);
    noTranslationInfo = GLKMatrix4SetRow(noTranslationInfo, 3, columnToInsert3);

    // Throw the world translation coordinates in the matrix
    noTranslationInfo.m30 = ( noTranslationInfo.m30 );
    noTranslationInfo.m31 = ( noTranslationInfo.m31 );
    noTranslationInfo.m32 = ( noTranslationInfo.m32 );

    // Now rotate the matrix so many angles
    noTranslationInfo = GLKMatrix4Rotate(noTranslationInfo, self.timeSinceOpenGlStarted, 0, 0, 1);

    // Latch the output
    coords->x = noTranslationInfo.m30;
    coords->y = noTranslationInfo.m31;
    coords->z = noTranslationInfo.m32;

    // Print the coords After
    NSLog(@"AFter: %f %f %f",coords->x,coords->y,coords->z);
    NSLog(@"Rotation After: %f %f %f",noTranslationInfo.m00,noTranslationInfo.m10,noTranslationInfo.m20);

}

I have a globe spinning along the Z axis and a billboarded sprite specified at a specific spherical coordinate ( representing a lat/lon location ) and need the ability to have the point rotate along with the earth or not.

What am I doing wrong? How do I calculate a new X and Y coordinate ( Z is constant ) to rotate an XYZ point around the Z axis when I know the number of radians I want to rotate? Thanks!

UPDATE: Now I've tried this:

// Rotate the XYZ coordinate for the pin image
/* http://www.blitzbasic.com/Community/posts.php?topic=70536
 ;rotate offset around Z axis
 newx# = x# * Cos#(zr#) - y# * Sin#(zr#)
 newy# = x# * Sin#(zr#) + y# * Cos#(zr#)
 x# = newx#
 y# = newy#

 ;rotate offset around X axis
 newy# = y# * Cos#(xr#) - z# * Sin#(xr#)
 newz# = y# * Sin#(xr#) + z# * Cos#(xr#)
 y# = newy#
 z# = newz#


 ;rotate offset around Y axis
 newx# = z# * Sin#(-yr#) + x# * Cos#(-yr#)
 newz# = z# * Cos#(-yr#) - x# * Sin#(-yr#)
 x# = newx#
 z# = newz#
 */
if ( [satName isEqualToString:@"pin"] && self.shouldAnimate == YES ) {

    //NSLog(@"ONE %f %f %f %f",xyz.x,xyz.y,xyz.z,sqrt(pow(xyz.x, 2)+pow(xyz.y,2)+pow(xyz.z,2)));

    double x = xyz.x;
    double y = xyz.y;
    double z = xyz.z;

    NSLog(@"%f",self.timeSinceOpenGlStarted); // Values like: 32521.473728

    double zr = self.timeSinceOpenGlStarted;
    double yr = 0.0f;
    double xr = 0.0f;

    // Rotations must be in this order: Z then X then Y

    // Rotate around Z
    x = x * cos(zr) - y * sin(zr);
    y = x * sin(zr) + y * cos(zr);

    // Rotate around X
    y = y * cos(xr) - z * sin(xr);
    z = y * sin(xr) + z * cos(xr);

    // Rotate around Y
    x = z * sin(-yr) + x * cos(-yr);
    z = z * cos(-yr) + x * sin(-yr);

    // Get the coordinates back
    xyz.x = x;
    xyz.y = y;
    xyz.z = z;

    //NSLog(@"TWO %f %f %f %f",xyz.x,xyz.y,xyz.z,sqrt(pow(xyz.x, 2)+pow(xyz.y,2)+pow(xyz.z,2)));

}

The problem is that my image dances around the lat/lon it should be at - it almost does a figure 8.

Upvotes: 0

Views: 319

Answers (2)

Matic Oblak
Matic Oblak

Reputation: 16774

I either don't understand what you want to achieve or these methods of yours are a bit strange. If you need to rotate a single point around centre (0,0,0) around Z axis (on the XY plane) then you should use something like this:

float x, y;
float currentAngle;
float radius = sqrt(x*x + y*y);
x = radius*cos(currentAngle);
y = radius*sin(currentAngle);

To make it even easier you can simply use radius (which should be constant in your case) and the angle in radians. In this case you only need last 2 lines of this snippet.

Upvotes: 1

Sulea Cosmin
Sulea Cosmin

Reputation: 598

It looks like you are adding each frame to your angle. You can compute an "delta angle" just the angle to rotate from the previous frame, or to use the angle as it is now but apply the rotation to the initial orientation, not to last frame's result.

Upvotes: 0

Related Questions