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 int main(int argc
, char** argv
) {
100 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 glFrustum(-1, 1, -1, 1, 6, 20);
138 glMatrixMode(GL_MODELVIEW
);
139 glTranslatef(0, 0, -15);
141 /* set other relevant state information */
142 glEnable(GL_DEPTH_TEST
);
144 glGetIntegerv(GL_DEPTH_BITS
, &z
);
145 printf("GL_DEPTH_BITS = %d\n", z
);
147 #ifdef GL_EXT_polygon_offset
148 printf("using 1.0 offset extension\n");
149 glPolygonOffsetEXT( 1.0, 0.00001 );
151 printf("using 1.1 offset\n");
152 glPolygonOffset( 1.0, 0.5 );
155 glShadeModel( GL_FLAT
);
156 glDisable( GL_DITHER
);
158 /* process events until the user presses ESC */
159 while (1) process_input(dpy
, win
);
165 draw_scene(int mx
, int my
) {
166 glClearColor(0.25, 0.25, 0.25, 0);
167 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
170 glTranslatef(-1.7, 0.0, 0.0);
171 cubes(mx
, my
, WIREFRAME
);
175 cubes(mx
, my
, HIDDEN_LINE
);
179 glTranslatef(1.7, 0.0, 0.0);
180 #ifdef GL_EXT_polygon_offset
181 glEnable(GL_POLYGON_OFFSET_EXT
);
183 glEnable(GL_POLYGON_OFFSET_FILL
);
185 cubes(mx
, my
, HIDDEN_LINE
);
186 #ifdef GL_EXT_polygon_offset
187 glDisable(GL_POLYGON_OFFSET_EXT
);
189 glDisable(GL_POLYGON_OFFSET_FILL
);
196 cubes(int mx
, int my
, int mode
) {
199 /* track the mouse */
200 glRotatef(mx
/ 2.0, 0, 1, 0);
201 glRotatef(my
/ 2.0, 1, 0, 0);
203 /* draw the lines as hidden polygons */
204 glTranslatef(-0.5, -0.5, -0.5);
205 glScalef(1.0/dimension
, 1.0/dimension
, 1.0/dimension
);
206 for (z
= 0; z
< dimension
; z
++) {
207 for (y
= 0; y
< dimension
; y
++) {
208 for (x
= 0; x
< dimension
; x
++) {
210 glTranslatef(x
, y
, z
);
211 glScalef(0.8, 0.8, 0.8);
212 for (i
= 0; i
< MAXQUAD
; i
++)
213 draw_hidden(quads
[i
], mode
, i
);
222 /* draw a filled polygon */
224 glVertex3fv(quad
[0]);
225 glVertex3fv(quad
[1]);
226 glVertex3fv(quad
[2]);
227 glVertex3fv(quad
[3]);
233 /* draw an outlined polygon */
234 glBegin(GL_LINE_LOOP
);
235 glVertex3fv(quad
[0]);
236 glVertex3fv(quad
[1]);
237 glVertex3fv(quad
[2]);
238 glVertex3fv(quad
[3]);
243 draw_hidden(Quad quad
, int mode
, int face
) {
244 static const GLfloat colors
[3][3] = {
249 if (mode
== HIDDEN_LINE
) {
250 glColor3fv(colors
[face
% 3]);
254 /* draw the outline using white */
260 process_input(Display
*dpy
, Window win
) {
262 static int prevx
, prevy
;
263 static int deltax
= 90, deltay
= 40;
269 XNextEvent(dpy
, &event
);
273 case ConfigureNotify
: {
274 /* this approach preserves a 1:1 viewport aspect ratio */
276 int eW
= event
.xconfigure
.width
, eH
= event
.xconfigure
.height
;
286 glViewport(vX
, vY
, vW
, vH
);
290 (void) XLookupString(&event
.xkey
, buf
, sizeof(buf
), &keysym
, NULL
);
298 prevx
= event
.xbutton
.x
;
299 prevy
= event
.xbutton
.y
;
302 deltax
+= (event
.xbutton
.x
- prevx
); prevx
= event
.xbutton
.x
;
303 deltay
+= (event
.xbutton
.y
- prevy
); prevy
= event
.xbutton
.y
;
308 } while (XPending(dpy
));
310 draw_scene(deltax
, deltay
);
311 glXSwapBuffers(dpy
, win
);
315 error(const char *prog
, const char *msg
) {
316 fprintf(stderr
, "%s: %s\n", prog
, msg
);
321 query_extension(char* extName
) {
322 char *p
= (char *) glGetString(GL_EXTENSIONS
);
323 char *end
= p
+ strlen(p
);
325 int n
= strcspn(p
, " ");
326 if ((strlen(extName
) == n
) && (strncmp(extName
, p
, n
) == 0))