mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-12-14 18:18:05 +00:00
intra:: walking mode
This commit is contained in:
@@ -2013,6 +2013,8 @@ EX void optimizeview() {
|
|||||||
fixmatrix(View);
|
fixmatrix(View);
|
||||||
callhooks(hooks_postoptimize);
|
callhooks(hooks_postoptimize);
|
||||||
|
|
||||||
|
walking::handle();
|
||||||
|
|
||||||
if(is_boundary(centerover))
|
if(is_boundary(centerover))
|
||||||
centerover = c, View = oView;
|
centerover = c, View = oView;
|
||||||
else
|
else
|
||||||
|
|||||||
197
intra.cpp
197
intra.cpp
@@ -541,11 +541,9 @@ EX const connection_data* through_portal() {
|
|||||||
|
|
||||||
EX void check_portal_movement() {
|
EX void check_portal_movement() {
|
||||||
auto p = through_portal();
|
auto p = through_portal();
|
||||||
ld c = camera_speed;
|
|
||||||
if(p) {
|
if(p) {
|
||||||
ld eps = 1e-5;
|
ld eps = 1e-5;
|
||||||
c /= p->id1.scale;
|
|
||||||
anims::cycle_length /= p->id1.scale;
|
|
||||||
ld ss = pow(eps, -2);
|
ld ss = pow(eps, -2);
|
||||||
|
|
||||||
array<hyperpoint, 4> ds; /* camera, forward, upward */
|
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]));
|
println(hlog, "goal: at = ", xds[0], " det = ", dsdet(xds), " bt = ", bt::minkowski_to_bt(xds[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
c *= p->id2.scale;
|
ld scale = p->id2.scale / p->id1.scale;
|
||||||
anims::cycle_length *= p->id2.scale;
|
|
||||||
camera_speed = c;
|
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();
|
dialog::display();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -790,8 +797,182 @@ auto hooks1 =
|
|||||||
arg::shift(); int i = arg::argi(); be_ratio_edge(i);
|
arg::shift(); int i = arg::argi(); be_ratio_edge(i);
|
||||||
})
|
})
|
||||||
+ arg::add3("-debug-portal", [] { arg::shift(); debug_portal = arg::argi(); });
|
+ arg::add3("-debug-portal", [] { arg::shift(); debug_portal = arg::argi(); });
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
EX }
|
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 }
|
||||||
}
|
}
|
||||||
@@ -2066,7 +2066,7 @@ void uniform2(GLint id, array<float, 2> fl) {
|
|||||||
|
|
||||||
color_t color_out_of_range = 0x0F0800FF;
|
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;
|
int z = a ? 1 : -1;
|
||||||
|
|
||||||
if(c->type == 3) {
|
if(c->type == 3) {
|
||||||
@@ -2096,7 +2096,7 @@ transmatrix get_ms(cell *c, int a, bool mirror) {
|
|||||||
|
|
||||||
int nesting;
|
int nesting;
|
||||||
|
|
||||||
transmatrix mirrorize(transmatrix T) {
|
EX transmatrix mirrorize(transmatrix T) {
|
||||||
T = inverse(T);
|
T = inverse(T);
|
||||||
hyperpoint h = tC0(T);
|
hyperpoint h = tC0(T);
|
||||||
ld d = hdist0(h);
|
ld d = hdist0(h);
|
||||||
|
|||||||
Reference in New Issue
Block a user