From 86492d1181a2ae68510eac006ad942c373c765d3 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sun, 25 Dec 2022 12:14:36 +0100 Subject: [PATCH] Improved the UI for 'geodesic movement' setting, and also make it work correctly in SL2 and hyperbolic geometries --- config.cpp | 7 ++++- drawing.cpp | 4 +-- geom-exp.cpp | 9 ++---- graph.cpp | 7 +++-- hyperpoint.cpp | 7 +++-- hypgraph.cpp | 79 ++++++++++++++++++++++++++++++++++++------------ nonisotropic.cpp | 4 +-- radar.cpp | 2 +- shaders.cpp | 6 ++-- vr.cpp | 3 +- 10 files changed, 84 insertions(+), 44 deletions(-) diff --git a/config.cpp b/config.cpp index 28083612..738486bf 100644 --- a/config.cpp +++ b/config.cpp @@ -1111,7 +1111,12 @@ EX void initConfig() { addsaver(bounded_mine_percentage, "bounded_mine_percentage"); - param_b(nisot::geodesic_movement, "solv_geodesic_movement", true); + param_enum(nisot::geodesic_movement, "solv_geodesic_movement", "solv_geodesic_movement", true) + -> editable({{"Lie group", "light, camera, and objects move in lines of constant direction, in the Lie group sense"}, {"geodesics", "light, camera, and objects always take the shortest path"}}, "straight lines", 'G') + -> set_reaction([] { + if(pmodel == mdLiePerspective && nisot::geodesic_movement) pmodel = hyperbolic ? mdPerspective : mdGeodesic; + if(among(pmodel, mdGeodesic, mdPerspective) && !nisot::geodesic_movement) pmodel = mdLiePerspective; + }); addsaver(s2xe::qrings, "s2xe-rings"); addsaver(rots::underlying_scale, "rots-underlying-scale"); diff --git a/drawing.cpp b/drawing.cpp index 48c7a7d7..dc20ee6e 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -482,9 +482,9 @@ bool behind3(shiftpoint h) { if(pmodel == mdGeodesic) return lp_apply(inverse_exp(h))[2] < 0; if(pmodel == mdLiePerspective) - return lp_apply(lie_log(unshift(h)))[2] < 0; + return lp_apply(lie_log(h))[2] < 0; if(pmodel == mdRelPerspective) - return lp_apply(rel_log(h))[2] < 0; + return lp_apply(rel_log(h, false))[2] < 0; return h[2] < 0; } diff --git a/geom-exp.cpp b/geom-exp.cpp index 904a0c99..8f0afb4b 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -1108,13 +1108,8 @@ EX void showEuclideanMenu() { dialog::add_action_push(show3D); } menuitem_projection('1'); - if(nonisotropic && !sl2 && !embedded_plane) { - dialog::addBoolItem(XLAT("geodesic movement in Sol/Nil"), nisot::geodesic_movement, 'G'); - dialog::add_action([] { - nisot::geodesic_movement = !nisot::geodesic_movement; - if(pmodel == mdLiePerspective && nisot::geodesic_movement) pmodel = mdGeodesic; - if(pmodel == mdGeodesic && !nisot::geodesic_movement) pmodel = mdLiePerspective; - }); + if(lie_movement_available()) { + add_edit(nisot::geodesic_movement); } #if CAP_CRYSTAL && MAXMDIM >= 4 crystal::add_crystal_transform('x'); diff --git a/graph.cpp b/graph.cpp index 3cce1ab0..04f39cc6 100644 --- a/graph.cpp +++ b/graph.cpp @@ -4093,7 +4093,7 @@ void make_clipping_planes() { sx /= hypot_d(3, sx); sx[3] = 0; sx = T * sx; - if(nisot::local_perspective_used()) sx = ortho_inverse(nlp) * sx; + if(nisot::local_perspective_used) sx = ortho_inverse(nlp) * sx; clipping_plane_sets.back().push_back(sx); }; @@ -5059,6 +5059,8 @@ EX ld wall_radar(cell *c, transmatrix T, transmatrix LPe, ld max) { EX bool nonisotropic_weird_transforms; EX void make_actual_view() { + nisot::local_perspective_used = gproduct; + if(!nisot::local_perspective_used) NLP = Id; sphereflip = Id; sphere_flipped = flip_sphere(); if(sphere_flipped) sphereflip[LDIM][LDIM] = -1; @@ -5083,11 +5085,12 @@ EX void make_actual_view() { camera_sign = cgi.FLOOR > cgi.WALL; } - if(nonisotropic && !nonisotropic_weird_transforms) { + if((nonisotropic || (hyperbolic && bt::in() && !nisot::geodesic_movement)) && !nonisotropic_weird_transforms) { transmatrix T = actual_view_transform * View; transmatrix T2 = eupush( tC0(view_inverse(T)) ); NLP = T * T2; actual_view_transform = ortho_inverse(NLP) * actual_view_transform; + nisot::local_perspective_used = true; } #endif #if MAXMDIM >= 4 diff --git a/hyperpoint.cpp b/hyperpoint.cpp index 65ecc2db..ed61ba0a 100644 --- a/hyperpoint.cpp +++ b/hyperpoint.cpp @@ -731,6 +731,7 @@ EX transmatrix euscale3(ld x, ld y, ld z) { EX transmatrix eupush(hyperpoint h, ld co IS(1)) { if(nonisotropic) return nisot::translate(h, co); + if(hyperbolic) { return co ? parabolic13_at(deparabolic13(h)) : inverse(parabolic13_at(deparabolic13(h))); } transmatrix T = Id; for(int i=0; i= 1 && flat_on + val < 1) { geometry = backup_geometry; variation = backup_variation; + nisot::local_perspective_used = backup_lpu; vid = backup_vid; geom3::apply_always3(); calcparam(); @@ -3121,6 +3117,20 @@ EX hyperpoint lie_exp(hyperpoint h) { h[1] *= (exp(+z) - 1) / z; } } + else if(sl2) { + h[3] = 0; + ld v = h[0] * h[0] + h[1] * h[1] - h[2] * h[2]; + if(v > 0) { + h *= sin(v) / sqrt(v); + h[3] += cos(v); + } + else if(v < 0) { + h *= sinh(v) / sqrt(-v); + h[3] += cosh(v); + } + else h[3]++; + return h; + } else { /* not implemented -- approximate for now */ const int steps = 16; @@ -3134,7 +3144,11 @@ EX hyperpoint lie_exp(hyperpoint h) { return h; } -EX hyperpoint rel_log(shiftpoint h) { +/** With relativistic_length off, compute the Lie logarithm in SL(2,R) or de Sitter space. + * With relativistic_length on, this corresponds to a geodesic in AdS/dS, so make it as long as the length of the geodesic in AdS/dS space. + **/ + +EX hyperpoint rel_log(shiftpoint h, bool relativistic_length) { if(sl2) { optimize_shift(h); ld cycles = floor(h.shift / TAU + .5); @@ -3148,6 +3162,7 @@ EX hyperpoint rel_log(shiftpoint h) { z += cycles * TAU; } else if(cycles || h1[3] < -1 || choice == 0) { + if(!relativistic_length) return h1 - C0; /* impossible, or light-like */ r = 1; z = 0; } @@ -3155,6 +3170,7 @@ EX hyperpoint rel_log(shiftpoint h) { r = sqrt(-choice); z = asinh(r); } + if(!relativistic_length) r = sqhypot_d(3, h1); h1 = h1 * z / r; h1[3] = 0; return h1; @@ -3165,13 +3181,22 @@ EX hyperpoint rel_log(shiftpoint h) { ld r, z; if(choice > 0) { r = sqrt(choice); z = asinh(r); } else { r = sqrt(-choice); z = asin_clamp(r); if(h1[2] < 0) z = M_PI - z; } + if(!relativistic_length) r = sqrt(h1[3] * h1[3] + h1[0] * h1[0] + h1[1] * h1[1]); h1 = h1 * z / r; h1[2] = h1[3]; h1[3] = 0; return h1; } throw hr_exception("rel_log in wrong geometry"); } -EX hyperpoint lie_log(hyperpoint h) { +/** Is Lie movement available? Depends on map geometry, not ambient geometry. */ +EX bool lie_movement_available() { + if(nonisotropic && !embedded_plane) return true; + if(mhyperbolic && bt::in()) return true; + return false; + }; + +EX hyperpoint lie_log(const shiftpoint h1) { + hyperpoint h = unshift(h1); if(nil) { h[3] = 0; h[2] -= h[0] * h[1] / 2; @@ -3210,12 +3235,26 @@ EX hyperpoint lie_log(hyperpoint h) { for(int i=1; i makeradar(shiftpoint h) { else if(sl2) h1 = slr::get_inverse_exp(h); else h1 = unshift(h); - if(nisot::local_perspective_used() && !embedded_plane) { + if(nisot::local_perspective_used && !embedded_plane) { h1 = NLP * h1; } diff --git a/shaders.cpp b/shaders.cpp index d3b02f3a..848694bb 100644 --- a/shaders.cpp +++ b/shaders.cpp @@ -660,7 +660,7 @@ void display_data::set_projection(int ed, ld shift) { } else M[2][2] /= 10000; glhr::projection_multiply(M); - if(nisot::local_perspective_used() && (shader_flags & SF_BOX)) + if(nisot::local_perspective_used && (shader_flags & SF_BOX)) glhr::projection_multiply(glhr::tmtogl_transpose(NLP)); if(ed && vid.stereo_mode != sODS) { glhr::glmatrix m = glhr::id; @@ -712,7 +712,7 @@ void display_data::set_projection(int ed, ld shift) { else { glhr::projection_multiply(glhr::frustum(cd->tanfov, cd->tanfov * cd->ysize / cd->xsize)); glhr::projection_multiply(glhr::scale(1, -1, -1)); - if(nisot::local_perspective_used()) { + if(nisot::local_perspective_used) { if(gproduct) { for(int i=0; i<3; i++) NLP[3][i] = NLP[i][3] = 0; NLP[3][3] = 1; @@ -758,7 +758,7 @@ void display_data::set_projection(int ed, ld shift) { pp = pp * pp0; - if(nisot::local_perspective_used()) + if(nisot::local_perspective_used) pp = glhr::tmtogl_transpose(NLP) * pp; if(get_shader_flags() & SF_ORIENT) { diff --git a/vr.cpp b/vr.cpp index 455003e7..3fc7374d 100644 --- a/vr.cpp +++ b/vr.cpp @@ -1007,10 +1007,9 @@ EX void gen_mv() { if(!pers) mu[1][1] *= pconf.stretch; hmd_mv = Id; - bool nlpu = nisot::local_perspective_used(); if(1) { E4; - if(nlpu) { + if(nisot::local_perspective_used) { be_33(NLP); hmd_mv = NLP * hmd_mv; }