Last active
August 24, 2019 15:34
-
-
Save snipsnipsnip/141360 to your computer and use it in GitHub Desktop.
http://gist.github.com/141327 with SDL and SDL_image
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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