1 #include "rogueviz.h"
2 
3 // implementation of this demo: https://twitter.com/ZenoRogue/status/1304130700870901761
4 
5 // compile with: ./mymake rogueviz/pentaroll.cpp
6 
7 // ./hyper -canvas-random 10 -noplayer -geo 534h -to-fq 72414D0C -pentaroll 1 -sight3 6 -animperiod 30000 -shot-1000
8 
9 // or -pentaroll 0 if you want to explore yourself
10 
11 namespace hr {
12 
13 namespace pentaroll {
14 
15 void animate();
16 
create_pentaroll(bool animated)17 void create_pentaroll(bool animated) {
18   start_game();
19   /* get the list of all close cells */
20   cell *c0 = currentmap->gamestart();
21   celllister cl(c0, 4, 1000, nullptr);
22 
23   /* construct the relative matrices for them */
24   map<cell*, transmatrix> rel;
25   rel[c0] = Id;
26   for(cell *c: cl.lst)
27     for(int i=0; i<c->type; i++)
28       if(rel.count(c->move(i)))
29         rel[c] = rel[c->move(i)] * currentmap->iadj(c, i);
30 
31   /* the construction */
32   for(cell *c: cl.lst) {
33     int common = 0;
34     for(auto& v: currentmap->get_cellshape(c).vertices_only_local)
35     for(auto& w: currentmap->get_cellshape(c).vertices_only_local)
36       if(hdist(v, rel[c] * w) < 1e-6)
37         common++;
38 
39     setdist(c, 7, nullptr);
40 
41     if(c == c0) c->wall = waPalace;
42     else if(common > 0) c->wall = waNone;
43     }
44 
45   c0->wall = waNone;
46   for(int i=1; i<=cgi.face; i++) {
47     int i0 = i;
48     if(cgi.face == 4 && i0 >= 3) i0++;
49     cellwalker cw(c0, i0);
50     cw.peek()->wall = waPlatform;
51     if(cgi.face == 5)  {
52       cellwalker cw1 = currentmap->strafe(cw, (i==1?cgi.face:i-1));
53       cw1.peek()->wall = waWaxWall;
54       cw1.peek()->landparam = hrand(0x1000000) | 0x808080;
55       }
56     }
57   if(animated)
58     rogueviz::rv_hook(anims::hooks_anim, 100, animate);
59   }
60 
61 /* currently not configurable */
62 
63 /* if <1, stay closer to the center */
64 ld how_far = 1;
65 ld orig_distance = 1;
66 ld far_distance = 1;
67 
animate()68 void animate() {
69 
70   centerover = currentmap->gamestart();
71 
72   ld t = ticks * 20. / anims::period;
73 
74   int tb = int(t) % cgi.face;
75 
76   hyperpoint m;
77   for(int i=0; i<cgi.face; i++) m += cgi.heptshape->vertices_only[i];
78   m /= cgi.face;
79 
80   auto normm = [&] (hyperpoint h) {
81     return normalize(lerp(m, h, how_far));
82     };
83 
84   hyperpoint h1 = normm(cgi.heptshape->vertices_only[tb]);
85   hyperpoint h2 = normm(cgi.heptshape->vertices_only[(tb+1) % cgi.face]);
86   hyperpoint h3 = normm(cgi.heptshape->vertices_only[(tb+2) % cgi.face]);
87 
88   hyperpoint a = gpushxto0(h2) * h1;
89   hyperpoint b = gpushxto0(h2) * h3;
90   b = spintox(a) * b;
91   a = spintox(a) * a;
92   b[3] = 0;
93   println(hlog, "a = ", a);
94   println(hlog, "b = ", b);
95 
96   b /= hypot_d(3, b);
97   ld angle = acos(b[0]);
98 
99   println(hlog, "b = ", b);
100   println(hlog, "angle = ", angle / degree, " deg");
101 
102   ld tf = t - floor(t);
103 
104   /* make it more smooth */
105   tf = tf * tf * (3-2*tf);
106 
107   hyperpoint h = lerp(h1, h2, tf);
108 
109   h = normalize(h);
110 
111   set_view(h, h2, h3);
112 
113   /* set_view does not orient correctly, so we rotate it */
114 
115   View = cspin(2, 0, M_PI/2) * View;
116 
117   /* we move the camera backward */
118 
119   View = zpush(lerp(orig_distance, far_distance, frac(ticks * 1. / anims::period))) * View;
120 
121   /* we also need to rotate the view to make it smooth */
122 
123   View = spin((angle-M_PI) * int(t)) * View;
124 
125   anims::moved();
126   }
127 
__anon2b0f4bf80202null128 auto hooks = arg::add3("-pentaroll", [] { create_pentaroll(arg::shift_argi()); });
129 
130 }
131 
132 }