/** * \defgroup unixsimulator Simulation of the Borg API for UNIX like platforms. */ /*@{*/ /** * @file main.c * @brief Simulator for Unix like platforms. * @author Martin Ongsiek, Peter Fuhrmann, Christian Kroll */ #ifdef OSX_ #include #else #include #endif #include #include #include #include #include #include #include #include "../config.h" #include "../display_loop.h" #include "trackball.h" /** Number of bytes per row. */ #define LINEBYTES (((NUM_COLS - 1) / 8) + 1) /** Fake port for simulating joystick input. */ volatile unsigned char fakeport; /** Flag which indicates if wait should jump to the menu if fire is pressed. */ volatile unsigned char waitForFire; /** The simulated frame buffer of the borg. */ volatile unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; /** Jump buffer which leads directly the menu. */ extern jmp_buf newmode_jmpbuf; /** Width of the window. */ int WindWidth; /** Height of the window. */ int WindHeight; /** Rotation of the x-axis of the scene. */ float view_rotx = 0; /** Rotation of the y-axis of the scene. */ float view_roty = 0; /** Rotation of the z-axis of the scene. */ float view_rotz = 0; /** GLUT window handle. */ int win; /** * Simple wait function. * @param ms The requested delay in milliseconds. */ void wait(unsigned int ms) { if (waitForFire) { if (fakeport & 0x01) { longjmp(newmode_jmpbuf, 0xFEu); } } usleep(ms * 1000); } /** * Draw a LED in the given color (which is a list). * @param color List which contains a sphere. * @param pos_x x-coordinate * @param pos_y y-coordinate * @param pos_z z-coordinate */ void drawLED(int color, float pos_x, float pos_y, float pos_z) { glPushMatrix(); glTranslatef(pos_x, pos_y, pos_z); glCallList(color); glPopMatrix(); } /** * Draws the LED matrix. */ void display(void) { int x, y, z, level, color; tbReshape(WindWidth, WindHeight); glClear(GL_COLOR_BUFFER_BIT); glPushMatrix(); glTranslatef(NUM_COLS * 2., 0., NUM_ROWS * 2.); tbMatrix(); glRotatef(view_rotx, 1.0, 0.0, 0.0); glRotatef(view_roty, 0.0, 1.0, 0.0); glRotatef(view_rotz, 0.0, 0.0, 1.0); glTranslatef(-NUM_COLS * 2, 0., -NUM_ROWS * 2.); for (x = 0; x < 1; x++) { for (y = 0; y < NUM_COLS; y++) { for (z = 0; z < NUM_ROWS; z++) { color = 0; for (level = 0; level < NUMPLANE; level++) { if (pixmap[level][z % NUM_ROWS][y / 8] & (1 << y % 8)) { color = level + 1; } } drawLED(color, (float) y * 4.0, (float) x * 4.0, (float) (NUM_ROWS - 1 - z) * 4.0); } } } glPopMatrix(); glutSwapBuffers(); usleep(20000); } /** * Handler for processing key presses. * @param key The pressed key encoded in ASCII. * @param x X-position of the mouse pointer. * @param y Y-position of the mouse pointer. */ void keyboard(unsigned char key, int x, int y) { switch (key) { case 'q': printf("Quit\n"); glutDestroyWindow(win); exit(0); break; case ' ': fakeport |= 0x01; break; case 'a': fakeport |= 0x02; break; case 'd': fakeport |= 0x04; break; case 's': fakeport |= 0x08; break; case 'w': fakeport |= 0x10; break; } } /** * Handler for processing key releases. * @param key The released key encoded in ASCII. * @param x X-position of the mouse pointer. * @param y Y-position of the mouse pointer. */ void keyboardup(unsigned char key, int x, int y) { switch (key) { case ' ': fakeport &= ~0x01; break; case 'a': fakeport &= ~0x02; break; case 'd': fakeport &= ~0x04; break; case 's': fakeport &= ~0x08; break; case 'w': fakeport &= ~0x10; break; } } /** * Relays mouse position and button state to the trackball implementation. * @param button Currently monitored button. * @param state State of that button. * @param x X-position of the mouse pointer. * @param y Y-position of the mouse pointer. */ void mouse(int button, int state, int x, int y) { tbMouse(button, state, x, y); } /** * Relays motion request to the trackball implementation. * @param x X-position for the motion direction. * @param y Y-position for the motion direction. */ void motion(int x, int y) { tbMotion(x, y); } /** * Updating the window size. * @param width Width of the window. * @param height Height of the window. */ void reshape(int width, int height) { tbReshape(width, height); glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (float) WindWidth / (float) WindWidth, 5., 1000.); gluLookAt(NUM_ROWS * 2., NUM_ROWS * 2. + 50., NUM_COLS * 2., NUM_ROWS * 2., NUM_ROWS * 2., NUM_COLS * 2., 0.0, 0.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); WindWidth = width; WindHeight = height; } /** * Handler for special keys (the arrow keys in particular) for adjusting the * view angle of the scene. * @param k The pressed special key using GLUT's nomenclature. * @param x X-position of the mouse pointer. * @param y Y-position of the mouse pointer. */ static void special(int k, int x, int y) { switch (k) { case GLUT_KEY_UP: view_rotx += 5.0; break; case GLUT_KEY_DOWN: view_rotx -= 5.0; break; case GLUT_KEY_LEFT: view_rotz += 5.0; break; case GLUT_KEY_RIGHT: view_rotz -= 5.0; break; default: return; } glutPostRedisplay(); } /** * Entry point for starting the display loop thread. * @param unused Not used. Only here to satisfy signature constraints. */ void *display_loop_run(void * unused) { display_loop(); return 0; } /** * Main function for the simulator. * @param argc The argument count. * @param argv Command line arguments. * @return Exit codem, always zero. */ int main(int argc, char **argv) { WindHeight = 700; WindWidth = 700; glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); glutInitWindowSize(WindHeight, WindWidth); win = glutCreateWindow("16x16 Borg Simulator"); // callback glutDisplayFunc(display); glutIdleFunc(display); glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF); glutKeyboardFunc(keyboard); glutKeyboardUpFunc(keyboardup); glutSpecialFunc(special); glutMouseFunc(mouse); glutMotionFunc(motion); // clearcolor & main loop glClearColor(0, 0, 0, 1.0); gluPerspective(60.0, (float) WindWidth / (float) WindWidth, 5., 1000.); gluLookAt(NUM_COLS * 2., NUM_COLS * 2. + 50., NUM_ROWS * 2., NUM_COLS * 2., NUM_COLS * 2., NUM_ROWS * 2., 0.0, 0.0, 1.0); // init Call List for LED GLUquadric* quad = gluNewQuadric(); glNewList(0, GL_COMPILE); glColor4f(0.8, 0.0, 0.0, 1.); gluSphere(quad, 1.0, 12, 12); glEndList(); glNewList(1, GL_COMPILE); glColor4f(0.5, 0.0, 0.0, 1.); gluSphere(quad, 1.4, 12, 12); glEndList(); glNewList(2, GL_COMPILE); glColor4f(0.7, 0.0, 0.0, 1.); gluSphere(quad, 1.55, 12, 12); glEndList(); glNewList(3, GL_COMPILE); glColor4f(1.00, 0.0, 0.0, 1.); gluSphere(quad, 1.7, 12, 12); glEndList(); tbInit(GLUT_LEFT_BUTTON); tbAnimate(GL_FALSE); pthread_t simthread; pthread_create(&simthread, NULL, display_loop_run, NULL); glutMainLoop(); return 0; } /*@}*/