669ede3f0a4e0ba1d6fd73b265cd74d9f3940b58
[lighthouse] / src / main.cc
1 #include <GL/glew.h>
2 #include <GL/freeglut.h>
3
4 #include <stdlib.h>
5 #include <stdio.h>
6
7 #include "sdr.h"
8
9 #define CURVE_VS "sdr/curve_top.v.glsl"
10 #define CURVE_FS "sdr/curve_top.f.glsl"
11 #define BEAM_VS "sdr/beam.v.glsl"
12 #define BEAM_FS "sdr/beam.f.glsl"
13
14 #define BEAM_SHELLS 40
15 #define BEAM_RMIN 0.01
16 #define BEAM_RMAX 0.125
17 #define BEAM_ENERGY 0.02
18
19 static bool init();
20 static void cleanup();
21
22 static void faros();
23 static void light();
24 static void ground();
25 static void backdrop();
26
27 static void display();
28 static void idle();
29 static void reshape(int x, int y);
30 static void keyboard(unsigned char c, int x, int y);
31 static void mbutton(int bn, int state, int x, int y);
32 static void mmotion(int x, int y);
33
34 static float cam_theta = 45, cam_phi, cam_dist = 10;
35 static unsigned int sdr_curve_top, sdr_beam, sdr_sky;
36 static unsigned int start_time;
37 static float beam_rot_speed = 0.1;
38
39 int main(int argc, char **argv)
40 {
41         glutInit(&argc, argv);
42         glutInitWindowSize(800, 600);
43         glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
44
45         glutCreateWindow("Faros");
46
47         glutDisplayFunc(display);
48         glutIdleFunc(idle);
49         glutReshapeFunc(reshape);
50         glutKeyboardFunc(keyboard);
51         glutMouseFunc(mbutton);
52         glutMotionFunc(mmotion);
53
54         if(!init()) {
55                 return 1;
56         }
57
58         atexit(cleanup);
59         glutMainLoop();
60
61         return 0;
62 }
63
64 static bool init()
65 {
66         glewInit();
67
68         glEnable(GL_CULL_FACE);
69         glEnable(GL_DEPTH_TEST);
70         glEnable(GL_MULTISAMPLE);
71
72 //      glEnable(GL_LIGHTING);
73         glEnable(GL_LIGHT0);
74
75         glEnable(GL_NORMALIZE);
76
77         if(!(sdr_curve_top = create_program_load(CURVE_VS, CURVE_FS)))
78                 return false;
79
80         if(!(sdr_beam = create_program_load(BEAM_VS, BEAM_FS)))
81                 return false;
82
83         if(!(sdr_sky = create_program_load("sdr/sky.v.glsl", "sdr/sky.f.glsl"))) {
84                 return false;
85         }
86
87         start_time = glutGet(GLUT_ELAPSED_TIME);
88         return true;
89 }
90
91 static void cleanup()
92 {
93 }
94
95 static void faros()
96 {
97         glColor3f(0, 0, 0);
98
99         // kormos
100         glPushMatrix();
101         glScalef(1.1, 3, 1.1);
102         glTranslatef(0, 0.5, 0);
103         glutSolidCube(1.0);
104         glPopMatrix();
105
106         glShadeModel(GL_FLAT);
107
108         // base
109         glPushMatrix();
110         glRotatef(90, 1, 0, 0);
111         glTranslatef(0, -0.15, 0);
112         glutSolidCylinder(2, 0.3, 16, 1);
113         glPopMatrix();
114
115         // middle cylinder
116         glPushMatrix();
117         glTranslatef(0, 3, 0);
118         glRotatef(22.5, 0, 1, 0);
119         glRotatef(-90, 1, 0, 0);
120         glutSolidCylinder(0.5, 1.0, 8, 1);
121         glPopMatrix();
122
123         // trim middle cylinder (mporntoura)
124         glPushMatrix();
125         glTranslatef(0, 3.9, 0);
126         glRotatef(22.5, 0, 1, 0);
127         glRotatef(-90, 1, 0, 0);
128         glutSolidCylinder(0.55, 0.02, 8, 1);
129         glPopMatrix();
130
131         // top smaller cylinder
132         glPushMatrix();
133         glTranslatef(0, 4, 0);
134         glRotatef(22.5, 0, 1, 0);
135         glRotatef(-90, 1, 0, 0);
136         glutSolidCylinder(0.28, 0.5, 8, 1);
137         glPopMatrix();
138
139         // top wire even smaller cylinder
140         glPushMatrix();
141         glTranslatef(0, 4.5, 0);
142         glRotatef(22.5, 0, 1, 0);
143         glRotatef(-90, 1, 0, 0);
144         glutWireCylinder(0.18, 0.3, 9, 3);
145         glPopMatrix();
146
147         glShadeModel(GL_SMOOTH);
148
149         // top troulos
150         glPushMatrix();
151         glTranslatef(0, 4.8, 0);
152         glRotatef(22.5, 0, 1, 0);
153         glRotatef(-90, 1, 0, 0);
154         glutSolidCone(0.18, 0.2, 9, 1);
155         glPopMatrix();
156
157         // tsamploukano
158         glPushMatrix();
159         glTranslatef(-0.28, 4, 0);
160         glScalef(1, 13, 1);
161         glutSolidSphere(0.1, 16, 16);
162         glPopMatrix();
163
164         //pyramid on top of kormos
165         bind_program(sdr_curve_top);
166
167         glPushMatrix();
168         glTranslatef(0, 3, 0);
169         glRotatef(45, 0, 1, 0);
170         glRotatef(-90, 1, 0, 0);
171         glScalef(1, 1, 0.45);
172         glutSolidCylinder(1, 1, 4, 16);
173         glPopMatrix();
174         
175         bind_program(0);
176 }
177
178 static void light()
179 {
180         glPushAttrib(GL_ENABLE_BIT);
181         glDisable(GL_CULL_FACE);
182
183         glPushMatrix();
184
185         glTranslatef(0, 4.65, 0.2);
186         bind_program(sdr_beam);
187
188         glEnable(GL_BLEND);
189         glBlendFunc(GL_SRC_ALPHA, GL_ONE);
190
191         for(int i=0; i<BEAM_SHELLS; i++) {
192                 float t = (float)i / (float)(BEAM_SHELLS - 1);
193                 float rad = BEAM_RMIN + (BEAM_RMAX - BEAM_RMIN) * t;
194                 float alpha = BEAM_ENERGY / t;
195
196                 glColor4f(0.8, 0.8, 0.2, alpha);
197
198                 glutSolidCylinder(rad, 6, 10, 1);
199         }
200
201         bind_program(0);
202
203         glPopMatrix();
204
205         glPopAttrib();
206 }
207
208 static void ground()
209 {
210         glPushMatrix();
211
212         glTranslatef(0, -1.25, 0);
213         glScalef(1, 0.1, 1);
214
215         glColor3f(0, 0, 0);
216         glutSolidSphere(10, 32, 32);
217
218         glPopMatrix();
219 }
220
221 static void backdrop()
222 {
223         glFrontFace(GL_CW);
224         bind_program(sdr_sky);
225         glutSolidSphere(200, 16, 32);
226         bind_program(0);
227         glFrontFace(GL_CCW);
228 }
229
230 static void display()
231 {
232         unsigned int tmsec = glutGet(GLUT_ELAPSED_TIME) - start_time;
233         float tsec = (float)tmsec / 1000.0;
234
235         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
236         backdrop();
237
238         glMatrixMode(GL_MODELVIEW);
239         glLoadIdentity();
240
241         glTranslatef(0, -2, -cam_dist);
242         glRotatef(cam_phi, 1, 0, 0);
243         glRotatef(cam_theta, 0, 1, 0);
244
245         ground();
246         faros();
247
248         glPushMatrix();
249
250         float beam_angle = tsec * beam_rot_speed * 360;
251
252         glRotatef(beam_angle, 0, 1, 0);
253         light();
254
255         glPopMatrix();
256
257         glutSwapBuffers();
258 }
259
260 static void idle()
261 {
262         glutPostRedisplay();
263 }
264
265 static void reshape(int x, int y)
266 {
267         glViewport(0, 0, x, y);
268
269         glMatrixMode(GL_PROJECTION);
270         glLoadIdentity();
271
272         gluPerspective(50, (float)x / (float)y, 0.5, 500);
273 }
274
275 static void keyboard(unsigned char c, int x, int y)
276 {
277         switch(c) {
278         case 27:
279                 exit(0);
280         default:
281                 break;
282         }
283 }
284
285 static int prev_x, prev_y;
286 static bool bst[8];
287 static void mbutton(int bn, int state, int x, int y)
288 {
289         int button = bn - GLUT_LEFT_BUTTON;
290         bst[button] = state == GLUT_DOWN;
291
292         prev_x = x;
293         prev_y = y;
294 }
295
296 static void mmotion(int x, int y)
297 {
298         int dx = x - prev_x;
299         int dy = y - prev_y;
300
301         prev_x = x;
302         prev_y = y;
303
304         if (dx == 0 && dy == 0)
305                 return;
306
307         if (bst[0]) {
308                 cam_theta += dx * 0.5;
309                 cam_phi += dy * 0.5;
310
311                 if (cam_phi < -90)
312                         cam_phi = -90;
313
314                 if (cam_phi > 90)
315                         cam_phi = 90;
316         }
317
318         if (bst[2]) {
319                 cam_dist += dy * 0.1;
320
321                 if (cam_dist < 0)
322                         cam_dist = 0;
323         }
324 }