added summerhack
[summerhack] / src / parts / temple.cpp
1 #include <cassert>
2 #include "temple.hpp"
3 #include "common/err_msg.h"
4
5 static void make_skycube(Scene *scene);
6 static void make_temple(Scene *scene);
7 static bool make_pillars(Scene *scene);
8 static void make_blobs(Scene *scene);
9
10 static void move_blobs(scalar_t t);
11 static scalar_t eval_func(const Vector3 &vec, scalar_t t);
12 static Vector3 eval_normals(const Vector3 &vec, scalar_t t);
13
14 static const int pillar_udiv = 16;
15
16 ParticleSysParams *pp[4];
17
18 Texture *greets;
19
20 #define BLOB_COUNT      4
21 static scalar_t bint[BLOB_COUNT] = {30, 28, 24, 15};
22 static Vector3 pos[BLOB_COUNT];
23 static ScalarField *sfield;
24 static Object *blob;
25
26 #define BLOBS
27 #define TEMPLE
28 #define EXIBITS
29
30 #define ANIM
31
32 TemplePart::TemplePart() : ScenePart("temple", new Scene) {
33 #ifdef ANIM
34         TargetCamera *cam = new TargetCamera(Vector3(0, 52, 0), Vector3(0, 50, 0));
35 #else
36         TargetCamera *cam = new TargetCamera(Vector3(0, 60, -160), Vector3(0, 50, 0));
37 #endif
38         cam->set_fov(DEG_TO_RAD(50));
39         scene->add_camera(cam);
40
41         PointLight *lt;
42         
43         lt = new PointLight(Vector3(-200, 250, -400));
44         lt->set_intensity(0.9);
45         scene->add_light(lt);
46
47         lt = new PointLight(Vector3(200, 20, 0));
48         lt->set_intensity(0.6);
49         scene->add_light(lt);
50
51         lt = new PointLight(Vector3(20, 500, -400));
52         lt->set_intensity(0.5);
53         scene->add_light(lt);
54
55         scene->set_ambient_light(0.1);
56
57         make_skycube(scene);
58 #ifdef TEMPLE
59         make_temple(scene);
60 #endif
61 #ifdef EXIBITS
62         make_pillars(scene);
63 #endif
64 #ifdef BLOBS
65         make_blobs(scene);
66 #endif
67         
68         MotionController ctrl;
69
70 #ifdef ANIM
71         ctrl = MotionController(CTRL_COS, TIME_FREE);
72         ctrl.set_sin_func(0.58, 250);
73         ctrl.set_control_axis(CTRL_X);
74         cam->add_controller(ctrl, CTRL_TRANSLATION);
75
76         ctrl = MotionController(CTRL_SIN, TIME_FREE);
77         ctrl.set_sin_func(1.17, 125);
78         ctrl.set_control_axis(CTRL_X);
79         cam->add_controller(ctrl, CTRL_TRANSLATION);
80
81         ctrl = MotionController(CTRL_SIN, TIME_FREE);
82         ctrl.set_sin_func(0.49, 220);
83         ctrl.set_control_axis(CTRL_Z);
84         cam->add_controller(ctrl, CTRL_TRANSLATION);
85
86         ctrl = MotionController(CTRL_COS, TIME_FREE);
87         ctrl.set_sin_func(0.99, 105);
88         ctrl.set_control_axis(CTRL_Z);
89         cam->add_controller(ctrl, CTRL_TRANSLATION);
90
91         ctrl = MotionController(CTRL_SIN, TIME_FREE);
92         ctrl.set_sin_func(0.45, 50);
93         ctrl.set_control_axis(CTRL_Y);
94         cam->add_controller(ctrl, CTRL_TRANSLATION);
95 #endif
96
97         greets = get_texture("data/img/greets.png");
98
99         scene->set_background(0.5);
100
101         // in order to precalculate the cubemaps...
102         scene->render(0);
103
104         //scene->render_sequence(0, 15000, 25);
105         //exit(0);
106 }
107
108 TemplePart::~TemplePart() {}
109
110 static void make_skycube(Scene *scene) {
111         const float size = 5000;
112         Object *face[6];
113         Texture *tex[6];
114
115         face[0] = new ObjPlane(Vector3(0, -1, 0), Vector2(size, size), 0);
116         face[0]->translate(Vector3(0, size / 2, 0));
117         tex[0] = get_texture("data/img/py.jpg");
118         
119         face[1] = new ObjPlane(Vector3(0, 1, 0), Vector2(size, size), 0);
120         face[1]->translate(Vector3(0, -size / 2, 0));
121         tex[1] = get_texture("data/img/ny.jpg");
122
123         face[2] = new ObjPlane(Vector3(0, 0, -1), Vector2(size, size), 0);
124         face[2]->translate(Vector3(0, 0, size / 2));
125         tex[2] = get_texture("data/img/pz.jpg");
126         
127         face[3] = new ObjPlane(Vector3(0, 0, 1), Vector2(size, size), 0);
128         face[3]->translate(Vector3(0, 0, -size / 2));
129         tex[3] = get_texture("data/img/nz.jpg");
130
131         face[4] = new ObjPlane(Vector3(-1, 0, 0), Vector2(size, size), 0);
132         face[4]->translate(Vector3(size / 2, 0, 0));
133         tex[4] = get_texture("data/img/px.jpg");
134         
135         face[5] = new ObjPlane(Vector3(1, 0, 0), Vector2(size, size), 0);
136         face[5]->translate(Vector3(-size / 2, 0, 0));
137         tex[5] = get_texture("data/img/nx.jpg");
138
139         for(int i=0; i<6; i++) {
140                 Material *mat = face[i]->get_material_ptr();
141                 mat->emissive_color = 1.0;
142                 add_texture(tex[i]);
143                 mat->set_texture(tex[i], TEXTYPE_DIFFUSE);
144                 face[i]->set_texture_addressing(TEXADDR_CLAMP);
145                 scene->add_object(face[i]);
146         }
147 }
148
149 void make_temple(Scene *scene) {
150         const Vector3 pillar_body[] = {
151                 Vector3(8, 4, 0),
152                 Vector3(12, 40, 0),
153                 Vector3(11, 70, 0),
154                 Vector3(4, 106, 0)
155         };
156
157         const Vector3 pillar_pos[] = {
158                 Vector3(-50, 0, -50),
159                 Vector3(-50, 0, 50),
160                 Vector3(50, 0, 50),
161                 Vector3(50, 0, -50)
162         };
163
164
165         TriMesh pillar_mesh;
166         create_revolution(&pillar_mesh, pillar_body, 4, pillar_udiv, 10);
167
168         Material pillar_mat;
169         pillar_mat.specular_color = 1.0;
170         pillar_mat.specular_power = 70.0;
171         pillar_mat.set_texture(get_texture("data/img/benedeti.jpg"), TEXTYPE_DIFFUSE);
172
173         for(int i=0; i<4; i++) {
174                 Object *obj = new Object;
175                 obj->get_mesh() = pillar_mesh;
176                 obj->set_position(pillar_pos[i]);
177                 *obj->get_material_ptr() = pillar_mat;
178                 scene->add_object(obj);
179
180                 obj = new ObjCylinder(13.0, 5.0, true, pillar_udiv);
181                 obj->set_position(pillar_pos[i] + Vector3(0, 6, 0));
182                 *obj->get_material_ptr() = pillar_mat;
183                 scene->add_object(obj);
184                 
185                 obj = new ObjCylinder(16.0, 5.0, true, pillar_udiv);
186                 obj->set_position(pillar_pos[i] + Vector3(0, 2, 0));
187                 *obj->get_material_ptr() = pillar_mat;
188                 scene->add_object(obj);
189
190                 obj = new ObjTorus(2.0, 5.0);
191                 obj->set_position(pillar_pos[i] + Vector3(0, 102, 0));
192                 *obj->get_material_ptr() = pillar_mat;
193                 scene->add_object(obj);
194
195                 obj = new ObjTorus(2.0, 7);
196                 obj->set_position(pillar_pos[i] + Vector3(0, 105, 0));
197                 *obj->get_material_ptr() = pillar_mat;
198                 scene->add_object(obj);
199         }
200
201
202         // floor
203         Object *obj = new ObjCylinder(95.0, 5, true, 25);
204         obj->set_position(Vector3(0, -2.5, 0));
205         obj->get_material_ptr()->set_texture(get_texture("data/img/brick1_base1.jpg"), TEXTYPE_DIFFUSE);
206         scene->add_object(obj);
207
208         obj = new ObjCylinder(103.0, 5, true, 25);
209         obj->set_position(Vector3(0, -7.5, 0));
210         obj->get_material_ptr()->set_texture(get_texture("data/img/brick1_base1.jpg"), TEXTYPE_DIFFUSE);
211         scene->add_object(obj);
212
213         // ceiling
214         const Vector3 ceil[] = {
215                 Vector3(90, 0, 0),
216                 Vector3(92, 4, 0),
217                 Vector3(98, 14, 0),
218                 Vector3(95, 20, 0),
219                 Vector3(60, 40, 0),
220                 Vector3(20, 60, 0),
221                 Vector3(18, 64, 0),
222                 Vector3(23, 66, 0),
223                 Vector3(26, 67, 0),
224                 Vector3(25, 70, 0),
225                 Vector3(10, 78, 0),
226                 Vector3(4, 84, 0),
227                 Vector3(2, 90, 0),
228                 Vector3(0.1, 100, 0)
229         };
230
231         obj = new Object;
232         create_revolution(obj->get_mesh_ptr(), ceil, 14, 24, 28);
233         obj->set_pivot(Vector3(0, 40, 0));
234         obj->set_position(Vector3(0, 110, 0));
235         obj->calculate_normals();
236
237         Texture *cubemap = new Texture(64, 64, TEX_CUBE);
238         add_texture(cubemap);
239
240         Material *mat = obj->get_material_ptr();
241         mat->diffuse_color = mat->ambient_color = int_color(239, 190, 37) * 0.8;
242         mat->specular_color = int_color(255, 198, 43);
243         mat->specular_power = 40.0;
244         mat->set_texture(get_texture("data/img/brick1_base1.jpg"), TEXTYPE_DIFFUSE);
245         mat->set_texture(cubemap, TEXTYPE_ENVMAP);
246         mat->auto_refl = false;
247         mat->env_intensity = 0.3;
248         scene->add_object(obj);
249
250         obj = new ObjCylinder(94, 5, true, 25);
251         obj->set_position(Vector3(0, 107.5, 0));
252         *obj->get_material_ptr() = *mat;
253         scene->add_object(obj);
254
255         // sting
256         const Vector3 sting[] = {
257                 Vector3(12, 0, 0),
258                 Vector3(9, 4, 0),
259                 Vector3(5, 6, 0),
260                 Vector3(2, 10, 0),
261                 Vector3(0.01, 34, 0)
262         };
263
264         cubemap = new Texture(16, 16, TEX_CUBE);
265         add_texture(cubemap);
266
267         obj = new Object;
268         create_revolution(obj->get_mesh_ptr(), sting, 5, 10, 10);
269         obj->set_pivot(Vector3(0, 5, 0));
270         mat = obj->get_material_ptr();
271         mat->diffuse_color = mat->ambient_color = 0.1;
272         mat->specular_color = 1.0;
273         mat->specular_power = 80.0;
274         mat->set_texture(cubemap, TEXTYPE_ENVMAP);
275         mat->auto_refl = false;
276         scene->add_object(obj);
277
278
279         // floor-floor
280         obj = new ObjPlane(Vector3(0, 1, 0), Vector2(1200, 1200), 6);
281         obj->set_position(Vector3(0, -10, 0));
282         mat = obj->get_material_ptr();
283         mat->set_texture(get_texture("data/img/mud.jpg"), TEXTYPE_DIFFUSE);
284         mat->tmat[TEXTYPE_DIFFUSE].set_scaling(Vector3(4.0, 4.0, 4.0));
285         scene->add_object(obj);
286 }
287
288 static bool make_pillars(Scene *scene) {
289         static const Vector3 ppos[] = {
290                 Vector3(-150, -7.5, 0),
291                 Vector3(0, -7.5, 150),
292                 Vector3(150, -7.5, 0),
293                 Vector3(0, -7.5, -150)
294         };
295
296         static const char *label_tex[] = {
297                 "data/img/label_dolphin.png",
298                 "data/img/label_duck.png",
299                 "data/img/label_face.png",
300                 "data/img/label_teapot.png",
301                 0
302         };
303         
304         Curve *curve = load_curve("data/pillar.curve");
305
306         for(int i=0; i<4; i++) {
307                 char name[128];
308                 sprintf(name, "pillar%02d", i);
309                 
310                 Object *obj = new Object;
311                 obj->name = name;
312                 Material *mat = obj->get_material_ptr();
313                 create_revolution(obj->get_mesh_ptr(), *curve, pillar_udiv, 10);
314                 obj->set_scaling(Vector3(2.3, 1.8, 2.3));
315                 obj->apply_xform();
316                 obj->normalize_normals();
317                 obj->set_position(ppos[i]);
318
319                 mat->specular_color = 1.0;
320                 mat->specular_power = 70.0;
321                 mat->set_texture(get_texture("data/img/benedeti.jpg"), TEXTYPE_DIFFUSE);
322                 scene->add_object(obj);
323
324                 obj = new ObjCylinder(14.0, 3.0);
325                 obj->set_position(ppos[i]);
326                 mat = obj->get_material_ptr();
327                 mat->specular_color = 1.0;
328                 mat->specular_power = 70.0;
329                 mat->set_texture(get_texture("data/img/benedeti.jpg"), TEXTYPE_DIFFUSE);
330                 scene->add_object(obj);
331
332
333                 Texture *cubemap = new Texture(64, 64, TEX_CUBE);
334                 add_texture(cubemap);
335                 
336                 // put exibit
337                 switch(i) {
338                 case 1:
339                         {
340                                 Scene *scene = load_scene("data/geom/duck.3ds");
341                                 if(!scene) {
342                                         error("failed to load duck.3ds");
343                                         return false;
344                                 }
345                                 obj = scene->get_object("Object03");
346                                 assert(obj);
347                                 scene->remove_object(obj);
348                                 delete scene;
349
350                                 obj->set_scaling(Vector3(0.009, 0.009, 0.009));
351                                 obj->set_auto_normalize(true);
352                         
353                                 obj->set_position(ppos[i] + Vector3(0, 50, 0));
354                                 obj->set_rotation(Vector3(0, quarter_pi, 0));
355                         }
356                         break;
357
358                 case 2:
359                         {
360                                 Scene *scene = load_scene("data/geom/chrmface.3ds");
361                                 if(!scene) {
362                                         error("failed to load chrmface.3ds");
363                                         return false;
364                                 }
365                                 obj = scene->get_object("0main01");
366                                 assert(obj);
367                                 scene->remove_object(obj);
368                                 delete scene;
369
370                                 obj->set_scaling(Vector3(0.2, 0.2, 0.2));
371                                 obj->set_auto_normalize(true);
372
373                                 obj->set_position(ppos[i] + Vector3(4, 58, 0));                         
374                                 obj->set_rotation(Vector3(0, half_pi, 0));
375
376                                 obj->get_material_ptr()->two_sided = true;
377                         }
378                         break;
379
380                 case 0:
381                         {
382                                 Scene *scene = load_scene("data/geom/dolphin.3ds");
383                                 if(!scene) {
384                                         error("failed to load dolphin.3ds");
385                                         return false;
386                                 }
387                                 obj = scene->get_object("Loft01");
388                                 assert(obj);
389                                 scene->remove_object(obj);
390                                 delete scene;
391
392                                 obj->set_scaling(Vector3(0.14, 0.14, 0.14));
393                                 obj->set_auto_normalize(true);
394
395                                 obj->set_position(ppos[i] + Vector3(0, 48, 0));
396                                 obj->set_rotation(Vector3(half_pi, half_pi, 0));
397                         }
398                         break;
399                 
400                 case 3:
401                 default:
402                         obj = new ObjTeapot(6.0);
403                         obj->set_position(ppos[i] + Vector3(0, 43.7, 0));
404                         break;
405                 }
406
407                 mat = obj->get_material_ptr();
408                 mat->diffuse_color = mat->ambient_color = 0.1;
409                 mat->specular_color = 1.0;
410                 mat->specular_power = 80.0;
411                 mat->set_texture(cubemap, TEXTYPE_ENVMAP);
412                 mat->auto_refl = false;
413                 
414                 MotionController ctrl(CTRL_SIN, TIME_FREE);
415                 ctrl.set_control_axis(CTRL_Y);
416                 ctrl.set_sin_func(frand(0.5) + 2.3, 3.0, frand(pi));
417                 obj->add_controller(ctrl, CTRL_TRANSLATION);
418                 obj->translate(Vector3(0, 3.0, 0));
419                 scene->add_object(obj);
420
421                 ParticleSystem *label = new ParticleSystem("data/exibit.psys");
422                 pp[i] = label->get_params();
423                 pp[i]->halo = get_texture(label_tex[i]);
424                 label->set_position(ppos[i] + Vector3(0, 80, 0));
425                 scene->add_particle_sys(label);
426
427                 ParticleSystem *trail = new ParticleSystem("data/test2.psys");
428                 trail->set_position(ppos[i] + Vector3(0, 50, 0));
429
430                 ctrl = MotionController(CTRL_SIN, TIME_FREE);
431                 ctrl.set_control_axis(CTRL_X);
432                 ctrl.set_sin_func(5.0, 30.0, (float)i * half_pi);
433                 trail->add_controller(ctrl, CTRL_TRANSLATION);
434
435                 ctrl = MotionController(CTRL_COS, TIME_FREE);
436                 ctrl.set_control_axis(CTRL_Z);
437                 ctrl.set_sin_func(5.0, 30.0, (float)i * half_pi);
438                 trail->add_controller(ctrl, CTRL_TRANSLATION);
439
440                 ctrl = MotionController(CTRL_SIN, TIME_FREE);
441                 ctrl.set_control_axis(CTRL_Y);
442                 ctrl.set_sin_func(1.8, 25.0, (float)i * half_pi);
443                 trail->add_controller(ctrl, CTRL_TRANSLATION);
444                 
445                 scene->add_particle_sys(trail);
446         }
447
448         delete curve;
449         return true;
450 }
451
452 #define MIN(a, b)       ((a) < (b) ? (a) : (b))
453 #define MAX(a, b)       ((a) > (b) ? (a) : (b))
454
455 void TemplePart::draw_part() {
456         static const float greets_time = 18.0;
457         float t = (float)time / 1000.0f;
458
459 #ifdef EXIBITS
460         float yoffs = MIN(150.0, t * 25.0);
461         for(int i=0; i<4; i++) {
462                 pp[i]->spawn_offset = FuzzyVec3(0.0, yoffs, 0.0);
463         }
464 #endif
465
466 #ifdef BLOBS
467         move_blobs(t);
468         sfield->triangulate(blob->get_mesh_ptr(), 1.0, t, true);
469 #endif
470
471         scene->render(time);
472
473         if(t > greets_time) {
474                 t *= 1.8;
475
476                 float a2 = sin(t);
477         a2 = a2 > 0 ? -a2 : a2;
478         a2 += 1.0f;
479         a2 *= frand(0.8) + 0.2;
480
481         float a1 = a2;//(cos(t)+1)/2;
482         a1 *= (sin(t / 2.0) > 0) ? 1.0 : 0.0;     // modulate with step func
483         a1 *= sin(t / 2.0);
484
485                 Color col(1.0, 1.0, 1.0, MAX(a2, a1) + 0.4);
486         
487                 set_matrix(XFORM_TEXTURE, Matrix4x4::identity_matrix);
488                 load_xform_matrices();
489
490                 for(int i=0; i<10; i++) {
491                         set_alpha_blending(true);
492                         set_blend_func(BLEND_SRC_ALPHA, BLEND_ONE);
493                         float off = (float)i * 0.0025;
494                         col.a *= 0.8;
495                         dsys::overlay(greets, Vector2(-off, -off), Vector2(1 + off, 1 + off), col, 0, false);
496                         set_alpha_blending(false);
497                 }
498         }
499 }
500
501 static void move_blobs(scalar_t t) {
502         Vector3 offs = Vector3(0, 2.75 * cos(t*1.5) + 2.25, 0);
503         pos[0] = offs + Vector3(sin(t), cos(t), 0) * 8.0;
504         pos[1] = offs + Vector3(sin(t*2) + cos(t*4)/2, sin(t*1.5), cos(t)) * 8.0;
505         pos[2] = offs + Vector3(cos(t*1.8)/2 + sin(t)/4, cos(t*2) + sin(t), sin(t*1.3)) * 8.0;
506         pos[3] = offs + Vector3(sin(t*1.2)/3 + cos(t*1.8)/3.5, sin(cos(t*2) + t)*1.5, cos(t*2.0)/2) * 7.0;
507
508         //cyl = Vector2(cos(t), sin(t*2.0)) * 8.0;
509 }
510
511 static scalar_t eval_func(const Vector3 &vec, scalar_t t) {
512         scalar_t val = 0.0;
513         for(int i=0; i<BLOB_COUNT; i++) {
514                 val += (bint[i] * 0.75) / (vec - pos[i]).length_sq();
515         }
516
517         return val;
518 }
519
520 //#define NORMAL_GRAD
521 static Vector3 eval_normals(const Vector3 &vec, scalar_t t) {
522 #ifdef NORMAL_GRAD
523         const scalar_t diff = 0.1;
524
525         Vector3 grad;
526         grad.x = eval_func(vec + Vector3(diff, 0, 0), t) - eval_func(vec + Vector3(-diff, 0, 0), t);
527         grad.y = eval_func(vec + Vector3(0, diff, 0), t) - eval_func(vec + Vector3(0, -diff, 0), t);
528         grad.z = eval_func(vec + Vector3(0, 0, diff), t) - eval_func(vec + Vector3(0, 0, -diff), t);
529
530         return -grad.normalized();
531 #else
532         Vector3 normal(0, 0, 0);
533         for(int i=0; i<BLOB_COUNT; i++) {
534                 scalar_t len_sq = (vec - pos[i]).length_sq();
535                 scalar_t len_quad = len_sq * len_sq;
536                 normal += (vec - pos[i]) * 2.0 * bint[i] / len_quad;
537         }
538
539         return normal.normalized();
540 #endif
541 }
542
543
544 static void make_blobs(Scene *scene) {
545         // scalar field
546         const int grid = 23;
547         const scalar_t field_size = 40.0;
548         const scalar_t hsz = field_size / 2.0;
549
550         sfield = new ScalarField(grid, Vector3(-hsz, -hsz, -hsz), Vector3(hsz, hsz, hsz));
551         sfield->set_evaluator(eval_func);
552         sfield->set_normal_evaluator(eval_normals);
553         
554         // rendering details
555         Texture *cubemap = new Texture(64, 64, TEX_CUBE);
556         add_texture(cubemap);
557
558         blob = new Object;
559         blob->name = "blob";
560         blob->set_dynamic(true);
561         blob->set_position(Vector3(0, 50, 0));
562         blob->set_scaling(Vector3(2.8, 2.6, 2.8));
563         blob->set_auto_normalize(true);
564
565         Material *mat = blob->get_material_ptr();
566         mat->ambient_color = mat->diffuse_color = Color(0.7, 0.4, 0.2) * 0.4;
567         mat->specular_color = Color(0.9, 0.7, 0.6);
568         mat->specular_power = 60.0;
569         mat->set_texture(cubemap, TEXTYPE_ENVMAP);
570         mat->env_intensity = 0.6;
571         mat->auto_refl = false;
572         mat->two_sided = true;
573
574         scene->add_object(blob);
575 }