From c527d4e61376d255fb02aeee73a6c55cb61d08f7 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Mon, 21 Oct 2019 22:42:27 +0200 Subject: [PATCH] ODS in hyperbolic --- config.cpp | 11 ++++- drawing.cpp | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++ graph.cpp | 2 +- rug.cpp | 48 +------------------ 4 files changed, 148 insertions(+), 49 deletions(-) diff --git a/config.cpp b/config.cpp index 2c86b3dc..8517b83b 100644 --- a/config.cpp +++ b/config.cpp @@ -1390,6 +1390,11 @@ EX void add_edit_fov(char key IS('f')) { }); } +bool supported_ods() { + if(!CAP_ODS) return false; + return rug::rugged || (hyperbolic && GDIM == 3); + } + EX void showStereo() { cmode = sm::SIDE | sm::MAYDARK; gamescreen(0); @@ -1437,8 +1442,10 @@ EX void showStereo() { "Currently, red-cyan anaglyph glasses and mobile VR googles are supported." ) + "\n\n"; - if(uni == 'm') - { vid.stereo_mode = eStereo((1 + vid.stereo_mode) % (CAP_ODS ? 4 : 3)); return; } + if(uni == 'm') { + vid.stereo_mode = eStereo((1 + vid.stereo_mode) % 4); + if(vid.stereo_mode == sODS && !supported_ods()) vid.stereo_mode = sOFF; + } else if(uni == 'e') dialog::editNumber(vid.ipd, -10, 10, 0.01, 0, XLAT("pupillary distance"), diff --git a/drawing.cpp b/drawing.cpp index 8c15eb34..39988404 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -1176,8 +1176,144 @@ void draw_s2xe0(dqi_poly *p) { } EX } +EX namespace ods { +#if CAP_ODS + + EX bool project(hyperpoint h, hyperpoint& h1, hyperpoint& h2, bool eye) { + ld tanalpha = tan_auto(vid.ipd/2); + if(eye) tanalpha = -tanalpha; + if(!sphere) tanalpha = -tanalpha; + + ld& x = h[0]; + ld z = -h[1]; + ld y = -h[2]; + ld& t = h[3]; + + ld y02 = (x*x + y*y - tanalpha*tanalpha*t*t); + if(y02 < 0) return false; + ld y0 = sqrt(y02); + ld theta = atan(z / y0); + + for(int i=0; i<2; i++) { + hyperpoint& h = (i ? h1 : h2); + if(i == 1) theta = -theta, y0 = -y0; + + ld x0 = t * tanalpha; + + ld phi = atan2(y, x) - atan2(y0, x0) + M_PI; + + // ld delta = euclid ? hypot(y0,z) : atan2_auto(z / sin(theta), t / cos_auto(vid.ipd/2)); + ld p = z / sin(theta) / t * cos_auto(vid.ipd / 2); + ld delta = (p > 1) ? 13 : (p < -1) ? -13 : atanh(p); + + if(euclid || hyperbolic) phi -= M_PI; + if(hyperbolic) delta = -delta; + + h[0] = phi; + h[1] = theta; + h[2] = delta; + if(euclid || hyperbolic) h[1] = -theta; + } + + return true; + } + + void draw_ods(dqi_poly *p) { + auto& stinf = s2xe::stinf; + + if(!p->cnt) return; + if(!(p->flags & POLY_TRIANGLES)) return; + + dqi_poly npoly = *p; + npoly.offset = 0; + npoly.tab = &glcoords; + npoly.V = Id; + npoly.tinf = p->tinf ? &stinf : NULL; + if(npoly.tinf) { + npoly.offset_texture = 0; + stinf.texture_id = p->tinf->texture_id; + stinf.tvertices.clear(); + } + npoly.V = Id; + glcoords.clear(); + + array h; + + if(0) for(int i=0; icnt; i+=3) { + for(int j=0; j<3; j++) + h[j] = p->V * glhr::gltopoint((*p->tab)[p->offset+i+j]); + + for(int j=0; j<3; j++) { + glcoords.push_back(glhr::makevertex(h[j][0], h[j][1], h[j][2])); + if(npoly.tinf) stinf.tvertices.push_back(p->tinf->tvertices[i+j]); + } + } + + if(1) for(int i=0; icnt; i+=3) { + + for(int j=0; j<3; j++) { + hyperpoint o = p->V * glhr::gltopoint((*p->tab)[p->offset+i+j]); + if(!project(o, h[j], h[j+3], global_projection == -1)) + goto next_i; + } + + for(int j=0; j<6; j++) { + // let Delta be from 0 to 2PI + if(h[j][2]<0) h[j][2] += 2 * M_PI; + // Theta is from -PI/2 to PI/2. Let it be from 0 to PI + h[j][1] += global_projection * M_PI/2; + h[j][3] = 1; + } + + /* natsph here */ + + if(h[0][2] < 0) swap(h[0], h[3]); + if(h[1][2] < 0) swap(h[1], h[4]); + if(h[2][2] < 0) swap(h[2], h[5]); + + cyclefix(h[0][0], 0); + cyclefix(h[1][0], h[0][0]); + cyclefix(h[2][0], h[0][0]); + cyclefix(h[3][0], 0); + cyclefix(h[4][0], h[3][0]); + cyclefix(h[5][0], h[3][0]); + + if(abs(h[1][1] - h[0][1]) > M_PI/2) goto next_i; + if(abs(h[2][1] - h[0][1]) > M_PI/2) goto next_i; + + if(h[0][0] < -M_PI || h[0][0] > M_PI) println(hlog, h[0][0]); + + if(1) { + int fst = 0, lst = 0; + if(h[1][0] < -M_PI || h[2][0] < -M_PI) lst++; + if(h[1][0] > +M_PI || h[2][0] > +M_PI) fst--; + for(int x=fst; x<=lst; x++) for(int j=0; j<3; j++) { + glcoords.push_back(glhr::makevertex(h[j][0] + 2 * M_PI * x, h[j][1], h[j][2])); + if(npoly.tinf) stinf.tvertices.push_back(p->tinf->tvertices[p->offset_texture+i+j]); + } + } + + /* natsph here */ + + next_i: ; + } + + npoly.cnt = isize(glcoords); + // npoly.color = 0xFFFFFFFF; + npoly.gldraw(); + } +#endif + EX } + void dqi_poly::draw() { if(flags & POLY_DEBUG) debug_this(); + + #if CAP_ODS + if(vid.stereo_mode == sODS) { + ods::draw_ods(this); + return; + } + #endif if(in_s2xe() && vid.usingGL && pmodel == mdPerspective && (current_display->set_all(global_projection), (get_shader_flags() & SF_DIRECT))) { s2xe::draw_s2xe(this); diff --git a/graph.cpp b/graph.cpp index bc9bc0ce..434f0832 100644 --- a/graph.cpp +++ b/graph.cpp @@ -4568,7 +4568,7 @@ EX int noclipped; void make_clipping_planes() { #if MAXMDIM >= 4 clipping_planes.clear(); - if(PIU(sphere) || experimental) return; + if(PIU(sphere) || experimental || vid.stereo_mode == sODS) return; auto add_clipping_plane = [] (ld x1, ld y1, ld x2, ld y2) { ld z1 = 1, z2 = 1; hyperpoint sx = point3(y1 * z2 - y2 * z1, z1 * x2 - z2 * x1, x1 * y2 - x2 * y1); diff --git a/rug.cpp b/rug.cpp index 76e6d2e4..a53360dd 100644 --- a/rug.cpp +++ b/rug.cpp @@ -1168,61 +1168,17 @@ extern int besti; #if CAP_ODS /* these functions are for the ODS projection, used in VR videos */ -void cyclefix(ld& a, ld b) { - if(a > b + M_PI) a -= 2 * M_PI; - if(a < b - M_PI) a += 2 * M_PI; - } - -ld raddif(ld a, ld b) { - ld d = a-b; - if(d < 0) d = -d; - if(d > 2*M_PI) d -= 2*M_PI; - if(d > M_PI) d = 2 * M_PI-d; - return d; - } - bool project_ods(hyperpoint azeq, hyperpoint& h1, hyperpoint& h2, bool eye) { USING_NATIVE_GEOMETRY; - ld tanalpha = tan_auto(vid.ipd/2); - if(eye) tanalpha = -tanalpha; - if(!sphere) tanalpha = -tanalpha; ld d = hypot_d(3, azeq); ld sindbd = sin_auto(d)/d, cosd = cos_auto(d); - ld x = azeq[0] * sindbd; - ld y = azeq[2] * sindbd; - ld z = azeq[1] * sindbd; - ld t = cosd; + return ods::project(hyperpoint(azeq[0] * sindbd, azeq[1] * sindbd, azeq[2] * sindbd, cosd), h1, h2, eye); // printf("%10.5lf %10.5lf %10.5lf ", azeq[0], azeq[1], azeq[2]); // printf(" => %10.5lf %10.5lf %10.5lf %10.5lf", x, y, z, t); - ld y02 = (x*x + y*y - tanalpha*tanalpha*t*t); - if(y02 < 0) return false; - ld y0 = sqrt(y02); - ld theta = atan(z / y0); - - for(int i=0; i<2; i++) { - hyperpoint& h = (i ? h1 : h2); - if(i == 1) theta = -theta, y0 = -y0; - - ld x0 = t * tanalpha; - - ld phi = atan2(y, x) - atan2(y0, x0) + M_PI; - - ld delta = euclid ? hypot(y0,z) : atan2_auto(z / sin(theta), t / cos_auto(vid.ipd/2)); - if(euclid || hyperbolic) phi -= M_PI; - if(hyperbolic) delta = -delta; - - h[0] = phi; - h[1] = theta; - h[2] = delta; - if(euclid || hyperbolic) h[1] = -theta; - - -// printf(" => %10.5lf %10.5lf %10.5lf", phi, theta, delta); - } // printf("\n"); return true; @@ -1242,7 +1198,7 @@ void drawTriangle(triangle& t) { dt++; #if CAP_ODS - if(vid.stereo_mode == current_display->sODS) { + if(vid.stereo_mode == sODS) { hyperpoint pts[3]; // not implemented