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)\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 #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("...\n");
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\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 }

執行結果:

附上執行程序鏈接: https://pan.baidu.com/s/1dSVNP0 密碼: 8anf


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM