MyOpenGLView.cpp
上传用户:cpy_520
上传日期:2022-06-11
资源大小:7828k
文件大小:13k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // MyOpenGLView.cpp : implementation of the CMyOpenGLView class
  2. //
  3. #include "stdafx.h"
  4. #include "MyOpenGL.h"
  5. #include "MyOpenGLDoc.h"
  6. #include "MyOpenGLView.h"
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CMyOpenGLView
  14. IMPLEMENT_DYNCREATE(CMyOpenGLView, CView)
  15. BEGIN_MESSAGE_MAP(CMyOpenGLView, CView)
  16. //{{AFX_MSG_MAP(CMyOpenGLView)
  17. ON_WM_CREATE()
  18. ON_WM_DESTROY()
  19. ON_WM_SIZE()
  20. //}}AFX_MSG_MAP
  21. END_MESSAGE_MAP()
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CMyOpenGLView construction/destruction
  24. CMyOpenGLView::CMyOpenGLView()
  25. {
  26. // TODO: add construction code here
  27. }
  28. CMyOpenGLView::~CMyOpenGLView()
  29. {
  30. }
  31. BOOL CMyOpenGLView::PreCreateWindow(CREATESTRUCT& cs)
  32. {
  33. // TODO: Modify the Window class or styles here by modifying
  34. //  the CREATESTRUCT cs
  35. cs.style |= WS_CLIPSIBLINGS|WS_CLIPCHILDREN; // 设置窗口风格,使支持OpenGL
  36. return CView::PreCreateWindow(cs);
  37. }
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CMyOpenGLView drawing
  40. void CMyOpenGLView::OnDraw(CDC* pDC)
  41. {
  42. CMyOpenGLDoc* pDoc = GetDocument();
  43. ASSERT_VALID(pDoc);
  44. // TODO: add draw code for native data here
  45. ///////////////////////////////////////////////////////////////////////
  46. //获得视区的宽与高,用于设置OpenGL的视口
  47. CRect rcClient;
  48. GetClientRect(&rcClient);
  49. GLsizei w = rcClient.Width(); //视区宽度
  50. GLsizei h = rcClient.Height(); //视区高度
  51. ///////////////////////////////////////////////////////////////////////
  52. //初始化各种设置
  53. wglMakeCurrent(pDC->m_hDC,m_hGLRC); //将绘图上下文绑定到设备上下文上
  54. glClearColor(0.5,0.5,0.5,0.0); //设置背景色
  55. glClearDepth(1.0f); //初始化深度
  56. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //清空缓冲区
  57. glEnable(GL_DEPTH_TEST); //开启深度测试
  58. glShadeModel(GL_SMOOTH); //平滑阴影模式
  59. ///////////////////////////////////////////////////////////////////////
  60. //设置透视模式
  61. glViewport(0,0,w,h);
  62. glMatrixMode(GL_PROJECTION); //选择投影矩阵
  63. glLoadIdentity(); //重置投影矩阵
  64. gluPerspective(60.0,(GLfloat)w/h,0.1,100.0); //设置投影方式及投影参数
  65. glMatrixMode(GL_MODELVIEW); //选择模视矩阵
  66. glLoadIdentity(); //重置模视矩阵
  67. ///////////////////////////////////////////////////////////////////////
  68. //设置光照(定义一个位于左上方的白色定位光源)
  69. GLfloat lmodel_ambient[] = {1.0f,1.0f,1.0f,1.0f}; //定义环境光
  70. glLightModelfv(GL_LIGHT_MODEL_AMBIENT,lmodel_ambient); //设置环境光
  71. GLfloat light0_ambient[] = {1.0,1.0,1.0,1.0}; //定义光源环境光
  72. GLfloat light0_diffuse[] = {1.0,1.0,1.0,1.0}; //定义光源散射光
  73. GLfloat light0_specular[] = {1.0,1.0,1.0,1.0}; //定义光源反射光
  74. GLfloat light0_position[] = {15.0,15.0,15.0,10.0}; //定义光源位置
  75. glLightfv(GL_LIGHT0,GL_AMBIENT,light0_ambient); //设置光源环境光
  76. glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse); //设置光源散射光
  77. glLightfv(GL_LIGHT0,GL_SPECULAR,light0_specular); //设置光源反射光
  78. glLightfv(GL_LIGHT0,GL_POSITION,light0_position); //设置光源位置
  79. glEnable(GL_LIGHT0); //启用光源
  80. glEnable(GL_LIGHTING); //启用光照效果
  81. ///////////////////////////绘制金字塔(正四棱锥)////////////////////////
  82. ///////////////////////////////////////////////////////////////////////
  83. //定义黄铜材质
  84. GLfloat brass_ambient[] = {0.329412f,0.223529f,0.027451f,1.0f}; //定义材质环境光
  85. GLfloat brass_diffuse[] = {0.780392f,0.568627f,0.113725f,1.0f}; //定义材质散射光
  86. GLfloat brass_specular[] = {0.992157f,0.941176f,0.807843f,1.0f}; //定义材质反射光
  87. GLfloat brass_sinines[] = {100.0f}; //定义材质镜面反射强度
  88. glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,brass_ambient); //设置材质环境光
  89. glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,brass_diffuse); //设置材质散射光
  90. glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,brass_specular); //设置材质反射光
  91. glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,brass_sinines); //设置材质镜面反射强度
  92. ///////////////////////////////////////////////////////////////////////
  93. //设置坐标系统
  94. glTranslatef(0.0f,-0.1f,-2.0f); //将坐标系统下移0.1,后移2.0
  95. glRotatef(45,1.0,0.0,0.0); //将坐标系统绕x轴逆时针旋转45度
  96. glRotatef(30,0.0,-1.0,0.0); //将坐标系统绕y轴顺时针旋转30度
  97. ///////////////////////////////////////////////////////////////////////
  98. //绘制金字塔
  99. GLfloat pyramid[][3] = {{0.0,1.0,0.0},{0.5,0.0,0.5}, //定义顶点坐标
  100. {-0.5,0.0,0.5},{-0.5,0.0,-0.5},{0.5,0.0,-0.5}}; 
  101. glBegin(GL_TRIANGLE_FAN); //使用扇形三角形模式
  102. glNormal3f(0.0,0.447214f,0.894427f); //前平面法向量
  103. glVertex3fv(pyramid[0]); //前平面
  104. glVertex3fv(pyramid[1]);
  105. glVertex3fv(pyramid[2]);
  106. glNormal3f(-0.894427f,0.447214f,0.0); //左平面法向量
  107. glVertex3fv(pyramid[3]); //左平面
  108. glNormal3f(0.0,0.447214f,-0.894427f); //后平面法向量
  109. glVertex3fv(pyramid[4]); //后平面
  110. glNormal3f(0.894427f,0.447214f,0.0); //右平面法向量
  111. glVertex3fv(pyramid[1]); //右平面
  112. glEnd(); //结束绘制
  113. ///////////////////////////绘制地板(贝塞尔曲面)////////////////////////
  114. ///////////////////////////////////////////////////////////////////////
  115. //定义塑料材质
  116. GLfloat plastic_ambient[] = {0.0f,0.0f,0.00f,1.0f}; //定义材质环境光
  117. GLfloat plastic_diffuse[] = {0.7f,0.85f,0.7f,1.0f}; //定义材质散射光
  118. GLfloat plastic_specular[] = {0.75f,0.75f,0.75f,1.0f}; //定义材质反射光
  119. GLfloat plastic_sinines[] = {10.0f}; //定义材质镜面反射强度
  120. glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,plastic_ambient); //设置材质环境光
  121. glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,plastic_diffuse); //设置材质散射光
  122. glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,plastic_specular); //设置材质反射光
  123. glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,plastic_sinines); //设置材质镜面反射强度
  124. ///////////////////////////////////////////////////////////////////////
  125. //定义纹理图案(类似于国际象棋的黑白棋盘)
  126. #define textureWidth  64 //定义纹理图案宽度
  127. #define textureHeight 64 //定义纹理图案高度
  128. GLubyte texture[textureWidth][textureHeight][3]; //定义纹理图案数组,3分量
  129. GLubyte c;
  130. for(int i=0; i<textureWidth; i++) //生成纹理图案数组
  131. {
  132. for(int j=0; j<textureHeight; j++)
  133. {
  134. c = ( ((i&8)==0)^((j&8)==0) )*255;
  135. texture[i][j][0] = c;
  136. texture[i][j][1] = c;
  137. texture[i][j][2] = c;
  138. }
  139. }
  140. glTexImage2D( //定义纹理
  141. GL_TEXTURE_2D, //二维纹理
  142. 0, //纹理级别,单重纹理
  143. 3, //3分量模式,包含R、G、B信息
  144. textureWidth, //纹理图案宽度
  145. textureHeight, //纹理图案高度
  146. 0, //纹理边界宽度
  147. GL_RGB, //纹理图案数据种类
  148. GL_UNSIGNED_BYTE, //纹理图案数据存储类型
  149. &texture[0][0][0] //纹理图案数据起始地址
  150. );
  151. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); //设置纹理在s方向上重复
  152. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); //设置纹理在t方向上重复
  153. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); //设置纹理放大方式
  154. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); //设置纹理缩小方式
  155. glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); //设置调节映射方式
  156. glEnable(GL_TEXTURE_2D); //启用纹理映射
  157. GLfloat texpoints[2][2][2] = //定义纹理坐标(s,t)
  158. {
  159. {{0.0,0.0},{1.0,0.0}},
  160. {{0.0,1.0},{1.0,1.0}}
  161. };
  162. glMap2f( //定义纹理坐标求值器
  163. GL_MAP2_TEXTURE_COORD_2, //求值器生成值种类,选用纹理坐标
  164. 0, 1, //u的取值范围
  165. 2, //u的跨度 = u方向上两个值之间的间隔 = texpoints数组第一个维度
  166. 2, //u的阶数 = texpoints数组第二个维度
  167. 0, 1, //v的取值范围
  168. 4, //v的跨度 = v方向上两个值之间的间隔 = texpoints数组第一个维度*第二个纬度
  169. 2, //v的阶数 = texpoints数组第三个维度
  170. &texpoints[0][0][0] //控制点矩阵的指针
  171. );
  172. glEnable(GL_MAP2_TEXTURE_COORD_2); //激活纹理坐标求值器
  173. ///////////////////////////////////////////////////////////////////////
  174. //定义曲面控制点
  175. #define ustride 3 //u的跨度
  176. #define uorder 6 //u的阶数
  177. #define vstride (ustride * uorder) //v的跨度
  178. #define vorder 5 //v的阶数
  179. GLdouble points[vorder][uorder][ustride] = //定义顶点坐标(x,y,z)
  180. {
  181. {{-2.00f,0.4f,-1.00f},{-1.20f,0.3f,-1.00f},{-0.40f,0.4f,-1.00f},
  182. {0.40f,-0.3f,-1.00f},{1.20f,0.0f,-1.00f},{2.00f,0.5f,-1.00f}},
  183. {{-2.00f,0.1f,-0.60f},{-1.20f,0.0f,-0.60f},{-0.40f,0.5f,-0.60f},
  184. {0.40f,0.0f,-0.60f},{1.20f,0.0f,-0.60f},{2.00f,0.0f,-0.60f}},
  185. {{-2.00f,0.3f,-0.20f},{-1.20f,0.3f,-0.20f},{-0.40f,0.0f,-0.20f},
  186. {0.40f,0.0f,-0.20f},{1.20f,0.0f,-0.20f},{2.00f,0.5f,-0.20f}},
  187. {{-2.00f,0.1f,0.50f},{-1.20f,0.2f,0.20f},{-0.40f,0.0f,0.50f},
  188. {0.40f,0.0f,0.20f},{1.20f,0.6f,0.60f},{2.00f,0.0f,0.40f}},
  189. {{-2.00f,-0.5f,1.00f},{-1.20f,0.6f,1.00f},{-0.40f,0.0f,1.00f},
  190. {0.40f,0.0f,1.00f},{1.20f,0.1f,1.00f},{2.00f,0.5f,1.00f}}
  191. };
  192. glMap2d( //定义顶点坐标求值器
  193. GL_MAP2_VERTEX_3,
  194. 0,1,ustride,uorder,
  195. 0,1,vstride,vorder,
  196. &points[0][0][0]
  197. );
  198. glEnable(GL_MAP2_VERTEX_3); //激活顶点坐标求值器
  199. ///////////////////////////////////////////////////////////////////////
  200. //绘制曲面
  201. glPushMatrix(); //将当前模视矩阵压栈,防止当前变换影响原有的变换模式
  202. glLoadIdentity(); //重置模视矩阵
  203. glTranslatef(0.0f,-0.1f,-2.2f); //将坐标系统下移0.1,后移2.2
  204. glRotatef(45,1.0,0.0,0.0); //将坐标系统绕x轴逆时针旋转45度
  205. glMapGrid2f(20,0.0,1.0,20,0.0,1.0); //定义二维均布网格
  206. glEvalMesh2(GL_FILL,0,20,0,20); //生成二维多边形网格
  207. glDisable(GL_TEXTURE_2D); //禁用纹理映射
  208. glPopMatrix(); //将模视矩阵出栈
  209. glFlush(); //强制输出
  210. SwapBuffers(pDC->m_hDC); //交换缓冲区
  211. wglMakeCurrent(pDC->m_hDC,NULL); //置绘图上下文为非当前状态,释放设备上下文
  212. }
  213. /////////////////////////////////////////////////////////////////////////////
  214. // CMyOpenGLView diagnostics
  215. #ifdef _DEBUG
  216. void CMyOpenGLView::AssertValid() const
  217. {
  218. CView::AssertValid();
  219. }
  220. void CMyOpenGLView::Dump(CDumpContext& dc) const
  221. {
  222. CView::Dump(dc);
  223. }
  224. CMyOpenGLDoc* CMyOpenGLView::GetDocument() // non-debug version is inline
  225. {
  226. ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyOpenGLDoc)));
  227. return (CMyOpenGLDoc*)m_pDocument;
  228. }
  229. #endif //_DEBUG
  230. /////////////////////////////////////////////////////////////////////////////
  231. // CMyOpenGLView message handlers
  232. int CMyOpenGLView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  233. {
  234. if (CView::OnCreate(lpCreateStruct) == -1)
  235. return -1;
  236. ///////////////////////////////////////////////////////////////////////
  237. //定义像素格式描述符
  238. static PIXELFORMATDESCRIPTOR pfd=
  239. {
  240. sizeof(PIXELFORMATDESCRIPTOR), // PIXELFORMATDESCRIPTOR结构的大小
  241. 1, // 版本号
  242. PFD_DRAW_TO_WINDOW | // 必须支持窗口
  243. PFD_SUPPORT_OPENGL | // 必须支持OpenGL
  244. PFD_DOUBLEBUFFER, // 必须支持双缓冲
  245. PFD_TYPE_RGBA, // 申请RGBA格式
  246. 24, // 选择颜色深度
  247. 0, 0, 0, 0, 0, 0, // 忽略色彩位
  248. 0, // 无Alpha缓冲
  249. 0, // 忽略Shift位
  250. 0, // 无堆积缓存
  251. 0, 0, 0, 0, // 忽略Accumulation位
  252. 32, // 32位Z-Buffer深度缓冲  
  253. 0, // 无模板缓冲
  254. 0, // 无辅助缓冲
  255. PFD_MAIN_PLANE, // 主绘图层
  256. 0, // 保留字段
  257. 0, 0, 0 // 忽略层掩码
  258. };
  259. CClientDC dc(this); //设备上下文
  260. int nPixelFormat;
  261. if((nPixelFormat = ChoosePixelFormat(dc.m_hDC,&pfd)) == FALSE) //选择像素格式
  262. {
  263. MessageBox("选择像素格式失败!");
  264. return -1;
  265. }
  266. if(SetPixelFormat(dc.m_hDC,nPixelFormat,&pfd) == FALSE) //设置像素格式
  267. {
  268. MessageBox("设置像素格式失败!");
  269. return -1; 
  270. }
  271. if((m_hGLRC = wglCreateContext(dc.m_hDC)) == FALSE) //创建绘图上下文
  272. {
  273. MessageBox("创建OpenGL绘图上下文失败!");
  274. return -1;
  275. }
  276. return 0;
  277. }
  278. void CMyOpenGLView::OnDestroy() 
  279. {
  280. CView::OnDestroy();
  281. if(m_hGLRC != NULL)
  282. {
  283. wglDeleteContext(m_hGLRC); //删除绘图上下文
  284. }
  285. }
  286. void CMyOpenGLView::OnSize(UINT nType, int cx, int cy) 
  287. {
  288. CView::OnSize(nType, cx, cy);
  289. if(cx > 0 && cy >0)
  290. {
  291. CDC* pDC = GetDC(); //获得当前设备上下文指针
  292. wglMakeCurrent(pDC->m_hDC,m_hGLRC); //将绘图上下文绑定到设备上下文上
  293. glViewport(0,0,cx,cy); //设置视口大小
  294. glMatrixMode(GL_PROJECTION); //选择投影矩阵
  295. glLoadIdentity(); //重置投影矩阵
  296. gluPerspective(60.0,(GLfloat)cx/cy,0.1,100.0); //设置透视投影模式
  297. glMatrixMode(GL_MODELVIEW); //选择模式矩阵
  298. glLoadIdentity(); //重置模式矩阵
  299. }
  300. }
  301. /*///////////////////////////////////////////////////////////////////////
  302.  * 获得平面法向量
  303.  * p1,p2,p3:平面三角形的三个顶点(法向量的方向跟顶点的顺序满足右手定则)
  304.  * pN:法向量指针(一个三维数组)
  305. /*///////////////////////////////////////////////////////////////////////
  306. #include <Math.h>
  307. void myGetNormal(double p1[3],double p2[3],double p3[3],double *pN)
  308. {
  309. double PL1[3]; //平面向量
  310. double PL2[3]; //平面向量
  311. //计算平面向量
  312. for(int i = 0; i < 3; i++)
  313. {
  314. PL1[i] = p2[i] - p1[i];
  315. PL2[i] = p3[i] - p2[i];
  316. }
  317. //计算平面法向量
  318. double PN[3]; //平面法向量
  319. PN[0] = PL1[1]*PL2[2] - PL1[2]*PL2[1];
  320. PN[1] = PL1[2]*PL2[0] - PL1[0]*PL2[2];
  321. PN[2] = PL1[0]*PL2[1] - PL1[1]*PL2[0];
  322. //将平面法向量规格化
  323. double NL = sqrt(PN[0]*PN[0]+PN[1]*PN[1]+PN[2]*PN[2]);
  324. *pN = PN[0]/NL;
  325. *(pN+1) = PN[1]/NL;
  326. *(pN+2) = PN[2]/NL;
  327. }