+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/select.h>
-#include <X11/Xlib.h>
-#include <GL/gl.h>
-#include <GL/glu.h>
-#include <GL/glx.h>
-#include "vmath.h"
-#include "device.h"
-
-int create_gfx(int xsz, int ysz);
-void destroy_gfx(void);
-void set_window_title(const char *title);
-void redraw(void);
-void draw_cube(void);
-int handle_event(XEvent *xev);
-int handle_dev_event(device_event *ev);
-
-Display *dpy;
-Atom wm_prot, wm_del_win;
-GLXContext ctx;
-Window win;
-
-vec3_t pos = {0, 0, -6};
-quat_t rot = {0, 0, 0, 1}; /* that's 1 + 0i + 0j + 0k */
-
-int redisplay;
-
-/* serial 6dof device */
-struct device *dev;
-
-int main(void)
-{
- int xsock, devfd, maxfd;
-
- register_all();
- set_port("/dev/ttyS0");
-
- if(!(dev = dev_init(0))) {
- fprintf(stderr, "failed to initialize 6dof serial device at /dev/ttyS0\n");
- return 1;
- }
- if((devfd = dev->start()) == -1) {
- return 1;
- }
-
- if(!(dpy = XOpenDisplay(0))) {
- fprintf(stderr, "failed to connect to the X server\n");
- return 1;
- }
- xsock = ConnectionNumber(dpy);
-
- if(create_gfx(512, 512) == -1) {
- return 1;
- }
-
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_CULL_FACE);
-
- maxfd = xsock > devfd ? xsock : devfd;
-
- for(;;) {
- fd_set rdset;
-
- FD_ZERO(&rdset);
- FD_SET(xsock, &rdset);
- FD_SET(devfd, &rdset);
-
- while(select(maxfd + 1, &rdset, 0, 0, 0) == -1 && errno == EINTR);
-
- if(FD_ISSET(xsock, &rdset)) {
- while(XPending(dpy)) {
- XEvent xev;
- XNextEvent(dpy, &xev);
-
- if(handle_event(&xev) != 0) {
- goto end;
- }
- }
- }
-
- if(FD_ISSET(devfd, &rdset)) {
- device_event ev;
-
- while(dev->getevent(&ev)) {
- handle_dev_event(&ev);
- }
- }
-
- if(redisplay) {
- redraw();
- redisplay = 0;
- }
- }
-
-end:
- destroy_gfx();
- XCloseDisplay(dpy);
- return 0;
-}
-
-int create_gfx(int xsz, int ysz)
-{
- int scr;
- Window root;
- XVisualInfo *vis;
- XSetWindowAttributes xattr;
- unsigned int events;
- XClassHint class_hint;
-
- int attr[] = {
- GLX_RGBA, GLX_DOUBLEBUFFER,
- GLX_RED_SIZE, 8,
- GLX_GREEN_SIZE, 8,
- GLX_BLUE_SIZE, 8,
- GLX_DEPTH_SIZE, 24,
- None
- };
-
- wm_prot = XInternAtom(dpy, "WM_PROTOCOLS", False);
- wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
-
- scr = DefaultScreen(dpy);
- root = RootWindow(dpy, scr);
-
- if(!(vis = glXChooseVisual(dpy, scr, attr))) {
- fprintf(stderr, "requested GLX visual is not available\n");
- return -1;
- }
-
- if(!(ctx = glXCreateContext(dpy, vis, 0, True))) {
- fprintf(stderr, "failed to create GLX context\n");
- XFree(vis);
- return -1;
- }
-
- xattr.background_pixel = xattr.border_pixel = BlackPixel(dpy, scr);
- xattr.colormap = XCreateColormap(dpy, root, vis->visual, AllocNone);
-
- if(!(win = XCreateWindow(dpy, root, 0, 0, xsz, ysz, 0, vis->depth, InputOutput,
- vis->visual, CWColormap | CWBackPixel | CWBorderPixel, &xattr))) {
- fprintf(stderr, "failed to create X window\n");
- return -1;
- }
- XFree(vis);
-
- /* set the window event mask */
- events = ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask |
- ButtonReleaseMask | ButtonPressMask | PointerMotionMask;
- XSelectInput(dpy, win, events);
-
- XSetWMProtocols(dpy, win, &wm_del_win, 1);
-
- set_window_title("libspnav cube");
-
- class_hint.res_name = "cube";
- class_hint.res_class = "cube";
- XSetClassHint(dpy, win, &class_hint);
-
- if(glXMakeCurrent(dpy, win, ctx) == False) {
- fprintf(stderr, "glXMakeCurrent failed\n");
- glXDestroyContext(dpy, ctx);
- XDestroyWindow(dpy, win);
- return -1;
- }
-
- XMapWindow(dpy, win);
- XFlush(dpy);
-
- return 0;
-}
-
-void destroy_gfx(void)
-{
- glXDestroyContext(dpy, ctx);
- XDestroyWindow(dpy, win);
- glXMakeCurrent(dpy, None, 0);
-}
-
-void set_window_title(const char *title)
-{
- XTextProperty wm_name;
-
- XStringListToTextProperty((char**)&title, 1, &wm_name);
- XSetWMName(dpy, win, &wm_name);
- XSetWMIconName(dpy, win, &wm_name);
- XFree(wm_name.value);
-}
-
-void redraw(void)
-{
- mat4_t xform;
-
- quat_to_mat(xform, rot);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(pos.x, pos.y, pos.z);
- glMultTransposeMatrixf((float*)xform);
-
- draw_cube();
-
- glXSwapBuffers(dpy, win);
-}
-
-void draw_cube(void)
-{
- glBegin(GL_QUADS);
- /* face +Z */
- glNormal3f(0, 0, 1);
- glColor3f(1, 0, 0);
- glVertex3f(-1, -1, 1);
- glVertex3f(1, -1, 1);
- glVertex3f(1, 1, 1);
- glVertex3f(-1, 1, 1);
- /* face +X */
- glNormal3f(1, 0, 0);
- glColor3f(0, 1, 0);
- glVertex3f(1, -1, 1);
- glVertex3f(1, -1, -1);
- glVertex3f(1, 1, -1);
- glVertex3f(1, 1, 1);
- /* face -Z */
- glNormal3f(0, 0, -1);
- glColor3f(0, 0, 1);
- glVertex3f(1, -1, -1);
- glVertex3f(-1, -1, -1);
- glVertex3f(-1, 1, -1);
- glVertex3f(1, 1, -1);
- /* face -X */
- glNormal3f(-1, 0, 0);
- glColor3f(1, 1, 0);
- glVertex3f(-1, -1, -1);
- glVertex3f(-1, -1, 1);
- glVertex3f(-1, 1, 1);
- glVertex3f(-1, 1, -1);
- /* face +Y */
- glNormal3f(0, 1, 0);
- glColor3f(0, 1, 1);
- glVertex3f(-1, 1, 1);
- glVertex3f(1, 1, 1);
- glVertex3f(1, 1, -1);
- glVertex3f(-1, 1, -1);
- /* face -Y */
- glNormal3f(0, -1, 0);
- glColor3f(1, 0, 1);
- glVertex3f(-1, -1, -1);
- glVertex3f(1, -1, -1);
- glVertex3f(1, -1, 1);
- glVertex3f(-1, -1, 1);
- glEnd();
-}
-
-int handle_event(XEvent *xev)
-{
- static int win_mapped;
- KeySym sym;
-
- switch(xev->type) {
- case MapNotify:
- win_mapped = 1;
- break;
-
- case UnmapNotify:
- win_mapped = 0;
- break;
-
- case Expose:
- if(win_mapped && xev->xexpose.count == 0) {
- redraw();
- }
- break;
-
- case KeyPress:
- sym = XLookupKeysym((XKeyEvent*)&xev->xkey, 0);
- if((sym & 0xff) == 27) {
- return 1;
- }
- break;
-
- case ConfigureNotify:
- {
- int x = xev->xconfigure.width;
- int y = xev->xconfigure.height;
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(45.0, (float)x / (float)y, 1.0, 1000.0);
-
- glViewport(0, 0, x, y);
- }
- break;
-
- default:
- break;
- }
- return 0;
-}
-
-#define TX(ev) ((ev)->motion.motion[0])
-#define TY(ev) ((ev)->motion.motion[1])
-#define TZ(ev) ((ev)->motion.motion[2])
-#define RX(ev) ((ev)->motion.motion[3])
-#define RY(ev) ((ev)->motion.motion[4])
-#define RZ(ev) ((ev)->motion.motion[5])
-
-int handle_dev_event(device_event *ev)
-{
- switch(ev->type) {
- case DEV_EV_MOTION:
- if(RX(ev) | RY(ev) | RZ(ev)) {
- float axis_len = sqrt(RX(ev) * RX(ev) + RY(ev) * RY(ev) + RZ(ev) * RZ(ev));
- if(axis_len != 0.0) {
- rot = quat_rotate(rot, axis_len * 0.001, -RX(ev) / axis_len,
- -RY(ev) / axis_len, -RZ(ev) / axis_len);
- }
- }
-
- pos.x += TX(ev) * 0.001;
- pos.y += TY(ev) * 0.001;
- pos.z += TZ(ev) * 0.001;
- redisplay = 1;
- break;
-
- case DEV_EV_BUTTON:
- if(ev->button.pressed) {
- pos = v3_cons(0, 0, -6);
- rot = quat_cons(1, 0, 0, 0);
- redisplay = 1;
- }
- break;
- }
-
- return 0;
-}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <X11/Xlib.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glx.h>
+#include "vmath.h"
+#include "device.h"
+
+int create_gfx(int xsz, int ysz);
+void destroy_gfx(void);
+void set_window_title(const char *title);
+void redraw(void);
+void draw_cube(void);
+int handle_event(XEvent *xev);
+int handle_dev_event(device_event *ev);
+
+Display *dpy;
+Atom wm_prot, wm_del_win;
+GLXContext ctx;
+Window win;
+
+vec3_t pos = {0, 0, -6};
+quat_t rot = {0, 0, 0, 1}; /* that's 1 + 0i + 0j + 0k */
+
+int redisplay;
+
+/* serial 6dof device */
+struct device *dev;
+
+int main(void)
+{
+ int xsock, devfd, maxfd;
+
+ register_all();
+ set_port("/dev/ttyS0");
+
+ if(!(dev = dev_init(0))) {
+ fprintf(stderr, "failed to initialize 6dof serial device at /dev/ttyS0\n");
+ return 1;
+ }
+ if((devfd = dev->start()) == -1) {
+ return 1;
+ }
+
+ if(!(dpy = XOpenDisplay(0))) {
+ fprintf(stderr, "failed to connect to the X server\n");
+ return 1;
+ }
+ xsock = ConnectionNumber(dpy);
+
+ if(create_gfx(512, 512) == -1) {
+ return 1;
+ }
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+
+ maxfd = xsock > devfd ? xsock : devfd;
+
+ for(;;) {
+ fd_set rdset;
+
+ FD_ZERO(&rdset);
+ FD_SET(xsock, &rdset);
+ FD_SET(devfd, &rdset);
+
+ while(select(maxfd + 1, &rdset, 0, 0, 0) == -1 && errno == EINTR);
+
+ if(FD_ISSET(xsock, &rdset)) {
+ while(XPending(dpy)) {
+ XEvent xev;
+ XNextEvent(dpy, &xev);
+
+ if(handle_event(&xev) != 0) {
+ goto end;
+ }
+ }
+ }
+
+ if(FD_ISSET(devfd, &rdset)) {
+ device_event ev;
+
+ while(dev->getevent(&ev)) {
+ handle_dev_event(&ev);
+ }
+ }
+
+ if(redisplay) {
+ redraw();
+ redisplay = 0;
+ }
+ }
+
+end:
+ destroy_gfx();
+ XCloseDisplay(dpy);
+ return 0;
+}
+
+int create_gfx(int xsz, int ysz)
+{
+ int scr;
+ Window root;
+ XVisualInfo *vis;
+ XSetWindowAttributes xattr;
+ unsigned int events;
+ XClassHint class_hint;
+
+ int attr[] = {
+ GLX_RGBA, GLX_DOUBLEBUFFER,
+ GLX_RED_SIZE, 8,
+ GLX_GREEN_SIZE, 8,
+ GLX_BLUE_SIZE, 8,
+ GLX_DEPTH_SIZE, 24,
+ None
+ };
+
+ wm_prot = XInternAtom(dpy, "WM_PROTOCOLS", False);
+ wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+
+ scr = DefaultScreen(dpy);
+ root = RootWindow(dpy, scr);
+
+ if(!(vis = glXChooseVisual(dpy, scr, attr))) {
+ fprintf(stderr, "requested GLX visual is not available\n");
+ return -1;
+ }
+
+ if(!(ctx = glXCreateContext(dpy, vis, 0, True))) {
+ fprintf(stderr, "failed to create GLX context\n");
+ XFree(vis);
+ return -1;
+ }
+
+ xattr.background_pixel = xattr.border_pixel = BlackPixel(dpy, scr);
+ xattr.colormap = XCreateColormap(dpy, root, vis->visual, AllocNone);
+
+ if(!(win = XCreateWindow(dpy, root, 0, 0, xsz, ysz, 0, vis->depth, InputOutput,
+ vis->visual, CWColormap | CWBackPixel | CWBorderPixel, &xattr))) {
+ fprintf(stderr, "failed to create X window\n");
+ return -1;
+ }
+ XFree(vis);
+
+ /* set the window event mask */
+ events = ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask |
+ ButtonReleaseMask | ButtonPressMask | PointerMotionMask;
+ XSelectInput(dpy, win, events);
+
+ XSetWMProtocols(dpy, win, &wm_del_win, 1);
+
+ set_window_title("libspnav cube");
+
+ class_hint.res_name = "cube";
+ class_hint.res_class = "cube";
+ XSetClassHint(dpy, win, &class_hint);
+
+ if(glXMakeCurrent(dpy, win, ctx) == False) {
+ fprintf(stderr, "glXMakeCurrent failed\n");
+ glXDestroyContext(dpy, ctx);
+ XDestroyWindow(dpy, win);
+ return -1;
+ }
+
+ XMapWindow(dpy, win);
+ XFlush(dpy);
+
+ return 0;
+}
+
+void destroy_gfx(void)
+{
+ glXDestroyContext(dpy, ctx);
+ XDestroyWindow(dpy, win);
+ glXMakeCurrent(dpy, None, 0);
+}
+
+void set_window_title(const char *title)
+{
+ XTextProperty wm_name;
+
+ XStringListToTextProperty((char**)&title, 1, &wm_name);
+ XSetWMName(dpy, win, &wm_name);
+ XSetWMIconName(dpy, win, &wm_name);
+ XFree(wm_name.value);
+}
+
+void redraw(void)
+{
+ mat4_t xform;
+
+ quat_to_mat(xform, rot);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(pos.x, pos.y, pos.z);
+ glMultTransposeMatrixf((float*)xform);
+
+ draw_cube();
+
+ glXSwapBuffers(dpy, win);
+}
+
+void draw_cube(void)
+{
+ glBegin(GL_QUADS);
+ /* face +Z */
+ glNormal3f(0, 0, 1);
+ glColor3f(1, 0, 0);
+ glVertex3f(-1, -1, 1);
+ glVertex3f(1, -1, 1);
+ glVertex3f(1, 1, 1);
+ glVertex3f(-1, 1, 1);
+ /* face +X */
+ glNormal3f(1, 0, 0);
+ glColor3f(0, 1, 0);
+ glVertex3f(1, -1, 1);
+ glVertex3f(1, -1, -1);
+ glVertex3f(1, 1, -1);
+ glVertex3f(1, 1, 1);
+ /* face -Z */
+ glNormal3f(0, 0, -1);
+ glColor3f(0, 0, 1);
+ glVertex3f(1, -1, -1);
+ glVertex3f(-1, -1, -1);
+ glVertex3f(-1, 1, -1);
+ glVertex3f(1, 1, -1);
+ /* face -X */
+ glNormal3f(-1, 0, 0);
+ glColor3f(1, 1, 0);
+ glVertex3f(-1, -1, -1);
+ glVertex3f(-1, -1, 1);
+ glVertex3f(-1, 1, 1);
+ glVertex3f(-1, 1, -1);
+ /* face +Y */
+ glNormal3f(0, 1, 0);
+ glColor3f(0, 1, 1);
+ glVertex3f(-1, 1, 1);
+ glVertex3f(1, 1, 1);
+ glVertex3f(1, 1, -1);
+ glVertex3f(-1, 1, -1);
+ /* face -Y */
+ glNormal3f(0, -1, 0);
+ glColor3f(1, 0, 1);
+ glVertex3f(-1, -1, -1);
+ glVertex3f(1, -1, -1);
+ glVertex3f(1, -1, 1);
+ glVertex3f(-1, -1, 1);
+ glEnd();
+}
+
+int handle_event(XEvent *xev)
+{
+ static int win_mapped;
+ KeySym sym;
+
+ switch(xev->type) {
+ case MapNotify:
+ win_mapped = 1;
+ break;
+
+ case UnmapNotify:
+ win_mapped = 0;
+ break;
+
+ case Expose:
+ if(win_mapped && xev->xexpose.count == 0) {
+ redraw();
+ }
+ break;
+
+ case KeyPress:
+ sym = XLookupKeysym((XKeyEvent*)&xev->xkey, 0);
+ if((sym & 0xff) == 27) {
+ return 1;
+ }
+ break;
+
+ case ConfigureNotify:
+ {
+ int x = xev->xconfigure.width;
+ int y = xev->xconfigure.height;
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(45.0, (float)x / (float)y, 1.0, 1000.0);
+
+ glViewport(0, 0, x, y);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+#define TX(ev) ((ev)->motion.motion[0])
+#define TY(ev) ((ev)->motion.motion[1])
+#define TZ(ev) ((ev)->motion.motion[2])
+#define RX(ev) ((ev)->motion.motion[3])
+#define RY(ev) ((ev)->motion.motion[4])
+#define RZ(ev) ((ev)->motion.motion[5])
+
+int handle_dev_event(device_event *ev)
+{
+ switch(ev->type) {
+ case DEV_EV_MOTION:
+ if(RX(ev) | RY(ev) | RZ(ev)) {
+ float axis_len = sqrt(RX(ev) * RX(ev) + RY(ev) * RY(ev) + RZ(ev) * RZ(ev));
+ if(axis_len != 0.0) {
+ rot = quat_rotate(rot, axis_len * 0.001, -RX(ev) / axis_len,
+ -RY(ev) / axis_len, -RZ(ev) / axis_len);
+ }
+ }
+
+ pos.x += TX(ev) * 0.001;
+ pos.y += TY(ev) * 0.001;
+ pos.z += TZ(ev) * 0.001;
+ redisplay = 1;
+ break;
+
+ case DEV_EV_BUTTON:
+ if(ev->button.pressed) {
+ pos = v3_cons(0, 0, -6);
+ rot = quat_cons(1, 0, 0, 0);
+ redisplay = 1;
+ }
+ break;
+ }
+
+ return 0;
+}