📄 splinedlg.cpp
字号:
// SplineDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "Spline.h"
#include "SplineDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#ifndef CALLBACK
#define CALLBACK
#endif
GLfloat ctlpoints[4][4][3];
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
void CALLBACK nurbsError(GLenum errorCode)
{
const GLubyte *estring;
estring = gluErrorString(errorCode);
fprintf (stderr, "Nurbs Error: %s\n", estring);
exit (0);
}
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CSplineDlg 对话框
CSplineDlg::CSplineDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSplineDlg::IDD, pParent)
, m_pDC(NULL)
, m_pNurb(NULL)
,m_hGLContext(NULL)
, m_bShowPoints(FALSE)
, m_pWnd(NULL)
, m_trans(0)
, m_width(0)
, m_height(0)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CSplineDlg::DoDataExchange(CDataExchange* pDX)
{
DDX_Control(IDC_STATICTRANS,m_sliTrans);
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CSplineDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_WM_DESTROY()
END_MESSAGE_MAP()
// CSplineDlg 消息处理程序
BOOL CSplineDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
myFirst();
CSliderCtrl m_sliTrans;
m_sliTrans.SetPos(0);
m_sliTrans.SetRange(-10,10);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CSplineDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CSplineDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
///////////////////自己加的语句////////////////////
static BOOL bBusy = FALSE; //紧接着的三句是为了 应用 双缓存
if(bBusy) return;
bBusy = TRUE;
// 没有下面的语句时 背景为 黑色
// glClearColor(0.2f,0.2f,0.5f,1.0f);
// 为了增加本章的趣味性 先屏蔽该句
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除缓存,将背景置空
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
InitSurface();
reshape();
myDraw(); // 自己绘制图形
//m_pWnd->Invalidate();
UpdateWindow();
glFinish();
SwapBuffers(wglGetCurrentDC()); // 双缓存 应用
bBusy = FALSE;
////////////////////////////////////////
}
//当用户拖动最小化窗口时系统调用此函数取得光标显示。
//
HCURSOR CSplineDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
BOOL CSplineDlg::myPixelFomat(void)
{
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL| // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
PFD_TYPE_RGBA,
24,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
32,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
int pixelformat;
if ( (pixelformat = ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd)) == 0 )
{
MessageBox("ChoosePixelFormat failed");
return FALSE;
}
if (SetPixelFormat(m_pDC->GetSafeHdc(), pixelformat, &pfd) == FALSE)
{
MessageBox("SetPixelFormat failed");
return FALSE;
}
return TRUE;
}
// 渲染描述表
void CSplineDlg::myFirst(void)
{
PIXELFORMATDESCRIPTOR pfd;
int n;
HGLRC hrc; //渲染描述表rc的句柄
CWnd* m_pWnd=GetDlgItem(IDC_STATICDISPLAY);
m_pDC = new CClientDC(m_pWnd);
CRect rect;
m_pWnd->GetClientRect(&rect);
m_width=rect.Width();
m_height=rect.Height();
ASSERT(m_pDC != NULL);
if (!myPixelFomat())
return;
n =::GetPixelFormat(m_pDC->GetSafeHdc()); // 成功了就返回这种像素形式的索引值,否则返回0
::DescribePixelFormat(m_pDC->GetSafeHdc(), n, sizeof(pfd), &pfd);
hrc = wglCreateContext(m_pDC->GetSafeHdc()); //创建并初始化 渲染描述表
wglMakeCurrent(m_pDC->GetSafeHdc(), hrc);
GetClientRect(&m_oldRect); // 获得客户区的大小
glClearDepth(1.0f); // 清除深度缓存 使它变为 1.0 为现在的深度缓存值
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW); //启动 模型-视图 矩阵
glLoadIdentity();
}
void CSplineDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: 在此处添加消息处理程序代码
// 删除渲染描述表及绑定的设备描述表
HGLRC hrc;
hrc = ::wglGetCurrentContext();
::wglMakeCurrent(NULL, NULL); // 使得当前的hdc 和 hglrc 都为空 其定义见下方
/*
BOOL wglMakeCurrent(
HDC hdc, // device context of device that OpenGL calls are
// to be drawn on
HGLRC hglrc // OpenGL rendering context to be made the calling
// thread's current rendering context
);
*/
if (hrc)
::wglDeleteContext(hrc);
if (m_pDC)
delete m_pDC;
}
void CSplineDlg::myDraw(void)
{
GLfloat knots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
int i, j;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(330.0, 1.,0.,0.);
glScalef (0.5, 0.5, 0.5);
gluBeginSurface(m_pNurb);
gluNurbsSurface(m_pNurb,
8, knots, 8, knots,
4 * 3, 3, &ctlpoints[0][0][0],
4, 4, GL_MAP2_VERTEX_3);
gluEndSurface(m_pNurb);
// if (m_bShowPoints) {
glPointSize(5.0);
glDisable(GL_LIGHTING);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_POINTS);
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
glVertex3f(ctlpoints[i][j][0],
ctlpoints[i][j][1], ctlpoints[i][j][2]);
}
//}
glEnd();
glEnable(GL_LIGHTING);
}
glPopMatrix();
glFlush();
}
void CSplineDlg::InitSurface(void)
{
GLfloat mat_diffuse[] = { 0.7, 0.7, 0.7, 1.0 };
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 100.0 };
glClearColor (0.0, 0.0, 0.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
// 初始化 表面
int u, v;
for (u = 0; u < 4; u++) {
for (v = 0; v < 4; v++) {
ctlpoints[u][v][0] = 2.0*((GLfloat)u - 1.5);
ctlpoints[u][v][1] = 2.0*((GLfloat)v - 1.5);
if ( (u == 1 || u == 2) && (v == 1 || v == 2))
ctlpoints[u][v][2] = 3.0;
else
ctlpoints[u][v][2] = -3.0;
}
}
m_pNurb = gluNewNurbsRenderer();
gluNurbsProperty(m_pNurb, GLU_SAMPLING_TOLERANCE, 25.0);
gluNurbsProperty(m_pNurb, GLU_DISPLAY_MODE, GLU_FILL);
//gluNurbsCallback(m_pNurb, GLU_ERROR, nurbsError);
}
BOOL CSplineDlg::CreateViewGLContext(HDC hDC) // 没有用到
{
m_hGLContext = wglCreateContext(hDC);
if(m_hGLContext==NULL)
return FALSE;
if(wglMakeCurrent(hDC,m_hGLContext)==FALSE)
return FALSE;
return TRUE;
}
// 调整显示比例
void CSplineDlg::reshape(void)
{
glViewport(0, 0, (GLsizei) m_width, (GLsizei) m_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (45.0, (GLdouble)m_width/(GLdouble)m_height, 3.0, 8.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef (0.0, 0.0, -5.0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -