1/**
2 * Test glPolygonMode w/ different front/back face modes.
3 *
4 * The left half of the window draws a torus with different front/back
5 * polygon modes.
6 *
7 * The right half of the windows tries to draw the same thing, but with
8 * a different approach:
9 *   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10 *   glEnable(GL_CULL_FACE);
11 *   glCullFace(GL_FRONT);
12 *   draw_object();
13 *   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14 *   glEnable(GL_CULL_FACE);
15 *   glCullFace(GL_BACK);
16 *   draw_object();
17 *
18 * The outcome is often the same, but not always (turn on blending with 'b').
19 *
20 * Brian Paul
21 * 2 Feb 2016
22 */
23
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <math.h>
28#include "glut_wrap.h"
29
30static int Win;
31static int WinWidth = 800, WinHeight = 400;
32static GLfloat Xrot = 0;
33static GLboolean Anim = GL_TRUE;
34static double t0;
35static GLboolean Blend = GL_TRUE;
36
37
38static void
39Idle(void)
40{
41   double t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
42   Xrot += (t1 - t0) * 20;  /* 20 degrees per second */
43   t0 = t1;
44   glutPostRedisplay();
45}
46
47
48static void
49Draw(void)
50{
51   int hw = WinWidth / 2;
52
53   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
54
55   if (Blend) {
56      glEnable(GL_BLEND);
57      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
58      glBlendFunc(GL_ONE, GL_ONE);
59   }
60   else {
61      glDisable(GL_BLEND);
62   }
63
64   glPushMatrix();
65   glRotatef(Xrot, 1, 0, 0);
66
67   /* draw left half */
68   glViewport(0, 0, hw, WinHeight);
69
70   glPolygonMode(GL_FRONT, GL_LINE);
71   glPolygonMode(GL_BACK, GL_FILL);
72   glDisable(GL_CULL_FACE);
73   glutSolidTorus(0.75, 2.0, 10, 20);
74
75   /* draw right half */
76   glViewport(hw, 0, WinWidth - hw, WinHeight);
77
78   /* draw back faces */
79   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
80   glEnable(GL_CULL_FACE);
81   glCullFace(GL_FRONT);
82   glutSolidTorus(0.75, 2.0, 10, 20);
83
84   /* draw front faces */
85   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
86   glEnable(GL_CULL_FACE);
87   glCullFace(GL_BACK);
88   glutSolidTorus(0.75, 2.0, 10, 20);
89
90   glPopMatrix();
91
92   glutSwapBuffers();
93}
94
95
96static void
97Reshape(int width, int height)
98{
99   WinWidth = width;
100   WinHeight = height;
101   glMatrixMode(GL_PROJECTION);
102   glLoadIdentity();
103   glFrustum(-1.0, 1.0, -1.0, 1.0, 3.0, 25.0);
104   glMatrixMode(GL_MODELVIEW);
105   glLoadIdentity();
106   glTranslatef(0.0, 0.0, -10.0);
107   glutPostRedisplay();
108}
109
110
111static void
112Key(unsigned char key, int x, int y)
113{
114   (void) x;
115   (void) y;
116   switch (key) {
117   case 'a':
118      Anim = !Anim;
119      if (Anim) {
120         t0 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
121         glutIdleFunc(Idle);
122      }
123      else
124         glutIdleFunc(NULL);
125      break;
126   case 'b':
127      Blend = !Blend;
128      break;
129   case 27:
130      glutDestroyWindow(Win);
131      exit(0);
132      break;
133   }
134   glutPostRedisplay();
135}
136
137
138static void
139SpecialKey(int key, int x, int y)
140{
141   const GLfloat step = 3.0;
142   (void) x;
143   (void) y;
144   switch (key) {
145   case GLUT_KEY_UP:
146      Xrot -= step;
147      break;
148   case GLUT_KEY_DOWN:
149      Xrot += step;
150      break;
151   }
152   glutPostRedisplay();
153}
154
155
156static void
157Init(void)
158{
159   static const float yellow[4] = {1, 1, 0, 0.5};
160   static const float blue[4] = {0.2, 0.2, 1, 0.5};
161   static const float gray[4] = {0.2, 0.2, 0.2, 1.0};
162
163   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, gray);
164   glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);
165   glMaterialfv(GL_BACK, GL_DIFFUSE, blue);
166   glEnable(GL_DEPTH_TEST);
167   glEnable(GL_LIGHTING);
168   glEnable(GL_LIGHT0);
169   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
170   glShadeModel(GL_FLAT);
171
172   glClearColor(0.25, 0.25, 0.25, 1.0);
173}
174
175
176int
177main(int argc, char *argv[])
178{
179   glutInit(&argc, argv);
180   glutInitWindowSize(WinWidth, WinHeight);
181   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
182   Win = glutCreateWindow(argv[0]);
183   glutReshapeFunc(Reshape);
184   glutKeyboardFunc(Key);
185   glutSpecialFunc(SpecialKey);
186   glutDisplayFunc(Draw);
187   if (Anim)
188      glutIdleFunc(Idle);
189   Init();
190   glutMainLoop();
191   return 0;
192}
193