added summerhack
[summerhack] / src / parts / pipes.cpp
1 #include "pipes.hpp"
2
3 static void make_skycube(Scene *scene);
4 static void make_title(Scene *scene);
5 static void make_vol(Scene *scene);
6 static void render_vol(unsigned long time);
7 static void render_presents(float t);
8
9 #define PSYS_COUNT      4
10 static ParticleSystem *ps[PSYS_COUNT];
11 static ParticleSysParams *psys_params[PSYS_COUNT];
12 static bool psys_removed = false;
13
14 static const float inner_sz = 30.0;
15 static const float outer_sz = 70.0;
16 static const int sph_count = 50;
17 static Object *inner_sph, *vol_sph[sph_count];
18
19 static Texture *presents, *summer_hack;
20
21 #define TITLE
22 #define VOL
23 #define ANIM
24
25 PipesPart::PipesPart() : ScenePart("pipes", new Scene) {
26 #ifdef ANIM
27         TargetCamera *cam = new TargetCamera(Vector3(0, 20, -150));
28 #else
29         TargetCamera *cam = new TargetCamera(Vector3(0, 10, -150));
30 #endif
31         cam->set_fov(DEG_TO_RAD(50));
32         scene->add_camera(cam);
33
34         PointLight *lt = new PointLight(Vector3(10, 100, -100));
35         scene->add_light(lt);
36
37         scene->set_ambient_light(0.1);
38
39         make_skycube(scene);
40 #ifdef TITLE
41         make_title(scene);
42 #endif
43 #ifdef VOL
44         make_vol(scene);
45 #endif
46
47         presents = get_texture("data/img/presents.png");
48         summer_hack = get_texture("data/img/title.png");
49
50         MotionController cam_x, cam_y, cam_z;
51
52         cam_x = MotionController(CTRL_COS, TIME_FREE);
53         cam_x.set_sin_func(0.5, 40);
54         cam_x.set_control_axis(CTRL_X);
55
56         cam_z = MotionController(CTRL_SIN, TIME_FREE);
57         cam_z.set_sin_func(1.5, 100);
58         cam_z.set_control_axis(CTRL_Z);
59
60         cam_y = MotionController(CTRL_SIN, TIME_FREE);
61         cam_y.set_sin_func(0.35, 20);
62         cam_y.set_control_axis(CTRL_Y);
63
64 #ifdef ANIM
65         cam->add_controller(cam_x, CTRL_TRANSLATION);
66         //cam->add_controller(cam_z, CTRL_TRANSLATION);
67         cam->add_controller(cam_y, CTRL_TRANSLATION);
68 #endif
69
70         scene->set_background(0.5);
71
72         // make sure the volume and title textures are resident from the beginning
73         dsys::overlay(get_texture("data/img/cracks.jpg"), Vector2(0, 0), Vector2(0.1, 0.1), 0.0);
74         dsys::overlay(get_texture("data/img/volcano.jpg"), Vector2(0, 0), Vector2(0.1, 0.1), 0.0);
75         dsys::overlay(get_texture("data/img/title.png"), Vector2(0, 0), Vector2(0.1, 0.1), 0.0);
76         dsys::overlay(get_texture("data/img/presents.png"), Vector2(0, 0), Vector2(0.1, 0.1), 0.0);
77
78         //scene->render_sequence(0, 15000, 25);
79         //exit(0);
80 }
81
82 PipesPart::~PipesPart() {
83         //if(psys_removed) {
84                 for(int i=0; i<PSYS_COUNT; i++) {
85                         delete ps[i];
86                 }
87         //}
88 }
89
90 static const float pexpl_time = half_pi * 8.0;
91 static const float pexpl_full_time = pexpl_time + half_pi * 3.4;
92 static const float pstop_time = pexpl_time + half_pi * 6.0;
93
94 void PipesPart::draw_part() {
95         float t = (float)time / 1000.0f;
96         
97         ScenePart::draw_part();
98 #ifdef VOL
99         render_vol(time);
100 #endif
101
102 #ifdef TITLE
103         if(t < pstop_time) {
104                 float p = t / 4.0;
105                 if(t > pexpl_time) {
106                         static unsigned long prev_drop;
107                         bool drop = (time - prev_drop > 33.3333) ? true : false;
108                         
109                         //Fuzzy val(0.0, 1.75 * (1.0 - sin(fmod(p, half_pi) + half_pi)));
110                         Fuzzy val(0.0, 1.75 * sin(fmod(p, half_pi)));
111                         for(int i=0; i<PSYS_COUNT; i++) {
112                                 psys_params[i]->shoot_dir = FuzzyVec3(val, val, val);
113
114                                 if(t > pexpl_full_time && drop) {
115                                         psys_params[i]->birth_rate.num *= 0.8;
116                                 }
117                         }
118                 }
119
120                 p = t / 15.0;
121                 for(int i=0; i<PSYS_COUNT; i++) {
122                         float val = p > 0.5 ? 0.5 : p;
123                         float range = val * 2.0;
124                         psys_params[i]->spawn_offset_curve_area = Fuzzy(val, range);
125
126                         ps[i]->update();
127                         ps[i]->draw();
128                 }
129         }/* else {
130                 if(!psys_removed) {
131                         //for(int i=0; i<PSYS_COUNT; i++) {
132                         //      scene->remove_particle_sys(ps[i]);
133                         //}
134                         psys_removed = true;
135                 }
136         }*/
137 #endif  // TITLE
138
139         render_presents(t);
140 }
141
142 static void make_skycube(Scene *scene) {
143         const float size = 1000;
144         Object *face[6];
145         Texture *tex[6];
146
147         face[0] = new ObjPlane(Vector3(0, -1, 0), Vector2(size, size), 0);
148         face[0]->translate(Vector3(0, size / 2, 0));
149         tex[0] = get_texture("data/img/nebula_py.jpg");
150         
151         face[1] = new ObjPlane(Vector3(0, 1, 0), Vector2(size, size), 0);
152         face[1]->translate(Vector3(0, -size / 2, 0));
153         tex[1] = get_texture("data/img/nebula_ny.jpg");
154
155         face[2] = new ObjPlane(Vector3(0, 0, -1), Vector2(size, size), 0);
156         face[2]->translate(Vector3(0, 0, size / 2));
157         tex[2] = get_texture("data/img/nebula_pz.jpg");
158         
159         face[3] = new ObjPlane(Vector3(0, 0, 1), Vector2(size, size), 0);
160         face[3]->translate(Vector3(0, 0, -size / 2));
161         tex[3] = get_texture("data/img/nebula_nz.jpg");
162
163         face[4] = new ObjPlane(Vector3(-1, 0, 0), Vector2(size, size), 0);
164         face[4]->translate(Vector3(size / 2, 0, 0));
165         tex[4] = get_texture("data/img/nebula_px.jpg");
166         
167         face[5] = new ObjPlane(Vector3(1, 0, 0), Vector2(size, size), 0);
168         face[5]->translate(Vector3(-size / 2, 0, 0));
169         tex[5] = get_texture("data/img/nebula_nx.jpg");
170
171         for(int i=0; i<6; i++) {
172                 face[i]->apply_xform();
173                 face[i]->set_rotation(Vector3(0, quarter_pi, 0));
174         
175                 Material *mat = face[i]->get_material_ptr();
176                 mat->emissive_color = 1.0;
177                 add_texture(tex[i]);
178                 mat->set_texture(tex[i], TEXTYPE_DIFFUSE);
179                 face[i]->set_texture_addressing(TEXADDR_CLAMP);
180                 scene->add_object(face[i]);
181         }
182 }
183
184
185 void make_title(Scene *scene) {
186
187         for(int i=0; i<PSYS_COUNT; i++) {
188                 char curve_fname[64];
189                 sprintf(curve_fname, "data/curve%02d", i);
190                 
191                 Curve *curve = load_curve(curve_fname);
192                 curve->set_arc_parametrization(true);
193                 ps[i] = new ParticleSystem("data/thelab.psys");
194                 psys_params[i] = ps[i]->get_params();
195                 psys_params[i]->spawn_offset_curve = curve;
196                 if(i == 2) {
197                         psys_params[i]->birth_rate.num /= 1.5;
198                 }
199                 if(i == 1) {
200                         psys_params[i]->birth_rate.num /= 6.0;
201                 }
202                 if(i == 3) {
203                         psys_params[i]->birth_rate.num *= 1.3;
204                 }
205                 //scene->add_particle_sys(ps[i]);
206         }
207 }
208
209 static float vol_alpha[sph_count];
210
211 static void make_vol(Scene *scene) {
212         Material *mat;
213
214         MotionController rot1(CTRL_LIN, TIME_FREE);
215         MotionController rot2(CTRL_SIN, TIME_FREE);
216         
217         rot1.set_control_axis(CTRL_XY);
218         rot1.set_slope(1.08);
219         rot2.set_control_axis(CTRL_YZ);
220         rot2.set_slope(1.439999);
221         rot2.set_sin_func(1.5, 1.5);
222
223         inner_sph = new ObjSphere(inner_sz, 4);
224         mat = inner_sph->get_material_ptr();
225         mat->set_texture(get_texture("data/img/volcano.jpg"), TEXTYPE_DIFFUSE);
226         inner_sph->add_controller(rot1, CTRL_ROTATION);
227         inner_sph->add_controller(rot2, CTRL_ROTATION);
228         //scene->add_object(obj);
229
230         for(int i=0; i<sph_count; i++) {
231                 float t = (float)i / (float)sph_count;
232                 vol_sph[i] = new ObjSphere(inner_sz + (outer_sz - inner_sz) * t, 3);
233                 mat = vol_sph[i]->get_material_ptr();
234                 mat->set_texture(get_texture("data/img/cracks.jpg"), TEXTYPE_DIFFUSE);
235                 mat->alpha = vol_alpha[i] = 1.0 - t;
236                 mat->emissive_color = 1.0;
237                 vol_sph[i]->set_handle_blending(false);
238                 vol_sph[i]->set_blending_mode(BLEND_SRC_ALPHA, BLEND_ONE);
239                 vol_sph[i]->set_blending(true);
240                 vol_sph[i]->add_controller(rot1, CTRL_ROTATION);
241                 vol_sph[i]->add_controller(rot2, CTRL_ROTATION);
242                 vol_sph[i]->set_zwrite(false);
243                 //scene->add_object(obj);
244         }
245 }
246
247 static void render_vol(unsigned long time) {
248         static const float leave_time = 34.0;
249         
250         float t = (float)time / 1000.0;
251         if(t < pexpl_full_time) return;
252
253         float sp = (t - pexpl_full_time) / (pstop_time - pexpl_full_time);
254         if(t > pstop_time) sp = 1.0;
255
256         // update
257         inner_sph->get_material_ptr()->alpha = sp;
258         for(int i=0; i<sph_count + 1; i++) {
259                 Object *obj = i < sph_count ? vol_sph[i] : inner_sph;
260
261                 obj->set_scaling(Vector3(sp, sp, sp));
262                 if(i < sph_count) obj->get_material_ptr()->alpha = vol_alpha[i] * sp;
263
264                 if(t > leave_time) {
265                         float lt = t - leave_time;
266                         obj->set_position(Vector3(0, pow(lt * 5.0, 2.0), 0));
267                 }
268         }
269         
270         // render
271         set_front_face(ORDER_CCW);
272         set_zbuffering(false);
273         for(int i=0; i<sph_count; i++) {
274                 vol_sph[i]->render(time);
275         }
276         set_zbuffering(true);
277         set_front_face(ORDER_CW);
278
279         inner_sph->render(time);
280
281         set_zbuffering(false);
282         for(int i=0; i<sph_count; i++) {
283                 vol_sph[i]->render(time);
284         }
285         set_zbuffering(true);
286 }
287
288 static void render_presents(float t) {
289         static const float pres_start = pexpl_full_time - 0.5;
290         static const Vector2 pres_sz(0.35, 0.12);
291         static const Vector2 hack_sz(0.55, 0.12);
292         
293         t -= pres_start;
294
295         if(t < 0.0 || t > pres_start + 5.0) return;
296
297         float x = pow((t * 0.2) - 1.0, 3.0);
298         Vector2 pres_pos(-x + 0.5, 0.3);
299         Vector2 hack_pos(x + 0.5, 0.7);
300         dsys::overlay(presents, pres_pos - pres_sz / 2.0, pres_pos + pres_sz / 2.0, 1.0);
301         dsys::overlay(summer_hack, hack_pos - hack_sz / 2.0, hack_pos + hack_sz / 2.0, 1.0);
302 }