diff --git a/3d-models.cpp b/3d-models.cpp index e0c0e8e9..7fb3047a 100644 --- a/3d-models.cpp +++ b/3d-models.cpp @@ -785,19 +785,19 @@ void geometry_information::shift_last_straight(ld z) { for(int i=last->s; imaster, cview()); while(!dq::drawqueue.empty()) { auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); + heptagon *h = p.first; + shiftmatrix V = p.second; dq::drawqueue.pop(); if(do_draw(h->c7, V)) drawcell(h->c7, V); else continue; for(int i=0; itype; i++) { - transmatrix V1 = V * adj(h, i); - bandfixer bf(V1); + shiftmatrix V1 = V * adj(h, i); + optimize_shift(V1); dq::enqueue(h->move(i), V1); } } diff --git a/archimedean.cpp b/archimedean.cpp index 04b436ee..175d0d77 100644 --- a/archimedean.cpp +++ b/archimedean.cpp @@ -677,14 +677,13 @@ struct hrmap_archimedean : hrmap { } void draw() override { - dq::visited.clear(); + dq::clear_all(); dq::enqueue(centerover->master, cview()); while(!dq::drawqueue.empty()) { auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); + heptagon *h = p.first; + shiftmatrix V = p.second; dq::drawqueue.pop(); int id = id_of(h); @@ -699,8 +698,8 @@ struct hrmap_archimedean : hrmap { if(DUAL && (i&1)) continue; h->cmove(i); if(PURE && id >= 2*current.N && h->move(i) && id_of(h->move(i)) >= 2*current.N) continue; - transmatrix V1 = V * current.adjcell_matrix(h, i); - bandfixer bf(V1); + shiftmatrix V1 = V * current.adjcell_matrix(h, i); + optimize_shift(V1); dq::enqueue(h->move(i), V1); } } @@ -712,7 +711,7 @@ struct hrmap_archimedean : hrmap { transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) override { if(use_gmatrix && gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) - return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7]; + return inverse_shift(gmatrix0[h1->c7], gmatrix0[h2->c7]); transmatrix gm = Id, where = Id; auto& cof = current_or_fake(); while(h1 != h2) { diff --git a/asonov.cpp b/asonov.cpp index 30e46dc6..4e76d3ad 100644 --- a/asonov.cpp +++ b/asonov.cpp @@ -178,14 +178,14 @@ struct hrmap_asonov : hrmap { } void draw() override { - dq::visited_by_matrix.clear(); + dq::clear_all(); dq::enqueue_by_matrix(centerover->master, cview()); while(!dq::drawqueue.empty()) { auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); + heptagon *h = p.first; + shiftmatrix V = p.second; dq::drawqueue.pop(); cell *c = h->c7; diff --git a/basegraph.cpp b/basegraph.cpp index 738adb72..43b6cd71 100644 --- a/basegraph.cpp +++ b/basegraph.cpp @@ -20,9 +20,9 @@ struct display_data { /** Camera rotation, used in nonisotropic geometries. */ transmatrix local_perspective; /** The view relative to the player character. */ - transmatrix player_matrix; + shiftmatrix player_matrix; /** On-screen coordinates for all the visible cells. */ - unordered_map cellmatrices, old_cellmatrices; + unordered_map cellmatrices, old_cellmatrices; /** Position of the current map view, relative to the screen (0 to 1). */ ld xmin, ymin, xmax, ymax; /** Position of the current map view, in pixels. */ @@ -43,14 +43,14 @@ struct display_data { bool in_anaglyph(); void set_viewport(int ed); - void set_projection(int ed); + void set_projection(int ed, ld shift); void set_mask(int ed); - void set_all(int ed); + void set_all(int ed, ld shift); /** Which copy of the player cell? */ transmatrix which_copy; /** On-screen coordinates for all the visible cells. */ - unordered_map> all_drawn_copies; + unordered_map> all_drawn_copies; }; #define View (::hr::current_display->view_matrix) @@ -245,13 +245,13 @@ inline void reset_projection() { new_projection_needed = true; } EX ld lband_shift; -void display_data::set_all(int ed) { +void display_data::set_all(int ed, ld shift) { auto t = this; auto current_projection = tie(ed, pmodel, t, current_rbuffer); - if(new_projection_needed || !glhr::current_glprogram || (next_shader_flags & GF_which) != (glhr::current_glprogram->shader_flags & GF_which) || current_projection != last_projection || band_shift != lband_shift) { + if(new_projection_needed || !glhr::current_glprogram || (next_shader_flags & GF_which) != (glhr::current_glprogram->shader_flags & GF_which) || current_projection != last_projection || shift != lband_shift) { last_projection = current_projection; - lband_shift = band_shift; - set_projection(ed); + lband_shift = shift; + set_projection(ed, shift); set_mask(ed); set_viewport(ed); new_projection_needed = false; @@ -956,7 +956,7 @@ EX void drawCircle(int x, int y, int size, color_t color, color_t fillcolor IS(0 float rr = (M_PI * 2 * r) / pts; glcoords.push_back(glhr::makevertex(x + size * sin(rr), y + size * pconf.stretch * cos(rr), 0)); } - current_display->set_all(0); + current_display->set_all(0, lband_shift); glhr::vertices(glcoords); glhr::set_depthtest(false); if(fillcolor) { diff --git a/binary-tiling.cpp b/binary-tiling.cpp index 8870a5d5..10d179ce 100644 --- a/binary-tiling.cpp +++ b/binary-tiling.cpp @@ -418,15 +418,13 @@ EX namespace bt { } void draw() override { - dq::visited.clear(); + dq::clear_all(); dq::enqueue(centerover->master, cview()); while(!dq::drawqueue.empty()) { auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); - bandfixer bf(V); + heptagon *h = p.first; + shiftmatrix V = p.second; dq::drawqueue.pop(); @@ -435,7 +433,7 @@ EX namespace bt { drawcell(c, V); for(int i=0; itype; i++) - dq::enqueue(h->cmove(i), V * adj(h, i)); + dq::enqueue(h->cmove(i), optimized_shift(V * adj(h, i))); } } @@ -449,7 +447,7 @@ EX namespace bt { transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) override { if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) - return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7]; + return inverse_shift(gmatrix0[h1->c7], gmatrix0[h2->c7]); transmatrix gm = Id, where = Id; while(h1 != h2) { if(h1->distance <= h2->distance) { @@ -809,32 +807,32 @@ EX namespace bt { #if MAXMDIM == 4 - EX void queuecube(const transmatrix& V, ld size, color_t linecolor, color_t facecolor) { + EX void queuecube(const shiftmatrix& V, ld size, color_t linecolor, color_t facecolor) { ld yy = log(2) / 2; const int STEP=3; const ld MUL = 1. / STEP; - auto at = [&] (ld x, ld y, ld z) { curvepoint(V * parabolic3(size*x, size*y) * xpush0(size*yy*z)); }; + auto at = [&] (ld x, ld y, ld z) { curvepoint(parabolic3(size*x, size*y) * xpush0(size*yy*z)); }; for(int a:{-1,1}) { for(ld t=-STEP; t qty; @@ -123,10 +123,10 @@ EX void drawBlizzards() { sball.next = &sball2; sball2.prev = &sball; - hyperpoint t = inverse(sball.global) * tC0(sball2.global); + hyperpoint t = inverse_shift(sball.global, tC0(sball2.global)); double at0 = at + sball.phase; if(at0>1) at0 -= 1; - transmatrix tpartial = sball.global * rspintox(t) * xpush(hdist0(t) * at0); + shiftmatrix tpartial = sball.global * rspintox(t) * xpush(hdist0(t) * at0); if(wmascii || wmblack) queuestr(tpartial, .2, ".", 0xFFFFFF); @@ -222,8 +222,8 @@ EX void drawArrowTraps() { auto r = traplimits(c); try { - transmatrix& t0 = gmatrix.at(r[0]); - transmatrix& t1 = gmatrix.at(r[4]); + shiftmatrix& t0 = gmatrix.at(r[0]); + shiftmatrix& t1 = gmatrix.at(r[4]); ignore(t0); ignore(t1); @@ -236,10 +236,10 @@ EX void drawArrowTraps() { int tt = int(fractick(64) * 401); for(int u=0; u<2; u++) { - transmatrix& tu = u ? t0 : t1; - transmatrix& tv = u ? t1 : t0; - hyperpoint trel = inverse(tu) * tC0(tv); - transmatrix tpartial = tu * rspintox(trel) * xpush(hdist0(trel) * tt / 401.0); + shiftmatrix& tu = u ? t0 : t1; + shiftmatrix& tv = u ? t1 : t0; + hyperpoint trel = inverse_shift(tu, tC0(tv)); + shiftmatrix tpartial = tu * rspintox(trel) * xpush(hdist0(trel) * tt / 401.0); tpartial = tpartial * ypush(.05); if(GDIM == 3) tpartial = tpartial * cspin(1, 2, M_PI/2); queuepoly(tpartial, cgi.shTrapArrow, 0xFFFFFFFF); diff --git a/celldrawer.cpp b/celldrawer.cpp index 9edec2e0..a1a390cf 100644 --- a/celldrawer.cpp +++ b/celldrawer.cpp @@ -6,7 +6,7 @@ int coastvalEdge(cell *c); struct celldrawer { cell *c; - transmatrix V; + shiftmatrix V; color_t fcol; color_t wcol; @@ -18,8 +18,8 @@ struct celldrawer { bool error; bool onradar; char asciichar; - transmatrix Vboat; - transmatrix Vd; + shiftmatrix Vboat; + shiftmatrix Vd; int sl; color_t asciiborder; color_t asciicol1; @@ -52,11 +52,11 @@ struct celldrawer { bool draw_shmup_monster(); void draw_gravity_particles(); - void set_land_floor(const transmatrix& Vf); + void set_land_floor(const shiftmatrix& Vf); void set_towerfloor(const cellfunction& cf = coastvalEdge); void set_zebrafloor(); void set_maywarp_floor(); - void set_reptile_floor(const transmatrix& V, color_t col, bool nodetails = false); + void set_reptile_floor(const shiftmatrix& V, color_t col, bool nodetails = false); void set_emeraldfloor(); void shmup_gravity_floor(); @@ -67,7 +67,7 @@ struct celldrawer { void do_viewdist(); }; -inline void drawcell(cell *c, const transmatrix& V) { +inline void drawcell(cell *c, const shiftmatrix& V) { celldrawer dd; dd.c = c; dd.V = V; @@ -703,14 +703,14 @@ void celldrawer::draw_wall() { int hdir = 0; for(int i=0; itype; i++) if(c->move(i) && c->move(i)->wall == waClosedGate) hdir = i; - transmatrix V2 = mscale(V, wmspatial?cgi.WALL:1) * ddspin(c, hdir, M_PI); + shiftmatrix V2 = mscale(V, wmspatial?cgi.WALL:1) * ddspin(c, hdir, M_PI); queuepolyat(V2, cgi.shPalaceGate, darkena(wcol, 0, 0xFF), wmspatial?PPR::WALL3A:PPR::WALL); starcol = 0; } hpcshape& shThisWall = isGrave(c->wall) ? cgi.shCross : cgi.shWall[ct6]; - transmatrix V1 = V; + shiftmatrix V1 = V; if(&shThisWall == &cgi.shCross) { auto si = patterns::getpatterninfo(c, patterns::PAT_ZEBRA, patterns::SPF_SYM0123); V1 = V * applyPatterndir(c, si); @@ -731,7 +731,7 @@ void celldrawer::draw_wall() { if(starcol) queuepoly(V1, shThisWall, darkena(starcol, 0, 0xFF)); } else { - transmatrix Vdepth = mscale(V1, cgi.WALL); + shiftmatrix Vdepth = mscale(V1, cgi.WALL); int alpha = 0xFF; if(c->wall == waIcewall) alpha = 0xC0; @@ -778,7 +778,7 @@ void celldrawer::draw_boat() { Vboat = V; nospin = c->wall == waBoat && applyAnimation(c, Vboat, footphase, LAYER_BOAT); if(!nospin) Vboat = face_the_player(V); - else Vboat = cspin(0, 2, M_PI) * Vboat; + else Vboat = Vboat * cspin(0, 2, M_PI); queuepolyat(mscale(Vboat, cgi.scalefactor/2), cgi.shBoatOuter, outcol, PPR::BOATLEV2); queuepolyat(mscale(Vboat, cgi.scalefactor/2-0.01), cgi.shBoatInner, incol, PPR::BOATLEV2); return; @@ -796,7 +796,7 @@ void celldrawer::draw_boat() { if(!nospin && c->mondir != NODIR) Vboat = Vboat * ddspin(c, c->mondir, M_PI); else { - transmatrix Vx; + shiftmatrix Vx; if(applyAnimation(c, Vx, footphase, LAYER_SMALL)) animations[LAYER_SMALL][c].footphase = 0; } @@ -885,8 +885,8 @@ void celldrawer::draw_grid() { auto horizontal = [&] (ld y, ld x1, ld x2, int steps, int dir) { if(vid.linequality > 0) steps <<= vid.linequality; if(vid.linequality < 0) steps >>= -vid.linequality; - for(int i=0; i<=steps; i++) curvepoint(V * bt::get_horopoint(y, x1 + (x2-x1) * i / steps)); - queuecurve(gridcolor(c, c->move(dir)), 0, PPR::LINE); + for(int i=0; i<=steps; i++) curvepoint(bt::get_horopoint(y, x1 + (x2-x1) * i / steps)); + queuecurve(V, gridcolor(c, c->move(dir)), 0, PPR::LINE); }; horizontal(yy, 2*xx, xx, 4, bt::bd_up_right); horizontal(yy, xx, -xx, 8, bt::bd_up); @@ -911,7 +911,7 @@ void celldrawer::draw_halfvine() { i = t; qfi.spin = ddspin(c, i, M_PI/S3); - transmatrix V2 = V * qfi.spin; + shiftmatrix V2 = V * qfi.spin; if(wmspatial && wmescher && GDIM == 2) { set_floor(cgi.shSemiFeatherFloor[0]); @@ -931,11 +931,11 @@ void celldrawer::draw_halfvine() { int vcol = winf[waVinePlant].color; int vcol2 = gradient(0, vcol, 0, .8, 1); - transmatrix Vdepth = mscale(V2, cgi.WALL); + shiftmatrix Vdepth = mscale(V2, cgi.WALL); queuepolyat(GDIM == 2 ? Vdepth : V2, cgi.shSemiFloor[0], darkena(vcol, fd, 0xFF), PPR::WALL3A); {dynamicval p(poly_outline, OUTLINE_TRANS); queuepolyat(V2 * spin(M_PI*2/3), cgi.shSemiFloorShadow, SHADOW_WALL, GDIM == 2 ? PPR::WALLSHADOW : PPR::TRANSPARENT_SHADOW); } - auto& side = queuepolyat(V2, cgi.shSemiFloorSide[SIDE_WALL], darkena(vcol, fd, 0xFF), PPR::WALL3A-2+away(V2)); + auto& side = queuepolyat(V2, cgi.shSemiFloorSide[SIDE_WALL], darkena(vcol, fd, 0xFF), PPR::WALL3A-2+away(V2.T)); #if MAXMDIM >= 4 if(GDIM == 3 && qfi.fshape) { side.tinf = &floor_texture_vertices[shar.id]; @@ -978,7 +978,7 @@ void celldrawer::draw_mirrorwall() { if(c->move(d) && c->modmove(d+1) && c->move(d)->land == laMirrorWall && c->modmove(d+1)->land == laMirrorWall) break; qfi.spin = ddspin(c, d, 0); - transmatrix V2 = V * qfi.spin; + shiftmatrix V2 = V * qfi.spin; if(!wmblack) for(int d=0; dtype; d++) { inmirrorcount+=d; queuepolyat(V2 * spin(d*M_PI/S3), cgi.shHalfFloor[2], darkena(fcol, fd, 0xFF), PPR::FLOORa); @@ -1002,7 +1002,7 @@ void celldrawer::draw_mirrorwall() { } else { qfi.spin = ddspin(c, d, M_PI); - transmatrix V2 = V * qfi.spin; + shiftmatrix V2 = V * qfi.spin; if(!wmblack) { inmirrorcount++; queuepolyat(mirrorif(V2, !onleft), cgi.shHalfFloor[ct6], darkena(fcol, fd, 0xFF), PPR::FLOORa); @@ -1030,7 +1030,7 @@ void celldrawer::draw_mirrorwall() { } } -void celldrawer::set_land_floor(const transmatrix& Vf) { +void celldrawer::set_land_floor(const shiftmatrix& Vf) { switch(c->land) { case laPrairie: case laAlchemist: @@ -1193,11 +1193,11 @@ void celldrawer::set_land_floor(const transmatrix& Vf) { set_floor(bspin, cgi.shMercuryBridge[0]); // only needed in one direction if(c < c->move(bridgedir)) { - bspin = Vf * bspin; - queuepoly(bspin, cgi.shMercuryBridge[1], darkena(fcol, fd+1, 0xFF)); + shiftmatrix Vbspin = Vf * bspin; + queuepoly(Vbspin, cgi.shMercuryBridge[1], darkena(fcol, fd+1, 0xFF)); if(wmspatial) { - queuepolyat(mscale(bspin, cgi.LAKE), cgi.shMercuryBridge[1], darkena(gradient(0, winf[waMercury].color, 0, 0.8,1), 0, 0x80), PPR::LAKELEV); - queuepolyat(mscale(bspin, cgi.BOTTOM), cgi.shMercuryBridge[1], darkena(0x202020, 0, 0xFF), PPR::LAKEBOTTOM); + queuepolyat(mscale(Vbspin, cgi.LAKE), cgi.shMercuryBridge[1], darkena(gradient(0, winf[waMercury].color, 0, 0.8,1), 0, 0x80), PPR::LAKELEV); + queuepolyat(mscale(Vbspin, cgi.BOTTOM), cgi.shMercuryBridge[1], darkena(0x202020, 0, 0xFF), PPR::LAKEBOTTOM); } } } @@ -1354,7 +1354,7 @@ void celldrawer::draw_features() { break; case waBigStatue: { - transmatrix V2 = V; + shiftmatrix V2 = V; double footphase; applyAnimation(c, V2, footphase, LAYER_BOAT); @@ -1381,7 +1381,7 @@ void celldrawer::draw_features() { /* fallthrough */ case waClosePlate: case waOpenPlate: { - transmatrix V2 = V; + shiftmatrix V2 = V; if(wmescher && geosupport_football() == 2 && pseudohept(c) && c->land == laPalace) V2 = V * spin(M_PI / c->type); if(GDIM == 3) { #if MAXMDIM >= 4 @@ -1433,7 +1433,7 @@ void celldrawer::draw_features() { if(wmspatial) { color_t col = winf[waGlass].color; int dcol = darkena(col, 0, 0x80); - transmatrix Vdepth = mscale(Vd, cgi.WALL); + shiftmatrix Vdepth = mscale(Vd, cgi.WALL); if(GDIM == 3) draw_shapevec(c, V, cgi.shMFloor.levels[SIDE_WALL], dcol, PPR::WALL); else @@ -1543,7 +1543,7 @@ void celldrawer::draw_features() { if(wmspatial) { color_t col = winf[c->wall].color; int dcol = darkena(col, 0, 0xC0); - transmatrix Vdepth = mscale(Vd, cgi.WALL); + shiftmatrix Vdepth = mscale(Vd, cgi.WALL); if(GDIM == 3) draw_shapevec(c, V, cgi.shMFloor.levels[SIDE_WALL], dcol, PPR::WALL); else @@ -1581,8 +1581,8 @@ void celldrawer::draw_features() { ld rad = cgi.hexf * (.3 * (u + ds)); int tcol = darkena(gradient(forecolor, backcolor, 0, rad, 1.5 * cgi.hexf), 0, 0xFF); PRING(a) - curvepoint(V*xspinpush0(a * M_PI / cgi.S42, rad)); - queuecurve(tcol, 0, PPR::LINE); + curvepoint(xspinpush0(a * M_PI / cgi.S42, rad)); + queuecurve(V, tcol, 0, PPR::LINE); } } if(hasTimeout(c)) V2 = V2 * spintick(c->land == laPower ? 5000 : 500); @@ -1644,16 +1644,16 @@ void celldrawer::draw_features_and_walls_3d() { } else if(prod) { if(a < c->type-2 && !in_s2xe()) { - ld d = in_e2xe() ? sqhypot_d(2, tC0(V)) : V[2][2]; - hyperpoint h = (V * cgi.walltester[ofs + a]); + ld d = in_e2xe() ? sqhypot_d(2, unshift(tC0(V))) : V[2][2]; + hyperpoint h = (unshift(V) * cgi.walltester[ofs + a]); ld d1 = in_e2xe() ? sqhypot_d(2, h) : h[2]; if(d1 >= d - 1e-6) continue; } else if(a == c->type-1) { - if(zlevel(tC0(V)) >= -cgi.plevel/2) continue; + if(zlevel(tC0(V.T)) >= -cgi.plevel/2) continue; } else if(a == c->type-2) { - if(zlevel(tC0(V)) <= +cgi.plevel/2) continue; + if(zlevel(tC0(V.T)) <= +cgi.plevel/2) continue; } } if(qfi.fshape && wmescher) { @@ -1763,12 +1763,12 @@ void celldrawer::check_rotations() { ds.best = c; ds.speed = spd; if(prod) { - auto pd = product_decompose(tC0(V)); + auto pd = product_decompose(unshift(tC0(V))); ds.total += pd.second; ds.depth += pd.first; } else - ds.total += tC0(V); + ds.total += unshift(tC0(V)); ds.qty++; ds.point = normalize_flat(ds.total); if(prod) ds.point = zshift(ds.point, ds.depth / ds.qty); @@ -1812,7 +1812,7 @@ void celldrawer::check_rotations() { void celldrawer::bookkeeping() { bool orig = false; if(!inmirrorcount) { - transmatrix& gm = gmatrix[c]; + shiftmatrix& gm = gmatrix[c]; orig = (gm[LDIM][LDIM] == 0) || hdist0(tC0(gm)) >= hdist0(tC0(V)); if(orig) gm = V; current_display->all_drawn_copies[c].emplace_back(V); @@ -1837,8 +1837,8 @@ void celldrawer::bookkeeping() { else { playerV = V * ddspin(c, cwt.spin, 0); if(cwt.mirrored) playerV = playerV * Mirror; - if((!confusingGeometry() && !fake::split() && !inmirrorcount) || eqmatrix(V, current_display->which_copy, 1e-2)) - current_display->which_copy = V; + if((!confusingGeometry() && !fake::split() && !inmirrorcount) || eqmatrix(unshift(V), current_display->which_copy, 1e-2)) + current_display->which_copy = unshift(V); if(orig) cwtV = playerV; } } @@ -1861,7 +1861,7 @@ void celldrawer::bookkeeping() { if(c->cpdist <= orbrange) if(multi::players > 1 || multi::alwaysuse) for(int i=0; iland == laZebra) fd++; if(c->land == laHalloween && !wmblack) { - transmatrix Vdepth = wmspatial ? mscale(V, cgi.BOTTOM) : V; + shiftmatrix Vdepth = wmspatial ? mscale(V, cgi.BOTTOM) : V; if(GDIM == 3) draw_shapevec(c, V, cgi.shFullFloor.levels[SIDE_LAKE], darkena(firecolor(0, 10), 0, 0xDF), PPR::TRANSPARENT_LAKE); else @@ -2178,7 +2178,7 @@ void celldrawer::draw_wall_full() { #if CAP_SHAPES int sha = shallow(c); -#define D(v) darkena(gradient(0, col, 0, v * (sphere ? spherity(V * currentmap->adj(c,i)) : 1), 1), fd, 0xFF) +#define D(v) darkena(gradient(0, col, 0, v * (sphere ? spherity(V.T * currentmap->adj(c,i)) : 1), 1), fd, 0xFF) if(wmspatial && c->wall == waShallow && WDIM == 2) { color_t col = (highwall(c) || c->wall == waTower) ? wcol : fcol; forCellIdEx(c2, i, c) if(chasmgraph(c2) && c2->wall != waShallow) @@ -2246,8 +2246,8 @@ void celldrawer::draw_item_full() { if(it == itCompass && isPlayerOn(c)) { cell *c1 = c ? findcompass(c) : NULL; if(c1) { - transmatrix P = ggmatrix(c1); - hyperpoint P1 = tC0(P); + shiftmatrix P = ggmatrix(c1); + shiftpoint P1 = tC0(P); queuestr(P1, 2*vid.fsize, "X", 0x10100 * int(128 + 100 * sintick(150))); queuestr(P1, vid.fsize, its(-compassDist(c)), 0x10101 * int(128 - 100 * sintick(150))); @@ -2332,8 +2332,8 @@ void celldrawer::draw_monster_full() { if(isize(ptds) != q) { if(WDIM == 2 && GDIM == 3 && abs(cgi.SLEV[sl] - cgi.FLOOR) > 1e-6) pushdown(c, q, V, cgi.SLEV[sl] - cgi.FLOOR, false, false); - if(GDIM ==2 && abs(geom3::factor_to_lev(zlevel(tC0(Vboat)))) > 1e-6) - pushdown(c, q, V, -geom3::factor_to_lev(zlevel(tC0(Vboat))), !isMultitile(c->monst), false); + if(GDIM ==2 && abs(geom3::factor_to_lev(zlevel(tC0(Vboat.T)))) > 1e-6) + pushdown(c, q, V, -geom3::factor_to_lev(zlevel(tC0(Vboat.T))), !isMultitile(c->monst), false); } #endif } @@ -2461,22 +2461,22 @@ void celldrawer::draw_gravity_particles() { switch(gravity_state) { case gsNormal: for(int i=0; i<6; i++) { - transmatrix T = V * spin(i*degree*60) * xpush(cgi.crossf/3); + shiftmatrix T = V * spin(i*degree*60) * xpush(cgi.crossf/3); queueline(mmscale(T, levf(r0)) * C0, mmscale(T, levf(r1)) * C0, grav_normal_color); } break; case gsAnti: for(int i=0; i<6; i++) { - transmatrix T = V * spin(i*degree*60) * xpush(cgi.crossf/3); + shiftmatrix T = V * spin(i*degree*60) * xpush(cgi.crossf/3); queueline(mmscale(T, levf(r0)) * C0, mmscale(T, levf(r1)) * C0, antigrav_color); } break; case gsLevitation: for(int i=0; i<6; i++) { - transmatrix T0 = V * spin(i*degree*60 + tt/60. * degree) * xpush(cgi.crossf/3); - transmatrix T1 = V * spin(i*degree*60 + (tt/60. + 30) * degree) * xpush(cgi.crossf/3); + shiftmatrix T0 = V * spin(i*degree*60 + tt/60. * degree) * xpush(cgi.crossf/3); + shiftmatrix T1 = V * spin(i*degree*60 + (tt/60. + 30) * degree) * xpush(cgi.crossf/3); ld lv = levf(GDIM == 3 ? (i+0.5)/6 : 0.5); queueline(mmscale(T0, lv) * C0, mmscale(T1, lv) * C0, levitate_color); } @@ -2488,24 +2488,24 @@ void celldrawer::draw_gravity_particles() { switch(gravity_state) { case gsNormal: for(int i=0; i<6; i++) { - transmatrix T0 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * (1-r0)); - transmatrix T1 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * (1-r1)); + shiftmatrix T0 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * (1-r0)); + shiftmatrix T1 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * (1-r1)); queueline(T0 * C0, T1 * C0, grav_normal_color); } break; case gsAnti: for(int i=0; i<6; i++) { - transmatrix T0 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * r0); - transmatrix T1 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * r1); + shiftmatrix T0 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * r0); + shiftmatrix T1 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * r1); queueline(T0 * C0, T1 * C0, antigrav_color); } break; case gsLevitation: for(int i=0; i<6; i++) { - transmatrix T0 = V * spin(i*degree*60 + tt/60. * degree) * xpush(cgi.crossf/3); - transmatrix T1 = V * spin(i*degree*60 + (tt/60. + 30) * degree) * xpush(cgi.crossf/3); + shiftmatrix T0 = V * spin(i*degree*60 + tt/60. * degree) * xpush(cgi.crossf/3); + shiftmatrix T1 = V * spin(i*degree*60 + (tt/60. + 30) * degree) * xpush(cgi.crossf/3); queueline(T0 * C0, T1 * C0, levitate_color); } break; @@ -2555,8 +2555,8 @@ void celldrawer::draw() { if(cw2.mirrored != cw.mirrored) V = V * Mirror; if(cw2.spin) V = V * spin(2*M_PI*cw2.spin/cw2.at->type); cw2.spin = 0; - dynamicval dc(cwtV, cwtV); - cwtV = V * inverse(gmatrix0[c]) * cwtV; + dynamicval dc(cwtV, cwtV); + cwtV = V * inverse_shift(gmatrix0[c], cwtV); drawcell(cw2.at, V); inmirrorcount -= cmc; return; @@ -2701,7 +2701,7 @@ void celldrawer::draw() { #endif #if CAP_MODEL - netgen::buildVertexInfo(c, V); + netgen::buildVertexInfo(c, unshift(V)); #endif } } @@ -2774,7 +2774,7 @@ void celldrawer::set_maywarp_floor() { else set_floor(cgi.shFloor); } -void celldrawer::set_reptile_floor(const transmatrix& V, color_t col, bool nodetails) { +void celldrawer::set_reptile_floor(const shiftmatrix& V, color_t col, bool nodetails) { auto si = euc::in(2,6) ? diff --git a/config.cpp b/config.cpp index 6d4bde76..241ca738 100644 --- a/config.cpp +++ b/config.cpp @@ -2003,7 +2003,7 @@ EX void showCustomizeChar() { double alpha = atan2(mousex - vid.xres/2, mousey - firsty) - M_PI/2; V = V * spin(alpha); - drawMonsterType(moPlayer, NULL, V, 0, cc_footphase / scale, NOCOLOR); + drawMonsterType(moPlayer, NULL, shiftless(V), 0, cc_footphase / scale, NOCOLOR); quickqueue(); keyhandler = [] (int sym, int uni) { diff --git a/control.cpp b/control.cpp index 0d3f490b..23bcac61 100644 --- a/control.cpp +++ b/control.cpp @@ -12,7 +12,7 @@ EX int frames; EX bool outoffocus = false; EX int mousex, mousey; -EX hyperpoint mouseh, mouseoh; +EX shiftpoint mouseh, mouseoh; EX bool pandora_leftclick, pandora_rightclick; @@ -66,17 +66,17 @@ EX int lastt; EX bool mouseout() { if((getcstat != '-' && getcstat) || (lgetcstat && lgetcstat != '-')) return true; - return outofmap(mouseh); + return outofmap(mouseh.h); } EX bool mouseout2() { if((getcstat && getcstat != '-') || (lgetcstat && lgetcstat != '-')) return true; - return outofmap(mouseh) || outofmap(mouseoh); + return outofmap(mouseh.h) || outofmap(mouseoh.h); } EX movedir vectodir(hyperpoint P) { - transmatrix U = ggmatrix(cwt.at); + transmatrix U = unshift(ggmatrix(cwt.at)); if(GDIM == 3 && WDIM == 2) U = radar_transform * U; P = direct_exp(lp_iapply(P)); @@ -137,18 +137,18 @@ EX void movepckeydir(int d) { EX void calcMousedest() { if(mouseout()) return; if(vid.revcontrol == true) { mouseh[0] = -mouseh[0]; mouseh[1] = -mouseh[1]; } - ld mousedist = intval(mouseh, tC0(ggmatrix(cwt.at))); + ld mousedist = hdist(mouseh, tC0(ggmatrix(cwt.at))); mousedest.d = -1; cellwalker bcwt = cwt; vector dists(cwt.at->type); - transmatrix U = ggmatrix(cwt.at); + shiftmatrix U = ggmatrix(cwt.at); for(int i=0; itype; i++) { transmatrix T = currentmap->adj(cwt.at, i); - dists[i] = intval(mouseh, U * T * C0); + dists[i] = hdist(mouseh, U * T * C0); } for(int i=0; itype; i++) if(dists[i] < mousedist) { @@ -331,9 +331,9 @@ EX void full_rotate_camera(int dir, ld val) { transmatrix T2 = eupush( tC0(inverse(View)) ); transmatrix nlp = View * T2; auto rV = inverse(nlp) * View; - h = nlp * inverse_exp(tC0(rV)); + h = nlp * inverse_exp(shiftless(tC0(rV))); } - else h = inverse_exp(tC0(View)); + else h = inverse_exp(shiftless(tC0(View))); shift_view(-h); rotate_view(cspin(dir, 2, val)); shift_view(h); @@ -1087,7 +1087,7 @@ EX bool gmodekeys(int sym, int uni) { ld maxs = 0; auto& cd = current_display; for(auto& p: gmatrix) for(int i=0; itype; i++) { - hyperpoint h = tC0(p.second * currentmap->adj(p.first, i)); + shiftpoint h = tC0(p.second * currentmap->adj(p.first, i)); hyperpoint onscreen; applymodel(h, onscreen); maxs = max(maxs, onscreen[0] / cd->xsize); diff --git a/crystal.cpp b/crystal.cpp index 1627a858..044223be 100644 --- a/crystal.cpp +++ b/crystal.cpp @@ -676,15 +676,13 @@ struct hrmap_crystal : hrmap_standard { // for(int i=0; imaster, cview()); while(!dq::drawqueue.empty()) { auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); - bandfixer bf(V); + heptagon *h = p.first; + shiftmatrix V = p.second; dq::drawqueue.pop(); cell *c = h->c7; @@ -694,7 +692,7 @@ struct hrmap_crystal : hrmap_standard { if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000) continue; for(int d=0; dmove(d), V * adj(h, d)); + dq::enqueue_by_matrix(h->move(d), optimized_shift(V * adj(h, d))); } } } @@ -704,7 +702,7 @@ struct hrmap_crystal : hrmap_standard { if(h2 == h1) return Id; for(int i=0; imove(i)) return adj(h1->master, i); if(gmatrix0.count(h2) && gmatrix0.count(h1)) - return inverse(gmatrix0[h1]) * gmatrix0[h2]; + return inverse_shift(gmatrix0[h1], gmatrix0[h2]); println(hlog, "unknown relmatrix, distance = ", celldistance(h1, h2)); return xpush(999); } @@ -828,7 +826,7 @@ EX ld compass_angle() { return (bitr ? M_PI/8 : 0) - master_to_c7_angle(); } -EX bool crystal_cell(cell *c, transmatrix V) { +EX bool crystal_cell(cell *c, shiftmatrix V) { if(!cryst) return false; @@ -846,7 +844,7 @@ EX bool crystal_cell(cell *c, transmatrix V) { ld dist = cellgfxdist(c, 0); for(int i=0; ihcoords[c->master]; auto lw = m->makewalker(co, i); @@ -1239,8 +1237,8 @@ void cut_triangle2(const hyperpoint pa, const hyperpoint pb, const hyperpoint pc pac[3] = pbc[3] = 1; - rug::rugpoint *rac = rug::addRugpoint(hac, 0); - rug::rugpoint *rbc = rug::addRugpoint(hbc, 0); + rug::rugpoint *rac = rug::addRugpoint(shiftless(hac), 0); + rug::rugpoint *rbc = rug::addRugpoint(shiftless(hbc), 0); rac->native = pac; rbc->native = pbc; rac->valid = true; @@ -1268,7 +1266,7 @@ EX void build_rugdata() { cell *c = gp.first; if(c->wall == waInvisibleFloor) continue; - const transmatrix& V = gp.second; + const shiftmatrix& V = gp.second; auto co = m->get_coord(c); vector vcoord(c->type); @@ -1307,7 +1305,7 @@ EX void build_rugdata() { for(int i=0; itype; i++) { int j = (i+1) % c->type; if((vco[i][3] >= 0) != (hco[3] >= 0) || (vco[j][3] >= 0) != (hco[3] >= 0)) { - cut_triangle(hco, vco[i], vco[j], tC0(V), V * get_corner_position(c, i), V * get_corner_position(c, j)); + cut_triangle(hco, vco[i], vco[j], unshift(tC0(V)), unshift(V * get_corner_position(c, i)), unshift(V * get_corner_position(c, j))); } } } diff --git a/drawing.cpp b/drawing.cpp index 05fdda78..d730e226 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -63,10 +63,8 @@ struct drawqueueitem { /** \brief Drawqueueitem used to draw polygons. The majority of drawqueueitems fall here. */ struct dqi_poly : drawqueueitem { - /** \brief see hr::band_shift */ - ld band_shift; /** \brief matrix used to transform the model */ - transmatrix V; + shiftmatrix V; /** \brief a vector of GL vertices where the model is stored */ const vector *tab; /** \brief the where does the model start */ @@ -95,10 +93,8 @@ struct dqi_poly : drawqueueitem { /** \brief Drawqueueitem used to draw lines */ struct dqi_line : drawqueueitem { - /** \brief see hr::band_shift */ - ld band_shift; /** \brief starting and ending point */ - hyperpoint H1, H2; + shiftpoint H1, H2; /** \brief how accurately to render the line */ int prf; /** \brief width of this line */ @@ -217,7 +213,7 @@ EX void glflush() { // printf("%08X | %d texts, %d vertices\n", text_color, texts_merged, isize(text_vertices)); current_display->next_shader_flags = GF_TEXTURE; dynamicval m(pmodel, mdPixel); - if(!svg::in) current_display->set_all(0); + if(!svg::in) current_display->set_all(0,0); glBindTexture(GL_TEXTURE_2D, text_texture); glhr::color2(text_color); glhr::set_depthtest(false); @@ -312,11 +308,11 @@ EX int get_side(const hyperpoint& H) { return (models::sin_ball * H[2] > models::cos_ball * H[1]) ? -1 : 1; if(pmodel == mdHemisphere) { hyperpoint res; - applymodel(H, res); + applymodel(shiftless(H), res); return res[2] < 0 ? -1 : 1; } if(pmodel == mdSpiral && pconf.spiral_cone < 360) { - return cone_side(H); + return cone_side(shiftless(H)); } return 0; } @@ -338,20 +334,20 @@ void fixpoint(glvertex& hscr, hyperpoint H) { bad = mid; } hyperpoint Hscr; - applymodel(good, Hscr); + applymodel(shiftless(good), Hscr); hscr = glhr::makevertex(Hscr[0]*current_display->radius, Hscr[1]*current_display->radius*pconf.stretch, Hscr[2]*current_display->radius); } -void addpoint(const hyperpoint& H) { +void addpoint(const shiftpoint& H) { if(true) { ld z = current_display->radius; // if(pconf.alpha + H[2] <= BEHIND_LIMIT && pmodel == mdDisk) poly_flags |= POLY_BEHIND; if(spherespecial) { - - if(correct_side(H)) { + auto H0 = H.h; + if(correct_side(H0)) { poly_flags |= POLY_INFRONT, last_infront = false; - if(!knowgood || (spherespecial > 0 ? H[2]>goodpoint[2] : H[2] 0 ? H[2]>goodpoint[2] : H[2] &tab, int ofs, int cnt) { +void addpoly(const shiftmatrix& V, const vector &tab, int ofs, int cnt) { if(pmodel == mdPixel) { for(int i=ofs; i &tab, int ofs, int cnt if(among(pmodel, mdPerspective, mdGeodesic)) { if(poly_flags & POLY_TRIANGLES) { for(int i=ofs; i &tab, int ofs, int cnt } if(start_behind == 2) { if(firstleave[0] * enter[0] + firstleave[1] * enter[1] < 0) poly_flags |= POLY_BEHIND; - else addpoint(firstleave); + else addpoint(shiftless(firstleave)); } if(knowgood && isize(tofix)) { if(true) { - hyperpoint Hx = V * C0, Hy = goodpoint; + hyperpoint Hx = V.T * C0, Hy = goodpoint; for(int i=0; i<20; i++) { hyperpoint mid = midz(Hx, Hy); if(correct_side(mid)) Hy = mid; @@ -613,18 +608,21 @@ void dqi_poly::gldraw() { for(int ed = current_display->stereo_active() ? -1 : 0; ed<2; ed+=2) { if(global_projection && global_projection != ed) continue; - current_display->set_all(ed); - bool draw = color; if(min_slr < max_slr) { - glhr::set_index_sl(band_shift + M_PI * min_slr * hybrid::csteps / cgi.psl_steps); + current_display->set_all(ed, sl2 ? 0 : V.shift); + glhr::set_index_sl(V.shift + M_PI * min_slr * hybrid::csteps / cgi.psl_steps); } - + else { + current_display->set_all(ed, V.shift); + } + bool draw = color; + flagtype sp = get_shader_flags(); if(sp & SF_DIRECT) { if((sp & SF_BAND) && V[2][2] > 1e8) continue; - glapplymatrix(V); + glapplymatrix(V.T); } if(draw) { @@ -666,7 +664,7 @@ void dqi_poly::gldraw() { glhr::id_modelview(); glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, 0, 4); glhr::vertices(v); - if(sp & SF_DIRECT) glapplymatrix(V); + if(sp & SF_DIRECT) glapplymatrix(V.T); } else { glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO); @@ -712,8 +710,8 @@ void dqi_poly::gldraw() { } #endif -EX ld scale_at(const transmatrix& T) { - if(GDIM == 3 && pmodel == mdPerspective) return 1 / abs((tC0(T))[2]); +EX ld scale_at(const shiftmatrix& T) { + if(GDIM == 3 && pmodel == mdPerspective) return 1 / abs((tC0(unshift(T)))[2]); if(sol) return 1; hyperpoint h1, h2, h3; applymodel(tC0(T), h1); @@ -724,7 +722,7 @@ EX ld scale_at(const transmatrix& T) { EX int perfect_linewidth = 1; -EX ld linewidthat(const hyperpoint& h) { +EX ld linewidthat(const shiftpoint& h) { if(!(vid.antialias & AA_LINEWIDTH)) return 1; else if(hyperbolic && pmodel == mdDisk && pconf.alpha == 1 && !ISWEB) { double dz = h[LDIM]; @@ -737,8 +735,8 @@ EX ld linewidthat(const hyperpoint& h) { } } else if(perfect_linewidth >= (inHighQual ? 1 : 2)) { - hyperpoint h0 = h / zlevel(h); - transmatrix T = rgpushxto0(h0); + hyperpoint h0 = h.h / zlevel(h.h); + shiftmatrix T = shiftless(rgpushxto0(h0), h.shift); return scale_at(T); } return 1; @@ -893,8 +891,8 @@ ld glhypot2(glvertex a, glvertex b) { void compute_side_by_centerin(dqi_poly *p, bool& nofill) { hyperpoint hscr; - hyperpoint h1 = p->V * p->intester; - if(is_behind(h1)) { + shiftpoint h1 = p->V * p->intester; + if(is_behind(h1.h)) { if(sphere) { for(int i=0; i<3; i++) h1[i] = -h1[i]; poly_flags &= ~POLY_CENTERIN; @@ -918,7 +916,7 @@ void compute_side_by_centerin(dqi_poly *p, bool& nofill) { poly_flags &= ~POLY_INVERSE; if(poly_flags & POLY_CENTERIN) { poly_flags |= POLY_INVERSE; - if(abs(zlevel(tC0(p->V)) - 1) > 1e-6) nofill = true; + if(abs(zlevel(tC0(p->V.T)) - 1) > 1e-6) nofill = true; /* nofill = true; outline = (flags & POLY_CENTERIN) ? 0x00FF00FF : 0xFF0000FF; @@ -952,7 +950,7 @@ ld get_width(dqi_poly* p) { else if(p->flags & POLY_PRECISE_WIDE) { ld maxwidth = 0; for(int i=0; icnt; i++) { - hyperpoint h1 = p->V * glhr::gltopoint((*p->tab)[p->offset+i]); + shiftpoint h1 = p->V * glhr::gltopoint((*p->tab)[p->offset+i]); maxwidth = max(maxwidth, linewidthat(h1)); } return maxwidth * p->linewidth; @@ -1136,14 +1134,15 @@ void draw_s2xe(dqi_poly *p) { else { npoly.tinf = NULL; } - npoly.V = Id; + npoly.V = shiftless(Id); + auto& pV = p->V.T; set_width(1); glcoords.clear(); stinf.tvertices.clear(); for(int i=0; icnt; i+=3) { array v; for(int k=0; k<3; k++) { - hyperpoint h = p->V * glhr::gltopoint( (*p->tab)[p->offset+i+k]); + hyperpoint h = pV * glhr::gltopoint( (*p->tab)[p->offset+i+k]); v[k][2] = hypot_d(3, h); auto dp = product_decompose(h); @@ -1178,7 +1177,7 @@ void draw_s2xe0(dqi_poly *p) { dqi_poly npoly = *p; npoly.offset = 0; npoly.tab = &glcoords; - npoly.V = Id; + npoly.V = shiftless(Id); npoly.flags &= ~ (POLY_INVERSE | POLY_FORCE_INVERTED); set_width(1); glcoords.clear(); @@ -1188,7 +1187,7 @@ void draw_s2xe0(dqi_poly *p) { auto crossdot = [&] (const hyperpoint h1, const hyperpoint h2) { return make_pair(h1[0] * h2[1] - h1[1] * h2[0], h1[0] * h2[0] + h1[1] * h2[1]); }; vector pd; for(int i=0; icnt; i++) { - hyperpoint h = p->V * glhr::gltopoint( (*p->tab)[p->offset+i]); + hyperpoint h = p->V.T * glhr::gltopoint( (*p->tab)[p->offset+i]); pd.emplace_back(); auto& next = pd.back(); auto dp = product_decompose(h); @@ -1263,13 +1262,13 @@ void draw_stretch(dqi_poly *p) { npoly.offset = 0; npoly.tab = &glcoords; - npoly.V = Id; + npoly.V = shiftless(Id); npoly.flags &= ~(POLY_INVERSE | POLY_FORCE_INVERTED); transmatrix T2 = stretch::translate( tC0(inverse(View)) ); transmatrix U = View * T2; - transmatrix iUV = inverse(U) * p->V; + transmatrix iUV = inverse(U) * p->V.T; vector hs; vector ths; @@ -1292,7 +1291,7 @@ void draw_stretch(dqi_poly *p) { else { npoly.tinf = NULL; } - npoly.V = Id; + npoly.V = shiftless(Id); set_width(1); glcoords.clear(); @@ -1492,7 +1491,7 @@ EX namespace ods { void dqi_poly::draw() { if(flags & POLY_DEBUG) debug_this(); if(debugflags & DF_VERTEX) { - println(hlog, tie(band_shift, V, offset, cnt, offset_texture, outline, linewidth, flags, intester, cache), (cell*) tinf); + println(hlog, tie(V, offset, cnt, offset_texture, outline, linewidth, flags, intester, cache), (cell*) tinf); for(int i=0; iset_all(global_projection), (get_shader_flags() & SF_DIRECT))) { + if(in_s2xe() && vid.usingGL && pmodel == mdPerspective && (current_display->set_all(global_projection, 0), (get_shader_flags() & SF_DIRECT))) { s2xe::draw_s2xe(this); return; } #endif - dynamicval bs(hr::band_shift, band_shift); if(!hyperbolic && among(pmodel, mdPolygonal, mdPolynomial)) { bool any = false; for(int i=0; i 0) any = true; } if(!any) return; @@ -1543,7 +1541,7 @@ void dqi_poly::draw() { int pha; if(twopoint_do_flips) { for(int i=0; iradius)); // check if the i-th edge intersects the boundary of the ellipse // (which corresponds to the segment between the antipodes of foci) // if yes, switch cpha to the opposite - hyperpoint h2 = V * glhr::gltopoint((*tab)[offset+(i+1)%cnt]); + shiftpoint h2 = V * glhr::gltopoint((*tab)[offset+(i+1)%cnt]); - hyperpoint ah1 = h1, ah2 = h2; + hyperpoint ah1 = h1.h, ah2 = h2.h; models::apply_orientation(ah1[0], ah1[1]); models::apply_orientation(ah2[0], ah2[1]); if(ah1[1] * ah2[1] > 0) continue; @@ -1597,7 +1595,7 @@ void dqi_poly::draw() { } } dynamicval d1(pmodel, mdPixel); - dynamicval d2(V, Id); + dynamicval d2(V.T, Id); dynamicval d3(offset, 0); dynamicval d4(tab, tab); for(int j=0; jset_all(global_projection), get_shader_flags() & SF_DIRECT) && sphere && (stretch::factor || ray::in_use)) { + if(vid.usingGL && (current_display->set_all(global_projection, V.shift), get_shader_flags() & SF_DIRECT) && sphere && (stretch::factor || ray::in_use)) { draw_stretch(this); return; } #if CAP_GL - if(vid.usingGL && (current_display->set_all(global_projection), get_shader_flags() & SF_DIRECT)) { + if(vid.usingGL && (current_display->set_all(global_projection, V.shift), get_shader_flags() & SF_DIRECT)) { if(sl2 && pmodel == mdGeodesic && hybrid::csteps) { - ld z = atan2(V[2][3], V[3][3]) + band_shift; + ld z = atan2(V.T[2][3], V.T[3][3]) + V.shift; auto zr = sightranges[geometry]; ld ns = stretch::not_squared(); ld db = cgi.psl_steps / M_PI / ns / hybrid::csteps; @@ -1647,7 +1645,7 @@ void dqi_poly::draw() { double d = 0, curradius = 0; if(sphere) { - d = det(V); + d = det(V.T); curradius = pow(abs(d), 1/3.); } @@ -1742,7 +1740,7 @@ void dqi_poly::draw() { } if(equi && (poly_flags & POLY_INVERSE)) { - if(abs(zlevel(V * C0) - 1) < 1e-6 && !tinf) { + if(abs(zlevel(V.T * C0) - 1) < 1e-6 && !tinf) { // we should fill the other side ld h = atan2(glcoords[0][0], glcoords[0][1]); for(int i=0; i<=360; i++) { @@ -1767,7 +1765,7 @@ void dqi_poly::draw() { } set_width(get_width(this)); dqi_poly npoly = (*this); - npoly.V = Id; + npoly.V = shiftless(Id, V.shift); npoly.tab = &glcoords; npoly.offset = 0; npoly.cnt = isize(glcoords); @@ -1859,13 +1857,12 @@ EX void prettylinesub(const hyperpoint& h1, const hyperpoint& h2, int lev) { else prettypoint(h2); } -EX void prettyline(hyperpoint h1, hyperpoint h2, color_t col, int lev, int flags, PPR prio) { +EX void prettyline(hyperpoint h1, hyperpoint h2, ld shift, color_t col, int lev, int flags, PPR prio) { prettylinepoints.clear(); prettypoint(h1); prettylinesub(h1, h2, lev); dqi_poly ptd; - ptd.V = Id; - ptd.band_shift = band_shift; + ptd.V = shiftless(Id, shift); ptd.tab = &prettylinepoints; ptd.offset = 0; ptd.cnt = isize(prettylinepoints); @@ -1885,8 +1882,7 @@ EX void prettypoly(const vector& t, color_t fillcol, color_t linecol for(int i=0; i d(vid.linewidth, width); - dynamicval bs(hr::band_shift, band_shift); - prettyline(H1, H2, color, prf, 0, prio); + prettyline(H1.h, unshift(H2, H1.shift), H1.shift, color, prf, 0, prio); } void dqi_string::draw() { @@ -1955,7 +1950,7 @@ EX void sortquickqueue() { EX void quickqueue() { current_display->next_shader_flags = 0; spherespecial = 0; - reset_projection(); current_display->set_all(0); + reset_projection(); current_display->set_all(0, 0); int siz = isize(ptds); for(int i=0; idraw(); ptds.clear(); @@ -1965,10 +1960,11 @@ EX void quickqueue() { } } -ld xintval(const hyperpoint& h) { - if(sphereflipped()) return -h[2]; - if(hyperbolic) return -h[2]; - return -intval(h, C0); +/* todo */ +ld xintval(const shiftpoint& h) { + if(sphereflipped()) return -h.h[2]; + if(hyperbolic) return -h.h[2]; + return -intval(h.h, C0); } EX ld backbrightness = .25; @@ -2352,13 +2348,12 @@ EX color_t monochromatize(color_t x) { return c * 0x1010100 | (part(x, 0)); } -EX dqi_poly& queuepolyat(const transmatrix& V, const hpcshape& h, color_t col, PPR prio) { +EX dqi_poly& queuepolyat(const shiftmatrix& V, const hpcshape& h, color_t col, PPR prio) { if(prio == PPR::DEFAULT) prio = h.prio; auto& ptd = queuea (prio); ptd.V = V; - ptd.band_shift = band_shift; ptd.offset = h.s; ptd.cnt = h.e-h.s; ptd.tab = &cgi.ourshape; @@ -2425,16 +2420,11 @@ EX dqi_poly& queuepolyat(const transmatrix& V, const hpcshape& h, color_t col, P } #endif -void addfloats(vector& v, hyperpoint h) { - for(int i=0; i<3; i++) v.push_back(h[i]); - } - -EX dqi_poly& queuetable(const transmatrix& V, const vector& f, int cnt, color_t linecol, color_t fillcol, PPR prio) { +EX dqi_poly& queuetable(const shiftmatrix& V, const vector& f, int cnt, color_t linecol, color_t fillcol, PPR prio) { auto& ptd = queuea (prio); ptd.V = V; - ptd.band_shift = band_shift; ptd.tab = &f; ptd.offset = 0; ptd.cnt = cnt; @@ -2448,11 +2438,11 @@ EX dqi_poly& queuetable(const transmatrix& V, const vector& f, int cnt } #if CAP_SHAPES -EX dqi_poly& queuepoly(const transmatrix& V, const hpcshape& h, color_t col) { +EX dqi_poly& queuepoly(const shiftmatrix& V, const hpcshape& h, color_t col) { return queuepolyat(V,h,col,h.prio); } -void queuepolyb(const transmatrix& V, const hpcshape& h, color_t col, int b) { +void queuepolyb(const shiftmatrix& V, const hpcshape& h, color_t col, int b) { queuepolyat(V,h,col,h.prio+b); } #endif @@ -2461,8 +2451,8 @@ EX void curvepoint(const hyperpoint& H1) { curvedata.push_back(glhr::pointtogl(H1)); } -EX dqi_poly& queuecurve(color_t linecol, color_t fillcol, PPR prio) { - auto &res = queuetable(Id, curvedata, isize(curvedata)-curvestart, linecol, fillcol, prio); +EX dqi_poly& queuecurve(const shiftmatrix& V, color_t linecol, color_t fillcol, PPR prio) { + auto &res = queuetable(V, curvedata, isize(curvedata)-curvestart, linecol, fillcol, prio); res.offset = curvestart; curvestart = isize(curvedata); return res; @@ -2472,12 +2462,11 @@ EX dqi_action& queueaction(PPR prio, const reaction_t& action) { return queuea (prio, action); } -EX dqi_line& queueline(const hyperpoint& H1, const hyperpoint& H2, color_t col, int prf IS(0), PPR prio IS(PPR::LINE)) { +EX dqi_line& queueline(const shiftpoint& H1, const shiftpoint& H2, color_t col, int prf IS(0), PPR prio IS(PPR::LINE)) { auto& ptd = queuea (prio); ptd.H1 = H1; ptd.H2 = H2; - ptd.band_shift = band_shift; ptd.prf = prf; ptd.width = vid.linewidth; ptd.color = (darkened(col >> 8) << 8) + (col & 0xFF); @@ -2507,7 +2496,7 @@ EX void queuecircle(int x, int y, int size, color_t color, PPR prio IS(PPR::CIRC ptd.linewidth = vid.linewidth; } -EX void getcoord0(const hyperpoint& h, int& xc, int &yc, int &sc) { +EX void getcoord0(const shiftpoint& h, int& xc, int &yc, int &sc) { hyperpoint hscr; applymodel(h, hscr); xc = current_display->xcenter + current_display->radius * hscr[0]; @@ -2516,30 +2505,30 @@ EX void getcoord0(const hyperpoint& h, int& xc, int &yc, int &sc) { // EYETODO sc = vid.eye * current_display->radius * hscr[2]; } -EX ld scale_in_pixels(const transmatrix& V) { +EX ld scale_in_pixels(const shiftmatrix& V) { return scale_at(V) * cgi.scalefactor * current_display->radius / 2.5; } -EX bool getcoord0_checked(const hyperpoint& h, int& xc, int &yc, int &zc) { +EX bool getcoord0_checked(const shiftpoint& h, int& xc, int &yc, int &zc) { if(invalid_point(h)) return false; if(point_behind(h)) return false; getcoord0(h, xc, yc, zc); return true; } -EX void queuestr(const hyperpoint& h, int size, const string& chr, color_t col, int frame IS(0)) { +EX void queuestr(const shiftpoint& h, int size, const string& chr, color_t col, int frame IS(0)) { int xc, yc, sc; if(getcoord0_checked(h, xc, yc, sc)) queuestr(xc, yc, sc, size, chr, col, frame); } -EX void queuestr(const transmatrix& V, double size, const string& chr, color_t col, int frame IS(0), int align IS(8)) { +EX void queuestr(const shiftmatrix& V, double size, const string& chr, color_t col, int frame IS(0), int align IS(8)) { int xc, yc, sc; if(getcoord0_checked(tC0(V), xc, yc, sc)) queuestr(xc, yc, sc, scale_in_pixels(V) * size, chr, col, frame, align); } -EX void queuestrn(const transmatrix& V, double size, const string& chr, color_t col, int frame IS(0), int align IS(8)) { +EX void queuestrn(const shiftmatrix& V, double size, const string& chr, color_t col, int frame IS(0), int align IS(8)) { switch(neon_mode) { case eNeon::none: queuestr(V, size, chr, col, frame, align); @@ -2572,7 +2561,7 @@ EX void queuestrn(const transmatrix& V, double size, const string& chr, color_t } } -EX void queuecircle(const transmatrix& V, double size, color_t col) { +EX void queuecircle(const shiftmatrix& V, double size, color_t col) { int xc, yc, sc; if(!getcoord0_checked(tC0(V), xc, yc, sc)) return; int xs, ys, ss; getcoord0(V * xpush0(.01), xs, ys, ss); diff --git a/euclid.cpp b/euclid.cpp index 38899c7a..3ea296ef 100644 --- a/euclid.cpp +++ b/euclid.cpp @@ -227,15 +227,13 @@ EX namespace euc { } void draw() override { - dq::visited_by_matrix.clear(); + dq::clear_all(); dq::enqueue_by_matrix(centerover->master, cview() * master_relative(centerover, true)); while(!dq::drawqueue.empty()) { auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); - bandfixer bf(V); + heptagon *h = p.first; + shiftmatrix V = p.second; dq::drawqueue.pop(); cell *c = h->c7; @@ -244,7 +242,7 @@ EX namespace euc { if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000 && !hybrid::pmap) continue; if(draw) for(int i=0; imove(i), V * adj(h, i)); + dq::enqueue_by_matrix(h->move(i), optimized_shift(V * adj(h, i))); } } @@ -816,13 +814,13 @@ EX namespace euc { EX void show_fundamental() { initquickqueue(); - transmatrix M = ggmatrix(cwt.at); - hyperpoint h0 = M*C0; + shiftmatrix M = ggmatrix(cwt.at); + shiftpoint h0 = M*C0; auto& T_edit = eu_edit.user_axes; - hyperpoint ha = M*(eumove(T_edit[0]) * C0 - C0) / 2; - hyperpoint hb = M*(eumove(T_edit[1]) * C0 - C0) / 2; + hyperpoint ha = M.T*(eumove(T_edit[0]) * C0 - C0) / 2; + hyperpoint hb = M.T*(eumove(T_edit[1]) * C0 - C0) / 2; if(WDIM == 3) { - hyperpoint hc = M*(eumove(T_edit[2]) * C0 - C0) / 2; + hyperpoint hc = M.T*(eumove(T_edit[2]) * C0 - C0) / 2; for(int d:{-1,1}) for(int e:{-1,1}) { queueline(h0+d*ha+e*hb-hc, h0+d*ha+e*hb+hc, 0xFFFFFFFF); queueline(h0+d*hb+e*hc-ha, h0+d*hb+e*hc+ha, 0xFFFFFFFF); @@ -1170,12 +1168,12 @@ EX coord to_coord(gp::loc p) { return coord(p.first, p.second, 0); } EX gp::loc sdxy() { return to_loc(eu.user_axes[1]) * gp::univ_param(); } -EX pair coord_display(const transmatrix& V, cell *c) { +EX pair coord_display(const shiftmatrix& V, cell *c) { if(c != c->master->c7) return {false, ""}; hyperpoint hx = eumove(main_axes[0]) * C0; hyperpoint hy = eumove(main_axes[1]) * C0; hyperpoint hz = WDIM == 2 ? C0 : eumove(main_axes[2]) * C0; - hyperpoint h = kz(inverse(build_matrix(hx, hy, hz, C03)) * inverse(ggmatrix(cwt.at->master->c7)) * V * C0); + hyperpoint h = kz(inverse(build_matrix(hx, hy, hz, C03)) * inverse_shift(ggmatrix(cwt.at->master->c7), V) * C0); if(WDIM == 3) return {true, fts(h[0]) + "," + fts(h[1]) + "," + fts(h[2]) }; diff --git a/fake.cpp b/fake.cpp index a231403e..c82696d5 100644 --- a/fake.cpp +++ b/fake.cpp @@ -119,8 +119,7 @@ EX namespace fake { return S1 * xpush(cgi.adjcheck) * S2; } - void draw_recursive(cell *c, const transmatrix& V, ld a0, ld a1, cell *parent, int depth) { - band_shift = 0; + void draw_recursive(cell *c, const shiftmatrix& V, ld a0, ld a1, cell *parent, int depth) { if(!do_draw(c, V)) return; drawcell(c, V); @@ -136,7 +135,7 @@ EX namespace fake { curvepoint(spin(-a1) * xpush0(d+.2)); curvepoint(spin(-a1) * xpush0(d)); curvepoint(spin(-a0) * xpush0(d)); - queuecurve(0xFF0000FF, 0, PPR::LINE); + queuecurve(shiftless(Id), 0xFF0000FF, 0, PPR::LINE); } @@ -144,11 +143,11 @@ EX namespace fake { for(int i=0; itype; i++) if(c->move(i) && c->move(i) != parent) { auto h0 = V * befake(FPIU(get_corner_position(c, i))); auto h1 = V * befake(FPIU(get_corner_position(c, (i+1) % c->type))); - ld b0 = atan2(h0); - ld b1 = atan2(h1); + ld b0 = atan2(unshift(h0)); + ld b1 = atan2(unshift(h1)); while(b1 < b0) b1 += 2 * M_PI; if(a0 == -1) { - draw_recursive(c->move(i), V * adj(c, i), b0, b1, c, depth+1); + draw_recursive(c->move(i), optimized_shift(V * adj(c, i)), b0, b1, c, depth+1); } else { if(b1 - b0 > M_PI) continue; @@ -163,7 +162,7 @@ EX namespace fake { if(b0 > b1) continue; - draw_recursive(c->move(i), V * adj(c, i), b0, b1, c, depth+1); + draw_recursive(c->move(i), optimized_shift(V * adj(c, i)), b0, b1, c, depth+1); } } } @@ -201,7 +200,7 @@ EX namespace fake { limit = INT_MAX; if(ordered_mode && !(multiple && multiple_special_draw)) { - using pct = pair; + using pct = pair; auto comparer = [] (pct& a1, pct& a2) { if(ordered_mode > 2) { auto val = [] (pct& a) { @@ -215,7 +214,7 @@ EX namespace fake { }; std::priority_queue, decltype(comparer)> myqueue(comparer); - auto enq = [&] (cell *c, const transmatrix& V) { + auto enq = [&] (cell *c, const shiftmatrix& V) { if(!c) return; if(ordered_mode == 1 || ordered_mode == 3) { if(dq::visited_c.count(c)) return; @@ -229,8 +228,8 @@ EX namespace fake { while(!myqueue.empty()) { auto& p = myqueue.top(); id++; - cell *c = get<0>(p); - transmatrix V = get<1>(p); + cell *c = p.first; + shiftmatrix V = p.second; myqueue.pop(); if(ordered_mode == 2 || ordered_mode == 4) { @@ -246,7 +245,7 @@ EX namespace fake { if(id > limit) continue; for(int i=0; itype; i++) if(c->move(i)) { - enq(c->move(i), V * adj(c, i)); + enq(c->move(i), optimized_shift(V * adj(c, i))); } } @@ -259,10 +258,8 @@ EX namespace fake { while(!dq::drawqueue_c.empty()) { auto& p = dq::drawqueue_c.front(); id++; - cell *c = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); - bandfixer bf(V); + cell *c = p.first; + shiftmatrix V = p.second; dq::drawqueue_c.pop(); if(!do_draw(c, V)) continue; @@ -272,7 +269,7 @@ EX namespace fake { if(id > limit) continue; for(int i=0; itype; i++) if(c->move(i)) { - enqueue(c->move(i), V * adj(c, i)); + enqueue(c->move(i), optimized_shift(V * adj(c, i))); } } } @@ -530,7 +527,7 @@ EX void change_around() { if(around >= 0 && around <= 2) return; ld t = in() ? scale : 1; - hyperpoint h = inverse_exp(tC0(View)); + hyperpoint h = inverse_exp(shiftless(tC0(View))); transmatrix T = gpushxto0(tC0(View)) * View; ld range = sightranges[geometry]; diff --git a/floorshapes.cpp b/floorshapes.cpp index 28fddccf..37ebf35c 100644 --- a/floorshapes.cpp +++ b/floorshapes.cpp @@ -938,7 +938,7 @@ EX int shvid(cell *c) { return ctof(c); } -EX struct dqi_poly *draw_shapevec(cell *c, const transmatrix& V, const vector &shv, color_t col, PPR prio IS(PPR::DEFAULT)) { +EX struct dqi_poly *draw_shapevec(cell *c, const shiftmatrix& V, const vector &shv, color_t col, PPR prio IS(PPR::DEFAULT)) { if(no_wall_rendering) return NULL; if(!c) return &queuepolyat(V, shv[0], col, prio); else if(WDIM == 3) return NULL; @@ -975,12 +975,12 @@ EX struct dqi_poly *draw_shapevec(cell *c, const transmatrix& V, const vector floorshape::* tab IS(&floorshape::b)) { +EX void draw_qfi(cell *c, const shiftmatrix& V, color_t col, PPR prio IS(PPR::DEFAULT), vector floorshape::* tab IS(&floorshape::b)) { if(no_wall_rendering) return; if(qfi.shape) queuepolyat(V * qfi.spin, *qfi.shape, col, prio); @@ -1002,15 +1002,15 @@ EX void draw_qfi(cell *c, const transmatrix& V, color_t col, PPR prio IS(PPR::DE EX bool floorshape_debug; EX void viewmat() { if(floorshape_debug) { - transmatrix V = ggmatrix(cwt.at); + shiftmatrix V = ggmatrix(cwt.at); for(int i=0; itype; i++) { - hyperpoint ci = V * get_corner_position(cwt.at, i); - hyperpoint ci1 = V * get_corner_position(cwt.at, (i+1) % cwt.at->type); + shiftpoint ci = V * get_corner_position(cwt.at, i); + shiftpoint ci1 = V * get_corner_position(cwt.at, (i+1) % cwt.at->type); - hyperpoint cn = V * nearcorner(cwt.at, i); - hyperpoint cf0 = V * farcorner(cwt.at, i, 0); - hyperpoint cf1 = V * farcorner(cwt.at, i, 1); + shiftpoint cn = V * nearcorner(cwt.at, i); + shiftpoint cf0 = V * farcorner(cwt.at, i, 0); + shiftpoint cf1 = V * farcorner(cwt.at, i, 1); queuestr(ci, 20, its(i), 0x0000FF, 1); if(vid.grid) queuestr(cn, 20, its(i), 0x00FF00, 1); @@ -1065,17 +1065,17 @@ void draw_shape_for_texture(floorshape* sh) { curvepoint(eupush(gx-s1, gy+s1) * C0); curvepoint(eupush(gx-s1, gy-s1) * C0); curvepoint(eupush(gx+s1, gy-s1) * C0); - queuecurve(0x000000FF, 0xFFFFFFFF - 0x1010100 * (sh->pstrength * 24/10), PPR::LAKELEV); + queuecurve(shiftless(Id), 0x000000FF, 0xFFFFFFFF - 0x1010100 * (sh->pstrength * 24/10), PPR::LAKELEV); } poly_outline = 0xFFFFFFFF - 0x1010100 * (sh->pstrength * 3/2); for(int a=-1; a<=1; a++) for(int b=-1; b<=1; b++) - queuepoly(eupush(gx+a, gy+b), sh->b[0], 0xFFFFFFFF); + queuepoly(shiftless(eupush(gx+a, gy+b)), sh->b[0], 0xFFFFFFFF); if(sh == &cgi.shCrossFloor) { - queuepoly(eupush(gx, gy) * spin(M_PI/4), cgi.shCross, 0x808080FF); + queuepoly(shiftless(eupush(gx, gy) * spin(M_PI/4)), cgi.shCross, 0x808080FF); } if(1) { @@ -1085,7 +1085,7 @@ void draw_shape_for_texture(floorshape* sh) { curvepoint(eupush(gx-sd, gy+sd) * C0); curvepoint(eupush(gx-sd, gy-sd) * C0); curvepoint(eupush(gx+sd, gy-sd) * C0); - queuecurve(0x40404000 + sh->fstrength * 192/10, 0, PPR::LINE); + queuecurve(shiftless(Id), 0x40404000 + sh->fstrength * 192/10, 0, PPR::LINE); } auto& ftv = floor_texture_vertices[sh->id]; @@ -1098,11 +1098,11 @@ void draw_shape_for_texture(floorshape* sh) { if(1) { hyperpoint inmodel; - applymodel(center, inmodel); + applymodel(shiftless(center), inmodel); glvertex tmap; tmap[0] = (1 + inmodel[0] * pconf.scale) / 2; tmap[1] = (1 - inmodel[1] * pconf.scale) / 2; - applymodel(center + v1, inmodel); + applymodel(shiftless(center + v1), inmodel); tmap[2] = (1 + inmodel[0] * pconf.scale) / 2 - tmap[0]; floor_texture_map[sh->id] = tmap; } @@ -1110,7 +1110,7 @@ void draw_shape_for_texture(floorshape* sh) { auto tvec_at = [&] (ld x, ld y) { hyperpoint h = center + v1 * x + v2 * y; hyperpoint inmodel; - applymodel(h, inmodel); + applymodel(shiftless(h), inmodel); glvec2 v; v[0] = (1 + inmodel[0] * pconf.scale) / 2; v[1] = (1 - inmodel[1] * pconf.scale) / 2; @@ -1193,7 +1193,7 @@ void geometry_information::make_floor_textures_here() { if(1) { current_display->next_shader_flags = GF_VARCOLOR; dynamicval m(pmodel, mdPixel); - current_display->set_all(0); + current_display->set_all(0,0); glhr::new_projection(); glhr::id_modelview(); glhr::prepare(gv); diff --git a/geometry2.cpp b/geometry2.cpp index 1fef1d64..8ba5f9fd 100644 --- a/geometry2.cpp +++ b/geometry2.cpp @@ -8,7 +8,7 @@ #include "hyper.h" namespace hr { -transmatrix &ggmatrix(cell *c); +shiftmatrix &ggmatrix(cell *c); EX void fixelliptic(transmatrix& at) { if(elliptic && at[LDIM][LDIM] < 0) { @@ -25,7 +25,7 @@ EX void fixelliptic(hyperpoint& h) { /** find relative_matrix via recursing the tree structure */ EX transmatrix relative_matrix_recursive(heptagon *h2, heptagon *h1) { if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) - return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7]; + return inverse_shift(gmatrix0[h1->c7], gmatrix0[h2->c7]); transmatrix gm = Id, where = Id; while(h1 != h2) { for(int i=0; itype; i++) { @@ -195,10 +195,12 @@ transmatrix hrmap_standard::relative_matrix(heptagon *h2, heptagon *h1, const hy return gm * where; } -EX transmatrix &ggmatrix(cell *c) { - transmatrix& t = gmatrix[c]; - if(t[LDIM][LDIM] == 0) - t = actual_view_transform * View * calc_relative_matrix(c, centerover, C0); +EX shiftmatrix &ggmatrix(cell *c) { + shiftmatrix& t = gmatrix[c]; + if(t[LDIM][LDIM] == 0) { + t.T = actual_view_transform * View * calc_relative_matrix(c, centerover, C0); + t.shift = 0; + } return t; } @@ -208,7 +210,7 @@ struct horo_distance { void become(hyperpoint h1); horo_distance(hyperpoint h) { become(h); } - horo_distance(hyperpoint h1, const transmatrix& T); + horo_distance(shiftpoint h1, const shiftmatrix& T); bool operator < (const horo_distance z) const; friend void print(hstream& hs, horo_distance x) { print(hs, "[", x.a, ":", x.b, "]"); } }; @@ -232,14 +234,14 @@ void horo_distance::become(hyperpoint h1) { a = 0, b = intval(h1, C0); } -horo_distance::horo_distance(hyperpoint h1, const transmatrix& T) { +horo_distance::horo_distance(shiftpoint h1, const shiftmatrix& T) { #if CAP_BT - if(bt::in()) become(inverse(T) * h1); + if(bt::in()) become(inverse_shift(T, h1)); else #endif - if(sn::in() || hybri || nil) become(inverse(T) * h1); + if(sn::in() || hybri || nil) become(inverse_shift(T, h1)); else - a = 0, b = intval(h1, tC0(T)); + a = 0, b = intval(h1.h, unshift(tC0(T), h1.shift)); } bool horo_distance::operator < (const horo_distance z) const { @@ -341,7 +343,7 @@ void virtualRebase(cell*& base, T& at, const U& check) { } EX void virtualRebase(cell*& base, transmatrix& at) { - virtualRebase(base, at, tC0); + virtualRebase(base, at, tC0_t); } EX void virtualRebase(cell*& base, hyperpoint& h) { diff --git a/glhr.cpp b/glhr.cpp index f050d17c..e491d670 100644 --- a/glhr.cpp +++ b/glhr.cpp @@ -824,7 +824,7 @@ EX void set_linewidth(ld lw) { EX void switch_to_text(const vector& v, const vector& t) { current_display->next_shader_flags = GF_TEXTURE; dynamicval pm(pmodel, mdPixel); - if(!svg::in) current_display->set_all(0); + if(!svg::in) current_display->set_all(0, 0); vertices_texture(v, t, 0, 0); } diff --git a/goldberg.cpp b/goldberg.cpp index f5f57923..cd4a84e1 100644 --- a/goldberg.cpp +++ b/goldberg.cpp @@ -1234,10 +1234,8 @@ EX namespace gp { while(!dq::drawqueue_c.empty()) { auto& p = dq::drawqueue_c.front(); - cell *c = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); - bandfixer bf(V); + cell *c = p.first; + shiftmatrix V = p.second; auto c1 = get_mapped(c, 0); in_underlying([&] { @@ -1257,7 +1255,7 @@ EX namespace gp { drawcell(c, V); for(int i=0; itype; i++) if(c->cmove(i)) - enqueue(c->move(i), V * adj(c, i)); + enqueue(c->move(i), optimized_shift(V * adj(c, i))); } } diff --git a/graph.cpp b/graph.cpp index aebb64b0..aed0c616 100644 --- a/graph.cpp +++ b/graph.cpp @@ -38,10 +38,10 @@ EX bool hide_player() { ; } -#define ADC(V,c) for(const transmatrix& V: current_display->all_drawn_copies[c]) +#define ADC(V,c) for(const shiftmatrix& V: current_display->all_drawn_copies[c]) EX hookset hooks_handleKey; -EX hookset hooks_drawcell; +EX hookset hooks_drawcell; EX purehookset hooks_frame, hooks_markers; EX ld animation_factor = 1; @@ -186,7 +186,7 @@ EX int lightat, safetyat; EX void drawLightning() { lightat = ticks; } EX void drawSafety() { safetyat = ticks; } -void drawShield(const transmatrix& V, eItem it) { +void drawShield(const shiftmatrix& V, eItem it) { #if CAP_CURVE float ds = ptick(300); color_t col = iinf[it].color; @@ -204,13 +204,13 @@ void drawShield(const transmatrix& V, eItem it) { #endif else { for(ld a=0; a<=cgi.S84*mt+1e-6; a+=pow(.5, vid.linequality)) - curvepoint(V*xspinpush0(a * M_PI/cgi.S42, d + sin(ds + M_PI*2*a/4/mt)*.1)); - queuecurve(darkena(col, 0, 0xFF), 0x8080808, PPR::LINE); + curvepoint(xspinpush0(a * M_PI/cgi.S42, d + sin(ds + M_PI*2*a/4/mt)*.1)); + queuecurve(V, darkena(col, 0, 0xFF), 0x8080808, PPR::LINE); } #endif } -void drawSpeed(const transmatrix& V) { +void drawSpeed(const shiftmatrix& V) { #if CAP_CURVE ld ds = ptick(10); color_t col = darkena(iinf[itOrbSpeed].color, 0, 0xFF); @@ -220,13 +220,13 @@ void drawSpeed(const transmatrix& V) { #endif for(int b=0; b= 4 + if(GDIM == 2) return V; + return V * zpush(cheilevel((a+.5) / b)); +#else + return V; +#endif + } + +void drawLove(const shiftmatrix& V, int hdir) { #if CAP_CURVE float ds = ptick(300); color_t col = darkena(iinf[itOrbLove].color, 0, 0xFF); col &= ~1; for(int u=0; u<5; u++) { + shiftmatrix V1 = chei(V, u, 5); PRING(a) { double d = (1 + cos(a * M_PI/cgi.S42)) / 2; double z = a; if(z>cgi.S42) z = cgi.S84-z; if(z <= 10) d += (10-z) * (10-z) * (10-z) / 3000.; ld rad = cgi.hexf * (2.5 + .5 * sin(ds+u*.3)) * d; - transmatrix V1 = chei(V, u, 5); - curvepoint(V1*xspinpush0((cgi.S42+hdir+a-1) * M_PI/cgi.S42, rad)); + curvepoint(xspinpush0((cgi.S42+hdir+a-1) * M_PI/cgi.S42, rad)); } - queuecurve(col, 0x8080808, PPR::LINE); + queuecurve(V1, col, 0x8080808, PPR::LINE); } #endif } -void drawWinter(const transmatrix& V, ld hdir) { +void drawWinter(const shiftmatrix& V, ld hdir) { #if CAP_QUEUE float ds = ptick(300); color_t col = darkena(iinf[itOrbWinter].color, 0, 0xFF); for(int u=0; u<20; u++) { ld rad = sin(ds+u * 2 * M_PI / 20) * M_PI / S7; - transmatrix V1 = chei(V, u, 20); + shiftmatrix V1 = chei(V, u, 20); queueline(V1*xspinpush0(M_PI+hdir+rad, cgi.hexf*.5), V1*xspinpush0(M_PI+hdir+rad, cgi.hexf*3), col, 2 + vid.linequality); } #endif } -void drawLightning(const transmatrix& V) { +void drawLightning(const shiftmatrix& V) { #if CAP_QUEUE color_t col = darkena(iinf[itOrbLightning].color, 0, 0xFF); for(int u=0; u<20; u++) { ld leng = 0.5 / (0.1 + (rand() % 100) / 100.0); ld rad = rand() % 1000; - transmatrix V1 = chei(V, u, 20); + shiftmatrix V1 = chei(V, u, 20); queueline(V1*xspinpush0(rad, cgi.hexf*0.3), V1*xspinpush0(rad, cgi.hexf*leng), col, 2 + vid.linequality); } #endif @@ -322,7 +331,7 @@ void drawLightning(const transmatrix& V) { #define UNTRANS (GDIM == 3 ? 0x000000FF : 0) -EX void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) { +EX void drawPlayerEffects(const shiftmatrix& V, cell *c, bool onplayer) { if(!onplayer && !items[itOrbEmpathy]) return; if(items[itOrbShield] > (shmup::on ? 0 : ORBBASE)) drawShield(V, itOrbShield); if(items[itOrbShell] > (shmup::on ? 0 : ORBBASE)) drawShield(V, itOrbShell); @@ -344,9 +353,9 @@ EX void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) { else if(SWORDDIM == 3) { #if CAP_SHAPES - transmatrix Vsword = + shiftmatrix Vsword = shmup::on ? V * shmup::swordmatrix[multi::cpid] * cspin(2, 0, M_PI/2) - : gmatrix[c] * rgpushxto0(inverse(gmatrix[c]) * tC0(V)) * sword::dir[multi::cpid].T; + : gmatrix[c] * rgpushxto0(inverse_shift(gmatrix[c], tC0(V))) * sword::dir[multi::cpid].T; if(items[itOrbSword]) queuepoly(Vsword * cspin(1,2, ticks / 150.), (peace::on ? cgi.shMagicShovel : cgi.shMagicSword), darkena(iinf[itOrbSword].color, 0, 0xC0 + 0x30 * sintick(200))); @@ -361,7 +370,7 @@ EX void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) { ang %= sword::sword_angles; #if CAP_QUEUE || CAP_SHAPES - transmatrix Vnow = gmatrix[c] * rgpushxto0(inverse(gmatrix[c]) * tC0(V)) * ddspin(c,0,M_PI); + shiftmatrix Vnow = gmatrix[c] * rgpushxto0(inverse_shift(gmatrix[c], tC0(V))) * ddspin(c,0,M_PI); #endif int adj = 1 - ((sword_angles/cwt.at->type)&1); @@ -382,7 +391,7 @@ EX void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) { hyperpoint h0 = xpush0(l0); hyperpoint h1 = xpush0(l1); #endif - transmatrix T = Vnow*spin((sword_angles + (-adj-2*a)) * M_PI / sword_angles); + shiftmatrix T = Vnow*spin((sword_angles + (-adj-2*a)) * M_PI / sword_angles); queueline(T*h0, T*h1, col, 1, PPR::SUPERLINE); } #endif @@ -415,16 +424,16 @@ EX void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) { ld rad = cgi.hexf * u / 250; color_t col = darkena(iinf[itOrbSafety].color, 0, 0xFF); PRING(a) - curvepoint(V*xspinpush0(a * M_PI / cgi.S42, rad)); - queuecurve(col, 0, PPR::LINE); + curvepoint(xspinpush0(a * M_PI / cgi.S42, rad)); + queuecurve(V, col, 0, PPR::LINE); } } } -void drawStunStars(const transmatrix& V, int t) { +void drawStunStars(const shiftmatrix& V, int t) { #if CAP_SHAPES for(int i=0; i<3*t; i++) { - transmatrix V2 = V * spin(M_PI * 2 * i / (3*t) + ptick(200)); + shiftmatrix V2 = V * spin(M_PI * 2 * i / (3*t) + ptick(200)); #if MAXMDIM >= 4 if(GDIM == 3) V2 = V2 * zpush(cgi.HEAD); #endif @@ -436,7 +445,7 @@ void drawStunStars(const transmatrix& V, int t) { EX namespace tortoise { // small is 0 or 2 - void draw(const transmatrix& V, int bits, int small, int stuntime) { + void draw(const shiftmatrix& V, int bits, int small, int stuntime) { #if CAP_SHAPES color_t eyecolor = getBit(bits, tfEyeHue) ? 0xFF0000 : 0xC0C0C0; @@ -506,7 +515,7 @@ double footfun(double d) { EX bool ivoryz; -void animallegs(const transmatrix& V, eMonster mo, color_t col, double footphase) { +void animallegs(const shiftmatrix& V, eMonster mo, color_t col, double footphase) { #if CAP_SHAPES footphase /= SCALE; @@ -546,8 +555,8 @@ void animallegs(const transmatrix& V, eMonster mo, color_t col, double footphase } #endif - const transmatrix VL = mmscale(V, cgi.ALEG0); - const transmatrix VAML = mmscale(V, cgi.ALEG); + const shiftmatrix VL = mmscale(V, cgi.ALEG0); + const shiftmatrix VAML = mmscale(V, cgi.ALEG); if(x[0]) queuepolyat(VL * xpush(rightfoot), *x[0], col, PPR::MONSTER_FOOT); if(x[0]) queuepolyat(VL * Mirror * xpush(leftfoot), *x[0], col, PPR::MONSTER_FOOT); @@ -564,7 +573,7 @@ void animallegs(const transmatrix& V, eMonster mo, color_t col, double footphase EX bool noshadow; #if CAP_SHAPES -EX void ShadowV(const transmatrix& V, const hpcshape& bp, PPR prio IS(PPR::MONSTER_SHADOW)) { +EX void ShadowV(const shiftmatrix& V, const hpcshape& bp, PPR prio IS(PPR::MONSTER_SHADOW)) { if(WDIM == 2 && GDIM == 3 && bp.shs != bp.she) { auto& p = queuepolyat(V, bp, 0x18, PPR::TRANSPARENT_SHADOW); p.outline = 0; @@ -586,7 +595,7 @@ EX void ShadowV(const transmatrix& V, const hpcshape& bp, PPR prio IS(PPR::MONST #if CAP_SHAPES -transmatrix otherbodyparts(const transmatrix& V, color_t col, eMonster who, double footphase) { +transmatrix otherbodyparts(const shiftmatrix& V, color_t col, eMonster who, double footphase) { #define VFOOT ((GDIM == 2 || hybri) ? V : mmscale(V, cgi.LEG0)) #define VLEG mmscale(V, cgi.LEG) @@ -621,24 +630,24 @@ transmatrix otherbodyparts(const transmatrix& V, color_t col, eMonster who, doub // todo if(detaillevel >= 2 && GDIM == 2) { - transmatrix VL = mmscale(V, cgi.LEG1); + shiftmatrix VL = mmscale(V, cgi.LEG1); queuepoly(VL * xpush(rightfoot*3/4), cgi.shHumanLeg, col); queuepoly(VL * Mirror * xpush(-rightfoot*3/4), cgi.shHumanLeg, col); } if(GDIM == 2) { - transmatrix VL = mmscale(V, cgi.LEG); + shiftmatrix VL = mmscale(V, cgi.LEG); queuepoly(VL * xpush(rightfoot/2), cgi.shHumanLeg, col); queuepoly(VL * Mirror * xpush(-rightfoot/2), cgi.shHumanLeg, col); } if(detaillevel >= 2 && GDIM == 2) { - transmatrix VL = mmscale(V, cgi.LEG3); + shiftmatrix VL = mmscale(V, cgi.LEG3); queuepoly(VL * xpush(rightfoot/4), cgi.shHumanLeg, col); queuepoly(VL * Mirror * xpush(-rightfoot/4), cgi.shHumanLeg, col); } - transmatrix Tright, Tleft; + shiftmatrix Tright, Tleft; if(GDIM == 2 || hybri) { Tright = VFOOT * xpush(rightfoot); @@ -646,7 +655,7 @@ transmatrix otherbodyparts(const transmatrix& V, color_t col, eMonster who, doub } #if MAXMDIM >= 4 else { - transmatrix V1 = V; + shiftmatrix V1 = V; if(WDIM == 2) V1 = V1 * zpush(cgi.GROIN); Tright = V1 * cspin(0, 2, rightfoot/ leg_length); Tleft = V1 * Mirror * cspin(2, 0, rightfoot / leg_length); @@ -715,12 +724,12 @@ EX color_t kind_outline(eItem it) { return OUTLINE_OTHER; } -EX transmatrix face_the_player(const transmatrix V) { +EX shiftmatrix face_the_player(const shiftmatrix V) { if(GDIM == 2) return V; if(prod) return mscale(V, cos(ptick(750)) * cgi.plevel / 16); if(hybri) return V * zpush(cos(ptick(750)) * cgi.plevel / 16); transmatrix dummy; /* used only in prod anyways */ - if(nonisotropic) return spin_towards(V, dummy, C0, 2, 0); + if(nonisotropic) return shiftless(spin_towards(unshift(V), dummy, C0, 2, 0)); return rgpushxto0(tC0(V)); } @@ -755,7 +764,7 @@ EX color_t orb_auxiliary_color(eItem it) { return iinf[it].color; } -EX bool drawItemType(eItem it, cell *c, const transmatrix& V, color_t icol, int pticks, bool hidden) { +EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int pticks, bool hidden) { #if !CAP_SHAPES return it; #else @@ -796,7 +805,7 @@ EX bool drawItemType(eItem it, cell *c, const transmatrix& V, color_t icol, int if(WDIM == 3 && c == centerover && in_perspective() && hdist0(tC0(V)) < cgi.orbsize * 0.25) return false; - transmatrix Vit = V; + shiftmatrix Vit = V; if(GDIM == 3 && WDIM == 2 && c && it != itBabyTortoise) Vit = mscale(V, cgi.STUFF); if(c && prod) Vit = mscale(Vit, sin(ptick(750)) * cgi.plevel / 4); @@ -831,7 +840,7 @@ EX bool drawItemType(eItem it, cell *c, const transmatrix& V, color_t icol, int } else if(it == itCompass) { - transmatrix V2; + shiftmatrix V2; #if CAP_CRYSTAL if(cryst) { if(crystal::compass_probability <= 0) return true; @@ -843,8 +852,8 @@ EX bool drawItemType(eItem it, cell *c, const transmatrix& V, color_t icol, int if(1) { cell *c1 = c ? findcompass(c) : NULL; if(c1) { - transmatrix P = ggmatrix(c1); - hyperpoint P1 = tC0(P); + shiftmatrix P = ggmatrix(c1); + shiftpoint P1 = tC0(P); if(isPlayerOn(c)) { queuestr(P1, 2*vid.fsize, "X", 0x10100 * int(128 + 100 * sintick(150))); @@ -853,7 +862,7 @@ EX bool drawItemType(eItem it, cell *c, const transmatrix& V, color_t icol, int addauraspecial(P1, 0xFF0000, 0); } - V2 = V * rspintox(inverse(V) * P1); + V2 = V * rspintox(inverse_shift(V, P1)); } else V2 = V; } @@ -880,7 +889,7 @@ EX bool drawItemType(eItem it, cell *c, const transmatrix& V, color_t icol, int #if MAXMDIM >= 4 if(GDIM == 3 && WDIM == 2) { dynamicval qfi2(qfi, qfi); - transmatrix V2 = V * spin(ticks / 1500.); + shiftmatrix V2 = V * spin(ticks / 1500.); /* divisors should be higher than in plate renderer */ qfi.fshape = &cgi.shMFloor2; draw_shapevec(c, V2 * zpush(-h/30), qfi.fshape->levels[0], 0xFFD500FF, PPR::WALL); @@ -892,7 +901,7 @@ EX bool drawItemType(eItem it, cell *c, const transmatrix& V, color_t icol, int draw_shapevec(c, V2 * zpush(-h/20), qfi.fshape->levels[0], 0xFFD500FF, PPR::WALL); } else if(WDIM == 3 && c) { - transmatrix V2 = Vit * spin(ticks / 1500.); + shiftmatrix V2 = Vit * spin(ticks / 1500.); draw_floorshape(c, V2 * zpush(h/100), cgi.shMFloor3, 0xFFD500FF); draw_floorshape(c, V2 * zpush(h/50), cgi.shMFloor4, darkena(icol, 0, 0xFF)); queuepoly(V2, cgi.shGem[ct6], 0xFFD500FF); @@ -904,7 +913,7 @@ EX bool drawItemType(eItem it, cell *c, const transmatrix& V, color_t icol, int #endif { color_t hider = hidden ? 0xFFFFFF20 : 0xFFFFFFFF; - transmatrix V2 = Vit * spin(ticks / 1500.); + shiftmatrix V2 = Vit * spin(ticks / 1500.); draw_floorshape(c, V2, cgi.shMFloor3, 0xFFD500FF & hider); draw_floorshape(c, V2, cgi.shMFloor4, darkena(icol, 0, 0xFF) & hider); queuepoly(V2, cgi.shGem[ct6], 0xFFD500FF & hider); @@ -936,7 +945,7 @@ EX bool drawItemType(eItem it, cell *c, const transmatrix& V, color_t icol, int if(it == itLotus) icol = 0x101010; if(it == itSwitch) icol = minf[active_switch()].color; - transmatrix V2 = Vit * spinptick(1500, 0); + shiftmatrix V2 = Vit * spinptick(1500, 0); if(xsh == &cgi.shBookCover && mmitem) { if(GDIM == 3) @@ -952,7 +961,7 @@ EX bool drawItemType(eItem it, cell *c, const transmatrix& V, color_t icol, int queuepolyat(V2, *xsh, darkena(icol, 0, alpha), pr); if(it == itZebra) { - transmatrix Vx = Vit * spinptick(1500, .5/(ct6+6)); + shiftmatrix Vx = Vit * spinptick(1500, .5/(ct6+6)); if(GDIM == 3) Vx = Vx * cpush(2, -1e-3); queuepolyat(Vx, *xsh, darkena(0x202020, 0, hidden ? 0x40 : 0xF0), PPR::ITEMb); @@ -986,14 +995,14 @@ EX bool drawItemType(eItem it, cell *c, const transmatrix& V, color_t icol, int #if CAP_SHAPES color_t skincolor = 0xD0C080FF; -void humanoid_eyes(const transmatrix& V, color_t ecol, color_t hcol = skincolor) { +void humanoid_eyes(const shiftmatrix& V, color_t ecol, color_t hcol = skincolor) { if(GDIM == 3) { queuepoly(VHEAD, cgi.shPHeadOnly, hcol); queuepoly(VHEAD, cgi.shSkullEyes, ecol); } } -EX void drawTerraWarrior(const transmatrix& V, int t, int hp, double footphase) { +EX void drawTerraWarrior(const shiftmatrix& V, int t, int hp, double footphase) { ShadowV(V, cgi.shPBody); color_t col = linf[laTerracotta].color; int bcol = darkena(false ? 0xC0B23E : col, 0, 0xFF); @@ -1009,7 +1018,7 @@ EX void drawTerraWarrior(const transmatrix& V, int t, int hp, double footphase) } #endif -EX void drawPlayer(eMonster m, cell *where, const transmatrix& V, color_t col, double footphase, bool stop IS(false)) { +EX void drawPlayer(eMonster m, cell *where, const shiftmatrix& V, color_t col, double footphase, bool stop IS(false)) { charstyle& cs = getcs(); auto& knighted = camelot::knighted; @@ -1124,7 +1133,7 @@ EX void drawPlayer(eMonster m, cell *where, const transmatrix& V, color_t col, d if(items[itOrbSide1] && !shmup::on) queuepoly(VBODY * VBS * spin(-M_PI/24), cs.charid >= 2 ? cgi.shSabre : cgi.shPSword, fc(314, cs.swordcolor, 3)); // 3 not colored - transmatrix VWPN = cs.lefthanded ? VBODY * VBS * Mirror : VBODY * VBS; + shiftmatrix VWPN = cs.lefthanded ? VBODY * VBS * Mirror : VBODY * VBS; if(peace::on) ; else if(racing::on) { @@ -1195,7 +1204,7 @@ transmatrix wingmatrix(int period, int phase = 0) { return Vwing; } -void drawMimic(eMonster m, cell *where, const transmatrix& V, color_t col, double footphase) { +void drawMimic(eMonster m, cell *where, const shiftmatrix& V, color_t col, double footphase) { charstyle& cs = getcs(); if(mapeditor::drawUserShape(V, mapeditor::sgPlayer, cs.charid, darkena(col, 0, 0x80), where)) return; @@ -1271,7 +1280,7 @@ void drawMimic(eMonster m, cell *where, const transmatrix& V, color_t col, doubl } } -EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t col, double footphase, color_t asciicol) { +EX bool drawMonsterType(eMonster m, cell *where, const shiftmatrix& V1, color_t col, double footphase, color_t asciicol) { #if MAXMDIM >= 4 if(GDIM == 3 && m != moPlayer && asciicol != NOCOLOR) @@ -1281,7 +1290,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t #if CAP_SHAPES char xch = minf[m].glyph; - transmatrix V = V1; + shiftmatrix V = V1; if(WDIM == 3 && (classflag(m) & CF_FACE_UP) && where && !hybri) V = V1 * cspin(0, 2, M_PI/2); // if(GDIM == 3) V = V * cspin(0, 2, M_PI/2); @@ -1351,7 +1360,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moEvilGolem: case moIceGolem: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 2, 0xC0), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 2, 0xC0), m, footphase); ShadowV(V, cgi.shPBody); queuepoly(VBS, cgi.shPBody, darkena(col, 0, 0XC0)); queuepoly(VHEAD, cgi.shGolemhead, darkena(col, 1, 0XFF)); @@ -1460,7 +1469,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t case moFrog: case moPhaser: case moVaulter: { ShadowV(V, cgi.shFrogBody); - const transmatrix VL = GDIM == 3 ? V : mmscale(V, cgi.ALEG0); + const shiftmatrix VL = GDIM == 3 ? V : mmscale(V, cgi.ALEG0); color_t xcolor = darkena(0xFF0000, 1, 0xFF); int alpha = (m == moPhaser ? 0xC0 : 0xFF); if(footphase) { @@ -1636,7 +1645,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moVariantWarrior: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xC0), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xC0), m, footphase); ShadowV(V, cgi.shPBody); queuepoly(VBS, cgi.shPBody, darkena(0xFFD500, 0, 0xF0)); if(!peace::on) queuepoly(VBS, cgi.shPSword, 0xFFFF00FF); @@ -1646,7 +1655,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moDesertman: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xC0), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xC0), m, footphase); ShadowV(V, cgi.shPBody); queuepoly(VBS, cgi.shPBody, darkena(col, 0, 0xC0)); if(!peace::on) queuepoly(VBS, cgi.shPSword, 0xFFFF00FF); @@ -1710,7 +1719,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moSkeleton: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(0xFFFFFF, 0, 0xFF), moSkeleton, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(0xFFFFFF, 0, 0xFF), moSkeleton, footphase); queuepoly(VBS, cgi.shSkeletonBody, darkena(0xFFFFFF, 0, 0xFF)); if(GDIM == 2) queuepoly(VHEAD, cgi.shSkull, darkena(0xFFFFFF, 0, 0xFF)); if(GDIM == 2) queuepoly(VHEAD1, cgi.shSkullEyes, 0x000000FF); @@ -1746,7 +1755,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moCrystalSage: { - const transmatrix VBS = VBODY * otherbodyparts(V, 0xFFFFFFFF, m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, 0xFFFFFFFF, m, footphase); ShadowV(V, cgi.shPBody); queuepoly(VBS, cgi.shPBody, 0xFFFFFFFF); queuepoly(VHEAD1, cgi.shPHead, 0xFFFFFFFF); @@ -1757,7 +1766,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t case moHedge: { ShadowV(V, cgi.shPBody); - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 1, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 1, 0xFF), m, footphase); queuepoly(VBS, cgi.shPBody, darkena(col, 0, 0xFF)); queuepoly(VBS, cgi.shHedgehogBlade, 0xC0C0C0FF); queuepoly(VHEAD1, cgi.shPHead, 0x804000FF); @@ -1767,7 +1776,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moYeti: case moMonkey: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xC0), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xC0), m, footphase); ShadowV(V, cgi.shPBody); queuepoly(VBS, cgi.shYeti, darkena(col, 0, 0xC0)); queuepoly(VHEAD1, cgi.shPHead, darkena(col, 0, 0xFF)); @@ -1776,7 +1785,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moResearcher: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); ShadowV(V, cgi.shPBody); queuepoly(VBS, cgi.shPBody, darkena(0xFFFF00, 0, 0xC0)); queuepoly(VHEAD, cgi.shAztecHead, darkena(col, 0, 0xFF)); @@ -1804,7 +1813,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t case moRanger: { ShadowV(V, cgi.shPBody); - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); queuepoly(VBS, cgi.shPBody, darkena(col, 0, 0xC0)); if(!peace::on) queuepoly(VBS, cgi.shPSword, darkena(col, 0, 0xFF)); queuepoly(VHEAD, cgi.shArmor, darkena(col, 1, 0xFF)); @@ -1814,7 +1823,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t case moNarciss: { ShadowV(V, cgi.shPBody); - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); queuepoly(VBS, cgi.shFlowerHand, darkena(col, 0, 0xFF)); queuepoly(VBS, cgi.shPBody, 0xFFE080FF); if(!peace::on) queuepoly(VBS, cgi.shPKnife, 0xC0C0C0FF); @@ -1826,7 +1835,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t case moMirrorSpirit: { ShadowV(V, cgi.shPBody); - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0x90), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0x90), m, footphase); queuepoly(VBS, cgi.shPBody, darkena(col, 0, 0x90)); if(!peace::on) queuepoly(VBS * Mirror, cgi.shPSword, darkena(col, 0, 0xD0)); queuepoly(VHEAD1, cgi.shPHead, darkena(col, 1, 0x90)); @@ -1867,7 +1876,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t case moFireFairy: { col = firecolor(0); - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); ShadowV(V, cgi.shFemaleBody); queuepoly(VBS, cgi.shFemaleBody, darkena(col, 0, 0XC0)); queuepoly(VHEAD, cgi.shWitchHair, darkena(col, 1, 0xFF)); @@ -1880,7 +1889,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t col = watercolor(0); bool girl = princessgender() == GEN_F; if(girl) { - const transmatrix VBS = VBODY * otherbodyparts(V, col, m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, col, m, footphase); ShadowV(V, cgi.shFemaleBody); queuepoly(VBS, cgi.shFemaleBody, watercolor(100)); queuepoly(VHEAD1, cgi.shFemaleHair, watercolor(150)); @@ -1891,7 +1900,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t humanoid_eyes(V, col | 0xFF); } else { - const transmatrix VBS = VBODY * otherbodyparts(V, col, m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, col, m, footphase); ShadowV(V, cgi.shPBody); queuepoly(VBS, cgi.shPBody, watercolor(100)); @@ -1926,7 +1935,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moCultist: case moPyroCultist: case moCultistLeader: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 1, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 1, 0xFF), m, footphase); ShadowV(V, cgi.shPBody); queuepoly(VBS, cgi.shPBody, darkena(col, 0, 0xC0)); if(!peace::on) queuepoly(VBS, cgi.shPSword, darkena(col, 2, 0xFF)); @@ -1936,7 +1945,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moPirate: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); ShadowV(V, cgi.shPBody); queuepoly(VBS, cgi.shPBody, darkena(0x404040, 0, 0xFF)); queuepoly(VBS, cgi.shPirateHook, darkena(0xD0D0D0, 0, 0xFF)); @@ -1965,7 +1974,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } #if MAXMDIM >= 4 else { - transmatrix V1 = V * zpush(cgi.AHEAD - zc(0.4) - zc(0.98) + cgi.HEAD); // * cpush(0, cgi.scalefactor * (-0.1)); + shiftmatrix V1 = V * zpush(cgi.AHEAD - zc(0.4) - zc(0.98) + cgi.HEAD); // * cpush(0, cgi.scalefactor * (-0.1)); queuepoly(V1, cgi.shRatHead, darkena(col, 0, 0xFF)); /* @@ -2011,7 +2020,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moNecromancer: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); ShadowV(V, cgi.shPBody); queuepoly(VBS, cgi.shPBody, 0xC00000C0 | UNTRANS); queuepoly(VHEAD, cgi.shHood, darkena(col, 1, 0xFF)); @@ -2020,7 +2029,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moDraugr: { - const transmatrix VBS = VBODY * otherbodyparts(V, 0x483828D0 | UNTRANS, m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, 0x483828D0 | UNTRANS, m, footphase); queuepoly(VBS, cgi.shPBody, 0x483828D0 | UNTRANS); queuepoly(VBS, cgi.shPSword, 0xFFFFD0A0 | UNTRANS); queuepoly(VHEAD, cgi.shPHead, 0x483828D0 | UNTRANS); @@ -2037,7 +2046,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moVoidBeast: { - const transmatrix VBS = VBODY * otherbodyparts(V, 0x080808D0 | UNTRANS, m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, 0x080808D0 | UNTRANS, m, footphase); queuepoly(VBS, cgi.shPBody, 0x080808D0 | UNTRANS); queuepoly(VHEAD, cgi.shPHead, 0x080808D0 | UNTRANS); queuepoly(VHEAD, cgi.shWightCloak, 0xFF0000A0 | UNTRANS); @@ -2046,7 +2055,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moGoblin: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); ShadowV(V, cgi.shYeti); queuepoly(VBS, cgi.shYeti, darkena(col, 0, 0xC0)); queuepoly(VHEAD, cgi.shArmor, darkena(col, 1, 0XFF)); @@ -2055,11 +2064,11 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moLancer: case moFlailer: case moMiner: { - transmatrix V2 = V; + shiftmatrix V2 = V; if(m == moLancer) V2 = V * spin((where && where->type == 6) ? -M_PI/3 : -M_PI/2 ); - transmatrix Vh = mmscale(V2, cgi.HEAD); - transmatrix Vb = mmscale(V2, cgi.BODY); + shiftmatrix Vh = mmscale(V2, cgi.HEAD); + shiftmatrix Vb = mmscale(V2, cgi.BODY); Vb = Vb * otherbodyparts(V2, darkena(col, 1, 0xFF), m, footphase); ShadowV(V2, cgi.shPBody); queuepoly(Vb, cgi.shPBody, darkena(col, 0, 0xC0)); @@ -2078,7 +2087,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moTroll: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); ShadowV(V, cgi.shYeti); queuepoly(VBS, cgi.shYeti, darkena(col, 0, 0xC0)); queuepoly(VHEAD1, cgi.shPHead, darkena(col, 1, 0XFF)); @@ -2088,7 +2097,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moFjordTroll: case moForestTroll: case moStormTroll: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); ShadowV(V, cgi.shYeti); queuepoly(VBS, cgi.shYeti, darkena(col, 0, 0xC0)); queuepoly(VHEAD1, cgi.shPHead, darkena(col, 1, 0XFF)); @@ -2098,7 +2107,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moDarkTroll: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); ShadowV(V, cgi.shYeti); queuepoly(VBS, cgi.shYeti, darkena(col, 0, 0xC0)); queuepoly(VHEAD1, cgi.shPHead, darkena(col, 1, 0XFF)); @@ -2108,7 +2117,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moRedTroll: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xFF), m, footphase); ShadowV(V, cgi.shYeti); queuepoly(VBS, cgi.shYeti, darkena(col, 0, 0xC0)); queuepoly(VHEAD1, cgi.shPHead, darkena(0xFF8000, 0, 0XFF)); @@ -2118,7 +2127,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moEarthElemental: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 1, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 1, 0xFF), m, footphase); ShadowV(V, cgi.shWaterElemental); queuepoly(VBS, cgi.shWaterElemental, darkena(col, 0, 0xC0)); queuepoly(VHEAD1, cgi.shFemaleHair, darkena(col, 0, 0XFF)); @@ -2128,7 +2137,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moWaterElemental: { - const transmatrix VBS = VBODY * otherbodyparts(V, watercolor(50), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, watercolor(50), m, footphase); ShadowV(V, cgi.shWaterElemental); queuepoly(VBS, cgi.shWaterElemental, watercolor(0)); queuepoly(VHEAD1, cgi.shFemaleHair, watercolor(100)); @@ -2138,7 +2147,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moFireElemental: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(firecolor(50), 0, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(firecolor(50), 0, 0xFF), m, footphase); ShadowV(V, cgi.shWaterElemental); queuepoly(VBS, cgi.shWaterElemental, darkena(firecolor(0), 0, 0xFF)); queuepoly(VHEAD1, cgi.shFemaleHair, darkena(firecolor(100), 0, 0xFF)); @@ -2148,7 +2157,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t } case moAirElemental: { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0x40), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0x40), m, footphase); ShadowV(V, cgi.shWaterElemental); queuepoly(VBS, cgi.shWaterElemental, darkena(col, 0, 0x80)); queuepoly(VHEAD1, cgi.shFemaleHair, darkena(col, 0, 0x80)); @@ -2221,7 +2230,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t queuepolyat(VHEAD, cgi.shSlimeEyes, 0xFF, PPR::MONSTER_HEAD); } else if(isDemon(m)) { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xC0), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 0, 0xC0), m, footphase); queuepoly(VBS, cgi.shPBody, darkena(col, 1, 0xC0)); ShadowV(V, cgi.shPBody); int acol = col; @@ -2246,7 +2255,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t queuepoly(VAHEAD, cgi.shTrylobiteHead, darkena(acol, 0, 0xFF)); } else if(isWitch(m)) { - const transmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 1, 0xFF), m, footphase); + const shiftmatrix VBS = VBODY * otherbodyparts(V, darkena(col, 1, 0xFF), m, footphase); int cc = 0xFF; if(m == moWitchGhost) cc = 0x85 + 120 * sintick(160); if(m == moWitchWinter && where) drawWinter(V, 0); @@ -2279,7 +2288,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t #endif } -bool drawMonsterTypeDH(eMonster m, cell *where, const transmatrix& V, color_t col, bool dh, ld footphase, color_t asciicol) { +bool drawMonsterTypeDH(eMonster m, cell *where, const shiftmatrix& V, color_t col, bool dh, ld footphase, color_t asciicol) { dynamicval p(poly_outline, poly_outline); if(dh) { poly_outline = OUTLINE_DEAD; @@ -2292,9 +2301,9 @@ bool drawMonsterTypeDH(eMonster m, cell *where, const transmatrix& V, color_t co return b; } -EX transmatrix playerV; +EX shiftmatrix playerV; -EX bool applyAnimation(cell *c, transmatrix& V, double& footphase, int layer) { +EX bool applyAnimation(cell *c, shiftmatrix& V, double& footphase, int layer) { if(!animations[layer].count(c)) return false; animation& a = animations[layer][c]; @@ -2306,7 +2315,7 @@ EX bool applyAnimation(cell *c, transmatrix& V, double& footphase, int layer) { if(sl2) { a.wherenow = slr::translate(tC0(a.wherenow)); hyperpoint h = tC0(inverse(a.wherenow)); - hyperpoint ie = slr::get_inverse_exp(h, 0); + hyperpoint ie = slr::get_inverse_exp(shiftless(h)); auto R = hypot_d(3, ie); aspd *= (1+R+(shmup::on?1:0)); if(R < aspd || std::isnan(R) || std::isnan(aspd) || R > 10) { @@ -2370,19 +2379,19 @@ EX bool applyAnimation(cell *c, transmatrix& V, double& footphase, int layer) { } } -double chainAngle(cell *c, transmatrix& V, cell *c2, double dft, const transmatrix &Vwhere) { +double chainAngle(cell *c, shiftmatrix& V, cell *c2, double dft, const shiftmatrix &Vwhere) { if(!gmatrix0.count(c2)) return dft; hyperpoint h = C0; if(animations[LAYER_BIG].count(c2)) h = animations[LAYER_BIG][c2].wherenow * h; - h = inverse(V) * Vwhere * calc_relative_matrix(c2, c, C0) * h; + h = inverse_shift(V, Vwhere) * calc_relative_matrix(c2, c, C0) * h; return atan2(h[1], h[0]); } // equivalent to V = V * spin(-chainAngle(c,V,c2,dft)); -bool chainAnimation(cell *c, cell *c2, transmatrix& V, const transmatrix &Vwhere, ld& length) { +bool chainAnimation(cell *c, cell *c2, shiftmatrix& V, const shiftmatrix &Vwhere, ld& length) { hyperpoint h = C0; if(animations[LAYER_BIG].count(c2)) h = animations[LAYER_BIG][c2].wherenow * h; - h = inverse(V) * Vwhere * h; + h = inverse_shift(V, Vwhere) * h; length = hdist0(h); V = V * rspintox(h); return true; @@ -2439,7 +2448,7 @@ void drawWormSegments() { EX bool dont_face_pc = false; -EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, color_t asciicol) { +EX bool drawMonster(const shiftmatrix& Vparam, int ct, cell *c, color_t col, color_t asciicol) { #if CAP_SHAPES bool darkhistory = history::includeHistory && history::inkillhistory.count(c); @@ -2453,14 +2462,14 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col bool nospins = false, nospinb = false; double footphaseb = 0, footphase = 0; - transmatrix Vs = Vparam; nospins = applyAnimation(c, Vs, footphase, LAYER_SMALL); - transmatrix Vb = Vparam; nospinb = applyAnimation(c, Vb, footphaseb, LAYER_BIG); + shiftmatrix Vs = Vparam; nospins = applyAnimation(c, Vs, footphase, LAYER_SMALL); + shiftmatrix Vb = Vparam; nospinb = applyAnimation(c, Vb, footphaseb, LAYER_BIG); // nospin = true; eMonster m = c->monst; bool half_elliptic = elliptic && GDIM == 3 && WDIM == 2; - bool mirrored = det(Vparam) > 0; + bool mirrored = det(Vparam.T) > 0; if(!m) ; @@ -2485,7 +2494,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col if(GDIM == 3) addradar(Vparam, minf[m].glyph, asciicol, isFriendly(m) ? 0x00FF00FF : 0xFF0000FF); - transmatrix Vb0 = Vb; + shiftmatrix Vb0 = Vb; if(c->mondir != NODIR && GDIM == 3 && isAnyIvy(c)) { queueline(tC0(Vparam), Vparam * tC0(currentmap->adj(c, c->mondir)), (col << 8) + 0xFF, 0); } @@ -2527,7 +2536,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col } else { if(c->monst == moTentacleGhost) { - hyperpoint V0 = history::on ? tC0(Vs) : inverse(cwtV) * tC0(Vs); + hyperpoint V0 = history::on ? unshift(tC0(Vs)) : inverse_shift(cwtV, tC0(Vs)); hyperpoint V1 = spintox(V0) * V0; Vs = cwtV * rspintox(V0) * rpushxto0(V1) * pispin; drawMonsterType(moGhost, c, Vs, col, footphase, asciicol); @@ -2552,10 +2561,10 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col add_segment(taildist(c), [=] () { for(int i=11; i>=0; i--) { if(i < 3 && (c->monst == moTentacle || c->monst == moTentaclewait)) continue; - transmatrix Vbx = Vb; + shiftmatrix Vbx = Vb; if(WDIM == 2) Vbx = Vbx * spin(sin(M_PI * i / 6.) * wav / (i+.1)); Vbx = Vbx * xpush(length * (i) / 12.0); - // transmatrix Vbx2 = Vnext * xpush(length2 * i / 6.0); + // shiftmatrix Vbx2 = Vnext * xpush(length2 * i / 6.0); // Vbx = Vbx * rspintox(inverse(Vbx) * Vbx2 * C0) * pispin; ShadowV(Vbx, sh, PPR::GIANTSHADOW); queuepoly(mmscale(Vbx, cgi.ABODY), sh, (col0 << 8) + 0xFF); @@ -2565,7 +2574,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col } else { - transmatrix T = Vparam * ddspin(c, c->mondir); + shiftmatrix T = Vparam * ddspin(c, c->mondir); color_t col = darkena(0x606020, 0, 0xFF); for(int u=-1; u<=1; u++) queueline(T*xspinpush0(M_PI/2, u*cgi.crossf/5), T*xspinpush(0, cgi.crossf)*xspinpush0(M_PI/2, u*cgi.crossf/5), col, 2 + vid.linequality); @@ -2580,9 +2589,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col queuepoly(Vb * spin(a * 2 * M_PI / (c->type-2)), cgi.shILeaf[2], darkena(col, 0, 0xFF)); } else if(GDIM == 3) { - hyperpoint V0 = tC0(Vb); - transmatrix Vs = rspintox(V0) * xpush(hdist0(V0)) * cspin(0, 2, -M_PI/2); - queuepoly(Vs, cgi.shILeaf[1], darkena(col, 0, 0xFF)); + queuepoly(face_the_player(Vb), cgi.shILeaf[1], darkena(col, 0, 0xFF)); } else { if(c->monmirror) Vb = Vb * Mirror; @@ -2593,14 +2600,14 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col else if(m == moWorm || m == moWormwait || m == moHexSnake) { Vb = Vb * pispin; if(c->monmirror) Vb = Vb * Mirror; - transmatrix Vbh = mmscale(Vb, cgi.AHEAD); + shiftmatrix Vbh = mmscale(Vb, cgi.AHEAD); queuepoly(Vbh, cgi.shWormHead, darkena(col, 0, 0xFF)); queuepolyat(Vbh, cgi.shWormEyes, 0xFF, PPR::ONTENTACLE_EYES); ShadowV(Vb, cgi.shWormHead, PPR::GIANTSHADOW); } else if(m == moDragonHead) { if(c->monmirror) Vb = Vb * Mirror; - transmatrix Vbh = mmscale(Vb, cgi.AHEAD); + shiftmatrix Vbh = mmscale(Vb, cgi.AHEAD); ShadowV(Vb, cgi.shDragonHead, PPR::GIANTSHADOW); queuepoly(Vbh, cgi.shDragonHead, darkena(col, c->hitpoints?0:1, 0xFF)); queuepolyat(Vbh/* * pispin */, cgi.shDragonEyes, 0xFF, PPR::ONTENTACLE_EYES); @@ -2612,7 +2619,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col else if(m == moTentacle || m == moTentaclewait || m == moTentacleEscaping) { Vb = Vb * pispin; if(c->monmirror) Vb = Vb * Mirror; - transmatrix Vbh = mmscale(Vb, cgi.AHEAD); + shiftmatrix Vbh = mmscale(Vb, cgi.AHEAD); queuepoly(Vbh, cgi.shTentHead, darkena(col, 0, 0xFF)); ShadowV(Vb, cgi.shTentHead, PPR::GIANTSHADOW); } @@ -2633,7 +2640,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col Vb = Vb0 * ddspin(c, nd, M_PI); } if(c->monmirror) Vb = Vb * Mirror; - transmatrix Vbb = mmscale(Vb, cgi.ABODY); + shiftmatrix Vbb = mmscale(Vb, cgi.ABODY); queuepoly(Vbb, cgi.shDragonTail, darkena(col, c->hitpoints?0:1, 0xFF)); ShadowV(Vb, cgi.shDragonTail, PPR::GIANTSHADOW); } @@ -2655,7 +2662,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col Vb = Vb0 * spin((hdir0 + hdir1)/2 + M_PI); } if(c->monmirror) Vb = Vb * Mirror; - transmatrix Vbb = mmscale(Vb, cgi.ABODY); + shiftmatrix Vbb = mmscale(Vb, cgi.ABODY); if(part == 'l' || part == '2') { queuepoly(Vbb, cgi.shDragonLegs, darkena(col, c->hitpoints?0:1, 0xFF)); } @@ -2683,7 +2690,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col Vb = Vb0 * ddspin(c, nd, M_PI); } if(c->monmirror) Vb = Vb * Mirror; - transmatrix Vbb = mmscale(Vb, cgi.ABODY) * pispin; + shiftmatrix Vbb = mmscale(Vb, cgi.ABODY) * pispin; hpcshape& sh = hexsnake ? cgi.shWormTail : cgi.shSmallWormTail; queuepoly(Vbb, sh, darkena(col, 0, 0xFF)); ShadowV(Vb, sh, PPR::GIANTSHADOW); @@ -2708,20 +2715,20 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col if(d&1) cw = cw.mirrorat(xdir); if(d>=2) cw += 2; if(d>=4) cw += 2; - transmatrix Vs = Vparam; + shiftmatrix Vs = Vparam; bool mirr = cw.mirrored; if(mirrored != mirr && half_elliptic) continue; - transmatrix T = Id; + shiftmatrix T = shiftless(Id); nospins = applyAnimation(cwt.at, T, footphase, LAYER_SMALL); if(nospins) - Vs = Vs * ddspin(c, cw.spin, 0) * iddspin(cwt.at, cwt.spin, 0) * T; + Vs = Vs * ddspin(c, cw.spin, 0) * iddspin(cwt.at, cwt.spin, 0) * unshift(T); else Vs = Vs * ddspin(c, cw.spin, 0); if(mirr) Vs = Vs * Mirror; if(inmirrorcount&1) mirr = !mirr; - col = mirrorcolor(geometry == gElliptic ? det(Vs) < 0 : mirr); + col = mirrorcolor(geometry == gElliptic ? det(Vs.T) < 0 : mirr); if(!mouseout() && !nospins && GDIM == 2) { - hyperpoint P2 = Vs * inverse(cwtV) * mouseh; + shiftpoint P2 = Vs * inverse_shift(cwtV, mouseh); queuestr(P2, 10, "x", 0xFF00); } if(!nospins && flipplayer) Vs = Vs * pispin; @@ -2800,7 +2807,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col if(!nospins) { if(WDIM == 2 || prod) { - hyperpoint V0 = inverse(cwtV) * tC0(Vs); + hyperpoint V0 = inverse_shift(cwtV, tC0(Vs)); ld z = 0; if(prod) { auto d = product_decompose(V0); @@ -2810,13 +2817,13 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, col hyperpoint V1 = spintox(V0) * V0; - if(hypot_d(2, tC0(Vs)) > 1e-3) { + if(hypot_d(2, tC0(unshift(Vs))) > 1e-3) { Vs = cwtV * rspintox(V0) * rpushxto0(V1) * pispin; if(prod) Vs = mscale(Vs, z); } } else if(!sl2) { - hyperpoint V0 = inverse(cwtV) * tC0(Vs); + hyperpoint V0 = inverse_shift(cwtV, tC0(Vs)); Vs = cwtV * rspintox(V0) * xpush(hdist0(V0)) * cspin(0, 2, -M_PI); // cwtV * rgpushxto0(inverse(cwtV) * tC0(Vs)); } @@ -2898,25 +2905,25 @@ EX void clearaura() { auramemo = 128 * 128 / vid.aurastr; } -void apply_joukowsky_aura(hyperpoint& h) { +void apply_joukowsky_aura(shiftpoint& h) { if(haveaura_cached == 2) { hyperpoint ret; applymodel(h, ret); - h = ret; + h.h = ret; } if(nonisotropic) { - h = lp_apply(inverse_exp(h, pfNO_DISTANCE)); + h.h = lp_apply(inverse_exp(h, pfNO_DISTANCE)); } } -EX void addauraspecial(hyperpoint h, color_t col, int dir) { +EX void addauraspecial(shiftpoint h, color_t col, int dir) { if(!haveaura_cached) return; apply_joukowsky_aura(h); int r = int(2*AURA + dir + atan2(h[1], h[0]) * AURA / 2 / M_PI) % AURA; auraspecials.emplace_back(r, col); } -EX void addaura(hyperpoint h, color_t col, int fd) { +EX void addaura(shiftpoint h, color_t col, int fd) { if(!haveaura_cached) return; apply_joukowsky_aura(h); @@ -3077,7 +3084,7 @@ EX void drawaura() { glflush(); current_display->next_shader_flags = GF_VARCOLOR; dynamicval m(pmodel, mdPixel); - current_display->set_all(0); + current_display->set_all(0, 0); glhr::id_modelview(); glhr::prepare(auravertices); glhr::set_depthtest(false); @@ -3162,24 +3169,24 @@ void draw_movement_arrows(cell *c, const transmatrix& V, int df) { if(vid.axes >= 5) keylist += key; else - queuepoly(fixrot * spin(-d * M_PI/4), cgi.shArrow, col); + queuepoly(shiftless(fixrot * spin(-d * M_PI/4)), cgi.shArrow, col); if((c->type & 1) && (isStunnable(c->monst) || isPushable(c->wall))) { - transmatrix Centered = rgpushxto0(tC0(cwtV)); + transmatrix Centered = rgpushxto0(unshift(tC0(cwtV))); int sd = md.subdir; transmatrix T = inverse(Centered) * rgpushxto0(Centered * tC0(V)) * rspintox(Centered*tC0(V)) * spin(-sd * M_PI/S7) * xpush(0.2); if(vid.axes >= 5) - queuestr(T, keysize, s0 + key, col >> 8, 1); + queuestr(shiftless(T), keysize, s0 + key, col >> 8, 1); else - queuepoly(T, cgi.shArrow, col); + queuepoly(shiftless(T), cgi.shArrow, col); } else if(!confusingGeometry()) break; } } - if(keylist != "") queuestr(V, keysize, keylist, col >> 8, 1); + if(keylist != "") queuestr(shiftless(V), keysize, keylist, col >> 8, 1); } EX int celldistAltPlus(cell *c) { return 1000000 + celldistAlt(c); } @@ -3308,7 +3315,7 @@ EX bool use_swapped_duals() { } #if CAP_SHAPES -EX void floorShadow(cell *c, const transmatrix& V, color_t col) { +EX void floorShadow(cell *c, const shiftmatrix& V, color_t col) { if(model_needs_depth() || noshadow) return; // shadows break the depth testing dynamicval p(poly_outline, OUTLINE_TRANS); @@ -3328,7 +3335,7 @@ EX bool use_warp_graphics() { return true; } -EX void escherSidewall(cell *c, int sidepar, const transmatrix& V, color_t col) { +EX void escherSidewall(cell *c, int sidepar, const shiftmatrix& V, color_t col) { if(sidepar >= SIDE_SLEV && sidepar <= SIDE_SLEV+2) { int sl = sidepar - SIDE_SLEV; for(int z=1; z<=4; z++) if(z == 1 || (z == 4 && detaillevel == 2)) @@ -3357,7 +3364,7 @@ EX void escherSidewall(cell *c, int sidepar, const transmatrix& V, color_t col) } } -EX bool placeSidewall(cell *c, int i, int sidepar, const transmatrix& V, color_t col) { +EX bool placeSidewall(cell *c, int i, int sidepar, const shiftmatrix& V, color_t col) { if(!qfi.fshape || !qfi.fshape->is_plain || !cgi.validsidepar[sidepar] || qfi.usershape >= 0) if(GDIM == 2) { escherSidewall(c, sidepar, V, col); @@ -3380,7 +3387,7 @@ EX bool placeSidewall(cell *c, int i, int sidepar, const transmatrix& V, color_t else prio = PPR::REDWALL-2+4*(sidepar-SIDE_SLEV); dynamicval ncor(approx_nearcorner, true); - transmatrix V2 = V * ddspin_side(c, i); + shiftmatrix V2 = V * ddspin_side(c, i); if(NONSTDVAR || !standard_tiling()) { #if CAP_ARCM @@ -3428,7 +3435,7 @@ EX int gridcolor(cell *c1, cell *c2) { } #if CAP_SHAPES -EX void pushdown(cell *c, int& q, const transmatrix &V, double down, bool rezoom, bool repriority) { +EX void pushdown(cell *c, int& q, const shiftmatrix &V, double down, bool rezoom, bool repriority) { #if MAXMDIM >= 4 if(GDIM == 3) { @@ -3460,7 +3467,7 @@ EX void pushdown(cell *c, int& q, const transmatrix &V, double down, bool rezoom double z2; - double z = zlevel(tC0(ptd.V)); + double z = zlevel(tC0(ptd.V.T)); double lev = geom3::factor_to_lev(z); double nlev = lev - down; @@ -3470,8 +3477,8 @@ EX void pushdown(cell *c, int& q, const transmatrix &V, double down, bool rezoom // xyscale = xyscale + (zscale-xyscale) * (1+sin(ticks / 1000.0)) / 2; - ptd.V = xyzscale( V, xyscale*zscale, zscale) - * inverse(V) * ptd.V; + ptd.V.T = xyzscale( V.T, xyscale*zscale, zscale) + * V.T * ptd.V.T; if(!repriority) ; else if(nlev < -vid.lake_bottom-1e-3) { @@ -3662,10 +3669,10 @@ EX int get_darkval(cell *c, int d) { return 0; } -EX ld mousedist(transmatrix T) { - if(GDIM == 2) return intval(mouseh, tC0(T)); - hyperpoint T1 = tC0(mscale(T, cgi.FLOOR)); - if(mouseaim_sensitivity) return sqhypot_d(2, T1) + (point_behind(T1) ? 1e10 : 0); +EX ld mousedist(shiftmatrix T) { + if(GDIM == 2) return hdist(mouseh, tC0(T)); + shiftpoint T1 = tC0(mscale(T, cgi.FLOOR)); + if(mouseaim_sensitivity) return sqhypot_d(2, T1.h) + (point_behind(T1) ? 1e10 : 0); hyperpoint h1; applymodel(T1, h1); h1 = h1 - hpxy((mousex - current_display->xcenter) / current_display->radius, (mousey - current_display->ycenter) / current_display->radius); @@ -3700,7 +3707,7 @@ void make_clipping_planes() { bool celldrawer::cell_clipped() { if(WDIM == 3 && pmodel == mdPerspective && !nonisotropic && !in_s2xe()) { - hyperpoint H = tC0(V); + hyperpoint H = unshift(tC0(V)); if(prod) H = product::inverse_exp(H); for(hyperpoint& cpoint: clipping_planes) if((H|cpoint) < -sin_auto(cgi.corner_bonus)) { drawcell_in_radar(); @@ -3709,19 +3716,19 @@ bool celldrawer::cell_clipped() { noclipped++; } if(pmodel == mdGeodesic && sn::in()) { - hyperpoint H = tC0(V); + hyperpoint H = unshift(tC0(V)); if(abs(H[0]) <= 3 && abs(H[1]) <= 3 && abs(H[2]) <= 3 ) ; else { - hyperpoint H2 = inverse_exp(H, pQUICK); + hyperpoint H2 = inverse_exp(shiftless(H), pQUICK); for(hyperpoint& cpoint: clipping_planes) if((H2|cpoint) < -.6) return true; } noclipped++; } if(pmodel == mdGeodesic && nil) { - hyperpoint H = tC0(V); + hyperpoint H = unshift(tC0(V)); if(abs(H[0]) <= 3 && abs(H[1]) <= 3 && abs(H[2]) <= 3 ) ; else { - hyperpoint H2 = inverse_exp(H, pQUICK); + hyperpoint H2 = inverse_exp(shiftless(H), pQUICK); for(hyperpoint& cpoint: clipping_planes) if((H2|cpoint) < -2) return true; } noclipped++; @@ -3735,13 +3742,14 @@ int grid_depth = 0; EX bool fat_edges = false; -EX void gridline(const transmatrix& V1, const hyperpoint h1, const transmatrix& V2, const hyperpoint h2, color_t col, int prec) { - ld d = hdist(V1*h1, V2*h2); +EX void gridline(const shiftmatrix& V1, const hyperpoint h1, const shiftmatrix& V2, const hyperpoint h2, color_t col, int prec) { + transmatrix U2 = unshift(V2, V1.shift); + ld d = hdist(V1.T*h1, U2*h2); #if MAXMDIM >= 4 if(WDIM == 3 && fat_edges) { - transmatrix T = V1 * rgpushxto0(h1); - transmatrix S = rspintox(inverse(T) * V2 * h2); + shiftmatrix T = V1 * rgpushxto0(h1); + transmatrix S = rspintox(inverse_shift(T, V2) * h2); auto& p = queuepoly(T * S, cgi.generate_pipe(d, vid.linewidth), col); p.intester = xpush0(d/2); return; @@ -3749,7 +3757,7 @@ EX void gridline(const transmatrix& V1, const hyperpoint h1, const transmatrix& #endif while(d > precise_width && d < 100 && grid_depth < 10) { - if(!eqmatrix(V1, V2, 1e-6)) { gridline(V1, h1, V1, inverse(V1) * V2 * h2, col, prec); return; } + if(V1.shift != V2.shift || !eqmatrix(V1.T, V2.T, 1e-6)) { gridline(V1, h1, V1, inverse_shift(V1, V2) * h2, col, prec); return; } hyperpoint h = midz(h1, h2); grid_depth++; gridline(V1, h1, V1, h, col, prec); @@ -3768,7 +3776,7 @@ EX void gridline(const transmatrix& V1, const hyperpoint h1, const transmatrix& queueline(V1*h1, V2*h2, col, prec); } -EX void gridline(const transmatrix& V, const hyperpoint h1, const hyperpoint h2, color_t col, int prec) { +EX void gridline(const shiftmatrix& V, const hyperpoint h1, const hyperpoint h2, color_t col, int prec) { gridline(V, h1, V, h2, col, prec); } @@ -3778,9 +3786,9 @@ EX int wall_offset(cell *c) { return 0; } -EX void queue_transparent_wall(const transmatrix& V, hpcshape& sh, color_t color) { +EX void queue_transparent_wall(const shiftmatrix& V, hpcshape& sh, color_t color) { auto& poly = queuepolyat(V, sh, color, PPR::TRANSPARENT_WALL); - hyperpoint h = V * sh.intester; + shiftpoint h = V * sh.intester; if(in_perspective()) poly.subprio = int(hdist0(h) * 100000); else { @@ -3905,7 +3913,7 @@ EX int ceiling_category(cell *c) { #endif -EX void set_detail_level(const transmatrix& V) { +EX void set_detail_level(const shiftmatrix& V) { ld dist0 = hdist0(tC0(V)) - 1e-6; if(vid.use_smart_range) detaillevel = 2; else if(dist0 < vid.highdetail) detaillevel = 2; @@ -4040,7 +4048,7 @@ void celldrawer::draw_fallanims() { if(t <= maxtime) { erase = false; c->stuntime = 0; - transmatrix V2 = V; + shiftmatrix V2 = V; double footphase = t / 200.0; applyAnimation(c, V2, footphase, LAYER_SMALL); drawMonsterType(fa.m, c, V2, minf[fa.m].color, footphase, NOCOLOR); @@ -4052,7 +4060,7 @@ void celldrawer::draw_fallanims() { } #if CAP_QUEUE -EX void queuecircleat1(cell *c, const transmatrix& V, double rad, color_t col) { +EX void queuecircleat1(cell *c, const shiftmatrix& V, double rad, color_t col) { if(WDIM == 3) { dynamicval p(poly_outline, col); // we must do hybrid::wall_offset in hybrid because the cached value is likely incorrect @@ -4063,7 +4071,7 @@ EX void queuecircleat1(cell *c, const transmatrix& V, double rad, color_t col) { return; } if(spatial_graphics || GDIM == 3) { - vector corners(c->type+1); + vector corners(c->type+1); for(int i=0; itype; i++) corners[i] = V * rgpushxto0(get_corner_position(c, i, 3 / rad)); corners[c->type] = corners[0]; for(int i=0; itype; i++) { @@ -4155,7 +4163,7 @@ EX void drawMarkers() { if(inscreenrange(c)) keycell = c; } - hyperpoint H = tC0(ggmatrix(keycell)); + shiftpoint H = tC0(ggmatrix(keycell)); #if CAP_QUEUE queuestr(H, 2*vid.fsize, "X", 0x10101 * int(128 + 100 * sintick(150))); int cd = celldistance(yi[yii].key(), cwt.at); @@ -4216,15 +4224,15 @@ EX void drawMarkers() { #if CAP_SHAPES if((vid.axes >= 4 || (vid.axes == 1 && !mousing)) && !shmup::on && GDIM == 2) { if(multi::players == 1) { - forCellIdAll(c2, d, cwt.at) if(gmatrix.count(cwt.at)) draw_movement_arrows(c2, gmatrix[cwt.at] * currentmap->adj(cwt.at, d), d); + forCellIdAll(c2, d, cwt.at) if(gmatrix.count(cwt.at)) draw_movement_arrows(c2, unshift(gmatrix[cwt.at]) * currentmap->adj(cwt.at, d), d); } else if(multi::players > 1) for(int p=0; p= 4 || !drawstaratvec(multi::mdx[p], multi::mdy[p]))) forCellIdAll(c2, d, multi::player[p].at) if(gmatrix.count(cwt.at)) { multi::cpid = p; - dynamicval ttm(cwtV, multi::whereis[p]); + dynamicval ttm(cwtV, multi::whereis[p]); dynamicval tcw(cwt, multi::player[p]); - draw_movement_arrows(c2, gmatrix[cwt.at] * currentmap->adj(cwt.at, d), d); + draw_movement_arrows(c2, unshift(gmatrix[cwt.at]) * currentmap->adj(cwt.at, d), d); } } } @@ -4293,9 +4301,9 @@ EX void drawMarkers() { auto mib = blowoff_destination(c1, di); if(!mib.proper()) break; auto& c2 = mib.t; - transmatrix T1 = ggmatrix(c1); - transmatrix T2 = ggmatrix(c2); - transmatrix T = T1 * rspintox(inverse(T1)*T2*C0) * xpush(hdist(T1*C0, T2*C0) * fractick(50, 0)); + 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)); color_t aircol = (orbToTarget == itOrbAir ? 0x8080FF40 : 0x8080FF20); queuepoly(T, cgi.shDisk, aircol); c1 = c2; @@ -4330,7 +4338,7 @@ void drawFlashes() { #if CAP_QUEUE always_false static_bubbles; -EX void draw_flash(struct flashdata& f, const transmatrix& V, bool& kill) { +EX void draw_flash(struct flashdata& f, const shiftmatrix& V, bool& kill) { int tim = ticks - f.t; if(tim <= f.size && !f.spd) kill = false; @@ -4346,18 +4354,18 @@ EX void draw_flash(struct flashdata& f, const transmatrix& V, bool& kill) { if(GDIM == 3 || sphere) queuestr(V, (1 - tim * 1. / f.size) * f.angle, f.text, col, r); else if(!kill) { - hyperpoint h = tC0(V); + shiftpoint h = tC0(V); if(hdist0(h) > .1) { - transmatrix V2 = rspintox(h) * xpush(hdist0(h) * (1 / (1 - tim * 1. / f.size))); - queuestr(V2, f.angle, f.text, col, r); + transmatrix V2 = rspintox(h.h) * xpush(hdist0(h.h) * (1 / (1 - tim * 1. / f.size))); + queuestr(shiftless(V2, h.shift), f.angle, f.text, col, r); } } if(static_bubbles) { ld rad[25]; for(int a=0; a<24; a++) rad[a] = (0.5 + randd() * .3 + 0.5 * (a&1)) / (2.8 + celldistance(f.where, cwt.at) * .2); rad[24] = rad[0]; - for(int a=0; a<24; a++) curvepoint(V * xspinpush0(15 * degree * a, rad[a])); - queuecurve(0xFF, 0xFF0000FF, PPR::SUPERLINE); + for(int a=0; a<24; a++) curvepoint(xspinpush0(15 * degree * a, rad[a])); + queuecurve(V, 0xFF, 0xFF0000FF, PPR::SUPERLINE); } } @@ -4367,7 +4375,7 @@ EX void draw_flash(struct flashdata& f, const transmatrix& V, bool& kill) { int partcol = darkena(f.color, 0, GDIM == 3 ? 255 : max(255 - tim*255/300, 0)); poly_outline = OUTLINE_DEFAULT; ld t = f.spd * tim * cgi.scalefactor / 50000.; - transmatrix T = + shiftmatrix T = GDIM == 2 ? V * spin(f.angle) * xpush(t) : V * cspin(0, 1, f.angle) * cspin(0, 2, f.angle2) * cpush(2, t); queuepoly(T, cgi.shParticle[f.size], partcol); @@ -4390,8 +4398,8 @@ EX void draw_flash(struct flashdata& f, const transmatrix& V, bool& kill) { else #endif { - PRING(a) curvepoint(V*xspinpush0(a * M_PI / cgi.S42, rad)); - queuecurve(flashcol, 0x8080808, PPR::LINE); + PRING(a) curvepoint(xspinpush0(a * M_PI / cgi.S42, rad)); + queuecurve(V, flashcol, 0x8080808, PPR::LINE); } } } @@ -4411,8 +4419,8 @@ EX void draw_flash(struct flashdata& f, const transmatrix& V, bool& kill) { else #endif { - PRING(a) curvepoint(V*xspinpush0(a * M_PI / cgi.S42, rad)); - queuecurve(flashcol, 0x8080808, PPR::LINE); + PRING(a) curvepoint(xspinpush0(a * M_PI / cgi.S42, rad)); + queuecurve(V, flashcol, 0x8080808, PPR::LINE); } } } @@ -4510,20 +4518,20 @@ EX void make_actual_view() { Viewbase = View; } -EX transmatrix cview() { - return actual_view_transform * View; +EX shiftmatrix cview(ld base_shift IS(0)) { + return shiftless(actual_view_transform * View, base_shift); } EX void precise_mouseover() { if(WDIM == 3) { mouseover2 = mouseover = centerover; ld best = HUGE_VAL; - hyperpoint h = direct_exp(lp_iapply(ztangent(0.01))); + shiftpoint h = shiftless(direct_exp(lp_iapply(ztangent(0.01)))); - transmatrix cov = ggmatrix(mouseover2); + shiftmatrix cov = ggmatrix(mouseover2); forCellIdEx(c1, i, mouseover2) { - hyperpoint h1 = tC0(cov * currentmap->adj(mouseover2, i)); - ld dist = geo_dist(h, h1) - geo_dist(C0, h1); + shiftpoint h1 = tC0(cov * currentmap->adj(mouseover2, i)); + ld dist = geo_dist(h, h1) - geo_dist(shiftless(C0), h1); if(dist < best) mouseover = c1, best = dist; } return; @@ -4534,7 +4542,7 @@ EX void precise_mouseover() { for(int loop = 0; loop < 10; loop++) { bool found = false; if(!gmatrix.count(mouseover)) return; - hyperpoint r_mouseh = inverse(gmatrix[mouseover]) * mouseh; + hyperpoint r_mouseh = inverse_shift(gmatrix[mouseover], mouseh); for(int i=0; itype; i++) { hyperpoint h1 = get_corner_position(mouseover, (i+mouseover->type-1) % mouseover->type); hyperpoint h2 = get_corner_position(mouseover, i); @@ -4685,11 +4693,11 @@ EX void drawthemap() { hyperpoint h; for(int i=0; i<3; i++) h[i] = 0; for(int p=0; ppat); + hyperpoint h1 = unshift(tC0(shmup::pc[p]->pat)); for(int i=0; i<3; i++) h[i] += h1[i]; } h = mid(h, h); - cwtV = rgpushxto0(h); + cwtV = shiftless(rgpushxto0(h)); } } @@ -4747,13 +4755,14 @@ EX void drawmovestar(double dx, double dy) { if(rug::rugged && multi::players == 1 && !multi::alwaysuse) return; #endif - hyperpoint H = tC0(cwtV); + shiftpoint H = tC0(cwtV); ld R = sqrt(H[0] * H[0] + H[1] * H[1]); - transmatrix Centered = Id; + shiftmatrix Centered; if(euclid) - Centered = eupush(H); + Centered = shiftless(eupush(H.h)); else if(R > 1e-9) Centered = rgpushxto0(H); + else Centered = shiftless(Id); Centered = Centered * rgpushxto0(hpxy(dx*5, dy*5)); if(multi::cpid >= 0) multi::crosscenter[multi::cpid] = Centered; @@ -4902,7 +4911,7 @@ EX void drawfullmap() { if(!inHighQual) { if((cmode & sm::NORMAL) && !rug::rugged) { if(multi::players > 1) { - transmatrix bcwtV = cwtV; + auto bcwtV = cwtV; for(int i=0; iat = inverse(first_center_view); m->base = first_center_at; v.push_back(m); - create(first_center_at, centerover, inverse(ggmatrix(centerover))); + create(first_center_at, centerover, inverse(unshift(ggmatrix(centerover)))); if(on) saved_ends = 2; return; } @@ -301,7 +301,7 @@ EX namespace history { EX void create_recenter_to_view(bool precise) { cell *c = centerover ? centerover : cwt.at; - create(path_for_lineanimation[0], c, precise ? inverse(ggmatrix(c)) : Id); + create(path_for_lineanimation[0], c, precise ? inverse(unshift(ggmatrix(c))) : Id); } EX void movetophase() { @@ -374,7 +374,7 @@ EX namespace history { v[j+1]->at * C0; hyperpoint nextscr; - applymodel(next, nextscr); + applymodel(shiftless(next), nextscr); tpixels += nextscr[0] * r; if(j == 0 || j == siz-2) @@ -452,7 +452,7 @@ EX namespace history { drawfullmap(); if(last_base) { - hyperpoint last = ggmatrix(last_base) * last_relative; + shiftpoint last = ggmatrix(last_base) * last_relative; hyperpoint hscr; applymodel(last, hscr); ld bwidth = -current_display->radius * hscr[0]; diff --git a/hprint.cpp b/hprint.cpp index 6247cd73..bedcbf28 100644 --- a/hprint.cpp +++ b/hprint.cpp @@ -216,6 +216,9 @@ inline void print(hstream& hs, const transmatrix T) { for(int j=0; j void print(hstream& hs, const pair & t) { print(hs, "(", t.first, ",", t.second, ")"); } template void print(hstream& hs, const tuple & t) { diff --git a/hud.cpp b/hud.cpp index edb00731..d2a50c9c 100644 --- a/hud.cpp +++ b/hud.cpp @@ -204,7 +204,7 @@ bool displayglyph(int cx, int cy, int buttonsize, char glyph, color_t color, int V[i][i] /= cgi.wormscale; int mcol = color; mcol -= (color & 0xFCFCFC) >> 2; - drawMonsterType(m, NULL, V, mcol, glyphphase[id]/500.0, NOCOLOR); + drawMonsterType(m, NULL, shiftless(V), mcol, glyphphase[id]/500.0, NOCOLOR); } else { eItem it = eItem(id); @@ -226,7 +226,7 @@ bool displayglyph(int cx, int cy, int buttonsize, char glyph, color_t color, int ((glyph == 't' && qty%5) || it == itOrbYendor) ? ticks/2 : it == itTerra ? glyphphase[id] * 3 * M_PI + 900 * M_PI: glyphphase[id] * 2; - drawItemType(it, NULL, V, icol, t, false); + drawItemType(it, NULL, shiftless(V), icol, t, false); } quickqueue(); } @@ -355,11 +355,11 @@ void drawMobileArrow(int i) { ld scale = vid.mobilecompasssize * (sphere ? 7 : euclid ? 6 : 5); // m2[0][0] = scale; m2[1][1] = scale; m2[2][2] = 1; - transmatrix U = ggmatrix(cwt.at); - hyperpoint H = sphereflip * tC0(U); - transmatrix Centered = sphereflip * rgpushxto0(H); + shiftmatrix U = ggmatrix(cwt.at); + shiftpoint H = tC0(U); + shiftmatrix Centered = rgpushxto0(H); - hyperpoint P = inverse(Centered) * U * T * C0; + hyperpoint P = inverse_shift(Centered, U * T * C0); double alpha = atan2(P[1], P[0]); using namespace shmupballs; @@ -367,7 +367,7 @@ void drawMobileArrow(int i) { double dx = xmove + rad*(1+SKIPFAC-.2)/2 * cos(alpha); double dy = yb + rad*(1+SKIPFAC-.2)/2 * sin(alpha); - queuepolyat(atscreenpos(dx, dy, scale) * spin(-alpha), cgi.shArrow, col, PPR::MOBILE_ARROW); + queuepolyat(shiftless(atscreenpos(dx, dy, scale) * spin(-alpha)), cgi.shArrow, col, PPR::MOBILE_ARROW); } #endif @@ -419,8 +419,8 @@ EX void drawStats() { if(crosshair_color && crosshair_size > 0) { initquickqueue(); vid.linewidth = 1; - queueline(tC0(atscreenpos(xc - crosshair_size, yc, 1)), tC0(atscreenpos(xc + crosshair_size, yc, 1)), crosshair_color).prio = PPR::SUPERLINE; - queueline(tC0(atscreenpos(xc, yc - crosshair_size, 1)), tC0(atscreenpos(xc, yc + crosshair_size, 1)), crosshair_color).prio = PPR::SUPERLINE; + queueline(shiftless(tC0(atscreenpos(xc - crosshair_size, yc, 1))), shiftless(tC0(atscreenpos(xc + crosshair_size, yc, 1))), crosshair_color).prio = PPR::SUPERLINE; + queueline(shiftless(tC0(atscreenpos(xc, yc - crosshair_size, 1))), shiftless(tC0(atscreenpos(xc, yc + crosshair_size, 1))), crosshair_color).prio = PPR::SUPERLINE; quickqueue(); } diff --git a/hyperpoint.cpp b/hyperpoint.cpp index 20eba419..5becb400 100644 --- a/hyperpoint.cpp +++ b/hyperpoint.cpp @@ -136,6 +136,45 @@ struct transmatrix { } }; +/** @brief hyperpoint with shift + * shift has two uses: + * (1) in the 'universal cover of SL' geometry, shift is used for the extra angular coordinate + * (2) in band models, shift is used to draw faraway points correctly + */ +struct shiftpoint { + hyperpoint h; + ld shift; + ld& operator [] (int i) { return h[i]; } + const ld& operator [] (int i) const { return h[i]; } + inline friend shiftpoint operator + (const shiftpoint& h, const hyperpoint& h2) { + return shiftpoint{h.h+h2, h.shift}; + } + inline friend shiftpoint operator - (const shiftpoint& h, const hyperpoint& h2) { + return shiftpoint{h.h-h2, h.shift}; + } + }; + +inline shiftpoint shiftless(const hyperpoint& h, ld shift = 0) { + shiftpoint res; res.h = h; res.shift = shift; return res; + } + +struct shiftmatrix { + transmatrix T; + ld shift; + hyperpoint& operator [] (int i) { return T[i]; } + const hyperpoint& operator [] (int i) const { return T[i]; } + inline friend shiftpoint operator * (const shiftmatrix& T, const hyperpoint& h) { + return shiftpoint{T.T*h, T.shift}; + } + inline friend shiftmatrix operator * (const shiftmatrix& T, const transmatrix& U) { + return shiftmatrix{T.T*U, T.shift}; + } + }; + +inline shiftmatrix shiftless(const transmatrix& T, ld shift = 0) { + shiftmatrix res; res.T = T; res.shift = shift; return res; + } + /** returns a diagonal matrix */ constexpr transmatrix diag(ld a, ld b, ld c, ld d) { #if MAXMDIM==3 @@ -324,7 +363,7 @@ EX ld atan2_auto(ld y, ld x) { case gcHyperbolic: return atanh(y/x); case gcSL2: return atanh(y/x); case gcSphere: return atan2(y, x); - case gcProduct: return PIU(atan2_auto(y, x)); + case gcProduct: return PIU(atan2_auto(y, x)); default: return y/x; } } @@ -480,6 +519,10 @@ EX hyperpoint mid(const hyperpoint& H1, const hyperpoint& H2) { return normalize(H1 + H2); } +EX shiftpoint mid(const shiftpoint& H1, const shiftpoint& H2) { + return shiftless(mid(H1.h, H2.h), (H1.shift + H2.shift)/2); + } + /** like mid, but take 3D into account */ EX hyperpoint midz(const hyperpoint& H1, const hyperpoint& H2) { if(prod) return mid(H1, H2); @@ -786,6 +829,10 @@ EX transmatrix rgpushxto0(const hyperpoint& H) { return ggpushxto0(H, 1); } +EX shiftmatrix rgpushxto0(const shiftpoint& H) { + return shiftless(rgpushxto0(H.h), H.shift); + } + /** \brief Fix the numerical inaccuracies in the isometry T * * The nature of hyperbolic geometry makes the computations numerically unstable. @@ -955,6 +1002,10 @@ EX ld hdist0(const hyperpoint& mh) { } } +EX ld hdist0(const shiftpoint& mh) { + return hdist0(unshift(mh)); + } + /** length of a circle of radius r */ EX ld circlelength(ld r) { switch(cgclass) { @@ -994,6 +1045,10 @@ EX ld hdist(const hyperpoint& h1, const hyperpoint& h2) { } } +EX ld hdist(const shiftpoint& h1, const shiftpoint& h2) { + return hdist(h1.h, unshift(h2, h1.shift)); + } + EX hyperpoint mscale(const hyperpoint& t, double fac) { if(GDIM == 3 && !prod) return cpush(2, fac) * t; if(prod) fac = exp(fac); @@ -1003,6 +1058,10 @@ EX hyperpoint mscale(const hyperpoint& t, double fac) { return res; } +EX shiftpoint mscale(const shiftpoint& t, double fac) { + return shiftless(mscale(t.h, fac), t.shift); + } + EX transmatrix mscale(const transmatrix& t, double fac) { if(GDIM == 3 && !prod) { // if(pmodel == mdFlatten) { transmatrix u = t; u[2][LDIM] -= fac; return u; } @@ -1015,6 +1074,10 @@ EX transmatrix mscale(const transmatrix& t, double fac) { return res; } +EX shiftmatrix mscale(const shiftmatrix& t, double fac) { + return shiftless(mscale(t.T, fac), t.shift); + } + EX transmatrix xyscale(const transmatrix& t, double fac) { transmatrix res; for(int i=0; i 1.1 && GDIM == 3; } #endif -void ghcheck(hyperpoint &ret, const hyperpoint &H) { +void ghcheck(hyperpoint &ret, const shiftpoint &H) { if(hypot_d(2, ret-ghxy) < hypot_d(2, ghgxy-ghxy)) { ghpm = H; ghgxy = ret; } @@ -88,7 +89,7 @@ EX hyperpoint space_to_perspective(hyperpoint z, ld alpha IS(pconf.alpha)) { return z; } -EX hyperpoint gethyper(ld x, ld y) { +EX shiftpoint gethyper(ld x, ld y) { ld hx = (x - current_display->xcenter) / current_display->radius; ld hy = (y - current_display->ycenter) / current_display->radius / pconf.stretch; @@ -97,9 +98,9 @@ EX hyperpoint gethyper(ld x, ld y) { if(pmodel) { ghxy = hxy; - transmatrix T = rgpushxto0(ghpm); + shiftmatrix T = rgpushxto0(ghpm); - auto distance_at = [&] (const transmatrix& T1) { + auto distance_at = [&] (const shiftmatrix& T1) { hyperpoint h1; applymodel(tC0(T1), h1); return sqhypot_d(2, hxy - h1); @@ -109,17 +110,17 @@ EX hyperpoint gethyper(ld x, ld y) { for(int it=0; it<50; it++) for(int s=0; s<4; s++) { - transmatrix T1 = T * spin(s * quarter_circle) * xpush(pow(1.2, -it)); + shiftmatrix T1 = T * spin(s * quarter_circle) * xpush(pow(1.2, -it)); ld dist = distance_at(T1); if(dist < best) best = dist, T = T1; if(mdBandAny()) { - band_shift += 2 * M_PI; + T1.shift += 2 * M_PI; dist = distance_at(T1); if(dist < best) best = dist, T = T1; - band_shift -= 4 * M_PI; + T1.shift -= 4 * M_PI; dist = distance_at(T1); if(dist < best) best = dist, T = T1; - band_shift += 2 * M_PI; + T1.shift += 2 * M_PI; } } @@ -128,7 +129,7 @@ EX hyperpoint gethyper(ld x, ld y) { if(pconf.camera_angle) camrotate(hx, hy); - return perspective_to_space(hpxyz(hx, hy, 0)); + return shiftless(perspective_to_space(hpxyz(hx, hy, 0))); } void ballmodel(hyperpoint& ret, double alpha, double d, double zl) { @@ -221,11 +222,11 @@ void move_y_to_z(hyperpoint& H, pair coef) { } } -template void makeband(hyperpoint H, hyperpoint& ret, const T& f) { - ld zlev = find_zlev(H); +template void makeband(shiftpoint H, hyperpoint& ret, const T& f) { + ld zlev = find_zlev(H.h); models::apply_orientation_yz(H[1], H[2]); models::apply_orientation(H[0], H[1]); - auto r = move_z_to_y(H); + auto r = move_z_to_y(H.h); ld x, y, yf, zf=0; y = asin_auto(H[1]); @@ -234,7 +235,7 @@ template void makeband(hyperpoint H, hyperpoint& ret, const T& f) { if(H[LDIM] < 0 && x > 0) x = M_PI - x; else if(H[LDIM] < 0 && x <= 0) x = -M_PI - x; } - x += band_shift; + x += H.shift; hypot_zlev(zlev, y, yf, zf); f(x, y); @@ -342,14 +343,14 @@ hyperpoint compute_hybrid(hyperpoint H, int rootid) { EX ld signed_sqrt(ld x) { return x > 0 ? sqrt(x) : -sqrt(-x); } -EX void applymodel(hyperpoint H, hyperpoint& ret) { +EX void applymodel(shiftpoint H_orig, hyperpoint& ret) { - hyperpoint H_orig = H; + hyperpoint H = H_orig.h; if(models::product_model(pmodel)) { - ld zlev = zlevel(H); - H /= exp(zlev); - hybrid::in_underlying_geometry([&] { applymodel(H, ret); }); + ld zlev = zlevel(H_orig.h); + H_orig.h /= exp(zlev); + hybrid::in_underlying_geometry([&] { applymodel(H_orig, ret); }); ret[2] = zlev * pconf.product_z_scale; ret = NLP * ret; return; @@ -368,7 +369,7 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) { } case mdGeodesic: { - auto S = lp_apply(inverse_exp(H, pNORMAL | pfNO_DISTANCE)); + auto S = lp_apply(inverse_exp(H_orig, pNORMAL | pfNO_DISTANCE)); ld ratio = vid.xres / current_display->tanfov / current_display->radius / 2; ret[0] = S[0]/S[2] * ratio; ret[1] = S[1]/S[2] * ratio; @@ -391,7 +392,7 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) { case mdDisk: { if(nonisotropic) { - ret = lp_apply(inverse_exp(H, pNORMAL | pfNO_DISTANCE)); + ret = lp_apply(inverse_exp(H_orig, pNORMAL | pfNO_DISTANCE)); ld w; if(sn::in()) { // w = 1 / sqrt(1 - sqhypot_d(3, ret)); @@ -578,7 +579,7 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) { case mdFisheye: { ld zlev; if(nonisotropic) { - H = lp_apply(inverse_exp(H)); + H = lp_apply(inverse_exp(H_orig)); zlev = 1; } else { @@ -742,15 +743,15 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) { models::apply_orientation(ret[1], ret[0]); } else - makeband(H, ret, band_conformal); + makeband(H_orig, ret, band_conformal); break; case mdTwoPoint: - makeband(H, ret, make_twopoint); + makeband(H_orig, ret, make_twopoint); break; case mdMollweide: - makeband(H, ret, [] (ld& x, ld& y) { + makeband(H_orig, ret, [] (ld& x, ld& y) { ld theta = hyperbolic ? min(y / 2 + 0.572365, y * 0.78509) : euclid ? y : @@ -770,12 +771,12 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) { break; case mdCentralCyl: - makeband(H, ret, [] (ld& x, ld& y) { y = tan_auto(y); ld top = vid.yres * M_PI / current_display->radius; if(y>top) y=top; if(y<-top) y=-top; }); + makeband(H_orig, ret, [] (ld& x, ld& y) { y = tan_auto(y); ld top = vid.yres * M_PI / current_display->radius; if(y>top) y=top; if(y<-top) y=-top; }); break; case mdCollignon: - find_zlev(H); - makeband(H, ret, [] (ld& x, ld& y) { + find_zlev(H_orig.h); + makeband(H_orig, ret, [] (ld& x, ld& y) { ld sgn = 1; if(pconf.collignon_reflected && y > 0) y = -y, sgn = -1; y = signed_sqrt(sin_auto(y) + pconf.collignon_parameter); @@ -787,20 +788,20 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) { break; case mdBandEquiarea: - makeband(H, ret, [] (ld& x, ld& y) { y = sin_auto(y); }); + makeband(H_orig, ret, [] (ld& x, ld& y) { y = sin_auto(y); }); break; case mdBandEquidistant: - makeband(H, ret, [] (ld& x, ld& y) { }); + makeband(H_orig, ret, [] (ld& x, ld& y) { }); break; case mdSinusoidal: - makeband(H, ret, [] (ld& x, ld& y) { x *= cos_auto(y); }); + makeband(H_orig, ret, [] (ld& x, ld& y) { x *= cos_auto(y); }); break; case mdEquidistant: case mdEquiarea: case mdEquivolume: { if(nonisotropic || prod) { - ret = lp_apply(inverse_exp(H)); + ret = lp_apply(inverse_exp(H_orig)); ret[3] = 1; break; } @@ -855,7 +856,7 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) { case mdFormula: { dynamicval m(pmodel, pconf.basic_model); - applymodel(H, ret); + applymodel(H_orig, ret); exp_parser ep; ep.extra_params["z"] = cld(ret[0], ret[1]); ep.extra_params["cx"] = ret[0]; @@ -880,7 +881,7 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) { case mdSpiral: { cld z; - if(hyperbolic || sphere) makeband(H, ret, band_conformal); + if(hyperbolic || sphere) makeband(H_orig, ret, band_conformal); else ret = H; z = cld(ret[0], ret[1]) * models::spiral_multiplier; @@ -934,7 +935,7 @@ EX hyperpoint mirrorif(const hyperpoint& V, bool b) { else return V; } -EX transmatrix mirrorif(const transmatrix& V, bool b) { +EX shiftmatrix mirrorif(const shiftmatrix& V, bool b) { if(b) return V*Mirror; else return V; } @@ -996,6 +997,10 @@ EX bool behindsphere(const transmatrix& V) { return behindsphere(tC0(V)); } +EX bool behindsphere(const shiftmatrix& V) { + return behindsphere(tC0(V.T)); + } + EX ld spherity(const transmatrix& V) { return spherity(tC0(V)); } @@ -1034,13 +1039,18 @@ EX transmatrix actualV(const heptspin& hs, const transmatrix& V) { return (hs.spin || !BITRUNCATED) ? V * spin(hs.spin*2*M_PI/hs.at->type + master_to_c7_angle()) : V; } -EX bool point_behind(hyperpoint h) { +EX shiftmatrix actualV(const heptspin& hs, const shiftmatrix& V) { + return shiftless(actualV(hs, V.T), V.shift); + } + +EX bool point_behind(const shiftpoint h) { if(sphere) return false; if(!in_perspective()) return false; - if(pmodel == mdGeodesic) h = inverse_exp(h, pQUICK); - if(pmodel == mdPerspective && prod) h = product::inverse_exp(h); - h = lp_apply(h); - return h[2] < 1e-8; + hyperpoint h1; + if(pmodel == mdGeodesic) h1 = inverse_exp(h, pQUICK); + if(pmodel == mdPerspective && prod) h1 = product::inverse_exp(h.h); + h1 = lp_apply(h1); + return h1[2] < 1e-8; } void raise_error() { @@ -1063,12 +1073,14 @@ EX bool invalid_point(const hyperpoint h) { return std::isnan(h[LDIM]) || h[LDIM] > 1e8 || std::isinf(h[LDIM]); } -EX bool in_smart_range(const transmatrix& T) { - hyperpoint h = tC0(T); +EX bool invalid_point(const shiftpoint h) { return invalid_point(h.h); } + +EX bool in_smart_range(const shiftmatrix& T) { + shiftpoint h = tC0(T); if(invalid_point(h)) return false; if(nil || nih) return true; #if CAP_SOLV - if(pmodel == mdGeodesic) return sn::in_table_range(h); + if(pmodel == mdGeodesic) return sn::in_table_range(h.h); #endif hyperpoint h1; applymodel(h, h1); @@ -1133,9 +1145,9 @@ void drawrec(cell *c, const transmatrix& V) { } } */ - bool drawrec(cell *c, const transmatrix& V, gp::loc at, int dir, int maindir) { + bool drawrec(cell *c, const shiftmatrix& V, gp::loc at, int dir, int maindir) { bool res = false; - transmatrix V1 = V * cgi.gpdata->Tf[draw_li.last_dir][at.first&31][at.second&31][fixg6(dir)]; + shiftmatrix V1 = V * cgi.gpdata->Tf[draw_li.last_dir][at.first&31][at.second&31][fixg6(dir)]; if(do_draw(c, V1)) { /* auto li = get_local_info(c); if((dir - li.total_dir) % S6) printf("totaldir %d/%d\n", dir, li.total_dir); @@ -1156,7 +1168,7 @@ void drawrec(cell *c, const transmatrix& V) { return res; } - bool drawrec(cell *c, const transmatrix& V) { + bool drawrec(cell *c, const shiftmatrix& V) { draw_li.relative = loc(0,0); draw_li.total_dir = 0; draw_li.last_dir = -1; @@ -1176,11 +1188,9 @@ void drawrec(cell *c, const transmatrix& V) { } #endif -vector > drawn_cells; +vector > drawn_cells; -bool in_multi = false; - -EX bool drawcell_subs(cell *c, transmatrix V) { +EX bool drawcell_subs(cell *c, const shiftmatrix& V) { #if CAP_GP if(GOLDBERG) { @@ -1196,7 +1206,7 @@ EX bool drawcell_subs(cell *c, transmatrix V) { auto& vc = irr::cells_of_heptagon[hi.base.at]; for(int i=0; ic.spin(d) == 0) { - transmatrix V2 = V * currentmap->adj(c, d); + shiftmatrix V2 = V * currentmap->adj(c, d); if(do_draw(c1, V2)) draw = true, drawcell(c1, V2); @@ -1223,32 +1233,37 @@ EX bool drawcell_subs(cell *c, transmatrix V) { } void hrmap_standard::draw() { + static ld shift = 0; + static bool in_multi = false; if(sphere && pmodel == mdSpiral && !in_multi) { + /* todo other types? */ in_multi = true; if(models::ring_not_spiral) { int qty = ceil(1. / pconf.sphere_spiral_multiplier); if(qty > 100) qty = 100; for(int i=-qty; i < qty; i++) { - band_shift = 2 * M_PI * i; + shift = 2 * M_PI * i; draw(); } } else { + shift = 0; draw(); if(vid.use_smart_range) for(int i=1;; i++) { int drawn = cells_drawn; - band_shift = 2 * M_PI * i; + shift = 2 * M_PI * i; draw(); - band_shift = -2 * M_PI * i; + shift = -2 * M_PI * i; draw(); if(drawn == cells_drawn) break; } } in_multi = false; + shift = 0; return; } drawn_cells.clear(); - drawn_cells.emplace_back(centerover->master, hsOrigin, cview() * master_relative(centerover, true), band_shift); + drawn_cells.emplace_back(centerover->master, hsOrigin, cview(shift) * master_relative(centerover, true)); for(int i=0; i(dc); auto& s = get<1>(dc); auto& V = get<2>(dc); - dynamicval bs(band_shift, get<3>(dc)); cell *c = hs.at->c7; - transmatrix V10; - const transmatrix& V1 = hs.mirrored ? (V10 = V * Mirror) : V; + const shiftmatrix& V1 = hs.mirrored ? V * Mirror : V; bool draw = drawcell_subs(c, actualV(hs, V1)); @@ -1273,15 +1286,15 @@ void hrmap_standard::draw() { hstate s2 = transition(s, d); if(s2 == hsError) continue; heptspin hs2 = hs + d + wstep; - transmatrix Vd; + shiftmatrix Vd; if(inforder::mixed()) { int d1 = gmod(hs.spin+d, c->type); Vd = V * spin(-2*M_PI*d/c->type) * xpush(spacedist(c, d1)) * spin(M_PI); } else Vd = V * cgi.heptmove[d]; - bandfixer bf(Vd); - drawn_cells.emplace_back(hs2, s2, Vd, band_shift); + optimize_shift(Vd); + drawn_cells.emplace_back(hs2, s2, Vd); } } } @@ -1320,7 +1333,7 @@ EX void spinEdge(ld aspd) { else rotate_view(their * inverse(our)); } else if(playerfound && vid.fixed_facing) { - hyperpoint H = gpushxto0(playerV * C0) * playerV * xpush0(5); + hyperpoint H = gpushxto0(unshift(playerV) * C0) * unshift(playerV) * xpush0(5); downspin = atan2(H[1], H[0]); downspin += vid.fixed_facing_dir * degree; if(flipplayer) downspin += M_PI; @@ -1378,12 +1391,12 @@ EX void centerpc(ld aspd) { DEBBI(DF_GRAPH, ("center pc")); auto& W = current_display->which_copy; - ors::unrotate(W); ors::unrotate(View); ors::unrotate(cwtV); + ors::unrotate(W); ors::unrotate(View); ors::unrotate(cwtV.T); /* what should we center? */ transmatrix T; if(multi::players > 1) - T = cwtV; /* do not even try */ + T = unshift(cwtV); /* do not even try */ else { T = W; if(shmup::on) @@ -1410,27 +1423,27 @@ EX void centerpc(ld aspd) { spinEdge(aspd); fixmatrix(View); if(gmatrix.count(cwt.at)) - current_display->which_copy = gmatrix[cwt.at]; + current_display->which_copy = unshift(gmatrix[cwt.at]); } else { aspd *= euclid ? (2+3*R*R) : (1+R+(shmup::on?1:0)); - if(R < aspd && gmatrix.count(cwt.at) && eqmatrix(gmatrix[cwt.at], current_display->which_copy)) { - current_display->which_copy = gmatrix[cwt.at]; + if(R < aspd && gmatrix.count(cwt.at) && eqmatrix(unshift(gmatrix[cwt.at]), current_display->which_copy)) { + current_display->which_copy = unshift(gmatrix[cwt.at]); } if(R < aspd) - shift_view_to(H); + shift_view_to(shiftless(H)); else - shift_view_towards(H, aspd); + shift_view_towards(shiftless(H), aspd); fixmatrix(View); fixmatrix(current_display->which_copy); spinEdge(aspd); } - ors::rerotate(W); ors::rerotate(cwtV); ors::rerotate(View); + ors::rerotate(W); ors::rerotate(cwtV.T); ors::rerotate(View); } EX void optimizeview() { @@ -1470,7 +1483,7 @@ void ballgeometry() { addball(0, 0, -vid.camera); addball(0, -10, 0); addball(0, 0, -vid.camera); - queuecurve(darkena(0xFF, 0, 0x80), 0, PPR::CIRCLE); + queuecurve(shiftless(Id), darkena(0xFF, 0, 0x80), 0, PPR::CIRCLE); queuereset(pmodel, PPR::CIRCLE); } @@ -1512,7 +1525,7 @@ EX void resetview() { centerover = currentmap->gamestart(); View = Id; } - cwtV = View; + cwtV = shiftless(View); current_display->which_copy = nonisotropic ? gpushxto0(tC0(inverse(View))) : View; @@ -1521,7 +1534,9 @@ EX void resetview() { } -EX void panning(hyperpoint hf, hyperpoint ht) { +EX void panning(shiftpoint hf0, shiftpoint ht0) { + hyperpoint hf = hf0.h; + hyperpoint ht = unshift(ht0, hf0.shift); View = rgpushxto0(hf) * rgpushxto0(gpushxto0(hf) * ht) * gpushxto0(hf) * View; playermoved = false; @@ -1623,7 +1638,7 @@ void circle_around_center(ld radius, color_t linecol, color_t fillcol, PPR prio) #if CAP_QUEUE if(among(pmodel, mdDisk, mdEquiarea, mdEquidistant, mdFisheye) && !(pmodel == mdDisk && hyperbolic && pconf.alpha <= -1) && pconf.camera_angle == 0) { hyperpoint ret; - applymodel(xpush0(radius), ret); + applymodel(shiftless(xpush0(radius)), ret); ld r = hypot_d(2, ret); queuecircle(current_display->xcenter, current_display->ycenter, r * current_display->radius, linecol, prio, fillcol); return; @@ -1631,7 +1646,7 @@ void circle_around_center(ld radius, color_t linecol, color_t fillcol, PPR prio) #endif #if CAP_QUEUE for(int i=0; i<=360; i++) curvepoint(xspinpush0(i * degree, 10)); - auto& c = queuecurve(linecol, fillcol, prio); + auto& c = queuecurve(shiftless(Id), linecol, fillcol, prio); if(pmodel == mdDisk && hyperbolic && pconf.alpha <= -1) c.flags |= POLY_FORCE_INVERTED; if(pmodel == mdJoukowsky) @@ -1672,7 +1687,7 @@ EX void draw_model_elements() { models::apply_orientation_yz(res[2], res[1]); curvepoint(res * current_display->radius); } - queuecurve(ringcolor, 0, PPR::CIRCLE); + queuecurve(shiftless(Id), ringcolor, 0, PPR::CIRCLE); } queuereset(pmodel, PPR::CIRCLE); @@ -1681,8 +1696,8 @@ EX void draw_model_elements() { case mdTwoPoint: case mdSimulatedPerspective: { ld a = -pconf.model_orientation * degree; - queuestr(xspinpush0(a, +pconf.twopoint_param), vid.xres / 100, "X", ringcolor >> 8); - queuestr(xspinpush0(a, -pconf.twopoint_param), vid.xres / 100, "X", ringcolor >> 8); + queuestr(shiftless(xspinpush0(a, +pconf.twopoint_param)), vid.xres / 100, "X", ringcolor >> 8); + queuestr(shiftless(xspinpush0(a, -pconf.twopoint_param)), vid.xres / 100, "X", ringcolor >> 8); return; } @@ -1697,7 +1712,7 @@ EX void draw_model_elements() { #if CAP_QUEUE curvepoint(point3(0,0,1)); curvepoint(point3(0,0,-pconf.alpha)); - queuecurve(ringcolor, 0, PPR::CIRCLE); + queuecurve(shiftless(Id), ringcolor, 0, PPR::CIRCLE); ld& tz = pconf.top_z; ld z = acosh(tz); @@ -1715,11 +1730,11 @@ EX void draw_model_elements() { a[0] = -a[0]; curvepoint(a); curvepoint(point3(0,0,-pconf.alpha)); - queuecurve(ringcolor, 0, PPR::CIRCLE); + queuecurve(shiftless(Id), ringcolor, 0, PPR::CIRCLE); curvepoint(point3(-1,0,0)); curvepoint(point3(1,0,0)); - queuecurve(ringcolor, 0, PPR::CIRCLE); + queuecurve(shiftless(Id), ringcolor, 0, PPR::CIRCLE); a[1] = sb * tz / -cb; a[0] = sqrt(tz * tz - a[1] * a[1]); @@ -1729,7 +1744,7 @@ EX void draw_model_elements() { curvepoint(point3(0,0,-pconf.alpha)); a[0] = -a[0]; curvepoint(a); - queuecurve(ringcolor, 0, PPR::CIRCLE); + queuecurve(shiftless(Id), ringcolor, 0, PPR::CIRCLE); #endif } return; @@ -1742,7 +1757,7 @@ EX void draw_model_elements() { void queuestraight(hyperpoint X, int style, color_t lc, color_t fc, PPR p) { hyperpoint H0, H1; - applymodel(X, H0); + applymodel(shiftless(X), H0); H0 *= current_display->radius; ld mul0 = hypot(vid.xres, vid.yres) / hypot_d(2, H0); @@ -1750,7 +1765,7 @@ void queuestraight(hyperpoint X, int style, color_t lc, color_t fc, PPR p) { H1 = H0 * -mul0; } else { - applymodel(pispin * X, H1); + applymodel(shiftless(pispin * X), H1); H1 *= current_display->radius; } @@ -1763,7 +1778,7 @@ void queuestraight(hyperpoint X, int style, color_t lc, color_t fc, PPR p) { curvepoint(H1 - spin(M_PI/2) * H1 * mul1); curvepoint(H0 + spin(M_PI/2) * H0 * mul0); - queuecurve(lc, fc, p).flags |= POLY_ALWAYS_IN | POLY_FORCEWIDE; + queuecurve(shiftless(Id), lc, fc, p).flags |= POLY_ALWAYS_IN | POLY_FORCEWIDE; queuereset(pmodel, p); /* for(int i=0; i<1; i++) { @@ -1812,7 +1827,7 @@ EX void draw_boundary(int w) { ld z = -sqrt(1 - x*x); models::apply_orientation(y, x); hyperpoint h1; - applymodel(hpxyz(x,y,z), h1); + applymodel(shiftless(hpxyz(x,y,z)), h1); models::apply_orientation(h1[0], h1[1]); h1[1] = abs(h1[1]) * b; @@ -1820,7 +1835,7 @@ EX void draw_boundary(int w) { curvepoint(h1); } - queuecurve(lc, fc, p).flags |= POLY_FORCEWIDE; + queuecurve(shiftless(Id), lc, fc, p).flags |= POLY_FORCEWIDE; queuereset(pmodel, p); return; } @@ -1846,7 +1861,7 @@ EX void draw_boundary(int w) { curvepoint(T * xpush(-xperiod) * ypush0(-a * adegree)); } curvepoint(T * xpush(xperiod) * ypush0(-90 * adegree)); - queuecurve(periodcolor, 0, PPR::CIRCLE).flags |= POLY_FORCEWIDE; + queuecurve(shiftless(Id), periodcolor, 0, PPR::CIRCLE).flags |= POLY_FORCEWIDE; } return; } @@ -1865,7 +1880,7 @@ EX void draw_boundary(int w) { ld s = sin(i * degree); curvepoint(point3(current_display->radius * cos(i * degree), current_display->radius * s * (models::cos_ball * s >= 0 - 1e-6 ? 1 : abs(models::sin_ball)), 0)); } - queuecurve(lc, fc, p); + queuecurve(shiftless(Id), lc, fc, p); queuereset(pmodel, p); p = PPR::CIRCLE; fc = 0; queuereset(mdPixel, p); @@ -1874,7 +1889,7 @@ EX void draw_boundary(int w) { ld s = sin(i * degree); curvepoint(point3(current_display->radius * cos(i * degree), current_display->radius * s * models::sin_ball, 0)); } - queuecurve(lc, fc, p); + queuecurve(shiftless(Id), lc, fc, p); queuereset(pmodel, p); } if(euclid || sphere) { @@ -1882,7 +1897,7 @@ EX void draw_boundary(int w) { for(int i=0; i<=360; i++) { curvepoint(point3(current_display->radius * cos(i * degree), current_display->radius * sin(i * degree), 0)); } - queuecurve(lc, fc, p); + queuecurve(shiftless(Id), lc, fc, p); queuereset(pmodel, p); } return; @@ -1928,14 +1943,14 @@ EX void draw_boundary(int w) { curvepoint(xspinpush0(+M_PI/2 - t * alpha, mz)); } - queuecurve(lc, fc, p); + queuecurve(shiftless(Id), lc, fc, p); fc = 0; p = PPR::CIRCLE; } for(ld t=0; t<=360; t ++) curvepoint(xspinpush0(t * degree, mz)); - queuecurve(lc, fc, p); + queuecurve(shiftless(Id), lc, fc, p); } return; } @@ -1955,7 +1970,7 @@ EX void draw_boundary(int w) { ret *= current_display->radius; curvepoint(ret); } - queuecurve(ringcolor, 0, p).flags |= POLY_ALWAYS_IN; + queuecurve(shiftless(Id), ringcolor, 0, p).flags |= POLY_ALWAYS_IN; queuereset(pmodel, p); } return; @@ -1975,11 +1990,59 @@ EX void draw_boundary(int w) { } #endif -EX ld band_shift = 0; -EX void fix_the_band(transmatrix& T) { - if(((mdinf[pmodel].flags & mf::uses_bandshift) && T[LDIM][LDIM] > 1e6) || (sphere && pmodel == mdSpiral)) { - T = spin(pconf.model_orientation * degree) * T; - hyperpoint H = tC0(T); +EX void change_shift(shiftpoint& h, ld by) { + h.shift += by; + if((mdinf[pmodel].flags & mf::uses_bandshift) || (sphere && pmodel == mdSpiral)) { + h.h = spin(pconf.model_orientation * degree) * h.h; + h.h = xpush(-by) * h.h; + h.h = spin(-pconf.model_orientation * degree) * h.h; + } + if(sl2) { + ld ca = cos(by), sa = sin(by); + tie(h[2], h[3]) = make_pair(h[2] * ca - h[3] * sa, h[3] * ca + h[2] * sa); + tie(h[0], h[1]) = make_pair(h[0] * ca - h[1] * sa, h[1] * ca + h[0] * sa); + } + } + +EX void change_shift(shiftmatrix& T, ld by) { + T.shift += by; + if((mdinf[pmodel].flags & mf::uses_bandshift) || (sphere && pmodel == mdSpiral)) { + T.T = spin(pconf.model_orientation * degree) * T.T; + T.T = xpush(-by) * T.T; + fixmatrix(T.T); + T.T = spin(-pconf.model_orientation * degree) * T.T; + } + if(sl2) { + ld ca = cos(by), sa = sin(by); + for(int a=0; a<4; a++) { + tie(T[2][a], T[3][a]) = make_pair(T[2][a] * ca - T[3][a] * sa, T[3][a] * ca + T[2][a] * sa); + tie(T[0][a], T[1][a]) = make_pair(T[0][a] * ca - T[1][a] * sa, T[1][a] * ca + T[0][a] * sa); + } + } + } + +EX transmatrix unshift(shiftmatrix T, ld to IS(0)) { + change_shift(T, to - T.shift); + return T.T; + } + +EX hyperpoint unshift(shiftpoint T, ld to IS(0)) { + change_shift(T, to - T.shift); + return T.h; + } + +EX transmatrix inverse_shift(const shiftmatrix& T1, const shiftmatrix& T2) { + return inverse(T1.T) * unshift(T2, T1.shift); + } + +EX hyperpoint inverse_shift(const shiftmatrix& T1, const shiftpoint& T2) { + return inverse(T1.T) * unshift(T2, T1.shift); + } + +EX void optimize_shift(shiftmatrix& T) { + if(((mdinf[pmodel].flags & mf::uses_bandshift) && T[LDIM][LDIM] > 1e6) || (sphere && pmodel == mdSpiral)) { + T.T = spin(pconf.model_orientation * degree) * T.T; + hyperpoint H = tC0(T.T); find_zlev(H); ld y = asin_auto(H[1]); @@ -1988,54 +2051,68 @@ EX void fix_the_band(transmatrix& T) { if(H[LDIM] < 0 && x > 0) x = M_PI - x; else if(H[LDIM] < 0 && x <= 0) x = -M_PI - x; } - band_shift += x; - T = xpush(-x) * T; - fixmatrix(T); - T = spin(-pconf.model_orientation * degree) * T; + T.shift += x; + T.T = xpush(-x) * T.T; + fixmatrix(T.T); + T.T = spin(-pconf.model_orientation * degree) * T.T; + } + + if(sl2) { + change_shift(T, atan2(T[2][3], T[3][3])); + if(hybrid::csteps) { + auto period = (M_PI * hybrid::csteps) / cgi.psl_steps; + while(T.shift > period*.4999) + T.shift -= period; + while(T.shift < -period*.5001) + T.shift += period; + } } } -#if HDR -struct bandfixer { - dynamicval bw; - bandfixer(transmatrix& T) : bw(band_shift, band_shift) { fix_the_band(T); } - }; -#endif +EX shiftmatrix optimized_shift(const shiftmatrix& T) { + shiftmatrix U = T; + optimize_shift(U); + return U; + } EX namespace dq { - EX queue> drawqueue; + EX queue> drawqueue; + + EX unsigned bucketer(const shiftpoint& T) { + return bucketer(T.h) + unsigned(floor(T.shift*81527+.5)); + } EX set visited; - EX void enqueue(heptagon *h, const transmatrix& T) { + EX void enqueue(heptagon *h, const shiftmatrix& T) { if(!h || visited.count(h)) { return; } visited.insert(h); - drawqueue.emplace(h, T, band_shift); + drawqueue.emplace(h, T); } - EX set visited_by_matrix; - EX void enqueue_by_matrix(heptagon *h, const transmatrix& T) { + EX set visited_by_matrix; + EX void enqueue_by_matrix(heptagon *h, const shiftmatrix& T) { if(!h) return; - int b = bucketer(tC0(T)) + int(floor(band_shift*81527+.5)); + unsigned b = bucketer(tC0(T)); if(visited_by_matrix.count(b)) { return; } visited_by_matrix.insert(b); - drawqueue.emplace(h, T, band_shift); + drawqueue.emplace(h, T); } - EX queue> drawqueue_c; + EX queue> drawqueue_c; EX set visited_c; - EX void enqueue_c(cell *c, const transmatrix& T) { + EX void enqueue_c(cell *c, const shiftmatrix& T) { if(!c || visited_c.count(c)) { return; } visited_c.insert(c); - drawqueue_c.emplace(c, T, band_shift); + drawqueue_c.emplace(c, T); } - EX void enqueue_by_matrix_c(cell *c, const transmatrix& T) { + EX void enqueue_by_matrix_c(cell *c, const shiftmatrix& T) { if(!c) return; - unsigned b = bucketer(tC0(T)) + int(floor(band_shift*81527+.5)); + unsigned b = bucketer(tC0(T)); if(visited_by_matrix.count(b)) { return; } visited_by_matrix.insert(b); - drawqueue_c.emplace(c, T, band_shift); + drawqueue_c.emplace(c, T); } EX void clear_all() { @@ -2072,7 +2149,7 @@ bool limited_generation(cell *c) { return true; } -EX bool do_draw(cell *c, const transmatrix& T) { +EX bool do_draw(cell *c, const shiftmatrix& T) { if(WDIM == 3) { // do not care about cells outside of the track @@ -2086,7 +2163,7 @@ EX bool do_draw(cell *c, const transmatrix& T) { if(dist <= extra_generation_distance && !limited_generation(c)) return false; } else if(pmodel == mdGeodesic && sol) { - if(!nisot::in_table_range(tC0(T))) return false; + if(!nisot::in_table_range(tC0(T.T))) return false; if(!limited_generation(c)) return false; } else if(pmodel == mdGeodesic && nih) { @@ -2096,8 +2173,8 @@ EX bool do_draw(cell *c, const transmatrix& T) { if(dist <= extra_generation_distance && !limited_generation(c)) return false; } else if(pmodel == mdGeodesic && sl2) { - if(hypot(tC0(T)[2], tC0(T)[3]) > cosh(slr::range_xy)) return false; - if(band_shift * stretch::not_squared() > sightranges[geometry]) return false; + if(hypot(tC0(T.T)[2], tC0(T.T)[3]) > cosh(slr::range_xy)) return false; + if(T.shift * stretch::not_squared() > sightranges[geometry]) return false; if(!limited_generation(c)) return false; } else if(vid.use_smart_range) { @@ -2105,7 +2182,7 @@ EX bool do_draw(cell *c, const transmatrix& T) { if(!limited_generation(c)) return false; } else { - ld dist = hdist0(tC0(T)); + ld dist = hdist0(tC0(T.T)); if(dist > sightranges[geometry] + (vid.sloppy_3d ? 0 : cgi.corner_bonus)) return false; if(dist <= extra_generation_distance && !limited_generation(c)) return false; } @@ -2115,7 +2192,7 @@ EX bool do_draw(cell *c, const transmatrix& T) { if(just_gmatrix && sphere) return true; if(!do_draw(c)) return false; if(euclid && pmodel == mdSpiral) { - hyperpoint h = tC0(T); + hyperpoint h = tC0(T.T); cld z(h[0], h[1]); z = z * models::spiral_multiplier; ld iz = imag(z) + 1.14279e-2; // make it never fall exactly on PI @@ -2123,7 +2200,7 @@ EX bool do_draw(cell *c, const transmatrix& T) { } if(pmodel == mdSpiral && models::ring_not_spiral) { cld z; - hyperpoint H = tC0(T); + shiftpoint H = tC0(T); hyperpoint ret; makeband(H, ret, band_conformal); z = cld(ret[0], ret[1]) * models::spiral_multiplier; @@ -2136,10 +2213,10 @@ EX bool do_draw(cell *c, const transmatrix& T) { return true; } -EX int cone_side(const hyperpoint H) { +EX int cone_side(const shiftpoint H) { hyperpoint ret; if(hyperbolic) makeband(H, ret, band_conformal); - else ret = H; + else ret = unshift(H); cld z = cld(ret[0], ret[1]) * models::spiral_multiplier; auto zth = [&] (cld z) { @@ -2217,16 +2294,16 @@ void multiply_view(transmatrix T) { wc = T * wc; } -EX void shift_view_to(hyperpoint H) { - if(!nonisotropic) multiply_view(gpushxto0(H)); +EX void shift_view_to(shiftpoint H) { + if(!nonisotropic) multiply_view(gpushxto0(unshift(H))); else shift_view(-inverse_exp(H)); } -EX void shift_view_towards(hyperpoint H, ld l) { +EX void shift_view_towards(shiftpoint H, ld l) { if(!nonisotropic && !prod) - multiply_view(rspintox(H) * xpush(-l) * spintox(H)); + multiply_view(rspintox(unshift(H)) * xpush(-l) * spintox(unshift(H))); else if(nonisotropic && !nisot::geodesic_movement) - shift_view(tangent_length(H-C0, -l)); + shift_view(tangent_length(unshift(H)-C0, -l)); else { hyperpoint ie = inverse_exp(H, pNORMAL | pfNO_DISTANCE); if(prod) ie = lp_apply(ie); diff --git a/inventory.cpp b/inventory.cpp index 6ac1c6b1..07169008 100644 --- a/inventory.cpp +++ b/inventory.cpp @@ -536,7 +536,7 @@ EX namespace inv { if(gg) { initquickqueue(); transmatrix V = atscreenpos(px, py, rad*2); - drawItemType(o, NULL, V, icol, ticks/3 + i * 137, false); + drawItemType(o, NULL, shiftless(V), icol, ticks/3 + i * 137, false); quickqueue(); } diff --git a/irregular.cpp b/irregular.cpp index 75750737..cb0239f8 100644 --- a/irregular.cpp +++ b/irregular.cpp @@ -552,7 +552,7 @@ EX void compute_geometry() { } } -bool draw_cell_schematics(cell *c, transmatrix V) { +bool draw_cell_schematics(cell *c, const shiftmatrix& V) { if(gridmaking) { heptagon *h = c->master; for(int i: cells_of_heptagon[h]) { diff --git a/kite.cpp b/kite.cpp index adc2fa6f..2dccb8d4 100644 --- a/kite.cpp +++ b/kite.cpp @@ -327,7 +327,7 @@ struct hrmap_kite : hrmap { transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) override { if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) - return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7]; + return inverse_shift(gmatrix0[h1->c7], gmatrix0[h2->c7]); transmatrix gm = Id, where = Id; while(h1 != h2) { if(h1->distance <= h2->distance) @@ -345,15 +345,13 @@ struct hrmap_kite : hrmap { void draw() override { - dq::visited.clear(); + dq::clear_all(); dq::enqueue(centerover->master, cview()); while(!dq::drawqueue.empty()) { auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); - bandfixer bf(V); + heptagon *h = p.first; + shiftmatrix V = p.second; dq::drawqueue.pop(); cell *c = h->c7; @@ -361,7 +359,7 @@ struct hrmap_kite : hrmap { drawcell(c, V); for(int i=0; itype; i++) - dq::enqueue(c->cmove(i)->master, V * adj(c, i)); + dq::enqueue(c->cmove(i)->master, optimized_shift(V * adj(c, i))); /* ld err = hdist(where[h->c7->cmove(i)->master] * C0, where[h] * M * C0); if(err > -.01) diff --git a/mapeditor.cpp b/mapeditor.cpp index 8f0da82f..95034870 100644 --- a/mapeditor.cpp +++ b/mapeditor.cpp @@ -30,7 +30,7 @@ EX namespace mapeditor { virtual void rotate(const transmatrix& T) = 0; virtual void save(hstream& hs) = 0; virtual dtshape* load(hstream& hs) = 0; - virtual void draw(const transmatrix& V) = 0; + virtual void draw(const shiftmatrix& V) = 0; virtual ld distance(hyperpoint h) = 0; virtual ~dtshape() {} }; @@ -53,7 +53,7 @@ EX namespace mapeditor { hs.read(e); return this; } - void draw(const transmatrix& V) override { + void draw(const shiftmatrix& V) override { queueline(V*s, V*e, col, 2 + vid.linequality); } ld distance(hyperpoint h) override { @@ -78,13 +78,13 @@ EX namespace mapeditor { hs.read(radius); return this; } - void draw(const transmatrix& V) override { + void draw(const shiftmatrix& V) override { ld len = sin_auto(radius); int ll = ceil(360 * len); - transmatrix W = V * rgpushxto0(s); + shiftmatrix W = V * rgpushxto0(s); for(int i=0; i<=ll; i++) - curvepoint(W * xspinpush0(360*degree*i/ll, radius)); - queuecurve(col, fill, PPR::LINE); + curvepoint(xspinpush0(360*degree*i/ll, radius)); + queuecurve(W, col, fill, PPR::LINE); } ld distance(hyperpoint h) override { @@ -115,7 +115,7 @@ EX namespace mapeditor { return this; } - void draw(const transmatrix& V) override { + void draw(const shiftmatrix& V) override { queuestr(V * rgpushxto0(where), size, caption, col); } @@ -139,9 +139,9 @@ EX namespace mapeditor { hs.read(lh); return this; } - void draw(const transmatrix& V) override { - for(auto& p: lh) curvepoint(V*p); - queuecurve(col, fill, PPR::LINE); + void draw(const shiftmatrix& V) override { + for(auto& p: lh) curvepoint(p); + queuecurve(V, col, fill, PPR::LINE); } ld distance(hyperpoint h) override { @@ -160,7 +160,7 @@ EX namespace mapeditor { if(shp == nullptr) continue; auto& sh = *shp; cell*& c = sh.where; - for(const transmatrix& V: current_display->all_drawn_copies[c]) { + for(const shiftmatrix& V: current_display->all_drawn_copies[c]) { dynamicval lw(vid.linewidth, vid.linewidth * sh.lw); sh.draw(V); } @@ -173,7 +173,7 @@ EX namespace mapeditor { else if(holdmouse && mousekey == 'l') queueline(lstart, mouseh, dtcolor, 4 + vid.linequality, PPR::LINE); else if(!holdmouse) { - transmatrix T = rgpushxto0(mouseh); + shiftmatrix T = rgpushxto0(mouseh); queueline(T * xpush0(-.1), T * xpush0(.1), dtcolor); queueline(T * ypush0(-.1), T * ypush0(.1), dtcolor); } @@ -190,47 +190,46 @@ EX namespace mapeditor { dtshapes.push_back(unique_ptr(sh)); } - EX void dt_add_line(hyperpoint h1, hyperpoint h2, int maxl) { + EX void dt_add_line(shiftpoint h1, shiftpoint h2, int maxl) { if(hdist(h1, h2) > 1 && maxl > 0) { - hyperpoint h3 = mid(h1, h2); + shiftpoint h3 = mid(h1, h2); dt_add_line(h1, h3, maxl-1); dt_add_line(h3, h2, maxl-1); return; } cell *b = centerover; - transmatrix T = rgpushxto0(h1); - auto T1 = inverse(ggmatrix(b)) * T; - virtualRebase(b, T1); + auto xh1 = inverse_shift(ggmatrix(b), h1); + virtualRebase(b, xh1); auto l = new dtline; - l->s = tC0(T1); - l->e = T1 * gpushxto0(h1) * h2; + l->s = xh1; + l->e = inverse_shift(ggmatrix(b), h2); dt_add(b, l); } - EX void dt_add_circle(hyperpoint h1, hyperpoint h2) { + EX void dt_add_circle(shiftpoint h1, shiftpoint h2) { cell *b = centerover; auto d = hdist(h1, h2); - h1 = inverse(ggmatrix(b)) * h1; - virtualRebase(b, h1); + auto xh1 = inverse_shift(ggmatrix(b), h1); + virtualRebase(b, xh1); auto l = new dtcircle; - l->s = h1; + l->s = xh1; l->radius = d; dt_add(b, l); } - EX void dt_add_text(hyperpoint h, ld size, string cap) { + EX void dt_add_text(shiftpoint h, ld size, string cap) { cell *b = centerover; - h = inverse(ggmatrix(b)) * h; - virtualRebase(b, h); + auto xh = inverse_shift(ggmatrix(b), h); + virtualRebase(b, xh); auto l = new dttext; - l->where = h; + l->where = xh; l->size = size; l->caption = cap; dt_add(b, l); @@ -257,26 +256,26 @@ EX namespace mapeditor { cell *cfree_at; transmatrix cfree_T; - EX void dt_add_free(hyperpoint h) { + EX void dt_add_free(shiftpoint h) { cell *b = centerover; - transmatrix T = rgpushxto0(h); - auto T1 = inverse(ggmatrix(b)) * T; + shiftmatrix T = rgpushxto0(h); + auto T1 = inverse_shift(ggmatrix(b), T); virtualRebase(b, T1); if(cfree) - cfree->lh.push_back(cfree_T * h); + cfree->lh.push_back(cfree_T * h.h); if(b != cfree_at && !(dtfill && cfree_at)) { cfree = new dtfree; dt_add(b, cfree); - cfree_T = T1 * gpushxto0(h); - cfree->lh.push_back(cfree_T * h); + cfree_T = T1 * gpushxto0(h.h); + cfree->lh.push_back(cfree_T * h.h); cfree_at = b; } } - EX void dt_erase(hyperpoint h) { + EX void dt_erase(shiftpoint h) { ld nearest = 1; int nearest_id = -1; int id = -1; @@ -285,8 +284,8 @@ EX namespace mapeditor { if(shp == nullptr) continue; auto& sh = *shp; cell*& c = sh.where; - for(const transmatrix& V: current_display->all_drawn_copies[c]) { - ld dist = sh.distance(inverse(V) * h); + for(const shiftmatrix& V: current_display->all_drawn_copies[c]) { + ld dist = sh.distance(inverse_shift(V, h)); if(dist < nearest) nearest = dist, nearest_id = id; } } @@ -294,7 +293,7 @@ EX namespace mapeditor { dtshapes.erase(dtshapes.begin() + nearest_id); } - EX hyperpoint lstart; + EX shiftpoint lstart; cell *lstartcell; ld front_edit = 0.5; enum class eFront { sphere_camera, sphere_center, equidistants, const_x, const_y }; @@ -1480,7 +1479,7 @@ namespace mapeditor { // fake key sent to change the color static const int COLORKEY = (-10000); - EX transmatrix drawtrans, drawtransnew; + EX shiftmatrix drawtrans, drawtransnew; #if CAP_POLY void loadShape(int sg, int id, hpcshape& sh, int d, int layer) { @@ -1492,7 +1491,7 @@ namespace mapeditor { } #endif - EX void drawGhosts(cell *c, const transmatrix& V, int ct) { + EX void drawGhosts(cell *c, const shiftmatrix& V, int ct) { if(!(cmode & sm::MAP)) return; if(darken != 0) return; if(GDIM == 2 && mouseout()) return; @@ -1510,33 +1509,33 @@ namespace mapeditor { unsigned gridcolor = 0xC0C0C040; - hyperpoint in_front_dist(ld d) { - return direct_exp(lp_iapply(ztangent(d))); + shiftpoint in_front_dist(ld d) { + return shiftless(direct_exp(lp_iapply(ztangent(d)))); /* todo direct_shift */ } - hyperpoint find_mouseh3() { + shiftpoint find_mouseh3() { if(front_config == eFront::sphere_camera) return in_front_dist(front_edit); ld step = 0.01; ld cdist = 0; - auto idt = inverse(drawtrans); + auto idt = inverse(unshift(drawtrans)); - auto qu = [&] (ld d) { + auto qu = [&] (ld d) { ld d1 = front_edit; - hyperpoint h1 = in_front_dist(d); + shiftpoint h1 = in_front_dist(d); if(front_config == eFront::sphere_center) d1 = geo_dist(drawtrans * C0, h1); if(front_config == eFront::equidistants) { - hyperpoint h = idt * in_front_dist(d); + hyperpoint h = idt * unshift(in_front_dist(d)); d1 = asin_auto(h[2]); } if(front_config == eFront::const_x) { - hyperpoint h = idt * in_front_dist(d); + hyperpoint h = idt * unshift(in_front_dist(d)); d1 = asin_auto(h[0]); } if(front_config == eFront::const_y) { - hyperpoint h = idt * in_front_dist(d); + hyperpoint h = idt * unshift(in_front_dist(d)); d1 = asin_auto(h[1]); } return pow(d1 - front_edit, 2); @@ -1558,29 +1557,29 @@ namespace mapeditor { if(!drawcell) drawcell = cwt.at; color_t lightgrid = gridcolor; lightgrid -= (lightgrid & 0xFF) / 2; - transmatrix d2 = drawtrans * rgpushxto0(ccenter) * rspintox(gpushxto0(ccenter) * coldcenter); + shiftmatrix d2 = drawtrans * rgpushxto0(ccenter) * rspintox(gpushxto0(ccenter) * coldcenter); if(GDIM == 3) { queuecircleat(mapeditor::drawcell, 1, 0x80D080FF); color_t cols[4] = { 0x80D080FF, 0x80D080FF, 0xFFFFFF40, 0x00000040 }; if(true) { - transmatrix t = rgpushxto0(find_mouseh3()); + shiftmatrix t = rgpushxto0(find_mouseh3()); for(int i=0; i<4; i++) queueline(t * cpush0(i&1, 0.1), t * cpush0(i&1, -0.1), cols[i], -1, i < 2 ? PPR::LINE : PPR::SUPERLINE); } if(front_config == eFront::sphere_center) for(int i=0; i<4; i+=2) { auto pt = [&] (ld a, ld b) { - return d2 * direct_exp(spin(a*degree) * cspin(0, 2, b*degree) * xtangent(front_edit)); + return direct_exp(spin(a*degree) * cspin(0, 2, b*degree) * xtangent(front_edit)); }; for(int ai=0; aitype) != 0)], 0, i < 2 ? PPR::LINE : PPR::SUPERLINE); + for(int u=0; u<=20; u++) curvepoint(T * xspinpush(M_PI*d/cgi.S42, u/20.) * zpush(front_edit) * C0); + queuecurve(d2, cols[i + (d % (cgi.S84/drawcell->type) != 0)], 0, i < 2 ? PPR::LINE : PPR::SUPERLINE); } } return; @@ -1609,9 +1608,9 @@ namespace mapeditor { } for(int u=2; u<=20; u++) { PRING(d) { - curvepoint(d2 * xspinpush0(M_PI*d/cgi.S42, u/20.)); + curvepoint(xspinpush0(M_PI*d/cgi.S42, u/20.)); } - queuecurve((u%5==0) ? gridcolor : lightgrid, 0, PPR::LINE); + queuecurve(d2, (u%5==0) ? gridcolor : lightgrid, 0, PPR::LINE); } queueline(drawtrans*ccenter, drawtrans*coldcenter, gridcolor, 4 + vid.linequality); } @@ -1844,18 +1843,18 @@ namespace mapeditor { if(!mouseout()) { hyperpoint mh; if(GDIM == 2) { - transmatrix T = inverse(drawtrans * rgpushxto0(ccenter)); - mh = spintox(gpushxto0(ccenter) * coldcenter) * T * mouseh; + transmatrix T = inverse(unshift(drawtrans)) * rgpushxto0(ccenter); /* todo? */ + mh = spintox(gpushxto0(ccenter) * coldcenter) * T * unshift(mouseh); } else - mh = inverse(drawtrans) * find_mouseh3(); + mh = inverse_shift(drawtrans, find_mouseh3()); displayfr(vid.xres-8, vid.yres-8-fs*7, 2, vid.fsize, XLAT("x: %1", fts(mh[0],4)), 0xC0C0C0, 16); displayfr(vid.xres-8, vid.yres-8-fs*6, 2, vid.fsize, XLAT("y: %1", fts(mh[1],4)), 0xC0C0C0, 16); displayfr(vid.xres-8, vid.yres-8-fs*5, 2, vid.fsize, XLAT("z: %1", fts(mh[2],4)), 0xC0C0C0, 16); if(MDIM == 4) displayfr(vid.xres-8, vid.yres-8-fs*4, 2, vid.fsize, XLAT("w: %1", fts(mh[3],4)), 0xC0C0C0, 16); - mh = inverse_exp(mh); + mh = inverse_exp(shiftless(mh)); displayfr(vid.xres-8, vid.yres-8-fs*3, 2, vid.fsize, XLAT("r: %1", fts(hypot_d(3, mh),4)), 0xC0C0C0, 16); if(GDIM == 3) { displayfr(vid.xres-8, vid.yres-8-fs, 2, vid.fsize, XLAT("ϕ: %1°", fts(-atan2(mh[2], hypot_d(2, mh)) / degree,4)), 0xC0C0C0, 16); @@ -1891,17 +1890,18 @@ namespace mapeditor { dynamicval ws(mmspatial, false); + auto sId = shiftless(Id); if(sg == 0) { - multi::cpid = id, drawMonsterType(moPlayer, drawcell, Id, 0xC0C0C0, 0, 0xC0C0C0); + multi::cpid = id, drawMonsterType(moPlayer, drawcell, sId, 0xC0C0C0, 0, 0xC0C0C0); } else if(sg == 1) { - drawMonsterType(eMonster(id), drawcell, Id, minf[id].color, 0, minf[id].color); + drawMonsterType(eMonster(id), drawcell, sId, minf[id].color, 0, minf[id].color); } else if(sg == 2) { - drawItemType(eItem(id), drawcell, Id, iinf[id].color, 0, false); + drawItemType(eItem(id), drawcell, sId, iinf[id].color, 0, false); } else { - draw_qfi(drawcell, Id, 0, PPR::FLOOR); + draw_qfi(drawcell, sId, 0, PPR::FLOOR); } sortquickqueue(); @@ -1933,7 +1933,7 @@ namespace mapeditor { int d = dsCur->rots * (dsCur->sym ? 2 : 1); for(int i=0; i < cnt/d; i++) - dsCur->list.push_back(ptd.V * glhr::gltopoint((*ptd.tab)[i+ptd.offset])); + dsCur->list.push_back(unshift(ptd.V) * glhr::gltopoint((*ptd.tab)[i+ptd.offset])); layer++; if(layer == USERLAYERS) break; @@ -2238,12 +2238,12 @@ namespace mapeditor { addMessage(XLAT("Hint: use F7 to edit floor under the player")); } - hyperpoint mh = GDIM == 2 ? mouseh : find_mouseh3(); - mh = inverse(drawtrans) * mh; + shiftpoint mh = GDIM == 2 ? mouseh : find_mouseh3(); + hyperpoint mh1 = inverse_shift(drawtrans, mh); bool clickused = false; - if((uni == 'p' && mousekey == 'g') || (uni == 'g' && coldcenter == ccenter && ccenter == mh)) { + if((uni == 'p' && mousekey == 'g') || (uni == 'g' && coldcenter == ccenter && ccenter == mh1)) { static unsigned grid_colors[] = { 8, 0x00000040, @@ -2262,7 +2262,7 @@ namespace mapeditor { char mkuni = uni == '-' ? mousekey : uni; if(mkuni == 'g') - coldcenter = ccenter, ccenter = mh, clickused = true; + coldcenter = ccenter, ccenter = mh1, clickused = true; if(uni == 'd' || uni == 'l' || uni == 'c' || uni == 'e' || uni == 'T') mousekey = uni; @@ -2413,7 +2413,7 @@ namespace mapeditor { ld rad = hdist(lstart, mouseh); int circp = int(1 + 3 * (circlelength(rad) / dtwidth)); if(circp > 1000) circp = 1000; - transmatrix T = rgpushxto0(lstart); + shiftmatrix T = rgpushxto0(lstart); texture::where = lstartcell; for(int i=0; i pts; int circp = int(6 * pow(2, vid.linequality)); if(radius > 0.04) circp *= 2; if(radius > .1) circp *= 2; for(int j=0; jtype; i += sih.symmetries) { - transmatrix M2 = V * applyPatterndir(c, sih) * spin(2*M_PI*i/c->type); + shiftmatrix M2 = V * applyPatterndir(c, sih) * spin(2*M_PI*i/c->type); if(j) M2 = M2 * Mirror; switch(holdmouse ? mousekey : 'd') { case 'c': @@ -2629,7 +2629,7 @@ namespace mapeditor { #endif #if CAP_POLY - EX bool drawUserShape(const transmatrix& V, eShapegroup group, int id, color_t color, cell *c, PPR prio IS(PPR::DEFAULT)) { + EX bool drawUserShape(const shiftmatrix& V, eShapegroup group, int id, color_t color, cell *c, PPR prio IS(PPR::DEFAULT)) { #if !CAP_EDIT return false; #else @@ -2686,37 +2686,37 @@ namespace mapeditor { usershapelayer &ds(us->d[mapeditor::dslayer]); - hyperpoint mh = inverse(mapeditor::drawtrans) * mouseh; + hyperpoint mh = inverse_shift(mapeditor::drawtrans, mouseh); for(int a=0; aradius, a*current_display->radius)); curvepoint(point2(+M_PI/2 * current_display->radius, a*current_display->radius)); - queuecurve(forecolor, 0, PPR::LINE); + queuecurve(shiftless(Id), forecolor, 0, PPR::LINE); curvepoint(point2(a*current_display->radius, -M_PI/2*current_display->radius)); curvepoint(point2(a*current_display->radius, +M_PI/2*current_display->radius)); - queuecurve(forecolor, 0, PPR::LINE); + queuecurve(shiftless(Id), forecolor, 0, PPR::LINE); } queuereset(vpconf.model, PPR::LINE); quickqueue(); diff --git a/multi.cpp b/multi.cpp index 871be4b5..2b8d3525 100644 --- a/multi.cpp +++ b/multi.cpp @@ -55,8 +55,8 @@ EX namespace multi { } } - EX transmatrix whereis[MAXPLAYER]; - EX transmatrix crosscenter[MAXPLAYER]; + EX shiftmatrix whereis[MAXPLAYER]; + EX shiftmatrix crosscenter[MAXPLAYER]; EX double ccdist[MAXPLAYER]; EX cell *ccat[MAXPLAYER]; @@ -804,7 +804,7 @@ EX void handleInput(int delta) { EX void handleMulti(int delta) { multi::handleInput(delta); - transmatrix bcwtV = cwtV; + shiftmatrix bcwtV = cwtV; cellwalker bcwt = cwt; bool alldecided = !needinput; diff --git a/multigame.cpp b/multigame.cpp index e1fc9935..0f4b853a 100644 --- a/multigame.cpp +++ b/multigame.cpp @@ -151,9 +151,11 @@ EX namespace dual { EX transmatrix get_orientation() { if(WDIM == 2) - return gpushxto0(tC0(cwtV)) * cwtV; - else if(cwt.at) - return gpushxto0(tC0(ggmatrix(cwt.at))) * ggmatrix(cwt.at) * sword::dir[0].T; + return gpushxto0(tC0(cwtV.T)) * cwtV.T; + else if(cwt.at) { + transmatrix T = unshift(ggmatrix(cwt.at)); + return gpushxto0(tC0(T)) * T * sword::dir[0].T; + } else return Id; } diff --git a/netgen.cpp b/netgen.cpp index e4fc51f4..6f0bd0e6 100644 --- a/netgen.cpp +++ b/netgen.cpp @@ -264,7 +264,7 @@ EX namespace netgen { color_t& hqpixel(hyperpoint h) { int hx, hy, hs; - getcoord0(h, hx, hy, hs); + getcoord0(shiftless(h), hx, hy, hs); return qpixel(hqsurface, hx, hy); } @@ -657,7 +657,7 @@ EX namespace netgen { nei[i][e] >= 0 ? 0x808080 : 0xC0C0C0; - queueline(hvec(i, (e+ofs)%t), hvec(i, (e+1+ofs)%t), (col << 8) + 0xFF, 3); + queueline(shiftless(hvec(i, (e+ofs)%t)), shiftless(hvec(i, (e+1+ofs)%t)), (col << 8) + 0xFF, 3); } } quickqueue(); diff --git a/nonisotropic.cpp b/nonisotropic.cpp index 30ec91ea..687a8e00 100644 --- a/nonisotropic.cpp +++ b/nonisotropic.cpp @@ -439,7 +439,7 @@ EX namespace sn { virtual transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) override { for(int i=0; itype; i++) if(h1->move(i) == h2) return adjmatrix(i, h1->c.spin(i)); if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) - return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7]; + return inverse_shift(gmatrix0[h1->c7], gmatrix0[h2->c7]); transmatrix front = Id, back = Id; @@ -460,14 +460,14 @@ EX namespace sn { } void draw() override { - dq::visited.clear(); + dq::clear_all(); dq::enqueue(centerover->master, cview()); while(!dq::drawqueue.empty()) { auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); + heptagon *h = p.first; + shiftmatrix V = p.second; dq::drawqueue.pop(); cell *c = h->c7; @@ -939,14 +939,14 @@ EX namespace nilv { } void draw() override { - dq::visited_by_matrix.clear(); + dq::clear_all(); dq::enqueue_by_matrix(centerover->master, cview()); while(!dq::drawqueue.empty()) { auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); + heptagon *h = p.first; + shiftmatrix V = p.second; dq::drawqueue.pop(); cell *c = h->c7; @@ -1281,17 +1281,15 @@ EX namespace hybrid { void draw() override { cell* start = centerover; - band_shift = 0; - auto period = (M_PI * csteps) / cgi.psl_steps; - dq::visited_by_matrix.clear(); + dq::clear_all(); dq::enqueue_by_matrix_c(start, cview()); while(!dq::drawqueue_c.empty()) { auto& p = dq::drawqueue_c.front(); cell *c = get<0>(p); - transmatrix V = get<1>(p); - band_shift = get<2>(p); + + shiftmatrix V = get<1>(p); dq::drawqueue_c.pop(); if(!do_draw(c, V)) continue; @@ -1301,23 +1299,8 @@ EX namespace hybrid { for(int i=0; itype; i++) { cell *c1 = c->cmove(i); - transmatrix V1 = V * adj(c, i); - dynamicval bs(band_shift, band_shift); - if(sl2) { - ld alpha = atan2(V1[2][3], V1[3][3]); - band_shift += alpha; - ld ca = cos(alpha), sa = sin(alpha); - if(alpha) for(int a=0; a<4; a++) { - tie(V1[2][a], V1[3][a]) = make_pair(V1[2][a] * ca - V1[3][a] * sa, V1[3][a] * ca + V1[2][a] * sa); - tie(V1[0][a], V1[1][a]) = make_pair(V1[0][a] * ca - V1[1][a] * sa, V1[1][a] * ca + V1[0][a] * sa); - } - if(csteps) { - while(band_shift > period*.4999) - band_shift -= period; - while(band_shift < -period*.5001) - band_shift += period; - } - } + shiftmatrix V1 = V * adj(c, i); + optimize_shift(V1); dq::enqueue_by_matrix_c(c1, V1); } } @@ -1641,6 +1624,7 @@ EX namespace product { EX bool current_spin_invalid, cmirror; EX int cspin; + /* todo might need a shiftpoint version */ EX hyperpoint inverse_exp(hyperpoint h) { hyperpoint res; res[2] = zlevel(h); @@ -1756,9 +1740,9 @@ EX namespace slr { return hyperpoint(x * f * cos(z) + y * f * sin(z), y * f * cos(z) - x * f * sin(z), cosh(r) * sin(z), cosh(r) * cos(z)); } - EX hyperpoint get_inverse_exp(hyperpoint h, ld index IS(0)) { - ld xy = hypot_d(2, h); - ld phi = atan2(h[2], h[3]) + index; + EX hyperpoint get_inverse_exp(shiftpoint h) { + ld xy = hypot_d(2, h.h); + ld phi = atan2(h[2], h[3]) + h.shift; bool flipped = phi > 0; if(flipped) phi = -phi, h[2] *= -1, h[0] *= -1; @@ -1766,7 +1750,7 @@ EX namespace slr { ld SV = stretch::not_squared(); ld K = -1; - ld alpha = atan2(h[1], -h[0]); + ld alpha = atan2(h[1], -h[0]); /* todo shift */ hyperpoint res; @@ -2098,7 +2082,7 @@ EX namespace rots { hybrid::in_underlying_geometry([&] { hyperpoint h = tC0(T); Spin = inverse(gpushxto0(h) * T); - d = hr::inverse_exp(h); + d = hr::inverse_exp(shiftless(h)); alpha = atan2(Spin[0][1], Spin[0][0]); distance = hdist0(h); beta = atan2(h[1], h[0]); @@ -2154,7 +2138,7 @@ EX namespace rots { virtual transmatrix relative_matrix(cell *c2, cell *c1, const hyperpoint& hint) override { if(c1 == c2) return Id; if(gmatrix0.count(c2) && gmatrix0.count(c1)) - return inverse(gmatrix0[c1]) * gmatrix0[c2]; + return inverse_shift(gmatrix0[c1], gmatrix0[c2]); for(int i=0; itype; i++) if(c1->move(i) == c2) return adj(c1, i); return Id; // not implemented yet } @@ -2243,8 +2227,9 @@ EX namespace rots { dynamicval m5(centerover, co); dynamicval m2(View, inprod ? pView : ypush(0) * qtm(h)); if(PURE) View = View * pispin; - dynamicval m3(playerV, Id); + dynamicval m3(playerV, shiftless(Id)); dynamicval m4(actual_view_transform, Id); + dynamicval m6(cwtV, shiftless(Id)); dynamicval pm(pmodel, mdDisk); dynamicval pss(pconf.scale, (sphere ? 10 : 1) * underlying_scale); dynamicval psa(pconf.alpha, sphere ? 10 : 1); @@ -2255,7 +2240,7 @@ EX namespace rots { dynamicval psy(vid.smart_range_detail, 1); calcparam(); - reset_projection(); current_display->set_all(0); + reset_projection(); current_display->set_all(0, 0); ptds.clear(); drawthemap(); drawqueue(); @@ -2265,7 +2250,7 @@ EX namespace rots { gmatrix = std::move(g); gmatrix0 = std::move(g0); calcparam(); - reset_projection(); current_display->set_all(0); + reset_projection(); current_display->set_all(0, 0); } /** @brief exponential function for both slr and Berger sphere */ @@ -2670,7 +2655,7 @@ EX namespace nisot { hyperpoint at = tC0(Position); transmatrix push_back = inverse(translate(at)); hyperpoint back_goal = push_back * goal; - back_goal = inverse_exp(back_goal, prec); + back_goal = inverse_exp(shiftless(back_goal), prec); transmatrix back_Position = push_back * Position; diff --git a/orbs.cpp b/orbs.cpp index 52dfff68..5c0b4689 100644 --- a/orbs.cpp +++ b/orbs.cpp @@ -579,7 +579,7 @@ EX void teleportTo(cell *dest) { cell *from = cwt.at; movecost(from, dest, 1); playerMoveEffects(cwt.at, dest); - current_display->which_copy = ggmatrix(dest); + current_display->which_copy = unshift(ggmatrix(dest)); cwt.at = dest; cwt.spin = hrand(dest->type); flipplayer = !!(hrand(2)); drainOrb(itOrbTeleport); @@ -666,7 +666,7 @@ EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill IS(0), eMons changes.commit(); - current_display->which_copy = ggmatrix(dest); + current_display->which_copy = unshift(ggmatrix(dest)); countLocalTreasure(); for(int i=9; i>=0; i--) diff --git a/pattern2.cpp b/pattern2.cpp index 33671321..cb4dab6f 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -2541,12 +2541,12 @@ EX namespace linepatterns { return col; } - void gridlinef(const transmatrix& V1, const hyperpoint& h1, const transmatrix& V2, const hyperpoint& h2, color_t col, int par) { + void gridlinef(const shiftmatrix& V1, const hyperpoint& h1, const shiftmatrix& V2, const hyperpoint& h2, color_t col, int par) { if(!elliptic) gridline(V1, h1, V2, h2, col, par); else { - hyperpoint vh1 = V1 * h1; - hyperpoint vh2 = V2 * h2; + hyperpoint vh1 = V1.T * h1; + hyperpoint vh2 = unshift(V2, V1.shift) * h2; ld cros = vh1[0]*vh2[0] + vh1[1]*vh2[1] + vh1[2]*vh2[2]; if(cros > 0) gridline(V1, h1, V2, h2, col, par), @@ -2557,13 +2557,13 @@ EX namespace linepatterns { } } - void gridlinef(const transmatrix& V, const hyperpoint& h1, const hyperpoint& h2, color_t col, int par) { gridlinef(V, h1, V, h2, col, par); } + void gridlinef(const shiftmatrix& V, const hyperpoint& h1, const hyperpoint& h2, color_t col, int par) { gridlinef(V, h1, V, h2, col, par); } #define ALLCELLS(R) \ [] (linepattern *lp) { auto& col = lp->color; for(auto& p: current_display->all_drawn_copies) for(auto& V: p.second) { cell *c = p.first; R } } #define ATCENTER(T) \ - [] (linepattern *lp) { auto& col = lp->color; transmatrix V = gmatrix[cwt.at]; T} + [] (linepattern *lp) { auto& col = lp->color; shiftmatrix V = gmatrix[cwt.at]; T} linepattern patDual("dual grid", 0xFFFFFF00, always_available, ALLCELLS( @@ -2631,7 +2631,7 @@ EX namespace linepatterns { cell *c2 = c->master->cmove(dir)->c7; if(gmatrix.count(c2)) { if(S3 >= OINF) - gridlinef(V, C0, Id, mid(tC0(V), tC0(V * currentmap->adj(c, dir))), col, 2 + vid.linequality); + gridlinef(V, C0, V, mid(C0, tC0(currentmap->adj(c, dir))), col, 2 + vid.linequality); else gridlinef(V, C0, V * master_relative(c, true) * currentmap->adj(c->master, dir), C0, col, 2 + vid.linequality); } @@ -2648,7 +2648,7 @@ EX namespace linepatterns { cell *c2 = c->master->move(i)->c7; if(gmatrix.count(c2)) { if(S3 >= OINF) { - gridlinef(V, C0, Id, mid(tC0(V), tC0(gmatrix[c2])), col, 2 + vid.linequality); + gridlinef(V, C0, V, mid(C0, tC0(inverse_shift(V, gmatrix[c2]))), col, 2 + vid.linequality); } else gridlinef(V, C0, V*master_relative(c, true) * currentmap->adj(c->master,i), C0, col, 2 + vid.linequality); @@ -2674,7 +2674,7 @@ EX namespace linepatterns { ALLCELLS( if(zebra40(c) / 4 == 10) { bool all = true; - transmatrix tri[3]; + shiftmatrix tri[3]; for(int i=0; i<3; i++) tri[i] = V * currentmap->adj(c, i*2); @@ -2821,7 +2821,7 @@ EX namespace linepatterns { for(int j=0; j<360; j+=15) { for(int k=0; k<=15; k++) curvepoint(xspinpush0((j+k) * degree, i * degree)); - queuecurve(col, 0, PPR::LINE).V=V; + queuecurve(shiftless(Id), col, 0, PPR::LINE).V=V; } } ) @@ -2833,7 +2833,7 @@ EX namespace linepatterns { for(int j=0; j<180; j+=15) { for(int k=0; k<=15; k++) curvepoint(xspinpush0(i * degree, (j+k) * degree)); - queuecurve(col, 0, PPR::LINE).V=V; + queuecurve(shiftless(Id), col, 0, PPR::LINE).V=V; } } ) @@ -2843,8 +2843,8 @@ EX namespace linepatterns { for(int j=-180; j<=180; j+=15) { for(int i=-90; i<90; i+=15) { for(int k=0; k<=15; k++) - curvepoint(V * xpush(j * degree) * ypush0((i+k) * degree)); - queuecurve(col, 0, PPR::LINE).V=V; + curvepoint(xpush(j * degree) * ypush0((i+k) * degree)); + queuecurve(V, col, 0, PPR::LINE).V=V; } } ) @@ -2854,8 +2854,8 @@ EX namespace linepatterns { for(int i=-90; i<=90; i += 15) { for(int j=-180; j<180; j+=15) { for(int k=0; k<=15; k++) - curvepoint(V * xpush((j+k) * degree) * ypush0(i * degree)); - queuecurve(col, 0, PPR::LINE).V=V; + curvepoint(xpush((j+k) * degree) * ypush0(i * degree)); + queuecurve(V, col, 0, PPR::LINE).V=V; } } ) diff --git a/racing.cpp b/racing.cpp index e02a1558..31715501 100644 --- a/racing.cpp +++ b/racing.cpp @@ -170,7 +170,7 @@ void write_ghosts(string seed, int mcode) { } #endif -transmatrix get_ghostmoment_matrix(ghostmoment& p) { +shiftmatrix get_ghostmoment_matrix(ghostmoment& p) { cell *w = rti[p.where_id].c; transmatrix T = spin_uchar(p.alpha) * xpush(uchar_to_frac(p.distance) * distance_multiplier) * spin_uchar(p.beta); return gmatrix[w] * T; @@ -615,7 +615,7 @@ EX void generate_track() { for(int i=0; i forbidden; + vector forbidden; for(auto& ghost: ghostset()[specialland]) forbidden.push_back(get_ghostmoment_matrix(ghost.history[0])); for(auto& ghost: oghostset()[specialland]) @@ -634,7 +634,7 @@ EX void generate_track() { who->at = straight * parabolic1(start_line_width * (rand() % 20000 - 10000) / 40000) * spin(rand() % 360); who->base = s; bool ok = true; - for(const transmatrix& t: forbidden) if(hdist(t*C0, who->at * C0) < 10. / (j+10)) ok = false; + for(const shiftmatrix& t: forbidden) if(hdist(t*C0, shiftless(who->at) * C0) < 10. / (j+10)) ok = false; if(ok) break; } virtualRebase(who); @@ -775,7 +775,7 @@ EX bool set_view() { if(use_standard_centering()) return false; if(player_relative && specialland == laAsteroids) return false; - transmatrix at = ypush(-vid.yshift) * ggmatrix(who->base) * who->at; + transmatrix at = ypush(-vid.yshift) * unshift(ggmatrix(who->base)) * who->at; if(racing::player_relative || quotient || (kite::in() && GDIM == 3)) { View = inverse(at) * View; @@ -785,8 +785,8 @@ EX bool set_view() { int steps = euclid ? 1000 : PURE ? 10 : 20; cell *c1 = racing::track[max(z-steps, 0)]; cell *c2 = racing::track[min(z+steps, isize(racing::track)-1)]; - transmatrix T1 = ypush(-vid.yshift) * ggmatrix(c1); - transmatrix T2 = ypush(-vid.yshift) * ggmatrix(c2); + transmatrix T1 = ypush(-vid.yshift) * unshift(ggmatrix(c1)); + transmatrix T2 = ypush(-vid.yshift) * unshift(ggmatrix(c2)); transmatrix T = spintox(inverse(T1) * T2 * C0); hyperpoint h = T * inverse(T1) * at * C0; ld y = GDIM == 2 ? asin_auto(h[1]) : asin_auto(hypot(h[1], h[2])); @@ -1326,7 +1326,7 @@ EX void race_won() { } } -void draw_ghost_at(ghost& ghost, cell *w, const transmatrix& V, ghostmoment& p) { +void draw_ghost_at(ghost& ghost, cell *w, const shiftmatrix& V, ghostmoment& p) { dynamicval x(getcs(), ghost.cs); if(ghost.cs.charid == -1) { dynamicval pc(peace::on, true); @@ -1355,9 +1355,9 @@ void draw_ghost(ghost& ghost) { draw_ghost_at(ghost, w, get_ghostmoment_matrix(p), p); } -transmatrix racerel(ld rel) { +shiftmatrix racerel(ld rel) { int bsize = vid.fsize * 2; - return atscreenpos(bsize, vid.yres - bsize - rel * (vid.yres - bsize*2) / 100, bsize) * spin(M_PI/2); + return shiftless(atscreenpos(bsize, vid.yres - bsize - rel * (vid.yres - bsize*2) / 100, bsize) * spin(M_PI/2)); } EX int get_percentage(cell *c) { @@ -1390,7 +1390,7 @@ EX void drawStats() { curvepoint(atscreenpos(bsize*3/2, y, bsize) * C0); curvepoint(atscreenpos(bsize, y, bsize) * C0); } - queuecurve(0xFFFFFFFF, 0, PPR::ZERO); + queuecurve(shiftless(Id), 0xFFFFFFFF, 0, PPR::ZERO); for(auto& ghost: ghostset()[specialland]) draw_ghost_state(ghost); for(auto& ghost: oghostset()[specialland]) draw_ghost_state(ghost); @@ -1418,8 +1418,8 @@ EX void markers() { if(!goal) return; - hyperpoint H = tC0(ggmatrix(goal)); - if(invalid_point(H)) return; + shiftpoint H = tC0(ggmatrix(goal)); + if(invalid_point(H.h)) return; queuestr(H, 2*vid.fsize, "X", 0x10100 * int(128 + 100 * sintick(150))); int cd = celldistance(track.back(), cwt.at); @@ -1444,8 +1444,8 @@ EX void markers() { if(gmatrix.count(track[0])) { hyperpoint h = WDIM == 2 && GDIM == 3 ? zpush(cgi.FLOOR - cgi.human_height/80) * C0 : C0; for(ld z=-start_line_width; z<=start_line_width; z+=0.1) - curvepoint(ggmatrix(track[0]) * straight * parabolic1(z) * h); - queuecurve(0xFFFFFFFF, 0, PPR::BFLOOR); + curvepoint(parabolic1(z) * h); + queuecurve(ggmatrix(track[0]) * straight, 0xFFFFFFFF, 0, PPR::BFLOOR); } } diff --git a/radar.cpp b/radar.cpp index ffb020f1..8290a556 100644 --- a/radar.cpp +++ b/radar.cpp @@ -20,46 +20,50 @@ EX vector radarlines; EX transmatrix radar_transform; -pair makeradar(hyperpoint h) { - if(GDIM == 3 && WDIM == 2) h = radar_transform * h; +pair makeradar(shiftpoint h) { + if(GDIM == 3 && WDIM == 2) h.h = radar_transform * h.h; ld d = hdist0(h); + hyperpoint h1; + if(sol && nisot::geodesic_movement) { - h = inverse_exp(h, pQUICK); - ld r = hypot_d(3, h); - if(r < 1) h = h * (atanh(r) / r); - else return {false, h}; + hyperpoint h1 = inverse_exp(h, pQUICK); + ld r = hypot_d(3, h1); + if(r < 1) h1 = h1 * (atanh(r) / r); + else return {false, h1}; } - if(prod) h = product::inverse_exp(h); - if(nisot::local_perspective_used()) h = NLP * h; + else + if(prod) h1 = product::inverse_exp(unshift(h)); + + if(nisot::local_perspective_used()) h1 = NLP * h1; if(WDIM == 3) { - if(d >= vid.radarrange) return {false, h}; - if(d) h = h * (d / vid.radarrange / hypot_d(3, h)); + if(d >= vid.radarrange) return {false, h1}; + if(d) h1 = h1 * (d / vid.radarrange / hypot_d(3, h1)); } else if(hyperbolic) { - for(int a=0; a<3; a++) h[a] = h[a] / (1 + h[3]); + for(int a=0; a<3; a++) h1[a] = h1[a] / (1 + h[3]); } else if(sphere) { - h[2] = h[3]; + h1[2] = h1[3]; } else { - if(d > vid.radarrange) return {false, h}; - if(d) h = h * (d / (vid.radarrange + cgi.scalefactor/4) / hypot_d(3, h)); + if(d > vid.radarrange) return {false, h1}; + if(d) h1 = h1 * (d / (vid.radarrange + cgi.scalefactor/4) / hypot_d(3, h1)); } - if(invalid_point(h)) return {false, h}; - return {true, h}; + if(invalid_point(h1)) return {false, h1}; + return {true, h1}; } -EX void addradar(const transmatrix& V, char ch, color_t col, color_t outline) { - hyperpoint h = tC0(V); +EX void addradar(const shiftmatrix& V, char ch, color_t col, color_t outline) { + shiftpoint h = tC0(V); auto hp = makeradar(h); if(hp.first) radarpoints.emplace_back(radarpoint{hp.second, ch, col, outline}); } -EX void addradar(const hyperpoint h1, const hyperpoint h2, color_t col) { +EX void addradar(const shiftpoint h1, const shiftpoint h2, color_t col) { auto hp1 = makeradar(h1); auto hp2 = makeradar(h2); if(hp1.first && hp2.first) @@ -107,10 +111,12 @@ EX void draw_radar(bool cornermode) { ld cx = dual::state ? (dual::currently_loaded ? vid.xres/2+rad+2 : vid.xres/2-rad-2) : cornermode ? rad+2 : vid.xres-rad-2; ld cy = vid.yres-rad-2 - vid.fsize; + + auto sId = shiftless(Id); for(int i=0; i<360; i++) curvepoint(atscreenpos(cx-cos(i * degree)*rad, cy-sin(i*degree)*rad, 1) * C0); - queuecurve(0xFFFFFFFF, 0x000000FF, PPR::ZERO); + queuecurve(sId, 0xFFFFFFFF, 0x000000FF, PPR::ZERO); ld alpha = 15 * degree; ld co = cos(alpha); @@ -119,28 +125,28 @@ EX void draw_radar(bool cornermode) { if(sph && !d3) { for(int i=0; i<360; i++) curvepoint(atscreenpos(cx-cos(i * degree)*rad, cy-sin(i*degree)*rad*si, 1) * C0); - queuecurve(0, 0x200000FF, PPR::ZERO); + queuecurve(sId, 0, 0x200000FF, PPR::ZERO); } if(d3) { for(int i=0; i<360; i++) curvepoint(atscreenpos(cx-cos(i * degree)*rad, cy-sin(i*degree)*rad*si, 1) * C0); - queuecurve(0xFF0000FF, 0x200000FF, PPR::ZERO); + queuecurve(sId, 0xFF0000FF, 0x200000FF, PPR::ZERO); curvepoint(atscreenpos(cx-sin(vid.fov*degree/2)*rad, cy-sin(vid.fov*degree/2)*rad*si, 1) * C0); curvepoint(atscreenpos(cx, cy, 1) * C0); curvepoint(atscreenpos(cx+sin(vid.fov*degree/2)*rad, cy-sin(vid.fov*degree/2)*rad*si, 1) * C0); - queuecurve(0xFF8000FF, 0, PPR::ZERO); + queuecurve(sId, 0xFF8000FF, 0, PPR::ZERO); } if(d3) for(auto& r: radarpoints) { - queueline(atscreenpos(cx+rad * r.h[0], cy - rad * r.h[2] * si + rad * r.h[1] * co, 0)*C0, atscreenpos(cx+rad*r.h[0], cy - rad*r.h[2] * si, 0)*C0, r.line, -1); + queueline(sId*atscreenpos(cx+rad * r.h[0], cy - rad * r.h[2] * si + rad * r.h[1] * co, 0)*C0, sId*atscreenpos(cx+rad*r.h[0], cy - rad*r.h[2] * si, 0)*C0, r.line, -1); } if(scompass) { auto compassdir = [&] (char dirname, hyperpoint h) { h = NLP * h * .8; - queueline(atscreenpos(cx+rad * h[0], cy - rad * h[2] * si + rad * h[1] * co, 0)*C0, atscreenpos(cx+rad*h[0], cy - rad*h[2] * si, 0)*C0, 0xA0401040, -1); + queueline(sId*atscreenpos(cx+rad * h[0], cy - rad * h[2] * si + rad * h[1] * co, 0)*C0, sId*atscreenpos(cx+rad*h[0], cy - rad*h[2] * si, 0)*C0, 0xA0401040, -1); displaychr(int(cx+rad * h[0]), int(cy - rad * h[2] * si + rad * h[1] * co), 0, 8, dirname, 0xA04010); }; compassdir('E', point3(+1, 0, 0)); @@ -165,7 +171,7 @@ EX void draw_radar(bool cornermode) { hyperpoint h2 = locate(r.h2); h1 = tC0(atscreenpos(h1[0], h1[1], 1)); h2 = tC0(atscreenpos(h2[0], h2[1], 1)); - queueline(h1, h2, r.line, -1); + queueline(sId*h1, sId*h2, r.line, -1); } quickqueue(); diff --git a/raycaster.cpp b/raycaster.cpp index 975e7dc0..0bcf9a0a 100644 --- a/raycaster.cpp +++ b/raycaster.cpp @@ -1146,7 +1146,7 @@ EX void cast() { cell *cs = centerover; - transmatrix T = cview(); + transmatrix T = cview().T; if(global_projection) T = xpush(vid.ipd * global_projection/2) * T; @@ -1280,7 +1280,7 @@ EX void cast() { celldrawer dd; dd.c = c1; dd.setcolors(); - transmatrix Vf; + shiftmatrix Vf; dd.set_land_floor(Vf); color_t wcol = darkena(dd.wcol, 0, 0xFF); int dv = get_darkval(c1, c->c.spin(i)); @@ -1325,7 +1325,7 @@ EX void cast() { celldrawer dd; dd.c = c; dd.setcolors(); - transmatrix Vf; + shiftmatrix Vf; dd.set_land_floor(Vf); int u = (id/per_row*length) + (id%per_row * deg) + c->type + a; wallcolor[u] = glhr::acolor(darkena(dd.fcol, 0, 0xFF)); diff --git a/reg3.cpp b/reg3.cpp index 7234d633..154cb37a 100644 --- a/reg3.cpp +++ b/reg3.cpp @@ -321,15 +321,13 @@ EX namespace reg3 { // for(int i=0; imaster, cview()); while(!dq::drawqueue.empty()) { auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); - bandfixer bf(V); + heptagon *h = p.first; + shiftmatrix V = p.second; dq::drawqueue.pop(); cell *c = h->c7; @@ -339,10 +337,10 @@ EX namespace reg3 { if(ultra_mirror_in()) for(auto& T: cgi.ultra_mirrors) - dq::enqueue_by_matrix(h, V * T); + dq::enqueue_by_matrix(h, optimized_shift(V * T)); for(int d=0; dmove(d), V * tmatrices[h->fieldval][d]); + dq::enqueue_by_matrix(h->move(d), optimized_shift(V * tmatrices[h->fieldval][d])); } } @@ -929,10 +927,8 @@ EX namespace reg3 { while(!dq::drawqueue.empty()) { auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); - bandfixer bf(V); + heptagon *h = p.first; + shiftmatrix V = p.second; dq::drawqueue.pop(); @@ -945,10 +941,10 @@ EX namespace reg3 { if(ultra_mirror_in()) for(auto& T: cgi.ultra_mirrors) - dq::enqueue_by_matrix(h, V * T); + dq::enqueue_by_matrix(h, optimized_shift(V * T)); for(int i=0; imove(i)) { - enq(h->move(i), V * adj(h, i)); + enq(h->move(i), optimized_shift(V * adj(h, i))); } } } @@ -1273,15 +1269,13 @@ EX namespace reg3 { // for(int i=0; imaster, cview()); while(!dq::drawqueue.empty()) { auto& p = dq::drawqueue.front(); - heptagon *h = get<0>(p); - transmatrix V = get<1>(p); - dynamicval b(band_shift, get<2>(p)); - bandfixer bf(V); + heptagon *h = p.first; + shiftmatrix V = p.second; dq::drawqueue.pop(); @@ -1291,7 +1285,7 @@ EX namespace reg3 { if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000) continue; for(int i=0; imove(i)) { - dq::enqueue(h->move(i), V * adj(h, i)); + dq::enqueue(h->move(i), optimized_shift(V * adj(h, i))); } } } diff --git a/rug.cpp b/rug.cpp index fcacd066..b3de7800 100644 --- a/rug.cpp +++ b/rug.cpp @@ -44,7 +44,7 @@ bool computed = false; bool valid; bool inqueue; double dist; - hyperpoint h; // point in the represented space + shiftpoint h; // point in the represented space hyperpoint native; // point in the native space hyperpoint precompute; vector edges; @@ -164,7 +164,7 @@ bool rug_hyperbolic() { USING_NATIVE_GEOMETRY; return hyperbolic; } bool rug_sphere() { USING_NATIVE_GEOMETRY; return sphere; } bool rug_elliptic() { USING_NATIVE_GEOMETRY; return elliptic; } -EX rugpoint *addRugpoint(hyperpoint h, double dist) { +EX rugpoint *addRugpoint(shiftpoint h, double dist) { rugpoint *m = new rugpoint; m->h = h; @@ -218,12 +218,12 @@ EX rugpoint *addRugpoint(hyperpoint h, double dist) { } else scale = 1; - m->native = h * scale; + m->native = unshift(h) * scale; m->native = hpxy3(m->native[0], m->native[1], m->native[2]); } else if(euclid && rug_euclid()) { - m->native = h * modelscale; + m->native = unshift(h) * modelscale; m->native[2] = 0; #if MAXMDIM >= 4 m->native[3] = 1; @@ -247,11 +247,11 @@ EX rugpoint *addRugpoint(hyperpoint h, double dist) { USING_NATIVE_GEOMETRY; - m->native = rgpushxto0(h) * cpush0(2, r); + m->native = rgpushxto0(unshift(h)) * cpush0(2, r); } else { - m->native = h; + m->native = unshift(h); ld hd = h[LDIM]; for(int d=GDIM; dnative[d] = (hd - .99) * (rand() % 1000 - rand() % 1000) / 1000; @@ -269,14 +269,14 @@ EX rugpoint *addRugpoint(hyperpoint h, double dist) { return m; } -EX rugpoint *findRugpoint(hyperpoint h) { +EX rugpoint *findRugpoint(shiftpoint h) { USING_NATIVE_GEOMETRY; for(int i=0; ih, h) < 1e-5) return points[i]; + if(geo_dist_q(points[i]->h.h, unshift(h, points[i]->h.shift)) < 1e-5) return points[i]; return NULL; } -EX rugpoint *findOrAddRugpoint(hyperpoint h, double dist) { +EX rugpoint *findOrAddRugpoint(shiftpoint h, double dist) { rugpoint *r = findRugpoint(h); return r ? r : addRugpoint(h, dist); } @@ -342,7 +342,7 @@ EX void sort_rug_points() { void calcLengths() { for(auto p: points) for(auto& edge: p->edges) - edge.len = geo_dist_q(p->h, edge.target->h) * modelscale; + edge.len = geo_dist_q(p->h.h, unshift(edge.target->h, p->h.shift)) * modelscale; } EX void calcparam_rug() { @@ -396,9 +396,9 @@ EX void buildTorusRug() { println(hlog, "mx = ", mx); auto addToruspoint = [&] (hyperpoint h) { - auto r = addRugpoint(C0, 0); + auto r = addRugpoint(shiftless(C0), 0); hyperpoint onscreen; - hyperpoint h1 = gmatrix[gs] * T * h; + shiftpoint h1 = gmatrix[gs] * T * h; applymodel(h1, onscreen); r->x1 = onscreen[0]; r->y1 = onscreen[1]; @@ -539,7 +539,7 @@ EX void buildRug() { for(int j=0; jtype; j++) addTriangle(v, p[j], p[(j+1) % c->type]); if((euclid && quotient) && nonorientable) { - transmatrix T = ggmatrix(c) * eumove(euc::eu.user_axes[1]); + shiftmatrix T = ggmatrix(c) * eumove(euc::eu.user_axes[1]); rugpoint *Tv = addRugpoint(T * C0, 0); for(int j=0; jtype; j++) p[j] = findOrAddRugpoint(T * get_corner_position(c, j), v->dist); for(int j=0; jtype; j++) addTriangle(Tv, p[j], p[(j+1) % c->type]); @@ -625,7 +625,7 @@ bool force(rugpoint& m1, rugpoint& m2, double rd, bool is_anticusp=false, double double forcev = (t - rd) / 2; // 20.0; transmatrix T = inverse(rgpushxto0(m1.native)); - hyperpoint ie = inverse_exp(T * m2.native); + hyperpoint ie = inverse_exp(shiftless(T * m2.native)); transmatrix iT = rgpushxto0(m1.native); @@ -1041,7 +1041,7 @@ EX void prepareTexture() { queueline(tC0(ggmatrix(playerpos(i))), mouseh, 0xFF00FF, 8 + vid.linequality); } if(finger_center) { - transmatrix V = rgpushxto0(finger_center->h); + shiftmatrix V = rgpushxto0(finger_center->h); queuestr(V, 0.5, "X", 0xFFFFFFFF, 2); for(int i=0; i<72; i++) queueline(V * xspinpush0(i*M_PI/32, finger_range), V * xspinpush0((i+1)*M_PI/32, finger_range), 0xFFFFFFFF, vid.linequality); @@ -1081,15 +1081,15 @@ EX void drawRugScene() { for(auto t: triangles) drawTriangle(t); - auto& rug = queuecurve(0, 0xFFFFFFFF, PPR::LINE); + auto& rug = queuecurve(shiftless(Id), 0, 0xFFFFFFFF, PPR::LINE); if(nonisotropic) { transmatrix T2 = eupush( tC0(inverse(rugView)) ); NLP = rugView * T2; - rug.V = inverse(NLP) * rugView; + rug.V = shiftless(inverse(NLP) * rugView); } else { - rug.V = rugView; + rug.V = shiftless(rugView); } rug.offset_texture = 0; @@ -1322,7 +1322,7 @@ int besti; static const ld RADAR_INF = 1e12; ld radar_distance = RADAR_INF; -EX hyperpoint gethyper(ld x, ld y) { +EX shiftpoint gethyper(ld x, ld y) { projection_configuration bak = pconf; pconf = rconf; @@ -1359,9 +1359,9 @@ EX hyperpoint gethyper(ld x, ld y) { if(sp == 1 || sp == 2) continue; } - applymodel(inverse(NLP) * rugView * r0->native, p0); - applymodel(inverse(NLP) * rugView * r1->native, p1); - applymodel(inverse(NLP) * rugView * r2->native, p2); + applymodel(shiftless(inverse(NLP) * rugView * r0->native), p0); + applymodel(shiftless(inverse(NLP) * rugView * r1->native), p1); + applymodel(shiftless(inverse(NLP) * rugView * r2->native), p2); } if(error || spherepoints == 1 || spherepoints == 2) continue; @@ -1390,13 +1390,13 @@ EX hyperpoint gethyper(ld x, ld y) { } pconf = bak; - if(!found) return Hypc; + if(!found) return shiftless(Hypc); double px = rx1 * TEXTURESIZE, py = (1-ry1) * TEXTURESIZE; calcparam_rug(); models::configure(); - hyperpoint h = hr::gethyper(px, py); + shiftpoint h = hr::gethyper(px, py); calcparam(); return h; diff --git a/screenshot.cpp b/screenshot.cpp index 5e96356d..6071d2b6 100644 --- a/screenshot.cpp +++ b/screenshot.cpp @@ -400,8 +400,7 @@ EX always_false in; tdata.push_back(p.tinf->tvertices[p.offset_texture+i]); } for(auto& d: data) { - hyperpoint h; - h = p.V * d; + shiftpoint h = p.V * d; applymodel(h, d); } if(print && (p.flags & POLY_FAT)) { @@ -1169,11 +1168,11 @@ bool joukowsky_anim; EX void reflect_view() { if(centerover) { - transmatrix T = Id; + shiftmatrix T = shiftless(Id); cell *mbase = centerover; cell *c = centerover; if(shmup::reflect(c, mbase, T)) - View = inverse(T) * View; + View = inverse(T.T) * View; } } @@ -1402,14 +1401,14 @@ EX bool record_video_std() { void display_animation() { if(ma == maCircle && (circle_display_color & 0xFF)) { for(int s=0; s<10; s++) { - if(s == 0) curvepoint(ggmatrix(rotation_center) * xpush0(circle_radius - .1)); - for(int z=0; z<100; z++) curvepoint(ggmatrix(rotation_center) * xspinpush0((z+s*100) * 2 * M_PI / 1000., circle_radius)); - queuecurve(circle_display_color, 0, PPR::LINE); + if(s == 0) curvepoint(xpush0(circle_radius - .1)); + for(int z=0; z<100; z++) curvepoint(xspinpush0((z+s*100) * 2 * M_PI / 1000., circle_radius)); + queuecurve(ggmatrix(rotation_center), circle_display_color, 0, PPR::LINE); } if(sphere) for(int s=0; s<10; s++) { - if(s == 0) curvepoint(centralsym * ggmatrix(rotation_center) * xpush0(circle_radius - .1)); - for(int z=0; z<100; z++) curvepoint(centralsym * ggmatrix(rotation_center) * xspinpush0((z+s*100) * 2 * M_PI / 1000., circle_radius)); - queuecurve(circle_display_color, 0, PPR::LINE); + if(s == 0) curvepoint(xpush0(circle_radius - .1)); + for(int z=0; z<100; z++) curvepoint(xspinpush0((z+s*100) * 2 * M_PI / 1000., circle_radius)); + queuecurve(ggmatrix(rotation_center) * centralsym, circle_display_color, 0, PPR::LINE); } } } @@ -1878,13 +1877,14 @@ reaction_t add_to_frame; #if CAP_STARTANIM void draw_ghost(const transmatrix V, int id) { + auto sV = shiftless(V); if(id % 13 == 0) { - queuepoly(V, cgi.shMiniGhost, 0xFFFF00C0); - queuepoly(V, cgi.shMiniEyes, 0xFF); + queuepoly(sV, cgi.shMiniGhost, 0xFFFF00C0); + queuepoly(sV, cgi.shMiniEyes, 0xFF); } else { - queuepoly(V, cgi.shMiniGhost, 0xFFFFFFC0); - queuepoly(V, cgi.shMiniEyes, 0xFF); + queuepoly(sV, cgi.shMiniGhost, 0xFFFFFFC0); + queuepoly(sV, cgi.shMiniEyes, 0xFF); } } @@ -1914,7 +1914,7 @@ startanim army_of_ghosts { "army of ghosts", no_init, [] { for(int y=0;; y++) { ld ay = (mod - y)/4.; transmatrix U = spin(M_PI/2) * xpush(ay / cosh(ax)) * T; - if(!in_smart_range(U)) break; + if(!in_smart_range(shiftless(U))) break; draw_ghost(U, (-y - t)); if(y) { ay = (mod + y)/4.; diff --git a/shaders.cpp b/shaders.cpp index 4b6e62b0..ea0242f0 100644 --- a/shaders.cpp +++ b/shaders.cpp @@ -313,7 +313,7 @@ shared_ptr write_shader(flagtype shader_flags) { } } -void display_data::set_projection(int ed) { +void display_data::set_projection(int ed, ld shift) { flagtype shader_flags = current_display->next_shader_flags; unsigned id; id = geometry; @@ -467,8 +467,9 @@ void display_data::set_projection(int ed) { if(selected->shader_flags & SF_BAND) glhr::projection_multiply(glhr::scale(2 / M_PI, 2 / M_PI, GDIM == 3 ? 2/M_PI : 1)); - if(selected->shader_flags & SF_BAND) - glhr::projection_multiply(glhr::translate(band_shift, 0, 0)); + if(selected->shader_flags & SF_BAND) { + glhr::projection_multiply(glhr::translate(shift, 0, 0)); + } if(selected->shader_flags & SF_HALFPLANE) { glhr::projection_multiply(glhr::translate(0, 1, 0)); diff --git a/shmup.cpp b/shmup.cpp index 33359e71..6c2ecdf7 100644 --- a/shmup.cpp +++ b/shmup.cpp @@ -21,9 +21,9 @@ EX namespace shmupballs { } EX } -ld sqdist(hyperpoint a, hyperpoint b) { +ld sqdist(shiftpoint a, shiftpoint b) { if(prod) return pow(hdist(a, b), 2); - else return intval(a, b); + else return intval(a.h, unshift(b, a.shift)); } /* @@ -53,7 +53,7 @@ struct monster { // tortoises: origin // butterflies: last position transmatrix at; - transmatrix pat; + shiftmatrix pat; /** orientation for the product geometry */ transmatrix ori; eMonster stk; @@ -84,9 +84,9 @@ struct monster { void findpat(); - cell *findbase(const transmatrix& T, int maxsteps); + cell *findbase(const shiftmatrix& T, int maxsteps); - void rebasePat(const transmatrix& new_pat, cell *tgt); + void rebasePat(const shiftmatrix& new_pat, cell *tgt); }; #endif @@ -112,23 +112,23 @@ typedef multimap::iterator mit; vector active, nonvirtual, additional; -cell *findbaseAround(hyperpoint p, cell *around, int maxsteps) { +cell *findbaseAround(shiftpoint p, cell *around, int maxsteps) { if(fake::split()) { - auto p0 = inverse(ggmatrix(around)) * p; + auto p0 = inverse_shift(ggmatrix(around), p); virtualRebase(around, p0); return around; } cell *best = around; - transmatrix T = ggmatrix(around); + shiftmatrix T = ggmatrix(around); horo_distance d0(p, T); for(int k=0; ktype; i++) { cell *c2 = around->move(i); if(c2) { - transmatrix U = ggmatrix(c2); + shiftmatrix U = ggmatrix(c2); horo_distance d1(p, U); if(d1 < d0) { best = c2; d0 = d1; } } @@ -139,7 +139,7 @@ cell *findbaseAround(hyperpoint p, cell *around, int maxsteps) { return around; } -cell *findbaseAround(const transmatrix& H, cell *around, int maxsteps) { +cell *findbaseAround(const shiftmatrix& H, cell *around, int maxsteps) { return findbaseAround(tC0(H), around, maxsteps); } @@ -153,15 +153,15 @@ void monster::store() { } void monster::findpat() { - isVirtual = !gmatrix.count(base) || invalid_matrix(gmatrix[base]); + isVirtual = !gmatrix.count(base) || invalid_matrix(gmatrix[base].T); if(!isVirtual) pat = gmatrix[base] * at; - else pat = at; + else pat = shiftless(at); } -cell *monster::findbase(const transmatrix& T, int maxsteps) { +cell *monster::findbase(const shiftmatrix& T, int maxsteps) { if(isVirtual) { cell *c = base; - auto cT = T; + auto cT = T.T; virtualRebase(c, cT); return c; } @@ -177,18 +177,18 @@ void fix_to_2(transmatrix& T) { fixelliptic(T); } -void monster::rebasePat(const transmatrix& new_pat, cell *c2) { +void monster::rebasePat(const shiftmatrix& new_pat, cell *c2) { if(isVirtual) { - at = new_pat; + at = new_pat.T; virtualRebase(this); fix_to_2(at); - pat = at; + pat = shiftless(at); if(multi::players == 1 && this == shmup::pc[0]) - current_display->which_copy = ggmatrix(base); + current_display->which_copy = unshift(ggmatrix(base)); return; } if(quotient || fake::split()) { - at = inverse(gmatrix[base]) * new_pat; + at = inverse_shift(gmatrix[base], new_pat); transmatrix old_at = at; virtualRebase(this); fix_to_2(at); @@ -205,21 +205,21 @@ void monster::rebasePat(const transmatrix& new_pat, cell *c2) { return; } if(multi::players == 1 && this == shmup::pc[0]) - current_display->which_copy = current_display->which_copy * inverse(gmatrix[base]) * gmatrix[c2]; + current_display->which_copy = current_display->which_copy * inverse_shift(gmatrix[base], gmatrix[c2]); pat = new_pat; // if(c2 != base) printf("rebase %p -> %p\n", base, c2); base = c2; - at = inverse(gmatrix[c2]) * pat; + at = inverse_shift(gmatrix[c2], pat); fix_to_2(at); fixelliptic(at); } -bool trackroute(monster *m, transmatrix goal, double spd) { +bool trackroute(monster *m, shiftmatrix goal, double spd) { cell *c = m->base; // queuepoly(goal, shGrail, 0xFFFFFFC0); - transmatrix mat = inverse(m->pat) * goal; + transmatrix mat = inverse_shift(m->pat, goal); transmatrix mat2 = spintox(mat*C0) * mat; @@ -227,7 +227,7 @@ bool trackroute(monster *m, transmatrix goal, double spd) { while(d < dist) { d += spd; - transmatrix nat = m->pat * rspintox(mat * C0) * xpush(d); + shiftmatrix nat = m->pat * rspintox(mat * C0) * xpush(d); // queuepoly(nat, cgi.shKnife, 0xFFFFFFC0); @@ -339,7 +339,7 @@ void awakenMimics(monster *m, cell *c2) { else m2->type = moMimic; - hyperpoint H = inverse(gmatrix[c2]) * gmatrix[c] * C0; + hyperpoint H = inverse_shift(gmatrix[c2], tC0(gmatrix[c])); transmatrix xfer = rgpushxto0(H); @@ -348,9 +348,9 @@ void awakenMimics(monster *m, cell *c2) { xfer = rspintox(H) * rpushxto0(H2) * mirrortrans * spintox(H); } - m2->pat = gmatrix[c2] * xfer * inverse(gmatrix[c2]) * m->pat; + m2->pat = gmatrix[c2] * xfer * inverse_shift(gmatrix[c2], m->pat); - m2->at = inverse(gmatrix[c]) * m2->pat; + m2->at = inverse_shift(gmatrix[c], m2->pat); m2->pid = cpid; additional.push_back(m2); @@ -430,7 +430,7 @@ EX void killThePlayer(eMonster m) { pc[cpid]->dead = true; } -monster *playerCrash(monster *who, hyperpoint where) { +monster *playerCrash(monster *who, shiftpoint where) { if(who->isVirtual) return NULL; // in the racing mode, neither crashing nor getting too far away is a problem if(racing::on) return NULL; @@ -442,7 +442,7 @@ monster *playerCrash(monster *who, hyperpoint where) { return NULL; } -void oceanCurrents(transmatrix& nat, monster *m, int delta) { +void oceanCurrents(shiftmatrix& nat, monster *m, int delta) { cell *c = m->base; if(c->land == laWhirlpool) { for(int i=0; itype; i++) { @@ -457,11 +457,11 @@ void oceanCurrents(transmatrix& nat, monster *m, int delta) { spd = SCALE * delta / 900.; if(spd) { - transmatrix goal = gmatrix[c2]; + shiftpoint goal = tC0(gmatrix[c2]); // transmatrix t = spintox(H) * xpush(delta/300.) * rspintox(H); - hyperpoint H = inverse(m->pat) * goal * C0; + hyperpoint H = inverse_shift(m->pat, goal); nat = nat * rspintox(H); nat = nat * xpush(spd); nat = nat * spintox(H); @@ -470,7 +470,7 @@ void oceanCurrents(transmatrix& nat, monster *m, int delta) { } } -bool airCurrents(transmatrix& nat, monster *m, int delta) { +bool airCurrents(shiftmatrix& nat, monster *m, int delta) { bool carried = false; cell *c = m->base; #if CAP_COMPLEX2 @@ -481,11 +481,11 @@ bool airCurrents(transmatrix& nat, monster *m, int delta) { if(m->type == moVoidBeast) spd = -spd; if(spd) { - transmatrix goal = gmatrix[c2]; + shiftpoint goal = tC0(gmatrix[c2]); // transmatrix t = spintox(H) * xpush(delta/300.) * rspintox(H); - hyperpoint H = inverse(m->pat) * goal * C0; + hyperpoint H = inverse_shift(m->pat, goal); nat = nat * rspintox(H); nat = nat * xpush(spd); nat = nat * spintox(H); @@ -503,11 +503,11 @@ bool airCurrents(transmatrix& nat, monster *m, int delta) { if(m->type == moVoidBeast) spd = -spd; if(spd) { - transmatrix goal = gmatrix[c2]; + shiftpoint goal = tC0(gmatrix[c2]); // transmatrix t = spintox(H) * xpush(delta/300.) * rspintox(H); - hyperpoint H = inverse(m->pat) * goal * C0; + hyperpoint H = inverse_shift(m->pat, goal); nat = nat * rspintox(H); nat = nat * xpush(spd); nat = nat * spintox(H); @@ -524,11 +524,11 @@ bool airCurrents(transmatrix& nat, monster *m, int delta) { if(z >= 128) z -= 256; if(m->type == moVoidBeast) z = -z; if(z < windmap::NOWINDFROM && z > -windmap::NOWINDFROM) { - transmatrix goal = gmatrix[c2]; + shiftmatrix goal = gmatrix[c2]; // transmatrix t = spintox(H) * xpush(delta/300.) * rspintox(H); - hyperpoint H = inverse(m->pat) * goal * C0; + hyperpoint H = inverse_shift(m->pat, goal) * C0; nat = nat * rspintox(H); nat = nat * xpush(z * SCALE * delta / 50000.); nat = nat * spintox(H); @@ -540,7 +540,7 @@ bool airCurrents(transmatrix& nat, monster *m, int delta) { return carried; } -void roseCurrents(transmatrix& nat, monster *m, int delta) { +void roseCurrents(shiftmatrix& nat, monster *m, int delta) { if(ignoresSmell(m->type)) return; cell *c = m->base; @@ -559,11 +559,11 @@ void roseCurrents(transmatrix& nat, monster *m, int delta) { double spd = SCALE * delta / 300. / qty; if(spd) { - transmatrix goal = gmatrix[c2]; + shiftpoint goal = tC0(gmatrix[c2]); // transmatrix t = spintox(H) * xpush(delta/300.) * rspintox(H); - hyperpoint H = inverse(m->pat) * goal * C0; + hyperpoint H = inverse_shift(m->pat, goal); nat = nat * rspintox(H); nat = nat * xpush(spd); nat = nat * spintox(H); @@ -571,7 +571,7 @@ void roseCurrents(transmatrix& nat, monster *m, int delta) { } } -hyperpoint keytarget(int i) { +shiftpoint keytarget(int i) { double d = 2 + sin(curtime / 350.); return pc[i]->pat * cpush0(WDIM == 3 ? 2 : 0, d * cgi.scalefactor); } @@ -589,14 +589,14 @@ ld getHornsSize() { return cgi.scalefactor * 0.33; } // used in 3D EX transmatrix swordmatrix[MAXPLAYER]; -hyperpoint swordpos(int id, bool rev, double frac) { +shiftpoint swordpos(int id, bool rev, double frac) { if(WDIM == 3) return pc[id]->pat * swordmatrix[id] * cpush0(2, (rev?-frac:frac) * getSwordSize()); else return pc[id]->pat * xspinpush0(pc[id]->swordangle, (rev?-frac:frac) * getSwordSize()); } -hyperpoint hornpos(int id) { +shiftpoint hornpos(int id) { return pc[id]->pat * xpush0(getHornsSize()); } @@ -649,11 +649,11 @@ void doTraps() { traplist.emplace(t.first + 500, t.second); for(int i=0; i<5; i += 4) try { - transmatrix& tu = gmatrix.at(tl[i]); - transmatrix& tv = gmatrix.at(tl[4-i]); + shiftmatrix& tu = gmatrix.at(tl[i]); + shiftmatrix& tv = gmatrix.at(tl[4-i]); monster* bullet = new monster; bullet->base = tl[i]; - bullet->at = rspintox(inverse(tu) * tC0(tv)); + bullet->at = rspintox(inverse_shift(tu, tC0(tv))); bullet->type = moArrowTrap; bullet->parent = &arrowtrap_fakeparent; bullet->pid = 0; @@ -790,7 +790,7 @@ void movePlayer(monster *m, int delta) { #endif } - transmatrix nat = m->pat; + shiftmatrix nat = m->pat; // if(ka == b+pcOrbPower) dropgreen = true; @@ -827,11 +827,11 @@ void movePlayer(monster *m, int delta) { if(mdd > 1e-6) { hyperpoint jh = hpxy(mdx/100.0, mdy/100.0); - hyperpoint ctr = m->pat * C0; + shiftpoint ctr = m->pat * C0; if(sphere && pconf.alpha > 1.001) for(int i=0; i<3; i++) ctr[i] = -ctr[i]; - hyperpoint h = inverse(m->pat) * rgpushxto0(ctr) * jh; + hyperpoint h = inverse_shift(m->pat, rgpushxto0(ctr) * jh); playerturn[cpid] = -atan2(h[1], h[0]); mgo += mdd; @@ -843,7 +843,7 @@ void movePlayer(monster *m, int delta) { bool forcetarget = (keystate[SDLK_RSHIFT] | keystate[SDLK_LSHIFT]); if(((mousepressed && !forcetarget) || facemouse) && delta > 0 && !mouseout() && !stdracing && GDIM == 2) { // playermoved = true; - hyperpoint h = inverse(m->pat) * mouseh; + hyperpoint h = inverse_shift(m->pat, mouseh); playerturn[cpid] = -atan2(h[1], h[0]); // nat = nat * spin(alpha); // mturn += alpha * 150. / delta; @@ -863,10 +863,10 @@ void movePlayer(monster *m, int delta) { if(playerturn[cpid] && canmove && !blown && WDIM == 2) { m->swordangle -= playerturn[cpid]; - rotate_object(nat, m->ori, spin(playerturn[cpid])); + rotate_object(nat.T, m->ori, spin(playerturn[cpid])); if(inertia_based) m->inertia = spin(-playerturn[cpid]) * m->inertia; } - transmatrix nat0 = nat; + shiftmatrix nat0 = nat; if(m->base->land == laWhirlpool && !markOrb(itOrbWater)) oceanCurrents(nat, m, delta); @@ -942,7 +942,7 @@ void movePlayer(monster *m, int delta) { nextstep: - transmatrix nat1 = nat; + shiftmatrix nat1 = nat; hyperpoint avg_inertia; @@ -983,14 +983,13 @@ void movePlayer(monster *m, int delta) { hyperpoint drag = m->inertia * cinertia * delta / -1. / SCALE; m->inertia += drag; avg_inertia += drag/2; - transmatrix T = inverse(m->pat); ld xp = SCALE / 60000. / isize(below) * delta / 15; ld yp = 0; if(cwt.at->land == laDungeon) xp = -xp; if(cwt.at->land == laWestWall) yp = xp * 1, xp *= 0.7; for(cell *c2: below) if(c2 != m->base) { - hyperpoint h = rspintox(T * tC0(gmatrix[c2])) * hpxy(xp, yp); + hyperpoint h = rspintox(inverse_shift(m->pat, tC0(gmatrix[c2]))) * hpxy(xp, yp); m->inertia += h; avg_inertia += h/2; @@ -1009,8 +1008,8 @@ void movePlayer(monster *m, int delta) { playergoturn[cpid] = 0; if(igo) { go = false; break; } ld r = hypot_d(WDIM, avg_inertia); - apply_parallel_transport(nat, m->ori, rspintox(avg_inertia) * xtangent(r * delta)); - if(WDIM == 3) rotate_object(nat, m->ori, cspin(0, 2, playerturn[cpid]) * cspin(1, 2, playerturny[cpid])); + apply_parallel_transport(nat.T, m->ori, rspintox(avg_inertia) * xtangent(r * delta)); + if(WDIM == 3) rotate_object(nat.T, m->ori, cspin(0, 2, playerturn[cpid]) * cspin(1, 2, playerturny[cpid])); m->vel = r * (600/SCALE); } else if(WDIM == 3) { @@ -1020,15 +1019,15 @@ void movePlayer(monster *m, int delta) { playersmallspin[cpid] = cspin(0, 1, fspin) * cspin(2, 0, igospan[igo]); if(fspin < 360) igo--; else fspin = 0; } - nat = parallel_transport(nat1, m->ori, playersmallspin[cpid] * point3(playerstrafe[cpid], 0, playergo[cpid])); - rotate_object(nat, m->ori, cspin(0, 2, playerturn[cpid]) * cspin(1, 2, playerturny[cpid])); + nat.T = parallel_transport(nat1.T, m->ori, playersmallspin[cpid] * point3(playerstrafe[cpid], 0, playergo[cpid])); + rotate_object(nat.T, m->ori, cspin(0, 2, playerturn[cpid]) * cspin(1, 2, playerturny[cpid])); m->inertia[0] = playerstrafe[cpid] / delta; m->inertia[1] = 0; m->inertia[2] = playergo[cpid] / delta; } else if(playergo[cpid]) { playergoturn[cpid] = igospan[igo]+godir[cpid]; - nat = parallel_transport(nat1, m->ori, spin(playergoturn[cpid]) * xtangent(playergo[cpid])); + nat.T = parallel_transport(nat1.T, m->ori, spin(playergoturn[cpid]) * xtangent(playergo[cpid])); m->inertia = spin(playergoturn[cpid]) * xtangent(playergo[cpid] / delta); } @@ -1118,7 +1117,7 @@ void movePlayer(monster *m, int delta) { int i0 = i; for(int a=0; a<3; a++) v[a] = (i0 % 3) - 1, i0 /= 3; v = v * .1 / hypot_d(3, v); - transmatrix T1 = (i == 13) ? nat : parallel_transport(nat, m->ori, v); + shiftmatrix T1 = (i == 13) ? nat : shiftless(parallel_transport(nat.T, m->ori, v), nat.shift); cell *c3 = c2; while(true) { cell *c4 = findbaseAround(tC0(T1), c3, 1); @@ -1246,7 +1245,7 @@ void movePlayer(monster *m, int delta) { playerfire[cpid] = false; if(items[itOrbHorns] && !m->isVirtual) { - hyperpoint H = hornpos(cpid); + shiftpoint H = hornpos(cpid); for(monster *m2: nonvirtual) { if(m2 == m) continue; @@ -1265,7 +1264,7 @@ void movePlayer(monster *m, int delta) { for(int b=0; b<2; b++) if(sword::orbcount(b) && !m->isVirtual) { for(double d=0; d<=1.001; d += .1) { - hyperpoint H = swordpos(cpid, b, d); + shiftpoint H = swordpos(cpid, b, d); for(monster *m2: nonvirtual) { if(m2 == m) continue; @@ -1343,23 +1342,23 @@ EX monster *getPlayer() { void virtualize(monster *m) { if(doall) forCellCM(c2, m->base) if(!gmatrix.count(c2)) { m->isVirtual = true; - m->pat = m->at; + m->pat = shiftless(m->at); return; } } -bool reflectmatrix(transmatrix& M, cell *c1, cell *c2, bool onlypos) { +bool reflectmatrix(shiftmatrix& M, cell *c1, cell *c2, bool onlypos) { if(!gmatrix.count(c1) || !gmatrix.count(c2)) return false; - transmatrix H = inverse(gmatrix[c1]) * gmatrix[c2]; + transmatrix H = inverse_shift(gmatrix[c1], gmatrix[c2]); transmatrix S = spintox(tC0(H)); ld d = hdist0(tC0(H)); - transmatrix T = xpush(-d/2) * S * inverse(gmatrix[c1]) * M; + transmatrix T = xpush(-d/2) * S * inverse_shift(gmatrix[c1], M); if(onlypos && tC0(T)[0] < 0) return false; M = gmatrix[c1] * inverse(S) * xpush(d/2) * MirrorX * T; return true; } -EX int reflect(cell*& c2, cell*& mbase, transmatrix& nat) { +EX int reflect(cell*& c2, cell*& mbase, shiftmatrix& nat) { int reflections = 0; if(c2 != mbase && c2->wall == waMirrorWall && inmirror(c2)) { if(reflectmatrix(nat, mbase, c2, false)) { @@ -1409,15 +1408,15 @@ EX int reflect(cell*& c2, cell*& mbase, transmatrix& nat) { void moveMimic(monster *m) { virtualize(m); - transmatrix nat = m->pat; + shiftmatrix nat = m->pat; cpid = m->pid; m->footphase = getPlayer()->footphase; // no need to care about Mirror images, as they already have their 'at' matrix reversed :| if(WDIM == 3) { - nat = parallel_transport(nat, m->ori, playersmallspin[cpid] * point3(playerstrafe[cpid], 0, playergo[cpid])); - rotate_object(nat, m->ori, cspin(0, 2, playerturn[cpid]) * cspin(1, 2, playerturny[cpid])); + nat.T = parallel_transport(nat.T, m->ori, playersmallspin[cpid] * point3(playerstrafe[cpid], 0, playergo[cpid])); + rotate_object(nat.T, m->ori, cspin(0, 2, playerturn[cpid]) * cspin(1, 2, playerturny[cpid])); } else nat = nat * spin(playerturn[cpid] + playergoturn[cpid]) * xpush(playergo[cpid]) * spin(-playergoturn[cpid]); @@ -1465,7 +1464,7 @@ void destroyMimics() { EX void teleported() { monster *m = pc[cpid]; m->base = cwt.at; - m->at = rgpushxto0(inverse(gmatrix[cwt.at]) * mouseh) * spin(rand() % 1000 * M_PI / 2000); + m->at = rgpushxto0(inverse_shift(gmatrix[cwt.at], mouseh)) * spin(rand() % 1000 * M_PI / 2000); m->findpat(); destroyMimics(); } @@ -1473,7 +1472,7 @@ EX void teleported() { void shoot(eItem it, monster *m) { monster* bullet = new monster; bullet->base = m->base; - bullet->at = m->at * rspintox(inverse(m->pat) * mouseh); + bullet->at = m->at * rspintox(inverse_shift(m->pat, mouseh)); /* ori */ if(WDIM == 3) bullet->at = bullet->at * cpush(2, 0.15 * SCALE); bullet->type = it == itOrbDragon ? moFireball : it == itOrbAir ? moAirball : moBullet; @@ -1485,7 +1484,7 @@ void shoot(eItem it, monster *m) { } eItem targetRangedOrbKey(orbAction a) { - hyperpoint h = mouseh; + shiftpoint h = mouseh; cell *b = mouseover; monster *mt = mousetarget; @@ -1578,7 +1577,7 @@ void spawn_asteroids(monster *bullet, monster *target) { if(target->hitpoints <= 1) return; hyperpoint rnd = random_spin() * point2(SCALE/3000., 0); - hyperpoint bullet_inertia = inverse(target->pat) * bullet->pat * bullet->inertia; + hyperpoint bullet_inertia = inverse_shift(target->pat, bullet->pat * bullet->inertia); for(int i=0; i<2; i++) { monster* child = new monster; @@ -1608,8 +1607,8 @@ void moveBullet(monster *m, int delta) { m->findpat(); virtualize(m); - transmatrix nat0 = m->pat; - transmatrix nat = m->pat; + shiftmatrix nat0 = m->pat; + shiftmatrix nat = m->pat; bool inertia_based = m->base->land == laAsteroids; @@ -1633,10 +1632,10 @@ void moveBullet(monster *m, int delta) { m->dead = true; if(inertia_based) { - nat = parallel_transport(nat, m->ori, m->inertia * delta); + nat.T = parallel_transport(nat.T, m->ori, m->inertia * delta); } else - nat = parallel_transport(nat, m->ori, fronttangent(delta * SCALE * m->vel / speedfactor())); + nat.T = parallel_transport(nat.T, m->ori, fronttangent(delta * SCALE * m->vel / speedfactor())); cell *c2 = m->findbase(nat, fake::split() ? 10 : 1); if(m->parent && isPlayer(m->parent) && markOrb(itOrbLava) && c2 != m->base && !isPlayerOn(m->base)) @@ -1717,7 +1716,7 @@ void moveBullet(monster *m, int delta) { if(m->type == moAirball && isBlowableMonster(m2->type)) { if(m2->blowoff < curtime) { - hyperpoint h = inverse(m2->pat) * nat0 * C0; + hyperpoint h = inverse_shift(m2->pat, nat0 * C0); if(WDIM == 3) swordmatrix[m2->pid] = spintox(h) * swordmatrix[m2->pid]; else @@ -1729,7 +1728,7 @@ void moveBullet(monster *m, int delta) { } // Hedgehog Warriors only killable outside of the 45 degree angle if(m2->type == moHedge && !peace::on && !slayer) { - hyperpoint h = inverse(m2->pat) * m->pat * C0; + hyperpoint h = inverse_shift(m2->pat, m->pat * C0); if(h[0] > fabsl(h[1])) { m->dead = true; continue; } } if(peace::on && !isIvy(m2->type)) { @@ -1822,7 +1821,7 @@ void moveBullet(monster *m, int delta) { } } -hyperpoint closerTo; +shiftpoint closerTo; bool closer(monster *m1, monster *m2) { return sqdist(m1->pat*C0, closerTo) < sqdist(m2->pat*C0, closerTo); @@ -1832,7 +1831,7 @@ EX bool dragonbreath(cell *dragon) { int randplayer = hrand(numplayers()); monster* bullet = new monster; bullet->base = dragon; - bullet->at = spin_towards(Id, bullet->ori, inverse(gmatrix[dragon]) * tC0(pc[randplayer]->pat), bulletdir(), 1); + bullet->at = spin_towards(Id, bullet->ori, inverse_shift(gmatrix[dragon], tC0(pc[randplayer]->pat)), bulletdir(), 1); bullet->type = moFireball; bullet->parent = bullet; bullet->pid = randplayer; @@ -1882,7 +1881,7 @@ void moveMonster(monster *m, int delta) { if(m->dead) return; cell *c = m->base; - transmatrix goal = gmatrix[c]; + shiftmatrix goal = gmatrix[c]; bool direct = false; // is there a direct path to the target? int directi = 0; // which player has direct path (to set as pid in missiles) @@ -1926,12 +1925,12 @@ void moveMonster(monster *m, int delta) { if(m->isVirtual) { if(inertia_based) { ld r = hypot_d(WDIM, m->inertia); - transmatrix nat = m->pat * rspintox(m->inertia) * xpush(r * delta) * spintox(m->inertia); + shiftmatrix nat = m->pat * rspintox(m->inertia) * xpush(r * delta) * spintox(m->inertia); m->rebasePat(nat, m->base); } return; } - transmatrix nat = m->pat; + shiftmatrix nat = m->pat; if(stunned) { if(m->blowoff > curtime) { @@ -2062,7 +2061,7 @@ void moveMonster(monster *m, int delta) { } if(m->type == moHedge) { - hyperpoint h = inverse(m->pat) * goal * C0; + hyperpoint h = inverse_shift(m->pat, tC0(goal)); if(h[1] < 0) nat = nat * spin(M_PI * delta / 3000 / speedfactor()); else @@ -2101,7 +2100,7 @@ void moveMonster(monster *m, int delta) { int igo = 0; - transmatrix nat0 = nat; + shiftmatrix nat0 = nat; igo_retry: @@ -2120,14 +2119,14 @@ void moveMonster(monster *m, int delta) { if(inertia_based) { if(igo) return; - nat = parallel_transport(nat, m->ori, m->inertia * delta); + nat.T = parallel_transport(nat.T, m->ori, m->inertia * delta); } else if(WDIM == 3 && igo) { ld fspin = rand() % 1000; - nat = parallel_transport(nat0, m->ori, cspin(1,2,fspin) * spin(igospan[igo]) * xtangent(step)); + nat.T = parallel_transport(nat0.T, m->ori, cspin(1,2,fspin) * spin(igospan[igo]) * xtangent(step)); } else { - nat = parallel_transport(nat0, m->ori, spin(igospan[igo]) * xtangent(step)); + nat.T = parallel_transport(nat0.T, m->ori, spin(igospan[igo]) * xtangent(step)); } if(m->type != moRagingBull && !peace::on) @@ -2136,7 +2135,7 @@ void moveMonster(monster *m, int delta) { for(int i=0; iisVirtual) continue; - hyperpoint H = swordpos(i, b, 1); + shiftpoint H = swordpos(i, b, 1); double d = sqdist(H, nat*C0); if(d < SCALE2 * 0.12) { igo++; goto igo_retry; } } @@ -2524,7 +2523,7 @@ EX void turn(int delta) { if(doall) for(cell *c: currentmap->allcells()) activateMonstersAt(c); else - for(unordered_map::iterator it = gmatrix.begin(); it != gmatrix.end(); it++) + for(unordered_map::iterator it = gmatrix.begin(); it != gmatrix.end(); it++) activateMonstersAt(it->first); /* printf("size: gmatrix = %ld, active = %ld, monstersAt = %ld, delta = %d\n", @@ -2757,7 +2756,7 @@ EX void init() { pc[i]->at = Id; else pc[i]->at = spin(2*M_PI*i/players) * xpush(firstland == laMotion ? .5 : .3) * Id; - pc[i]->pat = pc[i]->at; + pc[i]->pat = shiftless(pc[i]->at); pc[i]->base = cwt.at; pc[i]->vel = 0; pc[i]->inBoat = (firstland == laCaribbean || firstland == laOcean || firstland == laLivefjord || @@ -2785,7 +2784,7 @@ EX bool boatAt(cell *c) { return false; } -EX hookset hooks_draw; +EX hookset hooks_draw; EX void clearMonsters() { for(mit it = monstersAt.begin(); it != monstersAt.end(); it++) @@ -2895,7 +2894,7 @@ bool celldrawer::draw_shmup_monster() { monstersAt.equal_range(c); if(p.first == p.second) return false; - ld zlev = -geom3::factor_to_lev(zlevel(tC0(Vd))); + ld zlev = -geom3::factor_to_lev(zlevel(tC0(Vd.T))); vector monsters; @@ -2903,7 +2902,7 @@ bool celldrawer::draw_shmup_monster() { monster* m = it->second; if(c != m->base) continue; // may happen in RogueViz Collatz m->pat = ggmatrix(m->base) * m->at; - transmatrix view = V * m->at; + shiftmatrix view = V * m->at; if(!mouseout()) { if(m->no_targetting) ; else @@ -2975,7 +2974,7 @@ bool celldrawer::draw_shmup_monster() { } if(ths && keyresult[cpid]) { - hyperpoint h = keytarget(cpid); + shiftpoint h = keytarget(cpid); if(WDIM == 2) queuestr(h, vid.fsize, "+", iinf[keyresult[cpid]].color); else { @@ -2992,7 +2991,7 @@ bool celldrawer::draw_shmup_monster() { if(m->parenttype == moPlayer) col = getcs().swordcolor; else if(m->parenttype == moMimic) - col = (mirrorcolor(det(view) < 0) << 8) | 0xFF; + col = (mirrorcolor(det(view.T) < 0) << 8) | 0xFF; else col = (minf[m->parenttype].color << 8) | 0xFF; if(getcs().charid >= 4) { @@ -3004,7 +3003,7 @@ bool celldrawer::draw_shmup_monster() { ShadowV(view, cgi.shPHead); } else { - transmatrix t = view * spin(curtime / 50.0); + shiftmatrix t = view * spin(curtime / 50.0); queuepoly(WDIM == 3 ? t : GDIM == 3 ? mscale(t, cgi.BODY) : mmscale(t, 1.15), cgi.shKnife, col); ShadowV(t, cgi.shKnife); } @@ -3026,14 +3025,14 @@ bool celldrawer::draw_shmup_monster() { break; } case moFlailBullet: case moCrushball: { - transmatrix t = view * spin(curtime / 50.0); + shiftmatrix t = view * spin(curtime / 50.0); queuepoly(mmscale(t, 1.15), cgi.shFlailMissile, (minf[m->type].color << 8) | 0xFF); ShadowV(view, cgi.shFlailMissile); break; } case moAsteroid: { if(GDIM == 3) addradar(view, '*', 0xFFFFFF, 0xC0C0C0FF); - transmatrix t = view; + shiftmatrix t = view; if(WDIM == 3) t = face_the_player(t); t = t * spin(curtime / 500.0); ShadowV(t, cgi.shAsteroid[m->hitpoints & 7]); @@ -3054,7 +3053,7 @@ bool celldrawer::draw_shmup_monster() { if(m->inBoat) m->footphase = 0; color_t col = minf[m->type].color; if(m->type == moMimic) - col = mirrorcolor(det(view) < 0); + col = mirrorcolor(det(view.T) < 0); if(m->type == moSlime) { col = winf[c->wall].color; col |= (col >> 1); diff --git a/sky.cpp b/sky.cpp index b0398b19..28459690 100644 --- a/sky.cpp +++ b/sky.cpp @@ -14,9 +14,9 @@ EX int get_skybrightness(int mul IS(1)) { struct sky_item { cell *c; - transmatrix T; + shiftmatrix T; color_t color; - sky_item(cell *_c, const struct transmatrix _T, color_t _color) : c(_c), T(_T), color(_color) {} + sky_item(cell *_c, const struct shiftmatrix _T, color_t _color) : c(_c), T(_T), color(_color) {} }; struct dqi_sky : drawqueueitem { @@ -35,8 +35,8 @@ EX void prepare_sky() { if(euclid) { if(WDIM == 3 || GDIM == 2) return; if(no_wall_rendering) return; - transmatrix T = ggmatrix(currentmap->gamestart()); - T = gpushxto0(tC0(T)) * T; + shiftmatrix T = ggmatrix(currentmap->gamestart()); + T.T = gpushxto0(tC0(T.T)) * T.T; queuepoly(T, cgi.shEuclideanSky, 0x0044e4FF); queuepolyat(T * zpush(cgi.SKY+0.5) * xpush(cgi.SKY+0.5), cgi.shSun, 0xFFFF00FF, PPR::SKY); } @@ -83,7 +83,8 @@ void dqi_sky::draw() { this_poly.clear(); - transmatrix T1 = Tsh * si.T; + transmatrix T1 = unshift(si.T); + T1 = Tsh * T1; do { this_poly.emplace_back(T1 * skypoint, colors[cw.at]); T1 = T1 * currentmap->adj(cw.at, cw.spin); @@ -108,7 +109,7 @@ void dqi_sky::draw() { 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; - current_display->set_all(ed); + current_display->set_all(ed, 0); if(global_projection) glhr::projection_multiply(glhr::tmtogl(xpush(-vid.ipd * global_projection/2))); glapplymatrix(Id); diff --git a/sphere.cpp b/sphere.cpp index 2c71cda0..f12292d5 100644 --- a/sphere.cpp +++ b/sphere.cpp @@ -176,7 +176,7 @@ struct hrmap_spherical : hrmap_standard { #endif } if(gmatrix0.count(c2) && gmatrix0.count(c1)) { - transmatrix T = inverse(gmatrix0[c1]) * gmatrix0[c2]; + transmatrix T = inverse_shift(gmatrix0[c1], gmatrix0[c2]); if(elliptic && T[LDIM][LDIM] < 0) T = centralsym * T; return T; diff --git a/surface.cpp b/surface.cpp index 41067070..51ceb6e1 100644 --- a/surface.cpp +++ b/surface.cpp @@ -431,7 +431,7 @@ void run_hyperlike() { int lim = (int) sqrt(rug::vertex_limit); for(int r=0; rh; + auto h = unshift(p->h); coverage.emplace_back(h, rchar(id++) + 7 * 256); ld y = asinh(h[1]); @@ -496,7 +496,7 @@ void run_kuen() { vector newmesh(isize(mesh), nullptr); for(auto p: mesh) { - auto px = map_to_surface(p->h, m); + auto px = map_to_surface(unshift(p->h), m); p->surface_point = px; history::progress(XLAT("solving the geodesics on: %1, %2/%3", XLAT(captions[part]), its(p->dexp_id), its(isize(mesh)))); } @@ -544,7 +544,7 @@ void run_kuen() { for(auto t: mesh) { int c = coverages[t->dexp_id]; - coverage.emplace_back(t->h, rchar(t->dexp_id) + 256 * c); + coverage.emplace_back(unshift(t->h), rchar(t->dexp_id) + 256 * c); } // delete the old mesh @@ -559,7 +559,7 @@ template void run_function(T f) { full_mesh(); for(auto p: rug::points) { USING_NATIVE_GEOMETRY; - p->native = f(p->h), + p->native = f(unshift(p->h)), p->valid = true; } } @@ -571,7 +571,7 @@ void run_other() { int it = 0; for(auto p: rug::points) { it++; - auto h = p->h; + auto h = unshift(p->h); p->surface_point = map_to_surface(h, dp); if(1) { @@ -783,7 +783,7 @@ EX void show_surfaces() { if(coverage_style == 2) { if(rug::rugged) rug::close(); } - coverage_matrix = inverse(ggmatrix(coverage_center = cwt.at)); + coverage_matrix = inverse(unshift(ggmatrix(coverage_center = cwt.at))); } else if(rug::handlekeys(sym, uni)) ; else if(doexiton(sym, uni)) popScreen(); @@ -847,9 +847,9 @@ auto surface_hook = addHook(hooks_args, 100, surface_args); void display_coverage() { - transmatrix M = + shiftmatrix M = coverage_style == 3 ? ggmatrix(coverage_center) * coverage_matrix - : Id; + : shiftless(Id); if(coverage_style) for(auto p : coverage) diff --git a/textures.cpp b/textures.cpp index 9bad30fc..6a1d328a 100644 --- a/textures.cpp +++ b/textures.cpp @@ -12,16 +12,16 @@ namespace hr { #if HDR struct texture_triangle { array v; - array tv; - texture_triangle(array _v, array _tv) : v(_v), tv(_tv) {} + array tv; + texture_triangle(array _v, array _tv) : v(_v), tv(_tv) {} }; struct textureinfo : basic_textureinfo { - transmatrix M; + shiftmatrix M; vector triangles; vector vertices; cell *c; - vector matrices; + vector matrices; // these are required to adjust to geometry changes int current_type, symmetries; @@ -50,7 +50,7 @@ struct texture_data { } vector> undos; - vector > pixels_to_draw; + vector > pixels_to_draw; bool loadTextureGL(); bool whitetexture(); @@ -91,21 +91,21 @@ struct texture_config { bool texture_tuned; string texture_tuner; - vector tuned_vertices; + vector tuned_vertices; - bool apply(cell *c, const transmatrix &V, color_t col); + bool apply(cell *c, const shiftmatrix &V, color_t col); void mark_triangles(); void clear_texture_map(); void perform_mapping(); - void mapTextureTriangle(textureinfo &mi, const array& v, const array& tv, int splits); - void mapTextureTriangle(textureinfo &mi, const array& v, const array& tv) { mapTextureTriangle(mi, v, tv, gsplits); } + void mapTextureTriangle(textureinfo &mi, const array& v, const array& tv, int splits); + void mapTextureTriangle(textureinfo &mi, const array& v, const array& tv) { mapTextureTriangle(mi, v, tv, gsplits); } void mapTexture2(textureinfo& mi); void finish_mapping(); void true_remap(); void remap(); bool correctly_mapped; - hyperpoint texture_coordinates(hyperpoint); + hyperpoint texture_coordinates(shiftpoint); void drawRawTexture(); void saveFullTexture(string tn); @@ -349,7 +349,7 @@ void texture_data::saveRawTexture(string tn) { addMessage(XLAT("Saved the raw texture to %1", tn)); } -hyperpoint texture_config::texture_coordinates(hyperpoint h) { +hyperpoint texture_config::texture_coordinates(shiftpoint h) { hyperpoint inmodel; applymodel(h, inmodel); inmodel[0] *= current_display->radius * 1. / current_display->scrsize; @@ -361,11 +361,11 @@ hyperpoint texture_config::texture_coordinates(hyperpoint h) { return inmodel; } -void texture_config::mapTextureTriangle(textureinfo &mi, const array& v, const array& tv, int splits) { +void texture_config::mapTextureTriangle(textureinfo &mi, const array& v, const array& tv, int splits) { if(splits) { array v2 = make_array( mid(v[1], v[2]), mid(v[2], v[0]), mid(v[0], v[1]) ); - array tv2 = make_array( mid(tv[1], tv[2]), mid(tv[2], tv[0]), mid(tv[0], tv[1]) ); + array tv2 = make_array( mid(tv[1], tv[2]), mid(tv[2], tv[0]), mid(tv[0], tv[1]) ); mapTextureTriangle(mi, make_array(v[0], v2[2], v2[1]), make_array(tv[0], tv2[2], tv2[1]), splits-1); mapTextureTriangle(mi, make_array(v[1], v2[0], v2[2]), make_array(tv[1], tv2[0], tv2[2]), splits-1); mapTextureTriangle(mi, make_array(v[2], v2[1], v2[0]), make_array(tv[2], tv2[1], tv2[0]), splits-1); @@ -399,25 +399,25 @@ int celltriangles(cell *c) { return c->type; } -array findTextureTriangle(cell *c, patterns::patterninfo& si, int i) { - transmatrix M = ggmatrix(c) * applyPatterndir(c, si); +array findTextureTriangle(cell *c, patterns::patterninfo& si, int i) { + shiftmatrix M = ggmatrix(c) * applyPatterndir(c, si); return make_array(M * C0, M * get_corner_position(c, i), M * get_corner_position(c, i+1)); } // using: mouseh, mouseouver -int getTriangleID(cell *c, patterns::patterninfo& si, hyperpoint h) { +int getTriangleID(cell *c, patterns::patterninfo& si, shiftpoint h) { // auto si = getpatterninfo0(c); ld quality = 1e10; int best = 0; for(int i=0; i d(poly_outline, slave_color); draw_floorshape(c, V, cgi.shFullFloor, 0, PPR::LINE); - curvepoint(V * C0); + curvepoint(C0); for(int i=0; itype; i++) - curvepoint(V * get_corner_position(c, i)), curvepoint(V * C0); - queuecurve(slave_color, 0, PPR::LINE); + curvepoint(get_corner_position(c, i)), curvepoint(C0); + queuecurve(V, slave_color, 0, PPR::LINE); return false; } @@ -523,7 +523,7 @@ void texture_config::mark_triangles() { for(auto& t: mi.second.triangles) { vector t2; for(int i=0; i<3; i++) - t2.push_back(t.tv[i]); + t2.push_back(unshift(t.tv[i])); prettypoly(t2, master_color, master_color, gsplits); } } @@ -593,11 +593,11 @@ void texture_config::finish_mapping() { for(int a=0; a<8; a++) { auto& tri = tris[a % isize(tris)]; - hyperpoint center = tri.tv[0]; - hyperpoint v1 = tri.tv[1] - center; - hyperpoint v2 = tri.tv[2] - center; + shiftpoint center = tri.tv[0]; + hyperpoint v1 = unshift(tri.tv[1], center.shift) - center.h; + hyperpoint v2 = unshift(tri.tv[2], center.shift) - center.h; texture_order([&] (ld x, ld y) { - hyperpoint h = normalize(center + v1 * x + v2 * y); + shiftpoint h = shiftless(normalize(center.h + v1 * x + v2 * y), center.shift); tinf3.tvertices.push_back(glhr::pointtogl(texture_coordinates(h))); }); } @@ -653,7 +653,7 @@ void texture_config::drawRawTexture() { glflush(); current_display->next_shader_flags = GF_TEXTURE; dynamicval m(pmodel, mdPixel); - current_display->set_all(0); + current_display->set_all(0, 0); glhr::color2(0xFFFFFF20); glBindTexture(GL_TEXTURE_2D, config.data.textureid); for(int i=0; i<4; i++) { @@ -819,10 +819,10 @@ void mousemovement() { switch(panstate) { case tpsModel: if(!newmove && mouseh[2] < 50 && lastmouse[2] < 50) { - panning(lastmouse, mouseh); + panning(shiftless(lastmouse), mouseh); config.perform_mapping(); } - lastmouse = mouseh; newmove = false; + lastmouse = unshift(mouseh); newmove = false; break; case tpsMove: { @@ -913,12 +913,12 @@ void mousemovement() { for(auto& a: config.texture_map) for(auto& t: a.second.triangles) for(auto& v: t.tv) - if(intval(v, mouseh) < tdist) - tdist = intval(v, mouseh); + if(hdist(v, mouseh) < tdist) + tdist = hdist(v, mouseh); for(auto& a: config.texture_map) for(auto& t: a.second.triangles) for(auto& v: t.tv) - if(intval(v, mouseh) < tdist * (1.000001)) + if(hdist(v, mouseh) < tdist * (1.000001)) config.tuned_vertices.push_back(&v); newmove = false; } @@ -1153,7 +1153,7 @@ void showMagicMenu() { if(newmove) { magicmapper_point newpoint; newpoint.c = mouseover; - newpoint.cell_relative = inverse(gmatrix[mouseover]) * mouseh; + newpoint.cell_relative = inverse_shift(gmatrix[mouseover], mouseh); amp.push_back(newpoint); newmove = false; } @@ -1164,7 +1164,7 @@ void showMagicMenu() { initquickqueue(); char letter = 'A'; for(auto& am: amp) { - hyperpoint h = ggmatrix(am.c) * am.cell_relative; + shiftpoint h = ggmatrix(am.c) * am.cell_relative; queuestr(h, vid.fsize, s0+letter, 0xC00000, 1); /* @@ -1427,12 +1427,12 @@ EX void showMenu() { typedef pair point; -point ptc(hyperpoint h) { +point ptc(shiftpoint h) { hyperpoint inmodel = config.texture_coordinates(h); return make_pair(int(inmodel[0] * config.data.twidth), int(inmodel[1] * config.data.twidth)); } -array ptc(const array& h) { +array ptc(const array& h) { return make_array(ptc(h[0]), ptc(h[1]), ptc(h[2])); } @@ -1480,7 +1480,7 @@ void texture_data::undoLock() { undos.emplace_back(nullptr, 1); } -void filltriangle(const array& v, const array& p, color_t col, int lev) { +void filltriangle(const array& v, const array& p, color_t col, int lev) { int d2 = texture_distance(p[0], p[1]), d1 = texture_distance(p[0], p[2]), d0 = texture_distance(p[1], p[2]); @@ -1498,15 +1498,15 @@ void filltriangle(const array& v, const array& p, color else a = 1, b = 2, c = 0; - hyperpoint v3 = mid(v[a], v[b]); + shiftpoint v3 = mid(v[a], v[b]); point p3 = ptc(v3); filltriangle(make_array(v[c], v[a], v3), make_array(p[c], p[a], p3), col, lev+1); filltriangle(make_array(v[c], v[b], v3), make_array(p[c], p[b], p3), col, lev+1); } -void splitseg(const transmatrix& A, const array& angles, const array& h, const array& p, color_t col, int lev) { +void splitseg(const shiftmatrix& A, const array& angles, const array& h, const array& p, color_t col, int lev) { ld newangle = (angles[0] + angles[1]) / 2; - hyperpoint nh = A * xspinpush0(newangle, mapeditor::dtwidth); + shiftpoint nh = A * xspinpush0(newangle, mapeditor::dtwidth); auto np = ptc(nh); filltriangle(make_array(h[0],h[1],nh), make_array(p[0],p[1],np), col, lev); @@ -1518,12 +1518,12 @@ void splitseg(const transmatrix& A, const array& angles, const array mh = make_array(A * xpush0(mapeditor::dtwidth), A * xspinpush0(step, mapeditor::dtwidth), A * xspinpush0(-step, mapeditor::dtwidth)); + array mh = make_array(A * xpush0(mapeditor::dtwidth), A * xspinpush0(step, mapeditor::dtwidth), A * xspinpush0(-step, mapeditor::dtwidth)); auto mp = ptc(mh); filltriangle(mh, mp, col, 0); @@ -1537,36 +1537,36 @@ void fillcircle(hyperpoint h, color_t col) { EX bool texturesym = false; -void actDrawPixel(cell *c, hyperpoint h, color_t col) { +void actDrawPixel(cell *c, shiftpoint h, color_t col) { try { - transmatrix M = gmatrix.at(c); + shiftmatrix M = gmatrix.at(c); auto si = patterns::getpatterninfo0(c); - h = inverse(M * applyPatterndir(c, si)) * h; + hyperpoint h1 = inverse_shift(M * applyPatterndir(c, si), h); auto& tinf = config.texture_map[si.id]; for(auto& M2: tinf.matrices) for(int i = 0; itype; i += si.symmetries) { - fillcircle(M2 * spin(2 * M_PI * i / c->type) * h, col); + fillcircle(M2 * spin(2 * M_PI * i / c->type) * h1, col); if(texturesym) - fillcircle(M2 * spin(2 * M_PI * i / c->type) * Mirror * h, col); + fillcircle(M2 * spin(2 * M_PI * i / c->type) * Mirror * h1, col); } } catch(out_of_range&) {} } -EX void drawPixel(cell *c, hyperpoint h, color_t col) { +EX void drawPixel(cell *c, shiftpoint h, color_t col) { config.data.pixels_to_draw.emplace_back(c, h, col); } EX cell *where; -EX void drawPixel(hyperpoint h, color_t col) { +EX void drawPixel(shiftpoint h, color_t col) { try { again: - transmatrix g0 = gmatrix[where]; + shiftmatrix g0 = gmatrix[where]; ld cdist0 = hdist(tC0(g0), h); forCellEx(c, where) try { - transmatrix g = gmatrix[c]; + shiftmatrix g = gmatrix[c]; ld cdist = hdist(tC0(g), h); if(cdist < cdist0) { cdist0 = cdist; @@ -1580,9 +1580,9 @@ EX void drawPixel(hyperpoint h, color_t col) { catch(out_of_range&) {} } -EX void drawLine(hyperpoint h1, hyperpoint h2, color_t col, int steps IS(10)) { +EX void drawLine(shiftpoint h1, shiftpoint h2, color_t col, int steps IS(10)) { if(steps > 0 && hdist(h1, h2) > mapeditor::dtwidth / 3) { - hyperpoint h3 = mid(h1, h2); + shiftpoint h3 = mid(h1, h2); drawLine(h1, h3, col, steps-1); drawLine(h3, h2, col, steps-1); }