diff --git a/3d-models.cpp b/3d-models.cpp index e1e88dbe..a1b7f9da 100644 --- a/3d-models.cpp +++ b/3d-models.cpp @@ -17,7 +17,7 @@ ld eyepos; #define S (cgi.scalefactor / 0.805578) #define SH (cgi.scalefactor / 0.805578 * vid.height_width / 1.5) -#define revZ ((WDIM == 2 || prod) ? -1 : 1) +#define revZ ((WDIM == 2 || gproduct) ? -1 : 1) hyperpoint shcenter; @@ -46,9 +46,9 @@ EX ld zc(ld z) { void geometry_information::add_cone(ld z0, const vector& vh, ld z1) { last->flags |= POLY_TRIANGLES; for(int i=0; i vh0, ld z1, last->flags |= POLY_TRIANGLES; for(int i=0; i vh0, ld z1, vecto for(auto pp: pairs) { int id = pp.owner; - hpcpush(zpush(z0) * lasts[0]); - hpcpush(zpush(z1) * lasts[1]); - hpcpush(zpush(id == 0 ? z0 : z1) * pp.h); + hpcpush(lzpush(z0) * lasts[0]); + hpcpush(lzpush(z1) * lasts[1]); + hpcpush(lzpush(id == 0 ? z0 : z1) * pp.h); lasts[id] = pp.h; } } @@ -117,7 +117,7 @@ void geometry_information::add_texture(hpcshape& sh) { sh.texture_offset = isize(utt.tvertices); for(int i=sh.s; i scaleshape(const vector& vh, ld s) { } ld get_zlevel(hyperpoint h) { - if(prod) return zlevel(h); + if(gproduct) return zlevel(h); if(sl2) return atan2(h[2], h[3]); return asin_auto(h[2]); } void geometry_information::make_ha_3d(hpcshape& sh, bool isarmor, ld scale) { - shcenter = C0; + shcenter = tile_center(); auto groin = get_shape(shHumanGroin); auto body = get_shape(shPBodyOnly); @@ -207,12 +207,12 @@ void geometry_information::make_ha_3d(hpcshape& sh, bool isarmor, ld scale) { for(int i=arm0; i hs, int kind) { if(abs(h[1]) > 0.14*S) ok = false, zz -= revZ * (abs(h[1])/S - 0.14) * SH; if(abs(h[0]) > 0.08*S) ok = false, zz -= revZ * (abs(h[0])/S - 0.08) * (abs(h[0])/S - 0.08) * 25 * SH; h = normalize_flat(h); - if(!prod || kind != 1) ht[s] = zpush(zz) * h; + if(!gproduct || kind != 1) ht[s] = lzpush(zz) * h; else ht[s] = h; if(hsh[s] < 0.1*S) shi[s] = 0.5; else if(hsh[s] < 0.12*S) shi[s] = 0.1 + 0.4 * (hsh[s]/S - 0.1) / (0.12 - 0.1); @@ -285,14 +285,14 @@ void geometry_information::addtri(array hs, int kind) { htx[2][i][1] *= 1.7; htx[4][i][0] = htx[4][i][0] * 0.4 + scalefactor * 0.1; htx[5][i][0] = htx[5][i][0] * 0.3 + scalefactor * 0.1; - if(!prod) + if(!gproduct) for(int a=0; a<6; a++) htx[a][i] = hpxy3(htx[a][i][0], htx[a][i][1], htx[a][i][2]); else - for(int a=0; a<6; a++) htx[a][i] = zpush(zzes[i]) * hpxy(htx[a][i][0], htx[a][i][1]); + for(int a=0; a<6; a++) htx[a][i] = lzpush(zzes[i]) * hpxy(htx[a][i][0], htx[a][i][1]); } ld levels[6] = {0, 0.125, 0.125, 0.250, 0.375, 0.5}; for(int a=0; a<6; a++) for(int i=0; i<3; i++) - htx[a][i] = zpush(-min(shi[i], levels[a]) * human_height * revZ) * htx[a][i]; + htx[a][i] = lzpush(-min(shi[i], levels[a]) * human_height * revZ) * htx[a][i]; hpcpush(htx[0][0]); hpcpush(htx[0][1]); @@ -320,7 +320,7 @@ void geometry_information::addtri(array hs, int kind) { if(hdist0(h) <= 0.0501*S) { zz += revZ * sqrt(0.0026 - pow(hdist0(h)/S, 2)) * SH; } - hpcpush(zpush(zz) * h); + hpcpush(lzpush(zz) * h); } } } @@ -382,7 +382,7 @@ void geometry_information::make_foot_3d(hpcshape& sh) { void geometry_information::make_head_only() { auto addpt = [this] (int d, int u) { - hpcpush(zpush(zc(eyepos) + 0.06 * SH * sin(u * degree)) * xspinpush0(d * degree, 0.05 * S * cos(u * degree))); + hpcpush(lzpush(zc(eyepos) + 0.06 * SH * sin(u * degree)) * xspinpush0(d * degree, 0.05 * S * cos(u * degree))); }; bshape(shPHeadOnly, shPHeadOnly.prio); @@ -415,7 +415,7 @@ void geometry_information::make_head_3d(hpcshape& sh) { array zero = make_array(0,0); pts[1].emplace_back(zero); - head.push_back(C0); + head.push_back(tile_center()); bshape(sh, sh.prio); @@ -491,7 +491,7 @@ void geometry_information::make_skeletal(hpcshape& sh, ld push) { } hyperpoint yzspin(ld alpha, hyperpoint h) { - if(prod) return product::direct_exp(cspin(1, 2, alpha) * product::inverse_exp(h)); + if(gproduct) return product::direct_exp(cspin(1, 2, alpha) * product::inverse_exp(h)); else return cspin(1, 2, alpha) * h; } @@ -625,7 +625,7 @@ void geometry_information::slimetriangle(hyperpoint a, hyperpoint b, hyperpoint dynamicval d(vid.texture_step, 8); texture_order([&] (ld x, ld y) { ld z = 1-x-y; - ld r = scalefactor * hcrossf7 * (0 + pow(max(x,max(y,z)), .3) * 0.8) * (hybri ? .5 : 1); + ld r = scalefactor * hcrossf7 * (0 + pow(max(x,max(y,z)), .3) * 0.8) * (mhybrid ? .5 : 1); hyperpoint h = direct_exp(tangent_length(a*x+b*y+c*z, r)); hpcpush(h); }); @@ -709,16 +709,16 @@ void geometry_information::make_euclidean_sky() { for(int x=-20; x<20; x++) for(int y=-20; y<20; y++) hpcsquare( - zpush(cgi.WALL) * hpxy(x, y), - zpush(cgi.WALL) * hpxy(x, y+1), - zpush(cgi.WALL) * hpxy(x+1, y), - zpush(cgi.WALL) * hpxy(x+1, y+1) + lzpush(cgi.WALL) * hpxy(x, y), + lzpush(cgi.WALL) * hpxy(x, y+1), + lzpush(cgi.WALL) * hpxy(x+1, y), + lzpush(cgi.WALL) * hpxy(x+1, y+1) ); } /** res[0] and res[1] place H on the plane, while res[2] is the altitude */ hyperpoint psmin(hyperpoint H) { - if(prod) { + if(gproduct) { auto d = product_decompose(H); d.second[2] = d.first; return d.second; @@ -748,14 +748,14 @@ void geometry_information::adjust_eye(hpcshape& eye, hpcshape head, ld shift_eye vector pss; - for(int i=head.s; is; is; i dv(geometry, gArchimedean); @@ -478,9 +487,9 @@ void archimedean_tiling::compute_geometry() { auto& c = circumradius[i]; c = asin_auto(sin_auto(edgelength/2) / sin(gamma)); - inradius[i] = hdist0(mid(xpush0(circumradius[i]), xspinpush0(2*gamma, circumradius[i]))); + inradius[i] = hdist0(mid(lxpush0(circumradius[i]), xspinpush0(2*gamma, circumradius[i]))); - hyperpoint h = xpush(c) * spin(M_PI - 2*gamma) * xpush0(c); + hyperpoint h = lxpush(c) * spin(M_PI - 2*gamma) * lxpush0(c); ld a = atan2(h); cyclefix(a, 0); if(a < 0) a = -a; @@ -592,7 +601,7 @@ struct hrmap_archimedean : hrmap { current_altmap = newAltMap(alt); } - transmatrix T = xpush(.01241) * spin(1.4117) * xpush(0.1241) * Id; + transmatrix T = lxpush(.01241) * spin(1.4117) * lxpush(0.1241) * Id; archimedean_gmatrix[origin] = make_pair(alt, T); altmap[alt].emplace_back(origin, T); @@ -653,13 +662,13 @@ struct hrmap_archimedean : hrmap { auto& t1 = current.get_triangle(hi); - // * spin(-tri[id][pi+i].first) * xpush(t.second) * pispin * spin(tri[id'][p'+d'].first) + // * spin(-tri[id][pi+i].first) * lxpush(t.second) * pispin * spin(tri[id'][p'+d'].first) auto& p1 = archimedean_gmatrix[h]; heptagon *alt = p1.first; - transmatrix T = p1.second * spin(-t1.first) * xpush(t1.second); + transmatrix T = p1.second * spin(-t1.first) * lxpush(t1.second); transmatrix U = Id; if(hyperbolic) { @@ -680,22 +689,22 @@ struct hrmap_archimedean : hrmap { DEBB(DF_GEOM, ("look for: ", alt, " / ", kz(T * C0))); - for(auto& p2: altmap[alt]) if(same_point_may_warn(p2.second * C0, T * C0)) { + for(auto& p2: altmap[alt]) if(same_point_may_warn(p2.second * tile_center(), T * tile_center())) { DEBB(DF_GEOM, ("cell found: ", p2.first)); for(int d2=0; d2degree(); d2++) { heptspin hs(p2.first, d2); auto& t2 = current.get_triangle(p2.first, d2); transmatrix T1 = T * spin(M_PI + t2.first); - DEBB(DF_GEOM, ("compare: ", kz(T1 * xpush0(1)), ":: ", kz(p2.second * xpush0(1)))); - if(same_point_may_warn(T1 * xpush0(1), p2.second * xpush0(1))) { + DEBB(DF_GEOM, ("compare: ", kz(T1 * lxpush0(1)), ":: ", kz(p2.second * lxpush0(1)))); + if(same_point_may_warn(T1 * lxpush0(1), p2.second * lxpush0(1))) { // T1 = p2.second // T * spin(pi+t2.first) == p2.second - // p1.second * spinm(-t1.first) * xpush(t1.second) * spin(pi+t2.first) == p2.second + // p1.second * spinm(-t1.first) * lxpush(t1.second) * spin(pi+t2.first) == p2.second // bring p1 and p2 closer, to prevent floating point errors if(hyperbolic) { - fixup_matrix(p1.second, U * p2.second * spin(-M_PI - t2.first) * xpush(-t1.second) * spin(t1.first), 0.25); + fixup_matrix(p1.second, U * p2.second * spin(-M_PI - t2.first) * lxpush(-t1.second) * spin(t1.first), 0.25); fixup_matrix(p2.second, T1, 0.25); } @@ -837,7 +846,7 @@ struct hrmap_archimedean : hrmap { auto& t1 = ac.get_triangle(c->master, cid); hyperpoint h0 = xspinpush0(-t0.first, t0.second * 3 / cf * (ac.real_faces == 0 ? 0.999 : 1)); hyperpoint h1 = xspinpush0(-t1.first, t1.second * 3 / cf * (ac.real_faces == 0 ? 0.999 : 1)); - return mid3(C0, h0, h1); + return mid3(tile_center(), h0, h1); } if(DUAL) { auto& t0 = ac.get_triangle(c->master, 2*cid-1); @@ -965,7 +974,7 @@ transmatrix archimedean_tiling::adjcell_matrix(heptagon *h, int d) { int d2 = h->c.spin(d); auto& t2 = get_triangle(h2, d2); - return spin(-t1.first) * xpush(t1.second) * spin(M_PI + t2.first); + return spin(-t1.first) * lxpush(t1.second) * spin(M_PI + t2.first); } EX int fix(heptagon *h, int spin) { diff --git a/barriers.cpp b/barriers.cpp index 2a0ea1ca..acd22cae 100644 --- a/barriers.cpp +++ b/barriers.cpp @@ -38,7 +38,7 @@ EX bool hasbardir(cell *c) { } EX void preventbarriers(cell *c) { - if(hybri) c = hybrid::get_where(c).first; + if(mhybrid) c = hybrid::get_where(c).first; if(c && c->bardir == NODIR) c->bardir = NOBARRIERS; } diff --git a/basegraph.cpp b/basegraph.cpp index de13a17a..4db1827f 100644 --- a/basegraph.cpp +++ b/basegraph.cpp @@ -1496,7 +1496,7 @@ EX void initialize_all() { #if CAP_ARCM arcm::current.parse(); #endif - if(hybri) geometry = hybrid::underlying; + if(mhybrid) geometry = hybrid::underlying; #if CAP_COMMANDLINE arg::read(2); diff --git a/bigstuff.cpp b/bigstuff.cpp index dde7a248..ae900962 100644 --- a/bigstuff.cpp +++ b/bigstuff.cpp @@ -184,7 +184,7 @@ map altmap::quotient_relspins; auto qclear = addHook(hooks_clearmemory, 200, [] { altmap::quotient_relspins.clear(); }); void hrmap::extend_altmap(heptagon *h, int levs, bool link_cdata) { - if(hybri) { PIU ( extend_altmap(h, levs, link_cdata) ); } + if(mhybrid) { PIU ( extend_altmap(h, levs, link_cdata) ); } if(!h->alt) return; preventbarriers(h->c7); if(h->c7) forCellEx(c2, h->c7) preventbarriers(c2); @@ -230,7 +230,7 @@ EX int hrandom_adjacent(cellwalker cw) { EX heptagon *create_altmap(cell *c, int rad, hstate firststate, int special IS(0)) { - if(hybri) { + if(mhybrid) { if(hybrid::under_class() == gcSphere) return NULL; c = hybrid::get_where(c).first; return PIU ( create_altmap(c, rad, firststate, special) ); @@ -296,7 +296,7 @@ EX heptagon *create_altmap(cell *c, int rad, hstate firststate, int special IS(0 if(!currentmap->link_alt(h, alt, firststate, p.last.spin)) { return nullptr; } - if(hybri) hybrid::altmap_heights[alt] = hybrid::get_where(centerover).second; + if(mhybrid) hybrid::altmap_heights[alt] = hybrid::get_where(centerover).second; alt->alt = alt; h->alt = alt; alt->cdata = (cdata*) h; @@ -814,10 +814,10 @@ EX void buildEquidistant(cell *c) { ls::nice_walls() ? true : false; - if(c->landparam > 30 && b == laOcean && !generatingEquidistant && !hybri && hrand(10) < 5 && chance) + if(c->landparam > 30 && b == laOcean && !generatingEquidistant && !mhybrid && hrand(10) < 5 && chance) buildAnotherEquidistant(c); - if(c->landparam > HAUNTED_RADIUS+5 && b == laGraveyard && !generatingEquidistant && !hybri && hrand(100) < (PURE?25:5) && items[itBone] >= U10 && chance) + if(c->landparam > HAUNTED_RADIUS+5 && b == laGraveyard && !generatingEquidistant && !mhybrid && hrand(100) < (PURE?25:5) && items[itBone] >= U10 && chance) buildAnotherEquidistant(c); } @@ -959,7 +959,7 @@ EX void clear_euland(eLand first) { } bool valid_wall_at(int c) { - if(nonisotropic || hybri) return true; + if(nonisotropic || mhybrid) return true; return short(c) % 3 == 0; } @@ -972,7 +972,7 @@ EX eLand switchable(eLand nearland, eLand farland, int c) { else if(ls::no_walls()) { if((dual::state && nearland == laCrossroads4) || hrand(15) == 0) return getNewLand(nearland); - if(nearland == laCrossroads4 && (nonisotropic || hybri)) + if(nearland == laCrossroads4 && (nonisotropic || mhybrid)) return getNewLand(nearland); return nearland; } @@ -1372,7 +1372,7 @@ EX bool horo_ok() { if(INVERSE) return false; if(currentmap->strict_tree_rules()) return true; if(reg3::in_hrmap_h3() && !PURE) return false; - return hyperbolic && !bt::in() && !arcm::in() && !kite::in() && !experimental && !hybri && !arb::in() && !quotient; + return hyperbolic && !bt::in() && !arcm::in() && !kite::in() && !experimental && !mhybrid && !arb::in() && !quotient; } /** \brief should we either generate the horocycles in the current geometry, or have them exist via eubinary? */ @@ -1496,7 +1496,7 @@ EX bool old_nice_walls() { } EX bool nice_walls_available() { - if(hybri) return PIU(nice_walls_available()); + if(mhybrid) return PIU(nice_walls_available()); if(fake::in()) return FPIU(nice_walls_available()); return WDIM == 2; } @@ -1520,7 +1520,7 @@ EX void build_walls(cell *c, cell *from) { // buildgreatwalls - if(hybri) return; /* Great Walls generated via the underlying geometry */ + if(mhybrid) return; /* Great Walls generated via the underlying geometry */ if(walls_not_implemented()) return; // walls not implemented here @@ -1920,7 +1920,7 @@ EX void gen_temple(cell *c) { auto d = hybrid::get_where(c); if(!PIU(pseudohept(d.first))) c->wall = waColumn; } - else if(hybri) { + else if(mhybrid) { auto d = hybrid::get_where(c); if(d.first->wall == waColumn || (d.second&1)) c->wall = waColumn; } diff --git a/binary-tiling.cpp b/binary-tiling.cpp index 33bc95ed..6ea23b80 100644 --- a/binary-tiling.cpp +++ b/binary-tiling.cpp @@ -604,7 +604,7 @@ EX namespace bt { /** \brief by what factor do the lengths expand after moving one level in hr::bt::expansion_coordinate() */ EX ld expansion() { if(WDIM == 2) return area_expansion_rate(); - else if(prod) return PIU( area_expansion_rate() ); + else if(mproduct) return PIU( area_expansion_rate() ); else return sqrt(area_expansion_rate()); } diff --git a/cell.cpp b/cell.cpp index be1d92d5..4ff2a0db 100644 --- a/cell.cpp +++ b/cell.cpp @@ -187,7 +187,7 @@ transmatrix hrmap::adj(heptagon *h, int i) { return relative_matrix(h->cmove(i), vector& hrmap::allcells() { static vector default_allcells; if(disksize) return all_disk_cells; - if(closed_manifold && !(cgflags & qHUGE_BOUNDED) && !(hybri && hybrid::csteps == 0)) { + if(closed_manifold && !(cgflags & qHUGE_BOUNDED) && !(mhybrid && hybrid::csteps == 0)) { celllister cl(gamestart(), 1000000, 1000000, NULL); default_allcells = cl.lst; return default_allcells; @@ -403,13 +403,15 @@ EX bool is_in_disk(cell *c) { /** create a map in the current geometry */ EX void initcells() { DEBB(DF_INIT, ("initcells")); + + if(embedded_plane) return IPF( initcells() ); hrmap* res = callhandlers((hrmap*)nullptr, hooks_newmap); if(res) currentmap = res; #if CAP_SOLV else if(asonov::in()) currentmap = asonov::new_map(); #endif - else if(nonisotropic || hybri) currentmap = nisot::new_map(); + else if(nonisotropic || mhybrid) currentmap = nisot::new_map(); else if(INVERSE) currentmap = gp::new_inverse(); else if(fake::in()) currentmap = fake::new_map(); #if CAP_CRYSTAL @@ -586,7 +588,7 @@ EX int compdist(int dx[]) { EX int celldist(cell *c) { if(experimental) return 0; - if(hybri) + if(mhybrid) return hybrid::celldistance(c, currentmap->gamestart()); if(nil && !quotient) return DISTANCE_UNKNOWN; if(euc::in()) return celldistance(currentmap->gamestart(), c); @@ -617,7 +619,7 @@ static const int ALTDIST_ERROR = 90000; EX int celldistAlt(cell *c) { if(experimental) return 0; - if(hybri) { + if(mhybrid) { if(in_s2xe()) return hybrid::get_where(c).second; auto w = hybrid::get_where(c); int d = c->master->alt && c->master->alt->alt ? hybrid::altmap_heights[c->master->alt->alt] : 0; @@ -831,7 +833,8 @@ EX bool randpatternMajority(cell *c, int ival, int iterations) { cdata orig_cdata; EX bool geometry_supports_cdata() { - if(hybri) return PIU(geometry_supports_cdata()); + if(mhybrid) return PIU(geometry_supports_cdata()); + if(embedded_plane) return IPF( geometry_supports_cdata() ); return among(geometry, gEuclid, gEuclidSquare, gNormal, gOctagon, g45, g46, g47, gBinaryTiling) || (arcm::in() && !sphere) || (currentmap && currentmap->strict_tree_rules()); } @@ -925,7 +928,8 @@ cdata *getHeptagonCdata_legacy(heptagon *h) { cdata *getHeptagonCdata(heptagon *h) { - if(hybri) return PIU ( getHeptagonCdata(h) ); + if(mhybrid) return PIU ( getHeptagonCdata(h) ); + if(embedded_plane) return IPF( getHeptagonCdata(h) ); if(geometry == gNormal && BITRUNCATED) return getHeptagonCdata_legacy(h); if(h->cdata) return h->cdata; @@ -1090,8 +1094,9 @@ EX cdata *arcmCdata(cell *c) { EX int getCdata(cell *c, int j) { if(fake::in()) return FPIU(getCdata(c, j)); + if(embedded_plane) return IPF(getCdata(c, j)); if(experimental) return 0; - if(hybri) { c = hybrid::get_where(c).first; return PIU(getBits(c)); } + if(mhybrid) { c = hybrid::get_where(c).first; return PIU(getBits(c)); } else if(INVERSE) { cell *c1 = gp::get_mapped(c); return UIU(getCdata(c1, j)); @@ -1116,8 +1121,9 @@ EX int getCdata(cell *c, int j) { EX int getBits(cell *c) { if(fake::in()) return FPIU(getBits(c)); + if(embedded_plane) return IPF(getBits(c)); if(experimental) return 0; - if(hybri) { c = hybrid::get_where(c).first; return PIU(getBits(c)); } + if(mhybrid) { c = hybrid::get_where(c).first; return PIU(getBits(c)); } else if(INVERSE) { cell *c1 = gp::get_mapped(c); return UIU(getBits(c1)); @@ -1265,7 +1271,7 @@ EX int celldistance(cell *c1, cell *c2) { if(fake::in()) return FPIU(celldistance(c1, c2)); - if(hybri) return hybrid::celldistance(c1, c2); + if(mhybrid) return hybrid::celldistance(c1, c2); #if CAP_FIELD if(geometry == gFieldQuotient && (PURE || BITRUNCATED)) { @@ -1533,7 +1539,7 @@ EX vector reverse_directions(heptagon *c, int dir) { } EX bool standard_tiling() { - return !arcm::in() && !kite::in() && !bt::in() && !arb::in() && !nonisotropic && !hybri; + return !arcm::in() && !kite::in() && !bt::in() && !arb::in() && !nonisotropic && !mhybrid; } EX int valence() { diff --git a/celldrawer.cpp b/celldrawer.cpp index c80d1642..264442c2 100644 --- a/celldrawer.cpp +++ b/celldrawer.cpp @@ -1764,7 +1764,7 @@ void celldrawer::draw_features_and_walls_3d() { /* always render */ if(wrl::in && wrl::print) ; else #endif - if(pmodel == mdPerspective && !sphere && !quotient && !kite::in() && !nonisotropic && !hybri && !experimental && !nih) { + if(pmodel == mdPerspective && !sphere && !quotient && !kite::in() && !nonisotropic && !mhybrid && !experimental && !nih) { if(a < 4 && among(geometry, gHoroTris, gBinary3) && celldistAlt(c) >= celldistAlt(centerover)) continue; else if(a < 2 && among(geometry, gHoroRec) && celldistAlt(c) >= celldistAlt(centerover)) continue; // this optimization is not correct, need to fix @@ -1782,7 +1782,7 @@ void celldrawer::draw_features_and_walls_3d() { case 6: case 7: if (pmodel == mdPerspective && V[2][LDIM] <= -l) continue; break; } } - else if(prod) { + else if(mproduct) { if(a < c->type-2 && !in_s2xe()) { ld d = in_e2xe() ? sqhypot_d(2, unshift(tC0(V))) : V[2][2]; hyperpoint h = (unshift(V) * cgi.walltester[ofs + a]); @@ -1838,7 +1838,7 @@ void celldrawer::draw_features_and_walls_3d() { else if(c->wall == waMineOpen) { if(pmodel == mdGeodesic && hdist0(tC0(V)) < 1e-3) { } - else if(prod && hdist0(tC0(V)) < 1e-3) { + else if(mproduct && hdist0(tC0(V)) < 1e-3) { } else { int mines = countMinesAround(c); @@ -1903,7 +1903,7 @@ void celldrawer::check_rotations() { if(a <= b) { ds.best = c; ds.speed = spd; - if(prod) { + if(mproduct) { auto pd = product_decompose(unshift(tC0(V))); ds.total += pd.second; ds.depth += pd.first; @@ -1912,7 +1912,7 @@ void celldrawer::check_rotations() { ds.total += unshift(tC0(V)); ds.qty++; ds.point = normalize_flat(ds.total); - if(prod) ds.point = orthogonal_move(ds.point, ds.depth / ds.qty); + if(mproduct) ds.point = orthogonal_move(ds.point, ds.depth / ds.qty); if(side == 2) for(int i=0; i<3; i++) ds.point[i] = -ds.point[i]; if(side == 1) ds.point = spin(-90._deg) * ds.point; } diff --git a/complex.cpp b/complex.cpp index 80cfa615..eca27d8b 100644 --- a/complex.cpp +++ b/complex.cpp @@ -2796,7 +2796,7 @@ EX namespace sword { }; /** dimensions available to the Sword */ - #define SWORDDIM (hybri ? 2 : WDIM) + #define SWORDDIM (mhybrid ? 2 : WDIM) #endif @@ -2829,7 +2829,7 @@ EX namespace sword { EX cell *pos2(cell *c, int s) { int t = c->type; - if(hybri) t -= 2; + if(mhybrid) t -= 2; s *= 2; s += sword_angles/t; s %= (2 * sword_angles); @@ -2887,7 +2887,7 @@ EX namespace sword { neighborId(c2, c1); if(s1 < 0 || s2 < 0) return d; if(SWORDDIM == 2) { - int sub = (hybri) ? 2 : 0; + int sub = (mhybrid) ? 2 : 0; int t2 = c2->type - sub; int t1 = c1->type - sub; if(t1 == 0 || t2 == 0) return d; @@ -3590,7 +3590,7 @@ EX namespace windmap { // cw.spin = 0; neighbors.emplace_back(); auto &v = neighbors.back(); - if(NONSTDVAR && !sphere && !arcm::in() && !hybri && !INVERSE) + if(NONSTDVAR && !sphere && !arcm::in() && !mhybrid && !INVERSE) for(int l=0; leditable(geom3::spatial_embedding_options, "spatial embedding", 'E'); param_b(memory_saving_mode, "memory_saving_mode", (ISMOBILE || ISPANDORA || ISWEB) ? 1 : 0); param_i(reserve_limit, "memory_reserve", 128); @@ -2203,6 +2206,8 @@ EX void show3D() { dialog::add_action(geom3::switch_fpp); } #endif + + add_edit(geom3::spatial_embedding); dialog::addBreak(50); #if MAXMDIM >= 4 @@ -2278,7 +2283,7 @@ EX void show3D() { }); } - if((WDIM == 2 && GDIM == 3) || prod) + if(mproduct || embedded_plane) dialog::addBoolItem_action(XLAT("fixed Y/Z rotation"), vid.fixed_yz, 'Z'); if(WDIM == 2 && GDIM == 3) { diff --git a/control.cpp b/control.cpp index fceb5647..7f07a159 100644 --- a/control.cpp +++ b/control.cpp @@ -83,7 +83,7 @@ EX bool mouseout2() { EX movedir vectodir(hyperpoint P) { transmatrix U = unshift(ggmatrix(cwt.at)); - if(GDIM == 3 && WDIM == 2) U = current_display->radar_transform * U; + if(embedded_plane && geom3::same_in_same()) U = current_display->radar_transform * U; P = direct_exp(lp_iapply(P)); @@ -94,10 +94,12 @@ EX movedir vectodir(hyperpoint P) { vector dirdist(cwt.at->type); + auto TC0 = tile_center(); + for(int i=0; itype; i++) { transmatrix T = currentmap->adj(cwt.at, (cwt + i).spin); - ld d1 = geo_dist(U * T * C0, Centered * P); - ld d2 = geo_dist(U * T * C0, Centered * C0); + ld d1 = geo_dist(U * T * TC0, Centered * P); + ld d2 = geo_dist(U * T * TC0, Centered * TC0); dirdist[i] = d1 - d2; } diff --git a/drawing.cpp b/drawing.cpp index 6bd48f90..f797b5d3 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -1559,7 +1559,7 @@ EX namespace ods { for(int j=0; j<3; j++) { hyperpoint o = p->V * glhr::gltopoint((*p->tab)[p->offset+i+j]); - if(nonisotropic || prod) { + if(nonisotropic || gproduct) { o = lp_apply(inverse_exp(o, iTable, false)); o[3] = 1; dynamicval g(geometry, gEuclid); @@ -2456,7 +2456,7 @@ EX void drawqueue() { #endif #if MAXMDIM >= 4 && CAP_GL - if(WDIM == 2 && GDIM == 3 && hyperbolic && !vrhr::rendering()) make_air(); + if(embedded_plane && (hyperbolic || geom3::sph_in_euc()) && !vrhr::rendering()) make_air(); #endif #if CAP_VR diff --git a/euclid.cpp b/euclid.cpp index aa1ac010..88dc6b5e 100644 --- a/euclid.cpp +++ b/euclid.cpp @@ -137,10 +137,14 @@ EX namespace euc { map eucdata; void compute_tmatrix() { + bool b = geom3::flipped; + cgi.prepare_basics(); + if(b) geom3::light_flip(false); shifttable = get_shifttable(); tmatrix.resize(S7); for(int i=0; i, MAXMDIM> { bool operator == (const matrix& B) const { @@ -1409,7 +1409,7 @@ EX struct fpattern& getcurrfp() { return fp; } if(!hyperbolic) return fp_invalid; - if(WDIM == 3 && !quotient && !hybri && !bt::in()) { + if(WDIM == 3 && !quotient && !mhybrid && !bt::in()) { static fpattern fp(0); if(fp.Prime) return fp; for(int p=2; p<20; p++) { fp.Prime = p; if(!fp.solve()) break; } diff --git a/floorshapes.cpp b/floorshapes.cpp index cc321c0c..c6e498b2 100644 --- a/floorshapes.cpp +++ b/floorshapes.cpp @@ -693,14 +693,14 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i }); } if(!vid.pseudohedral) for(int t=0; t gm(pmodel, mdDisk); dynamicval va(variation, eVariation::pure); dynamicval gie(ginf[geometry].g, giEuclid2); + dynamicval gief(ginf[geometry].flags, qOPTQ); dynamicval gih(ginf[gNormal].g, giHyperb2); + dynamicval gihf(ginf[gNormal].flags, 0); dynamicval a3(vid.always3, false); dynamicval hq(inHighQual, true); dynamicval hd(darken, 0); diff --git a/geom-exp.cpp b/geom-exp.cpp index 3d5c615e..2f21369f 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -258,13 +258,13 @@ bool forced_quotient() { return quotient && !(cgflags & qOPTQ); } EX geometry_filter gf_hyperbolic = {"hyperbolic", 'h', [] { return (arcm::in() || arb::in() || hyperbolic) && !forced_quotient(); }}; EX geometry_filter gf_spherical = {"spherical", 's', [] { return (arcm::in() || arb::in() || sphere) && !forced_quotient(); }}; EX geometry_filter gf_euclidean = {"Euclidean", 'e', [] { return (arcm::in() || arb::in() || euclid) && !forced_quotient(); }}; -EX geometry_filter gf_other = {"non-isotropic", 'n', [] { return prod || nonisotropic; }}; +EX geometry_filter gf_other = {"non-isotropic", 'n', [] { return mproduct || nonisotropic; }}; EX geometry_filter gf_regular_2d = {"regular 2D tesselations", 'r', [] { return standard_tiling() && WDIM == 2 && !forced_quotient(); }}; EX geometry_filter gf_regular_3d = {"regular 3D honeycombs", '3', [] { if(euclid) return geometry == gCubeTiling; - return !bt::in() && !kite::in() && WDIM == 3 && !forced_quotient() && !nonisotropic && !prod; + return !bt::in() && !kite::in() && WDIM == 3 && !forced_quotient() && !nonisotropic && !mproduct; }}; EX geometry_filter gf_quotient = {"interesting quotient spaces", 'q', [] { return forced_quotient() && !elliptic; @@ -610,7 +610,7 @@ EX void select_quotient() { pushScreen(asonov::show_config); } #endif - else if(prod) + else if(mproduct) pushScreen(product::show_config); else if(rotspace) hybrid::configure_period(); @@ -634,7 +634,7 @@ EX void select_quotient() { EX string full_geometry_name() { string qstring = ginf[geometry].quotient_name; bool variable = - !(prod || hybri || bt::in() || (WDIM == 3 && !reg3::in()) || kite::in() || arb::in()); + !(mproduct || mhybrid || bt::in() || (WDIM == 3 && !reg3::in()) || kite::in() || arb::in()); string fgname = XLAT(ginf[geometry].tiling_name); if(qstring != "none") fgname += " " + XLAT(qstring); @@ -806,7 +806,7 @@ EX geometry_data compute_geometry_data() { gd.nom *= gd.euler; gd.denom *= 2; - if(hybri) gd.nom *= hybrid::csteps, gd.denom *= cgi.single_step; + if(mhybrid) gd.nom *= hybrid::csteps, gd.denom *= cgi.single_step; int g = gcd(gd.nom, gd.denom); if(g) { @@ -1000,14 +1000,14 @@ EX void showEuclideanMenu() { } #endif - if(prod) { + if(mproduct) { dialog::addSelItem(XLAT("Z-level height factor"), fts(vid.plevel_factor), 'Z'); dialog::add_action([] { dialog::editNumber(vid.plevel_factor, 0, 2, 0.1, 0.7, XLAT("Z-level height factor"), ""); dialog::reaction = ray::reset_raycaster; }); } - else if(hybri) { + else if(mhybrid) { dialog::addSelItem(XLAT("number of levels"), its(hybrid::csteps / cgi.single_step), 'L'); dialog::add_action(hybrid::configure_period); } @@ -1037,7 +1037,7 @@ EX void showEuclideanMenu() { } #if MAXMDIM >= 4 - if(hybri) { + if(mhybrid) { auto r = rots::underlying_scale; dialog::addSelItem(XLAT("view the underlying geometry"), r > 0 ? fts(r)+"x" : ONOFF(false), '6'); dialog::add_action([] { diff --git a/geometry.cpp b/geometry.cpp index 60021ea8..1a71e336 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -593,7 +593,7 @@ void geometry_information::prepare_basics() { xp_order = 0; - if(arcm::in() && !prod) + if(arcm::in() && !mproduct) ginf[gArchimedean].cclass = gcHyperbolic; dynamicval gv(variation, variation); @@ -603,9 +603,9 @@ void geometry_information::prepare_basics() { println(hlog, "bitruncated = ", BITRUNCATED); } - if(hybri) { + if(mhybrid) { auto t = this; - ld d = prod ? 1 : 2; + ld d = mproduct ? 1 : 2; hybrid::in_underlying_geometry([&] { t->rhexf = cgi.rhexf / d; t->hexf = cgi.hexf / d; @@ -619,6 +619,8 @@ void geometry_information::prepare_basics() { goto hybrid_finish; } + if(embedded_plane) geom3::light_flip(true); + if((sphere || hyperbolic) && WDIM == 3 && !bt::in()) { rhexf = hexf = 0.378077; crossf = hcrossf = 0.620672; @@ -675,18 +677,6 @@ void geometry_information::prepare_basics() { finish: - heptmove.resize(S7); - hexmove.resize(S7); - invhexmove.resize(S7); - - for(int d=0; d(4 / hypot_d(2, gp::next), 1); @@ -919,7 +939,7 @@ EX namespace geom3 { // tanh(depth) / tanh(camera) == pconf.alpha invalid = ""; - if(GDIM == 3) ; + if(GDIM == 3 || flipped) ; else if(vid.tc_alpha < vid.tc_depth && vid.tc_alpha < vid.tc_camera) pconf.alpha = tan_auto(vid.depth) / tan_auto(vid.camera); else if(vid.tc_depth < vid.tc_alpha && vid.tc_depth < vid.tc_camera) { @@ -976,7 +996,7 @@ EX namespace geom3 { human_height = vid.human_wall_ratio * wh; if(WDIM == 3) human_height = scalefactor * vid.height_width / 2; - if(hybri) human_height = min(human_height, cgi.plevel * .9); + if(mhybrid) human_height = min(human_height, cgi.plevel * .9); ld reduce = (WDIM == 3 ? human_height / 2 : 0); @@ -1020,26 +1040,134 @@ EX namespace geom3 { LOWSKY = lev_to_factor(2 * wh); HIGH = LOWSKY; HIGH2 = lev_to_factor(3 * wh); - SKY = LOWSKY - 5; + SKY = LOWSKY - (vid.wall_height > 0 ? 5 : -5); + + if(geom3::mgclass() == gcSphere && geom3::ggclass() != gcSphere) { + ld max_high = lerp(-FLOOR, -1, 0.8); + ld max_high2 = lerp(-FLOOR, -1, 0.9); + if(HIGH < max_high) HIGH = max_high; + if(HIGH2 < max_high2) HIGH2 = max_high2; + if(LOWSKY < max_high) LOWSKY = max_high; + if(SKY < max_high) SKY = max_high; + if(vid.wall_height < 0) { + SKY = -3 * vid.wall_height; + LOWSKY = 1.75 * SKY; + } + } } } EX namespace geom3 { + + #if HDR + enum eSpatialEmbedding { + seDefault, + seFlat, + seInverted, + seLowerCurvature, + seLowerCurvatureInverted, + seMuchLowerCurvature, + seMuchLowerCurvatureInverted, + seProduct + }; + #endif + + EX vector> spatial_embedding_options = { + {"default", "Embed as a equidistant surface in the 3D version of the same geometry. This is the model used by HyperRogue in its 2D graphics."}, + {"flat", "Embed as a flat surface in the 3D version of the same geometry."}, + {"inverted", "Embed as a equidistant surface, but this time it is inverted."}, + {"lower curvature", "Embed as a convex surface in a space of lower curvature."}, + {"lower curvature inverted", "Embed as a concave surface in a space of lower curvature."}, + {"much lower curvature", "Embed sphere as a convex sphere in hyperbolic space."}, + {"much lower curvature inverted", "Embed sphere as a concave sphere in hyperbolic space."}, + {"product", "Add one extra dimension in the Euclidean way."} + }; + + EX eSpatialEmbedding spatial_embedding; + + EX vector ginf_backup; + + EX eGeometryClass mgclass() { + return (embedded_plane ? ginf_backup : ginf)[geometry].g.kind; + } + + EX eGeometryClass ggclass() { + return (flipped ? ginf_backup : ginf)[geometry].g.kind; + } + + EX bool euc_in_hyp() { + return ggclass() == gcHyperbolic && mgclass() == gcEuclid; + } + + EX bool sph_in_euc() { + return ggclass() == gcEuclid && mgclass() == gcSphere; + } + + EX bool sph_in_hyp() { + return ggclass() == gcHyperbolic && mgclass() == gcSphere; + } + + EX bool in_product() { + return ggclass() == gcProduct; + } + + EX bool same_in_same() { + return mgclass() == ggclass(); + } + + EX bool flipped; + + EX void light_flip(bool f) { + if(f != flipped) { + swap(ginf[geometry].g, geom3::ginf_backup[geometry].g); + swap(ginf[geometry].flags, geom3::ginf_backup[geometry].flags); + flipped = f; + } + } -EX void apply_always3() { - for(geometryinfo& gi: ginf) { - auto &g = gi.g; - if(vid.always3 && g.gameplay_dimension == 2 && g.graphical_dimension == 2) { - g.graphical_dimension++; - g.homogeneous_dimension++; - g.sig[3] = g.sig[2]; - g.sig[2] = g.sig[1]; - } - if(!vid.always3 && g.gameplay_dimension == 2 && g.graphical_dimension == 3) { - g.graphical_dimension--; - g.homogeneous_dimension--; - g.sig[1] = g.sig[2]; - g.sig[2] = g.sig[3]; + #if HDR + template auto in_flipped(const T& f) -> decltype(f()) { + light_flip(true); + finalizer ff([] { light_flip(false); }); + return f(); + } + + #define IPF(x) geom3::in_flipped([&] { return (x); }) + #endif + + EX void apply_always3() { + if(!vid.always3 && !ginf_backup.empty()) { + ginf = ginf_backup; + ginf_backup.clear(); + } + if(vid.always3 && ginf_backup.empty()) { + ginf_backup = ginf; + for(geometryinfo& gi: ginf) { + auto &g = gi.g; + if(vid.always3 && g.gameplay_dimension == 2 && g.graphical_dimension == 2) { + g.graphical_dimension++; + g.homogeneous_dimension++; + g.sig[3] = g.sig[2]; + g.sig[2] = g.sig[1]; + + if(spatial_embedding == seProduct && g.kind != gcEuclid) { + g.kind = gcProduct; + g.homogeneous_dimension--; + g.sig[2] = g.sig[3]; + gi.flags |= qHYBRID; + } + + if(among(spatial_embedding, seLowerCurvature, seLowerCurvatureInverted)) { + if(g.kind == gcEuclid) g = ginf[gSpace534].g; + if(g.kind == gcSphere) g = ginf[gCubeTiling].g; + g.gameplay_dimension = 2; + } + + if(among(spatial_embedding, seMuchLowerCurvature, seMuchLowerCurvatureInverted)) { + g = ginf[gSpace534].g; + g.gameplay_dimension = 2; + } + } } } } @@ -1090,17 +1218,44 @@ EX void switch_always3() { vid.always3 = true; apply_always3(); ld ms = min(cgi.scalefactor, 1); + vid.depth = ms; vid.wall_height = 1.5 * ms; - if(sphere) { + if(sphere && same_in_same()) { vid.depth = 30 * degree; vid.wall_height = 60 * degree; } vid.human_wall_ratio = 0.8; - if(euclid && allowIncreasedSight() && vid.use_smart_range == 0) { + if(mgclass() == gcEuclid && allowIncreasedSight() && vid.use_smart_range == 0) { genrange_bonus = gamerange_bonus = sightrange_bonus = cgi.base_distlimit * 3/2; } vid.camera = 0; - vid.depth = ms; + vid.eye = 0; + if(sph_in_euc() || sph_in_hyp()) { + vid.depth = 0; + vid.wall_height = -1; + vid.eye = 0.5; + if(among(spatial_embedding, seLowerCurvatureInverted, seMuchLowerCurvatureInverted)) { + vid.wall_height = 1.4; + vid.eye = -0.2; + vid.depth = 0.5; + } + } + if(spatial_embedding == seFlat) { + vid.eye -= vid.depth / 2; + vid.depth = 0; + } + if(spatial_embedding == seInverted) { + vid.eye -= vid.depth * 1.5; + vid.depth *= -1; + } + if(euc_in_hyp() && spatial_embedding == seLowerCurvatureInverted) { + vid.wall_height *= -1; + vid.eye = 2 * vid.depth; + } + if(euc_in_hyp() && spatial_embedding == seMuchLowerCurvatureInverted) { + vid.wall_height *= -1; + vid.eye = 2 * vid.depth; + } if(pmodel == mdDisk) pmodel = mdPerspective; swapmatrix(View); swapmatrix(current_display->which_copy); @@ -1111,6 +1266,8 @@ EX void switch_always3() { #if CAP_RACING racing::player_relative = true; #endif + check_cgi(); + cgi.prepare_basics(); } else { vid.always3 = false; @@ -1188,12 +1345,11 @@ EX string cgi_string() { if(bt::in() || GDIM == 3) V("WQ", its(vid.texture_step)); - if(hybri) { + if(mhybrid) { V("U", PIU(cgi_string())); - // its(int(hybrid::underlying))); } - if(prod) V("PL", fts(vid.plevel_factor)); + if(mproduct) V("PL", fts(vid.plevel_factor)); if(geometry == gFieldQuotient) { V("S3=", its(S3)); V("S7=", its(S7)); } if(nil) V("NIL", its(S7)); @@ -1242,7 +1398,7 @@ EX void check_cgi() { cgip = &cgis[s]; cgi.timestamp = ++ntimestamp; - if(hybri) hybrid::underlying_cgip->timestamp = ntimestamp; + if(mhybrid) hybrid::underlying_cgip->timestamp = ntimestamp; if(fake::in()) fake::underlying_cgip->timestamp = ntimestamp; #if CAP_ARCM if(arcm::alt_cgip) arcm::alt_cgip->timestamp = ntimestamp; diff --git a/geometry2.cpp b/geometry2.cpp index 64bcce50..f21e77b1 100644 --- a/geometry2.cpp +++ b/geometry2.cpp @@ -100,7 +100,7 @@ transmatrix hrmap_standard::adj(heptagon *h, int d) { int t0 = h->type; int t1 = h->cmove(d)->type; int sp = h->c.spin(d); - return spin(-d * TAU / t0) * xpush(spacedist(h->c7, d)) * spin(M_PI + TAU * sp / t1); + return spin(-d * TAU / t0) * lxpush(spacedist(h->c7, d)) * spin(M_PI + TAU * sp / t1); } transmatrix T = cgi.heptmove[d]; if(h->c.mirror(d)) T = T * Mirror; @@ -235,10 +235,10 @@ void horo_distance::become(hyperpoint h1) { a = abs(bt::horo_level(h1)); } #endif - else if(hybri) + else if(mhybrid) a = 0, b = hdist(h1, C0); else - a = 0, b = intval(h1, C0); + a = 0, b = intval(h1, tile_center()); } horo_distance::horo_distance(shiftpoint h1, const shiftmatrix& T) { @@ -246,7 +246,7 @@ horo_distance::horo_distance(shiftpoint h1, const shiftmatrix& T) { if(bt::in()) become(inverse_shift(T, h1)); else #endif - if(sn::in() || hybri || nil) become(inverse_shift(T, h1)); + if(sn::in() || mhybrid || nil) become(inverse_shift(T, h1)); else a = 0, b = intval(h1.h, unshift(tC0(T), h1.shift)); } @@ -368,7 +368,7 @@ void virtualRebase(cell*& base, T& at, const U& check) { } /* todo variants of sol */ - if(prod) { + if(mproduct) { auto d = product_decompose(check(at)).first; while(d > cgi.plevel / 2) { at = currentmap->iadj(base, base->type-1) * at; @@ -530,7 +530,7 @@ transmatrix hrmap_standard::adj(cell *c, int i) { return calc_relative_matrix(c->cmove(i), c, C0); } double d = cellgfxdist(c, i); - transmatrix T = ddspin(c, i) * xpush(d); + transmatrix T = ddspin(c, i) * lxpush(d); if(c->c.mirror(i)) T = T * Mirror; cell *c1 = c->cmove(i); T = T * iddspin(c1, c->c.spin(i), M_PI); @@ -574,15 +574,15 @@ hyperpoint hrmap_standard::get_corner(cell *c, int cid, ld cf) { } #endif if(PURE) { - return ddspin(c,cid,M_PI/S7) * xpush0(cgi.hcrossf * 3 / cf); + return ddspin(c,cid,M_PI/S7) * lxpush0(cgi.hcrossf * 3 / cf); } if(BITRUNCATED) { if(!ishept(c)) - return ddspin(c,cid,M_PI/S6) * xpush0(cgi.hexvdist * 3 / cf); + return ddspin(c,cid,M_PI/S6) * lxpush0(cgi.hexvdist * 3 / cf); else - return ddspin(c,cid,M_PI/S7) * xpush0(cgi.rhexf * 3 / cf); + return ddspin(c,cid,M_PI/S7) * lxpush0(cgi.rhexf * 3 / cf); } - return C0; + return tile_center(); } EX bool approx_nearcorner = false; @@ -679,7 +679,7 @@ EX hyperpoint nearcorner(cell *c, int i) { } #endif double d = cellgfxdist(c, i); - return ddspin(c, i) * xpush0(d); + return ddspin(c, i) * lxpush0(d); } /** /brief get the coordinates of the another vertex of c->move(i) @@ -728,7 +728,7 @@ EX hyperpoint farcorner(cell *c, int i, int which) { int id = arcm::id_of(c->master); auto id1 = ac.get_adj(ac.get_adj(c->master, i-1), -2).first; int n1 = isize(ac.adjacent[id1]); - return spin(-t.first - M_PI / c->type) * xpush(ac.inradius[id/2] + ac.inradius[id1/2]) * xspinpush0(M_PI + M_PI/n1*(which?3:-3), ac.circumradius[id1/2]); + return spin(-t.first - M_PI / c->type) * lxpush(ac.inradius[id/2] + ac.inradius[id1/2]) * xspinpush0(M_PI + M_PI/n1*(which?3:-3), ac.circumradius[id1/2]); } if(BITRUNCATED || DUAL) { int mul = DUALMUL; @@ -742,7 +742,7 @@ EX hyperpoint farcorner(cell *c, int i, int which) { auto& t2 = arcm::current.get_triangle(adj); - return spin(-t1.first) * xpush(t1.second) * spin(M_PI + t2.first) * get_corner_position(&cx, which ? -mul : 2*mul); + return spin(-t1.first) * lxpush(t1.second) * spin(M_PI + t2.first) * get_corner_position(&cx, which ? -mul : 2*mul); } } #endif @@ -768,7 +768,7 @@ EX hyperpoint get_warp_corner(cell *c, int cid) { #if CAP_IRR || CAP_ARCM if(IRREGULAR || arcm::in()) return midcorner(c, cid, .5); #endif - return ddspin(c,cid,M_PI/S7) * xpush0(cgi.tessf/2); + return ddspin(c,cid,M_PI/S7) * lxpush0(cgi.tessf/2); } EX map>> brm_structure; @@ -899,7 +899,7 @@ EX pathgen generate_random_path(cellwalker start, int length, bool for_yendor, b p.last = p.path.back(); } - else if(hybri) { + else if(mhybrid) { /* I am lazy */ for(int i=1; i<=length; i++) p.path[i] = p.path[i-1]->cmove(p.path[i-1]->type-1); p.last = p.path.back(); diff --git a/goldberg.cpp b/goldberg.cpp index 336d7a37..633c45c1 100644 --- a/goldberg.cpp +++ b/goldberg.cpp @@ -646,7 +646,7 @@ EX namespace gp { } if(sp>SG3) sp -= SG6; - return normalize(spin(TAU*sp/S7) * cornmul(T, corner)); + return normalize_flat(spin(TAU*sp/S7) * cornmul(T, corner)); } transmatrix dir_matrix(int i) { @@ -654,14 +654,15 @@ EX namespace gp { return spin(M_PI - d * TAU / S7 - cgi.hexshift); }; return spin(-cgi.gpdata->alpha) * build_matrix( - C0, - ddspin(i) * xpush0(cgi.tessf), - ddspin(i+1) * xpush0(cgi.tessf), + tile_center(), + ddspin(i) * lxpush0(cgi.tessf), + ddspin(i+1) * lxpush0(cgi.tessf), C03 ); } - void prepare_matrices() { + EX void prepare_matrices(bool inv) { + if(!(GOLDBERG_INV || inv)) return; cgi.gpdata->corners = inverse(build_matrix( loctoh_ort(loc(0,0)), loctoh_ort(param), @@ -669,6 +670,10 @@ EX namespace gp { C03 )); cgi.gpdata->Tf.resize(S7); + + /* should work directly without flipping but it does not... flipping for now */ + + if(embedded_plane) geom3::light_flip(true); for(int i=0; icorners, at, 6); hyperpoint hl = atz(T, cgi.gpdata->corners, at + eudir(d), 6); cgi.gpdata->Tf[i][x&GOLDBERG_MASK][y&GOLDBERG_MASK][d] = rgpushxto0(h) * rspintox(gpushxto0(h) * hl) * spin180(); + // cgi.gpdata->Tf[i][x&GOLDBERG_MASK][y&GOLDBERG_MASK][d] = Id; // map_relative_push(h) * lrspintox(inverse(map_relative_push(h)) * hl) * spin180(); } } + + if(geom3::flipped) { + geom3::light_flip(false); + for(int i=0; iTf[i][x&GOLDBERG_MASK][y&GOLDBERG_MASK][d] ); + } + } } } EX hyperpoint get_corner_position(const local_info& li, int cid, ld cf IS(3)) { @@ -729,7 +745,6 @@ EX namespace gp { cgi.base_distlimit = 2 * param.first + 2 * param.second + 1; if(cgi.base_distlimit > SEE_ALL) cgi.base_distlimit = SEE_ALL; - prepare_matrices(); DEBB(DF_GEOM | DF_POLY, ("scale = ", scale)); } } diff --git a/graph.cpp b/graph.cpp index aaed131c..338d125b 100644 --- a/graph.cpp +++ b/graph.cpp @@ -393,7 +393,7 @@ EX void drawPlayerEffects(const shiftmatrix& V, const shiftmatrix& Vparam, cell int adj = 1 - ((sword_angles/cwt.at->type)&1); #if CAP_QUEUE - if(!euclid && !hybri) for(int a=0; astuntime >= 3) @@ -2641,7 +2641,7 @@ EX bool applyAnimation(cell *c, shiftmatrix& V, double& footphase, int layer) { else wnow = tC0(z_inverse(a.wherenow)); - if(prod) { + if(gproduct) { auto d = product_decompose(wnow); ld dist = d.first / R * aspd; if(abs(dist) > abs(d.first)) dist = -d.first; @@ -2856,8 +2856,8 @@ EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, col else { if(c->monst == moTentacleGhost) { hyperpoint V0 = history::on ? unshift(tC0(Vs)) : inverse_shift(cwtV, tC0(Vs)); - hyperpoint V1 = spintox(V0) * V0; - Vs = cwtV * rspintox(V0) * rpushxto0(V1) * pispin; + hyperpoint V1 = lspintox(V0) * V0; + Vs = cwtV * lrspintox(V0) * rpushxto0(V1) * pispin; drawMonsterType(moGhost, c, Vs, col, footphase, asciicol); col = minf[moTentacletail].color; } @@ -2904,7 +2904,7 @@ EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, col if(mmmon) { if(isAnyIvy(c)) { - if(hybri) { + if(mhybrid) { queuepoly(Vb, cgi.shILeaf[ctof(c)], darkena(col, 0, 0xFF)); for(int a=0; atype-2; a++) queuepoly(Vb * spin(a * TAU / (c->type-2)), cgi.shILeaf[2], darkena(col, 0, 0xFF)); @@ -3092,7 +3092,7 @@ EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, col } else if(NONSTDVAR) { transmatrix T = currentmap->adj(c, c->mondir); - Vb = Vb * T * rspintox(tC0(iso_inverse(T))) * xpush(cgi.tentacle_length); + Vb = Vb * T * lrspintox(tC0(iso_inverse(T))) * xpush(cgi.tentacle_length); } else { Vb = Vb * ddspin180(c, c->mondir); @@ -3129,27 +3129,27 @@ EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, col if(!nospins) { shiftmatrix& where = (c->monst == moMirrorSpirit && inmirrorcount) ? ocwtV : cwtV; - if(WDIM == 2 || prod) { - hyperpoint V0 = inverse_shift(Vs, tC0(where)); + if(WDIM == 2 || mproduct) { + hyperpoint V0 = inverse_shift(Vs, where * tile_center()); ld z = 0; - if(prod) { + if(gproduct) { auto d = product_decompose(V0); z = d.first; V0 = d.second; } if(hypot_d(2, tC0(unshift(Vs))) > 1e-3) { - Vs = Vs * rspintox(V0); - if(prod) Vs = orthogonal_move(Vs, z); + Vs = Vs * lrspintox(V0); + if(gproduct) Vs = orthogonal_move(Vs, z); } } else if(!sl2) { hyperpoint V0 = inverse_shift(Vs, tC0(where)); - Vs = Vs * rspintox(V0); + Vs = Vs * lrspintox(V0); // cwtV * rgpushxto0(inverse(cwtV) * tC0(Vs)); } if(c->monst == moHunterChanging) - Vs = Vs * (hybri ? spin180() : cspin180(WDIM-2, WDIM-1)); + Vs = Vs * (mhybrid ? spin180() : cspin180(WDIM-2, WDIM-1)); } if(c->monmirror) Vs = Vs * Mirror; @@ -3518,7 +3518,7 @@ void draw_movement_arrows(cell *c, const transmatrix& V, int df) { transmatrix Centered = rgpushxto0(unshift(tC0(cwtV))); int sd = md.subdir; - transmatrix T = iso_inverse(Centered) * rgpushxto0(Centered * tC0(V)) * rspintox(Centered*tC0(V)) * spin(-sd * M_PI/S7) * xpush(0.2); + transmatrix T = iso_inverse(Centered) * rgpushxto0(Centered * tC0(V)) * lrspintox(Centered*tC0(V)) * spin(-sd * M_PI/S7) * xpush(0.2); if(vid.axes >= 5) queuestr(shiftless(T), keysize, s0 + key, col >> 8, 1); @@ -3994,7 +3994,7 @@ EX color_t transcolor(cell *c, cell *c2, color_t wcol) { // how much should be the d-th wall darkened in 3D EX int get_darkval(cell *c, int d) { - if(hybri) { + if(mhybrid) { return d >= c->type - 2 ? 4 : 0; } const int darkval_hbt[9] = {0,2,2,0,6,6,8,8,0}; @@ -4054,7 +4054,7 @@ EX bool clip_checked = false; void make_clipping_planes() { #if MAXMDIM >= 4 clip_checked = false; - if(!frustum_culling || PIU(sphere) || experimental || vid.stereo_mode == sODS || panini_alpha || stereo_alpha || prod) return; + if(!frustum_culling || PIU(sphere) || experimental || vid.stereo_mode == sODS || panini_alpha || stereo_alpha || gproduct || embedded_plane) return; if(WDIM == 3 && pmodel == mdPerspective && !nonisotropic && !in_s2xe()) threshold = sin_auto(cgi.corner_bonus), xyz_threshold = 0, clip_checked = true; @@ -4221,26 +4221,26 @@ EX subcellshape& generate_subcellshape_if_needed(cell *c, int id) { auto& ss = cgi.subshapes[id]; if(!ss.faces.empty()) return ss; - cell *c1 = hybri ? hybrid::get_where(c).first : c; + cell *c1 = mhybrid ? hybrid::get_where(c).first : c; - if(hybri || WDIM == 2) for(int i=0; itype; i++) { + if(mhybrid || WDIM == 2) for(int i=0; itype; i++) { hyperpoint w; auto f = [&] { /* mirror image of C0 in the axis h1-h2 */ hyperpoint h1 = get_corner_position(c1, i); hyperpoint h2 = get_corner_position(c1, i+1); transmatrix T = gpushxto0(h1); - T = spintox(T * h2) * T; + T = lspintox(T * h2) * T; w = T * C0; w[1] = -w[1]; w = iso_inverse(T) * w; }; - if(prod) PIU(f()); + if(mproduct) PIU(f()); else f(); ss.walltester.push_back(w); } - if(hybri || WDIM == 2) { + if(mhybrid || WDIM == 2) { ss.walltester.push_back(C0); ss.walltester.push_back(C0); } @@ -4253,7 +4253,7 @@ EX subcellshape& generate_subcellshape_if_needed(cell *c, int id) { int z = a ? 1 : -1; hyperpoint ctr = zpush0(z * cgi.plevel/2); for(int i=0; itype; i++) - if(prod || WDIM == 2) + if(mproduct || WDIM == 2) l.push_back(hybrid::get_corner(c1, i, 0, z)); else { l.push_back(ctr); @@ -4274,7 +4274,7 @@ EX subcellshape& generate_subcellshape_if_needed(cell *c, int id) { int hrmap::wall_offset(cell *c) { int id = currentmap->full_shvid(c); - if(WDIM == 3 && !hybri && !reg3::in()) return 0; + if(WDIM == 3 && !mhybrid && !reg3::in()) return 0; if(isize(cgi.walloffsets) <= id) cgi.walloffsets.resize(id+1, {-1, nullptr}); auto &wop = cgi.walloffsets[id]; @@ -4791,7 +4791,7 @@ EX void drawMarkers() { #endif - if(hybri && !shmup::on) { + if(mhybrid && !shmup::on) { using namespace sword; int& ang = sword::dir[multi::cpid].angle; @@ -4854,7 +4854,7 @@ EX void drawMarkers() { auto& c2 = mib.t; shiftmatrix T1 = ggmatrix(c1); shiftmatrix T2 = ggmatrix(c2); - shiftmatrix T = T1 * rspintox(inverse_shift(T1,T2*C0)) * xpush(hdist(T1*C0, T2*C0) * fractick(50, 0)); + shiftmatrix T = T1 * lrspintox(inverse_shift(T1,T2*C0)) * xpush(hdist(T1*C0, T2*C0) * fractick(50, 0)); color_t aircol = (orbToTarget == itOrbAir ? 0x8080FF40 : 0x8080FF20); queuepoly(T, cgi.shDisk, aircol); c1 = c2; @@ -5017,7 +5017,7 @@ EX transmatrix actual_view_transform; EX ld wall_radar(cell *c, transmatrix T, transmatrix LPe, ld max) { if(!in_perspective() || !vid.use_wall_radar) return max; transmatrix ori; - if(prod) ori = ortho_inverse(LPe); + if(gproduct) ori = ortho_inverse(LPe); ld step = max / 20; ld fixed_yshift = 0; for(int i=0; i<20; i++) { @@ -5052,6 +5052,7 @@ EX void make_actual_view() { actual_view_transform = get_shift_view_of(ztangent(d), actual_view_transform * View) * view_inverse(View); } camera_level = asin_auto(tC0(view_inverse(actual_view_transform * View))[2]); + camera_sign = cgi.FLOOR > cgi.WALL; } if(nonisotropic && !nonisotropic_weird_transforms) { transmatrix T = actual_view_transform * View; @@ -5099,7 +5100,7 @@ EX void precise_mouseover() { if(WDIM == 3 && (cmode & (sm::EDIT_INSIDE_WALLS | sm::EDIT_BEFORE_WALLS))) { transmatrix T = view_inverse(View); transmatrix ori = Id; - if(prod) ori = ortho_inverse(NLP); + if(gproduct) ori = ortho_inverse(NLP); ld step = 0.2; cell *c = centerover; for(int i=0; i<100; i++) { @@ -5175,7 +5176,7 @@ EX void center_multiplayer_map(const vector& hs) { hyperpoint h = Hypc; for(auto h1: hs) h += h1; h /= isize(hs); - h = normalize(h); + h = normalize_flat(h); cwtV = shiftless(rgpushxto0(h)); if(isize(hs) == 2) { set_multi = true; @@ -5307,7 +5308,7 @@ EX void drawthemap() { else { vector pts; for(int p=0; p pts; for(int p=0; ppat))); + pts.push_back(unshift(shmup::pc[p]->pat * tile_center())); center_multiplayer_map(pts); } } @@ -5361,7 +5362,7 @@ EX void drawmovestar(double dx, double dy) { if(rug::rugged && multi::players == 1 && !multi::alwaysuse) return; #endif - shiftpoint H = tC0(cwtV); + shiftpoint H = cwtV * tile_center(); ld R = sqrt(H[0] * H[0] + H[1] * H[1]); shiftmatrix Centered; @@ -5886,7 +5887,7 @@ EX void restartGraph() { if(!autocheat) linepatterns::clearAll(); if(currentmap) { resetview(); - if(sphere) View = spin(-90._deg); + View = inverse(View); } } @@ -6001,7 +6002,7 @@ EX void animateAttackOrHug(const movei& m, int layer, int phase, ld ratio, ld de animation& a = animations[layer][m.s]; a.attacking = phase; if(phase == 3) println(hlog, "distance = ", hdist0(T * C0)); - a.attackat = rspintox(tC0(iso_inverse(T))) * xpush(hdist0(T*C0) * ratio + delta); + a.attackat = lrspintox(tC0(iso_inverse(T))) * lxpush(hdist0(T*C0) * ratio + delta); if(newanim) a.wherenow = Id, a.ltick = ticks, a.footphase = 0; } diff --git a/heptagon.cpp b/heptagon.cpp index 87a2ca32..39dd25d5 100644 --- a/heptagon.cpp +++ b/heptagon.cpp @@ -25,6 +25,7 @@ cell *newCell(int type, heptagon *master); */ EX hstate transition(hstate s, int dir) { + if(embedded_plane) return IPF(transition(s, dir)); if(sphere) { if(S7 == 4) { if(s == hsOrigin) return dir == 0 ? hsB0 : hsB1; diff --git a/history.cpp b/history.cpp index 44353b9e..dca30375 100644 --- a/history.cpp +++ b/history.cpp @@ -372,7 +372,7 @@ EX namespace history { v[ph+1]->at * C0; View = xpush(-(phase-ph) * hdist(now, next)) * View; - if(WDIM == 2 || prod) { + if(WDIM == 2 || mproduct) { View = models::rotmatrix() * View; } else { diff --git a/hyper.h b/hyper.h index 1332b820..fdf9e128 100644 --- a/hyper.h +++ b/hyper.h @@ -148,8 +148,6 @@ void addMessage(string s, char spamtype = 0); #define nih (cgflags & qNIH) #define nil (cgclass == gcNil) #define sl2 (cgclass == gcSL2) -#define prod (cgclass == gcProduct) -#define hybri (cgflags & qHYBRID) #define rotspace (geometry == gRotSpace) #define hyperbolic (cgclass == gcHyperbolic) #define nonisotropic (among(cgclass, gcSolNIH, gcNil, gcSL2)) @@ -160,6 +158,19 @@ void addMessage(string s, char spamtype = 0); #define smallbounded ((cgflags & qSMALL) || disksize) #define closed_manifold (cgflags & qCLOSED) #define closed_or_bounded (closed_manifold || disksize) +/** the actual map has hybrid geometry, not just the graphics */ +#define mhybrid (cgflags & qHYBRID) +/** graphics based on a product geometry -- either embedded or actual hybrid product */ +#define gproduct (cgclass == gcProduct) + +/** 2D geometry embedded in 3D */ +#define embedded_plane (WDIM == 2 && GDIM == 3) +/** the actual map is product, not just the graphics */ +#define mproduct (gproduct && !embedded_plane) +/** the actual map is product, not just the graphics */ +#define meuclid (geom3::mgclass() == gcEuclid) +#define msphere (geom3::mgclass() == gcSphere) +#define mhyperbolic (geom3::mgclass() == gcHyperbolic) // Dry Forest burning, heat transfer, etc. are performed on the whole universe #define doall (closed_or_bounded) diff --git a/hyperpoint.cpp b/hyperpoint.cpp index e958f199..1431665e 100644 --- a/hyperpoint.cpp +++ b/hyperpoint.cpp @@ -389,6 +389,13 @@ EX ld edge_of_triangle_with_angles(ld alpha, ld beta, ld gamma) { EX hyperpoint hpxy(ld x, ld y) { if(sl2) return hyperpoint(x, y, 0, sqrt(1+x*x+y*y)); if(rotspace) return hyperpoint(x, y, 0, sqrt(1-x*x-y*y)); + if(embedded_plane) { + geom3::light_flip(true); + hyperpoint h = hpxy(x, y); + geom3::light_flip(false); + swapmatrix(h); + return h; + } return PIU(hpxyz(x,y, translatable ? 1 : sphere ? sqrt(1-x*x-y*y) : sqrt(1+x*x+y*y))); } @@ -427,7 +434,7 @@ EX ld intval(const hyperpoint &h1, const hyperpoint &h2) { } EX ld quickdist(const hyperpoint &h1, const hyperpoint &h2) { - if(prod) return hdist(h1, h2); + if(gproduct) return hdist(h1, h2); return intval(h1, h2); } @@ -515,7 +522,7 @@ EX ld zlevel(const hyperpoint &h) { else if(translatable) return h[LDIM]; else if(sphere) return sqrt(intval(h, Hypc)); else if(in_e2xe()) return log(h[2]); - else if(prod) return log(sqrt(abs(intval(h, Hypc)))); /* abs works with both underlying spherical and hyperbolic */ + else if(gproduct) return log(sqrt(abs(intval(h, Hypc)))); /* abs works with both underlying spherical and hyperbolic */ else return (h[LDIM] < 0 ? -1 : 1) * sqrt(-intval(h, Hypc)); } @@ -534,7 +541,7 @@ EX ld hypot_auto(ld x, ld y) { /** normalize the homogeneous coordinates */ EX hyperpoint normalize(hyperpoint H) { - if(prod) return H; + if(gproduct) return H; ld Z = zlevel(H); for(int c=0; c 0) h[0] /= z, h[1] /= z, h[2] /= z; + h[3] = 1; + return h; + } + if(geom3::sph_in_hyp()) { + ld z = hypot_d(3, h); + z = sinh(1) / z; + if(z > 0) h[0] *= z, h[1] *= z, h[2] *= z; + h[3] = cosh(1); + return h; + } return normalize(h); } /** get the center of the line segment from H1 to H2 */ EX hyperpoint mid(const hyperpoint& H1, const hyperpoint& H2) { - if(prod) { + if(gproduct) { auto d1 = product_decompose(H1); auto d2 = product_decompose(H2); - return orthogonal_move(PIU( mid(d1.second, d2.second) ), (d1.first + d2.first) / 2); + hyperpoint res1 = PIU( mid(d1.second, d2.second) ); + hyperpoint res = orthogonal_move(res1, (d1.first + d2.first) / 2); + return res; } return normalize(H1 + H2); } @@ -571,7 +599,7 @@ EX shiftpoint mid(const shiftpoint& H1, const shiftpoint& H2) { /** like mid, but take 3D into account */ EX hyperpoint midz(const hyperpoint& H1, const hyperpoint& H2) { - if(prod) return mid(H1, H2); + if(gproduct) return mid(H1, H2); hyperpoint H3 = H1 + H2; ld Z = 2; @@ -691,7 +719,7 @@ EX transmatrix euaffine(hyperpoint h) { } EX transmatrix cpush(int cid, ld alpha) { - if(prod && cid == 2) + if(gproduct && cid == 2) return scale_matrix(Id, exp(alpha)); transmatrix T = Id; if(nonisotropic) @@ -703,6 +731,7 @@ EX transmatrix cpush(int cid, ld alpha) { } EX transmatrix lzpush(ld z) { + if(geom3::euc_in_hyp() && !destandarize_eih) return cpush(0, z); return cpush(2, z); } @@ -715,6 +744,17 @@ EX transmatrix cmirror(int cid) { // push alpha units to the right EX transmatrix xpush(ld alpha) { return cpush(0, alpha); } +EX transmatrix lxpush(ld alpha) { + if(WDIM == 2 && GDIM == 3) { + geom3::light_flip(true); + auto t = cpush(0, alpha); + geom3::light_flip(false); + swapmatrix(t); + return t; + } + return cpush(0, alpha); + } + EX bool eqmatrix(transmatrix A, transmatrix B, ld eps IS(.01)) { for(int i=0; i= 4 /** in the 3D space, move the point h orthogonally to the (x,y) plane by z units */ EX hyperpoint orthogonal_move(const hyperpoint& h, ld z) { + if(geom3::euc_in_hyp()) { + hyperpoint hf = deparabolic13(h); + hf[2] += z; + return parabolic13(hf); + } + if(geom3::sph_in_euc()) { + ld z0 = hypot_d(3, h); + ld f = ((z0 + z) / z0); + hyperpoint hf; + for(int i=0; i<3; i++) hf[i] = h[i] * f; + hf[3] = 1; + return hf; + } + if(geom3::sph_in_hyp()) { + ld z0 = acosh(h[3]); + ld f = sinh(z0 + z) / sinh(z0); + hyperpoint hf; + for(int i=0; i<3; i++) hf[i] = h[i] * f; + hf[3] = cosh(z0 + z); + return hf; + } if(GDIM == 2) return scale_point(h, geom3::scale_at_lev(z)); - if(prod) return scale_point(h, exp(z)); + if(gproduct) return scale_point(h, exp(z)); if(sl2) return slr::translate(h) * cpush0(2, z); if(!hyperbolic) return rgpushxto0(h) * cpush(2, z) * C0; if(nil) return nisot::translate(h) * cpush0(2, z); @@ -764,19 +825,44 @@ EX transmatrix matrix4(ld a, ld b, ld c, ld d, ld e, ld f, ld g, ld h, ld i, ld } #if MAXMDIM >= 4 +/** Transform a matrix between the 'embedded_plane' and underlying representation. Switches to the current variant. */ EX void swapmatrix(transmatrix& T) { - for(int i=0; i<4; i++) swap(T[i][2], T[i][3]); - for(int i=0; i<4; i++) swap(T[2][i], T[3][i]); - if(GDIM == 3) { - for(int i=0; i<4; i++) T[i][2] = T[2][i] = 0; - T[2][2] = 1; + if(geom3::euc_in_hyp() && !geom3::flipped) { + geom3::light_flip(true); + hyperpoint mov = T * C02; + transmatrix U = gpushxto0(mov) * T; + geom3::light_flip(false); + for(int i=0; i<4; i++) U[i][3] = U[3][i] = i == 3; + T = parabolic13(mov[0], mov[1]) * U; + } + else if(geom3::sph_in_euc() || geom3::sph_in_hyp()) { + if(!geom3::flipped) { + for(int i=0; i<4; i++) T[i][3] = T[3][i] = i == 3; + } + } + else if(geom3::in_product()) { + /* just do nothing */ + } + else { + for(int i=0; i<4; i++) swap(T[i][2], T[i][3]); + for(int i=0; i<4; i++) swap(T[2][i], T[3][i]); + if(GDIM == 3) { + for(int i=0; i<4; i++) T[i][2] = T[2][i] = 0; + T[2][2] = 1; + } } fixmatrix(T); - for(int i=0; i<4; i++) for(int j=0; j<4; j++) if(isnan(T[i][j])) T = Id; + for(int i=0; i 0) for(int i=0; i b + M_PI) a -= TAU; @@ -1617,7 +1768,7 @@ EX unsigned bucketer(ld x) { EX unsigned bucketer(hyperpoint h) { unsigned dx = 0; - if(prod) { + if(gproduct) { auto d = product_decompose(h); h = d.second; dx += bucketer(d.first) * 50; diff --git a/hypgraph.cpp b/hypgraph.cpp index ba6b93cb..98457f84 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -13,7 +13,7 @@ shiftpoint ghpm = shiftless(C02); EX ld flip_limit = 1.1; -EX bool flip_sphere() { return sphere && pconf.alpha > flip_limit; } +EX bool flip_sphere() { return GDIM == 2 && sphere && pconf.alpha > flip_limit; } EX bool sphere_flipped; @@ -516,7 +516,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) { switch(md) { case mdPerspective: { - if(prod) H = product::inverse_exp(H); + if(gproduct) H = product::inverse_exp(H); apply_nil_rotation(H); H = lp_apply(H); apply_perspective(H, ret); @@ -888,7 +888,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) { ret = lp_apply(H); break; } - if(prod) { + if(gproduct) { ret = H; break; } @@ -1259,7 +1259,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) { return; } - if(nonisotropic || prod) { + if(nonisotropic || gproduct) { ret = lp_apply(inverse_exp(H_orig)); ret[3] = 1; break; @@ -1557,7 +1557,7 @@ EX bool confusingGeometry() { } EX ld master_to_c7_angle() { - if(hybri) return hybrid::in_underlying_geometry(master_to_c7_angle); + if(mhybrid) return hybrid::in_underlying_geometry(master_to_c7_angle); if(WDIM == 3) return 0; ld alpha = 0; #if CAP_GP @@ -1567,7 +1567,7 @@ EX ld master_to_c7_angle() { } EX transmatrix actualV(const heptspin& hs, const transmatrix& V) { - if(prod) return PIU(actualV(hs, V)); + if(gproduct) return PIU(actualV(hs, V)); if(WDIM == 3) return V; #if CAP_IRR if(IRREGULAR) @@ -1592,7 +1592,7 @@ EX bool point_behind(const shiftpoint h) { if(!in_perspective()) return false; hyperpoint h1; if(pmodel == mdGeodesic) h1 = inverse_exp(h, pQUICK); - if(pmodel == mdPerspective && prod) h1 = product::inverse_exp(h.h); + if(pmodel == mdPerspective && gproduct) h1 = product::inverse_exp(h.h); h1 = lp_apply(h1); return h1[2] < 1e-8; } @@ -1605,7 +1605,7 @@ EX bool invalid_matrix(const transmatrix T) { for(int i=0; i 1e8 || T[i][j] < -1e8 || std::isinf(T[i][j])) return true; - if(prod || (cgflags & qAFFINE)) { + if(gproduct || (cgflags & qAFFINE)) { for(int i=0; i 1e-60) return false; } else @@ -1632,13 +1632,17 @@ EX bool in_smart_range(const shiftmatrix& T) { ld x = current_display->xcenter + current_display->radius * h1[0]; ld y = current_display->ycenter + current_display->radius * h1[1] * pconf.stretch; - if(x > current_display->xtop + current_display->xsize * 2) return false; - if(x < current_display->xtop - current_display->xsize * 1) return false; - if(y > current_display->ytop + current_display->ysize * 2) return false; - if(y < current_display->ytop - current_display->ysize * 1) return false; - if(GDIM == 3) { - if(-h1[2] < pconf.clip_min * 2 - pconf.clip_max) return false; - if(-h1[2] > pconf.clip_max * 2 - pconf.clip_min) return false; + bool culling = !geom3::euc_in_hyp(); + + if(culling) { + if(x > current_display->xtop + current_display->xsize * 2) return false; + if(x < current_display->xtop - current_display->xsize * 1) return false; + if(y > current_display->ytop + current_display->ysize * 2) return false; + if(y < current_display->ytop - current_display->ysize * 1) return false; + if(GDIM == 3) { + if(-h1[2] < pconf.clip_min * 2 - pconf.clip_max) return false; + if(-h1[2] > pconf.clip_max * 2 - pconf.clip_min) return false; + } } ld epsilon = 0.01; @@ -1675,6 +1679,8 @@ EX bool in_smart_range(const shiftmatrix& T) { ld scale = sqrt(dh[0] * dh[1]) * cgi.scalefactor * hcrossf7; if(scale <= vid.smart_range_detail) return false; } + + if(!culling) return true; return x - 2 * dx < current_display->xtop + current_display->xsize && @@ -1889,16 +1895,25 @@ void hrmap_standard::draw_at(cell *at, const shiftmatrix& where) { } EX bool keep_vertical() { - if((WDIM == 2 || prod) && GDIM == 3 && vid.fixed_yz) return !CAP_ORIENTATION; + if((WDIM == 2 || gproduct) && GDIM == 3 && vid.fixed_yz) return !CAP_ORIENTATION; if(downseek.qty) return true; return false; } EX hyperpoint vertical_vector() { auto& ds = downseek; - if((WDIM == 2 || prod) && GDIM == 3 && vid.fixed_yz) - return get_view_orientation() * ztangent(1); - else if(ds.qty && prod) + if(msphere && !sphere && vid.fixed_yz) { + hyperpoint h = get_view_orientation() * C0; + if(vid.wall_height > 0) h = -h; + return h; + } + if(meuclid && hyperbolic && vid.fixed_yz) { + hyperpoint h = iso_inverse(View) * C0; + return View * (orthogonal_move(h, vid.wall_height) - h); + } + if((WDIM == 2 || gproduct) && GDIM == 3 && vid.fixed_yz) + return get_view_orientation() * lztangent(1); + else if(ds.qty && gproduct) return get_view_orientation() * product::inverse_exp(ds.point); else if(ds.qty) return ds.point; @@ -1918,7 +1933,7 @@ EX void spinEdge(ld aspd) { transmatrix V = T * get_view_orientation(); hyperpoint h = inverse(V) * C0; - if(!prod) { + if(!gproduct) { V = V * rgpushxto0(h); } @@ -1943,7 +1958,7 @@ EX void spinEdge(ld aspd) { V = cspin90(dir, 2) * V; V = inverse(T) * V; - if(!prod) V = V * gpushxto0(h); + if(!gproduct) V = V * gpushxto0(h); get_view_orientation() = V; return; } @@ -2009,6 +2024,16 @@ void fix_whichcopy_if_near() { current_display->which_copy = T; } +EX void adjust_eye(transmatrix& T, cell *c) { + if(!embedded_plane) return; + geom3::do_auto_eye(); + int sl = snakelevel(c); + if(isWorm(c->monst) && sl < 3) sl++; + int i = (msphere && !sphere) ? 1 : 0; + if(sl || vid.eye || i) + T = T * lzpush(cgi.SLEV[sl] - cgi.FLOOR + vid.eye + i); + } + EX void centerpc(ld aspd) { if(subscreens::split([=] () {centerpc(aspd);})) return; @@ -2029,14 +2054,13 @@ EX void centerpc(ld aspd) { auto& pc = shmup::pc[id]; centerover = pc->base; transmatrix T = pc->at; - int sl = snakelevel(cwt.at); - if((sl || vid.eye) && WDIM == 2) T = T * zpush(cgi.SLEV[sl] - cgi.FLOOR + vid.eye); + adjust_eye(T, cwt.at); /* in nonisotropic geometries, T is isometry * rotation, so iso_inverse does not work */ if(nonisotropic) View = inverse(T); else View = iso_inverse(T); - if(prod) NLP = ortho_inverse(pc->ori); + if(gproduct) NLP = ortho_inverse(pc->ori); if(WDIM == 2) rotate_view( cspin180(0, 1) * cspin(2, 1, 90._deg + shmup::playerturny[id]) * spin270() ); return; } @@ -2061,22 +2085,17 @@ EX void centerpc(ld aspd) { if(invalid_matrix(T)) return; - #if MAXMDIM >= 4 - if(GDIM == 3 && WDIM == 2) { - geom3::do_auto_eye(); - int sl = snakelevel(cwt.at); - if(isWorm(cwt.at->monst) && sl < 3) sl++; - if(sl || vid.eye) T = T * zpush(cgi.SLEV[sl] - cgi.FLOOR + vid.eye); - } - #endif - + adjust_eye(T, cwt.at); + hyperpoint H = tC0(T); - ld R = (zero_d(GDIM, H) && !prod) ? 0 : hdist0(H); + + ld R = (zero_d(GDIM, H) && !gproduct) ? 0 : hdist0(H); if(R < 1e-9) { // either already centered or direction unknown /* if(playerfoundL && playerfoundR) { } */ + spinEdge(aspd); fixmatrix(View); fix_whichcopy(cwt.at); @@ -2182,6 +2201,7 @@ EX void resetview() { if(cwt.at) { centerover = cwt.at; View = iddspin(cwt.at, cwt.spin); + adjust_eye(View, cwt.at); if(!flipplayer) View = pispin * View; if(cwt.mirrored) View = Mirror * View; @@ -2197,21 +2217,22 @@ EX void resetview() { } if(GDIM == 2) View = spin(M_PI + vid.fixed_facing_dir * degree) * View; - if(GDIM == 3 && !prod) View = cspin90(0, 2) * View; - if(prod) NLP = cspin90(0, 2); + if(GDIM == 3 && !gproduct) View = cspin90(0, 2) * View; + if(gproduct) NLP = cspin90(0, 2); if(cheater && eqmatrix(View, lView) && !centering) { - View = Id; + View = Id; adjust_eye(View, cwt.at); static ld cyc = 0; cyc += 90._deg; View = spin(cyc) * View; if(GDIM == 2) View = spin(M_PI + vid.fixed_facing_dir * degree) * View; - if(GDIM == 3 && !prod) View = cspin90(0, 2) * View; + if(GDIM == 3 && !gproduct) View = cspin90(0, 2) * View; } } else if(currentmap) { centerover = currentmap->gamestart(); - View = Id; + View = Id; adjust_eye(View, cwt.at); } + cwtV = shiftless(View); current_display->which_copy = nonisotropic ? gpushxto0(tC0(view_inverse(View))) : @@ -2237,7 +2258,7 @@ EX void fullcenter() { if(playerfound && false) centerpc(INF); else { bfs(); - resetview(); + resetview(); View = inverse(View); drawthemap(); if(!centering) centerpc(INF); centerover = cwt.at; @@ -2539,7 +2560,7 @@ void queuestraight(hyperpoint X, int style, color_t lc, color_t fc, PPR p) { EX void draw_boundary(int w) { if(w == 1) return; - if(nonisotropic || euclid || prod) return; + if(nonisotropic || euclid || gproduct) return; #if CAP_VR if(vrhr::active() && pmodel == mdHyperboloid) return; #endif @@ -3039,7 +3060,7 @@ EX int cone_side(const shiftpoint H) { /** get the current orientation of the view */ EX transmatrix& get_view_orientation() { - return prod ? NLP : View; + return gproduct ? NLP : View; } EX hookset hooks_rotate_view; @@ -3050,7 +3071,7 @@ EX void rotate_view(transmatrix T) { if(callhandlers(false, hooks_rotate_view, T)) return; transmatrix& which = get_view_orientation(); which = T * which; - if(!prod && !rug::rugged) current_display->which_copy = T * current_display->which_copy; + if(!gproduct && !rug::rugged) current_display->which_copy = T * current_display->which_copy; } EX hyperpoint lie_exp(hyperpoint h) { @@ -3186,7 +3207,7 @@ EX transmatrix get_shift_view_of(const hyperpoint H, const transmatrix V) { else if(!nisot::geodesic_movement) { transmatrix IV = view_inverse(View); transmatrix view_shift = eupush( tC0(IV) ); - transmatrix rot = View * view_shift; + transmatrix rot = V * view_shift; hyperpoint tH = lie_exp(inverse(rot) * H); return rot * eupush(tH) * inverse(view_shift); } @@ -3211,25 +3232,66 @@ EX void shift_view(hyperpoint H) { wc = get_shift_view_of(H, wc); } -void multiply_view(transmatrix T) { +/** works in embedded_plane and isotropic spaces */ +void shift_view_isotropic(transmatrix T) { + + if(embedded_plane) { + transmatrix IV = view_inverse(View); + transmatrix rot = View * map_relative_push(IV * C0); + View = T * View; + transmatrix IV1 = view_inverse(View); + transmatrix rot1 = View * map_relative_push(IV1 * C0); + View = rot * inverse(rot1) * View; + auto& wc = current_display->which_copy; + wc = rot * inverse(rot1) * T * wc; + return; + } + View = T * View; auto& wc = current_display->which_copy; wc = T * wc; } +/* like rgpushxto0 but keeps the map orientation correct */ +EX transmatrix map_relative_push(hyperpoint h) { + if(!embedded_plane) return rgpushxto0(h); + if(geom3::same_in_same()) { + ld z = -asin_auto(h[2]); + ld u = 1 / cos_auto(z); + auto h1 = hpxy3(h[0] * u, h[1] * u, 0); + + transmatrix T = rgpushxto0(h1) * zpush(-z); + return T; + } + if(geom3::euc_in_hyp()) { + auto h1 = deparabolic13(h); + return parabolic13_at(h1); + } + if(msphere) { + ld z = hdist0(h); + geom3::light_flip(true); + auto h1 = normalize(h); + transmatrix T = rgpushxto0(h1); + geom3::light_flip(false); + return T * zpush(z); + } + return rgpushxto0(h); + } + EX void shift_view_to(shiftpoint H) { - if(!nonisotropic) multiply_view(gpushxto0(unshift(H))); + if(!nonisotropic) + shift_view_isotropic(gpushxto0(unshift(H))); else shift_view(-inverse_exp(H)); } EX void shift_view_towards(shiftpoint H, ld l) { - if(!nonisotropic && !prod) - multiply_view(rspintox(unshift(H)) * xpush(-l) * spintox(unshift(H))); + if(!nonisotropic && !gproduct) + shift_view_isotropic(rspintox(unshift(H)) * xpush(-l) * spintox(unshift(H))); else if(nonisotropic && !nisot::geodesic_movement) shift_view(tangent_length(unshift(H)-C0, -l)); else { hyperpoint ie = inverse_exp(H, pNORMAL | pfNO_DISTANCE); - if(prod) ie = lp_apply(ie); + if(gproduct) ie = lp_apply(ie); shift_view(tangent_length(ie, -l)); } } @@ -3279,7 +3341,7 @@ EX void set_view(hyperpoint camera, hyperpoint forward, hyperpoint upward) { if(det(rotator) < 0) rotator[0] = -rotator[0]; View = iso_inverse(rgpushxto0(camera)); - if(prod) + if(gproduct) NLP = rotator; else View = rotator * View; diff --git a/intra.cpp b/intra.cpp index 6758b08d..5e7022ca 100644 --- a/intra.cpp +++ b/intra.cpp @@ -49,7 +49,7 @@ struct portal_data { #endif hyperpoint portal_data::to_poco(hyperpoint h) const { - if(prod && kind == 1) { + if(mproduct && kind == 1) { auto dec = product_decompose(h); h = dec.second; if(bt::in()) { @@ -67,7 +67,7 @@ hyperpoint portal_data::to_poco(hyperpoint h) const { if(d<0) h[2] = -h[2], h[0] = -h[0]; return h; } - else if(prod && kind == 0) { + else if(mproduct && kind == 0) { h = T * h; ld z = product_decompose(h).first; h /= exp(z); @@ -105,7 +105,7 @@ hyperpoint portal_data::to_poco(hyperpoint h) const { } hyperpoint portal_data::from_poco(hyperpoint h) const { - if(prod && kind == 1) { + if(mproduct && kind == 1) { ld xd = h[2]; if(d<0) xd = -xd, h[0] = -h[0]; #if CAP_BT @@ -118,7 +118,7 @@ hyperpoint portal_data::from_poco(hyperpoint h) const { auto z = product_decompose(h).first; return iT * h * exp(d+xd-z); } - else if(prod && kind == 0) { + else if(mproduct && kind == 0) { auto h0 = h; h[0] = sin_auto(h0[2]); h[1] = sin_auto(h0[0]) * cos_auto(h0[2]); @@ -156,7 +156,7 @@ EX portal_data make_portal(cellwalker cw, int spin) { id.scale = 1; id.T = Id; auto gg = geometry; - if(prod && cw.spin >= cw.at->type - 2) { + if(mproduct && cw.spin >= cw.at->type - 2) { id.kind = 1; id.d = product_decompose(fac[0]).first; id.v0 = C0 * exp(id.d); @@ -180,7 +180,7 @@ EX portal_data make_portal(cellwalker cw, int spin) { id.T = gpushxto0(ctr); } } - else if(prod) { + else if(mproduct) { id.kind = 0; id.v0 = Hypc; id.scale = cgi.plevel; @@ -518,7 +518,7 @@ EX void analyze_orthonormal(array ds, ld sca) { vector orths; for(int i: {1,2,3}) { ds[i] = T * ds[i]; - if(prod) ds[i][2]--; + if(mproduct) ds[i][2]--; } for(int i=0; i<3; i++) for(int j=0; j<3; j++) @@ -811,7 +811,7 @@ EX void show_portals() { dialog::add_action_push(ray::configure); } - if(prod && point_direction < mouseover2->type - 2) { + if(mproduct && point_direction < mouseover2->type - 2) { ld r = get_ratio_edge(mouseover2, point_direction); dialog::addSelItem(XLAT("height-to-width ratio"), fts(r), 'r'); dialog::add_action([] { @@ -1047,7 +1047,7 @@ EX void handle() { z[2] = bt::minkowski_to_bt(fac.h0)[2]; return bt::bt_to_minkowski(z); } - else if(prod && bt::in()) { + else if(mproduct && bt::in()) { auto dec = product_decompose(at); hyperpoint dep = PIU( deparabolic13(dec.second) ); hyperpoint h = product_decompose(fac.h0).second; diff --git a/landgen.cpp b/landgen.cpp index b47ecf2e..724056d4 100644 --- a/landgen.cpp +++ b/landgen.cpp @@ -148,7 +148,7 @@ EX void createArrowTrapAt(cell *c, eLand land) { EX eMonster emerald_monster() { static eMonster emeraldmonsters[4] = { moHedge, moLancer, moFlailer, moMiner }; eMonster m = emeraldmonsters[hrand(4)]; - if(m == moHedge && (S3 != 3 || (hybri && !prod))) + if(m == moHedge && (S3 != 3 || (mhybrid && !mproduct))) m = moFlailer; return m; } @@ -399,7 +399,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { if(gs == 1) c->wall = waPalace; if(gs == 3) { - if(hybri) { + if(mhybrid) { c->wall = pick(waClosedGate, waOpenGate); if(c->wall == waClosedGate) toggleGates(c, waClosePlate, 1); else toggleGates(c, waOpenPlate, 1); @@ -415,7 +415,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { c->wall = pick(waClosePlate, waOpenPlate); if(gs == -6 && !reptilecheat) c->wall = waTrapdoor; - if(hybri) { + if(mhybrid) { int l = hybrid::get_where(c).second; if(gs >= 3 && (l % 4) == 0) c->wall = waPalace; if(gs < 3 && (l % 4) == 2) c->wall = waPalace; @@ -424,7 +424,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { else if(d == 8 && !sphere) { - if(prod && polarb50(c) && (hybrid::get_where(c).second & 3) == 2) { + if(mproduct && polarb50(c) && (hybrid::get_where(c).second & 3) == 2) { c->wall = waPalace; break; } @@ -462,19 +462,19 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { if(GOLDBERG) ; else { int q = 0, s = 0; - if(!ishept(c)) for(int i=0; itype - (hybri ? 2 : 0); i++) + if(!ishept(c)) for(int i=0; itype - (mhybrid ? 2 : 0); i++) if(cdist50(c->move(i)) == 3 && polarb50(c->move(i)) && !ishept(c->move(i))) q++, s += i; if(q == 1 && c->move(s)->land == laPalace) { switch(princess::generating ? 0 : hrand(2)) { case 0: c->wall = waClosedGate; - if(hybri) toggleGates(c, waClosePlate, 1); + if(mhybrid) toggleGates(c, waClosePlate, 1); c->move(s)->wall = waClosedGate; break; case 1: c->wall = waOpenGate; - if(hybri) toggleGates(c, waOpenPlate, 1); + if(mhybrid) toggleGates(c, waOpenPlate, 1); c->move(s)->wall = waOpenGate; break; } @@ -798,7 +798,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { else if(v == 25 || v == 59 || v == 27 || v == 57) c->wall = waVineHalfB; else c->wall = waNone; - if(hybri && cellHalfvine(c)) c->wall = waNone; + if(mhybrid && cellHalfvine(c)) c->wall = waNone; if(NONSTDVAR && cellHalfvine(c)) { c->wall = waNone; forCellCM(c2, c) if(emeraldval(c2) == (v^1)) @@ -1392,7 +1392,7 @@ EX void giantLandSwitch(cell *c, int d, cell *from) { while(i) { if(i&1) b++; i>>=1; } if(ctof(c) && (b&1) && hrand(100) < 20) c->wall = (z&2) ? waCharged : waGrounded; } - else if(hybri) { + else if(mhybrid) { cell *c1 = hybrid::get_where(c).first; if(among(c1->wall, waCharged, waGrounded)) c->wall = c1->wall; @@ -2834,7 +2834,7 @@ EX void set_land_for_geometry(cell *c) { #if MAXMDIM == 4 else if(euc::in(3)) euc::set_land(c); #endif - else if(hybri) setLandHybrid(c); + else if(mhybrid) setLandHybrid(c); else if(sphere || (euclid && closed_or_bounded)) setLandSphere(c); else if(euclid) setLandEuclid(c); else if(quotient) { setland(c, specialland); setLandQuotient(c); } @@ -2849,6 +2849,7 @@ EX void setdist(cell *c, int d, cell *from) { if(c == &out_of_bounds) return; if(fake::in()) return FPIU(setdist(c, d, from)); + if(embedded_plane) return IPF(setdist(c, d, from)); if(d < -64) d = -64; /* otherwise it will underflow */ if(c->mpdist <= d) return; @@ -2870,7 +2871,7 @@ EX void setdist(cell *c, int d, cell *from) { if(d <= 10 - getDistLimit()) lastexplore = shmup::on ? shmup::curtime : turncount; - if(hybri) { + if(mhybrid) { auto wc = hybrid::get_where(c).first; auto wf = from ? hybrid::get_where(from).first : NULL; if(c->land && !wc->land) wc->land = c->land; @@ -2888,7 +2889,7 @@ EX void setdist(cell *c, int d, cell *from) { if(d >= BARLEV) { #if CAP_BT - if(bt::in() && WDIM == 3 && !c->land && !sn::in() && !hybri) { + if(bt::in() && WDIM == 3 && !c->land && !sn::in() && !mhybrid) { ld z = vid.binary_width; cell *cseek = c; int step = 0; diff --git a/landlock.cpp b/landlock.cpp index e0c30489..ea25700e 100644 --- a/landlock.cpp +++ b/landlock.cpp @@ -757,7 +757,7 @@ EX land_validity_t& land_validity(eLand l) { if(walls_not_implemented() && isCrossroads(l)) return no_walls; - if(hybri || hybrid::pmap) { + if(mhybrid || hybrid::pmap) { if(among(l, laPrincessQuest, laPrairie, laMirrorOld, laMirror, laDual, laWarpCoast, laKraken, laBrownian, laWhirlpool, laWestWall, laHive, laClearing, laWhirlwind, laBlizzard, laBull, laTerracotta, laCrossroads5, laEndorian, laDungeon, laMountain)) return lv::not_implemented; @@ -765,7 +765,7 @@ EX land_validity_t& land_validity(eLand l) { return lv::bad_graphics; if((hybrid::actual_geometry == gRotSpace || geometry == gRotSpace) && l == laDryForest) return lv::hedgehogs; - if(hybri && hybrid::underlying && hybrid::underlying_cgip) { + if(mhybrid && hybrid::underlying && hybrid::underlying_cgip) { return *PIU(&land_validity(l)); } } diff --git a/mapeditor.cpp b/mapeditor.cpp index 86d01e55..f4d3a04e 100644 --- a/mapeditor.cpp +++ b/mapeditor.cpp @@ -518,7 +518,7 @@ EX namespace mapstream { f.write(asonov::period_z); } #endif - if(prod) { + if(mproduct) { f.write(hybrid::csteps); f.write(product::cspin); f.write(product::cmirror); @@ -527,7 +527,7 @@ EX namespace mapstream { if(rotspace) { f.write(hybrid::csteps); } - if(hybri) { + if(mhybrid) { hybrid::in_underlying_geometry([&] { save_geometry(f); }); } if(fake::in()) { @@ -661,7 +661,7 @@ EX namespace mapstream { if(geometry == gRotSpace && vernum >= 0xA833) { f.read(hybrid::csteps); } - if(hybri && vernum >= 0xA80C) { + if(mhybrid && vernum >= 0xA80C) { auto g = geometry; load_geometry(f); set_geometry(g); @@ -688,7 +688,7 @@ EX namespace mapstream { EX hookset hooks_loadmap; EX cell *save_start() { - return (closed_manifold || euclid || prod || arcm::in() || sol || INVERSE) ? currentmap->gamestart() : cwt.at->master->c7; + return (closed_manifold || euclid || mproduct || arcm::in() || sol || INVERSE) ? currentmap->gamestart() : cwt.at->master->c7; } #if CAP_EDIT @@ -926,7 +926,7 @@ EX namespace mapstream { for(int k=0; kc.spin(dir) - f.read_char(), c->type - sub); - if(GDIM == 3 && rspin && !hybri) { + if(GDIM == 3 && rspin && !mhybrid) { println(hlog, "rspin in 3D"); throw hstream_exception(); } diff --git a/models.cpp b/models.cpp index 6acbb661..6fbcce6a 100644 --- a/models.cpp +++ b/models.cpp @@ -135,7 +135,7 @@ EX namespace models { #endif EX transmatrix rotmatrix() { - if(GDIM == 2 || prod) return spin(rotation * degree); + if(GDIM == 2 || gproduct) return spin(rotation * degree); return spin(rotation_xy2 * degree) * cspin(0, 2, -rotation_xz * degree) * spin(rotation * degree); } @@ -190,7 +190,7 @@ EX namespace models { EX bool model_available(eModel pm) { if(mdinf[pm].flags & mf::technical) return false; - if(prod) { + if(gproduct) { if(pm == mdPerspective) return true; if(among(pm, mdBall, mdHemisphere)) return false; return PIU(model_available(pm)); @@ -205,7 +205,7 @@ EX namespace models { if(pm == mdLiePerspective && sphere) return false; if(pm == mdLieOrthogonal && sphere) return false; if(GDIM == 2 && pm == mdEquivolume) return false; - if(pm == mdThreePoint && !(GDIM == 3 && !nonisotropic && !prod)) return false; + if(pm == mdThreePoint && !(GDIM == 3 && !nonisotropic && !gproduct)) return false; if(GDIM == 3 && among(pm, mdBall, mdHyperboloid, mdFormula, mdPolygonal, mdRotatedHyperboles, mdSpiral, mdHemisphere)) return false; if(pm == mdCentralInversion && !euclid) return false; if(pm == mdPoorMan) return hyperbolic; @@ -247,7 +247,7 @@ EX namespace models { } EX bool product_model(eModel m) { - if(!prod) return false; + if(!gproduct) return false; if(among(m, mdPerspective, mdHyperboloid, mdEquidistant, mdThreePoint)) return false; return true; } @@ -256,8 +256,8 @@ EX namespace models { EX string get_model_name(eModel m) { if(m == mdDisk && GDIM == 3 && (hyperbolic || nonisotropic)) return XLAT("ball model/Gans"); - if(m == mdPerspective && prod) return XLAT("native perspective"); - if(prod) return PIU(get_model_name(m)); + if(m == mdPerspective && gproduct) return XLAT("native perspective"); + if(gproduct) return PIU(get_model_name(m)); if(nonisotropic) { if(m == mdHorocyclic && !sol) return XLAT("simple model: projection"); if(m == mdPerspective) return XLAT("simple model: perspective"); diff --git a/monstergen.cpp b/monstergen.cpp index f9538a60..a5e77185 100644 --- a/monstergen.cpp +++ b/monstergen.cpp @@ -796,7 +796,7 @@ EX void generateSnake(cell *c, int i, int snakecolor) { c2 = c3; c2->monst = moHexSnakeTail; c2->hitpoints = snakecolor; int t = c2->type; - if(hybri) t -= 2; + if(mhybrid) t -= 2; i = (j + (t%4 == 0 ? t/2 : (len%2 ? 2 : t - 2))) % t; createMov(c2, i); if(!inpair(c2->move(i), cpair)) { diff --git a/multigame.cpp b/multigame.cpp index ecfca214..3920e2e9 100644 --- a/multigame.cpp +++ b/multigame.cpp @@ -64,7 +64,7 @@ void gamedata_all(gamedata& gd) { if(gd.mode != 0) cgip->use_count--; gd.store(hybrid::underlying); gd.store(hybrid::csteps); - if(hybri && hybrid::underlying_cgip) { + if(mhybrid && hybrid::underlying_cgip) { if(gd.mode == 0) hybrid::underlying_cgip->use_count++; if(gd.mode != 0) hybrid::underlying_cgip->use_count--; } diff --git a/nonisotropic.cpp b/nonisotropic.cpp index cdde5dfb..a149cced 100644 --- a/nonisotropic.cpp +++ b/nonisotropic.cpp @@ -11,7 +11,7 @@ namespace hr { EX namespace nisot { #if HDR - inline bool local_perspective_used() { return nonisotropic || prod; } + inline bool local_perspective_used() { return nonisotropic || gproduct; } #endif EX bool geodesic_movement = true; @@ -1049,16 +1049,19 @@ EX void create_faces() { EX } -EX bool in_s2xe() { return prod && hybrid::under_class() == gcSphere; } -EX bool in_h2xe() { return prod && hybrid::under_class() == gcHyperbolic; } -EX bool in_e2xe() { return prod && hybrid::under_class() == gcEuclid; } +EX bool in_s2xe() { return gproduct && hybrid::under_class() == gcSphere; } +EX bool in_h2xe() { return gproduct && hybrid::under_class() == gcHyperbolic; } +EX bool in_e2xe() { return gproduct && hybrid::under_class() == gcEuclid; } EX namespace hybrid { EX eGeometry underlying; EX geometry_information *underlying_cgip; - EX eGeometryClass under_class() { return ginf[hybrid::underlying].cclass; } + EX eGeometryClass under_class() { + if(embedded_plane) return geom3::ginf_backup[geometry].cclass; + return ginf[hybrid::underlying].cclass; + } EX int csteps; @@ -1106,7 +1109,7 @@ EX namespace hybrid { } EX void reconfigure() { - if(!hybri) return; + if(!mhybrid) return; stop_game(); auto g = geometry; geometry = underlying; @@ -1364,7 +1367,13 @@ EX namespace hybrid { #if HDR template auto in_underlying_geometry(const T& f) -> decltype(f()) { - if(!hybri) return f(); + if(!mhybrid && !gproduct) return f(); + if(embedded_plane) { + geom3::light_flip(true); + finalizer ff([] { geom3::light_flip(false); }); + return f(); + } + if(geom3::flipped) throw hr_exception("called in_underlying_geometry in flipped"); pcgip = cgip; dynamicval gag(actual_geometry, geometry); dynamicval g(geometry, underlying); @@ -1381,7 +1390,8 @@ EX namespace hybrid { /** like in_underlying_geometry but does not return */ EX void switch_to_underlying() { - if(!hybri) return; + if(!mhybrid && !gproduct) return; + if(embedded_plane) throw hr_exception("switch_to_underlying in embedded_plane"); auto m = hmap(); pmap = m; actual_geometry = geometry; @@ -1410,7 +1420,7 @@ EX namespace hybrid { hyperpoint h = orthogonal_move(get_corner_position(c, i+next), zz); return h; } - if(prod) { + if(gproduct) { dynamicval g(geometry, hybrid::underlying); dynamicval gc(cgip, hybrid::underlying_cgip); dynamicval gm(currentmap, ((hrmap_hybrid*)currentmap)->underlying_map); @@ -1449,7 +1459,7 @@ EX namespace hybrid { }); EX vector> gen_sample_list() { - if(!hybri && WDIM != 2 && PURE) + if(!mhybrid && WDIM != 2 && PURE) return {make_pair(0, centerover), make_pair(centerover->type, nullptr)}; vector> result; for(auto& v: cgi.walloffsets) if(v.first >= 0) result.push_back(v); @@ -1668,7 +1678,7 @@ EX namespace product { } EX bool validate_spin() { - if(prod) return hybrid::in_underlying_geometry(validate_spin); + if(mproduct) return hybrid::in_underlying_geometry(validate_spin); if(kite::in()) return false; if(!quotient && !arcm::in()) return true; map cws; @@ -2232,7 +2242,7 @@ EX namespace rots { if(det(T) < 0) T = centralsym * T; - if(prod) d = 0; + if(mproduct) d = 0; hyperpoint h = inverse(View * spin(master_to_c7_angle()) * T) * C0; @@ -2241,7 +2251,7 @@ EX namespace rots { ld alpha = atan2(ortho_inverse(NLP) * point3(1, 0, 0)); - bool inprod = prod; + bool inprod = mproduct; transmatrix pView = View; if(inprod) { pView = spin(alpha) * View; @@ -2857,10 +2867,10 @@ EX namespace nisot { #if CAP_SOLV if(sn::in()) return new sn::hrmap_solnih; #endif - if(prod) return new product::hrmap_product; + if(mproduct) return new product::hrmap_product; #if MAXMDIM >= 4 if(nil) return new nilv::hrmap_nil; - if(hybri) return new rots::hrmap_rotation_space; + if(mhybrid) return new rots::hrmap_rotation_space; #endif return NULL; } @@ -2963,7 +2973,7 @@ EX namespace nisot { #endif else if(argis("-prodperiod")) { PHASEFROM(2); - if(prod) stop_game(); + if(mproduct) stop_game(); shift(); hybrid::csteps = argi(); hybrid::reconfigure(); return 0; @@ -2999,7 +3009,7 @@ EX namespace nisot { } else if(argis("-prodturn")) { PHASEFROM(2); - if(prod) stop_game(); + if(mproduct) stop_game(); shift(); product::cspin = argi(); shift(); product::cmirror = argi(); return 0; diff --git a/pattern2.cpp b/pattern2.cpp index 7ce5a26d..6365cd7c 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -28,7 +28,7 @@ EX int ctof(cell *c) { if(IRREGULAR) return irr::ctof(c); #endif if(PURE) return 1; - // if(euclid) return 0; + // if(meuclid) return 0; if(!c) return 1; if(bt::in()) return c->type == 7; return ishept(c) ? 1 : 0; @@ -68,7 +68,7 @@ EX bool ishept(cell *c) { if(cgflags & qPORTALSPACE) return 0; // EUCLIDEAN if(euc::in() && PURE) return eupattern(c) == 0; - else if(hybri) { cell *c1 = hybrid::get_where(c).first; return c1 == c1->master->c7; } + else if(mhybrid) { cell *c1 = hybrid::get_where(c).first; return c1 == c1->master->c7; } else return c == c->master->c7; } @@ -131,8 +131,8 @@ EX int chessvalue(cell *c) { EX int emeraldval(heptagon *h) { return h->emeraldval >> 3; } EX int emeraldval(cell *c) { - if(euclid) return eupattern(c); - if(sphere) return 0; + if(meuclid) return eupattern(c); + if(msphere) return 0; if(ctof(c)) return emeraldval(c->master); else { @@ -166,8 +166,8 @@ int eufifty(cell *c) { } int fiftyval(cell *c) { - if(euclid) return eufifty(c) * 32; - if(sphere || S7>7 || S6>6) return 0; + if(meuclid) return eufifty(c) * 32; + if(msphere || S7>7 || S6>6) return 0; if(ctof(c)) return c->master->fiftyval; else { @@ -180,13 +180,13 @@ int fiftyval(cell *c) { } EX int cdist50(cell *c) { - if(euclid && S3 == 4) { + if(meuclid && S3 == 4) { auto co = euc2_coordinates(c); int x = co.first, y = co.second; return abs(szgmod(x, 5)) + abs(zgmod(y, 5)); } - if(sphere || S7>7 || S6>6) return 0; - if(euclid) { + if(msphere || S7>7 || S6>6) return 0; + if(meuclid) { if(c->land == laWildWest) return "0123333332112332223322233211233333322"[eufifty(c)] - '0'; else return "012333321112322232222321123"[eufifty(c)] - '0'; @@ -201,7 +201,7 @@ EX int cdist50(cell *c) { } int land50(cell *c) { - if(sphere || euclid) return 0; + if(msphere || meuclid) return 0; else if(ctof(c)) return land50(fiftyval(c)); else { auto ar = gp::get_masters(c); @@ -212,7 +212,7 @@ int land50(cell *c) { } EX bool polara50(cell *c) { - if(sphere || euclid || S7>7 || S6>6) return false; + if(msphere || meuclid || S7>7 || S6>6) return false; else if(NONSTDVAR) return polara50(fiftyval(c->master->c7)); else if(ctof(c)) return polara50(fiftyval(c)); else { @@ -224,8 +224,8 @@ EX bool polara50(cell *c) { } EX bool polarb50(cell *c) { - if(euclid) return true; - if(sphere || euclid || S7>7 || S6>6) return true; + if(meuclid) return true; + if(msphere || meuclid || S7>7 || S6>6) return true; else if(NONSTDVAR) return polarb50(fiftyval(c->master->c7)); else if(ctof(c)) return polarb50(fiftyval(c)); else { @@ -257,9 +257,9 @@ EX int fiftyval049(heptagon *h) { } EX int fiftyval049(cell *c) { - if(euclid) return fiftyval(c) / 32; + if(meuclid) return fiftyval(c) / 32; else if(ctof(c)) return fiftyval049(c->master); - else if(sphere) return 0; + else if(msphere) return 0; else { int a[3], qa=0; bool pa = polara50(c); @@ -332,7 +332,7 @@ int dir_bitrunc457(cell *c) { int val46(cell *c); EX int zebra40(cell *c) { - if(euclid) return pattern_threecolor(c); + if(meuclid) return pattern_threecolor(c); else if(IRREGULAR) return c->master->zebraval/10; else if(INVERSE) { cell *c1 = gp::get_mapped(c); @@ -367,7 +367,7 @@ EX int zebra40(cell *c) { if(tot == 4+5+6+7) return 17+cod; return 24; } - else if(sphere) return 0; + else if(msphere) return 0; else if(S3 == 4 && S7 == 6) { return 8 + ((c->master->zebraval / 10 + c->c.spin(0))%2) * 2; } @@ -394,9 +394,9 @@ EX int zebra40(cell *c) { } EX int zebra3(cell *c) { - if(euclid) return 0; + if(meuclid) return 0; else if(ctof(c)) return (c->master->zebraval/10)/4; - else if(euclid || sphere || S7>7 || S6>6) return 0; + else if(meuclid || msphere || S7>7 || S6>6) return 0; else { int ii[3]; auto ar = gp::get_masters(c); @@ -424,11 +424,11 @@ EX int fieldval_uniq(cell *c) { if(experimental) return 0; if(reg3::in() && !PURE) return 0; else if(arb::in()) return arb::id_of(c->master); - else if(hybri) { + else if(mhybrid) { auto c1 = hybrid::get_where(c).first; return PIU ( fieldval_uniq(c1) ); } - else if(sphere) { + else if(msphere) { if(arcm::in()) return c->master->fiftyval; #if CAP_IRR else if(IRREGULAR) return irr::cellindex[c]; @@ -463,11 +463,11 @@ EX int fieldval_uniq(cell *c) { } EX int fieldval_uniq_rand(cell *c, int randval) { - if(hybri) { + if(mhybrid) { auto c1 = hybrid::get_where(c).first; return PIU ( fieldval_uniq_rand(c1, randval) ); } - if(sphere || euclid || NONSTDVAR) + if(msphere || meuclid || NONSTDVAR) // we do not care in these cases return fieldval_uniq(c); if(ctof(c)) return currfp.gmul(c->master->fieldval, randval)/7; @@ -539,9 +539,9 @@ EX int getHemisphere(heptagon *h, int which) { } EX int getHemisphere(cell *c, int which) { - if(euclid && quotient) return 0; - if(hybri) { auto d = hybrid::get_where(c); return PIU(getHemisphere(d.first, which)); } - if(WDIM == 3 && !hybri) { + if(meuclid && quotient) return 0; + if(mhybrid) { auto d = hybrid::get_where(c); return PIU(getHemisphere(d.first, which)); } + if(WDIM == 3 && !mhybrid) { hyperpoint p = tC0(calc_relative_matrix(c, currentmap->gamestart(), C0)); return int(p[which] * 6 + 10.5) - 10; } @@ -991,9 +991,9 @@ EX namespace patterns { if(subpattern_flags & SPF_FULLSYM) si.symmetries = 1; } - if(sphere && BITRUNCATED && !(S7 == 3)) + if(msphere && BITRUNCATED && !(S7 == 3)) si.symmetries = ctof(c) ? 1 : 2; - if(sphere && (sub & SPF_EXTRASYM)) { + if(msphere && (sub & SPF_EXTRASYM)) { si.symmetries = ctof(c) ? 1 : 2; } if(a38) @@ -1154,7 +1154,7 @@ EX namespace patterns { else if(pat == PAT_EMERALD && (stdhyperbolic || a38)) { si.id = emeraldval(c); // 44 to 99 - if(!euclid) { + if(!meuclid) { int tcdir = 0, tbest = (si.id&3); for(int i=0; itype; i++) { cell *c2 = c->move(i); @@ -1208,7 +1208,7 @@ EX namespace patterns { si.id -= ((si.id/4-1) % 7) * 4; } - else if(pat == PAT_PALACE && euclid) { + else if(pat == PAT_PALACE && meuclid) { si.id = fiftyval049(c); si.symmetries = 6; } @@ -1225,7 +1225,7 @@ EX namespace patterns { #if CAP_FIELD else if(pat == PAT_FIELD) { - if(euclid) + if(meuclid) // use the torus ID si.id = fieldpattern::fieldval_uniq(c); else if(PURE && standard_tiling()) @@ -1238,7 +1238,7 @@ EX namespace patterns { } #endif - else if(sphere && pat == PAT_SIBLING) { + else if(msphere && pat == PAT_SIBLING) { val_all(c, si, sub, pat); } @@ -1252,7 +1252,7 @@ EX namespace patterns { else val_threecolors(c, si, sub); } - else if(pat == PAT_COLORING && (S7 == 4 || euclid || (a38 && gp_threecolor() == 1) || arcm::in())) { + else if(pat == PAT_COLORING && (S7 == 4 || meuclid || (a38 && gp_threecolor() == 1) || arcm::in())) { val_threecolors(c, si, sub); } @@ -1403,7 +1403,7 @@ EX int pattern_threecolor(cell *c) { int i = si.id; return i >> 2; } - if(euclid) { + if(meuclid) { if(a4 && PURE) return eupattern4(c); if(euc::in(2,6) && !BITRUNCATED) return eupattern(c) % 3; return c == c->master->c7 ? 0 : (c->c.spin(0)&1) ? 1 : 2; @@ -1471,7 +1471,7 @@ EX bool pseudohept(cell *c) { #if CAP_IRR if(IRREGULAR) return irr::pseudohept(c); #endif - if(hybri) { auto d = hybrid::get_where(c); return ((!prod) || (d.second & 1)) && PIU(pseudohept(d.first)); } + if(mhybrid) { auto d = hybrid::get_where(c); return ((!mproduct) || (d.second & 1)) && PIU(pseudohept(d.first)); } #if CAP_BT if(nil) return c->master->zebraval & c->master->emeraldval & c->master->fieldval & 1; if(sol) return (c->master->emeraldval % 3 == 2) && (c->master->zebraval % 3 == 2) && (c->master->distance % 2); @@ -1506,7 +1506,7 @@ EX bool pseudohept(cell *c) { EX bool kraken_pseudohept(cell *c) { if(0); #if CAP_GP - else if(!euclid && S3 == 4 && GOLDBERG && (gp::param.first % 2 || gp::param.second % 2 || S7 % 2)) + else if(!meuclid && S3 == 4 && GOLDBERG && (gp::param.first % 2 || gp::param.second % 2 || S7 % 2)) return ishept(c); #endif #if CAP_IRR @@ -1521,7 +1521,7 @@ EX bool kraken_pseudohept(cell *c) { else if(arcm::in() && DUAL) return false; #endif - else if(!euclid && S3 == 3 && !(S7&1) && gp_threecolor() == 1) + else if(!meuclid && S3 == 3 && !(S7&1) && gp_threecolor() == 1) return ishept(c); else return pseudohept(c); @@ -1600,7 +1600,7 @@ EX namespace patterns { EX bool innerwalls; int sevenval(cell *c) { - if(!euclid) return 0; + if(!meuclid) return 0; auto p = euc2_coordinates(c); return gmod(p.first - p.second * 2, 7); } @@ -1706,7 +1706,7 @@ EX namespace patterns { ep.extra_params["mz"] = c->master->zebraval; } - if(sphere) { + if(msphere) { ep.extra_params["h0"] = getHemisphere(c, 0); ep.extra_params["h1"] = getHemisphere(c, 1); ep.extra_params["h2"] = getHemisphere(c, 2); @@ -1739,7 +1739,7 @@ EX namespace patterns { ep.extra_params["ny"] = szgmod(co[1], nilv::nilperiod[1]); ep.extra_params["nz"] = szgmod(co[2], nilv::nilperiod[2]); } - if(hybri) + if(mhybrid) ep.extra_params["level"] = hybrid::get_where(c).second; if(geometry_supports_cdata()) { @@ -2031,7 +2031,7 @@ EX namespace patterns { dialog::addSelItem(XLAT("random black-and-white"), "current", 'w'); #if CAP_FIELD - if(!sphere) { + if(!msphere) { dialog::addSelItem(XLAT("field pattern C"), "field", 'C'); dialog::addSelItem(XLAT("field pattern D"), "field", 'D'); dialog::addSelItem(XLAT("field pattern N"), "field", 'N'); @@ -2218,7 +2218,7 @@ EX namespace patterns { else if(a38) dialog::addBoolItem(XLAT("broken Emerald Pattern"), (whichPattern == PAT_EMERALD), PAT_EMERALD); - if(stdhyperbolic || euclid) + if(stdhyperbolic || meuclid) dialog::addBoolItem(XLAT("Palace Pattern"), (whichPattern == PAT_PALACE), PAT_PALACE); if(geosupport_chessboard()) @@ -2230,9 +2230,9 @@ EX namespace patterns { if(sphere_narcm) dialog::addBoolItem(XLAT("siblings"), (whichPattern == PAT_SIBLING), PAT_SIBLING); - if(euclid) + if(meuclid) dialog::addBoolItem(XLAT("torus"), (whichPattern == PAT_FIELD), PAT_FIELD); - else if(sphere) + else if(msphere) dialog::addBoolItem(XLAT("single cells"), (whichPattern == PAT_FIELD), PAT_FIELD); else dialog::addBoolItem(XLAT("field pattern"), (whichPattern == PAT_FIELD), PAT_FIELD); @@ -2245,17 +2245,17 @@ EX namespace patterns { (whichPattern == PAT_EMERALD && (stdhyperbolic || a38)) || (whichPattern == PAT_PALACE && stdhyperbolic) || (whichPattern == PAT_ZEBRA && stdhyperbolic) || - (whichPattern == PAT_SIBLING && sphere) || + (whichPattern == PAT_SIBLING && msphere) || (whichPattern == PAT_ZEBRA && a457)) { dialog::addBoolItem(XLAT("rotational symmetry"), subpattern_flags & SPF_ROT, '0'); } - if((euclid && whichPattern == PAT_COLORING) || + if((meuclid && whichPattern == PAT_COLORING) || (a38 && whichPattern == PAT_COLORING) || (a4 && !BITRUNCATED && whichPattern == PAT_COLORING && !a46)) dialog::addBoolItem(XLAT("edit all three colors"), subpattern_flags & SPF_ROT, '0'); - if(euclid && whichPattern == PAT_COLORING) + if(meuclid && whichPattern == PAT_COLORING) dialog::addBoolItem(XLAT("rotate the color groups"), subpattern_flags & SPF_CHANGEROT, '4'); if(a46 && whichPattern == PAT_COLORING) @@ -2275,7 +2275,7 @@ EX namespace patterns { dialog::addBoolItem(XLAT("symmetry 0-2"), subpattern_flags & SPF_SYM02, '2'); dialog::addBoolItem(XLAT("symmetry 0-3"), subpattern_flags & SPF_SYM03, '3'); } - if(euclid && among(whichPattern, PAT_COLORING, PAT_TYPES) && !arcm::in()) + if(meuclid && among(whichPattern, PAT_COLORING, PAT_TYPES) && !arcm::in()) dialog::addBoolItem(XLAT("extra symmetries"), subpattern_flags & SPF_EXTRASYM, '='); #if CAP_ARCM @@ -2288,7 +2288,7 @@ EX namespace patterns { dialog::addBoolItem(XLAT("extra symmetries"), subpattern_flags & SPF_EXTRASYM, '='); } - if(euclid && among(whichPattern, PAT_COLORING, 0)) + if(meuclid && among(whichPattern, PAT_COLORING, 0)) dialog::addBoolItem(XLAT("full symmetry"), subpattern_flags & SPF_FULLSYM, '!'); if(a38 && PURE && whichPattern == PAT_TYPES) { @@ -2517,8 +2517,8 @@ EX namespace patterns { } dialog::addBoolItem(s, geometry == g.geo && variation == g.var && whichPattern == g.whichPattern && subpattern_flags == g.subpattern_flags, 'a'+j); } - bool have_goldberg = (S3 == 3 && among(cgroup, cpFootball, cpThree) && !euclid); - bool have_variations = (among(cgroup, cpSingle, cpSingleSym) && !euclid); + bool have_goldberg = (S3 == 3 && among(cgroup, cpFootball, cpThree) && !meuclid); + bool have_variations = (among(cgroup, cpSingle, cpSingleSym) && !meuclid); if(!(S7&1) && BITRUNCATED) have_goldberg = false; // always start from pure if(have_goldberg) { dialog::addBoolItem(XLAT("Goldberg"), GOLDBERG, 'G'); @@ -2715,7 +2715,7 @@ EX namespace linepatterns { linepattern patBigTriangles("big triangular grid", 0x00606000, always_available, ALLCELLS( - if(is_master(c) && !euclid) for(int i=0; imaster->move(i) && c->master->move(i) < c->master) { gridlinef(V, C0, xspinpush0(-TAU*i/S7 - master_to_c7_angle(), cgi.tessf), col, 2 + vid.linequality); } @@ -2724,7 +2724,7 @@ EX namespace linepatterns { linepattern patBigRings("big triangles: rings", 0x00606000, [] { return standard_tiling() && S3 == 3 && mod_allowed(); }, ALLCELLS( - if(is_master(c) && !euclid) for(int i=0; imaster->move(i) && way(c->master, i) && c->master->move(i)->dm4 == c->master->dm4) gridlinef(V, C0, xspinpush0(-TAU*i/S7 - master_to_c7_angle(), cgi.tessf), col, 2 + vid.linequality); ) @@ -2790,7 +2790,7 @@ EX namespace linepatterns { if(fv2/4 == 4 || fv2/4 == 6 || fv2/4 == 5 || fv2/4 == 10) fv2 ^= 2; if((fv1&1) == (fv2&1)) continue; - double x = cgi.hexhexdist / 2; // sphere?.3651:euclid?.2611:.2849; + double x = cgi.hexhexdist / 2; // msphere?.3651:meuclid?.2611:.2849; gridlinef(V, ddspin(c,i,-M_PI/S3) * xpush0(x), ddspin(c,i,M_PI/S3) * xpush0(x), diff --git a/polygons.cpp b/polygons.cpp index e52df748..d12eeb94 100644 --- a/polygons.cpp +++ b/polygons.cpp @@ -111,7 +111,7 @@ void geometry_information::chasmifyPoly(double fol, double fol2, int k) { int zf = int(x); if(zf == isize(points)-1) zf--; x -= zf; - hpcpush(orthogonal_move(normalize(points[zf] + (points[zf+1] - points[zf]) * x), fol + (fol2-fol) * y)); + hpcpush(orthogonal_move(normalize_flat(points[zf] + (points[zf+1] - points[zf]) * x), fol + (fol2-fol) * y)); }; texture_order([&] (ld x, ld y) { at((1-x+y)/2, (1-x-y)/2); }); texture_order([&] (ld x, ld y) { at((1-x-y)/2, (1+x-y)/2); }); @@ -881,7 +881,7 @@ hyperpoint ray_kleinize(hyperpoint h, int id, ld pz) { return deparabolic13(final_coords(h)); } #endif - if(prod) { + if(gproduct) { if(bt::in()) return point3(h[0], h[1], pz); return point3(h[0]/h[2], h[1]/h[2], pz); } @@ -912,7 +912,7 @@ void geometry_information::make_wall(int id, vector vertices, vector vector altitudes; altitudes.resize(n); - if(prod) { + if(gproduct) { for(int i=0; i vertices, vector ld w = 0; for(int i=0; i vertices, vector hyperpoint h = center + v1 * x + v2 * y; if(nil && (x || y)) h = nilv::on_geodesic(center, nilv::on_geodesic(v1+center, v2+center, y / (x+y)), x + y); - if(prod) { + if(mproduct) { if(bt::in()) h = PIU( parabolic13(h) ); h = orthogonal_move(normalize_flat(h), center_altitude * (1-x-y) + altitudes[a] * x + altitudes[b] * y); hpcpush(h); return; @@ -971,7 +971,7 @@ void geometry_information::make_wall(int id, vector vertices, vector for(int a=0; a makeradar(shiftpoint h) { if(r < 1) h1 = h1 * (atanh(r) / r); else return {false, h1}; } - else if(prod) h1 = product::inverse_exp(unshift(h)); + else if(mproduct) h1 = product::inverse_exp(unshift(h)); else if(sl2) h1 = slr::get_inverse_exp(h); else h1 = unshift(h); @@ -84,7 +84,7 @@ EX void draw_radar(bool cornermode) { bool d3 = WDIM == 3; bool hyp = hyperbolic; bool sph = sphere; - bool scompass = nonisotropic && !hybri; + bool scompass = nonisotropic && !mhybrid; dynamicval g(geometry, gEuclid); dynamicval pm(pmodel, mdDisk); diff --git a/raycaster.cpp b/raycaster.cpp index 5524d8b0..47aff10c 100644 --- a/raycaster.cpp +++ b/raycaster.cpp @@ -125,7 +125,7 @@ EX bool available() { if(WDIM == 2 && (kite::in() || bt::in())) return false; #ifdef GLES_ONLY if(need_many_cell_types()) return false; - if(!euclid && !prod && !nil) return false; + if(!euclid && !gproduct && !nil) return false; #endif if(hyperbolic && pmodel == mdPerspective && !kite::in()) return true; @@ -137,7 +137,7 @@ EX bool available() { return true; if(euclid && pmodel == mdPerspective && !bt::in()) return true; - if(prod) + if(gproduct) return true; if(pmodel == mdPerspective && stretch::in()) return true; @@ -370,7 +370,7 @@ void raygen::compute_which_and_dist(int flat1, int flat2) { else if(in_h2xe() && hybrid::underlying == gBinaryTiling) fmain += "for(int i=0; i<=4; i++) if(i == 0 || i == 4) {"; else - fmain += "for(int i="+its(flat1)+"; i<"+(prod ? "sides-2" : ((WDIM == 2 || is_subcube_based(variation) || intra::in) && !bt::in()) ? "sides" : its(flat2))+"; i++) {\n"; + fmain += "for(int i="+its(flat1)+"; i<"+(gproduct ? "sides-2" : ((WDIM == 2 || is_subcube_based(variation) || intra::in) && !bt::in()) ? "sides" : its(flat2))+"; i++) {\n"; fmain += " mediump mat4 m = " + getM("walloffset+i") + ";\n"; @@ -454,14 +454,14 @@ void raygen::compute_which_and_dist(int flat1, int flat2) { "mediump float v = -(Mp*u-1.) / Mt;\n" "if(a < 1e-5) v = (1.-Mp*Mp) / (2. * Mt);\n" "mediump float d = asinh(v);\n"; - if(prod) fmain += "d /= xspeed;\n"; + if(gproduct) fmain += "d /= xspeed;\n"; fmain += "if(d < 0. && abs(log(position."+w+"*position."+w+"-position.x*position.x)) < uBLevel) continue;\n" "if(d < dist) { dist = d; which = i; }\n" "}\n"; } - if(prod) fmain += + if(gproduct) fmain += "if(zspeed > 0.) { mediump float d = (uPLevel - zpos) / zspeed; if(d < dist) { dist = d; which = sides-1; }}\n" "if(zspeed < 0.) { mediump float d = (-uPLevel - zpos) / zspeed; if(d < dist) { dist = d; which = sides-2; }}\n"; @@ -743,7 +743,7 @@ void raygen::move_forward() { if(eyes) { fmain += " mediump float t = go + dist;\n"; - fmain += prod ? + fmain += gproduct ? " mediump vec4 v = at1 * t;\n" : " mediump vec4 v = at0 * t;\n"; fmain += @@ -756,7 +756,7 @@ void raygen::move_forward() { " mediump vec4 xp = vec4(2.*c*sin(w/2.) * cos(w/2.+alpha), 2.*c*sin(w/2.)*sin(w/2.+alpha), w*(1.+(c*c/2.)*((1.-sin(w)/w)+(1.-cos(w))/w * sin(w+2.*alpha))), 1.);\n" " mediump vec4 orig_position = vw * vec4(0., 0., 0., 1.);\n" " mediump vec4 nposition = translate(orig_position, xp);\n"; - else if(prod) { + else if(gproduct) { fmain += " mediump float alen_xy = length(azeq.xy);\n"; fmain += " mediump float nzpos = zpos + azeq.z;\n"; @@ -808,10 +808,10 @@ void raygen::move_forward() { " mediump vec4 nposition = v;\n"; } - bool reg = hyperbolic || sphere || euclid || sl2 || prod; + bool reg = hyperbolic || sphere || euclid || sl2 || gproduct; if(reg) { - string s = (rotspace || prod) ? "-2" : ""; + string s = (rotspace || gproduct) ? "-2" : ""; fmain += " mediump float best = "+f_len()+"(nposition);\n" " for(int i=0; i= "+its(flat2)+")) {\n"; @@ -1014,7 +1014,7 @@ void raygen::emit_intra_portal(int gid1, int gid2) { intra::switch_to(gid2); } - if(prod) { + if(gproduct) { fmain += "mediump vec4 nposition;\n"; fmain += "if(pconnection.x != .5) {\n"; // kind != 0 if(1) { @@ -1089,7 +1089,7 @@ void raygen::emit_intra_portal(int gid1, int gid2) { intra::resetter ir; intra::switch_to(gid2); - if(prod) { + if(gproduct) { fmain += "if(pconnection.z != .5) {\n"; // kind != 0 if(1) { string sgn = in_h2xe() ? "-" : "+"; @@ -1182,11 +1182,11 @@ void raygen::emit_intra_portal(int gid1, int gid2) { void raygen::emit_iterate(int gid1) { using glhr::to_glsl; - if(intra::in && prod) + if(intra::in && gproduct) fmain += " const mediump float uPLevel = " + to_glsl(cgi.plevel/2) + ";\n"; int flat1 = 0, flat2 = deg; - if(prod || rotspace) flat2 -= 2; + if(gproduct || rotspace) flat2 -= 2; #if CAP_BT if(horos()) { @@ -1292,8 +1292,8 @@ void raygen::emit_iterate(int gid1) { fmain += "if(which == -1) continue;\n"; - if(prod && eyes) fmain += "position.w = -nzpos;\n"; - else if(prod) fmain += "position.w = -zpos;\n"; + if(gproduct && eyes) fmain += "position.w = -nzpos;\n"; + else if(gproduct) fmain += "position.w = -zpos;\n"; if(reg3::ultra_mirror_in()) fmain += "if(which >= " + its(S7) + ") {" @@ -1323,11 +1323,11 @@ void raygen::emit_iterate(int gid1) { "pos.xyz = pos.zxy;\n"; else if(hyperbolic || sphere) fmain += "pos /= pos.w;\n"; - else if(prod && bt::in()) fmain += + else if(gproduct && bt::in()) fmain += "pos.xy = deparabolic12(pos).xy;\n" "pos.z = -pos.w; pos.w = 0.;\n" ; - else if(prod) fmain += + else if(gproduct) fmain += "pos = vec4(pos.x/pos.z, pos.y/pos.z, -pos.w, 0);\n"; fmain += " mediump vec2 inface = map_texture(pos, which+walloffset);\n" @@ -1438,7 +1438,7 @@ void raygen::emit_iterate(int gid1) { " position = m * position;\n" " tangent = m * tangent;\n"; - if(prod) no_intra_portal = + if(gproduct) no_intra_portal = " if(which == sides-2) { zpos += uPLevel+uPLevel; }\n" " else if(which == sides-1) { zpos -= uPLevel+uPLevel; }\n" " else {\n" + no_intra_portal + "}\n"; @@ -1708,7 +1708,7 @@ void raygen::add_functions() { } void raygen::emit_raystarter() { - if(prod) { + if(gproduct) { string sgn=in_h2xe() ? "-" : "+"; fmain += " position = vw * vec4(0., 0., 1., 0.);\n" @@ -1863,10 +1863,10 @@ void raygen::create() { fsh += build_getter("mediump mat4", "uM", gms_limit); #endif - if(prod || intra::in) fsh += + if(gproduct || intra::in) fsh += "uniform mediump mat4 uLP;\n"; - if(prod || intra::in) fsh += + if(gproduct || intra::in) fsh += "uniform mediump float uPLevel;\n"; if(many_cell_types) fsh += @@ -1971,7 +1971,7 @@ void raygen::create() { fmain += " mediump vec4 position;\n"; fmain += " mediump vec4 tangent;\n"; - if(prod || intra::in) { + if(gproduct || intra::in) { fmain += " mediump float zspeed = 1.;\n"; fmain += " mediump float xspeed = 1.;\n"; fmain += " mediump float zpos = 0.;\n"; @@ -2195,7 +2195,7 @@ struct raycast_map { if(!c) continue; intra::may_switch_to(c); int id =p.first; - if(prod) { + if(gproduct) { ms[id+c->type-2] = Id; ms[id+c->type-1] = Id; } diff --git a/reg3.cpp b/reg3.cpp index c08c61bb..29226af5 100644 --- a/reg3.cpp +++ b/reg3.cpp @@ -16,7 +16,7 @@ EX hyperpoint final_coords(hyperpoint h) { if(sn::in() || !bt::in()) return ultra_normalize(h); #if CAP_BT - if(bt::in() && !prod) + if(bt::in() && !mproduct) return bt::bt_to_minkowski(h); #endif return h; @@ -121,7 +121,7 @@ EX namespace reg3 { EX bool in() { if(fake::in()) return FPIU(in()); if(geometry == gCubeTiling && (cubes_reg3 || !PURE)) return true; - return WDIM == 3 && !euclid && !bt::in() && !nonisotropic && !hybri && !kite::in(); + return WDIM == 3 && !euclid && !bt::in() && !nonisotropic && !mhybrid && !kite::in(); } EX void compute_ultra() { diff --git a/screenshot.cpp b/screenshot.cpp index ce4dfc9c..5f7ad8b0 100644 --- a/screenshot.cpp +++ b/screenshot.cpp @@ -1569,7 +1569,7 @@ EX void show() { if(among(pmodel, mdJoukowsky, mdJoukowskyInverted)) { animator(XLAT("Möbius transformations"), skiprope_rotation, 'S'); } - if(!prod) { + if(!mproduct) { dialog::addBoolItem(XLAT("circle"), ma == maCircle, '4'); dialog::add_action([] () { ma = maCircle; rotation_center = centerover; diff --git a/shaders.cpp b/shaders.cpp index 22456701..a4ae5a8c 100644 --- a/shaders.cpp +++ b/shaders.cpp @@ -265,13 +265,13 @@ shared_ptr write_shader(flagtype shader_flags) { "t.z = (sin(uCamera) * cos(zl) * cos(d) - sin(zl) * cos(uCamera)) / uz;\n" ; } - else if(pmodel == mdDisk && MDIM == 3 && !spherespecial && !prod) { + else if(pmodel == mdDisk && MDIM == 3 && !spherespecial && !gproduct) { shader_flags |= SF_DIRECT; } else if(glhr::noshaders) { shader_flags |= SF_PIXELS; } - else if(pmodel == mdDisk && GDIM == 3 && !spherespecial && !nonisotropic && !prod) { + else if(pmodel == mdDisk && GDIM == 3 && !spherespecial && !nonisotropic && !gproduct) { coordinator += "t /= (t[3] + uAlpha);\n"; vsh += "uniform mediump float uAlpha;"; shader_flags |= SF_DIRECT | SF_BOX | SF_ZFOG; @@ -454,7 +454,7 @@ shared_ptr write_shader(flagtype shader_flags) { if(shader_flags & GF_NO_FOG) { vmain += "// no fog used\n"; } - else if(GDIM == 3 && WDIM == 2 && hyperbolic && context_fog && pmodel == mdPerspective) { + else if(GDIM == 3 && WDIM == 2 && hyperbolic && context_fog && geom3::same_in_same() && pmodel == mdPerspective) { vsh += "uniform mediump mat4 uRadarTransform;\n" "uniform mediump sampler2D tAirMap;\n" @@ -586,7 +586,7 @@ void display_data::set_projection(int ed, ld shift) { if(sol && solv_all) id |= 1; if(in_h2xe()) id |= 1; if(in_s2xe()) id |= 2; - if(WDIM == 2 && GDIM == 3 && hyperbolic && context_fog) id |= 1; + if(WDIM == 2 && GDIM == 3 && hyperbolic && context_fog && geom3::same_in_same()) id |= 1; shared_ptr selected; if(matched_programs.count(id)) selected = matched_programs[id]; @@ -720,7 +720,7 @@ void display_data::set_projection(int ed, ld shift) { glhr::projection_multiply(glhr::frustum(cd->tanfov, cd->tanfov * cd->ysize / cd->xsize)); glhr::projection_multiply(glhr::scale(1, -1, -1)); if(nisot::local_perspective_used()) { - if(prod) { + if(gproduct) { for(int i=0; i<3; i++) NLP[3][i] = NLP[i][3] = 0; NLP[3][3] = 1; } diff --git a/shmup.cpp b/shmup.cpp index 6c364f2f..d86add22 100644 --- a/shmup.cpp +++ b/shmup.cpp @@ -22,7 +22,7 @@ EX namespace shmupballs { EX } ld sqdist(shiftpoint a, shiftpoint b) { - if(prod) return pow(hdist(a, b), 2); + if(gproduct) return pow(hdist(a, b), 2); else return intval(a.h, unshift(b, a.shift)); } @@ -422,7 +422,7 @@ void shootBullet(monster *m) { bullet->base = m->base; bullet->at = m->at; if(WDIM == 3) bullet->at = bullet->at * cpush(2, 0.15 * SCALE); - if(prod) bullet->ori = m->ori; + if(gproduct) bullet->ori = m->ori; bullet->type = moBullet; bullet->set_parent(m); bullet->pid = m->pid; @@ -441,7 +441,7 @@ void shootBullet(monster *m) { monster* bullet = new monster; bullet->base = m->base; bullet->at = m->at * cspin(0, WDIM-1, TAU * i/8); - if(prod) bullet->ori = m->ori; + if(gproduct) bullet->ori = m->ori; if(WDIM == 3) bullet->at = bullet->at * cpush(2, 0.15 * SCALE); bullet->type = moBullet; bullet->set_parent(m); @@ -3057,7 +3057,7 @@ bool celldrawer::draw_shmup_monster() { if(!ths || !h) { drawPlayerEffects(view, V, c, m->type); if(WDIM == 3) { - if(prod) { + if(gproduct) { hyperpoint h = m->ori * C0; // ztangent(1) view = view * spin(-atan2(h[1], h[0])); } @@ -3154,7 +3154,7 @@ bool celldrawer::draw_shmup_monster() { default: if(WDIM == 3) { - if(prod) { + if(gproduct) { hyperpoint h = m->ori * xtangent(1); view = view * spin(-atan2(h[1], h[0])); } diff --git a/sky.cpp b/sky.cpp index 9f0354a9..84ddc330 100644 --- a/sky.cpp +++ b/sky.cpp @@ -6,6 +6,12 @@ EX bool context_fog = true; EX ld camera_level; EX bool draw_sky = true; +EX bool camera_sign; + +EX bool camera_over(ld x) { + if(camera_sign) return camera_level <= x; + return camera_level >= x; + } #if MAXMDIM >= 4 && CAP_GL @@ -37,7 +43,7 @@ EX struct dqi_sky *sky; EX void prepare_sky() { sky = NULL; - if(euclid) { + if(euclid && !geom3::sph_in_euc()) { if(WDIM == 3 || GDIM == 2) return; if(no_wall_rendering) return; shiftmatrix T = ggmatrix(currentmap->gamestart()); @@ -46,7 +52,7 @@ EX void prepare_sky() { queuepolyat(T * zpush(cgi.SKY+0.5) * xpush(cgi.SKY+0.5), cgi.shSun, 0xFFFF00FF, PPR::SKY); } else { - sky = &queuea (PPR::MISSILE); + sky = &queuea (euclid ? PPR::EUCLIDEAN_SKY : PPR::MISSILE); } } @@ -57,6 +63,7 @@ shiftmatrix sky_cview; void compute_skyvertices(const vector& sky) { skyvertices.clear(); if(!draw_sky) return; + if(vid.wall_height < 0 && geom3::euc_in_hyp()) return; /* just looks bad */ int sk = get_skybrightness(); @@ -184,6 +191,7 @@ void compute_skyvertices(const vector& sky) { } if(true) { + hyperpoint tctr = tile_center(); cellwalker cw0(c, i); cellwalker cw = cw0; do { @@ -197,7 +205,7 @@ void compute_skyvertices(const vector& sky) { transmatrix T1 = Id; do { - vertices.push_back(tC0(T1)); + vertices.push_back(T1 * tctr); vcolors.push_back(colors[cw.at].first); T1 = T1 * currentmap->adj(cw.at, cw.spin); cw += wstep; cw++; @@ -210,15 +218,16 @@ void compute_skyvertices(const vector& sky) { for(int i=0; i& sky) { void dqi_sky::draw() { if(!vid.usingGL || sky.empty() || skyvertices.empty()) return; - + #if CAP_VR transmatrix s = (vrhr::rendering() ? vrhr::master_cview : cview()).T * inverse(sky_cview.T); #else transmatrix s = cview().T * inverse(sky_cview.T); #endif + if(euclid) be_euclidean_infinity(s); for(int ed = current_display->stereo_active() ? -1 : 0; ed<2; ed+=2) { if(global_projection && global_projection != ed) continue; current_display->next_shader_flags = GF_VARCOLOR; @@ -282,7 +292,27 @@ color_t skycolor(cell *c) { return gradient(0x4040FF, 0xFFFFFF, 0, z, 63); } -EX const ld star_val = 2; +/** move an Euclidean matrix to V(C0) == C0 */ +EX void be_euclidean_infinity(transmatrix& V) { for(int i=0; i<3; i++) V[i][3] = 0; } + +void draw_star(const shiftmatrix& V, const hpcshape& sh, color_t col, ld rev = false) { + ld star_val = 2; + bool have_stars = geom3::same_in_same() || geom3::sph_in_euc() || geom3::sph_in_hyp() || geom3::euc_in_hyp(); + if(geom3::sph_in_euc()) { if(cgi.SKY < 0) have_stars = false; star_val = 1.8; } + if(geom3::sph_in_hyp() && cgi.SKY < 0) have_stars = false; + if(geom3::euc_in_hyp() && (rev ? cgi.SKY > 0 : cgi.SKY < 0)) have_stars = false; + if(!have_stars) return; + ld val = cgi.SKY+star_val; + if(rev) val = -val; + + if(euclid) { + auto V1 = V; be_euclidean_infinity(V1.T); + queuepolyat(V1 * zpush(val), sh, col, PPR::EUCLIDEAN_SKY); + } + else { + queuepolyat(V * zpush(val), sh, col, PPR::SKY); + } + } void celldrawer::draw_ceiling() { @@ -291,19 +321,17 @@ void celldrawer::draw_ceiling() { auto add_to_sky = [this] (color_t col, color_t col2) { if(sky) sky->sky.emplace_back(c, V, col, col2); }; - + switch(ceiling_category(c)) { /* ceilingless levels */ case 1: { - if(euclid) return; - if(fieldpattern::fieldval_uniq(c) % 3 == 0) { - queuepolyat(V * zpush(cgi.SKY+star_val), cgi.shNightStar, 0xFFFFFFFF, PPR::SKY); - } + if(euclid && !geom3::sph_in_euc()) return; + if(fieldpattern::fieldval_uniq(c) % 3 == 0) + draw_star(V, cgi.shNightStar, 0xFFFFFFFF); add_to_sky(0x00000F, 0x00000F); if(c->land == laAsteroids) { - if(fieldpattern::fieldval_uniq(c) % 9 < 3) { - queuepolyat(V * zpush(-star_val-cgi.SKY), cgi.shNightStar, 0xFFFFFFFF, PPR::SKY); - } + if(fieldpattern::fieldval_uniq(c) % 9 < 3) + draw_star(V, cgi.shNightStar, 0xFFFFFFFF, true); int sk = get_skybrightness(-1); auto sky = draw_shapevec(c, V * MirrorZ, cgi.shFullFloor.levels[SIDE_SKY], 0x000000FF + 0x100 * (sk/17), PPR::SKY); if(sky) sky->tinf = NULL, sky->flags |= POLY_INTENSE; @@ -312,7 +340,7 @@ void celldrawer::draw_ceiling() { } case 2: { - if(euclid) return; + if(euclid && !geom3::sph_in_euc()) return; color_t col; color_t skycol; @@ -320,25 +348,19 @@ void celldrawer::draw_ceiling() { case laWineyard: col = 0x4040FF; skycol = 0x8080FF; - if(emeraldval(c) / 4 == 11) { - queuepolyat(V * zpush(cgi.SKY+star_val), cgi.shSun, 0xFFFF00FF, PPR::SKY); - } + if(emeraldval(c) / 4 == 11) draw_star(V, cgi.shSun, 0xFFFF00FF); break; case laDesert: col = 0x2020C0; skycol = 0x8080FF; - if(emeraldval(c) / 4 == 11) { - queuepolyat(V * zpush(cgi.SKY+star_val), cgi.shSun, 0xFFFF00FF, PPR::SKY); - } + if(emeraldval(c) / 4 == 11) draw_star(V, cgi.shSun, 0xFFFF00FF); break; case laFrog: col = 0x4040FF; skycol = 0x8080FF; - if(zebra40(c) / 4 == 1) { - queuepolyat(V * zpush(cgi.SKY+star_val), cgi.shSun, 0xFFFF00FF, PPR::SKY); - } + if(zebra40(c) / 4 == 1) draw_star(V, cgi.shSun, 0xFFFF00FF); break; case laPower: @@ -395,7 +417,7 @@ void celldrawer::draw_ceiling() { case 3: { add_to_sky(0, 0); - if(camera_level <= cgi.WALL) return; + if(camera_over(cgi.WALL)) return; if(c->land == laMercuryRiver) fcol = linf[laTerracotta].color, fd = 1; if(qfi.fshape) draw_shapevec(c, V, qfi.fshape->levels[SIDE_WALL], darkena(fcol, fd, 0xFF), PPR::WALL); forCellIdEx(c2, i, c) @@ -410,7 +432,7 @@ void celldrawer::draw_ceiling() { case 4: { add_to_sky(0x00000F, 0x00000F); - if(camera_level <= cgi.HIGH2) return; + if(camera_over(cgi.HIGH)) return; auto ispal = [&] (cell *c0) { return c0->land == laPalace && among(c0->wall, waPalace, waClosedGate, waOpenGate); }; color_t wcol2 = 0xFFD500; if(ispal(c)) { @@ -428,15 +450,13 @@ void celldrawer::draw_ceiling() { if(among(c->wall, waClosedGate, waOpenGate) && qfi.fshape) draw_shapevec(c, V, qfi.fshape->levels[SIDE_WALL], 0x202020FF, PPR::WALL); if(euclid) return; - if(true) { - queuepolyat(V * zpush(cgi.SKY+star_val), cgi.shNightStar, 0xFFFFFFFF, PPR::SKY); - } + draw_star(V, cgi.shNightStar, 0xFFFFFFFF); break; } case 6: { add_to_sky(skycolor(c), 0x4040C0); - if(camera_level <= cgi.HIGH2) return; + if(camera_over(cgi.HIGH2)) return; color_t wcol2 = winf[waRuinWall].color; if(c->landparam == 1) forCellIdEx(c2, i, c) if(c2->landparam != 1) @@ -453,10 +473,9 @@ void celldrawer::draw_ceiling() { case 7: { add_to_sky(0x00000F, 0x00000F); - if(fieldpattern::fieldval_uniq(c) % 5 < 2) { - queuepolyat(V * zpush(cgi.SKY+star_val), cgi.shNightStar, 0xFFFFFFFF, PPR::SKY); - } - if(camera_level <= cgi.HIGH2) return; + if(fieldpattern::fieldval_uniq(c) % 5 < 2) + draw_star(V, cgi.shNightStar, 0xFFFFFFFF); + if(camera_over(cgi.HIGH2)) return; color_t wcol2 = winf[waColumn].color; if(c->landparam == 1) forCellIdEx(c2, i, c) if(c2->landparam != 1) @@ -473,7 +492,7 @@ void celldrawer::draw_ceiling() { case 5: { add_to_sky(0x00000F, 0x00000F); - if(camera_level <= cgi.WALL) return; + if(camera_over(cgi.WALL)) return; if(pseudohept(c)) { forCellIdEx(c2, i, c) @@ -483,9 +502,7 @@ void celldrawer::draw_ceiling() { draw_shapevec(c, V, qfi.fshape->levels[SIDE_WALL], darkena(fcol, fd, 0xFF), PPR::WALL); if(euclid) return; - if(true) { - queuepolyat(V * zpush(cgi.SKY+star_val), cgi.shNightStar, 0xFFFFFFFF, PPR::SKY); - } + draw_star(V, cgi.shNightStar, 0xFFFFFFFF); } } } diff --git a/system.cpp b/system.cpp index 627ce067..d9e72077 100644 --- a/system.cpp +++ b/system.cpp @@ -278,7 +278,7 @@ EX void initgame() { if(cwt.at->land == laCrossroads2) { cell *c = cwt.at; - if(hybri) { c = hybrid::get_where(c).first; PIU( c->cmove(0) ); } + if(mhybrid) { c = hybrid::get_where(c).first; PIU( c->cmove(0) ); } c->landparam = 12; c->cmove(0)->landparam = 44; c->cmove(0)->land = laCrossroads2; @@ -1405,14 +1405,14 @@ EX void set_geometry(eGeometry target) { gp::param.second = 0; } #endif - if(DUAL && geometry != gArchimedean && !hybri) + if(DUAL && geometry != gArchimedean && !mhybrid) variation = ginf[geometry].default_variation; #if CAP_BT - if(bt::in() || WDIM == 3 || kite::in() || arb::in()) if(!hybri) variation = eVariation::pure; + if(bt::in() || WDIM == 3 || kite::in() || arb::in()) if(!mhybrid) variation = eVariation::pure; #endif if(S3 >= OINF) variation = eVariation::pure; - if(INVERSE && !hybri) variation = gp::variation_for(gp::param); - if(ginf[target].default_variation == eVariation::pure && geometry != gArchimedean && !hybri) + if(INVERSE && !mhybrid) variation = gp::variation_for(gp::param); + if(ginf[target].default_variation == eVariation::pure && geometry != gArchimedean && !mhybrid) variation = eVariation::pure; geometry_settings(was_default); @@ -1442,7 +1442,7 @@ EX void set_variation(eVariation target) { return; } if(target != eVariation::pure) { - if(bt::in() || sol || kite::in() || WDIM == 3) if(!prod) geometry = gNormal; + if(bt::in() || sol || kite::in() || WDIM == 3) if(!mproduct) geometry = gNormal; } auto& cd = ginf[gCrystal]; if(target == eVariation::bitruncated && cryst && cd.sides == 8 && cd.vertex == 4) {