Я использую SDL с OpenGL и до сих пор все делал в 2D (используя glOrtho())
Теперь я хочу попробовать рисовать вещи в 3D, но, конечно, поскольку я теперь добавил в смесь 3-е измерение, все становится сложнее.
Что я хочу сделать, так это взять координаты экрана курсора, перевести их в (?) мировые координаты (координаты, которые я могу использовать в OpenGL, так как теперь у меня есть перспектива и т. д.), и нарисовать четырехугольник в эта позиция (курсор мыши находится в центре четырехугольника)
Я прочитал несколько руководств по gluUnProject() и примерно понимаю, что я должен делать, но, поскольку я учусь сам, очень легко запутаться и не понять, что я делаю.
Таким образом, я в основном скопировал примеры, которые нашел.
Ниже приведен мой код (я убрал проверку ошибок и т. д., пытаясь немного его сократить)
Как видите, у меня есть переменные mouseX, mouseY и mouseZ, значения которых mouseX и mouseY получают из SDL.
Я пытался использовать glReadPixel() для получения mouseZ, но я не уверен, что делаю это правильно.
Проблема в том, что когда я нажимаю, четырехугольник не рисуется в правильном положении (я думаю, отчасти из-за того, что я не знаю, как правильно получить mouseZ, поэтому я просто заменил его в gluUnProject() на 1.0?)
Я использую новые координаты (wx, wy, wz) в функции glTranslatef(), но еще раз, потому что я не знаю, как правильно получить mouseZ, я предполагаю, что это причина, по которой она не работает должным образом. Если я заменю wz на -499, все будет работать нормально, но мне нужно знать, как получить точные результаты без ручного поиска правильных (или почти правильных) чисел.
Если кто-нибудь может сказать мне, что я делаю неправильно, или дать мне какой-либо совет, я был бы очень признателен.
#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;
}