aboutsummaryrefslogtreecommitdiff
path: root/progs/xdemos/offset.c
diff options
context:
space:
mode:
Diffstat (limited to 'progs/xdemos/offset.c')
-rw-r--r--progs/xdemos/offset.c323
1 files changed, 323 insertions, 0 deletions
diff --git a/progs/xdemos/offset.c b/progs/xdemos/offset.c
new file mode 100644
index 000000000..3e92e68da
--- /dev/null
+++ b/progs/xdemos/offset.c
@@ -0,0 +1,323 @@
+/****************************************************************************
+Copyright 1995 by Silicon Graphics Incorporated, Mountain View, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Silicon Graphics not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+****************************************************************************/
+
+/*
+ * Derived from code written by Kurt Akeley, November 1992
+ *
+ * Uses PolygonOffset to draw hidden-line images. PolygonOffset
+ * shifts the z values of polygons an amount that is
+ * proportional to their slope in screen z. This keeps
+ * the lines, which are drawn without displacement, from
+ * interacting with their respective polygons, and
+ * thus eliminates line dropouts.
+ *
+ * The left image shows an ordinary antialiased wireframe image.
+ * The center image shows an antialiased hidden-line image without
+ * PolygonOffset.
+ * The right image shows an antialiased hidden-line image using
+ * PolygonOffset to reduce artifacts.
+ *
+ * Drag with a mouse button pressed to rotate the models.
+ * Press the escape key to exit.
+ */
+
+/*
+ * Modified for OpenGL 1.1 glPolygonOffset() conventions
+ */
+
+
+#include <GL/glx.h>
+#include <GL/glu.h>
+#include <X11/keysym.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#undef GL_EXT_polygon_offset /* use GL 1.1 version instead of extension */
+
+
+#ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+#ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+#endif
+
+#define MAXQUAD 6
+
+typedef float Vertex[3];
+
+typedef Vertex Quad[4];
+
+/* data to define the six faces of a unit cube */
+Quad quads[MAXQUAD] = {
+ { {0,0,0}, {1,0,0}, {1,1,0}, {0,1,0} },
+ { {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1} },
+ { {0,0,0}, {1,0,0}, {1,0,1}, {0,0,1} },
+ { {0,1,0}, {1,1,0}, {1,1,1}, {0,1,1} },
+ { {0,0,0}, {0,0,1}, {0,1,1}, {0,1,0} },
+ { {1,0,0}, {1,0,1}, {1,1,1}, {1,1,0} }
+};
+
+#define WIREFRAME 0
+#define HIDDEN_LINE 1
+
+static void error(const char* prog, const char* msg);
+static void cubes(int mx, int my, int mode);
+static void fill(Quad quad);
+static void outline(Quad quad);
+static void draw_hidden(Quad quad, int mode);
+static void process_input(Display *dpy, Window win);
+static int query_extension(char* extName);
+
+static int attributeList[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 1, None };
+
+static int dimension = 3;
+
+int main(int argc, char** argv) {
+ Display *dpy;
+ XVisualInfo *vi;
+ XSetWindowAttributes swa;
+ Window win;
+ GLXContext cx;
+
+ dpy = XOpenDisplay(0);
+ if (!dpy) error(argv[0], "can't open display");
+
+ vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
+ if (!vi) error(argv[0], "no suitable visual");
+
+ cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
+
+ swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
+ vi->visual, AllocNone);
+
+ swa.border_pixel = 0;
+ swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask |
+ ButtonPressMask | ButtonMotionMask;
+ win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 900, 300,
+ 0, vi->depth, InputOutput, vi->visual,
+ CWBorderPixel|CWColormap|CWEventMask, &swa);
+ XStoreName(dpy, win, "hiddenline");
+ XMapWindow(dpy, win);
+
+ glXMakeCurrent(dpy, win, cx);
+
+ /* check for the polygon offset extension */
+#ifndef GL_VERSION_1_1
+ if (!query_extension("GL_EXT_polygon_offset"))
+ error(argv[0], "polygon_offset extension is not available");
+#else
+ (void) query_extension;
+#endif
+
+ /* set up viewing parameters */
+ glMatrixMode(GL_PROJECTION);
+ gluPerspective(20, 1, 0.1, 20);
+ glMatrixMode(GL_MODELVIEW);
+ glTranslatef(0, 0, -15);
+
+ /* set other relevant state information */
+ glEnable(GL_DEPTH_TEST);
+
+#ifdef GL_EXT_polygon_offset
+ printf("using 1.0 offset extension\n");
+ glPolygonOffsetEXT( 1.0, 0.00001 );
+#else
+ printf("using 1.1 offset\n");
+ glPolygonOffset( 1.0, 0.5 );
+#endif
+
+ glShadeModel( GL_FLAT );
+ glDisable( GL_DITHER );
+
+ /* process events until the user presses ESC */
+ while (1) process_input(dpy, win);
+
+ return 0;
+}
+
+static void
+draw_scene(int mx, int my) {
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix();
+ glTranslatef(-1.7, 0.0, 0.0);
+ cubes(mx, my, WIREFRAME);
+ glPopMatrix();
+
+ glPushMatrix();
+ cubes(mx, my, HIDDEN_LINE);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(1.7, 0.0, 0.0);
+#ifdef GL_EXT_polygon_offset
+ glEnable(GL_POLYGON_OFFSET_EXT);
+#else
+ glEnable(GL_POLYGON_OFFSET_FILL);
+#endif
+ cubes(mx, my, HIDDEN_LINE);
+#ifdef GL_EXT_polygon_offset
+ glDisable(GL_POLYGON_OFFSET_EXT);
+#else
+ glDisable(GL_POLYGON_OFFSET_FILL);
+#endif
+ glPopMatrix();
+}
+
+
+static void
+cubes(int mx, int my, int mode) {
+ int x, y, z, i;
+
+ /* track the mouse */
+ glRotatef(mx / 2.0, 0, 1, 0);
+ glRotatef(my / 2.0, 1, 0, 0);
+
+ /* draw the lines as hidden polygons */
+ glTranslatef(-0.5, -0.5, -0.5);
+ glScalef(1.0/dimension, 1.0/dimension, 1.0/dimension);
+ for (z = 0; z < dimension; z++) {
+ for (y = 0; y < dimension; y++) {
+ for (x = 0; x < dimension; x++) {
+ glPushMatrix();
+ glTranslatef(x, y, z);
+ glScalef(0.8, 0.8, 0.8);
+ for (i = 0; i < MAXQUAD; i++)
+ draw_hidden(quads[i], mode);
+ glPopMatrix();
+ }
+ }
+ }
+}
+
+static void
+fill(Quad quad) {
+ /* draw a filled polygon */
+ glBegin(GL_QUADS);
+ glVertex3fv(quad[0]);
+ glVertex3fv(quad[1]);
+ glVertex3fv(quad[2]);
+ glVertex3fv(quad[3]);
+ glEnd();
+}
+
+static void
+outline(Quad quad) {
+ /* draw an outlined polygon */
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(quad[0]);
+ glVertex3fv(quad[1]);
+ glVertex3fv(quad[2]);
+ glVertex3fv(quad[3]);
+ glEnd();
+}
+
+static void
+draw_hidden(Quad quad, int mode) {
+ if (mode == HIDDEN_LINE) {
+ glColor3f(0, 0, 0);
+ fill(quad);
+ }
+
+ /* draw the outline using white, optionally fill the interior with black */
+ glColor3f(1, 1, 1);
+ outline(quad);
+}
+
+static void
+process_input(Display *dpy, Window win) {
+ XEvent event;
+ static int prevx, prevy;
+ static int deltax = 90, deltay = 40;
+
+ do {
+ char buf[31];
+ KeySym keysym;
+
+ XNextEvent(dpy, &event);
+ switch(event.type) {
+ case Expose:
+ break;
+ case ConfigureNotify: {
+ /* this approach preserves a 1:1 viewport aspect ratio */
+ int vX, vY, vW, vH;
+ int eW = event.xconfigure.width, eH = event.xconfigure.height;
+ if (eW >= eH) {
+ vX = 0;
+ vY = (eH - eW) >> 1;
+ vW = vH = eW;
+ } else {
+ vX = (eW - eH) >> 1;
+ vY = 0;
+ vW = vH = eH;
+ }
+ glViewport(vX, vY, vW, vH);
+ }
+ break;
+ case KeyPress:
+ (void) XLookupString(&event.xkey, buf, sizeof(buf), &keysym, NULL);
+ switch (keysym) {
+ case XK_Escape:
+ exit(EXIT_SUCCESS);
+ default:
+ break;
+ }
+ case ButtonPress:
+ prevx = event.xbutton.x;
+ prevy = event.xbutton.y;
+ break;
+ case MotionNotify:
+ deltax += (event.xbutton.x - prevx); prevx = event.xbutton.x;
+ deltay += (event.xbutton.y - prevy); prevy = event.xbutton.y;
+ break;
+ default:
+ break;
+ }
+ } while (XPending(dpy));
+
+ draw_scene(deltax, deltay);
+ glXSwapBuffers(dpy, win);
+}
+
+static void
+error(const char *prog, const char *msg) {
+ fprintf(stderr, "%s: %s\n", prog, msg);
+ exit(EXIT_FAILURE);
+}
+
+static int
+query_extension(char* extName) {
+ char *p = (char *) glGetString(GL_EXTENSIONS);
+ char *end = p + strlen(p);
+ while (p < end) {
+ int n = strcspn(p, " ");
+ if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0))
+ return GL_TRUE;
+ p += (n + 1);
+ }
+ return GL_FALSE;
+}
+