mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 05:52:59 +00:00 
			
		
		
		
	3d:: native perspective is now pmodel == mdPerspective, and other models work too
This commit is contained in:
		| @@ -220,29 +220,29 @@ void display_data::set_projection(int ed, bool apply_models) { | ||||
|   if(vid.consider_shader_projection) { | ||||
|     if(pmodel == mdDisk && !spherespecial && !(hyperbolic && vid.alpha <= -1) && DIM == 2) | ||||
|       shaderside_projection = true; | ||||
|     if(pmodel == mdBand && hyperbolic && apply_models) | ||||
|     if(pmodel == mdBand && hyperbolic && apply_models && DIM == 2) | ||||
|       shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::band; | ||||
|     if(pmodel == mdHalfplane && hyperbolic && apply_models) | ||||
|     if(pmodel == mdHalfplane && hyperbolic && apply_models && DIM == 2) | ||||
|       shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::halfplane; | ||||
|     if(DIM == 3 && hyperbolic && apply_models) | ||||
|     if(DIM == 3 && hyperbolic && apply_models && pmodel == mdPerspective) | ||||
|       shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::standardH3; | ||||
|     if(DIM == 3 && euclid && apply_models) | ||||
|     if(DIM == 3 && euclid && apply_models && pmodel == mdPerspective) | ||||
|       shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::standardR3; | ||||
|     if(DIM == 3 && sphere && apply_models) { | ||||
|     if(DIM == 3 && sphere && apply_models && pmodel == mdPerspective) { | ||||
|       shaderside_projection = true; | ||||
|       if(spherephase == 0) glhr::new_shader_projection = glhr::shader_projection::standardS30; | ||||
|       if(spherephase == 1) glhr::new_shader_projection = glhr::shader_projection::standardS31; | ||||
|       if(spherephase == 2) glhr::new_shader_projection = glhr::shader_projection::standardS32; | ||||
|       if(spherephase == 3) glhr::new_shader_projection = glhr::shader_projection::standardS33; | ||||
|       } | ||||
|     if(DIM == 3 && apply_models) dim3 = true; | ||||
|     if(DIM == 3 && apply_models && shaderside_projection) dim3 = true; | ||||
|     } | ||||
|    | ||||
|   start_projection(ed, shaderside_projection); | ||||
|  | ||||
|   auto cd = current_display; | ||||
|  | ||||
|   if(!shaderside_projection && DIM != 3) { | ||||
|   if(!shaderside_projection) { | ||||
|     glhr::projection_multiply(glhr::ortho(cd->xsize/2, -cd->ysize/2, abs(current_display->scrdist) + 30000)); | ||||
|     if(ed) { | ||||
|       glhr::glmatrix m = glhr::id; | ||||
|   | ||||
| @@ -1822,6 +1822,7 @@ const modelinfo models[int(mdPolynomial)+1] = { | ||||
|   {X3("Joukowsky+inversion"), mf::hyper_only | mf::conformal}, | ||||
|   {X3("rotated hyperboles"), mf::hyper_only},   | ||||
|   {X3("spiral"), mf::hyper_or_torus | mf::quasiband}, | ||||
|   {X3("native perspective"), 0}, | ||||
|   {X3(""), 0}, | ||||
|   {X3(""), 0}, | ||||
|   {X3(""), 0}, | ||||
|   | ||||
| @@ -283,7 +283,7 @@ enum eModel { | ||||
|   mdEquidistant, mdEquiarea, mdBall, mdHyperboloid,  | ||||
|   mdHemisphere, mdBandEquidistant, mdBandEquiarea, mdSinusoidal, mdTwoPoint,  | ||||
|   mdFisheye, mdJoukowsky, mdJoukowskyInverted, | ||||
|   mdRotatedHyperboles, mdSpiral, | ||||
|   mdRotatedHyperboles, mdSpiral, mdPerspective, | ||||
|   mdGUARD, mdUnchanged, mdHyperboloidFlat, mdPolynomial | ||||
|   }; | ||||
|  | ||||
|   | ||||
| @@ -584,6 +584,8 @@ namespace conformal { | ||||
|   bool model_available(eModel pm) { | ||||
|     if(sphere && (pm == mdHalfplane || pm == mdBall)) | ||||
|       return false; | ||||
|     if(DIM == 2 && pm == mdPerspective) return false; | ||||
|     if(DIM == 3 && among(pm, mdBall, mdHyperboloid, mdFormula, mdPolygonal, mdRotatedHyperboles, mdSpiral, mdHemisphere)) return false; | ||||
|     return true; | ||||
|     }     | ||||
|    | ||||
| @@ -673,7 +675,7 @@ namespace conformal { | ||||
|       eModel m = eModel(i); | ||||
|       if(m == mdFormula && ISMOBILE) continue; | ||||
|       if(model_available(m)) { | ||||
|         dialog::addBoolItem(get_model_name(m), pmodel == m, "0123456789!@#$%^&*()" [m]); | ||||
|         dialog::addBoolItem(get_model_name(m), pmodel == m, "0123456789!@#$%^&*()]" [m]); | ||||
|         dialog::add_action([m] () { | ||||
|           if(m == mdFormula) { | ||||
|             edit_formula(); | ||||
| @@ -697,7 +699,8 @@ namespace conformal { | ||||
|     dialog::lastItem().value += " " + its(rotation) + "°"; | ||||
|  | ||||
|     // if(pmodel == mdBand && sphere) | ||||
|     dialog::addSelItem(XLAT("scale factor"), fts(vid.scale), 'z'); | ||||
|     if(pmodel != mdPerspective) | ||||
|       dialog::addSelItem(XLAT("scale factor"), fts(vid.scale), 'z'); | ||||
|      | ||||
|     if(abs(vid.alpha-1) > 1e-3 && pmodel != mdBall && pmodel != mdHyperboloid && pmodel != mdHemisphere && pmodel != mdDisk) { | ||||
|       dialog::addBreak(50); | ||||
|   | ||||
| @@ -677,13 +677,11 @@ void showEuclideanMenu() { | ||||
|   dialog::add_action([] { pushScreen(patterns::showPrePattern); }); | ||||
|   validity_info(); | ||||
|   if(DIM == 3) { | ||||
|     dialog::addItem(XLAT("3D configuration"), '1'); | ||||
|     dialog::addItem(XLAT("3D configuration"), '9'); | ||||
|     dialog::add_action([] { pushScreen(show3D); }); | ||||
|     } | ||||
|   else { | ||||
|     dialog::addSelItem(XLAT("projection"), current_proj_name(), '1'); | ||||
|     dialog::add_action([] { pushScreen(conformal::model_menu); }); | ||||
|     } | ||||
|   dialog::addSelItem(XLAT("projection"), current_proj_name(), '1'); | ||||
|   dialog::add_action([] { pushScreen(conformal::model_menu); }); | ||||
|   #if CAP_CRYSTAL && MAXMDIM >= 4 | ||||
|   crystal::add_crystal_transform('x');   | ||||
|   #endif | ||||
|   | ||||
| @@ -4808,8 +4808,8 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { | ||||
|  | ||||
|           for(int a=0; a<c->type; a++) | ||||
|             if(c->move(a) && !isWall3(c->move(a), dummy)) { | ||||
|               if(a < 4 && among(geometry, gHoroTris, gBinary3) && celldistAlt(c) >= celldistAlt(viewctr.at->c7)) continue; | ||||
|               if(a < 2 && among(geometry, gHoroRec) && celldistAlt(c) >= celldistAlt(viewctr.at->c7)) continue; | ||||
|               if(a < 4 && pmodel == mdPerspective && among(geometry, gHoroTris, gBinary3) && celldistAlt(c) >= celldistAlt(viewctr.at->c7)) continue; | ||||
|               if(a < 2 && pmodel == mdPerspective && among(geometry, gHoroRec) && celldistAlt(c) >= celldistAlt(viewctr.at->c7)) continue; | ||||
|               if(qfi.fshape && wmescher) { | ||||
|                 auto& poly = queuepoly(V, shWall3D[a], darkena(wcol - d * get_darkval(a), 0, 0xFF)); | ||||
|                 poly.tinf = &qfi.fshape->tinf3; | ||||
| @@ -5923,6 +5923,7 @@ void drawthemap() { | ||||
|   mmspatial = vid.monmode == 4 || vid.monmode == 5; | ||||
|    | ||||
|   spatial_graphics = wmspatial || mmspatial; | ||||
|   spatial_graphics = spatial_graphics && DIM == 2; | ||||
|   #if CAP_RUG | ||||
|   if(rug::rugged && !rug::spatial_rug) spatial_graphics = false; | ||||
|   #endif | ||||
| @@ -6146,7 +6147,7 @@ void calcparam() { | ||||
|     } | ||||
|  | ||||
|   cd->radius = vid.scale * cd->scrsize; | ||||
|   if(DIM == 3) cd->radius = cd->scrsize; | ||||
|   if(DIM == 3 && pmodel == mdPerspective) cd->radius = cd->scrsize; | ||||
|   realradius = min(realradius, cd->radius); | ||||
|    | ||||
|   if(dronemode) { cd->ycenter -= cd->radius; cd->ycenter += vid.fsize/2; cd->ycenter += vid.fsize/2; cd->radius *= 2; } | ||||
|   | ||||
							
								
								
									
										72
									
								
								hypgraph.cpp
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								hypgraph.cpp
									
									
									
									
									
								
							| @@ -69,7 +69,12 @@ hyperpoint space_to_perspective(hyperpoint z, ld alpha) { | ||||
|   ld s = 1 / (alpha + z[DIM]); | ||||
|   z[0] *= s; | ||||
|   z[1] *= s; | ||||
|   z[DIM] = 0; | ||||
|   if(DIM == 3) { | ||||
|     z[2] *= s; | ||||
|     z[3] = 0; | ||||
|     } | ||||
|   else | ||||
|     z[2] = 0; | ||||
|   return z; | ||||
|   } | ||||
|  | ||||
| @@ -154,7 +159,7 @@ ld find_zlev(hyperpoint& H) { | ||||
|   } | ||||
|  | ||||
| ld get_tz(hyperpoint H) { | ||||
|   ld tz = euclid ? (1+vid.alpha) : vid.alpha+H[2]; | ||||
|   ld tz = euclid ? (1+vid.alpha) : vid.alpha+H[DIM]; | ||||
|   if(tz < BEHIND_LIMIT && tz > -BEHIND_LIMIT) tz = BEHIND_LIMIT; | ||||
|   return tz; | ||||
|   } | ||||
| @@ -163,9 +168,26 @@ ld atan2(hyperpoint h) { | ||||
|   return atan2(h[1], h[0]); | ||||
|   } | ||||
|  | ||||
| pair<ld, ld> move_z_to_y(hyperpoint& H) { | ||||
|   if(DIM == 2) return make_pair(0, 0); | ||||
|   ld R = hypot(H[1], H[2]); | ||||
|   pair<ld, ld> res = { H[1] / R, H[2] / R }; | ||||
|   H[1] = R; H[2] = 0; | ||||
|   return res; | ||||
|   } | ||||
|  | ||||
| void move_y_to_z(hyperpoint& H, pair<ld, ld> coef) { | ||||
|   if(DIM == 3) { | ||||
|     H[2] = H[1] * coef.second; | ||||
|     H[1] = H[1] * coef.first; | ||||
|     H[3] = 1; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| template<class T> void makeband(hyperpoint H, hyperpoint& ret, const T& f) { | ||||
|   ld zlev = find_zlev(H); | ||||
|   conformal::apply_orientation(H[0], H[1]); | ||||
|   auto r = move_z_to_y(H); | ||||
|    | ||||
|   ld x, y, yf, zf=0; | ||||
|   y = asin_auto(H[1]); | ||||
| @@ -179,8 +201,9 @@ template<class T> void makeband(hyperpoint H, hyperpoint& ret, const T& f) { | ||||
|   f(x, y); | ||||
|    | ||||
|   ld yzf = y * zf; y *= yf; | ||||
|   conformal::apply_orientation(y, x); | ||||
|   ret = hpxyz(x / M_PI, y / M_PI, 0); | ||||
|   move_y_to_z(ret, r); | ||||
|   conformal::apply_orientation(ret[1], ret[0]); | ||||
|   if(zlev != 1 && current_display->stereo_active())  | ||||
|     apply_depth(ret, yzf / M_PI); | ||||
|   return; | ||||
| @@ -233,19 +256,19 @@ hyperpoint mobius(hyperpoint h, ld angle, ld scale = 1) { | ||||
|  | ||||
| void applymodel(hyperpoint H, hyperpoint& ret) { | ||||
|  | ||||
|   if(DIM == 3) {  | ||||
|     ld ratio = vid.xres / current_display->tanfov / current_display->radius / 2; | ||||
|     ret[0] = H[0]/H[2] * ratio; | ||||
|     ret[1] = H[1]/H[2] * ratio; | ||||
|     ret[2] = 1; | ||||
|     return;  | ||||
|     } | ||||
|    | ||||
|   using namespace hyperpoint_vec; | ||||
|    | ||||
|   hyperpoint H_orig = H; | ||||
|    | ||||
|   switch(pmodel) { | ||||
|     case mdPerspective: { | ||||
|       ld ratio = vid.xres / current_display->tanfov / current_display->radius / 2; | ||||
|       ret[0] = H[0]/H[2] * ratio; | ||||
|       ret[1] = H[1]/H[2] * ratio; | ||||
|       ret[2] = 1; | ||||
|       return; | ||||
|       } | ||||
|        | ||||
|     case mdUnchanged: | ||||
|       ret = H / current_display->radius; | ||||
|       return;  | ||||
| @@ -264,7 +287,9 @@ void applymodel(hyperpoint H, hyperpoint& ret) { | ||||
|       if(!vid.camera_angle) { | ||||
|         ret[0] = H[0] / tz; | ||||
|         ret[1] = H[1] / tz; | ||||
|         ret[2] = vid.xres * current_display->eyewidth() / 2 / current_display->radius - vid.ipd / tz / 2; | ||||
|         if(DIM == 3) ret[2] = H[2] / tz; | ||||
|         else ret[2] = vid.xres * current_display->eyewidth() / 2 / current_display->radius - vid.ipd / tz / 2; | ||||
|         if(MAXMDIM == 4) ret[3] = 1; | ||||
|         } | ||||
|       else { | ||||
|         ld tx = H[0]; | ||||
| @@ -289,7 +314,7 @@ void applymodel(hyperpoint H, hyperpoint& ret) { | ||||
|       conformal::apply_orientation(H[0], H[1]); | ||||
|    | ||||
|       H[1] += 1; | ||||
|       double rad = sqhypot_d(2, H); | ||||
|       double rad = sqhypot_d(DIM, H); | ||||
|       H /= -rad; | ||||
|       H[1] += .5; | ||||
|        | ||||
| @@ -307,7 +332,8 @@ void applymodel(hyperpoint H, hyperpoint& ret) { | ||||
|           H[1] += H[0] * conformal::osin * log(zlev); | ||||
|         } | ||||
|       ret[1] = conformal::ocos + H[1]; | ||||
|       ret[2] = 0; | ||||
|       ret[2] = DIM == 3 ? H[2] : 0; | ||||
|       if(MAXMDIM == 4) ret[3] = 1; | ||||
|       if(zlev != 1 && current_display->stereo_active())  | ||||
|         apply_depth(ret, -H[1] * geom3::factor_to_lev(zlev)); | ||||
|       break; | ||||
| @@ -378,8 +404,8 @@ void applymodel(hyperpoint H, hyperpoint& ret) { | ||||
|     case mdFisheye: { | ||||
|       ld zlev = find_zlev(H); | ||||
|       H = space_to_perspective(H); | ||||
|       H[2] = zlev; | ||||
|       ret = H / sqrt(1 + sqhypot_d(3, H)); | ||||
|       H[DIM] = zlev; | ||||
|       ret = H / sqrt(1 + sqhypot_d(DIM+1, H)); | ||||
|       break; | ||||
|       } | ||||
|      | ||||
| @@ -409,6 +435,7 @@ void applymodel(hyperpoint H, hyperpoint& ret) { | ||||
|         } | ||||
|    | ||||
|       H = space_to_perspective(H); | ||||
|       auto yz = move_z_to_y(H); | ||||
|       ld r = hypot_d(2, H); | ||||
|       ld c = H[0] / r; | ||||
|       ld s = H[1] / r; | ||||
| @@ -422,11 +449,12 @@ void applymodel(hyperpoint H, hyperpoint& ret) { | ||||
|  | ||||
|       if(vid.skiprope)  | ||||
|         ret = mobius(ret, vid.skiprope, 2); | ||||
|        | ||||
|          | ||||
|       if(pmodel == mdJoukowskyInverted) { | ||||
|         ld r2 = sqhypot_d(2, ret); | ||||
|         ret[0] = ret[0] / r2; | ||||
|         ret[1] = -ret[1] / r2; | ||||
|         move_y_to_z(ret, yz);       | ||||
|         conformal::apply_orientation(ret[1], ret[0]); | ||||
|          | ||||
|         /* | ||||
| @@ -439,7 +467,10 @@ void applymodel(hyperpoint H, hyperpoint& ret) { | ||||
|         ret[0] = alpha; | ||||
|         ret[1] = log(mod); */ | ||||
|         } | ||||
|       else conformal::apply_orientation(ret[0], ret[1]); | ||||
|       else { | ||||
|         move_y_to_z(ret, yz);       | ||||
|         conformal::apply_orientation(ret[0], ret[1]); | ||||
|         } | ||||
|    | ||||
|       break; | ||||
|       } | ||||
| @@ -511,7 +542,7 @@ void applymodel(hyperpoint H, hyperpoint& ret) { | ||||
|     case mdEquidistant: case mdEquiarea: { | ||||
|       ld zlev = find_zlev(H); | ||||
|  | ||||
|       ld rad = hypot_d(2, H); | ||||
|       ld rad = hypot_d(DIM, H); | ||||
|       if(rad == 0) rad = 1; | ||||
|       ld d = hdist0(H); | ||||
|       ld df, zf; | ||||
| @@ -525,7 +556,8 @@ void applymodel(hyperpoint H, hyperpoint& ret) { | ||||
|         d = sqrt(2*(cosh(d) - 1)) / 1.5; | ||||
|  | ||||
|       ret = H * (d * df / rad / M_PI); | ||||
|       ret[2] = 0;  | ||||
|       if(DIM == 2) ret[2] = 0;  | ||||
|       if(MAXMDIM == 4) ret[3] = 1; | ||||
|       if(zlev != 1 && current_display->stereo_active())  | ||||
|         apply_depth(ret, d * zf / M_PI); | ||||
|        | ||||
|   | ||||
| @@ -496,7 +496,7 @@ vector<glvertex> line_vertices; | ||||
| void glapplymatrix(const transmatrix& V) { | ||||
|   GLfloat mat[16]; | ||||
|   int id = 0; | ||||
|   if(DIM == 3) { | ||||
|   if(pmodel == mdPerspective && DIM == 3) { | ||||
|     if(elliptic && spherephase < 2) { | ||||
|       for(int y=0; y<4; y++) { | ||||
|         for(int x=0; x<4; x++) mat[id++] = -V[x][y]; | ||||
|   | ||||
| @@ -1170,6 +1170,7 @@ void push_game() { | ||||
|  | ||||
| void set_geometry(eGeometry target) { | ||||
|   if(geometry != target) { | ||||
|     int old_DIM = DIM; | ||||
|     stop_game(); | ||||
|     ors::reset(); | ||||
|     geometry = target; | ||||
| @@ -1196,6 +1197,8 @@ void set_geometry(eGeometry target) { | ||||
|     #if CAP_BT | ||||
|     if(geometry == gBinaryTiling || DIM == 3) variation = eVariation::pure; | ||||
|     #endif | ||||
|     if(DIM == 3 && old_DIM == 3 && pmodel == mdDisk) pmodel = mdPerspective; | ||||
|     if(DIM == 2 && pmodel == mdPerspective) pmodel = mdDisk; | ||||
|     | ||||
|     need_reset_geometry = true;  | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue