I'm trying to find coordinates after each transformation of a 3d object (space ship perceived as a sphere), so I can detect collisions with asteroids (who are also spheres). The problem is that my ship can rotate around 2 axes : x and y, and translate forward in the direction the ship is looking at, and so I don't know how to keep track of its coordinates. The ship initially has a float array to determine its position :
float position[3] = {0.f, 0.f, 0.f};
The ship is then drawn as the following :
glPushMatrix();
LoadTextures();
glRotatef(angle_x, 1., 0., 0.);
glRotatef(angle_y, 0., 1., 0.);
glPushMatrix();
glTranslatef(position[0], position[1], position[2]-5);
GLUquadric* cylinder1=gluNewQuadric();
gluQuadricDrawStyle(cylinder1, GLU_FILL);
gluQuadricTexture(cylinder1,GLU_TRUE);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID[1]);
gluCylinder(cylinder1, 4, 4, 15, 20, 20);
gluDeleteQuadric(cylinder1);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(position[0], position[1], position[2]-5);
GLUquadric* disk1_1=gluNewQuadric();
gluQuadricDrawStyle(disk1_1, GLU_FILL);
gluQuadricTexture(disk1_1,GLU_TRUE);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID[0]);
gluDisk(disk1_1, 0, 4, 20, 20);
gluDeleteQuadric(disk1_1);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(position[0], position[1], position[2]+10);
GLUquadric* disk1_2=gluNewQuadric();
gluQuadricDrawStyle(disk1_2, GLU_FILL);
gluQuadricTexture(disk1_2,GLU_TRUE);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID[2]);
gluDisk(disk1_2, 0, 4, 20, 20);
gluDeleteQuadric(disk1_2);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
// Second Cylinder
glPushMatrix();
glTranslatef(position[0], position[1], position[2]-15);
GLUquadric* cylinder2=gluNewQuadric();
gluQuadricDrawStyle(cylinder2, GLU_FILL);
gluQuadricTexture(cylinder2,GLU_TRUE);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID[0]);
gluCylinder(cylinder2, 3, 3, 10, 20, 20);
gluDeleteQuadric(cylinder2);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(position[0], position[1], position[2]-5);
GLUquadric* disk2_1=gluNewQuadric();
gluQuadricDrawStyle(disk2_1, GLU_FILL);
gluQuadricTexture(disk2_1,GLU_TRUE);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID[0]);
gluDisk(disk2_1, 0, 3, 20, 20);
gluDeleteQuadric(disk2_1);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(position[0], position[1], position[2]-15);
GLUquadric* disk2_2=gluNewQuadric();
gluQuadricDrawStyle(disk2_2, GLU_FILL);
gluQuadricTexture(disk2_2,GLU_TRUE);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID[0]);
gluDisk(disk2_2, 0, 3, 20, 20);
gluDeleteQuadric(disk2_2);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
And then, according to user input, we either move it using this :
void add_z(float pos) { position[2] += pos; };
Or we rotate it :
void add_x(float angle) { angle_x=angle_x+angle; };
void add_y(float angle) { angle_y=angle_y+angle; };
This is used in a keyPressEvent :
void MKWidget::keyPressEvent(QKeyEvent* keyEvent)
{
switch (keyEvent->key())
{
case Qt::Key_Left:
ship->add_y(7.);
this->update();
break;
case Qt::Key_Right:
ship->add_y(-7.);
this->update();
break;
case Qt::Key_Up:
ship->add_x(7.);
this->update();
break;
case Qt::Key_Down:
ship->add_x(-7.);
this->update();
break;
case Qt::Key_Space:
ship->add_z(ship->getSpeed());
this->update();
updateShipInfos();
break;
case Qt::Key_0:
this->GameOver();
break;
}
}
And so using all this, in the display function that is called in the paintEvent, we can redraw the ship according to the user input. Now position[0] and position[1] are not updated and I have no idea how to do that, and it works because we only need the position[2] and the glRotatef functions in the beginning of the Display() to determine where to draw the ship. The problem in all of this, is that I'm unable to keep track of the coordinates of the ship, which I need for collision detection. This is what I've been able to do for now :
void MKWidget::updateShipInfos()
{
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glTranslatef(0.0, 0.0, ship->getSpeed());
glRotatef(ship->getAngle_x(), 1., 0., 0.);
glRotatef(ship->getAngle_y(), 0., 1., 0.);
float matrix[16];
matrix[0] = p[0];
matrix[1] = p[1];
matrix[2] = p[2];
matrix[3] = 1;
glMultMatrixf(matrix);
glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
p[0] = matrix[0];
p[1] = matrix[1];
p[2] = matrix[2];
cout << p[0] << " " << p[1] << " " << p[2] << endl;
glPopMatrix();
}
The idea is to populate the current matrix with the transformations we have so that OpenGL can return the output coordinates of the point, but it works very badly and rarely outputs correct results. What can I do to improve this ?