e16-epplets/epplets/E-OpenGL-Demo.c

494 lines
14 KiB
C

/*
* Copyright (C) 1999-2000, Wayde Milas
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies of the Software, its documentation and marketing & publicity
* materials, and acknowledgment shall be given in the documentation, materials
* and software packages that this Software was used.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include "epplet.h"
static Epplet_gadget da, b_close, b_help, b_config;
static Epplet_gadget gObjectPopupButton, gLightingPopupButton,
gTexturingPopupButton;
static Window win;
static Display *dpy;
static GLfloat gSpin = 0.0;
static GLuint gObjectList, gTextureObject;
int gWhichRotate = 2, gLighting = 0, gTexturing = 0;
static void save_conf(void);
#define DEBUG 0
#define SQUARE 1
#define CUBE 2
#define OFF 0
#define ON 1
static const int object_type_table[] = {
SQUARE, CUBE
};
static const int lighting_type_table[] = {
OFF, ON
};
/* All setup_rotating_* fucntions compile our display lists. Since most
of the data is static, there is no reason we need to redraw it over
and over */
static void
setup_rotating_square(void)
{
GLfloat x = 40.0;
gObjectList = glGenLists(1);
glNewList(gObjectList, GL_COMPILE);
glBegin(GL_QUADS);
glColor3f(1.0, 0, 0);
glVertex3f(-x, -x, 0);
glColor3f(0, 1.0, 0);
glVertex3f(-x, x, 0);
glColor3f(0, 0, 1.0);
glVertex3f(x, x, 0);
glColor3f(1, 0, 1);
glVertex3f(x, -x, 0);
glEnd();
glPopMatrix();
glEndList();
}
static void
setup_rotating_cube(void)
{
/* coordinates for out cube... since im using + and -, the cube
* is actually 2*coords */
static GLfloat x = 32.0;
static GLfloat y = 32.0;
static GLfloat z = 32.0;
/* These are our 6 faces * 4 vertexes per face = 24 vertex
* coordinates. Its a bit messy, but its a hell of alot
* better than 24 glVertex3f() commands. */
GLfloat cubeVerts[] = {
-x, -y, z, -x, y, z, -x, y, -z, -x, -y, -z, /* left */
x, -y, z, x, -y, -z, x, y, -z, x, y, z, /* right */
-x, -y, z, x, -y, z, x, y, z, -x, y, z, /* front */
-x, -y, -z, -x, y, -z, x, y, -z, x, -y, -z, /* back */
-x, y, z, x, y, z, x, y, -z, -x, y, -z, /* top */
-x, -y, z, -x, -y, -z, x, -y, -z, x, -y, z
}; /* bottom */
static GLfloat cubeNormals[] = {
-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,
0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1,
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0
};
static GLfloat cubeColors[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,
1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1
};
static GLfloat cubeTexCords[] = {
0, 0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 1, 1, 1, 1, 0
};
gObjectList = glGenLists(1);
glNewList(gObjectList, GL_COMPILE);
if (gTexturing == 1)
glEnable(GL_TEXTURE_2D);
else
glDisable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBindTexture(GL_TEXTURE_2D, gTextureObject);
glEnable(GL_COLOR_MATERIAL);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, cubeVerts);
glNormalPointer(GL_FLOAT, 0, cubeNormals);
glColorPointer(3, GL_FLOAT, 0, cubeColors);
glTexCoordPointer(2, GL_FLOAT, 0, cubeTexCords);
glDrawArrays(GL_QUADS, 0, 24);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glEndList();
}
static void
enable_lighting(void)
{
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_amb_diff[] = { .447, .243, .678 };
GLfloat mat_shininess[] = { 100.0 };
#if 0
GLfloat light_position[] = { 0.0, 0.0, 1.0, 0.0 };
#endif /* Unused */
GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_amb_diff);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
/* We enable the lights, but notice we dont set the position till later */
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
static void
disable_lighting(void)
{
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
}
/* These are our actual drawing functions */
static void
draw_rotating(void)
{
GLfloat light_position[] = { 0.0, 20.0, 200.0, 1.0 };
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
/* If we have lights on, set the light position */
if (gLighting)
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glPushMatrix();
glRotatef(gSpin, 1, 1, .1);
glCallList(gObjectList);
glPopMatrix();
glXSwapBuffers(dpy, win);
}
static void
cb_timer(void *data __UNUSED__)
{
gSpin = gSpin + .5;
if (gSpin > 360.0)
gSpin = gSpin - 360.0;
draw_rotating();
Epplet_timer(cb_timer, NULL, 0, "TIMER");
}
static void
cb_close(void *data)
{
GLXContext *cx;
cx = (GLXContext *) data;
Epplet_unremember();
Esync();
if (cx)
Epplet_unbind_GL(*cx);
exit(0);
}
static void
cb_in(void *data __UNUSED__, Window w)
{
if (w == Epplet_get_main_window())
{
Epplet_gadget_show(b_close);
Epplet_gadget_show(b_help);
Epplet_gadget_show(b_config);
}
}
static void
cb_out(void *data __UNUSED__, Window w)
{
if (w == Epplet_get_main_window())
{
Epplet_gadget_hide(b_close);
Epplet_gadget_hide(b_help);
Epplet_gadget_hide(b_config);
}
}
static void
cb_help(void *data __UNUSED__)
{
Epplet_show_about("E-OpenGL-Demo");
}
static void
cb_config(void *data __UNUSED__)
{
Epplet_gadget_show(gObjectPopupButton);
Epplet_gadget_show(gLightingPopupButton);
Epplet_gadget_show(gTexturingPopupButton);
}
static void
cb_set_object(void *data)
{
int *newObject;
glDeleteLists(gObjectList, 1);
newObject = (int *)data;
gWhichRotate = *newObject;
save_conf();
Epplet_gadget_hide(gObjectPopupButton);
Epplet_gadget_hide(gLightingPopupButton);
Epplet_gadget_hide(gTexturingPopupButton);
if (gWhichRotate == SQUARE)
{
if (gLighting)
{
gLighting = OFF;
disable_lighting();
}
setup_rotating_square();
}
else
setup_rotating_cube();
}
static void
cb_set_lighting(void *data)
{
int *newLighting;
newLighting = (int *)data;
if (gLighting && !*(newLighting))
{ /* Lighting was on, turn it off */
gLighting = OFF;
disable_lighting();
}
else if (!gLighting && *newLighting && (gWhichRotate = CUBE))
{ /* Lighting was off, turn it on */
gLighting = ON;
enable_lighting();
}
save_conf();
Epplet_gadget_hide(gObjectPopupButton);
Epplet_gadget_hide(gLightingPopupButton);
Epplet_gadget_hide(gTexturingPopupButton);
}
static void
cb_set_texturing(void *data)
{
int *newTexturing;
newTexturing = (int *)data;
if (gTexturing && !*(newTexturing))
{ /* Texturing was on, turn it off */
gTexturing = OFF;
if (gWhichRotate == CUBE)
setup_rotating_cube();
}
else if (!gTexturing && *newTexturing && (gWhichRotate == CUBE))
{ /* Texturing was off, turn it on */
gTexturing = ON;
setup_rotating_cube();
}
save_conf();
Epplet_gadget_hide(gObjectPopupButton);
Epplet_gadget_hide(gLightingPopupButton);
Epplet_gadget_hide(gTexturingPopupButton);
}
static void
save_conf(void)
{
char s[8];
Esnprintf(s, sizeof(s), "%i", gWhichRotate);
Epplet_modify_config("gWhichRotate", s);
Esnprintf(s, sizeof(s), "%i", gLighting);
Epplet_modify_config("gLighting", s);
Esnprintf(s, sizeof(s), "%i", gTexturing);
Epplet_modify_config("gTexturing", s);
Epplet_save_config();
}
static void
load_conf(void)
{
const char *str;
str = Epplet_query_config_def("gWhichRotate", "2");
sscanf(str, "%i", &gWhichRotate);
str = Epplet_query_config_def("gLighting", "0");
sscanf(str, "%i", &gLighting);
str = Epplet_query_config_def("gTexturing", "0");
sscanf(str, "%i", &gTexturing);
}
int
main(int argc, char **argv)
{
char buf[1024];
GLXContext cx;
Epplet_gadget objectPopup, lightingPopup, texturePopup;
FILE *textureFile;
Epplet_adjust_priority(10);
/* This has to be an unsignned byte, otherwise you'll loose the 8th
* bit to the sign since the texture is 8 bits per color component. */
GLubyte textureArray[3 * 64 * 64];
atexit(Epplet_cleanup);
Epplet_Init("E-OpenGL-Demo", "0.1", "Enlightenment OpenGL Demo",
4, 4, argc, argv, 0);
Epplet_load_config();
Epplet_timer(cb_timer, NULL, 0, "TIMER");
Epplet_gadget_show(da = Epplet_create_drawingarea(2, 2, 60, 60));
/* We need win and dpy for the glXSwapBuffer */
win = Epplet_get_drawingarea_window(da);
dpy = Epplet_get_display();
b_close = Epplet_create_button(NULL, NULL, 0, 0, 0, 0, "CLOSE", win, NULL,
cb_close, (void *)(&cx));
b_help = Epplet_create_button(NULL, NULL, 14, 0, 0, 0, "HELP", win, NULL,
cb_help, NULL);
b_config = Epplet_create_button(NULL, NULL, 28, 0, 0, 0, "CONFIGURE",
win, NULL, cb_config, NULL);
objectPopup = Epplet_create_popup();
Epplet_add_popup_entry(objectPopup, "Square", NULL, cb_set_object,
(void *)(&(object_type_table[0])));
Epplet_add_popup_entry(objectPopup, "Cube", NULL, cb_set_object,
(void *)(&(object_type_table[1])));
gObjectPopupButton = Epplet_create_popupbutton("Objects", NULL,
9, 16, 46, 14, NULL,
objectPopup);
lightingPopup = Epplet_create_popup();
Epplet_add_popup_entry(lightingPopup, "Off", NULL, cb_set_lighting,
(void *)(&(lighting_type_table[0])));
Epplet_add_popup_entry(lightingPopup, "On", NULL, cb_set_lighting,
(void *)(&(lighting_type_table[1])));
gLightingPopupButton = Epplet_create_popupbutton("Lights", NULL,
13, 31, 38, 14, NULL,
lightingPopup);
texturePopup = Epplet_create_popup();
Epplet_add_popup_entry(texturePopup, "Off", NULL, cb_set_texturing,
(void *)(&(lighting_type_table[0])));
Epplet_add_popup_entry(texturePopup, "On", NULL, cb_set_texturing,
(void *)(&(lighting_type_table[1])));
gTexturingPopupButton = Epplet_create_popupbutton("Textures", NULL,
9, 46, 46, 14, NULL,
texturePopup);
Epplet_register_focus_in_handler(cb_in, NULL);
Epplet_register_focus_out_handler(cb_out, NULL);
load_conf();
cx = Epplet_default_bind_GL(da);
/* This could also be done as:
* cx = Epplet_bind_double_GL(da, 1, 1, 1, 0, 0, 8, 0, 0, 0, 0, 0); */
if (!cx)
cb_close(NULL);
/* To properly center the viewport, -2, -2 isntead of 0, 0 must be used.
* Why? I have no freak'n idea. For some reason in Ortho everything is
* coming ot 2 pixes shifted right and up. I'll look into it when I'm bored
* or something */
glViewport(-2, -2, 60, 60);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-60.0, 60.0, -60.0, 60.0, -60.0, 60.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0, 0, 0, 0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
/* Lets load teh texture */
Esnprintf(buf, sizeof(buf), "%s/cube_texture.RGB", Epplet_data_dir());
if (!(textureFile = fopen(buf, "rb")))
{
printf("Failed to load the cube texture file!\n");
}
else
{
fread(textureArray, sizeof(GLubyte), 3 * 64 * 64, textureFile);
fclose(textureFile);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &gTextureObject);
glBindTexture(GL_TEXTURE_2D, gTextureObject);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB,
GL_UNSIGNED_BYTE, textureArray);
}
Epplet_show();
/* Sstup the default lighting */
if (gLighting && gWhichRotate != SQUARE)
enable_lighting();
/* Compile the display lists */
if (gWhichRotate == SQUARE)
setup_rotating_square();
else
setup_rotating_cube();
Epplet_Loop();
return 0;
}