I'm close to finishing a prototype of a solar system animation. (It's still not as efficient as it could be). Currently I have a solar system with Saturn/Uranus/Neptune plus Triton/Proteus (moons of neptune). This program allows a user to animate these planets while awsd to rotate the camera about the Axis. ( 0,1,0 / 1, 0, 0 etc)
I put in a prototype compass (literally 3 lines) to indicate the current camera orientation. Y = White. X = Red. Z = blue. However whenever the camera is rotated, the compass appears to move (although it isnt really moving), thus confusing the user. Is there a way I can lock the compass position while allowing it to mimic the user's camera rotations in place?
I understand that the compass is a set of 3D lines in 3D space and visually locking it in a 2D field doesn't make sense but I'm hoping that there's a solution regardless. Thanks!
In addition I'm also trying to animate the compass so that it mimics the camera rotations in place to help the user understand his/her current camera orientation.
Compass drawn/initialized in display()
Camera Rotations declared in Cases "wasd"
float triton = 0;
float proteus = 0;
float neptune = 0;
float saturn = 0;
float uranus = 0;
int sun = 0;
int angle = 0;
GLint buf, sbuf;
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
// Stars
glNewList(1, GL_COMPILE);
glBegin(GL_POINTS);
glColor3f(1.0, 1.0, 1.0);
for (int i = 0; i < 200; i++){
for (int j = 0; j < 300; j++){
if (((i + j) % 2) == 0){
glVertex3f(100 * i, 100 * j, 0.0);
}
}
}
glEnd();
glEndList();
// Material Specs
GLfloat mat_specular[] = { 0.8, 0.8, 0.9, 0.1 };
GLfloat mat_shininess[] = { 128.0 };
GLfloat lightDiffuse[] = { 1.0, 1.0, 1.0, 0.0 };
GLfloat lmodel_ambient[] = { 0.1, 0.2, 0.7, 0.0 };
// Light 0 Initialized.
GLfloat light0[] = { 1.0, 1.0, 1.0, 0.1 };
GLfloat light_position[] = { 1.0, 0.5, 0.0, -100.0 };
// Light 0
glLightfv(GL_LIGHT0, GL_SPECULAR, light0);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
// Mat Specs Implmentations.
glMaterialfv(GL_FRONT, GL_DIFFUSE, lightDiffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
//Ambient surrounding light on object.
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
// Enable Lighting and Depth
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
// Enable AntiAliased Lines
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
glLineWidth(1.5);
}
// Orbit values are arbitrary
void orbit(void)
{
triton = triton - 0.11;
proteus = proteus - 0.08;
neptune = neptune - 0.04;
saturn = saturn - 0.02;
uranus = uranus - 0.037;
glutPostRedisplay();
}
void backorbit(void)
{
triton = triton + 0.11;
proteus = proteus + 0.08;
neptune = neptune + 0.04;
saturn = saturn + 0.02;
uranus = uranus + 0.037;
glutPostRedisplay();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_COLOR_MATERIAL);
glDisable(GL_LIGHTING);
// Compass
glPushMatrix();
glBegin(GL_LINES);
glColor3f(1.0, 1.0, 1.0);
// Y axis
glVertex3f(-15.0, 12.0, 0.0);
glVertex3f(-15.0, 17.0, 0.0);
glColor3f(1.0, 0.0, 0.0);
// X axis
glVertex3f(-12.5, 14.5, 0.0);
glVertex3f(-17.5, 14.5, 0.0);
glColor3f(0.0, 0.0, 1.0);
// Z axis
glVertex3f(-15.0, 14.5, 1.0);
glVertex3f(-15.0, 14.5, -1.5);
glEnd();
glPopMatrix();
glEnable(GL_LIGHTING);
// Sun
glPushMatrix();
glColor3f(1.0, 0.35, 0.1);
glutSolidSphere(2.0, 100, 100);
// Saturn
glPushMatrix();
glRotatef((GLfloat)saturn, 0.5, 0.6, 1.0);
glColor3f(0.7, 0.5, 0.3);
glTranslatef(5.0, 0.0, 0.0);
glutSolidSphere(0.38, 100, 100);
glRotatef(20.0, 1.0, 0.0, 0.0);
glutSolidTorus(.11, .60, 2, 50);
glPopMatrix();
// Uranus
glPushMatrix();
glRotatef((GLfloat)uranus, 0.0, 1.0, 0.0);
glColor3f(0.5, 0.85, 0.9);
glTranslatef(6.5, 0.0, 0.0);
glutSolidSphere(0.37, 100, 100);
glPopMatrix();
// End Uranus
// Neptune
glPushMatrix();
glRotatef((GLfloat)neptune, 0.3, 1.0, 0.8);
glTranslatef(8.0, 0.0, 0.0);
glColor3f(0.1, 0.1, 0.3);
glutSolidSphere(0.3, 100, 100);
// Neptune(Triton)
glPushMatrix();
glColor3f(0.85, 0.7, 0.8);
glRotatef((GLfloat)triton, 1.0, 1.0, 1.0);
glTranslatef(1.0, 0.0, 0.0);
glutSolidSphere(0.07, 100, 100);
glPopMatrix(); // Ends Triton
// Neptune(Proteus)
glPushMatrix();
glColor3f(1.0, 1.0, 1.0);
glRotatef((GLfloat)proteus, 0.0, 1.0, 0.0);
glTranslatef(1.0, 0.0, 0.0);
glutSolidSphere(0.04, 100, 100);
glPopMatrix(); // Ends Proteus
glPopMatrix(); // Ends Neptune
glPopMatrix(); // Ends Sun
glEnable(GL_MULTISAMPLE);
glDisable(GL_LIGHTING);
// Stars
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
// Arbitrary ortho
glOrtho(0, 1000, 0, 1000, 0, 1000);
glCallList(1);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopMatrix();
glDisable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glFlush();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(120.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -11.0); // Find location.
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
// Triton + Proteus Orbit.
case 'o':
glutIdleFunc(orbit);
break;
case 'p':
glutIdleFunc(backorbit);
break;
// Camera Rotations.
case 'd':
glRotatef(4, 1.0, 0.0, 0.0);
glutPostRedisplay();
break;
case 'a':
glRotatef(-4, 1.0, 0.0, 0.0);
glutPostRedisplay();
break;
case 'w':
angle -= 4.0;
glRotatef(-4.0, 0.0, 1.0, 0.0);
glutPostRedisplay();
break;
case 's':
glRotatef(4.0, 0.0, 1.0, 0.0);
glutPostRedisplay();
break;
// Stop Orbit.
case 't':
glutIdleFunc(NULL);
break;
// Reset to Origin (IP)
case '1':
angle = 0;
glutPostRedisplay();
break;
case ',':
glTranslatef(-0.3, 0.0, 0.0);
glutPostRedisplay();
break;
case '.':
glTranslatef(0.3, 0.0, 0.0);
glutPostRedisplay();
break;
// Exit
case 27:
exit(0);
break;
default:
break;
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB | GLUT_MULTISAMPLE);
glutInitWindowSize(1000, 1000);
glutInitWindowPosition(100, 100);
glutCreateWindow("Solar System");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
You have to draw the "compass " to the center of the view (0, 0, 0), then you have to apply the view matrix and finally you have to translate the "compass" to its final position.
The current model view matrix can be get by glGetFloatv( GL_MODELVIEW_MATRIX, view_mat )
:
glPushMatrix();
GLfloat view_mat[16];
glGetFloatv( GL_MODELVIEW_MATRIX, view_mat );
glLoadIdentity();
glTranslatef( -15.0, 14.5, 0.0 );
glMultMatrixf( view_mat );
glBegin(GL_LINES);
glColor3f(1.0, 1.0, 1.0);
// Y axis
glVertex3f(0.0, -2.5, 0.0);
glVertex3f(0.0, 2.5, 0.0);
glColor3f(1.0, 0.0, 0.0);
// X axis
glVertex3f(-2.5, 0.0, 0.0);
glVertex3f(2.5, 0.0, 0.0);
glColor3f(0.0, 0.0, 1.0);
// Z axis
glVertex3f(-0.0, 0.0, 1.0);
glVertex3f(-0.0, 0.0, -1.5);
glEnd();
glPopMatrix();
But note, drawing by glBegin
/glEnd
sequences and using the fixed function pipeline matrix stack is deprecated since several years.
Read about Fixed Function Pipeline and see Vertex Specification and Shader for a state of the art way of rendering.