Dump only relevant functions when in the debugging output.
[mesa.git] / progs / xdemos / offset.c
1 /****************************************************************************
2 Copyright 1995 by Silicon Graphics Incorporated, Mountain View, California.
3
4 All Rights Reserved
5
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that the name of Silicon Graphics not be
11 used in advertising or publicity pertaining to distribution of the
12 software without specific, written prior permission.
13
14 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
18 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 PERFORMANCE 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 /* use GL 1.1 version instead of extension */
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
68 typedef float Vertex[3];
69
70 typedef Vertex Quad[4];
71
72 /* data to define the six faces of a unit cube */
73 Quad quads[MAXQUAD] = {
74 { {0,0,0}, {0,0,1}, {0,1,1}, {0,1,0} }, /* x = 0 */
75 { {0,0,0}, {1,0,0}, {1,0,1}, {0,0,1} }, /* y = 0 */
76 { {0,0,0}, {1,0,0}, {1,1,0}, {0,1,0} }, /* z = 0 */
77 { {1,0,0}, {1,0,1}, {1,1,1}, {1,1,0} }, /* x = 1 */
78 { {0,1,0}, {1,1,0}, {1,1,1}, {0,1,1} }, /* y = 1 */
79 { {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1} } /* z = 1 */
80 };
81
82 #define WIREFRAME 0
83 #define HIDDEN_LINE 1
84
85 static void error(const char* prog, const char* msg);
86 static void cubes(int mx, int my, int mode);
87 static void fill(Quad quad);
88 static void outline(Quad quad);
89 static void draw_hidden(Quad quad, int mode, int face);
90 static void process_input(Display *dpy, Window win);
91 static int query_extension(char* extName);
92
93 static 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
96 static int dimension = 3;
97
98 int main(int argc, char** argv) {
99 Display *dpy;
100 XVisualInfo *vi;
101 XSetWindowAttributes swa;
102 Window win;
103 GLXContext cx;
104 GLint z;
105
106 dpy = XOpenDisplay(0);
107 if (!dpy) error(argv[0], "can't open display");
108
109 vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
110 if (!vi) error(argv[0], "no suitable visual");
111
112 cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
113
114 swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
115 vi->visual, AllocNone);
116
117 swa.border_pixel = 0;
118 swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask |
119 ButtonPressMask | ButtonMotionMask;
120 win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 900, 300,
121 0, vi->depth, InputOutput, vi->visual,
122 CWBorderPixel|CWColormap|CWEventMask, &swa);
123 XStoreName(dpy, win, "hiddenline");
124 XMapWindow(dpy, win);
125
126 glXMakeCurrent(dpy, win, cx);
127
128 /* check for the polygon offset extension */
129 #ifndef GL_VERSION_1_1
130 if (!query_extension("GL_EXT_polygon_offset"))
131 error(argv[0], "polygon_offset extension is not available");
132 #else
133 (void) query_extension;
134 #endif
135
136 /* set up viewing parameters */
137 glMatrixMode(GL_PROJECTION);
138 gluPerspective(20, 1, 10, 20);
139 glMatrixMode(GL_MODELVIEW);
140 glTranslatef(0, 0, -15);
141
142 /* set other relevant state information */
143 glEnable(GL_DEPTH_TEST);
144
145 glGetIntegerv(GL_DEPTH_BITS, &z);
146 printf("GL_DEPTH_BITS = %d\n", z);
147
148 #ifdef GL_EXT_polygon_offset
149 printf("using 1.0 offset extension\n");
150 glPolygonOffsetEXT( 1.0, 0.00001 );
151 #else
152 printf("using 1.1 offset\n");
153 glPolygonOffset( 1.0, 0.5 );
154 #endif
155
156 glShadeModel( GL_FLAT );
157 glDisable( GL_DITHER );
158
159 /* process events until the user presses ESC */
160 while (1) process_input(dpy, win);
161
162 return 0;
163 }
164
165 static void
166 draw_scene(int mx, int my) {
167 glClearColor(0.25, 0.25, 0.25, 0);
168 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
169
170 glPushMatrix();
171 glTranslatef(-1.7, 0.0, 0.0);
172 cubes(mx, my, WIREFRAME);
173 glPopMatrix();
174
175 glPushMatrix();
176 cubes(mx, my, HIDDEN_LINE);
177 glPopMatrix();
178
179 glPushMatrix();
180 glTranslatef(1.7, 0.0, 0.0);
181 #ifdef GL_EXT_polygon_offset
182 glEnable(GL_POLYGON_OFFSET_EXT);
183 #else
184 glEnable(GL_POLYGON_OFFSET_FILL);
185 #endif
186 cubes(mx, my, HIDDEN_LINE);
187 #ifdef GL_EXT_polygon_offset
188 glDisable(GL_POLYGON_OFFSET_EXT);
189 #else
190 glDisable(GL_POLYGON_OFFSET_FILL);
191 #endif
192 glPopMatrix();
193 }
194
195
196 static void
197 cubes(int mx, int my, int mode) {
198 int x, y, z, i;
199
200 /* track the mouse */
201 glRotatef(mx / 2.0, 0, 1, 0);
202 glRotatef(my / 2.0, 1, 0, 0);
203
204 /* draw the lines as hidden polygons */
205 glTranslatef(-0.5, -0.5, -0.5);
206 glScalef(1.0/dimension, 1.0/dimension, 1.0/dimension);
207 for (z = 0; z < dimension; z++) {
208 for (y = 0; y < dimension; y++) {
209 for (x = 0; x < dimension; x++) {
210 glPushMatrix();
211 glTranslatef(x, y, z);
212 glScalef(0.8, 0.8, 0.8);
213 for (i = 0; i < MAXQUAD; i++)
214 draw_hidden(quads[i], mode, i);
215 glPopMatrix();
216 }
217 }
218 }
219 }
220
221 static void
222 fill(Quad quad) {
223 /* draw a filled polygon */
224 glBegin(GL_QUADS);
225 glVertex3fv(quad[0]);
226 glVertex3fv(quad[1]);
227 glVertex3fv(quad[2]);
228 glVertex3fv(quad[3]);
229 glEnd();
230 }
231
232 static void
233 outline(Quad quad) {
234 /* draw an outlined polygon */
235 glBegin(GL_LINE_LOOP);
236 glVertex3fv(quad[0]);
237 glVertex3fv(quad[1]);
238 glVertex3fv(quad[2]);
239 glVertex3fv(quad[3]);
240 glEnd();
241 }
242
243 static void
244 draw_hidden(Quad quad, int mode, int face) {
245 static const GLfloat colors[3][3] = {
246 {0.5, 0.5, 0.0},
247 {0.8, 0.5, 0.0},
248 {0.0, 0.5, 0.8}
249 };
250 if (mode == HIDDEN_LINE) {
251 glColor3fv(colors[face % 3]);
252 fill(quad);
253 }
254
255 /* draw the outline using white */
256 glColor3f(1, 1, 1);
257 outline(quad);
258 }
259
260 static void
261 process_input(Display *dpy, Window win) {
262 XEvent event;
263 static int prevx, prevy;
264 static int deltax = 90, deltay = 40;
265
266 do {
267 char buf[31];
268 KeySym keysym;
269
270 XNextEvent(dpy, &event);
271 switch(event.type) {
272 case Expose:
273 break;
274 case ConfigureNotify: {
275 /* this approach preserves a 1:1 viewport aspect ratio */
276 int vX, vY, vW, vH;
277 int eW = event.xconfigure.width, eH = event.xconfigure.height;
278 if (eW >= eH) {
279 vX = 0;
280 vY = (eH - eW) >> 1;
281 vW = vH = eW;
282 } else {
283 vX = (eW - eH) >> 1;
284 vY = 0;
285 vW = vH = eH;
286 }
287 glViewport(vX, vY, vW, vH);
288 }
289 break;
290 case KeyPress:
291 (void) XLookupString(&event.xkey, buf, sizeof(buf), &keysym, NULL);
292 switch (keysym) {
293 case XK_Escape:
294 exit(EXIT_SUCCESS);
295 default:
296 break;
297 }
298 case ButtonPress:
299 prevx = event.xbutton.x;
300 prevy = event.xbutton.y;
301 break;
302 case MotionNotify:
303 deltax += (event.xbutton.x - prevx); prevx = event.xbutton.x;
304 deltay += (event.xbutton.y - prevy); prevy = event.xbutton.y;
305 break;
306 default:
307 break;
308 }
309 } while (XPending(dpy));
310
311 draw_scene(deltax, deltay);
312 glXSwapBuffers(dpy, win);
313 }
314
315 static void
316 error(const char *prog, const char *msg) {
317 fprintf(stderr, "%s: %s\n", prog, msg);
318 exit(EXIT_FAILURE);
319 }
320
321 static int
322 query_extension(char* extName) {
323 char *p = (char *) glGetString(GL_EXTENSIONS);
324 char *end = p + strlen(p);
325 while (p < end) {
326 int n = strcspn(p, " ");
327 if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0))
328 return GL_TRUE;
329 p += (n + 1);
330 }
331 return GL_FALSE;
332 }
333