mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-24 01:00:25 +00:00
vr:: correctly rendered 2D sphere
This commit is contained in:
parent
6217ec4702
commit
2e0ddd5a48
@ -995,7 +995,7 @@ enum eModel : int {
|
||||
/** list of available models (i.e., projections) */
|
||||
EX vector<modelinfo> mdinf = {
|
||||
{"disk/Gans", "general perspective", "general perspective", mf::azimuthal | mf::conformal, DEFAULTS},
|
||||
{"half-plane", "inversion", "half-plane", mf::conformal, DEFAULTS},
|
||||
{"half-plane", "inversion", "stereographic projection [VR]", mf::conformal, DEFAULTS},
|
||||
{"band", "band", "Mercator", mf::band | mf::conformal, DEFAULTS},
|
||||
{X3("polygonal"), mf::conformal, DEFAULTS},
|
||||
{X3("formula"), 0, DEFAULTS},
|
||||
|
36
drawing.cpp
36
drawing.cpp
@ -161,6 +161,9 @@ EX unsigned char& part(color_t& col, int i) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool in_vr_sphere;
|
||||
hyperpoint vr_sphere_center;
|
||||
|
||||
bool fatborder;
|
||||
|
||||
EX color_t poly_outline;
|
||||
@ -277,6 +280,7 @@ int axial_sign() {
|
||||
|
||||
bool is_behind(const hyperpoint& H) {
|
||||
if(pmodel == mdAxial && sphere) return axial_sign() * H[2] <= BEHIND_LIMIT;
|
||||
if(in_vr_sphere) return false;
|
||||
return pmodel == mdDisk && (hyperbolic ? H[2] >= 0 : true) && (nonisotropic ? false : pconf.alpha + H[2] <= BEHIND_LIMIT);
|
||||
}
|
||||
|
||||
@ -304,6 +308,7 @@ EX bool two_sided_model() {
|
||||
constexpr bool in_vr = false;
|
||||
#endif
|
||||
if(GDIM == 3) return false;
|
||||
if(in_vr_sphere) return true;
|
||||
if(pmodel == mdHyperboloid) return !euclid && !in_vr;
|
||||
// if(pmodel == mdHemisphere) return true;
|
||||
if(pmodel == mdDisk) return sphere;
|
||||
@ -316,6 +321,16 @@ EX bool two_sided_model() {
|
||||
}
|
||||
|
||||
EX int get_side(const hyperpoint& H) {
|
||||
if(in_vr_sphere) {
|
||||
hyperpoint Hscr;
|
||||
applymodel(shiftless(H), Hscr);
|
||||
Hscr[3] = 1;
|
||||
E4;
|
||||
hyperpoint actual = vrhr::hmd_mv * Hscr;
|
||||
ld val = 0;
|
||||
for(int i=0; i<3; i++) val += (vr_sphere_center[i] - actual[i]) * actual[i];
|
||||
return val > 0 ? -1 : 1;
|
||||
}
|
||||
if(pmodel == mdDisk && sphere) {
|
||||
double curnorm = H[0]*H[0]+H[1]*H[1]+H[2]*H[2];
|
||||
double horizon = curnorm / pconf.alpha;
|
||||
@ -951,7 +966,10 @@ void compute_side_by_centerin(dqi_poly *p, bool& nofill) {
|
||||
else
|
||||
nofill = true;
|
||||
}
|
||||
applymodel(h1, hscr); hscr[0] *= current_display->radius; hscr[1] *= current_display->radius * pconf.stretch;
|
||||
applymodel(h1, hscr);
|
||||
if(vrhr::state != 2) {
|
||||
hscr[0] *= current_display->radius; hscr[1] *= current_display->radius * pconf.stretch;
|
||||
}
|
||||
for(int i=0; i<isize(glcoords)-1; i++) {
|
||||
double x1 = glcoords[i][0] - hscr[0];
|
||||
double y1 = glcoords[i][1] - hscr[1];
|
||||
@ -1836,6 +1854,7 @@ void dqi_poly::draw() {
|
||||
|
||||
bool can_have_inverse = false;
|
||||
if(sphere && pmodel == mdDisk && (spherespecial > 0 || equi)) can_have_inverse = true;
|
||||
if(vrhr::state == 2) can_have_inverse = false;
|
||||
if(sphere && among(pmodel, mdEquidistant, mdEquiarea)) can_have_inverse = true;
|
||||
if(pmodel == mdJoukowsky) can_have_inverse = true;
|
||||
if(pmodel == mdJoukowskyInverted && pconf.skiprope) can_have_inverse = true;
|
||||
@ -2234,6 +2253,21 @@ EX void reverse_transparent_walls() {
|
||||
|
||||
EX void draw_main() {
|
||||
DEBBI(DF_GRAPH, ("draw_main"));
|
||||
|
||||
in_vr_sphere = false;
|
||||
#if CAP_VR
|
||||
in_vr_sphere = vrhr::state == 2 && among(pmodel, mdDisk, mdBall, mdHyperboloid, mdHalfplane, mdHemisphere);
|
||||
if(in_vr_sphere) {
|
||||
hyperpoint a, b;
|
||||
applymodel(shiftless(point3(0, 0, 1)), a);
|
||||
applymodel(shiftless(point3(0, 0, -1)), b);
|
||||
vr_sphere_center = (a + b) / 2;
|
||||
vr_sphere_center[3] = 1;
|
||||
E4;
|
||||
vr_sphere_center = vrhr::hmd_mv * vr_sphere_center;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(sphere && GDIM == 3 && pmodel == mdPerspective && !stretch::in() && !ray::in_use) {
|
||||
|
||||
if(ray::in_use && !ray::comparison_mode) {
|
||||
|
72
hypgraph.cpp
72
hypgraph.cpp
@ -376,6 +376,49 @@ EX void applymodel(shiftpoint H_orig, hyperpoint& ret) {
|
||||
apply_other_model(H_orig, ret, pmodel);
|
||||
}
|
||||
|
||||
EX void vr_sphere(hyperpoint& ret, hyperpoint& H, eModel md) {
|
||||
ret = H;
|
||||
int flip = 1;
|
||||
if(md == mdHalfplane) flip = -flip;
|
||||
if(pconf.alpha < 1) flip = -flip;
|
||||
ret *= pow(sqhypot_d(3, H), (flip * pconf.depth_scaling-1) / 2);
|
||||
ret[2] += pconf.alpha;
|
||||
if(md == mdHalfplane) {
|
||||
ld d = sqhypot_d(3, ret);
|
||||
ret /= abs(d);
|
||||
}
|
||||
models::apply_vr(ret[2], ret[1]);
|
||||
}
|
||||
|
||||
void vr_disk(hyperpoint& ret, hyperpoint& H) {
|
||||
if(euclid) {
|
||||
ret = H;
|
||||
ret[2] = vid.depth * (1 - (ret[2] - 1) * pconf.depth_scaling) + pconf.alpha + vid.camera;
|
||||
}
|
||||
else if(sphere) {
|
||||
vr_sphere(ret, H, mdDisk);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ld zlev = find_zlev(H);
|
||||
ld zl = vid.depth-geom3::factor_to_lev(zlev) * pconf.depth_scaling;
|
||||
|
||||
ld d = hdist0(H);
|
||||
ld dd = hypot_d(2, H);
|
||||
|
||||
hyperpoint H1 = ypush(vid.camera) * xpush(d) * ypush0(zl);
|
||||
ld tzh = pconf.alpha + H1[2];
|
||||
ld ax = H1[0] / tzh;
|
||||
ld ay = H1[1] / tzh;
|
||||
|
||||
ret[0] = ax * H[0] / dd;
|
||||
ret[1] = ax * H[1] / dd;
|
||||
ret[2] = ay;
|
||||
}
|
||||
|
||||
models::apply_vr(ret[2], ret[1]);
|
||||
}
|
||||
|
||||
EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
||||
|
||||
hyperpoint H = H_orig.h;
|
||||
@ -409,6 +452,10 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
||||
return;
|
||||
|
||||
case mdBall: {
|
||||
if(vrhr::state == 2) {
|
||||
vr_disk(ret, H);
|
||||
return;
|
||||
}
|
||||
ld zlev = find_zlev(H);
|
||||
|
||||
ld zl = vid.depth-geom3::factor_to_lev(zlev) * pconf.depth_scaling;
|
||||
@ -435,22 +482,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
||||
break;
|
||||
}
|
||||
if(vrhr::state == 2) {
|
||||
ld zlev = find_zlev(H);
|
||||
ld zl = vid.depth-geom3::factor_to_lev(zlev) * pconf.depth_scaling;
|
||||
|
||||
ld d = hdist0(H);
|
||||
ld dd = hypot_d(2, H);
|
||||
|
||||
hyperpoint H1 = ypush(vid.camera) * xpush(d) * ypush0(zl);
|
||||
ld tzh = pconf.alpha + H1[2];
|
||||
ld ax = H1[0] / tzh;
|
||||
ld ay = H1[1] / tzh;
|
||||
|
||||
ret[0] = ax * H[0] / dd;
|
||||
ret[1] = ax * H[1] / dd;
|
||||
ret[2] = ay;
|
||||
|
||||
models::apply_vr(ret[2], ret[1]);
|
||||
vr_disk(ret, H);
|
||||
return;
|
||||
}
|
||||
ld tz = get_tz(H);
|
||||
@ -486,6 +518,10 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
||||
}
|
||||
|
||||
case mdHalfplane: {
|
||||
if(sphere && vrhr::state == 2) {
|
||||
vr_sphere(ret, H, md);
|
||||
return;
|
||||
}
|
||||
// Poincare to half-plane
|
||||
|
||||
ld zlev = find_zlev(H);
|
||||
@ -661,6 +697,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
||||
}
|
||||
|
||||
case gcSphere: {
|
||||
if(vrhr::state == 2) { vr_sphere(ret, H, md); return; }
|
||||
ret = H;
|
||||
if(pconf.depth_scaling != 1) {
|
||||
ld v = intval(H, Hypc);
|
||||
@ -699,12 +736,13 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
||||
|
||||
#if CAP_VR
|
||||
if(vrhr::state == 2) {
|
||||
if(sphere) { vr_sphere(ret, H, md); return; }
|
||||
ret[0] = H[0] * pconf.hyperboloid_scaling;
|
||||
ret[1] = H[1] * pconf.hyperboloid_scaling;
|
||||
ret[2] = (pconf.alpha + H[2]);
|
||||
if(pconf.depth_scaling != 1) {
|
||||
ld v = intval(H, Hypc);
|
||||
ret *= pow(v, (pconf.depth_scaling*(sphere?-1:1)-1) / 2);
|
||||
ret *= pow(v, (pconf.depth_scaling-1) / 2);
|
||||
}
|
||||
models::apply_vr(ret[2], ret[1]);
|
||||
break;
|
||||
|
5
vr.cpp
5
vr.cpp
@ -143,8 +143,10 @@ EX string error_msg;
|
||||
/** 0 = not loaded, 1 = loaded but not currently rendering, 2 = currently rendering the VR screen, 3 = currently rendering the computer screen */
|
||||
EX int state = 0;
|
||||
|
||||
#if HDR
|
||||
// use E4 when working with real-world matrices to ensure that inverses, multiplications, etc. are computed correctly
|
||||
#define E4 dynamicval<eGeometry> g(geometry, gCubeTiling)
|
||||
#endif
|
||||
|
||||
#define IN_E4(x) [&]{ E4; return x; }()
|
||||
|
||||
@ -198,7 +200,7 @@ EX bool first = true;
|
||||
EX transmatrix hmd_at = Id;
|
||||
EX transmatrix hmd_ref_at = Id;
|
||||
|
||||
EX transmatrix hmd_mvp, hmd_pre;
|
||||
EX transmatrix hmd_mvp, hmd_pre, hmd_mv;
|
||||
|
||||
EX transmatrix sm;
|
||||
|
||||
@ -794,6 +796,7 @@ EX void render() {
|
||||
if(eyes == eEyes::equidistant) {
|
||||
hmd_mvp = inverse(vrdata.eyepos[i]) * hmd_mvp;
|
||||
}
|
||||
hmd_mv = hmd_mvp;
|
||||
hmd_mvp = vrdata.proj[i] * hmd_mvp;
|
||||
}
|
||||
eyeproj = vrdata.iproj[i];
|
||||
|
Loading…
Reference in New Issue
Block a user