opengl:如何在调整窗口大小时将对象保留在窗口中

我正在使用Bresenham的中点算法作为家庭作业在OpenGL上使用MS绘画类应用程序。 到目前为止,我可以绘制线条和椭圆。 在调整窗口大小时,我失去了它们。 我怎样才能让他们画出来?

完整代码:

#include "GL/glut.h" #include  #include  int i; //int mainWindow, subWindow; int X1, Y1, X2, Y2; int modoDeDibujo; int W = 1000, H = 1000; /*void menuApp (int value) { if (value == 1) printf("Linea\n"); if (value == 2) printf("Circulo\n"); if (value == 3) printf("Elipsis\n"); if (value == 4) exit(0); } void crearMenu() { //inicio Creando el menu int submenu; submenu = glutCreateMenu(menuApp); glutAddMenuEntry("Linea", 1); glutAddMenuEntry("Elipse",3); glutAddMenuEntry("Salir",4); glutCreateMenu(menuApp); glutAddSubMenu("SubMenu", submenu); glutAttachMenu(GLUT_RIGHT_BUTTON); //fin Creando el menu }*/ void renderPoint(void) /*REVISAR ESTO*/ { glClear (GL_COLOR_BUFFER_BIT); glBegin (GL_POINTS); glVertex2f (-0.98, 0.98); glEnd (); glFlush (); } void renderPoint(double x, double y) { //printf("BEFORE TRANSFORM %f\t%f\t# renderPoint\n", x, y); W = glutGet(GLUT_WINDOW_WIDTH); H = glutGet(GLUT_WINDOW_HEIGHT); float X; float Y; glBegin (GL_POINTS); X = (2*x/W) - 1; Y = (-2*y/H) + 1; glVertex2f (X, Y); //printf("TRANSFORMED POINT %f\t%f\t# renderPoint\n", X, Y); glEnd (); glFlush (); } /*wiki pseudo: function line(x0, x1, y0, y1) //x1 boolean steep := abs(y1 - y0) > abs(x1 - x0)//x2 if steep then//x3 swap(x0, y0) //x4 swap(x1, y1) //x5 if x0 > x1 then //x6 swap(x0, x1) //x7 swap(y0, y1) //x8 int deltax := x1 - x0 //x9 int deltay := abs(y1 - y0) //x10 int error := deltax / 2 //x11 int ystep //x12 int y := y0 //x13 if y0 < y1 then ystep := 1 else ystep := -1 //x14 for x from x0 to x1 //x15 if steep then plot(y,x) else plot(x,y) //x16 error := error - deltay //x17 if error  result2); //boolean steep := abs(y1 - y0) > abs(x1 - x0) if (steep){ //if steep then GLint aux1 = x0; //swap(x0, y0) x0=y0; y0 = aux1; GLint aux2 = x1; // swap (x1,y1) x1=y1; y1=aux2; } if(x0>x1){ // if (x0>x1) GLint aux3=x0; //swap(x0,x1) x0=x1; x1=aux3; GLint aux4=y0;//swap(y0,y1) y0=y1; y1=aux4; } int deltax = x1-x0; // deltax = x1-x0 int deltay = abs(y1-y0); // int deltay := abs(y1 - y0) - revisar int error = (deltax / 2); //int error := deltax / 2 int ystep; // int ystep int y = y0; //int y := y0 if (y0<y1){ //if y0 < y1 then ystep := 1 else ystep := -1 ystep=1; } else {ystep=-1;} for (int x=x0; x<=x1; x++){ //for x from x0 to x1 if (steep){ // if steep then plot(y,x) else plot(x,y) renderPoint(y,x); } else { renderPoint(x,y); } error = error - deltay; //error := error - deltay if (error<0) { //if error < 0 then y = y + ystep; // y := y + ystep error = error + deltax; //error := error + deltax } // end if (error= StoppingY){ Plot4EllipsePoints(X,Y,CX,CY); Y++; StoppingY=StoppingY + TwoASquare; EllipseError= EllipseError+ YChange; YChange= YChange+ TwoASquare; if( ((2*EllipseError) + XChange)>0) { X--; StoppingX = StoppingX - TwoBSquare; EllipseError= EllipseError + XChange; XChange = XChange + TwoBSquare; } } //1st set of points done, start second set X=0; Y= YRadius; XChange= YRadius*YRadius; YChange = XRadius*XRadius*(1-2*YRadius); EllipseError=0; StoppingX =0; StoppingY= TwoASquare * YRadius; while(StoppingX <= StoppingY){ // 2nd set of points, y'0){ Y--; StoppingY = StoppingY - TwoASquare; EllipseError = EllipseError + YChange; YChange = YChange + TwoASquare; } } } void renderAll (void) { /*glutSetWindow(mainWindow); glutPostRedisplay(); glutSetWindow(subWindow); glutPostRedisplay();*/ } void movimiento(int boton, int estado, int x, int y) { if((estado == GLUT_DOWN) && (boton == GLUT_LEFT_BUTTON))//mouse down { X1 = x; Y1 = y; PlotEllipse (x, y, 200, 100); renderPoint(x,y); } if((estado == GLUT_UP) && (boton == GLUT_LEFT_BUTTON))//mouse up { //printf(" Up|x:%d, y:%d\n",x,y); X2 = x; Y2 = y; //renderLine(); bresenham1(X1,X2,Y1,Y2); //PRUEBA USANDO LA PRIMITIVA DE OPENGL glBegin( GL_LINES ); glEnd(); //renderPoint(x, y); } } void MouseMove(int x, int y) { //printf("x:%d | y:%d\n", x,y); X2 = x; Y2 = y; //renderLine(); //bresenham1(X1, Y1, X2, Y2); } void teclado(unsigned char key, int x, int y) { if(key==1){ modoDeDibujo=1; // dibuja lineas printf("Modo de dibujo: linea"); } if (key==2){ modoDeDibujo=2; //dibuja elipses } if(key == 27)exit(0); } void especiales(int key, int x, int y) { if(key == GLUT_KEY_F1) exit(0); } static void key(unsigned char k, int x, int y) { switch (k) { case 27: /* Escape */ exit(0); break; default: return; } glutPostRedisplay(); } int main (int argc, char *argv []) { i = 0; //inicializa las operaciones de OpenGL/GLUT, db cr antes de usar funciones GLUT glutInit (&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGBA); glutInitWindowPosition (100, 100); glutInitWindowSize (W, H); //Crea una ventana de Opengl glutCreateWindow ("tarea"); glutDisplayFunc (renderPoint); glutMouseFunc(movimiento); glutKeyboardFunc(teclado);//teclas ASCII glutSpecialFunc(especiales);//captura las teclas [f1..f12] //glutPassiveMotionFunc(pasivo); glutKeyboardFunc(key); glutMotionFunc(MouseMove); //crearMenu(); glutMainLoop (); } 

