1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-27 14:37:16 +00:00

intra:: walking mode

This commit is contained in:
Zeno Rogue 2022-02-26 10:40:39 +01:00
parent cfaa52cf42
commit 94d660cc43
3 changed files with 194 additions and 11 deletions

View File

@ -2013,6 +2013,8 @@ EX void optimizeview() {
fixmatrix(View);
callhooks(hooks_postoptimize);
walking::handle();
if(is_boundary(centerover))
centerover = c, View = oView;
else

197
intra.cpp
View File

@ -541,11 +541,9 @@ EX const connection_data* through_portal() {
EX void check_portal_movement() {
auto p = through_portal();
ld c = camera_speed;
if(p) {
ld eps = 1e-5;
c /= p->id1.scale;
anims::cycle_length /= p->id1.scale;
ld ss = pow(eps, -2);
array<hyperpoint, 4> ds; /* camera, forward, upward */
@ -605,9 +603,16 @@ EX void check_portal_movement() {
println(hlog, "goal: at = ", xds[0], " det = ", dsdet(xds), " bt = ", bt::minkowski_to_bt(xds[0]));
}
c *= p->id2.scale;
anims::cycle_length *= p->id2.scale;
camera_speed = c;
ld scale = p->id2.scale / p->id1.scale;
camera_speed *= scale;
anims::cycle_length *= scale;
#if CAP_VR
absolute_units_in_meters *= scale;
#endif
if(walking::eye_level != -1) walking::eye_level *= scale;
walking::floor_dir = -1;
}
}
@ -691,6 +696,8 @@ void show_portals() {
}
}
walking::add_options();
dialog::display();
}
@ -790,8 +797,182 @@ auto hooks1 =
arg::shift(); int i = arg::argi(); be_ratio_edge(i);
})
+ arg::add3("-debug-portal", [] { arg::shift(); debug_portal = arg::argi(); });
#endif
EX }
EX namespace walking {
EX bool on;
EX bool auto_eyelevel;
EX int floor_dir = -1;
EX cell *on_floor_of = nullptr;
EX ld eye_level = 0.2174492;
EX ld eye_angle = 0;
EX ld eye_angle_scale = 1;
map<cell*, int> recorded_floor_dir;
int ticks_end, ticks_last;
EX set<color_t> colors_of_floors;
EX bool isFloor(cell *c) {
if(!isWall(c)) return false;
return colors_of_floors.count(c->landparam);
}
EX void handle() {
if(!on) return;
if(floor_dir == -1 || on_floor_of != centerover) {
vector<int> choices;
for(int i=0; i<centerover->type; i++)
if(isFloor(centerover->cmove(i)))
choices.push_back(i);
if(sol && isize(choices) == 2) choices.pop_back();
if(isize(choices) == 1) {
on_floor_of = centerover;
floor_dir = choices[0];
println(hlog, "set floor_dir to ", floor_dir);
}
else {
println(hlog, "there are ", isize(choices), " choices for floor_dir");
if(!on_floor_of) return;
}
}
struct face {
hyperpoint h0, hx, hy;
};
transmatrix ToOld = currentmap->relative_matrix(on_floor_of, centerover, C0);
auto& csh = currentmap->get_cellshape(on_floor_of);
face f;
f.h0 = ToOld * csh.faces_local[floor_dir][0];
f.hx = ToOld * csh.faces_local[floor_dir][1];
f.hy = ToOld * csh.faces_local[floor_dir][2];
auto find_nearest = [&] (const face& fac, hyperpoint at) {
if(sol) { at[2] = fac.h0[2]; return at; }
else if(sphere && false) {
hyperpoint h =
project_on_triangle(csh.faces_local[floor_dir][0], csh.faces_local[floor_dir][1], csh.faces_local[floor_dir][2]);
transmatrix T = rspintox(h);
T = T * MirrorX;
transmatrix M = ToOld * T * xpush(-2*hdist0(h)) * spintox(h);
return mid(at, M * at);
}
else if(prod && bt::in()) {
auto dec = product_decompose(at);
hyperpoint dep = PIU( deparabolic13(dec.second) );
hyperpoint h = product_decompose(fac.h0).second;
h = PIU( deparabolic13(h) );
dep[0] = h[0];
return zshift(PIU(parabolic13(dep)), dec.first);
}
else {
transmatrix M = ray::mirrorize(currentmap->ray_iadj(on_floor_of, floor_dir));
M = ToOld * M * inverse(ToOld);
return mid(at, M * at);
}
};
hyperpoint at = tC0(inverse(View));
if(invalid_point(at)) {
println(hlog, "at is invalid!");
on = false;
return;
}
auto wallpt = find_nearest(f, at);
if(on_floor_of == centerover)
recorded_floor_dir[centerover] = floor_dir;
ld view_eps = 1e-5;
if(eye_angle) rotate_view(cspin(1, 2, -eye_angle * degree));
hyperpoint front = inverse(get_shift_view_of(ctangent(2, -view_eps), View)) * C0;
hyperpoint up = inverse(get_shift_view_of(ctangent(1, +view_eps), View)) * C0;
auto fwallpt = find_nearest(f, front);
transmatrix T = nonisotropic ? nisot::translate(wallpt, -1) : gpushxto0(wallpt);
hyperpoint dx = inverse_exp(shiftless(T * at));
transmatrix Tf = nonisotropic ? nisot::translate(fwallpt, -1) : gpushxto0(fwallpt);
hyperpoint dxf = inverse_exp(shiftless(Tf * front));
if(eye_level == -1) eye_level = hypot_d(3, dx);
auto smooth = [&] (hyperpoint h1, hyperpoint h2) {
if(ticks < ticks_end) {
ld last_t = ilerp(ticks_end-1000, ticks_end, ticks_last);
ld curr_t = ilerp(ticks_end-1000, ticks_end, ticks);
last_t = last_t * last_t * (3-2*last_t);
curr_t = curr_t * curr_t * (3-2*curr_t);
ld t = ilerp(last_t, 1, curr_t);
return lerp(h1, h2, t);
}
return h2;
};
auto oView = View;
set_view(
smooth(at, inverse(T) * direct_exp(dx / hypot_d(3, dx) * eye_level)),
smooth(front, inverse(Tf) * direct_exp(dxf / hypot_d(3, dxf) * eye_level)),
smooth(up, inverse(T) * direct_exp(dx / hypot_d(3, dx) * (eye_level + view_eps)))
);
if(eye_angle) rotate_view(cspin(1, 2, eye_angle * degree));
playermoved = false;
auto nat = tC0(inverse(View));
if(invalid_point(nat)) {
println(hlog, "at is invalid after fixing!");
View = oView;
return;
}
ticks_last = ticks;
}
EX void add_options() {
dialog::addBoolItem("walking mode", on, 'w');
dialog::add_action([] {
on = !on;
if(on && auto_eyelevel) eye_level = -1;
floor_dir = -1;
on_floor_of = nullptr;
ticks_last = ticks;
ticks_end = ticks + 1000;
});
add_edit(eye_level);
add_edit(eye_angle);
}
auto a = addHook(hooks_configfile, 100, [] {
param_b(auto_eyelevel, "auto_eyelevel")
-> editable("keep eye level when walking enabled", 'L');
param_f(eye_level, "eye_level")
-> editable(0, 5, .1, "walking eye level",
"Distance from the floor to the eye in the walking mode, in absolute units. In VR this is adjusted automatically.",
'e')
->set_extra([] { add_edit(auto_eyelevel); });
param_f(eye_angle, "eye_angle")
-> editable(-90, 90, 15, "walking eye angle",
"0 = looking forward, 90 = looking upward. In VR this is adjusted automatically.",
'k')
->set_extra([] { add_edit(eye_angle_scale); });
param_f(eye_angle_scale, "eye_angle_scale")
-> editable(-2, 0, 2, "eye angle scale",
"1 = the angle can be changed with keyboard or mouse movements, 0 = the angle is fixed",
'k');
})
+ addHook(hooks_clearmemory, 40, [] { recorded_floor_dir.clear(); on_floor_of = nullptr; floor_dir = -1; });
EX }
}

View File

@ -2066,7 +2066,7 @@ void uniform2(GLint id, array<float, 2> fl) {
color_t color_out_of_range = 0x0F0800FF;
transmatrix get_ms(cell *c, int a, bool mirror) {
EX transmatrix get_ms(cell *c, int a, bool mirror) {
int z = a ? 1 : -1;
if(c->type == 3) {
@ -2096,7 +2096,7 @@ transmatrix get_ms(cell *c, int a, bool mirror) {
int nesting;
transmatrix mirrorize(transmatrix T) {
EX transmatrix mirrorize(transmatrix T) {
T = inverse(T);
hyperpoint h = tC0(T);
ld d = hdist0(h);