Created
November 19, 2023 04:00
-
-
Save 5HT/35480ce546e0781075ae5e5d274e5f8f to your computer and use it in GitHub Desktop.
Pure Windows X System, Xlib, GLX (Similar to Pure Win32 and Pure Cocoa/NeXT)
This file contains hidden or 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<X11/X.h> | |
#include<X11/Xlib.h> | |
#include<GL/gl.h> | |
#include<GL/glx.h> | |
#include<GL/glu.h> | |
Display *dpy; | |
Window root; | |
GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; | |
XVisualInfo *vi; | |
Colormap cmap; | |
XSetWindowAttributes swa; | |
Window win; | |
GLXContext glc; | |
XWindowAttributes gwa; | |
XEvent xev; | |
void DrawAQuad() { | |
glClearColor(1.0, 1.0, 1.0, 1.0); | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
glMatrixMode(GL_PROJECTION); | |
glLoadIdentity(); | |
glOrtho(-1., 1., -1., 1., 1., 20.); | |
glMatrixMode(GL_MODELVIEW); | |
glLoadIdentity(); | |
gluLookAt(0., 0., 10., 0., 0., 0., 0., 1., 0.); | |
glBegin(GL_QUADS); | |
glColor3f(1., 0., 0.); glVertex3f(-.75, -.75, 0.); | |
glColor3f(0., 1., 0.); glVertex3f( .75, -.75, 0.); | |
glColor3f(0., 0., 1.); glVertex3f( .75, .75, 0.); | |
glColor3f(1., 1., 0.); glVertex3f(-.75, .75, 0.); | |
glEnd(); | |
} | |
int main(int argc, char *argv[]) { | |
dpy = XOpenDisplay(NULL); | |
if(dpy == NULL) { | |
printf("\n\tcannot connect to X server\n\n"); | |
exit(0); | |
} | |
root = DefaultRootWindow(dpy); | |
vi = glXChooseVisual(dpy, 0, att); | |
if(vi == NULL) { | |
printf("\n\tno appropriate visual found\n\n"); | |
exit(0); | |
} | |
else { | |
printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */ | |
} | |
cmap = XCreateColormap(dpy, root, vi->visual, AllocNone); | |
swa.colormap = cmap; | |
swa.event_mask = ExposureMask | KeyPressMask; | |
win = XCreateWindow(dpy, root, 0, 0, 600, 600, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa); | |
XMapWindow(dpy, win); | |
XStoreName(dpy, win, "VERY SIMPLE APPLICATION"); | |
glc = glXCreateContext(dpy, vi, NULL, GL_TRUE); | |
glXMakeCurrent(dpy, win, glc); | |
glEnable(GL_DEPTH_TEST); | |
while(1) { | |
XNextEvent(dpy, &xev); | |
if(xev.type == Expose) { | |
XGetWindowAttributes(dpy, win, &gwa); | |
glViewport(0, 0, gwa.width, gwa.height); | |
DrawAQuad(); | |
glXSwapBuffers(dpy, win); | |
} | |
else if(xev.type == KeyPress) { | |
glXMakeCurrent(dpy, None, NULL); | |
glXDestroyContext(dpy, glc); | |
XDestroyWindow(dpy, win); | |
XCloseDisplay(dpy); | |
exit(0); | |
} | |
} | |
} |
This file contains hidden or 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 <X11/Xlib.h> | |
/* | |
If you get linking errors when using C++, you need | |
to add extern "C" here or in X11-xcb.h, unless | |
this bug is already fixed in your version: | |
http://bugs.freedesktop.org/show_bug.cgi?id=22252 | |
*/ | |
#include <X11/Xlib-xcb.h> /* for XGetXCBConnection, link with libX11-xcb */ | |
#include <xcb/xcb.h> | |
#include <GL/glx.h> | |
#include <GL/gl.h> | |
/* | |
Attribs filter the list of FBConfigs returned by glXChooseFBConfig(). | |
Visual attribs further described in glXGetFBConfigAttrib(3) | |
*/ | |
static int visual_attribs[] = | |
{ | |
GLX_X_RENDERABLE, True, | |
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, | |
GLX_RENDER_TYPE, GLX_RGBA_BIT, | |
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, | |
GLX_RED_SIZE, 8, | |
GLX_GREEN_SIZE, 8, | |
GLX_BLUE_SIZE, 8, | |
GLX_ALPHA_SIZE, 8, | |
GLX_DEPTH_SIZE, 24, | |
GLX_STENCIL_SIZE, 8, | |
GLX_DOUBLEBUFFER, True, | |
//GLX_SAMPLE_BUFFERS , 1, | |
//GLX_SAMPLES , 4, | |
None | |
}; | |
void draw() | |
{ | |
glClearColor(0.2, 0.4, 0.9, 1.0); | |
glClear(GL_COLOR_BUFFER_BIT); | |
} | |
int main_loop(Display *display, xcb_connection_t *connection, xcb_window_t window, GLXDrawable drawable) | |
{ | |
int running = 1; | |
while(running) | |
{ | |
/* Wait for event */ | |
xcb_generic_event_t *event = xcb_wait_for_event(connection); | |
if(!event) | |
{ | |
fprintf(stderr, "i/o error in xcb_wait_for_event"); | |
return -1; | |
} | |
switch(event->response_type & ~0x80) | |
{ | |
case XCB_KEY_PRESS: | |
/* Quit on key press */ | |
running = 0; | |
break; | |
case XCB_EXPOSE: | |
/* Handle expose event, draw and swap buffers */ | |
draw(); | |
glXSwapBuffers(display, drawable); | |
break; | |
default: | |
break; | |
} | |
free(event); | |
} | |
return 0; | |
} | |
int setup_and_run(Display* display, xcb_connection_t *connection, int default_screen, xcb_screen_t *screen) | |
{ | |
int visualID = 0; | |
/* Query framebuffer configurations that match visual_attribs */ | |
GLXFBConfig *fb_configs = 0; | |
int num_fb_configs = 0; | |
fb_configs = glXChooseFBConfig(display, default_screen, visual_attribs, &num_fb_configs); | |
if(!fb_configs || num_fb_configs == 0) | |
{ | |
fprintf(stderr, "glXGetFBConfigs failed\n"); | |
return -1; | |
} | |
printf("Found %d matching FB configs", num_fb_configs); | |
/* Select first framebuffer config and query visualID */ | |
GLXFBConfig fb_config = fb_configs[0]; | |
glXGetFBConfigAttrib(display, fb_config, GLX_VISUAL_ID , &visualID); | |
GLXContext context; | |
/* Create OpenGL context */ | |
context = glXCreateNewContext(display, fb_config, GLX_RGBA_TYPE, 0, True); | |
if(!context) | |
{ | |
fprintf(stderr, "glXCreateNewContext failed\n"); | |
return -1; | |
} | |
/* Create XID's for colormap and window */ | |
xcb_colormap_t colormap = xcb_generate_id(connection); | |
xcb_window_t window = xcb_generate_id(connection); | |
/* Create colormap */ | |
xcb_create_colormap( | |
connection, | |
XCB_COLORMAP_ALLOC_NONE, | |
colormap, | |
screen->root, | |
visualID | |
); | |
/* Create window */ | |
uint32_t eventmask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS; | |
uint32_t valuelist[] = { eventmask, colormap, 0 }; | |
uint32_t valuemask = XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; | |
xcb_create_window( | |
connection, | |
XCB_COPY_FROM_PARENT, | |
window, | |
screen->root, | |
0, 0, | |
150, 150, | |
0, | |
XCB_WINDOW_CLASS_INPUT_OUTPUT, | |
visualID, | |
valuemask, | |
valuelist | |
); | |
// NOTE: window must be mapped before glXMakeContextCurrent | |
xcb_map_window(connection, window); | |
/* Create GLX Window */ | |
GLXDrawable drawable = 0; | |
GLXWindow glxwindow = | |
glXCreateWindow( | |
display, | |
fb_config, | |
window, | |
0 | |
); | |
if(!window) | |
{ | |
xcb_destroy_window(connection, window); | |
glXDestroyContext(display, context); | |
fprintf(stderr, "glXDestroyContext failed\n"); | |
return -1; | |
} | |
drawable = glxwindow; | |
/* make OpenGL context current */ | |
if(!glXMakeContextCurrent(display, drawable, drawable, context)) | |
{ | |
xcb_destroy_window(connection, window); | |
glXDestroyContext(display, context); | |
fprintf(stderr, "glXMakeContextCurrent failed\n"); | |
return -1; | |
} | |
/* run main loop */ | |
int retval = main_loop(display, connection, window, drawable); | |
/* Cleanup */ | |
glXDestroyWindow(display, glxwindow); | |
xcb_destroy_window(connection, window); | |
glXDestroyContext(display, context); | |
return retval; | |
} | |
int main(int argc, char* argv[]) | |
{ | |
Display *display; | |
int default_screen; | |
/* Open Xlib Display */ | |
display = XOpenDisplay(0); | |
if(!display) | |
{ | |
fprintf(stderr, "Can't open display\n"); | |
return -1; | |
} | |
default_screen = DefaultScreen(display); | |
/* Get the XCB connection from the display */ | |
xcb_connection_t *connection = | |
XGetXCBConnection(display); | |
if(!connection) | |
{ | |
XCloseDisplay(display); | |
fprintf(stderr, "Can't get xcb connection from display\n"); | |
return -1; | |
} | |
/* Acquire event queue ownership */ | |
XSetEventQueueOwner(display, XCBOwnsEventQueue); | |
/* Find XCB screen */ | |
xcb_screen_t *screen = 0; | |
xcb_screen_iterator_t screen_iter = | |
xcb_setup_roots_iterator(xcb_get_setup(connection)); | |
for(int screen_num = default_screen; | |
screen_iter.rem && screen_num > 0; | |
--screen_num, xcb_screen_next(&screen_iter)); | |
screen = screen_iter.data; | |
/* Initialize window and OpenGL context, run main loop and deinitialize */ | |
int retval = setup_and_run(display, connection, default_screen, screen); | |
/* Cleanup */ | |
XCloseDisplay(display); | |
return retval; | |
} |
This file contains hidden or 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 <string.h> | |
#include <unistd.h> | |
#include <X11/Xlib.h> | |
#include <X11/Xutil.h> | |
#include <GL/glew.h> | |
#include <GL/gl.h> | |
#include <GL/glx.h> | |
#include "common/other.h" | |
#include "common/error.h" | |
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 | |
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 | |
typedef GLXContext (*glXCreateContextAttribsARBProc) | |
(Display*, GLXFBConfig, GLXContext, Bool, const int*); | |
const int visual_attribs[] = { | |
GLX_X_RENDERABLE , true, | |
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, | |
GLX_RENDER_TYPE , GLX_RGBA_BIT, | |
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR, | |
GLX_RED_SIZE , 8, | |
GLX_GREEN_SIZE , 8, | |
GLX_BLUE_SIZE , 8, | |
GLX_ALPHA_SIZE , 8, | |
GLX_DEPTH_SIZE , 24, | |
GLX_STENCIL_SIZE , 8, | |
GLX_DOUBLEBUFFER , true, | |
//GLX_SAMPLE_BUFFERS , 1, | |
//GLX_SAMPLES , 4, | |
None | |
}; | |
void checkGlxVersion(Display* display) { | |
int glx_major, glx_minor; | |
// FBConfigs were added in GLX version 1.3. | |
if (!glXQueryVersion(display, &glx_major, &glx_minor) || | |
((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1)) | |
fail("Invalid GLX version"); | |
} | |
GLXFBConfig chooseFBConfig(Display* display) { | |
printf("Getting matching framebuffer configs\n"); | |
int fbcount; | |
GLXFBConfig* fbc = glXChooseFBConfig(display, DefaultScreen(display), | |
visual_attribs, &fbcount); | |
if (!fbc) | |
fail("Failed to retrieve a framebuffer config\n"); | |
printf("Found %d matching FB configs.\n", fbcount); | |
// Pick the FB config/visual with the most samples per pixel | |
printf("Getting XVisualInfos\n"); | |
int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, | |
worst_num_samp = 999; | |
for (int i = 0; i < fbcount; ++i) { | |
XVisualInfo *vi = glXGetVisualFromFBConfig(display, fbc[i]); | |
if (vi) { | |
int samp_buf, samples; | |
glXGetFBConfigAttrib(display, fbc[i], GLX_SAMPLE_BUFFERS, | |
&samp_buf); | |
glXGetFBConfigAttrib(display, fbc[i], GLX_SAMPLES, &samples); | |
printf("\tMatching fbconfig %d, visual ID 0x%2lx: " | |
"SAMPLE_BUFFERS = %d, SAMPLES = %d\n", | |
i, vi -> visualid, samp_buf, samples); | |
if (best_fbc < 0 || (samp_buf && samples) > best_num_samp) | |
best_fbc = i, best_num_samp = samples; | |
if (worst_fbc < 0 || !samp_buf || samples < worst_num_samp) | |
worst_fbc = i, worst_num_samp = samples; | |
} | |
XFree(vi); | |
} | |
GLXFBConfig best = fbc[best_fbc]; | |
XFree(fbc); | |
return best; | |
} | |
GLXContext createContext(Display* display, GLXFBConfig bestFbc) { | |
// NOTE: It is not necessary to create or make current to a context before | |
// calling glXGetProcAddressARB | |
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; | |
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) | |
glXGetProcAddressARB((const GLubyte *) "glXCreateContextAttribsARB"); | |
int context_attribs[] = { | |
GLX_CONTEXT_MAJOR_VERSION_ARB, 3, | |
GLX_CONTEXT_MINOR_VERSION_ARB, 0, | |
//GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, | |
None | |
}; | |
printf("Creating context\n"); | |
GLXContext context = 0; | |
context = glXCreateContextAttribsARB(display, bestFbc, 0, | |
true, context_attribs); | |
// Sync to ensure any errors generated are processed. | |
XSync(display, false); | |
if (context) printf("Created GL 3.0 context\n"); | |
else fail("Failed to create GL 3.0 context\n"); | |
// Sync to ensure any errors generated are processed. | |
XSync(display, false); | |
if (! glXIsDirect(display, context)) | |
printf("Indirect GLX rendering context obtained\n"); | |
else | |
printf("Direct GLX rendering context obtained\n"); | |
return context; | |
} | |
int main(int argc, char* argv[]) { | |
Display *display = XOpenDisplay(NULL); | |
if (!display) | |
fail("Failed to open X display\n"); | |
checkGlxVersion(display); | |
auto bestFbc = chooseFBConfig(display); | |
// Get a visual | |
XVisualInfo *vi = glXGetVisualFromFBConfig(display, bestFbc); | |
printf("Chosen visual ID = 0x%lx\n", vi->visualid); | |
printf("Creating colormap\n"); | |
XSetWindowAttributes swa; | |
Colormap cmap; | |
swa.colormap = cmap = XCreateColormap(display, | |
RootWindow(display, vi->screen), | |
vi->visual, AllocNone); | |
swa.background_pixmap = None ; | |
swa.border_pixel = 0; | |
swa.event_mask = StructureNotifyMask; | |
printf("Creating window\n"); | |
Window win = XCreateWindow(display, RootWindow(display, vi->screen), | |
0, 0, 100, 100, 0, vi->depth, InputOutput, | |
vi->visual, | |
CWBorderPixel|CWColormap|CWEventMask, &swa); | |
if (!win) | |
fail("Failed to create window.\n"); | |
// Done with the visual info data | |
XFree(vi); | |
XStoreName(display, win, "GL 3.0 Window"); | |
printf("Mapping window\n"); | |
XMapWindow(display, win); | |
auto context = createContext(display, bestFbc); | |
printf("Making context current\n"); | |
glXMakeCurrent(display, win, context); | |
initGlew(); | |
glClearColor(0, 0.5, 1, 1); | |
glClear(GL_COLOR_BUFFER_BIT); | |
glXSwapBuffers(display, win); | |
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
sleep(1); | |
glClearColor(1, 0.5, 0, 1); | |
glClear(GL_COLOR_BUFFER_BIT); | |
glXSwapBuffers(display, win); | |
sleep(1); | |
glXMakeCurrent(display, 0, 0); | |
glXDestroyContext(display, context); | |
XDestroyWindow(display, win); | |
XFreeColormap(display, cmap); | |
XCloseDisplay(display); | |
return 0; | |
} |
This file contains hidden or 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 <X11/Xlib.h> | |
// This program draws a red line and some text in a chosen font. | |
Display *display; | |
Window window; | |
XSetWindowAttributes attributes; | |
XGCValues gr_values; | |
XFontStruct *fontinfo; | |
GC gr_context; | |
Visual *visual; | |
int depth; | |
int screen; | |
XEvent event; | |
XColor color, dummy; | |
int main() { | |
display = XOpenDisplay(NULL); | |
screen = DefaultScreen(display); | |
visual = DefaultVisual(display,screen); | |
depth = DefaultDepth(display,screen); | |
attributes.background_pixel = XWhitePixel(display,screen); | |
window = XCreateWindow( display,XRootWindow(display,screen), | |
200, 200, 350, 200, 5, depth, InputOutput, | |
visual ,CWBackPixel, &attributes); | |
XSelectInput(display,window,ExposureMask | KeyPressMask) ; | |
fontinfo = XLoadQueryFont(display,"8x14"); | |
XAllocNamedColor(display, DefaultColormap(display, screen),"red", | |
&color,&dummy); | |
gr_values.font = fontinfo->fid; | |
gr_values.foreground = color.pixel; | |
gr_context=XCreateGC(display,window,GCFont+GCForeground, &gr_values); | |
XFlush(display); | |
XMapWindow(display,window); | |
XFlush(display); | |
while(1){ | |
XNextEvent(display,&event); | |
switch(event.type){ | |
case Expose: | |
XDrawLine(display,window,gr_context,0,0, 100, 100); | |
XDrawString(display,window,gr_context,100,100,"hello",5); | |
break; | |
case KeyPress: | |
XCloseDisplay(display); | |
return 1; | |
} | |
} | |
return 0; | |
} |
This file contains hidden or 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<string.h> | |
#include<unistd.h> | |
#include<math.h> | |
#include<time.h> | |
#include<sys/time.h> | |
#include<X11/Xlib.h> | |
#include<X11/XKBlib.h> | |
#include<GL/glx.h> | |
#include<GL/glext.h> | |
#include<GL/glu.h> | |
////////////////////////////////////////////////////////////////////////////////// | |
// GLOBAL IDENTIFIERS // | |
////////////////////////////////////////////////////////////////////////////////// | |
Display *dpy; | |
Window root, win; | |
GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; | |
XVisualInfo *vi; | |
GLXContext glc; | |
Colormap cmap; | |
XSetWindowAttributes swa; | |
XWindowAttributes wa; | |
XEvent xev; | |
float TimeCounter, LastFrameTimeCounter, DT, prevTime = 0.0, FPS; | |
struct timeval tv, tv0; | |
int Frame = 1, FramesPerFPS; | |
GLfloat rotation_matrix[16]; | |
float rot_z_vel = 50.0, rot_y_vel = 30.0; | |
////////////////////////////////////////////////////////////////////////////////// | |
// DRAW A CUBE // | |
////////////////////////////////////////////////////////////////////////////////// | |
void DrawCube(float size) { | |
glBegin(GL_QUADS); | |
glColor3f(0.7, 0.0, 0.0); | |
glVertex3f(-size, -size, -size); | |
glVertex3f( size, -size, -size); | |
glVertex3f( size, size, -size); | |
glVertex3f(-size, size, -size); | |
glVertex3f(-size, -size, size); | |
glVertex3f( size, -size, size); | |
glVertex3f( size, size, size); | |
glVertex3f(-size, size, size); | |
glColor3f(0.0, 0.0, 0.7); | |
glVertex3f(-size, -size, -size); | |
glVertex3f(-size, -size, size); | |
glVertex3f(-size, size, size); | |
glVertex3f(-size, size, -size); | |
glVertex3f( size, -size, -size); | |
glVertex3f( size, -size, size); | |
glVertex3f( size, size, size); | |
glVertex3f( size, size, -size); | |
glColor3f(0.0, 0.7, 0.0); | |
glVertex3f(-size, -size, -size); | |
glVertex3f(-size, -size, size); | |
glVertex3f( size, -size, size); | |
glVertex3f( size, -size, -size); | |
glVertex3f(-size, size, -size); | |
glVertex3f(-size, size, size); | |
glVertex3f( size, size, size); | |
glVertex3f( size, size, -size); | |
glEnd(); | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// ROTATE THE CUBE // | |
////////////////////////////////////////////////////////////////////////////////// | |
void RotateCube() { | |
glMatrixMode(GL_MODELVIEW); | |
glLoadIdentity(); | |
glRotatef(rot_y_vel*DT, 0.0, 1.0, 0.0); | |
glRotatef(rot_z_vel*DT, 0.0, 0.0, 1.0); | |
glMultMatrixf(rotation_matrix); | |
glGetFloatv(GL_MODELVIEW_MATRIX, rotation_matrix); | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// EXPOSURE FUNCTION // | |
////////////////////////////////////////////////////////////////////////////////// | |
void ExposeFunc() { | |
float aspect_ratio; | |
char info_string[256]; | |
///////////////////////////////// | |
// RESIZE VIEWPORT // | |
///////////////////////////////// | |
XGetWindowAttributes(dpy, win, &wa); | |
glViewport(0, 0, wa.width, wa.height); | |
aspect_ratio = (float)(wa.width) / (float)(wa.height); | |
///////////////////////////////////////// | |
// SETUP PROJECTION & MODELVIEW // | |
///////////////////////////////////////// | |
glMatrixMode(GL_PROJECTION); | |
glLoadIdentity(); | |
glOrtho(-2.50*aspect_ratio, 2.50*aspect_ratio, -2.50, 2.50, 1., 100.); | |
glMatrixMode(GL_MODELVIEW); | |
glLoadIdentity(); | |
gluLookAt(10., 0., 0., 0., 0., 0., 0., 0., 1.); | |
glMultMatrixf(rotation_matrix); | |
///////////////////////////////// | |
// DRAW CUBE // | |
///////////////////////////////// | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
DrawCube(1.0); | |
///////////////////////////////// | |
// DISPLAY TIME, FPS etc. // | |
///////////////////////////////// | |
glMatrixMode(GL_PROJECTION); | |
glLoadIdentity(); | |
glOrtho(0, (float)wa.width, 0, (float)wa.height, -1., 1.); | |
glMatrixMode(GL_MODELVIEW); | |
glLoadIdentity(); | |
glColor3f(1.0, 1.0, 1.0); | |
sprintf(info_string, "%4.1f seconds * %4.1f fps at %i x %i", TimeCounter, FPS, wa.width, wa.height, rot_z_vel); | |
glRasterPos2i(10, 10); | |
glCallLists(strlen(info_string), GL_UNSIGNED_BYTE, info_string); | |
sprintf(info_string, "<up,down,left,right> rotate cube * <F1> stop rotation "); | |
glRasterPos2i(10, wa.height-32); | |
glCallLists(strlen(info_string), GL_UNSIGNED_BYTE, info_string); | |
///////////////////////////////// | |
// SWAP BUFFERS // | |
///////////////////////////////// | |
glXSwapBuffers(dpy, win); | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// CREATE A GL CAPABLE WINDOW // | |
////////////////////////////////////////////////////////////////////////////////// | |
void CreateWindow() { | |
if((dpy = XOpenDisplay(NULL)) == NULL) { | |
printf("\n\tcannot connect to x server\n\n"); | |
exit(0); | |
} | |
root = DefaultRootWindow(dpy); | |
if((vi = glXChooseVisual(dpy, 0, att)) == NULL) { | |
printf("\n\tno matching visual\n\n"); | |
exit(0); | |
} | |
if((cmap = XCreateColormap(dpy, root, vi->visual, AllocNone)) == 0) { | |
printf("\n\tcannot create colormap\n\n"); | |
exit(0); | |
} | |
swa.event_mask = KeyPressMask; | |
swa.colormap = cmap; | |
win = XCreateWindow(dpy, root, 0, 0, 700, 700, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa); | |
XStoreName(dpy, win, "OpenGL Animation"); | |
XMapWindow(dpy, win); | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// SETUP GL CONTEXT // | |
////////////////////////////////////////////////////////////////////////////////// | |
void SetupGL() { | |
char font_string[128]; | |
XFontStruct *font_struct; | |
///////////////////////////////////////////////// | |
// CREATE GL CONTEXT AND MAKE IT CURRENT // | |
///////////////////////////////////////////////// | |
if((glc = glXCreateContext(dpy, vi, NULL, GL_TRUE)) == NULL) { | |
printf("\n\tcannot create gl context\n\n"); | |
exit(0); | |
} | |
glXMakeCurrent(dpy, win, glc); | |
glEnable(GL_DEPTH_TEST); | |
glClearColor(0.00, 0.00, 0.40, 1.00); | |
///////////////////////////////////////////////// | |
// FIND A FONT // | |
///////////////////////////////////////////////// | |
for(int font_size = 14; font_size < 32; font_size += 2) { | |
sprintf(font_string, "Arial", font_size); | |
font_struct = XLoadQueryFont(dpy, font_string); | |
if(font_struct != NULL) { | |
glXUseXFont(font_struct->fid, 32, 192, 32); | |
break; | |
} | |
} | |
///////////////////////////////////////////////// | |
// INITIALIZE ROTATION MATRIX // | |
///////////////////////////////////////////////// | |
glMatrixMode(GL_MODELVIEW); | |
glLoadIdentity(); | |
glGetFloatv(GL_MODELVIEW_MATRIX, rotation_matrix); | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// TIME COUNTER FUNCTIONS // | |
////////////////////////////////////////////////////////////////////////////////// | |
void InitTimeCounter() { | |
gettimeofday(&tv0, NULL); | |
FramesPerFPS = 30; } | |
void UpdateTimeCounter() { | |
LastFrameTimeCounter = TimeCounter; | |
gettimeofday(&tv, NULL); | |
TimeCounter = (float)(tv.tv_sec-tv0.tv_sec) + 0.000001*((float)(tv.tv_usec-tv0.tv_usec)); | |
DT = TimeCounter - LastFrameTimeCounter; | |
} | |
void CalculateFPS() { | |
Frame ++; | |
if((Frame%FramesPerFPS) == 0) { | |
FPS = ((float)(FramesPerFPS)) / (TimeCounter-prevTime); | |
prevTime = TimeCounter; | |
} | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// EXIT PROGRAM // | |
////////////////////////////////////////////////////////////////////////////////// | |
void ExitProgram() { | |
glXMakeCurrent(dpy, None, NULL); | |
glXDestroyContext(dpy, glc); | |
XDestroyWindow(dpy, win); | |
XCloseDisplay(dpy); | |
exit(0); | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// CHECK EVENTS // | |
////////////////////////////////////////////////////////////////////////////////// | |
void CheckKeyboard() { | |
if(XCheckWindowEvent(dpy, win, KeyPressMask, &xev)) { | |
char *key_string = XKeysymToString(XkbKeycodeToKeysym(dpy, xev.xkey.keycode, 0, 0)); | |
if(strncmp(key_string, "Left", 4) == 0) { | |
rot_z_vel -= 200.0*DT; | |
} | |
else if(strncmp(key_string, "Right", 5) == 0) { | |
rot_z_vel += 200.0*DT; | |
} | |
else if(strncmp(key_string, "Up", 2) == 0) { | |
rot_y_vel -= 200.0*DT; | |
} | |
else if(strncmp(key_string, "Down", 4) == 0) { | |
rot_y_vel += 200.0*DT; | |
} | |
else if(strncmp(key_string, "F1", 2) == 0) { | |
rot_y_vel = 0.0; | |
rot_z_vel = 0.0; | |
} | |
else if(strncmp(key_string, "Escape", 5) == 0) { | |
ExitProgram(); | |
} | |
} | |
} | |
////////////////////////////////////////////////////////////////////////////////// | |
// MAIN PROGRAM // | |
////////////////////////////////////////////////////////////////////////////////// | |
int main(int argc, char *argv[]){ | |
CreateWindow(); | |
SetupGL(); | |
InitTimeCounter(); | |
while(1) { | |
UpdateTimeCounter(); | |
CalculateFPS(); | |
RotateCube(); | |
ExposeFunc(); | |
usleep(1000); | |
CheckKeyboard(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment