您的位置:首页 > 运维架构

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

2016-07-14 16:01 351 查看
上一次写了OpenGL的几何变换3之内观察全景图

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

先说下思路,数据分割化方式呢,是只读取一张图片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://pan.baidu.com/s/1dSVNP0 密码: 8anf
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: