diff --git a/basegraph.cpp b/basegraph.cpp index bc78dcd7..1ccbcec6 100644 --- a/basegraph.cpp +++ b/basegraph.cpp @@ -371,6 +371,11 @@ void display_data::set_projection(int ed) { glUniform1f(glhr::current->uPRECZ, solv::PRECZ); } + if(glhr::new_shader_projection == glhr::shader_projection::standardSL2) { + glUniform1f(glhr::current->uIndexSL, 0); + glUniform1i(glhr::current->uIterations, slr::steps); + } + auto cd = current_display; if(!shaderside_projection || glhr::new_shader_projection == glhr::shader_projection::flatten) { diff --git a/config.cpp b/config.cpp index fd4bdc1a..b9ecc1d1 100644 --- a/config.cpp +++ b/config.cpp @@ -504,6 +504,11 @@ EX void initConfig() { addsaver(vid.cells_drawn_limit, "limit on cells drawn", 10000); addsaver(vid.cells_generated_limit, "limit on cells generated", 25); + addsaver(solv::solrange_xy, "solrange-xy"); + addsaver(solv::solrange_z, "solrange-z"); + addsaver(slr::steps, "slr-steps"); + addsaver(slr::range_xy, "slr-range-xy"); + addsaver(vid.skiprope, "mobius", 0); addsaver(models::formula, "formula"); @@ -865,6 +870,26 @@ EX void edit_sightrange() { dialog::extra_options = xo; popScreen(); }); } + else if(pmodel == mdGeodesic && sl2) { + dialog::addSelItem(XLAT("fog effect"), fts(sightranges[geometry]), 'R'); + dialog::add_action([] { + auto xo = dialog::extra_options; + dialog::editNumber(sightranges[geometry], 0, 10, 0.5, M_PI, "", ""); + dialog::extra_options = xo; popScreen(); + }); + dialog::addSelItem(XLAT("max difference in X/Y coordinates"), fts(slr::range_xy), 'X'); + dialog::add_action([] { + auto xo = dialog::extra_options; + dialog::editNumber(solv::solrange_xy, 0, 10, 0.5, 4, XLAT("max difference in X/Y coordinates"), ""); + dialog::extra_options = xo; popScreen(); + }); + dialog::addSelItem(XLAT("steps"), its(slr::steps), 'Z'); + dialog::add_action([] { + auto xo = dialog::extra_options; + dialog::editNumber(slr::steps, 0, 50, 1, 10, "", ""); + dialog::extra_options = xo; popScreen(); + }); + } else { dialog::addBoolItem(XLAT("draw range based on distance"), vid.use_smart_range == 0, 'D'); dialog::add_action([] () { vid.use_smart_range = 0; popScreen(); edit_sightrange(); }); diff --git a/drawing.cpp b/drawing.cpp index fbe002bc..c0540ea6 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -538,6 +538,8 @@ void glapplymatrix(const transmatrix& V) { EX int global_projection; +int min_slr, max_slr = 0; + #if MAXMDIM >= 4 extern renderbuffer *floor_textures; #endif @@ -582,6 +584,8 @@ void dqi_poly::gldraw() { glhr::be_nontextured(); glhr::vertices(v); } + + next_slr: for(int ed = current_display->stereo_active() ? -1 : 0; ed<2; ed+=2) { if(global_projection && global_projection != ed) continue; @@ -653,6 +657,12 @@ void dqi_poly::gldraw() { glDrawArrays(GL_LINE_STRIP, offset, cnt); } } + + if(min_slr < max_slr) { + min_slr++; + glUniform1f(glhr::current->uIndexSL, M_PI * min_slr); + goto next_slr; + } } #endif @@ -1142,6 +1152,14 @@ void dqi_poly::draw() { #if CAP_GL if(vid.usingGL && (current_display->set_all(global_projection), shaderside_projection)) { + if(sl2 && pmodel == mdGeodesic) { + ld z = atan2(V[2][3], V[3][3]); + auto zr = sightranges[geometry]; + min_slr = ceil((-zr - z) / M_PI); + max_slr = floor((zr - z) / M_PI); + if(min_slr > max_slr) return; + glUniform1f(glhr::current->uIndexSL, M_PI * min_slr); + } set_width(get_width(this)); flags &= ~POLY_INVERSE; gldraw(); diff --git a/hypgraph.cpp b/hypgraph.cpp index 74144cb0..5665daab 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -2003,6 +2003,10 @@ EX bool do_draw(cell *c, const transmatrix& T) { if(!nisot::in_table_range(tC0(T))) return false; if(!limited_generation(c)) return false; } + else if(pmodel == mdGeodesic && sl2) { + if(hypot(tC0(T)[2], tC0(T)[3]) > cosh(slr::range_xy)) return false; + if(!limited_generation(c)) return false; + } else if(vid.use_smart_range) { if(cells_drawn >= 50 && !in_smart_range(T)) return false; if(!limited_generation(c)) return false; diff --git a/nonisotropic.cpp b/nonisotropic.cpp index cafdcd6d..e1d82b2f 100644 --- a/nonisotropic.cpp +++ b/nonisotropic.cpp @@ -804,6 +804,9 @@ EX namespace slr { // then coordinates 2<->3 are swapped */ + EX ld range_xy = 3; + EX int steps = 15; + EX hyperpoint from_phigans(hyperpoint h) { ld r = asinh(hypot_d(2, h)); ld x = h[0]; @@ -967,11 +970,11 @@ EX namespace slr { else beta = theta + atan(sin(alpha) * roottan(c, s)); } - EX hyperpoint get_inverse_exp(hyperpoint h) { - if(sqhypot_d(2, h) < 1e-12) return point3(0, 0, atan2(h[2], h[3])); + EX hyperpoint get_inverse_exp(hyperpoint h, ld index IS(0)) { + if(sqhypot_d(2, h) < 1e-12) return point3(0, 0, atan2(h[2], h[3]) + index); ld r = asinh(hypot_d(2, h)); - ld phi = atan2(h[2], h[3]); - ld theta = atan2(h[1], h[0]) + phi; + ld phi = atan2(h[2], h[3]) + index; + ld theta = atan2(h[1], h[0]) + phi + index; ld alpha, s, beta; find_alpha(phi, r, theta, alpha, s, beta); @@ -986,61 +989,80 @@ EX namespace slr { " if(y >= 0.) return atan(y / x) + PI;" " if(y < 0.) return atan(y / x) - PI;" " }" + + "uniform mediump float uIndexSL;" + "uniform mediump int uIterations;" "vec4 inverse_exp(vec4 h) {" - "if(h[0]*h[0] + h[1] * h[1] < 1e-6) return vec4(0, 0, atan(h[2], h[3]), 1);" + "if(h[0]*h[0] + h[1] * h[1] < 1e-6) return vec4(0, 0, atan(h[2], h[3]) + uIndexSL, 1);" "float r = asinh(sqrt(h[0] * h[0] + h[1] * h[1]));" - "float phi = atan2(h[2], h[3]);" - "float theta = atan2(h[1], h[0]) + phi;" + "float phi = atan2(h[2], h[3]) + uIndexSL;" + "float theta = atan2(h[1], h[0]) + phi + uIndexSL;" "float alpha;" "float s;" "float beta;" "float sgn = 1.;" + "float bound = .999;" "if(phi < 0.) { phi = -phi; theta = -theta; sgn = -1.; }" "float c;" "s = sinh(r) / cos(PI/4.);" "float gphi = 2.*sin(PI/4.)*s - atan(sin(PI/4.) * s);" + "float lo_gphi = gphi;" + "float lo_s = s;" + "float lo_alpha = PI/4.;" + "float hi_gphi = gphi;" + "float hi_s = s;" + "float hi_alpha = PI/4.;" "if(gphi > phi) {" " float mina = 0.;" " float maxa = PI/4.;" - " for(int it=0; it<40; it++) {" + " lo_gphi = 0.; lo_s = r; lo_alpha = 0.;" + " for(int it=0; it phi) maxa = alpha;" - " else mina = alpha;" + " if(gphi > phi) { maxa = alpha; hi_alpha = alpha; hi_s = s; hi_gphi = gphi; }" + " else { mina = alpha; lo_alpha = alpha; lo_s = s; lo_gphi = gphi; }" " }" - " beta = theta + atan(sin(alpha) * tanh(c * s) / c);" " }" "else {" + " hi_gphi = phi; hi_s = phi; hi_alpha = 9;" " int next_nan = 1;" " float mina = PI/4.;" " float maxa = PI/2.;" - " for(int it=0; it<40; it++) {" + " for(int it=0; it cos(alpha)) { next_nan = 1; maxa = alpha; continue; }" + " if(sinh(r) * c > bound * cos(alpha)) { next_nan = 1; maxa = alpha; continue; }" " s = asin(sinh(r) * c / cos(alpha)) / c;" " gphi = 2.*sin(alpha)*s - atan(sin(alpha) * tan(c*s) / c);" - " if(gphi > phi) { next_nan = 0; maxa = alpha; }" - " else mina = alpha;" + " if(gphi > phi) { next_nan = 0; maxa = alpha; hi_gphi = gphi; hi_s = s; hi_alpha = alpha; }" + " else { mina = alpha; lo_gphi = gphi; lo_s = s; lo_alpha = alpha; }" " }" " if(next_nan != 0) {" - " mina = PI/4.;" - " for(int it=0; it<10; it++) {" + " mina = PI/4.; " + " for(int it=0; itbound) { maxa = alpha; next_nan = 1; continue; }" + " float s1 = PI - asin(z);" + " s = s1 / c;" + " gphi = 2.*sin(alpha)*s - atan(sin(alpha) * tan(s1) / c) - PI;" + " if(gphi < phi) { next_nan = 0; maxa = alpha; hi_gphi = gphi; hi_s = s; hi_alpha = alpha; }" + " else { mina = alpha; lo_gphi = gphi; lo_s = s; lo_alpha = alpha; }" " }" - " beta = theta + atan(sin(alpha) * tanh(c * s) / c) + PI;" " }" - " else beta = theta + atan(sin(alpha) * tanh(c * s) / c);" " }" + "if(hi_alpha < 9) {" + "float fr = (phi-lo_gphi) / (hi_gphi-lo_gphi);" + "alpha = lo_alpha + (hi_alpha-lo_alpha) * fr;" + "s = lo_s + (hi_s-lo_s) * fr;" + "}" + "beta = theta - phi + 2.*sin(alpha)*s;" "alpha = alpha * sgn; beta = beta * sgn;" - "return vec4(s * cos(beta) * cos(alpha), s * sin(beta) * cos(alpha), s * sin(alpha), 1);" + "return vec4(s * cos(beta) * cos(alpha), s * sin(beta) * cos(alpha), s * sin(alpha), 1.);" "}"; EX transmatrix adjmatrix(int i, int j) { diff --git a/shaders.cpp b/shaders.cpp index 82b84bb9..b09c5267 100644 --- a/shaders.cpp +++ b/shaders.cpp @@ -290,7 +290,8 @@ struct GLprogram { GLuint _program; GLuint vertShader, fragShader; - GLint uMVP, uFog, uFogColor, uColor, tTexture, tInvExpTable, uMV, uProjection, uAlpha, uFogBase, uPRECX, uPRECY, uPRECZ; + GLint uMVP, uFog, uFogColor, uColor, tTexture, tInvExpTable, uMV, uProjection, uAlpha, uFogBase; + GLint uPRECX, uPRECY, uPRECZ, uIndexSL, uIterations; GLprogram(string vsh, string fsh) { _program = glCreateProgram(); @@ -351,6 +352,8 @@ struct GLprogram { uPRECX = glGetUniformLocation(_program, "PRECX"); uPRECY = glGetUniformLocation(_program, "PRECY"); uPRECZ = glGetUniformLocation(_program, "PRECZ"); + uIndexSL = glGetUniformLocation(_program, "uIndexSL"); + uIterations = glGetUniformLocation(_program, "uIterations"); #if DEBUG_GL printf("uniforms: %d %d %d %d\n", uMVP, uFog, uColor, tTexture);