+#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;
}
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)
#define DEMO_H_
extern int win_width, win_height;
+extern float win_aspect;
extern long time_msec;
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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_ */
--- /dev/null
+#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;
+ }
+}