OpenGL: 放大镜功能

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


 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值