1 #include "hyper.h"
2 namespace hr {
3 
4 #if HDR
5 struct radarpoint {
6   hyperpoint h;
7   char glyph;
8   color_t color;
9   color_t line;
10   };
11 
12 struct radarline {
13   hyperpoint h1, h2;
14   color_t line;
15   };
16 #endif
17 
18 EX vector<radarpoint> radarpoints;
19 EX vector<radarline> radarlines;
20 
21 EX transmatrix radar_transform;
22 
23 #if MAXMDIM >= 4
makeradar(shiftpoint h)24 pair<bool, hyperpoint> makeradar(shiftpoint h) {
25   if(GDIM == 3 && WDIM == 2) h.h = radar_transform * h.h;
26 
27   ld d = hdist0(h);
28 
29   hyperpoint h1;
30 
31   if(sol && nisot::geodesic_movement) {
32     hyperpoint h1 = inverse_exp(h, pQUICK);
33     ld r = hypot_d(3, h1);
34     if(r < 1) h1 = h1 * (atanh(r) / r);
35     else return {false, h1};
36     }
37   else if(prod) h1 = product::inverse_exp(unshift(h));
38   else if(sl2) h1 = slr::get_inverse_exp(h);
39   else h1 = unshift(h);
40 
41   if(nisot::local_perspective_used()) h1 = NLP * h1;
42 
43   if(WDIM == 3) {
44     if(d >= vid.radarrange) return {false, h1};
45     if(d) h1 = h1 * (d / vid.radarrange / hypot_d(3, h1));
46     }
47   else if(hyperbolic) {
48     for(int a=0; a<3; a++) h1[a] = h1[a] / (1 + h[3]);
49     }
50   else if(sphere) {
51     h1[2] = h1[3];
52     }
53   else {
54     if(d > vid.radarrange) return {false, h1};
55     if(d) h1 = h1 * (d / (vid.radarrange + cgi.scalefactor/4) / hypot_d(3, h1));
56     }
57   if(invalid_point(h1)) return {false, h1};
58   return {true, h1};
59   }
60 
addradar(const shiftmatrix & V,char ch,color_t col,color_t outline)61 EX void addradar(const shiftmatrix& V, char ch, color_t col, color_t outline) {
62   shiftpoint h = tC0(V);
63   auto hp = makeradar(h);
64   if(hp.first)
65     radarpoints.emplace_back(radarpoint{hp.second, ch, col, outline});
66   }
67 
addradar(const shiftpoint h1,const shiftpoint h2,color_t col)68 EX void addradar(const shiftpoint h1, const shiftpoint h2, color_t col) {
69   auto hp1 = makeradar(h1);
70   auto hp2 = makeradar(h2);
71   if(hp1.first && hp2.first)
72     radarlines.emplace_back(radarline{hp1.second, hp2.second, col});
73   }
74 
drawcell_in_radar()75 void celldrawer::drawcell_in_radar() {
76   #if CAP_SHMUP
77   if(shmup::on) {
78     pair<shmup::mit, shmup::mit> p =
79       shmup::monstersAt.equal_range(c);
80     for(shmup::mit it = p.first; it != p.second; it++) {
81       shmup::monster* m = it->second;
82       addradar(V*m->at, minf[m->type].glyph, minf[m->type].color, 0xFF0000FF);
83       }
84     }
85   #endif
86   if(c->monst)
87     addradar(V, minf[c->monst].glyph, minf[c->monst].color, isFriendly(c->monst) ? 0x00FF00FF : 0xFF0000FF);
88   else if(c->item && !itemHiddenFromSight(c))
89     addradar(V, iinf[c->item].glyph, iinf[c->item].color, kind_outline(c->item));
90   }
91 
radar_grid()92 void celldrawer::radar_grid() {
93   for(int t=0; t<c->type; t++)
94     if(c->move(t) && (c->move(t) < c || fake::split()))
95       addradar(V*get_corner_position(c, t%c->type), V*get_corner_position(c, (t+1)%c->type), gridcolor(c, c->move(t)));
96   }
97 #endif
98 
draw_radar(bool cornermode)99 EX void draw_radar(bool cornermode) {
100 #if MAXMDIM >= 4
101   if(dual::split([] { dual::in_subscreen([] { calcparam(); draw_radar(false); }); })) return;
102   bool d3 = WDIM == 3;
103   bool hyp = hyperbolic;
104   bool sph = sphere;
105   bool scompass = nonisotropic && !hybri;
106 
107   dynamicval<eGeometry> g(geometry, gEuclid);
108   dynamicval<eModel> pm(pmodel, mdDisk);
109   dynamicval<bool> ga(vid.always3, false);
110   dynamicval<geometryinfo1> gi(ginf[gEuclid].g, giEuclid2);
111   initquickqueue();
112   int rad = vid.radarsize;
113   if(dual::state) rad /= 2;
114 
115   ld cx = dual::state ? (dual::currently_loaded ? vid.xres/2+rad+2 : vid.xres/2-rad-2) : cornermode ? rad+2 : vid.xres-rad-2;
116   ld cy = vid.yres-rad-2 - vid.fsize;
117 
118   auto sId = shiftless(Id);
119 
120   for(int i=0; i<360; i++)
121     curvepoint(atscreenpos(cx-cos(i * degree)*rad, cy-sin(i*degree)*rad, 1) * C0);
122   queuecurve(sId, 0xFFFFFFFF, 0x000000FF, PPR::ZERO);
123 
124   ld alpha = 15 * degree;
125   ld co = cos(alpha);
126   ld si = sin(alpha);
127 
128   if(sph && !d3) {
129     for(int i=0; i<360; i++)
130       curvepoint(atscreenpos(cx-cos(i * degree)*rad, cy-sin(i*degree)*rad*si, 1) * C0);
131     queuecurve(sId, 0, 0x200000FF, PPR::ZERO);
132     }
133 
134   if(d3) {
135     for(int i=0; i<360; i++)
136       curvepoint(atscreenpos(cx-cos(i * degree)*rad, cy-sin(i*degree)*rad*si, 1) * C0);
137     queuecurve(sId, 0xFF0000FF, 0x200000FF, PPR::ZERO);
138 
139     curvepoint(atscreenpos(cx-sin(vid.fov*degree/2)*rad, cy-sin(vid.fov*degree/2)*rad*si, 1) * C0);
140     curvepoint(atscreenpos(cx, cy, 1) * C0);
141     curvepoint(atscreenpos(cx+sin(vid.fov*degree/2)*rad, cy-sin(vid.fov*degree/2)*rad*si, 1) * C0);
142     queuecurve(sId, 0xFF8000FF, 0, PPR::ZERO);
143     }
144 
145   if(d3) for(auto& r: radarpoints) {
146     queueline(sId*atscreenpos(cx+rad * r.h[0], cy - rad * r.h[2] * si + rad * r.h[1] * co, 0)*C0, sId*atscreenpos(cx+rad*r.h[0], cy - rad*r.h[2] * si, 0)*C0, r.line, -1);
147     }
148 
149   if(scompass) {
150     auto compassdir = [&] (char dirname, hyperpoint h) {
151       h = NLP * h * .8;
152       queueline(sId*atscreenpos(cx+rad * h[0], cy - rad * h[2] * si + rad * h[1] * co, 0)*C0, sId*atscreenpos(cx+rad*h[0], cy - rad*h[2] * si, 0)*C0, 0xA0401040, -1);
153       displaychr(int(cx+rad * h[0]), int(cy - rad * h[2] * si + rad * h[1] * co), 0, 8, dirname, 0xA04010);
154       };
155     compassdir('E', point3(+1, 0, 0));
156     compassdir('N', point3(0, +1, 0));
157     compassdir('W', point3(-1, 0, 0));
158     compassdir('S', point3(0, -1, 0));
159     compassdir('U', point3(0,  0,+1));
160     compassdir('D', point3(0,  0,-1));
161     }
162 
163   auto locate = [&] (hyperpoint h) {
164     if(sph)
165       return point3(cx + (rad-10) * h[0], cy + (rad-10) * h[2] * si + (rad-10) * h[1] * co, +h[1] * si > h[2] * co ? 8 : 16);
166     else if(hyp)
167       return point3(cx + rad * h[0], cy + rad * h[1], 1/(1+h[3]) * cgi.scalefactor * current_display->radius / (inHighQual ? 10 : 6));
168     else
169       return point3(cx + rad * h[0], cy + rad * h[1], rad * cgi.scalefactor / (vid.radarrange + cgi.scalefactor/4) * 0.8);
170     };
171 
172   for(auto& r: radarlines) {
173     hyperpoint h1 = locate(r.h1);
174     hyperpoint h2 = locate(r.h2);
175     h1 = tC0(atscreenpos(h1[0], h1[1], 1));
176     h2 = tC0(atscreenpos(h2[0], h2[1], 1));
177     queueline(sId*h1, sId*h2, r.line, -1);
178     }
179 
180   quickqueue();
181   glflush();
182 
183   for(auto& r: radarpoints) {
184     if(d3) displaychr(int(cx + rad * r.h[0]), int(cy - rad * r.h[2] * si + rad * r.h[1] * co), 0, 8, r.glyph, r.color);
185     else {
186       hyperpoint h = locate(r.h);
187       displaychr(int(h[0]), int(h[1]), 0, int(h[2]), r.glyph, r.color);
188       }
189     }
190 #endif
191   }
192 
193 #if MAXMDIM < 4
addradar(const shiftmatrix & V,char ch,color_t col,color_t outline)194 EX void addradar(const shiftmatrix& V, char ch, color_t col, color_t outline) { }
195   void drawcell_in_radar();
196 
drawcell_in_radar()197 void celldrawer::drawcell_in_radar() {}
radar_grid()198 void celldrawer::radar_grid() {}
199 #endif
200 }
201