From 2a0b0101fd07e4af32cb305a8ec8023b3a804a35 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Wed, 3 Jun 2020 15:11:20 +0200 Subject: [PATCH] raycasting in 2D --- celldrawer.cpp | 2 ++ fake.cpp | 6 ++-- floorshapes.cpp | 3 ++ geometry.cpp | 5 ++- graph.cpp | 2 +- nonisotropic.cpp | 33 ++++++++++++++------ raycaster.cpp | 81 ++++++++++++++++++++++++++++++++++-------------- sky.cpp | 1 + 8 files changed, 94 insertions(+), 39 deletions(-) diff --git a/celldrawer.cpp b/celldrawer.cpp index 1f5f07dd..34c18bb2 100644 --- a/celldrawer.cpp +++ b/celldrawer.cpp @@ -662,6 +662,8 @@ int celldrawer::getSnakelevColor(int i, int last) { void celldrawer::draw_wall() { + if(no_wall_rendering) return; + if(GDIM == 3 && WDIM == 2) { if(!qfi.fshape) qfi.fshape = &cgi.shFullFloor; if(conegraph(c)) { diff --git a/fake.cpp b/fake.cpp index 235781a4..937cdd01 100644 --- a/fake.cpp +++ b/fake.cpp @@ -26,9 +26,9 @@ EX namespace fake { EX bool available() { if(in()) return true; - if(GDIM == 2 && standard_tiling() && (PURE || BITRUNCATED)) return true; + if(WDIM == 2 && standard_tiling() && (PURE || BITRUNCATED)) return true; if(arcm::in() && PURE) return true; - if(GDIM == 2) return false; + if(WDIM == 2) return false; if(among(geometry, gRhombic3, gBitrunc3)) return false; return euc::in() || reg3::in(); } @@ -366,6 +366,7 @@ EX void compute_scale() { ginf[gFake].g = WDIM == 3 ? giSphere3 : giSphere2; } + geom3::apply_always3(); ld around_ideal = 1/(1/2. - 1./get_middle()); if(arcm::in()) { @@ -461,6 +462,7 @@ EX void change_around() { fixmatrix(View); sightranges[gFake] = range * t; texture::config.remap(); + geom3::apply_always3(); } EX void configure() { diff --git a/floorshapes.cpp b/floorshapes.cpp index 9a6d6b41..8be330a4 100644 --- a/floorshapes.cpp +++ b/floorshapes.cpp @@ -914,6 +914,7 @@ EX int shvid(cell *c) { } EX struct dqi_poly *draw_shapevec(cell *c, const transmatrix& V, const vector &shv, color_t col, PPR prio IS(PPR::DEFAULT)) { + if(no_wall_rendering) return NULL; if(!c) return &queuepolyat(V, shv[0], col, prio); else if(WDIM == 3) return NULL; #if CAP_GP @@ -950,10 +951,12 @@ EX struct dqi_poly *draw_shapevec(cell *c, const transmatrix& V, const vector floorshape::* tab IS(&floorshape::b)) { + if(no_wall_rendering) return; if(qfi.shape) queuepolyat(V * qfi.spin, *qfi.shape, col, prio); else if(qfi.usershape >= 0) { diff --git a/geometry.cpp b/geometry.cpp index 53faf247..f4f5afd5 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -616,12 +616,11 @@ void geometry_information::prepare_basics() { if(fake::in() && WDIM == 2) { auto& u = *fake::underlying_cgip; geometry = fake::underlying; - ld orig = xpush0(u.hcrossf)[0] / xpush0(u.hcrossf)[WDIM]; + ld orig = xpush0(u.hcrossf)[0] / xpush0(u.hcrossf)[GDIM]; geometry = gFake; - ld our = xpush0(hcrossf)[0] / xpush0(hcrossf)[WDIM]; + ld our = xpush0(hcrossf)[0] / xpush0(hcrossf)[GDIM]; fake::scale = our / orig; // if(debugflags & DF_GEOM) - println(hlog, "scale set to ", fake::scale); } if(fake::in() && WDIM == 3) { diff --git a/graph.cpp b/graph.cpp index a3c0a7ca..decb34f7 100644 --- a/graph.cpp +++ b/graph.cpp @@ -3769,7 +3769,7 @@ EX void gridline(const transmatrix& V, const hyperpoint h1, const hyperpoint h2, } EX int wall_offset(cell *c) { - if(hybri) return hybrid::wall_offset(c); + if(hybri || WDIM == 2) return hybrid::wall_offset(c); if(kite::in() && kite::getshape(c->master) == kite::pKite) return 10; return 0; } diff --git a/nonisotropic.cpp b/nonisotropic.cpp index 27f63829..3338f6dc 100644 --- a/nonisotropic.cpp +++ b/nonisotropic.cpp @@ -1068,6 +1068,9 @@ EX namespace hybrid { EX transmatrix ray_iadj(cell *c, int i) { if(prod && i == c->type-2) return (mscale(Id, +cgi.plevel)); if(prod && i == c->type-1) return (mscale(Id, -cgi.plevel)); + if(WDIM == 2) { + return to_other_side(get_corner_position(c, i), get_corner_position(c, (i+1))); + } if(prod) { transmatrix T; cell *cw = hybrid::get_where(c).first; @@ -1253,6 +1256,11 @@ EX namespace hybrid { EX hyperpoint get_corner(cell *c, int i, int next, ld z) { ld lev = cgi.plevel * z / 2; + if(WDIM == 2) { + ld zz = lerp(cgi.FLOOR, cgi.WALL, (1+z) / 2); + hyperpoint h = zshift(get_corner_position(c, i+next), zz); + return h; + } if(prod) { dynamicval g(geometry, hybrid::underlying); dynamicval gc(cgip, hybrid::underlying_cgip); @@ -1276,24 +1284,25 @@ EX namespace hybrid { EX int wall_offset(cell *c) { if(GOLDBERG) { /* a bit slow... */ - cell *c1 = get_where(c).first; - gp::draw_li = PIU(gp::get_local_info(c1)); + cell *c1 = WDIM == 2 ? c : get_where(c).first; + gp::draw_li = WDIM == 2 ? gp::get_local_info(c1) : PIU(gp::get_local_info(c1)); } - int id = hybrid::underlying == gArchimedean ? arcm::id_of(c->master) + 20 * arcm::parent_index_of(c->master) : shvid(c); + auto ugeometry = hybri ? hybrid::underlying : geometry; + int id = ugeometry == gArchimedean ? arcm::id_of(c->master) + 20 * arcm::parent_index_of(c->master) : shvid(c); if(isize(cgi.walloffsets) <= id) cgi.walloffsets.resize(id+1, {-1, nullptr}); auto &wop = cgi.walloffsets[id]; int &wo = wop.first; if(!wop.second) wop.second = c; if(wo == -1) { - cell *c1 = hybrid::get_where(c).first; + cell *c1 = hybri ? hybrid::get_where(c).first : c; wo = isize(cgi.shWall3D); - int won = wo + c->type; + int won = wo + c->type + (WDIM == 2 ? 2 : 0); if(!cgi.wallstart.empty()) cgi.wallstart.pop_back(); cgi.reserve_wall3d(won); - if(prod) for(int i=0; itype; i++) { + if(prod || WDIM == 2) for(int i=0; itype; i++) { hyperpoint w; - ((hrmap_hybrid*)currentmap)->in_underlying([&] { + auto f = [&] { /* mirror image of C0 in the axis h1-h2 */ hyperpoint h1 = get_corner_position(c1, i); hyperpoint h2 = get_corner_position(c1, i+1); @@ -1302,7 +1311,11 @@ EX namespace hybrid { w = T * C0; w[1] = -w[1]; w = inverse(T) * w; - }); + }; + if(prod) + ((hrmap_hybrid*)currentmap)->in_underlying(f); + else + f(); cgi.walltester[wo + i] = w; } @@ -1314,7 +1327,7 @@ EX namespace hybrid { int z = a ? 1 : -1; hyperpoint ctr = zpush0(z * cgi.plevel/2); for(int i=0; itype; i++) - if(prod) + if(prod || WDIM == 2) l.push_back(hybrid::get_corner(c1, i, 0, z)); else { l.push_back(ctr); @@ -1341,7 +1354,7 @@ EX namespace hybrid { }); EX vector> gen_sample_list() { - if(!hybri) return {make_pair(0, centerover), make_pair(centerover->type, nullptr)}; + if(!hybri && WDIM != 2) return {make_pair(0, centerover), make_pair(centerover->type, nullptr)}; vector> result; for(auto& v: cgi.walloffsets) if(v.first >= 0) result.push_back(v); sort(result.begin(), result.end()); diff --git a/raycaster.cpp b/raycaster.cpp index dced0a10..69cee0c7 100644 --- a/raycaster.cpp +++ b/raycaster.cpp @@ -65,7 +65,8 @@ eGeometry last_geometry; EX bool available() { if(noGUI) return false; if(!vid.usingGL) return false; - if(WDIM == 2) return false; + if(GDIM == 2) return false; + if(WDIM == 2 && (kite::in() || bt::in())) return false; if(hyperbolic && pmodel == mdPerspective && !kite::in()) return true; if(sphere && pmodel == mdPerspective && !rotspace) @@ -154,7 +155,7 @@ shared_ptr our_raycaster; EX void reset_raycaster() { our_raycaster = nullptr; } -int deg; +int deg, irays; #ifdef GLES_ONLY void add(string& tgt, string type, string name, int min_index, int max_index) { @@ -190,6 +191,8 @@ void enable_raycaster() { reset_raycaster(); } + wall_offset(centerover); /* so raywall is not empty and deg is not zero */ + deg = 0; auto samples = hybrid::gen_sample_list(); @@ -217,7 +220,7 @@ void enable_raycaster() { #endif " }\n"; - int irays = isize(cgi.raywall); + irays = isize(cgi.raywall); string rays = its(irays); string fsh = @@ -299,7 +302,7 @@ void enable_raycaster() { } else { fsh += "const int walloffset = 0;\n" - "const int sides = " + its(centerover->type) + ";\n"; + "const int sides = " + its(centerover->type+(WDIM == 2 ? 2 : 0)) + ";\n"; } @@ -417,47 +420,49 @@ void enable_raycaster() { fmain += " if(which == -1) {\n"; - fmain += "for(int i="+its(flat1)+"; i<"+(prod ? "sides-2" : its(flat2))+"; i++) {\n"; + fmain += "for(int i="+its(flat1)+"; i<"+(prod ? "sides-2" : WDIM == 2 ? "sides" : its(flat2))+"; i++) {\n"; + + fmain += "int woi = walloffset+i;\n"; if(in_h2xe()) fmain += - " mediump float v = ((position - uM[walloffset+i] * position)[2] / (uM[walloffset+i] * tangent - tangent)[2]);\n" + " mediump float v = ((position - uM[woi] * position)[2] / (uM[woi] * tangent - tangent)[2]);\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[2] < (uM[walloffset+i] * next_tangent)[2]) continue;\n" + " if(next_tangent[2] < (uM[woi] * next_tangent)[2]) continue;\n" " d /= xspeed;\n"; else if(in_s2xe()) fmain += - " mediump float v = ((position - uM[walloffset+i] * position)[2] / (uM[walloffset+i] * tangent - tangent)[2]);\n" + " mediump float v = ((position - uM[woi] * position)[2] / (uM[woi] * tangent - tangent)[2]);\n" " mediump float d = atan(v);\n" " mediump vec4 next_tangent = tangent * cos(d) - position * sin(d);\n" - " if(next_tangent[2] > (uM[walloffset+i] * next_tangent)[2]) continue;\n" + " if(next_tangent[2] > (uM[woi] * next_tangent)[2]) continue;\n" " d /= xspeed;\n"; else if(in_e2xe()) fmain += - " mediump float deno = dot(position, tangent) - dot(uM[walloffset+i]*position, uM[walloffset+i]*tangent);\n" + " mediump float deno = dot(position, tangent) - dot(uM[woi]*position, uM[woi]*tangent);\n" " if(deno < 1e-6 && deno > -1e-6) continue;\n" - " mediump float d = (dot(uM[walloffset+i]*position, uM[walloffset+i]*position) - dot(position, position)) / 2. / deno;\n" + " mediump float d = (dot(uM[woi]*position, uM[woi]*position) - dot(position, position)) / 2. / deno;\n" " if(d < 0.) continue;\n" " mediump vec4 next_position = position + d * tangent;\n" - " if(dot(next_position, tangent) < dot(uM[walloffset+i]*next_position, uM[walloffset+i]*tangent)) continue;\n" + " if(dot(next_position, tangent) < dot(uM[woi]*next_position, uM[woi]*tangent)) continue;\n" " d /= xspeed;\n"; else if(hyperbolic) fmain += - " mediump float v = ((position - uM[i] * position)[3] / (uM[i] * tangent - tangent)[3]);\n" + " mediump float v = ((position - uM[woi] * position)[3] / (uM[woi] * 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(next_tangent[3] < (uM[woi] * next_tangent)[3]) continue;\n"; else if(sphere) fmain += - " mediump float v = ((position - uM[i] * position)[3] / (uM[i] * tangent - tangent)[3]);\n" + " mediump float v = ((position - uM[woi] * position)[3] / (uM[woi] * tangent - tangent)[3]);\n" " mediump float d = atan(v);\n" " mediump vec4 next_tangent = -position * sin(d) + tangent * cos(d);\n" - " if(next_tangent[3] > (uM[i] * next_tangent)[3]) continue;\n"; + " if(next_tangent[3] > (uM[woi] * next_tangent)[3]) continue;\n"; else fmain += - " mediump float deno = dot(position, tangent) - dot(uM[i]*position, uM[i]*tangent);\n" + " mediump float deno = dot(position, tangent) - dot(uM[woi]*position, uM[woi]*tangent);\n" " if(deno < 1e-6 && deno > -1e-6) continue;\n" - " mediump float d = (dot(uM[i]*position, uM[i]*position) - dot(position, position)) / 2. / deno;\n" + " mediump float d = (dot(uM[woi]*position, uM[woi]*position) - dot(position, position)) / 2. / deno;\n" " if(d < 0.) continue;\n" " mediump vec4 next_position = position + d * tangent;\n" - " if(dot(next_position, tangent) < dot(uM[i]*next_position, uM[i]*tangent)) continue;\n"; + " if(dot(next_position, tangent) < dot(uM[woi]*next_position, uM[woi]*tangent)) continue;\n"; fmain += " if(d < dist) { dist = d; which = i; }\n" @@ -1140,7 +1145,7 @@ EX void cast() { if(o->uWallOffset != -1) { glUniform1i(o->uWallOffset, wall_offset(centerover)); - glUniform1i(o->uSides, centerover->type); + glUniform1i(o->uSides, centerover->type + (WDIM == 2 ? 2 : 0)); } auto sa = hybrid::gen_sample_list(); @@ -1153,6 +1158,18 @@ EX void cast() { if(!c) continue; for(int j=0; jtype; j++) ms[id+j] = hybrid::ray_iadj(c, j); + if(WDIM == 2) for(int a: {0, 1}) { + int z = a ? 1 : -1; + hyperpoint h = Hypc; + for(int a=0; atype; a++) { + hyperpoint corner = hybrid::get_corner(c, a, 0, z); + h += corner; + } + h = normalize(h); + ld d = hdist0(h); + if(h[2] > 0) d = -d; + ms[id+c->type+a] = zpush(2*d); + } } // println(hlog, ms); @@ -1219,17 +1236,35 @@ EX void cast() { } } - transmatrix T = currentmap->iadj(c, i) * inverse(ms[wall_offset(c) + i]); + int wo = wall_offset(c); + if(wo >= irays) { + println(hlog, "wo=", wo, " irays = ", irays); + return; + } + transmatrix T = currentmap->iadj(c, i) * inverse(ms[wo + i]); for(int k=0; k<=isize(ms); k++) { if(k < isize(ms) && !eqmatrix(ms[k], T)) continue; if(k == isize(ms)) ms.push_back(T); connections[u][2] = (k+.5) / 1024.; break; } - connections[u][3] = (wall_offset(c1) / 256.) + (c1->type + .5) / 4096.; + connections[u][3] = (wall_offset(c1) / 256.) + (c1->type + (WDIM == 2 ? 2 : 0) + .5) / 4096.; + } + if(WDIM == 2) for(int a: {0, 1}) { + celldrawer dd; + dd.c = c; + dd.setcolors(); + transmatrix Vf; + dd.set_land_floor(Vf); + int u = (id/per_row*length) + (id%per_row * deg) + c->type + a; + wallcolor[u] = glhr::acolor(darkena(dd.fcol, 0, 0xFF)); + if(qfi.fshape) + texturemap[u] = floor_texture_map[qfi.fshape->id]; + else + texturemap[u] = glhr::makevertex(0.1,0,0); } } - + if(prod) { for(auto p: sa) { int id =p.first; diff --git a/sky.cpp b/sky.cpp index ab77cf55..cc2496fc 100644 --- a/sky.cpp +++ b/sky.cpp @@ -34,6 +34,7 @@ EX void prepare_sky() { sky = NULL; if(euclid) { if(WDIM == 3 || GDIM == 2) return; + if(no_wall_rendering) return; transmatrix T = ggmatrix(currentmap->gamestart()); T = gpushxto0(tC0(T)) * T; queuepoly(T, cgi.shEuclideanSky, 0x0044e4FF);