494 lines
14 KiB
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;
|
|
}
|