上一次写了
上次采用的是图片分割化方式,这次采用数据分割化方式。
先说下思路,数据分割化方式呢,是只读取一张图片imgData,然后通过glTexCoord2f()配置纹理坐标和glVertex3f()配置图形坐标,然后该分隔的分隔,该组合的组合。
这次的代码使用的图片处理结果有些瑕疵,因为一张完整的全景图片是有角度拉伸的,且有些模糊化,将就着看吧
附上代码:
1 #include2 #include 3 #include 4 #include //引用相关包 5 #include 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)\n", 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)\n", 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)\n", 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)\n", 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)\n", 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)\n", 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)\n", 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 #else173 glBindTexture(GL_TEXTURE_2D, textureArr[0]); // 选择纹理,有多个纹理时这句话是必要de174 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 #endif196 }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("...\n");229 }230 231 void display(void)232 {233 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清楚颜色数据和深度数据(清屏)234 glLoadIdentity(); //Reset The View235 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\n", 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\n", 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("可通过↑↓←→按键控制全景图绕旋转\n");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 }
执行结果:
附上执行程序链接: 密码: 8anf