diff --git a/fake.cpp b/fake.cpp index d55378ee..2d7f7bb1 100644 --- a/fake.cpp +++ b/fake.cpp @@ -253,6 +253,8 @@ EX ld compute_around(bool setup) { h2 = gpushxto0(u) * h2; u = gpushxto0(u) * u; + + reg3::compute_ultra(); ld x = hypot(h2[1], h2[2]); ld y = h2[0]; diff --git a/geom-exp.cpp b/geom-exp.cpp index 80075b05..efcd7454 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -770,6 +770,14 @@ EX void showEuclideanMenu() { } #endif + if(cgflags & qULTRA) { + dialog::addBoolItem(XLAT("truncate ultra-vertices with mirrors"), reg3::ultra_mirror_on, 'Z'); + dialog::add_action([] { + reg3::ultra_mirror_on = !reg3::ultra_mirror_on; + ray::reset_raycaster(); + }); + } + if(prod) { dialog::addSelItem(XLAT("Z-level height factor"), fts(vid.plevel_factor), 'Z'); dialog::add_action([] { @@ -1072,6 +1080,9 @@ int read_geom_args() { cheat(); shift(); currfp.qpaths.push_back(args()); } + else if(argis("-truncate-ultra")) { + shift(); reg3::ultra_mirror_on = argi(); + } else if(argis("-d:quotient")) launch_dialog(showQuotientConfig); #endif diff --git a/geometry.cpp b/geometry.cpp index 5e2ba0b3..89a04b86 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -133,6 +133,10 @@ struct geometry_information { ld strafedist; bool dirs_adjacent[32][32]; + ld ultra_mirror_dist, ultra_material_part, ultra_mirror_part; + + vector ultra_mirrors; + /** \brief for adjacent directions a,b, next_dir[a][b] is the next direction adjacent to a, in (counter?)clockwise order from b */ int next_dir[32][32]; diff --git a/geometry2.cpp b/geometry2.cpp index 59772efd..41b12105 100644 --- a/geometry2.cpp +++ b/geometry2.cpp @@ -282,6 +282,18 @@ void virtualRebase_cell(cell*& base, T& at, const U& check) { base = newbase; at = best_at; } + if(reg3::ultra_mirror_in()) { + again: + for(auto& v: cgi.mirror_matrices) { + T cand_at = v * at; + horo_distance newz(check(cand_at)); + if(newz < currz) { + currz = newz; + at = cand_at; + goto again; + } + } + } } template diff --git a/hypgraph.cpp b/hypgraph.cpp index aed56bee..9d6bfbfa 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -997,7 +997,7 @@ EX ld spherity(const transmatrix& V) { } EX bool confusingGeometry() { - return quotient || elliptic; + return quotient || elliptic || reg3::ultra_mirror_in(); } EX ld master_to_c7_angle() { @@ -2013,6 +2013,14 @@ EX namespace dq { visited_by_matrix.insert(b); drawqueue_c.emplace(c, T, band_shift); } + + EX void clear_all() { + visited.clear(); + visited_by_matrix.clear(); + visited_c.clear(); + drawqueue_c = {}; + drawqueue = {}; + } EX } diff --git a/raycaster.cpp b/raycaster.cpp index d311dfa5..94016423 100644 --- a/raycaster.cpp +++ b/raycaster.cpp @@ -462,6 +462,19 @@ void enable_raycaster() { fmain += " if(d < dist) { dist = d; which = i; }\n" "}\n"; + + if(hyperbolic && reg3::ultra_mirror_in()) { + fmain += "for(int i="+its(S7*2)+"; i<"+its(S7*2+isize(cgi.vertices_only))+"; i++) {\n"; + fmain += + " mediump float v = ((position - uM[i] * position)[3] / (uM[i] * tangent - tangent)[3]);\n" + " if(v > 1. || v < -1.) continue;\n" + " mediump float d = atanh(v);\n" + " mediump vec4 next_tangent = position * sinh(d) + tangent * cosh(d);\n" + " if(next_tangent[3] < (uM[i] * next_tangent)[3]) continue;\n" + " if(d < dist) { dist = d; which = i; }\n" + "}\n"; + } + // 20: get to horosphere +uBLevel (take smaller root) // 21: get to horosphere -uBLevel (take larger root) @@ -831,6 +844,12 @@ void enable_raycaster() { if(prod) fmain += "position.w = -zpos;\n"; + if(reg3::ultra_mirror_in()) fmain += + "if(which >= " + its(S7) + ") {" + " tangent = uM[which] * tangent;\n" + " continue;\n" + " }\n"; + // apply wall color fmain += " mediump vec2 u = cid + vec2(float(which) / float(uLength), 0);\n" @@ -1137,7 +1156,7 @@ EX void cast() { // println(hlog, ms); - if(!sol && !nil && reflect_val) { + if(!sol && !nil && (reflect_val || reg3::ultra_mirror_in())) { if(BITRUNCATED) exit(1); for(int j=0; jtype; j++) { transmatrix T = inverse(ms[j]); @@ -1146,6 +1165,11 @@ EX void cast() { transmatrix U = rspintox(h) * xpush(d/2) * MirrorX * xpush(-d/2) * spintox(h); ms.push_back(U); } + + if(reg3::ultra_mirror_in()) { + for(auto v: cgi.ultra_mirrors) + ms.push_back(v); + } } vector> connections(length * rows); diff --git a/reg3.cpp b/reg3.cpp index c1c7ffbf..e0562a9f 100644 --- a/reg3.cpp +++ b/reg3.cpp @@ -27,11 +27,58 @@ EX namespace reg3 { inline short& altdist(heptagon *h) { return h->emeraldval; } #endif + EX bool ultra_mirror_on; + + EX bool ultra_mirror_in() { return (cgflags & qULTRA) && ultra_mirror_on; } + EX bool in() { if(fake::in()) return FPIU(in()); return GDIM == 3 && !euclid && !bt::in() && !nonisotropic && !hybri && !kite::in(); } + EX void compute_ultra() { + cgi.ultra_mirror_part = .99; + cgi.ultra_material_part = .99; + + if(cgflags & qULTRA) { + transmatrix T = spintox(cgi.cellshape[0]); + hyperpoint a = T * cgi.cellshape[0]; + hyperpoint b = T * cgi.cellshape[1]; + ld f0 = 0.5; + ld f1 = binsearch(0.5, 1, [&] (ld d) { + hyperpoint c = lerp(b, a, d); + if(debugflags & DF_GEOM) + println(hlog, "d=", d, " c= ", c, " material = ", material(c)); + return material(c) <= 0; + }); + cgi.ultra_material_part = f1; + auto f = [&] (ld d) { + hyperpoint c = lerp(b, a, d); + c = normalize(c); + return c[1] * c[1] + c[2] * c[2]; + }; + for(int it=0; it<100; it++) { + ld fa = (f0*2+f1) / 3; + ld fb = (f0*1+f1*2) / 3; + if(debugflags & DF_GEOM) + println(hlog, "f(", fa, ") = ", f(fa), " f(", fb, ") = ", f(fb)); + if(f(fa) > f(fb)) f0 = fa; + else f1 = fb; + } + + cgi.ultra_mirror_part = f0; + + hyperpoint c = lerp(b, a, f0); + c = normalize(c); + c[1] = c[2] = 0; + c = normalize(c); + cgi.ultra_mirror_dist = hdist0(c); + } + + if(cgflags & qULTRA) for(auto v: cgi.vertices_only) + cgi.ultra_mirrors.push_back(rspintox(v) * xpush(cgi.ultra_mirror_dist*2) * MirrorX * spintox(v)); + } + EX void generate() { if(fake::in()) { @@ -129,39 +176,6 @@ EX namespace reg3 { ld between_centers = 2 * hdist0(midface); DEBB(DF_GEOM, ("between_centers = ", between_centers)); - if(hyperbolic && klein_scale > 1) { - transmatrix T = spintox(h012); - hyperpoint a = T * (C0 + klein_scale * h012); - hyperpoint b = T * (C0 + klein_scale * h013); - ld f0 = 0.5; - println(hlog, "a=", a, " b=", b); - ld f1 = binsearch(0.5, 1, [&] (ld d) { - hyperpoint c = lerp(b, a, d); - println(hlog, "d=", d, " c= ", c, " material = ", material(c)); - return material(c) <= 0; - }); - println(hlog, "f1 = ", f1); - auto f = [&] (ld d) { - hyperpoint c = lerp(b, a, d); - c = normalize(c); - return c[1] * c[1] + c[2] * c[2]; - }; - for(int it=0; it<100; it++) { - ld fa = (f0*2+f1) / 3; - ld fb = (f0*1+f1*2) / 3; - println(hlog, "f(", fa, ") = ", f(fa), " f(", fb, ") = ", f(fb)); - if(f(fa) > f(fb)) f0 = fa; - else f1 = fb; - } - - hyperpoint c = lerp(b, a, f0); - c = normalize(c); - c[1] = c[2] = 0; - c = normalize(c); - mirrordist = hdist0(c); - println(hlog, "mirrordist = ", mirrordist); - } - if(S7 == 20) { spins[0] = Id; spins[1] = cspin(0, 1, angle_between_faces) * cspin(1, 2, M_PI); @@ -233,6 +247,8 @@ EX namespace reg3 { if(!found) vertices_only.push_back(h); } + compute_ultra(); + for(int a=0; a<12; a++) for(int b=0; b<12; b++) if(cgi.dirs_adjacent[a][b]) @@ -302,6 +318,10 @@ EX namespace reg3 { if(!do_draw(c, V)) continue; drawcell(c, V); if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000) continue; + + if(ultra_mirror_in()) + for(auto& T: cgi.ultra_mirrors) + dq::enqueue_by_matrix(h, V * T); for(int d=0; dmove(d), V * tmatrices[h->fieldval][d]); @@ -869,10 +889,9 @@ EX namespace reg3 { void draw() override { sphereflip = Id; - // for(int i=0; imaster, cview()); + dq::clear_all(); + auto& enq = (ultra_mirror_in() ? dq::enqueue_by_matrix : dq::enqueue); + enq(centerover->master, cview()); while(!dq::drawqueue.empty()) { auto& p = dq::drawqueue.front(); @@ -887,9 +906,15 @@ EX namespace reg3 { if(!do_draw(c, V)) continue; drawcell(c, V); if(in_wallopt() && isWall3(c) && isize(dq::drawqueue) > 1000) continue; + + if(sightranges[geometry] == 0) return; + + if(ultra_mirror_in()) + for(auto& T: cgi.ultra_mirrors) + dq::enqueue_by_matrix(h, V * T); for(int i=0; imove(i)) { - dq::enqueue(h->move(i), V * adj(h, i)); + enq(h->move(i), V * adj(h, i)); } } }