multi:: two-focus projections

This commit is contained in:
Zeno Rogue 2022-03-27 14:32:29 +02:00
parent a6cbedc944
commit 6d554d6b2e
5 changed files with 65 additions and 17 deletions

View File

@ -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<hyperpoint>& 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<multi::players; p++) if(multi::playerActive(p)) {
hyperpoint h1 = unshift(tC0(multi::whereis[p]));
h += h1;
}
h = mid(h, h);
cwtV = shiftless(rgpushxto0(h));
vector<hyperpoint> pts;
for(int p=0; p<multi::players; p++) if(multi::playerActive(p))
pts.push_back(unshift(tC0(multi::whereis[p])));
center_multiplayer_map(pts);
}
}
@ -5057,13 +5070,10 @@ EX void drawthemap() {
else if(multi::centerplayer != -1)
cwtV = shmup::pc[multi::centerplayer]->pat;
else {
hyperpoint h = Hypc;
for(int p=0; p<multi::players; p++) {
hyperpoint h1 = unshift(tC0(shmup::pc[p]->pat));
h += h1;
}
h = mid(h, h);
cwtV = shiftless(rgpushxto0(h));
vector<hyperpoint> pts;
for(int p=0; p<multi::players; p++)
pts.push_back(unshift(tC0(shmup::pc[p]->pat)));
center_multiplayer_map(pts);
}
}

View File

@ -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;
}
};

View File

@ -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);
}

View File

@ -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");

View File

@ -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++)