-
-
Save snipsnipsnip/141327 to your computer and use it in GitHub Desktop.
spherical_panorama_sample.c
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 DEBUG_H_FUNCTION_NAME __FUNCTION__ | |
#else | |
# define DEBUG_H_FUNCTION_NAME __func__ | |
#endif | |
#define PrintInfoFormatIntlIntl(p,line) \ | |
stderr, __FILE__ " " DEBUG_H_FUNCTION_NAME " " #line ": " p "\n" | |
#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 <glut.h> | |
#include <wand/studio.h> | |
#include "debug.h" | |
#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; | |
void cleanup(void) | |
{ | |
PrintInfo("start"); | |
if (glIsTexture(texture)) | |
{ | |
glDeleteTextures(1, &texture); | |
} | |
if (qo != NULL) | |
{ | |
gluDeleteQuadric(qo); | |
} | |
PrintInfo("end"); | |
} | |
unsigned char *load_texture_rawdata(const char *filename, unsigned long *width, unsigned long *height) | |
{ | |
size_t length = 0; | |
unsigned char *blob; | |
MagickWand *wand; | |
PrintInfo("start"); | |
Ensure(wand = NewMagickWand()); | |
Ensure(MagickReadImage(wand, filename)); | |
Ensure(MagickSetDepth(wand, 8)); | |
Ensure(MagickSetFormat(wand, "RGBA")); | |
Ensure(blob = MagickGetImagesBlob(wand, &length)); | |
*width = MagickGetImageWidth(wand); | |
*height = MagickGetImageHeight(wand); | |
DestroyMagickWand(wand); | |
PrintInfo3("image size %lux%lu (%lu byte)", *height, *width, length); | |
PrintInfo("end"); | |
return blob; | |
} | |
void load_texture(const char *filename) | |
{ | |
unsigned long width, height; | |
unsigned char *raw; | |
PrintInfo1("start (filename \"%s\")", filename); | |
raw = load_texture_rawdata(filename, &width, &height); | |
glGenTextures(1, &texture); | |
glBindTexture(GL_TEXTURE_2D, texture); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
//glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, raw); | |
Ensure(0 == gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width, height, GL_RGBA, GL_UNSIGNED_BYTE, raw)); | |
free(raw); | |
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(); | |
glutSwapBuffers(); | |
} | |
// mouse down/up event | |
void mouse(int button, int state, int x, int y) | |
{ | |
if (state == 0) | |
{ | |
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; | |
glutPostRedisplay(); // to redraw | |
} | |
void jelly(int count) | |
{ | |
PrintInfo1("count %d", count); | |
if (count == 48 * 2) | |
{ | |
return; | |
} | |
if (count == 0) | |
{ | |
slice = 3; | |
} | |
else if (count % 2 == 0) | |
{ | |
slice++; | |
} | |
glutPostRedisplay(); | |
glutTimerFunc(1000 / 30, jelly, count + 1); | |
} | |
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_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; | |
wireframe = 0; | |
draw_cylinder = 0; | |
radius = 1.3; | |
slice = 48; | |
angle = 80.0f; | |
aspect = 0.75f; | |
} | |
// 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': | |
glutTimerFunc(1000 / 30, jelly, 0); | |
PrintInfo("start jelly"); | |
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); | |
glutPostRedisplay(); | |
} | |
void init_glut(int *argc, char **argv) | |
{ | |
char *window_caption; | |
glutInit(argc, argv); | |
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); | |
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); | |
Ensure(argc != NULL); | |
Ensure(*argc > 1); | |
Ensure(window_caption = malloc(sizeof("Panorama View: \"\"") + strlen(argv[1]))); | |
sprintf(window_caption, "Panorama View: \"%s\"", argv[1]); | |
glutCreateWindow(window_caption); | |
free(window_caption); | |
} | |
void reshape(int width, int height) | |
{ | |
glViewport(0, 0, width, height); | |
aspect = width/(float)height; | |
reset_perspective(); | |
} | |
void init_gl(void) | |
{ | |
reshape(WINDOW_WIDTH, WINDOW_HEIGHT); | |
glEnable(GL_TEXTURE_2D); | |
glClearColor(0.2, 0.2, 0.2, 1.0); | |
Ensure(qo = gluNewQuadric()); | |
gluQuadricNormals(qo, GLU_SMOOTH); | |
gluQuadricTexture(qo, GL_TRUE); | |
} | |
void init(int argc, char **argv) | |
{ | |
atexit(cleanup); | |
init_glut(&argc, argv); | |
init_gl(); | |
load_texture(argv[1]); | |
reset_parameters(); | |
} | |
void run_glut(void) | |
{ | |
glutDisplayFunc(display); | |
glutKeyboardFunc(keyboard); | |
glutMouseFunc(mouse); | |
glutMotionFunc(motion); | |
glutReshapeFunc(reshape); | |
glutMainLoop(); | |
} | |
int main(int argc, char **argv) | |
{ | |
help(); | |
init(argc, argv); | |
run_glut(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment