OpenGL的几何变换4之内观察全景图
2016-07-14 16:01
351 查看
上一次写了OpenGL的几何变换3之内观察全景图
上次采用的是图片分割化方式,这次采用数据分割化方式。
先说下思路,数据分割化方式呢,是只读取一张图片imgData,然后通过glTexCoord2f()配置纹理坐标和[b]glVertex3f()[/b]配置图形坐标,然后该分隔的分隔,该组合的组合。
这次的代码使用的图片处理结果有些瑕疵,因为一张完整的全景图片是有角度拉伸的,且有些模糊化,将就着看吧
附上代码:
执行结果:
![](https://images2015.cnblogs.com/blog/549076/201607/549076-20160715192527357-1042075403.png)
![](https://images2015.cnblogs.com/blog/549076/201607/549076-20160715192537311-1000573433.png)
![](https://images2015.cnblogs.com/blog/549076/201607/549076-20160715192554123-377655439.png)
附上执行程序链接: https://pan.baidu.com/s/1dSVNP0 密码: 8anf
上次采用的是图片分割化方式,这次采用数据分割化方式。
先说下思路,数据分割化方式呢,是只读取一张图片imgData,然后通过glTexCoord2f()配置纹理坐标和[b]glVertex3f()[/b]配置图形坐标,然后该分隔的分隔,该组合的组合。
这次的代码使用的图片处理结果有些瑕疵,因为一张完整的全景图片是有角度拉伸的,且有些模糊化,将就着看吧
附上代码:
#include <stdio.h> #include <math.h> #include <windows.h> #include <gl/glut.h> //引用相关包 #include <gl/glaux.h> #define pi 3.141592654 GLfloat xangle = 0.0; //X 旋转量 GLfloat yangle = 0.0; //Y 旋转量 GLfloat zangle = 0.0; //Z 旋转量 GLuint textureArr[1]; //存储6个纹理 //交叉点的坐标 int cx = 0; int cy = 0; float vertex[61][31][3]; float texpoint[61][31][2]; //载入位图图象 AUX_RGBImageRec *loadBMP(CHAR *Filename) { FILE *File = NULL; //文件句柄 if (!Filename) //确保文件名已提供 { return NULL; //如果没提供,返回 NULL } File = fopen(Filename,"r"); //尝试打开文件 if (File) //文件存在么? { fclose(File); //关闭句柄 return auxDIBImageLoadA(Filename); //载入位图并返回指针 } return NULL; //如果载入失败,返回 NULL } //载入位图(调用上面的代码)并转换成纹理 int loadGLTexture2() { int Status = FALSE; //状态指示器 AUX_RGBImageRec *textureImage[1]; //创建纹理的存储空间 memset(textureArr, 0x0, sizeof(textureArr)); memset(textureImage,0,sizeof(textureImage)); //将指针设为NULL //载入位图,检查有无错误,如果位图没找到则退出 if (textureImage[0] = loadBMP("pano/pano_sphere.bmp")) { Status = TRUE; //将 Status 设为 TRUE glGenTextures(1, &textureArr[0]); //创建纹理 //使用来自位图数据生成 的典型纹理 glBindTexture(GL_TEXTURE_2D, textureArr[0]); //生成纹理 glTexImage2D(GL_TEXTURE_2D, 0, 3, textureImage[0]->sizeX, textureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImage[0]->data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //线形滤波 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //线形滤波 } if (textureImage[0]) //纹理是否存在 { if (textureImage[0]->data) //纹理图像是否存在 { free(textureImage[0]->data); //释放纹理图像占用的内存 } free(textureImage[0]); //释放图像结构 } return Status; //返回 Status } //从这里开始进行所有的绘制 void drawCube(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //重置当前的模型观察矩阵 glPushMatrix(); { gluLookAt(0, 0, -5, 0, 0, 0, 0, 1, 0); glTranslatef(0.0f, 0.0f, -5.0f); //移入屏幕 5 个单位 glRotatef(xangle, 1.0f, 0.0f, 0.0f); //绕X轴旋转 glRotatef(yangle, 0.0f, 1.0f, 0.0f); //绕Y轴旋转 glRotatef(zangle, 0.0f, 0.0f, 1.0f); //绕Z轴旋转 #if (0) glBindTexture(GL_TEXTURE_2D, textureArr[0]); //选择纹理 glBegin(GL_QUADS); { //前面:纹理顺时针,立方体逆时针 float fx = 1024.0/8.0; float fy = 512.0/4.0; float tx0 = fx*3.0/1024.0; float ty0 = fy*1.0/512.0; float tx1 = fx*5.0/1024.0; float ty1 = fy*3.0/512.0; //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)\n", fx*3.0, tx0, fy*1.0, ty0, fx*5.0, tx1, fy*3.0, ty1); glTexCoord2f(tx0, ty0); glVertex3f( 1.0f, -1.0f, 1.0f); //纹理和四边形的左下 glTexCoord2f(tx0, ty1); glVertex3f( 1.0f, 1.0f, 1.0f); //纹理和四边形的左上 glTexCoord2f(tx1, ty1); glVertex3f(-1.0f, 1.0f, 1.0f); //纹理和四边形的右上 glTexCoord2f(tx1, ty0); glVertex3f(-1.0f, -1.0f, 1.0f); //纹理和四边形的右下 //后面:纹理顺时针,立方体逆时针 tx0 = fx*0.0/1024.0; ty0 = fy*1.0/512.0; tx1 = fx*1.0/1024.0; ty1 = fy*3.0/512.0; //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)\n", fx*0.0, tx0, fy*1.0, ty0, fx*1.0, tx1, fy*3.0, ty1); glTexCoord2f(tx0, ty0); glVertex3f( 0.0f, -1.0f, -1.0f); //纹理和四边形的左下 glTexCoord2f(tx0, ty1); glVertex3f( 0.0f, 1.0f, -1.0f); //纹理和四边形的左上 glTexCoord2f(tx1, ty1); glVertex3f( 1.0f, 1.0f, -1.0f); //纹理和四边形的右上 glTexCoord2f(tx1, ty0); glVertex3f( 1.0f, -1.0f, -1.0f); //纹理和四边形的右下 tx0 = fx*7.0/1024.0; ty0 = fy*1.0/512.0; tx1 = fx*8.0/1024.0; ty1 = fy*3.0/512.0; //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)\n", fx*7.0, tx0, fy*1.0, ty0, fx*8.0, tx1, fy*3.0, ty1); glTexCoord2f(tx0, ty0); glVertex3f(-1.0f, -1.0f, -1.0f); //纹理和四边形的左下 glTexCoord2f(tx0, ty1); glVertex3f(-1.0f, 1.0f, -1.0f); //纹理和四边形的左上 glTexCoord2f(tx1, ty1); glVertex3f( 0.0f, 1.0f, -1.0f); //纹理和四边形的右上 glTexCoord2f(tx1, ty0); glVertex3f( 0.0f, -1.0f, -1.0f); //纹理和四边形的右下 //顶面:纹理顺时针,立方体逆时针 tx0 = fx*3.0/1024.0; ty0 = fy*3.0/512.0; tx1 = fx*5.0/1024.0; ty1 = fy*4.0/512.0; //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)\n", fx*3.0, tx0, fy*3.0, ty0, fx*5.0, tx1, fy*4.0, ty1); glTexCoord2f(tx0, ty0); glVertex3f( 1.0f, 1.0f, 1.0f); //纹理和四边形的左下 glTexCoord2f(tx0, ty1); glVertex3f( 1.0f, 1.0f, -1.0f); //纹理和四边形的左上 glTexCoord2f(tx1, ty1); glVertex3f(-1.0f, 1.0f, -1.0f); //纹理和四边形的右上 glTexCoord2f(tx1, ty0); glVertex3f(-1.0f, 1.0f, 1.0f); //纹理和四边形的右下 //底面:纹理顺时针,立方体逆时针 tx0 = fx*3.0/1024.0; ty0 = fy*0.0/512.0; tx1 = fx*5.0/1024.0; ty1 = fy*1.0/512.0; //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)\n", fx*3.0, tx0, fy*0.0, ty0, fx*5.0, tx1, fy*1.0, ty1); glTexCoord2f(tx0, ty0); glVertex3f( 1.0f, -1.0f, -1.0f); //纹理和四边形的左下 glTexCoord2f(tx0, ty1); glVertex3f( 1.0f, -1.0f, 1.0f); //纹理和四边形的左上 glTexCoord2f(tx1, ty1); glVertex3f(-1.0f, -1.0f, 1.0f); //纹理和四边形的右上 glTexCoord2f(tx1, ty0); glVertex3f(-1.0f, -1.0f, -1.0f); //纹理和四边形的右下 //左面:纹理顺时针,立方体逆时针 tx0 = fx*1.0/1024.0; ty0 = fy*1.0/512.0; tx1 = fx*3.0/1024.0; ty1 = fy*3.0/512.0; //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)\n", fx*1.0, tx0, fy*1.0, ty0, fx*3.0, tx1, fy*3.0, ty1); glTexCoord2f(tx0, ty0); glVertex3f( 1.0f, -1.0f, -1.0f); //纹理和四边形的左下 glTexCoord2f(tx0, ty1); glVertex3f( 1.0f, 1.0f, -1.0f); //纹理和四边形的左上 glTexCoord2f(tx1, ty1); glVertex3f( 1.0f, 1.0f, 1.0f); //纹理和四边形的右上 glTexCoord2f(tx1, ty0); glVertex3f( 1.0f, -1.0f, 1.0f); //纹理和四边形的右下 //右面:纹理顺时针,立方体逆时针 tx0 = fx*5.0/1024.0; ty0 = fy*1.0/512.0; tx1 = fx*7.0/1024.0; ty1 = fy*3.0/512.0; //printf("x0=%.f(%.3f), y0=%.f(%.3f), x1=%.f(%.3f), y1=%.f(%.3f)\n", fx*5.0, tx0, fy*1.0, ty0, fx*7.0, tx1, fy*3.0, ty1); glTexCoord2f(tx0, ty0); glVertex3f(-1.0f, -1.0f, 1.0f); //纹理和四边形的左下 glTexCoord2f(tx0, ty1); glVertex3f(-1.0f, 1.0f, 1.0f); //纹理和四边形的左上 glTexCoord2f(tx1, ty1); glVertex3f(-1.0f, 1.0f, -1.0f); //纹理和四边形的右上 glTexCoord2f(tx1, ty0); glVertex3f(-1.0f, -1.0f, -1.0f); //纹理和四边形的右下 }glEnd(); #else glBindTexture(GL_TEXTURE_2D, textureArr[0]); // 选择纹理,有多个纹理时这句话是必要de glBegin(GL_QUADS); { //四边形绘制开始 for(int i=0; i<60; i++) { for(int j=0; j<30; j++) { //第一个纹理坐标(左下角) glTexCoord2f(texpoint[i][j][0], texpoint[i][j][1]); glVertex3f(vertex[i][j][0], vertex[i][j][1], vertex[i][j][2]); //第二个纹理坐标(左上角) glTexCoord2f(texpoint[i][j][0], texpoint[i][j+1][1]); glVertex3f(vertex[i][j+1][0], vertex[i][j+1][1], vertex[i][j+1][2]); //第三个纹理坐标(右上角) glTexCoord2f(texpoint[i+1][j+1][0], texpoint[i+1][j+1][1]); glVertex3f(vertex[i+1][j+1][0], vertex[i+1][j+1][1], vertex[i+1][j+1][2]); //第四个纹理坐标(右下角) glTexCoord2f(texpoint[i+1][j][0], texpoint[i][j][1]); glVertex3f(vertex[i+1][j][0], vertex[i+1][j][1], vertex[i+1][j][2]); } } }glEnd(); #endif }glPopMatrix(); glFlush(); } //初始化 void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); //清理颜色,为黑色,(也可认为是背景颜色) glCullFace(GL_FRONT); //背面裁剪(背面不可见) glEnable(GL_CULL_FACE); //启用裁剪 glEnable(GL_TEXTURE_2D); loadGLTexture2(); //载入纹理贴图 //初始化数据 for(int i=0; i<=360; i+=6) { for( int j=180; j>=0; j-=6) { vertex[i/6][(180-j)/6][0] = cos((float)i/180.0*pi)*sin((float)j/180.0*pi)*2; vertex[i/6][(180-j)/6][1] = cos((float)j/180.0*pi)*2; vertex[i/6][(180-j)/6][2] = sin((float)i/180.0*pi)*sin((float)j/180.0*pi)*2; } } for(int i=0; i<61; i++) { for(int k=0; k<31; k++) { texpoint[i][k][0]= (float)i/60.0; //生成X浮点值 texpoint[i][k][1]= (float)k/30.0; //生成Y浮点值 } } printf("...\n"); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清楚颜色数据和深度数据(清屏) glLoadIdentity(); //Reset The View drawCube(); glutSwapBuffers(); //交换缓冲区。显示图形 //xangle += 0.3f; //yangle += 0.3f; //zangle += 0.3f; Sleep(10); } //当窗口大小改变时,会调用这个函数 void reshape(GLsizei w,GLsizei h) { glViewport(0,0,w,h); //设置视口 glMatrixMode(GL_PROJECTION); //设置矩阵模式为投影变换矩阵, glLoadIdentity(); //变为单位矩阵 gluPerspective(110, (GLfloat)w / h, 0.1f, 100.0f); //设置投影矩阵 glMatrixMode(GL_MODELVIEW); //设置矩阵模式为视图矩阵(模型) glLoadIdentity(); //变为单位矩阵 } //处理鼠标点击 void Mouse(int button, int state, int x, int y) { if(state == GLUT_DOWN) //第一次鼠标按下时,记录鼠标在窗口中的初始坐标 { //记住鼠标点击后光标坐标 cx = x; cy = y; //printf("Mouse: x=%d, y=%d, oldx_Translatef=%f, oldy_Translatef=%f\n", x, y, oldx_Translatef, oldy_Translatef); } } //处理鼠标拖动 void onMouseMove(int x, int y) { float offset = 0.18; //计算拖动后的偏移量,然后进行xy叠加减 yangle -= ((x - cx) * offset); if (xangle < 90 && y > cy) {//往下拉 xangle += ((y - cy) * offset); } else if (xangle > -90 && y < cy) {//往上拉 xangle += ((y - cy) * offset); } //printf("Move: x=%d(%d)[%d], y=%d(%d)[%d], xangle_Textures=%f, yangle_Textures=%f\n", // x, cx_Textures, x-cx_Textures, // y, cy_Textures, y-cy_Textures, // xangle_Textures, yangle_Textures); glutPostRedisplay(); //保存好当前拖放后光标坐标点 cx = x; cy = y; } //键盘输入事件函数 void keyboard(unsigned char key,int x,int y) { switch(key) { case 'x': //当按下键盘上d时,以沿X轴旋转为主 if (xangle < 85.0f) { xangle += 1.0f; //设置旋转增量 } break; case 'X': if (xangle > -85.0f) { xangle -= 1.0f; //设置旋转增量 } break; case 'y': yangle += 1.0f; break; case 'Y': yangle -= 1.0f; break; //case 'z': // zangle += 1.0f; // break; //case 'Z': // zangle -= 1.0f; // break; default: return; } glutPostRedisplay(); //重绘函数 } //特殊按键 void specialKey(int key, int x, int y) { float offset = 1.5; switch (key) { case GLUT_KEY_UP: //脑袋向上往前看 if (xangle < 90.0f) { xangle += offset; //设置旋转增量 } break; case GLUT_KEY_DOWN: //脑袋向下往前看 if (xangle > -90.0f) { xangle -= offset; //设置旋转增量 } break; case GLUT_KEY_LEFT: //脑袋想左往前看 yangle -= offset; break; case GLUT_KEY_RIGHT: //脑袋向右往前看 yangle += offset; break; default: break; } glutPostRedisplay(); } int main(int argc, char *argv[]) { printf("可通过↑↓←→按键控制全景图绕旋转\n"); glutInit(&argc, argv); //固定格式 glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowSize(512, 512); //显示框的大小 glutInitWindowPosition(100,100); //确定显示框左上角的位置 glutCreateWindow("OpenGL纹理贴图"); init(); //初始化资源,这里一定要在创建窗口以后,不然会无效。 glutDisplayFunc(display); //glutIdleFunc(display); glutReshapeFunc(reshape); //绘制图形时的回调 glutMouseFunc(Mouse); glutMotionFunc(onMouseMove); glutKeyboardFunc(keyboard); glutSpecialFunc(specialKey); // 特殊按键 glutMainLoop(); return 0; }
执行结果:
![](https://images2015.cnblogs.com/blog/549076/201607/549076-20160715192527357-1042075403.png)
![](https://images2015.cnblogs.com/blog/549076/201607/549076-20160715192537311-1000573433.png)
![](https://images2015.cnblogs.com/blog/549076/201607/549076-20160715192554123-377655439.png)
附上执行程序链接: https://pan.baidu.com/s/1dSVNP0 密码: 8anf
相关文章推荐
- linux自学之路·LVM卷
- 【智能路由器】openwrt添加服务项
- 在一台电脑上运行两个tomcat
- Linux中查看CPU信息【转】
- centos python 安装 readability
- linux多线程服务器编程 muduo库学习笔记二
- 让apache解析后缀为.aspx和.asp的文件
- 【牛客网】copy-list-with-random-pointer题解
- Hadoop+Hive部署安装配置
- opengl 学习资料
- Linux运维工程师入门须掌握的10个技术点
- Tomcat内存设置详解
- VMwareVsphere在克隆部署Linux虚拟机后网卡的相关操作
- 运行基准测试hadoop集群中的问题:org.apache.hadoop.ipc.RemoteException: java.io.IOException: File /benchmarks/TestDFSIO/io_data/test_
- 马哥linux 教程---vim编辑器进阶课后题
- cronolog分割tomcat的catalina.out日志
- LiLinux系统下如何修改主机名
- Mac上Apache部署本地PHP工程虚拟地址
- linux 配置多个tomcat(本文配置了两个)
- 结合Android使用的Linux命令