首先,您需要安排代码。 您必须只有一个显示function,清除缓冲区,调用其他绘图function并将它们刷新到屏幕(如果使用双缓冲区,则交换缓冲区)。

在调整窗口大小时,GLUT将调用Display Function(),如您所知:

 glutDisplayFunc (renderPoint); 

renderPoint在重绘“点”之前清除缓冲区,例如:

 void renderPoint(void) /*REVISAR ESTO*/ { glClear (GL_COLOR_BUFFER_BIT); glBegin (GL_POINTS); glVertex2f (-0.98, 0.98); glEnd (); glFlush (); } 

由于缓冲区已被清除,因此在函数renderPoint外部绘制的所有点(圆点,线点……)都没有意义,因为您没有从“主显示函数即renderPoint”中调用它们。

如何保持屏幕上的点数?

您必须将点(您想要绘制的任何点)存储在缓冲区中,例如数组,动态数组,std :: vector或其他任何内容。 在display函数中,写一个循环语句来访问每个点并提取x和y ..然后绘制它们。

例如,代替上述函数,将其替换为:

 class MyPoint { public: float x; float y; MyPoint(float x, float y) { this->x = x; this->y = y; } }; #include  std::vector testPoints; void renderPoint(void) /*REVISAR ESTO*/ { testPoints.push_back(MyPoint(-0.58,0.58)); testPoints.push_back(MyPoint(0.58,0.58)); testPoints.push_back(MyPoint(0.58,-0.58)); glClear (GL_COLOR_BUFFER_BIT); glPointSize(2); glBegin (GL_POINTS); for(int i=0;i 

正如您所看到的,通过使用动态数组(如(std :: vector)来存储点并使用for循环语句),我们可以保持三个点可见。

还有什么 ?

  • 使用其他形状执行相同的方法,这样对于每个“ mouse click ”事件,您可以add or push_back两个点表示数组中的行结束点或std :: vector称为lineArray 。 在display function ,在提取两个线点后,使用for循环语句绘制每一行。

  • 你应该使用glutReshapeFuncglViewport来确保视口在resize事件后具有与窗口相同的尺寸。 而且我认为gluOrtho2d比尝试从Windows坐标空间映射到OpenGL坐标空间更优雅

  • 安排你的代码,这样你只需使用一个显示function。

你的程序可能是这样的:

 void drawTestPoints() { for(int i=0;i 

==

不要把它想象成“让它们被吸引”。 请考虑事件和“我什么时候需要重绘我的对象”。

为此,您需要处理resize事件并重新运行绘图代码。 我也猜测你的对象可能不会在另一个应用程序被移动到它们之后重绘,或者它被移出屏幕稍微然后被带回来。 如果是这种情况,您需要确定要处理的事件,这也将导致重绘。

以下是Windows的一个简单示例: http : //www.falloutsoftware.com/tutorials/gl/gl2.htm