学习OpenGL过程中
所编写的学习程序,从网上搜集整理改写而成,如果你第一次接触OpenGL,希望这个例子对你有所帮助,欢迎同行共同探讨。
在Dialog中的用户区域上画三个齿轮,如下图所示,
首先,在stdafx.h文件中包含相关头文件gl.h和glu.h,
然后,在项目属性页中添加opengl32.lib和glu32.lib,
所需的动态连接库opengl32.dll和glu32.dll位于目录c:\windows\system32下,
相关代码如下,
// FirstOpenGl.cpp : 定义应用程序的类行为。
#include "stdafx.h"
#include "FirstOpenGl.h"
#include "MainFrm.h"
#include "FirstOpenGlDoc.h"
#include "FirstOpenGlView.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define M_PI 3.14159265
static GLfloat viewDist = 1; //40.0
static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
static GLint gear1, gear2, gear3;
static GLfloat angle = 10.0;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
///////////////////////////////////////////////////////////////////////////////
// CFirstOpenGlApp
BEGIN_MESSAGE_MAP(CFirstOpenGlApp, CWinApp)
ON_COMMAND(ID_APP_ABOUT, &CFirstOpenGlApp::OnAppAbout)
// 基于文件的标准文档命令
ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////////
// CFirstOpenGlApp 构造
CFirstOpenGlApp::CFirstOpenGlApp()
{ // TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在 InitInstance 中
}
///////////////////////////////////////////////////////////////////////////////
// 唯一的一个 CFirstOpenGlApp 对象
CFirstOpenGlApp theApp;
///////////////////////////////////////////////////////////////////////////////
// CFirstOpenGlApp 初始化
BOOL CFirstOpenGlApp::InitInstance()
{ // 如果一个运行在 Windows XP 上的应用程序清单指定要
// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
//则需要 InitCommonControlsEx()。否则,将无法创建窗口。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 将它设置为包括所有要在应用程序中使用的
// 公共控件类。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
// 初始化 OLE 库
if (!AfxOleInit())
{ AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
// 标准初始化
// 如果未使用这些功能并希望减小
// 最终可执行文件的大小,则应移除下列
// 不需要的特定初始化例程
// 更改用于存储设置的注册表项
// TODO: 应适当修改该字符串,
// 例如修改为公司或组织名
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
LoadStdProfileSettings(4); // 加载标准 INI 文件选项(包括 MRU)
// 注册应用程序的文档模板。文档模板
// 将用作文档、框架窗口和视图之间的连接
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CFirstOpenGlDoc),
RUNTIME_CLASS(CMainFrame), // 主 SDI 框架窗口
RUNTIME_CLASS(CFirstOpenGlView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
// 分析标准外壳命令、DDE、打开文件操作的命令行
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// 调度在命令行中指定的命令。如果
// 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// 唯一的一个窗口已初始化,因此显示它并对其进行更新
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
// 仅当具有后缀时才调用 DragAcceptFiles
// 在 SDI 应用程序中,这应在 ProcessShellCommand 之后发生
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
virtual BOOL OnInitDialog();
// 实现
protected:
DECLARE_MESSAGE_MAP()
public:
HDC hDC;
HGLRC hRC;
BOOL SetWindowPixelFormat(HDC hDC);
void RenderScene();
void gear(GLfloat inner_radius, GLfloat outer_radius,
GLfloat width, GLint teeth, GLfloat tooth_depth);
afx_msg void OnBnClickedOk();
afx_msg void OnClose();
afx_msg void OnDestroy();
afx_msg void OnPaint();
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnBnClickedViewDistPlus();
afx_msg void OnBnClickedViewDistSub();
afx_msg void OnBnClickedRotateXPlus();
afx_msg void OnBnClickedRotateXSub();
afx_msg void OnBnClickedRotateYPlus();
afx_msg void OnBnClickedRotateYSub();
afx_msg void OnBnClickedOpenglInfo();
};
///////////////////////////////////////////////////////////////////////////////
// 用于运行对话框的应用程序命令
void CFirstOpenGlApp::OnAppAbout()
{ CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
///////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
ON_WM_CLOSE()
ON_WM_DESTROY()
ON_WM_PAINT()
ON_WM_SIZE()
ON_WM_TIMER()
ON_WM_KEYDOWN()
ON_WM_ERASEBKGND()
ON_BN_CLICKED(IDOK, &CAboutDlg::OnBnClickedOk)
ON_BN_CLICKED(IDC_VIEW_DIST_PLUS, &CAboutDlg::OnBnClickedViewDistPlus)
ON_BN_CLICKED(IDC_VIEW_DIST_SUB, &CAboutDlg::OnBnClickedViewDistSub)
ON_BN_CLICKED(IDC_ROTATE_X_PLUS, &CAboutDlg::OnBnClickedRotateXPlus)
ON_BN_CLICKED(IDC_ROTATE_X_SUB, &CAboutDlg::OnBnClickedRotateXSub)
ON_BN_CLICKED(IDC_ROTATE_Y_PLUS, &CAboutDlg::OnBnClickedRotateYPlus)
ON_BN_CLICKED(IDC_ROTATE_Y_SUB, &CAboutDlg::OnBnClickedRotateYSub)
ON_BN_CLICKED(IDC_OPENGL_INFO, &CAboutDlg::OnBnClickedOpenglInfo)
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////////
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{ hDC = NULL;
hRC = NULL;
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{ CDialog::DoDataExchange(pDX);
}
///////////////////////////////////////////////////////////////////////////////
BOOL CAboutDlg::OnInitDialog()
{ CDialog::OnInitDialog();
//TODO: 在此添加额外的初始化
// For every window, we get the HDC
hDC =::GetDC(m_hWnd);
SetWindowPixelFormat(hDC);
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
glDrawBuffer(GL_BACK);
SetTimer(1, 30, NULL);
static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
static GLfloat red[4] = {0.8, 0.2, 0.2, 1.0};
static GLfloat green[4] = {0.2, 0.8, 0.2, 1.0};
static GLfloat blue[4] = {0.2, 0.2, 0.8, 1.0};
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
/* make the gears */
gear1 = glGenLists(1);
glNewList(gear1, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
gear(1.0, 4.0, 1.0, 20, 0.7);
glEndList();
gear2 = glGenLists(1);
glNewList(gear2, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
gear(0.5, 2.0, 2.0, 10, 0.7);
glEndList();
gear3 = glGenLists(1);
glNewList(gear3, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
gear(1.3, 2.0, 0.5, 10, 0.7);
glEndList();
glEnable(GL_NORMALIZE);
return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
///////////////////////////////////////////////////////////////////////////////
// CFirstOpenGlApp 消息处理程序
void CAboutDlg::OnBnClickedOk()
{ // TODO: 在此添加控件通知处理程序代码
OnOK();
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnClose()
{ // TODO: 在此添加消息处理程序代码和/或调用默认值
CDialog::OnClose();
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnDestroy()
{ CDialog::OnDestroy();
// TODO: 在此处添加消息处理程序代码
if(wglGetCurrentContext()!=NULL)
wglMakeCurrent(NULL, NULL); // make the rendering context not current
if(hRC!=NULL)
{ wglDeleteContext(hRC);
hRC = NULL;
}
if(m_hWnd!=NULL)
::ReleaseDC(m_hWnd, hDC);
glDeleteLists(gear1, 1);
glDeleteLists(gear2, 1);
glDeleteLists(gear3, 1);
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnPaint()
{ CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
RenderScene();
SwapBuffers(hDC);
// 不为绘图消息调用 CDialog::OnPaint()
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnSize(UINT nType, int cx, int cy)
{ CDialog::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
GLfloat h = 0.0f;
if(cx==0)
h = (GLfloat)cy;
else
h = (GLfloat)cy / (GLfloat)cx;
glViewport(0, 0, (GLint)cx, (GLint)cy);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -h, h, 5.0, 200.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnBnClickedViewDistPlus()
{ // TODO: 在此添加控件通知处理程序代码
//viewDist -= 0.1;
//InvalidateRect(NULL, FALSE);
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnBnClickedViewDistSub()
{ // TODO: 在此添加控件通知处理程序代码
//viewDist += 0.1;
//InvalidateRect(NULL, FALSE);
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnBnClickedRotateXPlus()
{ // TODO: 在此添加控件通知处理程序代码
view_roty += 5.0;
InvalidateRect(NULL, FALSE);
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnBnClickedRotateXSub()
{ // TODO: 在此添加控件通知处理程序代码
view_roty -= 5.0;
InvalidateRect(NULL, FALSE);
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnBnClickedRotateYPlus()
{ // TODO: 在此添加控件通知处理程序代码
view_rotx += 5.0;
InvalidateRect(NULL, FALSE);
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnBnClickedRotateYSub()
{ // TODO: 在此添加控件通知处理程序代码
view_rotx -= 5.0;
InvalidateRect(NULL, FALSE);
}
///////////////////////////////////////////////////////////////////////////////
BOOL CAboutDlg::OnEraseBkgnd(CDC* pDC)
{ // TODO: 在此添加消息处理程序代码和/或调用默认值
return FALSE;
//return CDialog::OnEraseBkgnd(pDC);
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnTimer(UINT_PTR nIDEvent)
{ // TODO: 在此添加消息处理程序代码和/或调用默认值
if(nIDEvent==1)
{ angle += 70.0; // 70 degrees per second
angle = fmod(angle, 360.0f); // prevents eventual overflow
//view_rotz += 5.0;
//RenderScene();
//SwapBuffers(hDC);
InvalidateRect(NULL, FALSE);
}
CDialog::OnTimer(nIDEvent);
}
///////////////////////////////////////////////////////////////////////////////
void CAboutDlg::OnBnClickedOpenglInfo()
{ // TODO: 在此添加控件通知处理程序代码
CString strTemp0("");
CString strTemp("");
strTemp0.Format("GL_RENDERER = %s\n", (char *)glGetString(GL_RENDERER));
strTemp += strTemp0;
strTemp0.Format("GL_VERSION = %s\n", (char *)glGetString(GL_VERSION));
strTemp += strTemp0;
strTemp0.Format("GL_VENDOR = %s\n", (char *)glGetString(GL_VENDOR));
strTemp += strTemp0;
strTemp0.Format("GL_EXTENSIONS = %s", (char *)glGetString(GL_EXTENSIONS));
strTemp += strTemp0;
AfxMessageBox(strTemp);
}
///////////////////////////////////////////////////////////////////////////////
//BOOL CAboutDlg::SetWindowPixelFormat(HDC hDC)
//{ PIXELFORMATDESCRIPTOR pixelDesc;
// pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
// pixelDesc.nVersion = 1;
//
// //pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP |
// // PFD_SUPPORT_OPENGL | PFD_SUPPORT_GDI | PFD_STEREO_DONTCARE;
// pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
// PFD_DOUBLEBUFFER | PFD_STEREO_DONTCARE;
// pixelDesc.iPixelType = PFD_TYPE_RGBA;
// pixelDesc.cColorBits = 32;
// pixelDesc.cRedBits = 8;
// pixelDesc.cRedShift = 16;
// pixelDesc.cGreenBits = 8;
// pixelDesc.cGreenShift = 8;
// pixelDesc.cBlueBits = 8;
// pixelDesc.cBlueShift = 0;
// pixelDesc.cAlphaBits = 0;
// pixelDesc.cAlphaShift = 0;
// pixelDesc.cAccumBits = 64;
// pixelDesc.cAccumRedBits = 16;
// pixelDesc.cAccumGreenBits = 16;
// pixelDesc.cAccumBlueBits = 16;
// pixelDesc.cAccumAlphaBits = 0;
// pixelDesc.cDepthBits = 32;
// pixelDesc.cStencilBits = 8;
// pixelDesc.cAuxBuffers = 0;
// pixelDesc.iLayerType = PFD_MAIN_PLANE;
// pixelDesc.bReserved = 0;
// pixelDesc.dwLayerMask = 0;
// pixelDesc.dwVisibleMask = 0;
// pixelDesc.dwDamageMask = 0;
//
// int m_GLPixelIndex = ChoosePixelFormat(hDC, &pixelDesc);
// if(m_GLPixelIndex==0) // Let's choose a default index.
// { m_GLPixelIndex = 1;
// if(DescribePixelFormat(hDC, m_GLPixelIndex, sizeof(PIXELFORMATDESCRIPTOR), &pixelDesc)==0)
// return FALSE;
// }
//
// if(SetPixelFormat(hDC, m_GLPixelIndex, &pixelDesc)==FALSE)
// return FALSE;
//
// return TRUE;
//}
BOOL CAboutDlg::SetWindowPixelFormat(HDC hDC)
{ PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL | // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
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
};
int iPixelFormat = 0;
// get the device context's best, available pixel format match
if((iPixelFormat = ChoosePixelFormat(hDC, &pfd))==0)
return FALSE;
// make that match the device context's current pixel format
if(SetPixelFormat(hDC, iPixelFormat, &pfd) == FALSE)
return FALSE;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// we will draw a simple 3D-Triangle
void CAboutDlg::RenderScene()
{ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();
//glTranslatef(0, 0, -viewDist);
glScalef(0.1f, 0.1f, 0.1f);
glRotatef(view_rotx, 1.0, 0.0, 0.0);
glRotatef(view_roty, 0.0, 1.0, 0.0);
glRotatef(view_rotz, 0.0, 0.0, 1.0);
glPushMatrix();
glTranslatef(-3.0, -2.0, 0.0);
glRotatef(angle, 0.0, 0.0, 1.0);
glCallList(gear1);
glPopMatrix();
glPushMatrix();
glTranslatef(3.1, -2.0, 0.0);
glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
glCallList(gear2);
glPopMatrix();
glPushMatrix();
glTranslatef(-3.1, 4.2, 0.0);
glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
glCallList(gear3);
glPopMatrix();
glPopMatrix();
}
///////////////////////////////////////////////////////////////////////////////
// 来自Mesa 的范例
void CAboutDlg::gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
GLint teeth, GLfloat tooth_depth)
{ GLint i;
GLfloat r0, r1, r2;
GLfloat angle, da;
GLfloat u, v, len;
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.0;
r2 = outer_radius + tooth_depth / 2.0;
da = 2.0 * M_PI / teeth / 4.0;
glShadeModel(GL_FLAT);
glNormal3f(0.0, 0.0, 1.0);
/* draw front face */
glBegin(GL_QUAD_STRIP);
for(i = 0; i <= teeth; i++)
{ angle = i * 2.0 * M_PI / teeth;
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
if(i < teeth)
{ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
}
}
glEnd();
/* draw front sides of teeth */
glBegin(GL_QUADS);
da = 2.0 * M_PI / teeth / 4.0;
for(i = 0; i < teeth; i++)
{ angle = i * 2.0 * M_PI / teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
}
glEnd();
glNormal3f(0.0, 0.0, -1.0);
/* draw back face */
glBegin(GL_QUAD_STRIP);
for(i = 0; i <= teeth; i++)
{ angle = i * 2.0 * M_PI / teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
if(i < teeth)
{ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
}
}
glEnd();
/* draw back sides of teeth */
glBegin(GL_QUADS);
da = 2.0 * M_PI / teeth / 4.0;
for(i = 0; i < teeth; i++)
{ angle = i * 2.0 * M_PI / teeth;
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
}
glEnd();
/* draw outward faces of teeth */
glBegin(GL_QUAD_STRIP);
for(i = 0; i < teeth; i++)
{ angle = i * 2.0 * M_PI / teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
u = r2 * cos(angle + da) - r1 * cos(angle);
v = r2 * sin(angle + da) - r1 * sin(angle);
len = sqrt(u * u + v * v);
u /= len;
v /= len;
glNormal3f(v, -u, 0.0);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
glNormal3f(cos(angle), sin(angle), 0.0);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
glNormal3f(v, -u, 0.0);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
glNormal3f(cos(angle), sin(angle), 0.0);
}
glVertex3f(r1 * cos(0.0f), r1 * sin(0.0f), width * 0.5);
glVertex3f(r1 * cos(0.0f), r1 * sin(0.0f), -width * 0.5);
glEnd();
glShadeModel(GL_SMOOTH);
/* draw inside radius cylinder */
glBegin(GL_QUAD_STRIP);
for(i = 0; i <= teeth; i++)
{ angle = i * 2.0 * M_PI / teeth;
glNormal3f(-cos(angle), -sin(angle), 0.0);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
}
glEnd();
}
///////////////////////////////////////////////////////////////////////////////
可执行文件如下,
该范例是本人在Mesa3d范例基础上改写的,原范例运行界面如下,
源代码如下,
存在问题:改写后齿轮的咬合没原来的好,三个齿轮分布在三个不同层面而不是在一个层面上,原因不明。
文章评论(0条评论)
登录后参与讨论