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]); } #if CAP_BT 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); } #endif void bshape_regular(floorshape &fsh, int id, int sides, int shift, ld size) { fsh.b.resize(2); fsh.shadow.resize(2); #if CAP_BT 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); } } #endif 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); } } #if CAP_GP 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; } } #endif 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); #if CAP_GP else if(GOLDBERG) { int id = gp::get_plainshape_id(c); queuepolyat(V, shv[id], col, prio); } #endif #if CAP_IRR else if(IRREGULAR) { int id = irr::cellindex[c]; if(id < 0 || id >= isize(shv)) { return; } queuepolyat(V, shv[id], col, prio); } #endif #if CAP_ARCM else if(archimedean) { queuepolyat(V, shv[arcm::id_of(c->master)], col, prio); } #endif 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 #endif }