mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 14:02:59 +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:
		| @@ -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) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue