From ab7a322e5e50889a3b95f0386e94fd5cd7473d65 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Thu, 21 Mar 2019 19:13:45 +0100 Subject: [PATCH] 3d:: smart display for 3D --- config.cpp | 70 +++++++++++++++++++++++++--------------------------- debug.cpp | 2 +- graph.cpp | 2 ++ hyper.h | 1 + hypgraph.cpp | 69 ++++++++++++++++++++++++++++++++++----------------- 5 files changed, 85 insertions(+), 59 deletions(-) diff --git a/config.cpp b/config.cpp index f00996f0..6df56b01 100644 --- a/config.cpp +++ b/config.cpp @@ -360,6 +360,7 @@ void initConfig() { addsaver(vid.use_smart_range, "smart-range", 0); addsaver(vid.smart_range_detail, "smart-range-detail", 8); + addsaver(vid.smart_range_detail_3, "smart-range-detail", 30); addsaver(vid.cells_drawn_limit, "limit on cells drawn", 10000); addsaver(vid.skiprope, "mobius", 0); @@ -739,7 +740,23 @@ void add_cells_drawn(char c = 'C') { } void edit_sightrange() { - if(vid.use_smart_range == 0) { + if(vid.use_smart_range) { + ld& det = DIM == 2 ? vid.smart_range_detail : vid.smart_range_detail_3; + dialog::editNumber(det, 1, 50, 1, DIM == 2 ? 8 : 30, XLAT("minimum visible cell in pixels"), ""); + } + else if(DIM == 3) { + dialog::editNumber(sightranges[geometry], 0, 2 * M_PI, 0.5, M_PI, XLAT("3D sight range"), + XLAT( + "Sight range for 3D geometries is specified in the absolute units. This value also affects the fog effect.\n\n" + "In spherical geometries, the sight range of 2pi will let you see things behind you as if they were in front of you, " + "and the sight range of pi (or more) will let you see things on the antipodal point just as if they were close to you.\n\n" + "In hyperbolic geometries, the number of cells to render depends exponentially on the sight range. More cells to drawn " + "reduces the performance.\n\n" + "Sight range affects the gameplay, and monsters act iff they are visible. Monster generation takes this into account." + ) + ); + } + else { dialog::editNumber(sightrange_bonus, -5, allowIncreasedSight() ? 3 : 0, 1, 0, XLAT("sight range"), XLAT("Roughly 42% cells are on the edge of your sight range. Reducing " "the sight range makes HyperRogue work faster, but also makes " @@ -748,13 +765,10 @@ void edit_sightrange() { dialog::bound_low(1-getDistLimit()); dialog::bound_up(allowIncreasedSight() ? gp::dist_2() * 5 : 0); } - else { - dialog::editNumber(vid.smart_range_detail, 1, 50, 1, 8, XLAT("minimum visible cell in pixels"), ""); - } dialog::extra_options = [] () { dialog::addBoolItem(XLAT("draw range based on distance"), vid.use_smart_range == 0, 'D'); dialog::add_action([] () { vid.use_smart_range = 0; popScreen(); edit_sightrange(); }); - if(allowIncreasedSight()) { + if(DIM == 2 && allowIncreasedSight()) { dialog::addBoolItem(XLAT("draw based on size in the projection (no generation)"), vid.use_smart_range == 1, 'N'); dialog::add_action([] () { vid.use_smart_range = 1; popScreen(); edit_sightrange(); }); } @@ -762,7 +776,7 @@ void edit_sightrange() { dialog::addBoolItem(XLAT("draw based on size in the projection (generation)"), vid.use_smart_range == 2, 'G'); dialog::add_action([] () { vid.use_smart_range = 2; popScreen(); edit_sightrange(); }); } - if(vid.use_smart_range == 0 && allowChangeRange()) { + if(vid.use_smart_range == 0 && allowChangeRange() && DIM == 2) { dialog::addSelItem(XLAT("generation range bonus"), its(genrange_bonus), 'O'); dialog::add_action([] () { genrange_bonus = sightrange_bonus; doOvergenerate(); }); dialog::addSelItem(XLAT("game range bonus"), its(gamerange_bonus), 'S'); @@ -772,42 +786,26 @@ void edit_sightrange() { dialog::addItem(XLAT("enable the cheat mode for additional options"), 'X'); dialog::add_action(enable_cheat); } + if(DIM == 3 && !vid.use_smart_range) { + dialog::addSelItem(XLAT("limit generation"), fts(extra_generation_distance), 'E'); + dialog::add_action([] { + dialog::editNumber(extra_generation_distance, 0, 999, 0.5, 999, XLAT("limit generation"), + "Cells over this distance will not be generated, but they will be drawn if they are already generated and in the sight range." + ); + }); + } add_cells_drawn('C'); }; } void menuitem_sightrange(char c) { - if(DIM == 3) { + if(vid.use_smart_range) + dialog::addSelItem(XLAT("minimum visible cell in pixels"), fts(DIM == 3 ? vid.smart_range_detail_3 : vid.smart_range_detail), c); + else if(DIM == 3) dialog::addSelItem(XLAT("3D sight range"), fts(sightranges[geometry]), c); - dialog::add_action([] { - dialog::editNumber(sightranges[geometry], 0, 2 * M_PI, 0.5, M_PI, XLAT("sight range"), - XLAT( - "Sight range for 3D geometries is specified in the absolute units. This value also affects the fog effect.\n\n" - "In spherical geometries, the sight range of 2pi will let you see things behind you as if they were in front of you, " - "and the sight range of pi (or more) will let you see things on the antipodal point just as if they were close to you.\n\n" - "In hyperbolic geometries, the number of cells to render depends exponentially on the sight range. More cells to drawn " - "reduces the performance.\n\n" - "Sight range affects the gameplay, and monsters act iff they are visible. Monster generation takes this into account." - ) - ); - dialog::extra_options = [] { - add_cells_drawn('C'); - dialog::addSelItem(XLAT("limit generation"), fts(extra_generation_distance), 'G'); - dialog::add_action([] { - dialog::editNumber(extra_generation_distance, 0, 999, 0.5, 999, XLAT("limit generation"), - "Cells over this distance will not be generated, but they will be drawn if they are already generated and in the sight range." - ); - }); - }; - }); - } - else { - if(vid.use_smart_range) - dialog::addSelItem(XLAT("minimum visible cell in pixels"), fts(vid.smart_range_detail), c); - else - dialog::addSelItem(XLAT("sight range"), its(sightrange_bonus), c); - dialog::add_action(edit_sightrange); - } + else + dialog::addSelItem(XLAT("sight range"), its(sightrange_bonus), c); + dialog::add_action(edit_sightrange); } void showGraphConfig() { diff --git a/debug.cpp b/debug.cpp index 437079d2..382f134a 100644 --- a/debug.cpp +++ b/debug.cpp @@ -678,7 +678,7 @@ int read_cheat_args() { else if(argis("-smart")) { PHASEFROM(2); cheat(); vid.use_smart_range = 2; - shift_arg_formula(vid.smart_range_detail); + shift_arg_formula(DIM == 3 ? vid.smart_range_detail_3 : vid.smart_range_detail); } else if(argis("-smartn")) { PHASEFROM(2); diff --git a/graph.cpp b/graph.cpp index a4e300f6..4b4391cb 100644 --- a/graph.cpp +++ b/graph.cpp @@ -5829,6 +5829,7 @@ bool allowIncreasedSight() { if(randomPatternsMode) return true; if(racing::on) return true; if(quotient || !hyperbolic || archimedean) return true; + if(DIM == 3) return true; return false; } @@ -5840,6 +5841,7 @@ bool allowChangeRange() { if(racing::on) return true; if(sightrange_bonus >= 0) return true; if(archimedean) return true; + if(DIM == 3) return true; return false; } diff --git a/hyper.h b/hyper.h index 3059ee21..a4c4c5d0 100644 --- a/hyper.h +++ b/hyper.h @@ -1122,6 +1122,7 @@ struct videopar { int use_smart_range; // 0 = distance-based, 1 = model-based, 2 = model-based and generate ld smart_range_detail;// minimum visible cell for modes 1 and 2 + ld smart_range_detail_3;// minimum visible cell in 3D (for mode 2, there is no mode 1) int cells_drawn_limit; ld skiprope; diff --git a/hypgraph.cpp b/hypgraph.cpp index 6b21e33f..fef691f1 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -787,41 +787,60 @@ bool invis_point(const hyperpoint h) { } bool invalid_point(const hyperpoint h) { - return std::isnan(h[2]) || h[2] > 1e8 || std::isinf(h[2]); + return std::isnan(h[DIM]) || h[DIM] > 1e8 || std::isinf(h[DIM]); } bool invalid_point(const transmatrix T) { - return std::isnan(T[2][2]) || T[2][2] > 1e8 || std::isinf(T[2][2]); + return std::isnan(T[DIM][DIM]) || T[DIM][DIM] > 1e8 || std::isinf(T[DIM][DIM]); } bool in_smart_range(const transmatrix& T) { if(invalid_point(T)) return false; - hyperpoint h1, h2, h3; + hyperpoint h1; applymodel(tC0(T), h1); - if(std::isnan(h1[0]) || std::isnan(h1[1])) return false; - if(std::isinf(h1[0]) || std::isinf(h1[1])) return false; + for(int i=0; ixcenter + current_display->radius * h1[0]; ld y = current_display->ycenter + current_display->radius * h1[1] * vid.stretch; - if(x > current_display->xtop + current_display->xsize * 2)return false; + if(x > current_display->xtop + current_display->xsize * 2) return false; if(x < current_display->xtop - current_display->xsize * 1) return false; - if(y > current_display->ytop + current_display->ysize * 2)return false; + if(y > current_display->ytop + current_display->ysize * 2) return false; if(y < current_display->ytop - current_display->ysize * 1) return false; + if(DIM == 3) { + if(-h1[2] < conformal::clip_min * 2 - conformal::clip_max) return false; + if(-h1[2] > conformal::clip_max * 2 - conformal::clip_min) return false; + } ld epsilon = 0.01; - applymodel(T * xpush0(epsilon), h2); - ld x1 = current_display->radius * abs(h2[0] - h1[0]) / epsilon; - ld y1 = current_display->radius * abs(h2[1] - h1[1]) * vid.stretch / epsilon; - applymodel(T * ypush(epsilon) * C0, h3); - ld x2 = current_display->radius * abs(h3[0] - h1[0]) / epsilon; - ld y2 = current_display->radius * abs(h3[1] - h1[1]) * vid.stretch / epsilon; - ld scale = sqrt(hypot(x1, y1) * hypot(x2, y2)) * scalefactor * hcrossf7; + + ld dx = 0, dy = 0, dz = 0, dh[MAXMDIM]; + for(int i=0; iradius * abs(h2[0] - h1[0]) / epsilon; + ld y1 = current_display->radius * abs(h2[1] - h1[1]) * vid.stretch / epsilon; + dx = max(dx, x1); dy = max(dy, y1); + if(DIM == 3) dz = max(dz, abs(h2[2] - h1[2])); + dh[i] = hypot(x1, y1); + } + + if(DIM == 3) { + if(-h1[2] + 2 * dz < conformal::clip_min || -h1[2] - 2 * dz > conformal::clip_max) return false; + sort(dh, dh+DIM); + ld scale = sqrt(dh[1] * dh[2]) * scalefactor * hcrossf7; + if(scale <= vid.smart_range_detail_3) return false; + } + else { + ld scale = sqrt(dh[0] * dh[1]) * scalefactor * hcrossf7; + if(scale <= vid.smart_range_detail) return false; + } + return - scale > vid.smart_range_detail && - x - 2 * max(x1, x2) < current_display->xtop + current_display->xsize && - x + 2 * max(x1, x2) > current_display->xtop && - y - 2 * max(y1, y2) < current_display->ytop + current_display->ysize && - y + 2 * max(y1, y2) > current_display->ytop; + x - 2 * dx < current_display->xtop + current_display->xsize && + x + 2 * dx > current_display->xtop && + y - 2 * dy < current_display->ytop + current_display->ysize && + y + 2 * dy > current_display->ytop; } #if CAP_GP @@ -1613,9 +1632,15 @@ ld extra_generation_distance = 99; bool do_draw(cell *c, const transmatrix& T) { if(DIM == 3) { if(cells_drawn > vid.cells_drawn_limit) return false; - ld dist = hdist0(tC0(T)); - if(dist > sightranges[geometry]) return false; - if(dist <= extra_generation_distance) setdist(c, 7, c); + if(vid.use_smart_range) { + if(cells_drawn >= 50 && !in_smart_range(T)) return false; + setdist(c, 7, c); + } + else { + ld dist = hdist0(tC0(T)); + if(dist > sightranges[geometry]) return false; + if(dist <= extra_generation_distance) setdist(c, 7, c); + } return true; }