前言

这是从零开始openGL系列文章的第二篇,在上篇文章中介绍了基本的环境配置,这篇文章将介绍如何绘制基本图形(圆、三角形、立方体、圆柱、圆锥)。

基本框架

下面这里我先给出opengl的3D绘图的基本框架

  1. #include <windows.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <gl\glui.h>
  5. #include <math.h>
  6. #include "common.h"
  7.  
  8. int g_xform_mode = TRANSFORM_NONE;
  9. int g_main_window;
  10. double g_windows_width, g_windows_height;
  11.  
  12. CObj g_obj;
  13. //the lighting
  14. static GLfloat g_light0_ambient[] = {0.0f, 0.0f, 0.0f, 1.0f};//环境光
  15. static GLfloat g_light0_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};//散射光
  16. static GLfloat g_light0_specular[] = {1.0f,1.0f,1.0f,1.0f}; //镜面光
  17. static GLfloat g_light0_position[] = {0.0f, 0.0f, 100.0f, 0.0f};//光源的位置。第4个参数为1,表示点光源;第4个参数量为0,表示平行光束{0.0f, 0.0f, 10.0f, 0.0f}
  18.  
  19. static GLfloat g_material[] = {0.96f, 0.8f, 0.69f, 1.0f};//材质
  20. static GLfloat g_rquad = ;
  21. static GLfloat g_rquad_x = ;
  22. static GLfloat g_rquad_y = ;
  23.  
  24. static float g_x_offset = 0.0;
  25. static float g_y_offset = 0.0;
  26. static float g_z_offset = 0.0;
  27. static float g_scale_size = ;
  28. static int g_press_x; //鼠标按下时的x坐标
  29. static int g_press_y; //鼠标按下时的y坐标
  30.  
  31. const int n = ;
  32. const GLfloat R = 0.5f;
  33. const GLfloat Pi = 3.1415926536f;
  34. int g_view_type = VIEW_FLAT;
  35. int g_draw_content = SHAPE_TRIANGLE;
  36.  
  37. void DrawTriangle()
  38. {//绘制三角形
  39. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  40.  
  41. glBegin(GL_TRIANGLES);
  42. glNormal3f(0.0f, 0.0f, 1.0f); //指定面法向
  43. glVertex3f( 0.0f, 1.0f, 0.0f); // 上顶点
  44. glVertex3f(-1.0f,-1.0f, 0.0f); // 左下
  45. glVertex3f( 1.0f,-1.0f, 0.0f); // 右下
  46. glEnd();
  47. glFlush();
  48. }
  49.  
  50. void DrawCube()
  51. {//绘制立方体
  52. glBegin(GL_QUADS);
  53. glNormal3f( 0.0f, 0.0f, 1.0f); //指定面法向
  54. glVertex3f( 1.0f, 1.0f,1.0f); //列举面顶点数据,逆时针顺序
  55. glVertex3f(-1.0f, 1.0f, 1.0f);
  56. glVertex3f(-1.0f,-1.0f, 1.0f);
  57. glVertex3f( 1.0f,-1.0f, 1.0f);
  58. //前----------------------------
  59. glNormal3f( 0.0f, 0.0f,-1.0f);
  60. glVertex3f(-1.0f,-1.0f,-1.0f);
  61. glVertex3f(-1.0f, 1.0f,-1.0f);
  62. glVertex3f( 1.0f, 1.0f,-1.0f);
  63. glVertex3f( 1.0f,-1.0f,-1.0f);
  64. //后----------------------------
  65. glNormal3f( 0.0f, 1.0f, 0.0f);
  66. glVertex3f( 1.0f, 1.0f, 1.0f);
  67. glVertex3f( 1.0f, 1.0f,-1.0f);
  68. glVertex3f(-1.0f, 1.0f,-1.0f);
  69. glVertex3f(-1.0f, 1.0f, 1.0f);
  70. //上----------------------------
  71. glNormal3f( 0.0f,-1.0f, 0.0f);
  72. glVertex3f(-1.0f,-1.0f,-1.0f);
  73. glVertex3f( 1.0f,-1.0f,-1.0f);
  74. glVertex3f( 1.0f,-1.0f, 1.0f);
  75. glVertex3f(-1.0f,-1.0f, 1.0f);
  76. //下----------------------------
  77. glNormal3f( 1.0f, 0.0f, 0.0f);
  78. glVertex3f( 1.0f, 1.0f, 1.0f);
  79. glVertex3f( 1.0f,-1.0f, 1.0f);
  80. glVertex3f( 1.0f,-1.0f,-1.0f);
  81. glVertex3f( 1.0f, 1.0f,-1.0f);
  82. //右----------------------------
  83. glNormal3f(-1.0f, 0.0f, 0.0f);
  84. glVertex3f(-1.0f,-1.0f,-1.0f);
  85. glVertex3f(-1.0f,-1.0f, 1.0f);
  86. glVertex3f(-1.0f, 1.0f, 1.0f);
  87. glVertex3f(-1.0f, 1.0f,-1.0f);
  88. //左----------------------------*/
  89. glEnd();
  90. glFlush();
  91. }
  92.  
  93. void DrawCircle()
  94. {//绘制圆
  95. glBegin(GL_POLYGON);
  96. glNormal3f(0.0f, 0.0f, 1.0f);
  97. for (int i = ; i < n; ++i) {
  98. glVertex2f(R*cos( * Pi / n * i), R*sin( * Pi / n * i));
  99. }
  100. glEnd();
  101. }
  102.  
  103. void DrawCylinder()
  104. {//绘制圆柱
  105.  
  106. }
  107.  
  108. void DrawTorus()
  109. {
  110.  
  111. }void myInit()
  112. {
  113. glClearColor(1.0f, 1.0f, 1.0f, 1.0f);//用白色清屏
  114.  
  115. glLightfv(GL_LIGHT0, GL_AMBIENT, g_light0_ambient);//设置场景的环境光
  116. glLightfv(GL_LIGHT0, GL_DIFFUSE, g_light0_diffuse);//设置场景的散射光
  117. glLightfv(GL_LIGHT0, GL_POSITION, g_light0_position);//设置场景的位置
  118.  
  119. glMaterialfv(GL_FRONT, GL_DIFFUSE, g_material);//指定用于光照计算的当前材质属性
  120. glEnable(GL_TEXTURE_2D);
  121. glEnable(GL_LIGHTING);//开启灯光
  122. glEnable(GL_LIGHT0);//开启光照0
  123.  
  124. glShadeModel(GL_SMOOTH); //设置着色模式为光滑着色
  125. glEnable(GL_DEPTH_TEST);//启用深度测试
  126.  
  127. glMatrixMode(GL_MODELVIEW); //指定当前矩阵为模型视景矩阵
  128. glLoadIdentity(); //将当前的用户坐标系的原点移到了屏幕中心:类似于一个复位操作
  129. gluLookAt(0.0, 0.0, 8.0, , , , , 1.0, );//该函数定义一个视图矩阵,并与当前矩阵相乘.
  130. //第一组eyex, eyey,eyez 相机在世界坐标的位置;第二组centerx,centery,centerz 相机镜头对准的物体在世界坐标的位置;第三组upx,upy,upz 相机向上的方向在世界坐标中的方向
  131. }void myGlutDisplay() //绘图函数, 操作系统在必要时刻就会对窗体进行重新绘制操作
  132. {
  133. glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); //清除颜色缓冲以及深度缓冲
  134. glEnable(GL_NORMALIZE); //打开法线向量归一化,确保了法线的长度为1
  135.  
  136. glMatrixMode(GL_MODELVIEW);//模型视图矩阵
  137. glPushMatrix(); //压入当前矩阵堆栈
  138.  
  139. if (g_draw_content == SHAPE_MODEL)
  140. {//绘制模型
  141.  
  142. }
  143. else if (g_draw_content == SHAPE_TRIANGLE) //画三角形
  144. {
  145. glLoadIdentity();
  146. glTranslatef(0.0f, 0.0f, -6.0f);
  147. DrawTriangle();
  148. }
  149. else if(g_draw_content == SHAPE_CUBE) //画立方体
  150. {
  151. glLoadIdentity();
  152. glTranslatef(0.0f, 0.0f, -6.0f);
  153. glRotatef(g_rquad, g_rquad, g_rquad, 1.0f); // 在XYZ轴上旋转立方体
  154. DrawCube();
  155. g_rquad+=0.2f;// 增加旋转变量
  156. }
  157. else if (g_draw_content == SHAPE_CIRCLE) // 画圆
  158. {
  159. glLoadIdentity();
  160. glTranslatef(0.0f, 0.0f, -6.0f);
  161. DrawCircle();
  162. }
  163. else if (g_draw_content == SHAPE_CYLINDER)
  164. {//TODO: 添加画圆柱的代码
  165.  
  166. }
  167. else if (g_draw_content == SHAPE_TORUS)
  168. {//TODO:添加画圆环的代码
  169.  
  170. }
  171. glPopMatrix();
  172. glutSwapBuffers(); //双缓冲
  173. }
  174.  
  175. void myGlutReshape(int x,int y) //当改变窗口大小时的回调函数
  176. {
  177. if (y == )
  178. {
  179. y = ;
  180. }
  181.  
  182. g_windows_width = x;
  183. g_windows_height = y;
  184. double xy_aspect = (float)x / (float)y;
  185. GLUI_Master.auto_set_viewport(); //自动设置视口大小
  186.  
  187. glMatrixMode( GL_PROJECTION );//当前矩阵为投影矩阵
  188. glLoadIdentity();
  189. gluPerspective(60.0, xy_aspect, 0.01, 1000.0);//视景体
  190.  
  191. glutPostRedisplay(); //标记当前窗口需要重新绘制
  192. }
  193.  
  194. void myGlutKeyboard(unsigned char Key, int x, int y)
  195. {//键盘时间回调函数
  196.  
  197. }
  198.  
  199. void myGlutMouse(int button, int state, int x, int y)
  200. {
  201. if (state == GLUT_DOWN) //鼠标的状态为按下
  202. {
  203. g_press_x = x;
  204. g_press_y = y;
  205. if (button == GLUT_LEFT_BUTTON)
  206. {//按下鼠标的左键表示对模型进行旋转操作
  207. g_xform_mode = TRANSFORM_ROTATE;
  208. }
  209. else if (button == GLUT_RIGHT_BUTTON)
  210. {//按下鼠标的右键表示对模型进行平移操作
  211. g_xform_mode = TRANSFORM_TRANSLATE;
  212. }
  213. else if (button == GLUT_MIDDLE_BUTTON)
  214. {//按下鼠标的滑轮表示按下鼠标的右键表示对模型进行缩放操作
  215. g_xform_mode = TRANSFORM_SCALE;
  216. }
  217. }
  218. else if (state == GLUT_UP)
  219. {//如果没有按鼠标,则不对模型进行任何操作
  220. g_xform_mode = TRANSFORM_NONE;
  221. }
  222. }
  223.  
  224. void myGlutMotion(int x, int y) //处理当鼠标键摁下时,鼠标拖动的事件
  225. {
  226. if (g_xform_mode == TRANSFORM_ROTATE) //旋转
  227. {//TODO:添加鼠标移动控制模型旋转参数的代码
  228.  
  229. }
  230. else if(g_xform_mode == TRANSFORM_SCALE) //缩放
  231. {//TODO:添加鼠标移动控制模型缩放参数的代码
  232.  
  233. }
  234. else if(g_xform_mode == TRANSFORM_TRANSLATE) //平移
  235. {//TODO:添加鼠标移动控制模型平移参数的代码
  236.  
  237. }
  238.  
  239. // force the redraw function
  240. glutPostRedisplay();
  241. }
  242.  
  243. void myGlutIdle(void) //空闲回调函数
  244. {
  245. if ( glutGetWindow() != g_main_window )
  246. glutSetWindow(g_main_window);
  247.  
  248. glutPostRedisplay();
  249. }
  250.  
  251. void glui_control(int control ) //处理控件的返回值
  252. {
  253. switch(control)
  254. {
  255. case CRTL_LOAD://选择“open”控件
  256. loadObjFile();
  257. g_draw_content = SHAPE_MODEL;
  258. break;
  259. case CRTL_CHANGE://选择Type面板
  260. if (g_view_type == VIEW_POINT)
  261. {
  262. glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); // 设置两面均为顶点绘制方式
  263. }
  264. else if (g_view_type == VIEW_WIRE)
  265. {
  266. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // 设置两面均为线段绘制方式
  267. }
  268. else
  269. {
  270. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // 设置两面为填充方式
  271. }
  272. break;
  273. case CRTL_TRIANGLE:
  274. g_draw_content = SHAPE_TRIANGLE;
  275. break;
  276. case CRTL_CUBE:
  277. g_draw_content = SHAPE_CUBE;
  278. break;
  279. case CRTL_CIRCLE:
  280. g_draw_content = SHAPE_CIRCLE;
  281. break;
  282. case CRTL_CYLINDER:
  283. g_draw_content = SHAPE_CYLINDER;
  284. break;
  285. case CRTL_CONE:
  286. g_draw_content = SHAPE_TORUS;
  287. break;
  288. case CRTL_MODEL:
  289. g_draw_content = SHAPE_MODEL;
  290. break;
  291. default:
  292. break;
  293. }
  294. }
  295.  
  296. void myGlui()
  297. {
  298. GLUI_Master.set_glutDisplayFunc( myGlutDisplay ); //注册渲染事件回调函数, 系统在需要对窗体进行重新绘制操作时调用
  299. GLUI_Master.set_glutReshapeFunc( myGlutReshape ); //注册窗口大小改变事件回调函数
  300. GLUI_Master.set_glutKeyboardFunc( myGlutKeyboard );//注册键盘输入事件回调函数
  301. glutMotionFunc( myGlutMotion);//注册鼠标移动事件回调函数
  302. GLUI_Master.set_glutMouseFunc( myGlutMouse );//注册鼠标点击事件回调函数
  303. GLUI_Master.set_glutIdleFunc(myGlutIdle); //为GLUI注册一个标准的GLUT空闲回调函数,当系统处于空闲时,就会调用该注册的函数
  304.  
  305. //GLUI
  306. GLUI *glui = GLUI_Master.create_glui_subwindow( g_main_window, GLUI_SUBWINDOW_RIGHT); //新建子窗体,位于主窗体的右部
  307. new GLUI_StaticText(glui, "GLUI" ); //在GLUI下新建一个静态文本框,输出内容为“GLUI”
  308. new GLUI_Separator(glui); //新建分隔符
  309. new GLUI_Button(glui,"Open", CRTL_LOAD, glui_control); //新建按钮控件,参数分别为:所属窗体、名字、ID、回调函数,当按钮被触发时,它会被调用.
  310. new GLUI_Button(glui, "Quit", ,(GLUI_Update_CB)exit );//新建退出按钮,当按钮被触发时,退出程序
  311.  
  312. GLUI_Panel *type_panel = glui->add_panel("Type" ); //在子窗体glui中新建面板,名字为“Type”
  313. GLUI_RadioGroup *radio = glui->add_radiogroup_to_panel(type_panel, &g_view_type, CRTL_CHANGE, glui_control); //在Type面板中添加一组单选按钮
  314. glui->add_radiobutton_to_group(radio, "points");
  315. glui->add_radiobutton_to_group(radio, "wire");
  316. glui->add_radiobutton_to_group(radio, "flat");
  317.  
  318. GLUI_Panel *draw_panel = glui->add_panel("Draw" ); //在子窗体glui中新建面板,名字为“Draw”
  319. new GLUI_Button(draw_panel,"Triangle",CRTL_TRIANGLE,glui_control);
  320. new GLUI_Button(draw_panel,"Cube",CRTL_CUBE,glui_control);
  321. new GLUI_Button(draw_panel,"Circle",CRTL_CIRCLE,glui_control);
  322. new GLUI_Button(draw_panel,"Cylinder",CRTL_CYLINDER,glui_control);
  323. new GLUI_Button(draw_panel,"Torus",CRTL_CONE,glui_control);
  324. new GLUI_Button(draw_panel,"Model",CRTL_MODEL,glui_control);
  325.  
  326. glui->set_main_gfx_window(g_main_window ); //将子窗体glui与主窗体main_window绑定,当窗体glui中的控件的值发生过改变,则该glui窗口被重绘
  327. GLUI_Master.set_glutIdleFunc( myGlutIdle );
  328. }
  329.  
  330. int main(int argc, char* argv[]) //程序入口
  331. {
  332. /****************************************/
  333. /* Initialize GLUT and create window */
  334. /****************************************/
  335.  
  336. freopen("log.txt", "w", stdout);//重定位,将输出放入log.txt文件中
  337. glutInit(&argc, argv);//初始化glut
  338. glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);//初始化渲染模式
  339. glutInitWindowPosition(, ); //初始化窗口位置
  340. glutInitWindowSize(, ); //初始化窗口大小
  341.  
  342. g_main_window = glutCreateWindow("Model Viewer"); //创建主窗体Model Viewer
  343.  
  344. myGlui();
  345. myInit();
  346.  
  347. glutMainLoop();//进入glut消息循环
  348.  
  349. return EXIT_SUCCESS;
  350. }
  1. #ifndef COMMON
  2. #define COMMON
  3.  
  4. #define VIEW_POINT 0x00
  5. #define VIEW_WIRE 0x01
  6. #define VIEW_FLAT 0x02
  7.  
  8. #define CRTL_LOAD 0x00
  9. #define CRTL_CHANGE 0x01
  10. #define CRTL_TRIANGLE 0x02
  11. #define CRTL_CUBE 0x03
  12. #define CRTL_CIRCLE 0x04
  13. #define CRTL_CYLINDER 0x05
  14. #define CRTL_CONE 0x06
  15. #define CRTL_MODEL 0x07
  16.  
  17. #define SHAPE_TRIANGLE 0x00
  18. #define SHAPE_CUBE 0x01
  19. #define SHAPE_CIRCLE 0x02
  20. #define SHAPE_CYLINDER 0x03
  21. #define SHAPE_TORUS 0x04
  22. #define SHAPE_MODEL 0x05
  23.  
  24. #define TRANSFORM_NONE 0x51
  25. #define TRANSFORM_ROTATE 0x52
  26. #define TRANSFORM_SCALE 0x53
  27. #define TRANSFORM_TRANSLATE 0x54
  28.  
  29. #endif

