mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-02-02 12:19:18 +00:00
Improved the UI for 'geodesic movement' setting, and also make it work correctly in SL2 and hyperbolic geometries
This commit is contained in:
parent
080e853364
commit
86492d1181
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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');
|
||||
|
@ -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
|
||||
|
@ -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<GDIM; i++) T[i][LDIM] = h[i] * co;
|
||||
return T;
|
||||
@ -1651,7 +1652,7 @@ EX eShiftMethod shift_method(eShiftMethodApplication sma) {
|
||||
if(gproduct) return smProduct;
|
||||
if(embedded_plane && sma == smaObject) return geom3::same_in_same() ? smIsotropic : smEmbedded;
|
||||
if(embedded_plane && use_embedded_shift(sma)) return nonisotropic ? smLie : smEmbedded;
|
||||
if(!nonisotropic && !stretch::in()) return smIsotropic;
|
||||
if(!nonisotropic && !stretch::in() && !(!nisot::geodesic_movement && hyperbolic && bt::in())) return smIsotropic;
|
||||
if(!nisot::geodesic_movement && !embedded_plane) return smLie;
|
||||
return smGeodesic;
|
||||
}
|
||||
@ -1897,11 +1898,11 @@ EX ld geo_dist_q(const hyperpoint h1, const hyperpoint h2, flagtype prec IS(pNOR
|
||||
}
|
||||
|
||||
EX hyperpoint lp_iapply(const hyperpoint h) {
|
||||
return nisot::local_perspective_used() ? inverse(NLP) * h : h;
|
||||
return nisot::local_perspective_used ? inverse(NLP) * h : h;
|
||||
}
|
||||
|
||||
EX hyperpoint lp_apply(const hyperpoint h) {
|
||||
return nisot::local_perspective_used() ? NLP * h : h;
|
||||
return nisot::local_perspective_used ? NLP * h : h;
|
||||
}
|
||||
|
||||
EX hyperpoint smalltangent() { return xtangent(.1); }
|
||||
|
79
hypgraph.cpp
79
hypgraph.cpp
@ -539,11 +539,8 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
||||
exit(1);
|
||||
/* x wanes as z grows! */
|
||||
}
|
||||
if(hyperbolic) {
|
||||
models::apply_orientation_yz(H[1], H[2]);
|
||||
models::apply_orientation(H[0], H[1]);
|
||||
}
|
||||
auto S = lie_log(H); S[3] = 1;
|
||||
hyperpoint S = lie_log_correct(H_orig, H);
|
||||
S[3] = 1;
|
||||
S = lp_apply(S);
|
||||
if(hyperbolic) {
|
||||
models::apply_orientation(ret[1], ret[0]);
|
||||
@ -554,7 +551,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
||||
}
|
||||
|
||||
case mdRelPerspective: {
|
||||
auto S = rel_log(H_orig); S[3] = 1;
|
||||
auto S = rel_log(H_orig, true); S[3] = 1;
|
||||
S = lp_apply(S);
|
||||
apply_perspective(S, ret);
|
||||
return;
|
||||
@ -778,20 +775,14 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
||||
models::apply_orientation_yz(ret[2], ret[1]);
|
||||
}
|
||||
|
||||
if(nonisotropic && !vrhr::rendering()) ret = lp_apply(ret);
|
||||
if(!vrhr::rendering()) ret = lp_apply(ret);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case mdLieOrthogonal: {
|
||||
find_zlev(H);
|
||||
ret = lie_log_correct(H_orig, H);
|
||||
|
||||
if(hyperbolic) {
|
||||
models::apply_orientation_yz(H[1], H[2]);
|
||||
models::apply_orientation(H[0], H[1]);
|
||||
}
|
||||
|
||||
ret = lie_log(H);
|
||||
ret *= .5;
|
||||
ret[LDIM] = 1;
|
||||
|
||||
@ -800,18 +791,18 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
||||
models::apply_orientation_yz(ret[2], ret[1]);
|
||||
}
|
||||
|
||||
if(nonisotropic && !vrhr::rendering()) ret = lp_apply(ret);
|
||||
if(!vrhr::rendering()) ret = lp_apply(ret);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case mdRelOrthogonal: {
|
||||
|
||||
ret = rel_log(H_orig);
|
||||
ret = rel_log(H_orig, true);
|
||||
ret *= .5;
|
||||
ret[LDIM] = 1;
|
||||
|
||||
if(nonisotropic && !vrhr::rendering()) ret = lp_apply(ret);
|
||||
if(!vrhr::rendering()) ret = lp_apply(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2299,6 +2290,7 @@ EX int flat_on;
|
||||
eGeometry backup_geometry;
|
||||
eVariation backup_variation;
|
||||
videopar backup_vid;
|
||||
bool backup_lpu;
|
||||
|
||||
/** \brief enable the 'flat' model for drawing HUD. See hr::flat_model_enabler */
|
||||
EX void enable_flat_model(int val) {
|
||||
@ -2308,9 +2300,12 @@ EX void enable_flat_model(int val) {
|
||||
#endif
|
||||
backup_geometry = geometry;
|
||||
backup_variation = variation;
|
||||
backup_lpu = nisot::local_perspective_used;
|
||||
backup_vid = vid;
|
||||
geometry = gNormal;
|
||||
variation = eVariation::bitruncated;
|
||||
nisot::local_perspective_used = false;
|
||||
|
||||
pmodel = mdDisk;
|
||||
pconf.alpha = 1;
|
||||
pconf.scale = 1;
|
||||
@ -2330,6 +2325,7 @@ EX void enable_flat_model(int val) {
|
||||
if(flat_on >= 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<LDIM; i++)
|
||||
h[i] *= h[0] / (exp(h[0])-1);
|
||||
}
|
||||
else if(sl2) {
|
||||
return rel_log(h1, false);
|
||||
}
|
||||
else {
|
||||
/* not implemented */
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/** Like lie_log but includes orientation and level in hyperbolic space. May modify H */
|
||||
EX hyperpoint lie_log_correct(const shiftpoint H_orig, hyperpoint& H) {
|
||||
find_zlev(H);
|
||||
if(hyperbolic) {
|
||||
models::apply_orientation_yz(H[1], H[2]);
|
||||
models::apply_orientation(H[0], H[1]);
|
||||
return lie_log(shiftless(H));
|
||||
}
|
||||
return lie_log(H_orig);
|
||||
}
|
||||
|
||||
/** shift the view according to the given tangent vector */
|
||||
EX transmatrix get_shift_view_of(const hyperpoint H, const transmatrix V, eShiftMethod sm IS(shift_method(smaManualCamera))) {
|
||||
switch(sm) {
|
||||
@ -3328,7 +3367,7 @@ EX void shift_view_to(shiftpoint H, eShiftMethod sm IS(shift_method(smaManualCam
|
||||
shift_view_by_matrix(gpushxto0(unshift(H)), sm);
|
||||
return;
|
||||
case smLie:
|
||||
shift_view(-lie_log(unshift(H)), sm);
|
||||
shift_view(-lie_log(H), sm);
|
||||
return;
|
||||
case smGeodesic:
|
||||
shift_view(-inverse_exp(H), sm);
|
||||
|
@ -10,9 +10,7 @@ namespace hr {
|
||||
|
||||
EX namespace nisot {
|
||||
|
||||
#if HDR
|
||||
inline bool local_perspective_used() { return nonisotropic || gproduct; }
|
||||
#endif
|
||||
EX bool local_perspective_used;
|
||||
|
||||
EX bool geodesic_movement = true;
|
||||
|
||||
|
@ -19,7 +19,7 @@ pair<bool, hyperpoint> 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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user