OpenGL的几何变换2之内观察立方体
我想实现的一个场景是:一个立方体,相机的坐标在立方体的中心点,相机不变,立方体旋转,可以站在立方体中心点查看立方体内部。
实际上就是立方体图像,这是在全景图片当作比较简单的方式,画面不会变形和扭曲,但是现在拍摄的全景图不会这样拍摄,更多的可点击先搞清楚全景视频是如何实现的查看
其实就是当下炒得火热的VR视频,而现在呢简单一些,查看全景图片,VR和全景是有区别的,可以去了解下一张图看懂360°全景和VR的区别
我们接下来全景图片,关于相机坐标和事物坐标,貌似都指向了下面几个函数:
1、观察变换函数gluLookAt(),寻找观察点;
2、旋转变换glRotatef(),全方位旋转立方体;
3、平移变换函数gluTranslatef(),创建立方体使用;
4、最后还少不了投影变换函数gluPerspective()。
这是单纯的画立方体,而不是加载本地图片贴图,贴图是我最终目的,后期再跟上,先附上这次的代码:
1 #include <stdio.h> 2 #include <math.h> 3 #include <Windows.h> 4 #include "include\glut.h" 5 6 /* 7 功能描述:使用OpenGL简单画立方体,在内部透视查看立方体内部 8 */ 9 10 //输出模式,0-单缓存模式;非0双缓存模式 11 #define OUTPUT_MODE 1 12 13 //矩阵变换的坐标 14 float oldx = 0; 15 float oldy = 0; 16 17 //交叉点的坐标 18 int cx = 0; 19 int cy = 0; 20 21 int angle = 0; 22 23 void init(void) 24 { 25 const GLfloat LightAmbient[4] = {0.1, 0.1, 0.1, 1.0}; 26 const GLfloat LightDiffuse[4] = {0, 0.8, 0.8, 1.0}; 27 const GLfloat LightPosition[4]={0,0,1,0}; 28 29 //glClearColor函数设置好清除颜色,glClear利用glClearColor函数设置好的当前清除颜色设置窗口颜色 30 glClearColor(1.0, 1.0, 0.8, 1.0); 31 32 glShadeModel(GL_SMOOTH);//选择单位或平滑阴影 33 glEnable(GL_DEPTH_TEST); 34 } 35 36 #if (0) 37 void display(void) 38 { 39 //printf("oldx=%f, oldy=%f\n", oldx, oldy); 40 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 41 42 static float rotate = 0; 43 static int times = 0; 44 45 static float centerX = 0.0; 46 static float centerY = 0.0; 47 static float centerZ = 0.0; 48 static bool add = TRUE; 49 50 glMatrixMode(GL_MODELVIEW); 51 glLoadIdentity(); 52 glPushMatrix(); 53 { 54 gluLookAt(0, 0, -10.0f, centerX, centerY, centerZ, 0, 1, 0); 55 glTranslatef(0, 0, -10.0); //平移 56 glScalef(1, 1, 1); //缩放 57 58 glRotatef(angle, 1, 1, 1); 59 60 //将立方体的八个顶点保存到一个数组里面 61 static const float vertex_list[][3] = 62 { 63 //0 1 2 64 -1.0f, -1.0f, -1.0f,//0 65 1.0f, -1.0f, -1.0f, //1 66 -1.0f, 1.0f, -1.0f, //2 67 1.0f, 1.0f, -1.0f, //3 68 -1.0f, -1.0f, 1.0f, //4 69 1.0f, -1.0f, 1.0f, //5 70 -1.0f, 1.0f, 1.0f, //6 71 1.0f, 1.0f, 1.0f //7 72 }; 73 74 //将要使用的顶点的序号保存到一个数组里面 75 static const GLint index_list[][2] = 76 { 77 {0, 1}, 78 {2, 3}, 79 {4, 5}, 80 {6, 7}, 81 {0, 2}, 82 {1, 3}, 83 {4, 6}, 84 {5, 7}, 85 {0, 4}, 86 {1, 5}, 87 {7, 3}, 88 {2, 6} 89 }; 90 float rgb[] = {0.1, 0.3, 1.0}; 91 int i,j; 92 glBegin(GL_LINES); 93 { 94 for(i=0; i<12; ++i) //12条线段 95 { 96 for(j=0; j<2; ++j) //每条线段2个顶点 97 { 98 printf("index : %d, [%d][%d], vertex : %.1f, %.1f, %.1f\n", index_list[i][j], i, j, vertex_list[index_list[i][j]][0], vertex_list[index_list[i][j]][1], vertex_list[index_list[i][j]][2]); 99 glColor3f (rgb[0], rgb[1], rgb[2]); //画笔颜色 100 glVertex3fv(vertex_list[index_list[i][j]]); 101 102 rgb[0] += 0.2; 103 rgb[1] += 0.1; 104 rgb[2] -= 0.1; 105 } 106 } 107 } 108 glEnd(); 109 } 110 glPopMatrix(); 111 112 printf("centerX=%f, centerY=%f\n", centerX, centerY); 113 if (add) 114 { 115 centerX += 0.1; 116 centerY += 0.1; 117 centerZ += 0.1; 118 } else { 119 centerX -= 0.1; 120 centerY -= 0.1; 121 centerZ -= 0.1; 122 } 123 if (centerX > 10) 124 { 125 add = FALSE; 126 } else if (centerX < -10) { 127 add = TRUE; 128 } 129 angle += 1; 130 angle %= 360; 131 132 if (OUTPUT_MODE == 0) { 133 glFlush();//单缓存GLUT_SINGLE时使用 134 } else { 135 glutSwapBuffers();//因为使用的是双缓存GLUT_DOUBLE,所以这里必须要交换缓存才会显示 136 } 137 } 138 139 #else 140 void display(void) 141 { 142 //printf("oldx=%f, oldy=%f\n", oldx, oldy); 143 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 144 145 float rotatefs[][4] = { 146 {90.0, 1.0, 0.0, 0.0}, //top 147 {-90.0, 1.0, 0.0, 0.0}, //bottom 148 {90.0, 0.0, 0.0, 1.0}, //front 149 {-90.0, 0.0, 1.0, 0.0}, //left 150 {-90.0, 0.0, 0.0, 1.0}, //back 151 {90.0, 0.0, 1.0, 0.0}, //right 152 }; 153 154 float translefs[][3] = { 155 {0.0, 0.5, 0.0}, //top 156 {0.0, -0.5, 0.0},//bottom 157 {0.0, 0.0, -0.5},//front 158 {-0.5, 0.0, 0.0},//left 159 {0.0, 0.0, 0.5}, //back 160 {0.5, 0.0, 0.0} //right 161 }; 162 163 glPushMatrix(); { 164 glColor3f (0, 0, 0); 165 glLoadIdentity(); //加载单位矩阵 166 glTranslatef(0.0f,0.0f,-10.0f); 167 glRectf(-1.0f, -1.0f, -0.5f, -0.5f); 168 } 169 glPopMatrix(); 170 171 glMatrixMode(GL_MODELVIEW); 172 glLoadIdentity(); //加载单位矩阵 173 glPushMatrix(); { 174 glLoadIdentity(); //加载单位矩阵 175 static float centerX = 0.0; 176 static float centerY = 0.0; 177 static float centerZ = 0.0; 178 static bool add = TRUE; 179 gluLookAt(0, 0, -10.0f, centerX, centerY, centerZ, 0, 1, 0); 180 glTranslatef(0.0f,0.0f,-10.0f); 181 glRotatef(angle, 0, 1, 0); 182 glScalef(0.5, 0.5, 0.5); 183 float rgb[] = {0.1, 0.3, 1.0}; 184 for(int i = 0; i < 6; i++) { 185 glPushMatrix(); { 186 glTranslatef(translefs[i][0], translefs[i][1], translefs[i][2]); 187 glRotatef(rotatefs[i][0], rotatefs[i][1], rotatefs[i][2], rotatefs[i][3]); 188 //glScalef(-0.5, -0.5, -0.5); 189 glColor3f (rgb[0], rgb[1], rgb[2]); //画笔颜色 190 glRectf(-0.5f, -0.5f, 0.5f, 0.5f); 191 192 rgb[0] += 0.2; 193 rgb[1] += 0.1; 194 rgb[2] -= 0.1; 195 } 196 glPopMatrix(); 197 } 198 } 199 glPopMatrix(); 200 201 printf("centerX=%f, centerY=%f\n", centerX, centerY); 202 if (add) 203 { 204 centerX += 0.1; 205 centerY += 0.1; 206 centerZ += 0.1; 207 } else { 208 centerX -= 0.1; 209 centerY -= 0.1; 210 centerZ -= 0.1; 211 } 212 if (centerX > 10) 213 { 214 add = FALSE; 215 } else if (centerX < -10) { 216 add = TRUE; 217 } 218 //如果通过鼠标控制,可以把下面两行代码注视掉,留着也没关系 219 angle += 1; 220 angle %= 360; 221 222 if (OUTPUT_MODE == 0) { 223 glFlush();//单缓存GLUT_SINGLE时使用 224 } else { 225 glutSwapBuffers();//因为使用的是双缓存GLUT_DOUBLE,所以这里必须要交换缓存才会显示 226 } 227 } 228 229 #endif 230 231 //处理鼠标点击 232 void Mouse(int button, int state, int x, int y) 233 { 234 if(state == GLUT_DOWN) //第一次鼠标按下时,记录鼠标在窗口中的初始坐标 235 { 236 //记住鼠标点击后光标坐标 237 cx = x; 238 cy = y; 239 //printf("Mouse: x=%d, y=%d, oldx=%f, oldy=%f\n", x, y, oldx, oldy); 240 } 241 } 242 243 //处理鼠标拖动 244 void onMouseMove(int x, int y) 245 { 246 int offset = 5; 247 if (cx <= 200 && y < cy) {//左半边区:顺时针手势 248 angle -= offset; 249 printf("angle1=%d\n", angle); 250 } else if (cx > 200 && y > cy) {//右半边区:顺时针手势 251 angle -= offset; 252 printf("angle2=%d\n", angle); 253 } else if (cx <= 200 && y > cy) {//左半边区:逆时针手势 254 angle += offset; 255 printf("angle3=%d\n", angle); 256 } else if (cx > 200 && y < cy) {//右半边区:逆时针手势 257 angle += offset; 258 printf("angle4=%d\n", angle); 259 } 260 angle %= 360; 261 262 //计算拖动后的偏移量,然后进行xy叠加减 263 oldx += ((x - cx) * 0.01); 264 oldy -= ((y - cy) * 0.01); 265 //printf("Move: x=%d(%d)[%d], y=%d(%d)[%d], oldx=%f, oldy=%f\n", x, cx, x-cx, y, cy, y-cy, oldx, oldy); 266 glutPostRedisplay(); 267 268 //保存好当前拖放后光标坐标点 269 cx = x; 270 cy = y; 271 } 272 273 void reshape(int w, int h) 274 { 275 int offset = 10; 276 int dis = (w > h ? h : w) - offset * 2; 277 278 //配置显示物体屏幕的大小 279 glViewport(offset, offset, (GLsizei)dis, (GLsizei)dis); 280 printf("reshape: w=%d, h=%d, dis=%d\n", w, h, dis); 281 282 glMatrixMode(GL_PROJECTION); 283 glLoadIdentity(); 284 285 //glOrtho(-1.5, 1.5, -1.5, 1.5, 0, 100); 286 //gluOrtho2D(-1.5, 1.5, -1.5, 1.5); 287 gluPerspective(90.0f, (GLfloat)w/(GLfloat)h, 0.1f, 100.0f); 288 289 glMatrixMode(GL_MODELVIEW); 290 glLoadIdentity(); 291 } 292 293 int main(int argc, char *argv[]) 294 { 295 glutInit(&argc, argv); 296 297 glutInitDisplayMode(GLUT_RGB | (OUTPUT_MODE == 0 ? GLUT_SINGLE : GLUT_DOUBLE)); 298 glutInitWindowPosition(100, 100); 299 glutInitWindowSize(400, 400); 300 glutCreateWindow("第一个 OpenGL 程序"); 301 302 init(); 303 glutDisplayFunc(&display); 304 glutIdleFunc(display); //设置不断调用显示函数 305 glutReshapeFunc(reshape); 306 glutMouseFunc(Mouse); 307 glutMotionFunc(onMouseMove); 308 glutMainLoop(); 309 return 0; 310 }
没有录制,附上几张图
最后附上代码执行文件链接: https://pan.baidu.com/s/1hsS3vEk 密码: tmdg