要求:
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; }