用openGL做一个时钟动画

本文介绍了一个使用OpenGL绘制动态时钟的程序。通过定时更新时、分、秒针的位置,实现了时钟指针的实时转动效果。同时,文章还展示了如何绘制时钟圆面及其刻度线,并介绍了OpenGL的基本绘图函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<stdlib.h>
#include<glut.h>
#include<gl\GLU.h>
#include<gl\GL.h>
#include<math.h>
#include<stdio.h>
#include<windows.h>

float tite = 0.0f;
const float PI = 3.14159f;
const int W_width = 500;
const int W_height = 500;
float xc, yc, R, n;
float ss, mm, hh;
const int S_width = glutGet(GLUT_SCREEN_WIDTH);
const int S_height = glutGet(GLUT_SCREEN_HEIGHT);

//system
void init();
void draw();
void reShape(int ww, int hh);

//colck
void drawCircle();
void myIdle();
void drawline();
void TimerFunc(int value);
void arith_foot();
void drawshortLine();
void TimerFunc(int value);

void init(){
	glClear(GL_COLOR_BUFFER_BIT);
	glClearColor(1.0f, 0.5f, 0.8f, 1.0);
	//colck
	SYSTEMTIME Timetite;
	GetLocalTime(&Timetite);
	xc = 0.0f, yc = 0.0f, R = 100.0f, n = 20.0f, ss = Timetite.wSecond, mm = Timetite.wMinute, hh = Timetite.wHour;
}
int main(int agrs, char **args) {
	glutInit(&agrs, args);
	init();
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(W_width, W_height);
	glutInitWindowPosition((S_width - W_width) / 2, (S_height - W_width) / 2);
	glutCreateWindow("openGL");
	//设置视景体窗口

	glClearColor(0.6f, 0.4f, 0.3f, 1.0f); //清除窗口颜色的代码
	glutDisplayFunc(draw);
	glutReshapeFunc(reShape);
	glutMainLoop();
	return 0;
}

void draw(void) {
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0f, 0.0f, 0.0f);
	drawCircle();
	arith_foot();
	drawshortLine();
	//TimerFunc(10);
	glutTimerFunc(1000, TimerFunc, 10);
	//drawline();
	glutSwapBuffers();
	//shapes
}
void reShape(int ww, int hh) {
	glViewport(0, 0, ww, hh);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (hh == 0) hh = 1;
	if (ww >= hh) {
		gluOrtho2D(-500, 500 * (float)ww / hh, -500, 500);
	}
	else
	{
		gluOrtho2D(-500, 500, -500, 500 * (float)hh / ww);
	}
	glMatrixMode(GL_MODELVIEW);
}
//利用基本图元的绘制来实现简单动画的功能(时钟)
//draw circle
void drawCircle() {
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < n; i++) {
		glVertex2d(xc + R * cos(i * 2 * PI / n), yc + R * sin(i * 2 * PI / n));
	}
	glEnd();
}//画出时钟圆
//直线测试
void drawline() {
	glBegin(GL_LINES);
	glVertex2d(xc, yc);
	glVertex2d(R*cos(tite), R*sin(tite));
	glEnd();
}
//闲置函数
void myIdle(void) {
	tite += 0.002f;
	if (tite >= 2 * PI) {
		tite = 0.0f;
	}
	glutPostRedisplay();
}
void TimerFunc(int value) {//更新时分秒的值
	int carry1 = 0;
	ss += 1;
	if (ss >= 60) {
		ss = 0;
		carry1 = 1;
	}
	mm += carry1;
	int carry2 = 0;
	if (mm >= 60) {
		carry2 = 1;
		mm = 0;
	}
	hh += carry2;
	if (hh == 24) hh = 0;
	glutPostRedisplay();//(回调函数)返回draw方法根据ss,mm,hh更新xs,xm,xh的刻度值
}
//draw hh,ss,mm lines(绘制时针与分针的刻度线)
void drawshortLine(){
	int lines = 60;
	for (int i = 0; i < lines;i++){
		if (i % 5 == 0){//时针
			glLineWidth(5);
			glColor3f(0.0, 1.0, 0.0);
			glBegin(GL_LINES);
			glVertex2f(xc + (R-10)*sin(2*PI*i/lines),yc+(R-10)*cos(2*PI*i/lines));
			glVertex2f(xc + R*sin(2 * PI*i / lines), yc + R*cos(2 * PI*i / lines));
			glEnd();
		}
		else{
			glLineWidth(2);
			glColor3f(0.0,0.0,1.0);
			glBegin(GL_LINES);
			glVertex2f(xc+(R-5)*sin(2*PI*i/lines),yc+(R-5)*cos(2*PI*i/lines));
			glVertex2f(xc + R*sin(2 * PI*i / lines), yc + R*cos(2 * PI*i / lines));
			glEnd();
		}
	}	
}
//arith foot colck(每一次调用draw方法的时候都会根据此时不同的ss,mm,hh重新计算时分秒指针的值)
void arith_foot(){
	float xs = 0.0f, ys=0.0f, xm=0.0f, ym=0.0f, xh=0.0f, yh=0.0f;
	glLineWidth(1);
	xs = xc + (R-10)*sin(ss*2*PI/60);//根据比值法计算出秒针与y轴之间的角度来计算x终点位置与y终点位置
	ys = yc + (R - 10)*cos(ss * 2 * PI / 60);
	glColor3f(1.0f,0.0f,0.0f);
	glBegin(GL_LINES);
	glVertex2f(xc,yc);
	glVertex2f(xs,ys);
	glEnd();

	glLineWidth(3); 
	xm = xm + (R - 25)*sin((mm + ss / 60) * 2 * PI / 60);//秒针与分针都是60份
	ym = ym + (R - 25)*cos((mm + ss / 60) * 2 * PI / 60);
	glColor3f(0.0f, 1.0f, 0.0f);
	glBegin(GL_LINES);
	glVertex2f(xc,yc);
	glVertex2f(xm,ym);
	glEnd();
	
	glLineWidth(5);
	xh = xh + (R - 45)*sin((hh + (mm + ss / 60) / 60) * 2 * PI / 12);//每一次走的角度分为12份
	yh = yh + (R - 45)*cos((hh + (mm + ss / 60) / 60) * 2 * PI / 12);
	glColor3f(0.0f,0.0f,1.0f);
	glBegin(GL_LINES);
	glVertex2f(xc,yc);
	glVertex2f(xh,yh);
	glEnd();
}
//draw a lots of shapes
void Shapes(){
	//draw points
	glPointSize(10);
	glBegin(GL_POINT);
	//glVertex2d();
	//glVertex2d();
	//glVertex2d();
	glEnd();
}

 

