blob: 158e52a97ce33158eaef0e0028c2823fb5835cec [file] [log] [blame]
jtgafb833d1999-08-19 00:55:39 +00001/****************************************************************************
2Copyright 1995 by Silicon Graphics Incorporated, Mountain View, California.
3
4 All Rights Reserved
5
6Permission to use, copy, modify, and distribute this software and its
7documentation for any purpose and without fee is hereby granted,
8provided that the above copyright notice appear in all copies and that
9both that copyright notice and this permission notice appear in
10supporting documentation, and that the name of Silicon Graphics not be
11used in advertising or publicity pertaining to distribution of the
12software without specific, written prior permission.
13
14SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
18USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20PERFORMANCE OF THIS SOFTWARE.
21
22****************************************************************************/
23
24/*
25 * Derived from code written by Kurt Akeley, November 1992
26 *
27 * Uses PolygonOffset to draw hidden-line images. PolygonOffset
28 * shifts the z values of polygons an amount that is
29 * proportional to their slope in screen z. This keeps
30 * the lines, which are drawn without displacement, from
31 * interacting with their respective polygons, and
32 * thus eliminates line dropouts.
33 *
34 * The left image shows an ordinary antialiased wireframe image.
35 * The center image shows an antialiased hidden-line image without
36 * PolygonOffset.
37 * The right image shows an antialiased hidden-line image using
38 * PolygonOffset to reduce artifacts.
39 *
40 * Drag with a mouse button pressed to rotate the models.
41 * Press the escape key to exit.
42 */
43
44/*
45 * Modified for OpenGL 1.1 glPolygonOffset() conventions
46 */
47
48
49#include <GL/glx.h>
50#include <GL/glu.h>
51#include <X11/keysym.h>
52#include <stdlib.h>
53#include <stdio.h>
54#include <string.h>
55
56/*#undef GL_EXT_polygon_offset uncomment to use new version*/
57
58
59#ifndef EXIT_FAILURE
60# define EXIT_FAILURE 1
61#endif
62#ifndef EXIT_SUCCESS
63# define EXIT_SUCCESS 0
64#endif
65
66#define MAXQUAD 6
67
68typedef float Vertex[3];
69
70typedef Vertex Quad[4];
71
72/* data to define the six faces of a unit cube */
73Quad quads[MAXQUAD] = {
74 { {0,0,0}, {1,0,0}, {1,1,0}, {0,1,0} },
75 { {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1} },
76 { {0,0,0}, {1,0,0}, {1,0,1}, {0,0,1} },
77 { {0,1,0}, {1,1,0}, {1,1,1}, {0,1,1} },
78 { {0,0,0}, {0,0,1}, {0,1,1}, {0,1,0} },
79 { {1,0,0}, {1,0,1}, {1,1,1}, {1,1,0} }
80};
81
82#define WIREFRAME 0
83#define HIDDEN_LINE 1
84
85static void error(const char* prog, const char* msg);
86static void cubes(int mx, int my, int mode);
87static void fill(Quad quad);
88static void outline(Quad quad);
89static void draw_hidden(Quad quad, int mode);
90static void process_input(Display *dpy, Window win);
91static int query_extension(char* extName);
92
93static int attributeList[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
94 GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 1, None };
95
96static int dimension = 3;
97
98int main(int argc, char** argv) {
99 Display *dpy;
100 XVisualInfo *vi;
101 XSetWindowAttributes swa;
102 Window win;
103 GLXContext cx;
104
105 dpy = XOpenDisplay(0);
106 if (!dpy) error(argv[0], "can't open display");
107
108 vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
109 if (!vi) error(argv[0], "no suitable visual");
110
111 cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
112
113 swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
114 vi->visual, AllocNone);
115
116 swa.border_pixel = 0;
117 swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask |
118 ButtonPressMask | ButtonMotionMask;
119 win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 900, 300,
120 0, vi->depth, InputOutput, vi->visual,
121 CWBorderPixel|CWColormap|CWEventMask, &swa);
122 XStoreName(dpy, win, "hiddenline");
123 XMapWindow(dpy, win);
124
125 glXMakeCurrent(dpy, win, cx);
126
127 /* check for the polygon offset extension */
128#ifndef GL_VERSION_1_1
129 if (!query_extension("GL_EXT_polygon_offset"))
130 error(argv[0], "polygon_offset extension is not available");
131#else
132 (void) query_extension;
133#endif
134
135 /* set up viewing parameters */
136 glMatrixMode(GL_PROJECTION);
137 gluPerspective(20, 1, 0.1, 20);
138 glMatrixMode(GL_MODELVIEW);
139 glTranslatef(0, 0, -15);
140
141 /* set other relevant state information */
142 glEnable(GL_DEPTH_TEST);
143
144#ifdef GL_EXT_polygon_offset
145 printf("using 1.0 offset extension\n");
146 glPolygonOffsetEXT( 1.0, 0.00001 );
147#else
148 printf("using 1.1 offset\n");
149 glPolygonOffset( 1.0, 0.5 );
150#endif
151
152 glShadeModel( GL_FLAT );
153 glDisable( GL_DITHER );
154
155 /* process events until the user presses ESC */
156 while (1) process_input(dpy, win);
157
158 return 0;
159}
160
161static void
162draw_scene(int mx, int my) {
163 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
164
165 glPushMatrix();
166 glTranslatef(-1.7, 0.0, 0.0);
167 cubes(mx, my, WIREFRAME);
168 glPopMatrix();
169
170 glPushMatrix();
171 cubes(mx, my, HIDDEN_LINE);
172 glPopMatrix();
173
174 glPushMatrix();
175 glTranslatef(1.7, 0.0, 0.0);
176#ifdef GL_EXT_polygon_offset
177 glEnable(GL_POLYGON_OFFSET_EXT);
178#else
179 glEnable(GL_POLYGON_OFFSET_FILL);
180#endif
181 cubes(mx, my, HIDDEN_LINE);
182#ifdef GL_EXT_polygon_offset
183 glDisable(GL_POLYGON_OFFSET_EXT);
184#else
185 glDisable(GL_POLYGON_OFFSET_FILL);
186#endif
187 glPopMatrix();
188}
189
190
191static void
192cubes(int mx, int my, int mode) {
193 int x, y, z, i;
194
195 /* track the mouse */
196 glRotatef(mx / 2.0, 0, 1, 0);
197 glRotatef(my / 2.0, 1, 0, 0);
198
199 /* draw the lines as hidden polygons */
200 glTranslatef(-0.5, -0.5, -0.5);
201 glScalef(1.0/dimension, 1.0/dimension, 1.0/dimension);
202 for (z = 0; z < dimension; z++) {
203 for (y = 0; y < dimension; y++) {
204 for (x = 0; x < dimension; x++) {
205 glPushMatrix();
206 glTranslatef(x, y, z);
207 glScalef(0.8, 0.8, 0.8);
208 for (i = 0; i < MAXQUAD; i++)
209 draw_hidden(quads[i], mode);
210 glPopMatrix();
211 }
212 }
213 }
214}
215
216static void
217fill(Quad quad) {
218 /* draw a filled polygon */
219 glBegin(GL_QUADS);
220 glVertex3fv(quad[0]);
221 glVertex3fv(quad[1]);
222 glVertex3fv(quad[2]);
223 glVertex3fv(quad[3]);
224 glEnd();
225}
226
227static void
228outline(Quad quad) {
229 /* draw an outlined polygon */
230 glBegin(GL_LINE_LOOP);
231 glVertex3fv(quad[0]);
232 glVertex3fv(quad[1]);
233 glVertex3fv(quad[2]);
234 glVertex3fv(quad[3]);
235 glEnd();
236}
237
238static void
239draw_hidden(Quad quad, int mode) {
240 if (mode == HIDDEN_LINE) {
241 glColor3f(0, 0, 0);
242 fill(quad);
243 }
244
245 /* draw the outline using white, optionally fill the interior with black */
246 glColor3f(1, 1, 1);
247 outline(quad);
248}
249
250static void
251process_input(Display *dpy, Window win) {
252 XEvent event;
253 static int prevx, prevy;
254 static int deltax = 90, deltay = 40;
255
256 do {
257 char buf[31];
258 KeySym keysym;
259
260 XNextEvent(dpy, &event);
261 switch(event.type) {
262 case Expose:
263 break;
264 case ConfigureNotify: {
265 /* this approach preserves a 1:1 viewport aspect ratio */
266 int vX, vY, vW, vH;
267 int eW = event.xconfigure.width, eH = event.xconfigure.height;
268 if (eW >= eH) {
269 vX = 0;
270 vY = (eH - eW) >> 1;
271 vW = vH = eW;
272 } else {
273 vX = (eW - eH) >> 1;
274 vY = 0;
275 vW = vH = eH;
276 }
277 glViewport(vX, vY, vW, vH);
278 }
279 break;
280 case KeyPress:
281 (void) XLookupString(&event.xkey, buf, sizeof(buf), &keysym, NULL);
282 switch (keysym) {
283 case XK_Escape:
284 exit(EXIT_SUCCESS);
285 default:
286 break;
287 }
288 case ButtonPress:
289 prevx = event.xbutton.x;
290 prevy = event.xbutton.y;
291 break;
292 case MotionNotify:
293 deltax += (event.xbutton.x - prevx); prevx = event.xbutton.x;
294 deltay += (event.xbutton.y - prevy); prevy = event.xbutton.y;
295 break;
296 default:
297 break;
298 }
299 } while (XPending(dpy));
300
301 draw_scene(deltax, deltay);
302 glXSwapBuffers(dpy, win);
303}
304
305static void
306error(const char *prog, const char *msg) {
307 fprintf(stderr, "%s: %s\n", prog, msg);
308 exit(EXIT_FAILURE);
309}
310
311static int
312query_extension(char* extName) {
313 char *p = (char *) glGetString(GL_EXTENSIONS);
314 char *end = p + strlen(p);
315 while (p < end) {
316 int n = strcspn(p, " ");
317 if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0))
318 return GL_TRUE;
319 p += (n + 1);
320 }
321 return GL_FALSE;
322}
323