// Hyperbolic Rogue: staircase simulation in RogueViz // Copyright (C) 2011-2018 Zeno and Tehora Rogue, see 'hyper.cpp' for details // Kohonen's self-organizing networks. // This is a part of RogueViz, not a part of HyperRogue. namespace staircase { using namespace hyperpoint_vec; ld scurvature = 0; ld acurvature = 0; ld global_r; ld szoom = 5; ld progress = 0; ld strafex, strafey; hyperpoint spcoord(hyperpoint h) { ld phi = h[0], y = h[1], z = h[2], r = global_r; dynamicval gw(geometry, rug::gwhere == gElliptic ? gSphere : rug::gwhere); hyperpoint inh = xpush(-acurvature*(y + r - frac(progress))/szoom) * spin(M_PI/2) * xpush(acurvature*z) * C0; hyperpoint i = inh * (hdist0(inh) / hypot2(inh)); ld aphi = (r+phi + floor(progress))*M_PI/6; return hpxyz(i[1] * sin(aphi), i[1] * cos(aphi), i[0]); } rug::rugpoint *pt(hyperpoint h, hyperpoint c) { auto r = rug::addRugpoint(C0, -1); r->flat = spcoord(h); r->x1 = c[0]; r->y1 = c[1]; r->valid = true; return r; } void addRect(hyperpoint h, hyperpoint hx, hyperpoint hy, hyperpoint v, hyperpoint vx, hyperpoint vy, int ix, int iy) { using namespace hyperpoint_vec; vector > rps(iy+1, vector (ix+1)); for(int y=0; y<=iy; y++) for(int x=0; x<=ix; x++) { rps[y][x] = pt(h+hx*x/ix+hy*y/iy, v+vx*x/ix+vy*y/iy); } for(int y=0; y > rps(i+1, vector (i+1)); for(int y=0; y<=i; y++) for(int x=0; x<=i; x++) { if(x+y <= i) rps[y][x] = pt(h+hx*x/i+hy*y/i, v+vx*x/i+vy*y/i); } for(int y=0; y unsigned& { return tdata.texture_pixels[y * tw + x + (k&3) * fw + (k>>2) * fw * tw]; }; for(int y=0; y -1e-6 && scurvature < 1e-6) { rug::gwhere = gEuclid; acurvature = 1; } else if(scurvature < 0) { rug::gwhere = gNormal; acurvature = -scurvature; } else { rug::gwhere = gSphere; acurvature = scurvature; } rug::ruggospeed = acurvature; stereo::ipd = 0.15 * acurvature; if(!rug::rugged || !staircase::on) { staircase::on = true; rug::reopen(); } if(need_texture) { make_texture(); rug::alternate_texture = tdata.textureid; } rug::clear_model(); printf("compute\n"); for(int r=-maxr; r 7*12) continue; if(scurvature > 1e-6 && abs(acurvature*r/szoom) > M_PI) continue; global_r = r; // step addRect(hpxyz(0,0,1), hpxyz(0,0,1), hpxyz(1,0,0), hpxy(0,0), hpxy(.25,0), hpxy(0,.25), prec, prec); // step connection addRect(hpxyz(1,0,1), hpxyz(0,0,1), hpxyz(0,1,0), hpxy(0.75,0.25), hpxy(.25,0), hpxy(0,.25), prec, prec); // triangle inner side addTri(hpxyz(1,0,1), hpxyz(0,1,0), hpxyz(-1,0,0), hpxy(.5,0), hpxy(.125,.125), hpxy(0,.125), prec); // rectangle under triangle addRect(hpxyz(0,0,1), hpxyz(1,1,0), hpxyz(0,1,0), hpxy(.5,.125), hpxy(.125,0), hpxy(0,.125), prec, prec); // barrier post addRect(hpxyz(.45,0,1.1), hpxyz(.1,.1,0), hpxyz(0,-3,0), hpxy(0,.5), hpxy(.25,0), hpxy(0,.25), 2, prec); // barrier addRect(hpxyz(.45,-3,1), hpxyz(0,0,.2), hpxyz(1,1,0), hpxy(.5,.5), hpxy(.25,0), hpxy(0,.25), 1, prec); // outer wall addRect(hpxyz(0,0,2), hpxyz(1,1,0), hpxyz(0,12,0), hpxy(.25,.25), hpxy(.25,0), hpxy(0,.25), prec, prec); // lower wall addRect(hpxyz(0,1,1), hpxyz(1,1,0), hpxyz(0,0,1), hpxy(.5,0), hpxy(.25,0), hpxy(0,.25), prec, prec); } printf("push\n"); rug::push_all_points(0, strafex * acurvature); rug::push_all_points(1, strafey * acurvature); for(auto p: rug::points) p->valid = true; rug::good_shape = true; printf("done (%d points)\n", size(rug::points)); rug::lowrug = 1e-2 * acurvature; rug::hirug = 1e3 * acurvature; } // -0.50 .. 0.16 int ctick; void check() { if(ctick && ctick < ticks) { calcparam(); make_staircase(); ctick = 0; } if(on && !rug::rugged) { on = false; rug::alternate_texture = 0; rug::no_fog = false; rug::ruggospeed = 1; staircase::on = false; } } void showMenu() { cmode = sm::SIDE; gamescreen(0); dialog::init(XLAT("Spiral Staircase"), iinf[itPalace].color, 150, 0); dialog::addSelItem(" " + XLAT("X"), fts(strafex), 'x'); dialog::addSelItem(" " + XLAT("Y"), fts(strafey), 'y'); dialog::addSelItem(" " + XLAT("curvature"), fts(scurvature), 'c'); dialog::addBreak(100); dialog::addItem(XLAT("disable menu"), SDLK_ESCAPE); dialog::addBoolItem(XLAT("low quality"), prec == 1, '1'); dialog::addBoolItem(XLAT("medium quality"), prec == 2, '2'); dialog::addBoolItem(XLAT("high quality"), prec == 4, '3'); dialog::addItem(XLAT("take me back"), 'q'); dialog::display(); keyhandler = [] (int sym, int uni) { dialog::handleNavigation(sym, uni); if(uni == 'x') { dialog::editNumber(strafex, -1, 1, .05, 1, XLAT("X"), XLAT("Also changed with keys A/D") ); dialog::reaction = [] () { ctick = ticks + 500; }; } else if(uni == 'y') { dialog::editNumber(strafey, -1, 1, .05, 1, XLAT("Y"), XLAT("Also changed with keys W/S") ); dialog::reaction = [] () { ctick = ticks + 500; }; } else if(uni == 'c') { dialog::editNumber(scurvature, -1, 1, .05, 1, XLAT("curvature"), XLAT("Also changed with keys K/L. Press G for the golden spiral") ); dialog::reaction = [] () { ctick = ticks + 500; }; } else if(uni == 'w') { strafey += .1; ctick = ticks + 200; } else if(uni == 's') { strafey -= .1; ctick = ticks + 200; } else if(uni == 'd') { strafex += .1; ctick = ticks + 200; } else if(uni == 'a') { strafex -= .1; ctick = ticks + 200; } else if(uni == 'k') { scurvature += .02; ctick = ticks + 200; } else if(uni == 'l') { scurvature -= .02; ctick = ticks + 200; } else if(uni == 'p') { progress += .1; ctick = ticks + 200; } else if(uni == 'g') { scurvature = -4 * log((sqrt(5)+1)/2) / 2.4; ctick = ticks + 200; } else if(uni == '1') { prec = 1, maxr = 100; make_staircase(); } else if(uni == '2') { prec = 2, maxr = 300; make_staircase(); } else if(uni == '3') { prec = 4, maxr = 1000; make_staircase(); } else if(uni == 'q') { ctick = 0; rug::close(); popScreen(); } else if(doexiton(sym, uni)) popScreen(); }; } #if CAP_COMMANDLINE int readArgs() { using namespace arg; // #1: load the samples if(argis("-stair")) { showstartmenu = false; ctick = ticks + 2000; pushScreen(showMenu); } else return 1; return 0; } #endif int phooks = addHook(hooks_args, 100, readArgs) + addHook(hooks_fixticks, 100, check); }