MAJOR CHANGE: replaced (transmatrix,band_shift) pair with shiftmatrix

This commit is contained in:
Zeno Rogue 2020-07-27 18:49:04 +02:00
parent d046023164
commit 82f32607e6
47 changed files with 1266 additions and 1129 deletions

View File

@ -785,19 +785,19 @@ void geometry_information::shift_last_straight(ld z) {
for(int i=last->s; i<isize(hpc); i++) hpc[i] = zpush(z) * hpc[i]; for(int i=last->s; i<isize(hpc); i++) hpc[i] = zpush(z) * hpc[i];
} }
EX void queueball(const transmatrix& V, ld rad, color_t col, eItem what) { EX void queueball(const shiftmatrix& V, ld rad, color_t col, eItem what) {
if(what == itOrbSpeed) { if(what == itOrbSpeed) {
transmatrix V1 = V * cspin(1, 2, M_PI/2); shiftmatrix V1 = V * cspin(1, 2, M_PI/2);
ld tt = ptick(100); ld tt = ptick(100);
for(int t=0; t<5; t++) { for(int t=0; t<5; t++) {
for(int a=-50; a<50; a++) for(int a=-50; a<50; a++)
curvepoint(V1 * cspin(0, 2, a * M_PI/100.) * cspin(0, 1, t * 72 * degree + tt + a*2*M_PI/50.) * xpush0(rad)); curvepoint(cspin(0, 2, a * M_PI/100.) * cspin(0, 1, t * 72 * degree + tt + a*2*M_PI/50.) * xpush0(rad));
queuecurve(col, 0, PPR::LINE); queuecurve(V1, col, 0, PPR::LINE);
} }
return; return;
} }
ld z = 63.43 * degree; ld z = 63.43 * degree;
transmatrix V1 = V * cspin(0, 2, M_PI/2); shiftmatrix V1 = V * cspin(0, 2, M_PI/2);
if(what == itOrbShield) V1 = V * cspin(0, 1, ptick(500)); if(what == itOrbShield) V1 = V * cspin(0, 1, ptick(500));
if(what == itOrbFlash) V1 = V * cspin(0, 1, ptick(1500)); if(what == itOrbFlash) V1 = V * cspin(0, 1, ptick(1500));
if(what == itOrbShield) V1 = V * cspin(1, 2, ptick(1000)); if(what == itOrbShield) V1 = V * cspin(1, 2, ptick(1000));
@ -808,8 +808,8 @@ EX void queueball(const transmatrix& V, ld rad, color_t col, eItem what) {
hyperpoint h0 = A * xpush0(1); hyperpoint h0 = A * xpush0(1);
hyperpoint h1 = B * xpush0(1); hyperpoint h1 = B * xpush0(1);
for(int i=0; i<=8; i++) for(int i=0; i<=8; i++)
curvepoint(V1 * rspintox(normalize(h0*(8-i) + h1*i)) * xpush0(rad)); curvepoint(rspintox(normalize(h0*(8-i) + h1*i)) * xpush0(rad));
queuecurve(col, 0, PPR::LINE); queuecurve(V1, col, 0, PPR::LINE);
}; };
for(int i=0; i<5; i++) { for(int i=0; i<5; i++) {
auto a = cspin(1, 2, (72 * i ) * degree) * spin(z); auto a = cspin(1, 2, (72 * i ) * degree) * spin(z);

View File

@ -139,11 +139,11 @@ void start_poly_debugger(hr_polygon_error& err) {
mapeditor::dtcolor = 0xFF0000FF; mapeditor::dtcolor = 0xFF0000FF;
mapeditor::dtwidth = 0.02; mapeditor::dtwidth = 0.02;
for(int i=0; i<n-1; i++) for(int i=0; i<n-1; i++)
mapeditor::dt_add_line(tC0(err.v[i]), tC0(err.v[i+1]), 0); mapeditor::dt_add_line(shiftless(tC0(err.v[i])), shiftless(tC0(err.v[i+1])), 0);
mapeditor::dtcolor = 0xFFFFFFFF; mapeditor::dtcolor = 0xFFFFFFFF;
for(int i=0; i<n; i++) for(int i=0; i<n; i++)
mapeditor::dt_add_text(tC0(err.v[i]), 0.5, its(i)); mapeditor::dt_add_text(shiftless(tC0(err.v[i])), 0.5, its(i));
#endif #endif
} }
@ -494,27 +494,27 @@ void connection_debugger() {
for(auto& p: debug_polys) { for(auto& p: debug_polys) {
int id = p.second; int id = p.second;
transmatrix V = gmatrix[cwt.at] * p.first; shiftmatrix V = gmatrix[cwt.at] * p.first;
auto& sh = debugged.shapes[id].vertices; auto& sh = debugged.shapes[id].vertices;
for(auto& v: sh) for(auto& v: sh)
curvepoint(V * v); curvepoint(v);
curvepoint(V * sh[0]); curvepoint(sh[0]);
color_t col = colortables['A'][id]; color_t col = colortables['A'][id];
col = darkena(col, 0, 0xFF); col = darkena(col, 0, 0xFF);
if(&p == &last) { if(&p == &last) {
vid.linewidth *= 2; vid.linewidth *= 2;
queuecurve(0xFFFF00FF, col, PPR::LINE); queuecurve(V, 0xFFFF00FF, col, PPR::LINE);
vid.linewidth /= 2; vid.linewidth /= 2;
for(int i=0; i<isize(sh); i++) for(int i=0; i<isize(sh); i++)
queuestr(V * sh[i], vid.fsize, its(i), 0xFFFFFFFF); queuestr(V * sh[i], vid.fsize, its(i), 0xFFFFFFFF);
} }
else else
queuecurve(0xFFFFFFFF, col, PPR::LINE); queuecurve(V, 0xFFFFFFFF, col, PPR::LINE);
} }
quickqueue(); quickqueue();
@ -795,22 +795,21 @@ struct hrmap_arbi : hrmap {
} }
void draw() override { void draw() override {
dq::visited.clear(); dq::clear_all();
dq::enqueue(centerover->master, cview()); dq::enqueue(centerover->master, cview());
while(!dq::drawqueue.empty()) { while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front(); auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p); heptagon *h = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dynamicval<ld> b(band_shift, get<2>(p));
dq::drawqueue.pop(); dq::drawqueue.pop();
if(do_draw(h->c7, V)) drawcell(h->c7, V); if(do_draw(h->c7, V)) drawcell(h->c7, V);
else continue; else continue;
for(int i=0; i<h->type; i++) { for(int i=0; i<h->type; i++) {
transmatrix V1 = V * adj(h, i); shiftmatrix V1 = V * adj(h, i);
bandfixer bf(V1); optimize_shift(V1);
dq::enqueue(h->move(i), V1); dq::enqueue(h->move(i), V1);
} }
} }

View File

@ -677,14 +677,13 @@ struct hrmap_archimedean : hrmap {
} }
void draw() override { void draw() override {
dq::visited.clear(); dq::clear_all();
dq::enqueue(centerover->master, cview()); dq::enqueue(centerover->master, cview());
while(!dq::drawqueue.empty()) { while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front(); auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p); heptagon *h = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dynamicval<ld> b(band_shift, get<2>(p));
dq::drawqueue.pop(); dq::drawqueue.pop();
int id = id_of(h); int id = id_of(h);
@ -699,8 +698,8 @@ struct hrmap_archimedean : hrmap {
if(DUAL && (i&1)) continue; if(DUAL && (i&1)) continue;
h->cmove(i); h->cmove(i);
if(PURE && id >= 2*current.N && h->move(i) && id_of(h->move(i)) >= 2*current.N) continue; 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); shiftmatrix V1 = V * current.adjcell_matrix(h, i);
bandfixer bf(V1); optimize_shift(V1);
dq::enqueue(h->move(i), 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 { transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) override {
if(use_gmatrix && gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) 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; transmatrix gm = Id, where = Id;
auto& cof = current_or_fake(); auto& cof = current_or_fake();
while(h1 != h2) { while(h1 != h2) {

View File

@ -178,14 +178,14 @@ struct hrmap_asonov : hrmap {
} }
void draw() override { void draw() override {
dq::visited_by_matrix.clear(); dq::clear_all();
dq::enqueue_by_matrix(centerover->master, cview()); dq::enqueue_by_matrix(centerover->master, cview());
while(!dq::drawqueue.empty()) { while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front(); auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p); heptagon *h = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dq::drawqueue.pop(); dq::drawqueue.pop();
cell *c = h->c7; cell *c = h->c7;

View File

@ -20,9 +20,9 @@ struct display_data {
/** Camera rotation, used in nonisotropic geometries. */ /** Camera rotation, used in nonisotropic geometries. */
transmatrix local_perspective; transmatrix local_perspective;
/** The view relative to the player character. */ /** The view relative to the player character. */
transmatrix player_matrix; shiftmatrix player_matrix;
/** On-screen coordinates for all the visible cells. */ /** On-screen coordinates for all the visible cells. */
unordered_map<cell*, transmatrix> cellmatrices, old_cellmatrices; unordered_map<cell*, shiftmatrix> cellmatrices, old_cellmatrices;
/** Position of the current map view, relative to the screen (0 to 1). */ /** Position of the current map view, relative to the screen (0 to 1). */
ld xmin, ymin, xmax, ymax; ld xmin, ymin, xmax, ymax;
/** Position of the current map view, in pixels. */ /** Position of the current map view, in pixels. */
@ -43,14 +43,14 @@ struct display_data {
bool in_anaglyph(); bool in_anaglyph();
void set_viewport(int ed); void set_viewport(int ed);
void set_projection(int ed); void set_projection(int ed, ld shift);
void set_mask(int ed); void set_mask(int ed);
void set_all(int ed); void set_all(int ed, ld shift);
/** Which copy of the player cell? */ /** Which copy of the player cell? */
transmatrix which_copy; transmatrix which_copy;
/** On-screen coordinates for all the visible cells. */ /** On-screen coordinates for all the visible cells. */
unordered_map<cell*, vector<transmatrix>> all_drawn_copies; unordered_map<cell*, vector<shiftmatrix>> all_drawn_copies;
}; };
#define View (::hr::current_display->view_matrix) #define View (::hr::current_display->view_matrix)
@ -245,13 +245,13 @@ inline void reset_projection() { new_projection_needed = true; }
EX ld lband_shift; EX ld lband_shift;
void display_data::set_all(int ed) { void display_data::set_all(int ed, ld shift) {
auto t = this; auto t = this;
auto current_projection = tie(ed, pmodel, t, current_rbuffer); 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; last_projection = current_projection;
lband_shift = band_shift; lband_shift = shift;
set_projection(ed); set_projection(ed, shift);
set_mask(ed); set_mask(ed);
set_viewport(ed); set_viewport(ed);
new_projection_needed = false; 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; float rr = (M_PI * 2 * r) / pts;
glcoords.push_back(glhr::makevertex(x + size * sin(rr), y + size * pconf.stretch * cos(rr), 0)); 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::vertices(glcoords);
glhr::set_depthtest(false); glhr::set_depthtest(false);
if(fillcolor) { if(fillcolor) {

View File

@ -418,15 +418,13 @@ EX namespace bt {
} }
void draw() override { void draw() override {
dq::visited.clear(); dq::clear_all();
dq::enqueue(centerover->master, cview()); dq::enqueue(centerover->master, cview());
while(!dq::drawqueue.empty()) { while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front(); auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p); heptagon *h = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
dq::drawqueue.pop(); dq::drawqueue.pop();
@ -435,7 +433,7 @@ EX namespace bt {
drawcell(c, V); drawcell(c, V);
for(int i=0; i<h->type; i++) for(int i=0; i<h->type; 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 { transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) override {
if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) 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; transmatrix gm = Id, where = Id;
while(h1 != h2) { while(h1 != h2) {
if(h1->distance <= h2->distance) { if(h1->distance <= h2->distance) {
@ -809,32 +807,32 @@ EX namespace bt {
#if MAXMDIM == 4 #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; ld yy = log(2) / 2;
const int STEP=3; const int STEP=3;
const ld MUL = 1. / STEP; 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(int a:{-1,1}) {
for(ld t=-STEP; t<STEP; t++) at(a, 1,t*MUL); for(ld t=-STEP; t<STEP; t++) at(a, 1,t*MUL);
for(ld t=-STEP; t<STEP; t++) at(a, -t*MUL,1); for(ld t=-STEP; t<STEP; t++) at(a, -t*MUL,1);
for(ld t=-STEP; t<STEP; t++) at(a, -1,-t*MUL); for(ld t=-STEP; t<STEP; t++) at(a, -1,-t*MUL);
for(ld t=-STEP; t<STEP; t++) at(a, t*MUL,-1); for(ld t=-STEP; t<STEP; t++) at(a, t*MUL,-1);
at(a, 1,-1); at(a, 1,-1);
queuecurve(linecolor, facecolor, PPR::LINE); queuecurve(V, linecolor, facecolor, PPR::LINE);
for(ld t=-STEP; t<STEP; t++) at(1,t*MUL,a); for(ld t=-STEP; t<STEP; t++) at(1,t*MUL,a);
for(ld t=-STEP; t<STEP; t++) at(-t*MUL,1,a); for(ld t=-STEP; t<STEP; t++) at(-t*MUL,1,a);
for(ld t=-STEP; t<STEP; t++) at(-1,-t*MUL,a); for(ld t=-STEP; t<STEP; t++) at(-1,-t*MUL,a);
for(ld t=-STEP; t<STEP; t++) at(t*MUL,-1,a); for(ld t=-STEP; t<STEP; t++) at(t*MUL,-1,a);
at(1,-1,a); at(1,-1,a);
queuecurve(linecolor, facecolor, PPR::LINE); queuecurve(V, linecolor, facecolor, PPR::LINE);
for(ld t=-STEP; t<STEP; t++) at(1,a,t*MUL); for(ld t=-STEP; t<STEP; t++) at(1,a,t*MUL);
for(ld t=-STEP; t<STEP; t++) at(-t*MUL,a,1); for(ld t=-STEP; t<STEP; t++) at(-t*MUL,a,1);
for(ld t=-STEP; t<STEP; t++) at(-1,a,-t*MUL); for(ld t=-STEP; t<STEP; t++) at(-1,a,-t*MUL);
for(ld t=-STEP; t<STEP; t++) at(t*MUL,a,-1); for(ld t=-STEP; t<STEP; t++) at(t*MUL,a,-1);
at(1,a,-1); at(1,a,-1);
queuecurve(linecolor, facecolor, PPR::LINE); queuecurve(V, linecolor, facecolor, PPR::LINE);
} }
/*for(int a:{-1,1}) for(int b:{-1,1}) for(int c:{-1,1}) { /*for(int a:{-1,1}) for(int b:{-1,1}) for(int c:{-1,1}) {
at(0,0,0); at(a,b,c); queuecurve(linecolor, facecolor, PPR::LINE); at(0,0,0); at(a,b,c); queuecurve(linecolor, facecolor, PPR::LINE);

View File

@ -10,7 +10,7 @@ namespace hr {
struct snowball { struct snowball {
transmatrix T; transmatrix T;
transmatrix global; shiftmatrix global;
snowball *prev; snowball *prev;
snowball *next; snowball *next;
double phase; double phase;
@ -25,7 +25,7 @@ struct blizzardcell {
cell *c; cell *c;
int frame; int frame;
int tmp; int tmp;
transmatrix *gm; shiftmatrix *gm;
char wmap; char wmap;
int inward, outward, ward; int inward, outward, ward;
vector<int> qty; vector<int> qty;
@ -123,10 +123,10 @@ EX void drawBlizzards() {
sball.next = &sball2; sball.next = &sball2;
sball2.prev = &sball; 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; double at0 = at + sball.phase;
if(at0>1) at0 -= 1; 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) if(wmascii || wmblack)
queuestr(tpartial, .2, ".", 0xFFFFFF); queuestr(tpartial, .2, ".", 0xFFFFFF);
@ -222,8 +222,8 @@ EX void drawArrowTraps() {
auto r = traplimits(c); auto r = traplimits(c);
try { try {
transmatrix& t0 = gmatrix.at(r[0]); shiftmatrix& t0 = gmatrix.at(r[0]);
transmatrix& t1 = gmatrix.at(r[4]); shiftmatrix& t1 = gmatrix.at(r[4]);
ignore(t0); ignore(t0);
ignore(t1); ignore(t1);
@ -236,10 +236,10 @@ EX void drawArrowTraps() {
int tt = int(fractick(64) * 401); int tt = int(fractick(64) * 401);
for(int u=0; u<2; u++) { for(int u=0; u<2; u++) {
transmatrix& tu = u ? t0 : t1; shiftmatrix& tu = u ? t0 : t1;
transmatrix& tv = u ? t1 : t0; shiftmatrix& tv = u ? t1 : t0;
hyperpoint trel = inverse(tu) * tC0(tv); hyperpoint trel = inverse_shift(tu, tC0(tv));
transmatrix tpartial = tu * rspintox(trel) * xpush(hdist0(trel) * tt / 401.0); shiftmatrix tpartial = tu * rspintox(trel) * xpush(hdist0(trel) * tt / 401.0);
tpartial = tpartial * ypush(.05); tpartial = tpartial * ypush(.05);
if(GDIM == 3) tpartial = tpartial * cspin(1, 2, M_PI/2); if(GDIM == 3) tpartial = tpartial * cspin(1, 2, M_PI/2);
queuepoly(tpartial, cgi.shTrapArrow, 0xFFFFFFFF); queuepoly(tpartial, cgi.shTrapArrow, 0xFFFFFFFF);

View File

@ -6,7 +6,7 @@ int coastvalEdge(cell *c);
struct celldrawer { struct celldrawer {
cell *c; cell *c;
transmatrix V; shiftmatrix V;
color_t fcol; color_t fcol;
color_t wcol; color_t wcol;
@ -18,8 +18,8 @@ struct celldrawer {
bool error; bool error;
bool onradar; bool onradar;
char asciichar; char asciichar;
transmatrix Vboat; shiftmatrix Vboat;
transmatrix Vd; shiftmatrix Vd;
int sl; int sl;
color_t asciiborder; color_t asciiborder;
color_t asciicol1; color_t asciicol1;
@ -52,11 +52,11 @@ struct celldrawer {
bool draw_shmup_monster(); bool draw_shmup_monster();
void draw_gravity_particles(); 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_towerfloor(const cellfunction& cf = coastvalEdge);
void set_zebrafloor(); void set_zebrafloor();
void set_maywarp_floor(); 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 set_emeraldfloor();
void shmup_gravity_floor(); void shmup_gravity_floor();
@ -67,7 +67,7 @@ struct celldrawer {
void do_viewdist(); void do_viewdist();
}; };
inline void drawcell(cell *c, const transmatrix& V) { inline void drawcell(cell *c, const shiftmatrix& V) {
celldrawer dd; celldrawer dd;
dd.c = c; dd.c = c;
dd.V = V; dd.V = V;
@ -703,14 +703,14 @@ void celldrawer::draw_wall() {
int hdir = 0; int hdir = 0;
for(int i=0; i<c->type; i++) if(c->move(i) && c->move(i)->wall == waClosedGate) for(int i=0; i<c->type; i++) if(c->move(i) && c->move(i)->wall == waClosedGate)
hdir = i; 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); queuepolyat(V2, cgi.shPalaceGate, darkena(wcol, 0, 0xFF), wmspatial?PPR::WALL3A:PPR::WALL);
starcol = 0; starcol = 0;
} }
hpcshape& shThisWall = isGrave(c->wall) ? cgi.shCross : cgi.shWall[ct6]; hpcshape& shThisWall = isGrave(c->wall) ? cgi.shCross : cgi.shWall[ct6];
transmatrix V1 = V; shiftmatrix V1 = V;
if(&shThisWall == &cgi.shCross) { if(&shThisWall == &cgi.shCross) {
auto si = patterns::getpatterninfo(c, patterns::PAT_ZEBRA, patterns::SPF_SYM0123); auto si = patterns::getpatterninfo(c, patterns::PAT_ZEBRA, patterns::SPF_SYM0123);
V1 = V * applyPatterndir(c, si); V1 = V * applyPatterndir(c, si);
@ -731,7 +731,7 @@ void celldrawer::draw_wall() {
if(starcol) queuepoly(V1, shThisWall, darkena(starcol, 0, 0xFF)); if(starcol) queuepoly(V1, shThisWall, darkena(starcol, 0, 0xFF));
} }
else { else {
transmatrix Vdepth = mscale(V1, cgi.WALL); shiftmatrix Vdepth = mscale(V1, cgi.WALL);
int alpha = 0xFF; int alpha = 0xFF;
if(c->wall == waIcewall) if(c->wall == waIcewall)
alpha = 0xC0; alpha = 0xC0;
@ -778,7 +778,7 @@ void celldrawer::draw_boat() {
Vboat = V; Vboat = V;
nospin = c->wall == waBoat && applyAnimation(c, Vboat, footphase, LAYER_BOAT); nospin = c->wall == waBoat && applyAnimation(c, Vboat, footphase, LAYER_BOAT);
if(!nospin) Vboat = face_the_player(V); 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), cgi.shBoatOuter, outcol, PPR::BOATLEV2);
queuepolyat(mscale(Vboat, cgi.scalefactor/2-0.01), cgi.shBoatInner, incol, PPR::BOATLEV2); queuepolyat(mscale(Vboat, cgi.scalefactor/2-0.01), cgi.shBoatInner, incol, PPR::BOATLEV2);
return; return;
@ -796,7 +796,7 @@ void celldrawer::draw_boat() {
if(!nospin && c->mondir != NODIR) if(!nospin && c->mondir != NODIR)
Vboat = Vboat * ddspin(c, c->mondir, M_PI); Vboat = Vboat * ddspin(c, c->mondir, M_PI);
else { else {
transmatrix Vx; shiftmatrix Vx;
if(applyAnimation(c, Vx, footphase, LAYER_SMALL)) if(applyAnimation(c, Vx, footphase, LAYER_SMALL))
animations[LAYER_SMALL][c].footphase = 0; 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) { 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;
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)); for(int i=0; i<=steps; i++) curvepoint(bt::get_horopoint(y, x1 + (x2-x1) * i / steps));
queuecurve(gridcolor(c, c->move(dir)), 0, PPR::LINE); queuecurve(V, gridcolor(c, c->move(dir)), 0, PPR::LINE);
}; };
horizontal(yy, 2*xx, xx, 4, bt::bd_up_right); horizontal(yy, 2*xx, xx, 4, bt::bd_up_right);
horizontal(yy, xx, -xx, 8, bt::bd_up); horizontal(yy, xx, -xx, 8, bt::bd_up);
@ -911,7 +911,7 @@ void celldrawer::draw_halfvine() {
i = t; i = t;
qfi.spin = ddspin(c, i, M_PI/S3); qfi.spin = ddspin(c, i, M_PI/S3);
transmatrix V2 = V * qfi.spin; shiftmatrix V2 = V * qfi.spin;
if(wmspatial && wmescher && GDIM == 2) { if(wmspatial && wmescher && GDIM == 2) {
set_floor(cgi.shSemiFeatherFloor[0]); set_floor(cgi.shSemiFeatherFloor[0]);
@ -931,11 +931,11 @@ void celldrawer::draw_halfvine() {
int vcol = winf[waVinePlant].color; int vcol = winf[waVinePlant].color;
int vcol2 = gradient(0, vcol, 0, .8, 1); 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); queuepolyat(GDIM == 2 ? Vdepth : V2, cgi.shSemiFloor[0], darkena(vcol, fd, 0xFF), PPR::WALL3A);
{dynamicval<color_t> p(poly_outline, OUTLINE_TRANS); queuepolyat(V2 * spin(M_PI*2/3), cgi.shSemiFloorShadow, SHADOW_WALL, GDIM == 2 ? PPR::WALLSHADOW : PPR::TRANSPARENT_SHADOW); } {dynamicval<color_t> 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 MAXMDIM >= 4
if(GDIM == 3 && qfi.fshape) { if(GDIM == 3 && qfi.fshape) {
side.tinf = &floor_texture_vertices[shar.id]; 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) if(c->move(d) && c->modmove(d+1) && c->move(d)->land == laMirrorWall && c->modmove(d+1)->land == laMirrorWall)
break; break;
qfi.spin = ddspin(c, d, 0); qfi.spin = ddspin(c, d, 0);
transmatrix V2 = V * qfi.spin; shiftmatrix V2 = V * qfi.spin;
if(!wmblack) for(int d=0; d<c->type; d++) { if(!wmblack) for(int d=0; d<c->type; d++) {
inmirrorcount+=d; inmirrorcount+=d;
queuepolyat(V2 * spin(d*M_PI/S3), cgi.shHalfFloor[2], darkena(fcol, fd, 0xFF), PPR::FLOORa); 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 { else {
qfi.spin = ddspin(c, d, M_PI); qfi.spin = ddspin(c, d, M_PI);
transmatrix V2 = V * qfi.spin; shiftmatrix V2 = V * qfi.spin;
if(!wmblack) { if(!wmblack) {
inmirrorcount++; inmirrorcount++;
queuepolyat(mirrorif(V2, !onleft), cgi.shHalfFloor[ct6], darkena(fcol, fd, 0xFF), PPR::FLOORa); 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) { switch(c->land) {
case laPrairie: case laPrairie:
case laAlchemist: case laAlchemist:
@ -1193,11 +1193,11 @@ void celldrawer::set_land_floor(const transmatrix& Vf) {
set_floor(bspin, cgi.shMercuryBridge[0]); set_floor(bspin, cgi.shMercuryBridge[0]);
// only needed in one direction // only needed in one direction
if(c < c->move(bridgedir)) { if(c < c->move(bridgedir)) {
bspin = Vf * bspin; shiftmatrix Vbspin = Vf * bspin;
queuepoly(bspin, cgi.shMercuryBridge[1], darkena(fcol, fd+1, 0xFF)); queuepoly(Vbspin, cgi.shMercuryBridge[1], darkena(fcol, fd+1, 0xFF));
if(wmspatial) { 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(Vbspin, 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.BOTTOM), cgi.shMercuryBridge[1], darkena(0x202020, 0, 0xFF), PPR::LAKEBOTTOM);
} }
} }
} }
@ -1354,7 +1354,7 @@ void celldrawer::draw_features() {
break; break;
case waBigStatue: { case waBigStatue: {
transmatrix V2 = V; shiftmatrix V2 = V;
double footphase; double footphase;
applyAnimation(c, V2, footphase, LAYER_BOAT); applyAnimation(c, V2, footphase, LAYER_BOAT);
@ -1381,7 +1381,7 @@ void celldrawer::draw_features() {
/* fallthrough */ /* fallthrough */
case waClosePlate: case waOpenPlate: { 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(wmescher && geosupport_football() == 2 && pseudohept(c) && c->land == laPalace) V2 = V * spin(M_PI / c->type);
if(GDIM == 3) { if(GDIM == 3) {
#if MAXMDIM >= 4 #if MAXMDIM >= 4
@ -1433,7 +1433,7 @@ void celldrawer::draw_features() {
if(wmspatial) { if(wmspatial) {
color_t col = winf[waGlass].color; color_t col = winf[waGlass].color;
int dcol = darkena(col, 0, 0x80); int dcol = darkena(col, 0, 0x80);
transmatrix Vdepth = mscale(Vd, cgi.WALL); shiftmatrix Vdepth = mscale(Vd, cgi.WALL);
if(GDIM == 3) if(GDIM == 3)
draw_shapevec(c, V, cgi.shMFloor.levels[SIDE_WALL], dcol, PPR::WALL); draw_shapevec(c, V, cgi.shMFloor.levels[SIDE_WALL], dcol, PPR::WALL);
else else
@ -1543,7 +1543,7 @@ void celldrawer::draw_features() {
if(wmspatial) { if(wmspatial) {
color_t col = winf[c->wall].color; color_t col = winf[c->wall].color;
int dcol = darkena(col, 0, 0xC0); int dcol = darkena(col, 0, 0xC0);
transmatrix Vdepth = mscale(Vd, cgi.WALL); shiftmatrix Vdepth = mscale(Vd, cgi.WALL);
if(GDIM == 3) if(GDIM == 3)
draw_shapevec(c, V, cgi.shMFloor.levels[SIDE_WALL], dcol, PPR::WALL); draw_shapevec(c, V, cgi.shMFloor.levels[SIDE_WALL], dcol, PPR::WALL);
else else
@ -1581,8 +1581,8 @@ void celldrawer::draw_features() {
ld rad = cgi.hexf * (.3 * (u + ds)); ld rad = cgi.hexf * (.3 * (u + ds));
int tcol = darkena(gradient(forecolor, backcolor, 0, rad, 1.5 * cgi.hexf), 0, 0xFF); int tcol = darkena(gradient(forecolor, backcolor, 0, rad, 1.5 * cgi.hexf), 0, 0xFF);
PRING(a) PRING(a)
curvepoint(V*xspinpush0(a * M_PI / cgi.S42, rad)); curvepoint(xspinpush0(a * M_PI / cgi.S42, rad));
queuecurve(tcol, 0, PPR::LINE); queuecurve(V, tcol, 0, PPR::LINE);
} }
} }
if(hasTimeout(c)) V2 = V2 * spintick(c->land == laPower ? 5000 : 500); 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) { else if(prod) {
if(a < c->type-2 && !in_s2xe()) { if(a < c->type-2 && !in_s2xe()) {
ld d = in_e2xe() ? sqhypot_d(2, tC0(V)) : V[2][2]; ld d = in_e2xe() ? sqhypot_d(2, unshift(tC0(V))) : V[2][2];
hyperpoint h = (V * cgi.walltester[ofs + a]); hyperpoint h = (unshift(V) * cgi.walltester[ofs + a]);
ld d1 = in_e2xe() ? sqhypot_d(2, h) : h[2]; ld d1 = in_e2xe() ? sqhypot_d(2, h) : h[2];
if(d1 >= d - 1e-6) continue; if(d1 >= d - 1e-6) continue;
} }
else if(a == c->type-1) { 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) { 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) { if(qfi.fshape && wmescher) {
@ -1763,12 +1763,12 @@ void celldrawer::check_rotations() {
ds.best = c; ds.best = c;
ds.speed = spd; ds.speed = spd;
if(prod) { if(prod) {
auto pd = product_decompose(tC0(V)); auto pd = product_decompose(unshift(tC0(V)));
ds.total += pd.second; ds.total += pd.second;
ds.depth += pd.first; ds.depth += pd.first;
} }
else else
ds.total += tC0(V); ds.total += unshift(tC0(V));
ds.qty++; ds.qty++;
ds.point = normalize_flat(ds.total); ds.point = normalize_flat(ds.total);
if(prod) ds.point = zshift(ds.point, ds.depth / ds.qty); if(prod) ds.point = zshift(ds.point, ds.depth / ds.qty);
@ -1812,7 +1812,7 @@ void celldrawer::check_rotations() {
void celldrawer::bookkeeping() { void celldrawer::bookkeeping() {
bool orig = false; bool orig = false;
if(!inmirrorcount) { if(!inmirrorcount) {
transmatrix& gm = gmatrix[c]; shiftmatrix& gm = gmatrix[c];
orig = (gm[LDIM][LDIM] == 0) || hdist0(tC0(gm)) >= hdist0(tC0(V)); orig = (gm[LDIM][LDIM] == 0) || hdist0(tC0(gm)) >= hdist0(tC0(V));
if(orig) gm = V; if(orig) gm = V;
current_display->all_drawn_copies[c].emplace_back(V); current_display->all_drawn_copies[c].emplace_back(V);
@ -1837,8 +1837,8 @@ void celldrawer::bookkeeping() {
else { else {
playerV = V * ddspin(c, cwt.spin, 0); playerV = V * ddspin(c, cwt.spin, 0);
if(cwt.mirrored) playerV = playerV * Mirror; if(cwt.mirrored) playerV = playerV * Mirror;
if((!confusingGeometry() && !fake::split() && !inmirrorcount) || eqmatrix(V, current_display->which_copy, 1e-2)) if((!confusingGeometry() && !fake::split() && !inmirrorcount) || eqmatrix(unshift(V), current_display->which_copy, 1e-2))
current_display->which_copy = V; current_display->which_copy = unshift(V);
if(orig) cwtV = playerV; if(orig) cwtV = playerV;
} }
} }
@ -1861,7 +1861,7 @@ void celldrawer::bookkeeping() {
if(c->cpdist <= orbrange) if(multi::players > 1 || multi::alwaysuse) if(c->cpdist <= orbrange) if(multi::players > 1 || multi::alwaysuse)
for(int i=0; i<multi::players; i++) if(multi::playerActive(i)) { for(int i=0; i<multi::players; i++) if(multi::playerActive(i)) {
double dfc = intval(tC0(V), tC0(multi::crosscenter[i])); double dfc = hdist(tC0(V), tC0(multi::crosscenter[i]));
if(dfc < multi::ccdist[i] && celldistance(playerpos(i), c) <= orbrange) { if(dfc < multi::ccdist[i] && celldistance(playerpos(i), c) <= orbrange) {
multi::ccdist[i] = dfc; multi::ccdist[i] = dfc;
multi::ccat[i] = c; multi::ccat[i] = c;
@ -1932,8 +1932,8 @@ void celldrawer::draw_cellstat() {
void celldrawer::draw_wall_full() { void celldrawer::draw_wall_full() {
transmatrix Vf0; shiftmatrix Vf0;
const transmatrix& Vf = (chasmg && wmspatial) ? (Vf0=mscale(V, cgi.BOTTOM)) : V; const shiftmatrix& Vf = (chasmg && wmspatial) ? (Vf0=mscale(V, cgi.BOTTOM)) : V;
#if CAP_SHAPES #if CAP_SHAPES
int flooralpha = 255; int flooralpha = 255;
@ -1976,7 +1976,7 @@ void celldrawer::draw_wall_full() {
} }
if(c->land == laZebra) fd++; if(c->land == laZebra) fd++;
if(c->land == laHalloween && !wmblack) { if(c->land == laHalloween && !wmblack) {
transmatrix Vdepth = wmspatial ? mscale(V, cgi.BOTTOM) : V; shiftmatrix Vdepth = wmspatial ? mscale(V, cgi.BOTTOM) : V;
if(GDIM == 3) if(GDIM == 3)
draw_shapevec(c, V, cgi.shFullFloor.levels[SIDE_LAKE], darkena(firecolor(0, 10), 0, 0xDF), PPR::TRANSPARENT_LAKE); draw_shapevec(c, V, cgi.shFullFloor.levels[SIDE_LAKE], darkena(firecolor(0, 10), 0, 0xDF), PPR::TRANSPARENT_LAKE);
else else
@ -2178,7 +2178,7 @@ void celldrawer::draw_wall_full() {
#if CAP_SHAPES #if CAP_SHAPES
int sha = shallow(c); 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) { if(wmspatial && c->wall == waShallow && WDIM == 2) {
color_t col = (highwall(c) || c->wall == waTower) ? wcol : fcol; color_t col = (highwall(c) || c->wall == waTower) ? wcol : fcol;
forCellIdEx(c2, i, c) if(chasmgraph(c2) && c2->wall != waShallow) forCellIdEx(c2, i, c) if(chasmgraph(c2) && c2->wall != waShallow)
@ -2246,8 +2246,8 @@ void celldrawer::draw_item_full() {
if(it == itCompass && isPlayerOn(c)) { if(it == itCompass && isPlayerOn(c)) {
cell *c1 = c ? findcompass(c) : NULL; cell *c1 = c ? findcompass(c) : NULL;
if(c1) { if(c1) {
transmatrix P = ggmatrix(c1); shiftmatrix P = ggmatrix(c1);
hyperpoint P1 = tC0(P); shiftpoint P1 = tC0(P);
queuestr(P1, 2*vid.fsize, "X", 0x10100 * int(128 + 100 * sintick(150))); 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))); 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(isize(ptds) != q) {
if(WDIM == 2 && GDIM == 3 && abs(cgi.SLEV[sl] - cgi.FLOOR) > 1e-6) if(WDIM == 2 && GDIM == 3 && abs(cgi.SLEV[sl] - cgi.FLOOR) > 1e-6)
pushdown(c, q, V, cgi.SLEV[sl] - cgi.FLOOR, false, false); pushdown(c, q, V, cgi.SLEV[sl] - cgi.FLOOR, false, false);
if(GDIM ==2 && abs(geom3::factor_to_lev(zlevel(tC0(Vboat)))) > 1e-6) 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))), !isMultitile(c->monst), false); pushdown(c, q, V, -geom3::factor_to_lev(zlevel(tC0(Vboat.T))), !isMultitile(c->monst), false);
} }
#endif #endif
} }
@ -2461,22 +2461,22 @@ void celldrawer::draw_gravity_particles() {
switch(gravity_state) { switch(gravity_state) {
case gsNormal: case gsNormal:
for(int i=0; i<6; i++) { 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); queueline(mmscale(T, levf(r0)) * C0, mmscale(T, levf(r1)) * C0, grav_normal_color);
} }
break; break;
case gsAnti: case gsAnti:
for(int i=0; i<6; i++) { 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); queueline(mmscale(T, levf(r0)) * C0, mmscale(T, levf(r1)) * C0, antigrav_color);
} }
break; break;
case gsLevitation: case gsLevitation:
for(int i=0; i<6; i++) { for(int i=0; i<6; i++) {
transmatrix T0 = V * spin(i*degree*60 + tt/60. * degree) * xpush(cgi.crossf/3); shiftmatrix 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 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); ld lv = levf(GDIM == 3 ? (i+0.5)/6 : 0.5);
queueline(mmscale(T0, lv) * C0, mmscale(T1, lv) * C0, levitate_color); queueline(mmscale(T0, lv) * C0, mmscale(T1, lv) * C0, levitate_color);
} }
@ -2488,24 +2488,24 @@ void celldrawer::draw_gravity_particles() {
switch(gravity_state) { switch(gravity_state) {
case gsNormal: case gsNormal:
for(int i=0; i<6; i++) { for(int i=0; i<6; i++) {
transmatrix T0 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * (1-r0)); shiftmatrix 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 T1 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * (1-r1));
queueline(T0 * C0, T1 * C0, grav_normal_color); queueline(T0 * C0, T1 * C0, grav_normal_color);
} }
break; break;
case gsAnti: case gsAnti:
for(int i=0; i<6; i++) { for(int i=0; i<6; i++) {
transmatrix T0 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * r0); shiftmatrix T0 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * r0);
transmatrix T1 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * r1); shiftmatrix T1 = V * spin(i*degree*60) * xpush(cgi.crossf/3 * r1);
queueline(T0 * C0, T1 * C0, antigrav_color); queueline(T0 * C0, T1 * C0, antigrav_color);
} }
break; break;
case gsLevitation: case gsLevitation:
for(int i=0; i<6; i++) { for(int i=0; i<6; i++) {
transmatrix T0 = V * spin(i*degree*60 + tt/60. * degree) * xpush(cgi.crossf/3); shiftmatrix 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 T1 = V * spin(i*degree*60 + (tt/60. + 30) * degree) * xpush(cgi.crossf/3);
queueline(T0 * C0, T1 * C0, levitate_color); queueline(T0 * C0, T1 * C0, levitate_color);
} }
break; break;
@ -2555,8 +2555,8 @@ void celldrawer::draw() {
if(cw2.mirrored != cw.mirrored) V = V * Mirror; if(cw2.mirrored != cw.mirrored) V = V * Mirror;
if(cw2.spin) V = V * spin(2*M_PI*cw2.spin/cw2.at->type); if(cw2.spin) V = V * spin(2*M_PI*cw2.spin/cw2.at->type);
cw2.spin = 0; cw2.spin = 0;
dynamicval<transmatrix> dc(cwtV, cwtV); dynamicval<shiftmatrix> dc(cwtV, cwtV);
cwtV = V * inverse(gmatrix0[c]) * cwtV; cwtV = V * inverse_shift(gmatrix0[c], cwtV);
drawcell(cw2.at, V); drawcell(cw2.at, V);
inmirrorcount -= cmc; inmirrorcount -= cmc;
return; return;
@ -2701,7 +2701,7 @@ void celldrawer::draw() {
#endif #endif
#if CAP_MODEL #if CAP_MODEL
netgen::buildVertexInfo(c, V); netgen::buildVertexInfo(c, unshift(V));
#endif #endif
} }
} }
@ -2774,7 +2774,7 @@ void celldrawer::set_maywarp_floor() {
else set_floor(cgi.shFloor); 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 = auto si =
euc::in(2,6) ? euc::in(2,6) ?

View File

@ -2003,7 +2003,7 @@ EX void showCustomizeChar() {
double alpha = atan2(mousex - vid.xres/2, mousey - firsty) - M_PI/2; double alpha = atan2(mousex - vid.xres/2, mousey - firsty) - M_PI/2;
V = V * spin(alpha); V = V * spin(alpha);
drawMonsterType(moPlayer, NULL, V, 0, cc_footphase / scale, NOCOLOR); drawMonsterType(moPlayer, NULL, shiftless(V), 0, cc_footphase / scale, NOCOLOR);
quickqueue(); quickqueue();
keyhandler = [] (int sym, int uni) { keyhandler = [] (int sym, int uni) {

View File

@ -12,7 +12,7 @@ EX int frames;
EX bool outoffocus = false; EX bool outoffocus = false;
EX int mousex, mousey; EX int mousex, mousey;
EX hyperpoint mouseh, mouseoh; EX shiftpoint mouseh, mouseoh;
EX bool pandora_leftclick, pandora_rightclick; EX bool pandora_leftclick, pandora_rightclick;
@ -66,17 +66,17 @@ EX int lastt;
EX bool mouseout() { EX bool mouseout() {
if((getcstat != '-' && getcstat) || (lgetcstat && lgetcstat != '-')) return true; if((getcstat != '-' && getcstat) || (lgetcstat && lgetcstat != '-')) return true;
return outofmap(mouseh); return outofmap(mouseh.h);
} }
EX bool mouseout2() { EX bool mouseout2() {
if((getcstat && getcstat != '-') || (lgetcstat && lgetcstat != '-')) return true; if((getcstat && getcstat != '-') || (lgetcstat && lgetcstat != '-')) return true;
return outofmap(mouseh) || outofmap(mouseoh); return outofmap(mouseh.h) || outofmap(mouseoh.h);
} }
EX movedir vectodir(hyperpoint P) { 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; if(GDIM == 3 && WDIM == 2) U = radar_transform * U;
P = direct_exp(lp_iapply(P)); P = direct_exp(lp_iapply(P));
@ -137,18 +137,18 @@ EX void movepckeydir(int d) {
EX void calcMousedest() { EX void calcMousedest() {
if(mouseout()) return; if(mouseout()) return;
if(vid.revcontrol == true) { mouseh[0] = -mouseh[0]; mouseh[1] = -mouseh[1]; } 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; mousedest.d = -1;
cellwalker bcwt = cwt; cellwalker bcwt = cwt;
vector<ld> dists(cwt.at->type); vector<ld> dists(cwt.at->type);
transmatrix U = ggmatrix(cwt.at); shiftmatrix U = ggmatrix(cwt.at);
for(int i=0; i<cwt.at->type; i++) { for(int i=0; i<cwt.at->type; i++) {
transmatrix T = currentmap->adj(cwt.at, 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; i<cwt.at->type; i++) if(dists[i] < mousedist) { for(int i=0; i<cwt.at->type; 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 T2 = eupush( tC0(inverse(View)) );
transmatrix nlp = View * T2; transmatrix nlp = View * T2;
auto rV = inverse(nlp) * View; 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); shift_view(-h);
rotate_view(cspin(dir, 2, val)); rotate_view(cspin(dir, 2, val));
shift_view(h); shift_view(h);
@ -1087,7 +1087,7 @@ EX bool gmodekeys(int sym, int uni) {
ld maxs = 0; ld maxs = 0;
auto& cd = current_display; auto& cd = current_display;
for(auto& p: gmatrix) for(int i=0; i<p.first->type; i++) { for(auto& p: gmatrix) for(int i=0; i<p.first->type; i++) {
hyperpoint h = tC0(p.second * currentmap->adj(p.first, i)); shiftpoint h = tC0(p.second * currentmap->adj(p.first, i));
hyperpoint onscreen; hyperpoint onscreen;
applymodel(h, onscreen); applymodel(h, onscreen);
maxs = max(maxs, onscreen[0] / cd->xsize); maxs = max(maxs, onscreen[0] / cd->xsize);

View File

@ -676,15 +676,13 @@ struct hrmap_crystal : hrmap_standard {
// for(int i=0; i<S6; i++) queuepoly(ggmatrix(cwt.at), shWall3D[i], 0xFF0000FF); // for(int i=0; i<S6; i++) queuepoly(ggmatrix(cwt.at), shWall3D[i], 0xFF0000FF);
dq::visited_by_matrix.clear(); dq::clear_all();
dq::enqueue_by_matrix(centerover->master, cview()); dq::enqueue_by_matrix(centerover->master, cview());
while(!dq::drawqueue.empty()) { while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front(); auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p); heptagon *h = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
dq::drawqueue.pop(); dq::drawqueue.pop();
cell *c = h->c7; cell *c = h->c7;
@ -694,7 +692,7 @@ struct hrmap_crystal : hrmap_standard {
if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000) continue; if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000) continue;
for(int d=0; d<S7; d++) { for(int d=0; d<S7; d++) {
dq::enqueue_by_matrix(h->move(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; if(h2 == h1) return Id;
for(int i=0; i<S7; i++) if(h2 == h1->move(i)) return adj(h1->master, i); for(int i=0; i<S7; i++) if(h2 == h1->move(i)) return adj(h1->master, i);
if(gmatrix0.count(h2) && gmatrix0.count(h1)) 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)); println(hlog, "unknown relmatrix, distance = ", celldistance(h1, h2));
return xpush(999); return xpush(999);
} }
@ -828,7 +826,7 @@ EX ld compass_angle() {
return (bitr ? M_PI/8 : 0) - master_to_c7_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; if(!cryst) return false;
@ -846,7 +844,7 @@ EX bool crystal_cell(cell *c, transmatrix V) {
ld dist = cellgfxdist(c, 0); ld dist = cellgfxdist(c, 0);
for(int i=0; i<S7; i++) { for(int i=0; i<S7; i++) {
transmatrix T = V * spin(compass_angle() - 2 * M_PI * i / S7) * xpush(dist*.3); shiftmatrix T = V * spin(compass_angle() - 2 * M_PI * i / S7) * xpush(dist*.3);
auto co = m->hcoords[c->master]; auto co = m->hcoords[c->master];
auto lw = m->makewalker(co, i); 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; pac[3] = pbc[3] = 1;
rug::rugpoint *rac = rug::addRugpoint(hac, 0); rug::rugpoint *rac = rug::addRugpoint(shiftless(hac), 0);
rug::rugpoint *rbc = rug::addRugpoint(hbc, 0); rug::rugpoint *rbc = rug::addRugpoint(shiftless(hbc), 0);
rac->native = pac; rac->native = pac;
rbc->native = pbc; rbc->native = pbc;
rac->valid = true; rac->valid = true;
@ -1268,7 +1266,7 @@ EX void build_rugdata() {
cell *c = gp.first; cell *c = gp.first;
if(c->wall == waInvisibleFloor) continue; if(c->wall == waInvisibleFloor) continue;
const transmatrix& V = gp.second; const shiftmatrix& V = gp.second;
auto co = m->get_coord(c); auto co = m->get_coord(c);
vector<ldcoord> vcoord(c->type); vector<ldcoord> vcoord(c->type);
@ -1307,7 +1305,7 @@ EX void build_rugdata() {
for(int i=0; i<c->type; i++) { for(int i=0; i<c->type; i++) {
int j = (i+1) % c->type; int j = (i+1) % c->type;
if((vco[i][3] >= 0) != (hco[3] >= 0) || (vco[j][3] >= 0) != (hco[3] >= 0)) { 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)));
} }
} }
} }

View File

@ -63,10 +63,8 @@ struct drawqueueitem {
/** \brief Drawqueueitem used to draw polygons. The majority of drawqueueitems fall here. */ /** \brief Drawqueueitem used to draw polygons. The majority of drawqueueitems fall here. */
struct dqi_poly : drawqueueitem { struct dqi_poly : drawqueueitem {
/** \brief see hr::band_shift */
ld band_shift;
/** \brief matrix used to transform the model */ /** \brief matrix used to transform the model */
transmatrix V; shiftmatrix V;
/** \brief a vector of GL vertices where the model is stored */ /** \brief a vector of GL vertices where the model is stored */
const vector<glvertex> *tab; const vector<glvertex> *tab;
/** \brief the where does the model start */ /** \brief the where does the model start */
@ -95,10 +93,8 @@ struct dqi_poly : drawqueueitem {
/** \brief Drawqueueitem used to draw lines */ /** \brief Drawqueueitem used to draw lines */
struct dqi_line : drawqueueitem { struct dqi_line : drawqueueitem {
/** \brief see hr::band_shift */
ld band_shift;
/** \brief starting and ending point */ /** \brief starting and ending point */
hyperpoint H1, H2; shiftpoint H1, H2;
/** \brief how accurately to render the line */ /** \brief how accurately to render the line */
int prf; int prf;
/** \brief width of this line */ /** \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)); // printf("%08X | %d texts, %d vertices\n", text_color, texts_merged, isize(text_vertices));
current_display->next_shader_flags = GF_TEXTURE; current_display->next_shader_flags = GF_TEXTURE;
dynamicval<eModel> m(pmodel, mdPixel); dynamicval<eModel> 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); glBindTexture(GL_TEXTURE_2D, text_texture);
glhr::color2(text_color); glhr::color2(text_color);
glhr::set_depthtest(false); 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; return (models::sin_ball * H[2] > models::cos_ball * H[1]) ? -1 : 1;
if(pmodel == mdHemisphere) { if(pmodel == mdHemisphere) {
hyperpoint res; hyperpoint res;
applymodel(H, res); applymodel(shiftless(H), res);
return res[2] < 0 ? -1 : 1; return res[2] < 0 ? -1 : 1;
} }
if(pmodel == mdSpiral && pconf.spiral_cone < 360) { if(pmodel == mdSpiral && pconf.spiral_cone < 360) {
return cone_side(H); return cone_side(shiftless(H));
} }
return 0; return 0;
} }
@ -338,20 +334,20 @@ void fixpoint(glvertex& hscr, hyperpoint H) {
bad = mid; bad = mid;
} }
hyperpoint Hscr; 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); 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) { if(true) {
ld z = current_display->radius; ld z = current_display->radius;
// if(pconf.alpha + H[2] <= BEHIND_LIMIT && pmodel == mdDisk) poly_flags |= POLY_BEHIND; // if(pconf.alpha + H[2] <= BEHIND_LIMIT && pmodel == mdDisk) poly_flags |= POLY_BEHIND;
if(spherespecial) { if(spherespecial) {
auto H0 = H.h;
if(correct_side(H)) { if(correct_side(H0)) {
poly_flags |= POLY_INFRONT, last_infront = false; poly_flags |= POLY_INFRONT, last_infront = false;
if(!knowgood || (spherespecial > 0 ? H[2]>goodpoint[2] : H[2]<goodpoint[2])) goodpoint = H, knowgood = true; if(!knowgood || (spherespecial > 0 ? H[2]>goodpoint[2] : H[2]<goodpoint[2])) goodpoint = H0, knowgood = true;
} }
else if(sphere && (poly_flags & POLY_ISSIDE)) { else if(sphere && (poly_flags & POLY_ISSIDE)) {
double curnorm = H[0]*H[0]+H[1]*H[1]+H[2]*H[2]; double curnorm = H[0]*H[0]+H[1]*H[1]+H[2]*H[2];
@ -368,8 +364,8 @@ void addpoint(const hyperpoint& H) {
} }
else { else {
poly_flags |= POLY_NOTINFRONT; poly_flags |= POLY_NOTINFRONT;
tofix.push_back(make_pair(glcoords.size(), H)); tofix.push_back(make_pair(glcoords.size(), H0));
add1(H); add1(H0);
return; return;
} }
} }
@ -378,13 +374,12 @@ void addpoint(const hyperpoint& H) {
if(sphere && pmodel == mdSpiral) { if(sphere && pmodel == mdSpiral) {
if(isize(glcoords)) { if(isize(glcoords)) {
hyperpoint Hscr1; hyperpoint Hscr1;
band_shift += 2 * M_PI; shiftpoint H1 = H; H1.shift += 2 * M_PI;
applymodel(H, Hscr1); applymodel(H1, Hscr1);
if(hypot_d(2, Hlast-Hscr1) < hypot_d(2, Hlast-Hscr)) { Hscr = Hscr1; } if(hypot_d(2, Hlast-Hscr1) < hypot_d(2, Hlast-Hscr)) { Hscr = Hscr1; }
band_shift -= 4 * M_PI; H1.shift -= 4 * M_PI;
applymodel(H, Hscr1); applymodel(H1, Hscr1);
if(hypot_d(2, Hlast-Hscr1) < hypot_d(2, Hlast-Hscr)) { Hscr = Hscr1; } if(hypot_d(2, Hlast-Hscr1) < hypot_d(2, Hlast-Hscr)) { Hscr = Hscr1; }
band_shift += 2 * M_PI;
} }
Hlast = Hscr; Hlast = Hscr;
} }
@ -412,18 +407,18 @@ void coords_to_poly() {
} }
} }
bool behind3(hyperpoint h) { bool behind3(shiftpoint h) {
if(pmodel == mdGeodesic) if(pmodel == mdGeodesic)
h = lp_apply(inverse_exp(h)); return lp_apply(inverse_exp(h))[2] < 0;
return h[2] < 0; return h[2] < 0;
} }
void addpoly(const transmatrix& V, const vector<glvertex> &tab, int ofs, int cnt) { void addpoly(const shiftmatrix& V, const vector<glvertex> &tab, int ofs, int cnt) {
if(pmodel == mdPixel) { if(pmodel == mdPixel) {
for(int i=ofs; i<ofs+cnt; i++) { for(int i=ofs; i<ofs+cnt; i++) {
hyperpoint h = glhr::gltopoint(tab[i]); hyperpoint h = glhr::gltopoint(tab[i]);
h[3] = 1; h[3] = 1;
h = V * h; h = V.T * h;
add1(h); add1(h);
} }
return; return;
@ -432,35 +427,35 @@ void addpoly(const transmatrix& V, const vector<glvertex> &tab, int ofs, int cnt
if(among(pmodel, mdPerspective, mdGeodesic)) { if(among(pmodel, mdPerspective, mdGeodesic)) {
if(poly_flags & POLY_TRIANGLES) { if(poly_flags & POLY_TRIANGLES) {
for(int i=ofs; i<ofs+cnt; i+=3) { for(int i=ofs; i<ofs+cnt; i+=3) {
hyperpoint h0 = V * glhr::gltopoint(tab[i]); shiftpoint h0 = V * glhr::gltopoint(tab[i]);
hyperpoint h1 = V * glhr::gltopoint(tab[i+1]); shiftpoint h1 = V * glhr::gltopoint(tab[i+1]);
hyperpoint h2 = V * glhr::gltopoint(tab[i+2]); shiftpoint h2 = V * glhr::gltopoint(tab[i+2]);
if(!behind3(h0) && !behind3(h1) && !behind3(h2)) if(!behind3(h0) && !behind3(h1) && !behind3(h2))
addpoint(h0), addpoint(h1), addpoint(h2); addpoint(h0), addpoint(h1), addpoint(h2);
} }
} }
else { else {
for(int i=ofs; i<ofs+cnt; i++) { for(int i=ofs; i<ofs+cnt; i++) {
hyperpoint h = V * glhr::gltopoint(tab[i]); shiftpoint h = V * glhr::gltopoint(tab[i]);
if(!behind3(h)) addpoint(h); if(!behind3(h)) addpoint(h);
} }
} }
return; return;
} }
hyperpoint last = V * glhr::gltopoint(tab[ofs]); shiftpoint last = V * glhr::gltopoint(tab[ofs]);
bool last_behind = is_behind(last); bool last_behind = is_behind(last.h);
if(!last_behind) addpoint(last); if(!last_behind) addpoint(last);
hyperpoint enter = C0; hyperpoint enter = C0;
hyperpoint firstleave; hyperpoint firstleave;
int start_behind = last_behind ? 1 : 0; int start_behind = last_behind ? 1 : 0;
for(int i=ofs+1; i<ofs+cnt; i++) { for(int i=ofs+1; i<ofs+cnt; i++) {
hyperpoint curr = V*glhr::gltopoint(tab[i]); shiftpoint curr = V*glhr::gltopoint(tab[i]);
if(is_behind(curr) != last_behind) { if(is_behind(curr.h) != last_behind) {
hyperpoint h = be_just_on_view(last, curr); hyperpoint h = be_just_on_view(last.h, curr.h);
if(start_behind == 1) start_behind = 2, firstleave = h; if(start_behind == 1) start_behind = 2, firstleave = h;
if(!last_behind) enter = h; if(!last_behind) enter = h;
else if(h[0] * enter[0] + h[1] * enter[1] < 0) poly_flags |= POLY_BEHIND; else if(h[0] * enter[0] + h[1] * enter[1] < 0) poly_flags |= POLY_BEHIND;
addpoint(h); addpoint(shiftless(h));
last_behind = !last_behind; last_behind = !last_behind;
} }
if(!last_behind) addpoint(curr); if(!last_behind) addpoint(curr);
@ -468,12 +463,12 @@ void addpoly(const transmatrix& V, const vector<glvertex> &tab, int ofs, int cnt
} }
if(start_behind == 2) { if(start_behind == 2) {
if(firstleave[0] * enter[0] + firstleave[1] * enter[1] < 0) poly_flags |= POLY_BEHIND; 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(knowgood && isize(tofix)) {
if(true) { if(true) {
hyperpoint Hx = V * C0, Hy = goodpoint; hyperpoint Hx = V.T * C0, Hy = goodpoint;
for(int i=0; i<20; i++) { for(int i=0; i<20; i++) {
hyperpoint mid = midz(Hx, Hy); hyperpoint mid = midz(Hx, Hy);
if(correct_side(mid)) Hy = mid; 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) { for(int ed = current_display->stereo_active() ? -1 : 0; ed<2; ed+=2) {
if(global_projection && global_projection != ed) continue; if(global_projection && global_projection != ed) continue;
current_display->set_all(ed);
bool draw = color;
if(min_slr < max_slr) { 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(); flagtype sp = get_shader_flags();
if(sp & SF_DIRECT) { if(sp & SF_DIRECT) {
if((sp & SF_BAND) && V[2][2] > 1e8) continue; if((sp & SF_BAND) && V[2][2] > 1e8) continue;
glapplymatrix(V); glapplymatrix(V.T);
} }
if(draw) { if(draw) {
@ -666,7 +664,7 @@ void dqi_poly::gldraw() {
glhr::id_modelview(); glhr::id_modelview();
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, 0, 4); glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, 0, 4);
glhr::vertices(v); glhr::vertices(v);
if(sp & SF_DIRECT) glapplymatrix(V); if(sp & SF_DIRECT) glapplymatrix(V.T);
} }
else { else {
glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO); glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO);
@ -712,8 +710,8 @@ void dqi_poly::gldraw() {
} }
#endif #endif
EX ld scale_at(const transmatrix& T) { EX ld scale_at(const shiftmatrix& T) {
if(GDIM == 3 && pmodel == mdPerspective) return 1 / abs((tC0(T))[2]); if(GDIM == 3 && pmodel == mdPerspective) return 1 / abs((tC0(unshift(T)))[2]);
if(sol) return 1; if(sol) return 1;
hyperpoint h1, h2, h3; hyperpoint h1, h2, h3;
applymodel(tC0(T), h1); applymodel(tC0(T), h1);
@ -724,7 +722,7 @@ EX ld scale_at(const transmatrix& T) {
EX int perfect_linewidth = 1; EX int perfect_linewidth = 1;
EX ld linewidthat(const hyperpoint& h) { EX ld linewidthat(const shiftpoint& h) {
if(!(vid.antialias & AA_LINEWIDTH)) return 1; if(!(vid.antialias & AA_LINEWIDTH)) return 1;
else if(hyperbolic && pmodel == mdDisk && pconf.alpha == 1 && !ISWEB) { else if(hyperbolic && pmodel == mdDisk && pconf.alpha == 1 && !ISWEB) {
double dz = h[LDIM]; double dz = h[LDIM];
@ -737,8 +735,8 @@ EX ld linewidthat(const hyperpoint& h) {
} }
} }
else if(perfect_linewidth >= (inHighQual ? 1 : 2)) { else if(perfect_linewidth >= (inHighQual ? 1 : 2)) {
hyperpoint h0 = h / zlevel(h); hyperpoint h0 = h.h / zlevel(h.h);
transmatrix T = rgpushxto0(h0); shiftmatrix T = shiftless(rgpushxto0(h0), h.shift);
return scale_at(T); return scale_at(T);
} }
return 1; return 1;
@ -893,8 +891,8 @@ ld glhypot2(glvertex a, glvertex b) {
void compute_side_by_centerin(dqi_poly *p, bool& nofill) { void compute_side_by_centerin(dqi_poly *p, bool& nofill) {
hyperpoint hscr; hyperpoint hscr;
hyperpoint h1 = p->V * p->intester; shiftpoint h1 = p->V * p->intester;
if(is_behind(h1)) { if(is_behind(h1.h)) {
if(sphere) { if(sphere) {
for(int i=0; i<3; i++) h1[i] = -h1[i]; for(int i=0; i<3; i++) h1[i] = -h1[i];
poly_flags &= ~POLY_CENTERIN; poly_flags &= ~POLY_CENTERIN;
@ -918,7 +916,7 @@ void compute_side_by_centerin(dqi_poly *p, bool& nofill) {
poly_flags &= ~POLY_INVERSE; poly_flags &= ~POLY_INVERSE;
if(poly_flags & POLY_CENTERIN) { if(poly_flags & POLY_CENTERIN) {
poly_flags |= POLY_INVERSE; 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; /* nofill = true;
outline = (flags & POLY_CENTERIN) ? 0x00FF00FF : 0xFF0000FF; outline = (flags & POLY_CENTERIN) ? 0x00FF00FF : 0xFF0000FF;
@ -952,7 +950,7 @@ ld get_width(dqi_poly* p) {
else if(p->flags & POLY_PRECISE_WIDE) { else if(p->flags & POLY_PRECISE_WIDE) {
ld maxwidth = 0; ld maxwidth = 0;
for(int i=0; i<p->cnt; i++) { for(int i=0; i<p->cnt; 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)); maxwidth = max(maxwidth, linewidthat(h1));
} }
return maxwidth * p->linewidth; return maxwidth * p->linewidth;
@ -1136,14 +1134,15 @@ void draw_s2xe(dqi_poly *p) {
else { else {
npoly.tinf = NULL; npoly.tinf = NULL;
} }
npoly.V = Id; npoly.V = shiftless(Id);
auto& pV = p->V.T;
set_width(1); set_width(1);
glcoords.clear(); glcoords.clear();
stinf.tvertices.clear(); stinf.tvertices.clear();
for(int i=0; i<p->cnt; i+=3) { for(int i=0; i<p->cnt; i+=3) {
array<pt, 3> v; array<pt, 3> v;
for(int k=0; k<3; k++) { 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); v[k][2] = hypot_d(3, h);
auto dp = product_decompose(h); auto dp = product_decompose(h);
@ -1178,7 +1177,7 @@ void draw_s2xe0(dqi_poly *p) {
dqi_poly npoly = *p; dqi_poly npoly = *p;
npoly.offset = 0; npoly.offset = 0;
npoly.tab = &glcoords; npoly.tab = &glcoords;
npoly.V = Id; npoly.V = shiftless(Id);
npoly.flags &= ~ (POLY_INVERSE | POLY_FORCE_INVERTED); npoly.flags &= ~ (POLY_INVERSE | POLY_FORCE_INVERTED);
set_width(1); set_width(1);
glcoords.clear(); 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]); }; 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<point_data> pd; vector<point_data> pd;
for(int i=0; i<p->cnt; i++) { for(int i=0; i<p->cnt; 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(); pd.emplace_back();
auto& next = pd.back(); auto& next = pd.back();
auto dp = product_decompose(h); auto dp = product_decompose(h);
@ -1263,13 +1262,13 @@ void draw_stretch(dqi_poly *p) {
npoly.offset = 0; npoly.offset = 0;
npoly.tab = &glcoords; npoly.tab = &glcoords;
npoly.V = Id; npoly.V = shiftless(Id);
npoly.flags &= ~(POLY_INVERSE | POLY_FORCE_INVERTED); npoly.flags &= ~(POLY_INVERSE | POLY_FORCE_INVERTED);
transmatrix T2 = stretch::translate( tC0(inverse(View)) ); transmatrix T2 = stretch::translate( tC0(inverse(View)) );
transmatrix U = View * T2; transmatrix U = View * T2;
transmatrix iUV = inverse(U) * p->V; transmatrix iUV = inverse(U) * p->V.T;
vector<hyperpoint> hs; vector<hyperpoint> hs;
vector<hyperpoint> ths; vector<hyperpoint> ths;
@ -1292,7 +1291,7 @@ void draw_stretch(dqi_poly *p) {
else { else {
npoly.tinf = NULL; npoly.tinf = NULL;
} }
npoly.V = Id; npoly.V = shiftless(Id);
set_width(1); set_width(1);
glcoords.clear(); glcoords.clear();
@ -1492,7 +1491,7 @@ EX namespace ods {
void dqi_poly::draw() { void dqi_poly::draw() {
if(flags & POLY_DEBUG) debug_this(); if(flags & POLY_DEBUG) debug_this();
if(debugflags & DF_VERTEX) { 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; i<cnt; i++) print(hlog, (*tab)[i]); for(int i=0; i<cnt; i++) print(hlog, (*tab)[i]);
println(hlog); println(hlog);
} }
@ -1505,17 +1504,16 @@ void dqi_poly::draw() {
#endif #endif
#if CAP_GL #if CAP_GL
if(in_s2xe() && vid.usingGL && pmodel == mdPerspective && (current_display->set_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); s2xe::draw_s2xe(this);
return; return;
} }
#endif #endif
dynamicval<ld> bs(hr::band_shift, band_shift);
if(!hyperbolic && among(pmodel, mdPolygonal, mdPolynomial)) { if(!hyperbolic && among(pmodel, mdPolygonal, mdPolynomial)) {
bool any = false; bool any = false;
for(int i=0; i<cnt; i++) { for(int i=0; i<cnt; i++) {
hyperpoint h1 = V * glhr::gltopoint((*tab)[offset+i]); hyperpoint h1 = V.T * glhr::gltopoint((*tab)[offset+i]);
if(h1[2] > 0) any = true; if(h1[2] > 0) any = true;
} }
if(!any) return; if(!any) return;
@ -1543,7 +1541,7 @@ void dqi_poly::draw() {
int pha; int pha;
if(twopoint_do_flips) { if(twopoint_do_flips) {
for(int i=0; i<cnt; i++) { for(int i=0; i<cnt; i++) {
hyperpoint h1 = V * glhr::gltopoint((*tab)[offset+i]); shiftpoint h1 = V * glhr::gltopoint((*tab)[offset+i]);
for(int j=0; j<MAX_PHASE; j++) { for(int j=0; j<MAX_PHASE; j++) {
twopoint_sphere_flips = j; twopoint_sphere_flips = j;
hyperpoint h2; applymodel(h1, h2); hyperpoint h2; applymodel(h1, h2);
@ -1574,16 +1572,16 @@ void dqi_poly::draw() {
int cpha = 0; int cpha = 0;
for(int i=0; i<cnt; i++) { for(int i=0; i<cnt; i++) {
hyperpoint h1 = V * glhr::gltopoint((*tab)[offset+i]); shiftpoint h1 = V * glhr::gltopoint((*tab)[offset+i]);
hyperpoint mh1; applymodel(h1, mh1); mh1[1] *= pconf.stretch; hyperpoint mh1; applymodel(h1, mh1); mh1[1] *= pconf.stretch;
phases[cpha].push_back(glhr::pointtogl(mh1 * current_display->radius)); phases[cpha].push_back(glhr::pointtogl(mh1 * current_display->radius));
// check if the i-th edge intersects the boundary of the ellipse // check if the i-th edge intersects the boundary of the ellipse
// (which corresponds to the segment between the antipodes of foci) // (which corresponds to the segment between the antipodes of foci)
// if yes, switch cpha to the opposite // 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(ah1[0], ah1[1]);
models::apply_orientation(ah2[0], ah2[1]); models::apply_orientation(ah2[0], ah2[1]);
if(ah1[1] * ah2[1] > 0) continue; if(ah1[1] * ah2[1] > 0) continue;
@ -1597,7 +1595,7 @@ void dqi_poly::draw() {
} }
} }
dynamicval<eModel> d1(pmodel, mdPixel); dynamicval<eModel> d1(pmodel, mdPixel);
dynamicval<transmatrix> d2(V, Id); dynamicval<transmatrix> d2(V.T, Id);
dynamicval<int> d3(offset, 0); dynamicval<int> d3(offset, 0);
dynamicval<decltype(tab)> d4(tab, tab); dynamicval<decltype(tab)> d4(tab, tab);
for(int j=0; j<pha; j++) { for(int j=0; j<pha; j++) {
@ -1615,15 +1613,15 @@ void dqi_poly::draw() {
return; return;
} */ } */
if(vid.usingGL && (current_display->set_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); draw_stretch(this);
return; return;
} }
#if CAP_GL #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) { 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]; auto zr = sightranges[geometry];
ld ns = stretch::not_squared(); ld ns = stretch::not_squared();
ld db = cgi.psl_steps / M_PI / ns / hybrid::csteps; ld db = cgi.psl_steps / M_PI / ns / hybrid::csteps;
@ -1647,7 +1645,7 @@ void dqi_poly::draw() {
double d = 0, curradius = 0; double d = 0, curradius = 0;
if(sphere) { if(sphere) {
d = det(V); d = det(V.T);
curradius = pow(abs(d), 1/3.); curradius = pow(abs(d), 1/3.);
} }
@ -1742,7 +1740,7 @@ void dqi_poly::draw() {
} }
if(equi && (poly_flags & POLY_INVERSE)) { 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 // we should fill the other side
ld h = atan2(glcoords[0][0], glcoords[0][1]); ld h = atan2(glcoords[0][0], glcoords[0][1]);
for(int i=0; i<=360; i++) { for(int i=0; i<=360; i++) {
@ -1767,7 +1765,7 @@ void dqi_poly::draw() {
} }
set_width(get_width(this)); set_width(get_width(this));
dqi_poly npoly = (*this); dqi_poly npoly = (*this);
npoly.V = Id; npoly.V = shiftless(Id, V.shift);
npoly.tab = &glcoords; npoly.tab = &glcoords;
npoly.offset = 0; npoly.offset = 0;
npoly.cnt = isize(glcoords); npoly.cnt = isize(glcoords);
@ -1859,13 +1857,12 @@ EX void prettylinesub(const hyperpoint& h1, const hyperpoint& h2, int lev) {
else prettypoint(h2); 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(); prettylinepoints.clear();
prettypoint(h1); prettypoint(h1);
prettylinesub(h1, h2, lev); prettylinesub(h1, h2, lev);
dqi_poly ptd; dqi_poly ptd;
ptd.V = Id; ptd.V = shiftless(Id, shift);
ptd.band_shift = band_shift;
ptd.tab = &prettylinepoints; ptd.tab = &prettylinepoints;
ptd.offset = 0; ptd.offset = 0;
ptd.cnt = isize(prettylinepoints); ptd.cnt = isize(prettylinepoints);
@ -1885,8 +1882,7 @@ EX void prettypoly(const vector<hyperpoint>& t, color_t fillcol, color_t linecol
for(int i=0; i<isize(t); i++) for(int i=0; i<isize(t); i++)
prettylinesub(t[i], t[(i+1)%3], lev); prettylinesub(t[i], t[(i+1)%3], lev);
dqi_poly ptd; dqi_poly ptd;
ptd.V = Id; ptd.V = shiftless(Id);
ptd.band_shift = band_shift;
ptd.tab = &prettylinepoints; ptd.tab = &prettylinepoints;
ptd.offset = 0; ptd.offset = 0;
ptd.cnt = isize(prettylinepoints); ptd.cnt = isize(prettylinepoints);
@ -1909,8 +1905,7 @@ EX void queuereset(eModel m, PPR prio) {
void dqi_line::draw() { void dqi_line::draw() {
dynamicval<ld> d(vid.linewidth, width); dynamicval<ld> d(vid.linewidth, width);
dynamicval<ld> bs(hr::band_shift, band_shift); prettyline(H1.h, unshift(H2, H1.shift), H1.shift, color, prf, 0, prio);
prettyline(H1, H2, color, prf, 0, prio);
} }
void dqi_string::draw() { void dqi_string::draw() {
@ -1955,7 +1950,7 @@ EX void sortquickqueue() {
EX void quickqueue() { EX void quickqueue() {
current_display->next_shader_flags = 0; current_display->next_shader_flags = 0;
spherespecial = 0; spherespecial = 0;
reset_projection(); current_display->set_all(0); reset_projection(); current_display->set_all(0, 0);
int siz = isize(ptds); int siz = isize(ptds);
for(int i=0; i<siz; i++) ptds[i]->draw(); for(int i=0; i<siz; i++) ptds[i]->draw();
ptds.clear(); ptds.clear();
@ -1965,10 +1960,11 @@ EX void quickqueue() {
} }
} }
ld xintval(const hyperpoint& h) { /* todo */
if(sphereflipped()) return -h[2]; ld xintval(const shiftpoint& h) {
if(hyperbolic) return -h[2]; if(sphereflipped()) return -h.h[2];
return -intval(h, C0); if(hyperbolic) return -h.h[2];
return -intval(h.h, C0);
} }
EX ld backbrightness = .25; EX ld backbrightness = .25;
@ -2352,13 +2348,12 @@ EX color_t monochromatize(color_t x) {
return c * 0x1010100 | (part(x, 0)); 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; if(prio == PPR::DEFAULT) prio = h.prio;
auto& ptd = queuea<dqi_poly> (prio); auto& ptd = queuea<dqi_poly> (prio);
ptd.V = V; ptd.V = V;
ptd.band_shift = band_shift;
ptd.offset = h.s; ptd.offset = h.s;
ptd.cnt = h.e-h.s; ptd.cnt = h.e-h.s;
ptd.tab = &cgi.ourshape; ptd.tab = &cgi.ourshape;
@ -2425,16 +2420,11 @@ EX dqi_poly& queuepolyat(const transmatrix& V, const hpcshape& h, color_t col, P
} }
#endif #endif
void addfloats(vector<GLfloat>& v, hyperpoint h) { EX dqi_poly& queuetable(const shiftmatrix& V, const vector<glvertex>& f, int cnt, color_t linecol, color_t fillcol, PPR prio) {
for(int i=0; i<3; i++) v.push_back(h[i]);
}
EX dqi_poly& queuetable(const transmatrix& V, const vector<glvertex>& f, int cnt, color_t linecol, color_t fillcol, PPR prio) {
auto& ptd = queuea<dqi_poly> (prio); auto& ptd = queuea<dqi_poly> (prio);
ptd.V = V; ptd.V = V;
ptd.band_shift = band_shift;
ptd.tab = &f; ptd.tab = &f;
ptd.offset = 0; ptd.offset = 0;
ptd.cnt = cnt; ptd.cnt = cnt;
@ -2448,11 +2438,11 @@ EX dqi_poly& queuetable(const transmatrix& V, const vector<glvertex>& f, int cnt
} }
#if CAP_SHAPES #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); 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); queuepolyat(V,h,col,h.prio+b);
} }
#endif #endif
@ -2461,8 +2451,8 @@ EX void curvepoint(const hyperpoint& H1) {
curvedata.push_back(glhr::pointtogl(H1)); curvedata.push_back(glhr::pointtogl(H1));
} }
EX dqi_poly& queuecurve(color_t linecol, color_t fillcol, PPR prio) { EX dqi_poly& queuecurve(const shiftmatrix& V, color_t linecol, color_t fillcol, PPR prio) {
auto &res = queuetable(Id, curvedata, isize(curvedata)-curvestart, linecol, fillcol, prio); auto &res = queuetable(V, curvedata, isize(curvedata)-curvestart, linecol, fillcol, prio);
res.offset = curvestart; res.offset = curvestart;
curvestart = isize(curvedata); curvestart = isize(curvedata);
return res; return res;
@ -2472,12 +2462,11 @@ EX dqi_action& queueaction(PPR prio, const reaction_t& action) {
return queuea<dqi_action> (prio, action); return queuea<dqi_action> (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<dqi_line> (prio); auto& ptd = queuea<dqi_line> (prio);
ptd.H1 = H1; ptd.H1 = H1;
ptd.H2 = H2; ptd.H2 = H2;
ptd.band_shift = band_shift;
ptd.prf = prf; ptd.prf = prf;
ptd.width = vid.linewidth; ptd.width = vid.linewidth;
ptd.color = (darkened(col >> 8) << 8) + (col & 0xFF); 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; 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; hyperpoint hscr;
applymodel(h, hscr); applymodel(h, hscr);
xc = current_display->xcenter + current_display->radius * hscr[0]; 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]; // 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; 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(invalid_point(h)) return false;
if(point_behind(h)) return false; if(point_behind(h)) return false;
getcoord0(h, xc, yc, zc); getcoord0(h, xc, yc, zc);
return true; 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; int xc, yc, sc;
if(getcoord0_checked(h, xc, yc, sc)) if(getcoord0_checked(h, xc, yc, sc))
queuestr(xc, yc, sc, size, chr, col, frame); 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; int xc, yc, sc;
if(getcoord0_checked(tC0(V), xc, yc, sc)) if(getcoord0_checked(tC0(V), xc, yc, sc))
queuestr(xc, yc, sc, scale_in_pixels(V) * size, chr, col, frame, align); 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) { switch(neon_mode) {
case eNeon::none: case eNeon::none:
queuestr(V, size, chr, col, frame, align); 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; int xc, yc, sc;
if(!getcoord0_checked(tC0(V), xc, yc, sc)) return; if(!getcoord0_checked(tC0(V), xc, yc, sc)) return;
int xs, ys, ss; getcoord0(V * xpush0(.01), xs, ys, ss); int xs, ys, ss; getcoord0(V * xpush0(.01), xs, ys, ss);

View File

@ -227,15 +227,13 @@ EX namespace euc {
} }
void draw() override { void draw() override {
dq::visited_by_matrix.clear(); dq::clear_all();
dq::enqueue_by_matrix(centerover->master, cview() * master_relative(centerover, true)); dq::enqueue_by_matrix(centerover->master, cview() * master_relative(centerover, true));
while(!dq::drawqueue.empty()) { while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front(); auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p); heptagon *h = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
dq::drawqueue.pop(); dq::drawqueue.pop();
cell *c = h->c7; cell *c = h->c7;
@ -244,7 +242,7 @@ EX namespace euc {
if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000 && !hybrid::pmap) continue; if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000 && !hybrid::pmap) continue;
if(draw) for(int i=0; i<S7; i++) if(draw) for(int i=0; i<S7; i++)
dq::enqueue_by_matrix(h->move(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() { EX void show_fundamental() {
initquickqueue(); initquickqueue();
transmatrix M = ggmatrix(cwt.at); shiftmatrix M = ggmatrix(cwt.at);
hyperpoint h0 = M*C0; shiftpoint h0 = M*C0;
auto& T_edit = eu_edit.user_axes; auto& T_edit = eu_edit.user_axes;
hyperpoint ha = M*(eumove(T_edit[0]) * C0 - C0) / 2; hyperpoint ha = M.T*(eumove(T_edit[0]) * C0 - C0) / 2;
hyperpoint hb = M*(eumove(T_edit[1]) * C0 - C0) / 2; hyperpoint hb = M.T*(eumove(T_edit[1]) * C0 - C0) / 2;
if(WDIM == 3) { 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}) { 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*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); 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 gp::loc sdxy() { return to_loc(eu.user_axes[1]) * gp::univ_param(); }
EX pair<bool, string> coord_display(const transmatrix& V, cell *c) { EX pair<bool, string> coord_display(const shiftmatrix& V, cell *c) {
if(c != c->master->c7) return {false, ""}; if(c != c->master->c7) return {false, ""};
hyperpoint hx = eumove(main_axes[0]) * C0; hyperpoint hx = eumove(main_axes[0]) * C0;
hyperpoint hy = eumove(main_axes[1]) * C0; hyperpoint hy = eumove(main_axes[1]) * C0;
hyperpoint hz = WDIM == 2 ? C0 : eumove(main_axes[2]) * 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) if(WDIM == 3)
return {true, fts(h[0]) + "," + fts(h[1]) + "," + fts(h[2]) }; return {true, fts(h[0]) + "," + fts(h[1]) + "," + fts(h[2]) };

View File

@ -119,8 +119,7 @@ EX namespace fake {
return S1 * xpush(cgi.adjcheck) * S2; return S1 * xpush(cgi.adjcheck) * S2;
} }
void draw_recursive(cell *c, const transmatrix& V, ld a0, ld a1, cell *parent, int depth) { void draw_recursive(cell *c, const shiftmatrix& V, ld a0, ld a1, cell *parent, int depth) {
band_shift = 0;
if(!do_draw(c, V)) return; if(!do_draw(c, V)) return;
drawcell(c, V); drawcell(c, V);
@ -136,7 +135,7 @@ EX namespace fake {
curvepoint(spin(-a1) * xpush0(d+.2)); curvepoint(spin(-a1) * xpush0(d+.2));
curvepoint(spin(-a1) * xpush0(d)); curvepoint(spin(-a1) * xpush0(d));
curvepoint(spin(-a0) * 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; i<c->type; i++) if(c->move(i) && c->move(i) != parent) { for(int i=0; i<c->type; i++) if(c->move(i) && c->move(i) != parent) {
auto h0 = V * befake(FPIU(get_corner_position(c, i))); auto h0 = V * befake(FPIU(get_corner_position(c, i)));
auto h1 = V * befake(FPIU(get_corner_position(c, (i+1) % c->type))); auto h1 = V * befake(FPIU(get_corner_position(c, (i+1) % c->type)));
ld b0 = atan2(h0); ld b0 = atan2(unshift(h0));
ld b1 = atan2(h1); ld b1 = atan2(unshift(h1));
while(b1 < b0) b1 += 2 * M_PI; while(b1 < b0) b1 += 2 * M_PI;
if(a0 == -1) { 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 { else {
if(b1 - b0 > M_PI) continue; if(b1 - b0 > M_PI) continue;
@ -163,7 +162,7 @@ EX namespace fake {
if(b0 > b1) continue; 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; limit = INT_MAX;
if(ordered_mode && !(multiple && multiple_special_draw)) { if(ordered_mode && !(multiple && multiple_special_draw)) {
using pct = pair<cell*, transmatrix>; using pct = pair<cell*, shiftmatrix>;
auto comparer = [] (pct& a1, pct& a2) { auto comparer = [] (pct& a1, pct& a2) {
if(ordered_mode > 2) { if(ordered_mode > 2) {
auto val = [] (pct& a) { auto val = [] (pct& a) {
@ -215,7 +214,7 @@ EX namespace fake {
}; };
std::priority_queue<pct, std::vector<pct>, decltype(comparer)> myqueue(comparer); std::priority_queue<pct, std::vector<pct>, decltype(comparer)> myqueue(comparer);
auto enq = [&] (cell *c, const transmatrix& V) { auto enq = [&] (cell *c, const shiftmatrix& V) {
if(!c) return; if(!c) return;
if(ordered_mode == 1 || ordered_mode == 3) { if(ordered_mode == 1 || ordered_mode == 3) {
if(dq::visited_c.count(c)) return; if(dq::visited_c.count(c)) return;
@ -229,8 +228,8 @@ EX namespace fake {
while(!myqueue.empty()) { while(!myqueue.empty()) {
auto& p = myqueue.top(); auto& p = myqueue.top();
id++; id++;
cell *c = get<0>(p); cell *c = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
myqueue.pop(); myqueue.pop();
if(ordered_mode == 2 || ordered_mode == 4) { if(ordered_mode == 2 || ordered_mode == 4) {
@ -246,7 +245,7 @@ EX namespace fake {
if(id > limit) continue; if(id > limit) continue;
for(int i=0; i<c->type; i++) if(c->move(i)) { for(int i=0; i<c->type; 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()) { while(!dq::drawqueue_c.empty()) {
auto& p = dq::drawqueue_c.front(); auto& p = dq::drawqueue_c.front();
id++; id++;
cell *c = get<0>(p); cell *c = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
dq::drawqueue_c.pop(); dq::drawqueue_c.pop();
if(!do_draw(c, V)) continue; if(!do_draw(c, V)) continue;
@ -272,7 +269,7 @@ EX namespace fake {
if(id > limit) continue; if(id > limit) continue;
for(int i=0; i<c->type; i++) if(c->move(i)) { for(int i=0; i<c->type; 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; if(around >= 0 && around <= 2) return;
ld t = in() ? scale : 1; ld t = in() ? scale : 1;
hyperpoint h = inverse_exp(tC0(View)); hyperpoint h = inverse_exp(shiftless(tC0(View)));
transmatrix T = gpushxto0(tC0(View)) * View; transmatrix T = gpushxto0(tC0(View)) * View;
ld range = sightranges[geometry]; ld range = sightranges[geometry];

View File

@ -938,7 +938,7 @@ EX int shvid(cell *c) {
return ctof(c); return ctof(c);
} }
EX struct dqi_poly *draw_shapevec(cell *c, const transmatrix& V, const vector<hpcshape> &shv, color_t col, PPR prio IS(PPR::DEFAULT)) { EX struct dqi_poly *draw_shapevec(cell *c, const shiftmatrix& V, const vector<hpcshape> &shv, color_t col, PPR prio IS(PPR::DEFAULT)) {
if(no_wall_rendering) return NULL; if(no_wall_rendering) return NULL;
if(!c) return &queuepolyat(V, shv[0], col, prio); if(!c) return &queuepolyat(V, shv[0], col, prio);
else if(WDIM == 3) return NULL; else if(WDIM == 3) return NULL;
@ -975,12 +975,12 @@ EX struct dqi_poly *draw_shapevec(cell *c, const transmatrix& V, const vector<hp
return &queuepolyat(V, shv[shvid(c)], col, prio); return &queuepolyat(V, shv[shvid(c)], col, prio);
} }
EX void draw_floorshape(cell *c, const transmatrix& V, const floorshape &fsh, color_t col, PPR prio IS(PPR::DEFAULT)) { EX void draw_floorshape(cell *c, const shiftmatrix& V, const floorshape &fsh, color_t col, PPR prio IS(PPR::DEFAULT)) {
if(no_wall_rendering) return; if(no_wall_rendering) return;
draw_shapevec(c, V, fsh.b, col, prio); draw_shapevec(c, V, fsh.b, col, prio);
} }
EX void draw_qfi(cell *c, const transmatrix& V, color_t col, PPR prio IS(PPR::DEFAULT), vector<hpcshape> floorshape::* tab IS(&floorshape::b)) { EX void draw_qfi(cell *c, const shiftmatrix& V, color_t col, PPR prio IS(PPR::DEFAULT), vector<hpcshape> floorshape::* tab IS(&floorshape::b)) {
if(no_wall_rendering) return; if(no_wall_rendering) return;
if(qfi.shape) if(qfi.shape)
queuepolyat(V * qfi.spin, *qfi.shape, col, prio); 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 bool floorshape_debug;
EX void viewmat() { EX void viewmat() {
if(floorshape_debug) { if(floorshape_debug) {
transmatrix V = ggmatrix(cwt.at); shiftmatrix V = ggmatrix(cwt.at);
for(int i=0; i<cwt.at->type; i++) { for(int i=0; i<cwt.at->type; i++) {
hyperpoint ci = V * get_corner_position(cwt.at, i); shiftpoint ci = V * get_corner_position(cwt.at, i);
hyperpoint ci1 = V * get_corner_position(cwt.at, (i+1) % cwt.at->type); shiftpoint ci1 = V * get_corner_position(cwt.at, (i+1) % cwt.at->type);
hyperpoint cn = V * nearcorner(cwt.at, i); shiftpoint cn = V * nearcorner(cwt.at, i);
hyperpoint cf0 = V * farcorner(cwt.at, i, 0); shiftpoint cf0 = V * farcorner(cwt.at, i, 0);
hyperpoint cf1 = V * farcorner(cwt.at, i, 1); shiftpoint cf1 = V * farcorner(cwt.at, i, 1);
queuestr(ci, 20, its(i), 0x0000FF, 1); queuestr(ci, 20, its(i), 0x0000FF, 1);
if(vid.grid) if(vid.grid)
queuestr(cn, 20, its(i), 0x00FF00, 1); 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); 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); poly_outline = 0xFFFFFFFF - 0x1010100 * (sh->pstrength * 3/2);
for(int a=-1; a<=1; a++) for(int a=-1; a<=1; a++)
for(int b=-1; b<=1; b++) 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) { 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) { 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); 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]; auto& ftv = floor_texture_vertices[sh->id];
@ -1098,11 +1098,11 @@ void draw_shape_for_texture(floorshape* sh) {
if(1) { if(1) {
hyperpoint inmodel; hyperpoint inmodel;
applymodel(center, inmodel); applymodel(shiftless(center), inmodel);
glvertex tmap; glvertex tmap;
tmap[0] = (1 + inmodel[0] * pconf.scale) / 2; tmap[0] = (1 + inmodel[0] * pconf.scale) / 2;
tmap[1] = (1 - inmodel[1] * 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]; tmap[2] = (1 + inmodel[0] * pconf.scale) / 2 - tmap[0];
floor_texture_map[sh->id] = tmap; floor_texture_map[sh->id] = tmap;
} }
@ -1110,7 +1110,7 @@ void draw_shape_for_texture(floorshape* sh) {
auto tvec_at = [&] (ld x, ld y) { auto tvec_at = [&] (ld x, ld y) {
hyperpoint h = center + v1 * x + v2 * y; hyperpoint h = center + v1 * x + v2 * y;
hyperpoint inmodel; hyperpoint inmodel;
applymodel(h, inmodel); applymodel(shiftless(h), inmodel);
glvec2 v; glvec2 v;
v[0] = (1 + inmodel[0] * pconf.scale) / 2; v[0] = (1 + inmodel[0] * pconf.scale) / 2;
v[1] = (1 - inmodel[1] * pconf.scale) / 2; v[1] = (1 - inmodel[1] * pconf.scale) / 2;
@ -1193,7 +1193,7 @@ void geometry_information::make_floor_textures_here() {
if(1) { if(1) {
current_display->next_shader_flags = GF_VARCOLOR; current_display->next_shader_flags = GF_VARCOLOR;
dynamicval<eModel> m(pmodel, mdPixel); dynamicval<eModel> m(pmodel, mdPixel);
current_display->set_all(0); current_display->set_all(0,0);
glhr::new_projection(); glhr::new_projection();
glhr::id_modelview(); glhr::id_modelview();
glhr::prepare(gv); glhr::prepare(gv);

View File

@ -8,7 +8,7 @@
#include "hyper.h" #include "hyper.h"
namespace hr { namespace hr {
transmatrix &ggmatrix(cell *c); shiftmatrix &ggmatrix(cell *c);
EX void fixelliptic(transmatrix& at) { EX void fixelliptic(transmatrix& at) {
if(elliptic && at[LDIM][LDIM] < 0) { if(elliptic && at[LDIM][LDIM] < 0) {
@ -25,7 +25,7 @@ EX void fixelliptic(hyperpoint& h) {
/** find relative_matrix via recursing the tree structure */ /** find relative_matrix via recursing the tree structure */
EX transmatrix relative_matrix_recursive(heptagon *h2, heptagon *h1) { EX transmatrix relative_matrix_recursive(heptagon *h2, heptagon *h1) {
if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) 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; transmatrix gm = Id, where = Id;
while(h1 != h2) { while(h1 != h2) {
for(int i=0; i<h1->type; i++) { for(int i=0; i<h1->type; i++) {
@ -195,10 +195,12 @@ transmatrix hrmap_standard::relative_matrix(heptagon *h2, heptagon *h1, const hy
return gm * where; return gm * where;
} }
EX transmatrix &ggmatrix(cell *c) { EX shiftmatrix &ggmatrix(cell *c) {
transmatrix& t = gmatrix[c]; shiftmatrix& t = gmatrix[c];
if(t[LDIM][LDIM] == 0) if(t[LDIM][LDIM] == 0) {
t = actual_view_transform * View * calc_relative_matrix(c, centerover, C0); t.T = actual_view_transform * View * calc_relative_matrix(c, centerover, C0);
t.shift = 0;
}
return t; return t;
} }
@ -208,7 +210,7 @@ struct horo_distance {
void become(hyperpoint h1); void become(hyperpoint h1);
horo_distance(hyperpoint h) { become(h); } 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; bool operator < (const horo_distance z) const;
friend void print(hstream& hs, horo_distance x) { print(hs, "[", x.a, ":", x.b, "]"); } 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); 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 CAP_BT
if(bt::in()) become(inverse(T) * h1); if(bt::in()) become(inverse_shift(T, h1));
else else
#endif #endif
if(sn::in() || hybri || nil) become(inverse(T) * h1); if(sn::in() || hybri || nil) become(inverse_shift(T, h1));
else 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 { 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) { EX void virtualRebase(cell*& base, transmatrix& at) {
virtualRebase(base, at, tC0); virtualRebase(base, at, tC0_t);
} }
EX void virtualRebase(cell*& base, hyperpoint& h) { EX void virtualRebase(cell*& base, hyperpoint& h) {

View File

@ -824,7 +824,7 @@ EX void set_linewidth(ld lw) {
EX void switch_to_text(const vector<glvertex>& v, const vector<glvertex>& t) { EX void switch_to_text(const vector<glvertex>& v, const vector<glvertex>& t) {
current_display->next_shader_flags = GF_TEXTURE; current_display->next_shader_flags = GF_TEXTURE;
dynamicval<eModel> pm(pmodel, mdPixel); dynamicval<eModel> 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); vertices_texture(v, t, 0, 0);
} }

View File

@ -1234,10 +1234,8 @@ EX namespace gp {
while(!dq::drawqueue_c.empty()) { while(!dq::drawqueue_c.empty()) {
auto& p = dq::drawqueue_c.front(); auto& p = dq::drawqueue_c.front();
cell *c = get<0>(p); cell *c = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
auto c1 = get_mapped(c, 0); auto c1 = get_mapped(c, 0);
in_underlying([&] { in_underlying([&] {
@ -1257,7 +1255,7 @@ EX namespace gp {
drawcell(c, V); drawcell(c, V);
for(int i=0; i<c->type; i++) if(c->cmove(i)) for(int i=0; i<c->type; i++) if(c->cmove(i))
enqueue(c->move(i), V * adj(c, i)); enqueue(c->move(i), optimized_shift(V * adj(c, i)));
} }
} }

417
graph.cpp

File diff suppressed because it is too large Load Diff

View File

@ -204,7 +204,7 @@ EX namespace history {
m->at = inverse(first_center_view); m->at = inverse(first_center_view);
m->base = first_center_at; m->base = first_center_at;
v.push_back(m); 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; if(on) saved_ends = 2;
return; return;
} }
@ -301,7 +301,7 @@ EX namespace history {
EX void create_recenter_to_view(bool precise) { EX void create_recenter_to_view(bool precise) {
cell *c = centerover ? centerover : cwt.at; 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() { EX void movetophase() {
@ -374,7 +374,7 @@ EX namespace history {
v[j+1]->at * C0; v[j+1]->at * C0;
hyperpoint nextscr; hyperpoint nextscr;
applymodel(next, nextscr); applymodel(shiftless(next), nextscr);
tpixels += nextscr[0] * r; tpixels += nextscr[0] * r;
if(j == 0 || j == siz-2) if(j == 0 || j == siz-2)
@ -452,7 +452,7 @@ EX namespace history {
drawfullmap(); drawfullmap();
if(last_base) { if(last_base) {
hyperpoint last = ggmatrix(last_base) * last_relative; shiftpoint last = ggmatrix(last_base) * last_relative;
hyperpoint hscr; hyperpoint hscr;
applymodel(last, hscr); applymodel(last, hscr);
ld bwidth = -current_display->radius * hscr[0]; ld bwidth = -current_display->radius * hscr[0];

View File

@ -216,6 +216,9 @@ inline void print(hstream& hs, const transmatrix T) {
for(int j=0; j<MDIM; j++) c(T[i][j]); for(int j=0; j<MDIM; j++) c(T[i][j]);
print(hs, ")"); } print(hs, ")"); }
inline void print(hstream& hs, const shiftpoint h) { print(hs, h.h, "@", h.shift); }
inline void print(hstream& hs, const shiftmatrix T) { print(hs, T.T, "@", T.shift); }
template<class T, class U> void print(hstream& hs, const pair<T, U> & t) { print(hs, "(", t.first, ",", t.second, ")"); } template<class T, class U> void print(hstream& hs, const pair<T, U> & t) { print(hs, "(", t.first, ",", t.second, ")"); }
template<class... T> void print(hstream& hs, const tuple<T...> & t) { template<class... T> void print(hstream& hs, const tuple<T...> & t) {

18
hud.cpp
View File

@ -204,7 +204,7 @@ bool displayglyph(int cx, int cy, int buttonsize, char glyph, color_t color, int
V[i][i] /= cgi.wormscale; V[i][i] /= cgi.wormscale;
int mcol = color; int mcol = color;
mcol -= (color & 0xFCFCFC) >> 2; 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 { else {
eItem it = eItem(id); 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 : ((glyph == 't' && qty%5) || it == itOrbYendor) ? ticks/2 :
it == itTerra ? glyphphase[id] * 3 * M_PI + 900 * M_PI: it == itTerra ? glyphphase[id] * 3 * M_PI + 900 * M_PI:
glyphphase[id] * 2; glyphphase[id] * 2;
drawItemType(it, NULL, V, icol, t, false); drawItemType(it, NULL, shiftless(V), icol, t, false);
} }
quickqueue(); quickqueue();
} }
@ -355,11 +355,11 @@ void drawMobileArrow(int i) {
ld scale = vid.mobilecompasssize * (sphere ? 7 : euclid ? 6 : 5); ld scale = vid.mobilecompasssize * (sphere ? 7 : euclid ? 6 : 5);
// m2[0][0] = scale; m2[1][1] = scale; m2[2][2] = 1; // m2[0][0] = scale; m2[1][1] = scale; m2[2][2] = 1;
transmatrix U = ggmatrix(cwt.at); shiftmatrix U = ggmatrix(cwt.at);
hyperpoint H = sphereflip * tC0(U); shiftpoint H = tC0(U);
transmatrix Centered = sphereflip * rgpushxto0(H); 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]); double alpha = atan2(P[1], P[0]);
using namespace shmupballs; using namespace shmupballs;
@ -367,7 +367,7 @@ void drawMobileArrow(int i) {
double dx = xmove + rad*(1+SKIPFAC-.2)/2 * cos(alpha); double dx = xmove + rad*(1+SKIPFAC-.2)/2 * cos(alpha);
double dy = yb + rad*(1+SKIPFAC-.2)/2 * sin(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 #endif
@ -419,8 +419,8 @@ EX void drawStats() {
if(crosshair_color && crosshair_size > 0) { if(crosshair_color && crosshair_size > 0) {
initquickqueue(); initquickqueue();
vid.linewidth = 1; vid.linewidth = 1;
queueline(tC0(atscreenpos(xc - crosshair_size, yc, 1)), tC0(atscreenpos(xc + crosshair_size, yc, 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(tC0(atscreenpos(xc, yc - crosshair_size, 1)), tC0(atscreenpos(xc, yc + crosshair_size, 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(); quickqueue();
} }

View File

@ -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 */ /** returns a diagonal matrix */
constexpr transmatrix diag(ld a, ld b, ld c, ld d) { constexpr transmatrix diag(ld a, ld b, ld c, ld d) {
#if MAXMDIM==3 #if MAXMDIM==3
@ -324,7 +363,7 @@ EX ld atan2_auto(ld y, ld x) {
case gcHyperbolic: return atanh(y/x); case gcHyperbolic: return atanh(y/x);
case gcSL2: return atanh(y/x); case gcSL2: return atanh(y/x);
case gcSphere: return atan2(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; default: return y/x;
} }
} }
@ -480,6 +519,10 @@ EX hyperpoint mid(const hyperpoint& H1, const hyperpoint& H2) {
return normalize(H1 + 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 */ /** like mid, but take 3D into account */
EX hyperpoint midz(const hyperpoint& H1, const hyperpoint& H2) { EX hyperpoint midz(const hyperpoint& H1, const hyperpoint& H2) {
if(prod) return mid(H1, H2); if(prod) return mid(H1, H2);
@ -786,6 +829,10 @@ EX transmatrix rgpushxto0(const hyperpoint& H) {
return ggpushxto0(H, 1); 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 /** \brief Fix the numerical inaccuracies in the isometry T
* *
* The nature of hyperbolic geometry makes the computations numerically unstable. * 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 */ /** length of a circle of radius r */
EX ld circlelength(ld r) { EX ld circlelength(ld r) {
switch(cgclass) { 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) { EX hyperpoint mscale(const hyperpoint& t, double fac) {
if(GDIM == 3 && !prod) return cpush(2, fac) * t; if(GDIM == 3 && !prod) return cpush(2, fac) * t;
if(prod) fac = exp(fac); if(prod) fac = exp(fac);
@ -1003,6 +1058,10 @@ EX hyperpoint mscale(const hyperpoint& t, double fac) {
return res; 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) { EX transmatrix mscale(const transmatrix& t, double fac) {
if(GDIM == 3 && !prod) { if(GDIM == 3 && !prod) {
// if(pmodel == mdFlatten) { transmatrix u = t; u[2][LDIM] -= fac; return u; } // 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; 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) { EX transmatrix xyscale(const transmatrix& t, double fac) {
transmatrix res; transmatrix res;
for(int i=0; i<MDIM; i++) for(int j=0; j<GDIM; j++) for(int i=0; i<MDIM; i++) for(int j=0; j<GDIM; j++)
@ -1031,6 +1094,10 @@ EX transmatrix xyzscale(const transmatrix& t, double fac, double facz) {
return res; return res;
} }
EX shiftmatrix xyzscale(const shiftmatrix& t, double fac, double facz) {
return shiftless(xyzscale(t.T, fac, facz), t.shift);
}
EX transmatrix mzscale(const transmatrix& t, double fac) { EX transmatrix mzscale(const transmatrix& t, double fac) {
if(GDIM == 3) return t * cpush(2, fac); if(GDIM == 3) return t * cpush(2, fac);
// take only the spin // take only the spin
@ -1045,6 +1112,10 @@ EX transmatrix mzscale(const transmatrix& t, double fac) {
return res; return res;
} }
EX shiftmatrix mzscale(const shiftmatrix& t, double fac) {
return shiftless(mzscale(t.T, fac), t.shift);
}
EX hyperpoint mid3(hyperpoint h1, hyperpoint h2, hyperpoint h3) { EX hyperpoint mid3(hyperpoint h1, hyperpoint h2, hyperpoint h3) {
return mid(h1+h2+h3, h1+h2+h3); return mid(h1+h2+h3, h1+h2+h3);
} }
@ -1134,6 +1205,10 @@ EX transmatrix spin_towards(const transmatrix Position, transmatrix& ori, const
return T; return T;
} }
EX shiftmatrix spin_towards(const shiftmatrix Position, transmatrix& ori, const shiftpoint goal, int dir, int back) {
return shiftless(spin_towards(Position.T, ori, unshift(goal, Position.shift), dir, back), Position.shift);
}
EX ld ortho_error(transmatrix T) { EX ld ortho_error(transmatrix T) {
ld err = 0; ld err = 0;
@ -1194,6 +1269,12 @@ inline hyperpoint tC0(const transmatrix &T) {
for(int i=0; i<MDIM; i++) z[i] = T[i][LDIM]; for(int i=0; i<MDIM; i++) z[i] = T[i][LDIM];
return z; return z;
} }
inline hyperpoint tC0_t(const transmatrix &T) { return tC0(T); }
inline shiftpoint tC0(const shiftmatrix &T) {
return shiftpoint{tC0(T.T), T.shift};
}
#endif #endif
/** tangent vector in the given direction */ /** tangent vector in the given direction */
@ -1235,18 +1316,18 @@ constexpr flagtype pNORMAL = 0;
#endif #endif
/** inverse exponential function \see hr::direct_exp */ /** inverse exponential function \see hr::direct_exp */
EX hyperpoint inverse_exp(const hyperpoint h, flagtype prec IS(pNORMAL)) { EX hyperpoint inverse_exp(const shiftpoint h, flagtype prec IS(pNORMAL)) {
#if CAP_SOLV #if CAP_SOLV
if(sn::in()) { if(sn::in()) {
if(nih) if(nih)
return sn::get_inverse_exp_nsym(h, prec); return sn::get_inverse_exp_nsym(h.h, prec);
else else
return sn::get_inverse_exp_symsol(h, prec); return sn::get_inverse_exp_symsol(h.h, prec);
} }
#endif #endif
if(nil) return nilv::get_inverse_exp(h, prec); if(nil) return nilv::get_inverse_exp(h.h, prec);
if(sl2) return slr::get_inverse_exp(h); if(sl2) return slr::get_inverse_exp(h);
if(prod) return product::inverse_exp(h); if(prod) return product::inverse_exp(h.h);
ld d = acos_auto_clamp(h[GDIM]); ld d = acos_auto_clamp(h[GDIM]);
hyperpoint v = Hypc; hyperpoint v = Hypc;
if(d && sin_auto(d)) for(int i=0; i<GDIM; i++) v[i] = h[i] * d / sin_auto(d); if(d && sin_auto(d)) for(int i=0; i<GDIM; i++) v[i] = h[i] * d / sin_auto(d);
@ -1256,7 +1337,12 @@ EX hyperpoint inverse_exp(const hyperpoint h, flagtype prec IS(pNORMAL)) {
EX ld geo_dist(const hyperpoint h1, const hyperpoint h2, flagtype prec IS(pNORMAL)) { EX ld geo_dist(const hyperpoint h1, const hyperpoint h2, flagtype prec IS(pNORMAL)) {
if(!nonisotropic) return hdist(h1, h2); if(!nonisotropic) return hdist(h1, h2);
return hypot_d(3, inverse_exp(inverse(nisot::translate(h1)) * h2, prec)); return hypot_d(3, inverse_exp(shiftless(inverse(nisot::translate(h1)) * h2, prec)));
}
EX ld geo_dist(const shiftpoint h1, const shiftpoint h2, flagtype prec IS(pNORMAL)) {
if(!nonisotropic) return hdist(h1, h2);
return hypot_d(3, inverse_exp(shiftless(inverse(nisot::translate(h1.h)) * h2.h, h2.shift - h1.shift), prec));
} }
EX ld geo_dist_q(const hyperpoint h1, const hyperpoint h2, flagtype prec IS(pNORMAL)) { EX ld geo_dist_q(const hyperpoint h1, const hyperpoint h2, flagtype prec IS(pNORMAL)) {

View File

@ -8,13 +8,14 @@
#include "hyper.h" #include "hyper.h"
namespace hr { namespace hr {
hyperpoint ghxy, ghgxy, ghpm = C0; hyperpoint ghxy, ghgxy;
shiftpoint ghpm = shiftless(C0);
#if HDR #if HDR
inline bool sphereflipped() { return sphere && pconf.alpha > 1.1 && GDIM == 3; } inline bool sphereflipped() { return sphere && pconf.alpha > 1.1 && GDIM == 3; }
#endif #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)) { if(hypot_d(2, ret-ghxy) < hypot_d(2, ghgxy-ghxy)) {
ghpm = H; ghgxy = ret; ghpm = H; ghgxy = ret;
} }
@ -88,7 +89,7 @@ EX hyperpoint space_to_perspective(hyperpoint z, ld alpha IS(pconf.alpha)) {
return z; 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 hx = (x - current_display->xcenter) / current_display->radius;
ld hy = (y - current_display->ycenter) / current_display->radius / pconf.stretch; ld hy = (y - current_display->ycenter) / current_display->radius / pconf.stretch;
@ -97,9 +98,9 @@ EX hyperpoint gethyper(ld x, ld y) {
if(pmodel) { if(pmodel) {
ghxy = hxy; ghxy = hxy;
transmatrix T = rgpushxto0(ghpm); shiftmatrix T = rgpushxto0(ghpm);
auto distance_at = [&] (const transmatrix& T1) { auto distance_at = [&] (const shiftmatrix& T1) {
hyperpoint h1; hyperpoint h1;
applymodel(tC0(T1), h1); applymodel(tC0(T1), h1);
return sqhypot_d(2, hxy - 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 it=0; it<50; it++)
for(int s=0; s<4; s++) { 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); ld dist = distance_at(T1);
if(dist < best) best = dist, T = T1; if(dist < best) best = dist, T = T1;
if(mdBandAny()) { if(mdBandAny()) {
band_shift += 2 * M_PI; T1.shift += 2 * M_PI;
dist = distance_at(T1); dist = distance_at(T1);
if(dist < best) best = dist, T = T1; if(dist < best) best = dist, T = T1;
band_shift -= 4 * M_PI; T1.shift -= 4 * M_PI;
dist = distance_at(T1); dist = distance_at(T1);
if(dist < best) best = dist, T = 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); 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) { void ballmodel(hyperpoint& ret, double alpha, double d, double zl) {
@ -221,11 +222,11 @@ void move_y_to_z(hyperpoint& H, pair<ld, ld> coef) {
} }
} }
template<class T> void makeband(hyperpoint H, hyperpoint& ret, const T& f) { template<class T> void makeband(shiftpoint H, hyperpoint& ret, const T& f) {
ld zlev = find_zlev(H); ld zlev = find_zlev(H.h);
models::apply_orientation_yz(H[1], H[2]); models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]); 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; ld x, y, yf, zf=0;
y = asin_auto(H[1]); y = asin_auto(H[1]);
@ -234,7 +235,7 @@ template<class T> void makeband(hyperpoint H, hyperpoint& ret, const T& f) {
if(H[LDIM] < 0 && x > 0) x = M_PI - x; if(H[LDIM] < 0 && x > 0) x = M_PI - x;
else 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); hypot_zlev(zlev, y, yf, zf);
f(x, y); 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 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)) { if(models::product_model(pmodel)) {
ld zlev = zlevel(H); ld zlev = zlevel(H_orig.h);
H /= exp(zlev); H_orig.h /= exp(zlev);
hybrid::in_underlying_geometry([&] { applymodel(H, ret); }); hybrid::in_underlying_geometry([&] { applymodel(H_orig, ret); });
ret[2] = zlev * pconf.product_z_scale; ret[2] = zlev * pconf.product_z_scale;
ret = NLP * ret; ret = NLP * ret;
return; return;
@ -368,7 +369,7 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) {
} }
case mdGeodesic: { 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; ld ratio = vid.xres / current_display->tanfov / current_display->radius / 2;
ret[0] = S[0]/S[2] * ratio; ret[0] = S[0]/S[2] * ratio;
ret[1] = S[1]/S[2] * ratio; ret[1] = S[1]/S[2] * ratio;
@ -391,7 +392,7 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) {
case mdDisk: { case mdDisk: {
if(nonisotropic) { if(nonisotropic) {
ret = lp_apply(inverse_exp(H, pNORMAL | pfNO_DISTANCE)); ret = lp_apply(inverse_exp(H_orig, pNORMAL | pfNO_DISTANCE));
ld w; ld w;
if(sn::in()) { if(sn::in()) {
// w = 1 / sqrt(1 - sqhypot_d(3, ret)); // w = 1 / sqrt(1 - sqhypot_d(3, ret));
@ -578,7 +579,7 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) {
case mdFisheye: { case mdFisheye: {
ld zlev; ld zlev;
if(nonisotropic) { if(nonisotropic) {
H = lp_apply(inverse_exp(H)); H = lp_apply(inverse_exp(H_orig));
zlev = 1; zlev = 1;
} }
else { else {
@ -742,15 +743,15 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) {
models::apply_orientation(ret[1], ret[0]); models::apply_orientation(ret[1], ret[0]);
} }
else else
makeband(H, ret, band_conformal); makeband(H_orig, ret, band_conformal);
break; break;
case mdTwoPoint: case mdTwoPoint:
makeband(H, ret, make_twopoint); makeband(H_orig, ret, make_twopoint);
break; break;
case mdMollweide: case mdMollweide:
makeband(H, ret, [] (ld& x, ld& y) { makeband(H_orig, ret, [] (ld& x, ld& y) {
ld theta = ld theta =
hyperbolic ? min(y / 2 + 0.572365, y * 0.78509) : hyperbolic ? min(y / 2 + 0.572365, y * 0.78509) :
euclid ? y : euclid ? y :
@ -770,12 +771,12 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) {
break; break;
case mdCentralCyl: 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; break;
case mdCollignon: case mdCollignon:
find_zlev(H); find_zlev(H_orig.h);
makeband(H, ret, [] (ld& x, ld& y) { makeband(H_orig, ret, [] (ld& x, ld& y) {
ld sgn = 1; ld sgn = 1;
if(pconf.collignon_reflected && y > 0) y = -y, sgn = -1; if(pconf.collignon_reflected && y > 0) y = -y, sgn = -1;
y = signed_sqrt(sin_auto(y) + pconf.collignon_parameter); y = signed_sqrt(sin_auto(y) + pconf.collignon_parameter);
@ -787,20 +788,20 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) {
break; break;
case mdBandEquiarea: 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; break;
case mdBandEquidistant: case mdBandEquidistant:
makeband(H, ret, [] (ld& x, ld& y) { }); makeband(H_orig, ret, [] (ld& x, ld& y) { });
break; break;
case mdSinusoidal: 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; break;
case mdEquidistant: case mdEquiarea: case mdEquivolume: { case mdEquidistant: case mdEquiarea: case mdEquivolume: {
if(nonisotropic || prod) { if(nonisotropic || prod) {
ret = lp_apply(inverse_exp(H)); ret = lp_apply(inverse_exp(H_orig));
ret[3] = 1; ret[3] = 1;
break; break;
} }
@ -855,7 +856,7 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) {
case mdFormula: { case mdFormula: {
dynamicval<eModel> m(pmodel, pconf.basic_model); dynamicval<eModel> m(pmodel, pconf.basic_model);
applymodel(H, ret); applymodel(H_orig, ret);
exp_parser ep; exp_parser ep;
ep.extra_params["z"] = cld(ret[0], ret[1]); ep.extra_params["z"] = cld(ret[0], ret[1]);
ep.extra_params["cx"] = ret[0]; ep.extra_params["cx"] = ret[0];
@ -880,7 +881,7 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) {
case mdSpiral: { case mdSpiral: {
cld z; cld z;
if(hyperbolic || sphere) makeband(H, ret, band_conformal); if(hyperbolic || sphere) makeband(H_orig, ret, band_conformal);
else ret = H; else ret = H;
z = cld(ret[0], ret[1]) * models::spiral_multiplier; z = cld(ret[0], ret[1]) * models::spiral_multiplier;
@ -934,7 +935,7 @@ EX hyperpoint mirrorif(const hyperpoint& V, bool b) {
else return V; else return V;
} }
EX transmatrix mirrorif(const transmatrix& V, bool b) { EX shiftmatrix mirrorif(const shiftmatrix& V, bool b) {
if(b) return V*Mirror; if(b) return V*Mirror;
else return V; else return V;
} }
@ -996,6 +997,10 @@ EX bool behindsphere(const transmatrix& V) {
return behindsphere(tC0(V)); return behindsphere(tC0(V));
} }
EX bool behindsphere(const shiftmatrix& V) {
return behindsphere(tC0(V.T));
}
EX ld spherity(const transmatrix& V) { EX ld spherity(const transmatrix& V) {
return spherity(tC0(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; 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(sphere) return false;
if(!in_perspective()) return false; if(!in_perspective()) return false;
if(pmodel == mdGeodesic) h = inverse_exp(h, pQUICK); hyperpoint h1;
if(pmodel == mdPerspective && prod) h = product::inverse_exp(h); if(pmodel == mdGeodesic) h1 = inverse_exp(h, pQUICK);
h = lp_apply(h); if(pmodel == mdPerspective && prod) h1 = product::inverse_exp(h.h);
return h[2] < 1e-8; h1 = lp_apply(h1);
return h1[2] < 1e-8;
} }
void raise_error() { 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]); return std::isnan(h[LDIM]) || h[LDIM] > 1e8 || std::isinf(h[LDIM]);
} }
EX bool in_smart_range(const transmatrix& T) { EX bool invalid_point(const shiftpoint h) { return invalid_point(h.h); }
hyperpoint h = tC0(T);
EX bool in_smart_range(const shiftmatrix& T) {
shiftpoint h = tC0(T);
if(invalid_point(h)) return false; if(invalid_point(h)) return false;
if(nil || nih) return true; if(nil || nih) return true;
#if CAP_SOLV #if CAP_SOLV
if(pmodel == mdGeodesic) return sn::in_table_range(h); if(pmodel == mdGeodesic) return sn::in_table_range(h.h);
#endif #endif
hyperpoint h1; hyperpoint h1;
applymodel(h, 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; 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)) { if(do_draw(c, V1)) {
/* auto li = get_local_info(c); /* auto li = get_local_info(c);
if((dir - li.total_dir) % S6) printf("totaldir %d/%d\n", dir, li.total_dir); 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; return res;
} }
bool drawrec(cell *c, const transmatrix& V) { bool drawrec(cell *c, const shiftmatrix& V) {
draw_li.relative = loc(0,0); draw_li.relative = loc(0,0);
draw_li.total_dir = 0; draw_li.total_dir = 0;
draw_li.last_dir = -1; draw_li.last_dir = -1;
@ -1176,11 +1188,9 @@ void drawrec(cell *c, const transmatrix& V) {
} }
#endif #endif
vector<tuple<heptspin, hstate, transmatrix, ld> > drawn_cells; vector<tuple<heptspin, hstate, shiftmatrix> > drawn_cells;
bool in_multi = false; EX bool drawcell_subs(cell *c, const shiftmatrix& V) {
EX bool drawcell_subs(cell *c, transmatrix V) {
#if CAP_GP #if CAP_GP
if(GOLDBERG) { if(GOLDBERG) {
@ -1196,7 +1206,7 @@ EX bool drawcell_subs(cell *c, transmatrix V) {
auto& vc = irr::cells_of_heptagon[hi.base.at]; auto& vc = irr::cells_of_heptagon[hi.base.at];
for(int i=0; i<isize(vc); i++) { for(int i=0; i<isize(vc); i++) {
cell *c = hi.subcells[i]; cell *c = hi.subcells[i];
transmatrix V1 = V * irr::cells[vc[i]].pusher; shiftmatrix V1 = V * irr::cells[vc[i]].pusher;
if(do_draw(c, V1)) if(do_draw(c, V1))
draw = true, draw = true,
drawcell(hi.subcells[i], V * irr::cells[vc[i]].pusher); drawcell(hi.subcells[i], V * irr::cells[vc[i]].pusher);
@ -1212,7 +1222,7 @@ EX bool drawcell_subs(cell *c, transmatrix V) {
if(BITRUNCATED) forCellIdEx(c1, d, c) { if(BITRUNCATED) forCellIdEx(c1, d, c) {
if(c->c.spin(d) == 0) { if(c->c.spin(d) == 0) {
transmatrix V2 = V * currentmap->adj(c, d); shiftmatrix V2 = V * currentmap->adj(c, d);
if(do_draw(c1, V2)) if(do_draw(c1, V2))
draw = true, draw = true,
drawcell(c1, V2); drawcell(c1, V2);
@ -1223,32 +1233,37 @@ EX bool drawcell_subs(cell *c, transmatrix V) {
} }
void hrmap_standard::draw() { void hrmap_standard::draw() {
static ld shift = 0;
static bool in_multi = false;
if(sphere && pmodel == mdSpiral && !in_multi) { if(sphere && pmodel == mdSpiral && !in_multi) {
/* todo other types? */
in_multi = true; in_multi = true;
if(models::ring_not_spiral) { if(models::ring_not_spiral) {
int qty = ceil(1. / pconf.sphere_spiral_multiplier); int qty = ceil(1. / pconf.sphere_spiral_multiplier);
if(qty > 100) qty = 100; if(qty > 100) qty = 100;
for(int i=-qty; i < qty; i++) { for(int i=-qty; i < qty; i++) {
band_shift = 2 * M_PI * i; shift = 2 * M_PI * i;
draw(); draw();
} }
} }
else { else {
shift = 0;
draw(); draw();
if(vid.use_smart_range) for(int i=1;; i++) { if(vid.use_smart_range) for(int i=1;; i++) {
int drawn = cells_drawn; int drawn = cells_drawn;
band_shift = 2 * M_PI * i; shift = 2 * M_PI * i;
draw(); draw();
band_shift = -2 * M_PI * i; shift = -2 * M_PI * i;
draw(); draw();
if(drawn == cells_drawn) break; if(drawn == cells_drawn) break;
} }
} }
in_multi = false; in_multi = false;
shift = 0;
return; return;
} }
drawn_cells.clear(); 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<isize(drawn_cells); i++) { for(int i=0; i<isize(drawn_cells); i++) {
// prevent reallocation due to insertion // prevent reallocation due to insertion
if(drawn_cells.capacity() < drawn_cells.size() + 16) if(drawn_cells.capacity() < drawn_cells.size() + 16)
@ -1258,12 +1273,10 @@ void hrmap_standard::draw() {
auto& hs = get<0>(dc); auto& hs = get<0>(dc);
auto& s = get<1>(dc); auto& s = get<1>(dc);
auto& V = get<2>(dc); auto& V = get<2>(dc);
dynamicval<ld> bs(band_shift, get<3>(dc));
cell *c = hs.at->c7; cell *c = hs.at->c7;
transmatrix V10; const shiftmatrix& V1 = hs.mirrored ? V * Mirror : V;
const transmatrix& V1 = hs.mirrored ? (V10 = V * Mirror) : V;
bool draw = drawcell_subs(c, actualV(hs, V1)); bool draw = drawcell_subs(c, actualV(hs, V1));
@ -1273,15 +1286,15 @@ void hrmap_standard::draw() {
hstate s2 = transition(s, d); hstate s2 = transition(s, d);
if(s2 == hsError) continue; if(s2 == hsError) continue;
heptspin hs2 = hs + d + wstep; heptspin hs2 = hs + d + wstep;
transmatrix Vd; shiftmatrix Vd;
if(inforder::mixed()) { if(inforder::mixed()) {
int d1 = gmod(hs.spin+d, c->type); int d1 = gmod(hs.spin+d, c->type);
Vd = V * spin(-2*M_PI*d/c->type) * xpush(spacedist(c, d1)) * spin(M_PI); Vd = V * spin(-2*M_PI*d/c->type) * xpush(spacedist(c, d1)) * spin(M_PI);
} }
else else
Vd = V * cgi.heptmove[d]; Vd = V * cgi.heptmove[d];
bandfixer bf(Vd); optimize_shift(Vd);
drawn_cells.emplace_back(hs2, s2, Vd, band_shift); drawn_cells.emplace_back(hs2, s2, Vd);
} }
} }
} }
@ -1320,7 +1333,7 @@ EX void spinEdge(ld aspd) {
else rotate_view(their * inverse(our)); else rotate_view(their * inverse(our));
} }
else if(playerfound && vid.fixed_facing) { 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 = atan2(H[1], H[0]);
downspin += vid.fixed_facing_dir * degree; downspin += vid.fixed_facing_dir * degree;
if(flipplayer) downspin += M_PI; if(flipplayer) downspin += M_PI;
@ -1378,12 +1391,12 @@ EX void centerpc(ld aspd) {
DEBBI(DF_GRAPH, ("center pc")); DEBBI(DF_GRAPH, ("center pc"));
auto& W = current_display->which_copy; 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? */ /* what should we center? */
transmatrix T; transmatrix T;
if(multi::players > 1) if(multi::players > 1)
T = cwtV; /* do not even try */ T = unshift(cwtV); /* do not even try */
else { else {
T = W; T = W;
if(shmup::on) if(shmup::on)
@ -1410,27 +1423,27 @@ EX void centerpc(ld aspd) {
spinEdge(aspd); spinEdge(aspd);
fixmatrix(View); fixmatrix(View);
if(gmatrix.count(cwt.at)) if(gmatrix.count(cwt.at))
current_display->which_copy = gmatrix[cwt.at]; current_display->which_copy = unshift(gmatrix[cwt.at]);
} }
else { else {
aspd *= euclid ? (2+3*R*R) : (1+R+(shmup::on?1:0)); 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)) { if(R < aspd && gmatrix.count(cwt.at) && eqmatrix(unshift(gmatrix[cwt.at]), current_display->which_copy)) {
current_display->which_copy = gmatrix[cwt.at]; current_display->which_copy = unshift(gmatrix[cwt.at]);
} }
if(R < aspd) if(R < aspd)
shift_view_to(H); shift_view_to(shiftless(H));
else else
shift_view_towards(H, aspd); shift_view_towards(shiftless(H), aspd);
fixmatrix(View); fixmatrix(View);
fixmatrix(current_display->which_copy); fixmatrix(current_display->which_copy);
spinEdge(aspd); spinEdge(aspd);
} }
ors::rerotate(W); ors::rerotate(cwtV); ors::rerotate(View); ors::rerotate(W); ors::rerotate(cwtV.T); ors::rerotate(View);
} }
EX void optimizeview() { EX void optimizeview() {
@ -1470,7 +1483,7 @@ void ballgeometry() {
addball(0, 0, -vid.camera); addball(0, 0, -vid.camera);
addball(0, -10, 0); addball(0, -10, 0);
addball(0, 0, -vid.camera); 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); queuereset(pmodel, PPR::CIRCLE);
} }
@ -1512,7 +1525,7 @@ EX void resetview() {
centerover = currentmap->gamestart(); centerover = currentmap->gamestart();
View = Id; View = Id;
} }
cwtV = View; cwtV = shiftless(View);
current_display->which_copy = current_display->which_copy =
nonisotropic ? gpushxto0(tC0(inverse(View))) : nonisotropic ? gpushxto0(tC0(inverse(View))) :
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 = View =
rgpushxto0(hf) * rgpushxto0(gpushxto0(hf) * ht) * gpushxto0(hf) * View; rgpushxto0(hf) * rgpushxto0(gpushxto0(hf) * ht) * gpushxto0(hf) * View;
playermoved = false; playermoved = false;
@ -1623,7 +1638,7 @@ void circle_around_center(ld radius, color_t linecol, color_t fillcol, PPR prio)
#if CAP_QUEUE #if CAP_QUEUE
if(among(pmodel, mdDisk, mdEquiarea, mdEquidistant, mdFisheye) && !(pmodel == mdDisk && hyperbolic && pconf.alpha <= -1) && pconf.camera_angle == 0) { if(among(pmodel, mdDisk, mdEquiarea, mdEquidistant, mdFisheye) && !(pmodel == mdDisk && hyperbolic && pconf.alpha <= -1) && pconf.camera_angle == 0) {
hyperpoint ret; hyperpoint ret;
applymodel(xpush0(radius), ret); applymodel(shiftless(xpush0(radius)), ret);
ld r = hypot_d(2, ret); ld r = hypot_d(2, ret);
queuecircle(current_display->xcenter, current_display->ycenter, r * current_display->radius, linecol, prio, fillcol); queuecircle(current_display->xcenter, current_display->ycenter, r * current_display->radius, linecol, prio, fillcol);
return; return;
@ -1631,7 +1646,7 @@ void circle_around_center(ld radius, color_t linecol, color_t fillcol, PPR prio)
#endif #endif
#if CAP_QUEUE #if CAP_QUEUE
for(int i=0; i<=360; i++) curvepoint(xspinpush0(i * degree, 10)); 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) if(pmodel == mdDisk && hyperbolic && pconf.alpha <= -1)
c.flags |= POLY_FORCE_INVERTED; c.flags |= POLY_FORCE_INVERTED;
if(pmodel == mdJoukowsky) if(pmodel == mdJoukowsky)
@ -1672,7 +1687,7 @@ EX void draw_model_elements() {
models::apply_orientation_yz(res[2], res[1]); models::apply_orientation_yz(res[2], res[1]);
curvepoint(res * current_display->radius); curvepoint(res * current_display->radius);
} }
queuecurve(ringcolor, 0, PPR::CIRCLE); queuecurve(shiftless(Id), ringcolor, 0, PPR::CIRCLE);
} }
queuereset(pmodel, PPR::CIRCLE); queuereset(pmodel, PPR::CIRCLE);
@ -1681,8 +1696,8 @@ EX void draw_model_elements() {
case mdTwoPoint: case mdSimulatedPerspective: { case mdTwoPoint: case mdSimulatedPerspective: {
ld a = -pconf.model_orientation * degree; ld a = -pconf.model_orientation * degree;
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(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; return;
} }
@ -1697,7 +1712,7 @@ EX void draw_model_elements() {
#if CAP_QUEUE #if CAP_QUEUE
curvepoint(point3(0,0,1)); curvepoint(point3(0,0,1));
curvepoint(point3(0,0,-pconf.alpha)); curvepoint(point3(0,0,-pconf.alpha));
queuecurve(ringcolor, 0, PPR::CIRCLE); queuecurve(shiftless(Id), ringcolor, 0, PPR::CIRCLE);
ld& tz = pconf.top_z; ld& tz = pconf.top_z;
ld z = acosh(tz); ld z = acosh(tz);
@ -1715,11 +1730,11 @@ EX void draw_model_elements() {
a[0] = -a[0]; a[0] = -a[0];
curvepoint(a); curvepoint(a);
curvepoint(point3(0,0,-pconf.alpha)); 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));
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[1] = sb * tz / -cb;
a[0] = sqrt(tz * tz - a[1] * a[1]); a[0] = sqrt(tz * tz - a[1] * a[1]);
@ -1729,7 +1744,7 @@ EX void draw_model_elements() {
curvepoint(point3(0,0,-pconf.alpha)); curvepoint(point3(0,0,-pconf.alpha));
a[0] = -a[0]; a[0] = -a[0];
curvepoint(a); curvepoint(a);
queuecurve(ringcolor, 0, PPR::CIRCLE); queuecurve(shiftless(Id), ringcolor, 0, PPR::CIRCLE);
#endif #endif
} }
return; return;
@ -1742,7 +1757,7 @@ EX void draw_model_elements() {
void queuestraight(hyperpoint X, int style, color_t lc, color_t fc, PPR p) { void queuestraight(hyperpoint X, int style, color_t lc, color_t fc, PPR p) {
hyperpoint H0, H1; hyperpoint H0, H1;
applymodel(X, H0); applymodel(shiftless(X), H0);
H0 *= current_display->radius; H0 *= current_display->radius;
ld mul0 = hypot(vid.xres, vid.yres) / hypot_d(2, H0); 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; H1 = H0 * -mul0;
} }
else { else {
applymodel(pispin * X, H1); applymodel(shiftless(pispin * X), H1);
H1 *= current_display->radius; 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(H1 - spin(M_PI/2) * H1 * mul1);
curvepoint(H0 + spin(M_PI/2) * H0 * mul0); 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); queuereset(pmodel, p);
/* /*
for(int i=0; i<1; i++) { for(int i=0; i<1; i++) {
@ -1812,7 +1827,7 @@ EX void draw_boundary(int w) {
ld z = -sqrt(1 - x*x); ld z = -sqrt(1 - x*x);
models::apply_orientation(y, x); models::apply_orientation(y, x);
hyperpoint h1; hyperpoint h1;
applymodel(hpxyz(x,y,z), h1); applymodel(shiftless(hpxyz(x,y,z)), h1);
models::apply_orientation(h1[0], h1[1]); models::apply_orientation(h1[0], h1[1]);
h1[1] = abs(h1[1]) * b; h1[1] = abs(h1[1]) * b;
@ -1820,7 +1835,7 @@ EX void draw_boundary(int w) {
curvepoint(h1); curvepoint(h1);
} }
queuecurve(lc, fc, p).flags |= POLY_FORCEWIDE; queuecurve(shiftless(Id), lc, fc, p).flags |= POLY_FORCEWIDE;
queuereset(pmodel, p); queuereset(pmodel, p);
return; return;
} }
@ -1846,7 +1861,7 @@ EX void draw_boundary(int w) {
curvepoint(T * xpush(-xperiod) * ypush0(-a * adegree)); curvepoint(T * xpush(-xperiod) * ypush0(-a * adegree));
} }
curvepoint(T * xpush(xperiod) * ypush0(-90 * 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; return;
} }
@ -1865,7 +1880,7 @@ EX void draw_boundary(int w) {
ld s = sin(i * degree); 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)); 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); queuereset(pmodel, p);
p = PPR::CIRCLE; fc = 0; p = PPR::CIRCLE; fc = 0;
queuereset(mdPixel, p); queuereset(mdPixel, p);
@ -1874,7 +1889,7 @@ EX void draw_boundary(int w) {
ld s = sin(i * degree); ld s = sin(i * degree);
curvepoint(point3(current_display->radius * cos(i * degree), current_display->radius * s * models::sin_ball, 0)); 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); queuereset(pmodel, p);
} }
if(euclid || sphere) { if(euclid || sphere) {
@ -1882,7 +1897,7 @@ EX void draw_boundary(int w) {
for(int i=0; i<=360; i++) { for(int i=0; i<=360; i++) {
curvepoint(point3(current_display->radius * cos(i * degree), current_display->radius * sin(i * degree), 0)); 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); queuereset(pmodel, p);
} }
return; return;
@ -1928,14 +1943,14 @@ EX void draw_boundary(int w) {
curvepoint(xspinpush0(+M_PI/2 - t * alpha, mz)); curvepoint(xspinpush0(+M_PI/2 - t * alpha, mz));
} }
queuecurve(lc, fc, p); queuecurve(shiftless(Id), lc, fc, p);
fc = 0; p = PPR::CIRCLE; fc = 0; p = PPR::CIRCLE;
} }
for(ld t=0; t<=360; t ++) for(ld t=0; t<=360; t ++)
curvepoint(xspinpush0(t * degree, mz)); curvepoint(xspinpush0(t * degree, mz));
queuecurve(lc, fc, p); queuecurve(shiftless(Id), lc, fc, p);
} }
return; return;
} }
@ -1955,7 +1970,7 @@ EX void draw_boundary(int w) {
ret *= current_display->radius; ret *= current_display->radius;
curvepoint(ret); curvepoint(ret);
} }
queuecurve(ringcolor, 0, p).flags |= POLY_ALWAYS_IN; queuecurve(shiftless(Id), ringcolor, 0, p).flags |= POLY_ALWAYS_IN;
queuereset(pmodel, p); queuereset(pmodel, p);
} }
return; return;
@ -1975,11 +1990,59 @@ EX void draw_boundary(int w) {
} }
#endif #endif
EX ld band_shift = 0; EX void change_shift(shiftpoint& h, ld by) {
EX void fix_the_band(transmatrix& T) { h.shift += by;
if(((mdinf[pmodel].flags & mf::uses_bandshift) && T[LDIM][LDIM] > 1e6) || (sphere && pmodel == mdSpiral)) { if((mdinf[pmodel].flags & mf::uses_bandshift) || (sphere && pmodel == mdSpiral)) {
T = spin(pconf.model_orientation * degree) * T; h.h = spin(pconf.model_orientation * degree) * h.h;
hyperpoint H = tC0(T); 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); find_zlev(H);
ld y = asin_auto(H[1]); 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; if(H[LDIM] < 0 && x > 0) x = M_PI - x;
else 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.shift += x;
T = xpush(-x) * T; T.T = xpush(-x) * T.T;
fixmatrix(T); fixmatrix(T.T);
T = spin(-pconf.model_orientation * degree) * 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 EX shiftmatrix optimized_shift(const shiftmatrix& T) {
struct bandfixer { shiftmatrix U = T;
dynamicval<ld> bw; optimize_shift(U);
bandfixer(transmatrix& T) : bw(band_shift, band_shift) { fix_the_band(T); } return U;
}; }
#endif
EX namespace dq { EX namespace dq {
EX queue<tuple<heptagon*, transmatrix, ld>> drawqueue; EX queue<pair<heptagon*, shiftmatrix>> drawqueue;
EX unsigned bucketer(const shiftpoint& T) {
return bucketer(T.h) + unsigned(floor(T.shift*81527+.5));
}
EX set<heptagon*> visited; EX set<heptagon*> visited;
EX void enqueue(heptagon *h, const transmatrix& T) { EX void enqueue(heptagon *h, const shiftmatrix& T) {
if(!h || visited.count(h)) { return; } if(!h || visited.count(h)) { return; }
visited.insert(h); visited.insert(h);
drawqueue.emplace(h, T, band_shift); drawqueue.emplace(h, T);
} }
EX set<int> visited_by_matrix; EX set<unsigned> visited_by_matrix;
EX void enqueue_by_matrix(heptagon *h, const transmatrix& T) { EX void enqueue_by_matrix(heptagon *h, const shiftmatrix& T) {
if(!h) return; 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; } if(visited_by_matrix.count(b)) { return; }
visited_by_matrix.insert(b); visited_by_matrix.insert(b);
drawqueue.emplace(h, T, band_shift); drawqueue.emplace(h, T);
} }
EX queue<tuple<cell*, transmatrix, ld>> drawqueue_c; EX queue<pair<cell*, shiftmatrix>> drawqueue_c;
EX set<cell*> visited_c; EX set<cell*> 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; } if(!c || visited_c.count(c)) { return; }
visited_c.insert(c); 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; 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; } if(visited_by_matrix.count(b)) { return; }
visited_by_matrix.insert(b); visited_by_matrix.insert(b);
drawqueue_c.emplace(c, T, band_shift); drawqueue_c.emplace(c, T);
} }
EX void clear_all() { EX void clear_all() {
@ -2072,7 +2149,7 @@ bool limited_generation(cell *c) {
return true; return true;
} }
EX bool do_draw(cell *c, const transmatrix& T) { EX bool do_draw(cell *c, const shiftmatrix& T) {
if(WDIM == 3) { if(WDIM == 3) {
// do not care about cells outside of the track // 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; if(dist <= extra_generation_distance && !limited_generation(c)) return false;
} }
else if(pmodel == mdGeodesic && sol) { 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; if(!limited_generation(c)) return false;
} }
else if(pmodel == mdGeodesic && nih) { 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; if(dist <= extra_generation_distance && !limited_generation(c)) return false;
} }
else if(pmodel == mdGeodesic && sl2) { else if(pmodel == mdGeodesic && sl2) {
if(hypot(tC0(T)[2], tC0(T)[3]) > cosh(slr::range_xy)) return false; if(hypot(tC0(T.T)[2], tC0(T.T)[3]) > cosh(slr::range_xy)) return false;
if(band_shift * stretch::not_squared() > sightranges[geometry]) return false; if(T.shift * stretch::not_squared() > sightranges[geometry]) return false;
if(!limited_generation(c)) return false; if(!limited_generation(c)) return false;
} }
else if(vid.use_smart_range) { 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; if(!limited_generation(c)) return false;
} }
else { 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 > sightranges[geometry] + (vid.sloppy_3d ? 0 : cgi.corner_bonus)) return false;
if(dist <= extra_generation_distance && !limited_generation(c)) 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(just_gmatrix && sphere) return true;
if(!do_draw(c)) return false; if(!do_draw(c)) return false;
if(euclid && pmodel == mdSpiral) { if(euclid && pmodel == mdSpiral) {
hyperpoint h = tC0(T); hyperpoint h = tC0(T.T);
cld z(h[0], h[1]); cld z(h[0], h[1]);
z = z * models::spiral_multiplier; z = z * models::spiral_multiplier;
ld iz = imag(z) + 1.14279e-2; // make it never fall exactly on PI 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) { if(pmodel == mdSpiral && models::ring_not_spiral) {
cld z; cld z;
hyperpoint H = tC0(T); shiftpoint H = tC0(T);
hyperpoint ret; hyperpoint ret;
makeband(H, ret, band_conformal); makeband(H, ret, band_conformal);
z = cld(ret[0], ret[1]) * models::spiral_multiplier; z = cld(ret[0], ret[1]) * models::spiral_multiplier;
@ -2136,10 +2213,10 @@ EX bool do_draw(cell *c, const transmatrix& T) {
return true; return true;
} }
EX int cone_side(const hyperpoint H) { EX int cone_side(const shiftpoint H) {
hyperpoint ret; hyperpoint ret;
if(hyperbolic) makeband(H, ret, band_conformal); if(hyperbolic) makeband(H, ret, band_conformal);
else ret = H; else ret = unshift(H);
cld z = cld(ret[0], ret[1]) * models::spiral_multiplier; cld z = cld(ret[0], ret[1]) * models::spiral_multiplier;
auto zth = [&] (cld z) { auto zth = [&] (cld z) {
@ -2217,16 +2294,16 @@ void multiply_view(transmatrix T) {
wc = T * wc; wc = T * wc;
} }
EX void shift_view_to(hyperpoint H) { EX void shift_view_to(shiftpoint H) {
if(!nonisotropic) multiply_view(gpushxto0(H)); if(!nonisotropic) multiply_view(gpushxto0(unshift(H)));
else shift_view(-inverse_exp(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) 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) else if(nonisotropic && !nisot::geodesic_movement)
shift_view(tangent_length(H-C0, -l)); shift_view(tangent_length(unshift(H)-C0, -l));
else { else {
hyperpoint ie = inverse_exp(H, pNORMAL | pfNO_DISTANCE); hyperpoint ie = inverse_exp(H, pNORMAL | pfNO_DISTANCE);
if(prod) ie = lp_apply(ie); if(prod) ie = lp_apply(ie);

View File

@ -536,7 +536,7 @@ EX namespace inv {
if(gg) { if(gg) {
initquickqueue(); initquickqueue();
transmatrix V = atscreenpos(px, py, rad*2); 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(); quickqueue();
} }

View File

@ -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) { if(gridmaking) {
heptagon *h = c->master; heptagon *h = c->master;
for(int i: cells_of_heptagon[h]) { for(int i: cells_of_heptagon[h]) {

View File

@ -327,7 +327,7 @@ struct hrmap_kite : hrmap {
transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) override { transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) override {
if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) 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; transmatrix gm = Id, where = Id;
while(h1 != h2) { while(h1 != h2) {
if(h1->distance <= h2->distance) if(h1->distance <= h2->distance)
@ -345,15 +345,13 @@ struct hrmap_kite : hrmap {
void draw() override { void draw() override {
dq::visited.clear(); dq::clear_all();
dq::enqueue(centerover->master, cview()); dq::enqueue(centerover->master, cview());
while(!dq::drawqueue.empty()) { while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front(); auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p); heptagon *h = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
dq::drawqueue.pop(); dq::drawqueue.pop();
cell *c = h->c7; cell *c = h->c7;
@ -361,7 +359,7 @@ struct hrmap_kite : hrmap {
drawcell(c, V); drawcell(c, V);
for(int i=0; i<c->type; i++) for(int i=0; i<c->type; 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); ld err = hdist(where[h->c7->cmove(i)->master] * C0, where[h] * M * C0);
if(err > -.01) if(err > -.01)

View File

@ -30,7 +30,7 @@ EX namespace mapeditor {
virtual void rotate(const transmatrix& T) = 0; virtual void rotate(const transmatrix& T) = 0;
virtual void save(hstream& hs) = 0; virtual void save(hstream& hs) = 0;
virtual dtshape* load(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 ld distance(hyperpoint h) = 0;
virtual ~dtshape() {} virtual ~dtshape() {}
}; };
@ -53,7 +53,7 @@ EX namespace mapeditor {
hs.read(e); hs.read(e);
return this; return this;
} }
void draw(const transmatrix& V) override { void draw(const shiftmatrix& V) override {
queueline(V*s, V*e, col, 2 + vid.linequality); queueline(V*s, V*e, col, 2 + vid.linequality);
} }
ld distance(hyperpoint h) override { ld distance(hyperpoint h) override {
@ -78,13 +78,13 @@ EX namespace mapeditor {
hs.read(radius); hs.read(radius);
return this; return this;
} }
void draw(const transmatrix& V) override { void draw(const shiftmatrix& V) override {
ld len = sin_auto(radius); ld len = sin_auto(radius);
int ll = ceil(360 * len); int ll = ceil(360 * len);
transmatrix W = V * rgpushxto0(s); shiftmatrix W = V * rgpushxto0(s);
for(int i=0; i<=ll; i++) for(int i=0; i<=ll; i++)
curvepoint(W * xspinpush0(360*degree*i/ll, radius)); curvepoint(xspinpush0(360*degree*i/ll, radius));
queuecurve(col, fill, PPR::LINE); queuecurve(W, col, fill, PPR::LINE);
} }
ld distance(hyperpoint h) override { ld distance(hyperpoint h) override {
@ -115,7 +115,7 @@ EX namespace mapeditor {
return this; return this;
} }
void draw(const transmatrix& V) override { void draw(const shiftmatrix& V) override {
queuestr(V * rgpushxto0(where), size, caption, col); queuestr(V * rgpushxto0(where), size, caption, col);
} }
@ -139,9 +139,9 @@ EX namespace mapeditor {
hs.read(lh); hs.read(lh);
return this; return this;
} }
void draw(const transmatrix& V) override { void draw(const shiftmatrix& V) override {
for(auto& p: lh) curvepoint(V*p); for(auto& p: lh) curvepoint(p);
queuecurve(col, fill, PPR::LINE); queuecurve(V, col, fill, PPR::LINE);
} }
ld distance(hyperpoint h) override { ld distance(hyperpoint h) override {
@ -160,7 +160,7 @@ EX namespace mapeditor {
if(shp == nullptr) continue; if(shp == nullptr) continue;
auto& sh = *shp; auto& sh = *shp;
cell*& c = sh.where; 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<ld> lw(vid.linewidth, vid.linewidth * sh.lw); dynamicval<ld> lw(vid.linewidth, vid.linewidth * sh.lw);
sh.draw(V); sh.draw(V);
} }
@ -173,7 +173,7 @@ EX namespace mapeditor {
else if(holdmouse && mousekey == 'l') else if(holdmouse && mousekey == 'l')
queueline(lstart, mouseh, dtcolor, 4 + vid.linequality, PPR::LINE); queueline(lstart, mouseh, dtcolor, 4 + vid.linequality, PPR::LINE);
else if(!holdmouse) { else if(!holdmouse) {
transmatrix T = rgpushxto0(mouseh); shiftmatrix T = rgpushxto0(mouseh);
queueline(T * xpush0(-.1), T * xpush0(.1), dtcolor); queueline(T * xpush0(-.1), T * xpush0(.1), dtcolor);
queueline(T * ypush0(-.1), T * ypush0(.1), dtcolor); queueline(T * ypush0(-.1), T * ypush0(.1), dtcolor);
} }
@ -190,47 +190,46 @@ EX namespace mapeditor {
dtshapes.push_back(unique_ptr<dtshape>(sh)); dtshapes.push_back(unique_ptr<dtshape>(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) { 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(h1, h3, maxl-1);
dt_add_line(h3, h2, maxl-1); dt_add_line(h3, h2, maxl-1);
return; return;
} }
cell *b = centerover; cell *b = centerover;
transmatrix T = rgpushxto0(h1);
auto T1 = inverse(ggmatrix(b)) * T; auto xh1 = inverse_shift(ggmatrix(b), h1);
virtualRebase(b, T1); virtualRebase(b, xh1);
auto l = new dtline; auto l = new dtline;
l->s = tC0(T1); l->s = xh1;
l->e = T1 * gpushxto0(h1) * h2; l->e = inverse_shift(ggmatrix(b), h2);
dt_add(b, l); 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; cell *b = centerover;
auto d = hdist(h1, h2); auto d = hdist(h1, h2);
h1 = inverse(ggmatrix(b)) * h1; auto xh1 = inverse_shift(ggmatrix(b), h1);
virtualRebase(b, h1); virtualRebase(b, xh1);
auto l = new dtcircle; auto l = new dtcircle;
l->s = h1; l->s = xh1;
l->radius = d; l->radius = d;
dt_add(b, l); 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; cell *b = centerover;
h = inverse(ggmatrix(b)) * h; auto xh = inverse_shift(ggmatrix(b), h);
virtualRebase(b, h); virtualRebase(b, xh);
auto l = new dttext; auto l = new dttext;
l->where = h; l->where = xh;
l->size = size; l->size = size;
l->caption = cap; l->caption = cap;
dt_add(b, l); dt_add(b, l);
@ -257,26 +256,26 @@ EX namespace mapeditor {
cell *cfree_at; cell *cfree_at;
transmatrix cfree_T; transmatrix cfree_T;
EX void dt_add_free(hyperpoint h) { EX void dt_add_free(shiftpoint h) {
cell *b = centerover; cell *b = centerover;
transmatrix T = rgpushxto0(h); shiftmatrix T = rgpushxto0(h);
auto T1 = inverse(ggmatrix(b)) * T; auto T1 = inverse_shift(ggmatrix(b), T);
virtualRebase(b, T1); virtualRebase(b, T1);
if(cfree) if(cfree)
cfree->lh.push_back(cfree_T * h); cfree->lh.push_back(cfree_T * h.h);
if(b != cfree_at && !(dtfill && cfree_at)) { if(b != cfree_at && !(dtfill && cfree_at)) {
cfree = new dtfree; cfree = new dtfree;
dt_add(b, cfree); dt_add(b, cfree);
cfree_T = T1 * gpushxto0(h); cfree_T = T1 * gpushxto0(h.h);
cfree->lh.push_back(cfree_T * h); cfree->lh.push_back(cfree_T * h.h);
cfree_at = b; cfree_at = b;
} }
} }
EX void dt_erase(hyperpoint h) { EX void dt_erase(shiftpoint h) {
ld nearest = 1; ld nearest = 1;
int nearest_id = -1; int nearest_id = -1;
int id = -1; int id = -1;
@ -285,8 +284,8 @@ EX namespace mapeditor {
if(shp == nullptr) continue; if(shp == nullptr) continue;
auto& sh = *shp; auto& sh = *shp;
cell*& c = sh.where; cell*& c = sh.where;
for(const transmatrix& V: current_display->all_drawn_copies[c]) { for(const shiftmatrix& V: current_display->all_drawn_copies[c]) {
ld dist = sh.distance(inverse(V) * h); ld dist = sh.distance(inverse_shift(V, h));
if(dist < nearest) nearest = dist, nearest_id = id; if(dist < nearest) nearest = dist, nearest_id = id;
} }
} }
@ -294,7 +293,7 @@ EX namespace mapeditor {
dtshapes.erase(dtshapes.begin() + nearest_id); dtshapes.erase(dtshapes.begin() + nearest_id);
} }
EX hyperpoint lstart; EX shiftpoint lstart;
cell *lstartcell; cell *lstartcell;
ld front_edit = 0.5; ld front_edit = 0.5;
enum class eFront { sphere_camera, sphere_center, equidistants, const_x, const_y }; 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 // fake key sent to change the color
static const int COLORKEY = (-10000); static const int COLORKEY = (-10000);
EX transmatrix drawtrans, drawtransnew; EX shiftmatrix drawtrans, drawtransnew;
#if CAP_POLY #if CAP_POLY
void loadShape(int sg, int id, hpcshape& sh, int d, int layer) { void loadShape(int sg, int id, hpcshape& sh, int d, int layer) {
@ -1492,7 +1491,7 @@ namespace mapeditor {
} }
#endif #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(!(cmode & sm::MAP)) return;
if(darken != 0) return; if(darken != 0) return;
if(GDIM == 2 && mouseout()) return; if(GDIM == 2 && mouseout()) return;
@ -1510,33 +1509,33 @@ namespace mapeditor {
unsigned gridcolor = 0xC0C0C040; unsigned gridcolor = 0xC0C0C040;
hyperpoint in_front_dist(ld d) { shiftpoint in_front_dist(ld d) {
return direct_exp(lp_iapply(ztangent(d))); return shiftless(direct_exp(lp_iapply(ztangent(d)))); /* todo direct_shift */
} }
hyperpoint find_mouseh3() { shiftpoint find_mouseh3() {
if(front_config == eFront::sphere_camera) if(front_config == eFront::sphere_camera)
return in_front_dist(front_edit); return in_front_dist(front_edit);
ld step = 0.01; ld step = 0.01;
ld cdist = 0; ld cdist = 0;
auto idt = inverse(drawtrans); auto idt = inverse(unshift(drawtrans));
auto qu = [&] (ld d) { auto qu = [&] (ld d) {
ld d1 = front_edit; ld d1 = front_edit;
hyperpoint h1 = in_front_dist(d); shiftpoint h1 = in_front_dist(d);
if(front_config == eFront::sphere_center) if(front_config == eFront::sphere_center)
d1 = geo_dist(drawtrans * C0, h1); d1 = geo_dist(drawtrans * C0, h1);
if(front_config == eFront::equidistants) { 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]); d1 = asin_auto(h[2]);
} }
if(front_config == eFront::const_x) { 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]); d1 = asin_auto(h[0]);
} }
if(front_config == eFront::const_y) { 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]); d1 = asin_auto(h[1]);
} }
return pow(d1 - front_edit, 2); return pow(d1 - front_edit, 2);
@ -1558,29 +1557,29 @@ namespace mapeditor {
if(!drawcell) drawcell = cwt.at; if(!drawcell) drawcell = cwt.at;
color_t lightgrid = gridcolor; color_t lightgrid = gridcolor;
lightgrid -= (lightgrid & 0xFF) / 2; 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) { if(GDIM == 3) {
queuecircleat(mapeditor::drawcell, 1, 0x80D080FF); queuecircleat(mapeditor::drawcell, 1, 0x80D080FF);
color_t cols[4] = { 0x80D080FF, 0x80D080FF, 0xFFFFFF40, 0x00000040 }; color_t cols[4] = { 0x80D080FF, 0x80D080FF, 0xFFFFFF40, 0x00000040 };
if(true) { if(true) {
transmatrix t = rgpushxto0(find_mouseh3()); shiftmatrix t = rgpushxto0(find_mouseh3());
for(int i=0; i<4; i++) 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); 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) { if(front_config == eFront::sphere_center) for(int i=0; i<4; i+=2) {
auto pt = [&] (ld a, ld b) { 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; ai<parallels; ai++) { for(int ai=0; ai<parallels; ai++) {
ld a = ai * 360 / parallels; ld a = ai * 360 / parallels;
for(int b=-90; b<90; b+=5) curvepoint(pt(a,b)); for(int b=-90; b<90; b+=5) curvepoint(pt(a,b));
queuecurve(cols[i + ((ai*4) % parallels != 0)], 0, i < 2 ? PPR::LINE : PPR::SUPERLINE); queuecurve(d2, cols[i + ((ai*4) % parallels != 0)], 0, i < 2 ? PPR::LINE : PPR::SUPERLINE);
} }
for(int bi=1-meridians; bi<meridians; bi++) { for(int bi=1-meridians; bi<meridians; bi++) {
ld b = 90 * bi / meridians; ld b = 90 * bi / meridians;
for(int a=0; a<=360; a+=5) curvepoint(pt(a, b)); for(int a=0; a<=360; a+=5) curvepoint(pt(a, b));
queuecurve(cols[i + (bi != 0)], 0, i < 2 ? PPR::LINE : PPR::SUPERLINE); queuecurve(d2, cols[i + (bi != 0)], 0, i < 2 ? PPR::LINE : PPR::SUPERLINE);
} }
} }
transmatrix T; transmatrix T;
@ -1591,13 +1590,13 @@ namespace mapeditor {
for(int i=0; i<4; i+=2) { for(int i=0; i<4; i+=2) {
for(int u=2; u<=20; u++) { for(int u=2; u<=20; u++) {
PRING(d) { PRING(d) {
curvepoint(d2 * T * xspinpush(M_PI*d/cgi.S42, u/20.) * zpush0(front_edit)); curvepoint(T * xspinpush(M_PI*d/cgi.S42, u/20.) * zpush0(front_edit));
} }
queuecurve(cols[i + (u%5 != 0)], 0, i < 2 ? PPR::LINE : PPR::SUPERLINE); queuecurve(d2, cols[i + (u%5 != 0)], 0, i < 2 ? PPR::LINE : PPR::SUPERLINE);
} }
for(int d=0; d<cgi.S84; d++) { for(int d=0; d<cgi.S84; d++) {
for(int u=0; u<=20; u++) curvepoint(d2 * T * xspinpush(M_PI*d/cgi.S42, u/20.) * zpush(front_edit) * C0); for(int u=0; u<=20; u++) curvepoint(T * xspinpush(M_PI*d/cgi.S42, u/20.) * zpush(front_edit) * C0);
queuecurve(cols[i + (d % (cgi.S84/drawcell->type) != 0)], 0, i < 2 ? PPR::LINE : PPR::SUPERLINE); queuecurve(d2, cols[i + (d % (cgi.S84/drawcell->type) != 0)], 0, i < 2 ? PPR::LINE : PPR::SUPERLINE);
} }
} }
return; return;
@ -1609,9 +1608,9 @@ namespace mapeditor {
} }
for(int u=2; u<=20; u++) { for(int u=2; u<=20; u++) {
PRING(d) { 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); queueline(drawtrans*ccenter, drawtrans*coldcenter, gridcolor, 4 + vid.linequality);
} }
@ -1844,18 +1843,18 @@ namespace mapeditor {
if(!mouseout()) { if(!mouseout()) {
hyperpoint mh; hyperpoint mh;
if(GDIM == 2) { if(GDIM == 2) {
transmatrix T = inverse(drawtrans * rgpushxto0(ccenter)); transmatrix T = inverse(unshift(drawtrans)) * rgpushxto0(ccenter); /* todo? */
mh = spintox(gpushxto0(ccenter) * coldcenter) * T * mouseh; mh = spintox(gpushxto0(ccenter) * coldcenter) * T * unshift(mouseh);
} }
else 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*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*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); displayfr(vid.xres-8, vid.yres-8-fs*5, 2, vid.fsize, XLAT("z: %1", fts(mh[2],4)), 0xC0C0C0, 16);
if(MDIM == 4) if(MDIM == 4)
displayfr(vid.xres-8, vid.yres-8-fs*4, 2, vid.fsize, XLAT("w: %1", fts(mh[3],4)), 0xC0C0C0, 16); 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); 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) { 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); 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<bool> ws(mmspatial, false); dynamicval<bool> ws(mmspatial, false);
auto sId = shiftless(Id);
if(sg == 0) { 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) { 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) { 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 { else {
draw_qfi(drawcell, Id, 0, PPR::FLOOR); draw_qfi(drawcell, sId, 0, PPR::FLOOR);
} }
sortquickqueue(); sortquickqueue();
@ -1933,7 +1933,7 @@ namespace mapeditor {
int d = dsCur->rots * (dsCur->sym ? 2 : 1); int d = dsCur->rots * (dsCur->sym ? 2 : 1);
for(int i=0; i < cnt/d; i++) 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++; layer++;
if(layer == USERLAYERS) break; if(layer == USERLAYERS) break;
@ -2238,12 +2238,12 @@ namespace mapeditor {
addMessage(XLAT("Hint: use F7 to edit floor under the player")); addMessage(XLAT("Hint: use F7 to edit floor under the player"));
} }
hyperpoint mh = GDIM == 2 ? mouseh : find_mouseh3(); shiftpoint mh = GDIM == 2 ? mouseh : find_mouseh3();
mh = inverse(drawtrans) * mh; hyperpoint mh1 = inverse_shift(drawtrans, mh);
bool clickused = false; 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[] = { static unsigned grid_colors[] = {
8, 8,
0x00000040, 0x00000040,
@ -2262,7 +2262,7 @@ namespace mapeditor {
char mkuni = uni == '-' ? mousekey : uni; char mkuni = uni == '-' ? mousekey : uni;
if(mkuni == 'g') 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') if(uni == 'd' || uni == 'l' || uni == 'c' || uni == 'e' || uni == 'T')
mousekey = uni; mousekey = uni;
@ -2413,7 +2413,7 @@ namespace mapeditor {
ld rad = hdist(lstart, mouseh); ld rad = hdist(lstart, mouseh);
int circp = int(1 + 3 * (circlelength(rad) / dtwidth)); int circp = int(1 + 3 * (circlelength(rad) / dtwidth));
if(circp > 1000) circp = 1000; if(circp > 1000) circp = 1000;
transmatrix T = rgpushxto0(lstart); shiftmatrix T = rgpushxto0(lstart);
texture::where = lstartcell; texture::where = lstartcell;
for(int i=0; i<circp; i++) for(int i=0; i<circp; i++)
texture::drawPixel(T * xspinpush0(2 * M_PI * i / circp, rad), tcolor); texture::drawPixel(T * xspinpush0(2 * M_PI * i / circp, rad), tcolor);
@ -2427,7 +2427,7 @@ namespace mapeditor {
else if(mousekey == 'T') { else if(mousekey == 'T') {
static string text = ""; static string text = "";
dialog::edit_string(text, "", ""); dialog::edit_string(text, "", "");
hyperpoint h = mouseh; shiftpoint h = mouseh;
dialog::reaction_final = [h] { dialog::reaction_final = [h] {
if(text != "") if(text != "")
dt_add_text(h, dtwidth * 50, text); dt_add_text(h, dtwidth * 50, text);
@ -2474,7 +2474,7 @@ namespace mapeditor {
else { else {
dslayer %= USERLAYERS; dslayer %= USERLAYERS;
applyToShape(drawcellShapeGroup(), drawcellShapeID(), uni, mh); applyToShape(drawcellShapeGroup(), drawcellShapeID(), uni, mh1);
if(uni == 'e' || (uni == '-' && mousekey == 'e')) { if(uni == 'e' || (uni == '-' && mousekey == 'e')) {
initdraw(mouseover ? mouseover : cwt.at); initdraw(mouseover ? mouseover : cwt.at);
@ -2569,17 +2569,17 @@ namespace mapeditor {
transmatrix textrans; transmatrix textrans;
EX void queue_hcircle(transmatrix Ctr, ld radius) { EX void queue_hcircle(shiftmatrix Ctr, ld radius) {
vector<hyperpoint> pts; vector<hyperpoint> pts;
int circp = int(6 * pow(2, vid.linequality)); int circp = int(6 * pow(2, vid.linequality));
if(radius > 0.04) circp *= 2; if(radius > 0.04) circp *= 2;
if(radius > .1) circp *= 2; if(radius > .1) circp *= 2;
for(int j=0; j<circp; j++) for(int j=0; j<circp; j++)
pts.push_back(Ctr * xspinpush0(M_PI*j*2/circp, radius)); pts.push_back(xspinpush0(M_PI*j*2/circp, radius));
for(int j=0; j<circp; j++) curvepoint(pts[j]); for(int j=0; j<circp; j++) curvepoint(pts[j]);
curvepoint(pts[0]); curvepoint(pts[0]);
queuecurve(dtcolor, 0, PPR::LINE); queuecurve(Ctr, dtcolor, 0, PPR::LINE);
} }
#if CAP_POLY #if CAP_POLY
@ -2593,7 +2593,7 @@ namespace mapeditor {
#endif #endif
#if CAP_TEXTURE #if CAP_TEXTURE
EX void draw_texture_ghosts(cell *c, const transmatrix& V) { EX void draw_texture_ghosts(cell *c, const shiftmatrix& V) {
if(!c) return; if(!c) return;
if(holdmouse && !lstartcell) return; if(holdmouse && !lstartcell) return;
cell *ls = lstartcell ? lstartcell : lmouseover; cell *ls = lstartcell ? lstartcell : lmouseover;
@ -2604,14 +2604,14 @@ namespace mapeditor {
if(sio.id == sih.id) { if(sio.id == sih.id) {
if(c == ls) if(c == ls)
textrans = inverse(V * applyPatterndir(ls, sio)); textrans = inverse(V.T * applyPatterndir(ls, sio));
transmatrix mh = textrans * rgpushxto0(mouseh); transmatrix mh = textrans * rgpushxto0(unshift(mouseh, V.shift));
transmatrix ml = textrans * rgpushxto0(lstart); transmatrix ml = textrans * rgpushxto0(unshift(lstart, V.shift));
for(int j=0; j<=texture::texturesym; j++) for(int j=0; j<=texture::texturesym; j++)
for(int i=0; i<c->type; i += sih.symmetries) { for(int i=0; i<c->type; 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; if(j) M2 = M2 * Mirror;
switch(holdmouse ? mousekey : 'd') { switch(holdmouse ? mousekey : 'd') {
case 'c': case 'c':
@ -2629,7 +2629,7 @@ namespace mapeditor {
#endif #endif
#if CAP_POLY #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 #if !CAP_EDIT
return false; return false;
#else #else
@ -2686,37 +2686,37 @@ namespace mapeditor {
usershapelayer &ds(us->d[mapeditor::dslayer]); usershapelayer &ds(us->d[mapeditor::dslayer]);
hyperpoint mh = inverse(mapeditor::drawtrans) * mouseh; hyperpoint mh = inverse_shift(mapeditor::drawtrans, mouseh);
for(int a=0; a<ds.rots; a++) for(int a=0; a<ds.rots; a++)
for(int b=0; b<(ds.sym?2:1); b++) { for(int b=0; b<(ds.sym?2:1); b++) {
if(mouseout()) break; if(mouseout()) break;
hyperpoint P2 = V * spin(2*M_PI*a/ds.rots) * (b?Mirror*mh:mh); shiftpoint P2 = V * spin(2*M_PI*a/ds.rots) * (b?Mirror*mh:mh);
queuestr(P2, 10, "x", 0xFF00FF); queuestr(P2, 10, "x", 0xFF00FF);
} }
if(isize(ds.list) == 0) return us; if(isize(ds.list) == 0) return us;
hyperpoint Plast = V * spin(-2*M_PI/ds.rots) * (ds.sym?Mirror*ds.list[0]:ds.list[isize(ds.list)-1]); shiftpoint Plast = V * spin(-2*M_PI/ds.rots) * (ds.sym?Mirror*ds.list[0]:ds.list[isize(ds.list)-1]);
int state = 0; int state = 0;
int gstate = 0; int gstate = 0;
double dist2 = 0; double dist2 = 0;
hyperpoint lpsm; shiftpoint lpsm;
for(int a=0; a<ds.rots; a++) for(int a=0; a<ds.rots; a++)
for(int b=0; b<(ds.sym?2:1); b++) { for(int b=0; b<(ds.sym?2:1); b++) {
hyperpoint mh2 = spin(2*M_PI*-ew.rotid/ds.rots) * mh; hyperpoint mh2 = spin(2*M_PI*-ew.rotid/ds.rots) * mh;
if(ew.symid) mh2 = Mirror * mh2; if(ew.symid) mh2 = Mirror * mh2;
hyperpoint pseudomouse = V * spin(2*M_PI*a/ds.rots) * mirrorif(mh2, b); shiftpoint pseudomouse = V * spin(2*M_PI*a/ds.rots) * mirrorif(mh2, b);
for(int t=0; t<isize(ds.list); t++) { for(int t=0; t<isize(ds.list); t++) {
int ti = b ? isize(ds.list)-1-t : t; int ti = b ? isize(ds.list)-1-t : t;
hyperpoint P2 = V * spin(2*M_PI*a/ds.rots) * mirrorif(ds.list[ti], b); shiftpoint P2 = V * spin(2*M_PI*a/ds.rots) * mirrorif(ds.list[ti], b);
if(!mouseout()) { if(!mouseout()) {
double d = hdist(mouseh, P2); double d = hdist(mouseh, P2);
@ -2757,7 +2757,7 @@ namespace mapeditor {
if(gstate == 1) queueline(lpsm, V * ds.list[0], 0x90000080), gstate = 0; if(gstate == 1) queueline(lpsm, V * ds.list[0], 0x90000080), gstate = 0;
if(state == 1) { if(state == 1) {
hyperpoint P2 = V * ds.list[0]; shiftpoint P2 = V * ds.list[0];
if(hdist(mouseh, P2) + hdist(mouseh, Plast) - hdist(P2, Plast) < dist2) if(hdist(mouseh, P2) + hdist(mouseh, Plast) - hdist(P2, Plast) < dist2)
ewsearch.side = 1; ewsearch.side = 1;
} }

View File

@ -173,7 +173,7 @@ EX namespace models {
spiral_multiplier = cld(cos_spiral, sin_spiral) * cld(spiral_cone_rad * mul / 2., 0); spiral_multiplier = cld(cos_spiral, sin_spiral) * cld(spiral_cone_rad * mul / 2., 0);
} }
if(euclid) { if(euclid) {
euclidean_spin = pispin * inverse(cview() * master_relative(centerover, true)); euclidean_spin = pispin * inverse(cview().T * master_relative(centerover, true));
euclidean_spin = gpushxto0(euclidean_spin * C0) * euclidean_spin; euclidean_spin = gpushxto0(euclidean_spin * C0) * euclidean_spin;
hyperpoint h = inverse(euclidean_spin) * (C0 + (euc::eumove(gp::loc{1,0})*C0 - C0) * vpconf.spiral_x + (euc::eumove(gp::loc{0,1})*C0 - C0) * vpconf.spiral_y); hyperpoint h = inverse(euclidean_spin) * (C0 + (euc::eumove(gp::loc{1,0})*C0 - C0) * vpconf.spiral_x + (euc::eumove(gp::loc{0,1})*C0 - C0) * vpconf.spiral_y);
spiral_multiplier = cld(0, 2 * M_PI) / cld(h[0], h[1]); spiral_multiplier = cld(0, 2 * M_PI) / cld(h[0], h[1]);
@ -183,8 +183,6 @@ EX namespace models {
if(isize(history::path_for_lineanimation) == 0 || ((quotient || arb::in()) && history::path_for_lineanimation.back() != centerover)) { if(isize(history::path_for_lineanimation) == 0 || ((quotient || arb::in()) && history::path_for_lineanimation.back() != centerover)) {
history::path_for_lineanimation.push_back(centerover); history::path_for_lineanimation.push_back(centerover);
} }
band_shift = 0;
} }
EX bool model_available(eModel pm) { EX bool model_available(eModel pm) {
@ -301,10 +299,10 @@ EX namespace models {
for(int a=-1; a<=1; a++) { for(int a=-1; a<=1; a++) {
curvepoint(point2(-M_PI/2 * current_display->radius, a*current_display->radius)); curvepoint(point2(-M_PI/2 * current_display->radius, a*current_display->radius));
curvepoint(point2(+M_PI/2 * current_display->radius, 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));
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); queuereset(vpconf.model, PPR::LINE);
quickqueue(); quickqueue();

View File

@ -55,8 +55,8 @@ EX namespace multi {
} }
} }
EX transmatrix whereis[MAXPLAYER]; EX shiftmatrix whereis[MAXPLAYER];
EX transmatrix crosscenter[MAXPLAYER]; EX shiftmatrix crosscenter[MAXPLAYER];
EX double ccdist[MAXPLAYER]; EX double ccdist[MAXPLAYER];
EX cell *ccat[MAXPLAYER]; EX cell *ccat[MAXPLAYER];
@ -804,7 +804,7 @@ EX void handleInput(int delta) {
EX void handleMulti(int delta) { EX void handleMulti(int delta) {
multi::handleInput(delta); multi::handleInput(delta);
transmatrix bcwtV = cwtV; shiftmatrix bcwtV = cwtV;
cellwalker bcwt = cwt; cellwalker bcwt = cwt;
bool alldecided = !needinput; bool alldecided = !needinput;

View File

@ -151,9 +151,11 @@ EX namespace dual {
EX transmatrix get_orientation() { EX transmatrix get_orientation() {
if(WDIM == 2) if(WDIM == 2)
return gpushxto0(tC0(cwtV)) * cwtV; return gpushxto0(tC0(cwtV.T)) * cwtV.T;
else if(cwt.at) else if(cwt.at) {
return gpushxto0(tC0(ggmatrix(cwt.at))) * ggmatrix(cwt.at) * sword::dir[0].T; transmatrix T = unshift(ggmatrix(cwt.at));
return gpushxto0(tC0(T)) * T * sword::dir[0].T;
}
else else
return Id; return Id;
} }

View File

@ -264,7 +264,7 @@ EX namespace netgen {
color_t& hqpixel(hyperpoint h) { color_t& hqpixel(hyperpoint h) {
int hx, hy, hs; int hx, hy, hs;
getcoord0(h, hx, hy, hs); getcoord0(shiftless(h), hx, hy, hs);
return qpixel(hqsurface, hx, hy); return qpixel(hqsurface, hx, hy);
} }
@ -657,7 +657,7 @@ EX namespace netgen {
nei[i][e] >= 0 ? 0x808080 : nei[i][e] >= 0 ? 0x808080 :
0xC0C0C0; 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(); quickqueue();

View File

@ -439,7 +439,7 @@ EX namespace sn {
virtual transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) override { virtual transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) override {
for(int i=0; i<h1->type; i++) if(h1->move(i) == h2) return adjmatrix(i, h1->c.spin(i)); for(int i=0; i<h1->type; i++) if(h1->move(i) == h2) return adjmatrix(i, h1->c.spin(i));
if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) 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; transmatrix front = Id, back = Id;
@ -460,14 +460,14 @@ EX namespace sn {
} }
void draw() override { void draw() override {
dq::visited.clear(); dq::clear_all();
dq::enqueue(centerover->master, cview()); dq::enqueue(centerover->master, cview());
while(!dq::drawqueue.empty()) { while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front(); auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p); heptagon *h = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dq::drawqueue.pop(); dq::drawqueue.pop();
cell *c = h->c7; cell *c = h->c7;
@ -939,14 +939,14 @@ EX namespace nilv {
} }
void draw() override { void draw() override {
dq::visited_by_matrix.clear(); dq::clear_all();
dq::enqueue_by_matrix(centerover->master, cview()); dq::enqueue_by_matrix(centerover->master, cview());
while(!dq::drawqueue.empty()) { while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front(); auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p); heptagon *h = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dq::drawqueue.pop(); dq::drawqueue.pop();
cell *c = h->c7; cell *c = h->c7;
@ -1281,17 +1281,15 @@ EX namespace hybrid {
void draw() override { void draw() override {
cell* start = centerover; 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()); dq::enqueue_by_matrix_c(start, cview());
while(!dq::drawqueue_c.empty()) { while(!dq::drawqueue_c.empty()) {
auto& p = dq::drawqueue_c.front(); auto& p = dq::drawqueue_c.front();
cell *c = get<0>(p); cell *c = get<0>(p);
transmatrix V = get<1>(p);
band_shift = get<2>(p); shiftmatrix V = get<1>(p);
dq::drawqueue_c.pop(); dq::drawqueue_c.pop();
if(!do_draw(c, V)) continue; if(!do_draw(c, V)) continue;
@ -1301,23 +1299,8 @@ EX namespace hybrid {
for(int i=0; i<c->type; i++) { for(int i=0; i<c->type; i++) {
cell *c1 = c->cmove(i); cell *c1 = c->cmove(i);
transmatrix V1 = V * adj(c, i); shiftmatrix V1 = V * adj(c, i);
dynamicval<ld> bs(band_shift, band_shift); optimize_shift(V1);
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;
}
}
dq::enqueue_by_matrix_c(c1, V1); dq::enqueue_by_matrix_c(c1, V1);
} }
} }
@ -1641,6 +1624,7 @@ EX namespace product {
EX bool current_spin_invalid, cmirror; EX bool current_spin_invalid, cmirror;
EX int cspin; EX int cspin;
/* todo might need a shiftpoint version */
EX hyperpoint inverse_exp(hyperpoint h) { EX hyperpoint inverse_exp(hyperpoint h) {
hyperpoint res; hyperpoint res;
res[2] = zlevel(h); 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)); 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)) { EX hyperpoint get_inverse_exp(shiftpoint h) {
ld xy = hypot_d(2, h); ld xy = hypot_d(2, h.h);
ld phi = atan2(h[2], h[3]) + index; ld phi = atan2(h[2], h[3]) + h.shift;
bool flipped = phi > 0; bool flipped = phi > 0;
if(flipped) phi = -phi, h[2] *= -1, h[0] *= -1; if(flipped) phi = -phi, h[2] *= -1, h[0] *= -1;
@ -1766,7 +1750,7 @@ EX namespace slr {
ld SV = stretch::not_squared(); ld SV = stretch::not_squared();
ld K = -1; ld K = -1;
ld alpha = atan2(h[1], -h[0]); ld alpha = atan2(h[1], -h[0]); /* todo shift */
hyperpoint res; hyperpoint res;
@ -2098,7 +2082,7 @@ EX namespace rots {
hybrid::in_underlying_geometry([&] { hybrid::in_underlying_geometry([&] {
hyperpoint h = tC0(T); hyperpoint h = tC0(T);
Spin = inverse(gpushxto0(h) * 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]); alpha = atan2(Spin[0][1], Spin[0][0]);
distance = hdist0(h); distance = hdist0(h);
beta = atan2(h[1], h[0]); 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 { virtual transmatrix relative_matrix(cell *c2, cell *c1, const hyperpoint& hint) override {
if(c1 == c2) return Id; if(c1 == c2) return Id;
if(gmatrix0.count(c2) && gmatrix0.count(c1)) if(gmatrix0.count(c2) && gmatrix0.count(c1))
return inverse(gmatrix0[c1]) * gmatrix0[c2]; return inverse_shift(gmatrix0[c1], gmatrix0[c2]);
for(int i=0; i<c1->type; i++) if(c1->move(i) == c2) return adj(c1, i); for(int i=0; i<c1->type; i++) if(c1->move(i) == c2) return adj(c1, i);
return Id; // not implemented yet return Id; // not implemented yet
} }
@ -2243,8 +2227,9 @@ EX namespace rots {
dynamicval<cell*> m5(centerover, co); dynamicval<cell*> m5(centerover, co);
dynamicval<transmatrix> m2(View, inprod ? pView : ypush(0) * qtm(h)); dynamicval<transmatrix> m2(View, inprod ? pView : ypush(0) * qtm(h));
if(PURE) View = View * pispin; if(PURE) View = View * pispin;
dynamicval<transmatrix> m3(playerV, Id); dynamicval<shiftmatrix> m3(playerV, shiftless(Id));
dynamicval<transmatrix> m4(actual_view_transform, Id); dynamicval<transmatrix> m4(actual_view_transform, Id);
dynamicval<shiftmatrix> m6(cwtV, shiftless(Id));
dynamicval<eModel> pm(pmodel, mdDisk); dynamicval<eModel> pm(pmodel, mdDisk);
dynamicval<ld> pss(pconf.scale, (sphere ? 10 : 1) * underlying_scale); dynamicval<ld> pss(pconf.scale, (sphere ? 10 : 1) * underlying_scale);
dynamicval<ld> psa(pconf.alpha, sphere ? 10 : 1); dynamicval<ld> psa(pconf.alpha, sphere ? 10 : 1);
@ -2255,7 +2240,7 @@ EX namespace rots {
dynamicval<ld> psy(vid.smart_range_detail, 1); dynamicval<ld> psy(vid.smart_range_detail, 1);
calcparam(); calcparam();
reset_projection(); current_display->set_all(0); reset_projection(); current_display->set_all(0, 0);
ptds.clear(); ptds.clear();
drawthemap(); drawthemap();
drawqueue(); drawqueue();
@ -2265,7 +2250,7 @@ EX namespace rots {
gmatrix = std::move(g); gmatrix = std::move(g);
gmatrix0 = std::move(g0); gmatrix0 = std::move(g0);
calcparam(); 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 */ /** @brief exponential function for both slr and Berger sphere */
@ -2670,7 +2655,7 @@ EX namespace nisot {
hyperpoint at = tC0(Position); hyperpoint at = tC0(Position);
transmatrix push_back = inverse(translate(at)); transmatrix push_back = inverse(translate(at));
hyperpoint back_goal = push_back * goal; 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; transmatrix back_Position = push_back * Position;

View File

@ -579,7 +579,7 @@ EX void teleportTo(cell *dest) {
cell *from = cwt.at; cell *from = cwt.at;
movecost(from, dest, 1); movecost(from, dest, 1);
playerMoveEffects(cwt.at, dest); 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)); cwt.at = dest; cwt.spin = hrand(dest->type); flipplayer = !!(hrand(2));
drainOrb(itOrbTeleport); drainOrb(itOrbTeleport);
@ -666,7 +666,7 @@ EX bool jumpTo(orbAction a, cell *dest, eItem byWhat, int bonuskill IS(0), eMons
changes.commit(); changes.commit();
current_display->which_copy = ggmatrix(dest); current_display->which_copy = unshift(ggmatrix(dest));
countLocalTreasure(); countLocalTreasure();
for(int i=9; i>=0; i--) for(int i=9; i>=0; i--)

View File

@ -2541,12 +2541,12 @@ EX namespace linepatterns {
return col; 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) if(!elliptic)
gridline(V1, h1, V2, h2, col, par); gridline(V1, h1, V2, h2, col, par);
else { else {
hyperpoint vh1 = V1 * h1; hyperpoint vh1 = V1.T * h1;
hyperpoint vh2 = V2 * h2; hyperpoint vh2 = unshift(V2, V1.shift) * h2;
ld cros = vh1[0]*vh2[0] + vh1[1]*vh2[1] + vh1[2]*vh2[2]; ld cros = vh1[0]*vh2[0] + vh1[1]*vh2[1] + vh1[2]*vh2[2];
if(cros > 0) if(cros > 0)
gridline(V1, h1, V2, h2, col, par), 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) \ #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 } } [] (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) \ #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, linepattern patDual("dual grid", 0xFFFFFF00, always_available,
ALLCELLS( ALLCELLS(
@ -2631,7 +2631,7 @@ EX namespace linepatterns {
cell *c2 = c->master->cmove(dir)->c7; cell *c2 = c->master->cmove(dir)->c7;
if(gmatrix.count(c2)) { if(gmatrix.count(c2)) {
if(S3 >= OINF) 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 else
gridlinef(V, C0, V * master_relative(c, true) * currentmap->adj(c->master, dir), C0, col, 2 + vid.linequality); 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; cell *c2 = c->master->move(i)->c7;
if(gmatrix.count(c2)) { if(gmatrix.count(c2)) {
if(S3 >= OINF) { 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 else
gridlinef(V, C0, V*master_relative(c, true) * currentmap->adj(c->master,i), C0, col, 2 + vid.linequality); 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( ALLCELLS(
if(zebra40(c) / 4 == 10) { if(zebra40(c) / 4 == 10) {
bool all = true; bool all = true;
transmatrix tri[3]; shiftmatrix tri[3];
for(int i=0; i<3; i++) for(int i=0; i<3; i++)
tri[i] = V * currentmap->adj(c, i*2); 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 j=0; j<360; j+=15) {
for(int k=0; k<=15; k++) for(int k=0; k<=15; k++)
curvepoint(xspinpush0((j+k) * degree, i * degree)); 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 j=0; j<180; j+=15) {
for(int k=0; k<=15; k++) for(int k=0; k<=15; k++)
curvepoint(xspinpush0(i * degree, (j+k) * degree)); 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 j=-180; j<=180; j+=15) {
for(int i=-90; i<90; i+=15) { for(int i=-90; i<90; i+=15) {
for(int k=0; k<=15; k++) for(int k=0; k<=15; k++)
curvepoint(V * xpush(j * degree) * ypush0((i+k) * degree)); curvepoint(xpush(j * degree) * ypush0((i+k) * degree));
queuecurve(col, 0, PPR::LINE).V=V; 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 i=-90; i<=90; i += 15) {
for(int j=-180; j<180; j+=15) { for(int j=-180; j<180; j+=15) {
for(int k=0; k<=15; k++) for(int k=0; k<=15; k++)
curvepoint(V * xpush((j+k) * degree) * ypush0(i * degree)); curvepoint(xpush((j+k) * degree) * ypush0(i * degree));
queuecurve(col, 0, PPR::LINE).V=V; queuecurve(V, col, 0, PPR::LINE).V=V;
} }
} }
) )

View File

@ -170,7 +170,7 @@ void write_ghosts(string seed, int mcode) {
} }
#endif #endif
transmatrix get_ghostmoment_matrix(ghostmoment& p) { shiftmatrix get_ghostmoment_matrix(ghostmoment& p) {
cell *w = rti[p.where_id].c; 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); transmatrix T = spin_uchar(p.alpha) * xpush(uchar_to_frac(p.distance) * distance_multiplier) * spin_uchar(p.beta);
return gmatrix[w] * T; return gmatrix[w] * T;
@ -615,7 +615,7 @@ EX void generate_track() {
for(int i=0; i<motypes; i++) kills[i] = 0; for(int i=0; i<motypes; i++) kills[i] = 0;
vector<transmatrix> forbidden; vector<shiftmatrix> forbidden;
for(auto& ghost: ghostset()[specialland]) for(auto& ghost: ghostset()[specialland])
forbidden.push_back(get_ghostmoment_matrix(ghost.history[0])); forbidden.push_back(get_ghostmoment_matrix(ghost.history[0]));
for(auto& ghost: oghostset()[specialland]) 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->at = straight * parabolic1(start_line_width * (rand() % 20000 - 10000) / 40000) * spin(rand() % 360);
who->base = s; who->base = s;
bool ok = true; 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; if(ok) break;
} }
virtualRebase(who); virtualRebase(who);
@ -775,7 +775,7 @@ EX bool set_view() {
if(use_standard_centering()) return false; if(use_standard_centering()) return false;
if(player_relative && specialland == laAsteroids) 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)) { if(racing::player_relative || quotient || (kite::in() && GDIM == 3)) {
View = inverse(at) * View; View = inverse(at) * View;
@ -785,8 +785,8 @@ EX bool set_view() {
int steps = euclid ? 1000 : PURE ? 10 : 20; int steps = euclid ? 1000 : PURE ? 10 : 20;
cell *c1 = racing::track[max(z-steps, 0)]; cell *c1 = racing::track[max(z-steps, 0)];
cell *c2 = racing::track[min(z+steps, isize(racing::track)-1)]; cell *c2 = racing::track[min(z+steps, isize(racing::track)-1)];
transmatrix T1 = ypush(-vid.yshift) * ggmatrix(c1); transmatrix T1 = ypush(-vid.yshift) * unshift(ggmatrix(c1));
transmatrix T2 = ypush(-vid.yshift) * ggmatrix(c2); transmatrix T2 = ypush(-vid.yshift) * unshift(ggmatrix(c2));
transmatrix T = spintox(inverse(T1) * T2 * C0); transmatrix T = spintox(inverse(T1) * T2 * C0);
hyperpoint h = T * inverse(T1) * at * C0; hyperpoint h = T * inverse(T1) * at * C0;
ld y = GDIM == 2 ? asin_auto(h[1]) : asin_auto(hypot(h[1], h[2])); 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<charstyle> x(getcs(), ghost.cs); dynamicval<charstyle> x(getcs(), ghost.cs);
if(ghost.cs.charid == -1) { if(ghost.cs.charid == -1) {
dynamicval<bool> pc(peace::on, true); dynamicval<bool> pc(peace::on, true);
@ -1355,9 +1355,9 @@ void draw_ghost(ghost& ghost) {
draw_ghost_at(ghost, w, get_ghostmoment_matrix(p), p); draw_ghost_at(ghost, w, get_ghostmoment_matrix(p), p);
} }
transmatrix racerel(ld rel) { shiftmatrix racerel(ld rel) {
int bsize = vid.fsize * 2; 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) { EX int get_percentage(cell *c) {
@ -1390,7 +1390,7 @@ EX void drawStats() {
curvepoint(atscreenpos(bsize*3/2, y, bsize) * C0); curvepoint(atscreenpos(bsize*3/2, y, bsize) * C0);
curvepoint(atscreenpos(bsize, 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: ghostset()[specialland]) draw_ghost_state(ghost);
for(auto& ghost: oghostset()[specialland]) draw_ghost_state(ghost); for(auto& ghost: oghostset()[specialland]) draw_ghost_state(ghost);
@ -1418,8 +1418,8 @@ EX void markers() {
if(!goal) return; if(!goal) return;
hyperpoint H = tC0(ggmatrix(goal)); shiftpoint H = tC0(ggmatrix(goal));
if(invalid_point(H)) return; if(invalid_point(H.h)) return;
queuestr(H, 2*vid.fsize, "X", 0x10100 * int(128 + 100 * sintick(150))); queuestr(H, 2*vid.fsize, "X", 0x10100 * int(128 + 100 * sintick(150)));
int cd = celldistance(track.back(), cwt.at); int cd = celldistance(track.back(), cwt.at);
@ -1444,8 +1444,8 @@ EX void markers() {
if(gmatrix.count(track[0])) { if(gmatrix.count(track[0])) {
hyperpoint h = WDIM == 2 && GDIM == 3 ? zpush(cgi.FLOOR - cgi.human_height/80) * C0 : C0; 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) for(ld z=-start_line_width; z<=start_line_width; z+=0.1)
curvepoint(ggmatrix(track[0]) * straight * parabolic1(z) * h); curvepoint(parabolic1(z) * h);
queuecurve(0xFFFFFFFF, 0, PPR::BFLOOR); queuecurve(ggmatrix(track[0]) * straight, 0xFFFFFFFF, 0, PPR::BFLOOR);
} }
} }

View File

@ -20,46 +20,50 @@ EX vector<radarline> radarlines;
EX transmatrix radar_transform; EX transmatrix radar_transform;
pair<bool, hyperpoint> makeradar(hyperpoint h) { pair<bool, hyperpoint> makeradar(shiftpoint h) {
if(GDIM == 3 && WDIM == 2) h = radar_transform * h; if(GDIM == 3 && WDIM == 2) h.h = radar_transform * h.h;
ld d = hdist0(h); ld d = hdist0(h);
hyperpoint h1;
if(sol && nisot::geodesic_movement) { if(sol && nisot::geodesic_movement) {
h = inverse_exp(h, pQUICK); hyperpoint h1 = inverse_exp(h, pQUICK);
ld r = hypot_d(3, h); ld r = hypot_d(3, h1);
if(r < 1) h = h * (atanh(r) / r); if(r < 1) h1 = h1 * (atanh(r) / r);
else return {false, h}; else return {false, h1};
} }
if(prod) h = product::inverse_exp(h); else
if(nisot::local_perspective_used()) h = NLP * h; if(prod) h1 = product::inverse_exp(unshift(h));
if(nisot::local_perspective_used()) h1 = NLP * h1;
if(WDIM == 3) { if(WDIM == 3) {
if(d >= vid.radarrange) return {false, h}; if(d >= vid.radarrange) return {false, h1};
if(d) h = h * (d / vid.radarrange / hypot_d(3, h)); if(d) h1 = h1 * (d / vid.radarrange / hypot_d(3, h1));
} }
else if(hyperbolic) { 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) { else if(sphere) {
h[2] = h[3]; h1[2] = h1[3];
} }
else { else {
if(d > vid.radarrange) return {false, h}; if(d > vid.radarrange) return {false, h1};
if(d) h = h * (d / (vid.radarrange + cgi.scalefactor/4) / hypot_d(3, h)); if(d) h1 = h1 * (d / (vid.radarrange + cgi.scalefactor/4) / hypot_d(3, h1));
} }
if(invalid_point(h)) return {false, h}; if(invalid_point(h1)) return {false, h1};
return {true, h}; return {true, h1};
} }
EX void addradar(const transmatrix& V, char ch, color_t col, color_t outline) { EX void addradar(const shiftmatrix& V, char ch, color_t col, color_t outline) {
hyperpoint h = tC0(V); shiftpoint h = tC0(V);
auto hp = makeradar(h); auto hp = makeradar(h);
if(hp.first) if(hp.first)
radarpoints.emplace_back(radarpoint{hp.second, ch, col, outline}); 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 hp1 = makeradar(h1);
auto hp2 = makeradar(h2); auto hp2 = makeradar(h2);
if(hp1.first && hp2.first) 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 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; ld cy = vid.yres-rad-2 - vid.fsize;
auto sId = shiftless(Id);
for(int i=0; i<360; i++) for(int i=0; i<360; i++)
curvepoint(atscreenpos(cx-cos(i * degree)*rad, cy-sin(i*degree)*rad, 1) * C0); 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 alpha = 15 * degree;
ld co = cos(alpha); ld co = cos(alpha);
@ -119,28 +125,28 @@ EX void draw_radar(bool cornermode) {
if(sph && !d3) { if(sph && !d3) {
for(int i=0; i<360; i++) for(int i=0; i<360; i++)
curvepoint(atscreenpos(cx-cos(i * degree)*rad, cy-sin(i*degree)*rad*si, 1) * C0); 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) { if(d3) {
for(int i=0; i<360; i++) for(int i=0; i<360; i++)
curvepoint(atscreenpos(cx-cos(i * degree)*rad, cy-sin(i*degree)*rad*si, 1) * C0); 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-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, cy, 1) * C0);
curvepoint(atscreenpos(cx+sin(vid.fov*degree/2)*rad, cy-sin(vid.fov*degree/2)*rad*si, 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) { 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) { if(scompass) {
auto compassdir = [&] (char dirname, hyperpoint h) { auto compassdir = [&] (char dirname, hyperpoint h) {
h = NLP * h * .8; 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); displaychr(int(cx+rad * h[0]), int(cy - rad * h[2] * si + rad * h[1] * co), 0, 8, dirname, 0xA04010);
}; };
compassdir('E', point3(+1, 0, 0)); compassdir('E', point3(+1, 0, 0));
@ -165,7 +171,7 @@ EX void draw_radar(bool cornermode) {
hyperpoint h2 = locate(r.h2); hyperpoint h2 = locate(r.h2);
h1 = tC0(atscreenpos(h1[0], h1[1], 1)); h1 = tC0(atscreenpos(h1[0], h1[1], 1));
h2 = tC0(atscreenpos(h2[0], h2[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(); quickqueue();

View File

@ -1146,7 +1146,7 @@ EX void cast() {
cell *cs = centerover; cell *cs = centerover;
transmatrix T = cview(); transmatrix T = cview().T;
if(global_projection) if(global_projection)
T = xpush(vid.ipd * global_projection/2) * T; T = xpush(vid.ipd * global_projection/2) * T;
@ -1280,7 +1280,7 @@ EX void cast() {
celldrawer dd; celldrawer dd;
dd.c = c1; dd.c = c1;
dd.setcolors(); dd.setcolors();
transmatrix Vf; shiftmatrix Vf;
dd.set_land_floor(Vf); dd.set_land_floor(Vf);
color_t wcol = darkena(dd.wcol, 0, 0xFF); color_t wcol = darkena(dd.wcol, 0, 0xFF);
int dv = get_darkval(c1, c->c.spin(i)); int dv = get_darkval(c1, c->c.spin(i));
@ -1325,7 +1325,7 @@ EX void cast() {
celldrawer dd; celldrawer dd;
dd.c = c; dd.c = c;
dd.setcolors(); dd.setcolors();
transmatrix Vf; shiftmatrix Vf;
dd.set_land_floor(Vf); dd.set_land_floor(Vf);
int u = (id/per_row*length) + (id%per_row * deg) + c->type + a; int u = (id/per_row*length) + (id%per_row * deg) + c->type + a;
wallcolor[u] = glhr::acolor(darkena(dd.fcol, 0, 0xFF)); wallcolor[u] = glhr::acolor(darkena(dd.fcol, 0, 0xFF));

View File

@ -321,15 +321,13 @@ EX namespace reg3 {
// for(int i=0; i<S6; i++) queuepoly(ggmatrix(cwt.at), shWall3D[i], 0xFF0000FF); // for(int i=0; i<S6; i++) queuepoly(ggmatrix(cwt.at), shWall3D[i], 0xFF0000FF);
dq::visited_by_matrix.clear(); dq::clear_all();
dq::enqueue_by_matrix(centerover->master, cview()); dq::enqueue_by_matrix(centerover->master, cview());
while(!dq::drawqueue.empty()) { while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front(); auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p); heptagon *h = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
dq::drawqueue.pop(); dq::drawqueue.pop();
cell *c = h->c7; cell *c = h->c7;
@ -339,10 +337,10 @@ EX namespace reg3 {
if(ultra_mirror_in()) if(ultra_mirror_in())
for(auto& T: cgi.ultra_mirrors) 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; d<S7; d++) for(int d=0; d<S7; d++)
dq::enqueue_by_matrix(h->move(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()) { while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front(); auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p); heptagon *h = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
dq::drawqueue.pop(); dq::drawqueue.pop();
@ -945,10 +941,10 @@ EX namespace reg3 {
if(ultra_mirror_in()) if(ultra_mirror_in())
for(auto& T: cgi.ultra_mirrors) 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; i<S7; i++) if(h->move(i)) { for(int i=0; i<S7; i++) if(h->move(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; i<S6; i++) queuepoly(ggmatrix(cwt.at), shWall3D[i], 0xFF0000FF); // for(int i=0; i<S6; i++) queuepoly(ggmatrix(cwt.at), shWall3D[i], 0xFF0000FF);
dq::visited.clear(); dq::clear_all();
dq::enqueue(centerover->master, cview()); dq::enqueue(centerover->master, cview());
while(!dq::drawqueue.empty()) { while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front(); auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p); heptagon *h = p.first;
transmatrix V = get<1>(p); shiftmatrix V = p.second;
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
dq::drawqueue.pop(); dq::drawqueue.pop();
@ -1291,7 +1285,7 @@ EX namespace reg3 {
if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000) continue; if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000) continue;
for(int i=0; i<S7; i++) if(h->move(i)) { for(int i=0; i<S7; i++) if(h->move(i)) {
dq::enqueue(h->move(i), V * adj(h, i)); dq::enqueue(h->move(i), optimized_shift(V * adj(h, i)));
} }
} }
} }

48
rug.cpp
View File

@ -44,7 +44,7 @@ bool computed = false;
bool valid; bool valid;
bool inqueue; bool inqueue;
double dist; double dist;
hyperpoint h; // point in the represented space shiftpoint h; // point in the represented space
hyperpoint native; // point in the native space hyperpoint native; // point in the native space
hyperpoint precompute; hyperpoint precompute;
vector<edge> edges; vector<edge> edges;
@ -164,7 +164,7 @@ bool rug_hyperbolic() { USING_NATIVE_GEOMETRY; return hyperbolic; }
bool rug_sphere() { USING_NATIVE_GEOMETRY; return sphere; } bool rug_sphere() { USING_NATIVE_GEOMETRY; return sphere; }
bool rug_elliptic() { USING_NATIVE_GEOMETRY; return elliptic; } 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; rugpoint *m = new rugpoint;
m->h = h; m->h = h;
@ -218,12 +218,12 @@ EX rugpoint *addRugpoint(hyperpoint h, double dist) {
} }
else else
scale = 1; scale = 1;
m->native = h * scale; m->native = unshift(h) * scale;
m->native = hpxy3(m->native[0], m->native[1], m->native[2]); m->native = hpxy3(m->native[0], m->native[1], m->native[2]);
} }
else if(euclid && rug_euclid()) { else if(euclid && rug_euclid()) {
m->native = h * modelscale; m->native = unshift(h) * modelscale;
m->native[2] = 0; m->native[2] = 0;
#if MAXMDIM >= 4 #if MAXMDIM >= 4
m->native[3] = 1; m->native[3] = 1;
@ -247,11 +247,11 @@ EX rugpoint *addRugpoint(hyperpoint h, double dist) {
USING_NATIVE_GEOMETRY; USING_NATIVE_GEOMETRY;
m->native = rgpushxto0(h) * cpush0(2, r); m->native = rgpushxto0(unshift(h)) * cpush0(2, r);
} }
else { else {
m->native = h; m->native = unshift(h);
ld hd = h[LDIM]; ld hd = h[LDIM];
for(int d=GDIM; d<MAXMDIM-1; d++) { for(int d=GDIM; d<MAXMDIM-1; d++) {
m->native[d] = (hd - .99) * (rand() % 1000 - rand() % 1000) / 1000; m->native[d] = (hd - .99) * (rand() % 1000 - rand() % 1000) / 1000;
@ -269,14 +269,14 @@ EX rugpoint *addRugpoint(hyperpoint h, double dist) {
return m; return m;
} }
EX rugpoint *findRugpoint(hyperpoint h) { EX rugpoint *findRugpoint(shiftpoint h) {
USING_NATIVE_GEOMETRY; USING_NATIVE_GEOMETRY;
for(int i=0; i<isize(points); i++) for(int i=0; i<isize(points); i++)
if(geo_dist_q(points[i]->h, 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; return NULL;
} }
EX rugpoint *findOrAddRugpoint(hyperpoint h, double dist) { EX rugpoint *findOrAddRugpoint(shiftpoint h, double dist) {
rugpoint *r = findRugpoint(h); rugpoint *r = findRugpoint(h);
return r ? r : addRugpoint(h, dist); return r ? r : addRugpoint(h, dist);
} }
@ -342,7 +342,7 @@ EX void sort_rug_points() {
void calcLengths() { void calcLengths() {
for(auto p: points) for(auto p: points)
for(auto& edge: p->edges) 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() { EX void calcparam_rug() {
@ -396,9 +396,9 @@ EX void buildTorusRug() {
println(hlog, "mx = ", mx); println(hlog, "mx = ", mx);
auto addToruspoint = [&] (hyperpoint h) { auto addToruspoint = [&] (hyperpoint h) {
auto r = addRugpoint(C0, 0); auto r = addRugpoint(shiftless(C0), 0);
hyperpoint onscreen; hyperpoint onscreen;
hyperpoint h1 = gmatrix[gs] * T * h; shiftpoint h1 = gmatrix[gs] * T * h;
applymodel(h1, onscreen); applymodel(h1, onscreen);
r->x1 = onscreen[0]; r->x1 = onscreen[0];
r->y1 = onscreen[1]; r->y1 = onscreen[1];
@ -539,7 +539,7 @@ EX void buildRug() {
for(int j=0; j<c->type; j++) addTriangle(v, p[j], p[(j+1) % c->type]); for(int j=0; j<c->type; j++) addTriangle(v, p[j], p[(j+1) % c->type]);
if((euclid && quotient) && nonorientable) { 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); rugpoint *Tv = addRugpoint(T * C0, 0);
for(int j=0; j<c->type; j++) p[j] = findOrAddRugpoint(T * get_corner_position(c, j), v->dist); for(int j=0; j<c->type; j++) p[j] = findOrAddRugpoint(T * get_corner_position(c, j), v->dist);
for(int j=0; j<c->type; j++) addTriangle(Tv, p[j], p[(j+1) % c->type]); for(int j=0; j<c->type; 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; double forcev = (t - rd) / 2; // 20.0;
transmatrix T = inverse(rgpushxto0(m1.native)); 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); transmatrix iT = rgpushxto0(m1.native);
@ -1041,7 +1041,7 @@ EX void prepareTexture() {
queueline(tC0(ggmatrix(playerpos(i))), mouseh, 0xFF00FF, 8 + vid.linequality); queueline(tC0(ggmatrix(playerpos(i))), mouseh, 0xFF00FF, 8 + vid.linequality);
} }
if(finger_center) { if(finger_center) {
transmatrix V = rgpushxto0(finger_center->h); shiftmatrix V = rgpushxto0(finger_center->h);
queuestr(V, 0.5, "X", 0xFFFFFFFF, 2); queuestr(V, 0.5, "X", 0xFFFFFFFF, 2);
for(int i=0; i<72; i++) 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); 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); for(auto t: triangles) drawTriangle(t);
auto& rug = queuecurve(0, 0xFFFFFFFF, PPR::LINE); auto& rug = queuecurve(shiftless(Id), 0, 0xFFFFFFFF, PPR::LINE);
if(nonisotropic) { if(nonisotropic) {
transmatrix T2 = eupush( tC0(inverse(rugView)) ); transmatrix T2 = eupush( tC0(inverse(rugView)) );
NLP = rugView * T2; NLP = rugView * T2;
rug.V = inverse(NLP) * rugView; rug.V = shiftless(inverse(NLP) * rugView);
} }
else { else {
rug.V = rugView; rug.V = shiftless(rugView);
} }
rug.offset_texture = 0; rug.offset_texture = 0;
@ -1322,7 +1322,7 @@ int besti;
static const ld RADAR_INF = 1e12; static const ld RADAR_INF = 1e12;
ld radar_distance = RADAR_INF; ld radar_distance = RADAR_INF;
EX hyperpoint gethyper(ld x, ld y) { EX shiftpoint gethyper(ld x, ld y) {
projection_configuration bak = pconf; projection_configuration bak = pconf;
pconf = rconf; pconf = rconf;
@ -1359,9 +1359,9 @@ EX hyperpoint gethyper(ld x, ld y) {
if(sp == 1 || sp == 2) continue; if(sp == 1 || sp == 2) continue;
} }
applymodel(inverse(NLP) * rugView * r0->native, p0); applymodel(shiftless(inverse(NLP) * rugView * r0->native), p0);
applymodel(inverse(NLP) * rugView * r1->native, p1); applymodel(shiftless(inverse(NLP) * rugView * r1->native), p1);
applymodel(inverse(NLP) * rugView * r2->native, p2); applymodel(shiftless(inverse(NLP) * rugView * r2->native), p2);
} }
if(error || spherepoints == 1 || spherepoints == 2) continue; if(error || spherepoints == 1 || spherepoints == 2) continue;
@ -1390,13 +1390,13 @@ EX hyperpoint gethyper(ld x, ld y) {
} }
pconf = bak; pconf = bak;
if(!found) return Hypc; if(!found) return shiftless(Hypc);
double px = rx1 * TEXTURESIZE, py = (1-ry1) * TEXTURESIZE; double px = rx1 * TEXTURESIZE, py = (1-ry1) * TEXTURESIZE;
calcparam_rug(); calcparam_rug();
models::configure(); models::configure();
hyperpoint h = hr::gethyper(px, py); shiftpoint h = hr::gethyper(px, py);
calcparam(); calcparam();
return h; return h;

View File

@ -400,8 +400,7 @@ EX always_false in;
tdata.push_back(p.tinf->tvertices[p.offset_texture+i]); tdata.push_back(p.tinf->tvertices[p.offset_texture+i]);
} }
for(auto& d: data) { for(auto& d: data) {
hyperpoint h; shiftpoint h = p.V * d;
h = p.V * d;
applymodel(h, d); applymodel(h, d);
} }
if(print && (p.flags & POLY_FAT)) { if(print && (p.flags & POLY_FAT)) {
@ -1169,11 +1168,11 @@ bool joukowsky_anim;
EX void reflect_view() { EX void reflect_view() {
if(centerover) { if(centerover) {
transmatrix T = Id; shiftmatrix T = shiftless(Id);
cell *mbase = centerover; cell *mbase = centerover;
cell *c = centerover; cell *c = centerover;
if(shmup::reflect(c, mbase, T)) 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() { void display_animation() {
if(ma == maCircle && (circle_display_color & 0xFF)) { if(ma == maCircle && (circle_display_color & 0xFF)) {
for(int s=0; s<10; s++) { for(int s=0; s<10; s++) {
if(s == 0) curvepoint(ggmatrix(rotation_center) * xpush0(circle_radius - .1)); if(s == 0) curvepoint(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)); for(int z=0; z<100; z++) curvepoint(xspinpush0((z+s*100) * 2 * M_PI / 1000., circle_radius));
queuecurve(circle_display_color, 0, PPR::LINE); queuecurve(ggmatrix(rotation_center), circle_display_color, 0, PPR::LINE);
} }
if(sphere) for(int s=0; s<10; s++) { if(sphere) for(int s=0; s<10; s++) {
if(s == 0) curvepoint(centralsym * ggmatrix(rotation_center) * xpush0(circle_radius - .1)); if(s == 0) curvepoint(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)); for(int z=0; z<100; z++) curvepoint(xspinpush0((z+s*100) * 2 * M_PI / 1000., circle_radius));
queuecurve(circle_display_color, 0, PPR::LINE); queuecurve(ggmatrix(rotation_center) * centralsym, circle_display_color, 0, PPR::LINE);
} }
} }
} }
@ -1878,13 +1877,14 @@ reaction_t add_to_frame;
#if CAP_STARTANIM #if CAP_STARTANIM
void draw_ghost(const transmatrix V, int id) { void draw_ghost(const transmatrix V, int id) {
auto sV = shiftless(V);
if(id % 13 == 0) { if(id % 13 == 0) {
queuepoly(V, cgi.shMiniGhost, 0xFFFF00C0); queuepoly(sV, cgi.shMiniGhost, 0xFFFF00C0);
queuepoly(V, cgi.shMiniEyes, 0xFF); queuepoly(sV, cgi.shMiniEyes, 0xFF);
} }
else { else {
queuepoly(V, cgi.shMiniGhost, 0xFFFFFFC0); queuepoly(sV, cgi.shMiniGhost, 0xFFFFFFC0);
queuepoly(V, cgi.shMiniEyes, 0xFF); queuepoly(sV, cgi.shMiniEyes, 0xFF);
} }
} }
@ -1914,7 +1914,7 @@ startanim army_of_ghosts { "army of ghosts", no_init, [] {
for(int y=0;; y++) { for(int y=0;; y++) {
ld ay = (mod - y)/4.; ld ay = (mod - y)/4.;
transmatrix U = spin(M_PI/2) * xpush(ay / cosh(ax)) * T; 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)); draw_ghost(U, (-y - t));
if(y) { if(y) {
ay = (mod + y)/4.; ay = (mod + y)/4.;

View File

@ -313,7 +313,7 @@ shared_ptr<glhr::GLprogram> 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; flagtype shader_flags = current_display->next_shader_flags;
unsigned id; unsigned id;
id = geometry; id = geometry;
@ -467,8 +467,9 @@ void display_data::set_projection(int ed) {
if(selected->shader_flags & SF_BAND) if(selected->shader_flags & SF_BAND)
glhr::projection_multiply(glhr::scale(2 / M_PI, 2 / M_PI, GDIM == 3 ? 2/M_PI : 1)); glhr::projection_multiply(glhr::scale(2 / M_PI, 2 / M_PI, GDIM == 3 ? 2/M_PI : 1));
if(selected->shader_flags & SF_BAND) if(selected->shader_flags & SF_BAND) {
glhr::projection_multiply(glhr::translate(band_shift, 0, 0)); glhr::projection_multiply(glhr::translate(shift, 0, 0));
}
if(selected->shader_flags & SF_HALFPLANE) { if(selected->shader_flags & SF_HALFPLANE) {
glhr::projection_multiply(glhr::translate(0, 1, 0)); glhr::projection_multiply(glhr::translate(0, 1, 0));

207
shmup.cpp
View File

@ -21,9 +21,9 @@ EX namespace shmupballs {
} }
EX } EX }
ld sqdist(hyperpoint a, hyperpoint b) { ld sqdist(shiftpoint a, shiftpoint b) {
if(prod) return pow(hdist(a, b), 2); 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 // tortoises: origin
// butterflies: last position // butterflies: last position
transmatrix at; transmatrix at;
transmatrix pat; shiftmatrix pat;
/** orientation for the product geometry */ /** orientation for the product geometry */
transmatrix ori; transmatrix ori;
eMonster stk; eMonster stk;
@ -84,9 +84,9 @@ struct monster {
void findpat(); 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 #endif
@ -112,23 +112,23 @@ typedef multimap<cell*, monster*>::iterator mit;
vector<monster*> active, nonvirtual, additional; vector<monster*> active, nonvirtual, additional;
cell *findbaseAround(hyperpoint p, cell *around, int maxsteps) { cell *findbaseAround(shiftpoint p, cell *around, int maxsteps) {
if(fake::split()) { if(fake::split()) {
auto p0 = inverse(ggmatrix(around)) * p; auto p0 = inverse_shift(ggmatrix(around), p);
virtualRebase(around, p0); virtualRebase(around, p0);
return around; return around;
} }
cell *best = around; cell *best = around;
transmatrix T = ggmatrix(around); shiftmatrix T = ggmatrix(around);
horo_distance d0(p, T); horo_distance d0(p, T);
for(int k=0; k<maxsteps; k++) { for(int k=0; k<maxsteps; k++) {
for(int i=0; i<around->type; i++) { for(int i=0; i<around->type; i++) {
cell *c2 = around->move(i); cell *c2 = around->move(i);
if(c2) { if(c2) {
transmatrix U = ggmatrix(c2); shiftmatrix U = ggmatrix(c2);
horo_distance d1(p, U); horo_distance d1(p, U);
if(d1 < d0) { best = c2; d0 = d1; } if(d1 < d0) { best = c2; d0 = d1; }
} }
@ -139,7 +139,7 @@ cell *findbaseAround(hyperpoint p, cell *around, int maxsteps) {
return around; 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); return findbaseAround(tC0(H), around, maxsteps);
} }
@ -153,15 +153,15 @@ void monster::store() {
} }
void monster::findpat() { 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; 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) { if(isVirtual) {
cell *c = base; cell *c = base;
auto cT = T; auto cT = T.T;
virtualRebase(c, cT); virtualRebase(c, cT);
return c; return c;
} }
@ -177,18 +177,18 @@ void fix_to_2(transmatrix& T) {
fixelliptic(T); fixelliptic(T);
} }
void monster::rebasePat(const transmatrix& new_pat, cell *c2) { void monster::rebasePat(const shiftmatrix& new_pat, cell *c2) {
if(isVirtual) { if(isVirtual) {
at = new_pat; at = new_pat.T;
virtualRebase(this); virtualRebase(this);
fix_to_2(at); fix_to_2(at);
pat = at; pat = shiftless(at);
if(multi::players == 1 && this == shmup::pc[0]) if(multi::players == 1 && this == shmup::pc[0])
current_display->which_copy = ggmatrix(base); current_display->which_copy = unshift(ggmatrix(base));
return; return;
} }
if(quotient || fake::split()) { if(quotient || fake::split()) {
at = inverse(gmatrix[base]) * new_pat; at = inverse_shift(gmatrix[base], new_pat);
transmatrix old_at = at; transmatrix old_at = at;
virtualRebase(this); virtualRebase(this);
fix_to_2(at); fix_to_2(at);
@ -205,21 +205,21 @@ void monster::rebasePat(const transmatrix& new_pat, cell *c2) {
return; return;
} }
if(multi::players == 1 && this == shmup::pc[0]) 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; pat = new_pat;
// if(c2 != base) printf("rebase %p -> %p\n", base, c2); // if(c2 != base) printf("rebase %p -> %p\n", base, c2);
base = c2; base = c2;
at = inverse(gmatrix[c2]) * pat; at = inverse_shift(gmatrix[c2], pat);
fix_to_2(at); fix_to_2(at);
fixelliptic(at); fixelliptic(at);
} }
bool trackroute(monster *m, transmatrix goal, double spd) { bool trackroute(monster *m, shiftmatrix goal, double spd) {
cell *c = m->base; cell *c = m->base;
// queuepoly(goal, shGrail, 0xFFFFFFC0); // queuepoly(goal, shGrail, 0xFFFFFFC0);
transmatrix mat = inverse(m->pat) * goal; transmatrix mat = inverse_shift(m->pat, goal);
transmatrix mat2 = spintox(mat*C0) * mat; transmatrix mat2 = spintox(mat*C0) * mat;
@ -227,7 +227,7 @@ bool trackroute(monster *m, transmatrix goal, double spd) {
while(d < dist) { while(d < dist) {
d += spd; 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); // queuepoly(nat, cgi.shKnife, 0xFFFFFFC0);
@ -339,7 +339,7 @@ void awakenMimics(monster *m, cell *c2) {
else else
m2->type = moMimic; m2->type = moMimic;
hyperpoint H = inverse(gmatrix[c2]) * gmatrix[c] * C0; hyperpoint H = inverse_shift(gmatrix[c2], tC0(gmatrix[c]));
transmatrix xfer = rgpushxto0(H); transmatrix xfer = rgpushxto0(H);
@ -348,9 +348,9 @@ void awakenMimics(monster *m, cell *c2) {
xfer = rspintox(H) * rpushxto0(H2) * mirrortrans * spintox(H); 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; m2->pid = cpid;
additional.push_back(m2); additional.push_back(m2);
@ -430,7 +430,7 @@ EX void killThePlayer(eMonster m) {
pc[cpid]->dead = true; pc[cpid]->dead = true;
} }
monster *playerCrash(monster *who, hyperpoint where) { monster *playerCrash(monster *who, shiftpoint where) {
if(who->isVirtual) return NULL; if(who->isVirtual) return NULL;
// in the racing mode, neither crashing nor getting too far away is a problem // in the racing mode, neither crashing nor getting too far away is a problem
if(racing::on) return NULL; if(racing::on) return NULL;
@ -442,7 +442,7 @@ monster *playerCrash(monster *who, hyperpoint where) {
return NULL; return NULL;
} }
void oceanCurrents(transmatrix& nat, monster *m, int delta) { void oceanCurrents(shiftmatrix& nat, monster *m, int delta) {
cell *c = m->base; cell *c = m->base;
if(c->land == laWhirlpool) { if(c->land == laWhirlpool) {
for(int i=0; i<c->type; i++) { for(int i=0; i<c->type; i++) {
@ -457,11 +457,11 @@ void oceanCurrents(transmatrix& nat, monster *m, int delta) {
spd = SCALE * delta / 900.; spd = SCALE * delta / 900.;
if(spd) { if(spd) {
transmatrix goal = gmatrix[c2]; shiftpoint goal = tC0(gmatrix[c2]);
// transmatrix t = spintox(H) * xpush(delta/300.) * rspintox(H); // 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 * rspintox(H);
nat = nat * xpush(spd); nat = nat * xpush(spd);
nat = nat * spintox(H); 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; bool carried = false;
cell *c = m->base; cell *c = m->base;
#if CAP_COMPLEX2 #if CAP_COMPLEX2
@ -481,11 +481,11 @@ bool airCurrents(transmatrix& nat, monster *m, int delta) {
if(m->type == moVoidBeast) spd = -spd; if(m->type == moVoidBeast) spd = -spd;
if(spd) { if(spd) {
transmatrix goal = gmatrix[c2]; shiftpoint goal = tC0(gmatrix[c2]);
// transmatrix t = spintox(H) * xpush(delta/300.) * rspintox(H); // 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 * rspintox(H);
nat = nat * xpush(spd); nat = nat * xpush(spd);
nat = nat * spintox(H); nat = nat * spintox(H);
@ -503,11 +503,11 @@ bool airCurrents(transmatrix& nat, monster *m, int delta) {
if(m->type == moVoidBeast) spd = -spd; if(m->type == moVoidBeast) spd = -spd;
if(spd) { if(spd) {
transmatrix goal = gmatrix[c2]; shiftpoint goal = tC0(gmatrix[c2]);
// transmatrix t = spintox(H) * xpush(delta/300.) * rspintox(H); // 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 * rspintox(H);
nat = nat * xpush(spd); nat = nat * xpush(spd);
nat = nat * spintox(H); nat = nat * spintox(H);
@ -524,11 +524,11 @@ bool airCurrents(transmatrix& nat, monster *m, int delta) {
if(z >= 128) z -= 256; if(z >= 128) z -= 256;
if(m->type == moVoidBeast) z = -z; if(m->type == moVoidBeast) z = -z;
if(z < windmap::NOWINDFROM && z > -windmap::NOWINDFROM) { if(z < windmap::NOWINDFROM && z > -windmap::NOWINDFROM) {
transmatrix goal = gmatrix[c2]; shiftmatrix goal = gmatrix[c2];
// transmatrix t = spintox(H) * xpush(delta/300.) * rspintox(H); // 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 * rspintox(H);
nat = nat * xpush(z * SCALE * delta / 50000.); nat = nat * xpush(z * SCALE * delta / 50000.);
nat = nat * spintox(H); nat = nat * spintox(H);
@ -540,7 +540,7 @@ bool airCurrents(transmatrix& nat, monster *m, int delta) {
return carried; return carried;
} }
void roseCurrents(transmatrix& nat, monster *m, int delta) { void roseCurrents(shiftmatrix& nat, monster *m, int delta) {
if(ignoresSmell(m->type)) return; if(ignoresSmell(m->type)) return;
cell *c = m->base; cell *c = m->base;
@ -559,11 +559,11 @@ void roseCurrents(transmatrix& nat, monster *m, int delta) {
double spd = SCALE * delta / 300. / qty; double spd = SCALE * delta / 300. / qty;
if(spd) { if(spd) {
transmatrix goal = gmatrix[c2]; shiftpoint goal = tC0(gmatrix[c2]);
// transmatrix t = spintox(H) * xpush(delta/300.) * rspintox(H); // 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 * rspintox(H);
nat = nat * xpush(spd); nat = nat * xpush(spd);
nat = nat * spintox(H); 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.); double d = 2 + sin(curtime / 350.);
return pc[i]->pat * cpush0(WDIM == 3 ? 2 : 0, d * cgi.scalefactor); 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 // used in 3D
EX transmatrix swordmatrix[MAXPLAYER]; EX transmatrix swordmatrix[MAXPLAYER];
hyperpoint swordpos(int id, bool rev, double frac) { shiftpoint swordpos(int id, bool rev, double frac) {
if(WDIM == 3) if(WDIM == 3)
return pc[id]->pat * swordmatrix[id] * cpush0(2, (rev?-frac:frac) * getSwordSize()); return pc[id]->pat * swordmatrix[id] * cpush0(2, (rev?-frac:frac) * getSwordSize());
else else
return pc[id]->pat * xspinpush0(pc[id]->swordangle, (rev?-frac:frac) * getSwordSize()); 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()); return pc[id]->pat * xpush0(getHornsSize());
} }
@ -649,11 +649,11 @@ void doTraps() {
traplist.emplace(t.first + 500, t.second); traplist.emplace(t.first + 500, t.second);
for(int i=0; i<5; i += 4) try { for(int i=0; i<5; i += 4) try {
transmatrix& tu = gmatrix.at(tl[i]); shiftmatrix& tu = gmatrix.at(tl[i]);
transmatrix& tv = gmatrix.at(tl[4-i]); shiftmatrix& tv = gmatrix.at(tl[4-i]);
monster* bullet = new monster; monster* bullet = new monster;
bullet->base = tl[i]; bullet->base = tl[i];
bullet->at = rspintox(inverse(tu) * tC0(tv)); bullet->at = rspintox(inverse_shift(tu, tC0(tv)));
bullet->type = moArrowTrap; bullet->type = moArrowTrap;
bullet->parent = &arrowtrap_fakeparent; bullet->parent = &arrowtrap_fakeparent;
bullet->pid = 0; bullet->pid = 0;
@ -790,7 +790,7 @@ void movePlayer(monster *m, int delta) {
#endif #endif
} }
transmatrix nat = m->pat; shiftmatrix nat = m->pat;
// if(ka == b+pcOrbPower) dropgreen = true; // if(ka == b+pcOrbPower) dropgreen = true;
@ -827,11 +827,11 @@ void movePlayer(monster *m, int delta) {
if(mdd > 1e-6) { if(mdd > 1e-6) {
hyperpoint jh = hpxy(mdx/100.0, mdy/100.0); 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]; 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]); playerturn[cpid] = -atan2(h[1], h[0]);
mgo += mdd; mgo += mdd;
@ -843,7 +843,7 @@ void movePlayer(monster *m, int delta) {
bool forcetarget = (keystate[SDLK_RSHIFT] | keystate[SDLK_LSHIFT]); bool forcetarget = (keystate[SDLK_RSHIFT] | keystate[SDLK_LSHIFT]);
if(((mousepressed && !forcetarget) || facemouse) && delta > 0 && !mouseout() && !stdracing && GDIM == 2) { if(((mousepressed && !forcetarget) || facemouse) && delta > 0 && !mouseout() && !stdracing && GDIM == 2) {
// playermoved = true; // playermoved = true;
hyperpoint h = inverse(m->pat) * mouseh; hyperpoint h = inverse_shift(m->pat, mouseh);
playerturn[cpid] = -atan2(h[1], h[0]); playerturn[cpid] = -atan2(h[1], h[0]);
// nat = nat * spin(alpha); // nat = nat * spin(alpha);
// mturn += alpha * 150. / delta; // mturn += alpha * 150. / delta;
@ -863,10 +863,10 @@ void movePlayer(monster *m, int delta) {
if(playerturn[cpid] && canmove && !blown && WDIM == 2) { if(playerturn[cpid] && canmove && !blown && WDIM == 2) {
m->swordangle -= playerturn[cpid]; 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; if(inertia_based) m->inertia = spin(-playerturn[cpid]) * m->inertia;
} }
transmatrix nat0 = nat; shiftmatrix nat0 = nat;
if(m->base->land == laWhirlpool && !markOrb(itOrbWater)) if(m->base->land == laWhirlpool && !markOrb(itOrbWater))
oceanCurrents(nat, m, delta); oceanCurrents(nat, m, delta);
@ -942,7 +942,7 @@ void movePlayer(monster *m, int delta) {
nextstep: nextstep:
transmatrix nat1 = nat; shiftmatrix nat1 = nat;
hyperpoint avg_inertia; hyperpoint avg_inertia;
@ -983,14 +983,13 @@ void movePlayer(monster *m, int delta) {
hyperpoint drag = m->inertia * cinertia * delta / -1. / SCALE; hyperpoint drag = m->inertia * cinertia * delta / -1. / SCALE;
m->inertia += drag; m->inertia += drag;
avg_inertia += drag/2; avg_inertia += drag/2;
transmatrix T = inverse(m->pat);
ld xp = SCALE / 60000. / isize(below) * delta / 15; ld xp = SCALE / 60000. / isize(below) * delta / 15;
ld yp = 0; ld yp = 0;
if(cwt.at->land == laDungeon) xp = -xp; if(cwt.at->land == laDungeon) xp = -xp;
if(cwt.at->land == laWestWall) yp = xp * 1, xp *= 0.7; if(cwt.at->land == laWestWall) yp = xp * 1, xp *= 0.7;
for(cell *c2: below) if(c2 != m->base) { 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; m->inertia += h;
avg_inertia += h/2; avg_inertia += h/2;
@ -1009,8 +1008,8 @@ void movePlayer(monster *m, int delta) {
playergoturn[cpid] = 0; playergoturn[cpid] = 0;
if(igo) { go = false; break; } if(igo) { go = false; break; }
ld r = hypot_d(WDIM, avg_inertia); ld r = hypot_d(WDIM, avg_inertia);
apply_parallel_transport(nat, m->ori, rspintox(avg_inertia) * xtangent(r * delta)); apply_parallel_transport(nat.T, 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])); if(WDIM == 3) rotate_object(nat.T, m->ori, cspin(0, 2, playerturn[cpid]) * cspin(1, 2, playerturny[cpid]));
m->vel = r * (600/SCALE); m->vel = r * (600/SCALE);
} }
else if(WDIM == 3) { 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]); playersmallspin[cpid] = cspin(0, 1, fspin) * cspin(2, 0, igospan[igo]);
if(fspin < 360) igo--; else fspin = 0; if(fspin < 360) igo--; else fspin = 0;
} }
nat = parallel_transport(nat1, m->ori, playersmallspin[cpid] * point3(playerstrafe[cpid], 0, playergo[cpid])); nat.T = parallel_transport(nat1.T, 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])); rotate_object(nat.T, m->ori, cspin(0, 2, playerturn[cpid]) * cspin(1, 2, playerturny[cpid]));
m->inertia[0] = playerstrafe[cpid] / delta; m->inertia[0] = playerstrafe[cpid] / delta;
m->inertia[1] = 0; m->inertia[1] = 0;
m->inertia[2] = playergo[cpid] / delta; m->inertia[2] = playergo[cpid] / delta;
} }
else if(playergo[cpid]) { else if(playergo[cpid]) {
playergoturn[cpid] = igospan[igo]+godir[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); m->inertia = spin(playergoturn[cpid]) * xtangent(playergo[cpid] / delta);
} }
@ -1118,7 +1117,7 @@ void movePlayer(monster *m, int delta) {
int i0 = i; int i0 = i;
for(int a=0; a<3; a++) v[a] = (i0 % 3) - 1, i0 /= 3; for(int a=0; a<3; a++) v[a] = (i0 % 3) - 1, i0 /= 3;
v = v * .1 / hypot_d(3, v); 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; cell *c3 = c2;
while(true) { while(true) {
cell *c4 = findbaseAround(tC0(T1), c3, 1); cell *c4 = findbaseAround(tC0(T1), c3, 1);
@ -1246,7 +1245,7 @@ void movePlayer(monster *m, int delta) {
playerfire[cpid] = false; playerfire[cpid] = false;
if(items[itOrbHorns] && !m->isVirtual) { if(items[itOrbHorns] && !m->isVirtual) {
hyperpoint H = hornpos(cpid); shiftpoint H = hornpos(cpid);
for(monster *m2: nonvirtual) { for(monster *m2: nonvirtual) {
if(m2 == m) continue; 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(int b=0; b<2; b++) if(sword::orbcount(b) && !m->isVirtual) {
for(double d=0; d<=1.001; d += .1) { 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) { for(monster *m2: nonvirtual) {
if(m2 == m) continue; if(m2 == m) continue;
@ -1343,23 +1342,23 @@ EX monster *getPlayer() {
void virtualize(monster *m) { void virtualize(monster *m) {
if(doall) forCellCM(c2, m->base) if(!gmatrix.count(c2)) { if(doall) forCellCM(c2, m->base) if(!gmatrix.count(c2)) {
m->isVirtual = true; m->isVirtual = true;
m->pat = m->at; m->pat = shiftless(m->at);
return; 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; 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)); transmatrix S = spintox(tC0(H));
ld d = hdist0(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; if(onlypos && tC0(T)[0] < 0) return false;
M = gmatrix[c1] * inverse(S) * xpush(d/2) * MirrorX * T; M = gmatrix[c1] * inverse(S) * xpush(d/2) * MirrorX * T;
return true; return true;
} }
EX int reflect(cell*& c2, cell*& mbase, transmatrix& nat) { EX int reflect(cell*& c2, cell*& mbase, shiftmatrix& nat) {
int reflections = 0; int reflections = 0;
if(c2 != mbase && c2->wall == waMirrorWall && inmirror(c2)) { if(c2 != mbase && c2->wall == waMirrorWall && inmirror(c2)) {
if(reflectmatrix(nat, mbase, c2, false)) { if(reflectmatrix(nat, mbase, c2, false)) {
@ -1409,15 +1408,15 @@ EX int reflect(cell*& c2, cell*& mbase, transmatrix& nat) {
void moveMimic(monster *m) { void moveMimic(monster *m) {
virtualize(m); virtualize(m);
transmatrix nat = m->pat; shiftmatrix nat = m->pat;
cpid = m->pid; cpid = m->pid;
m->footphase = getPlayer()->footphase; m->footphase = getPlayer()->footphase;
// no need to care about Mirror images, as they already have their 'at' matrix reversed :| // no need to care about Mirror images, as they already have their 'at' matrix reversed :|
if(WDIM == 3) { if(WDIM == 3) {
nat = parallel_transport(nat, m->ori, playersmallspin[cpid] * point3(playerstrafe[cpid], 0, playergo[cpid])); nat.T = parallel_transport(nat.T, 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])); rotate_object(nat.T, m->ori, cspin(0, 2, playerturn[cpid]) * cspin(1, 2, playerturny[cpid]));
} }
else else
nat = nat * spin(playerturn[cpid] + playergoturn[cpid]) * xpush(playergo[cpid]) * spin(-playergoturn[cpid]); nat = nat * spin(playerturn[cpid] + playergoturn[cpid]) * xpush(playergo[cpid]) * spin(-playergoturn[cpid]);
@ -1465,7 +1464,7 @@ void destroyMimics() {
EX void teleported() { EX void teleported() {
monster *m = pc[cpid]; monster *m = pc[cpid];
m->base = cwt.at; 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(); m->findpat();
destroyMimics(); destroyMimics();
} }
@ -1473,7 +1472,7 @@ EX void teleported() {
void shoot(eItem it, monster *m) { void shoot(eItem it, monster *m) {
monster* bullet = new monster; monster* bullet = new monster;
bullet->base = m->base; bullet->base = m->base;
bullet->at = m->at * rspintox(inverse(m->pat) * mouseh); bullet->at = m->at * rspintox(inverse_shift(m->pat, mouseh));
/* ori */ /* ori */
if(WDIM == 3) bullet->at = bullet->at * cpush(2, 0.15 * SCALE); if(WDIM == 3) bullet->at = bullet->at * cpush(2, 0.15 * SCALE);
bullet->type = it == itOrbDragon ? moFireball : it == itOrbAir ? moAirball : moBullet; bullet->type = it == itOrbDragon ? moFireball : it == itOrbAir ? moAirball : moBullet;
@ -1485,7 +1484,7 @@ void shoot(eItem it, monster *m) {
} }
eItem targetRangedOrbKey(orbAction a) { eItem targetRangedOrbKey(orbAction a) {
hyperpoint h = mouseh; shiftpoint h = mouseh;
cell *b = mouseover; cell *b = mouseover;
monster *mt = mousetarget; monster *mt = mousetarget;
@ -1578,7 +1577,7 @@ void spawn_asteroids(monster *bullet, monster *target) {
if(target->hitpoints <= 1) return; if(target->hitpoints <= 1) return;
hyperpoint rnd = random_spin() * point2(SCALE/3000., 0); 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++) { for(int i=0; i<2; i++) {
monster* child = new monster; monster* child = new monster;
@ -1608,8 +1607,8 @@ void moveBullet(monster *m, int delta) {
m->findpat(); m->findpat();
virtualize(m); virtualize(m);
transmatrix nat0 = m->pat; shiftmatrix nat0 = m->pat;
transmatrix nat = m->pat; shiftmatrix nat = m->pat;
bool inertia_based = m->base->land == laAsteroids; bool inertia_based = m->base->land == laAsteroids;
@ -1633,10 +1632,10 @@ void moveBullet(monster *m, int delta) {
m->dead = true; m->dead = true;
if(inertia_based) { if(inertia_based) {
nat = parallel_transport(nat, m->ori, m->inertia * delta); nat.T = parallel_transport(nat.T, m->ori, m->inertia * delta);
} }
else 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); cell *c2 = m->findbase(nat, fake::split() ? 10 : 1);
if(m->parent && isPlayer(m->parent) && markOrb(itOrbLava) && c2 != m->base && !isPlayerOn(m->base)) 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(m->type == moAirball && isBlowableMonster(m2->type)) {
if(m2->blowoff < curtime) { if(m2->blowoff < curtime) {
hyperpoint h = inverse(m2->pat) * nat0 * C0; hyperpoint h = inverse_shift(m2->pat, nat0 * C0);
if(WDIM == 3) if(WDIM == 3)
swordmatrix[m2->pid] = spintox(h) * swordmatrix[m2->pid]; swordmatrix[m2->pid] = spintox(h) * swordmatrix[m2->pid];
else else
@ -1729,7 +1728,7 @@ void moveBullet(monster *m, int delta) {
} }
// Hedgehog Warriors only killable outside of the 45 degree angle // Hedgehog Warriors only killable outside of the 45 degree angle
if(m2->type == moHedge && !peace::on && !slayer) { 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(h[0] > fabsl(h[1])) { m->dead = true; continue; }
} }
if(peace::on && !isIvy(m2->type)) { 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) { bool closer(monster *m1, monster *m2) {
return sqdist(m1->pat*C0, closerTo) < sqdist(m2->pat*C0, closerTo); return sqdist(m1->pat*C0, closerTo) < sqdist(m2->pat*C0, closerTo);
@ -1832,7 +1831,7 @@ EX bool dragonbreath(cell *dragon) {
int randplayer = hrand(numplayers()); int randplayer = hrand(numplayers());
monster* bullet = new monster; monster* bullet = new monster;
bullet->base = dragon; 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->type = moFireball;
bullet->parent = bullet; bullet->parent = bullet;
bullet->pid = randplayer; bullet->pid = randplayer;
@ -1882,7 +1881,7 @@ void moveMonster(monster *m, int delta) {
if(m->dead) return; if(m->dead) return;
cell *c = m->base; cell *c = m->base;
transmatrix goal = gmatrix[c]; shiftmatrix goal = gmatrix[c];
bool direct = false; // is there a direct path to the target? 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) 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(m->isVirtual) {
if(inertia_based) { if(inertia_based) {
ld r = hypot_d(WDIM, m->inertia); 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); m->rebasePat(nat, m->base);
} }
return; return;
} }
transmatrix nat = m->pat; shiftmatrix nat = m->pat;
if(stunned) { if(stunned) {
if(m->blowoff > curtime) { if(m->blowoff > curtime) {
@ -2062,7 +2061,7 @@ void moveMonster(monster *m, int delta) {
} }
if(m->type == moHedge) { if(m->type == moHedge) {
hyperpoint h = inverse(m->pat) * goal * C0; hyperpoint h = inverse_shift(m->pat, tC0(goal));
if(h[1] < 0) if(h[1] < 0)
nat = nat * spin(M_PI * delta / 3000 / speedfactor()); nat = nat * spin(M_PI * delta / 3000 / speedfactor());
else else
@ -2101,7 +2100,7 @@ void moveMonster(monster *m, int delta) {
int igo = 0; int igo = 0;
transmatrix nat0 = nat; shiftmatrix nat0 = nat;
igo_retry: igo_retry:
@ -2120,14 +2119,14 @@ void moveMonster(monster *m, int delta) {
if(inertia_based) { if(inertia_based) {
if(igo) return; 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) { else if(WDIM == 3 && igo) {
ld fspin = rand() % 1000; 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 { 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) if(m->type != moRagingBull && !peace::on)
@ -2136,7 +2135,7 @@ void moveMonster(monster *m, int delta) {
for(int i=0; i<multi::players; i++) for(int b=0; b<2; b++) if(sword::orbcount(b)) { for(int i=0; i<multi::players; i++) for(int b=0; b<2; b++) if(sword::orbcount(b)) {
if(pc[i]->isVirtual) continue; if(pc[i]->isVirtual) continue;
hyperpoint H = swordpos(i, b, 1); shiftpoint H = swordpos(i, b, 1);
double d = sqdist(H, nat*C0); double d = sqdist(H, nat*C0);
if(d < SCALE2 * 0.12) { igo++; goto igo_retry; } if(d < SCALE2 * 0.12) { igo++; goto igo_retry; }
} }
@ -2524,7 +2523,7 @@ EX void turn(int delta) {
if(doall) if(doall)
for(cell *c: currentmap->allcells()) activateMonstersAt(c); for(cell *c: currentmap->allcells()) activateMonstersAt(c);
else else
for(unordered_map<cell*, transmatrix>::iterator it = gmatrix.begin(); it != gmatrix.end(); it++) for(unordered_map<cell*, shiftmatrix>::iterator it = gmatrix.begin(); it != gmatrix.end(); it++)
activateMonstersAt(it->first); activateMonstersAt(it->first);
/* printf("size: gmatrix = %ld, active = %ld, monstersAt = %ld, delta = %d\n", /* printf("size: gmatrix = %ld, active = %ld, monstersAt = %ld, delta = %d\n",
@ -2757,7 +2756,7 @@ EX void init() {
pc[i]->at = Id; pc[i]->at = Id;
else else
pc[i]->at = spin(2*M_PI*i/players) * xpush(firstland == laMotion ? .5 : .3) * Id; 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]->base = cwt.at;
pc[i]->vel = 0; pc[i]->vel = 0;
pc[i]->inBoat = (firstland == laCaribbean || firstland == laOcean || firstland == laLivefjord || pc[i]->inBoat = (firstland == laCaribbean || firstland == laOcean || firstland == laLivefjord ||
@ -2785,7 +2784,7 @@ EX bool boatAt(cell *c) {
return false; return false;
} }
EX hookset<bool(const transmatrix&, cell*, shmup::monster*)> hooks_draw; EX hookset<bool(const shiftmatrix&, cell*, shmup::monster*)> hooks_draw;
EX void clearMonsters() { EX void clearMonsters() {
for(mit it = monstersAt.begin(); it != monstersAt.end(); it++) for(mit it = monstersAt.begin(); it != monstersAt.end(); it++)
@ -2895,7 +2894,7 @@ bool celldrawer::draw_shmup_monster() {
monstersAt.equal_range(c); monstersAt.equal_range(c);
if(p.first == p.second) return false; 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<monster*> monsters; vector<monster*> monsters;
@ -2903,7 +2902,7 @@ bool celldrawer::draw_shmup_monster() {
monster* m = it->second; monster* m = it->second;
if(c != m->base) continue; // may happen in RogueViz Collatz if(c != m->base) continue; // may happen in RogueViz Collatz
m->pat = ggmatrix(m->base) * m->at; m->pat = ggmatrix(m->base) * m->at;
transmatrix view = V * m->at; shiftmatrix view = V * m->at;
if(!mouseout()) { if(!mouseout()) {
if(m->no_targetting) ; else if(m->no_targetting) ; else
@ -2975,7 +2974,7 @@ bool celldrawer::draw_shmup_monster() {
} }
if(ths && keyresult[cpid]) { if(ths && keyresult[cpid]) {
hyperpoint h = keytarget(cpid); shiftpoint h = keytarget(cpid);
if(WDIM == 2) if(WDIM == 2)
queuestr(h, vid.fsize, "+", iinf[keyresult[cpid]].color); queuestr(h, vid.fsize, "+", iinf[keyresult[cpid]].color);
else { else {
@ -2992,7 +2991,7 @@ bool celldrawer::draw_shmup_monster() {
if(m->parenttype == moPlayer) if(m->parenttype == moPlayer)
col = getcs().swordcolor; col = getcs().swordcolor;
else if(m->parenttype == moMimic) else if(m->parenttype == moMimic)
col = (mirrorcolor(det(view) < 0) << 8) | 0xFF; col = (mirrorcolor(det(view.T) < 0) << 8) | 0xFF;
else else
col = (minf[m->parenttype].color << 8) | 0xFF; col = (minf[m->parenttype].color << 8) | 0xFF;
if(getcs().charid >= 4) { if(getcs().charid >= 4) {
@ -3004,7 +3003,7 @@ bool celldrawer::draw_shmup_monster() {
ShadowV(view, cgi.shPHead); ShadowV(view, cgi.shPHead);
} }
else { 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); queuepoly(WDIM == 3 ? t : GDIM == 3 ? mscale(t, cgi.BODY) : mmscale(t, 1.15), cgi.shKnife, col);
ShadowV(t, cgi.shKnife); ShadowV(t, cgi.shKnife);
} }
@ -3026,14 +3025,14 @@ bool celldrawer::draw_shmup_monster() {
break; break;
} }
case moFlailBullet: case moCrushball: { 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); queuepoly(mmscale(t, 1.15), cgi.shFlailMissile, (minf[m->type].color << 8) | 0xFF);
ShadowV(view, cgi.shFlailMissile); ShadowV(view, cgi.shFlailMissile);
break; break;
} }
case moAsteroid: { case moAsteroid: {
if(GDIM == 3) addradar(view, '*', 0xFFFFFF, 0xC0C0C0FF); if(GDIM == 3) addradar(view, '*', 0xFFFFFF, 0xC0C0C0FF);
transmatrix t = view; shiftmatrix t = view;
if(WDIM == 3) t = face_the_player(t); if(WDIM == 3) t = face_the_player(t);
t = t * spin(curtime / 500.0); t = t * spin(curtime / 500.0);
ShadowV(t, cgi.shAsteroid[m->hitpoints & 7]); ShadowV(t, cgi.shAsteroid[m->hitpoints & 7]);
@ -3054,7 +3053,7 @@ bool celldrawer::draw_shmup_monster() {
if(m->inBoat) m->footphase = 0; if(m->inBoat) m->footphase = 0;
color_t col = minf[m->type].color; color_t col = minf[m->type].color;
if(m->type == moMimic) if(m->type == moMimic)
col = mirrorcolor(det(view) < 0); col = mirrorcolor(det(view.T) < 0);
if(m->type == moSlime) { if(m->type == moSlime) {
col = winf[c->wall].color; col = winf[c->wall].color;
col |= (col >> 1); col |= (col >> 1);

13
sky.cpp
View File

@ -14,9 +14,9 @@ EX int get_skybrightness(int mul IS(1)) {
struct sky_item { struct sky_item {
cell *c; cell *c;
transmatrix T; shiftmatrix T;
color_t color; 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 { struct dqi_sky : drawqueueitem {
@ -35,8 +35,8 @@ EX void prepare_sky() {
if(euclid) { if(euclid) {
if(WDIM == 3 || GDIM == 2) return; if(WDIM == 3 || GDIM == 2) return;
if(no_wall_rendering) return; if(no_wall_rendering) return;
transmatrix T = ggmatrix(currentmap->gamestart()); shiftmatrix T = ggmatrix(currentmap->gamestart());
T = gpushxto0(tC0(T)) * T; T.T = gpushxto0(tC0(T.T)) * T.T;
queuepoly(T, cgi.shEuclideanSky, 0x0044e4FF); queuepoly(T, cgi.shEuclideanSky, 0x0044e4FF);
queuepolyat(T * zpush(cgi.SKY+0.5) * xpush(cgi.SKY+0.5), cgi.shSun, 0xFFFF00FF, PPR::SKY); 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(); this_poly.clear();
transmatrix T1 = Tsh * si.T; transmatrix T1 = unshift(si.T);
T1 = Tsh * T1;
do { do {
this_poly.emplace_back(T1 * skypoint, colors[cw.at]); this_poly.emplace_back(T1 * skypoint, colors[cw.at]);
T1 = T1 * currentmap->adj(cw.at, cw.spin); 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) { for(int ed = current_display->stereo_active() ? -1 : 0; ed<2; ed+=2) {
if(global_projection && global_projection != ed) continue; if(global_projection && global_projection != ed) continue;
current_display->next_shader_flags = GF_VARCOLOR; current_display->next_shader_flags = GF_VARCOLOR;
current_display->set_all(ed); current_display->set_all(ed, 0);
if(global_projection) if(global_projection)
glhr::projection_multiply(glhr::tmtogl(xpush(-vid.ipd * global_projection/2))); glhr::projection_multiply(glhr::tmtogl(xpush(-vid.ipd * global_projection/2)));
glapplymatrix(Id); glapplymatrix(Id);

View File

@ -176,7 +176,7 @@ struct hrmap_spherical : hrmap_standard {
#endif #endif
} }
if(gmatrix0.count(c2) && gmatrix0.count(c1)) { 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) if(elliptic && T[LDIM][LDIM] < 0)
T = centralsym * T; T = centralsym * T;
return T; return T;

View File

@ -431,7 +431,7 @@ void run_hyperlike() {
int lim = (int) sqrt(rug::vertex_limit); int lim = (int) sqrt(rug::vertex_limit);
for(int r=0; r<lim; r++) for(int r=0; r<lim; r++)
for(int h=0; h<lim; h++) for(int h=0; h<lim; h++)
rug::addRugpoint(xpush(2 * M_PI * hyper_b * (2*r-lim) / lim) * ypush(hyperlike_bound() * (2*h-lim) / lim) * C0, -1); rug::addRugpoint(shiftless(xpush(2 * M_PI * hyper_b * (2*r-lim) / lim) * ypush(hyperlike_bound() * (2*h-lim) / lim) * C0), -1);
for(int r=0; r<lim-1; r++) for(int r=0; r<lim-1; r++)
for(int h=0; h<lim-1; h++) { for(int h=0; h<lim-1; h++) {
addTriangle(rug::points[lim*r+h], rug::points[lim*r+h+1], rug::points[lim*r+h+lim]); addTriangle(rug::points[lim*r+h], rug::points[lim*r+h+1], rug::points[lim*r+h+lim]);
@ -444,7 +444,7 @@ void run_hyperlike() {
int id = 0; int id = 0;
for(auto p: rug::points) { for(auto p: rug::points) {
auto h = p->h; auto h = unshift(p->h);
coverage.emplace_back(h, rchar(id++) + 7 * 256); coverage.emplace_back(h, rchar(id++) + 7 * 256);
ld y = asinh(h[1]); ld y = asinh(h[1]);
@ -496,7 +496,7 @@ void run_kuen() {
vector<rug::rugpoint*> newmesh(isize(mesh), nullptr); vector<rug::rugpoint*> newmesh(isize(mesh), nullptr);
for(auto p: mesh) { 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; p->surface_point = px;
history::progress(XLAT("solving the geodesics on: %1, %2/%3", XLAT(captions[part]), its(p->dexp_id), its(isize(mesh)))); 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) { for(auto t: mesh) {
int c = coverages[t->dexp_id]; 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 // delete the old mesh
@ -559,7 +559,7 @@ template<class T> void run_function(T f) {
full_mesh(); full_mesh();
for(auto p: rug::points) { for(auto p: rug::points) {
USING_NATIVE_GEOMETRY; USING_NATIVE_GEOMETRY;
p->native = f(p->h), p->native = f(unshift(p->h)),
p->valid = true; p->valid = true;
} }
} }
@ -571,7 +571,7 @@ void run_other() {
int it = 0; int it = 0;
for(auto p: rug::points) { for(auto p: rug::points) {
it++; it++;
auto h = p->h; auto h = unshift(p->h);
p->surface_point = map_to_surface(h, dp); p->surface_point = map_to_surface(h, dp);
if(1) { if(1) {
@ -783,7 +783,7 @@ EX void show_surfaces() {
if(coverage_style == 2) { if(coverage_style == 2) {
if(rug::rugged) rug::close(); 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(rug::handlekeys(sym, uni)) ;
else if(doexiton(sym, uni)) popScreen(); else if(doexiton(sym, uni)) popScreen();
@ -847,9 +847,9 @@ auto surface_hook = addHook(hooks_args, 100, surface_args);
void display_coverage() { void display_coverage() {
transmatrix M = shiftmatrix M =
coverage_style == 3 ? ggmatrix(coverage_center) * coverage_matrix coverage_style == 3 ? ggmatrix(coverage_center) * coverage_matrix
: Id; : shiftless(Id);
if(coverage_style) if(coverage_style)
for(auto p : coverage) for(auto p : coverage)

View File

@ -12,16 +12,16 @@ namespace hr {
#if HDR #if HDR
struct texture_triangle { struct texture_triangle {
array<hyperpoint, 3> v; array<hyperpoint, 3> v;
array<hyperpoint, 3> tv; array<shiftpoint, 3> tv;
texture_triangle(array<hyperpoint, 3> _v, array<hyperpoint, 3> _tv) : v(_v), tv(_tv) {} texture_triangle(array<hyperpoint, 3> _v, array<shiftpoint, 3> _tv) : v(_v), tv(_tv) {}
}; };
struct textureinfo : basic_textureinfo { struct textureinfo : basic_textureinfo {
transmatrix M; shiftmatrix M;
vector<texture_triangle> triangles; vector<texture_triangle> triangles;
vector<glvertex> vertices; vector<glvertex> vertices;
cell *c; cell *c;
vector<transmatrix> matrices; vector<shiftmatrix> matrices;
// these are required to adjust to geometry changes // these are required to adjust to geometry changes
int current_type, symmetries; int current_type, symmetries;
@ -50,7 +50,7 @@ struct texture_data {
} }
vector<pair<color_t*, color_t>> undos; vector<pair<color_t*, color_t>> undos;
vector<tuple<cell*, hyperpoint, int> > pixels_to_draw; vector<tuple<cell*, shiftpoint, int> > pixels_to_draw;
bool loadTextureGL(); bool loadTextureGL();
bool whitetexture(); bool whitetexture();
@ -91,21 +91,21 @@ struct texture_config {
bool texture_tuned; bool texture_tuned;
string texture_tuner; string texture_tuner;
vector<hyperpoint*> tuned_vertices; vector<shiftpoint*> 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 mark_triangles();
void clear_texture_map(); void clear_texture_map();
void perform_mapping(); void perform_mapping();
void mapTextureTriangle(textureinfo &mi, const array<hyperpoint, 3>& v, const array<hyperpoint, 3>& tv, int splits); void mapTextureTriangle(textureinfo &mi, const array<hyperpoint, 3>& v, const array<shiftpoint, 3>& tv, int splits);
void mapTextureTriangle(textureinfo &mi, const array<hyperpoint, 3>& v, const array<hyperpoint, 3>& tv) { mapTextureTriangle(mi, v, tv, gsplits); } void mapTextureTriangle(textureinfo &mi, const array<hyperpoint, 3>& v, const array<shiftpoint, 3>& tv) { mapTextureTriangle(mi, v, tv, gsplits); }
void mapTexture2(textureinfo& mi); void mapTexture2(textureinfo& mi);
void finish_mapping(); void finish_mapping();
void true_remap(); void true_remap();
void remap(); void remap();
bool correctly_mapped; bool correctly_mapped;
hyperpoint texture_coordinates(hyperpoint); hyperpoint texture_coordinates(shiftpoint);
void drawRawTexture(); void drawRawTexture();
void saveFullTexture(string tn); void saveFullTexture(string tn);
@ -349,7 +349,7 @@ void texture_data::saveRawTexture(string tn) {
addMessage(XLAT("Saved the raw texture to %1", 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; hyperpoint inmodel;
applymodel(h, inmodel); applymodel(h, inmodel);
inmodel[0] *= current_display->radius * 1. / current_display->scrsize; inmodel[0] *= current_display->radius * 1. / current_display->scrsize;
@ -361,11 +361,11 @@ hyperpoint texture_config::texture_coordinates(hyperpoint h) {
return inmodel; return inmodel;
} }
void texture_config::mapTextureTriangle(textureinfo &mi, const array<hyperpoint, 3>& v, const array<hyperpoint, 3>& tv, int splits) { void texture_config::mapTextureTriangle(textureinfo &mi, const array<hyperpoint, 3>& v, const array<shiftpoint, 3>& tv, int splits) {
if(splits) { if(splits) {
array<hyperpoint, 3> v2 = make_array( mid(v[1], v[2]), mid(v[2], v[0]), mid(v[0], v[1]) ); array<hyperpoint, 3> v2 = make_array( mid(v[1], v[2]), mid(v[2], v[0]), mid(v[0], v[1]) );
array<hyperpoint, 3> tv2 = make_array( mid(tv[1], tv[2]), mid(tv[2], tv[0]), mid(tv[0], tv[1]) ); array<shiftpoint, 3> 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[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[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); 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; return c->type;
} }
array<hyperpoint, 3> findTextureTriangle(cell *c, patterns::patterninfo& si, int i) { array<shiftpoint, 3> findTextureTriangle(cell *c, patterns::patterninfo& si, int i) {
transmatrix M = ggmatrix(c) * applyPatterndir(c, si); 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)); return make_array(M * C0, M * get_corner_position(c, i), M * get_corner_position(c, i+1));
} }
// using: mouseh, mouseouver // 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); // auto si = getpatterninfo0(c);
ld quality = 1e10; ld quality = 1e10;
int best = 0; int best = 0;
for(int i=0; i<celltriangles(c); i++) { for(int i=0; i<celltriangles(c); i++) {
auto t = findTextureTriangle(c, si, i); auto t = findTextureTriangle(c, si, i);
ld q = intval(t[1], h) + intval(t[2], h); ld q = hdist(t[1], h) + hdist(t[2], h);
if(q < quality) quality = q, best = i; if(q < quality) quality = q, best = i;
} }
return best; return best;
} }
void mapTexture(cell *c, textureinfo& mi, patterns::patterninfo &si, const transmatrix& T, int shift = 0) { void mapTexture(cell *c, textureinfo& mi, patterns::patterninfo &si, const shiftmatrix& T, int shift = 0) {
mi.c = c; mi.c = c;
mi.symmetries = si.symmetries; mi.symmetries = si.symmetries;
mi.current_type = celltriangles(c); mi.current_type = celltriangles(c);
@ -457,7 +457,7 @@ EX bool using_aura() {
return texture_aura && config.tstate == texture::tsActive; return texture_aura && config.tstate == texture::tsActive;
} }
bool texture_config::apply(cell *c, const transmatrix &V, color_t col) { bool texture_config::apply(cell *c, const shiftmatrix &V, color_t col) {
if(config.tstate == tsOff || !correctly_mapped) return false; if(config.tstate == tsOff || !correctly_mapped) return false;
using namespace patterns; using namespace patterns;
@ -467,10 +467,10 @@ bool texture_config::apply(cell *c, const transmatrix &V, color_t col) {
dynamicval<color_t> d(poly_outline, slave_color); dynamicval<color_t> d(poly_outline, slave_color);
draw_floorshape(c, V, cgi.shFullFloor, 0, PPR::LINE); draw_floorshape(c, V, cgi.shFullFloor, 0, PPR::LINE);
curvepoint(V * C0); curvepoint(C0);
for(int i=0; i<c->type; i++) for(int i=0; i<c->type; i++)
curvepoint(V * get_corner_position(c, i)), curvepoint(V * C0); curvepoint(get_corner_position(c, i)), curvepoint(C0);
queuecurve(slave_color, 0, PPR::LINE); queuecurve(V, slave_color, 0, PPR::LINE);
return false; return false;
} }
@ -523,7 +523,7 @@ void texture_config::mark_triangles() {
for(auto& t: mi.second.triangles) { for(auto& t: mi.second.triangles) {
vector<hyperpoint> t2; vector<hyperpoint> t2;
for(int i=0; i<3; i++) 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); prettypoly(t2, master_color, master_color, gsplits);
} }
} }
@ -593,11 +593,11 @@ void texture_config::finish_mapping() {
for(int a=0; a<8; a++) { for(int a=0; a<8; a++) {
auto& tri = tris[a % isize(tris)]; auto& tri = tris[a % isize(tris)];
hyperpoint center = tri.tv[0]; shiftpoint center = tri.tv[0];
hyperpoint v1 = tri.tv[1] - center; hyperpoint v1 = unshift(tri.tv[1], center.shift) - center.h;
hyperpoint v2 = tri.tv[2] - center; hyperpoint v2 = unshift(tri.tv[2], center.shift) - center.h;
texture_order([&] (ld x, ld y) { 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))); tinf3.tvertices.push_back(glhr::pointtogl(texture_coordinates(h)));
}); });
} }
@ -653,7 +653,7 @@ void texture_config::drawRawTexture() {
glflush(); glflush();
current_display->next_shader_flags = GF_TEXTURE; current_display->next_shader_flags = GF_TEXTURE;
dynamicval<eModel> m(pmodel, mdPixel); dynamicval<eModel> m(pmodel, mdPixel);
current_display->set_all(0); current_display->set_all(0, 0);
glhr::color2(0xFFFFFF20); glhr::color2(0xFFFFFF20);
glBindTexture(GL_TEXTURE_2D, config.data.textureid); glBindTexture(GL_TEXTURE_2D, config.data.textureid);
for(int i=0; i<4; i++) { for(int i=0; i<4; i++) {
@ -819,10 +819,10 @@ void mousemovement() {
switch(panstate) { switch(panstate) {
case tpsModel: case tpsModel:
if(!newmove && mouseh[2] < 50 && lastmouse[2] < 50) { if(!newmove && mouseh[2] < 50 && lastmouse[2] < 50) {
panning(lastmouse, mouseh); panning(shiftless(lastmouse), mouseh);
config.perform_mapping(); config.perform_mapping();
} }
lastmouse = mouseh; newmove = false; lastmouse = unshift(mouseh); newmove = false;
break; break;
case tpsMove: { case tpsMove: {
@ -913,12 +913,12 @@ void mousemovement() {
for(auto& a: config.texture_map) for(auto& a: config.texture_map)
for(auto& t: a.second.triangles) for(auto& t: a.second.triangles)
for(auto& v: t.tv) for(auto& v: t.tv)
if(intval(v, mouseh) < tdist) if(hdist(v, mouseh) < tdist)
tdist = intval(v, mouseh); tdist = hdist(v, mouseh);
for(auto& a: config.texture_map) for(auto& a: config.texture_map)
for(auto& t: a.second.triangles) for(auto& t: a.second.triangles)
for(auto& v: t.tv) 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); config.tuned_vertices.push_back(&v);
newmove = false; newmove = false;
} }
@ -1153,7 +1153,7 @@ void showMagicMenu() {
if(newmove) { if(newmove) {
magicmapper_point newpoint; magicmapper_point newpoint;
newpoint.c = mouseover; newpoint.c = mouseover;
newpoint.cell_relative = inverse(gmatrix[mouseover]) * mouseh; newpoint.cell_relative = inverse_shift(gmatrix[mouseover], mouseh);
amp.push_back(newpoint); amp.push_back(newpoint);
newmove = false; newmove = false;
} }
@ -1164,7 +1164,7 @@ void showMagicMenu() {
initquickqueue(); initquickqueue();
char letter = 'A'; char letter = 'A';
for(auto& am: amp) { 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); queuestr(h, vid.fsize, s0+letter, 0xC00000, 1);
/* /*
@ -1427,12 +1427,12 @@ EX void showMenu() {
typedef pair<int,int> point; typedef pair<int,int> point;
point ptc(hyperpoint h) { point ptc(shiftpoint h) {
hyperpoint inmodel = config.texture_coordinates(h); hyperpoint inmodel = config.texture_coordinates(h);
return make_pair(int(inmodel[0] * config.data.twidth), int(inmodel[1] * config.data.twidth)); return make_pair(int(inmodel[0] * config.data.twidth), int(inmodel[1] * config.data.twidth));
} }
array<point, 3> ptc(const array<hyperpoint, 3>& h) { array<point, 3> ptc(const array<shiftpoint, 3>& h) {
return make_array(ptc(h[0]), ptc(h[1]), ptc(h[2])); 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); undos.emplace_back(nullptr, 1);
} }
void filltriangle(const array<hyperpoint, 3>& v, const array<point, 3>& p, color_t col, int lev) { void filltriangle(const array<shiftpoint, 3>& v, const array<point, 3>& 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]); 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<hyperpoint, 3>& v, const array<point, 3>& p, color
else else
a = 1, b = 2, c = 0; a = 1, b = 2, c = 0;
hyperpoint v3 = mid(v[a], v[b]); shiftpoint v3 = mid(v[a], v[b]);
point p3 = ptc(v3); 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[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); 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<ld, 2>& angles, const array<hyperpoint, 2>& h, const array<point, 2>& p, color_t col, int lev) { void splitseg(const shiftmatrix& A, const array<ld, 2>& angles, const array<shiftpoint, 2>& h, const array<point, 2>& p, color_t col, int lev) {
ld newangle = (angles[0] + angles[1]) / 2; 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); auto np = ptc(nh);
filltriangle(make_array(h[0],h[1],nh), make_array(p[0],p[1],np), col, lev); 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<ld, 2>& angles, const array<hype
} }
} }
void fillcircle(hyperpoint h, color_t col) { void fillcircle(shiftpoint h, color_t col) {
transmatrix A = rgpushxto0(h); shiftmatrix A = rgpushxto0(h);
ld step = M_PI * 2/3; ld step = M_PI * 2/3;
array<hyperpoint, 3> mh = make_array(A * xpush0(mapeditor::dtwidth), A * xspinpush0(step, mapeditor::dtwidth), A * xspinpush0(-step, mapeditor::dtwidth)); array<shiftpoint, 3> mh = make_array(A * xpush0(mapeditor::dtwidth), A * xspinpush0(step, mapeditor::dtwidth), A * xspinpush0(-step, mapeditor::dtwidth));
auto mp = ptc(mh); auto mp = ptc(mh);
filltriangle(mh, mp, col, 0); filltriangle(mh, mp, col, 0);
@ -1537,36 +1537,36 @@ void fillcircle(hyperpoint h, color_t col) {
EX bool texturesym = false; EX bool texturesym = false;
void actDrawPixel(cell *c, hyperpoint h, color_t col) { void actDrawPixel(cell *c, shiftpoint h, color_t col) {
try { try {
transmatrix M = gmatrix.at(c); shiftmatrix M = gmatrix.at(c);
auto si = patterns::getpatterninfo0(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]; auto& tinf = config.texture_map[si.id];
for(auto& M2: tinf.matrices) for(int i = 0; i<c->type; i += si.symmetries) { for(auto& M2: tinf.matrices) for(int i = 0; i<c->type; 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) 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&) {} 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); config.data.pixels_to_draw.emplace_back(c, h, col);
} }
EX cell *where; EX cell *where;
EX void drawPixel(hyperpoint h, color_t col) { EX void drawPixel(shiftpoint h, color_t col) {
try { try {
again: again:
transmatrix g0 = gmatrix[where]; shiftmatrix g0 = gmatrix[where];
ld cdist0 = hdist(tC0(g0), h); ld cdist0 = hdist(tC0(g0), h);
forCellEx(c, where) forCellEx(c, where)
try { try {
transmatrix g = gmatrix[c]; shiftmatrix g = gmatrix[c];
ld cdist = hdist(tC0(g), h); ld cdist = hdist(tC0(g), h);
if(cdist < cdist0) { if(cdist < cdist0) {
cdist0 = cdist; cdist0 = cdist;
@ -1580,9 +1580,9 @@ EX void drawPixel(hyperpoint h, color_t col) {
catch(out_of_range&) {} 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) { 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(h1, h3, col, steps-1);
drawLine(h3, h2, col, steps-1); drawLine(h3, h2, col, steps-1);
} }