diff --git a/crystal.cpp b/crystal.cpp index 09d63526..e01dc2f6 100644 --- a/crystal.cpp +++ b/crystal.cpp @@ -14,6 +14,15 @@ const int MAXDIM = 7; typedef array coord; static const coord c0 = {}; +typedef array ldcoord; +static const ldcoord ldc0 = {}; + +ldcoord told(coord c) { ldcoord a; for(int i=0; i> 1)); } void resize2(vector>& v, int a, int b, int z) { @@ -22,8 +31,8 @@ void resize2(vector>& v, int a, int b, int z) { for(auto& w: v) w.resize(b, z); } -const int FULLSTEP = 16; -const int HALFSTEP = 8; +const int FULLSTEP = 2; +const int HALFSTEP = 1; struct crystal_structure { int dir; @@ -286,23 +295,21 @@ heptagon *get_heptagon_at(coord c, int deg) { h->c7 = newCell(deg, h); h->distance = 0; for(int i=0; idistance += abs(c[i]); + h->distance /= 2; hcoords[h] = c; // for(int i=0; i<6; i++) crystalstep(h, i); return h; } -coord get_coord(cell *c) { +ldcoord get_coord(cell *c) { if(c->master->c7 != c) { - coord res = c0; - for(int i=0; itype; i+=2) { - coord co = hcoords[c->move(i)->master]; - for(int d=0; dtype/2) / c->type; - return res; + ldcoord res = ldc0; + for(int i=0; itype; i+=2) + res = res + told(hcoords[c->cmove(i)->master]); + return res * 2 / c->type; } else - return hcoords[c->master]; + return told(hcoords[c->master]); } struct hrmap_crystal : hrmap { @@ -348,7 +355,7 @@ void create_step(heptagon *h, int d) { } else { auto coc = add(add(co, lw, HALFSTEP), lw+1, HALFSTEP); - auto hc = get_heptagon_at(coc, HALFSTEP); + auto hc = get_heptagon_at(coc, 8); for(int a=0; a<8; a+=2) { hc->c.connect(a, heptspin(h, lw.spin)); if(h->modmove(lw.spin-1)) { @@ -366,41 +373,12 @@ array, MAX_EDGE> distlimit_table = {{ {6, 4}, {5, 3}, {4, 3}, {4, 3}, {3, 2}, {3, 2}, {3, 2}, {3, 2}, {3, 2} }}; -int readArgs() { - using namespace arg; - - if(0) ; - else if(argis("-crystal")) { - stop_game(); - geometry = gCrystal; variation = eVariation::pure; - shift(); int N = argi(); - ginf[gCrystal].sides = N; - ginf[gCrystal].vertex = 4; - if(N < MAX_EDGE) - ginf[gCrystal].distlimit = distlimit_table[N]; - add_bitruncation = false; - } - else if(argis("-crystalb")) { - stop_game(); - geometry = gCrystal; variation = eVariation::bitruncated; - ginf[gCrystal].sides = 8; - ginf[gCrystal].vertex = 3; - ginf[gCrystal].distlimit = {7, 5}; - add_bitruncation = true; - } - else if(argis("-cview")) { - view_coordinates = true; - } - else return 1; - return 0; - } - color_t colorize(cell *c) { - coord co = get_coord(c); + ldcoord co = get_coord(c); color_t res; res = 0; for(int i=0; i<3; i++) - res |= ((i == 2 && S7 == 5) ? (co[i] ? 255 : 0) : (128 + co[i] * 3)) << (8*i); + res |= ((int)(((i == 2 && S7 == 5) ? (128 + co[i] * 50) : (128 + co[i] * 50)))) << (8*i); return res; } @@ -452,6 +430,129 @@ int distance(cell *c1, cell *c2) { } } +ld crug_rotation[MAXDIM][MAXDIM]; + +int ho = 1; + +void init_rotation() { + for(int i=0; i=1; i--) { + ld c = cos(M_PI / 2 / (i+1)); + ld s = sin(M_PI / 2 / (i+1)); + for(int j=0; jflat = coord_to_flat(co); + v->valid = true; + + rugpoint *p[MAX_EDGE]; + + for(int i=0; itype; i++) { + p[i] = addRugpoint(V * get_corner_position(c, i), 0); + p[i]->valid = true; + if(VALENCE == 4) + p[i]->flat = coord_to_flat((get_coord(c->cmove(i)) + get_coord(c->cmodmove(i-1))) / 2); + else + p[i]->flat = coord_to_flat((get_coord(c->cmove(i)) + get_coord(c->cmodmove(i-1)) + co) / 3); + } + + for(int i=0; itype; i++) addTriangle(v, p[i], p[(i+1) % c->type]); + } + } + +int readArgs() { + using namespace arg; + + if(0) ; + else if(argis("-crystal")) { + PHASE(2); + stop_game(); + geometry = gCrystal; variation = eVariation::pure; + shift(); int N = argi(); + ginf[gCrystal].sides = N; + ginf[gCrystal].vertex = 4; + if(N < MAX_EDGE) + ginf[gCrystal].distlimit = distlimit_table[N]; + add_bitruncation = false; + } + else if(argis("-crystalb")) { + PHASE(2); + stop_game(); + geometry = gCrystal; variation = eVariation::bitruncated; + ginf[gCrystal].sides = 8; + ginf[gCrystal].vertex = 3; + ginf[gCrystal].distlimit = {7, 5}; + add_bitruncation = true; + } + else if(argis("-cview")) { + view_coordinates = true; + } + else if(argis("-crug")) { + PHASE(3); + if(rug::rugged) rug::close(); + calcparam(); + rug::reopen(); + init_rotation(); + surface::sh = surface::dsCrystal; + rug::good_shape = true; + } + else return 1; + return 0; + } + auto crystalhook = addHook(hooks_args, 100, readArgs) + addHook(hooks_drawcell, 100, crystal_cell); diff --git a/hyper.h b/hyper.h index 76846734..083b0dcd 100644 --- a/hyper.h +++ b/hyper.h @@ -3447,7 +3447,7 @@ extern int ewhichscreen; #if CAP_SURFACE namespace surface { - enum eShape { dsNone, dsTractricoid, dsDini, dsKuen, dsHyperlike, dsHyperboloid, dsHemisphere }; + enum eShape { dsNone, dsTractricoid, dsDini, dsKuen, dsHyperlike, dsHyperboloid, dsHemisphere, dsCrystal }; extern eShape sh; void show_surfaces(); void run_shape(eShape); @@ -4141,6 +4141,10 @@ namespace crystal { int distance(cell *c1, cell *c2); hrmap *new_map(); void create_step(heptagon *h, int d); + void build_rugdata(); + void apply_rotation(const transmatrix t); + void switch_z_coordinate(); + void next_home_orientation(); } hyperpoint get_warp_corner(cell *c, int cid); diff --git a/rug.cpp b/rug.cpp index 257adae7..05e0f12c 100644 --- a/rug.cpp +++ b/rug.cpp @@ -14,6 +14,8 @@ bool rug_failure = false; namespace rug { +bool in_crystal() { return surface::sh == surface::dsCrystal; } + bool computed = false; vector points; @@ -1018,6 +1020,11 @@ void addNewPoints() { void physics() { + if(in_crystal()) { + crystal::build_rugdata(); + return; + } + if(good_shape) return; auto t = SDL_GetTicks(); @@ -1442,7 +1449,8 @@ ld protractor = 0; void apply_rotation(const transmatrix& t) { if(!rug_perspective) currentrot = t * currentrot; - for(auto p: points) p->flat = t * p->flat; + if(in_crystal()) crystal::apply_rotation(t); + else for(auto p: points) p->flat = t * p->flat; } void move_forward(ld distance) { @@ -1468,11 +1476,17 @@ bool handlekeys(int sym, int uni) { return true; } else if(uni == '2') { - apply_rotation(rotmatrix(M_PI, 0, 2)); + if(in_crystal()) + crystal::switch_z_coordinate(); + else + apply_rotation(rotmatrix(M_PI, 0, 2)); return true; } else if(uni == '3') { - apply_rotation(rotmatrix(M_PI/2, 0, 2)); + if(in_crystal()) + crystal::next_home_orientation(); + else + apply_rotation(rotmatrix(M_PI/2, 0, 2)); return true; } #if !CAP_HOLDKEYS @@ -1598,8 +1612,12 @@ void actDraw() { if(finger_center) perform_finger(); else { - if(keystate[SDLK_HOME]) qm++, t = inverse(currentrot); - if(keystate[SDLK_END]) qm++, t = currentrot * rotmatrix(alpha, 0, 1) * inverse(currentrot); + if(keystate[SDLK_HOME] && !in_crystal()) qm++, t = inverse(currentrot); + if(keystate[SDLK_END]) { + qm++; + if(in_crystal()) t = t * rotmatrix(alpha, 0, 1); + else t = currentrot * rotmatrix(alpha, 0, 1) * inverse(currentrot); + } if(keystate[SDLK_DOWN]) qm++, t = t * rotmatrix(alpha, 1, 2); if(keystate[SDLK_UP]) qm++, t = t * rotmatrix(alpha, 2, 1); if(keystate[SDLK_LEFT]) qm++, t = t * rotmatrix(alpha, 0, 2); diff --git a/surface.cpp b/surface.cpp index 9588b3d8..4c21f5cd 100644 --- a/surface.cpp +++ b/surface.cpp @@ -11,7 +11,7 @@ using namespace hyperpoint_vec; ld sech(ld d) { return 1 / cosh(d); } string shape_name[] = { "hypersian rug", "tractricoid", "Dini's surface", "Kuen surface", "concave barrel", - "hyperboloid", "hemisphere" }; + "hyperboloid", "hemisphere", "crystal" }; eShape sh;