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,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() {

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