From 2182f442d926a3717194d01cfcd7bd2c61e800cd Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Thu, 5 Jan 2023 14:01:23 +0100 Subject: [PATCH] more detailed Euclidean embedding parameters --- config.cpp | 17 +++++++++++++++-- geometry.cpp | 38 ++++++++++++++++++++++++++++++++++++-- graph.cpp | 4 ++-- hyperpoint.cpp | 31 ++++++++++--------------------- hypgraph.cpp | 6 +++--- 5 files changed, 66 insertions(+), 30 deletions(-) diff --git a/config.cpp b/config.cpp index 2aa47254..6ed30dda 100644 --- a/config.cpp +++ b/config.cpp @@ -838,10 +838,19 @@ EX void initConfig() { addsaver(vid.always3, "3D always", false); param_f(geom3::euclid_embed_scale, "euclid_embed_scale", "euclid_embed_scale") - -> editable(0, 2, 0.05, "Euclidean embedding scale", "How to scale the Euclidean map, relatively to the 3D absolute unit.", 'F') + -> editable(0, 2, 0.05, "Euclidean embedding scale", "How to scale the Euclidean map, relatively to the 3D absolute unit.", 'X') -> set_sets([] { dialog::bound_low(0.05); }) -> set_reaction([] { if(vid.always3) { geom3::switch_fpp(); geom3::switch_fpp(); } }); + param_f(geom3::euclid_embed_scale_y, "euclid_embed_scale_y", "euclid_embed_scale_y") + -> editable(0, 2, 0.05, "Euclidean embedding scale Y/X", "This scaling factor affects only the Y coordinate.", 'Y') + -> set_sets([] { dialog::bound_low(0.05); }) + -> set_reaction([] { if(vid.always3) { geom3::switch_fpp(); geom3::switch_fpp(); } }); + + param_f(geom3::euclid_embed_rotate, "euclid_embed_rotate", "euclid_embed_rotate") + -> editable(0, 360, 15, "Euclidean embedding rotation", "How to rotate the Euclidean embedding, in degrees.", 'F') + -> set_reaction([] { if(vid.always3) { geom3::switch_fpp(); geom3::switch_fpp(); } }); + param_enum(embedded_shift_method_choice, "embedded_shift_method", "embedded_shift_method", smcBoth) -> editable({ {"geodesic", "always move on geodesics"}, @@ -2316,7 +2325,11 @@ EX void show3D() { } if(WDIM == 2) { - if(geom3::euc_in_noniso()) add_edit(geom3::euclid_embed_scale); + if(geom3::euc_in_noniso()) { + add_edit(geom3::euclid_embed_scale); + add_edit(geom3::euclid_embed_scale_y); + add_edit(geom3::euclid_embed_rotate); + } add_edit(embedded_shift_method_choice); add_edit(vid.camera); if(GDIM == 3) diff --git a/geometry.cpp b/geometry.cpp index 16b5883b..a6294c03 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -200,6 +200,12 @@ struct geometry_information { int base_distlimit; + /* convert the tangent space in logical coordinates to actual coordinates */ + transmatrix logical_to_actual; + + /* convert the tangent space in actual coordinates to logical coordinates */ + transmatrix actual_to_logical; + /** size of the Sword (from Orb of the Sword), used in the shmup mode */ ld sword_size; /** scale factor for the graphics of most things*/ @@ -440,6 +446,8 @@ hpcshape void prepare_shapes(); void prepare_usershapes(); + void prepare_lta(); + void hpcpush(hyperpoint h); void hpc_connect_ideal(hyperpoint a, hyperpoint b); void hpcsquare(hyperpoint h1, hyperpoint h2, hyperpoint h3, hyperpoint h4); @@ -577,6 +585,21 @@ EX bool is_reg3_variation(eVariation var) { return var == eVariation::coxeter; } +void geometry_information::prepare_lta() { + auto& lta = logical_to_actual; + lta = Id; + if(embedded_plane) { + if(geom3::euc_in_noniso()) { + lta[0][0] *= geom3::euclid_embed_scale; + lta[1][1] *= geom3::euclid_embed_scale * geom3::euclid_embed_scale_y; + lta = cspin(0, 1, geom3::euclid_embed_rotate * degree) * lta; + } + if(geom3::euc_in_nil()) lta = cspin90(2, 1) * lta; + if(geom3::hyp_in_solnih()) lta = cspin90(0, 1) * cspin90(1, 2) * cspin90(0, 1) * lta; + } + actual_to_logical = inverse(lta); + } + void geometry_information::prepare_basics() { DEBBI(DF_INIT | DF_POLY | DF_GEOM, ("prepare_basics")); @@ -593,6 +616,8 @@ void geometry_information::prepare_basics() { xp_order = 0; + prepare_lta(); + if(arcm::in() && !mproduct) ginf[gArchimedean].cclass = gcHyperbolic; @@ -1023,7 +1048,7 @@ EX namespace geom3 { reduce = (GDIM == 3 ? human_height * .3 : 0); int sgn = vid.wall_height > 0 ? 1 : -1; - ld ees = geom3::euc_in_noniso() ? geom3::euclid_embed_scale : 1; + ld ees = geom3::euc_in_noniso() ? geom3::euclid_embed_scale_mean() : 1; STUFF = lev_to_factor(0) - sgn * max(orbsize * ees * 0.3, zhexf * ees * .6); @@ -1099,10 +1124,15 @@ EX namespace geom3 { EX eSpatialEmbedding spatial_embedding = seDefault; EX ld euclid_embed_scale = 1; + EX ld euclid_embed_scale_y = 1; + EX ld euclid_embed_rotate = 0; EX bool auto_configure = true; EX bool flat_embedding = false; EX bool inverted_embedding = false; + EX ld euclid_embed_scale_mean() { return euclid_embed_scale * sqrt(euclid_embed_scale_y); } + EX void set_euclid_embed_scale(ld x) { euclid_embed_scale = x; euclid_embed_scale_y = 1; euclid_embed_rotate = 0; } + EX bool supports_flat() { return spatial_embedding == seDefault; } EX bool supports_invert() { return among(spatial_embedding, seDefault, seLowerCurvature, seMuchLowerCurvature, seNil, seSol, seNIH, seSolN); } @@ -1480,7 +1510,11 @@ EX string cgi_string() { if(embedded_plane) V("X:", its(geom3::ggclass())); - if(embedded_plane && meuclid) V("XS:", fts(geom3::euclid_embed_scale)); + if(embedded_plane && meuclid) { + V("XS:", fts(geom3::euclid_embed_scale)); + V("YS:", fts(geom3::euclid_embed_scale_y)); + V("RS:", fts(geom3::euclid_embed_rotate)); + } if(scale_used()) V("CS", fts(vid.creature_scale)); diff --git a/graph.cpp b/graph.cpp index 04f39cc6..3ca4e5f5 100644 --- a/graph.cpp +++ b/graph.cpp @@ -5099,13 +5099,13 @@ EX void make_actual_view() { transmatrix T = actual_view_transform * View; ld z = -tC0(view_inverse(T)) [2]; transmatrix R = actual_view_transform; - R = (logical_to_actual()) * R; + R = cgi.logical_to_actual * R; if(R[1][2] || R[2][2]) R = cspin(1, 2, -atan2(R[1][2], R[2][2])) * R; if(R[0][2] || R[2][2]) R = cspin(0, 2, -atan2(R[0][2], R[2][2])) * R; if(geom3::hyp_in_solnih()) R = Id; - R = inverse(logical_to_actual()) * R; + R = cgi.actual_to_logical * R; current_display->radar_transform = inverse(R) * zpush(-z); } else if(gproduct) { diff --git a/hyperpoint.cpp b/hyperpoint.cpp index 5ecf1da6..2f024a27 100644 --- a/hyperpoint.cpp +++ b/hyperpoint.cpp @@ -665,14 +665,8 @@ EX transmatrix spin(ld alpha) { return cspin(0, 1, alpha); } -EX transmatrix logical_to_actual() { - if(embedded_plane && geom3::euc_in_nil()) return cspin90(2, 1); - if(embedded_plane && geom3::hyp_in_solnih()) return cspin90(0, 1) * cspin90(1, 2) * cspin90(0, 1); - return Id; - } - EX transmatrix unswap_spin(transmatrix T) { - return ortho_inverse(logical_to_actual()) * T * logical_to_actual(); + return cgi.actual_to_logical * T * cgi.logical_to_actual; } /** rotate by 90 degrees in the XY plane */ @@ -896,11 +890,6 @@ EX transmatrix matrix4(ld a, ld b, ld c, ld d, ld e, ld f, ld g, ld h, ld i, ld #endif } -EX void euc_in_sph_rescale(hyperpoint& h) { - h[0] *= TAU * geom3::euclid_embed_scale; - h[1] *= TAU * geom3::euclid_embed_scale; - } - #if MAXMDIM >= 4 /** Transform a matrix between the 'embedded_plane' and underlying representation. Switches to the current variant. */ EX void swapmatrix(transmatrix& T) { @@ -926,17 +915,17 @@ EX void swapmatrix(transmatrix& T) { } else if(geom3::euc_in_nil()) { if(!geom3::flipped) { - hyperpoint h1 = get_column(T, 2); + hyperpoint h1 = cgi.logical_to_actual * get_column(T, 2); // rotations are illegal anyway... - T = eupush(hyperpoint(h1[0] * geom3::euclid_embed_scale, 0, h1[1] * geom3::euclid_embed_scale, 1)); + T = eupush(hyperpoint(h1[0], 0, h1[2], 1)); return; } } else if(geom3::euc_in_solnih()) { if(!geom3::flipped) { - hyperpoint h1 = get_column(T, 2); + hyperpoint h1 = cgi.logical_to_actual * get_column(T, 2); // rotations are illegal anyway... - T = eupush(hyperpoint(h1[0] * geom3::euclid_embed_scale, h1[1] * geom3::euclid_embed_scale, 0, 1)); + T = eupush(hyperpoint(h1[0], h1[1], 0, 1)); return; } } @@ -944,8 +933,7 @@ EX void swapmatrix(transmatrix& T) { /* just do nothing */ } else if(geom3::euc_in_sph()) { - hyperpoint h1 = get_column(T, 2); - euc_in_sph_rescale(h1); + hyperpoint h1 = cgi.logical_to_actual * get_column(T, 2); T = cspin(0, 2, h1[0]) * cspin(1, 3, h1[1]); } else { @@ -965,12 +953,13 @@ EX void swapmatrix(hyperpoint& h) { if(geom3::in_product()) return; if(geom3::sph_in_euc()) { h[3] = 1; return; } if(geom3::sph_in_hyp()) { h[0] *= sinh(1); h[1] *= sinh(1); h[2] *= sinh(1); h[3] = cosh(1); return; } - if(geom3::euc_in_nil()) { h[3] = 1; h[2] = h[1] * geom3::euclid_embed_scale; h[1] = 0; h[0] *= geom3::euclid_embed_scale; return; } + if(geom3::euc_in_nil()) { h = cgi.logical_to_actual * h; h[3] = 1; h[1] = 0; return; } if(geom3::euc_in_sph()) { - euc_in_sph_rescale(h); h = cspin(0, 2, h[0]) * cspin(1, 3, h[1]) * lzpush(1) * C0; + h = cgi.logical_to_actual * h; + h = cspin(0, 2, h[0]) * cspin(1, 3, h[1]) * lzpush(1) * C0; return; } - if(geom3::euc_in_solnih()) { h[3] = 1; h[1] = h[1] * geom3::euclid_embed_scale; h[2] = 0; h[0] *= geom3::euclid_embed_scale; return; } + if(geom3::euc_in_solnih()) { h = cgi.logical_to_actual * h; h[3] = 1; h[2] = 0; return; } if(geom3::hyp_in_solnih()) { // copied from deparabolic13 h /= (1 + h[2]); diff --git a/hypgraph.cpp b/hypgraph.cpp index a2380746..c8ce1dfe 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -2036,11 +2036,11 @@ EX void adjust_eye(transmatrix& T, cell *c, ld sign) { /** achieve top-down perspective */ EX transmatrix default_spin() { - return cspin90(0, 1) * inverse(logical_to_actual()); + return cspin90(0, 1) * cgi.actual_to_logical; } EX void centerpc(ld aspd) { - + if(subscreens::split([=] () {centerpc(aspd);})) return; if(dual::split([=] () { centerpc(aspd); })) return; @@ -2239,7 +2239,7 @@ EX void resetview() { if(WDIM == 2) View = spin(M_PI + vid.fixed_facing_dir * degree) * View; if(WDIM == 3 && !gproduct) View = cspin90(0, 2) * View; if(gproduct) NLP = cspin90(0, 2); - View = inverse(logical_to_actual()) * View; + View = cgi.actual_to_logical * View; if(embedded_plane) get_view_orientation() = cspin90(1, 2) * get_view_orientation(); if(embedded_plane && vid.wall_height < 0) View = cspin180(0, 1) * View;