将透视投影转换为正交投影 [英] Converting perspective projection to orthogonal projection

查看:246
本文介绍了将透视投影转换为正交投影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I created this program where the user clicks the right click of the mouse and he gets a menu where he can choose to draw a cube or a sphere in a perspective projection

我希望他能够将透视投影更改为正交投影.我希望将这些形状仅通过正交投影放置在同一位置.

I would like him to be able to change the perspective projection to orthogonal projection. I want the shapes to be placed in the same spot just with orthogonal projection.

我希望他能够通过单击键盘上的"O"来做到这一点,并通过单击"p"返回到透视图.

I want him to be able to do it by clicking "O" in the keyboard and go back to perspective by clicking "p".

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

how do I mix the orthogonal projection in this code?

#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;
}

推荐答案

使用正交投影当然不能获得与透视投影相同的图像.但是,您可以定义在两个变换中投影到相同位置的平面(我们称其为聚焦平面).

With an orthographic projection, you can't get the same image as with a perspective projection, of course. However, you can define a plane (let's call it the focus plane) that is projected to the same location in both transformations.

您具有20 * sqrt (1 + a * a)的垂直视场(顺便说一句,我怀疑这是一个合理的计算;弯曲度应以度为单位).为了计算正交的边缘,我们需要半角.然后:

You have a vertical field of view of 20 * sqrt (1 + a * a) (btw, I doubt that this is a reasonable calculation; the fovy should be in degrees). In order to calculate the ortho's edges, we need the half angle. Then:

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.

You could set focus_plane to the middle between zNear and zFar, in this case to 10.

这篇关于将透视投影转换为正交投影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