将透视投影转换为正交投影

时间:2014-05-18 07:13:27

标签: opengl glut projection

我创建了这个程序,用户单击右键单击鼠标,然后获得一个菜单,他可以选择在透视投影中绘制立方体或球体

我希望他能够将透视投影改为正交投影。我希望只需使用正交投影就可以将形状放置在同一个位置。

我希望他能够点击" O"在键盘上,点击" p"。

返回透视图

如何在此代码中混合正交投影?

#include <windows.h>
#include <stdio.h>
#include<math.h>

 #include <gl\glut.h>  // glut.h must come before gl.h and glu.h
#include <gl\gl.h>
#include <gl\glu.h> 

void menu(int value);
static int win;
static int menid;
static int submenid;
static int  left_click = GLUT_UP;
static int  right_click = GLUT_UP;
static int  xold;
static int  yold;
static int  width;
static int  height;
static float    rotate_x = 30;
static float    rotate_y = 15;
static float    alpha = 0;
static float    beta = 0;
static int primitive = 0;
 static int orth =0;
static int flag =0;

void        sphere (void)
{
  glBegin (GL_LINES);
  glColor3f (1, 0, 0); glVertex3f (-1, -1, -1); glVertex3f ( 1, -1, -1);
  glColor3f (0, 1, 0); glVertex3f (-1, -1, -1); glVertex3f (-1,  1, -1);
  glColor3f (0, 0, 1); glVertex3f (-1, -1, -1); glVertex3f (-1, -1,  1);

  glEnd ();
  glRotatef (beta, 1, 0, 0);
  glRotatef (alpha, 0, 1, 0);
  glColor3f (0, 1, 0);
  glutWireSphere(1.0, 20, 16);  
}

void        cube (void)
{
  glBegin (GL_LINES);
  glColor3f (1, 0, 0); glVertex3f (-1, -1, -1); glVertex3f ( 1, -1, -1);
  glColor3f (0, 1, 0); glVertex3f (-1, -1, -1); glVertex3f (-1,  1, -1);
  glColor3f (0, 0, 1); glVertex3f (-1, -1, -1); glVertex3f (-1, -1,  1);

  glEnd ();
  glRotatef (beta, 1, 0, 0);
  glRotatef (alpha, 0, 1, 0);
  glColor3f (1, 0, 0);
 glutWireCube(1);

}

void        KeyboardFunc (unsigned char key, int x, int y)
{
  xold = x; /* Has no effect: just to avoid a warning */
  yold = y;
  if ('q' == key || 'Q' == key || 27 == key)
      exit (0);
  if(key=='O' || key =='o')
 //does something to change the perspective to orthogonal...  
  // you would want to redraw now
  glutPostRedisplay();

}
void createMenu(void){

  // MENU //

  submenid = glutCreateMenu(menu);

  glutAddMenuEntry("cube", 2);
  glutAddMenuEntry("sphere", 3);

  menid = glutCreateMenu(menu);

  // Create an entry
  glutAddMenuEntry("Clear", 1);

  glutAddSubMenu("Draw", submenid);

  glutAddMenuEntry("Quit", 0);

  glutAttachMenu(GLUT_RIGHT_BUTTON);


}

void menu(int value)
{
  if(value == 0)
  {
    glutDestroyWindow(win);
    exit(0);
  }
  else{
    primitive=value;
  }
  glutPostRedisplay();
}

void        DisplayFunc (void)
{
  const float a = height / (float) width;
  const float b = width / (float) height;

  glClear (GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);

 /* Perspective projection */
     glLoadIdentity();
    gluPerspective (20 * sqrt (1 + a * a), b, 8, 12);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();


/* Perspective view */
 glViewport (0, 0, width , height);
 glPushMatrix ();
glTranslatef (0, 0, -10);
glRotatef (rotate_y, 1, 0, 0);
glRotatef (rotate_x, 0, 1, 0);


  switch(primitive)
  {

case 2:
    cube();
    break;

case 3:
    sphere();
    break;
  }

  glPopMatrix ();

  glFlush ();
  glutSwapBuffers ();
}

void        ReshapeFunc (int new_width, int new_height)
{
  width = new_width;
  height = new_height;
  glutPostRedisplay();
}


void        MouseFunc (int button, int state, int x, int y)
{
  if (GLUT_LEFT_BUTTON == button)
    left_click = state;
  if (GLUT_RIGHT_BUTTON == button)
    right_click = state;
  xold = x;
  yold = y;
}

void        MotionFunc (int x, int y)
{
  if (GLUT_DOWN == left_click)
    {
      rotate_y = rotate_y + (y - yold) / 5.f;
      rotate_x = rotate_x + (x - xold) / 5.f;
      if (rotate_y > 90)
    rotate_y = 90;
      if (rotate_y < -90)
    rotate_y = -90;
      glutPostRedisplay ();
    }
  if (GLUT_DOWN == right_click)
    {
      beta = beta + (y - yold) / 2.f;
      alpha = alpha + (x - xold) / 2.f;
      glutPostRedisplay ();
    }
  xold = x;
  yold = y;
}


int     main (int argc, char **argv)
{
  /* Creation of the window */
  glutInit (&argc, argv);
  glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE);
  glutInitWindowSize (500, 500);
  glutCreateWindow ("perspective");

  /* OpenGL settings */
  glClearColor (0, 0, 0, 0);
  glEnable (GL_CULL_FACE);
  glCullFace (GL_BACK);
  glEnable (GL_BLEND);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  /* Declaration of the callbacks */
  glutDisplayFunc (&DisplayFunc);
  glutReshapeFunc (&ReshapeFunc);
  glutKeyboardFunc (&KeyboardFunc);
  glutMouseFunc (&MouseFunc);
  glutMotionFunc (&MotionFunc);

    // put all the menu functions in one nice procedure
  createMenu();

  /* Loop */
  glutMainLoop ();
  return 0;
}

1 个答案:

答案 0 :(得分:4)

当然,使用正交投影,您无法获得与透视投影相同的图像。但是,您可以定义投影到两个转换中相同位置的平面(让我们称之为焦平面)。

Visualization

你有20 * sqrt (1 + a * a)的垂直视野(顺便说一句,我怀疑这是一个合理的计算; fovy应该是度数)。为了计算邻域的边缘,我们需要半角。然后:

float halfY = 20 * sqrt (1 + a * a) / 2.0f * 3.1415926f / 180.0f;
float top = focus_plane * tan(halfY); //focus_plane is the distance from the camera
float right = top * aspectRatio;
glOrtho(-right, right, -top, top, 8, 12);

您可以将focus_plane设置为zNearzFar之间的中间位置,在本例中为10

相关问题