3d:: smart display for 3D

This commit is contained in:
Zeno Rogue 2019-03-21 19:13:45 +01:00
parent fed102a7e1
commit ab7a322e5e
5 changed files with 85 additions and 59 deletions

View File

@ -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,48 +740,12 @@ void add_cells_drawn(char c = 'C') {
}
void edit_sightrange() {
if(vid.use_smart_range == 0) {
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 "
"the game effectively harder."));
dialog::reaction = doOvergenerate;
dialog::bound_low(1-getDistLimit());
dialog::bound_up(allowIncreasedSight() ? gp::dist_2() * 5 : 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 {
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()) {
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(); });
}
if(allowChangeRange() && allowIncreasedSight()) {
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()) {
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');
dialog::add_action([] () { gamerange_bonus = sightrange_bonus; doOvergenerate(); });
}
if(!allowChangeRange() || !allowIncreasedSight()) {
dialog::addItem(XLAT("enable the cheat mode for additional options"), 'X');
dialog::add_action(enable_cheat);
}
add_cells_drawn('C');
};
}
void menuitem_sightrange(char c) {
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"),
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, "
@ -790,25 +755,58 @@ void menuitem_sightrange(char c) {
"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');
}
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 "
"the game effectively harder."));
dialog::reaction = doOvergenerate;
dialog::bound_low(1-getDistLimit());
dialog::bound_up(allowIncreasedSight() ? gp::dist_2() * 5 : 0);
}
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(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(); });
}
if(allowChangeRange() && allowIncreasedSight()) {
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() && 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');
dialog::add_action([] () { gamerange_bonus = sightrange_bonus; doOvergenerate(); });
}
if(!allowChangeRange() || !allowIncreasedSight()) {
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."
);
});
};
});
}
else {
add_cells_drawn('C');
};
}
void menuitem_sightrange(char c) {
if(vid.use_smart_range)
dialog::addSelItem(XLAT("minimum visible cell in pixels"), fts(vid.smart_range_detail), c);
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);
else
dialog::addSelItem(XLAT("sight range"), its(sightrange_bonus), c);
dialog::add_action(edit_sightrange);
}
}
void showGraphConfig() {
cmode = vid.xres > vid.yres * 1.4 ? sm::SIDE : sm::MAYDARK;

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -787,19 +787,19 @@ 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; i<DIM; i++)
if(std::isnan(h1[i]) || std::isinf(h1[i])) return false;
ld x = current_display->xcenter + current_display->radius * h1[0];
ld y = current_display->ycenter + current_display->radius * h1[1] * vid.stretch;
@ -807,21 +807,40 @@ bool in_smart_range(const transmatrix& T) {
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 * 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 dx = 0, dy = 0, dz = 0, dh[MAXMDIM];
for(int i=0; i<DIM; i++) {
hyperpoint h2;
applymodel(T * cpush0(i, 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;
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;
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;
}