I am using SDL with OpenGL and up until now I have done everything in 2d (Using glOrtho())
Now I want to try drawing things in 3D but of course since I have now thrown a 3rd dimension into the mixture, things are getting more complicated.
What I want to do is, take the screen co-ordinates of the cursor, translate them to (?)world co-ordinates (Co-ordinates I can use in OpenGL since I now have perspective etc.), and draw a quad at that position (The mouse cursor being at the center of the quad)
I have read a few tutorials on gluUnProject() and I sort of understand what I am supposed to do, but since I am learning by myself it is very easy to get confused and not properly understand what I am doing.
As such, I have mainly copied from examples I have found.
Below is my code (I took out error checking etc in an attempt to cut it down a bit)
As you can see, I have mouseX, mouseY and mouseZ variables, of which mouseX and mouseY get their values from SDL.
I tried to use glReadPixel() to get mouseZ but I am not sure if I am doing it right.
The problem is that when I click, the quad is not drawn in the correct position (I guess partly due to the fact that I don't know how to get mouseZ properly, so I just replaced it in gluUnProject() with 1.0?)
I am using the new co-ordinates (wx, wy, wz) in the glTranslatef() function but once again because I don't know how to get mouseZ properly I am guessing this is the reason it doesn't work properly. If I replace wz with -499 it seems to work ok, but I need to know how to get accurate results without manually finding the correct (Or almost correct) numbers
If anybody can tell me what I am doing wrong, or give me any advice it would be greatly appreciated.
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
SDL_Surface* screen = 0;
SDL_Event event;
bool isRunning = true;
int mouseX, mouseY, mouseZ = 0;
GLint viewport[4];
GLdouble mvmatrix[16], projmatrix[16];
GLint realY; /* OpenGL y coordinate position */
GLdouble wx, wy, wz; /* returned world x, y, z coords */
int main(int argc, char **argv) {
SDL_Init(SDL_INIT_EVERYTHING);
screen = SDL_SetVideoMode(800, 600, 32, SDL_OPENGL);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glViewport(0, 0, 800, 600);
glClearDepth(1.f);
glClearColor(0, 0, 0, 0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.f, 1.f, 1.f, 500.f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
while(isRunning) {
while(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT) {
isRunning = false;
}
if(event.type == SDL_MOUSEBUTTONDOWN) {
if(event.button.button == SDL_BUTTON_LEFT) {
SDL_GetMouseState(&mouseX, &mouseY);
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
realY = viewport[3] - (GLint) mouseY - 1;
glReadPixels(mouseX, realY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &mouseZ);
gluUnProject((GLdouble)mouseX, (GLdouble)realY, 1.0, mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
}
}
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(wx, wy, wz);
glBegin(GL_QUADS);
glColor4f(1.f, 0.f, 0.f, 1.f);
glVertex3f(-20.f, -20.f, 0.f);
glColor4f(0.f, 1.f, 0.f, 1.f);
glVertex3f(-20.f, 20.f, 0.f);
glColor4f(0.f, 0.f, 1.f, 1.f);
glVertex3f(20.f, 20.f, 0.f);
glColor4f(1.f, 0.f, 1.f, 1.f);
glVertex3f(20.f, -20.f, 0.f);
glEnd();
glPopMatrix();
SDL_GL_SwapBuffers();
}
SDL_FreeSurface(screen);
return 0;
}
I found that if I added the following:
GLfloat depth[2];
then changed the glReadPixels() from:
glReadPixels(mouseX, realY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &mouseZ);
to:
glReadPixels(mouseX, realY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, depth);
then I just changed gluUnProject() from:
gluUnProject((GLdouble)mouseX, (GLdouble)realY, mouseZ, mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
to:
gluUnProject((GLdouble) mouseX, (GLdouble) realY, depth[0], mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
then I could get the Z value I wanted.
Then I just added a small value to wz, for example: wz += 1; to make sure the quad appeared above the place I clicked and it seems to work as I intended now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With