intra:: first version

This commit is contained in:
Zeno Rogue 2021-09-16 21:30:26 +02:00
parent 30f964e6e3
commit 663e334e38
12 changed files with 652 additions and 32 deletions

View File

@ -156,7 +156,7 @@ makeh$(EXE_EXTENSION): makeh.cpp
$(CXX) -O2 makeh.cpp -o $@
autohdr.h: makeh$(EXE_EXTENSION) language-data.cpp *.cpp
./makeh classes.cpp locations.cpp colors.cpp hyperpoint.cpp geometry.cpp goldberg.cpp init.cpp floorshapes.cpp cell.cpp multi.cpp shmup.cpp pattern2.cpp mapeditor.cpp graph.cpp textures.cpp hprint.cpp language.cpp util.cpp complex.cpp *.cpp > autohdr.h
./makeh classes.cpp locations.cpp colors.cpp hyperpoint.cpp geometry.cpp goldberg.cpp init.cpp floorshapes.cpp cell.cpp multi.cpp shmup.cpp pattern2.cpp mapeditor.cpp graph.cpp textures.cpp hprint.cpp language.cpp util.cpp complex.cpp multigame.cpp *.cpp > autohdr.h
language-data.cpp: langen$(EXE_EXTENSION)
./langen > language-data.cpp

View File

@ -1450,7 +1450,7 @@ EX int valence() {
/** portalspaces are not defined outside of a boundary */
EX bool is_boundary(cell *c) {
if(c == &out_of_bounds) return true;
return (cgflags & qPORTALSPACE) && isWall(c->wall);
return ((cgflags & qPORTALSPACE) || intra::in) && isWall(c->wall);
}
/** compute the distlimit for a tessellation automatically */

View File

@ -1196,7 +1196,7 @@ EX void check_cgi() {
if(fake::in()) fake::underlying_cgip->timestamp = ntimestamp;
if(arcm::alt_cgip) arcm::alt_cgip->timestamp = ntimestamp;
if(isize(cgis) > 4) {
if(isize(cgis) > 4 && !intra::in) {
vector<pair<int, string>> timestamps;
for(auto& t: cgis) timestamps.emplace_back(-t.second.timestamp, t.first);
sort(timestamps.begin(), timestamps.end());

View File

@ -4014,6 +4014,11 @@ EX subcellshape& generate_subcellshape_if_needed(cell *c, int id) {
ss.walltester.push_back(w);
}
if(hybri || WDIM == 2) {
ss.walltester.push_back(C0);
ss.walltester.push_back(C0);
}
for(int i=0; i<c1->type; i++)
ss.faces.push_back({hybrid::get_corner(c1, i, 0, -1), hybrid::get_corner(c1, i, 0, +1), hybrid::get_corner(c1, i, 1, +1), hybrid::get_corner(c1, i, 1, -1)});

View File

@ -123,6 +123,7 @@
#include "inforder.cpp"
#include "dpgen.cpp"
#include "vr.cpp"
#include "intra.cpp"
#if CAP_ROGUEVIZ
#include "rogueviz/rogueviz-all.cpp"

View File

@ -2902,6 +2902,17 @@ EX transmatrix get_shift_view_of(const hyperpoint H, const transmatrix V) {
/** shift the view according to the given tangent vector */
EX void shift_view(hyperpoint H) {
if(callhandlers(false, hooks_shift_view, H)) return;
static bool recursive = false;
if(!recursive && intra::in) {
H /= 10;
recursive = true;
for(int i=0; i<10; i++) {
shift_view(H);
intra::check_portal_movement();
}
recursive = false;
return;
}
auto oView = View;
View = get_shift_view_of(H, View);
auto& wc = current_display->which_copy;

297
intra.cpp Normal file
View File

@ -0,0 +1,297 @@
#include "hyper.h"
namespace hr {
EX namespace intra {
EX bool in;
#if HDR
/** information per every space connected with intra-portals */
struct intra_data {
gamedata gd;
geometryinfo gi;
int wallindex;
};
#endif
EX vector<intra_data> data;
/** index of the space we are currently in */
EX int intra_current;
/** map cells to their intra spaces */
EX map<cell*, int> intra_id;
#if HDR
/** information about portal (one side) */
struct portal_data {
int kind;
hyperpoint v0;
ld d;
transmatrix T;
transmatrix iT;
hyperpoint co0;
hyperpoint co1;
ld scale;
/* convert h to portal coordinates ('poco') to usual coordinates */
hyperpoint to_poco(hyperpoint h) const;
/* convert h from portal coordinates ('poco') to usual coordinates */
hyperpoint from_poco(hyperpoint h) const;
};
#endif
hyperpoint portal_data::to_poco(hyperpoint h) const {
if(prod && kind == 1) {
auto dec = product_decompose(h);
h = dec.second;
h[0] /= h[2];
h[1] /= h[2];
h[2] = dec.first - d;
h[3] = 1;
return h;
}
else if(prod && kind == 0) {
h = T * h;
ld z = product_decompose(h).first;
h /= exp(z);
auto h1 = h;
h[0] = asin_auto(h1[1]);
h[1] = z;
h[2] = asin_auto_clamp(h1[0] / cos_auto(h[0]));
h[3] = 1;
return h;
}
else {
h = T * h;
h /= h[3];
return h;
}
}
hyperpoint portal_data::from_poco(hyperpoint h) const {
if(prod && kind == 1) {
ld d = h[2];
h[2] = 1;
auto z = product_decompose(h).first;
return h * exp(d+d-z);
}
else if(prod && kind == 0) {
auto h0 = h;
h[0] = sin_auto(h0[2]) * cos_auto(h0[0]);
h[1] = sin_auto(h0[0]);
h[2] = cos_auto(h0[0]) * cos_auto(h0[2]);
h[3] = 1;
return iT * h * exp(h0[1]);
}
else {
h[3] = 1;
return normalize(iT * h);
}
}
EX portal_data make_portal(cellwalker cw) {
auto& ss = currentmap->get_cellshape(cw.at);
auto& fac = ss.faces[cw.spin];
portal_data id;
id.scale = 1;
if(prod && cw.spin == cw.at->type - 1) {
id.kind = 1;
id.d = product_decompose(fac[0]).first;
id.v0 = C0 * exp(id.d);
}
else if(prod && cw.spin == cw.at->type - 2) {
throw hr_exception("cannot construct a portal in this direction");
}
else if(prod) {
id.kind = 0;
id.v0 = Hypc;
id.scale = cgi.plevel;
for(auto p: fac) id.v0 += p;
id.v0 /= sqrt(abs(intval(id.v0, Hypc)));
id.T = cpush(0, -hdist0(id.v0)) * spintox(id.v0);
for(int i=0; i<3; i++) id.T[3][i] = id.T[i][3] = i==3;
if(debugflags & DF_GEOM)
for(int a=0; a<4; a++) {
hyperpoint h = fac[a];
println(hlog, kz(h), " -> ", kz(spintox(id.v0)*h), " -> ", kz(cpush(0, -hdist0(id.v0))) * kz(spintox(id.v0) * h), " -> ", kz(id.to_poco(h)));
}
}
else {
id.kind = 0;
id.v0 = Hypc;
for(auto p: fac) id.v0 += p;
id.v0 = normalize(id.v0);
id.T = cpush(2, -hdist0(id.v0)) * cspin(2, 0, 90*degree) * spintox(id.v0);
}
id.iT = inverse(id.T);
if(MDIM == 3) for(int i=0; i<4; i++) id.iT[3][i] = id.iT[i][3] = i==3;
id.co0 = id.to_poco(fac[(in_s2xe() || sphere) ? 2 : 0]);
id.co1 = id.to_poco(fac[1]);
return id;
}
#if HDR
/** information about connection (portal-to-portal) */
struct connection_data {
int source_world;
int target_world;
cellwalker scw, tcw;
portal_data id1;
portal_data id2;
transmatrix T;
};
#endif
EX map<cellwalker, connection_data> connections;
EX connection_data* find_connection(int a, int b) {
for(auto& p: connections)
if(intra_id[p.first.at] == a && p.second.target_world == b)
return &p.second;
return nullptr;
}
EX void switch_to(int id) {
if(intra_current == id) return;
data[intra_current].gd.storegame();
intra_current = id;
ginf[gProduct] = data[intra_current].gi;
data[intra_current].gd.restoregame();
}
void connect_portal_1(cellwalker cw1, cellwalker cw2) {
auto& p = connections[cw1];
p.source_world = intra_id[cw1.at];
p.target_world = intra_id[cw2.at];
p.scw = cw1;
p.tcw = cw2;
switch_to(intra_id[cw1.at]);
p.id1 = make_portal(cw1);
switch_to(intra_id[cw2.at]);
p.id2 = make_portal(cw2);
if(1) {
dynamicval<eGeometry> g(geometry, gCubeTiling);
transmatrix T1;
set_column(T1, 0, p.id1.co0);
set_column(T1, 1, p.id1.co1);
set_column(T1, 2, hyperpoint(0,0,p.id1.scale,0));
set_column(T1, 3, C03);
transmatrix T2;
set_column(T2, 0, p.id2.co0);
set_column(T2, 1, p.id2.co1);
set_column(T2, 2, hyperpoint(0,0,-p.id2.scale,0));
set_column(T2, 3, C03);
if(debugflags & DF_GEOM) for(int i=0; i<4; i++)
println(hlog, "mapping ", get_column(T1, i), " to ", get_column(T2, i));
p.T = T2 * inverse(T1);
}
}
EX vector<pair<int, cell*>> full_sample_list;
EX void connect_portal(cellwalker cw1, cellwalker cw2) {
connect_portal_1(cw1, cw2);
connect_portal_1(cw2, cw1);
}
/** make currentmap into one of the spaces in intra */
EX void become() {
auto& ac = currentmap->allcells();
for(cell *c: ac)
intra_id[c] = intra_current;
for(cell *c: ac)
currentmap->wall_offset(c);
for(cell *c: ac) c->item = itNone;
data.emplace_back();
data.back().gd.storegame();
data.back().gi = ginf[gProduct];
auto v = hybrid::gen_sample_list();
int gi = 0;
if(full_sample_list.size()) {
gi = full_sample_list.back().first;
full_sample_list.pop_back();
}
data.back().wallindex = gi;
for(auto x: v)
full_sample_list.emplace_back(x.first + gi, x.second);
sightranges[geometry] = 10;
}
/** after called become() on some spaces, actually start intra */
EX void start(int id IS(0)) {
in = true;
intra_current = id;
data[intra_current].gd.restoregame();
ginf[gProduct] = data[intra_current].gi;
}
#if HDR
/** a convenience struct to switch back after a temporary switch_to */
struct resetter {
int ic;
resetter() { ic = intra::intra_current; }
~resetter() { if(intra::in) switch_to(ic); }
};
#endif
EX void may_switch_to(cell *c) {
if(in) switch_to(intra_id[c]);
}
EX int full_wall_offset(cell *c) {
int wo = currentmap->wall_offset(c);
if(in) wo += data[intra_id[c]].wallindex;
return wo;
}
EX void check_portal_movement() {
transmatrix iView = view_inverse(View);
ld dist = hdist0(iView * C0);
int nei = -1;
for(int i=0; i<centerover->type; i++) {
ld dist1 = hdist0(currentmap->ray_iadj(centerover, i) * iView * C0);
if(dist1 < dist) nei = i, dist = dist1;
}
auto cw1 = cellwalker(centerover, nei);
ld c = camera_speed;
auto p = at_or_null(connections, cw1);
if(p) {
ld eps = 1e-3;
c /= p->id1.scale;
anims::cycle_length /= p->id1.scale;
array<hyperpoint, 3> ds; /* camera, forward, upward */
ds[0] = inverse(View) * C0;
ds[1] = inverse(get_shift_view_of(ctangent(2, -eps), View)) * C0;
ds[2] = inverse(get_shift_view_of(ctangent(1, +eps), View)) * C0;
for(auto& h: ds) h = p->id1.to_poco(h);
/* reset the original */
View = Id; NLP = Id;
switch_to(p->target_world);
centerover = p->tcw.at;
if(1) {
dynamicval<eGeometry> g(geometry, gCubeTiling);
for(auto& h: ds) h = p->T * h;
}
for(auto& h: ds) h = p->id2.from_poco(h);
set_view(ds[0], ds[1], ds[2]);
c *= p->id2.scale;
anims::cycle_length *= p->id2.scale;
camera_speed = c;
}
}
EX }
}

View File

@ -61,6 +61,8 @@ void gamedata_all(gamedata& gd) {
gd.store(land_structure);
gd.store(*current_display);
gd.store(cgip);
gd.store(hybrid::underlying);
gd.store(hybrid::underlying_cgip);
gd.store_ptr(vid);
gd.store(sightrange_bonus);
gd.store(genrange_bonus);

View File

@ -1410,7 +1410,7 @@ EX namespace hybrid {
vector<pair<int, cell*>> result;
for(auto& v: cgi.walloffsets) if(v.first >= 0) result.push_back(v);
sort(result.begin(), result.end());
result.emplace_back(isize(cgi.wallstart), nullptr);
result.emplace_back(isize(cgi.wallstart)-1, nullptr);
return result;
}

View File

@ -57,11 +57,13 @@ EX int max_cells = 2048;
EX bool rays_generate = true;
EX ld& exp_decay_current() {
if(intra::in) return exp_decay_exp;
if(fake::in()) return *FPIU(&exp_decay_current());
return (sn::in() || hyperbolic || sl2) ? exp_decay_exp : exp_decay_poly;
}
EX int& max_iter_current() {
if(intra::in) return max_iter_iso;
if(nonisotropic || stretch::in()) return max_iter_sol;
else if(is_eyes()) return max_iter_eyes;
else return max_iter_iso;
@ -93,6 +95,7 @@ ld& maxstep_current() {
eGeometry last_geometry;
vector<pair<int, cell*>> used_sample_list() {
if(intra::in) return intra::full_sample_list;
return hybrid::gen_sample_list();
}
@ -322,7 +325,8 @@ struct raygen {
void compute_which_and_dist();
void apply_reflect();
void move_forward();
void emit_iterate();
void emit_intra_portal(int gid1, int gid2);
void emit_iterate(int gid1);
void create();
};
@ -336,7 +340,7 @@ void raygen::compute_which_and_dist() {
fmain +=
" if(which == -1) {\n";
fmain += "for(int i="+its(flat1)+"; i<"+(prod ? "sides-2" : (WDIM == 2 || is_subcube_based(variation)) ? "sides" : its(flat2))+"; i++) {\n";
fmain += "for(int i="+its(flat1)+"; i<"+(prod ? "sides-2" : (WDIM == 2 || is_subcube_based(variation) || intra::in) ? "sides" : its(flat2))+"; i++) {\n";
// fmain += "int woi = walloffset+i;\n";
@ -961,15 +965,132 @@ void raygen::apply_reflect() {
}
}
void raygen::emit_iterate() {
void raygen::emit_intra_portal(int gid1, int gid2) {
int they_curvature = false;
if(1) {
intra::resetter ir;
intra::switch_to(gid2);
they_curvature = hyperbolic ? -1 : sphere ? 1 : 0;
/* product also has 0 */
}
if(prod && they_curvature) {
string fn = in_h2xe() ? "to_poco_h2xr_h" : "to_poco_s2xr_s";
fmain +=
" mediump vec4 nposition = position + tangent * xspeed * 1e-3;\n"
" position = "+fn+"(position);\n"
" position.z = 0.;\n" // zpos - uPLevel;\n"
" nposition = "+fn+"(nposition);\n"
" nposition.z = zspeed * 1e-3;\n";
}
else if(prod) {
string fn = in_h2xe() ? "to_poco_h2xr_e" : "to_poco_s2xr_e";
fmain +=
" mediump vec4 nposition = position + tangent * xspeed * 1e-3;\n"
" mediump mat4 tkt = " + getM("mid+1") + ";\n"
" position = "+fn+"(tkt * position);\n"
" position.y = zpos;\n"
" nposition = "+fn+"(tkt * nposition);\n"
" nposition.y = zpos + zspeed * 1e-3;\n";
}
else {
fmain +=
" mediump vec4 nposition = position + tangent * 1e-3;\n"
" mediump mat4 tkt = " + getM("mid+1") + ";\n";
if(hyperbolic) fmain +=
" position = to_poco_h3(tkt * position);\n"
" nposition = to_poco_h3(tkt * nposition);\n";
else if(sphere) fmain +=
" position = to_poco_s3(tkt * position);\n"
" nposition = to_poco_s3(tkt * nposition);\n";
else fmain +=
" position = tkt * position;\n"
" nposition = tkt * nposition;\n";
}
fmain +=
" mediump mat4 m = " + getM("mid") + ";\n"
" position = m * position;\n"
" nposition = m * nposition;\n";
int we_curvature = hyperbolic ? -1 : sphere ? 1 : 0;
intra::resetter ir;
intra::switch_to(gid2);
if(prod && we_curvature) {
string sgn = in_h2xe() ? "-" : "+";
string fn = in_h2xe() ? "from_poco_h2xr_h" : "from_poco_s2xr_s";
ld their_plevel = cgi.plevel / 2;
fmain +=
" zspeed = (nposition.z - position.z) * 1e3;\n"
" zpos = position.z + " + glhr::to_glsl(their_plevel) + ";\n"
" position = "+fn+"(position);\n"
" nposition = "+fn+"(nposition);\n"
" tangent = (nposition - position) * 1e3;\n"
" mediump float pnorm = tangent.z * position.z "+sgn+" tangent.x * position.x "+sgn+" tangent.y * position.y;\n"
" tangent -= position * pnorm;\n"
" xspeed = sqrt(tangent.x * tangent.x + tangent.y * tangent.y "+sgn+" tangent.z * tangent.z);\n"
" tangent /= xspeed;\n";
}
else if(prod) {
string sgn = in_h2xe() ? "-" : "+";
string fn = in_h2xe() ? "from_poco_h2xr_e" : "from_poco_s2xr_e";
fmain +=
" mediump mat4 itkt = " + getM("mid+2") + ";\n";
fmain +=
" zpos = position.y;\n"
" zspeed = (nposition.y - zpos) * 1e3;\n"
" position = itkt * "+fn+"(position);\n"
" nposition = itkt * "+fn+"(nposition);\n"
" tangent = (nposition - position) * 1e3;\n"
" mediump float pnorm = tangent.z * position.z "+sgn+" dot(position.xy, tangent.xy);\n"
" tangent -= position * pnorm;\n"
" xspeed = sqrt(dot(tangent.xy, tangent.xy) "+sgn+" tangent.z * tangent.z);\n"
" tangent /= xspeed;\n"
" mediump float l = xspeed*xspeed+zspeed*zspeed;\n"
" xspeed /= sqrt(l); zspeed /= sqrt(l);\n";
}
else {
string sgn = hyperbolic ? "-" : "+";
string he = hyperbolic ? "from_poco_h3" : "from_poco_s3";
fmain +=
" mediump mat4 itkt = " + getM("mid+2") + ";\n";
if(hyperbolic || sphere) fmain +=
" position = itkt * "+he+"(position);\n"
" nposition = itkt * "+he+"(nposition);\n"
" tangent = (nposition - position) * 1e3;\n"
" mediump float pnorm = position.w * position.w "+sgn+" dot(position.xyz, position.xyz);\n"
" position /= sqrt(pnorm);\n"
" pnorm = tangent.w * position.w "+sgn+" dot(position.xyz, tangent.xyz);\n"
" tangent -= position * pnorm;\n"
" mediump float xspeed = sqrt(dot(tangent.xyz, tangent.xyz) "+sgn+" tangent.w * tangent.w);\n"
" tangent /= xspeed;\n";
else fmain +=
" position = itkt * position;\n"
" nposition = itkt * nposition;\n"
" tangent = (nposition - position) * 1e3;\n"
" tangent /= dot(tangent.xyz, tangent.xyz);\n";
}
}
void raygen::emit_iterate(int gid1) {
using glhr::to_glsl;
if(intra::in && prod)
fmain += " const mediump float uPLevel = " + to_glsl(cgi.plevel/2) + ";\n";
fmain +=
" mediump float dist = 100.;\n";
fmain +=
" int which = -1;\n";
if(hyperbolic && intra::in) fmain += "iter +=8;\n";
if(in_e2xe() && !eyes) fmain += "tangent.w = position.w = 0.;\n";
if(IN_ODS) fmain +=
@ -1183,7 +1304,111 @@ void raygen::emit_iterate() {
" m[0][1] = -m[0][1]; m[1][0] = -m[1][0];\n" // inverse
" toOrig = toOrig * m;\n";
fmain += no_intra_portal;
if(!intra::in) fmain += no_intra_portal;
else {
if(hyperbolic) {
fsh +=
"mediump vec4 to_poco_h3(mediump vec4 pos) {\n"
" return pos / pos[3];\n"
" }\n\n";
fsh +=
"mediump vec4 from_poco_h3(mediump vec4 pos) {\n"
" float s = 1. - dot(pos.xyz, pos.xyz);\n"
" return pos / sqrt(s);\n"
" }\n\n";
}
if(sphere) {
fsh +=
"mediump vec4 to_poco_s3(mediump vec4 pos) {\n"
" return pos / pos[3];\n"
" }\n\n";
fsh +=
"mediump vec4 from_poco_s3(mediump vec4 pos) {\n"
" float s = 1. + dot(pos.xyz, pos.xyz);\n"
" return pos / sqrt(s);\n"
" }\n\n";
}
if(prod) {
if(in_h2xe()) {
fsh +=
"mediump vec4 from_poco_h2xr_h(mediump vec4 pos) {\n"
" float s = 1. - pos.x*pos.x - pos.y * pos.y;\n"
" pos.z = 1.;\n"
" return pos / sqrt(s);\n"
" }\n\n";
fsh +=
"mediump vec4 to_poco_h2xr_h(mediump vec4 pos) {\n"
" pos /= pos[2];\n"
" pos.w = 1.;\n"
" return pos;\n"
" }\n\n";
fsh +=
"mediump vec4 from_poco_h2xr_e(mediump vec4 pos) {\n"
" return vec4(sinh(pos[2]) * cosh(pos[0]), sinh(pos[0]), cosh(pos[0]) * cosh(pos[2]), 0);\n"
" }\n\n";
fsh +=
"mediump vec4 to_poco_h2xr_e(mediump vec4 pos) {\n"
" mediump float x = asinh(pos[1]);\n"
" return vec4(x, 0, asinh(pos[0] / cosh(x)), 1);\n"
" }\n\n";
}
else {
fsh +=
"mediump vec4 from_poco_s2xr_s(mediump vec4 pos) {\n"
" float s = 1. + pos.x*pos.x + pos.y * pos.y;\n"
" pos.z = 1.;\n"
" return pos / sqrt(s);\n"
" }\n\n";
fsh +=
"mediump vec4 to_poco_s2xr_s(mediump vec4 pos) {\n"
" pos /= pos[2];\n"
" pos.w = 1.;\n"
" return pos;\n"
" }\n\n";
fsh +=
"mediump vec4 from_poco_s2xr_e(mediump vec4 pos) {\n"
" return vec4(sin(pos[2]) * cos(pos[0]), sin(pos[0]), cos(pos[0]) * cos(pos[2]), 0);\n"
" }\n\n";
fsh +=
"mediump vec4 to_poco_s2xr_e(mediump vec4 pos) {\n"
" mediump float x = asin_clamp(pos[1]);\n"
" return vec4(x, 0, asin_clamp(pos[0] / cos(x)), 1);\n"
" }\n\n";
}
}
if(intra::in) {
int q = isize(intra::data);
for(int gid2=0; gid2<q; gid2++) {
if(gid2 == q-1)
fmain += " {\n";
else {
fmain += " if(nwalloffset < " + its(intra::data[gid2+1].wallindex) + ") {\n";
}
if(gid1 == gid2)
fmain += no_intra_portal;
else
emit_intra_portal(gid1, gid2);
if(gid2 == q-1)
fmain += " }\n";
else
fmain += " } else\n";
}
}
else
fmain += no_intra_portal;
}
if(many_cell_types) {
fmain +=
@ -1239,7 +1464,15 @@ void raygen::create() {
" gl_Position = aPosition; at = uProjection * aPosition; \n"
" }\n";
irays = isize(cgi.raywall);
if(intra::in) {
irays = 0;
intra::resetter ir;
for(int i=0; i<isize(intra::data); i++) {
intra::switch_to(i);
irays += isize(cgi.raywall);
}
}
else irays = isize(cgi.raywall);
string rays = its(irays);
fsh =
@ -1481,6 +1714,11 @@ void raygen::create() {
" mediump vec4 position = vw * vec4(0., 0., 0., 1.);\n"
" mediump vec4 tangent = vw * at0;\n";
}
if(intra::in && !prod) {
fmain += " mediump float zspeed = 1.;\n";
fmain += " mediump float xspeed = 1.;\n";
fmain += " mediump float zpos = 0.;\n";
}
if(eyes) {
fsh += "mediump uniform mat4 uEyeShift;\n";
@ -1522,7 +1760,25 @@ void raygen::create() {
" mediump vec2 cid = uStartid;\n"
" for(int iter=0; iter<" + its(max_iter_current()) + "; iter++) {\n";
emit_iterate();
if(intra::in) {
int gi = isize(intra::data);
for(int i=0; i<gi; i++) {
if(i == gi-1)
fmain += " {\n";
else {
fmain += " if(walloffset < " + its(intra::data[i+1].wallindex) + ") {\n";
}
intra::resetter ir;
intra::switch_to(i);
emit_iterate(i);
if(i == gi-1)
fmain += " }\n";
else
fmain += " } else\n";
}
}
else
emit_iterate(-1);
fmain +=
" }\n"
@ -1644,9 +1900,12 @@ struct raycast_map {
ms.clear();
ms.resize(sa.back().first, Id);
intra::resetter ir;
for(auto& p: sa) {
int id = p.first;
cell *c = p.second;
intra::may_switch_to(c);
if(!c) continue;
for(int j=0; j<c->type; j++)
ms[id+j] = protect_prod(currentmap->ray_iadj(c, j));
@ -1667,6 +1926,7 @@ struct raycast_map {
int id = p.first;
cell *c = p.second;
if(!c) continue;
intra::may_switch_to(c);
for(int j=0; j<c->type; j++)
ms[mirror_shift+id+j] = protect_prod(mirrorize(ms[id+j]));
if(WDIM == 2) for(int a: {0, 1}) {
@ -1680,12 +1940,14 @@ struct raycast_map {
}
}
if(prod) {
for(auto p: sa) {
int id =p.first;
if(id == 0) continue;
ms[id-2] = Id;
ms[id-1] = Id;
for(auto p: sa) {
cell *c = p.second;
if(!c) continue;
intra::may_switch_to(c);
int id =p.first;
if(prod) {
ms[id+c->type-2] = Id;
ms[id+c->type-1] = Id;
}
}
}
@ -1694,13 +1956,22 @@ struct raycast_map {
manual_celllister cl;
cl.add(cs);
bool optimize = !isWall3(cs);
intra::resetter ir;
// vector<int> legaldir = { -1 };
for(int i=0; i<isize(cl.lst); i++) {
cell *c = cl.lst[i];
intra::may_switch_to(c);
if(racing::on && i > 0 && c->wall == waBarrier) continue;
if(optimize && isWall3(c)) continue;
forCellIdCM(c2, d, c) {
// if(reflect_val == 0 && !((1<<d) & legaldir[i])) continue;
if(intra::in) {
cellwalker cw(c, d);
auto p = at_or_null(intra::connections, cw);
if(p) c2 = p->tcw.at;
}
if(rays_generate) setdist(c2, 7, c);
/* if(!cl.listed(c2))
legaldir.push_back(legaldir[i] &~ (1<<((d+3)%6)) ); */
@ -1722,6 +1993,7 @@ struct raycast_map {
}
void generate_connections(cell *c, int id) {
intra::may_switch_to(c);
auto& vmap = volumetric::vmap;
if(volumetric::on) {
celldrawer dd;
@ -1735,7 +2007,14 @@ struct raycast_map {
vcolor = (backcolor << 8);
volumetric[u] = glhr::acolor(vcolor);
}
forCellIdEx(c1, i, c) {
forCellIdEx(c1_real, i, c) {
cell *c1 = c1_real;
const intra::connection_data *p = nullptr;
if(intra::in) {
cellwalker cw(c, i);
p = at_or_null(intra::connections, cw);
if(p) c1 = p->tcw.at;
}
int u = (id/per_row*length) + (id%per_row * deg) + i;
if(!ids.count(c1)) {
wallcolor[u] = glhr::acolor(color_out_of_range | 0xFF);
@ -1775,23 +2054,36 @@ struct raycast_map {
}
}
int wo = currentmap->wall_offset(c);
int wo = intra::full_wall_offset(c);
if(wo >= our_raygen.irays) {
println(hlog, "wo=", wo, " irays = ", our_raygen.irays);
reset_raycaster();
return;
}
transmatrix T = currentmap->iadj(c, i) * inverse(ms[wo + i]);
if(in_e2xe() && i >= c->type-2)
T = Id;
T = protect_prod(T);
for(int k=0; k<=isize(ms); k++) {
if(k < isize(ms) && !eqmatrix(ms[k], T, 1e-5)) continue;
if(k == isize(ms)) ms.push_back(T);
if(p) {
int k = isize(ms);
auto bak = geometry;
ms.push_back(p->T);
geometry = bak;
ms.push_back(p->id1.T);
ms.push_back(p->id2.iT);
connections[u][2] = (k+.5) / 1024.;
break;
}
auto wo1 = currentmap->wall_offset(c1);
else {
transmatrix T = currentmap->iadj(c, i) * inverse(ms[wo + i]);
if(in_e2xe() && i >= c->type-2)
T = Id;
T = protect_prod(T);
for(int k=0; k<=isize(ms); k++) {
if(k < isize(ms) && !eqmatrix(ms[k], T, 1e-5)) continue;
if(k == isize(ms)) ms.push_back(T);
connections[u][2] = (k+.5) / 1024.;
break;
}
}
intra::resetter ir;
intra::may_switch_to(c1);
int wo1 = intra::full_wall_offset(c1);
if(wo1 >= max_wall_offset)
println(hlog, "error: wall_offset ", wo1, " exceeds ", max_wall_offset);
if(c1->type >= max_celltype)
@ -1815,6 +2107,7 @@ struct raycast_map {
void generate_connections() {
int id = 0;
intra::resetter ir;
for(cell* c: lst) if(!reset_rmap)
generate_connections(c, id++);
}
@ -2012,14 +2305,22 @@ EX void cast() {
}
if(o->uWallOffset != -1) {
glUniform1i(o->uWallOffset, currentmap->wall_offset(cs));
glUniform1i(o->uWallOffset, intra::full_wall_offset(cs));
glUniform1i(o->uSides, cs->type + (WDIM == 2 ? 2 : 0));
}
vector<glvertex> wallx, wally;
vector<GLint> wallstart;
load_walls(wallx, wally, wallstart);
if(intra::in) {
intra::resetter ir;
for(int i=0; i<isize(intra::data); i++) {
intra::switch_to(i);
load_walls(wallx, wally, wallstart);
}
}
else
load_walls(wallx, wally, wallstart);
if(wall_via_texture) {
int wlength = next_p2(isize(wallx));

View File

@ -801,21 +801,23 @@ EX void take(string fname, const function<void()>& what IS(default_screenshot_co
#if CAP_WRL
wrl::take(fname);
#endif
return;
break;
case screenshot_format::svg:
#if CAP_SVG
svg::render(fname, what);
#endif
return;
break;
case screenshot_format::png:
case screenshot_format::rawfile:
#if CAP_PNG
render_png(fname, what);
#endif
return;
break;
}
v.backup.plevel_factor = vid.plevel_factor;
}
#if CAP_COMMANDLINE

View File

@ -751,6 +751,7 @@ EX void add_fixed_functions(string& shader) {
add_if(shader, "tanh", "mediump float tanh(mediump float x) { return sinh(x) / cosh(x); }\n");
add_if(shader, "sinh", "mediump float sinh(mediump float x) { return (exp(x) - exp(-x)) / 2.0; }\n");
add_if(shader, "asin_clamp", "mediump float asin_clamp(mediump float x) { return x > 1. ? PI/2. : x < -1. ? -PI/2. : asin(x); }\n");
add_if(shader, "cosh", "mediump float cosh(mediump float x) { return (exp(x) + exp(-x)) / 2.0; }\n");
add_if(shader, "asinh", "mediump float asinh(mediump float x) { return log(sqrt(x*x + 1.0) + x); }\n");
add_if(shader, "acosh", "mediump float acosh(mediump float x) { return log(sqrt(x*x - 1.0) + x); }\n");