more detailed 3D depth settings

This commit is contained in:
Zeno Rogue 2023-02-18 18:32:01 +01:00
parent 1eaa6d4dd9
commit 573304faab
7 changed files with 229 additions and 93 deletions

View File

@ -745,13 +745,18 @@ void geometry_information::make_star(hpcshape& sh, ld rad) {
void geometry_information::make_euclidean_sky() {
bshape(cgi.shEuclideanSky, PPR::EUCLIDEAN_SKY);
for(int x=-20; x<20; x++)
for(int y=-20; y<20; y++)
for(int y=-20; y<20; y++) {
auto x0 = x * cgi.LOWSKY;
auto x1 = (x+1) * cgi.LOWSKY;
auto y0 = y * cgi.LOWSKY;
auto y1 = (y+1) * cgi.LOWSKY;
hpcsquare(
lzpush(cgi.WALL) * hpxy(x, y),
lzpush(cgi.WALL) * hpxy(x, y+1),
lzpush(cgi.WALL) * hpxy(x+1, y),
lzpush(cgi.WALL) * hpxy(x+1, y+1)
lzpush(cgi.LOWSKY) * hpxy(x0, y0),
lzpush(cgi.LOWSKY) * hpxy(x0, y1),
lzpush(cgi.LOWSKY) * hpxy(x1, y0),
lzpush(cgi.LOWSKY) * hpxy(x1, y1)
);
}
}
/** res[0] and res[1] place H on the plane, while res[2] is the altitude */
@ -1118,13 +1123,10 @@ void geometry_information::make_3d_models() {
make_ball(shDisk, orbsize*.2, 2);
make_ball(shHeptaMarker, zhexf*.2, 1);
make_ball(shSnowball, zhexf*.1, 1);
if(euclid) {
make_ball(shSun, 0.5, 2);
make_euclidean_sky();
}
else
make_star(shSun, 3);
make_star(shNightStar, euclid ? 0.05 : 0.75);
make_ball(shSkyboxSun, 8 * zhexf, 2);
if(euclid) make_euclidean_sky();
make_star(shSun, vid.sun_size * zhexf);
make_star(shNightStar, vid.star_size * zhexf);
if(WDIM == 2) {
for(int i=0; i<3; i++) {

View File

@ -325,6 +325,7 @@ void non_editable() {
void float_setting::show_edit_option(int key) {
if(modify_me) modify_me(this);
dialog::addSelItem(XLAT(menu_item_name), fts(*value) + unit, key);
if(*value == use_the_default_value) dialog::lastItem().value = XLAT("default");
dialog::add_action([this] () {
add_to_changed(this);
dialog::editNumber(*value, min_value, max_value, step, dft, XLAT(menu_item_name), help_text);
@ -2368,6 +2369,45 @@ EX void show_spatial_embedding() {
dialog::display();
}
EX void show3D_height_details() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
dialog::init(XLAT("3D detailed settings"));
add_edit(vid.wall_height);
dialog::addBreak(50);
add_edit(vid.rock_wall_ratio);
add_edit(vid.human_wall_ratio);
add_edit(vid.lake_top);
add_edit(vid.lake_shallow);
add_edit(vid.lake_bottom);
dialog::addBreak(50);
if(embedded_plane) {
add_edit(auto_remove_roofs);
add_edit(vid.wall_height2);
add_edit(vid.wall_height3);
add_edit(draw_sky);
add_edit(vid.lowsky_height);
add_edit(vid.sky_height);
add_edit(vid.star_height);
add_edit(vid.infdeep_height);
add_edit(vid.sun_size);
add_edit(vid.star_size);
add_edit(vid.height_limits);
if(euclid && msphere) add_edit(use_euclidean_infinity);
}
else dialog::addInfo(XLAT("more options in 3D engine"));
dialog::addBreak(100);
dialog::addBack();
dialog::display();
}
EX void show3D() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
@ -2411,11 +2451,9 @@ EX void show3D() {
dialog::addBreak(50);
add_edit(vid.wall_height);
dialog::addSelItem("height details", "", 'D');
dialog::add_action_push(show3D_height_details);
add_edit(vid.rock_wall_ratio);
add_edit(vid.human_wall_ratio);
add_edit(vid.lake_top);
add_edit(vid.lake_bottom);
if(scale_used())
add_edit(vid.creature_scale);
}
@ -2584,7 +2622,10 @@ EX int config3 = addHook(hooks_configfile, 100, [] {
param_b(numerical_minefield, "numerical_minefield")
->editable("display mine counts numerically", 'n');
param_b(dont_display_minecount, "dont_display_minecount");
param_b(draw_sky, "draw sky", true);
param_enum(draw_sky, "draw_sky", "draw_sky", skyAutomatic)
-> editable({{"NO", "do not draw sky"}, {"automatic", ""}, {"skybox", "works only in Euclidean"}, {"always", "might be glitched in some settings"}}, "sky rendering", 's');
param_b(use_euclidean_infinity, "use_euclidean_infinity", true)
-> editable("infinite sky", 'i');
param_f(linepatterns::parallel_count, "parallel_count")
->editable(0, 24, 1, "number of parallels drawn", "", 'n');
param_f(linepatterns::parallel_max, "parallel_max")
@ -2688,10 +2729,44 @@ EX int config3 = addHook(hooks_configfile, 100, [] {
fts(cosh(vid.depth - vid.wall_height * vid.human_wall_ratio) / cosh(vid.depth)))
);
});
param_f(vid.lake_top, "lake_top", "3D lake top", .25)
param_f(vid.lake_top, "lake_top", "3D lake top", .25 / 0.3)
->editable(0, 1, .1, "Level of water surface", "", 'l');
param_f(vid.lake_bottom, "lake_bottom", "3D lake bottom", .9)
param_f(vid.lake_shallow, "lake_shallow", "3D lake shallow", .4 / 0.3)
->editable(0, 1, .1, "Level of shallow water", "", 's');
param_f(vid.lake_bottom, "lake_bottom", "3D lake bottom", .9 / 0.3)
->editable(0, 1, .1, "Level of water bottom", "", 'k');
param_f(vid.wall_height2, "wall_height2", "wall_height2", 2)
->editable(0, 5, .1, "ratio of high walls to normal walls", "", '2');
param_f(vid.wall_height3, "wall_height3", "wall_height3", 3)
->editable(0, 5, .1, "ratio of very high walls to normal walls", "", '3');
param_f(vid.lowsky_height, "lowsky_height", "lowsky_height", 2)
->editable(0, 5, .1, "lowsky height", "", '4');
param_f(vid.sky_height, "sky_height", "sky_height", use_the_default_value)
->editable(0, 10, .1, "altitude of the sky", "", '5')
->set_extra([] {
dialog::addSelItem(XLAT("use the default value"), 0, 'D');
dialog::add_action([] { vid.sky_height = use_the_default_value; });
});
param_f(vid.star_height, "star_height", "star_height", use_the_default_value)
->editable(0, 10, .1, "altitude of the stars", "", '6')
->set_extra([] {
dialog::addSelItem(XLAT("use the default value"), 0, 'D');
dialog::add_action([] { vid.star_height = use_the_default_value; });
});
param_f(vid.infdeep_height, "infdeep_height", "infdeep_height", use_the_default_value)
->editable(0, 10, .1, "infinite depth", "", '7')
->set_extra([] {
dialog::addSelItem(XLAT("use the default value"), 0, 'D');
dialog::add_action([] { vid.infdeep_height = use_the_default_value; });
});
param_f(vid.sun_size, "sun_size", "sun_size", 8)
->editable(0, 10, .1, "sun size (relative to item sizes)", "", '8');
param_f(vid.star_size, "star_size", "star_size", 0.75)
->editable(0, 10, .1, "night star size (relative to item sizes)", "", '9');
param_b(vid.height_limits, "height_limits", true)
->editable("automatically limit heights if too high", 'l');
param_b(auto_remove_roofs, "auto_remove_roofs", true)
->editable("do not render higher levels if camera too high", 'r');
addsaver(vid.tc_depth, "3D TC depth", 1);
addsaver(vid.tc_camera, "3D TC camera", 2);
addsaver(vid.tc_alpha, "3D TC alpha", 3);

View File

@ -727,7 +727,7 @@ void dqi_poly::gldraw() {
glhr::color2(color, (flags & POLY_INTENSE) ? 2 : 1);
glhr::set_depthtest(model_needs_depth() && prio < PPR::SUPERLINE);
glhr::set_depthwrite(model_needs_depth() && prio != PPR::TRANSPARENT_SHADOW && prio != PPR::EUCLIDEAN_SKY);
glhr::set_fogbase(prio == PPR::SKY ? 1.0 + (euclid ? 20 : 5 / sightranges[geometry]) : 1.0);
glhr::set_fogbase(prio == PPR::SKY ? 1.0 + ((abs(cgi.SKY - cgi.LOWSKY)) / sightranges[geometry]) : 1.0);
glDrawArrays(GL_TRIANGLES, ioffset, cnt);
}
else {
@ -2456,7 +2456,7 @@ EX void drawqueue() {
#endif
#if MAXMDIM >= 4 && CAP_GL
if(embedded_plane && (hyperbolic || cgi.emb->is_sph_in_low() || cgi.emb->is_in_noniso()) && !vrhr::rendering()) make_air();
make_air();
#endif
#if CAP_VR

View File

@ -271,6 +271,7 @@ EX }
virtual ld anim_center_z() { return center_z(); }
virtual hyperpoint anim_tile_center();
virtual void logical_fix(transmatrix&) = 0;
virtual ld height_limit(ld sign);
virtual bool is_euc_in_product() { return false; }
virtual bool is_product_embedding() { return false; }
@ -283,7 +284,6 @@ EX }
virtual bool is_euc_in_nil() { return false; }
virtual bool is_euc_in_noniso() { return false; }
virtual bool is_in_noniso() { return false; }
virtual bool is_depth_limited() { return false; }
virtual bool is_cylinder() { return false; }
virtual bool no_spin() { return false; }
@ -307,6 +307,21 @@ EX }
EX geometry_information *swapper;
ld embedding_method::height_limit(ld sign) {
if(sign > 0) {
if(hyperbolic || sol || nih || sl2 || in_h2xe()) return 5;
if(sphere || nil || in_s2xe()) return M_PI/2;
return 100;
}
if(sign < 0) {
if(center_z()) return -center_z();
if(hyperbolic || sol || nih || sl2 || in_h2xe()) return -5;
if(sphere || nil || in_s2xe()) return -M_PI/2;
return -100;
}
return 0;
}
hyperpoint embedding_method::tile_center() {
ld z = center_z();
if(z == 0) return C0;
@ -608,7 +623,6 @@ struct emb_euc_in_hyp : emb_actual {
struct emb_sphere_in_low : emb_actual {
bool is_sph_in_low() override { return true; }
bool is_depth_limited() override { return true; }
transmatrix intermediate_to_actual_translation(hyperpoint i) override {
return map_relative_push(logical_to_actual(i)) * zpush(-1);
}
@ -757,7 +771,6 @@ struct emb_euc_in_sl2 : emb_euclid_noniso {
struct emb_euc_cylinder : emb_euclid_noniso {
bool is_cylinder() override { return true; }
ld center_z() override { return 1; }
bool is_depth_limited() override { return true; }
transmatrix get_lsti() override { return cspin90(0, 1); }
hyperpoint actual_to_intermediate(hyperpoint a) override {
ld z0 = asin_auto(hypot(a[1], a[2]));
@ -845,9 +858,11 @@ struct emb_euc_cylinder_sl2 : emb_euc_cylinder_twisted {
}
};
/** Clifford torus */
struct emb_euc_in_sph : emb_euclid_noniso {
bool is_euc_in_sph() override { return true; }
ld center_z() override { return 1; }
virtual ld height_limit(ld sign) { return sign < 0 ? 0 : 90._deg; }
hyperpoint actual_to_intermediate(hyperpoint a) override {
ld tx = hypot(a[0], a[2]);
ld ty = hypot(a[1], a[3]);

View File

@ -236,7 +236,7 @@ struct geometry_information {
BODY, BODY1, BODY2, BODY3,
NECK1, NECK, NECK3, HEAD, HEAD1, HEAD2, HEAD3,
ALEG0, ALEG, ABODY, AHEAD, BIRD, LOWSKY, SKY, HIGH, HIGH2,
SHALLOW;
HELL, STAR, SHALLOW;
ld human_height, slev;
ld eyelevel_familiar, eyelevel_human, eyelevel_dog;
@ -308,7 +308,7 @@ hpcshape
shKnife, shTongue, shFlailMissile, shTrapArrow,
shPirateHook, shSmallPirateHook, shPirateHood, shEyepatch, shPirateX,
// shScratch,
shHeptaMarker, shSnowball, shHugeDisk, shSun, shNightStar, shEuclideanSky,
shHeptaMarker, shSnowball, shHugeDisk, shSkyboxSun, shSun, shNightStar, shEuclideanSky,
shSkeletonBody, shSkull, shSkullEyes, shFatBody, shWaterElemental,
shPalaceGate, shFishTail,
shMouse, shMouseLegs, shMouseEyes,
@ -991,10 +991,9 @@ EX namespace geom3 {
BIRD = 1.20;
SHALLOW = .95;
STUFF = 1;
LOWSKY = SKY = HIGH = HIGH2 = 1;
LOWSKY = SKY = HIGH = HIGH2 = STAR = 1;
}
else {
INFDEEP = GDIM == 3 ? (sphere ? 90._deg : +5) : (euclid || sphere) ? 0.01 : lev_to_projection(0) * tanh(vid.camera);
ld wh = actual_wall_height();
WALL = lev_to_factor(wh);
FLOOR = lev_to_factor(0);
@ -1041,36 +1040,43 @@ EX namespace geom3 {
slev = vid.rock_wall_ratio * wh / 3;
for(int s=0; s<=3; s++)
SLEV[s] = lev_to_factor(vid.rock_wall_ratio * wh * s/3);
LAKE = lev_to_factor(sgn * -vid.lake_top);
SHALLOW = lev_to_factor(sgn * -.4);
LAKE = lev_to_factor(sgn * wh * -vid.lake_top);
SHALLOW = lev_to_factor(sgn * wh * -vid.lake_shallow);
HELLSPIKE = lev_to_factor(sgn * -(vid.lake_top+vid.lake_bottom)/2);
BOTTOM = lev_to_factor(sgn * -vid.lake_bottom);
LOWSKY = lev_to_factor(2 * wh);
HIGH = LOWSKY;
HIGH2 = lev_to_factor(3 * wh);
SKY = LOWSKY - sgn * 5;
LOWSKY = lev_to_factor(vid.lowsky_height * wh);
HIGH = lev_to_factor(vid.wall_height2 * wh);
HIGH2 = lev_to_factor(vid.wall_height3 * wh);
SKY = vid.sky_height == use_the_default_value ? cgi.emb->height_limit(-sgn) : lev_to_factor(vid.sky_height * wh);
STAR = vid.star_height == use_the_default_value ? lerp(FLOOR, SKY, 0.95) : lev_to_factor(vid.star_height * wh);
HELL = -SKY;
if(embedded_plane)
INFDEEP = vid.infdeep_height == use_the_default_value ? cgi.emb->height_limit(sgn) : lev_to_factor(vid.infdeep_height * wh);
else
INFDEEP = (euclid || sphere) ? 0.01 : lev_to_projection(0) * tanh(vid.camera);
/* in spherical/cylindrical case, make sure that the high stuff does not go through the center */
if(cgi.emb->is_depth_limited()) {
ld max_high = lerp(-FLOOR, -1, 0.8);
ld max_high2 = lerp(-FLOOR, -1, 0.9);
if(HIGH < max_high) HIGH = max_high;
if(HIGH2 < max_high2) HIGH2 = max_high2;
if(LOWSKY < max_high) LOWSKY = max_high;
if(SKY < max_high) SKY = max_high;
if(vid.wall_height < 0) {
SKY = -3 * vid.wall_height;
LOWSKY = 1.75 * SKY;
}
if(SHALLOW < max_high) SHALLOW = max_high;
if(LAKE < max_high) LAKE = max_high;
if(BOTTOM < max_high2) BOTTOM = max_high2;
if(HELLSPIKE < max_high) HELLSPIKE = max_high;
if(sgn < 0) INFDEEP = -1;
if(vid.height_limits) {
auto hp = cgi.emb->height_limit(1);
auto hn = cgi.emb->height_limit(-1);
auto adjust = [&] (ld& val, ld& guide, ld lerpval) {
if(val > hp)
val = lerp(guide, hp, lerpval);
else if(val < hn)
val = lerp(guide, hn, lerpval);
};
adjust(HIGH, FLOOR, 0.8);
adjust(HIGH2, HIGH, 0.5);
adjust(SKY, FLOOR, 1);
adjust(STAR, FLOOR, 0.9);
adjust(LAKE, FLOOR, 0.8);
adjust(SHALLOW, LAKE, 0.9);
adjust(BOTTOM, SHALLOW, 0.5);
adjust(INFDEEP, FLOOR, 1);
}
if(cgi.emb->is_euc_in_hyp() && sgn < 0) INFDEEP = FLOOR - 5;
println(hlog, "WALL = ", WALL, " LOWSKY = ", LOWSKY, " SKY = ", SKY, " STAR = ", STAR, " INFDEEP = ", INFDEEP, " wh = ", wh);
}
}
@ -1269,6 +1275,15 @@ EX string cgi_string() {
V("LB", fts(vid.lake_bottom));
if(GDIM == 3 && vid.pseudohedral)
V("PS", fts(vid.depth_bonus));
V("LS", fts(vid.lake_shallow));
V("SSu", fts(vid.sun_size));
V("SSt", fts(vid.star_size));
V("WH2", fts(vid.wall_height2));
V("WH3", fts(vid.wall_height3));
V("WHL", fts(vid.lowsky_height));
if(vid.sky_height != use_the_default_value) V("SHe", fts(vid.sky_height));
if(vid.star_height != use_the_default_value) V("StH", fts(vid.star_height));
if(vid.infdeep_height != use_the_default_value) V("ID", fts(vid.infdeep_height));
}
V("3D", ONOFF(vid.always3));

View File

@ -313,6 +313,8 @@ struct projection_configuration {
enum eThreatLevel { tlNoThreat, tlSpam, tlNormal, tlHighThreat };
constexpr ld use_the_default_value = -20.0625;
struct videopar {
projection_configuration projection_config, rug_config;
ld yshift;
@ -416,7 +418,9 @@ struct videopar {
ld depth; // world level below the plane
ld camera; // camera level above the plane
ld wall_height, creature_scale, height_width;
ld lake_top, lake_bottom;
ld lake_top, lake_bottom, lake_shallow, wall_height2, wall_height3;
ld lowsky_height, sky_height, star_height, infdeep_height, star_size, sun_size;
bool height_limits;
ld rock_wall_ratio;
ld human_wall_ratio;
bool pseudohedral; // in 3D modes

107
sky.cpp
View File

@ -5,10 +5,18 @@ namespace hr {
EX bool context_fog = true;
EX ld camera_level;
EX bool draw_sky = true;
EX bool camera_sign;
#if HDR
enum eSkyMode { skyNone, skyAutomatic, skySkybox, skyAlways };
#endif
EX eSkyMode draw_sky;
EX bool auto_remove_roofs;
EX bool camera_over(ld x) {
if(!auto_remove_roofs) return false;
if(camera_sign) return camera_level <= x;
return camera_level >= x;
}
@ -41,16 +49,22 @@ struct dqi_sky : drawqueueitem {
EX struct dqi_sky *sky;
EX bool do_draw_skybox() {
if(no_wall_rendering) return false;
if(!euclid) return false;
if(draw_sky == skySkybox) return true;
if(!embedded_plane) return false;
if(draw_sky == skyAutomatic) return !cgi.emb->is_sph_in_low() && !cgi.emb->is_cylinder();
return false;
}
EX void prepare_sky() {
sky = NULL;
if(euclid && !cgi.emb->is_sph_in_low() && !cgi.emb->is_cylinder()) {
if(WDIM == 3 || GDIM == 2) return;
if(no_wall_rendering) return;
if(!draw_sky) return;
if(do_draw_skybox()) {
shiftmatrix T = ggmatrix(currentmap->gamestart());
T.T = gpushxto0(tC0(T.T)) * T.T;
queuepoly(T, cgi.shEuclideanSky, 0x0044e4FF);
queuepolyat(T * zpush(cgi.SKY+0.5) * xpush(cgi.SKY+0.5), cgi.shSun, 0xFFFF00FF, PPR::SKY);
queuepolyat(T * zpush(cgi.STAR * 0.7) * xpush(cgi.STAR * 0.7), cgi.shSkyboxSun, 0xFFFF00FF, PPR::SKY);
}
else {
sky = &queuea<dqi_sky> (euclid ? PPR::EUCLIDEAN_SKY : PPR::MISSILE);
@ -66,17 +80,35 @@ EX void delete_sky() {
skyvertices.clear();
}
EX bool do_draw_sky() {
if(!embedded_plane) return false;
if(draw_sky == skyAlways) return true;
if(draw_sky != skyAutomatic) return false;
if(vid.wall_height < 0 && cgi.emb->is_euc_in_hyp()) return false; /* just looks bad, hollow horospheres should not have sky */
if(vid.wall_height < 0 && meuclid && geom3::ggclass() == gcNIH) return false; /* same */
if(among(geom3::ggclass(), gcSol, gcSolN)) return false; /* errors */
if(among(geom3::ggclass(), gcNil)) return false; /* errors sometimes too */
if(cgi.emb->is_hyp_in_solnih()) return false;
if(cgi.emb->is_euc_in_product()) return false;
if(cgi.emb->is_euc_in_sl2()) return false;
if(cgi.emb->is_cylinder()) return false;
return true;
}
EX bool do_draw_stars(bool rev) {
if(!do_draw_sky()) return false;
if(cgi.emb->is_sph_in_low()) {
if(cgi.SKY < 0) return false;
}
if(cgi.emb->is_euc_in_hyp() && (rev ? cgi.SKY > 0 : cgi.SKY < 0)) return false;
return true;
}
void compute_skyvertices(const vector<sky_item>& sky) {
skyvertices.clear();
if(!draw_sky) return;
if(vid.wall_height < 0 && cgi.emb->is_euc_in_hyp()) return; /* just looks bad, hollow horospheres should not have sky */
if(vid.wall_height < 0 && meuclid && geom3::ggclass() == gcNIH) return; /* same */
if(among(geom3::ggclass(), gcSol, gcSolN)) return; /* errors */
if(among(geom3::ggclass(), gcNil)) return; /* errors sometimes too */
if(cgi.emb->is_hyp_in_solnih()) return;
if(cgi.emb->is_euc_in_product()) return;
if(cgi.emb->is_euc_in_sl2()) return;
if(cgi.emb->is_cylinder()) return;
if(!do_draw_sky()) return;
int sk = get_skybrightness();
@ -87,10 +119,10 @@ void compute_skyvertices(const vector<sky_item>& sky) {
);
hyperpoint skypoint = cpush0(2, cgi.SKY);
hyperpoint hellpoint = cpush0(2, -cgi.SKY);
hyperpoint hellpoint = cpush0(2, cgi.HELL);
vector<glhr::colored_vertex> this_poly;
for(const sky_item& si: sky) {
auto c = si.c;
@ -271,7 +303,7 @@ void compute_skyvertices(const vector<sky_item>& sky) {
void dqi_sky::draw() {
if(!vid.usingGL || sky.empty() || skyvertices.empty()) return;
if(!draw_sky) { delete_sky(); return; }
if(!do_draw_sky()) { delete_sky(); return; }
#if CAP_VR
transmatrix s = (vrhr::rendering() ? vrhr::master_cview : cview()).T * inverse(sky_cview.T);
@ -279,7 +311,8 @@ void dqi_sky::draw() {
transmatrix s = cview().T * inverse(sky_cview.T);
#endif
if(euclid) be_euclidean_infinity(s);
be_euclidean_infinity(s);
for(int ed = current_display->stereo_active() ? -1 : 0; ed<2; ed+=2) {
if(global_projection && global_projection != ed) continue;
current_display->next_shader_flags = GF_VARCOLOR;
@ -292,7 +325,7 @@ void dqi_sky::draw() {
glapplymatrix(s);
}
glhr::prepare(skyvertices);
glhr::set_fogbase(1.0 + 5 / sightranges[geometry]);
glhr::set_fogbase(1.0 + abs(cgi.SKY - cgi.LOWSKY) / sightranges[geometry]);
glhr::set_depthtest(model_needs_depth() && prio < PPR::SUPERLINE);
glhr::set_depthwrite(model_needs_depth() && prio != PPR::TRANSPARENT_SHADOW && prio != PPR::EUCLIDEAN_SKY);
glDrawArrays(GL_TRIANGLES, 0, isize(skyvertices));
@ -306,28 +339,22 @@ color_t skycolor(cell *c) {
return gradient(0x4040FF, 0xFFFFFF, 0, z, 63);
}
EX bool use_euclidean_infinity = true;
/** move an Euclidean matrix to V(C0) == C0 */
EX void be_euclidean_infinity(transmatrix& V) { for(int i=0; i<3; i++) V[i][3] = 0; }
EX void be_euclidean_infinity(transmatrix& V) {
if(euclid && msphere && use_euclidean_infinity)
for(int i=0; i<3; i++) V[i][3] = 0;
}
void draw_star(const shiftmatrix& V, const hpcshape& sh, color_t col, ld rev = false) {
ld star_val = 2;
bool have_stars = cgi.emb->is_same_in_same() || cgi.emb->is_sph_in_low() || cgi.emb->is_euc_in_hyp();
if(cgi.emb->is_sph_in_low()) {
if(cgi.SKY < 0) have_stars = false;
if(euclid) star_val = 1.8;
}
if(cgi.emb->is_euc_in_hyp() && (rev ? cgi.SKY > 0 : cgi.SKY < 0)) have_stars = false;
if(!have_stars) return;
ld val = cgi.SKY+star_val;
if(!do_draw_stars(rev)) return;
ld val = cgi.STAR;
if(rev) val = -val;
if(euclid) {
auto V1 = V; be_euclidean_infinity(V1.T);
queuepolyat(V1 * zpush(val), sh, col, PPR::EUCLIDEAN_SKY);
}
else {
queuepolyat(V * zpush(val), sh, col, PPR::SKY);
}
auto V1 = V; be_euclidean_infinity(V1.T);
queuepolyat(V1 * zpush(val), sh, col, PPR::SKY);
}
void celldrawer::draw_ceiling() {
@ -341,7 +368,6 @@ void celldrawer::draw_ceiling() {
switch(ceiling_category(c)) {
/* ceilingless levels */
case 1: {
if(euclid && !cgi.emb->is_sph_in_low()) return;
if(fieldpattern::fieldval_uniq(c) % 3 == 0)
draw_star(V, cgi.shNightStar, 0xFFFFFFFF);
add_to_sky(0x00000F, 0x00000F);
@ -356,7 +382,6 @@ void celldrawer::draw_ceiling() {
}
case 2: {
if(euclid && !cgi.emb->is_sph_in_low()) return;
color_t col;
color_t skycol;
@ -464,7 +489,6 @@ void celldrawer::draw_ceiling() {
placeSidewall(c, i, SIDE_HIGH2, V, darkena(wcol2, fd, 0xFF));
}
if(among(c->wall, waClosedGate, waOpenGate) && qfi.fshape) draw_shapevec(c, V, qfi.fshape->levels[SIDE_WALL], 0x202020FF, PPR::WALL);
if(euclid) return;
draw_star(V, cgi.shNightStar, 0xFFFFFFFF);
break;
@ -517,7 +541,6 @@ void celldrawer::draw_ceiling() {
else if(qfi.fshape)
draw_shapevec(c, V, qfi.fshape->levels[SIDE_WALL], darkena(fcol, fd, 0xFF), PPR::WALL);
if(euclid) return;
draw_star(V, cgi.shNightStar, 0xFFFFFFFF);
break;
}
@ -539,6 +562,7 @@ EX void swap_if_missing(bool missing) {
EX void make_air() {
if(!sky) return;
if(!embedded_plane) return;
if(centerover != sky_centerover) {
sky_centerover = centerover;
@ -547,6 +571,7 @@ EX void make_air() {
}
if(!context_fog) return;
if(vrhr::rendering()) return;
const int AIR_TEXTURE = 512;
if(!airbuf) {