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), 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(!gp::on && !irr::on && !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, 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, 0); 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; qfloorinfo qfi_dc; int chasmg; void set_no_floor() { qfi.fshape = NULL; qfi.shape = NULL; } void set_floor(floorshape& sh) { qfi.fshape = &sh; qfi.shape = NULL; qfi.tinf = NULL; } void set_floor(hpcshape& sh) { qfi.shape = &sh; qfi.fshape = NULL; qfi.spin = Id; qfi.tinf = NULL; } void set_floor(const transmatrix& spin, hpcshape& sh) { qfi.shape = &sh; qfi.fshape = NULL; qfi.spin = spin; } void draw_shapevec(cell *c, const transmatrix& V, const vector &shv, int col, int prio = -1) { if(!c) queuepolyat(V, shv[0], col, prio); else if(gp::on) { int id = gp::get_plainshape_id(c); queuepolyat(V, shv[id], col, prio); } else if(irr::on) { 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 || gp::on) && ishex1(c)) queuepolyat(V * pispin, shv[0], col, prio); else if(!(S7&1) && nonbitrunc) { 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, int col, int prio = -1) { draw_shapevec(c, V, fsh.b, col, prio); } void draw_qfi(cell *c, const transmatrix& V, int col, int prio = -1, vector floorshape::* tab = &floorshape::b) { if(qfi.shape) queuepolyat(V * qfi.spin, *qfi.shape, col, prio); else if(!qfi.fshape) ; #if CAP_TEXTURE else if(qfi.tinf) { queuetable(V * qfi.spin, qfi.tinf->vertices, isize(qfi.tinf->vertices), texture::config.mesh_color, texture::config.recolor(col), prio == -1 ? PPR_FLOOR : prio); lastptd().u.poly.tinf = qfi.tinf; if(true) lastptd().u.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); } } } auto hook = addHook(hooks_args, 100, [] () { using namespace arg; if(argis("-floordebug")) { floorshape_debug = true; return 0; } else return 1; }); }