• OpenGL的几何变换4之内观察全景图


    上一次写了OpenGL的几何变换3之内观察全景图

    上次采用的是图片分割化方式,这次采用数据分割化方式

    先说下思路,数据分割化方式呢,是只读取一张图片imgData,然后通过glTexCoord2f()配置纹理坐标和glVertex3f()配置图形坐标,然后该分隔的分隔,该组合的组合。

    这次的代码使用的图片处理结果有些瑕疵,因为一张完整的全景图片是有角度拉伸的,且有些模糊化,将就着看吧

    附上代码:

      1 #include <stdio.h>
      2 #include <math.h>
      3 #include <windows.h>
      4 #include <gl/glut.h>    //引用相关包
      5 #include <gl/glaux.h>
      6 
      7 #define  pi 3.141592654
      8 
      9 GLfloat  xangle = 0.0;    //X 旋转量
     10 GLfloat  yangle = 0.0;    //Y 旋转量
     11 GLfloat  zangle = 0.0;    //Z 旋转量
     12 GLuint  textureArr[1];    //存储6个纹理
     13 
     14 //交叉点的坐标
     15 int cx = 0;
     16 int cy = 0;
     17 
     18 float vertex[61][31][3];
     19 float texpoint[61][31][2];
     20 
     21 //载入位图图象
     22 AUX_RGBImageRec *loadBMP(CHAR *Filename)
     23 {
     24     FILE *File = NULL;    //文件句柄
     25     if (!Filename)    //确保文件名已提供
     26     {
     27         return NULL;    //如果没提供,返回 NULL
     28     }
     29 
     30     File = fopen(Filename,"r");    //尝试打开文件
     31     if (File)    //文件存在么?
     32     {
     33         fclose(File);    //关闭句柄
     34         return auxDIBImageLoadA(Filename);    //载入位图并返回指针
     35     }
     36     return NULL;    //如果载入失败,返回 NULL
     37 }
     38 
     39 //载入位图(调用上面的代码)并转换成纹理
     40 int loadGLTexture2()
     41 {
     42     int Status = FALSE;    //状态指示器
     43     AUX_RGBImageRec *textureImage[1];    //创建纹理的存储空间
     44 
     45     memset(textureArr, 0x0, sizeof(textureArr));
     46     memset(textureImage,0,sizeof(textureImage));    //将指针设为NULL
     47 
     48     //载入位图,检查有无错误,如果位图没找到则退出
     49     if (textureImage[0] = loadBMP("pano/pano_sphere.bmp"))
     50     {
     51         Status = TRUE;    //将 Status 设为 TRUE
     52         glGenTextures(1, &textureArr[0]);    //创建纹理
     53 
     54         //使用来自位图数据生成 的典型纹理
     55         glBindTexture(GL_TEXTURE_2D, textureArr[0]);
     56         //生成纹理
     57         glTexImage2D(GL_TEXTURE_2D, 0, 3, textureImage[0]->sizeX, textureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImage[0]->data);
     58 
     59         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    //线形滤波
     60         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);    //线形滤波
     61     }
     62 
     63     if (textureImage[0])    //纹理是否存在
     64     {
     65         if (textureImage[0]->data)    //纹理图像是否存在
     66         {
     67             free(textureImage[0]->data);    //释放纹理图像占用的内存
     68         }
     69         free(textureImage[0]);    //释放图像结构
     70     }
     71     
     72     return Status;    //返回 Status
     73 }
     74 
     75 //从这里开始进行所有的绘制
     76 void drawCube(void)
     77 {
     78     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    //清除屏幕和深度缓存
     79     glMatrixMode(GL_MODELVIEW);
     80     glLoadIdentity();    //重置当前的模型观察矩阵
     81 
     82     glPushMatrix();
     83     {
     84         gluLookAt(0, 0, -5, 0, 0, 0, 0, 1, 0);
     85         glTranslatef(0.0f, 0.0f, -5.0f);    //移入屏幕 5 个单位
     86         glRotatef(xangle, 1.0f, 0.0f, 0.0f);    //绕X轴旋转
     87         glRotatef(yangle, 0.0f, 1.0f, 0.0f);    //绕Y轴旋转
     88         glRotatef(zangle, 0.0f, 0.0f, 1.0f);    //绕Z轴旋转
     89 
     90 #if (0)
     91         glBindTexture(GL_TEXTURE_2D, textureArr[0]);    //选择纹理
     92         glBegin(GL_QUADS); {
     93             //前面:纹理顺时针,立方体逆时针
     94             float fx = 1024.0/8.0;
     95             float fy = 512.0/4.0;
     96 
     97             float tx0 = fx*3.0/1024.0;
     98             float ty0 = fy*1.0/512.0;
     99             float tx1 = fx*5.0/1024.0;
    100             float ty1 = fy*3.0/512.0;
    101             //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)
    ", fx*3.0, tx0, fy*1.0, ty0, fx*5.0, tx1, fy*3.0, ty1);
    102             glTexCoord2f(tx0, ty0); glVertex3f( 1.0f, -1.0f,  1.0f);    //纹理和四边形的左下
    103             glTexCoord2f(tx0, ty1); glVertex3f( 1.0f,  1.0f,  1.0f);    //纹理和四边形的左上
    104             glTexCoord2f(tx1, ty1); glVertex3f(-1.0f,  1.0f,  1.0f);    //纹理和四边形的右上
    105             glTexCoord2f(tx1, ty0); glVertex3f(-1.0f, -1.0f,  1.0f);    //纹理和四边形的右下
    106 
    107             //后面:纹理顺时针,立方体逆时针
    108             tx0 = fx*0.0/1024.0;
    109             ty0 = fy*1.0/512.0;
    110             tx1 = fx*1.0/1024.0;
    111             ty1 = fy*3.0/512.0;
    112             //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)
    ", fx*0.0, tx0, fy*1.0, ty0, fx*1.0, tx1, fy*3.0, ty1);
    113             glTexCoord2f(tx0, ty0); glVertex3f( 0.0f, -1.0f, -1.0f);    //纹理和四边形的左下
    114             glTexCoord2f(tx0, ty1); glVertex3f( 0.0f,  1.0f, -1.0f);    //纹理和四边形的左上
    115             glTexCoord2f(tx1, ty1); glVertex3f( 1.0f,  1.0f, -1.0f);    //纹理和四边形的右上
    116             glTexCoord2f(tx1, ty0); glVertex3f( 1.0f, -1.0f, -1.0f);    //纹理和四边形的右下
    117 
    118             tx0 = fx*7.0/1024.0;
    119             ty0 = fy*1.0/512.0;
    120             tx1 = fx*8.0/1024.0;
    121             ty1 = fy*3.0/512.0;
    122             //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)
    ", fx*7.0, tx0, fy*1.0, ty0, fx*8.0, tx1, fy*3.0, ty1);
    123             glTexCoord2f(tx0, ty0); glVertex3f(-1.0f, -1.0f, -1.0f);    //纹理和四边形的左下
    124             glTexCoord2f(tx0, ty1); glVertex3f(-1.0f,  1.0f, -1.0f);    //纹理和四边形的左上
    125             glTexCoord2f(tx1, ty1); glVertex3f( 0.0f,  1.0f, -1.0f);    //纹理和四边形的右上
    126             glTexCoord2f(tx1, ty0); glVertex3f( 0.0f, -1.0f, -1.0f);    //纹理和四边形的右下
    127 
    128             //顶面:纹理顺时针,立方体逆时针
    129             tx0 = fx*3.0/1024.0;
    130             ty0 = fy*3.0/512.0;
    131             tx1 = fx*5.0/1024.0;
    132             ty1 = fy*4.0/512.0;
    133             //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)
    ", fx*3.0, tx0, fy*3.0, ty0, fx*5.0, tx1, fy*4.0, ty1);
    134             glTexCoord2f(tx0, ty0); glVertex3f( 1.0f,  1.0f,  1.0f);    //纹理和四边形的左下
    135             glTexCoord2f(tx0, ty1); glVertex3f( 1.0f,  1.0f, -1.0f);    //纹理和四边形的左上
    136             glTexCoord2f(tx1, ty1); glVertex3f(-1.0f,  1.0f, -1.0f);    //纹理和四边形的右上
    137             glTexCoord2f(tx1, ty0); glVertex3f(-1.0f,  1.0f,  1.0f);    //纹理和四边形的右下
    138 
    139             //底面:纹理顺时针,立方体逆时针
    140             tx0 = fx*3.0/1024.0;
    141             ty0 = fy*0.0/512.0;
    142             tx1 = fx*5.0/1024.0;
    143             ty1 = fy*1.0/512.0;
    144             //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)
    ", fx*3.0, tx0, fy*0.0, ty0, fx*5.0, tx1, fy*1.0, ty1);
    145             glTexCoord2f(tx0, ty0); glVertex3f( 1.0f, -1.0f, -1.0f);    //纹理和四边形的左下
    146             glTexCoord2f(tx0, ty1); glVertex3f( 1.0f, -1.0f,  1.0f);    //纹理和四边形的左上
    147             glTexCoord2f(tx1, ty1); glVertex3f(-1.0f, -1.0f,  1.0f);    //纹理和四边形的右上
    148             glTexCoord2f(tx1, ty0); glVertex3f(-1.0f, -1.0f, -1.0f);    //纹理和四边形的右下
    149 
    150             //左面:纹理顺时针,立方体逆时针
    151             tx0 = fx*1.0/1024.0;
    152             ty0 = fy*1.0/512.0;
    153             tx1 = fx*3.0/1024.0;
    154             ty1 = fy*3.0/512.0;
    155             //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)
    ", fx*1.0, tx0, fy*1.0, ty0, fx*3.0, tx1, fy*3.0, ty1);
    156             glTexCoord2f(tx0, ty0); glVertex3f( 1.0f, -1.0f, -1.0f);    //纹理和四边形的左下
    157             glTexCoord2f(tx0, ty1); glVertex3f( 1.0f,  1.0f, -1.0f);    //纹理和四边形的左上
    158             glTexCoord2f(tx1, ty1); glVertex3f( 1.0f,  1.0f,  1.0f);    //纹理和四边形的右上
    159             glTexCoord2f(tx1, ty0); glVertex3f( 1.0f, -1.0f,  1.0f);    //纹理和四边形的右下
    160 
    161             //右面:纹理顺时针,立方体逆时针
    162             tx0 = fx*5.0/1024.0;
    163             ty0 = fy*1.0/512.0;
    164             tx1 = fx*7.0/1024.0;
    165             ty1 = fy*3.0/512.0;
    166             //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)
    ", fx*5.0, tx0, fy*1.0, ty0, fx*7.0, tx1, fy*3.0, ty1);
    167             glTexCoord2f(tx0, ty0); glVertex3f(-1.0f, -1.0f,  1.0f);    //纹理和四边形的左下
    168             glTexCoord2f(tx0, ty1); glVertex3f(-1.0f,  1.0f,  1.0f);    //纹理和四边形的左上
    169             glTexCoord2f(tx1, ty1); glVertex3f(-1.0f,  1.0f, -1.0f);    //纹理和四边形的右上
    170             glTexCoord2f(tx1, ty0); glVertex3f(-1.0f, -1.0f, -1.0f);    //纹理和四边形的右下
    171         }glEnd();
    172 #else
    173         glBindTexture(GL_TEXTURE_2D, textureArr[0]);                // 选择纹理,有多个纹理时这句话是必要de
    174         glBegin(GL_QUADS); {    //四边形绘制开始
    175             for(int i=0; i<60; i++) {
    176                 for(int j=0; j<30; j++) {
    177                     //第一个纹理坐标(左下角)
    178                     glTexCoord2f(texpoint[i][j][0], texpoint[i][j][1]);
    179                     glVertex3f(vertex[i][j][0], vertex[i][j][1], vertex[i][j][2]);
    180                     
    181                     //第二个纹理坐标(左上角)
    182                     glTexCoord2f(texpoint[i][j][0], texpoint[i][j+1][1]);
    183                     glVertex3f(vertex[i][j+1][0], vertex[i][j+1][1], vertex[i][j+1][2]);
    184                     
    185                     //第三个纹理坐标(右上角)
    186                     glTexCoord2f(texpoint[i+1][j+1][0], texpoint[i+1][j+1][1]);
    187                     glVertex3f(vertex[i+1][j+1][0], vertex[i+1][j+1][1], vertex[i+1][j+1][2]);
    188                     
    189                     //第四个纹理坐标(右下角)
    190                     glTexCoord2f(texpoint[i+1][j][0], texpoint[i][j][1]);
    191                     glVertex3f(vertex[i+1][j][0], vertex[i+1][j][1], vertex[i+1][j][2]);
    192                 }
    193             }
    194         }glEnd();
    195 #endif
    196     }glPopMatrix();
    197     glFlush();
    198 }
    199 
    200 //初始化
    201 void init(void)
    202 {
    203     glClearColor (0.0, 0.0, 0.0, 0.0);    //清理颜色,为黑色,(也可认为是背景颜色)
    204 
    205     glCullFace(GL_FRONT);    //背面裁剪(背面不可见)
    206     glEnable(GL_CULL_FACE);    //启用裁剪
    207     glEnable(GL_TEXTURE_2D);
    208     loadGLTexture2();    //载入纹理贴图
    209 
    210     //初始化数据
    211     for(int i=0; i<=360; i+=6)
    212     {
    213         for( int j=180; j>=0; j-=6)
    214         {
    215             vertex[i/6][(180-j)/6][0] = cos((float)i/180.0*pi)*sin((float)j/180.0*pi)*2;
    216             vertex[i/6][(180-j)/6][1] = cos((float)j/180.0*pi)*2;
    217             vertex[i/6][(180-j)/6][2] = sin((float)i/180.0*pi)*sin((float)j/180.0*pi)*2;
    218         }
    219     }
    220     for(int i=0; i<61; i++)
    221     {
    222         for(int k=0; k<31; k++)
    223         {
    224             texpoint[i][k][0]= (float)i/60.0;        //生成X浮点值
    225             texpoint[i][k][1]= (float)k/30.0;        //生成Y浮点值
    226         }
    227     }
    228     printf("...
    ");
    229 }
    230 
    231 void display(void)
    232 {
    233     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    //清楚颜色数据和深度数据(清屏)
    234     glLoadIdentity();    //Reset The View
    235 
    236     drawCube();
    237 
    238     glutSwapBuffers();    //交换缓冲区。显示图形
    239     
    240     //xangle += 0.3f;
    241     //yangle += 0.3f;
    242     //zangle += 0.3f;
    243     Sleep(10);
    244 }
    245 
    246 //当窗口大小改变时,会调用这个函数
    247 void reshape(GLsizei w,GLsizei h)
    248 {    
    249     glViewport(0,0,w,h);    //设置视口
    250     glMatrixMode(GL_PROJECTION);    //设置矩阵模式为投影变换矩阵,
    251     glLoadIdentity();    //变为单位矩阵
    252     gluPerspective(110, (GLfloat)w / h, 0.1f, 100.0f);    //设置投影矩阵
    253     glMatrixMode(GL_MODELVIEW);    //设置矩阵模式为视图矩阵(模型)
    254     glLoadIdentity();    //变为单位矩阵
    255 }
    256 
    257 //处理鼠标点击
    258 void Mouse(int button, int state, int x, int y)
    259 {
    260     if(state == GLUT_DOWN) //第一次鼠标按下时,记录鼠标在窗口中的初始坐标
    261     {
    262         //记住鼠标点击后光标坐标
    263         cx = x;
    264         cy = y;
    265         //printf("Mouse: x=%d, y=%d, oldx_Translatef=%f, oldy_Translatef=%f
    ", x, y, oldx_Translatef, oldy_Translatef);
    266     }
    267 }
    268 
    269 //处理鼠标拖动
    270 void onMouseMove(int x, int y)
    271 {
    272     float offset = 0.18;
    273     //计算拖动后的偏移量,然后进行xy叠加减
    274     yangle -= ((x - cx) * offset);
    275 
    276     if (xangle < 90 && y > cy) {//往下拉
    277         xangle += ((y - cy) * offset);
    278     } else if (xangle > -90 && y < cy) {//往上拉
    279         xangle += ((y - cy) * offset);
    280     }
    281     //printf("Move: x=%d(%d)[%d], y=%d(%d)[%d], xangle_Textures=%f, yangle_Textures=%f
    ", 
    282     //    x, cx_Textures, x-cx_Textures, 
    283     //    y, cy_Textures, y-cy_Textures, 
    284     //    xangle_Textures, yangle_Textures);
    285     glutPostRedisplay();
    286 
    287     //保存好当前拖放后光标坐标点
    288     cx = x;
    289     cy = y;
    290 }
    291 
    292 //键盘输入事件函数
    293 void keyboard(unsigned char key,int x,int y)
    294 {
    295     switch(key)
    296     {
    297         case 'x':        //当按下键盘上d时,以沿X轴旋转为主
    298             if (xangle < 85.0f)
    299             {
    300                 xangle += 1.0f;    //设置旋转增量
    301             }
    302             break;
    303         case 'X':
    304             if (xangle > -85.0f)
    305             {
    306                 xangle -= 1.0f;    //设置旋转增量
    307             }
    308             break;
    309         case 'y':
    310             yangle += 1.0f;
    311             break;
    312         case 'Y':
    313             yangle -= 1.0f;
    314             break;
    315         //case 'z':
    316         //    zangle += 1.0f;
    317         //    break;
    318         //case 'Z':
    319         //    zangle -= 1.0f;
    320         //    break;
    321         default:
    322             return;
    323     }
    324     glutPostRedisplay();    //重绘函数
    325 }
    326 
    327 //特殊按键
    328 void specialKey(int key, int x, int y)
    329 {
    330     float offset = 1.5;
    331     switch (key)
    332     {
    333     case GLUT_KEY_UP:    //脑袋向上往前看
    334         if (xangle < 90.0f)
    335         {
    336             xangle += offset;    //设置旋转增量
    337         }
    338         break;
    339     case GLUT_KEY_DOWN:    //脑袋向下往前看
    340         if (xangle > -90.0f)
    341         {
    342             xangle -= offset;    //设置旋转增量
    343         }
    344         break;
    345     case GLUT_KEY_LEFT:    //脑袋想左往前看
    346         yangle -= offset;
    347         break;
    348     case GLUT_KEY_RIGHT:    //脑袋向右往前看
    349         yangle += offset;
    350         break;
    351     default:
    352         break;
    353     }
    354     glutPostRedisplay();
    355 }
    356 
    357 int main(int argc, char *argv[])
    358 {
    359     printf("可通过↑↓←→按键控制全景图绕旋转
    ");
    360 
    361     glutInit(&argc, argv);    //固定格式
    362     glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); 
    363     glutInitWindowSize(512, 512);    //显示框的大小
    364     glutInitWindowPosition(100,100);    //确定显示框左上角的位置
    365     glutCreateWindow("OpenGL纹理贴图");
    366 
    367     init();    //初始化资源,这里一定要在创建窗口以后,不然会无效。
    368     glutDisplayFunc(display);
    369     //glutIdleFunc(display);
    370     glutReshapeFunc(reshape);    //绘制图形时的回调
    371     glutMouseFunc(Mouse);
    372     glutMotionFunc(onMouseMove);
    373     glutKeyboardFunc(keyboard);
    374     glutSpecialFunc(specialKey); // 特殊按键
    375     glutMainLoop();
    376     return 0;
    377 }

    执行结果:

    附上执行程序链接: https://pan.baidu.com/s/1dSVNP0 密码: 8anf

  • 相关阅读:
    Qbxt 模拟题 day2(am) T2 jian
    Codevs 1017 乘积最大 2000年NOIP全国联赛普及组NOIP全国联赛提高组
    洛谷比赛 U5442 买(最长链)
    洛谷 P1800 software_NOI导刊2010提高(06)(二分答案+DP检验)
    Codevs 4373 窗口(线段树 单调队列 st表)
    P1453 城市环路
    P1841 [JSOI2007]重要的城市
    P1410 子序列
    H
    GSS4 D
  • 原文地址:https://www.cnblogs.com/1024Planet/p/5670737.html
Copyright © 2020-2023  润新知