common.h

运行这段代码可以得到如下所示的结果

图形绘制

在上面那段代码中,已经给出了三角形、圆、正方体的绘制代码,下面还将介绍圆柱与圆环的绘制

在opengl中并不能直接绘制圆,那么,此时想到了极限的方法,如果把圆分割成很多个扇形,这个扇形的角度足够小的话,那么曲线自然可以看作直线。有了这个思路,代码就很好写了。

  1. void DrawCircle()
  2. {//绘制圆
  3. glBegin(GL_POLYGON);
  4. glNormal3f(0.0f, 0.0f, 1.0f);
  5. for (int i = ; i < n; ++i) {
  6. glVertex2f(R*cos( * Pi / n * i), R*sin( * Pi / n * i));
  7. }
  8. glEnd();
  9. }

三角形

三角形的绘制就十分的简单了,确定三个顶点,然后连线

  1. void DrawTriangle()
  2. {//绘制三角形
  3. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  4. glBegin(GL_TRIANGLES);
  5. glNormal3f(0.0f, 0.0f, 1.0f); //指定面法向
  6. glVertex3f( 0.0f, 1.0f, 0.0f); // 上顶点
  7. glVertex3f(-1.0f,-1.0f, 0.0f); // 左下
  8. glVertex3f( 1.0f,-1.0f, 0.0f); // 右下
  9. glEnd();
  10. glFlush();
  11. }

