1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-07 22:49:54 +00:00
hyperrogue/rogueviz/embedded-chess.cpp
2023-05-15 02:50:41 +02:00

1876 lines
65 KiB
C++

#include "rogueviz.h"
// for this video: https://youtu.be/Rhjv_PazzZE
namespace hr {
/** load Chess? */
EX bool with_chess = false;
/** load other models? */
EX bool with_models = false;
/** including the CGtrader models? (not included here) */
EX bool cgtrader_models = false;
/** floor disabled */
EX bool no_floor = false;
/** do not include the models inside the house for faster transition */
EX bool light_models = false;
/** higher periods needs to be set to display scaffold correctly */
int periods = 1;
/** how many chess moves performed */
int chess_moves = 0;
namespace smoothcam {
using namespace rogueviz::smoothcam;
}
vector<pair<hyperpoint, hyperpoint>> map54_edges;
vector<hyperpoint> map54_nodes;
vector<pair<hyperpoint, hyperpoint>> map534_edges;
vector<hyperpoint> map534_nodes;
struct embset {
string name;
geom3::eSpatialEmbedding se;
ld walls, scale, depth, eye, sun, sky, star;
};
embset current() {
embset e;
e.name = "current";
e.se = geom3::spatial_embedding;
e.scale = geom3::euclid_embed_scale;
auto actscale = e.scale;
if(e.se == geom3::seDefault) { e.scale = 0; actscale = 1; }
e.walls = vid.wall_height / actscale;
e.depth = vid.depth / e.walls;
e.eye = (vid.eye-vid.depth) / e.walls;
e.sun = vid.sun_size / e.walls;
e.sky = vid.sky_height;
e.star = vid.star_height;
e.se = geom3::spatial_embedding;
return e;
}
void activate(const embset& e) {
if(GDIM == 2) invoke_embed(geom3::seDefault);
embset c = current();
auto wh = vid.wall_height;
geom3::changing_embedded_settings = true;
geom3::switch_always3();
geom3::euclid_embed_scale = e.se == geom3::seDefault ? 1 : e.scale;
vid.wall_height = e.walls * geom3::euclid_embed_scale;
vid.depth = e.depth * vid.wall_height;
vid.eye = vid.depth + e.eye * vid.wall_height;
vid.sun_size = e.sun * vid.wall_height;
vid.sky_height = e.sky;
vid.star_height = e.star;
geom3::spatial_embedding = e.se;
geom3::switch_always3();
geom3::changing_embedded_settings = false;
if(e.se != c.se) {
if(vid.usingGL) resetGL();
}
delete_sky();
if(vid.wall_height * wh < 0) View = MirrorY * View;
pmodel = default_model();
};
embset lerp(const embset& a, const embset& b, ld f) {
embset e;
e.name = lalign(0, "lerp(", a, ", ", b, ", ", f, ")");
e.se = b.se;
e.scale = lerp(a.scale, b.scale, f);
e.walls = lerp(a.walls, b.walls, f);
e.depth = lerp(a.depth, b.depth, f);
e.eye = lerp(a.eye, b.eye, f);
e.sun = lerp(a.sun, b.sun, f);
e.sky = lerp(a.sky, b.sky, f);
e.star = lerp(a.star, b.star, f);
return e;
}
void print(hstream& hs, const embset& e) {
print(hlog, "embset{.name=\"", e.name, "\", .se=eEmbeddingMethod(", int(e.se), "), .walls=", e.walls, ", .scale=", e.scale, ", .depth=", e.depth, ", .eye=", e.eye, ", .sun=", e.sun, ", .sky=", e.sky, ", .star=", e.star, "}");
}
embset edefault = embset{.name="default", .se=geom3::seDefault, .walls=1.2, .scale=0, .depth=0, .eye=1.5, .sun=0.333333, .sky=10, .star=9};
embset edefaulti = embset{.name="default", .se=geom3::seDefault, .walls=-1.2, .scale=0, .depth=0, .eye=-1.5, .sun=0.333333, .sky=10, .star=9};
// embset eincyl = embset{.name="in cylinder", .se=geom3::seCylinderE, .walls=0.75, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=4, .star=3.6};
embset eincyl = embset{.name="in cylinder E", .se=geom3::seCylinderE, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
embset eoutcyl = embset{.name="out cylinder E", .se=geom3::seCylinderE, .walls=-1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.3, .sky=10, .star=9};
embset eouthoro = embset{.name="out horosphere", .se=geom3::seLowerCurvature, .walls=1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=8, .star=7.5};
embset einhoro = embset{.name="in horosphere", .se=geom3::seLowerCurvature, .walls=-1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=12, .star=11};
embset einhoro_small = embset{.name="in horosphere (small sky)", .se=geom3::seLowerCurvature, .walls=-1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=18, .star=17};
embset esolv = embset{.name="solv", .se=geom3::seSol, .walls=1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=12, .star=11};
embset einnih = embset{.name="in NIH", .se=geom3::seNIH, .walls=-1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=12, .star=11};
embset eoutnih = embset{.name="out NIH", .se=geom3::seNIH, .walls=1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=8, .star=7.5};
embset eclifford = embset{.name="Clifford", .se=geom3::seCliffordTorus, .walls=1.2, .scale=M_PI/10, .depth=-0.0561826, .eye=1.5, .sun=0.25, .sky=2.55, .star=2.3};
embset enil = embset{.name="Nil flat", .se=geom3::seNil, .walls=1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=12, .star=11};
embset esl2 = embset{.name="SL(2,R) flat", .se=geom3::seSL2, .walls=1.2, .scale=0.1, .depth=0, .eye=1.5, .sun=0.25, .sky=12, .star=11};
embset eincylh = embset{.name="in cylinderH", .se=geom3::seCylinderH, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
embset eincylhe = embset{.name="in cylinderHE", .se=geom3::seCylinderHE, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
embset eincylnil = embset{.name="in cylinder Nil", .se=geom3::seCylinderNil, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
embset eincylsl = embset{.name="in cylinder SL(2,R)", .se=geom3::seCylinderSL2, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
embset einhorocyl = embset{.name="in horocylinder", .se=geom3::seCylinderHoro, .walls=-1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=8, .star=7.5};
embset eouthorocyl = embset{.name="out horocylinder", .se=geom3::seCylinderHoro, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=4, .star=3.5};
embset eprodh_flat = embset{.name="hyperbolic product (flat)", .se=geom3::seProductH, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
embset eprodh_concave = embset{.name="hyperbolic product (concave)", .se=geom3::seProductH, .walls=1.2, .scale=M_PI/10, .depth=1, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
embset eprods_flat = embset{.name="spherical product (flat)", .se=geom3::seProductS, .walls=1.2, .scale=M_PI/10, .depth=0, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
embset eprods_concave = embset{.name="spherical product (concave)", .se=geom3::seProductS, .walls=1.2, .scale=M_PI/10, .depth=0.8333, .eye=1.5, .sun=0.10472, .sky=2.6, .star=2.4};
embset& edok() { return vid.wall_height > 0 ? edefault : edefaulti; }
vector<embset> embsets = {
edefault,
eincyl, eoutcyl, eouthoro, einhoro, einhoro_small, esolv, eclifford, einnih, eoutnih,
enil, esl2, eincylh, eincylhe, eincylnil, eincylsl,
einhorocyl, eouthorocyl, eprodh_flat, eprodh_concave, eprods_flat, eprods_concave
};
ld fix_chess = 0;
int draw_digger = 0;
bool move_cat = false;
vector<string> xmap = {
{"......B..........p#"},
{".................p#"},
{"..xxxxxxxx.......p#"},
{"..xxxxxxxx..T....p#"},
{"..xxxxxxxx.....T.p#"},
{"..xxxxxxxx...~~..p#"},
{"..xxxxxxxx..~uv~.p#"},
{"..xxxxxxxx..~vu~.p#"},
{"..xxxxxxxx..~~~~.p#"},
{"..xxxxxxxx......Tp#"},
{".............T...p#"},
{"......C..........p#"},
{"......p..........p#"},
{".>>>..p..DDDDDDD.p#"},
{".>>>..pK.DddddrD.p#"},
{".>>>..pK.DdddtdD.p#"},
{"......pK.DdddddD.p#"},
{"..e...p..DOD+DOD.p#"},
{"......p.....p....p#"},
{"....^.pppppppppppp#"},
};
namespace embchess {
void build_map();
ld hmul;
set<cell*> domek1, domek2;
vector<cell*> ac, bac;
using namespace rogueviz::objmodels;
void prepare_tf();
hyperpoint adjust(hyperpoint h) {
h = cspin90(1, 2) * h * 40. + point3(-0.5, -0.5, 0);
return h;
}
hyperpoint rechess(hyperpoint h) {
h[2] = lerp(cgi.FLOOR, cgi.WALL, 0.01-h[2]/4 * hmul * 2 / 0.6) + fix_chess;
if(GDIM == 3) h = cgi.emb->logical_to_actual(h);
else h[2] = 1;
return h;
}
struct split_model_data : gi_extension {
map<pair<int, int>, vector<shared_ptr<object>>> objs_at;
void render(const shiftmatrix& V, int x, int y);
};
struct chessmodel : public model {
void process_triangle(vector<hyperpoint>& hys, vector<hyperpoint>& tot, bool textured, object *co) override {
for(auto& h: hys) h = adjust(h);
hyperpoint norm = (hys[1] - hys[0]) ^ (hys[2] - hys[0]);
norm /= hypot_d(3, norm);
ld y = .5 + (.2 * norm[0] + .16 * norm[1] + .14 * norm[2]);
glvertex shade = glhr::makevertex(0, y, 0);
glvertex shadecol = glhr::makevertex(y, y, y);
auto elen = [] (hyperpoint a, hyperpoint b) { return ceil(hypot_d(3, a-b) * 5); };
int parts = max( max(elen(hys[0], hys[1]), elen(hys[0], hys[2])), elen(hys[1], hys[1]) );
// if(parts > 8) println(hlog, "parts = ", parts, " levels = ", tie(hys[0][2], hys[1][2], hys[2][2]), " .. ", hys);
// if(parts > 8) return;
auto tri = [&] (int a, int b) {
cgi.hpcpush(rechess(hys[0] + (hys[1] - hys[0]) * a / parts + (hys[2] - hys[0]) * b / parts));
if(textured) {
co->tv.tvertices.push_back(glhr::pointtogl(tot[0] + (tot[1] - tot[0]) * a / parts + (tot[2] - tot[0]) * b / parts));
co->tv.colors.push_back(shadecol);
}
else {
co->tv.tvertices.push_back(shade);
}
};
for(int a=0; a<parts; a++)
for(int b=0; b<parts-a; b++) {
tri(a, b);
tri(a+1, b);
tri(a, b+1);
if(a+b < parts-1) {
tri(a, b+1);
tri(a+1, b);
tri(a+1, b+1);
}
}
}
chessmodel(string a, string b) : model(a,b) {}
void split(model_data& md, split_model_data& smd);
split_model_data& get_split() {
auto& md = (unique_ptr<split_model_data>&) cgi.ext[fname + "-SPLIT"];
if(!md) {
md = std::make_unique<split_model_data>();
auto& md0 = get();
split(md0, *md);
}
return *md;
}
};
bool ispiece(color_t col) {
return among(col, color_t(0xFFFFFFFF), color_t(0x202020FF), color_t(0x2B2B2BFF));
}
void chessmodel::split(model_data& md, split_model_data& smd) {
cgi.extra_vertices();
map<pair<int, int>, map<color_t, vector<pair<hyperpoint, glvertex>>>> mm;
for(auto& obj: md.objs) {
for(int i=obj->sh.s; i<obj->sh.e; i+=3) {
hyperpoint ctr = Hypc;
array<hyperpoint, 3> hs;
for(int j=0; j<3; j++) hs[j] = GDIM == 2 ? cgi.hpc[i+j] : cgi.emb->actual_to_logical(cgi.hpc[i+j]);
ctr += hs[0];
ctr += hs[1];
ctr += hs[2];
ctr /= 3;
int x = floor(ctr[0] + .5);
int y = floor(ctr[1] + .5);
int ax = x + 6, ay = y + 6;
if(chess_moves >= 1 && ispiece(obj->color)) {
if(ax == 6) { if(ay == 8) ay = 6; else if(ay == 6) ay = 8; }
}
if(chess_moves >= 2 && ispiece(obj->color)) {
if(ax == 6) { if(ay == 3) ay = 5; else if(ay == 5) ay = 3; }
}
if(chess_moves >= 3 && ispiece(obj->color)) {
if(ax == 8) { if(ay == 9) ay = 7, ax = 7; }
}
for(int j=0; j<3; j++)
mm[{ax,ay}][obj->color].emplace_back(hs[j] - hyperpoint(x, y, 0, 0), obj->tv.tvertices[i+j-obj->sh.s]);
}
}
for(auto& a: mm)
for(auto& b: a.second) {
auto& objs = smd.objs_at[a.first];
objs.push_back(make_shared<object>());
auto co = &*objs.back();
cgi.bshape(co->sh, PPR::THORNS);
cgi.last->flags |= POLY_TRIANGLES;
cgi.last->texture_offset = 0;
cgi.last->tinf = &co->tv;
co->tv.texture_id = floor_textures->renderedTexture;
if(GDIM == 2) cgi.last->tinf = nullptr;
co->color = b.first;
if(co->color == 0xCCCCCCFF) co->color = GDIM == 2 ? 0 : 0xFFE080FF;
else if(co->color == 0x5B5B5BFF) co->color = GDIM == 2 ? 0 : 0x807020FF;
// else for(auto& v: b.second) v.first = cspin180(0, 1) * v.first;
for(auto v: b.second) {
cgi.hpcpush(GDIM == 2 ? v.first : cgi.emb->logical_to_actual(v.first));
co->tv.tvertices.push_back(v.second);
}
cgi.finishshape();
}
cgi.extra_vertices();
if(0) for(auto& p: smd.objs_at) {
println(hlog, p.first, " : ", isize(p.second), " objects");
for(auto& obj: p.second) {
vector<hyperpoint> hs;
for(int i=obj->sh.s; i<obj->sh.e; i++) hs.push_back(cgi.hpc[i]);
if(isize(hs) > 3) hs.resize(3);
println(hlog, "vertices: ", obj->sh.e - obj->sh.s, " of color ", obj->color, " : ", hs);
}
}
}
void split_model_data::render(const shiftmatrix& V, int x, int y) {
for(auto& obj: objs_at[{x, y}]) if(obj->color) {
queuepoly(V, obj->sh, obj->color);
}
}
chessmodel chess("rogueviz/models/", "Polyfjord_Chess_Set.obj");
ld minz = 100, maxz = -100;
ld minx = 100, maxx = -100;
ld miny = 100, maxy = -100;
struct bunnymodel : public model {
hyperpoint transform(hyperpoint h) override {
h = cspin90(1, 2) * h;
h = cspin(0, 1, 15._deg) * h;
h[0] *= 800;
h[1] *= 800;
h[2] = lerp(cgi.FLOOR, cgi.WALL, ilerp(-0.000333099, -0.00186996, h[2]) * hmul * 4/3.);
if(GDIM == 3) h = cgi.emb->logical_to_actual(h);
else h[2] = 1;
return h;
}
bunnymodel(string a, string b) : model(a,b) {}
};
bunnymodel bunny("rogueviz/models/", "bunny.obj");
struct catmodel : public model {
hyperpoint transform(hyperpoint h) override {
if(0) println(hlog, "scale = 1 to ",
lerp(cgi.FLOOR, cgi.WALL, ilerp(0.00767046, -0.184471, 1) * hmul * 4/3.)
- lerp(cgi.FLOOR, cgi.WALL, ilerp(0.00767046, -0.184471, 0) * hmul * 4/3.)
);
h = cspin90(1, 2) * h;
h = cspin180(0, 1) * h;
h = cspin(1, 0, 30._deg) * h;
h[0] *= 6;
h[1] *= 6;
h[2] = lerp(cgi.FLOOR, cgi.WALL, ilerp(0.00767046, -0.184471, h[2]) * hmul * 4/3.) / 8.3272 * 6;
if(GDIM == 3) h = cgi.emb->logical_to_actual(h);
else h[2] = 1;
return h;
}
void load_obj(model_data& md) override {
model::load_obj(md);
for(auto& o: md.objs) if(o->mtlname == "whiskers") o->sh.prio = PPR::TRANSPARENT_WALL;
}
catmodel(string a, string b) : model(a,b) {}
};
catmodel maxwellcat("rogueviz/models/", "maxwellcat.obj");
struct tulipmodel : public model {
hyperpoint transform(hyperpoint h) override {
h = cspin90(1, 2) * h;
h = cspin180(0, 1) * h;
h[0] *= 400;
h[1] *= 400;
h[0] -= 0.1*2; h[1] += 0.36*2;
h[2] = lerp(cgi.FLOOR, cgi.WALL, ilerp(0, -0.00307639, h[2]) * hmul);
if(GDIM == 3) h = cgi.emb->logical_to_actual(h);
else h[2] = 1;
return h;
}
tulipmodel(string a, string b) : model(a,b) {}
};
tulipmodel tulip("rogueviz/models/", "tulip.obj");
tulipmodel tulip1("rogueviz/models/", "tulip1.obj");
tulipmodel tulip2("rogueviz/models/", "tulip2.obj");
struct diggermodel : public model {
hyperpoint transform(hyperpoint h) override {
h = cspin90(1, 2) * h;
h[0] *= 50;
h[1] *= 50;
/* h[0] *= 400;
h[1] *= 400;
h[0] -= 0.1*2; h[1] += 0.36*2; */
h[2] = lerp(cgi.FLOOR, cgi.WALL, ilerp(0.00027, -0.0549454, h[2]) * hmul * 1.5);
if(GDIM == 3) h = cgi.emb->logical_to_actual(h);
else h[2] = 1;
return h;
}
diggermodel(string a, string b) : model(a,b) {}
};
diggermodel digger("rogueviz/models/", "digger.obj");
struct tablemodel : public model {
hyperpoint transform(hyperpoint h) override {
h = cspin90(1, 2) * h;
h[1] -= 0.005;
h[0] *= 100;
h[1] *= 100;
/* h[0] *= 400;
h[1] *= 400;
h[0] -= 0.1*2; h[1] += 0.36*2; */
h[2] = lerp(cgi.FLOOR, cgi.WALL, ilerp(0, -0.008, h[2]) * hmul / 2);
if(GDIM == 3) h = cgi.emb->logical_to_actual(h);
else h[2] = 1;
return h;
}
tablemodel(string a, string b) : model(a,b) {}
};
tablemodel table("rogueviz/models/", "table.obj");
struct cheesemodel : public model {
hyperpoint transform(hyperpoint h) override {
h = cspin90(1, 2) * h;
h[0] *= 15;
h[1] *= 15;
/* h[0] *= 400;
h[1] *= 400;
h[0] -= 0.1*2; h[1] += 0.36*2; */
h[0] -= 0.2;
h[2] = lerp(cgi.FLOOR, cgi.WALL, (ilerp(0.00577916, -0.01166, h[2])/3 + 1.05) * hmul / 2);
if(GDIM == 3) h = cgi.emb->logical_to_actual(h);
else h[2] = 1;
return h;
}
cheesemodel(string a, string b) : model(a,b) {}
};
cheesemodel cheese("rogueviz/models/", "cheese.obj");
struct coffeemodel : public model {
int cid;
hyperpoint transform(hyperpoint h) override {
h = cspin90(1, 2) * h;
h[0] += 0.00077;
h[1] += 0.011;
h[0] *= 200; h[1] *= 200;
if(cid == 1) h[0] += 0.3;
if(cid == 2) h[1] += 0.5;
h[2] = lerp(cgi.FLOOR, cgi.WALL, (ilerp(-0.0083, -0.0089, h[2])) * 1.2 / 10 + .51);
if(GDIM == 3) h = cgi.emb->logical_to_actual(h);
else h[2] = 1;
return h;
}
coffeemodel(string a, string b, int _id) : model(a,b), cid(_id) {}
};
/* need different file names */
coffeemodel coffee1("rogueviz/models/", "coffee.obj", 1), coffee2("rogueviz/models/", "./coffee.obj", 2);
struct lilymodel : public model {
hyperpoint transform(hyperpoint h) override {
h = cspin90(1, 2) * h;
h[0] += 0.67; h[1] -= 0.36;
h[0] *= 5;
h[1] *= 5;
/* h[0] *= 400;
h[1] *= 400;
h[0] -= 0.1*2; h[1] += 0.36*2; */
h[2] = lerp(cgi.LAKE, cgi.FLOOR, ilerp(0.018, -0.0496, h[2]) * hmul);
if(GDIM == 3) h = cgi.emb->logical_to_actual(h);
else h[2] = 1;
return h;
}
lilymodel(string a, string b) : model(a,b) {}
};
lilymodel lily("rogueviz/models/", "lily.obj");
struct duckmodel : public model {
hyperpoint transform(hyperpoint h) override {
h = cspin90(1, 2) * h;
h[0] += 3.8; h[1] -= 2;
/* h[0] *= 400;
h[1] *= 400;
h[0] -= 0.1*2; h[1] += 0.36*2; */
h[2] = lerp(cgi.LAKE, cgi.FLOOR, ilerp(0.056, -0.408, h[2]) * hmul * 1.5);
if(GDIM == 3) h = cgi.emb->logical_to_actual(h);
else h[2] = 1;
return h;
}
duckmodel(string a, string b) : model(a,b) {}
};
duckmodel duck("rogueviz/models/", "duck.obj");
struct ratmodel : public model {
hyperpoint transform(hyperpoint h) override {
h = cspin90(1, 2) * h;
h[0] *= 100;
h[1] *= 100;
h[2] *= 100;
h[0] /= 3 * 3;
h[1] /= 3 * 3;
h[2] /= 3 * 3;
h = cspin(0, 1, 135._deg) * h;
if(h[2] < minz) minz = h[2];
if(h[2] > maxz) maxz = h[2];
if(h[0] < minx) minx = h[0];
if(h[0] > maxx) maxx = h[0];
if(h[1] < miny) miny = h[1];
if(h[1] > maxy) maxy = h[1];
h[2] = lerp(cgi.FLOOR, cgi.WALL, ilerp(1/9., 1/9. - 1.2, h[2]) * hmul);
if(GDIM == 3) h = cgi.emb->logical_to_actual(h);
else h[2] = 1;
return h;
}
ratmodel(string a, string b) : model(a,b) {}
};
ratmodel rat("rogueviz/models/", "spinning-rat.obj");
bool hedge_constructed = false;
const int hx = 7;
array<char, hx*hx*hx> hedge_visited;
array<int, 6> hdirs = {1, hx, hx*hx, -1, -hx, -hx*hx};
array<vector<int>, hx*hx*hx> hedge_dirs;
int hstart;
void construct_hedge() {
for(int x=0; x<hx*hx*hx; x++) hedge_visited[x] = false;
hstart = (hx/2)+(hx/2)*hx;
hedge_visited[hstart] = true;
vector<int> inorder = {hstart};
for(int i=0; i<hx*hx*hx; i++) {
int at = inorder[i];
for(int dir: {0, 1, 3, 4, 2, 5}) {
int co = (at / abs(hdirs[dir])) % hx;
if(hdirs[dir] < 0 && co == 0) continue;
if(hdirs[dir] > 0 && co == hx-1) continue;
if(hedge_visited[at+hdirs[dir]]) continue;
hedge_visited[at+hdirs[dir]] = true;
hedge_dirs[at].push_back(dir);
inorder.push_back(at+hdirs[dir]);
}
}
/*
int qty = hx*hx*hx-1;
while(qty > 0) {
int at = hrand(hx*hx*hx);
if(!hedge_visited[at]) continue;
int dir = hrand(6);
int co = (at / abs(hdirs[dir])) % hx;
if(hdirs[dir] < 0 && co == 0) continue;
if(hdirs[dir] > 0 && co == hx-1) continue;
if(hedge_visited[at+hdirs[dir]]) continue;
hedge_visited[at+hdirs[dir]] = true;
hedge_dirs[at].push_back(dir);
qty--;
} */
}
void add_oct(transmatrix T, int idx, int face, ld len) {
array<hyperpoint, 3> p;
for(int i=0; i<3; i++) { p[i] = C03; p[i][i] = ((face>>i)&1) ? len/2 : -len/2; p[i] = cgi.emb->logical_scaled_to_intermediate * p[i]; }
hyperpoint c = (p[0] + p[1] + p[2]) / 3;
for(int f=0; f<3; f++) {
hyperpoint a = p[f] - c;
hyperpoint b = p[(f+1)%3] - c;
texture_order([&] (ld x, ld y) {
hyperpoint h = c + a * x + b * y;
hyperpoint t = T * cpush(0, h[0]) * cpush(1, h[1]) * cpush(2, h[2]) * C0;
cgi.hpcpush(t);
});
}
if(true) for(auto d: hedge_dirs[idx]) {
hyperpoint h = C0;
h[d%3] = (d<3 ? -len: len);
h = cgi.emb->logical_scaled_to_intermediate * h;
transmatrix T1 = T;
for(int i=0; i<3; i++) if(h[i]) T1 = T1 * cpush(i, h[i]);
add_oct(T1, idx + hdirs[d], face, len);
}
}
void create_hedge(model_data& md) {
if(!hedge_constructed) construct_hedge();
hyperpoint start = cgi.emb->logical_to_actual(point31(0, 0, cgi.FLOOR));
hyperpoint npt = cgi.emb->logical_to_actual(point31(0.01, 0, cgi.FLOOR));
transmatrix S = cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point31(0, 0, cgi.emb->center_z() + cgi.FLOOR));
ld len = hdist(start, npt) * 100 / 7;
len *= 3;
if(vid.wall_height < 0) len = -len;
md.objs.resize(8);
for(int i=0; i<8; i++) {
md.objs[i] = make_shared<object> ();
auto& obj = *md.objs[i];
obj.color = 0xFF00FF;
if(i & 1) obj.color ^= 0x200000;
if(i & 2) obj.color ^= 0x20000000;
if(i & 4) obj.color ^= 0x2000;
cgi.bshape(obj.sh, PPR::FLOOR_DRAGON);
cgi.last->flags |= POLY_TRIANGLES;
cgi.last->texture_offset = 0;
cgi.last->tinf = &obj.tv;
obj.tv.texture_id = floor_textures->renderedTexture;
add_oct(S * lzpush(-len/2), hstart, i, len);
cgi.finishshape();
bind_floor_texture(obj.sh, cgi.shFeatherFloor.id);
}
cgi.extra_vertices();
}
void draw_hedge(const shiftmatrix& V) {
auto& md = (unique_ptr<model_data>&) cgi.ext["hedge"];
if(!md) {
md = std::make_unique<model_data>();
create_hedge(*md);
}
md->render(V);
}
hyperpoint inverse_exp_newton(hyperpoint h, int iter) {
auto approx = inverse_exp(shiftless(h));
for(int i=0; i<iter; i++) {
transmatrix T;
ld eps = 1e-3;
hyperpoint cur = direct_exp(approx);
println(hlog, approx, " error = ", hdist(cur, h), " iteration ", i, "/", iter);
for(int i=0; i<3; i++)
set_column(T, i, direct_exp(approx + ctangent(i, eps)) - h);
set_column(T, 3, C03);
approx = approx - inverse(T) * (cur - h) * eps;
}
return approx;
}
hpcshape& get_noniso_pipe(hyperpoint target, ld width, ePipeEnd endtype) {
int id = bucketer(target) + int(157003 * log(width+.001));
if(cgi.shPipe.count(id)) return cgi.shPipe[id];
hpcshape& pipe = cgi.shPipe[id];
println(hlog, "generating pipe at target ", target, " and width ", width);
cgi.bshape(pipe, PPR::HEPTAMARK);
#if CAP_GL
auto& utt = cgi.models_texture;
if(floor_textures) {
pipe.tinf = &utt;
pipe.texture_offset = isize(utt.tvertices);
}
#endif
hyperpoint lmax = inverse_exp_newton(target, 10);
println(hlog, "error = ", hdist(direct_exp(lmax), target));
transmatrix lT;
ld length;
if(1) {
dynamicval<eGeometry> g(geometry, gCubeTiling);
length = hdist0(lmax);
lT = rspintox(lmax);
println(hlog, "target = ", target, " lmax = ", lmax, " length = ", length, " lT = ", kz(lT));
println(hlog, "test: ", lT * xpush0(length), " vs ", lmax);
}
const int MAX_X = 32;
const int MAX_R = 20;
auto at = [&] (ld i, ld a, ld z = 1, ld s = 1) {
a += 0.5;
ld alpha = TAU * a / MAX_R;
hyperpoint p;
if(1) {
dynamicval<eGeometry> g(geometry, gCubeTiling);
p = xpush(i * length / MAX_X) * cspin(1, 2, alpha) * ypush0(width*z);
p = lT * p;
}
p = direct_exp(p);
cgi.hpcpush(p);
#if CAP_GL
if(floor_textures) utt.tvertices.push_back(glhr::makevertex(0, true ? 0.549 - s * 0.45 * sin(alpha) : 0.999, 0));
#endif
};
for(int i=0; i<MAX_X; i++) {
for(int a=0; a<MAX_R; a++) {
at(i, a, 1);
at(i, a+1, 1);
at(i+1, a, 1);
at(i+1, a+1, 1);
at(i+1, a, 1);
at(i, a+1, 1);
}
}
if(endtype == ePipeEnd::sharp) for(int a=0; a<MAX_R; a++) for(int x: {0, MAX_X}) {
at(x, a, 1, 0);
at(x, a+1, 1, 0);
at(x, 0, 0, 0);
}
if(endtype == ePipeEnd::ball) for(int a=0; a<MAX_R; a++) for(int x=-MAX_R; x<MAX_R; x++) {
ld xb = x < 0 ? 0 : MAX_X;
ld mul = MAX_X * width/length * .9; // .9 to prevent Z-fighting
ld x0 = xb + mul * sin(x * 90._deg / MAX_R);
ld x1 = xb + mul * sin((x+1) * 90._deg / MAX_R);
ld z0 = cos(x * 90._deg / MAX_R);
ld z1 = cos((x+1) * 90._deg / MAX_R);
at(x0, a, z0, z0);
at(x0, a+1, z0, z0);
at(x1, a, z1, z1);
at(x1, a+1, z1, z1);
at(x1, a, z1, z1);
at(x0, a+1, z0, z0);
}
cgi.last->flags |= POLY_TRIANGLES | POLY_PRINTABLE;
cgi.finishshape();
cgi.extra_vertices();
return pipe;
}
void fat_line(const shiftmatrix& V1, const hyperpoint h1, const shiftmatrix& V2, const hyperpoint h2, color_t col, int prec, ld lw) {
if(nonisotropic) {
auto nV1 = V1 * rgpushxto0(h1);
hyperpoint U2 = inverse_shift(nV1, V2*rgpushxto0(h2)) * C0;
auto& p = get_noniso_pipe(U2, lw, ePipeEnd::ball);
queuepoly(nV1, p, col);
return;
}
ld d = hdist(V1.T*h1, V2.T*h2);
shiftmatrix T = V1 * rgpushxto0(h1);
transmatrix S = rspintox(inverse_shift(T, V2) * h2);
transmatrix U = rspintoc(inverse_shift(T*S, shiftless(C0)), 2, 1);
auto& p = queuepoly(T * S * U, cgi.generate_pipe(d, lw, ePipeEnd::ball), col);
p.intester = xpush0(d/2);
}
int scaffoldx = 0, scaffoldy = 0, scaffoldb = 0, scaffoldx_move = 0, scaffoldy_move;
template<class T> void draw_map54(const shiftmatrix& S, const T& f, color_t col) {
for(auto p: map54_nodes) queuepoly(S * rgpushxto0(f(p)), cgi.shSnowball, 0xFFFFFFFF);
for(auto& p: map54_edges) fat_line(S, f(p.first), S, f(p.second), (abs(p.first[1])<1e-3 && abs(p.second[1])<1e-3 && scaffoldx && scaffoldy) ? 0xFFFFFFFF : col, 2, 0.01);
}
void draw_scaffold(const shiftmatrix& V) {
ld levz = log(2);
if(nih) levz = 1;
ld levx = 1;
if(hyperbolic) levx = exp(-cgi.FLOOR);
levx *= 5;
if(scaffoldx == 1)
for(int z=-5; z<=5; z++)
for(int s=-20; s<=20; s++) {
shiftmatrix S = V * lzpush(cgi.FLOOR + z * levz) * cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(s*levx,0,0));
queuepoly(S, cgi.shSnowball, 0xFFFFFFFF);
fat_line(S, C0, S, lzpush(-levz) * C0, (s == 0 && scaffoldy) ? 0xFFFFFFFF : 0xFF0000FF, 2, 0.01);
for(int s=0; s<8; s++)
fat_line(S, cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(levx*(s+0)/8.,0,0)) * C0,
S, cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(levx*(s+1)/8.,0,0)) * C0,
0x8000FFFF, 2, 0.01);
}
if(scaffoldx == 2) {
if(hyperbolic) {
draw_map54(V, [] (hyperpoint h) { return cgi.emb->intermediate_to_actual_translation(point3(h[1],0,0)) * zpush(h[0]) * C0; }, 0xFFD500FF);
}
if(sol) {
draw_map54(V, [] (hyperpoint h) { return cgi.emb->intermediate_to_actual_translation(point3(h[1],0,0)) * zpush(-h[0]) * C0; }, 0xFFD500FF);
}
if(nih) {
draw_map54(V, [] (hyperpoint h) { return cgi.emb->intermediate_to_actual_translation(point3(-h[1]/log(2),0,0)) * zpush(h[0]/log(2)) * C0; }, 0xFFD500FF);
}
}
ld levy = 5;
if(scaffoldy == 1)
for(int z=-5; z<=5; z++)
for(int s=-20; s<=20; s++) {
shiftmatrix S = V * lzpush(cgi.FLOOR + z * levz) * cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(0,s*levy,0));
queuepoly(S, cgi.shSnowball, 0xFFFFFFFF);
fat_line(S, C0, S, lzpush(sol ? levz : -levz) * C0, (s == 0 && scaffoldx) ? 0xFFFFFFFF : 0x0000FFFF, 2, 0.01);
for(int s=0; s<8; s++)
fat_line(S, cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(0, levy*(s+0)/8.,0)) * C0,
S, cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(0, levy*(s+1)/8.,0)) * C0,
0x0080FF, 2, 0.01);
}
if(scaffoldy == 2) {
if(hyperbolic) {
draw_map54(V, [] (hyperpoint h) { return cgi.emb->intermediate_to_actual_translation(point3(0,h[1],0)) * zpush(h[0]) * C0; }, 0x80D500FF);
}
if(sol) {
draw_map54(V, [] (hyperpoint h) { return cgi.emb->intermediate_to_actual_translation(point3(0,h[1],0)) * zpush(h[0]) * C0; }, 0x80D500FF);
}
if(nih) {
draw_map54(V, [] (hyperpoint h) { return cgi.emb->intermediate_to_actual_translation(point3(0,h[1]/log(3),0)) * zpush(h[0]/log(3)) * C0; }, 0x80D500FF);
}
}
if(scaffoldb == 1)
for(int z=-5; z<=5; z++)
for(int sx=-5; sx<=5; sx++)
for(int sy=-5; sy<=5; sy++) {
shiftmatrix S = V * lzpush(cgi.FLOOR + z * levz) * cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(sx*levx,sy*levy,0));
queuepoly(S, cgi.shSnowball, 0xFFFFFFFF);
fat_line(S, C0, S, lzpush(-levz) * C0, 0xFF0000FF, 2, 0.01);
for(int s=0; s<8; s++) {
fat_line(S, cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(levx*(s+0)/8.,0,0)) * C0,
S, cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(levx*(s+1)/8.,0,0)) * C0,
0xFF8000FF, 2, 0.01);
fat_line(S, cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(0,levy*(s+0)/8.,0)) * C0,
S, cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(0,levy*(s+1)/8.,0)) * C0,
0xFF8000FF, 2, 0.01);
}
}
if(scaffoldb == 2 && hyperbolic) {
for(auto h: map534_nodes) queuepoly(V * rgpushxto0(h), cgi.shSnowball, 0xFFFFFFFF);
for(auto h: map534_edges) fat_line(V, h.first, V, h.second, 0xFFFFFFFF, 2, 0.01);
}
}
/*
static bool first = true;
if(first) println(hlog, tie(minx, maxx), tie(miny, maxy), tie(minz, maxz));
first = false;
*/
string losowo = "1100002102001211";
void draw_shape(const shiftmatrix& V, vector<ld> tab, color_t col, ld mul = 1) {
int n = isize(tab);
for(int i=0; i<n; i+=2) curvepoint(hpxy(tab[i]*mul, tab[i+1]*mul));
curvepoint(hpxy(tab[0]*mul, tab[1]*mul));
queuecurve(V, 0xFF, col, PPR::MONSTER_LEG);
}
bool draw_chess_at(cell *c, const shiftmatrix& V) {
if(c->item == itHyperstone) c->item = itNone;
if(false) {
if(c == cwt.at) chess.render(V);
}
else {
auto co = euc::full_coords2(c);
char& chr = xmap[gmod(co.second, 20)][gmod(co.first, 20)];
char ch = chr;
if(no_floor && ch != '^') ch = '<';
// if(co.first == 0 && co.second == 0) bunny.render(V);
switch(ch) {
case 'r':
if(GDIM == 3 && with_models) {
rat.render(V);
static bool first = true;
if(first) println(hlog, tie(minx, maxx), tie(miny, maxy), tie(minz, maxz));
first = false;
}
else {
drawMonsterType(moMouse, c, V * spin(-135._deg), 0x804000, 0, 0x804000);
}
break;
case '<':
c->wall = waChasm;
domek1.erase(c); domek2.erase(c);
fat_line(V, cgi.emb->logical_to_actual(point31(0.5, 0.5, 0)), V, cgi.emb->logical_to_actual(point31(0.5, -0.5, 0)), 0xFFFFFFFF, 2, 0.001);
fat_line(V, cgi.emb->logical_to_actual(point31(0.5, 0.5, 0)), V, cgi.emb->logical_to_actual(point31(-0.5, 0.5, 0)), 0xFFFFFFFF, 2, 0.001);
break;
case 'u': {
if(GDIM == 3 && with_models) {
lily.render(V);
c->item = itNone;
}
else c->item = itWet;
break;
}
case 'v': {
if(GDIM == 3 && with_models) duck.render(V);
else {
draw_shape(V, {-0.164988, 0.0033671, -0.114197, 0.0638159, 0.0401905, 0.063635, 0.10735, 0.0268375, 0.10735, -0.0268375, 0.0401905, -0.063635, -0.114197, -0.0638159, -0.164988, -0.0033671, }, 0xC0C0C0FF, 2);
draw_shape(V, {-0.0753584, 0.00669852, -0.111558, 0.0184533, -0.0812589, 0.0326711, -0.161669, 0.0479953, -0.10074, 0.0780737, -0.0184331, 0.0896519, 0.0830064, 0.065399, 0.113269, 0.0335611, 0.117466, 0.0151028, 0.117466, -0.0151028, 0.113269, -0.0335611, 0.0830064, -0.065399, -0.0184331, -0.0896519, -0.10074, -0.0780737, -0.161669, -0.0479953, -0.0812589, -0.0326711, -0.111558, -0.0184533, -0.0753584, -0.00669852, }, 0x806010FF, 2);
draw_shape(V, {0.164139, 0.0109426, 0.200142, 0.0185786, 0.239985, 0.00848005, 0.239985, -0.00848005, 0.200142, -0.0185786, 0.164139, -0.0109426, }, 0xE0E000FF, 2);
draw_shape(V, {0.0820785, 0.00670028, 0.0963908, 0.0243072, 0.121722, 0.0352575, 0.159071, 0.0361908, 0.183838, 0.028672, 0.199268, 0.00844354, 0.199268, -0.00844354, 0.183838, -0.028672, 0.159071, -0.0361908, 0.121722, -0.0352575, 0.0963908, -0.0243072, 0.0820785, -0.00670}, 0x106010FF, 2);
}
break;
}
case 'B':
if(GDIM == 3 && with_models) bunny.render(V);
else {
auto V1 = V * spin270();
draw_shape(V1, {-0.272437, 0.00681093, -0.247911, 0.0339604, -0.199391, 0.0506926, -0.165034, 0.0336804, -0.151363, 0.0100908, -0.151363, -0.0100908, -0.165034, -0.0336804, -0.199391, -0.0506926, -0.247911, -0.0339604, -0.272437, -0.00681093, }, 0xFFFFFFFF, 2);
draw_shape(V1, {-0.209613, 0.00676172, -0.161797, 0.0741567, -0.107602, 0.100877, 0.0033535, 0.103959, 0.100724, 0.0738645, 0.134426, 0.0369672, 0.14796, 0.00672545, 0.14796, -0.00672545, 0.134426, -0.0369672, 0.100724, -0.0738645, 0.0033535, -0.103959, -0.107602, -0.100877, -0.161797, -0.0741567, -0.209613, -0.00676172, }, 0xC0C0C0FF, 2);
draw_shape(V1, {0.0502023, 0.0167341, 0.0737312, 0.0536227, 0.151647, 0.0876183, 0.240969, 0.0441211, 0.272441, 0.0102165, 0.272441, -0.0102165, 0.240969, -0.0441211, 0.151647, -0.0876183, 0.0737312, -0.0536227, 0.0502023, -0.0167341, }, 0xD0D0D0FF, 2);
draw_shape(V1, {0.103977, 0.0268328, 0.0267753, 0.0468568, -0.0536042, 0.063655, -0.00335237, 0.0972189, 0.094003, 0.080574, 0.144678, 0.0571982, 0.154836, 0.0437579, 0.134405, 0.0268809, }, 0xC0C0C0FF, 2);
draw_shape(V1 * MirrorY, {0.103977, 0.0268328, 0.0267753, 0.0468568, -0.0536042, 0.063655, -0.00335237, 0.0972189, 0.094003, 0.080574, 0.144678, 0.0571982, 0.154836, 0.0437579, 0.134405, 0.0268809, }, 0xC0C0C0FF, 2);
draw_shape(V1, {0.168425, 0.0235794, 0.178774, 0.0505965, 0.188982, 0.0269974, }, 0xC00000FF, 2);
draw_shape(V1 * MirrorY, {0.168425, 0.0235794, 0.178774, 0.0505965, 0.188982, 0.0269974, }, 0xC00000FF, 2);
}
break;
case 't':
if(GDIM == 2) c->wall = waRoundTable; else if(with_models && !light_models) {
c->wall = waNone;
table.render(V);
cheese.render(V);
coffee1.render(V);
coffee2.render(V);
}
break;
case 'C':
if(GDIM == 3 && with_models) maxwellcat.render(V);
else {
dynamicval<bool> b(mapeditor::drawplayer, true);
drawPlayer(moPlayer, c, V * spin90(), 0xFFFFFFFF, 0);
}
if(move_cat) {
move_cat = false;
mapeditor::drawplayer = true;
chr = '.';
cwt.at = c;
vid.sspeed = -5;
cwt.spin = 1;
vid.axes = 0;
}
break;
case 'e':
if(GDIM == 3 && draw_digger == 2) digger.render(V);
break;
case 'K': {
int a = gmod(co.first + co.second, 3);
if(GDIM == 3 && with_models) {
auto gtulip = [&] (int a, int b) -> tulipmodel& { char ch = losowo[5*a+b]; if(ch == '0') return tulip; if(ch == '1') return tulip1; if(ch == '2') return tulip2; return tulip2; };
gtulip(a, 0).render(V);
gtulip(a, 1).render(V * cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(1/3., 1/3., 0)));
gtulip(a, 2).render(V * cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(1/3., -1/3., 0)));
gtulip(a, 3).render(V * cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(-1/3., 1/3., 0)));
gtulip(a, 4).render(V * cgi.emb->intermediate_to_actual_translation(cgi.emb->logical_to_intermediate * point3(-1/3., -1/3., 0)));
}
else {
vector<color_t> tcols = {0xFFFF80FF, 0xFF1010FF, 0xC000C0FF};
draw_shape(V*spin90(), {-0.202738, 0.0236527, -0.145213, 0.135082, -0.0438177, 0.1719, 0.0708783, 0.178883, 0.220846, 0.125712, 0.120989, 0.0705769, 0.219991, 0.00338448, 0.219991, -0.00338448, 0.120989, -0.0705769, 0.220846, -0.125712, 0.0708783, -0.178883, -0.0438177, -0.1719, -0.145213, -0.135082, -0.202738, -0.0236527}, tcols[a], 2);
}
break;
}
case 'H':
if(GDIM == 3) draw_hedge(V);
else queuepoly(V, cgi.shGem[0], 0xFF00FF);
break;
case '^': {
c->wall = no_floor ? waChasm : waNone;
auto ax = co.first - scaffoldx_move * 20;
auto ay = co.second - scaffoldy_move * 20;
if(ax >= 0 && ay >= 0 && ax < 20 && ay < 20)
draw_scaffold(V);
break;
}
case '>':
c->wall = draw_digger ? waChasm : waNone;
break;
}
if(with_chess) chess.get_split().render(V, gmod(co.first, 20), gmod(co.second, 20));
}
return false;
}
ld fov, otanfov;
void switch_fpp_fixed() {
auto& cd = current_display;
transmatrix tView;
ld ys;
tView = View;
otanfov = (cd->xsize/2) / cd->radius * 2;
auto d = vid.depth;
if(GDIM == 3) invoke_embed(geom3::seNone);
else {
invoke_embed(geom3::seDefault);
activate(edefault);
}
if(GDIM == 3) {
// pconf.camera_angle = 90;
ld tfov = vid.fov * degree / 2;
cd->tanfov = tan(tfov);
// tanfov * z + depth = fov
// z = (fov - depth) / tanfov
ld yshift = (otanfov - vid.depth) / cd->tanfov;
// drawthemap();
// centerpc(INF);
// shift_view(zpush0(yshift));
println(hlog, "yshift = ", yshift, " from ", vid.yshift);
// playermoved = false;
// vid.fov = fov;
// vid.yshift = yshift;
View = Id;
for(int a=0; a<2; a++)
for(int b=0; b<2; b++)
View[a][b] = tView[a][b];
for(int a=0; a<2; a++)
View[a][3] = tView[a][2];
println(hlog, tie(tView[2][0], tView[2][1]));
// rotate_view(cspin90(2, 1));
shift_view(zpush0(yshift));
playermoved = false;
}
else {
pconf.camera_angle = 0;
vid.yshift = 0;
ys = tView[2][3];
println(hlog, "ys = ", ys, " from ", tView);
otanfov = ys * cd->tanfov + d;
cd->radius = cd->xsize / otanfov;
pconf.scale = cd->radius / cd->scrsize;
}
if(GDIM == 2) {
View = spin90() * View;
View[0][2] = tView[0][3];
View[1][2] = tView[1][3];
}
}
void load_anim(string fname) {
fhstream f(fname, "r");
mapstream::cellbyid = ac;
while(isize(mapstream::cellbyid) < 400 * 400) for(auto c: ac) mapstream::cellbyid.push_back(c);
smoothcam::enable();
smoothcam::load_animation(f);
}
void append_anim(string fname) {
smoothcam::backup();
load_anim(fname);
smoothcam::append_backup();
}
void save_anim(string fname) {
fhstream f(fname, "w");
for(int i=0; i<isize(ac); i++) mapstream::cellids[ac[i]] = i;
smoothcam::save_animation(f);
}
void transition(ld a, ld b, int frames) {
anims::noframes = frames;
auto _edok = edok();
auto cu = current();
auto vn = glhr::vnear_default;
auto vf = glhr::vfar_default;
int lev = addHook(anims::hooks_anim, 100, [&] {
ld t = ticks / anims::period;
println(hlog, "transition, t = ", t);
indenter ind(2);
t = t * t * (3 - 2 * t);
t = lerp(a, b, t);
sightranges[geometry] = 50 * t;
glhr::vnear_default = vn * t;
glhr::vfar_default = vf * t;
activate(lerp(_edok, cu, t));
});
anims::record_video();
delHook(anims::hooks_anim, lev);
activate(cu);
sightranges[geometry] = 50;
glhr::vnear_default = vn;
glhr::vfar_default = vf;
}
void animate_forward(ld d, int frames) {
anims::noframes = frames;
ld lastt = 0;
int lev = addHook(anims::hooks_anim, 100, [&] {
println(hlog, "centerover is ", centerover);
ld t = ticks / anims::period;
t = t * t * (3 - 2 * t);
shift_view(ztangent(-(t - lastt) * d));
lastt = t;
spinEdge(100);
anims::moved();
});
anims::record_video();
delHook(anims::hooks_anim, lev);
}
void transition_test(ld t) {
auto _edok = edok();
auto cu = current();
auto vn = glhr::vnear_default;
auto vf = glhr::vfar_default;
sightranges[geometry] = 50 * t;
glhr::vnear_default = vn * t;
glhr::vfar_default = vf * t;
activate(lerp(_edok, cu, t));
}
void embset_list() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
dialog::init(XLAT("embset list"), 0xFFFFFFFF, 150, 0);
dialog::start_list(900, 900, '1');
for(auto& e: embsets) {
dialog::addItem(e.name, dialog::list_fake_key++);
dialog::add_action([&e] { activate(e); });
}
dialog::end_list();
dialog::addBack();
dialog::display();
}
void look_downwards() {
transmatrix T = View;
if(GDIM == 3) {
for(int i=0; i<3; i++) T[i][3] = T[3][i] = 0;
rotate_view(inverse(T));
ld x = T[3][0], y = T[3][1];
shift_view(point31(x+.5, y+.5, 0));
}
else {
for(int i=0; i<2; i++) T[i][2] = T[2][i] = 0;
rotate_view(inverse(T));
}
}
void show() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
dialog::init(XLAT("embchess"), 0xFFFFFFFF, 150, 0);
if(true) {
dialog::addItem("2D to 3D", 'a');
dialog::add_action(switch_fpp_fixed);
dialog::addItem("look downwards", 'l');
dialog::add_action(look_downwards);
}
if(true) {
dialog::addItem("save smoothcam animation", 's');
dialog::add_action([] { save_anim("emb/animation.sav"); });
}
if(true) {
dialog::addItem("load smoothcam animation", 'l');
dialog::add_action([] { load_anim("emb/animation.sav"); });
}
if(true) {
dialog::addItem("create smoothcam animation", 'c');
dialog::add_action([] { smoothcam::enable_and_show(); });
}
if(true) {
dialog::addBoolItem("run the animation", smoothcam::animate_on, 'r');
dialog::add_action([] {
smoothcam::animate_on = !smoothcam::animate_on;
smoothcam::last_time = HUGE_VAL;
});
}
if(true) {
dialog::addBoolItem("animation T0", false, 'a');
dialog::add_action([] { smoothcam::animate_on = false; smoothcam::handle_animation(0); });
dialog::addBoolItem("animation T1", false, 'b');
dialog::add_action([] { smoothcam::animate_on = false; smoothcam::handle_animation(1-1e-7); });
}
if(true) {
dialog::addSelItem("invert walls", fts(vid.wall_height), 'i');
dialog::add_action([] {
auto cur = current();
cur.walls = -cur.walls;
activate(cur);
});
}
if(true) {
dialog::addSelItem("closer to default", fts(geom3::euclid_embed_scale), '[');
dialog::add_action([] {
activate(lerp(edok(), current(), .99));
});
dialog::addSelItem("further from default", fts(geom3::euclid_embed_scale), ']');
dialog::add_action([] {
activate(lerp(edok(), current(), 1.01));
});
}
if(true) {
dialog::addItem("embset list", 'e');
dialog::add_action_push(embset_list);
}
if(true) {
dialog::addItem("print embset", 'p');
dialog::add_action([] {
embset e = current();
println(hlog, e);
});
}
if(false) {
dialog::addItem("transition to", 'u');
dialog::add_action([] { anims::videofile = "transition_to.mp4"; transition(0.01, 1, 60); });
}
if(false) {
dialog::addItem("transition from", 'i');
dialog::add_action([] { anims::videofile = "transition_from.mp4"; transition(1, 0.01, 60); });
}
if(true) {
static ld dist = 0;
dialog::addSelItem("measure forward distance", fts(dist), 'f');
dialog::add_action([] {
shift_view(ztangent(-0.2));
spinEdge(100);
dist += 0.2;
});
dialog::addSelItem("go backward", fts(dist), 'b');
dialog::add_action([] {
shift_view(ztangent(+0.05));
spinEdge(100);
dist += -0.05;
});
}
if(true) {
dialog::addItem("low range", 'r');
dialog::add_action([] { vid.cells_drawn_limit = 400; delete_sky(); });
dialog::addItem("mid range", 't');
dialog::add_action([] { vid.cells_drawn_limit = 2000; delete_sky(); });
dialog::addItem("high range", 'y');
dialog::add_action([] { vid.cells_drawn_limit = 20000; delete_sky(); });
dialog::addItem("extreme range", 'u');
dialog::add_action([] { vid.cells_drawn_limit = 200000; delete_sky(); });
dialog::addBoolItem_action("with models", with_models, 'm');
dialog::addBoolItem_action("with chess", with_chess, 'h');
dialog::addSelItem("draw the digger", its(draw_digger), 'g');
dialog::add_action([] { draw_digger = (1 + draw_digger) % 3; });
}
if(true) {
dialog::addSelItem("scaffolding X", its(scaffoldx), 'X');
dialog::add_action([] { scaffoldx = (1 + scaffoldx) % 3; });
dialog::addSelItem("scaffolding Y", its(scaffoldy), 'Y');
dialog::add_action([] { scaffoldy = (1 + scaffoldy) % 3; });
dialog::addSelItem("scaffolding B", its(scaffoldb), 'B');
dialog::add_action([] { scaffoldb = (1 + scaffoldb) % 3; });
dialog::addSelItem("no floor", ONOFF(no_floor), '<');
dialog::add_action([] { no_floor = !no_floor; mapeditor::drawplayer = false; build_map(); });
}
dialog::addBoolItem("move the cat", mapeditor::drawplayer, 'd');
dialog::add_action([] {
move_cat = true;
game_keys_scroll = false;
});
/* println(hlog, "sol = ", sol);
if(true) {
dialog::addItem("reset GL", 'r');
dialog::add_action([] { resetGL(); reset_all_shaders(); });
} */
dialog::addBack();
dialog::display();
}
void o_key(o_funcs& v) {
v.push_back(named_dialog("embchess options", show));
}
color_t domcol = 0xf8dba0;
color_t domcolf = 0x785b20;
color_t domroof = 0x802020;
color_t our_skycolor(cell *c) {
auto co = euc::full_coords2(c);
ld x = co.first * TAU / 20;
ld y = co.second * TAU / 20;
ld p = sin(x+2*y) + cos(3*x-y) + sin(x);
return gradient(0x4040FF, 0xFFFFFF, -3, p, 3);
}
bool chess_ceiling(celldrawer *cw) {
auto co = euc::full_coords2(cw->c);
if(co == gp::loc{0, 0})
draw_star(cw->V, cgi.shSun, 0xFFFF00FF);
if(domek2.count(cw->c)) {
color_t col = (domcol << 8) | 0xFF;
color_t wcol1 = (gradient(0, domcol, 0, .9, 1) << 8) | 0xFF;
color_t wcol2 = (gradient(0, domcol, 0, .8, 1) << 8) | 0xFF;
if(domek1.count(cw->c)) forCellIdEx(c2, i, cw->c) if(!domek1.count(c2)) {
placeSidewall(cw->c, i, SIDE_HIGH, cw->V, (i&1)?wcol1:wcol2);
placeSidewall(cw->c, i, SIDE_HIGH2, cw->V, (i&1)?wcol1:wcol2);
}
forCellIdEx(c2, i, cw->c) if(!domek2.count(c2)) {
placeSidewall(cw->c, i, SIDE_HIGH2, cw->V, (i&1)?wcol1:wcol2);
}
if(domek1.count(cw->c) != domek2.count(cw->c))
draw_shapevec(cw->c, cw->V, qfi.fshape->levels[SIDE_HIGH], col, PPR::REDWALL);
if(domek2.count(cw->c))
draw_shapevec(cw->c, cw->V, qfi.fshape->levels[SIDE_HIGH2], (domroof << 8) | 0xFF, PPR::REDWALL);
auto co = euc::full_coords2(cw->c);
int x = gmod(co.first, 20);
int y = gmod(co.second, 20);
char ch = xmap[y][x];
if(ch == 'O') {
placeSidewall(cw->c, 1, SIDE_HIGH, cw->V, 0xC0E0FFC0);
((dqi_poly&)(*ptds.back())).tinf = nullptr;
}
}
color_t skycol = our_skycolor(cw->c);
g_add_to_sky(cw->c, cw->V, skycol, skycol);
return true;
}
int cells_drawn = 50, split_qty = 1;
void build_map() {
for(cell *c: bac) {
c->land = laCanvas;
c->wall = waNone; // Chasm; // waNone;
c->item = itNone;
c->monst = moNone;
c->mpdist = 0;
c->landparam = 0x205020;
auto co = euc::full_coords2(c);
int x = gmod(co.first, 20);
int y = gmod(co.second, 20);
ac[x + 20*y + gmod(gdiv(co.first, 20), periods) * 400 + gmod(gdiv(co.second, 20), periods) * 400 * periods] = c;
char ch = xmap[y][x];
switch(ch) {
case 'x':
c->landparam = ((x+y) & 1) ? 0x807020 : 0xFFE080;
break;
case '1':
c->wall = waRed3;
domek2.insert(c);
c->landparam = domcol;
break;
case '2':
c->wall = waRed2;
break;
case '3':
c->wall = waRed3;
break;
case '#':
c->wall = waBarrier;
break;
case 'T':
c->wall = waCTree;
break;
case 'D':
c->wall = waWaxWall;
domek1.insert(c);
domek2.insert(c);
c->landparam = domcol;
break;
case 't':
case 'r':
case 'd':
c->wall = waNone;
domek2.insert(c);
c->landparam = domcolf;
break;
case '+':
c->wall = waNone;
domek2.insert(c);
c->landparam = domcol;
break;
case 'O':
c->wall = waWaxWall;
domek2.insert(c);
c->landparam = domcol;
break;
case 'u':
case 'v':
case '~':
c->wall = waShallow;
break;
case 'p':
c->land = laCrossroads;
floorcolors[laCrossroads] = 0x808080;
break;
// c->landparam = 0xC0C080;
case '>':
if(draw_digger) c->wall = waChasm;
break;
}
}
}
void enable() {
arg::shift(); hmul = arg::argf();
stop_game();
never_invert = true;
vid.wallmode = 3;
vid.monmode = 2;
geometry = gArchimedean;
variation = eVariation::pure;
arcm::current.parse("4^5");
start_game();
resetview();
View = spin(45._deg);
if(1) {
dynamicval<int> d(min_cells_drawn, cells_drawn);
// vid.cells_generated_limit = 9999;
// vid.cells_drawn_limit = 9999;
// vid.use_smart_range = 2;
drawthemap();
}
auto f = [] (hyperpoint h) { return deparabolic13(h); };
set<cell*> seen;
for(auto c: dcal) if(gmatrix.count(c)) {
map54_nodes.push_back(f(unshift(gmatrix[c]*C0)));
seen.insert(c);
}
for(auto c: dcal) if(seen.count(c)) forCellEx(c1, c) if(seen.count(c1)) if(c1<c) {
auto h = unshift(gmatrix[c]*C0);
auto h1 = unshift(gmatrix[c1]*C0);
int qty = split_qty;
vector<hyperpoint> hs(qty+1);
hs[0] = h; hs[qty] = h1;
for(int a=qty/2; a; a/=2) for(int i=0; i<qty; i+=a*2) hs[i+a] = mid(hs[i], hs[i+2*a]);
for(int i=0; i<=qty; i++) hs[i] = f(hs[i]);
for(int i=0; i<qty; i++) map54_edges.emplace_back(hs[i], hs[i+1]);
}
println(hlog, "map54: nodes = ", isize(map54_nodes), " edges = ", isize(map54_edges));
stop_game();
geometry = gSpace435;
start_game();
resetview();
if(1) {
dynamicval<int> d(min_cells_drawn, 500);
drawthemap();
bfs();
println(hlog, "dcal size = ", isize(dcal), " size map = ", isize(gmatrix));
}
seen.clear();
for(auto c: dcal) if(gmatrix.count(c)) {
map534_nodes.push_back(unshift(gmatrix[c]*C0));
seen.insert(c);
}
for(auto c: dcal) if(seen.count(c)) forCellEx(c1, c) if(seen.count(c1)) if(c1<c) {
map534_edges.emplace_back(unshift(gmatrix[c])*C0, unshift(gmatrix[c1])*C0);
}
stop_game();
// vid.cells_drawn_limit = 400;
if(!floor_textures) make_floor_textures();
auto& T0 = euc::eu_input.user_axes;
T0[0][0] = 20 * periods;
T0[1][1] = 20 * periods;
euc::eu_input.twisted = 0;
T0[0][1] = 0;
T0[1][0] = 0;
euc::build_torus3();
geometry = gEuclidSquare;
variation = eVariation::pure;
start_game();
bac = currentmap->allcells();
ac.resize(bac.size());
build_map();
rogueviz::rv_hook(hooks_drawcell, 100, draw_chess_at);
// rogueviz::rv_hook(hooks_frame, 100, [] { restart = true; });
rogueviz::rv_hook(hooks_ceiling, 100, chess_ceiling);
rogueviz::rv_hook(hooks_o_key, 80, o_key);
rogueviz::rv_hook(hooks_handleKey, 101, [] (int sym, int uni) {
if((cmode & sm::NORMAL) && uni == 't') {
vid.sspeed = 0;
playermoved = true;
fix_whichcopy(cwt.at);
// game_keys_scroll = true;
return true;
}
return false;
});
frustum_culling = false;
game_keys_scroll = true;
bright = true;
draw_sky = skyAlways;
vid.cells_generated_limit = 9999;
noshadow = true;
auto_remove_roofs = false;
vid.lake_top = 0.2;
simple_sky = true;
}
struct solv_grapher : rogueviz::pres::grapher {
solv_grapher(transmatrix U) : grapher(-2, -2, 12, 12) {
T = T * U;
using rogueviz::pres::p2;
for(int x=-1; x<=11; x++) if(x) {
line(p2(x,-2), p2(x,12), 0x8080FFFF);
line(p2(-2,x), p2(12,x), 0x8080FFFF);
}
vid.linewidth *= 2;
arrow(p2(0,-2), p2(0,12), .5);
arrow(p2(-2,0), p2(12,0), .5);
vid.linewidth /= 2;
}
};
ld geo_zero;
transmatrix xyzscale(ld x) {
transmatrix T = Id;
T[0][0] = T[1][1] = T[2][2] = x;
return T;
}
transmatrix solvscale(ld x) {
transmatrix T = Id;
T[0][0] *= exp(-x);
T[1][1] *= exp(x);
return T;
}
ld geodesic_t = 0;
void geodesic_screen(tour::presmode mode, int id) {
if(!params.count("geodesic_t")) param_f(geodesic_t, "geodesic_t");
using namespace rogueviz::pres;
if(mode == pmStart) geo_zero = ticks;
use_angledir(mode, id == 0);
static hyperpoint start, middle, target, nlh, nlh1, nlh2;
const ld coord = 10;
setCanvas(mode, '0');
if(mode == pmStart) {
slide_backup(pmodel);
slide_backup(pconf.clip_min);
slide_backup(pconf.clip_max);
slide_backup(vid.cells_drawn_limit);
stop_game(), pmodel = mdHorocyclic, geometry = gCubeTiling, variation = eVariation::pure, pconf.clip_min = -10000, pconf.clip_max = +100, start_game();
dynamicval<eGeometry> dg(geometry, gSol);
dynamicval<int> dr(nisot::rk_steps, 500);
ld x = coord;
start = C0;
middle = point31(0, x, 0);
auto bmiddle = point31(x, 0, 0);
target = point31(x, x, 0);
nlh = inverse_exp_newton(target, 200);
nlh[2] *= -1;
println(hlog, "best newton: ", hypot_d(3, nlh), " via ", nlh, " result ", nisot::numerical_exp(nlh));
nlh1 = inverse_exp(shiftless(middle));
nlh2 = inverse_exp(shiftless(bmiddle));
println(hlog, "intermediate: ", hypot_d(3, nlh1) * 2, " via ", nlh1);
println(hlog, "Pythagoras: ", x * sqrt(2));
}
add_stat(mode, [id, coord] {
cmode |= sm::SIDE;
calcparam();
vid.cells_drawn_limit = 0;
drawthemap();
// flat_model_enabler fme;
initquickqueue();
solv_grapher g(MirrorZ * ypush(5 * angle / 90._deg) * cspin(1, 2, .9 * angle / 90._deg) * spin(angle/2) * xyzscale(lerp(1, 0.8, angle / 90._deg)));
ld maxtime = 10 * sqrt(2) + 5;
auto frac_of = [&] (ld t, ld z) { return t - z * floor(t/z); };
ld t = inHighQual ? geodesic_t : frac_of((ticks - geo_zero) / 500, maxtime);
auto draw_path = [&] (auto f, color_t col) {
vid.linewidth *= 10;
for(ld t=0; t<=maxtime; t+=1/16.) curvepoint(f(t));
queuecurve(g.T, col, 0, PPR::LINE);
auto be_shadow = [&] (hyperpoint& h) {
// ld part = 1 - angle / 90._deg;
// h[0] += h[2] * part / 10;
h[2] = 0;
};
for(ld t=0; t<=25; t+=1/16.) {
hyperpoint h = f(t);
be_shadow(h);
curvepoint(h);
}
queuecurve(g.T, col & 0xFFFFFF40, 0, PPR::LINE);
vid.linewidth /= 10;
hyperpoint eaglepos = f(t);
hyperpoint next_eaglepos = f(t + 1e-2);
auto z = eaglepos[2];
// queuepolyat(g.pos(x+z * .1,y,1.5) * spin(s), cgi.shEagle, 0x40, PPR::MONSTER_SHADOW).outline = 0;
drawMonsterType(moEagle, nullptr, g.T * eupush(eaglepos) * solvscale(z) * rspintox(next_eaglepos - eaglepos) * xyzscale(2), col >> 8, t, 0);
be_shadow(eaglepos);
be_shadow(next_eaglepos);
auto& bp = cgi.shEagle;
if(bp.she > bp.shs && bp.she < bp.shs + 1000) {
auto& p = queuepolyat(g.T * eupush(eaglepos) * solvscale(z) * rspintox(next_eaglepos - eaglepos) * xyzscale(2), bp, 0x18, PPR::TRANSPARENT_SHADOW);
p.outline = 0;
p.subprio = -100;
p.offset = bp.shs;
p.cnt = bp.she - bp.shs;
p.flags &=~ POLY_TRIANGLES;
p.tinf = NULL;
return;
}
};
color_t pythagoras = 0xcd7f32FF;
color_t hyperb = 0xaaa9adFF;
color_t solv = 0xFFD500FF;
write_in_space(g.T * rgpushxto0(point31(-.5, -.5, 1)) * MirrorY * zpush(-1), 72, 1, "A", 0xFF);
write_in_space(g.T * rgpushxto0(point31(coord+.5, coord+.5, 1)) * MirrorY * zpush(-1), 72, 1, "B", 0xFF);
if(id >= 1) write_in_space(g.T * rgpushxto0(point31(0, coord+.5, 1)) * MirrorY * zpush(-1), 72, 1, "C", 0xFF);
if(id >= 0)
draw_path([&] (ld t) { return t < coord * sqrt(2) ? point31(t/sqrt(2), t/sqrt(2), 0) : target; }, pythagoras);
if(id >= 1)
draw_path([&] (ld t) {
ld len = hypot_d(3, nlh1);
dynamicval<eGeometry> g(geometry, gSol);
if(t < len)
return nisot::numerical_exp(nlh1 * t / len);
else if(t < len*2)
return rgpushxto0(middle) * nisot::numerical_exp(nlh2 * (t-len) / len);
else return target;
}, hyperb);
if(id >= 2)
draw_path([&] (ld t) {
ld len = hypot_d(3, nlh);
dynamicval<eGeometry> g(geometry, gSol);
if(t < len)
return nisot::numerical_exp(nlh * t / len);
else
return target;
}, solv);
auto cat = [] (PPR x) {
if(x == PPR::MONSTER_SHADOW) return 1;
else if(x == PPR::MONSTER_BODY) return 2;
else return 0;
};
for(int i=1; i<isize(ptds);)
if(i && cat(ptds[i]->prio) < cat(ptds[i-1]->prio)) {
swap(ptds[i], ptds[i-1]);
i--;
}
else i++;
quickqueue();
dialog::init();
dialog_may_latex("\\textsf{from $(0,0,0)$ to $(10,10,0)$}", "from (0,0,0) to (10,10,0)", forecolor, 150);
dialog::addBreak(100);
dialog_may_latex("\\textsf{XY plane}", "XY plane", pythagoras >> 8);
dialog_may_latex("\\textsf{$"+fts(coord)+"\\sqrt{2}$ (Pythagoras)}", fts(coord) + "√2 (Pythagoras)", pythagoras >> 8);
ld len = coord * sqrt(2);
dialog_may_latex("\\textsf{$" + fts(len) + "$}", fts(len), pythagoras >> 8);
if(id >= 1) {
dialog::addBreak(100);
dialog_may_latex("\\textsf{YZ + XZ}", "YZ + XZ", hyperb >> 8);
dialog_may_latex("\\textsf{hyperbolic geodesics}", "hyperbolic geodesics", hyperb >> 8);
ld len = 2 * hypot_d(3, nlh1);
dialog_may_latex("\\textsf{$" + fts(len) + "$}", fts(len), hyperb >> 8);
}
else dialog::addBreak(300);
if(id >= 2) {
dialog::addBreak(100);
dialog_may_latex("\\textsf{optimal}", "optimal", solv >> 8);
dialog_may_latex("\\textsf{no sharp bends}", "no sharp bends", solv >> 8);
ld len = hypot_d(3, nlh);
dialog_may_latex("\\textsf{$"+fts(len)+"$}", fts(len), solv >> 8);
}
else dialog::addBreak(300);
dialog::display();
return false;
});
}
ld square_diagram_size = 10;
void enable_square_diagram() {
param_f(square_diagram_size, "square_diagram_size");
rogueviz::rv_hook(hooks_frame, 100, [] {
auto p = [] (ld x, ld y) { return hpxy(x, y); };
for(int i=0; i<4; i++) {
ld si = square_diagram_size;
ld big = 100;
curvepoint(p(si, big));
curvepoint(p(si, -big));
curvepoint(p(big, -big));
curvepoint(p(big, big));
curvepoint(p(si, big));
queuecurve(shiftless(Id) * cspin(0, 1, i*90._deg), 0, 0xFF, PPR::CIRCLE).flags |= POLY_ALWAYS_IN;
}
});
}
using namespace rogueviz::pres;
string defs =
"\\def\\map{m}"
"\\def\\VofH{V}"
"\\def\\dist{\\delta}"
"\\def\\ra{\\rightarrow}"
"\\def\\bbH{\\mathbb{H}}"
"\\def\\bbE{\\mathbb{E}}"
"\\renewcommand{\\rmdefault}{\\sfdefault}\\sf"
;
slide solv_slides[] = {
{"from A to B in Solv 1", 999, LEGAL::NONE | QUICKGEO | NOTITLE,
"not written"
,
[] (presmode mode) {
println(hlog, "A mode ", int(mode));
empty_screen(mode);
geodesic_screen(mode, 0);
no_other_hud(mode);
}
},
{"from A to B in Solv 2", 999, LEGAL::NONE | QUICKGEO | NOTITLE,
"not written"
,
[] (presmode mode) {
println(hlog, "B mode ", int(mode));
empty_screen(mode);
geodesic_screen(mode, 1);
no_other_hud(mode);
}
},
{"from A to B in Solv 3", 999, LEGAL::NONE | QUICKGEO | NOTITLE,
"not written"
,
[] (presmode mode) {
println(hlog, "C mode ", int(mode));
empty_screen(mode);
geodesic_screen(mode, 2);
no_other_hud(mode);
}
},
{"Euler's polyhedron formula", 999, LEGAL::NONE | QUICKGEO | USE_SLIDE_NAME | NOTITLE,
"-show the formula",
[] (presmode mode) {
latex_slide(mode, defs+R"=(
{\color{remph}Euler's polyhedron formula: }
\begin{itemize}
\item $F+V-E = 2$
\item $F$ -- the number of {\color{remph}faces} (square grid: the number of squares $n$)
\item $V$ -- the number of {\color{remph}vertices} (square grid: also $n$)
\item $E$ -- the number of {\color{remph}edges} (square grid: $2n$)
\item $F + V - E = n + n - 2n = 0 = 2$
\end{itemize}
)=", sm::NOSCR, 150);
}},
{"final slide", 123, LEGAL::ANY | NOTITLE | QUICKSKIP | FINALSLIDE,
"FINAL SLIDE",
[] (presmode mode) {
empty_screen(mode);
add_stat(mode, [] {
dialog::init();
color_t d = dialog::dialogcolor;
dialog::addTitle("Thanks for your attention!", 0xC00000, 200);
dialog::addBreak(100);
dialog::addTitle("twitter.com/zenorogue/", d, 150);
dialog::display();
return true;
});
no_other_hud(mode);
}
},
};
auto embchess_ah =
arg::add3("-embchess", enable)
+ arg::add3("-embperiods", [] { arg::shift(); periods = arg::argi(); })
+ arg::add3("-emb-noceil", [] {
rogueviz::rv_hook(hooks_ceiling, 100, [] (celldrawer*) { return true; });
})
+ arg::add3("-chessmul", [] { arg::shift(); hmul = arg::argf(); })
+ arg::add3("-embset", [] {
arg::shift(); string ss = arg::args();
for(auto& e: embsets) if(appears(e.name, ss)) activate(e);
})
+ arg::add3("-embscaffold", [] {
arg::shift(); scaffoldx = arg::argi();
arg::shift(); scaffoldy = arg::argi();
arg::shift(); scaffoldb = arg::argi();
})
+ arg::add3("-embscaffold-move", [] {
arg::shift(); scaffoldx_move = arg::argi();
arg::shift(); scaffoldy_move = arg::argi();
})
+ arg::add3("-embwchess", [] { with_chess = !with_chess; })
+ arg::add3("-embfix", [] { arg::shift(); fix_chess = arg::argf(); })
+ arg::add3("-embwmodel", [] { with_models = !with_models; })
+ arg::add3("-embwmlight", [] { with_models = true; light_models = true; })
+ arg::add3("-embwdig", [] { arg::shift(); draw_digger = arg::argi(); })
+ arg::add3("-embload", [] { arg::shift(); load_anim(arg::args()); })
+ arg::add3("-embappend", [] { arg::shift(); append_anim(arg::args()); })
+ arg::add3("-embsave", [] { arg::shift(); save_anim(arg::args()); })
+ arg::add3("-embt0", [] { smoothcam::animate_on = false; smoothcam::handle_animation(0); playermoved = false; })
+ arg::add3("-embt1", [] { smoothcam::animate_on = false; smoothcam::handle_animation(1-1e-7); playermoved = false; })
+ arg::add3("-embmin", [] { arg::shift(); cells_drawn = arg::argi(); })
+ arg::add3("-emb-chess-moves", [] { arg::shift(); chess_moves = arg::argi(); })
+ arg::add3("-emb-sqd", enable_square_diagram)
+ arg::add3("-embtrans-test", [] { arg::shift(); transition_test(arg::argf()); })
+ arg::add3("-emb-no-floor", [] { no_floor = true; })
+ arg::add3("-embtrans", [] {
arg::shift(); anims::videofile = arg::args();
arg::shift(); ld a = arg::argf();
arg::shift(); ld b = arg::argf();
arg::shift(); int t = arg::argi();
transition(a, b, t);
})
+ arg::add3("-avp", [] { semidirect_rendering = true; vid.consider_shader_projection = false; })
+ arg::add3("-embforward", [] {
arg::shift(); int t = arg::argi();
arg::shift(); anims::videofile = arg::args();
arg::shift(); ld d = arg::argf();
animate_forward(d, t);
})
+ arg::add3("-emb-goforward", [] {
arg::shift(); ld d = arg::argf();
for(int i=0; i<1000; i++) {
shift_view(ztangent(-d / 1000.));
optimizeview();
spinEdge(100);
}
});
;
auto embchess_show =
addHook_slideshows(100, [] (tour::ss::slideshow_callback cb) {
cb(XLAT("Solv geodesics"), &solv_slides[0], 'S');
});
}}