From 6d554d6b2ec7a74fb99a6040769404a901f26c4f Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sun, 27 Mar 2022 14:32:29 +0200 Subject: [PATCH] multi:: two-focus projections --- graph.cpp | 38 ++++++++++++++++++++++++-------------- hyper.h | 2 ++ hypgraph.cpp | 21 +++++++++++++++++++++ models.cpp | 6 ++++++ multi.cpp | 15 ++++++++++++--- 5 files changed, 65 insertions(+), 17 deletions(-) diff --git a/graph.cpp b/graph.cpp index 972c3e3f..38557afd 100644 --- a/graph.cpp +++ b/graph.cpp @@ -4918,6 +4918,21 @@ EX transmatrix Viewbase; EX bool no_wall_rendering; +EX bool set_multi = false; +EX hyperpoint multi_point; + +EX void center_multiplayer_map(const vector& hs) { + hyperpoint h = Hypc; + for(auto h1: hs) h += h1; + h /= isize(hs); + h = normalize(h); + cwtV = shiftless(rgpushxto0(h)); + if(isize(hs) == 2) { + set_multi = true; + multi_point = hs[1]; + } + } + EX void drawthemap() { check_cgi(); cgi.require_shapes(); @@ -5032,6 +5047,7 @@ EX void drawthemap() { drawFlashes(); mapeditor::draw_dtshapes(); + set_multi = false; if(multi::players > 1 && !shmup::on) { if(multi::split_screen) @@ -5039,13 +5055,10 @@ EX void drawthemap() { else if(multi::centerplayer != -1) cwtV = multi::whereis[multi::centerplayer]; else { - hyperpoint h = Hypc; - for(int p=0; p pts; + for(int p=0; ppat; else { - hyperpoint h = Hypc; - for(int p=0; ppat)); - h += h1; - } - h = mid(h, h); - cwtV = shiftless(rgpushxto0(h)); + vector pts; + for(int p=0; ppat))); + center_multiplayer_map(pts); } } diff --git a/hyper.h b/hyper.h index a307313e..f0902e50 100644 --- a/hyper.h +++ b/hyper.h @@ -266,6 +266,7 @@ struct projection_configuration { ld depth_scaling; ld hyperboloid_scaling; ld vr_angle, vr_zshift, vr_scale_factor; + bool dualfocus_autoscale; int back_and_front; /* 0 = do not, 1 = do, 2 = only back */ @@ -289,6 +290,7 @@ struct projection_configuration { vr_zshift = 0; vr_scale_factor = 1; back_and_front = 0; + dualfocus_autoscale = false; } }; diff --git a/hypgraph.cpp b/hypgraph.cpp index 1768a73c..3a4dd281 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -947,6 +947,9 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) { if(pmodel == mdJoukowskyInverted) { ld r2 = sqhypot_d(2, ret); + if(pconf.dualfocus_autoscale) + ret *= (1-pconf.model_transition) / 2; + ret[0] = ret[0] / r2; ret[1] = -ret[1] / r2; move_y_to_z(ret, yz); @@ -1315,11 +1318,18 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) { } case mdPanini: { + find_zlev(H); + models::apply_orientation_yz(H[1], H[2]); + models::apply_orientation(H[0], H[1]); + ld proh = sqrt(H[2]*H[2] + curvature() * H[0] * H[0]); H /= proh; H /= (H[2] + pconf.alpha); ret = H; ret[2] = 0; ret[3] = 1; + + models::apply_orientation(ret[1], ret[0]); + models::apply_orientation_yz(ret[2], ret[1]); break; } @@ -1998,6 +2008,17 @@ EX void centerpc(ld aspd) { spinEdge(aspd); } + if(set_multi && multi::two_focus) { + pconf.model_orientation = atan2(multi_point) / degree; + auto& d = pconf.twopoint_param; + d = hdist0(multi_point); + if(among(pmodel, mdJoukowsky, mdJoukowskyInverted)) { + pconf.model_orientation += 90; + pconf.model_transition = sinh(d) / (1 + cosh(d)); + pconf.dualfocus_autoscale = true; + } + } + ors::rerotate(W); ors::rerotate(cwtV.T); ors::rerotate(View); } diff --git a/models.cpp b/models.cpp index 56d88b7d..099afbbf 100644 --- a/models.cpp +++ b/models.cpp @@ -600,6 +600,9 @@ EX namespace models { if(among(vpmodel, mdJoukowsky, mdJoukowskyInverted, mdSpiral) && GDIM == 2) add_edit(vpconf.skiprope); + + if(vpmodel == mdJoukowskyInverted) + add_edit(vpconf.dualfocus_autoscale); if(vpmodel == mdHemisphere && euclid) add_edit(vpconf.euclid_to_sphere); @@ -1024,6 +1027,9 @@ EX namespace models { param_f(p.skiprope, sp+"mobius", 0) -> editable(0, 360, 15, "Möbius transformations", "", 'S')->unit = "°"; + + param_b(p.dualfocus_autoscale, sp+"dualfocus_autoscale", 0) + -> editable("autoscale dual focus", 'A'); addsaver(p.formula, sp+"formula"); addsaverenum(p.basic_model, sp+"basic model"); diff --git a/multi.cpp b/multi.cpp index cc44390a..3e8b0418 100644 --- a/multi.cpp +++ b/multi.cpp @@ -32,6 +32,7 @@ EX namespace multi { EX bool pvp_mode; EX bool friendly_fire = true; EX bool self_hits; + EX bool two_focus; EX int players = 1; EX cellwalker player[MAXPLAYER]; @@ -518,6 +519,7 @@ EX void showConfigureMultiplayer() { }); } + add_edit(self_hits); if(multi::players > 1) { dialog::addItem(XLAT("reset per-player statistics"), 'r'); dialog::add_action([] { @@ -531,7 +533,6 @@ EX void showConfigureMultiplayer() { if(shmup::on && !racing::on) { add_edit(pvp_mode); add_edit(friendly_fire); - add_edit(self_hits); if(pvp_mode) dialog::addInfo(XLAT("PvP grants infinite lives -- achievements disabled")); else if(friendly_fire) @@ -539,10 +540,16 @@ EX void showConfigureMultiplayer() { else dialog::addBreak(100); } - else + else { dialog::addInfo(XLAT("PvP available only in shmup")); + dialog::addBreak(400); + } + if(multi::players == 2 && !split_screen) + add_edit(two_focus); + else + dialog::addBreak(100); } - else dialog::addBreak(200); + else dialog::addBreak(600); dialog::addBack(); dialog::display(); @@ -720,6 +727,8 @@ EX void initConfig() { ->editable("friendly fire", 'f'); param_b(multi::self_hits, "self_hits", false) ->editable("self hits", 'h'); + param_b(multi::two_focus, "two_focus", false) + ->editable("auto-adjust two-focus projections", 'f'); addsaver(alwaysuse, "use configured keys"); // unfortunately we cannot use key names here because SDL is not yet initialized for(int i=0; i<512; i++)