Calculating Phi

Started by
10 comments, last by csuguy 15 years, 7 months ago
Quote:Original post by csuguy
Ah! Lots of math lol. Anyways - I tried plugging in your formula (with a few corrections) but it didn't work :/. If I pass it a point like: (50,0,0) it turns it into (0,0,50)?! lol. I noticed that your equation for setPhi and setTheta were reversed so I switched them - but I just got the same results...

In order to work this out I'm going to take what you and Zipster have said and I'm going to make a sample program to test everything out. No custom classes - just the math.

If I can't get that to work then I'll post my sample code to see if guys can't solve it.

Thanks so much for your help!
Ryan

Yeah, I switched phi and theta like that because it's a standard math convention for phi to be the angle between the z-axis and the point (plus I hadn't realized you were using the opposite). Clicky. If you switch phi and theta, you get exactly what you had before (except for normalizing the vector, because that step is unnecessary). Anyway, I'll leave it up to you to choose what theta and phi represent. Just realize that if you are using the standard convention, then

x = rho * sin(phi) * cos(theta)
y = rho * sin(phi) * sin(theta)
z = rho * cos(theta)

Using my original code and not changing the code in your original post would cause some weirdness when converting to cartesian coordinates.

The only other thing I can think of is to make sure you are passing in the proper coordinates for the rotation axis. i.e. if you are rotating about the z-axis you do axisRotation(&x, &y, zangle); if you were rotating about the y-axis then you do axisRotation(&z, &x, yangle); if you were rotating about the x-axis you would do axisRotation(&y, &z, zangle).
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
Advertisement
SUCCESS!!!! I have successfully written a program (code below) which will rotate around a sphere. It not only uses the arrow keys to change the phi and theta values, but it allows for axis rotation using the '-' and '+/=' keys! You can set the rate at which it rotates using the number keys 1-9! Oh - and you can switch the axis your rotating around by hitting x,y, or z respectively.

There are a few problems I'm not sure how to solve, though they are pretty small errors. 1) Sometimes it will randomly go back to a previous position. 2) Sometimes there is a slight jump when you switch from axis rotation to normal phi theta rotation. There are pretty small errors - but if you have any know-how as to how to fix these do tell.

Well, compile it and tell me what you think:


/* Basic Rotation Program
Written By: Ryan Williams
Copyright 2008

Special Thanks:
Zipster &
MikeTacular
*/

#include <GL/glut.h>
#include <stdlib.h>
#include <math.h>
#include <fstream>

#define PI 3.14159265358979323846

float toDeg(float rad);
float toRad(float deg);

/*Variables*/
float rho = 25.0f,phi = toRad(90.0f), theta = 0.0f;
float x,y,z;
float cx = 0.0f,cy = 0.0f,cz = 100.0f;
char axis = 'z'; //Which axis to rotate around
float deg_chg = 1.0f;

std::ofstream out("diagnostics.txt",std::ios::out);

void axisRotation(float* d1,float* d2, float deg)
{
out << "axisRotation()\n";

float m = sqrt( (*d1)*(*d1) + (*d2)*(*d2) );
out << "Calculated Magnitude: " << m << "\n";

float a = toDeg(atan2f( (*d2)/m,(*d1)/m )) + deg;
out << "Calculated Angle: " << a << "\n";

(*d1) = cos(toRad(a))*m;
(*d2) = sin(toRad(a))*m;

out << "Calculated D1: " << (*d1) << "\n";
out << "Calculated D2: " << (*d2) << "\n";
out << "\n"<< "\n"<< "\n";
}

float toDeg(float rad)
{
return rad*180.0f/PI;
}

float toRad(float deg)
{
return deg*PI/180.0f;
}

void toVector()
{
out << "toVector() \n";
out << "X: " << x << "\n";
out << "Y: " << y << "\n";
out << "Z: " << z << "\n";
out << "OLD RHO: "<<rho<< "\n";
out << "OLD PHI: "<<toDeg(phi)<<"\n";
out << "OLD THETA: "<<toDeg(theta)<< "\n\n";


rho = sqrt( x*x + y*y + z*z );
out << "NEW RHO: " << rho << "\n";
float z2 = (z>0)? 1-(z/rho) : 1+(z/rho);
phi = atan2(z2,z/rho);
out << "NEW PHI: "<< toDeg(phi) << "\n";
theta = atan2(y/rho/sin(phi), x/rho/sin(phi));
out << "NEW THETA: " << toDeg(theta) << "\n";
out << "\n"<< "\n"<< "\n";
}

