// Hyperbolic Rogue // geometrical constants // Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details namespace hr { // the results are: // hexf = 0.378077 hcrossf = 0.620672 tessf = 1.090550 // hexhexdist = 0.566256 ld hcrossf7 = 0.620672; ld hexf7 = 0.378077; // the distance between two hexagon centers void geometry_information::prepare_basics() { DEBBI(DF_INIT | DF_POLY | DF_GEOM, ("prepare_basics")); hexshift = 0; ld fmin, fmax; if(archimedean) ginf[gArchimedean].cclass = gcHyperbolic; if(euclid) { // dynamicval g(geometry, gNormal); // for(int i=0; i= 4 if(binarytiling && WDIM == 3) binary::build_tmatrix(); #endif scalefactor = crossf / hcrossf7; orbsize = crossf; if(WDIM == 3) scalefactor *= geom3::creature_scale; zhexf = BITRUNCATED ? hexf : crossf* .55; if(WDIM == 3) zhexf *= geom3::creature_scale; if(WDIM == 2 && GDIM == 3) zhexf *= 1.5, orbsize *= 1.2; floorrad0 = hexvdist* (GDIM == 3 ? 1 : 0.92); floorrad1 = rhexf * (GDIM == 3 ? 1 : 0.94); if(euclid4) { if(!BITRUNCATED) floorrad0 = floorrad1 = rhexf * (GDIM == 3 ? 1 : .94); else floorrad0 = hexvdist * (GDIM == 3 ? 1 : .9), floorrad1 = rhexf * (GDIM == 3 ? 1 : .8); } set_sibling_limit(); prepare_compute3(); if(hyperbolic && &currfp != &fieldpattern::fp_invalid) currfp.analyze(); } transmatrix xspinpush(ld dir, ld dist) { if(euclid) return eupush(cos(dir) * dist, -sin(dir) * dist); else return spin(dir) * xpush(dist) * spin(-dir); } purehookset hooks_swapdim; namespace geom3 { bool always3 = false; int tc_alpha=3, tc_depth=1, tc_camera=2; ld depth = 1; // world below the plane ld camera = 1; // camera above the plane ld wall_height = .3; ld lake_top = .25, lake_bottom = .9; ld rock_wall_ratio = .9; ld human_wall_ratio = .7; bool gp_autoscale_heights = true; ld creature_scale, height_width; ld highdetail = 8, middetail = 8; // Here we convert between the following parameters: // abslev: level below the plane // lev: level above the world (abslev = depth-lev) // projection: projection parameter // factor: zoom factor ld abslev_to_projection(ld abslev) { if(sphere || euclid) return camera+abslev; return tanh(abslev) / tanh(camera); } ld projection_to_abslev(ld proj) { if(sphere || euclid) return proj-camera; // tanh(abslev) / tanh(camera) = proj return atanh(proj * tanh(camera)); } ld lev_to_projection(ld lev) { return abslev_to_projection(depth - lev); } ld projection_to_factor(ld proj) { return lev_to_projection(0) / proj; } ld factor_to_projection(ld fac) { return lev_to_projection(0) / fac; } ld lev_to_factor(ld lev) { if(WDIM == 3) return lev; if(GDIM == 3) return depth - lev; return projection_to_factor(lev_to_projection(lev)); } ld factor_to_lev(ld fac) { if(DIM == 3) return fac; return depth - projection_to_abslev(factor_to_projection(fac)); } // how should we scale at level lev ld scale_at_lev(ld lev) { if(sphere || euclid) return 1; return cosh(depth - lev); } string invalid; ld actual_wall_height() { #if CAP_GP if(GOLDBERG && gp_autoscale_heights) return wall_height * min(4 / hypot_d(2, gp::next), 1); #endif return wall_height; } } void geometry_information::prepare_compute3() { using namespace geom3; DEBBI(DF_INIT | DF_POLY | DF_GEOM, ("geom3::compute")); // tanh(depth) / tanh(camera) == vid.alpha invalid = ""; if(GDIM == 3) ; else if(tc_alpha < tc_depth && tc_alpha < tc_camera) vid.alpha = tan_auto(depth) / tan_auto(camera); else if(tc_depth < tc_alpha && tc_depth < tc_camera) { ld v = vid.alpha * tan_auto(camera); if(hyperbolic && (v<1e-6-12 || v>1-1e-12)) invalid = "cannot adjust depth", depth = camera; else depth = atan_auto(v); } else { ld v = tan_auto(depth) / vid.alpha; if(hyperbolic && (v<1e-12-1 || v>1-1e-12)) invalid = "cannot adjust camera", camera = depth; else camera = atan_auto(v); } if(fabs(vid.alpha) < 1e-6) invalid = "does not work with perfect Klein"; if(invalid != "") { INFDEEP = .7; BOTTOM = .8; HELLSPIKE = .85; LAKE = .9; FLOOR = 1; WALL = 1.25; SLEV[0] = 1; SLEV[1] = 1.08; SLEV[2] = 1.16; SLEV[3] = 1.24; FLATEYE = 1.03; LEG1 = 1.025; LEG = 1.05; LEG3 = 1.075; GROIN = 1.09; GROIN1 = 1.105; GHOST = 1.1; BODY = 1.15; BODY1 = 1.151; BODY2 = 1.152; BODY3 = 1.153; NECK1 = 1.16; NECK = 1.17; NECK3 = 1.18; HEAD = 1.188; HEAD1= 1.189; HEAD2= 1.190; HEAD3= 1.191; ABODY = 1.08; AHEAD = 1.12; BIRD = 1.20; } else { INFDEEP = GDIM == 3 ? (sphere ? M_PI/2 : +5) : (euclid || sphere) ? 0.01 : lev_to_projection(0) * tanh(camera); ld wh = actual_wall_height(); WALL = lev_to_factor(wh); FLOOR = lev_to_factor(0); human_height = human_wall_ratio * wh; if(WDIM == 3) human_height = scalefactor * height_width / 2; ld reduce = (WDIM == 3 ? human_height / 2 : 0); LEG0 = lev_to_factor(human_height * .0 - reduce); LEG1 = lev_to_factor(human_height * .1 - reduce); LEG = lev_to_factor(human_height * .2 - reduce); LEG3 = lev_to_factor(human_height * .3 - reduce); GROIN = lev_to_factor(human_height * .4 - reduce); GROIN1= lev_to_factor(human_height * .5 - reduce); BODY = lev_to_factor(human_height * .6 - reduce); BODY1 = lev_to_factor(human_height * .61 - reduce); BODY2 = lev_to_factor(human_height * .62 - reduce); BODY3 = lev_to_factor(human_height * .63 - reduce); NECK1 = lev_to_factor(human_height * .7 - reduce); NECK = lev_to_factor(human_height * .8 - reduce); NECK3 = lev_to_factor(human_height * .9 - reduce); HEAD = lev_to_factor(human_height * .97 - reduce); HEAD1 = lev_to_factor(human_height * .98 - reduce); HEAD2 = lev_to_factor(human_height * .99 - reduce); HEAD3 = lev_to_factor(human_height - reduce); reduce = (DIM == 3 ? human_height * .3 : 0); STUFF = lev_to_factor(0) - max(orbsize * 0.3, zhexf * .6); ABODY = lev_to_factor(human_height * .4 - reduce); ALEG0 = lev_to_factor(human_height * .0 - reduce); ALEG = lev_to_factor(human_height * .2 - reduce); AHEAD = lev_to_factor(human_height * .6 - reduce); BIRD = lev_to_factor(WDIM == 3 ? 0 : (human_wall_ratio+1)/2 * wh * .8); GHOST = lev_to_factor(WDIM == 3 ? 0 : human_height * .5); FLATEYE = lev_to_factor(human_height * .15); slev = rock_wall_ratio * wh / 3; for(int s=0; s<=3; s++) SLEV[s] = lev_to_factor(rock_wall_ratio * wh * s/3); LAKE = lev_to_factor(-lake_top); HELLSPIKE = lev_to_factor(-(lake_top+lake_bottom)/2); BOTTOM = lev_to_factor(-lake_bottom); LOWSKY = lev_to_factor((1 + rock_wall_ratio) * wh); HIGH = LOWSKY; HIGH2 = lev_to_factor((2 + rock_wall_ratio) * wh); SKY = LOWSKY - 5; } } namespace geom3 { #if MAXMDIM >= 4 void switch_always3() { if(rug::rugged) rug::close(); geom3::always3 = !geom3::always3; swapmatrix(View); callhooks(hooks_swapdim); } #endif void switch_tpp() { if(pmodel == mdDisk && vid.camera_angle) { vid.yshift = 0; vid.camera_angle = 0; vid.xposition = 0; vid.yposition = 0; vid.scale = 1; vid.fixed_facing = false; } else { vid.yshift = -0.3; vid.camera_angle = -45; vid.scale = 18/16. * vid.xres / vid.yres / multi::players; vid.xposition = 0; vid.yposition = -0.9; vid.fixed_facing = true; vid.fixed_facing_dir = 90; } } void switch_fpp() { #if MAXMDIM >= 4 if(rug::rugged) rug::close(); if(!geom3::always3) { geom3::always3 = true; geom3::wall_height = 1.5; if(sphere) { geom3::depth = M_PI / 6; geom3::wall_height = M_PI / 3; } geom3::human_wall_ratio = 0.8; geom3::camera = 0; if(pmodel == mdDisk) pmodel = mdPerspective; swapmatrix(View); callhooks(hooks_swapdim); #if CAP_RACING racing::player_relative = true; #endif } else { geom3::always3 = false; geom3::wall_height = .3; geom3::human_wall_ratio = .7; geom3::camera = 1; geom3::depth = 1; if(pmodel == mdPerspective) pmodel = mdDisk; swapmatrix(View); callhooks(hooks_swapdim); } #endif } } geometry_information *cgip; map cgis; void check_cgi() { string s; auto V = [&] (string a, string b) { s += a; s += ": "; s += b; s += "; "; }; V("GEO", its(int(geometry))); V("VAR", its(int(variation))); if(GOLDBERG) V("GP", its(gp::param.first) + "," + its(gp::param.second)); if(IRREGULAR) V("IRR", its(irr::irrid)); if(geometry == gArchimedean) V("ARCM", arcm::current.symbol); if(geometry == gCrystal) V("CRYSTAL", its(ginf[gCrystal].sides) + its(ginf[gCrystal].vertex)); if(binarytiling || DIM == 3) V("WQ", its(vid.texture_step)); if(binarytiling) V("BT", fts(vid.binary_width)); if(GDIM == 2) { V("CAMERA", fts(geom3::camera)); } if(WDIM == 2) { V("WH", fts(geom3::wall_height)); V("HW", fts(geom3::human_wall_ratio)); V("RW", fts(geom3::rock_wall_ratio)); V("DEPTH", fts(geom3::depth)); V("ASH", ONOFF(geom3::gp_autoscale_heights)); V("LT", fts(geom3::lake_top)); V("LB", fts(geom3::lake_bottom)); } V("3D", ONOFF(geom3::always3)); if(WDIM == 3) { V("CS", fts(geom3::creature_scale)); V("HTW", fts(geom3::height_width)); } V("LQ", its(vid.linequality)); cgip = &cgis[s]; } }