要求:
1.在练习5的基础上,实现放大镜功能,放大场景中的任意部分;
2.放大镜可以通过鼠标键盘进行控制;
考察目的:
1.对OpenGL坐标系变换的理解;
我的思路就是,获取屏幕坐标,转换成opengl 坐标。移动glulookat到相应的位置,然后拉近摄像头距离,实现放大
不过,不能是正交投影,正交投影下,照相机远近不能影响大小。
特别坑爹,感觉肯定有其他方法实现。
屏幕坐标的转换,参考http://nehe.gamedev.net/article/using_gluunproject/16013/
pos就是转换后的结果
void GLPOS(int x,int y,GLdouble pos[3])
{
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX,winY,winZ;
glGetDoublev(GL_MODELVIEW_MATRIX,modelview);
glGetDoublev(GL_PROJECTION_MATRIX,projection);
glGetIntegerv(GL_VIEWPORT,viewport);
winX = (float)x;
winY = viewport[3]-(float)y;
glReadPixels((int)x,(int)y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&winZ);
gluUnProject(winX,winY,winZ,modelview,projection,viewport,&pos[0],&pos[1],&pos[2]);
}
本来是想画一个 小的十字 去跟踪鼠标。
结果,透视投影下面,用上面坐标转换的方法,跟踪鼠标,因为是视景体是梯形,所以效果不好
正交投影下,十字可以跟着鼠标走,但是又没办法放大了。
全部代码如下:
#include <windows.h>
#include <GL/glut.h>
#include <GL/glext.h>
#include <GL/SOIL.h>
#include <cstdio>
/* 正方体旋转*/
GLfloat xrot1 = 0.0f;
GLfloat yrot1 = 0.0f;
GLfloat xrot2 = 0.0f;
GLfloat yrot2 = 0.0f;
GLfloat xrot3 = 0.0f;
GLfloat yrot3 = 0.0f;
GLfloat xrot4 = 0.0f;
GLfloat yrot4 = 0.0f;
/*旋转速度*/
GLfloat xspeed = 5.0f;
GLfloat yspeed = 5.0f;
/*放大相关*/
GLdouble eyex = 0.0f;
GLdouble eyey = 0.0f;
GLdouble centerx = 0.0f;
GLdouble centery = 0.0f;
GLdouble eyez = 15.0f;//放大镜值
/*焦点*/
GLfloat focusx = 0.0f;
GLfloat focusy = 0.0f;
GLfloat focusz = 15.0f;
GLuint texture[1];
int loadGLTextures()
{
for(int i=0; i<3; i++)
{
texture[i] = SOIL_load_OGL_texture
(
"F://LI//opengl-test//practice_big//Crate.bmp",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_INVERT_Y
);
}
if(texture[0] == 0)
{
printf("load error");
return 0;
}
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
return true;
}
void init ()
{
loadGLTextures();
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0,0.0,0.0,0.0);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
}
void reshape(int w,int h)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0,(GLfloat)w/(GLfloat)h,0.1,100.0);
// glOrtho(-10.0f,10.0f,-10.0f*(GLfloat)h/(GLfloat)w,10.0f*(GLfloat)h/(GLfloat)w,0.1,100.0);
glMatrixMode(GL_MODELVIEW);
}
void drawQuads(GLfloat xrot,GLfloat yrot)
{
glTranslatef(0.0f,0.0f,0.0f);
glRotatef(xrot1,1.0f,0.0f,0.0f);
glRotatef(yrot1,0.0f,1.0f,0.0f);
glBindTexture(GL_TEXTURE_2D,texture[0]);
glBegin(GL_QUADS);
// 前侧面
glNormal3f( 0.0f, 0.0f, 1.0f); // 法线指向观察者
glTexCoord2f(0.0f, 0.0f);glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);glVertex3f(-1.0f, 1.0f, 1.0f);
// 后侧面
glNormal3f( 0.0f, 0.0f,-1.0f); // 法线背向观察者
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
// 顶面
glNormal3f( 0.0f, 1.0f, 0.0f); // 法线向上
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
// 底面
glNormal3f( 0.0f,-1.0f, 0.0f); // 法线朝下
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
// 右侧面
glNormal3f( 1.0f, 0.0f, 0.0f); // 法线朝右
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
// 左侧面
glNormal3f(-1.0f, 0.0f, 0.0f); // 法线朝左
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
}
void drawFocus()
{
GLfloat a = 1.0f;
glColor3f(1.0f,1.0f,1.0f);
glLineWidth(1.0f);
glBegin(GL_LINES);
glVertex3f(-1.0f/a,1.0f/a,0.0f);
glVertex3f(-1.0f/a,3.0f/a,0.0f);
glEnd();
glBegin(GL_LINES);
glVertex3f(-1.0f/a,1.0f/a,0.0f);
glVertex3f(-3.0f/a,1.0f/a,0.0f);
glEnd();
glBegin(GL_LINES);
glVertex3f(1.0f/a,1.0f/a,0.0f);
glVertex3f(1.0f/a,3.0f/a,0.0f);
glEnd();
glBegin(GL_LINES);
glVertex3f(1.0f/a,1.0f/a,0.0f);
glVertex3f(3.0f/a,1.0f/a,0.0f);
glEnd();
glBegin(GL_LINES);
glVertex3f(-1.0f/a,-1.0f/a,0.0f);
glVertex3f(-1.0f/a,-3.0f/a,0.0f);
glEnd();
glBegin(GL_LINES);
glVertex3f(-1.0f/a,-1.0f/a,0.0f);
glVertex3f(-3.0f/a,-1.0f/a,0.0f);
glEnd();
glBegin(GL_LINES);
glVertex3f(1.0f/a,-1.0f/a,0.0f);
glVertex3f(1.0f/a,-3.0f/a,0.0f);
glEnd();
glBegin(GL_LINES);
glVertex3f(1.0f/a,-1.0f/a,0.0f);
glVertex3f(3.0f/a,-1.0f/a,0.0f);
glEnd();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
/*glPushMatrix();
glDisable(GL_TEXTURE_2D);
glTranslatef(focusx,focusy,focusz);
drawFocus();
glEnable(GL_TEXTURE_2D);
glPopMatrix();*/
gluLookAt(eyex,eyey,eyez,centerx,centery,-1.0f,0.0f,1.0f,0.0f);
/*glPushMatrix();
glPointSize(5.0f);
glBegin(GL_POINTS);
glVertex3f(9.0f,0.0f,0.0f);
glEnd();
glPopMatrix();*/
glPushMatrix();
glTranslatef(-3.5f,2.5f,0.0f);
drawQuads(xrot1,yrot1);
glPopMatrix();
glPushMatrix();
glTranslatef(3.5f,2.5f,0.0f);
drawQuads(xrot2,yrot2);
glPopMatrix();
glPushMatrix();
glTranslatef(-3.5f,-2.5f,0.0f);
drawQuads(xrot3,yrot3);
glPopMatrix();
glPushMatrix();
glTranslatef(3.5f,-2.5f,0.0f);
drawQuads(xrot4,yrot4);
glPopMatrix();
glFlush();
}
void GLPOS(int x,int y,GLdouble pos[3])
{
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX,winY,winZ;
glGetDoublev(GL_MODELVIEW_MATRIX,modelview);
glGetDoublev(GL_PROJECTION_MATRIX,projection);
glGetIntegerv(GL_VIEWPORT,viewport);
winX = (float)x;
winY = viewport[3]-(float)y;
glReadPixels((int)x,(int)y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&winZ);
gluUnProject(winX,winY,winZ,modelview,projection,viewport,&pos[0],&pos[1],&pos[2]);
}
void mouse(int button,int state,int x,int y)
{
switch(button)
{
case GLUT_LEFT_BUTTON:
if(state == GLUT_DOWN)
{
printf("%d,%d\n",x,y);
GLdouble *pos = new GLdouble[3];
GLPOS(x,y,pos);
printf("%f,%f,%f\n",pos[0],pos[1],pos[2]);
eyex = pos[0];
eyey = pos[1];
centerx = pos[0];
centery = pos[1];
glutPostRedisplay();
}
break;
case GLUT_RIGHT_BUTTON:
if(state == GLUT_DOWN)
{
eyex = 0.0f;
eyey = 0.0f;
centerx = 0.0f;
centery = 0.0f;
glutPostRedisplay();
}
break;
}
}
void mouse_move(int x,int y)
{
GLdouble *pos = new GLdouble[3];
GLPOS(x,y,pos);
printf("%f,%f,%f\n",pos[0],pos[1],pos[2]);
focusx = (GLfloat)pos[0];
focusy = (GLfloat)pos[1];
focusz = (GLfloat)pos[2];
delete [] pos;
glutPostRedisplay();
}
void keyboard(unsigned char key,int x,int y)
{
switch(key)
{
case 'u':
eyez-=0.5f;
break;
case 'd':
eyez+=0.5f;
break;
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
int main(int argc,char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(900,600);
glutInitWindowPosition(400,100);
glutCreateWindow("hello world");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
//glutPassiveMotionFunc(mouse_move);
glutMainLoop();
return 0;
}