一、程序要求
偶然翻到自己两年前写的一个opengl实现的曲柄连杆机构程序,内容分为设计要求、主要代码及函数说明、设计方法三大块。编程环境是vs2010,窗口是MFC设计,注释都已详细解释。
•图形显示要求:
1、利用opengl实现附件的零件动画显示
2、具体尺寸自定
3、可以使用学过的各种显示方法
•菜单要求,利用鼠标右键选择菜单项
1、利用鼠标右键弹出两个菜单
2、运动速度选择:高中低三档
3、填充图选择:线框图、填充图
•窗口无要求,可以是DOS窗口,也可以是MFC Window风格窗口
二、设计方法
1.新建MFC应用程序,项目名称是opengl_homework
2.在opengl_homeworkView.h声明函数和全局变量,在opengl_homeworkView.cpp中定义函数
4. 把机构各个零件尺寸设置为全局变量,方便修改尺寸
5.设置DC像素格式、光源、创建RC、设置计时器等。
6.在OnDraw函数中渲染屏幕,绘制具体图形
7. 在已知各个零件的尺寸及曲柄的旋转角度条件下,利用正弦定理和余弦定理计算摇杆和连杆的旋转角度,确定了机构的运动方式
8.在世界坐标系中将当前绘图坐标系保存
9.将当前绘图坐标系沿Z轴负方向平移适当距离以便观察物体
10.完成拖动鼠标左键改变观察物体方向的操作
11.绘制长方体基座,坐标原点在基座后面中心
12. 沿Z轴正方向移动长方体基座的宽
13.沿X轴负方向移动基座有效长度的一半,到基座左边圆柱中心
14.绘制基座左边圆柱,给半径,高参数
15.沿X轴正方向移动基有效长度座在基座右边圆柱中心
16.画基座右边圆柱,给半径,高参数
17.沿X轴负方向移动基有效长度回到基座左边圆柱中心
18.把在基座左边圆柱中心的坐标系存起来
19.绕Z轴旋转alpha,画曲柄
20.把坐标轴移动到曲柄的中点
21.绘制红色的曲柄
22.把在基座左边圆柱中心的坐标系放出来
23.把在基座左边圆柱中心的坐标系存起来
24.沿x轴正方向移动基座有效长度回到右边圆柱中心
25.旋转摇杆角度
26.把坐标轴移动到的摇杆中点
27.绘制绿色的摇杆
28.绘制完绿色的摇杆后,画连杆
29.因为连杆螺钉高度比摇杆厚度大,所以沿Z轴负方向移动(螺钉高度/2-曲柄厚度)距离
30.绘制链接连杆和摇杆、曲柄的螺钉
31.把基座左边圆柱的坐标系放出来
32.把在基座左边圆柱中心的坐标系存起来
33.旋转曲柄角度大小
34.将坐标系沿X正方向移动曲柄有效长度
35.再将坐标系转正
36.坐标系旋转连杆的角度大小
37.将坐标系移动到连杆的后面中心
38.画连杆
39.将坐标系移动到连杆左端螺钉的底部
40.画连杆左端的圆柱,即螺钉
41.把基座左边圆柱的坐标系放出来
42.回到原始坐标系观察物体
三、主要代码
#include "stdafx.h"
#ifndef SHARED_HANDLERS
#include "opengl_homework.h"
#endif
#include "opengl_homeworkDoc.h"
#include "opengl_homeworkView.h"
#include "gl\GL.h"
#include "gl\GLU.h"
#include "gl\glut.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define C 57.2958
IMPLEMENT_DYNCREATE(Copengl_homeworkView, CView)
BEGIN_MESSAGE_MAP(Copengl_homeworkView, CView)
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &Copengl_homeworkView::OnFilePrintPreview)
ON_WM_CONTEXTMENU()
ON_WM_KEYDOWN()
ON_WM_MOUSEMOVE()
ON_WM_DESTROY()
ON_WM_LBUTTONDOWN()
ON_WM_TIMER()
ON_WM_CREATE()
ON_WM_ERASEBKGND()
ON_WM_SIZE()
ON_WM_RBUTTONDOWN()
ON_COMMAND(ID_32773, &Copengl_homeworkView::On32773)
ON_COMMAND(ID_32774, &Copengl_homeworkView::On32774)
ON_COMMAND(ID_32775, &Copengl_homeworkView::On32775)
ON_COMMAND(ID_32776, &Copengl_homeworkView::On32776)
ON_COMMAND(ID_32777, &Copengl_homeworkView::On32777)
ON_WM_LBUTTONUP()
END_MESSAGE_MAP()
Copengl_homeworkView::Copengl_homeworkView()
{
m_hDC = NULL;
m_hRC = NULL;
xRot = 0; //鼠标左键旋转角度
yRot = 0;
alpha = 45; //曲柄初始化角度
L1 = 10; //曲柄有效长度
L2 = 26; //连杆有效长度
L3 = 12; //摇杆有效长度
L4 = 24; //基座有效长度
r = 1; //所有螺钉的半径
h0 = 2; //基座上螺钉高度
h1 = 4; //连杆螺钉高度
h_qubing = 1; //曲柄的厚度
w_qubing = 3; //曲柄的宽
W4 = 10; //基座的宽
H4 = 8; //基座的高
angle = 10; //每一帧变化的角度
enter_flag = false;
light = true; //开启灯光
full = true; //初始化面填充
leftbutton_flag = false;
}
Copengl_homeworkView::~Copengl_homeworkView()
{
}
BOOL Copengl_homeworkView::PreCreateWindow(CREATESTRUCT& cs)
{
// CREATESTRUCT cs 来修改窗口类或样式
cs.style |= WS_CLIPSIBLINGS|WS_CLIPCHILDREN|CS_OWNDC;//增加属性
return CView::PreCreateWindow(cs);
}
int Copengl_homeworkView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
Init(); //像素格式的设置和RC的创建
return 0;
}
void Copengl_homeworkView::Init()
{
m_hDC = ::GetDC(m_hWnd);//获取DC
ASSERT(m_hDC);
//指定DC像素格式,填充数据结构
static PIXELFORMATDESCRIPTOR pfdWnd =
{
sizeof(PIXELFORMATDESCRIPTOR), // Structure size.
1, // Structure version number.结构版本,一般设置1
PFD_DRAW_TO_WINDOW | // Property flags. 使之能在窗口或者其他设备上画图
PFD_SUPPORT_OPENGL | //使之能使用opengl函数
PFD_DOUBLEBUFFER, //指明使用了双缓冲
PFD_TYPE_RGBA, //定义显示颜色的方法
24, // 24-bit color.制定了一个颜色的位数
0, 0, 0, 0, 0, 0, // Not concerned with these.
0, 0, 0, 0, 0, 0, 0, // No alpha or accum buffer.
32, // 32-bit depth buffer.
0, 0, // No stencil or aux buffer.
PFD_MAIN_PLANE, // Main layer type.
0, // Reserved.
0, 0, 0 // Unsupported.
};
int pixelformat;
pixelformat = ChoosePixelFormat(m_hDC, &pfdWnd); //选择像素格式,选择成功就返回格式索引,否则返回0
ASSERT(SetPixelFormat(m_hDC, pixelformat, &pfdWnd)); //为DC设置像素格式
m_hRC = wglCreateContext(m_hDC); //创建RC
VERIFY(wglMakeCurrent(m_hDC,m_hRC)); //激活RC
SetupRC(); //渲染绘图
VERIFY(wglMakeCurrent(NULL,NULL)); //关闭RC
SetTimer(1,50,NULL); //计时器ID是1,每100毫秒变化
}
void Copengl_homeworkView::Release()
{
wglDeleteContext(m_hRC); //删除创建的RC
KillTimer(1); //删除计时器
::ReleaseDC(m_hWnd,m_hDC); //释放窗口和DC,释放DC,使其他应用程序可以使用
}
void Copengl_homeworkView::Resize(int width,int height)
{
GLfloat w_h;
glViewport(0,0,width,height); //为了选择一个更小的绘图区域,将图像映射到像素矩形中,根据窗口的变化实时重绘窗口
w_h = (GLfloat)width/(GLfloat)height;
glMatrixMode(GL_PROJECTION); //对接下来要做什么进行声明 这里是投影,投影下面有系列函数
glLoadIdentity(); //把矩阵设置为单位矩阵
gluPerspective(45,w_h,5,155); //指定视野角度,y轴的上下方向 物体的宽高比 近平面距离 远平面距离
glMatrixMode(GL_MODELVIEW); //模型视图
glLoadIdentity();
}
void Copengl_homeworkView::OnDraw(CDC* pDC)
{
wglMakeCurrent(m_hDC,m_hRC); //设定当前线程的渲染环境,设置当前RC
RenderScene(); //具体绘制图形
SwapBuffers(m_hDC); //交换缓存
wglMakeCurrent(m_hDC,NULL); //非当前化RC
}
void Copengl_homeworkView::SetupRC() //打底初始化,在初始化函数里面
{
glShadeModel(GL_SMOOTH); //启用阴影平滑
glEnable(GL_DEPTH_TEST); //启用深度测试
glFrontFace(GL_CCW); //逆时针方面为正面
glEnable(GL_CULL_FACE); //不计算面的反面内部
glClearColor(1,1,1,1); //最后一个参数是透明度
glEnable(GL_COLOR_MATERIAL); //开启灯光后显示材料颜色
glLightModeli(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);