1 /****************************************************************************
2 Copyright 1995 by Silicon Graphics Incorporated, Mountain View, California.
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.
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.
22 ****************************************************************************/
25 * Derived from code written by Kurt Akeley, November 1992
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.
34 * The left image shows an ordinary antialiased wireframe image.
35 * The center image shows an antialiased hidden-line image without
37 * The right image shows an antialiased hidden-line image using
38 * PolygonOffset to reduce artifacts.
40 * Drag with a mouse button pressed to rotate the models.
41 * Press the escape key to exit.
45 * Modified for OpenGL 1.1 glPolygonOffset() conventions
50 #include <X11/keysym.h>
55 #undef GL_EXT_polygon_offset /* use GL 1.1 version instead of extension */
59 # define EXIT_FAILURE 1
62 # define EXIT_SUCCESS 0
67 typedef float Vertex
[3];
69 typedef Vertex Quad
[4];
71 /* data to define the six faces of a unit cube */
72 Quad quads
[MAXQUAD
] = {
73 { {0,0,0}, {0,0,1}, {0,1,1}, {0,1,0} }, /* x = 0 */
74 { {0,0,0}, {1,0,0}, {1,0,1}, {0,0,1} }, /* y = 0 */
75 { {0,0,0}, {1,0,0}, {1,1,0}, {0,1,0} }, /* z = 0 */
76 { {1,0,0}, {1,0,1}, {1,1,1}, {1,1,0} }, /* x = 1 */
77 { {0,1,0}, {1,1,0}, {1,1,1}, {0,1,1} }, /* y = 1 */
78 { {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1} } /* z = 1 */
84 static void error(const char* prog
, const char* msg
);
85 static void cubes(int mx
, int my
, int mode
);
86 static void fill(Quad quad
);
87 static void outline(Quad quad
);
88 static void draw_hidden(Quad quad
, int mode
, int face
);
89 static void process_input(Display
*dpy
, Window win
);
90 static int query_extension(char* extName
);
92 static int attributeList
[] = { GLX_RGBA
, GLX_RED_SIZE
, 1, GLX_GREEN_SIZE
, 1,
93 GLX_BLUE_SIZE
, 1, GLX_DOUBLEBUFFER
, GLX_DEPTH_SIZE
, 1, None
};
95 static int dimension
= 3;
97 static float Scale
= 1.0;
100 int main(int argc
, char** argv
) {
103 XSetWindowAttributes swa
;
108 dpy
= XOpenDisplay(0);
109 if (!dpy
) error(argv
[0], "can't open display");
111 vi
= glXChooseVisual(dpy
, DefaultScreen(dpy
), attributeList
);
112 if (!vi
) error(argv
[0], "no suitable visual");
114 cx
= glXCreateContext(dpy
, vi
, 0, GL_TRUE
);
116 swa
.colormap
= XCreateColormap(dpy
, RootWindow(dpy
, vi
->screen
),
117 vi
->visual
, AllocNone
);
119 swa
.border_pixel
= 0;
120 swa
.event_mask
= ExposureMask
| StructureNotifyMask
| KeyPressMask
|
121 ButtonPressMask
| ButtonMotionMask
;
122 win
= XCreateWindow(dpy
, RootWindow(dpy
, vi
->screen
), 0, 0, 900, 300,
123 0, vi
->depth
, InputOutput
, vi
->visual
,
124 CWBorderPixel
|CWColormap
|CWEventMask
, &swa
);
125 XStoreName(dpy
, win
, "hiddenline");
126 XMapWindow(dpy
, win
);
128 glXMakeCurrent(dpy
, win
, cx
);
130 /* check for the polygon offset extension */
131 #ifndef GL_VERSION_1_1
132 if (!query_extension("GL_EXT_polygon_offset"))
133 error(argv
[0], "polygon_offset extension is not available");
135 (void) query_extension
;
138 /* set up viewing parameters */
139 glMatrixMode(GL_PROJECTION
);
140 glFrustum(-1, 1, -1, 1, 6, 20);
141 glMatrixMode(GL_MODELVIEW
);
142 glTranslatef(0, 0, -15);
144 /* set other relevant state information */
145 glEnable(GL_DEPTH_TEST
);
147 glGetIntegerv(GL_DEPTH_BITS
, &z
);
148 printf("GL_DEPTH_BITS = %d\n", z
);
150 #ifdef GL_EXT_polygon_offset
151 printf("using 1.0 offset extension\n");
152 glPolygonOffsetEXT( 1.0, 0.00001 );
154 printf("using 1.1 offset\n");
155 glPolygonOffset( 1.0, 0.5 );
158 glShadeModel( GL_FLAT
);
159 glDisable( GL_DITHER
);
161 /* process events until the user presses ESC */
162 while (1) process_input(dpy
, win
);
168 draw_scene(int mx
, int my
) {
169 glClearColor(0.25, 0.25, 0.25, 0);
170 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
173 glTranslatef(-1.7, 0.0, 0.0);
174 cubes(mx
, my
, WIREFRAME
);
178 cubes(mx
, my
, HIDDEN_LINE
);
182 glTranslatef(1.7, 0.0, 0.0);
183 #ifdef GL_EXT_polygon_offset
184 glEnable(GL_POLYGON_OFFSET_EXT
);
186 glEnable(GL_POLYGON_OFFSET_FILL
);
188 glScalef(Scale
, Scale
, Scale
);
189 cubes(mx
, my
, HIDDEN_LINE
);
190 #ifdef GL_EXT_polygon_offset
191 glDisable(GL_POLYGON_OFFSET_EXT
);
193 glDisable(GL_POLYGON_OFFSET_FILL
);
200 cubes(int mx
, int my
, int mode
) {
203 /* track the mouse */
204 glRotatef(mx
/ 2.0, 0, 1, 0);
205 glRotatef(my
/ 2.0, 1, 0, 0);
207 /* draw the lines as hidden polygons */
208 glTranslatef(-0.5, -0.5, -0.5);
209 glScalef(1.0/dimension
, 1.0/dimension
, 1.0/dimension
);
210 for (z
= 0; z
< dimension
; z
++) {
211 for (y
= 0; y
< dimension
; y
++) {
212 for (x
= 0; x
< dimension
; x
++) {
214 glTranslatef(x
, y
, z
);
215 glScalef(0.8, 0.8, 0.8);
216 for (i
= 0; i
< MAXQUAD
; i
++)
217 draw_hidden(quads
[i
], mode
, i
);
226 /* draw a filled polygon */
228 glVertex3fv(quad
[0]);
229 glVertex3fv(quad
[1]);
230 glVertex3fv(quad
[2]);
231 glVertex3fv(quad
[3]);
237 /* draw an outlined polygon */
238 glBegin(GL_LINE_LOOP
);
239 glVertex3fv(quad
[0]);
240 glVertex3fv(quad
[1]);
241 glVertex3fv(quad
[2]);
242 glVertex3fv(quad
[3]);
247 draw_hidden(Quad quad
, int mode
, int face
) {
248 static const GLfloat colors
[3][3] = {
253 if (mode
== HIDDEN_LINE
) {
254 glColor3fv(colors
[face
% 3]);
258 /* draw the outline using white */
264 process_input(Display
*dpy
, Window win
) {
266 static int prevx
, prevy
;
267 static int deltax
= 90, deltay
= 40;
273 XNextEvent(dpy
, &event
);
277 case ConfigureNotify
: {
278 /* this approach preserves a 1:1 viewport aspect ratio */
280 int eW
= event
.xconfigure
.width
, eH
= event
.xconfigure
.height
;
290 glViewport(vX
, vY
, vW
, vH
);
294 (void) XLookupString(&event
.xkey
, buf
, sizeof(buf
), &keysym
, NULL
);
309 prevx
= event
.xbutton
.x
;
310 prevy
= event
.xbutton
.y
;
313 deltax
+= (event
.xbutton
.x
- prevx
); prevx
= event
.xbutton
.x
;
314 deltay
+= (event
.xbutton
.y
- prevy
); prevy
= event
.xbutton
.y
;
319 } while (XPending(dpy
));
321 draw_scene(deltax
, deltay
);
322 glXSwapBuffers(dpy
, win
);
326 error(const char *prog
, const char *msg
) {
327 fprintf(stderr
, "%s: %s\n", prog
, msg
);
332 query_extension(char* extName
) {
333 char *p
= (char *) glGetString(GL_EXTENSIONS
);
334 char *end
= p
+ strlen(p
);
336 int n
= strcspn(p
, " ");
337 if ((strlen(extName
) == n
) && (strncmp(extName
, p
, n
) == 0))