用MFC VC++实现的时钟源代码 // MFCFrame1View.cpp : implementation of the CMFCFrame1View class // #include "stdafx.h" #include "MFCFrame1.h" #include "MFCFrame1Doc.h" #include "MFCFrame1View.h" #include "PointDialog.h" #include "math.h" GLUquadricObj *objCylinder = gluNewQuadric(); #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View IMPLEMENT_DYNCREATE(CMFCFrame1View, CView) BEGIN_MESSAGE_MAP(CMFCFrame1View, CView) //{{AFX_MSG_MAP(CMFCFrame1View) ON_WM_CREATE() ON_WM_DESTROY() ON_WM_SIZE() ON_COMMAND(IDM_ZIXUAN, OnZixuan) ON_WM_TIMER() ON_COMMAND(IDM_ChangDirect, OnChangDirect) //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View construction/destruction CMFCFrame1View::CMFCFrame1View() { // TODO: add construction code here this->m_GLPixelIndex = 0; this->m_hGLContext = NULL; Angle1=0.0; Angle2=30.0; Timer=0; x=0.0; z=0.0; juli=40.0; } CMFCFrame1View::~CMFCFrame1View() { } BOOL CMFCFrame1View::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs cs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS); return CView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View drawing ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View printing BOOL CMFCFrame1View::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CMFCFrame1View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void CMFCFrame1View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View diagnostics #ifdef _DEBUG void CMFCFrame1View::AssertValid() const { CView::AssertValid(); } void CMFCFrame1View::Dump(CDumpContext& dc) const { CView::Dump(dc); } CMFCFrame1Doc* CMFCFrame1View::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCFrame1Doc))); return (CMFCFrame1Doc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View message handlers BOOL CMFCFrame1View::SetWindowPixelFormat(HDC hDC) { PIXELFORMATDESCRIPTOR pixelDesc= { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| PFD_DOUBLEBUFFER|PFD_SUPPORT_GDI, 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 }; this->m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc); if(this->m_GLPixelIndex==0) { this->m_GLPixelIndex = 1; if(DescribePixelFormat(hDC,this->m_GLPixelIndex,sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0) { return FALSE; } } if(SetPixelFormat(hDC,this->m_GLPixelIndex,&pixelDesc)==FALSE) { return FALSE; } return TRUE; } int CMFCFrame1View::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here HWND hWnd = this->GetSafeHwnd(); HDC hDC = ::GetDC(hWnd); if(this->SetWindowPixelFormat(hDC)==FALSE) { return 0; } if(this->CreateViewGLContext(hDC)==FALSE) { return 0; } return 0; } BOOL CMFCFrame1View::CreateViewGLContext(HDC hDC) { this->m_hGLContext = wglCreateContext(hDC); if(this->m_hGLContext==NULL) {//创建失败 return FALSE; } if(wglMakeCurrent(hDC,this->m_hGLContext)==FALSE) {//选为当前RC失败 return FALSE; } return TRUE; } void CMFCFrame1View::OnDestroy() { CView::OnDestroy(); // TODO: Add your message handler code here if(wglGetCurrentContext()!=NULL) { wglMakeCurrent(NULL,NULL); } if(this->m_hGLContext!=NULL) { wglDeleteContext(this->m_hGLContext); this->m_hGLContext = NULL; } } void CMFCFrame1View::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); // TODO: Add your message handler code here GLsizei width,height; GLdouble aspect; width = cx; height = cy; if(cy==0) { aspect = (GLdouble)width; } else { aspect = (GLdouble)width/(GLdouble)height; } glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(40.0,aspect,5.0,1000.0); } void CMFCFrame1View::OnDraw(CDC* pDC) { CMFCFrame1Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CPaintDC dc(this); glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0,0.0,10.0,0.0,0.0,0.0,0.0,1.0,0.0); glRotatef(-90.0,1.0,0.0,0.0);/*返回原坐标*/ glTranslatef(-3.0,0.0,0.0); SwapBuffers(dc.m_ps.hdc); glDrawBuffer (GL_BACK); glFlush(); } void CMFCFrame1View::OnZixuan() { // TODO: Add your command handler code here Timer=1; SetTimer(1,100,NULL); } void CMFCFrame1View::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default CPaintDC dc(this); if (Timer==1) { Angle1=Angle1-1; Angle2=Angle2-1; glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW);/**/ glLoadIdentity(); gluLookAt(0.0,20.0,0.000000001,0.0,0.0,0.0,0.0,1.0,0.0); glPushMatrix(); glColor3f(0.7,0.7,0.7); glTranslatef(0.0,0.0,1.1); glRotatef(-90.0,1.0,0.0,0.0); glutSolidCone(5.0,0.0,60.0,60.0); /*底盘*/ glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.0); glTranslatef(3.9,0.99,1.0); /*刻度*/ glRotatef(90.0,0.0,1.0,0.0); gluCylinder(objCylinder, 0.05, 0.05, 0.8, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.0); glTranslatef(-4.7,0.99,1.0); /*刻度*/ glRotatef(90.0,0.0,1.0,0.0); gluCylinder(objCylinder,0.05, 0.05, 0.8, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.0); glTranslatef(0.0,0.99,-2.9); /*刻度*/ glRotatef(180.0,0.0,1.0,0.0); gluCylinder(objCylinder,0.05, 0.05, 0.8, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.0); glTranslatef(0.0,0.99,5.8); /*刻度*/ glRotatef(180.0,0.0,1.0,0.0); gluCylinder(objCylinder,0.05, 0.05,0.8, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,1.0,0.0); glRotatef(45.0,0.0,1.0,0.0); glTranslatef(-0.67,0.99,0.7); /*时针*/ glRotatef(Angle1/129600,0.0,1.0,0.0); gluCylinder(objCylinder, 0.07, 0.02, 2.5, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,0.0); glTranslatef(0.0,0.99,1.0); /*分针*/ glRotatef(Angle2/360,0.0,1.0,0.0); gluCylinder(objCylinder, 0.05, 0.02, 3.5, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.5); glTranslatef(0.0,0.99,1.0); /*秒针*/ glRotatef(Angle1,0.0,1.0,0.0); gluCylinder(objCylinder, 0.07, 0.02, 4.5, 9999, 9); glPopMatrix(); SwapBuffers(dc.m_ps.hdc); glDrawBuffer (GL_BACK); glFlush(); } else if(Timer==2) { glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT); if (juli>12.0) { glMatrixMode(GL_MODELVIEW);/*建立了从世界坐标系到观察坐标系的转换矩阵*/ glLoadIdentity(); gluLookAt(0.0,8.0,juli,0.0,0.0,0.0,0.0,1.0,0.0); juli=juli-0.1; glPushMatrix(); glColor3f(0.0,0.0,0.0); glRotatef(-90.0,1.0,0.0,0.0); glutWireCone(40.0,0.0,30.0,30.0); /*高度为0的圆锥*/ glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,1.0); glLineWidth(4.0); glTranslatef(4.0,1.0,0.0); glutWireOctahedron(); /*八面体*/ glLineWidth(1.0); glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,1.0); glTranslatef(0.0,1.1,0.0); glRotatef(Angle2,0.0,1.0,0.0); gluCylinder(objCylinder, 1.0, 1.0, 10.0, 9999, 9); /*壶*/ glPopMatrix(); } else if(juli<=12.0) { Angle2=Angle2+0.01; if (Angle2==360.0) Angle2=0.0; glMatrixMode(GL_MODELVIEW);/*建立了从世界坐标系到观察坐标系的转换矩阵*/ glLoadIdentity(); x=12.0*sin(Angle2); z=12.0*cos(Angle2); gluLookAt(x,5.0,z,0.0,0.0,0.0,0.0,1.0,0.0); glPushMatrix(); glColor3f(0.0,0.0,0.0); glRotatef(-90.0,1.0,0.0,0.0); glutWireCone(40.0,0.0,30.0,30.0); /*高度为0的圆锥*/ glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,1.0); glLineWidth(4.0); glTranslatef(4.0,1.0,0.0); glutWireOctahedron(); /*八面体*/ glLineWidth(1.0); glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,1.0); glTranslatef(0.0,1.1,0.0); gluCylinder(objCylinder, 1.0, 1.0, 10.0, 9999, 9); /*壶*/ glPopMatrix(); } SwapBuffers(dc.m_ps.hdc); glDrawBuffer (GL_BACK); glFlush(); } CView::OnTimer(nIDEvent); } void CMFCFrame1View::OnChangDirect() { // TODO: Add your command handler code here Timer=2; SetTimer(1,100 ,NULL); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JustEasyCode

谢谢您

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值