Skip to content

Instantly share code, notes, and snippets.

@snipsnipsnip
Last active August 24, 2019 15:34
Show Gist options
  • Save snipsnipsnip/141360 to your computer and use it in GitHub Desktop.
Save snipsnipsnip/141360 to your computer and use it in GitHub Desktop.
http://gist.github.com/141327 with SDL and SDL_image
#ifndef DEBUG_H_
#define DEBUG_H_
#ifdef _MSC_VER
#define PrintInfoFormatIntlIntl(p,line) \
stderr, __FILE__ ":" #line ":" __FUNCTION__ ": " p "\n"
#else
#define PrintInfoFormatIntlIntl(p,line) \
stderr, __FILE__ ":" #line ":%s: " p "\n", __func__
#endif
#define PrintInfoFormatIntl(p,line) PrintInfoFormatIntlIntl(p,line)
#define PrintInfoFormat(p) PrintInfoFormatIntl(p,__LINE__)
#define PrintInfo(p) fprintf(PrintInfoFormat(p))
#define PrintInfo1(p,x) fprintf(PrintInfoFormat(p), x)
#define PrintInfo2(p,x,y) fprintf(PrintInfoFormat(p), x, y)
#define PrintInfo3(p,x,y,z) fprintf(PrintInfoFormat(p), x, y, z)
#define PrintInfo4(p,x,y,z,w) fprintf(PrintInfoFormat(p), x, y, z, w)
#define PrintInfo5(p,x,y,z,w,v) fprintf(PrintInfoFormat(p), x, y, z, w, v)
#define EnsureIntl(x) \
do \
{ \
if (!(x)) \
{ \
PrintInfo("ensure failed: " #x); \
exit(EXIT_FAILURE); \
} \
} while (0)
#define Ensure(x) EnsureIntl(x)
#endif /* DEBUG_H_ */
#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <GL/glu.h>
#include "debug.h"
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
#define OPENGL_RGBA_MASKS 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
#else
#define OPENGL_RGBA_MASKS 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF
#endif
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
typedef struct
{
int x;
int y;
}
Coordinates;
static Coordinates viewpos, viewpos_saved, drag_start_pos;
static int wireframe = 0;
static GLUquadric *qo = NULL;
static GLuint texture = -1;
static int draw_cylinder = 0;
static GLuint slice = 48;
static double radius = 1.3;
static float angle = 80.0f;
static float aspect = 0.75f;
static int jelly_count = -1;
static SDL_TimerID jelly_timer;
void stop_jelly(void)
{
if (jelly_count != -1)
{
SDL_RemoveTimer(jelly_timer);
}
jelly_count = -1;
PrintInfo("jelly stopped");
}
void cleanup(void)
{
PrintInfo("start");
stop_jelly();
if (glIsTexture(texture))
{
glDeleteTextures(1, &texture);
}
if (qo != NULL)
{
gluDeleteQuadric(qo);
}
PrintInfo("end");
}
void load_texture(const char *filename)
{
SDL_Surface *tex;
SDL_Surface *intermediary;
PrintInfo1("start (filename \"%s\")", filename);
if(!(tex = IMG_Load(filename)))
{
PrintInfo1("%s", IMG_GetError());
Ensure(0);
}
Ensure(intermediary = SDL_CreateRGBSurface(
SDL_SWSURFACE | SDL_HWSURFACE,
tex->w, tex->h, 32,
OPENGL_RGBA_MASKS));
SDL_BlitSurface(tex, 0, intermediary, 0);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Ensure(0 == gluBuild2DMipmaps(
GL_TEXTURE_2D, 4, intermediary->w, intermediary->h,
GL_RGBA, GL_UNSIGNED_BYTE, intermediary->pixels));
SDL_FreeSurface(intermediary);
SDL_FreeSurface(tex);
PrintInfo("end");
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glLoadIdentity();
glRotated(viewpos.y, 1, 0, 0);
glRotated(viewpos.x, 0, 0, 1);
gluQuadricDrawStyle(qo, wireframe ? GLU_LINE : GLU_FILL);
gluSphere(qo, radius, slice, slice); // draw sphere
if (draw_cylinder)
{
glTranslated(0, 0, -radius);
gluCylinder(qo, radius, radius, radius * 2, slice, slice);
}
glPopMatrix();
glFlush();
SDL_GL_SwapBuffers();
}
// mouse down/up event
void mouse(int button, int state, int x, int y)
{
if (state == SDL_PRESSED)
{
drag_start_pos.x = x;
drag_start_pos.y = y;
viewpos_saved = viewpos;
}
}
// mouse move event
void motion(int x, int y)
{
double fac = 0.2;
viewpos.x = viewpos_saved.x + ((int)((x - drag_start_pos.x) * fac)) % 360;
viewpos.y = viewpos_saved.y + ((int)((drag_start_pos.y - y) * fac)) % 360;
display(); // to redraw
}
void jelly(void)
{
PrintInfo1("count %d", jelly_count);
if (jelly_count < 0 || jelly_count == 48 * 2)
{
stop_jelly();
PrintInfo("jelly finished");
return;
}
if (jelly_count == 0)
{
slice = 3;
}
else if (jelly_count % 2 == 0)
{
slice++;
}
jelly_count++;
display();
}
void help(void)
{
puts("Z or X: increment/decrement slice");
puts("A or S: increment/decrement radius");
puts("D or F: increment/decrement view angle");
puts("J: jelly");
puts("C: toggle cylinder");
puts("R: reset parameters");
puts("H: show this help");
puts("Q or ESC: exit");
}
void reset_perspective(void)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(angle, aspect, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void reset_view_parameters(void)
{
Coordinates viewpos_initial = { 0, 90 };
Coordinates drag_start_pos_initial = { 0, 0 };
viewpos = viewpos_initial;
viewpos_saved = viewpos_initial;
drag_start_pos = drag_start_pos_initial;
}
void reset_parameters(void)
{
stop_jelly();
reset_view_parameters();
wireframe = 0;
draw_cylinder = 0;
radius = 1.3;
slice = 48;
angle = 80.0f;
aspect = 0.75f;
}
Uint32 push_user_event(Uint32 interval, void *param)
{
SDL_Event event;
event.type = SDL_USEREVENT;
SDL_PushEvent(&event);
return interval;
}
// keyboard down event
void keyboard(unsigned char key, int x, int y)
{
PrintInfo1("key: '%c'", key);
switch (key)
{
case 'd':
angle++;
reset_perspective();
break;
case 'f':
angle--;
reset_perspective();
break;
case 'z':
slice++;
break;
case 'x':
slice--;
break;
case 'a':
radius += 0.1;
break;
case 's':
radius -= 0.1;
break;
case 'j':
if (jelly_count < 0)
{
PrintInfo("jelly started");
jelly_count = 0;
jelly_timer = SDL_AddTimer(1000 / 30, push_user_event, NULL);
}
else
{
PrintInfo("jelly is already started");
}
return;
case 'c':
draw_cylinder = !draw_cylinder;
break;
case 'w':
wireframe = !wireframe;
break;
case 'r':
reset_parameters();
break;
case 'h':
help();
return;
case 'q':
case 27:
exit(1);
}
PrintInfo4("slice: %d, radius: %lf, angle: %f, wireframe: %d", slice, radius, angle, wireframe);
display();
}
void init_sdl(const char *filename)
{
char *window_caption;
Ensure(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) >= 0);
Ensure(SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 0, SDL_OPENGL | SDL_RESIZABLE));
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
Ensure(window_caption = malloc(sizeof("Panorama View: \"\"") + strlen(filename)));
sprintf(window_caption, "Panorama View: \"%s\"", filename);
SDL_WM_SetCaption(window_caption, window_caption);
free(window_caption);
}
void reshape(int width, int height)
{
glViewport(0, 0, width, height);
aspect = width/(float)height;
reset_view_parameters();
reset_perspective();
display();
}
void push_resize_event(void)
{
SDL_Event event;
event.type = SDL_VIDEORESIZE;
event.resize.w = WINDOW_WIDTH;
event.resize.h = WINDOW_HEIGHT;
SDL_PushEvent(&event);
}
void init_gl(void)
{
glEnable(GL_TEXTURE_2D);
glClearColor(0.2, 0.2, 0.2, 1.0);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
Ensure(qo = gluNewQuadric());
gluQuadricNormals(qo, GLU_SMOOTH);
gluQuadricTexture(qo, GL_TRUE);
push_resize_event();
}
void init(int argc, char **argv)
{
atexit(cleanup);
Ensure(argc > 1);
init_sdl(argv[1]);
init_gl();
load_texture(argv[1]);
reset_parameters();
}
void process_event(SDL_Event *event)
{
switch (event->type)
{
case SDL_VIDEORESIZE:
reshape(event->resize.w, event->resize.h);
break;
case SDL_VIDEOEXPOSE:
display();
break;
case SDL_KEYDOWN:
keyboard(event->key.keysym.sym, 0, 0);
break;
case SDL_MOUSEMOTION:
if (event->motion.state == SDL_PRESSED)
{
motion(event->motion.x, event->motion.y);
}
break;
case SDL_MOUSEBUTTONDOWN:
mouse(event->button.button, event->button.state, event->button.x, event->button.y);
break;
case SDL_USEREVENT:
jelly();
break;
case SDL_QUIT:
exit(0);
}
}
void run_sdl(void)
{
SDL_Event event;
for (;;)
{
Ensure(SDL_WaitEvent(&event));
process_event(&event);
}
}
int main(int argc, char **argv)
{
help();
init(argc, argv);
run_sdl();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment