1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-23 21:07:17 +00:00

raycasting in 2D

This commit is contained in:
Zeno Rogue 2020-06-03 15:11:20 +02:00
parent fad1c650c7
commit 2a0b0101fd
8 changed files with 94 additions and 39 deletions

View File

@ -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)) {

View File

@ -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() {

View File

@ -914,6 +914,7 @@ EX int shvid(cell *c) {
}
EX struct dqi_poly *draw_shapevec(cell *c, const transmatrix& V, const vector<hpcshape> &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<hp
}
EX void draw_floorshape(cell *c, const transmatrix& V, const floorshape &fsh, color_t col, PPR prio IS(PPR::DEFAULT)) {
if(no_wall_rendering) return;
draw_shapevec(c, V, fsh.b, col, prio);
}
EX void draw_qfi(cell *c, const transmatrix& V, color_t col, PPR prio IS(PPR::DEFAULT), vector<hpcshape> 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) {

View File

@ -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) {

View File

@ -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;
}

View File

@ -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<eGeometry> g(geometry, hybrid::underlying);
dynamicval<geometry_information*> 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; i<c1->type; i++) {
if(prod || WDIM == 2) for(int i=0; i<c1->type; 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; i<c1->type; 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<pair<int, cell*>> 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<pair<int, cell*>> result;
for(auto& v: cgi.walloffsets) if(v.first >= 0) result.push_back(v);
sort(result.begin(), result.end());

View File

@ -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<raycaster> 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; j<c->type; 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; a<c->type; 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;

View File

@ -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);