OpenGL glOrtho 设置匹配 window 大小
OpenGL glOrtho set up match the window size
我是 OpenGl 的初学者,我在设置 glOrtho 相机以匹配 window 大小以便我可以使用 window 的坐标绘制一条线时遇到了一些困难。例如,如果我想从坐标 0,10 (x,y) 到 600,10 画一条线。我设法在我当前的设置中画线(这将是来自视口的 "Separator" 和带有按钮的工具栏)但它是通过 "try end error" 方法和我需要放置的坐标对我来说没有任何意义。当我尝试使用上述坐标绘制一条线时,这条线根本就没有显示出来。为了使用这些 (1000x600) 屏幕尺寸并绘制我的顶点而不是这些,我需要在 glOrtho 设置中进行更改:
glVertex3f(-2.0, 11.0, 0.0);
glVertex3f(20.0, 11.0, 0.0);
请注意,我当前的 window 尺寸是 1000x600 (width/height)
这是一行(在横跨整个屏幕的顶部):
这是我处理所有绘图的 OGWindow class:
void OGWindow::MyReSizeGLScene(int fwidth, int fheight)
{
// Store window size in class variables so it can be accessed in myDrawGLScene() if necessary
wWidth = fwidth;
wHeight = fheight;
// Calculate aspect ration of the OpenGL window
aspect_ratio = (float) fwidth / fheight;
// Set camera so it can see a square area of space running from 0 to 10
// in both X and Y directions, plus a bit of space around it.
Ymin = -1;
Ymax = 12;
Xmin = -1;
// Choose Xmax so that the aspect ration of the projection
// = the aspect ratio of the viewport
Xmax = (aspect_ratio * (Ymax -Ymin)) + Xmin;
glMatrixMode(GL_PROJECTION); // Select The Projection Stack
glLoadIdentity();
glOrtho(Xmin, Xmax, Ymin, Ymax, -1.0, 1.0);
glViewport(0, 0, wWidth, wHeight); // Viewport fills the window
}
void OGWindow::myDrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the drawing area
OGWindow::myDrawModel();
drawToolbar();
glutSwapBuffers(); // Needed if we're running an animation
glFlush();
}
void OGWindow::myDrawModel(GLvoid)
{
switch ( squareColour ) {
case RED:
glColor3f(1.0, 0.0, 0.0);
break;
case BLUE:
glColor3f(0.0, 0.0, 1.0);
break;
}
glBegin( GL_QUADS );
glVertex3f( squareX, squareY, 0.0 ); // Coordinates of bottom-left corner of square
glVertex3f( squareX + squareWidth, squareY, 0.0 );
glVertex3f( squareX + squareWidth, squareY + squareHeight, 0.0 );
glVertex3f( squareX, squareY + squareHeight, 0.0 );
glEnd();
}
// Convert from screen coords returned by mouse
// to world coordinates.
// Return result in worldX, worldY
void OGWindow::screen2World(int screenX, int screenY, double & worldX, double & worldY)
{
// Dimensions of rectangle viewed by camera projection
double projWidth = Xmax -Xmin;
double projHeight = Ymax - Ymin;
// Screen coords with origin at bottom left
int screenLeft = screenX;
int screenUp = wHeight - screenY;
worldX = Xmin + screenLeft * projWidth / wWidth ;
worldY = Ymin + screenUp * projHeight / wHeight ;
}
//Method to draw the toolbar separator line
void OGWindow::drawToolbar(GLvoid) {
//draw toolbar line separator
glColor3f(0.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(-2.0, 11.0, 0.0);
glVertex3f(20.0, 11.0, 0.0);
glEnd();
//draw create button
glPushMatrix();
glTranslatef(2.0, 10.0, 0.0);
glutSolidCube(2.0);
glPopMatrix();
}
这是我的主要 class 调用 OGWindow 方法的地方:
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize( 1000, 600 );
glutInitWindowPosition(0, 0);
glutCreateWindow("OpenGL Demo");
glEnable(GL_DEPTH_TEST); // enable the depth buffer test
glutDisplayFunc(DrawGLScene);
glutReshapeFunc(ReSizeGLScene);
glutMouseFunc(mouseClick);
glutMotionFunc(mouseMotion);
glutPassiveMotionFunc(mousePassiveMotion);
glutIdleFunc(Idle);
theWindow.initGL();
glutMainLoop();
}
查看 documentation of glOrtho 函数。如您所见,有 6 个参数:left、right、bottom、top、near、far。您错误地将 window 宽度设置为 top 而不是 bottom 参数。下面是函数的正确用法:
glOrtho (0, 1000, 600, 0, -1.0, 1.0)
所以,首先您的正射设置。如果您希望相机与屏幕尺寸匹配,glOrtho 必须使用相同的尺寸。
// This will anchor the camera to the center of the screen
// Camera will be centered on (0,0)
glOrtho( -screenWidth/2.f, screenWidth/2.f, -screenHeight/2.f, screenHeight/2.f, -1, 1 );
// This will anchor the camera to the lower left corner of the screen
// Camera will be centered on (screenWidth/2, screenHeight/2)
glOrtho( 0, screenWidth, 0, screenHeight, -1, 1 );
两者都试一下,看看有什么不同。虽然如果您正在制作某种编辑器,但您的相机不会移动,您可能正在寻找第二个正射设置。
Second,你只用过(显然)GL_PROJECTION
矩阵模式。您必须使用此模式设置相机投影并GL_MODELVIEW
将变换应用于相机或对象。
因此,当您调用调整大小并且不将矩阵模式更改回 GL_MODELVIEW
时,您将对投影矩阵应用平移。
如果您忘记初始化模型视图矩阵,它可能包含垃圾值并产生意外结果。
我是 OpenGl 的初学者,我在设置 glOrtho 相机以匹配 window 大小以便我可以使用 window 的坐标绘制一条线时遇到了一些困难。例如,如果我想从坐标 0,10 (x,y) 到 600,10 画一条线。我设法在我当前的设置中画线(这将是来自视口的 "Separator" 和带有按钮的工具栏)但它是通过 "try end error" 方法和我需要放置的坐标对我来说没有任何意义。当我尝试使用上述坐标绘制一条线时,这条线根本就没有显示出来。为了使用这些 (1000x600) 屏幕尺寸并绘制我的顶点而不是这些,我需要在 glOrtho 设置中进行更改:
glVertex3f(-2.0, 11.0, 0.0);
glVertex3f(20.0, 11.0, 0.0);
请注意,我当前的 window 尺寸是 1000x600 (width/height)
这是一行(在横跨整个屏幕的顶部):
这是我处理所有绘图的 OGWindow class:
void OGWindow::MyReSizeGLScene(int fwidth, int fheight)
{
// Store window size in class variables so it can be accessed in myDrawGLScene() if necessary
wWidth = fwidth;
wHeight = fheight;
// Calculate aspect ration of the OpenGL window
aspect_ratio = (float) fwidth / fheight;
// Set camera so it can see a square area of space running from 0 to 10
// in both X and Y directions, plus a bit of space around it.
Ymin = -1;
Ymax = 12;
Xmin = -1;
// Choose Xmax so that the aspect ration of the projection
// = the aspect ratio of the viewport
Xmax = (aspect_ratio * (Ymax -Ymin)) + Xmin;
glMatrixMode(GL_PROJECTION); // Select The Projection Stack
glLoadIdentity();
glOrtho(Xmin, Xmax, Ymin, Ymax, -1.0, 1.0);
glViewport(0, 0, wWidth, wHeight); // Viewport fills the window
}
void OGWindow::myDrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the drawing area
OGWindow::myDrawModel();
drawToolbar();
glutSwapBuffers(); // Needed if we're running an animation
glFlush();
}
void OGWindow::myDrawModel(GLvoid)
{
switch ( squareColour ) {
case RED:
glColor3f(1.0, 0.0, 0.0);
break;
case BLUE:
glColor3f(0.0, 0.0, 1.0);
break;
}
glBegin( GL_QUADS );
glVertex3f( squareX, squareY, 0.0 ); // Coordinates of bottom-left corner of square
glVertex3f( squareX + squareWidth, squareY, 0.0 );
glVertex3f( squareX + squareWidth, squareY + squareHeight, 0.0 );
glVertex3f( squareX, squareY + squareHeight, 0.0 );
glEnd();
}
// Convert from screen coords returned by mouse
// to world coordinates.
// Return result in worldX, worldY
void OGWindow::screen2World(int screenX, int screenY, double & worldX, double & worldY)
{
// Dimensions of rectangle viewed by camera projection
double projWidth = Xmax -Xmin;
double projHeight = Ymax - Ymin;
// Screen coords with origin at bottom left
int screenLeft = screenX;
int screenUp = wHeight - screenY;
worldX = Xmin + screenLeft * projWidth / wWidth ;
worldY = Ymin + screenUp * projHeight / wHeight ;
}
//Method to draw the toolbar separator line
void OGWindow::drawToolbar(GLvoid) {
//draw toolbar line separator
glColor3f(0.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(-2.0, 11.0, 0.0);
glVertex3f(20.0, 11.0, 0.0);
glEnd();
//draw create button
glPushMatrix();
glTranslatef(2.0, 10.0, 0.0);
glutSolidCube(2.0);
glPopMatrix();
}
这是我的主要 class 调用 OGWindow 方法的地方:
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize( 1000, 600 );
glutInitWindowPosition(0, 0);
glutCreateWindow("OpenGL Demo");
glEnable(GL_DEPTH_TEST); // enable the depth buffer test
glutDisplayFunc(DrawGLScene);
glutReshapeFunc(ReSizeGLScene);
glutMouseFunc(mouseClick);
glutMotionFunc(mouseMotion);
glutPassiveMotionFunc(mousePassiveMotion);
glutIdleFunc(Idle);
theWindow.initGL();
glutMainLoop();
}
查看 documentation of glOrtho 函数。如您所见,有 6 个参数:left、right、bottom、top、near、far。您错误地将 window 宽度设置为 top 而不是 bottom 参数。下面是函数的正确用法:
glOrtho (0, 1000, 600, 0, -1.0, 1.0)
所以,首先您的正射设置。如果您希望相机与屏幕尺寸匹配,glOrtho 必须使用相同的尺寸。
// This will anchor the camera to the center of the screen
// Camera will be centered on (0,0)
glOrtho( -screenWidth/2.f, screenWidth/2.f, -screenHeight/2.f, screenHeight/2.f, -1, 1 );
// This will anchor the camera to the lower left corner of the screen
// Camera will be centered on (screenWidth/2, screenHeight/2)
glOrtho( 0, screenWidth, 0, screenHeight, -1, 1 );
两者都试一下,看看有什么不同。虽然如果您正在制作某种编辑器,但您的相机不会移动,您可能正在寻找第二个正射设置。
Second,你只用过(显然)GL_PROJECTION
矩阵模式。您必须使用此模式设置相机投影并GL_MODELVIEW
将变换应用于相机或对象。
因此,当您调用调整大小并且不将矩阵模式更改回 GL_MODELVIEW
时,您将对投影矩阵应用平移。
如果您忘记初始化模型视图矩阵,它可能包含垃圾值并产生意外结果。