void toCoords()
{
out << "toCoords() \n";
out << "OLD X: " << x << "\n";
out << "OLD Y: " << y << "\n";
out << "OLD Z: " << z << "\n";
out << "RHO: "<<rho<< "\n";
out << "PHI: "<<toDeg(phi)<<"\n";
out << "THETA: "<<toDeg(theta)<< "\n\n";
x = rho*cos(theta)*sin(phi);
y = rho*sin(theta)*sin(phi);
z = rho*cos(phi);
out << "NEW X: " << x << "\n";
out << "NEW Y: " << y << "\n";
out << "NEW Z: " << z << "\n";
out << "\n"<< "\n"<< "\n";
}


static void resize(int w, int h)
{
if(h == 0)
h = 1;


float ratio = 1.0* w / h;

// Reset the coordinate system before modifying
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Set the viewport to be the entire window
glViewport(0, 0, w, h);

// Set the correct perspective.
gluPerspective(45,ratio,1,1000);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//cm.view();
}

static void display(void)
{
glMatrixMode(GL_MODELVIEW);
glClearColor (0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(cx,cy,cz,0,0,0,0,1,0);

glPushMatrix();
glColor4f(1.0, 1.0, 1.0,.2);
glBegin(GL_LINES);
glVertex3f(-100.0,0.0,0.0);
glVertex3f(100.0,0.0,0.0);
glVertex3f(0.0,-100.0,0.0);
glVertex3f(0.0,100.0,0.0);
glVertex3f(0.0,0.0,-100.0);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.0,0.0,100.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glPopMatrix();

glPushMatrix();
glColor3d(1,0,0);
glTranslatef(x,y,z);
glutSolidCube(5);
glPopMatrix();

glutSwapBuffers();
}


static void key(unsigned char key, int kx, int ky)
{
switch (key)
{
case 27 :
case 'q':
out.close();
exit(0);
break;

case '+':
case '=':
if(axis == 'x')
axisRotation(&z,&y,deg_chg);
else if(axis == 'y')
axisRotation(&x,&z,deg_chg);
else
axisRotation(&x,&y,deg_chg);
toVector();
break;

case '-':
if(axis == 'x')
axisRotation(&z,&y,-deg_chg);
else if(axis == 'y')
axisRotation(&x,&z,-deg_chg);
else
axisRotation(&x,&y,-deg_chg);
toVector();
break;

case 'x':
axis = 'x';
break;

case 'y':
axis = 'y';
break;

case 'z':
axis = 'z';
break;

case '1':
deg_chg = 1.0f;
break;

case '2':
deg_chg = 2.0f;
break;

case '3':
deg_chg = 3.0f;
break;

case '4':
deg_chg = 4.0f;
break;

case '5':
deg_chg = 5.0f;
break;

case '6':
deg_chg = 6.0f;
break;

case '7':
deg_chg = 7.0f;
break;

case '8':
deg_chg = 8.0f;
break;

case '9':
deg_chg = 9.0f;
break;
}

display();
}

void key_special(int key, int x, int y)
{
switch(key)
{
case GLUT_KEY_UP:
//Increase Phi
out<< "UP!\n";
phi = toRad(toDeg(phi)+deg_chg);
toCoords();
break;

case GLUT_KEY_DOWN:
//Decrease Phi
out<< "DOWN!\n";
phi = toRad(toDeg(phi)-deg_chg);
toCoords();
break;

case GLUT_KEY_LEFT:
//Decrease Theta
out<< "LEFT!\n";
theta = toRad(toDeg(theta)-deg_chg);
toCoords();
break;

case GLUT_KEY_RIGHT:
//Increase Theta
out<< "RIGHT!\n";
theta = toRad(toDeg(theta)+deg_chg);
toCoords();
break;
}

if(phi < 0) phi += 360;
if(theta > 360) theta += 360;
if(phi > 360) phi -= 360;
if(theta > 360) theta -= 360;

display();
}

void init()
{
out << "INIT()\n";
toCoords();
}

int main(int argc, char *argv[])
{
init();
glutInit(&argc,argv);

glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGBA); /*Glut_Double provides a double buffer for smooth animation*/

glutInitWindowPosition(100,100); //Let it decide where to put it
glutInitWindowSize(800,600);
glutCreateWindow("Pocket Billiards");

glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(resize);

glutKeyboardFunc(key);
glutSpecialFunc(key_special);

glEnable(GL_DEPTH_TEST);
glutMainLoop();

return EXIT_SUCCESS;
}

This topic is closed to new replies.

Advertisement