2019-10-25 10:44:41 +00:00
|
|
|
#include "hyper.h"
|
|
|
|
namespace hr {
|
|
|
|
|
2021-03-30 09:27:48 +00:00
|
|
|
#if MAXMDIM >= 4
|
2020-07-27 16:49:04 +00:00
|
|
|
pair<bool, hyperpoint> makeradar(shiftpoint h) {
|
2022-12-17 22:59:39 +00:00
|
|
|
if(embedded_plane) h.h = current_display->radar_transform * h.h;
|
2019-10-25 10:44:41 +00:00
|
|
|
|
|
|
|
ld d = hdist0(h);
|
|
|
|
|
2020-07-27 16:49:04 +00:00
|
|
|
hyperpoint h1;
|
|
|
|
|
2022-12-17 22:59:39 +00:00
|
|
|
if(sol && nisot::geodesic_movement && !embedded_plane) {
|
2020-07-27 16:49:04 +00:00
|
|
|
hyperpoint h1 = inverse_exp(h, pQUICK);
|
|
|
|
ld r = hypot_d(3, h1);
|
|
|
|
if(r < 1) h1 = h1 * (atanh(r) / r);
|
|
|
|
else return {false, h1};
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
2022-12-08 18:38:06 +00:00
|
|
|
else if(mproduct) h1 = product::inverse_exp(unshift(h));
|
2020-07-28 11:18:28 +00:00
|
|
|
else if(sl2) h1 = slr::get_inverse_exp(h);
|
|
|
|
else h1 = unshift(h);
|
2020-07-27 16:49:04 +00:00
|
|
|
|
2022-12-25 11:14:36 +00:00
|
|
|
if(nisot::local_perspective_used && !embedded_plane) {
|
2022-12-17 22:59:39 +00:00
|
|
|
h1 = NLP * h1;
|
|
|
|
}
|
2019-10-25 10:44:41 +00:00
|
|
|
|
|
|
|
if(WDIM == 3) {
|
2020-07-27 16:49:04 +00:00
|
|
|
if(d >= vid.radarrange) return {false, h1};
|
|
|
|
if(d) h1 = h1 * (d / vid.radarrange / hypot_d(3, h1));
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
2022-12-17 22:59:39 +00:00
|
|
|
else if(mhyperbolic) {
|
2023-01-26 23:27:10 +00:00
|
|
|
if(cgi.emb->is_hyp_in_solnih()) {
|
2022-12-17 22:59:39 +00:00
|
|
|
geom3::light_flip(true);
|
|
|
|
h1 = parabolic1(h1[1]) * xpush0(h1[0]);
|
|
|
|
geom3::light_flip(false);
|
|
|
|
h1[3] = h1[2]; h1[2] = 0;
|
|
|
|
// h1 = current_display->radar_transform * h1;
|
|
|
|
}
|
2022-12-17 23:31:41 +00:00
|
|
|
for(int a=0; a<LDIM; a++) h1[a] = h1[a] / (1 + h1[LDIM]);
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
2022-12-17 22:59:39 +00:00
|
|
|
else if(msphere) {
|
2023-01-26 23:27:10 +00:00
|
|
|
if(cgi.emb->is_same_in_same()) h1[2] = h1[LDIM];
|
|
|
|
if(hyperbolic) h1 /= sinh(1);
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
|
|
|
else {
|
2023-01-26 23:27:10 +00:00
|
|
|
if(cgi.emb->is_euc_in_hyp()) {
|
2022-12-17 22:59:39 +00:00
|
|
|
for(int a=0; a<3; a++) h1[a] = h1[a] / (1 + h1[3]);
|
|
|
|
h1[2] -= 1;
|
|
|
|
h1 *= 2 / sqhypot_d(3, h1);
|
|
|
|
d = hypot_d(2, h1);
|
|
|
|
if(d > vid.radarrange) return {false, h1};
|
|
|
|
if(d) h1 = h1 / (vid.radarrange + cgi.scalefactor/4);
|
|
|
|
}
|
2023-01-26 23:27:10 +00:00
|
|
|
else if(cgi.emb->is_same_in_same()) {
|
2022-12-17 22:59:39 +00:00
|
|
|
if(d > vid.radarrange) return {false, h1};
|
|
|
|
if(d) h1 = h1 * (d / (vid.radarrange + cgi.scalefactor/4) / hypot_d(3, h1));
|
|
|
|
}
|
2023-01-26 23:27:10 +00:00
|
|
|
else if(cgi.emb->is_euc_in_sph()) {
|
2023-01-08 14:48:34 +00:00
|
|
|
h1[0] = atan2(h.h[0], h.h[2]);
|
|
|
|
h1[1] = atan2(h.h[1], h.h[3]);
|
|
|
|
h1[2] = 0;
|
2023-01-26 23:27:10 +00:00
|
|
|
h1 = cgi.emb->intermediate_to_logical * h1;
|
2023-01-08 14:48:34 +00:00
|
|
|
d = hypot_d(2, h1);
|
|
|
|
if(d > vid.radarrange) return {false, h1};
|
|
|
|
if(d) h1 = h1 / (vid.radarrange + cgi.scalefactor/4);
|
|
|
|
}
|
2023-01-26 23:27:10 +00:00
|
|
|
else if(cgi.emb->is_cylinder()) {
|
2023-01-24 14:17:09 +00:00
|
|
|
h1[0] = h.h[0];
|
|
|
|
h1[1] = atan2(h.h[1], h.h[2]);
|
|
|
|
h1[2] = 0;
|
2023-01-26 23:27:10 +00:00
|
|
|
h1 = cgi.emb->intermediate_to_logical * h1;
|
2023-01-24 14:17:09 +00:00
|
|
|
d = hypot_d(2, h1);
|
|
|
|
if(d > vid.radarrange) return {false, h1};
|
|
|
|
if(d) h1 = h1 / (vid.radarrange + cgi.scalefactor/4);
|
|
|
|
}
|
2023-01-26 23:27:10 +00:00
|
|
|
else if(cgi.emb->is_euc_in_sl2()) {
|
|
|
|
h1 = cgi.emb->intermediate_to_logical * esl2_ati(unshift(h)); h1[1] = -h1[1];
|
2023-01-08 14:57:51 +00:00
|
|
|
d = hypot_d(2, h1);
|
|
|
|
if(d > vid.radarrange) return {false, h1};
|
|
|
|
if(d) h1 = h1 / (vid.radarrange + cgi.scalefactor/4);
|
|
|
|
}
|
2023-01-26 23:27:10 +00:00
|
|
|
else if(cgi.emb->is_euc_in_product()) {
|
2023-01-08 14:48:34 +00:00
|
|
|
if(in_h2xe())
|
|
|
|
h1[0] = atanh(h.h[0] / h.h[2]);
|
|
|
|
else
|
|
|
|
h1[0] = atan2(h.h[2], h.h[0]);
|
|
|
|
h1[2] = - zlevel(h.h) - h.shift;
|
|
|
|
h1[1] = 0;
|
|
|
|
h1[3] = 0;
|
2023-01-26 23:27:10 +00:00
|
|
|
h1 = cgi.emb->intermediate_to_logical * h1;
|
2023-01-08 14:48:34 +00:00
|
|
|
d = hypot_d(2, h1);
|
|
|
|
if(d > vid.radarrange) return {false, h1};
|
|
|
|
if(d) h1 = h1 / (vid.radarrange + cgi.scalefactor/4);
|
|
|
|
}
|
2022-12-17 22:59:39 +00:00
|
|
|
else {
|
|
|
|
d = hypot_d(2, h1);
|
|
|
|
if(d > vid.radarrange) return {false, h1};
|
|
|
|
if(d) h1 = h1 / (vid.radarrange + cgi.scalefactor/4);
|
|
|
|
}
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
2020-07-27 16:49:04 +00:00
|
|
|
if(invalid_point(h1)) return {false, h1};
|
|
|
|
return {true, h1};
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 16:49:04 +00:00
|
|
|
EX void addradar(const shiftmatrix& V, char ch, color_t col, color_t outline) {
|
2022-12-17 22:59:39 +00:00
|
|
|
shiftpoint h = V * tile_center();
|
2019-10-25 10:44:41 +00:00
|
|
|
auto hp = makeradar(h);
|
|
|
|
if(hp.first)
|
2022-03-27 18:35:09 +00:00
|
|
|
current_display->radarpoints.emplace_back(radarpoint{hp.second, ch, col, outline});
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 16:49:04 +00:00
|
|
|
EX void addradar(const shiftpoint h1, const shiftpoint h2, color_t col) {
|
2019-10-25 10:44:41 +00:00
|
|
|
auto hp1 = makeradar(h1);
|
|
|
|
auto hp2 = makeradar(h2);
|
|
|
|
if(hp1.first && hp2.first)
|
2022-03-27 18:35:09 +00:00
|
|
|
current_display->radarlines.emplace_back(radarline{hp1.second, hp2.second, col});
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void celldrawer::drawcell_in_radar() {
|
|
|
|
#if CAP_SHMUP
|
|
|
|
if(shmup::on) {
|
|
|
|
pair<shmup::mit, shmup::mit> p =
|
|
|
|
shmup::monstersAt.equal_range(c);
|
|
|
|
for(shmup::mit it = p.first; it != p.second; it++) {
|
|
|
|
shmup::monster* m = it->second;
|
|
|
|
addradar(V*m->at, minf[m->type].glyph, minf[m->type].color, 0xFF0000FF);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if(c->monst)
|
|
|
|
addradar(V, minf[c->monst].glyph, minf[c->monst].color, isFriendly(c->monst) ? 0x00FF00FF : 0xFF0000FF);
|
|
|
|
else if(c->item && !itemHiddenFromSight(c))
|
|
|
|
addradar(V, iinf[c->item].glyph, iinf[c->item].color, kind_outline(c->item));
|
|
|
|
}
|
|
|
|
|
|
|
|
void celldrawer::radar_grid() {
|
|
|
|
for(int t=0; t<c->type; t++)
|
2020-06-03 10:22:50 +00:00
|
|
|
if(c->move(t) && (c->move(t) < c || fake::split()))
|
2019-10-25 10:44:41 +00:00
|
|
|
addradar(V*get_corner_position(c, t%c->type), V*get_corner_position(c, (t+1)%c->type), gridcolor(c, c->move(t)));
|
|
|
|
}
|
2021-03-30 09:27:48 +00:00
|
|
|
#endif
|
2019-10-25 10:44:41 +00:00
|
|
|
|
|
|
|
EX void draw_radar(bool cornermode) {
|
2021-03-30 09:27:48 +00:00
|
|
|
#if MAXMDIM >= 4
|
2022-03-27 18:35:09 +00:00
|
|
|
if(subscreens::split([=] () { calcparam(); draw_radar(false); })) return;
|
2019-10-25 10:44:41 +00:00
|
|
|
if(dual::split([] { dual::in_subscreen([] { calcparam(); draw_radar(false); }); })) return;
|
|
|
|
bool d3 = WDIM == 3;
|
2022-12-18 00:12:28 +00:00
|
|
|
int ldim = LDIM;
|
2022-12-17 23:31:41 +00:00
|
|
|
bool hyp = mhyperbolic;
|
|
|
|
bool sph = msphere;
|
|
|
|
bool scompass = nonisotropic && !mhybrid && !embedded_plane;
|
2019-10-25 10:44:41 +00:00
|
|
|
|
|
|
|
dynamicval<eGeometry> g(geometry, gEuclid);
|
|
|
|
dynamicval<eModel> pm(pmodel, mdDisk);
|
|
|
|
dynamicval<bool> ga(vid.always3, false);
|
|
|
|
dynamicval<geometryinfo1> gi(ginf[gEuclid].g, giEuclid2);
|
|
|
|
initquickqueue();
|
|
|
|
int rad = vid.radarsize;
|
2022-03-27 18:35:09 +00:00
|
|
|
int divby = 1;
|
|
|
|
if(dual::state) divby *= 2;
|
|
|
|
if(subscreens::in) divby *= 2;
|
|
|
|
rad /= divby;
|
|
|
|
auto& cd = current_display;
|
2019-10-25 10:44:41 +00:00
|
|
|
|
2022-03-27 18:35:09 +00:00
|
|
|
ld cx = dual::state ? (dual::currently_loaded ? vid.xres/2+rad+2 : vid.xres/2-rad-2) :
|
|
|
|
subscreens::in ? cd->xtop + cd->xsize - rad - 2 :
|
|
|
|
cornermode ? rad+2 : vid.xres-rad-2;
|
|
|
|
ld cy = subscreens::in ? cd->ytop + cd->ysize - rad - 2 - vid.fsize :
|
|
|
|
vid.yres-rad-2 - vid.fsize;
|
2020-07-27 16:49:04 +00:00
|
|
|
|
|
|
|
auto sId = shiftless(Id);
|
2019-10-25 10:44:41 +00:00
|
|
|
|
|
|
|
for(int i=0; i<360; i++)
|
|
|
|
curvepoint(atscreenpos(cx-cos(i * degree)*rad, cy-sin(i*degree)*rad, 1) * C0);
|
2020-07-27 16:49:04 +00:00
|
|
|
queuecurve(sId, 0xFFFFFFFF, 0x000000FF, PPR::ZERO);
|
2019-10-25 10:44:41 +00:00
|
|
|
|
2022-11-12 21:38:45 +00:00
|
|
|
ld alpha = 15._deg;
|
2019-10-25 10:44:41 +00:00
|
|
|
ld co = cos(alpha);
|
|
|
|
ld si = sin(alpha);
|
|
|
|
|
|
|
|
if(sph && !d3) {
|
|
|
|
for(int i=0; i<360; i++)
|
|
|
|
curvepoint(atscreenpos(cx-cos(i * degree)*rad, cy-sin(i*degree)*rad*si, 1) * C0);
|
2020-07-27 16:49:04 +00:00
|
|
|
queuecurve(sId, 0, 0x200000FF, PPR::ZERO);
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(d3) {
|
|
|
|
for(int i=0; i<360; i++)
|
|
|
|
curvepoint(atscreenpos(cx-cos(i * degree)*rad, cy-sin(i*degree)*rad*si, 1) * C0);
|
2020-07-27 16:49:04 +00:00
|
|
|
queuecurve(sId, 0xFF0000FF, 0x200000FF, PPR::ZERO);
|
2019-10-25 10:44:41 +00:00
|
|
|
|
|
|
|
curvepoint(atscreenpos(cx-sin(vid.fov*degree/2)*rad, cy-sin(vid.fov*degree/2)*rad*si, 1) * C0);
|
|
|
|
curvepoint(atscreenpos(cx, cy, 1) * C0);
|
|
|
|
curvepoint(atscreenpos(cx+sin(vid.fov*degree/2)*rad, cy-sin(vid.fov*degree/2)*rad*si, 1) * C0);
|
2020-07-27 16:49:04 +00:00
|
|
|
queuecurve(sId, 0xFF8000FF, 0, PPR::ZERO);
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
|
|
|
|
2022-03-27 18:35:09 +00:00
|
|
|
if(d3) for(auto& r: cd->radarpoints) {
|
2020-07-27 16:49:04 +00:00
|
|
|
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);
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(scompass) {
|
|
|
|
auto compassdir = [&] (char dirname, hyperpoint h) {
|
2019-11-14 16:20:55 +00:00
|
|
|
h = NLP * h * .8;
|
2020-07-27 16:49:04 +00:00
|
|
|
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);
|
2019-10-25 10:44:41 +00:00
|
|
|
displaychr(int(cx+rad * h[0]), int(cy - rad * h[2] * si + rad * h[1] * co), 0, 8, dirname, 0xA04010);
|
|
|
|
};
|
|
|
|
compassdir('E', point3(+1, 0, 0));
|
|
|
|
compassdir('N', point3(0, +1, 0));
|
|
|
|
compassdir('W', point3(-1, 0, 0));
|
|
|
|
compassdir('S', point3(0, -1, 0));
|
|
|
|
compassdir('U', point3(0, 0,+1));
|
|
|
|
compassdir('D', point3(0, 0,-1));
|
|
|
|
}
|
|
|
|
|
|
|
|
auto locate = [&] (hyperpoint h) {
|
|
|
|
if(sph)
|
|
|
|
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);
|
|
|
|
else if(hyp)
|
2022-12-18 00:12:28 +00:00
|
|
|
return point3(cx + rad * h[0], cy + rad * h[1], 1/(1+h[ldim]) * cgi.scalefactor * current_display->radius / (inHighQual ? 10 : 6));
|
2019-10-25 10:44:41 +00:00
|
|
|
else
|
|
|
|
return point3(cx + rad * h[0], cy + rad * h[1], rad * cgi.scalefactor / (vid.radarrange + cgi.scalefactor/4) * 0.8);
|
|
|
|
};
|
|
|
|
|
2022-03-27 18:35:09 +00:00
|
|
|
for(auto& r: cd->radarlines) {
|
2019-10-25 10:44:41 +00:00
|
|
|
hyperpoint h1 = locate(r.h1);
|
|
|
|
hyperpoint h2 = locate(r.h2);
|
|
|
|
h1 = tC0(atscreenpos(h1[0], h1[1], 1));
|
|
|
|
h2 = tC0(atscreenpos(h2[0], h2[1], 1));
|
2020-07-27 16:49:04 +00:00
|
|
|
queueline(sId*h1, sId*h2, r.line, -1);
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
quickqueue();
|
|
|
|
glflush();
|
|
|
|
|
2022-03-27 18:35:09 +00:00
|
|
|
for(auto& r: cd->radarpoints) {
|
2019-10-25 10:44:41 +00:00
|
|
|
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);
|
|
|
|
else {
|
|
|
|
hyperpoint h = locate(r.h);
|
2022-03-27 18:35:09 +00:00
|
|
|
displaychr(int(h[0]), int(h[1]), 0, int(h[2]) / divby, r.glyph, r.color);
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
|
|
|
}
|
2021-03-30 09:27:48 +00:00
|
|
|
#endif
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|
|
|
|
|
2021-03-30 09:27:48 +00:00
|
|
|
#if MAXMDIM < 4
|
|
|
|
EX void addradar(const shiftmatrix& V, char ch, color_t col, color_t outline) { }
|
|
|
|
void drawcell_in_radar();
|
|
|
|
|
|
|
|
void celldrawer::drawcell_in_radar() {}
|
|
|
|
void celldrawer::radar_grid() {}
|
|
|
|
#endif
|
2019-10-25 10:44:41 +00:00
|
|
|
}
|