mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-27 18:40:35 +00:00
229 lines
5.2 KiB
C++
229 lines
5.2 KiB
C++
|
#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 *= M_PI/10 * sqrt(2)/2;
|
||
|
y *= M_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, -M_PI/4) * hyperpoint(sin(x)*a, sin(y)*a, cos(x)*a, cos(y)*a);
|
||
|
return h;
|
||
|
}
|
||
|
|
||
|
if(hyperbolic)
|
||
|
return cspin(0, 2, -M_PI/2) * 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, -M_PI/4) * 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(cspin(2, 0, M_PI/2));
|
||
|
if(prod) rotate_view(cspin(1, 2, M_PI/2));
|
||
|
|
||
|
if(emba == 1) {
|
||
|
rotate_view(cspin(0, 1, M_PI/4));
|
||
|
rotate_view(cspin(1, 2, M_PI/6));
|
||
|
}
|
||
|
|
||
|
if(emba == 2) {
|
||
|
rotate_view(cspin(1, 2, M_PI/2 * .9));
|
||
|
}
|
||
|
|
||
|
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<eGeometry> g(geometry, gg);
|
||
|
if(g2 != gNormal) {
|
||
|
hybrid::configure(g2);
|
||
|
geometry = g2;
|
||
|
}
|
||
|
// dynamicval<color_t> gc(gridcol, col);
|
||
|
dynamicval<eModel> gm(pmodel, default_model());
|
||
|
int idx = id % 3;
|
||
|
int idy = id / 3;
|
||
|
id++;
|
||
|
auto& cd = current_display;
|
||
|
dynamicval<ld> gx1(cd->xmin, idx / 3.);
|
||
|
dynamicval<ld> gxy(cd->ymin, idy / 3.);
|
||
|
dynamicval<ld> gx2(cd->xmax, (idx+1) / 3.);
|
||
|
dynamicval<ld> gy2(cd->ymax, (idy+1) / 3.);
|
||
|
calcparam();
|
||
|
dynamicval<ld> 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;
|
||
|
});
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|