我正在使用SDL和OpenGL,直到现在我已经在2d完成了所有工作(使用glOrtho())
现在我想尝试用3D绘制东西但当然因为我现在已经在混合物中投入了第三维,事情变得越来越复杂。
我想要做的是,取光标的屏幕坐标,将它们转换为(?)世界坐标(我可以在OpenGL中使用的坐标,因为我现在有透视等),并绘制该位置的四边形(鼠标光标位于四边形的中心)
我已经阅读了一些关于gluUnProject()的教程,我有点理解我应该做的事情,但是因为我自己学习很容易混淆并且不能正确理解我在做什么。
因此,我主要从我找到的例子中复制过来。
下面是我的代码(我拿出了错误检查等,试图将其删除一点)
如您所见,我有mouseX,mouseY和mouseZ变量,其中mouseX和mouseY从SDL获取它们的值。
我尝试使用glReadPixel()获取mouseZ,但我不确定我是否做得对。
问题在于,当我点击时,四边形没有被绘制在正确的位置(我想部分是因为我不知道如何正确获取mouseZ,所以我只是在gluUnProject()中替换它1.0?)
我在glTranslatef()函数中使用新的坐标(wx,wy,wz),但又一次因为我不知道如何正确获取mouseZ我猜这是它不起作用的原因正常。 如果我用-499替换wz它似乎工作正常,但我需要知道如何获得准确的结果而无需手动找到正确的(或几乎正确的)数字
如果有人能告诉我我做错了什么,或者给我任何建议,我将不胜感激。
#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;
}
答案 0 :(得分:1)
我发现如果我添加以下内容:
GLfloat depth[2];
然后改变了glReadPixels():
glReadPixels(mouseX, realY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &mouseZ);
为:
glReadPixels(mouseX, realY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, depth);
然后我刚刚改变了gluUnProject():
gluUnProject((GLdouble)mouseX, (GLdouble)realY, mouseZ, mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
为:
gluUnProject((GLdouble) mouseX, (GLdouble) realY, depth[0], mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
然后我可以得到我想要的Z值。
然后我向wz添加了一个小值,例如:wz += 1;
以确保四边形出现在我点击的位置上方,它似乎按照我的预期工作。
答案 1 :(得分:0)
要猜测Z,你需要对这个z有意义:
通常意思是你想要与显示的3d对象相交的(相机原点,像素)对应的线相交。你可以使用Z缓冲区。
如果不是(您希望将多边形粘贴到没有3D关系的光标上),只需使用2D功能,您可以在绘制同一帧(使用投影矩阵或使用投影矩阵)时在3D和2D投影之间切换2D特定功能),因此您不需要z。
如果设计中没有基本原理,那么为Z设置默认值是一个坏主意。
只有一个Z值可以为您提供正确的像素坐标。
openGL中2D和3D坐标之间的链接是OpenGl使用Z = 1处的投影平面。 然后将像素坐标从[-1,1]缩放到像素坐标。