-src = $(wildcard src/*.c)
+src = $(src_main) $(filter-out $(wildcard src/main_*.c), $(wildcard src/*.c))
obj = $(src:.c=.o)
dep = $(obj:.o=.d)
bin = censuslogo
sys ?= $(shell uname -s | sed 's/MINGW.*/mingw/')
CFLAGS = -pedantic -Wall -g -DNOLOAD
-LDFLAGS = $(LDFLAGS_$(sys)) -lm
+LDFLAGS = $(ldflags_sys) -lm
-LDFLAGS_Linux = -lGL -lGLU -lglut
-LDFLAGS_mingw = -lmingw32 -mconsole -lfreeglut_static -lopengl32 -lglu32 -lgdi32 -lwinmm
ifeq ($(sys), mingw)
+ src_main = src/main_w32.c
obj = $(src:.c=.w32.o)
bin = censuslogo.exe
CFLAGS += -DFREEGLUT_STATIC
+
+ ldflags_sys = -lmingw32 -mconsole -lfreeglut_static -lopengl32 -lglu32 -lgdi32 -lwinmm
+else
+ src_main = src/main_glut.c
+ ldflags_sys = -lGL -lGLU -lglut
endif
$(bin): $(obj)
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <GL/gl.h>
+#include "app.h"
+#include "logo.h"
+
+#ifndef GL_MULTISAMPLE
+#define GL_MULTISAMPLE 0x809d
+#endif
+
+int nverts = 256;
+int msaa = 1;
+int fullscr = 0;
+
+
+static void draw_disc(float x, float y, float rad, int sub);
+static void draw_line(float x0, float y0, float x1, float y1, float rad);
+static void print_usage(const char *argv0);
+
+int app_init(void)
+{
+ if(init_logo("data/census.curves") == -1) {
+ return -1;
+ }
+
+#ifdef MSAA
+ if(msaa) {
+ glEnable(GL_MULTISAMPLE);
+ }
+#endif
+
+ return 0;
+}
+
+#define LOOPTIME 1.45f
+
+void app_display(void)
+{
+ int i;
+ float t = (float)msec / 1000.0f;
+ float a[2], b[2], dt;
+ float anim, alpha;
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glLineWidth(5.0);
+
+ anim = fmod(t / 6.0f, LOOPTIME);
+ alpha = 1.0f - ((anim - (LOOPTIME - 0.075)) / 0.06f);
+ if(alpha < 0.0f) alpha = 0.0f;
+ if(alpha > 1.0f) alpha = 1.0f;
+
+ dt = (anim > 1.0f ? 1.0f : anim) / (float)(nverts - 1);
+
+ glColor4f(1, 1, 1, alpha);
+ for(i=0; i<nverts-1; i++) {
+ float t0 = (float)i * dt;
+ float t1 = (float)(i + 1) * dt;
+ eval_logo(a, t0);
+ eval_logo(b, t1);
+ draw_line(a[0], a[1], b[0], b[1], 0.02);
+ }
+
+ if(anim > 0.0f) {
+ eval_logo(a, 0);
+ draw_disc(a[0], a[1], 0.05, 22);
+ }
+ if(anim >= 1.0f) {
+ eval_logo(b, 1);
+ draw_disc(b[0], b[1], 0.05, 22);
+ }
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glColor4f(0.8, 0, 0, 2.0 * (anim - 1.0f) / (LOOPTIME - 1.0f));
+ draw_disc(0, 0, 0.14, 30);
+
+ if(alpha < 1.0f) {
+ glBegin(GL_QUADS);
+ glColor4f(0, 0, 0, 1.0f - alpha);
+ glVertex2f(-1, -1);
+ glVertex2f(1, -1);
+ glVertex2f(1, 1);
+ glVertex2f(-1, 1);
+ glEnd();
+ }
+
+ glDisable(GL_BLEND);
+}
+
+static void draw_disc(float x, float y, float rad, int sub)
+{
+ int i;
+ glBegin(GL_TRIANGLE_FAN);
+ glVertex2f(x, y);
+ for(i=0; i<sub; i++) {
+ float t = (float)i / (float)(sub - 1);
+ float theta = t * M_PI * 2.0;
+ glVertex2f(cos(theta) * rad + x, sin(theta) * rad + y);
+ }
+ glEnd();
+}
+
+static void draw_line(float x0, float y0, float x1, float y1, float rad)
+{
+ float dx, dy, rx, ry, len;
+
+ dx = x1 - x0;
+ dy = y1 - y0;
+ len = sqrt(dx * dx + dy * dy);
+
+ rx = rad * dy / len;
+ ry = -rad * dx / len;
+
+ draw_disc(x0, y0, rad, 12);
+ draw_disc(x1, y1, rad, 12);
+
+ glBegin(GL_QUADS);
+ glVertex2f(x0 + rx, y0 + ry);
+ glVertex2f(x1 + rx, y1 + ry);
+ glVertex2f(x1 - rx, y1 - ry);
+ glVertex2f(x0 - rx, y0 - ry);
+ glEnd();
+}
+
+
+void app_reshape(int x, int y)
+{
+ float aspect = (float)x / (float)y;
+ glViewport(0, 0, x, y);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glScalef(1.0f / aspect, 1.0f, 1.0f);
+}
+
+void app_keyboard(int key, int pressed)
+{
+ switch(key) {
+ case 27:
+ app_quit();
+
+ case '-':
+ nverts -= 8;
+ printf("nverts: %d\n", nverts);
+ break;
+
+ case '=':
+ nverts += 8;
+ printf("nverts: %d\n", nverts);
+ break;
+
+ case 'f':
+ fullscr = !fullscr;
+ if(fullscr) {
+ app_fullscreen();
+ } else {
+ app_windowed();
+ }
+ break;
+ }
+}
+
+
+int app_parse_args(int argc, char **argv)
+{
+ int i;
+
+ for(i=1; i<argc; i++) {
+ if(argv[i][0] == '-') {
+ if(strcmp(argv[i], "-fs") == 0) {
+ fullscr = 1;
+ } else if(strcmp(argv[i], "-noaa") == 0) {
+ msaa = 0;
+ } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) {
+ print_usage(argv[0]);
+ exit(0);
+ } else {
+ fprintf(stderr, "invalid option: %s\n", argv[i]);
+ return -1;
+ }
+ } else {
+ fprintf(stderr, "unexpected argument: %s\n", argv[i]);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static void print_usage(const char *argv0)
+{
+ printf("Usage: %s [options]\n", argv0);
+ printf("Options:\n");
+ printf(" -fs: fullscreen\n");
+ printf(" -noaa: disable anti-aliasing\n");
+ printf(" -h,-help: print usage and exit\n");
+}
--- /dev/null
+#ifndef APP_H_
+#define APP_H_
+
+/* undefine to build without anti-aliasing */
+#define MSAA
+
+int win_width, win_height;
+int nverts;
+int msaa;
+int fullscr;
+long msec;
+
+int app_init(void);
+void app_display(void);
+void app_reshape(int x, int y);
+void app_keyboard(int key, int pressed);
+int app_parse_args(int argc, char **argv);
+
+/* defined in main_*.c */
+void app_quit(void);
+void app_fullscreen(void);
+void app_windowed(void);
+
+#endif /* APP_H_ */
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <assert.h>
-#include <GL/glut.h>
-#include "logo.h"
-
-#ifndef GL_MULTISAMPLE
-#define GL_MULTISAMPLE 0x809d
-#endif
-
-#define MSAA
-
-int init(void);
-void display(void);
-void idle(void);
-void reshape(int x, int y);
-void keyb(unsigned char key, int x, int y);
-int parse_args(int argc, char **argv);
-void print_usage(const char *argv0);
-
-int win_width, win_height;
-int nverts = 256;
-long start_time;
-int msaa = 1;
-int fullscr = 0;
-
-
-int main(int argc, char **argv)
-{
- unsigned int flags = GLUT_RGB | GLUT_DOUBLE;
-
- glutInit(&argc, argv);
- if(parse_args(argc, argv) == -1) {
- return 1;
- }
-
-#ifdef MSAA
- if(msaa) {
- flags |= GLUT_MULTISAMPLE;
- }
-#endif
-
- glutInitWindowSize(1280, 800);
- glutInitDisplayMode(flags);
- glutCreateWindow("census");
-
- if(fullscr) {
- glutFullScreen();
- glutSetCursor(GLUT_CURSOR_NONE);
- }
-
- glutDisplayFunc(display);
- glutIdleFunc(idle);
- glutReshapeFunc(reshape);
- glutKeyboardFunc(keyb);
-
- if(init() == -1) {
- return 1;
- }
-
- glutMainLoop();
- return 0;
-}
-
-int init(void)
-{
- if(init_logo("data/census.curves") == -1) {
- return -1;
- }
-
-#ifdef MSAA
- if(msaa) {
- glEnable(GL_MULTISAMPLE);
- }
-#endif
-
- start_time = glutGet(GLUT_ELAPSED_TIME);
- return 0;
-}
-
-static void draw_disc(float x, float y, float rad, int sub)
-{
- int i;
- glBegin(GL_TRIANGLE_FAN);
- glVertex2f(x, y);
- for(i=0; i<sub; i++) {
- float t = (float)i / (float)(sub - 1);
- float theta = t * M_PI * 2.0;
- glVertex2f(cos(theta) * rad + x, sin(theta) * rad + y);
- }
- glEnd();
-}
-
-static void draw_line(float x0, float y0, float x1, float y1, float rad)
-{
- float dx, dy, rx, ry, len;
-
- dx = x1 - x0;
- dy = y1 - y0;
- len = sqrt(dx * dx + dy * dy);
-
- rx = rad * dy / len;
- ry = -rad * dx / len;
-
- draw_disc(x0, y0, rad, 12);
- draw_disc(x1, y1, rad, 12);
-
- glBegin(GL_QUADS);
- glVertex2f(x0 + rx, y0 + ry);
- glVertex2f(x1 + rx, y1 + ry);
- glVertex2f(x1 - rx, y1 - ry);
- glVertex2f(x0 - rx, y0 - ry);
- glEnd();
-}
-
-#define LOOPTIME 1.45f
-
-void display(void)
-{
- int i;
- long msec = glutGet(GLUT_ELAPSED_TIME) - start_time;
- float t = (float)msec / 1000.0f;
- float a[2], b[2], dt;
- float anim, alpha;
-
- glClear(GL_COLOR_BUFFER_BIT);
-
- glLineWidth(5.0);
-
- anim = fmod(t / 6.0f, LOOPTIME);
- alpha = 1.0f - ((anim - (LOOPTIME - 0.075)) / 0.06f);
- if(alpha < 0.0f) alpha = 0.0f;
- if(alpha > 1.0f) alpha = 1.0f;
-
- dt = (anim > 1.0f ? 1.0f : anim) / (float)(nverts - 1);
-
- glColor4f(1, 1, 1, alpha);
- for(i=0; i<nverts-1; i++) {
- float t0 = (float)i * dt;
- float t1 = (float)(i + 1) * dt;
- eval_logo(a, t0);
- eval_logo(b, t1);
- draw_line(a[0], a[1], b[0], b[1], 0.02);
- }
-
- if(anim > 0.0f) {
- eval_logo(a, 0);
- draw_disc(a[0], a[1], 0.05, 22);
- }
- if(anim >= 1.0f) {
- eval_logo(b, 1);
- draw_disc(b[0], b[1], 0.05, 22);
- }
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glColor4f(0.8, 0, 0, 2.0 * (anim - 1.0f) / (LOOPTIME - 1.0f));
- draw_disc(0, 0, 0.14, 30);
-
- if(alpha < 1.0f) {
- glBegin(GL_QUADS);
- glColor4f(0, 0, 0, 1.0f - alpha);
- glVertex2f(-1, -1);
- glVertex2f(1, -1);
- glVertex2f(1, 1);
- glVertex2f(-1, 1);
- glEnd();
- }
-
- glDisable(GL_BLEND);
-
- glutSwapBuffers();
- assert(glGetError() == GL_NO_ERROR);
-}
-
-void idle(void)
-{
- glutPostRedisplay();
-}
-
-void reshape(int x, int y)
-{
- float aspect = (float)x / (float)y;
- win_width = x;
- win_height = y;
-
- glViewport(0, 0, x, y);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glScalef(1.0f / aspect, 1.0f, 1.0f);
-}
-
-void keyb(unsigned char key, int x, int y)
-{
- static int saved_width = 800, saved_height = 600;
-
- switch(key) {
- case 27:
- exit(0);
-
- case '-':
- nverts -= 8;
- printf("nverts: %d\n", nverts);
- glutPostRedisplay();
- break;
-
- case '=':
- nverts += 8;
- printf("nverts: %d\n", nverts);
- glutPostRedisplay();
- break;
-
- case 'f':
- fullscr = !fullscr;
- if(fullscr) {
- saved_width = win_width;
- saved_height = win_height;
- glutFullScreen();
- glutSetCursor(GLUT_CURSOR_NONE);
- } else {
- glutReshapeWindow(saved_width, saved_height);
- glutSetCursor(GLUT_CURSOR_INHERIT);
- }
- break;
- }
-}
-
-int parse_args(int argc, char **argv)
-{
- int i;
-
- for(i=1; i<argc; i++) {
- if(argv[i][0] == '-') {
- if(strcmp(argv[i], "-fs") == 0) {
- fullscr = 1;
- } else if(strcmp(argv[i], "-noaa") == 0) {
- msaa = 0;
- } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) {
- print_usage(argv[0]);
- exit(0);
- } else {
- fprintf(stderr, "invalid option: %s\n", argv[i]);
- return -1;
- }
- } else {
- fprintf(stderr, "unexpected argument: %s\n", argv[i]);
- return -1;
- }
- }
- return 0;
-}
-
-void print_usage(const char *argv0)
-{
- printf("Usage: %s [options]\n", argv0);
- printf("Options:\n");
- printf(" -fs: fullscreen\n");
- printf(" -noaa: disable anti-aliasing\n");
- printf(" -h,-help: print usage and exit\n");
-}
--- /dev/null
+#include <stdlib.h>
+#include <assert.h>
+#include <GL/glut.h>
+#include "app.h"
+
+static void display(void);
+static void idle(void);
+static void reshape(int x, int y);
+static void keyb(unsigned char key, int x, int y);
+
+static long start_time;
+
+int main(int argc, char **argv)
+{
+ unsigned int flags = GLUT_RGB | GLUT_DOUBLE;
+
+ glutInit(&argc, argv);
+ if(app_parse_args(argc, argv) == -1) {
+ return 1;
+ }
+
+#ifdef MSAA
+ if(msaa) {
+ flags |= GLUT_MULTISAMPLE;
+ }
+#endif
+
+ glutInitWindowSize(1280, 800);
+ glutInitDisplayMode(flags);
+ glutCreateWindow("census");
+
+ if(fullscr) {
+ glutFullScreen();
+ glutSetCursor(GLUT_CURSOR_NONE);
+ }
+
+ glutDisplayFunc(display);
+ glutIdleFunc(idle);
+ glutReshapeFunc(reshape);
+ glutKeyboardFunc(keyb);
+
+ if(app_init() == -1) {
+ return 1;
+ }
+ start_time = glutGet(GLUT_ELAPSED_TIME);
+
+ glutMainLoop();
+ return 0;
+}
+
+static void display(void)
+{
+ msec = glutGet(GLUT_ELAPSED_TIME) - start_time;
+
+ app_display();
+
+ glutSwapBuffers();
+ assert(glGetError() == GL_NO_ERROR);
+}
+
+static void idle(void)
+{
+ glutPostRedisplay();
+}
+
+static void reshape(int x, int y)
+{
+ app_reshape(x, y);
+ win_width = x;
+ win_height = y;
+}
+
+static void keyb(unsigned char key, int x, int y)
+{
+ app_keyboard(key, 1);
+}
+
+void app_quit(void)
+{
+ exit(0);
+}
+
+static int saved_width = 1280, saved_height = 800;
+
+void app_fullscreen(void)
+{
+ saved_width = win_width;
+ saved_height = win_height;
+ glutFullScreen();
+ glutSetCursor(GLUT_CURSOR_NONE);
+}
+
+void app_windowed(void)
+{
+ glutReshapeWindow(saved_width, saved_height);
+ glutSetCursor(GLUT_CURSOR_INHERIT);
+}
--- /dev/null
+#include <stdio.h>
+#include <windows.h>
+#include "app.h"
+
+static int create_glwin(int xsz, int ysz);
+static void destroy_glwin(void);
+static long CALLBACK handle_events(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam);
+
+static HWND win;
+static HDC dc;
+static HGLRC ctx;
+static int quit;
+static long start_time;
+
+
+int WINAPI WinMain(HINSTANCE pid, HINSTANCE prevpid, char *cmdline, int showcmd)
+{
+ if(memcmp(cmdline, "-c", 2) == 0) {
+ return 0;
+ }
+ if(memcmp(cmdline, "-s", 2) == 0) {
+ fullscr = 1;
+ }
+
+ if(create_glwin(1280, 800) == -1) {
+ return 1;
+ }
+
+ if(app_init() == -1) {
+ return 1;
+ }
+ start_time = timeGetTime();
+
+ while(!quit) {
+ MSG ev;
+ while(PeekMessage(&ev, 0, 0, 0, PM_REMOVE)) {
+ if(ev.message == WM_QUIT) {
+ goto done;
+ }
+ TranslateMessage(&ev);
+ DispatchMessage(&ev);
+ }
+ if(quit) goto done;
+
+ msec = timeGetTime() - start_time;
+ app_display();
+ SwapBuffers(dc);
+ }
+
+done:
+ destroy_glwin();
+ return 0;
+}
+
+void app_quit(void)
+{
+ quit = 1;
+}
+
+void app_fullscreen(void)
+{
+}
+
+void app_windowed(void)
+{
+}
+
+
+static int create_glwin(int xsz, int ysz)
+{
+ int x, y, win_xsz, win_ysz, pix_fmt;
+ unsigned int style;
+ HINSTANCE pid;
+ WNDCLASSEX wc;
+ PIXELFORMATDESCRIPTOR pfd;
+ RECT rect;
+
+ pid = GetModuleHandle(0);
+
+ memset(&wc, 0, sizeof wc);
+ wc.cbSize = sizeof wc;
+ wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
+ wc.hCursor = LoadCursor(0, IDC_ARROW);
+ wc.hIcon = wc.hIconSm = LoadIcon(0, IDI_APPLICATION);
+ wc.hInstance = pid;
+ wc.lpfnWndProc = (WNDPROC)handle_events;
+ wc.lpszClassName = "census";
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ RegisterClassEx(&wc);
+
+ if(fullscr) {
+ x = y = 0;
+ win_xsz = xsz = GetSystemMetrics(SM_CXSCREEN);
+ win_ysz = ysz = GetSystemMetrics(SM_CYSCREEN);
+
+ style = WS_POPUP;
+ } else {
+ x = y = CW_USEDEFAULT;
+ style = WS_OVERLAPPEDWINDOW;
+
+ rect.left = rect.top = 0;
+ rect.right = xsz;
+ rect.bottom = ysz;
+ AdjustWindowRect(&rect, style, 0);
+
+ win_xsz = rect.right - rect.left;
+ win_ysz = rect.bottom - rect.top;
+ }
+
+ printf("creating window: %dx%d\n", xsz, ysz);
+ win = CreateWindow("census", "census", style, x, y, win_xsz, win_ysz, 0, 0, pid, 0);
+ dc = GetDC(win);
+
+ memset(&pfd, 0, sizeof pfd);
+ pfd.nSize = sizeof pfd;
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 24;
+ pfd.cDepthBits = 24;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+
+ if(!(pix_fmt = ChoosePixelFormat(dc, &pfd)) || !SetPixelFormat(dc, pix_fmt, &pfd)) {
+ fprintf(stderr, "Failed to get suitable pixel format\n");
+ ReleaseDC(win, dc);
+ DestroyWindow(win);
+ UnregisterClass("census", pid);
+ return -1;
+ }
+
+ if(!(ctx = wglCreateContext(dc))) {
+ fprintf(stderr, "Failed to create WGL context\n");
+ ReleaseDC(win, dc);
+ DestroyWindow(win);
+ UnregisterClass("census", pid);
+ return -1;
+ }
+ wglMakeCurrent(dc, ctx);
+
+ ShowWindow(win, SW_SHOW);
+ UpdateWindow(win);
+ SetFocus(win);
+
+ app_reshape(xsz, ysz);
+ win_width = xsz;
+ win_height = ysz;
+ return 0;
+}
+
+static void destroy_glwin(void)
+{
+ wglMakeCurrent(0, 0);
+ wglDeleteContext(ctx);
+ ReleaseDC(win, dc);
+ DestroyWindow(win);
+ UnregisterClass("census", GetModuleHandle(0));
+}
+
+static long CALLBACK handle_events(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam)
+{
+ static int window_mapped;
+
+ switch(msg) {
+ case WM_SHOWWINDOW:
+ window_mapped = wparam;
+ break;
+
+ case WM_PAINT:
+ if(window_mapped) {
+ ValidateRect(win, 0);
+ }
+ break;
+
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ quit = 1;
+ break;
+
+ case WM_KEYDOWN:
+ app_keyboard(wparam, 1);
+ break;
+
+ case WM_ACTIVATE:
+ if(!wparam) {
+ PostQuitMessage(0);
+ quit = 1;
+ }
+ break;
+
+ case WM_SYSCOMMAND:
+ if(wparam == SC_SCREENSAVE) {
+ break;
+ }
+
+ default:
+ return DefWindowProc(win, msg, wparam, lparam);
+ }
+ return 0;
+}