mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-28 11:00:34 +00:00
fixed shift in nonisotropic embeddings; also you can now choose between geodesic or embed-aware, for both manual and auto camera movement
This commit is contained in:
parent
dfbf553608
commit
1210de672e
@ -840,6 +840,13 @@ EX void initConfig() {
|
||||
-> set_sets([] { dialog::bound_low(0.05); })
|
||||
-> set_reaction([] { if(vid.always3) { geom3::switch_fpp(); geom3::switch_fpp(); } });
|
||||
|
||||
param_enum(embedded_shift_method_choice, "embedded_shift_method", "embedded_shift_method", smcBoth)
|
||||
-> editable({
|
||||
{"geodesic", "always move on geodesics"},
|
||||
{"keep levels", "keep the vertical angle of the camera"},
|
||||
{"mixed", "on geodesics when moving camera manually, keep level when auto-centering"}
|
||||
}, "view shift for embedded planes", 'H');
|
||||
|
||||
param_b(geom3::auto_configure, "auto_configure_3d", "auto_configure_3d")
|
||||
-> editable("set 3D settings automatically", 'A');
|
||||
|
||||
@ -2295,6 +2302,7 @@ EX void show3D() {
|
||||
|
||||
if(WDIM == 2) {
|
||||
if(geom3::euc_in_noniso()) add_edit(geom3::euclid_embed_scale);
|
||||
add_edit(embedded_shift_method_choice);
|
||||
add_edit(vid.camera);
|
||||
if(GDIM == 3)
|
||||
add_edit(vid.eye);
|
||||
|
@ -1102,7 +1102,7 @@ EX void showEuclideanMenu() {
|
||||
dialog::add_action_push(show3D);
|
||||
}
|
||||
menuitem_projection('1');
|
||||
if(nonisotropic && !sl2)
|
||||
if(nonisotropic && !sl2 && !embedded_plane)
|
||||
dialog::addBoolItem_action(XLAT("geodesic movement in Sol/Nil"), nisot::geodesic_movement, 'G');
|
||||
#if CAP_CRYSTAL && MAXMDIM >= 4
|
||||
crystal::add_crystal_transform('x');
|
||||
|
162
hypgraph.cpp
162
hypgraph.cpp
@ -2115,9 +2115,9 @@ EX void centerpc(ld aspd) {
|
||||
if(R < aspd) fix_whichcopy_if_near();
|
||||
|
||||
if(R < aspd)
|
||||
shift_view_to(shiftless(H));
|
||||
shift_view_to(shiftless(H), shift_method(true));
|
||||
else
|
||||
shift_view_towards(shiftless(H), aspd);
|
||||
shift_view_towards(shiftless(H), aspd, shift_method(true));
|
||||
|
||||
fixmatrix(View);
|
||||
fixmatrix(current_display->which_copy);
|
||||
@ -3206,25 +3206,59 @@ EX hyperpoint lie_log(hyperpoint h) {
|
||||
return h;
|
||||
}
|
||||
|
||||
#if HDR
|
||||
enum eShiftMethod { smProduct, smIsometric, smEmbedded, smLie, smGeodesic };
|
||||
enum eEmbeddedShiftMethodChoice { smcNone, smcBoth, smcAuto };
|
||||
#endif
|
||||
|
||||
EX eEmbeddedShiftMethodChoice embedded_shift_method_choice = smcBoth;
|
||||
|
||||
EX bool use_embedded_shift(bool automatic) {
|
||||
if(automatic) return embedded_shift_method_choice;
|
||||
return embedded_shift_method_choice == smcBoth;
|
||||
}
|
||||
|
||||
EX eShiftMethod shift_method(bool automatic IS(false)) {
|
||||
if(gproduct) return smProduct;
|
||||
if(embedded_plane && use_embedded_shift(automatic)) return nonisotropic ? smLie : smEmbedded;
|
||||
if(!nonisotropic && !stretch::in()) return smIsometric;
|
||||
if(!nisot::geodesic_movement && !embedded_plane) return smLie;
|
||||
return smGeodesic;
|
||||
}
|
||||
|
||||
EX eShiftMethod shift_method_auto() {
|
||||
if(gproduct) return smProduct;
|
||||
if(embedded_plane) return nonisotropic ? smLie : smEmbedded;
|
||||
if(!nonisotropic && !stretch::in()) return smIsometric;
|
||||
if(!nisot::geodesic_movement) return smLie;
|
||||
return smGeodesic;
|
||||
}
|
||||
|
||||
/** shift the view according to the given tangent vector */
|
||||
EX transmatrix get_shift_view_of(const hyperpoint H, const transmatrix V) {
|
||||
if(!nonisotropic && !stretch::in()) {
|
||||
return rgpushxto0(direct_exp(lp_iapply(H))) * V;
|
||||
}
|
||||
else if(!nisot::geodesic_movement) {
|
||||
transmatrix IV = view_inverse(View);
|
||||
transmatrix view_shift = eupush( tC0(IV) );
|
||||
transmatrix rot = V * view_shift;
|
||||
hyperpoint tH = lie_exp(inverse(rot) * H);
|
||||
return rot * eupush(tH) * inverse(view_shift);
|
||||
}
|
||||
else {
|
||||
return iview_inverse(nisot::parallel_transport(view_inverse(V), -H));
|
||||
EX transmatrix get_shift_view_of(const hyperpoint H, const transmatrix V, eShiftMethod sm IS(shift_method())) {
|
||||
switch(sm) {
|
||||
case smProduct:
|
||||
return rgpushxto0(direct_exp(lp_iapply(H))) * V;
|
||||
case smIsometric:
|
||||
return rgpushxto0(direct_exp(H)) * V;
|
||||
case smEmbedded:
|
||||
return get_shift_view_embedded_of(V, rgpushxto0(direct_exp(H))) * V;
|
||||
case smLie: {
|
||||
transmatrix IV = view_inverse(View);
|
||||
transmatrix view_shift = eupush( tC0(IV) );
|
||||
transmatrix rot = V * view_shift;
|
||||
hyperpoint tH = lie_exp(inverse(rot) * H);
|
||||
return rot * eupush(tH) * inverse(view_shift);
|
||||
}
|
||||
case smGeodesic:
|
||||
return iview_inverse(nisot::parallel_transport(view_inverse(V), -H));
|
||||
default:
|
||||
throw hr_exception("unknown shift method (embedded not supported)");
|
||||
}
|
||||
}
|
||||
|
||||
/** shift the view according to the given tangent vector */
|
||||
EX void shift_view(hyperpoint H) {
|
||||
EX void shift_view(hyperpoint H, eShiftMethod sm IS(shift_method())) {
|
||||
if(callhandlers(false, hooks_shift_view, H)) return;
|
||||
static bool recursive = false;
|
||||
if(!recursive && intra::in) {
|
||||
@ -3234,31 +3268,50 @@ EX void shift_view(hyperpoint H) {
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
View = get_shift_view_of(H, View);
|
||||
View = get_shift_view_of(H, View, sm);
|
||||
auto& wc = current_display->which_copy;
|
||||
wc = get_shift_view_of(H, wc);
|
||||
wc = get_shift_view_of(H, wc, sm);
|
||||
}
|
||||
|
||||
/** works in embedded_plane and isotropic spaces */
|
||||
void shift_view_isotropic(transmatrix T) {
|
||||
/** works in embedded_plane (except embedded product where shift_view works) */
|
||||
EX transmatrix get_shift_view_embedded_of(const transmatrix V, const transmatrix T) {
|
||||
transmatrix IV = view_inverse(View);
|
||||
transmatrix rot = View * map_relative_push(IV * C0);
|
||||
View = T * View;
|
||||
transmatrix IV1 = view_inverse(View);
|
||||
transmatrix rot1 = View * map_relative_push(IV1 * C0);
|
||||
return rot * inverse(rot1) * T;
|
||||
}
|
||||
|
||||
if(embedded_plane) {
|
||||
transmatrix IV = view_inverse(View);
|
||||
transmatrix rot = View * map_relative_push(IV * C0);
|
||||
View = T * View;
|
||||
transmatrix IV1 = view_inverse(View);
|
||||
transmatrix rot1 = View * map_relative_push(IV1 * C0);
|
||||
View = rot * inverse(rot1) * View;
|
||||
auto& wc = current_display->which_copy;
|
||||
wc = rot * inverse(rot1) * T * wc;
|
||||
return;
|
||||
}
|
||||
/** works in embedded_plane (except embedded product where shift_view works) */
|
||||
void shift_view_embedded(const transmatrix T) {
|
||||
transmatrix R = get_shift_view_embedded_of(View, T);
|
||||
View = R * View;
|
||||
auto& wc = current_display->which_copy;
|
||||
wc = R * wc;
|
||||
}
|
||||
|
||||
/** works in isotropic and product spaces */
|
||||
void shift_view_mmul(const transmatrix T) {
|
||||
View = T * View;
|
||||
auto& wc = current_display->which_copy;
|
||||
wc = T * wc;
|
||||
}
|
||||
|
||||
void shift_view_by_matrix(const transmatrix T, eShiftMethod sm) {
|
||||
switch(sm) {
|
||||
case smEmbedded:
|
||||
shift_view_embedded(T);
|
||||
return;
|
||||
case smIsometric:
|
||||
case smProduct:
|
||||
shift_view_mmul(T);
|
||||
return;
|
||||
default:
|
||||
throw hr_exception("unsupported shift method in shift_view_by_matrix");
|
||||
}
|
||||
}
|
||||
|
||||
/* like rgpushxto0 but keeps the map orientation correct */
|
||||
EX transmatrix map_relative_push(hyperpoint h) {
|
||||
if(!embedded_plane) return rgpushxto0(h);
|
||||
@ -3285,21 +3338,42 @@ EX transmatrix map_relative_push(hyperpoint h) {
|
||||
return rgpushxto0(h);
|
||||
}
|
||||
|
||||
EX void shift_view_to(shiftpoint H) {
|
||||
if(!nonisotropic)
|
||||
shift_view_isotropic(gpushxto0(unshift(H)));
|
||||
else shift_view(-inverse_exp(H));
|
||||
EX void shift_view_to(shiftpoint H, eShiftMethod sm IS(shift_method())) {
|
||||
switch(sm) {
|
||||
case smIsometric:
|
||||
case smEmbedded:
|
||||
case smProduct:
|
||||
shift_view_by_matrix(gpushxto0(unshift(H)), sm);
|
||||
return;
|
||||
case smLie:
|
||||
shift_view(-lie_log(unshift(H)), sm);
|
||||
return;
|
||||
case smGeodesic:
|
||||
shift_view(-inverse_exp(H), sm);
|
||||
return;
|
||||
default:
|
||||
throw hr_exception("unsupported shift method in shift_view_to");
|
||||
}
|
||||
}
|
||||
|
||||
EX void shift_view_towards(shiftpoint H, ld l) {
|
||||
if(!nonisotropic && !gproduct)
|
||||
shift_view_isotropic(rspintox(unshift(H)) * xpush(-l) * spintox(unshift(H)));
|
||||
else if(nonisotropic && !nisot::geodesic_movement)
|
||||
shift_view(tangent_length(unshift(H)-C0, -l));
|
||||
else {
|
||||
hyperpoint ie = inverse_exp(H, pNORMAL | pfNO_DISTANCE);
|
||||
if(gproduct) ie = lp_apply(ie);
|
||||
shift_view(tangent_length(ie, -l));
|
||||
EX void shift_view_towards(shiftpoint H, ld l, eShiftMethod sm IS(shift_method())) {
|
||||
switch(sm) {
|
||||
case smIsometric:
|
||||
case smEmbedded:
|
||||
shift_view_by_matrix(rspintox(unshift(H)) * xpush(-l) * spintox(unshift(H)), sm);
|
||||
return;
|
||||
case smLie:
|
||||
shift_view(tangent_length(unshift(H)-C0, -l), sm);
|
||||
return;
|
||||
case smGeodesic:
|
||||
case smProduct: {
|
||||
hyperpoint ie = inverse_exp(H, pNORMAL | pfNO_DISTANCE);
|
||||
if(gproduct) ie = lp_apply(ie);
|
||||
shift_view(tangent_length(ie, -l), sm);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
throw hr_exception("unsupported shift method in shift_view_towards");
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user