From cc9e03ddb83f26a1424660c6f92fe06b2ff12f3a Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sat, 9 Nov 2019 13:14:42 +0100 Subject: [PATCH] product:: product projections --- hypgraph.cpp | 15 ++++++++++++++- models.cpp | 23 ++++++++++++++++++++++- nonisotropic.cpp | 2 +- shaders.cpp | 8 ++++---- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/hypgraph.cpp b/hypgraph.cpp index 68bcc8ce..7d4f67a7 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -315,6 +315,15 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) { hyperpoint H_orig = H; + if(models::product_model()) { + ld zlev = zlevel(H); + H /= exp(zlev); + hybrid::in_underlying_geometry([&] { applymodel(H, ret); }); + ret[2] = zlev * models::product_z_scale; + ret = nisot::local_perspective * ret; + return; + } + switch(pmodel) { case mdPerspective: { ld ratio = vid.xres / current_display->tanfov / current_display->radius / 2; @@ -509,6 +518,10 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) { ret = lp_apply(H); break; } + if(prod) { + ret = H; + break; + } if(pmodel == mdHyperboloid) { ld& topz = models::top_z; if(H[2] > topz) { @@ -754,7 +767,7 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) { break; case mdEquidistant: case mdEquiarea: case mdEquivolume: { - if(nonisotropic) { + if(nonisotropic || prod) { ret = lp_apply(inverse_exp(H, iTable, false)); ret[3] = 1; break; diff --git a/models.cpp b/models.cpp index a70dca32..390966c0 100644 --- a/models.cpp +++ b/models.cpp @@ -159,6 +159,8 @@ EX namespace models { EX ld spiral_cone = 360; EX ld spiral_cone_rad; EX bool ring_not_spiral; + + EX ld product_z_scale = 1; EX void configure() { ld ball = -vid.ballangle * degree; @@ -198,7 +200,11 @@ EX namespace models { } EX bool model_available(eModel pm) { - if(prod) return pm == mdPerspective; + if(prod) { + if(pm == mdPerspective) return true; + if(among(pm, mdBall, mdHemisphere)) return false; + return PIU(model_available(pm)); + } if(sl2) return pm == mdGeodesic; if(nonisotropic) return among(pm, mdDisk, mdPerspective, mdHorocyclic, mdGeodesic, mdEquidistant, mdFisheye); if(pm == mdGeodesic && !sol) return false; @@ -220,11 +226,18 @@ EX namespace models { return among(pmodel, mdJoukowsky, mdJoukowskyInverted, mdBand) && GDIM == 2; } + EX bool product_model() { + if(!prod) return false; + if(among(pmodel, mdPerspective, mdHyperboloid, mdEquidistant)) return false; + return true; + } + int editpos = 0; EX string get_model_name(eModel m) { if(m == mdDisk && GDIM == 3 && (hyperbolic || nonisotropic)) return XLAT("ball model/Gans"); if(m == mdPerspective && prod) return XLAT("native perspective"); + if(prod) return PIU(get_model_name(m)); if(nonisotropic) { if(m == mdHorocyclic && !sol) return XLAT("simple model: projection"); if(m == mdPerspective) return XLAT("simple model: perspective"); @@ -630,6 +643,14 @@ EX namespace models { dialog::addSelItem(XLAT("vertical stretch"), fts(vid.stretch), 's'); dialog::add_action(edit_stretch); + + if(product_model()) { + dialog::addSelItem(XLAT("product Z stretch"), fts(product_z_scale), 'Z'); + dialog::add_action([] { + dialog::editNumber(product_z_scale, 0.1, 10, 0.1, 1, XLAT("product Z stretch"), ""); + dialog::scaleLog(); + }); + } dialog::addBoolItem(XLAT("use GPU to compute projections"), vid.consider_shader_projection, 'G'); bool shaderside_projection = get_shader_flags() & SF_DIRECT; diff --git a/nonisotropic.cpp b/nonisotropic.cpp index 6ef84cb9..b9b18f31 100644 --- a/nonisotropic.cpp +++ b/nonisotropic.cpp @@ -1167,7 +1167,7 @@ EX namespace product { EX void drawcell_stack(cellwalker cw, transmatrix V) { cell *c = cw.at; if(sphere) gmatrix[c] = V; /* some computations need gmatrix0 for underlying geometry */ - bool s = sphere; + bool s = sphere || pmodel != mdPerspective; hybrid::in_actual([&] { cell *c0 = hybrid::get_at(c, hybrid::current_view_level); cwall_offset = hybrid::wall_offset(c0); diff --git a/shaders.cpp b/shaders.cpp index f2e0bc92..d57abbd3 100644 --- a/shaders.cpp +++ b/shaders.cpp @@ -117,13 +117,13 @@ shared_ptr write_shader(flagtype shader_flags) { else if(!vid.consider_shader_projection) { shader_flags |= SF_PIXELS; } - else if(pmodel == mdDisk && MDIM == 3 && !spherespecial) { + else if(pmodel == mdDisk && MDIM == 3 && !spherespecial && !prod) { shader_flags |= SF_DIRECT; } else if(glhr::noshaders) { shader_flags |= SF_PIXELS; } - else if(pmodel == mdDisk && GDIM == 3 && !spherespecial && !nonisotropic) { + else if(pmodel == mdDisk && GDIM == 3 && !spherespecial && !nonisotropic && !prod) { coordinator += "t /= (t[3] + uAlpha);\n"; vsh += "uniform mediump float uAlpha;"; shader_flags |= SF_DIRECT | SF_BOX; @@ -197,7 +197,7 @@ shared_ptr write_shader(flagtype shader_flags) { break; } } - else if(geometry == gProduct && !hybrid::over_sphere()) { + else if(geometry == gProduct && !hybrid::over_sphere() && pmodel == mdPerspective) { shader_flags |= SF_PERS3 | SF_DIRECT; coordinator += "float z = log(t[2] * t[2] - t[0] * t[0] - t[1] * t[1]) / 2.;\n" @@ -209,7 +209,7 @@ shared_ptr write_shader(flagtype shader_flags) { distfun = "sqrt(z*z+d*d)"; treset = true; } - else if(geometry == gProduct && hybrid::over_sphere()) { + else if(geometry == gProduct && hybrid::over_sphere() && pmodel == mdPerspective) { shader_flags |= SF_PERS3 | SF_DIRECT; distfun = "length(t.xyz)", treset = true; }