0

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 ?

Zouhair
  • 23
  • 6
  • a rotated shpere is still a shpere. Maybe I dont understand, but you merely need the distance between centers to know if two shperes intersect – 463035818_is_not_an_ai May 30 '22 at 12:17
  • Yes that is well implemented, using euclidean distance between the two centers, the problem is I don't have the new coordinates of the first sphere(ship), after translating and/or rotating it. – Zouhair May 30 '22 at 12:23
  • @Zouhair Yes, of course you don't have the new coordinates, because you're using the old and deprecated fixed-function matrix stack instead of CPU-based model transformation matrices. Use something like [glm-math](https://glm.g-truc.net/0.9.2/api/index.html) and read [LearnOpenGL - Transformations](https://learnopengl.com/Getting-started/Transformations) – Rabbid76 May 30 '22 at 12:35
  • @Rabbid76 It's for a school project and so obviously I'm limited by their outdated course, is there any way how to do it using the old matrix stack ? – Zouhair May 30 '22 at 12:39
  • You can compute the model matrices with glm-math and load the matrices with [`glLoadMatrix`](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLoadMatrix.xml). Alternatively you can read back a matrix with [`glGetFloatv(GL_MODELVIEW_MATRIX, ...)`](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGet.xml) (see https://stackoverflow.com/questions/4202456/how-do-you-get-the-modelview-and-projection-matrices-in-opengl) – Rabbid76 May 30 '22 at 13:12
  • The position is position[0],position[1],position[2]. The problem is that you are rendering it as a weird position. Imagine the ship is (0,1,0) and then you rotate 90 degrees, you will render the ship at (1,0,0) which makes no sense. It needs to still be at (0,1,0) but rotated 90 degrees. – user253751 May 30 '22 at 13:21
  • @user253751 in the example you gave, I think my code does render the ship at (0, 1, 0) but rotated, the problem is after a translation occurs just after, how do you retrieve the new coordinates ? – Zouhair May 30 '22 at 13:36
  • 1
    As suggested by @Rabbid76 the best way is to implement your own transformation routines to be able to keep track yourself of rotation and translation per object. This is not so complicated. Once you done that, you'll probably face the fact that moving an object along its rotation axis require to pre-multiply your applyed translation by object rotation matrix, nothin so complex. –  May 30 '22 at 13:48

0 Answers0