📄 surfaceview.cpp
字号:
// SurfaceView.cpp : implementation of the CSurfaceView class
//
#include "stdafx.h"
#include "Surface.h"
#include "SurfaceDoc.h"
#include "SurfaceView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#pragma comment(lib, "OpenGL32.lib")
#pragma comment(lib, "glu32.lib")
#include "GL\gl.h"
#include "GL\glu.h"
/////////////////////////////////////////////////////////////////////////////
// CSurfaceView
IMPLEMENT_DYNCREATE(CSurfaceView, CView)
BEGIN_MESSAGE_MAP(CSurfaceView, CView)
//{{AFX_MSG_MAP(CSurfaceView)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSurfaceView construction/destruction
CSurfaceView::CSurfaceView()
{
// TODO: add construction code here
m_pDC = NULL;
m_pDib = NULL;
}
CSurfaceView::~CSurfaceView()
{
}
BOOL CSurfaceView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
//设置 OpenGL 窗口风格,
cs.style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CSurfaceView drawing
void CSurfaceView::OnDraw(CDC* pDC)
{
DrawScene();
}
/////////////////////////////////////////////////////////////////////////////
// CSurfaceView diagnostics
#ifdef _DEBUG
void CSurfaceView::AssertValid() const
{
CView::AssertValid();
}
void CSurfaceView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CSurfaceDoc* CSurfaceView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSurfaceDoc)));
return (CSurfaceDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CSurfaceView message handlers
//设置像素格式
BOOL CSurfaceView::SetupPixelFormat()
{
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL, // support OpenGL
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
32, // 32-bit z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
//选择硬件所支持的像素格式与 pfd 最接近的一个
int nPixelformat;
if ( (nPixelformat = ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd)) == 0 )
{
MessageBox("ChoosePixelFormat failed");
return FALSE;
}
//设置已经匹配的像素格式
if (SetPixelFormat(m_pDC->GetSafeHdc(), nPixelformat, &pfd) == FALSE)
{
MessageBox("SetPixelFormat failed");
return FALSE;
}
return TRUE;
}
//初始化OpenGL
void CSurfaceView::Init()
{
PIXELFORMATDESCRIPTOR pfd;
m_pDC = new CClientDC(this);
ASSERT(m_pDC != NULL);
//设置像素格式
if(!SetupPixelFormat())return;
//测试并描述像素格式
int nIndex = GetPixelFormat(m_pDC->GetSafeHdc());
DescribePixelFormat(m_pDC->GetSafeHdc(), nIndex, sizeof(pfd), &pfd);
//创建着色描述表
HGLRC hrc = wglCreateContext(m_pDC->GetSafeHdc());
//当前化着色描述表
wglMakeCurrent(m_pDC->GetSafeHdc(), hrc);
//允许深度测试, 深度初始值为远剪切面深度(规格化坐标系中)
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
}
int CSurfaceView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
Init();
m_pDib = new CDib("valley.bmp");
return 0;
}
void CSurfaceView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add your message handler code here
//获取当前着色描述表句柄
HGLRC hrc = wglGetCurrentContext();
//撤消与着色描述表关联的着色任务
wglMakeCurrent(NULL, NULL);
//释放
if(hrc)wglDeleteContext(hrc);
if(m_pDC) delete m_pDC;
if(m_pDib) delete m_pDib;
}
void CSurfaceView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
//启动透视变换矩阵
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//设置视景体
glFrustum(-1.0, 1.0, -1.0, 1.0, 3.0, 7.0);
//设置视口
glViewport(0, 0, (GLsizei)cx, (GLsizei)cy);
}
//
void CSurfaceView::DrawScene()
{
//启动模型变换矩阵, 并单位化
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//将景物移至视景体之中
glTranslatef(0.0f, 0.0f, -4.5f);
//颜色缓冲区清除颜色为白色
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
//同时清除颜色缓冲区和深度缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawBezierSurface();
//完成绘制指令后交换缓冲区
glFinish();
}
//绘制纹理映射Bezier曲面
void CSurfaceView::DrawBezierSurface()
{
//几何控制点
GLfloat vertexCtrlPts[4][4][3] = {
{{-1.1f, -0.6f, 0.2f}, {-0.2f, -0.6f, 0.4f},
{0.2f, -0.6f, 0.4f}, {0.4f, -0.6f, 0.2f}},
{{-0.6f, -0.2f, 0.1f}, {-0.2f, -0.2f, 0.5f},
{0.2f, -0.2f, 0.5f}, {0.6f, -0.2f, 0.1f}},
{{-0.6f, 0.2f, 0.3f}, {-0.2f, 0.2f, 0.5f},
{0.2f, 0.2f, 0.5f}, {0.6f, 0.2f, 0.3f}},
{{-0.6f, 0.6f, 0.2f}, {-0.2f, 0.6f, 0.4f},
{0.2f, 0.6f, 0.4f}, {1.1f, 0.6f, 0.2f}},
};
//纹理控制点
GLfloat textureCtrlPts[2][2][2] = {
{{1.0f, 0.0f}, {1.0f, 1.0f}},
{{0.0f, 0.0f}, {0.0f, 1.0f}}};
//构造纹理图像数据
GLubyte* pTextureBits = (GLubyte*)m_pDib->GetDibData();
//图像的宽度一定要满足(以下解释来自于在线帮助):
//(1) The width of the texture image. Must be 2 ^ n + 2 (border) for some integer n.
//(2) The height of the texture image. Must be 2 ^ m + 2 (border) for some integer m.
// OpenGL在这一点上作得并不好!
GLint nWidth = m_pDib->GetWidth();
GLint nHeight = m_pDib->GetHeight();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
//(3) The width of the border. Must be either 0 or 1.
//定义纹理
glTexImage2D(GL_TEXTURE_2D, 0, 3, nWidth, nHeight,
0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pTextureBits);
//控制纹理, 说明滤波方式
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
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_DECAL);
//二维评价器: 生成几何坐标和纹理坐标
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4,
0, 1, 12, 4, (const float*)vertexCtrlPts);
glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2,
0, 1, 4, 2, (const float*)textureCtrlPts);
//光照
CreateLightAndMaterial();
//启动纹理贴图和法线自动计算功能
glEnable(GL_TEXTURE_2D);
glEnable(GL_MAP2_TEXTURE_COORD_2);
glEnable(GL_MAP2_VERTEX_3);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
//利用二维评价器的计算结果实现网格分割
glMapGrid2f(30, 0.0, 1.0, 30, 0.0, 1.0);
//绘制
glPushMatrix ();
glScalef(1.1f, 1.1f, 1.1f);
glRotatef(90.0f, 0.0f, .0f, 1.0f);
glEvalMesh2(GL_FILL, 0, 30, 0, 30);
glPopMatrix();
//挂起各功能
glDisable(GL_MAP2_VERTEX_3);
glDisable(GL_MAP2_TEXTURE_COORD_2);
glDisable(GL_TEXTURE_2D);
glDisable(GL_AUTO_NORMAL);
glDisable(GL_NORMALIZE);
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
}
//创建光源、材质
void CSurfaceView::CreateLightAndMaterial()
{
//定义光源属性.漫反射、镜面高光均采用缺省值.
//泛光光源。
GLfloat lightAmb[] = {0.2f, 0.2f, 0.2f, 1.0f };
GLfloat lightPos[] = {1.0f, 1.0f, 2.0f, 1.0f };
//材质,环境反射系数采用缺省值,光照射前面。
GLfloat matDiffuse[] = {0.0f, 0.7f, 0.7f, 1.0f };
GLfloat matSpecular[] = {1.0f, 1.0f, 1.0f, 1.0f };
GLfloat matShininess[] = {60.0f };
//允许光照, 并开启第0个光源
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
//设置第0个光源的属性
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
//设置材质属性.
glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, matSpecular);
glMaterialfv(GL_FRONT, GL_SHININESS, matShininess);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -