rots:: show the underlying geometry

This commit is contained in:
Zeno Rogue 2019-09-09 15:31:49 +02:00
parent e600c0af0a
commit f8963a1c75
4 changed files with 124 additions and 5 deletions

View File

@ -709,7 +709,24 @@ EX void showEuclideanMenu() {
});
}
if(euwrap || geometry == gFieldQuotient || cryst || archimedean || (euclid && WDIM == 3)) {
else if(geometry == gRotSpace) {
constexpr auto& r = rots::underlying_scale;
dialog::addSelItem(XLAT("view the underlying geometry"), r > 0 ? fts(r)+"x" : "NO", '4');
dialog::add_action([] {
dialog::editNumber(r, 0, 1, 0.05, 0.25, XLAT("view the underlying geometry"),
XLAT(
"The space you are currently in the space of rotations of the underlying hyperbolic or spherical geometry. "
"This option lets you see the underlying space. Lands and some walls (e.g. in the Graveyard) are based on "
"the respective features in the underlying world, but details such as monsters or items are ignored."
)
);
dialog::bound_low(0);
dialog::bound_up(1);
dialog::extra_options = [] () { rots::draw_underlying(true); };
});
}
else if(euwrap || geometry == gFieldQuotient || cryst || archimedean || (euclid && WDIM == 3)) {
dialog::addItem(XLAT("advanced parameters"), '4');
dialog::add_action([] {
if(0);

View File

@ -7531,6 +7531,8 @@ EX bool dronemode;
purehookset hooks_calcparam;
EX int corner_centering;
EX void calcparam() {
DEBBI(DF_GRAPH, ("calc param"));
@ -7571,11 +7573,21 @@ EX void calcparam() {
if(GDIM == 3 && in_perspective()) cd->radius = cd->scrsize;
realradius = min(realradius, cd->radius);
ld aradius = sphere ? cd->radius / (vid.alpha - 1) : cd->radius;
if(dronemode) { cd->ycenter -= cd->radius; cd->ycenter += vid.fsize/2; cd->ycenter += vid.fsize/2; cd->radius *= 2; }
if(corner_centering) {
cd->ycenter = cd->ytop + cd->ysize - vid.fsize - aradius;
if(corner_centering == 1)
cd->xcenter = cd->xtop + vid.fsize + aradius;
if(corner_centering == 2)
cd->xcenter = cd->xtop + cd->xsize - vid.fsize - aradius;
}
cd->xcenter += cd->scrsize * vid.xposition;
cd->ycenter += cd->scrsize * vid.yposition;
cd->tanfov = tan(vid.fov * degree / 2);
if(pmodel)

View File

@ -481,6 +481,10 @@ EX void drawStats() {
first_cell_to_draw = true;
bool h = hide_player();
bool cornermode = (vid.xres > vid.yres * 85/100 && vid.yres > vid.xres * 85/100);
if(geometry == gRotSpace) rots::draw_underlying(!cornermode);
{
dynamicval<eModel> pm(pmodel, flat_model());
glClear(GL_DEPTH_BUFFER_BIT);
@ -492,9 +496,7 @@ EX void drawStats() {
if(prod) vid.alpha = 30, vid.scale = 30;
calcparam();
bool cornermode = (vid.xres > vid.yres * 85/100 && vid.yres > vid.xres * 85/100);
if(vid.radarsize > 0 && h)
#if CAP_RACING
if(!racing::on)

View File

@ -1217,6 +1217,89 @@ EX namespace rots {
}
};
/** reinterpret the given point of rotspace as a rotation matrix in the underlying geometry */
EX transmatrix qtm(hyperpoint h) {
if(hyperbolic) {
hyperpoint k = slr::to_phigans(h);
ld z = k[2]; k[2] = 0;
ld r = hypot_d(2, k);
// k[1] = -k[1];
k[0] = -k[0];
if(r) k = tangent_length(k, asinh(r) * 2);
return spin(-z * 2) * rgpushxto0(direct_exp(k, 0));
}
double sq0 = h[0]*h[0];
double sq1 = h[1]*h[1];
double sq2 = h[2]*h[2];
double sq3 = h[3]*h[3];
transmatrix M;
M[0][0] = sq0 - sq1 - sq2 + sq3;
M[1][1] = -sq0 + sq1 - sq2 + sq3;
M[2][2] = -sq0 - sq1 + sq2 + sq3;
double tmp1 = h[0]*h[1];
double tmp2 = h[2]*h[3];
M[0][1] = -2 * (tmp1 + tmp2);
M[1][0] = -2 * (tmp1 - tmp2);
tmp1 = h[0]*h[2];
tmp2 = h[1]*h[3];
M[0][2] = 2 * (tmp1 - tmp2);
M[2][0] = 2 * (tmp1 + tmp2);
tmp1 = h[1]*h[2];
tmp2 = h[0]*h[3];
M[1][2] = -2 * (tmp1 + tmp2);
M[2][1] = -2 * (tmp1 - tmp2);
return M;
}
EX ld underlying_scale = 0;
EX void draw_underlying(bool cornermode) {
if(underlying_scale <= 0) return;
ld d = hybrid::current_view_level;
d *= cgi.plevel;
transmatrix T = rots::uzpush(-d) * spin(-2*d);
if(det(T) < 0) T = centralsym * T;
hyperpoint h = inverse(View * spin(master_to_c7_angle()) * T) * C0;
auto g = std::move(gmatrix);
auto g0 = std::move(gmatrix0);
hybrid::in_underlying_map([&] {
cgi.require_shapes();
dynamicval<int> pcc(corner_centering, cornermode ? 1 : 2);
dynamicval<bool> pf(playerfound, true);
dynamicval<cellwalker> m5(centerover, viewctr.at->c7);
dynamicval<transmatrix> m2(View, ypush(0) * qtm(h));
dynamicval<transmatrix> m3(playerV, Id);
dynamicval<transmatrix> m4(actual_view_transform, Id);
dynamicval<eModel> pm(pmodel, mdDisk);
dynamicval<ld> pss(vid.scale, (sphere ? 10 : 1) * underlying_scale);
dynamicval<ld> psa(vid.alpha, sphere ? 10 : 1);
dynamicval<hrmap*> p(hybrid::pmap, NULL);
dynamicval<int> psr(sightrange_bonus, 0);
calcparam();
reset_projection(); current_display->set_all(0);
ptds.clear();
drawthemap();
drawqueue();
displaychr(current_display->xcenter, current_display->ycenter, 0, 24, '+', 0xFFFFFFFF);
glflush();
});
gmatrix = std::move(g);
gmatrix0 = std::move(g0);
calcparam();
reset_projection(); current_display->set_all(0);
}
EX }
EX namespace nisot {
@ -1370,6 +1453,11 @@ EX namespace nisot {
set_geometry(gRotSpace);
return 0;
}
else if(argis("-rot_uscale")) {
PHASEFROM(2);
shift_arg_formula(rots::underlying_scale);
return 0;
}
return 1;
});