OpenGL 模拟时钟无法正确显示?

OpenGL analog clock doesn't show correctly?

本文关键字:显示 模拟 时钟 OpenGL      更新时间:2023-10-16

我的时钟有问题。在前 10 分钟内,时针没有显示正确的小时,当分针发生变化时它会发生变化,但在 10 分钟后它会正确显示。你能帮我修复它吗?

我认为这些行有问题,但我不确定:

static void TimeEvent(int te)
{
    rx = 30 * cos( angle );
    ry = 30 * sin( angle );
    rz = 30 * cos( angle );
    angle += 0.01;
    if (angle > M_TWOPI) angle = 0;
    glutPostRedisplay();
    glutTimerFunc( 100, TimeEvent, 1);
 }

这是我的整个代码:

#include <GL/glut.h>
#include <gl/gl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
GLUquadricObj *Cylinder;
struct tm *newtime;
time_t l_time;
int M_TWOPI=0;
GLfloat rx, ry, rz, angle;
GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightDiffuse[]= { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightPosition[]= { 5.0f, 25.0f, 15.0f, 1.0f };
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
static int view_state = 1; // Ortho view = 1, Perspective = 0

void newLine(float Start, float End, float angle){
  float c = cos(angle), s = sin(angle);
  glVertex2f( -8.0f*Start*c, -8.0f*Start*s);
  glVertex2f( -8.0f*End*c, -8.0f*End*s);
}

void Sprint( float x, float y, char *st)
{
    int l,i;
    l=strlen( st );
    glRasterPos3f( x, y, -1);
    for( i=0; i < l; i++)
        {
        glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, st[i]);
    }
}
static void TimeEvent(int te)
{
    rx = 30 * cos( angle );
    ry = 30 * sin( angle );
    rz = 30 * cos( angle );
    angle += 0.01;
    if (angle > M_TWOPI) angle = 0;
    glutPostRedisplay();
    glutTimerFunc( 100, TimeEvent, 1);
}

void Draw_clock( GLfloat cx, GLfloat cy, GLfloat cz )
{
  int hour_ticks , sec_ticks;
  glPushMatrix();
  glTranslatef(cx,cy,cz);
  glRotatef(180, 1.0, 0.0, 0.0);

  glPushMatrix();
  glColor3f(1.0, 0.5, 0.0);
  glTranslatef( 0, 0, 0.0);
  glRotatef((360/12) * newtime->tm_hour  + (360/60) * (60 / (newtime->tm_min+1)), 0.0, 0.0, 1.0);
  glPushMatrix();
  glTranslatef(0.0, 0.0, 2.0);
  glPopMatrix();
  glRotatef(90, 1.0, 0.0, 0.0);
  gluCylinder(Cylinder, 0.75, 0, 4, 16, 16);
  glPopMatrix();
  glPushMatrix();
  glColor3f(1.0, 0.0, 1.0);
  glTranslatef( 0, 0, 0.0);
  glRotatef( (360/60) * newtime->tm_min, 0.0, 0.0, 1.0);
  glPushMatrix();
  glTranslatef(0.0, 0.0, 3.0);
  glScalef(0.5, 0.5, 1.0);
  glPopMatrix();
  glRotatef( 90, 1.0, 0.0, 0.0);
  glutSolidCone (0.5, 6, 6, 16);
  glPopMatrix();
  glPushMatrix();
  glColor3f(1.0, 0.0, 0.0);
  glTranslatef( 0, 0, -0.0);
  glRotatef( (360/60) * newtime->tm_sec, 0.0, 0.0, 1.0);
  glPushMatrix();
  glTranslatef(0.0, 0.0, 4.0);
  glScalef(0.25, 0.25, 1.0);
  glPopMatrix();
  glRotatef( 90, 1.0, 0.0, 0.0);
  gluCylinder(Cylinder, 0.25, 0, 6, 16, 16);
  glPopMatrix();

  for(hour_ticks = 0; hour_ticks < 12; hour_ticks++)
      {
      glPushMatrix();// Draw next arm axis.
      glColor3f(0.0, 1.0, 1.0); // give it a color
      glTranslatef(0.0, 0.0, 0.0);
      glRotatef( (360/12) * hour_ticks, 0.0, 0.0, 1.0);
      glTranslatef( 6.0, 0.0, 0.0);
      glEnable(GL_LINE_SMOOTH);
      glBegin(GL_LINES);
      newLine(0.08f, 0.2f, 0.0f);
      glEnd();
      glPopMatrix();
  }
  for(sec_ticks = 0; sec_ticks < 60; sec_ticks++)
    {
    glPushMatrix();
    glTranslatef(0.0, 0.0, 0.0);
    glRotatef( (360/60) * sec_ticks, 0.0, 0.0, 1.0);
    glTranslatef(6.0, 0.0, 0.0);
    glutSolidCone(1.0, 2.0, 3, 4);
    glPopMatrix();
    }

  glPopMatrix();
}
void num()
{
    glColor3f( 0.0, 0.0, 1.0);
    Sprint(-6.2,-0.2,"9"); //counting from center
    Sprint(-0.2,-6.2,"6");
    Sprint(2.8,-5.5,"5");
    Sprint(5.0,-3.2,"4");
    Sprint(5.0,+2.8,"2");
    Sprint(2.8,+5.0,"1");
    Sprint(-3.33,+4.95,"11");
    Sprint(-0.2,-6.2,"6");
    Sprint(-3.2,-5.45,"7");
    Sprint(-0.4,5.7,"12");
    Sprint(-5.35,-3.25,"8");
    Sprint(-5.55,+2.8,"10");
    Sprint(5.8,-0.2,"3");
}

void display_clock()
{
  time(&l_time); // Get time
  newtime = localtime(&l_time); // Convert to local time
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  // easy way to put text on the screen.
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-8.0, 8.0, -8.0, 8.0, 1.0, 60.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glDisable(GL_LIGHTING);
  glDisable(GL_COLOR_MATERIAL);
  glColor3f( 1.0, 1.0, 1.0);
    Sprint(-2, 3, "     Clock");

Draw_clock( 0.0, 0.0, -14.0);
num();
glutSwapBuffers();
}

void display(void)
{
  glClear(GL_COLOR_BUFFER_BIT);
     display_clock();
     glFlush();
}
void reshape (int w, int h)
{
   glViewport (0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
}

int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
   glutInitWindowSize (500, 500);
   glutInitWindowPosition (50, 50);
   glutCreateWindow (argv[0]);
   glutSetWindowTitle("Clock");
   Cylinder = gluNewQuadric();
   glutAttachMenu(GLUT_RIGHT_BUTTON);
   glutDisplayFunc(display);
   glutReshapeFunc(reshape);
   glutTimerFunc( 10, TimeEvent, 1);
   glutMainLoop();
   return 0;
}

你正在做整数算术:

 glRotatef((360/12) * newtime->tm_hour  + (360/60) * (60 / (newtime->tm_min+1)), 0.0, 0.0, 1.0);

应该是:

 glRotatef(30.0 * newtime->tm_hour + 6.0) * (60.0 / (newtime->tm_min+1)), 0.0, 0.0, 1.0);

等等。

但是,由于 360/

12 和 360/60 是常量,因此您也可以将它们替换为计算值。

我相信

你的问题就在这里:

 glRotatef((360/12) * newtime->tm_hour  + (360/60) * (60 / (newtime->tm_min+1)), 0.0, 0.0, 1.0);

它必须是:

 glRotatef((360/12) * newtime->tm_hour  + (360.0/12 / 60 ) * (newtime->tm_min+1), 0.0, 0.0, 1.0);