Improved the UI for 'geodesic movement' setting, and also make it work correctly in SL2 and hyperbolic geometries

This commit is contained in:
Zeno Rogue 2022-12-25 12:14:36 +01:00
parent 080e853364
commit 86492d1181
10 changed files with 84 additions and 44 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

3
vr.cpp
View File

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