无法正确重塑窗口中的多边形

Posted

技术标签:

【中文标题】无法正确重塑窗口中的多边形【英文标题】:Can't correctly reshape polygons in the window 【发布时间】:2019-09-05 04:53:07 【问题描述】:

我正在尝试开发一个程序,在该程序中,每次在窗口上执行点击时,都会在窗口上以点击发生的位置为中心出现一个随机大小的圆圈。 之后,我需要使用 glOrtho() 或 gluOrtho2D() 以便设置查看体积,以便在调整窗口大小时,圆圈不会改变其大小或在屏幕上变形。

我尝试以不同的方式编写重塑函数,但无法得到正确的结果。

int winWidth = 800;             
int winHeight = 600; 

int main( int argc, char** argv )

    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE );  
    glutInitWindowSize( winWidth, winHeight );
    glutCreateWindow( "main" );

    MyInit();

    glutDisplayFunc( MyDisplay );
    glutReshapeFunc( MyReshape );
    glutMouseFunc( MyMouse );

    glutMainLoop();
    return 0;


void MyReshape( int w, int h )

    winWidth = w;
    winHeight = h;

    glViewport( 0, 0, w, h );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    if (w <= h)
        glOrtho(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w,
            2.0 * (GLfloat) h / (GLfloat) w, -20.0, 20.0);
    else
        glOrtho(-2.0 * (GLfloat) w / (GLfloat) h,
            2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0, -20.0, 20.0);

    glMatrixMode( GL_MODELVIEW );



void MyMouse( int btn, int state, int x, int y )

    if ( btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
    
        disc[numDiscs].pos[0] = x;
        disc[numDiscs].pos[1] = y;
        disc[numDiscs].speed[0] = ((rand() % 2) * 2 - 1) * (MIN_X_SPEED + rand() / (RAND_MAX / (MAX_X_SPEED - MIN_X_SPEED)));
        disc[numDiscs].speed[1] = ((rand() % 2) * 2 - 1) * (MIN_Y_SPEED + rand() / (RAND_MAX / (MAX_Y_SPEED - MIN_Y_SPEED)));
        disc[numDiscs].radius = (MIN_RADIUS + rand() / (RAND_MAX / (MAX_RADIUS - MIN_RADIUS)))/10;
        disc[numDiscs].color[0] = (char)rand() % 256;
        disc[numDiscs].color[1] = (char)rand() % 256;
        disc[numDiscs].color[2] = (char)rand() % 256;

        numDiscs++;
        glutPostRedisplay();
    


void MyDisplay( void )

    glClear( GL_COLOR_BUFFER_BIT );
    glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );

    for ( int i = 0; i < numDiscs; i++ ) DrawDisc( &disc[i] );

    glFlush();  


void MyInit( void )

    glClearColor( 0.0, 0.0, 0.0, 1.0 ); 
    glShadeModel( GL_FLAT );

【问题讨论】:

您可以简单地设置glOrtho(0, w, 0, h, -1, 1) 并绘制大小以像素为单位的圆圈。如果您想将原点保留在视图中心,glOrtho(-w / 2, w / 2, -h / 2, h / 2, -1, 1) 可以。或者,您是否想要一个恒定的相对大小的圆圈以供查看? 谢谢!似乎它们在调整窗口大小时起作用。唯一的问题是,在第一个解决方案中,圆圈是在我单击的位置水平镜像绘制的,而在第二个解决方案中,它们是垂直镜像绘制的。知道为什么吗? 鼠标坐标是从窗口的左上角测量的,而在 OpenGL 视图中(使用提到的glOrtho(0, w, 0, h, -1, 1)),原点位于左下角。您可以尝试glOrtho(0, w, h, 0, -1, 1);,它使视图坐标与像素坐标相同。或者,您可以将鼠标坐标转换为视图空间(例如通过y = h - y;)。 这对我帮助很大!非常感谢! glOrtho(0, w, 0, h, -1, 1)glOrtho(0, w, h, 0, -1, 1) 之间的区别在于前者在“屏幕空间”中创建左手坐标系,而后者是右手坐标系。这对于 2d 可能是可以容忍的(并且没有背面剔除),但在 3d 中可能会成为一个问题。我曾经在SO: Ortho and Persp are reversing Z depth sign? 中摆弄过这个。 ;-) 【参考方案1】:

[...] 这样当窗口调整大小时,圆圈不会改变它们的大小或扭曲[...]

如果圆应该保持以像素为单位的大小,那么您必须定义一个正交投影,它基于窗口的当前大小与窗口的初始大小之间的关系。 由于窗口的大小为 (800, 600),因此您必须根据窗口的高度分别缩放 w/600.0 h/600.0 的投影,因为高度小于宽度并且方面应用于长边:

void MyReshape( int w, int h )

    winWidth = w;
    winHeight = h;

    glViewport( 0, 0, w, h );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    if (w <= h)
    
        GLdouble  aspect = (GLdouble)h / w;
        GLdouble  scale  = w / 600.0;

        scale *= 2.0;
        project = glm::ortho(-scale, scale, -scale * aspect, scale * aspect, -20.0, 20.0);
    
    else
    
        GLdouble  aspect = (GLdouble)w / h;
        GLdouble  scale  = h / 600.0;

        scale *= 2.0;
        project = glm::ortho(-scale * aspect, scale * aspect, -scale, scale, -20.0, 20.0);
    
    glMatrixMode( GL_MODELVIEW );

【讨论】:

else 中,调用glOrtho 时缺少(; @kiner_shah 是的,复制过去的问题。谢谢。

以上是关于无法正确重塑窗口中的多边形的主要内容,如果未能解决你的问题,请参考以下文章

ios 14 中的 .ply(多边形)格式文件问题

在多边形查询中的点上缓冲多边形

多边形与 Openlayers 叠加时显示多个弹出窗口

MFC异形窗口-多边形窗口-根据图片自定义窗口形状-CRgn

iOS中的多色多边形

R:在 shapefile 中的多边形上绘制 .gdb 文件中的点