立方体

原理同三角形,确定八个顶点坐标,然后连线,不过这里要注意的是立方体为3D图形,要展示光照效果的话需要在绘制的时候确定各个面的法向量。

  1. void DrawCube()
  2. {//绘制立方体
  3. glBegin(GL_QUADS);
  4. glNormal3f( 0.0f, 0.0f, 1.0f); //指定面法向
  5. glVertex3f( 1.0f, 1.0f,1.0f); //列举面顶点数据,逆时针顺序
  6. glVertex3f(-1.0f, 1.0f, 1.0f);
  7. glVertex3f(-1.0f,-1.0f, 1.0f);
  8. glVertex3f( 1.0f,-1.0f, 1.0f);
  9. //前----------------------------
  10. glNormal3f( 0.0f, 0.0f,-1.0f);
  11. glVertex3f(-1.0f,-1.0f,-1.0f);
  12. glVertex3f(-1.0f, 1.0f,-1.0f);
  13. glVertex3f( 1.0f, 1.0f,-1.0f);
  14. glVertex3f( 1.0f,-1.0f,-1.0f);
  15. //后----------------------------
  16. glNormal3f( 0.0f, 1.0f, 0.0f);
  17. glVertex3f( 1.0f, 1.0f, 1.0f);
  18. glVertex3f( 1.0f, 1.0f,-1.0f);
  19. glVertex3f(-1.0f, 1.0f,-1.0f);
  20. glVertex3f(-1.0f, 1.0f, 1.0f);
  21. //上----------------------------
  22. glNormal3f( 0.0f,-1.0f, 0.0f);
  23. glVertex3f(-1.0f,-1.0f,-1.0f);
  24. glVertex3f( 1.0f,-1.0f,-1.0f);
  25. glVertex3f( 1.0f,-1.0f, 1.0f);
  26. glVertex3f(-1.0f,-1.0f, 1.0f);
  27. //下----------------------------
  28. glNormal3f( 1.0f, 0.0f, 0.0f);
  29. glVertex3f( 1.0f, 1.0f, 1.0f);
  30. glVertex3f( 1.0f,-1.0f, 1.0f);
  31. glVertex3f( 1.0f,-1.0f,-1.0f);
  32. glVertex3f( 1.0f, 1.0f,-1.0f);
  33. //右----------------------------
  34. glNormal3f(-1.0f, 0.0f, 0.0f);
  35. glVertex3f(-1.0f,-1.0f,-1.0f);
  36. glVertex3f(-1.0f,-1.0f, 1.0f);
  37. glVertex3f(-1.0f, 1.0f, 1.0f);
  38. glVertex3f(-1.0f, 1.0f,-1.0f);
  39. //左----------------------------*/
  40. glEnd();
  41. glFlush();
  42. }

