#include "rogueviz.h" /** \brief Immersed plane * * Euclidean plane immersed in various geometries. * * Compile with HyperRogue, enable a 3D geometry, and press oo to view or to change the direction. * **/ namespace rogueviz { namespace embed { ld scale = 1; color_t gridcol = 0xFFFFFFFF; hyperpoint fp(ld x, ld y) { x *= scale; y *= scale; x *= A_PI/10 * sqrt(2)/2; y *= A_PI/10 * sqrt(2)/2; if(euclid) return hyperpoint(x, y, 0, 1); if(sphere) { ld a = sqrt(2)/2; x /= a; y /= a; hyperpoint h = cspin(2, 3, -45._deg) * hyperpoint(sin(x)*a, sin(y)*a, cos(x)*a, cos(y)*a); return h; } if(hyperbolic) return cspin90(2, 0) * tC0(parabolic13(x, y)); if(nil) return hyperpoint(0, y, x, 1); if(prod) return zpush(y) * xpush0(x); if(sl2) { ld a = sqrt(2)/2; x /= a; y /= a; hyperpoint h = cspin(2, 3, -45._deg) * hyperpoint(sinh(x)*a, sinh(y)*a, cosh(x)*a, cosh(y)*a); return h; } if(sol || nih) return hyperpoint(x, y, 0, 1); return hyperpoint(x, y, 0, 1); } void embed(const transmatrix& V, ld x, ld y, ld x1, ld y1) { queueline(V* fp(x, y), V*fp(x1, y1), gridcol, 0, PPR::LINE); } void draw_grid(const transmatrix& V) { for(int x=-10; x<=10; x++) { for(int y=-10; y<10; y++) { for(int a=0; a<=10; a++) curvepoint(V * fp(x, y+a/10.)); queuecurve(gridcol, 0, PPR::LINE).flags |= POLY_FORCEWIDE | POLY_ONE_LEVEL; for(int a=0; a<=10; a++) curvepoint(V * fp(y+a/10., x)); queuecurve(gridcol, 0, PPR::LINE).flags |= POLY_FORCEWIDE | POLY_ONE_LEVEL; } } } bool draw_embed(cell *c, const transmatrix& V) { if(c == cwt.at && false) draw_grid(V); return false; } int emba; void relocate() { View = Id; NLP = Id; centerover = currentmap->gamestart(); vid.fixed_yz = false; if(nil) rotate_view(cspin90(2, 0)); if(prod) rotate_view(cspin90(1, 2)); if(emba == 1) { rotate_view(cspin(0, 1, 45._deg)); rotate_view(cspin(1, 2, 30._deg)); } if(emba == 2) { rotate_view(cspin(1, 2, 81._deg)); } for(int a=0; a<100; a++) shift_view(ztangent(scale/100)); if(scale < 0) rotate_view(diag(-1,-1,-1,1)); playermoved = false; } int part = 1; ld wider = 1.5; void draw_all() { vid.linewidth *= wider; if(1) { int id = 0; auto draw_colored = [&] (eGeometry gg, eGeometry g2, color_t col) { dynamicval g(geometry, gg); if(g2 != gNormal) { hybrid::configure(g2); geometry = g2; } // dynamicval gc(gridcol, col); dynamicval gm(pmodel, default_model()); int idx = id % 3; int idy = id / 3; id++; auto& cd = current_display; dynamicval gx1(cd->xmin, idx / 3.); dynamicval gxy(cd->ymin, idy / 3.); dynamicval gx2(cd->xmax, (idx+1) / 3.); dynamicval gy2(cd->ymax, (idy+1) / 3.); calcparam(); dynamicval gs(scale, scale); /* verification hyperpoint h1 = fp(0, 0); hyperpoint h2 = fp(1, 0); hyperpoint h3 = fp(0, 1); hyperpoint h4 = fp(1, 1); println(hlog, geometry_name(), " : ", geo_dist(h1, h2), " = ", geo_dist(h3, h4)); println(hlog, geometry_name(), " : ", geo_dist(h1, h3), " = ", geo_dist(h2, h4)); */ if(nih) scale /= log(2); relocate(); initquickqueue(); make_actual_view(); draw_grid(cview()); drawqueue(); }; draw_colored(gCell120, gNormal, 0x00FF00FF); draw_colored(gNil, gNormal, 0xFF0000FF); draw_colored(gNormal, gRotSpace, 0x0000FFFF); draw_colored(gSphere, gProduct, 0x00FF80FF); draw_colored(gNIH, gNormal, 0xFF8000FF); draw_colored(gNormal, gProduct, 0x00FFFFFF); draw_colored(gSpace534, gNormal, 0xFF0000FF); draw_colored(gSolN, gNormal, 0xFF80FFFF); draw_colored(gSol, gNormal, 0xFF00FFFF); calcparam(); //draw_colored(gCubeTiling, gNormal, 0xFFFFFFFF); relocate(); } vid.linewidth /= wider; } void show() { dialog::editNumber(scale, -2, 2, 0.1, 1, "distance", "distance"); dialog::extra_options = [] { draw_all(); dialog::addItem("direction", 'A'); dialog::add_action([] { emba ++; emba %= 3; }); }; dialog::reaction = [] { relocate(); }; } void o_key(o_funcs& v) { v.push_back(named_functionality("plane embedding", show)); } auto hchook = addHook(hooks_drawcell, 100, draw_embed) + addHook(hooks_o_key, 80, o_key) + addHook(hooks_args, 100, [] { using namespace arg; if(0) ; else if(argis("-embed-angle")) { shift(); emba = argi(); } else if(argis("-embed-video")) { start_game(); shot::transparent = 0; shot::shotx = 500; shot::shoty = 500; shift(); anims::record_video(args(), [] { for(int i=0; i<360; i++) { scale = sin((i+.5) * degree); shot::take("x", draw_all); } return true; }); } else return 1; return 0; }); } }