#include <GL/glut.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <chrono>
#include <thread>
// Global variables for stopwatch state
bool stopwatchRunning = false;
std::chrono::steady_clock::time_point startTime;
std::chrono::milliseconds elapsedTime(0);
// Function to render text on the screen using bitmap fonts
void renderBitmapString(float x, float y, void *font, const char *string) {
glRasterPos2f(x, y);
for (const char *c = string; *c != '\0'; ++c) {
glutBitmapCharacter(font, *c);
}
}
// Function to display time in HH:MM:SS:MS format
void displayTime() {
using namespace std::chrono;
// Calculate elapsed time
auto now = steady_clock::now();
auto duration = now - startTime + elapsedTime;
// Convert duration to hours, minutes, seconds, and milliseconds
auto millis
= duration_cast
<milliseconds
>(duration
).count() % 1000; auto seconds
= duration_cast
<seconds
>(duration
).count() % 60; auto minutes
= duration_cast
<minutes
>(duration
).count() % 60; auto hours
= duration_cast
<hours
>(duration
).count();
std::ostringstream timeStream;
timeStream << std::setw(2) << std::setfill('0') << hours << ":"
<< std::setw(2) << std::setfill('0') << minutes << ":"
<< std::setw(2) << std::setfill('0') << seconds << ":"
<< std::setw(3) << std::setfill('0') << millis;
std::string timeString = timeStream.str();
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0); // Set the text color to white
// Display student ID
renderBitmapString(-0.9, 0.9, GLUT_BITMAP_HELVETICA_18, "Student ID: MC123456789");
// Display stopwatch time in the center
renderBitmapString(-0.2, 0.0, GLUT_BITMAP_HELVETICA_18, timeString.c_str());
glutSwapBuffers();
}
// Function to update the display every 10 milliseconds
void update(int value) {
if (stopwatchRunning) {
glutPostRedisplay(); // Request a redraw
glutTimerFunc(10, update, 0); // Set up the next update
}
}
// Function to handle keyboard input
void keyboard
(unsigned char
key, int x
, int y
) { if (key == 'S' || key == 's') { if (stopwatchRunning) {
elapsedTime += std::chrono::steady_clock::now() - startTime;
stopwatchRunning = false;
} else {
startTime = std::chrono::steady_clock::now();
stopwatchRunning = true;
glutTimerFunc(10, update, 0); // Start the update loop
}
} else if (key == 'R' || key == 'r') { stopwatchRunning = false;
elapsedTime = std::chrono::milliseconds(0);
glutPostRedisplay(); // Redraw the window
}
}
// Function to initialize OpenGL settings
void init() {
glClearColor(0.0, 0.0, 0.0, 1.0); // Set the background color to black
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); // Set up orthographic projection
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(800, 600);
glutCreateWindow("Digital Stopwatch");
init();
glutDisplayFunc(displayTime); // Register display function
glutKeyboardFunc(keyboard); // Register keyboard function
glutMainLoop(); // Enter the GLUT event processing loop
return 0;
}