MyOpenGLView.cpp
上传用户:cpy_520
上传日期:2022-06-11
资源大小:7828k
文件大小:13k
- // MyOpenGLView.cpp : implementation of the CMyOpenGLView class
- //
- #include "stdafx.h"
- #include "MyOpenGL.h"
- #include "MyOpenGLDoc.h"
- #include "MyOpenGLView.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // CMyOpenGLView
- IMPLEMENT_DYNCREATE(CMyOpenGLView, CView)
- BEGIN_MESSAGE_MAP(CMyOpenGLView, CView)
- //{{AFX_MSG_MAP(CMyOpenGLView)
- ON_WM_CREATE()
- ON_WM_DESTROY()
- ON_WM_SIZE()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CMyOpenGLView construction/destruction
- CMyOpenGLView::CMyOpenGLView()
- {
- // TODO: add construction code here
- }
- CMyOpenGLView::~CMyOpenGLView()
- {
- }
- BOOL CMyOpenGLView::PreCreateWindow(CREATESTRUCT& cs)
- {
- // TODO: Modify the Window class or styles here by modifying
- // the CREATESTRUCT cs
-
- cs.style |= WS_CLIPSIBLINGS|WS_CLIPCHILDREN; // 设置窗口风格,使支持OpenGL
- return CView::PreCreateWindow(cs);
- }
- /////////////////////////////////////////////////////////////////////////////
- // CMyOpenGLView drawing
- void CMyOpenGLView::OnDraw(CDC* pDC)
- {
- CMyOpenGLDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- // TODO: add draw code for native data here
- ///////////////////////////////////////////////////////////////////////
- //获得视区的宽与高,用于设置OpenGL的视口
- CRect rcClient;
- GetClientRect(&rcClient);
- GLsizei w = rcClient.Width(); //视区宽度
- GLsizei h = rcClient.Height(); //视区高度
- ///////////////////////////////////////////////////////////////////////
- //初始化各种设置
- wglMakeCurrent(pDC->m_hDC,m_hGLRC); //将绘图上下文绑定到设备上下文上
- glClearColor(0.5,0.5,0.5,0.0); //设置背景色
- glClearDepth(1.0f); //初始化深度
- glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //清空缓冲区
- glEnable(GL_DEPTH_TEST); //开启深度测试
- glShadeModel(GL_SMOOTH); //平滑阴影模式
- ///////////////////////////////////////////////////////////////////////
- //设置透视模式
- glViewport(0,0,w,h);
- glMatrixMode(GL_PROJECTION); //选择投影矩阵
- glLoadIdentity(); //重置投影矩阵
- gluPerspective(60.0,(GLfloat)w/h,0.1,100.0); //设置投影方式及投影参数
- glMatrixMode(GL_MODELVIEW); //选择模视矩阵
- glLoadIdentity(); //重置模视矩阵
- ///////////////////////////////////////////////////////////////////////
- //设置光照(定义一个位于左上方的白色定位光源)
- GLfloat lmodel_ambient[] = {1.0f,1.0f,1.0f,1.0f}; //定义环境光
- glLightModelfv(GL_LIGHT_MODEL_AMBIENT,lmodel_ambient); //设置环境光
- GLfloat light0_ambient[] = {1.0,1.0,1.0,1.0}; //定义光源环境光
- GLfloat light0_diffuse[] = {1.0,1.0,1.0,1.0}; //定义光源散射光
- GLfloat light0_specular[] = {1.0,1.0,1.0,1.0}; //定义光源反射光
- GLfloat light0_position[] = {15.0,15.0,15.0,10.0}; //定义光源位置
- glLightfv(GL_LIGHT0,GL_AMBIENT,light0_ambient); //设置光源环境光
- glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse); //设置光源散射光
- glLightfv(GL_LIGHT0,GL_SPECULAR,light0_specular); //设置光源反射光
- glLightfv(GL_LIGHT0,GL_POSITION,light0_position); //设置光源位置
- glEnable(GL_LIGHT0); //启用光源
- glEnable(GL_LIGHTING); //启用光照效果
- ///////////////////////////绘制金字塔(正四棱锥)////////////////////////
- ///////////////////////////////////////////////////////////////////////
- //定义黄铜材质
- GLfloat brass_ambient[] = {0.329412f,0.223529f,0.027451f,1.0f}; //定义材质环境光
- GLfloat brass_diffuse[] = {0.780392f,0.568627f,0.113725f,1.0f}; //定义材质散射光
- GLfloat brass_specular[] = {0.992157f,0.941176f,0.807843f,1.0f}; //定义材质反射光
- GLfloat brass_sinines[] = {100.0f}; //定义材质镜面反射强度
- glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,brass_ambient); //设置材质环境光
- glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,brass_diffuse); //设置材质散射光
- glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,brass_specular); //设置材质反射光
- glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,brass_sinines); //设置材质镜面反射强度
- ///////////////////////////////////////////////////////////////////////
- //设置坐标系统
- glTranslatef(0.0f,-0.1f,-2.0f); //将坐标系统下移0.1,后移2.0
- glRotatef(45,1.0,0.0,0.0); //将坐标系统绕x轴逆时针旋转45度
- glRotatef(30,0.0,-1.0,0.0); //将坐标系统绕y轴顺时针旋转30度
- ///////////////////////////////////////////////////////////////////////
- //绘制金字塔
- GLfloat pyramid[][3] = {{0.0,1.0,0.0},{0.5,0.0,0.5}, //定义顶点坐标
- {-0.5,0.0,0.5},{-0.5,0.0,-0.5},{0.5,0.0,-0.5}};
- glBegin(GL_TRIANGLE_FAN); //使用扇形三角形模式
- glNormal3f(0.0,0.447214f,0.894427f); //前平面法向量
- glVertex3fv(pyramid[0]); //前平面
- glVertex3fv(pyramid[1]);
- glVertex3fv(pyramid[2]);
- glNormal3f(-0.894427f,0.447214f,0.0); //左平面法向量
- glVertex3fv(pyramid[3]); //左平面
- glNormal3f(0.0,0.447214f,-0.894427f); //后平面法向量
- glVertex3fv(pyramid[4]); //后平面
- glNormal3f(0.894427f,0.447214f,0.0); //右平面法向量
- glVertex3fv(pyramid[1]); //右平面
- glEnd(); //结束绘制
- ///////////////////////////绘制地板(贝塞尔曲面)////////////////////////
- ///////////////////////////////////////////////////////////////////////
- //定义塑料材质
- GLfloat plastic_ambient[] = {0.0f,0.0f,0.00f,1.0f}; //定义材质环境光
- GLfloat plastic_diffuse[] = {0.7f,0.85f,0.7f,1.0f}; //定义材质散射光
- GLfloat plastic_specular[] = {0.75f,0.75f,0.75f,1.0f}; //定义材质反射光
- GLfloat plastic_sinines[] = {10.0f}; //定义材质镜面反射强度
- glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,plastic_ambient); //设置材质环境光
- glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,plastic_diffuse); //设置材质散射光
- glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,plastic_specular); //设置材质反射光
- glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,plastic_sinines); //设置材质镜面反射强度
- ///////////////////////////////////////////////////////////////////////
- //定义纹理图案(类似于国际象棋的黑白棋盘)
- #define textureWidth 64 //定义纹理图案宽度
- #define textureHeight 64 //定义纹理图案高度
- GLubyte texture[textureWidth][textureHeight][3]; //定义纹理图案数组,3分量
- GLubyte c;
- for(int i=0; i<textureWidth; i++) //生成纹理图案数组
- {
- for(int j=0; j<textureHeight; j++)
- {
- c = ( ((i&8)==0)^((j&8)==0) )*255;
- texture[i][j][0] = c;
- texture[i][j][1] = c;
- texture[i][j][2] = c;
- }
- }
- glTexImage2D( //定义纹理
- GL_TEXTURE_2D, //二维纹理
- 0, //纹理级别,单重纹理
- 3, //3分量模式,包含R、G、B信息
- textureWidth, //纹理图案宽度
- textureHeight, //纹理图案高度
- 0, //纹理边界宽度
- GL_RGB, //纹理图案数据种类
- GL_UNSIGNED_BYTE, //纹理图案数据存储类型
- &texture[0][0][0] //纹理图案数据起始地址
- );
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); //设置纹理在s方向上重复
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); //设置纹理在t方向上重复
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); //设置纹理放大方式
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); //设置纹理缩小方式
- glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); //设置调节映射方式
- glEnable(GL_TEXTURE_2D); //启用纹理映射
- GLfloat texpoints[2][2][2] = //定义纹理坐标(s,t)
- {
- {{0.0,0.0},{1.0,0.0}},
- {{0.0,1.0},{1.0,1.0}}
- };
- glMap2f( //定义纹理坐标求值器
- GL_MAP2_TEXTURE_COORD_2, //求值器生成值种类,选用纹理坐标
- 0, 1, //u的取值范围
- 2, //u的跨度 = u方向上两个值之间的间隔 = texpoints数组第一个维度
- 2, //u的阶数 = texpoints数组第二个维度
- 0, 1, //v的取值范围
- 4, //v的跨度 = v方向上两个值之间的间隔 = texpoints数组第一个维度*第二个纬度
- 2, //v的阶数 = texpoints数组第三个维度
- &texpoints[0][0][0] //控制点矩阵的指针
- );
- glEnable(GL_MAP2_TEXTURE_COORD_2); //激活纹理坐标求值器
- ///////////////////////////////////////////////////////////////////////
- //定义曲面控制点
- #define ustride 3 //u的跨度
- #define uorder 6 //u的阶数
- #define vstride (ustride * uorder) //v的跨度
- #define vorder 5 //v的阶数
- GLdouble points[vorder][uorder][ustride] = //定义顶点坐标(x,y,z)
- {
- {{-2.00f,0.4f,-1.00f},{-1.20f,0.3f,-1.00f},{-0.40f,0.4f,-1.00f},
- {0.40f,-0.3f,-1.00f},{1.20f,0.0f,-1.00f},{2.00f,0.5f,-1.00f}},
- {{-2.00f,0.1f,-0.60f},{-1.20f,0.0f,-0.60f},{-0.40f,0.5f,-0.60f},
- {0.40f,0.0f,-0.60f},{1.20f,0.0f,-0.60f},{2.00f,0.0f,-0.60f}},
- {{-2.00f,0.3f,-0.20f},{-1.20f,0.3f,-0.20f},{-0.40f,0.0f,-0.20f},
- {0.40f,0.0f,-0.20f},{1.20f,0.0f,-0.20f},{2.00f,0.5f,-0.20f}},
- {{-2.00f,0.1f,0.50f},{-1.20f,0.2f,0.20f},{-0.40f,0.0f,0.50f},
- {0.40f,0.0f,0.20f},{1.20f,0.6f,0.60f},{2.00f,0.0f,0.40f}},
- {{-2.00f,-0.5f,1.00f},{-1.20f,0.6f,1.00f},{-0.40f,0.0f,1.00f},
- {0.40f,0.0f,1.00f},{1.20f,0.1f,1.00f},{2.00f,0.5f,1.00f}}
- };
- glMap2d( //定义顶点坐标求值器
- GL_MAP2_VERTEX_3,
- 0,1,ustride,uorder,
- 0,1,vstride,vorder,
- &points[0][0][0]
- );
- glEnable(GL_MAP2_VERTEX_3); //激活顶点坐标求值器
- ///////////////////////////////////////////////////////////////////////
- //绘制曲面
- glPushMatrix(); //将当前模视矩阵压栈,防止当前变换影响原有的变换模式
- glLoadIdentity(); //重置模视矩阵
- glTranslatef(0.0f,-0.1f,-2.2f); //将坐标系统下移0.1,后移2.2
- glRotatef(45,1.0,0.0,0.0); //将坐标系统绕x轴逆时针旋转45度
-
- glMapGrid2f(20,0.0,1.0,20,0.0,1.0); //定义二维均布网格
- glEvalMesh2(GL_FILL,0,20,0,20); //生成二维多边形网格
- glDisable(GL_TEXTURE_2D); //禁用纹理映射
- glPopMatrix(); //将模视矩阵出栈
- glFlush(); //强制输出
- SwapBuffers(pDC->m_hDC); //交换缓冲区
- wglMakeCurrent(pDC->m_hDC,NULL); //置绘图上下文为非当前状态,释放设备上下文
- }
- /////////////////////////////////////////////////////////////////////////////
- // CMyOpenGLView diagnostics
- #ifdef _DEBUG
- void CMyOpenGLView::AssertValid() const
- {
- CView::AssertValid();
- }
- void CMyOpenGLView::Dump(CDumpContext& dc) const
- {
- CView::Dump(dc);
- }
- CMyOpenGLDoc* CMyOpenGLView::GetDocument() // non-debug version is inline
- {
- ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyOpenGLDoc)));
- return (CMyOpenGLDoc*)m_pDocument;
- }
- #endif //_DEBUG
- /////////////////////////////////////////////////////////////////////////////
- // CMyOpenGLView message handlers
- int CMyOpenGLView::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- if (CView::OnCreate(lpCreateStruct) == -1)
- return -1;
- ///////////////////////////////////////////////////////////////////////
- //定义像素格式描述符
- static PIXELFORMATDESCRIPTOR pfd=
- {
- sizeof(PIXELFORMATDESCRIPTOR), // PIXELFORMATDESCRIPTOR结构的大小
- 1, // 版本号
- PFD_DRAW_TO_WINDOW | // 必须支持窗口
- PFD_SUPPORT_OPENGL | // 必须支持OpenGL
- PFD_DOUBLEBUFFER, // 必须支持双缓冲
- PFD_TYPE_RGBA, // 申请RGBA格式
- 24, // 选择颜色深度
- 0, 0, 0, 0, 0, 0, // 忽略色彩位
- 0, // 无Alpha缓冲
- 0, // 忽略Shift位
- 0, // 无堆积缓存
- 0, 0, 0, 0, // 忽略Accumulation位
- 32, // 32位Z-Buffer深度缓冲
- 0, // 无模板缓冲
- 0, // 无辅助缓冲
- PFD_MAIN_PLANE, // 主绘图层
- 0, // 保留字段
- 0, 0, 0 // 忽略层掩码
- };
- CClientDC dc(this); //设备上下文
- int nPixelFormat;
- if((nPixelFormat = ChoosePixelFormat(dc.m_hDC,&pfd)) == FALSE) //选择像素格式
- {
- MessageBox("选择像素格式失败!");
- return -1;
- }
- if(SetPixelFormat(dc.m_hDC,nPixelFormat,&pfd) == FALSE) //设置像素格式
- {
- MessageBox("设置像素格式失败!");
- return -1;
- }
- if((m_hGLRC = wglCreateContext(dc.m_hDC)) == FALSE) //创建绘图上下文
- {
- MessageBox("创建OpenGL绘图上下文失败!");
- return -1;
- }
-
- return 0;
- }
- void CMyOpenGLView::OnDestroy()
- {
- CView::OnDestroy();
-
- if(m_hGLRC != NULL)
- {
- wglDeleteContext(m_hGLRC); //删除绘图上下文
- }
- }
- void CMyOpenGLView::OnSize(UINT nType, int cx, int cy)
- {
- CView::OnSize(nType, cx, cy);
- if(cx > 0 && cy >0)
- {
- CDC* pDC = GetDC(); //获得当前设备上下文指针
- wglMakeCurrent(pDC->m_hDC,m_hGLRC); //将绘图上下文绑定到设备上下文上
- glViewport(0,0,cx,cy); //设置视口大小
- glMatrixMode(GL_PROJECTION); //选择投影矩阵
- glLoadIdentity(); //重置投影矩阵
- gluPerspective(60.0,(GLfloat)cx/cy,0.1,100.0); //设置透视投影模式
- glMatrixMode(GL_MODELVIEW); //选择模式矩阵
- glLoadIdentity(); //重置模式矩阵
- }
- }
- /*///////////////////////////////////////////////////////////////////////
- * 获得平面法向量
- * p1,p2,p3:平面三角形的三个顶点(法向量的方向跟顶点的顺序满足右手定则)
- * pN:法向量指针(一个三维数组)
- /*///////////////////////////////////////////////////////////////////////
- #include <Math.h>
- void myGetNormal(double p1[3],double p2[3],double p3[3],double *pN)
- {
- double PL1[3]; //平面向量
- double PL2[3]; //平面向量
- //计算平面向量
- for(int i = 0; i < 3; i++)
- {
- PL1[i] = p2[i] - p1[i];
- PL2[i] = p3[i] - p2[i];
- }
-
- //计算平面法向量
- double PN[3]; //平面法向量
- PN[0] = PL1[1]*PL2[2] - PL1[2]*PL2[1];
- PN[1] = PL1[2]*PL2[0] - PL1[0]*PL2[2];
- PN[2] = PL1[0]*PL2[1] - PL1[1]*PL2[0];
-
- //将平面法向量规格化
- double NL = sqrt(PN[0]*PN[0]+PN[1]*PN[1]+PN[2]*PN[2]);
- *pN = PN[0]/NL;
- *(pN+1) = PN[1]/NL;
- *(pN+2) = PN[2]/NL;
- }