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
51 #include <X11/keysym.h>
56 #undef GL_EXT_polygon_offset /* use GL 1.1 version instead of extension */
60 # define EXIT_FAILURE 1
63 # define EXIT_SUCCESS 0
68 typedef float Vertex
[3];
70 typedef Vertex Quad
[4];
72 /* data to define the six faces of a unit cube */
73 Quad 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} }
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
);
90 static void process_input(Display
*dpy
, Window win
);
91 static int query_extension(char* extName
);
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
};
96 static int dimension
= 3;
98 int main(int argc
, char** argv
) {
101 XSetWindowAttributes swa
;
105 dpy
= XOpenDisplay(0);
106 if (!dpy
) error(argv
[0], "can't open display");
108 vi
= glXChooseVisual(dpy
, DefaultScreen(dpy
), attributeList
);
109 if (!vi
) error(argv
[0], "no suitable visual");
111 cx
= glXCreateContext(dpy
, vi
, 0, GL_TRUE
);
113 swa
.colormap
= XCreateColormap(dpy
, RootWindow(dpy
, vi
->screen
),
114 vi
->visual
, AllocNone
);
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
);
125 glXMakeCurrent(dpy
, win
, cx
);
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");
132 (void) query_extension
;
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);
141 /* set other relevant state information */
142 glEnable(GL_DEPTH_TEST
);
144 #ifdef GL_EXT_polygon_offset
145 printf("using 1.0 offset extension\n");
146 glPolygonOffsetEXT( 1.0, 0.00001 );
148 printf("using 1.1 offset\n");
149 glPolygonOffset( 1.0, 0.5 );
152 glShadeModel( GL_FLAT
);
153 glDisable( GL_DITHER
);
155 /* process events until the user presses ESC */
156 while (1) process_input(dpy
, win
);
162 draw_scene(int mx
, int my
) {
163 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
166 glTranslatef(-1.7, 0.0, 0.0);
167 cubes(mx
, my
, WIREFRAME
);
171 cubes(mx
, my
, HIDDEN_LINE
);
175 glTranslatef(1.7, 0.0, 0.0);
176 #ifdef GL_EXT_polygon_offset
177 glEnable(GL_POLYGON_OFFSET_EXT
);
179 glEnable(GL_POLYGON_OFFSET_FILL
);
181 cubes(mx
, my
, HIDDEN_LINE
);
182 #ifdef GL_EXT_polygon_offset
183 glDisable(GL_POLYGON_OFFSET_EXT
);
185 glDisable(GL_POLYGON_OFFSET_FILL
);
192 cubes(int mx
, int my
, int mode
) {
195 /* track the mouse */
196 glRotatef(mx
/ 2.0, 0, 1, 0);
197 glRotatef(my
/ 2.0, 1, 0, 0);
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
++) {
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
);
218 /* draw a filled polygon */
220 glVertex3fv(quad
[0]);
221 glVertex3fv(quad
[1]);
222 glVertex3fv(quad
[2]);
223 glVertex3fv(quad
[3]);
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]);
239 draw_hidden(Quad quad
, int mode
) {
240 if (mode
== HIDDEN_LINE
) {
245 /* draw the outline using white, optionally fill the interior with black */
251 process_input(Display
*dpy
, Window win
) {
253 static int prevx
, prevy
;
254 static int deltax
= 90, deltay
= 40;
260 XNextEvent(dpy
, &event
);
264 case ConfigureNotify
: {
265 /* this approach preserves a 1:1 viewport aspect ratio */
267 int eW
= event
.xconfigure
.width
, eH
= event
.xconfigure
.height
;
277 glViewport(vX
, vY
, vW
, vH
);
281 (void) XLookupString(&event
.xkey
, buf
, sizeof(buf
), &keysym
, NULL
);
289 prevx
= event
.xbutton
.x
;
290 prevy
= event
.xbutton
.y
;
293 deltax
+= (event
.xbutton
.x
- prevx
); prevx
= event
.xbutton
.x
;
294 deltay
+= (event
.xbutton
.y
- prevy
); prevy
= event
.xbutton
.y
;
299 } while (XPending(dpy
));
301 draw_scene(deltax
, deltay
);
302 glXSwapBuffers(dpy
, win
);
306 error(const char *prog
, const char *msg
) {
307 fprintf(stderr
, "%s: %s\n", prog
, msg
);
312 query_extension(char* extName
) {
313 char *p
= (char *) glGetString(GL_EXTENSIONS
);
314 char *end
= p
+ strlen(p
);
316 int n
= strcspn(p
, " ");
317 if ((strlen(extName
) == n
) && (strncmp(extName
, p
, n
) == 0))