圆柱

对于圆柱的绘制,思想同圆十分相似,就是分割。不过需要注意的是上下两个圆面和一个侧面需要分开来绘制。这里需要思考的是这个侧面该如何绘制呢?想象以下,把圆柱侧面展开,我们得到的是一个矩形,那分割成小片段的话也就是矩形了,即绘制无数个矩形,然后拼接形成侧面。

注:绘制时注意法向量的选取

  1. void DrawCylinder()
  2. {//绘制圆柱
  3. //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  4. glBegin(GL_POLYGON);
  5. glNormal3f(0.0f, 1.0f, 0.0f);
  6. for (int i = ; i < n; i++) {
  7. glVertex3f(R*cos( * Pi / n * i), 1.0f, R*sin( * Pi / n * i));
  8. }
  9. glEnd();
  10. glBegin(GL_POLYGON);
  11. glNormal3f(0.0f, -1.0f, 0.0f);
  12. for (int i = ; i < n; i++) {
  13. glVertex3f(R*cos( * Pi / n * i), 0.0f, R*sin( * Pi / n * i));
  14. }
  15. glEnd();
  16. glBegin(GL_QUADS);
  17. for (int i = ; i <= n; i++)
  18. {
  19. glNormal3f(R*cos( * Pi / n * i), 0.0f, R*sin( * Pi / n * i));
  20. glVertex3f(R*cos( * Pi / n * i), 1.0f, R*sin( * Pi / n * i));
  21. glVertex3f(R*cos( * Pi / n * i), 0.0f, R*sin( * Pi / n * i));
  22. glNormal3f(R*cos( * Pi / n * (i + )), 0.0f, R*sin( * Pi / n * (i + )));
  23. glVertex3f(R*cos( * Pi / n * (i + )), 0.0f, R*sin( * Pi / n * (i + )));
  24. glVertex3f(R*cos( * Pi / n * (i + )), 1.0f, R*sin( * Pi / n * (i + )));
  25. }
  26. glEnd();
  27. }

