1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-27 06:27:17 +00:00

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];
}
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) {
transmatrix V1 = V * cspin(1, 2, M_PI/2);
shiftmatrix V1 = V * cspin(1, 2, M_PI/2);
ld tt = ptick(100);
for(int t=0; t<5; t++) {
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));
queuecurve(col, 0, PPR::LINE);
curvepoint(cspin(0, 2, a * M_PI/100.) * cspin(0, 1, t * 72 * degree + tt + a*2*M_PI/50.) * xpush0(rad));
queuecurve(V1, col, 0, PPR::LINE);
}
return;
}
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 == itOrbFlash) V1 = V * cspin(0, 1, ptick(1500));
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 h1 = B * xpush0(1);
for(int i=0; i<=8; i++)
curvepoint(V1 * rspintox(normalize(h0*(8-i) + h1*i)) * xpush0(rad));
queuecurve(col, 0, PPR::LINE);
curvepoint(rspintox(normalize(h0*(8-i) + h1*i)) * xpush0(rad));
queuecurve(V1, col, 0, PPR::LINE);
};
for(int i=0; i<5; i++) {
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::dtwidth = 0.02;
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;
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
}
@ -494,27 +494,27 @@ void connection_debugger() {
for(auto& p: debug_polys) {
int id = p.second;
transmatrix V = gmatrix[cwt.at] * p.first;
shiftmatrix V = gmatrix[cwt.at] * p.first;
auto& sh = debugged.shapes[id].vertices;
for(auto& v: sh)
curvepoint(V * v);
curvepoint(v);
curvepoint(V * sh[0]);
curvepoint(sh[0]);
color_t col = colortables['A'][id];
col = darkena(col, 0, 0xFF);
if(&p == &last) {
vid.linewidth *= 2;
queuecurve(0xFFFF00FF, col, PPR::LINE);
queuecurve(V, 0xFFFF00FF, col, PPR::LINE);
vid.linewidth /= 2;
for(int i=0; i<isize(sh); i++)
queuestr(V * sh[i], vid.fsize, its(i), 0xFFFFFFFF);
}
else
queuecurve(0xFFFFFFFF, col, PPR::LINE);
queuecurve(V, 0xFFFFFFFF, col, PPR::LINE);
}
quickqueue();
@ -795,22 +795,21 @@ struct hrmap_arbi : hrmap {
}
void draw() override {
dq::visited.clear();
dq::clear_all();
dq::enqueue(centerover->master, cview());
while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p);
transmatrix V = get<1>(p);
dynamicval<ld> b(band_shift, get<2>(p));
heptagon *h = p.first;
shiftmatrix V = p.second;
dq::drawqueue.pop();
if(do_draw(h->c7, V)) drawcell(h->c7, V);
else continue;
for(int i=0; i<h->type; i++) {
transmatrix V1 = V * adj(h, i);
bandfixer bf(V1);
shiftmatrix V1 = V * adj(h, i);
optimize_shift(V1);
dq::enqueue(h->move(i), V1);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,7 +12,7 @@ EX int frames;
EX bool outoffocus = false;
EX int mousex, mousey;
EX hyperpoint mouseh, mouseoh;
EX shiftpoint mouseh, mouseoh;
EX bool pandora_leftclick, pandora_rightclick;
@ -66,17 +66,17 @@ EX int lastt;
EX bool mouseout() {
if((getcstat != '-' && getcstat) || (lgetcstat && lgetcstat != '-')) return true;
return outofmap(mouseh);
return outofmap(mouseh.h);
}
EX bool mouseout2() {
if((getcstat && getcstat != '-') || (lgetcstat && lgetcstat != '-')) return true;
return outofmap(mouseh) || outofmap(mouseoh);
return outofmap(mouseh.h) || outofmap(mouseoh.h);
}
EX movedir vectodir(hyperpoint P) {
transmatrix U = ggmatrix(cwt.at);
transmatrix U = unshift(ggmatrix(cwt.at));
if(GDIM == 3 && WDIM == 2) U = radar_transform * U;
P = direct_exp(lp_iapply(P));
@ -137,18 +137,18 @@ EX void movepckeydir(int d) {
EX void calcMousedest() {
if(mouseout()) return;
if(vid.revcontrol == true) { mouseh[0] = -mouseh[0]; mouseh[1] = -mouseh[1]; }
ld mousedist = intval(mouseh, tC0(ggmatrix(cwt.at)));
ld mousedist = hdist(mouseh, tC0(ggmatrix(cwt.at)));
mousedest.d = -1;
cellwalker bcwt = cwt;
vector<ld> dists(cwt.at->type);
transmatrix U = ggmatrix(cwt.at);
shiftmatrix U = ggmatrix(cwt.at);
for(int i=0; i<cwt.at->type; 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) {
@ -331,9 +331,9 @@ EX void full_rotate_camera(int dir, ld val) {
transmatrix T2 = eupush( tC0(inverse(View)) );
transmatrix nlp = View * T2;
auto rV = inverse(nlp) * View;
h = nlp * inverse_exp(tC0(rV));
h = nlp * inverse_exp(shiftless(tC0(rV)));
}
else h = inverse_exp(tC0(View));
else h = inverse_exp(shiftless(tC0(View)));
shift_view(-h);
rotate_view(cspin(dir, 2, val));
shift_view(h);
@ -1087,7 +1087,7 @@ EX bool gmodekeys(int sym, int uni) {
ld maxs = 0;
auto& cd = current_display;
for(auto& p: gmatrix) for(int i=0; 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;
applymodel(h, onscreen);
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);
dq::visited_by_matrix.clear();
dq::clear_all();
dq::enqueue_by_matrix(centerover->master, cview());
while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p);
transmatrix V = get<1>(p);
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
heptagon *h = p.first;
shiftmatrix V = p.second;
dq::drawqueue.pop();
cell *c = h->c7;
@ -694,7 +692,7 @@ struct hrmap_crystal : hrmap_standard {
if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000) continue;
for(int d=0; 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;
for(int i=0; i<S7; i++) if(h2 == h1->move(i)) return adj(h1->master, i);
if(gmatrix0.count(h2) && gmatrix0.count(h1))
return inverse(gmatrix0[h1]) * gmatrix0[h2];
return inverse_shift(gmatrix0[h1], gmatrix0[h2]);
println(hlog, "unknown relmatrix, distance = ", celldistance(h1, h2));
return xpush(999);
}
@ -828,7 +826,7 @@ EX ld compass_angle() {
return (bitr ? M_PI/8 : 0) - master_to_c7_angle();
}
EX bool crystal_cell(cell *c, transmatrix V) {
EX bool crystal_cell(cell *c, shiftmatrix V) {
if(!cryst) return false;
@ -846,7 +844,7 @@ EX bool crystal_cell(cell *c, transmatrix V) {
ld dist = cellgfxdist(c, 0);
for(int i=0; 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 lw = m->makewalker(co, i);
@ -1239,8 +1237,8 @@ void cut_triangle2(const hyperpoint pa, const hyperpoint pb, const hyperpoint pc
pac[3] = pbc[3] = 1;
rug::rugpoint *rac = rug::addRugpoint(hac, 0);
rug::rugpoint *rbc = rug::addRugpoint(hbc, 0);
rug::rugpoint *rac = rug::addRugpoint(shiftless(hac), 0);
rug::rugpoint *rbc = rug::addRugpoint(shiftless(hbc), 0);
rac->native = pac;
rbc->native = pbc;
rac->valid = true;
@ -1268,7 +1266,7 @@ EX void build_rugdata() {
cell *c = gp.first;
if(c->wall == waInvisibleFloor) continue;
const transmatrix& V = gp.second;
const shiftmatrix& V = gp.second;
auto co = m->get_coord(c);
vector<ldcoord> vcoord(c->type);
@ -1307,7 +1305,7 @@ EX void build_rugdata() {
for(int i=0; i<c->type; i++) {
int j = (i+1) % c->type;
if((vco[i][3] >= 0) != (hco[3] >= 0) || (vco[j][3] >= 0) != (hco[3] >= 0)) {
cut_triangle(hco, vco[i], vco[j], tC0(V), V * get_corner_position(c, i), V * get_corner_position(c, j));
cut_triangle(hco, vco[i], vco[j], unshift(tC0(V)), unshift(V * get_corner_position(c, i)), unshift(V * get_corner_position(c, j)));
}
}
}

View File

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

View File

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

View File

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

View File

@ -938,7 +938,7 @@ EX int shvid(cell *c) {
return ctof(c);
}
EX struct dqi_poly *draw_shapevec(cell *c, const transmatrix& V, const vector<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(!c) return &queuepolyat(V, shv[0], col, prio);
else if(WDIM == 3) return NULL;
@ -975,12 +975,12 @@ EX struct dqi_poly *draw_shapevec(cell *c, const transmatrix& V, const vector<hp
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;
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(qfi.shape)
queuepolyat(V * qfi.spin, *qfi.shape, col, prio);
@ -1002,15 +1002,15 @@ EX void draw_qfi(cell *c, const transmatrix& V, color_t col, PPR prio IS(PPR::DE
EX bool floorshape_debug;
EX void viewmat() {
if(floorshape_debug) {
transmatrix V = ggmatrix(cwt.at);
shiftmatrix V = ggmatrix(cwt.at);
for(int i=0; i<cwt.at->type; i++) {
hyperpoint ci = V * get_corner_position(cwt.at, i);
hyperpoint ci1 = V * get_corner_position(cwt.at, (i+1) % cwt.at->type);
shiftpoint ci = V * get_corner_position(cwt.at, i);
shiftpoint ci1 = V * get_corner_position(cwt.at, (i+1) % cwt.at->type);
hyperpoint cn = V * nearcorner(cwt.at, i);
hyperpoint cf0 = V * farcorner(cwt.at, i, 0);
hyperpoint cf1 = V * farcorner(cwt.at, i, 1);
shiftpoint cn = V * nearcorner(cwt.at, i);
shiftpoint cf0 = V * farcorner(cwt.at, i, 0);
shiftpoint cf1 = V * farcorner(cwt.at, i, 1);
queuestr(ci, 20, its(i), 0x0000FF, 1);
if(vid.grid)
queuestr(cn, 20, its(i), 0x00FF00, 1);
@ -1065,17 +1065,17 @@ void draw_shape_for_texture(floorshape* sh) {
curvepoint(eupush(gx-s1, gy+s1) * C0);
curvepoint(eupush(gx-s1, gy-s1) * C0);
curvepoint(eupush(gx+s1, gy-s1) * C0);
queuecurve(0x000000FF, 0xFFFFFFFF - 0x1010100 * (sh->pstrength * 24/10), PPR::LAKELEV);
queuecurve(shiftless(Id), 0x000000FF, 0xFFFFFFFF - 0x1010100 * (sh->pstrength * 24/10), PPR::LAKELEV);
}
poly_outline = 0xFFFFFFFF - 0x1010100 * (sh->pstrength * 3/2);
for(int a=-1; a<=1; a++)
for(int b=-1; b<=1; b++)
queuepoly(eupush(gx+a, gy+b), sh->b[0], 0xFFFFFFFF);
queuepoly(shiftless(eupush(gx+a, gy+b)), sh->b[0], 0xFFFFFFFF);
if(sh == &cgi.shCrossFloor) {
queuepoly(eupush(gx, gy) * spin(M_PI/4), cgi.shCross, 0x808080FF);
queuepoly(shiftless(eupush(gx, gy) * spin(M_PI/4)), cgi.shCross, 0x808080FF);
}
if(1) {
@ -1085,7 +1085,7 @@ void draw_shape_for_texture(floorshape* sh) {
curvepoint(eupush(gx-sd, gy+sd) * C0);
curvepoint(eupush(gx-sd, gy-sd) * C0);
curvepoint(eupush(gx+sd, gy-sd) * C0);
queuecurve(0x40404000 + sh->fstrength * 192/10, 0, PPR::LINE);
queuecurve(shiftless(Id), 0x40404000 + sh->fstrength * 192/10, 0, PPR::LINE);
}
auto& ftv = floor_texture_vertices[sh->id];
@ -1098,11 +1098,11 @@ void draw_shape_for_texture(floorshape* sh) {
if(1) {
hyperpoint inmodel;
applymodel(center, inmodel);
applymodel(shiftless(center), inmodel);
glvertex tmap;
tmap[0] = (1 + inmodel[0] * pconf.scale) / 2;
tmap[1] = (1 - inmodel[1] * pconf.scale) / 2;
applymodel(center + v1, inmodel);
applymodel(shiftless(center + v1), inmodel);
tmap[2] = (1 + inmodel[0] * pconf.scale) / 2 - tmap[0];
floor_texture_map[sh->id] = tmap;
}
@ -1110,7 +1110,7 @@ void draw_shape_for_texture(floorshape* sh) {
auto tvec_at = [&] (ld x, ld y) {
hyperpoint h = center + v1 * x + v2 * y;
hyperpoint inmodel;
applymodel(h, inmodel);
applymodel(shiftless(h), inmodel);
glvec2 v;
v[0] = (1 + inmodel[0] * pconf.scale) / 2;
v[1] = (1 - inmodel[1] * pconf.scale) / 2;
@ -1193,7 +1193,7 @@ void geometry_information::make_floor_textures_here() {
if(1) {
current_display->next_shader_flags = GF_VARCOLOR;
dynamicval<eModel> m(pmodel, mdPixel);
current_display->set_all(0);
current_display->set_all(0,0);
glhr::new_projection();
glhr::id_modelview();
glhr::prepare(gv);

View File

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

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) {
current_display->next_shader_flags = GF_TEXTURE;
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);
}

View File

@ -1234,10 +1234,8 @@ EX namespace gp {
while(!dq::drawqueue_c.empty()) {
auto& p = dq::drawqueue_c.front();
cell *c = get<0>(p);
transmatrix V = get<1>(p);
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
cell *c = p.first;
shiftmatrix V = p.second;
auto c1 = get_mapped(c, 0);
in_underlying([&] {
@ -1257,7 +1255,7 @@ EX namespace gp {
drawcell(c, V);
for(int i=0; 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->base = first_center_at;
v.push_back(m);
create(first_center_at, centerover, inverse(ggmatrix(centerover)));
create(first_center_at, centerover, inverse(unshift(ggmatrix(centerover))));
if(on) saved_ends = 2;
return;
}
@ -301,7 +301,7 @@ EX namespace history {
EX void create_recenter_to_view(bool precise) {
cell *c = centerover ? centerover : cwt.at;
create(path_for_lineanimation[0], c, precise ? inverse(ggmatrix(c)) : Id);
create(path_for_lineanimation[0], c, precise ? inverse(unshift(ggmatrix(c))) : Id);
}
EX void movetophase() {
@ -374,7 +374,7 @@ EX namespace history {
v[j+1]->at * C0;
hyperpoint nextscr;
applymodel(next, nextscr);
applymodel(shiftless(next), nextscr);
tpixels += nextscr[0] * r;
if(j == 0 || j == siz-2)
@ -452,7 +452,7 @@ EX namespace history {
drawfullmap();
if(last_base) {
hyperpoint last = ggmatrix(last_base) * last_relative;
shiftpoint last = ggmatrix(last_base) * last_relative;
hyperpoint hscr;
applymodel(last, hscr);
ld bwidth = -current_display->radius * hscr[0];

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

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 */
constexpr transmatrix diag(ld a, ld b, ld c, ld d) {
#if MAXMDIM==3
@ -324,7 +363,7 @@ EX ld atan2_auto(ld y, ld x) {
case gcHyperbolic: return atanh(y/x);
case gcSL2: return atanh(y/x);
case gcSphere: return atan2(y, x);
case gcProduct: return PIU(atan2_auto(y, x));
case gcProduct: return PIU(atan2_auto(y, x));
default: return y/x;
}
}
@ -480,6 +519,10 @@ EX hyperpoint mid(const hyperpoint& H1, const hyperpoint& H2) {
return normalize(H1 + H2);
}
EX shiftpoint mid(const shiftpoint& H1, const shiftpoint& H2) {
return shiftless(mid(H1.h, H2.h), (H1.shift + H2.shift)/2);
}
/** like mid, but take 3D into account */
EX hyperpoint midz(const hyperpoint& H1, const hyperpoint& H2) {
if(prod) return mid(H1, H2);
@ -786,6 +829,10 @@ EX transmatrix rgpushxto0(const hyperpoint& H) {
return ggpushxto0(H, 1);
}
EX shiftmatrix rgpushxto0(const shiftpoint& H) {
return shiftless(rgpushxto0(H.h), H.shift);
}
/** \brief Fix the numerical inaccuracies in the isometry T
*
* The nature of hyperbolic geometry makes the computations numerically unstable.
@ -955,6 +1002,10 @@ EX ld hdist0(const hyperpoint& mh) {
}
}
EX ld hdist0(const shiftpoint& mh) {
return hdist0(unshift(mh));
}
/** length of a circle of radius r */
EX ld circlelength(ld r) {
switch(cgclass) {
@ -994,6 +1045,10 @@ EX ld hdist(const hyperpoint& h1, const hyperpoint& h2) {
}
}
EX ld hdist(const shiftpoint& h1, const shiftpoint& h2) {
return hdist(h1.h, unshift(h2, h1.shift));
}
EX hyperpoint mscale(const hyperpoint& t, double fac) {
if(GDIM == 3 && !prod) return cpush(2, fac) * t;
if(prod) fac = exp(fac);
@ -1003,6 +1058,10 @@ EX hyperpoint mscale(const hyperpoint& t, double fac) {
return res;
}
EX shiftpoint mscale(const shiftpoint& t, double fac) {
return shiftless(mscale(t.h, fac), t.shift);
}
EX transmatrix mscale(const transmatrix& t, double fac) {
if(GDIM == 3 && !prod) {
// if(pmodel == mdFlatten) { transmatrix u = t; u[2][LDIM] -= fac; return u; }
@ -1015,6 +1074,10 @@ EX transmatrix mscale(const transmatrix& t, double fac) {
return res;
}
EX shiftmatrix mscale(const shiftmatrix& t, double fac) {
return shiftless(mscale(t.T, fac), t.shift);
}
EX transmatrix xyscale(const transmatrix& t, double fac) {
transmatrix res;
for(int i=0; i<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;
}
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) {
if(GDIM == 3) return t * cpush(2, fac);
// take only the spin
@ -1045,6 +1112,10 @@ EX transmatrix mzscale(const transmatrix& t, double fac) {
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) {
return mid(h1+h2+h3, h1+h2+h3);
}
@ -1134,6 +1205,10 @@ EX transmatrix spin_towards(const transmatrix Position, transmatrix& ori, const
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) {
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];
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
/** tangent vector in the given direction */
@ -1235,18 +1316,18 @@ constexpr flagtype pNORMAL = 0;
#endif
/** 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(sn::in()) {
if(nih)
return sn::get_inverse_exp_nsym(h, prec);
return sn::get_inverse_exp_nsym(h.h, prec);
else
return sn::get_inverse_exp_symsol(h, prec);
return sn::get_inverse_exp_symsol(h.h, prec);
}
#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(prod) return product::inverse_exp(h);
if(prod) return product::inverse_exp(h.h);
ld d = acos_auto_clamp(h[GDIM]);
hyperpoint v = Hypc;
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)) {
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)) {

View File

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

View File

@ -536,7 +536,7 @@ EX namespace inv {
if(gg) {
initquickqueue();
transmatrix V = atscreenpos(px, py, rad*2);
drawItemType(o, NULL, V, icol, ticks/3 + i * 137, false);
drawItemType(o, NULL, shiftless(V), icol, ticks/3 + i * 137, false);
quickqueue();
}

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

View File

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

View File

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

View File

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

View File

@ -264,7 +264,7 @@ EX namespace netgen {
color_t& hqpixel(hyperpoint h) {
int hx, hy, hs;
getcoord0(h, hx, hy, hs);
getcoord0(shiftless(h), hx, hy, hs);
return qpixel(hqsurface, hx, hy);
}
@ -657,7 +657,7 @@ EX namespace netgen {
nei[i][e] >= 0 ? 0x808080 :
0xC0C0C0;
queueline(hvec(i, (e+ofs)%t), hvec(i, (e+1+ofs)%t), (col << 8) + 0xFF, 3);
queueline(shiftless(hvec(i, (e+ofs)%t)), shiftless(hvec(i, (e+1+ofs)%t)), (col << 8) + 0xFF, 3);
}
}
quickqueue();

View File

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

View File

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

View File

@ -2541,12 +2541,12 @@ EX namespace linepatterns {
return col;
}
void gridlinef(const transmatrix& V1, const hyperpoint& h1, const transmatrix& V2, const hyperpoint& h2, color_t col, int par) {
void gridlinef(const shiftmatrix& V1, const hyperpoint& h1, const shiftmatrix& V2, const hyperpoint& h2, color_t col, int par) {
if(!elliptic)
gridline(V1, h1, V2, h2, col, par);
else {
hyperpoint vh1 = V1 * h1;
hyperpoint vh2 = V2 * h2;
hyperpoint vh1 = V1.T * h1;
hyperpoint vh2 = unshift(V2, V1.shift) * h2;
ld cros = vh1[0]*vh2[0] + vh1[1]*vh2[1] + vh1[2]*vh2[2];
if(cros > 0)
gridline(V1, h1, V2, h2, col, par),
@ -2557,13 +2557,13 @@ EX namespace linepatterns {
}
}
void gridlinef(const transmatrix& V, const hyperpoint& h1, const hyperpoint& h2, color_t col, int par) { gridlinef(V, h1, V, h2, col, par); }
void gridlinef(const shiftmatrix& V, const hyperpoint& h1, const hyperpoint& h2, color_t col, int par) { gridlinef(V, h1, V, h2, col, par); }
#define ALLCELLS(R) \
[] (linepattern *lp) { auto& col = lp->color; for(auto& p: current_display->all_drawn_copies) for(auto& V: p.second) { cell *c = p.first; R } }
#define ATCENTER(T) \
[] (linepattern *lp) { auto& col = lp->color; transmatrix V = gmatrix[cwt.at]; T}
[] (linepattern *lp) { auto& col = lp->color; shiftmatrix V = gmatrix[cwt.at]; T}
linepattern patDual("dual grid", 0xFFFFFF00, always_available,
ALLCELLS(
@ -2631,7 +2631,7 @@ EX namespace linepatterns {
cell *c2 = c->master->cmove(dir)->c7;
if(gmatrix.count(c2)) {
if(S3 >= OINF)
gridlinef(V, C0, Id, mid(tC0(V), tC0(V * currentmap->adj(c, dir))), col, 2 + vid.linequality);
gridlinef(V, C0, V, mid(C0, tC0(currentmap->adj(c, dir))), col, 2 + vid.linequality);
else
gridlinef(V, C0, V * master_relative(c, true) * currentmap->adj(c->master, dir), C0, col, 2 + vid.linequality);
}
@ -2648,7 +2648,7 @@ EX namespace linepatterns {
cell *c2 = c->master->move(i)->c7;
if(gmatrix.count(c2)) {
if(S3 >= OINF) {
gridlinef(V, C0, Id, mid(tC0(V), tC0(gmatrix[c2])), col, 2 + vid.linequality);
gridlinef(V, C0, V, mid(C0, tC0(inverse_shift(V, gmatrix[c2]))), col, 2 + vid.linequality);
}
else
gridlinef(V, C0, V*master_relative(c, true) * currentmap->adj(c->master,i), C0, col, 2 + vid.linequality);
@ -2674,7 +2674,7 @@ EX namespace linepatterns {
ALLCELLS(
if(zebra40(c) / 4 == 10) {
bool all = true;
transmatrix tri[3];
shiftmatrix tri[3];
for(int i=0; i<3; i++)
tri[i] = V * currentmap->adj(c, i*2);
@ -2821,7 +2821,7 @@ EX namespace linepatterns {
for(int j=0; j<360; j+=15) {
for(int k=0; k<=15; k++)
curvepoint(xspinpush0((j+k) * degree, i * degree));
queuecurve(col, 0, PPR::LINE).V=V;
queuecurve(shiftless(Id), col, 0, PPR::LINE).V=V;
}
}
)
@ -2833,7 +2833,7 @@ EX namespace linepatterns {
for(int j=0; j<180; j+=15) {
for(int k=0; k<=15; k++)
curvepoint(xspinpush0(i * degree, (j+k) * degree));
queuecurve(col, 0, PPR::LINE).V=V;
queuecurve(shiftless(Id), col, 0, PPR::LINE).V=V;
}
}
)
@ -2843,8 +2843,8 @@ EX namespace linepatterns {
for(int j=-180; j<=180; j+=15) {
for(int i=-90; i<90; i+=15) {
for(int k=0; k<=15; k++)
curvepoint(V * xpush(j * degree) * ypush0((i+k) * degree));
queuecurve(col, 0, PPR::LINE).V=V;
curvepoint(xpush(j * degree) * ypush0((i+k) * degree));
queuecurve(V, col, 0, PPR::LINE).V=V;
}
}
)
@ -2854,8 +2854,8 @@ EX namespace linepatterns {
for(int i=-90; i<=90; i += 15) {
for(int j=-180; j<180; j+=15) {
for(int k=0; k<=15; k++)
curvepoint(V * xpush((j+k) * degree) * ypush0(i * degree));
queuecurve(col, 0, PPR::LINE).V=V;
curvepoint(xpush((j+k) * degree) * ypush0(i * degree));
queuecurve(V, col, 0, PPR::LINE).V=V;
}
}
)

View File

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

View File

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

View File

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

View File

@ -321,15 +321,13 @@ EX namespace reg3 {
// 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());
while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p);
transmatrix V = get<1>(p);
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
heptagon *h = p.first;
shiftmatrix V = p.second;
dq::drawqueue.pop();
cell *c = h->c7;
@ -339,10 +337,10 @@ EX namespace reg3 {
if(ultra_mirror_in())
for(auto& T: cgi.ultra_mirrors)
dq::enqueue_by_matrix(h, V * T);
dq::enqueue_by_matrix(h, optimized_shift(V * T));
for(int d=0; 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()) {
auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p);
transmatrix V = get<1>(p);
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
heptagon *h = p.first;
shiftmatrix V = p.second;
dq::drawqueue.pop();
@ -945,10 +941,10 @@ EX namespace reg3 {
if(ultra_mirror_in())
for(auto& T: cgi.ultra_mirrors)
dq::enqueue_by_matrix(h, V * T);
dq::enqueue_by_matrix(h, optimized_shift(V * T));
for(int i=0; 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);
dq::visited.clear();
dq::clear_all();
dq::enqueue(centerover->master, cview());
while(!dq::drawqueue.empty()) {
auto& p = dq::drawqueue.front();
heptagon *h = get<0>(p);
transmatrix V = get<1>(p);
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
heptagon *h = p.first;
shiftmatrix V = p.second;
dq::drawqueue.pop();
@ -1291,7 +1285,7 @@ EX namespace reg3 {
if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000) continue;
for(int i=0; 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 inqueue;
double dist;
hyperpoint h; // point in the represented space
shiftpoint h; // point in the represented space
hyperpoint native; // point in the native space
hyperpoint precompute;
vector<edge> edges;
@ -164,7 +164,7 @@ bool rug_hyperbolic() { USING_NATIVE_GEOMETRY; return hyperbolic; }
bool rug_sphere() { USING_NATIVE_GEOMETRY; return sphere; }
bool rug_elliptic() { USING_NATIVE_GEOMETRY; return elliptic; }
EX rugpoint *addRugpoint(hyperpoint h, double dist) {
EX rugpoint *addRugpoint(shiftpoint h, double dist) {
rugpoint *m = new rugpoint;
m->h = h;
@ -218,12 +218,12 @@ EX rugpoint *addRugpoint(hyperpoint h, double dist) {
}
else
scale = 1;
m->native = h * scale;
m->native = unshift(h) * scale;
m->native = hpxy3(m->native[0], m->native[1], m->native[2]);
}
else if(euclid && rug_euclid()) {
m->native = h * modelscale;
m->native = unshift(h) * modelscale;
m->native[2] = 0;
#if MAXMDIM >= 4
m->native[3] = 1;
@ -247,11 +247,11 @@ EX rugpoint *addRugpoint(hyperpoint h, double dist) {
USING_NATIVE_GEOMETRY;
m->native = rgpushxto0(h) * cpush0(2, r);
m->native = rgpushxto0(unshift(h)) * cpush0(2, r);
}
else {
m->native = h;
m->native = unshift(h);
ld hd = h[LDIM];
for(int d=GDIM; d<MAXMDIM-1; d++) {
m->native[d] = (hd - .99) * (rand() % 1000 - rand() % 1000) / 1000;
@ -269,14 +269,14 @@ EX rugpoint *addRugpoint(hyperpoint h, double dist) {
return m;
}
EX rugpoint *findRugpoint(hyperpoint h) {
EX rugpoint *findRugpoint(shiftpoint h) {
USING_NATIVE_GEOMETRY;
for(int i=0; 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;
}
EX rugpoint *findOrAddRugpoint(hyperpoint h, double dist) {
EX rugpoint *findOrAddRugpoint(shiftpoint h, double dist) {
rugpoint *r = findRugpoint(h);
return r ? r : addRugpoint(h, dist);
}
@ -342,7 +342,7 @@ EX void sort_rug_points() {
void calcLengths() {
for(auto p: points)
for(auto& edge: p->edges)
edge.len = geo_dist_q(p->h, edge.target->h) * modelscale;
edge.len = geo_dist_q(p->h.h, unshift(edge.target->h, p->h.shift)) * modelscale;
}
EX void calcparam_rug() {
@ -396,9 +396,9 @@ EX void buildTorusRug() {
println(hlog, "mx = ", mx);
auto addToruspoint = [&] (hyperpoint h) {
auto r = addRugpoint(C0, 0);
auto r = addRugpoint(shiftless(C0), 0);
hyperpoint onscreen;
hyperpoint h1 = gmatrix[gs] * T * h;
shiftpoint h1 = gmatrix[gs] * T * h;
applymodel(h1, onscreen);
r->x1 = onscreen[0];
r->y1 = onscreen[1];
@ -539,7 +539,7 @@ EX void buildRug() {
for(int j=0; j<c->type; j++) addTriangle(v, p[j], p[(j+1) % c->type]);
if((euclid && quotient) && nonorientable) {
transmatrix T = ggmatrix(c) * eumove(euc::eu.user_axes[1]);
shiftmatrix T = ggmatrix(c) * eumove(euc::eu.user_axes[1]);
rugpoint *Tv = addRugpoint(T * C0, 0);
for(int j=0; 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]);
@ -625,7 +625,7 @@ bool force(rugpoint& m1, rugpoint& m2, double rd, bool is_anticusp=false, double
double forcev = (t - rd) / 2; // 20.0;
transmatrix T = inverse(rgpushxto0(m1.native));
hyperpoint ie = inverse_exp(T * m2.native);
hyperpoint ie = inverse_exp(shiftless(T * m2.native));
transmatrix iT = rgpushxto0(m1.native);
@ -1041,7 +1041,7 @@ EX void prepareTexture() {
queueline(tC0(ggmatrix(playerpos(i))), mouseh, 0xFF00FF, 8 + vid.linequality);
}
if(finger_center) {
transmatrix V = rgpushxto0(finger_center->h);
shiftmatrix V = rgpushxto0(finger_center->h);
queuestr(V, 0.5, "X", 0xFFFFFFFF, 2);
for(int i=0; i<72; i++)
queueline(V * xspinpush0(i*M_PI/32, finger_range), V * xspinpush0((i+1)*M_PI/32, finger_range), 0xFFFFFFFF, vid.linequality);
@ -1081,15 +1081,15 @@ EX void drawRugScene() {
for(auto t: triangles) drawTriangle(t);
auto& rug = queuecurve(0, 0xFFFFFFFF, PPR::LINE);
auto& rug = queuecurve(shiftless(Id), 0, 0xFFFFFFFF, PPR::LINE);
if(nonisotropic) {
transmatrix T2 = eupush( tC0(inverse(rugView)) );
NLP = rugView * T2;
rug.V = inverse(NLP) * rugView;
rug.V = shiftless(inverse(NLP) * rugView);
}
else {
rug.V = rugView;
rug.V = shiftless(rugView);
}
rug.offset_texture = 0;
@ -1322,7 +1322,7 @@ int besti;
static const ld RADAR_INF = 1e12;
ld radar_distance = RADAR_INF;
EX hyperpoint gethyper(ld x, ld y) {
EX shiftpoint gethyper(ld x, ld y) {
projection_configuration bak = pconf;
pconf = rconf;
@ -1359,9 +1359,9 @@ EX hyperpoint gethyper(ld x, ld y) {
if(sp == 1 || sp == 2) continue;
}
applymodel(inverse(NLP) * rugView * r0->native, p0);
applymodel(inverse(NLP) * rugView * r1->native, p1);
applymodel(inverse(NLP) * rugView * r2->native, p2);
applymodel(shiftless(inverse(NLP) * rugView * r0->native), p0);
applymodel(shiftless(inverse(NLP) * rugView * r1->native), p1);
applymodel(shiftless(inverse(NLP) * rugView * r2->native), p2);
}
if(error || spherepoints == 1 || spherepoints == 2) continue;
@ -1390,13 +1390,13 @@ EX hyperpoint gethyper(ld x, ld y) {
}
pconf = bak;
if(!found) return Hypc;
if(!found) return shiftless(Hypc);
double px = rx1 * TEXTURESIZE, py = (1-ry1) * TEXTURESIZE;
calcparam_rug();
models::configure();
hyperpoint h = hr::gethyper(px, py);
shiftpoint h = hr::gethyper(px, py);
calcparam();
return h;

View File

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

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

207
shmup.cpp
View File

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

13
sky.cpp
View File

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

View File

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

View File

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

View File

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