diff --git a/graph.cpp b/graph.cpp index f9ca7f12..b50fb30e 100644 --- a/graph.cpp +++ b/graph.cpp @@ -3730,64 +3730,108 @@ EX ld mousedist(shiftmatrix T) { return sqhypot_d(2, h1) + (point_behind(T1) ? 1e10 : 0); } -vector clipping_planes; +vector> clipping_plane_sets; EX int noclipped; EX bool frustum_culling = true; +EX ld threshold, xyz_threshold; + +EX bool clip_checked = false; + void make_clipping_planes() { #if MAXMDIM >= 4 - clipping_planes.clear(); + clip_checked = false; if(!frustum_culling || PIU(sphere) || experimental || vid.stereo_mode == sODS || panini_alpha) return; - #if CAP_VR - if(vrhr::active()) return; - #endif - auto add_clipping_plane = [] (ld x1, ld y1, ld x2, ld y2) { + if(WDIM == 3 && pmodel == mdPerspective && !nonisotropic && !in_s2xe()) + threshold = sin_auto(cgi.corner_bonus), xyz_threshold = 0, clip_checked = true; + else if(pmodel == mdGeodesic && sn::in()) + threshold = .6, xyz_threshold = 3, clip_checked = true; + else if(pmodel == mdGeodesic && nil) + threshold = 2, xyz_threshold = 3, clip_checked = true; + else return; + + clipping_plane_sets.clear(); + + auto add_clipping_plane_txy = [] (transmatrix T, const transmatrix& nlp, 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); sx /= hypot_d(3, sx); sx[3] = 0; - if(nisot::local_perspective_used()) sx = ortho_inverse(NLP) * sx; - clipping_planes.push_back(sx); + sx = T * sx; + if(nisot::local_perspective_used()) sx = ortho_inverse(nlp) * sx; + clipping_plane_sets.back().push_back(sx); }; - ld tx = current_display->tanfov; - ld ty = tx * current_display->ysize / current_display->xsize; - add_clipping_plane(+tx, +ty, -tx, +ty); - add_clipping_plane(-tx, +ty, -tx, -ty); - add_clipping_plane(-tx, -ty, +tx, -ty); - add_clipping_plane(+tx, -ty, +tx, +ty); + + auto add_clipping_plane_proj = [&] (transmatrix T, const transmatrix& nlp, const transmatrix& iproj, ld x1, ld y1, ld x2, ld y2) { + hyperpoint h1 = iproj * point31(x1, y1, .5); + hyperpoint h2 = iproj * point31(x2, y2, .5); + h1 /= h1[2]; h2 /= h2[2]; + add_clipping_plane_txy(T, nlp, h1[0], h1[1], h2[0], h2[1]); + }; + + auto clipping_planes_screen = [&] (const transmatrix& T, const transmatrix& nlp) { + ld tx = current_display->tanfov; + ld ty = tx * current_display->ysize / current_display->xsize; + clipping_plane_sets.push_back({}); + add_clipping_plane_txy(T, nlp, +tx, +ty, -tx, +ty); + add_clipping_plane_txy(T, nlp, -tx, +ty, -tx, -ty); + add_clipping_plane_txy(T, nlp, -tx, -ty, +tx, -ty); + add_clipping_plane_txy(T, nlp, +tx, -ty, +tx, +ty); + }; + + bool stdview = true; + + #if CAP_VR + if(vrhr::active()) { + for(auto p: vrhr::frusta) { + if(p.screen) + clipping_planes_screen(inverse(p.pre), p.nlp); + else { + auto iproj = inverse(p.proj); + auto ipre = inverse(p.pre); + clipping_plane_sets.push_back({}); + add_clipping_plane_proj(ipre, p.nlp, iproj, 1, 1, 0, 1); + add_clipping_plane_proj(ipre, p.nlp, iproj, 0, 1, 0, 0); + add_clipping_plane_proj(ipre, p.nlp, iproj, 0, 0, 1, 0); + add_clipping_plane_proj(ipre, p.nlp, iproj, 1, 0, 1, 1); + } + stdview = false; + } + } + #endif + if(stdview) clipping_planes_screen(Id, NLP); #endif } +bool clipped_by(const hyperpoint& H, const vector& v) { + for(auto& cpoint: v) if((H|cpoint) < -threshold) return true; + return false; + } + +bool clipped_by(const hyperpoint& H, const vector>& vv) { + for(auto& cps: vv) if(!clipped_by(H, cps)) return false; + return true; + } + bool celldrawer::cell_clipped() { - if(WDIM == 3 && pmodel == mdPerspective && !nonisotropic && !in_s2xe()) { - hyperpoint H = unshift(tC0(V)); - if(prod) H = product::inverse_exp(H); - for(hyperpoint& cpoint: clipping_planes) if((H|cpoint) < -sin_auto(cgi.corner_bonus)) { - drawcell_in_radar(); - return true; - } + + if(!clip_checked) return false; + + hyperpoint H = unshift(tC0(V)); + + if(xyz_threshold && abs(H[0]) <= xyz_threshold && abs(H[1]) <= xyz_threshold && abs(H[2]) <= xyz_threshold) { noclipped++; + return false; } - if(pmodel == mdGeodesic && sn::in()) { - hyperpoint H = unshift(tC0(V)); - if(abs(H[0]) <= 3 && abs(H[1]) <= 3 && abs(H[2]) <= 3 ) ; - else { - hyperpoint H2 = inverse_exp(shiftless(H), pQUICK); - for(hyperpoint& cpoint: clipping_planes) if((H2|cpoint) < -.6) return true; - } - noclipped++; - } - if(pmodel == mdGeodesic && nil) { - hyperpoint H = unshift(tC0(V)); - if(abs(H[0]) <= 3 && abs(H[1]) <= 3 && abs(H[2]) <= 3 ) ; - else { - hyperpoint H2 = inverse_exp(shiftless(H), pQUICK); - for(hyperpoint& cpoint: clipping_planes) if((H2|cpoint) < -2) return true; - } - noclipped++; + + if(clipped_by(H, clipping_plane_sets)) { + drawcell_in_radar(); + return true; } + + noclipped++; return false; } diff --git a/vr.cpp b/vr.cpp index 17125bf9..71ed8b3c 100644 --- a/vr.cpp +++ b/vr.cpp @@ -236,6 +236,17 @@ EX int ui_xmin, ui_ymin, ui_xmax, ui_ymax; EX reaction_t change_ui_bounds; +#if HDR +struct frustum_info { + transmatrix pre; + transmatrix nlp; + bool screen; + transmatrix proj; + }; +#endif + +EX vector frusta; + EX void set_ui_bounds() { ui_xmin = 0; ui_ymin = 0; @@ -1011,6 +1022,7 @@ EX void render() { track_poses(); resetbuffer rb; state = 2; + vrhr::frusta.clear(); // cscr = lshiftclick ? eCompScreen::eyes : eCompScreen::single; @@ -1042,6 +1054,11 @@ EX void render() { hmd_pre = hmd_pre_for[i] = cview().T * inverse(master_cview.T); radar_transform = trt.backup * inverse(hmd_pre); + if(i < 2) + frusta.push_back(frustum_info{hmd_pre, NLP, false, vrdata.proj[i]}); + else + frusta.push_back(frustum_info{hmd_pre, NLP, true, Id}); + if(1) { gen_mv(); E4;