圆环

圆环的绘制稍微有些麻烦,先来看看下面这个圆环的线图

这里的难点就是各点的坐标表示,首先我们需要做的是把圆环压缩成一个圆面

压缩之后的表示为 R+r*cos(θ),然后再把压缩完后的点映射到x y轴上

X轴:(R+r*cos(θ))*cosα

Y轴:(R+r*cos(θ))*sinα

Z轴:r*sin(θ)

这样,我们的圆环就可以实现了

  1. void DrawTorus()
  2. {
  3. int num = n / ;
  4. for (int i = ; i < num; i++)
  5. {
  6. glBegin(GL_QUAD_STRIP);
  7. for (int j = ; j <= num; j++)
  8. {
  9. for (int k = ; k >= ; k--)
  10. {
  11. double s = (i + k) % num + 0.5;
  12. double t = j % num;
  13. glNormal3f(cos( * Pi / num * s) * cos( * Pi / num * t), cos( * Pi / num * s)*sin( * Pi / num * t), sin( * Pi / num * s));
  14. glVertex3f(( + R*cos( * Pi / num * s))*cos( * Pi / num * t), ( + R*cos( * Pi / num * s))*sin( * Pi / num * t), R*sin( * Pi / num * s));
  15. }
  16. }
  17. glEnd();
  18. }
  19. }

