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}, {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 */
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
);
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
;
106 dpy
= XOpenDisplay(0);
107 if (!dpy
) error(argv
[0], "can't open display");
109 vi
= glXChooseVisual(dpy
, DefaultScreen(dpy
), attributeList
);
110 if (!vi
) error(argv
[0], "no suitable visual");
112 cx
= glXCreateContext(dpy
, vi
, 0, GL_TRUE
);
114 swa
.colormap
= XCreateColormap(dpy
, RootWindow(dpy
, vi
->screen
),
115 vi
->visual
, AllocNone
);
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
);
126 glXMakeCurrent(dpy
, win
, cx
);
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");
133 (void) query_extension
;
136 /* set up viewing parameters */
137 glMatrixMode(GL_PROJECTION
);
138 gluPerspective(20, 1, 10, 20);
139 glMatrixMode(GL_MODELVIEW
);
140 glTranslatef(0, 0, -15);
142 /* set other relevant state information */
143 glEnable(GL_DEPTH_TEST
);
145 glGetIntegerv(GL_DEPTH_BITS
, &z
);
146 printf("GL_DEPTH_BITS = %d\n", z
);
148 #ifdef GL_EXT_polygon_offset
149 printf("using 1.0 offset extension\n");
150 glPolygonOffsetEXT( 1.0, 0.00001 );
152 printf("using 1.1 offset\n");
153 glPolygonOffset( 1.0, 0.5 );
156 glShadeModel( GL_FLAT
);
157 glDisable( GL_DITHER
);
159 /* process events until the user presses ESC */
160 while (1) process_input(dpy
, win
);
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
);
171 glTranslatef(-1.7, 0.0, 0.0);
172 cubes(mx
, my
, WIREFRAME
);
176 cubes(mx
, my
, HIDDEN_LINE
);
180 glTranslatef(1.7, 0.0, 0.0);
181 #ifdef GL_EXT_polygon_offset
182 glEnable(GL_POLYGON_OFFSET_EXT
);
184 glEnable(GL_POLYGON_OFFSET_FILL
);
186 cubes(mx
, my
, HIDDEN_LINE
);
187 #ifdef GL_EXT_polygon_offset
188 glDisable(GL_POLYGON_OFFSET_EXT
);
190 glDisable(GL_POLYGON_OFFSET_FILL
);
197 cubes(int mx
, int my
, int mode
) {
200 /* track the mouse */
201 glRotatef(mx
/ 2.0, 0, 1, 0);
202 glRotatef(my
/ 2.0, 1, 0, 0);
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
++) {
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
);
223 /* draw a filled polygon */
225 glVertex3fv(quad
[0]);
226 glVertex3fv(quad
[1]);
227 glVertex3fv(quad
[2]);
228 glVertex3fv(quad
[3]);
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]);
244 draw_hidden(Quad quad
, int mode
, int face
) {
245 static const GLfloat colors
[3][3] = {
250 if (mode
== HIDDEN_LINE
) {
251 glColor3fv(colors
[face
% 3]);
255 /* draw the outline using white */
261 process_input(Display
*dpy
, Window win
) {
263 static int prevx
, prevy
;
264 static int deltax
= 90, deltay
= 40;
270 XNextEvent(dpy
, &event
);
274 case ConfigureNotify
: {
275 /* this approach preserves a 1:1 viewport aspect ratio */
277 int eW
= event
.xconfigure
.width
, eH
= event
.xconfigure
.height
;
287 glViewport(vX
, vY
, vW
, vH
);
291 (void) XLookupString(&event
.xkey
, buf
, sizeof(buf
), &keysym
, NULL
);
299 prevx
= event
.xbutton
.x
;
300 prevy
= event
.xbutton
.y
;
303 deltax
+= (event
.xbutton
.x
- prevx
); prevx
= event
.xbutton
.x
;
304 deltay
+= (event
.xbutton
.y
- prevy
); prevy
= event
.xbutton
.y
;
309 } while (XPending(dpy
));
311 draw_scene(deltax
, deltay
);
312 glXSwapBuffers(dpy
, win
);
316 error(const char *prog
, const char *msg
) {
317 fprintf(stderr
, "%s: %s\n", prog
, msg
);
322 query_extension(char* extName
) {
323 char *p
= (char *) glGetString(GL_EXTENSIONS
);
324 char *end
= p
+ strlen(p
);
326 int n
= strcspn(p
, " ");
327 if ((strlen(extName
) == n
) && (strncmp(extName
, p
, n
) == 0))