namespace hr { vector all_plain_floorshapes; vector all_escher_floorshapes; plain_floorshape shFloor, shMFloor, shMFloor2, shMFloor3, shMFloor4, shFullFloor, shBigTriangle, shTriheptaFloor, shBigHepta; escher_floorshape shStarFloor(1,2), shCloudFloor(3, 4), shCrossFloor(5, 6, 2, 54), shChargedFloor(7, 385, 1, 10), shSStarFloor(11, 12), shOverFloor(13, 15, 1, 14), shTriFloor(17, 18, 0, 385), shFeatherFloor(19, 21, 1, 20), shBarrowFloor(23, 24, 1, 25), shNewFloor(26, 27, 2, 54), shTrollFloor(28, 29), shButterflyFloor(325, 326, 1, 178), shLavaFloor(359, 360, 1, 178), shLavaSeabed(386, 387, 1, 178), shSeabed(334, 335), shCloudSeabed(336, 337), shCaveSeabed(338, 339, 2, 54), shPalaceFloor(45, 46, 0, 385), shDemonFloor(51, 50, 1, 178), shCaveFloor(52, 53, 2, 54), shDesertFloor(55, 56, 0, 4), shPowerFloor(57, 58, 0, 12), /* dragon */ shRoseFloor(174, 175, 1, 173), shSwitchFloor(377, 378, 1, 379), shTurtleFloor(176, 177, 1, 178), shRedRockFloor[3] = {{55, 56}, {55, 56}, {55, 56}}, // 1 - .1 * i shDragonFloor(181, 182, 2, 183); /* dragon */ typedef pair> matrixitem; struct mesher { eGeometry g; int sym; ld bspi; hyperpoint lcorner, rcorner, mfar[2], vfar[4]; }; mesher msh(eGeometry g, int sym, ld main, ld v0, ld v1, ld bspi, ld scale) { main *= scale; v0 *= scale; v1 *= scale; mesher m; m.sym = sym; m.bspi = bspi; dynamicval dg(geometry, g); hyperpoint rot = xpush(v0) * xspinpush0(M_PI - M_PI/sym, main); hyperpoint bnlfar = xpush(v0) * spin(M_PI) * rspintox(rot) * rspintox(rot) * rspintox(rot) * xpush0(hdist0(rot)); hyperpoint bnrfar = xpush(v0) * spin(M_PI) * spintox(rot) * spintox(rot) * spintox(rot) * xpush0(hdist0(rot)); m.lcorner = xspinpush0 (bspi-M_PI/sym, main); m.rcorner = xspinpush0 (bspi+M_PI/sym, main); m.mfar[0] = xspinpush0 (bspi, v0); m.mfar[1] = xspinpush0 (bspi, v1); m.vfar[0] = spin(bspi) * bnlfar; m.vfar[2] = spin(bspi) * bnrfar; m.vfar[1] = spin(-2*M_PI/sym) * m.vfar[2]; m.vfar[3] = spin(+2*M_PI/sym) * m.vfar[0]; return m; } struct matrixlist { mesher o, n; vector v; }; matrixitem genitem(const transmatrix& m1, const transmatrix& m2, int nsym) { matrixitem mi; mi.first = m1; for(int i=0; i lst; for(int i=0; i dg(geometry, gNormal); lst.push_back(hpxy(polydata[whereis+2*i], polydata[whereis+2*i+1])); } if(sym == 2) for(int i=qty-1; i>=0; i--) { dynamicval dg(geometry, gNormal); lst.push_back(hpxy(polydata[whereis+2*i], -polydata[whereis+2*i+1])); } hyperpoint lstmid = hpxyz(0,0,0); using namespace hyperpoint_vec; for(auto pp: lst) lstmid += pp; transmatrix T = spin(-m.o.bspi); while((spin(2*M_PI / rots) * T* lstmid)[0] < (T*lstmid)[0]) T = spin(2*M_PI / rots) * T; while((spin(-2*M_PI / rots) * T* lstmid)[0] < (T*lstmid)[0]) T = spin(-2*M_PI / rots) * T; T = spin(m.o.bspi) * T; for(auto &pp: lst) pp = T * pp; if(osym % rots && rots % osym) printf("warning: rotation oddity (shapeid %d, osym=%d rots=%d)\n", shapeid, osym, rots); if(rots > osym && rots % osym == 0) { int rep = rots / osym; int s = lst.size(); for(int i=0; i -1e-5 && z[1] > -1e-5 && z[2] > -1e-5) { nh = m.second[r] * z, mapped++; } } if(mapped == 0) printf("warning: not mapped (shapeid %d)\n", shapeid); hpcpush(mid(nh, nh)); } } hpcpush(hpc[last->s]); } void horopoint(ld y, ld x) { hpcpush(get_horopoint(y, x)); } void horopoint(ld y, ld x, cell &fc, int c) { hpcpush(iddspin(&fc, c) * get_horopoint(y, x)); } void horoline(ld y, ld x1, ld x2) { for(int a=0; a<=16; a++) horopoint(y, x1 + (x2-x1) * a / 16.); } void horoline(ld y, ld x1, ld x2, cell &fc, int c) { for(int a=0; a<=16; a++) horopoint(y, x1 + (x2-x1) * a / 16., fc, c); } void bshape_regular(floorshape &fsh, int id, int sides, int shift, ld size) { fsh.b.resize(2); fsh.shadow.resize(2); if(binarytiling) { bshape(fsh.b[id], fsh.prio); ld yx = size * log(2) / 2; ld yy = yx; ld xx = size / sqrt(2)/2; horoline(-yx, -xx, xx); horoline(yx, xx*2, -xx*2); horopoint(-yx, -xx); bshape(fsh.shadow[id], fsh.prio); horoline(-yx*SHADMUL, -xx*SHADMUL, xx*SHADMUL); horoline(yx*SHADMUL, xx*SHADMUL*2, -xx*SHADMUL*2); horopoint(-yx*SHADMUL, -xx*SHADMUL); cell fc; fc.type = 6+id; for(int k=0; k void sizeto(T& t, int n) { if(isize(t) <= n) t.resize(n+1); } // !siid equals pseudohept(c) void generate_floorshapes_for(int id, cell *c, int siid, int sidir) { for(auto pfsh: all_plain_floorshapes) { auto& fsh = *pfsh; if(STDVAR && !archimedean) { // standard and binary ld hexside = fsh.rad0, heptside = fsh.rad1; for(int k=0; k cornerlist; int cor = c->type; if(&fsh == &shTriheptaFloor) { if(!siid) { for(int i=0; itype, 3.1))); } } } else if(&fsh == &shBigTriangle) { if(!siid) { for(int i=0; itype; m.n.sym = cor; int v = sidir+siid; for(int ii=0; ii<2; ii++) { int i = 0; for(int d=0; d= 4 ? 1 : 0); else generate_floorshapes_for(i, &model, 0, 0); } } else { cell model; model.type = S6; generate_floorshapes_for(0, &model, 0, 0); model.type = S7; generate_floorshapes_for(1, &model, binarytiling ? 0 : 1, 0); } } namespace gp { int pshid[3][8][32][32][8]; int nextid; extern gp::local_info draw_li; void clear_plainshapes() { for(int m=0; m<3; m++) for(int sd=0; sd<8; sd++) for(int i=0; i<32; i++) for(int j=0; j<32; j++) for(int k=0; k<8; k++) pshid[m][sd][i][j][k] = -1; nextid = 0; } void build_plainshape(int& id, gp::local_info& li, cell *c0, int siid, int sidir) { id = nextid++; bool master = !(li.relative.first||li.relative.second); int cor = master ? S7 : SG6; if(master) li.last_dir = -1; if(debug_geometry) printf("last=%d at=%d,%d tot=%d siid=%d sidir=%d cor=%d id=%d\n", li.last_dir, li.relative.first, li.relative.second, li.total_dir, siid, sidir, cor, id); generate_floorshapes_for(id, c0, siid, sidir); finishshape(); last = NULL; extra_vertices(); } int get_plainshape_id(cell *c) { int siid, sidir; if(geosupport_threecolor() == 2) { auto si = patterns::getpatterninfo(c, patterns::PAT_COLORING, patterns::SPF_NO_SUBCODES); siid = si.id>>2; // if(siid == 2) si.dir++; // if(siid != pattern_threecolor(c)) printf("threecolor mismatch\n"); // if(pattern_threecolor(createMov(c, fixdir(si.dir, c))) != (siid+1)%3) printf("threecolor mismatch direction\n"); sidir = fixdir(si.dir, c); } else if(geosupport_football() == 2) { siid = !pseudohept(c); sidir = !ishex1(c); } else { siid = 0; sidir = 0; } auto& id = pshid[siid][sidir][draw_li.relative.first&31][draw_li.relative.second&31][fix6(draw_li.total_dir)]; if(id == -1 && sphere && isize(shFloor.b) > 0) { forCellEx(c1, c) if(!gmatrix0.count(c1)) return 0; } if(id == -1) build_plainshape(id, draw_li, c, siid, sidir); return id; } } qfloorinfo qfi; int chasmg; void set_no_floor() { qfi.fshape = NULL; qfi.shape = NULL; qfi.tinf = NULL; qfi.usershape = -1; } void set_floor(floorshape& sh) { qfi.fshape = &sh; qfi.shape = NULL; qfi.tinf = NULL; qfi.usershape = -1; } void set_floor(hpcshape& sh) { qfi.shape = &sh; qfi.fshape = NULL; qfi.spin = Id; qfi.tinf = NULL; qfi.usershape = -1; } void set_floor(const transmatrix& spin, hpcshape& sh) { qfi.shape = &sh; qfi.fshape = NULL; qfi.spin = spin; qfi.usershape = -1; } void draw_shapevec(cell *c, const transmatrix& V, const vector &shv, color_t col, PPR prio = PPR::DEFAULT) { if(!c) queuepolyat(V, shv[0], col, prio); else if(GOLDBERG) { int id = gp::get_plainshape_id(c); queuepolyat(V, shv[id], col, prio); } else if(IRREGULAR) { int id = irr::cellindex[c]; if(id < 0 || id >= isize(shv)) { return; } queuepolyat(V, shv[id], col, prio); } else if(archimedean) { queuepolyat(V, shv[arcm::id_of(c->master)], col, prio); } else if((euclid || GOLDBERG) && ishex1(c)) queuepolyat(V * pispin, shv[0], col, prio); else if(!(S7&1) && PURE) { auto si = patterns::getpatterninfo(c, patterns::PAT_COLORING, 0); if(si.id == 8) si.dir++; transmatrix D = applyPatterndir(c, si); queuepolyat(V*D, shv[pseudohept(c)], col, prio); } else if(geosupport_threecolor() == 2) queuepolyat(V, shv[pseudohept(c)], col, prio); else if(binarytiling) queuepolyat(V, shv[c->type-6], col, prio); else queuepolyat(V, shv[ctof(c)], col, prio); } void draw_floorshape(cell *c, const transmatrix& V, const floorshape &fsh, color_t col, PPR prio = PPR::DEFAULT) { draw_shapevec(c, V, fsh.b, col, prio); } void draw_qfi(cell *c, const transmatrix& V, color_t col, PPR prio = PPR::DEFAULT, vector floorshape::* tab = &floorshape::b) { if(qfi.shape) queuepolyat(V * qfi.spin, *qfi.shape, col, prio); else if(qfi.usershape >= 0) { mapeditor::drawUserShape(V * qfi.spin, mapeditor::sgFloor, qfi.usershape, col, c); } else if(!qfi.fshape) ; #if CAP_TEXTURE else if(qfi.tinf) { auto& poly = queuetable(V * qfi.spin, qfi.tinf->vertices, isize(qfi.tinf->vertices), texture::config.mesh_color, texture::config.recolor(col), prio == PPR::DEFAULT ? PPR::FLOOR : prio); poly.tinf = qfi.tinf; poly.flags = POLY_INVERSE; } #endif else draw_shapevec(c, V, (qfi.fshape->*tab), col, prio); } bool floorshape_debug; void viewmat() { if(floorshape_debug) { transmatrix V = ggmatrix(cwt.at); for(int i=0; itype; i++) { hyperpoint ci = V * get_corner_position(cwt.at, i); hyperpoint ci1 = V * get_corner_position(cwt.at, (i+1) % cwt.at->type); hyperpoint cn = V * nearcorner(cwt.at, i); hyperpoint cf0 = V * farcorner(cwt.at, i, 0); hyperpoint cf1 = V * farcorner(cwt.at, i, 1); queuestr(ci, 20, its(i), 0x0000FF, 1); if(vid.grid) queuestr(cn, 20, its(i), 0x00FF00, 1); else queuestr(gmatrix[cwt.at->move(i)] * C0, 20, its(i), 0x00FFFF, 1); queueline(V * C0, ci, 0xFFFFFFFF, 3); queueline(ci, ci1, 0xFFFF00FF, 3); queueline(ci, cn, 0xFF00FFFF, 3); queueline(ci1, cn, 0xFF0000FF, 3); queueline(ci, cf0, 0x00FFFFFF, 3); queueline(cn, cf0, 0x00FF00FF, 3); queueline(cn, cf1, 0x0000FFFF, 3); } } } #if CAP_COMMANDLINE auto floor_hook = addHook(hooks_args, 100, [] () { using namespace arg; if(argis("-floordebug")) { floorshape_debug = true; return 0; } else return 1; }); #endif }