小节

以上介绍了如何使用opengl绘制基本图形,下篇文章中将介绍如何使用opengl加载绘制模型,以及鼠标交互的实现。

从零开始openGL—— 二、 基本图形绘制的更多相关文章

  1. VS2008集成QT的OpenGL开发(实现二维图形的旋转)

    主要是利用Qt中的定时器实现了二维图形的旋转功能: #ifndef QGLTEST_H #define QGLTEST_H #include <QGLWidget> #include &l ...

  2. matlab绘制二维图形

    常用的二维图形命令: plot:绘制二维图形 loglog:用全对数坐标绘图 semilogx:用半对数坐标(X)绘图 semilogy:用半对数坐标(Y)绘图 fill:绘制二维多边填充图形 pol ...

  3. [github项目]基于百度地图二次开发实现的车辆监管(包含车辆定位、车辆图片和方向控制,电子围栏,图形绘制等功能)前端实现(不包含后端实现)

    前言:基于百度地图javascript版本开发,百度地图中所用的key已承诺仅用于测试,不用于商业用途 注:本文所有代码可以到github上进行下载,github地址:http://map.eguid ...

  4. SVG.js 基础图形绘制整理(二)

    一.折线 var draw = SVG('svg1').size(300, 300); //画折线 //使用字符串点 // var polyline=draw.polyline('0,0 100,50 ...

  5. Android OpenGL ES 开发:绘制图形

    OpenGL 绘制图形步骤 上一篇介绍了 OpenGL 的相关概念,今天来实际操作,使用 OpenGL 绘制出图形,对其过程有一个初步的了解. OpenGL 绘制图形主要概括成以下几个步骤: 创建程序 ...

  6. QT 二维图形 原理、发展及应用

    转载自 网易博客:sun的博客 http://zhouyang340.blog.163.com/blog/static/3024095920126710504178/ 2D绘图 Qt4中的2D绘图部分 ...

  7. (转)GPU图形绘制管线

    摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人”第二章. 图形绘制管线描述GPU渲染流程, ...

  8. 13个JavaScript图表(JS图表)图形绘制插件【转】

    现在网络上又有越来越多的免费的(JS 图表)JavaScript图表图形绘制插件.我之前给一家网站做过复杂的图形,我们用的是 highchart.在那段时间,没有很多可供选择的插件.但现在不同了,很容 ...

  9. 13个JavaScript图表(JS图表)图形绘制插件

    转自:http://blog.jobbole.com/13671/ 1. Flash 过去是最佳解决方案,但很多人多在从那迁移: 2. 现代浏览器及其更强大的计算能力,使其在转化绘制实时数据方面的能力 ...

