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