我创建了这个程序,用户单击右键单击鼠标,然后获得一个菜单,他可以选择在透视投影中绘制立方体或球体
我希望他能够将透视投影改为正交投影。我希望只需使用正交投影就可以将形状放置在同一个位置。
我希望他能够点击" 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;
}
答案 0 :(得分:4)
当然,使用正交投影,您无法获得与透视投影相同的图像。但是,您可以定义投影到两个转换中相同位置的平面(让我们称之为焦平面)。
你有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
设置为zNear
和zFar
之间的中间位置,在本例中为10
。