随机推荐

  1. [2018-01-08] Python强化周的第一天

    Python强化周的第一天 学生管理系统-制作(成绩类)模块 class Score: lesson_name = "python" # 课程名 score = 0 # 分数 # ...

  2. python设置环境变量(临时和永久)

    设置临时环境变量 import os # 设置环境变量 os.environ['WORKON_HOME']="value" # 获取环境变量方法1 os.environ.get(' ...

  3. 网络安全-主动信息收集篇第二章-二层网络扫描之scapy

    scapy是python第三方库文件,可以使用python进行调用也单独进行使用. 非常强大可以用于抓包.分析.创建.修改.注入网络流量. 使用scapy 详细使用方式可以查看github:https ...

  4. [ASP.NET Core 3框架揭秘] 依赖注入[5]: 利用容器提供服务

    毫不夸张地说,整个ASP.NET Core框架是建立在依赖注入框架之上的.ASP.NET Core应用在启动时构建管道以及利用该管道处理每个请求过程中使用到的服务对象均来源于依赖注入容器.该依赖注入容 ...

  5. hadoop2.6集群环境搭建

    版权声明:本文为博主原创文章,未经博主允许不得转载. 一.环境说明 1.机器:一台物理机 和一台虚拟机 2.Linux版本:[Spark@S1PA11 ~]$ cat /etc/issueRed Ha ...

  6. %%%GXZ大佬回关

  7. 磁盘冗余阵列之RAID5的配置

    1988年由加利福尼亚大学伯克利分校发表的文章首次提到并定义了RAID,当今CPU性能每年可提升30%-50%但硬盘仅提升7%,渐渐的已经成为计算机整体性能的瓶颈,并且为了避免硬盘的突然损坏导致数据丢 ...

  8. sublime3中运行python文件

    sublime3中运行python文件 tools->build system->new build stystem 粘贴下面代码{"cmd":["pytho ...

  9. python面向对象<三>

    类属性.实例属性: class Tool(object): #属性(类属性)类对象(Tool) num = 0 #方法 def __init__(self,new_name): self.name = ...

  10. PHP 中四大经典排序算法

    1.冒泡排序 在要排序的一组数中,对当前还未排好的序列,从前往后对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒.即,每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换. ...