opengl实现曲柄连杆
一、程序要求
偶然翻到自己两年前写的一个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);//获取DCASSERT(m_hDC);//指定DC像素格式,填充数据结构static PIXELFORMATDESCRIPTOR pfdWnd ={sizeof(PIXELFORMATDESCRIPTOR), // Structure size.1, // Structure version number.结构版本,一般设置1PFD_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); //选择像素格式,选择成功就返回格式索引,否则返回0ASSERT(SetPixelFormat(m_hDC, pixelformat, &pfdWnd)); //为DC设置像素格式m_hRC = wglCreateContext(m_hDC); //创建RCVERIFY(wglMakeCurrent(m_hDC,m_hRC)); //激活RCSetupRC(); //渲染绘图VERIFY(wglMakeCurrent(NULL,NULL)); //关闭RCSetTimer(1,50,NULL); //计时器ID是1,每100毫秒变化
}void Copengl_homeworkView::Release()
{wglDeleteContext(m_hRC); //删除创建的RCKillTimer(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); //设定当前线程的渲染环境,设置当前RCRenderScene(); //具体绘制图形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); //设置材料属性GLfloat ambienlight[4] = {0.5,0.5,0.5,1}; //环境光GLfloat diffuselight[4] = {0.8,0.8,0.8,1}; //漫反射光GLfloat specularlight[4] = {1,1,1,1}; //镜面反射光GLfloat lightposition[4] = {-10,15,0,1}; //设置点光源,即最后一个参数是1glLightfv(GL_LIGHT0,GL_AMBIENT,ambienlight);glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuselight);glLightfv(GL_LIGHT0,GL_SPECULAR,specularlight);glLightfv(GL_LIGHT0,GL_POSITION,lightposition);glEnable(GL_LIGHT0);//启用光源0
}void Copengl_homeworkView::RenderScene() //渲染屏幕,在draw函数里面
{if (light) //如果打开灯标记位给了glEnable(GL_LIGHTING);elseglDisable(GL_LIGHTING);if (full) //如果填充标记位给了glPolygonMode(GL_FRONT,GL_FILL); //面填充elseglPolygonMode(GL_FRONT,GL_LINE); //线填充//由曲柄转过的角度计算连杆和摇杆角度if (alpha>=0 && alpha<180){double h = sqrt(L1*L1+L4*L4-2*L1*L4*cos(alpha/C));fai1 = asin(L1*sin(alpha/C)/h)*C;fai2 = acos((h*h+L3*L3-L2*L2)/2/h/L3)*C;fai = fai1+fai2;fai_yaogan = 180-fai; //摇杆的角度double xx = L4 + L3*cos((180-fai1-fai2)/C)-L1*cos(alpha/C);fai_liangan = acos(xx/L2)*57.3; //连杆的角度}if (alpha>=180 && alpha<270){double h = sqrt(L1*L1+L4*L4-2*L1*L4*cos(alpha/C));fai1 = asin(L1*sin((360-alpha)/C)/h)*C;fai2 = acos((L2*L2+h*h-L3*L3)/2/h/L2)*C;fai_liangan = fai1+fai2; //连杆的角度fai_yaogan = 180-(acos((L3*L3+h*h-L2*L2)/2/h/L3)*C-fai1);//摇杆的角度}if (alpha>=270&&alpha<360){double h = sqrt(L1*L1+L4*L4-2*L1*L4*cos(alpha/C));fai1 = asin(sin((360-alpha)/C)*L1/h)*C;fai2 = acos((L3*L3+h*h-L2*L2)/2/h/L3)*C;fai_yaogan = 180-(fai2-fai1);//摇杆的角度fai_liangan = acos((L2*L2+h*h-L3*L3)/2/h/L2)*C+fai1; //连杆的角度}glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix(); //最原始的坐标系glTranslatef(0,0,-60); //将物体向后平移,不然贴在脸上了glRotatef(xRot,1,0,0); //鼠标左键绕x轴旋转glRotatef(yRot,0,1,0); //鼠标左键绕y轴旋转DrawBasic(L4+6,W4,H4); //画长方体基座,给长宽高,坐标系在基座的后面中心glTranslatef(0,0,W4); //沿z轴正方向移动长方体基座的宽glTranslatef(-L4/2,0,0); //沿x轴负方向移动基座有效长度的一半,到基座左边圆柱中心DrawShaft(r,h0); //画基座左边圆柱,半径,高glTranslatef(L4,0,0); //沿x轴正方向移动基有效长度座在基座右边圆柱中心DrawShaft(r,h0); //画基座右边圆柱,半径,高glTranslatef(-L4,0,0); //沿x轴负方向移动基有效长度回到基座左边圆柱中心glPushMatrix(); //把在基座左边圆柱中心的坐标系存起来glRotatef(alpha,0,0,1); //绕z轴旋转alpha,画曲柄glTranslatef(L1/2,0,0); //把坐标轴移动到曲柄的中点DrawQuBing(L1,h_qubing,w_qubing,1,0,0); //红色的曲柄glPopMatrix(); //把在基座左边圆柱中心的坐标系放出来glPushMatrix(); //把在基座左边圆柱中心的坐标系存起来glTranslatef(L4,0,0); //沿x轴正方向移动基座有效长度回到右边圆柱中心glRotatef(fai_yaogan,0,0,1); //旋转摇杆角度glTranslatef(L3/2,0,0); //把坐标轴移动到的摇杆中点DrawQuBing(L3,h_qubing,w_qubing,0,1,0); //绿色的摇杆//画完绿色的摇杆后,画连杆glTranslatef(L3/2,0,-h1/2+h_qubing); //连杆的圆柱比摇杆的大DrawShaft(r,h1); //把摇杆的圆柱画好了glPopMatrix(); //把基座左边圆柱的坐标系放出来glPushMatrix(); //把在基座左边圆柱中心的坐标系存起来glRotatef(alpha,0,0,1); //旋转曲柄角度大小glTranslatef(L1,0,0); //将坐标系沿x正方向移动曲柄有效长度glRotatef(-alpha,0,0,1); //再将坐标系转正glRotatef(fai_liangan,0,0,1); //坐标系旋转连杆的角度大小glTranslatef(L2/2,0,h_qubing); //将坐标系移动到连杆的后面中心DrawQuBing(L2,h_qubing,w_qubing,0.5,0.5,0); //画连杆glTranslatef(-L2/2,0,-h1/2); //将坐标系移动到连杆左端螺钉的底部DrawShaft(r,h1); //画连杆左端的圆柱,即螺钉glPopMatrix(); //把基座左边圆柱的坐标系放出来
glPopMatrix(); //回到原始坐标系观察物体
}void Copengl_homeworkView::OnFilePrintPreview()
{#ifndef SHARED_HANDLERSAFXPrintPreview(this);
#endif
}BOOL Copengl_homeworkView::OnPreparePrinting(CPrintInfo* pInfo)
{// 默认准备return DoPreparePrinting(pInfo);
}void Copengl_homeworkView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{// TODO: 添加额外的打印前进行的初始化过程
}void Copengl_homeworkView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{// TODO: 添加打印后进行的清理过程
}void Copengl_homeworkView::OnContextMenu(CWnd* /* pWnd */, CPoint point)
{#ifndef SHARED_HANDLERStheApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}#ifdef _DEBUG
Copengl_homeworkDoc* Copengl_homeworkView::GetDocument() const // 非调试版本是内联的
{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(Copengl_homeworkDoc)));return (Copengl_homeworkDoc*)m_pDocument;
}
#endif //_DEBUGvoid Copengl_homeworkView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{if (nChar==VK_RETURN)//回车键{enter_flag = true;}if (nChar=='s'||nChar=='S')//停止{enter_flag = false;}if(nChar=='l'||nChar=='L')//开灯{if (!light)light = true;elselight = false;}CView::OnKeyDown(nChar, nRepCnt, nFlags);
}void Copengl_homeworkView::OnMouseMove(UINT nFlags, CPoint point)
{if (leftbutton_flag)//鼠标左键按下{xRot = point.y-old_point.y;yRot = point.x-old_point.x;}Invalidate();CView::OnMouseMove(nFlags, point);
}void Copengl_homeworkView::OnDestroy()
{Release(); //先释放RCCView::OnDestroy();
}void Copengl_homeworkView::OnLButtonDown(UINT nFlags, CPoint point)//鼠标左键按下
{old_point = point;leftbutton_flag = true;CView::OnLButtonDown(nFlags, point);
}void Copengl_homeworkView::OnTimer(UINT_PTR nIDEvent)//计时器的ID
{if (nIDEvent==1 && enter_flag==1){alpha+=angle;if (alpha>=360){alpha = 0;}}Invalidate(FALSE);CView::OnTimer(nIDEvent);
}void Copengl_homeworkView::DrawBasic(double length,double width,double height)
{GLfloat materialAmbient[] = {0.5f, 0.5f, 0.5f, 1.0f}; //材质环境光GLfloat materialDiffuse[] = {0.5f, 0.5f, 0.5f, 1.0f}; //材质漫射光GLfloat materialSpecular[] = {0.3f, 0.3f, 0.3f, 1.0f}; //材质反射光GLfloat materialShininess = 10.0f; //高光反射区域glMaterialfv(GL_FRONT, GL_AMBIENT, materialAmbient); //材质环境光属性glMaterialfv(GL_FRONT, GL_DIFFUSE, materialDiffuse); //设置材质漫射光属性glMaterialfv(GL_FRONT, GL_SPECULAR, materialSpecular); //设置材质反射光属性glMaterialf(GL_FRONT, GL_SHININESS, materialShininess); //设置高光反射区域glColor3f(0.4,0,0.4);//设置基座颜色glBegin(GL_POLYGON);glNormal3f(0,1,0);glVertex3f(-length/2,height/2,0);//上面glVertex3f(-length/2,height/2,width);glVertex3f(length/2,height/2,width);glVertex3f(length/2,height/2,0);glEnd();glBegin(GL_POLYGON);//右面glNormal3f(1,0,0);glVertex3f(length/2,height/2,0);glVertex3f(length/2,height/2,width);glVertex3f(length/2,-height/2,width);glVertex3f(length/2,-height/2,0);glEnd();glBegin(GL_POLYGON);//下面glNormal3f(0,-1,0);glVertex3f(length/2,-height/2,width);glVertex3f(-length/2,-height/2,width);glVertex3f(-length/2,-height/2,0);glVertex3f(length/2,-height/2,0);glEnd();glBegin(GL_POLYGON);//左面glNormal3f(-1,0,0);glVertex3f(-length/2,-height/2,0);glVertex3f(-length/2,-height/2,width);glVertex3f(-length/2,height/2,width);glVertex3f(-length/2,height/2,0);glEnd();glBegin(GL_POLYGON);//后面glNormal3f(0,0,-1);glVertex3f(-length/2,height/2,0);glVertex3f(length/2,height/2,0);glVertex3f(length/2,-height/2,0);glVertex3f(-length/2,-height/2,0);glEnd();glBegin(GL_POLYGON);//前面glNormal3f(0,0,1);glVertex3f(-length/2,height/2,width);glVertex3f(-length/2,-height/2,width);glVertex3f(length/2,-height/2,width);glVertex3f(length/2,height/2,width);glEnd();
}void Copengl_homeworkView::DrawShaft(double r,double height)//画圆柱
{GLUquadricObj *pObj; // Quadric ObjectpObj = gluNewQuadric(); //管理二次方程的gluQuadricNormals(pObj, GLU_SMOOTH);GLfloat materialAmbient[] = {0.5f, 0.5f, 0.5f, 1.0f}; //材质环境光GLfloat materialDiffuse[] = {0.5f, 0.5f, 0.5f, 1.0f}; //材质漫射光GLfloat materialSpecular[] = {0.5f, 0.5f, 0.5f, 1.0f}; //材质反射光GLfloat materialShininess = 10.0f; //高光反射区域glMaterialfv(GL_FRONT, GL_AMBIENT, materialAmbient); //材质环境光属性glMaterialfv(GL_FRONT, GL_DIFFUSE, materialDiffuse); //设置材质漫射光属性glMaterialfv(GL_FRONT, GL_SPECULAR, materialSpecular); //设置材质反射光属性glMaterialf(GL_FRONT, GL_SHININESS, materialShininess); //设置高光反射区域glPushMatrix();glColor3f(0,0,1); //左边圆柱是蓝色gluCylinder(pObj,r,r,height,360,300); //z轴周围的细分数和沿z轴的细分数glTranslatef(0,0,height); //给圆柱加一个顶面glColor3f(0,0,1); //圆柱顶面是蓝色glBegin(GL_POLYGON);for (double angle=0;angle<=360;angle+=1){glVertex2f(r*cos(angle/C),r*sin(angle/C));}glEnd(); //把圆柱上面的盖子画完了glTranslatef(0,0,-height); //给圆柱加一个底面glBegin(GL_POLYGON);for (double angle=360;angle>=0;angle-=1){glVertex2f(r*cos(angle/C),r*sin(angle/C));}glEnd(); //把圆柱下面的盖子画完了glPopMatrix();gluDeleteQuadric(pObj);
}void Copengl_homeworkView::DrawQuBing(double length,double width,double height,double red,double green,double blue)//长方体的宽是圆柱高,长方体的高是圆柱的直径
{//设置材质属性GLfloat materialAmbient[] = {0.5f, 0.5f, 0.5f, 1.0f}; //材质环境光GLfloat materialDiffuse[] = {0.5f, 0.5f, 0.5f, 1.0f}; //材质漫射光GLfloat materialSpecular[] = {0.3f, 0.3f, 0.3f, 1.0f}; //材质反射光GLfloat materialShininess = 10.0f; //高光反射区域glMaterialfv(GL_FRONT, GL_AMBIENT, materialAmbient); //材质环境光属性glMaterialfv(GL_FRONT, GL_DIFFUSE, materialDiffuse); //设置材质漫射光属性glMaterialfv(GL_FRONT, GL_SPECULAR, materialSpecular); //设置材质反射光属性glMaterialf(GL_FRONT, GL_SHININESS, materialShininess); //设置高光反射区域glColor3f(red,green,blue);//设置曲柄颜色glBegin(GL_POLYGON);glNormal3f(0,1,0);glVertex3f(-length/2,height/2,0);//上面glVertex3f(-length/2,height/2,width);glVertex3f(length/2,height/2,width);glVertex3f(length/2,height/2,0);glEnd();glBegin(GL_POLYGON);//右面glNormal3f(1,0,0);glVertex3f(length/2,height/2,0);glVertex3f(length/2,height/2,width);glVertex3f(length/2,-height/2,width);glVertex3f(length/2,-height/2,0);glEnd();glBegin(GL_POLYGON);//下面glNormal3f(0,-1,0);glVertex3f(length/2,-height/2,width);glVertex3f(-length/2,-height/2,width);glVertex3f(-length/2,-height/2,0);glVertex3f(length/2,-height/2,0);glEnd();glBegin(GL_POLYGON);//左面glNormal3f(-1,0,0);glVertex3f(-length/2,-height/2,0);glVertex3f(-length/2,-height/2,width);glVertex3f(-length/2,height/2,width);glVertex3f(-length/2,height/2,0);glEnd();glBegin(GL_POLYGON);//后面glNormal3f(0,0,-1);glVertex3f(-length/2,height/2,0);glVertex3f(length/2,height/2,0);glVertex3f(length/2,-height/2,0);glVertex3f(-length/2,-height/2,0);glEnd();glBegin(GL_POLYGON);//前面glNormal3f(0,0,1);glVertex3f(-length/2,height/2,width);glVertex3f(-length/2,-height/2,width);glVertex3f(length/2,-height/2,width);glVertex3f(length/2,height/2,width);glEnd();GLUquadricObj *pObj; pObj = gluNewQuadric();gluQuadricNormals(pObj, GLU_SMOOTH);glPushMatrix(); glTranslatef(-length/2,0.0f,0.0f); glColor3f(red,green,blue); //圆柱和曲柄一个颜色gluCylinder(pObj,height/2,height/2,width,360,300); glTranslatef(0.0f,0.0f,width);//给圆柱加个顶面glBegin(GL_POLYGON);for (double angle=0;angle<=360;angle+=1){glVertex2f(height/2*cos(angle/C),height/2*sin(angle/C));}glEnd();glTranslatef(0.0f,0.0f,-width);glBegin(GL_POLYGON); //加圆柱底面for (double angle=360;angle>=0;angle-=1){glVertex2f(height/2*cos(angle/C),height/2*sin(angle/C));}glEnd();glTranslatef(length,0.0f,0);//画上面的圆柱gluCylinder(pObj,height/2,height/2,width,360,300);glTranslatef(0,0.0f,width);glBegin(GL_POLYGON);for (double angle=0;angle<=360;angle+=1){glVertex2f(height/2*cos(angle/C),height/2*sin(angle/C));}glEnd();glTranslatef(0,0.0f,-width);//画底面glBegin(GL_POLYGON);for (double angle=360;angle>=0;angle-=1){glVertex2f(height/2*cos(angle/C),height/2*sin(angle/C));}glEnd();glPopMatrix();//曲柄长方体的坐标系再出来gluDeleteQuadric(pObj);
}BOOL Copengl_homeworkView::OnEraseBkgnd(CDC* pDC)//重载背景擦除函数避免窗口闪烁
{return TRUE;
}void Copengl_homeworkView::OnSize(UINT nType, int cx, int cy)
{CView::OnSize(nType, cx, cy);VERIFY(wglMakeCurrent(m_hDC,m_hRC));Resize(cx,cy);VERIFY(wglMakeCurrent(NULL,NULL));
}void Copengl_homeworkView::OnRButtonDown(UINT nFlags, CPoint point)//右键点下去消息处理函数
{CMenu menu;menu.LoadMenuW(IDR_MENU1); //加载菜单ClientToScreen(&point); //将屏幕坐标转换成客户坐标,point是客户坐标menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON,point.x,point.y,GetParent());//创建一个浮动的菜单CView::OnRButtonDown(nFlags, point);
}void Copengl_homeworkView::On32773()//线填充
{full = false;Invalidate(FALSE);
}void Copengl_homeworkView::On32774()//面填充
{full = true;Invalidate(FALSE);
}void Copengl_homeworkView::On32775()//高速旋转
{angle = 80;Invalidate(FALSE);
}void Copengl_homeworkView::On32776()//中速旋转
{angle = 40;Invalidate(FALSE);
}void Copengl_homeworkView::On32777()//低速旋转
{angle = 10;Invalidate(FALSE);
}void Copengl_homeworkView::OnLButtonUp(UINT nFlags, CPoint point)//鼠标左键一起来就不旋转角度了
{leftbutton_flag = false;CView::OnLButtonUp(nFlags, point);
}
四、函数说明
函数 | 函数说明 |
---|---|
Copengl_homeworkView | 构造函数,进行全局变量的初始化 |
PreCreateWindow | 修改窗口类或样式 |
OnCreate | 建立窗口 |
Init | 设置像素格式和RC的创建,设置计时器 |
Resize | 设置窗口大小 |
OnDraw | 绘图函数 |
SetupRC | 启用阴影平滑、深度测试等,设置光和材料属性 |
RenderScene | 渲染屏幕 |
OnKeyDown | 按下enter键使曲柄逆时针旋转,按下L或者l键开灯或关灯,按下S或者s键停止运动 |
OnMouseMove | 鼠标移动消息响应函数,如果鼠标左键按下并移动,就旋转机构 |
OnDestroy | 释放RC,再释放窗口资源 |
OnTimer | 如果enter键按下,每隔计时器设定时间就触发曲柄旋转一个角度,造成机构运动 |
DrawBasic | 绘制基座,六个面依次绘制,面的正方向为逆时针方向 |
DrawShaft | 绘制轴,即机构中的螺钉,调用gluCylinder函数绘制圆柱,再绘制圆柱的上下底面 |
DrawQuBing | 绘制曲柄,曲柄由一个长方体两端加圆柱组成 |
OnEraseBkgnd | 重载背景擦除函数避免窗口闪烁 |
OnSize | 改变窗口大小消息响应函数 |
OnRButtonDown | 右键按下消息响应函数,弹出速度和填充模式菜单 |
OnLButtonUp | 鼠标左键起来消息响应函数 |
五、程序测试
1.执行程序默认显示
2.拖动鼠标左键旋转机构
3.按下enter键曲柄逆时针旋转,按下S或者s键停止运动
4.右键按下弹出菜单,选择运动速度和填充模式
六、当时的心得
之前没有接触过Opengl,但是接触过MFC,所以上手还较快。绘制点,线,面,建模,变换,颜色设置,深度测试,阴影平滑等,熟悉RC和DC,让自己了解到最基本的图形显示是怎么一回事,感觉Opengl是一个很大的库,封装了很多函数,功能太强大。
这次画图,在画长方形平面的时候,忘了绘制面的点是有逆时针顺时针顺序的,显示老不对,绕了一些弯子,直到看到自己写了规定逆时针为面的正方向才反应过来。
opengl实现曲柄连杆相关推荐
- 精密压接之曲柄连杆模型计算(含MATLAB仿真+博途SCL源代码)
曲柄连杆机构和凸轮曲线计算在工程里有大量应用,这篇博客主要给出曲柄连杆机构的位移和曲柄转动角度之间的关系方程,有关凸轮的相关内容可以参看下面的文章链接: 凸轮表(ECAM)的本质-运动控制轨迹规划(线 ...
- virtual lab motion对连杆载荷进行扫速瀑布图及阶次切片分析
对动载荷,影响系统强度和NVH性能除了载荷的大小,还有载荷的频率,即载荷变化的快慢.如果系统含有旋转件,则载荷的频率分布和转速有一定的关系,常采用瀑布图及阶次切片进行分析. 主要步骤:利用Motion ...
- 套上这个壳,手机自己“跑步”去充电
贾浩楠 发自 凹非寺 量子位 报道 | 公众号 QbitAI 周末好不容易休息,瘫在床上的你连给手机充电都懒得动-- 可以满足你!首尔国立大学生物机器人实验室开发出了"进击的手机壳" ...
- catia知识工程_【开团】CATIA超全直播课程&实例讲解!
为了广大盟友的学习需求 我们特别为盟友们准备这次 "超值.超全.超量" 的CATIA全面直播课 更是业界大牛:小狼老师 全程授课! 越多报名! 越多优惠! (开团人数只要达到折扣要 ...
- 【meArm机械臂】第一篇·结构设计及搭建
系列文章目录 [meArm机械臂]第一篇·结构设计及搭建 [meArm机械臂]第二篇·Arduino控制程序 文章目录 系列文章目录 前言 一.机械臂搭建 1.结构分析 a.底盘 b.大臂 c.小臂 ...
- 如何用计算机算出男朋友的身高,【趣味物理】如何用物理方法测出男生的真实身高?...
原标题:[趣味物理]如何用物理方法测出男生的真实身高? 毕导,本名毕啸天,清华大学化工系博士生,今日头条优质科普内容创作者. 如何测出男生的真实身高? 男生常常会隐瞒身高,173敢报178,175就敢 ...
- 清华计算机博士蓝宴翔的工作是,毕啸天:清华博士玩成“科研段子手”
小亮 说到理工博士,许多人印象中的他们木讷无趣,似乎除了工作和试验再无所好,简直是一群不解风情的书呆子.实则不然,清华理工博士毕啸天,在个人公众号上写的近百篇科普类段子,诸如<跳一跳攻略> ...
- 汽车空调、刮水器和车窗控制
一.汽车空调 1.汽车空调概述 空调的主要功能是调节空气的温度.湿度.清洁度以及气流的流动性这四个要素.其中温度的调节是最主要的. 汽车空调系统一般为非独立式的机组,其运转动力直接取自汽车发动机.并通 ...
- matlab单缸内燃机设计
已知活塞的行程为216mm,进气门控制杆的行程为13mm. 1.设计曲柄滑块机构,分析所设计机构的最小传动角,若机构运动时存在问题,请提出解决方案. 2.取基圆半径为30mm,自拟进气门控制杆运动规律 ...
最新文章
- laravel mysql like_Laravel数据库查询中对 like 的值进行转义
- C++虚继承内存布局===写得很牛!推荐
- Simulink仿真---SPWM算法
- cta策略 有哪些_CTA 主流的交易策略都有哪些?
- 唐山师范学院计算机论文,唐山师范学院校园网络解决方案 毕业论文
- sc925 文档服务器,dell服务器磁盘阵列配置手册.docx
- fg jobs bg
- 解决办法:Transport security has blocked a cleartext HTTP (http://) resource load since it is insecure. T
- 软件工程简答题和应用题
- 银行新一代信息系统项目集群管理实践分享︱秦皇岛银行信息科技部总经理王登峰
- 计算机网络的三级结构是什么,计算机的三级存储结构是什么
- Android的View事件分发机制原理
- 2021,自动驾驶的“五代十国”
- 不要让优秀的现有客户蒙蔽了你未来的客户
- abb式c语言,ABB机器人是用什么语言编程的? ——ABB机器人
- 深度学习可解释性研究(二): Understanding Black-box Predictions via Influence Functions(详细公式推导)
- WIFI性能测试二 --- wifi的ANI功能
- 5秒钟用google earth engine(GEE)填补Landsat7条带问题
- blank=True, null=True的区别
- Android开发视频教程大总结—23部视频教程
热门文章
- 薄荷油为什么可以使人感觉凉爽
- 无法调用独显,nvidia-setting打开失败
- 推荐三款鲜为人知的gif制作工具,原来表情包是这样做的!
- 基于网管的企业IT管理解决方案
- 春节假期已步入尾声,正在找实习的大学生们,工作有着落了吗?
- 如何给台式计算机风扇加油,正确给风扇上油的过程,入门必看哦
- 华为畅玩5 (CUN-AL00) 刷入第三方twrp Recovery 及 root
- 2、“精细数据化标题“进阶之“数据化选款”第一节
- SO_REUSEADDR 套接字,解决(Address already in ues)问题
- MMSegmentation V0.27.0训练与推理自己的数据集(二)