part system
authorJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 3 Dec 2020 17:03:14 +0000 (19:03 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 3 Dec 2020 17:03:14 +0000 (19:03 +0200)
src/demo.c
src/demo.h
src/part.c [new file with mode: 0644]
src/part.h [new file with mode: 0644]
src/part_whitted.c [new file with mode: 0644]

index 8653aa4..d0b1127 100644 (file)
@@ -1,12 +1,19 @@
+#include <stdio.h>
 #include "opengl.h"
 #include "demo.h"
+#include "part.h"
+
+void reg_whitted(void);
 
 int win_width, win_height;
+float win_aspect;
 long time_msec;
 
 
 int demo_init(void)
 {
+       int i;
+
        if(init_opengl() == -1) {
                return -1;
        }
@@ -16,54 +23,98 @@ int demo_init(void)
        glEnable(GL_FRAMEBUFFER_SRGB);
        glEnable(GL_MULTISAMPLE);
 
+       reg_whitted();
+
+       for(i=0; i<num_parts; i++) {
+               if(parts[i]->init() == -1) {
+                       fprintf(stderr, "part %s init failed\n", parts[i]->name);
+                       return -1;
+               }
+       }
+
+       switch_part(parts[0]);
        return 0;
 }
 
 void demo_cleanup(void)
 {
+       int i;
+
+       for(i=0; i<num_parts; i++) {
+               parts[i]->destroy();
+       }
 }
 
 void demo_display(void)
 {
-       glClearColor(0.05, 0.05, 0.05, 1);
+       long part_time;
+
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
-       glMatrixMode(GL_MODELVIEW);
-       glLoadIdentity();
-       glTranslatef(0, 0, -8);
+       if(!cur_part) return;
+
+       part_time = time_msec - cur_part->start_time;
+       if(part_time < cur_part->in_time) {
+               float t = (float)part_time / cur_part->in_time;
 
-       glFrontFace(GL_CW);
-       glutSolidTeapot(1.0);
-       glFrontFace(GL_CCW);
+               if(prev_part) {
+                       long prev_part_time = time_msec - prev_part->start_time;
+                       if(prev_part->draw_out) {
+                               prev_part->draw_out(prev_part_time, t);
+                       } else {
+                               prev_part->draw(prev_part_time);
+                       }
+               }
+
+               if(cur_part->draw_in) {
+                       cur_part->draw_in(part_time, t);
+               } else {
+                       cur_part->draw(part_time);
+               }
+       } else {
+               prev_part = 0;
+               cur_part->draw(part_time);
+       }
 }
 
 void demo_reshape(int x, int y)
 {
+       win_width = x;
+       win_height = y;
+       win_aspect = (float)x / (float)y;
+
        glViewport(0, 0, x, y);
 
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
-       gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0);
+       gluPerspective(50.0, win_aspect, 0.5, 500.0);
 }
 
 void demo_keyboard(int key, int st)
 {
-       if(st) {
-               switch(key) {
-               case 27:
-                       demo_quit();
-                       break;
-               }
+       if(st && key == 27) {
+               demo_quit();
+               return;
+       }
+
+       if(cur_part && cur_part->keyboard) {
+               cur_part->keyboard(key, st);
        }
 }
 
 
 void demo_mbutton(int bn, int st, int x, int y)
 {
+       if(cur_part && cur_part->mbutton) {
+               cur_part->mbutton(bn, st, x, y);
+       }
 }
 
 void demo_mmotion(int x, int y)
 {
+       if(cur_part && cur_part->mmotion) {
+               cur_part->mmotion(x, y);
+       }
 }
 
 void demo_sball_motion(int x, int y, int z)
index 381fbe9..6ede328 100644 (file)
@@ -2,6 +2,7 @@
 #define DEMO_H_
 
 extern int win_width, win_height;
+extern float win_aspect;
 extern long time_msec;
 
 
diff --git a/src/part.c b/src/part.c
new file mode 100644 (file)
index 0000000..8067a1e
--- /dev/null
@@ -0,0 +1,24 @@
+#include "part.h"
+#include "demo.h"
+
+struct demo_part *cur_part, *prev_part;
+
+struct demo_part *parts[MAX_DEMO_PARTS];
+int num_parts;
+
+void add_part(struct demo_part *part)
+{
+       parts[num_parts++] = part;
+}
+
+void switch_part(struct demo_part *part)
+{
+       part->start_time = time_msec;
+
+       if(cur_part) {
+               prev_part = cur_part;
+               cur_part = part;
+       } else {
+               cur_part = part;
+       }
+}
diff --git a/src/part.h b/src/part.h
new file mode 100644 (file)
index 0000000..8d0fbdf
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef PART_H_
+#define PART_H_
+
+struct demo_part {
+       const char *name;
+       long start_time;
+       long in_time;   /* transition overlap with previous part */
+
+       int (*init)(void);
+       void (*destroy)(void);
+
+       void (*start)(void);
+       void (*stop)(void);
+
+       /* tm is the time from the start of this part in milliseconds */
+       void (*draw)(long tm);
+
+       /* optional: transition draw functions. if null, the regular draw will be
+        * called for the duration of the transition instead
+        */
+       void (*draw_in)(long tm, float t);
+       void (*draw_out)(long tm, float t);
+
+       /* optional, will be called only when active */
+       void (*reshape)(int x, int y);
+       void (*keyboard)(int key, int st);
+       void (*mbutton)(int bn, int st, int x, int y);
+       void (*mmotion)(int x, int y);
+};
+
+#define MAX_DEMO_PARTS 64
+extern struct demo_part *parts[MAX_DEMO_PARTS];
+extern int num_parts;
+
+extern struct demo_part *cur_part, *prev_part;
+
+void add_part(struct demo_part *part);
+void switch_part(struct demo_part *part);
+
+struct demo_part *find_part(const char *name);
+
+#endif /* PART_H_ */
diff --git a/src/part_whitted.c b/src/part_whitted.c
new file mode 100644 (file)
index 0000000..7154abf
--- /dev/null
@@ -0,0 +1,94 @@
+#include "opengl.h"
+#include "demo.h"
+#include "part.h"
+
+static int init(void);
+static void destroy(void);
+static void start(void);
+static void stop(void);
+static void draw(long tm);
+static void mbutton(int bn, int st, int x, int y);
+static void mmotion(int x, int y);
+
+static float cam_theta, cam_phi, cam_dist = 8;
+
+static int bnstate[8];
+static int mouse_x, mouse_y;
+
+static struct demo_part part = {
+       "whitted",
+       0, 0,
+       init, destroy,
+       start, stop,
+       draw,
+       0, 0,
+       0, 0,
+       mbutton, mmotion
+};
+
+void reg_whitted(void)
+{
+       add_part(&part);
+}
+
+
+static int init(void)
+{
+       return 0;
+}
+
+static void destroy(void)
+{
+}
+
+static void start(void)
+{
+}
+
+static void stop(void)
+{
+}
+
+static void draw(long tm)
+{
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+       glTranslatef(0, 0, -cam_dist);
+       glRotatef(cam_phi, 1, 0, 0);
+       glRotatef(cam_theta, 0, 1, 0);
+
+       glEnable(GL_LIGHTING);
+       glEnable(GL_LIGHT0);
+
+       glFrontFace(GL_CW);
+       glutSolidTeapot(1.0);
+       glFrontFace(GL_CCW);
+}
+
+static void mbutton(int bn, int st, int x, int y)
+{
+       bnstate[bn] = st;
+       mouse_x = x;
+       mouse_y = y;
+}
+
+static void mmotion(int x, int y)
+{
+       int dx = x - mouse_x;
+       int dy = y - mouse_y;
+       mouse_x = x;
+       mouse_y = y;
+
+       if(!(dx | dy)) return;
+
+       if(bnstate[0]) {
+               cam_theta += dx * 0.5;
+               cam_phi += dy * 0.5;
+               if(cam_phi < -90) cam_phi = -90;
+               if(cam_phi > 90) cam_phi = 90;
+       }
+       if(bnstate[2]) {
+               cam_dist += dy * 0.1;
+               if(cam_dist < 0) cam_dist = 0;
+       }
+}