1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-24 05:17:17 +00:00

improved spherical display of low-face polyhedra

This commit is contained in:
Zeno Rogue 2018-08-21 02:38:50 +02:00
parent e6bdba1441
commit 0fd9cc46f2
2 changed files with 72 additions and 15 deletions

View File

@ -1673,7 +1673,7 @@ geometryinfo ginf[gGUARD] = {
{"four hexagons", "4x6", 6, 4, 0, gcHyperbolic, 0x08400, {{5, 3}}}, {"four hexagons", "4x6", 6, 4, 0, gcHyperbolic, 0x08400, {{5, 3}}},
{"four heptagons", "4x7", 7, 4, 0, gcHyperbolic, 0x08600, {{4, 3}}}, {"four heptagons", "4x7", 7, 4, 0, gcHyperbolic, 0x08600, {{4, 3}}},
{"cube", "3x4", 4, 3, 0, gcSphere, 0x10000, {{SEE_ALL, SEE_ALL}}}, {"cube", "3x4", 4, 3, 0, gcSphere, 0x10000, {{SEE_ALL, SEE_ALL}}},
{"tetrahedron (buggy)", "3x3", 3, 3, 0, gcSphere, 0x10200, {{SEE_ALL, SEE_ALL}}}, {"tetrahedron", "3x3", 3, 3, 0, gcSphere, 0x10200, {{SEE_ALL, SEE_ALL}}},
{"square grid", "4x4", 4, 4, 0, gcEuclid, 0x10400, {{7, 7}}}, {"square grid", "4x4", 4, 4, 0, gcEuclid, 0x10400, {{7, 7}}},
{"cube/elliptic", "e3x4", 4, 3, qNONOR, gcSphere, 0x10600, {{SEE_ALL, SEE_ALL}}}, {"cube/elliptic", "e3x4", 4, 3, qNONOR, gcSphere, 0x10600, {{SEE_ALL, SEE_ALL}}},
{"Klein Quartic", "Klein", 7, 3, qSMALL, gcHyperbolic, 0x18000, {{7, 5}}}, {"Klein Quartic", "Klein", 7, 3, qSMALL, gcHyperbolic, 0x18000, {{7, 5}}},

View File

@ -188,34 +188,66 @@ bool nif_error_in(ld x1, ld y1, ld x2, ld y2) {
return pow(x1 * x2 + y2 * y2, 2) < (x1*x1+y1*y1)*(x2*x2+y2*y2)*.5; return pow(x1 * x2 + y2 * y2, 2) < (x1*x1+y1*y1)*(x2*x2+y2*y2)*.5;
} }
bool knowgood;
hyperpoint goodpoint;
vector<pair<int, hyperpoint>> tofix;
bool correct_side(const hyperpoint& H) {
double curnorm = H[0]*H[0]+H[1]*H[1]+H[2]*H[2];
double horizon = curnorm / vid.alpha;
return (spherespecial>0) ^ (H[2] <= -horizon);
}
void fixpoint(array<float, 3>& hscr, hyperpoint H) {
hyperpoint bad = H, good = goodpoint;
for(int i=0; i<10; i++) {
hyperpoint mid = midz(bad, good);
if(correct_side(mid))
good = mid;
else
bad = mid;
}
hyperpoint Hscr;
applymodel(good, Hscr);
hscr = make_array<GLfloat>(Hscr[0]*vid.radius, Hscr[1]*vid.radius*vid.stretch, Hscr[2]*vid.radius);
}
void addpoint(const hyperpoint& H) { void addpoint(const hyperpoint& H) {
if(true) { if(true) {
hyperpoint Hscr; ld z = vid.radius;
applymodel(H, Hscr);
for(int i=0; i<3; i++) Hscr[i] *= vid.radius;
Hscr[1] *= vid.stretch;
// if(vid.alpha + H[2] <= BEHIND_LIMIT && pmodel == mdDisk) poly_flags |= POLY_BEHIND; // if(vid.alpha + H[2] <= BEHIND_LIMIT && pmodel == mdDisk) poly_flags |= POLY_BEHIND;
if(spherespecial) { if(spherespecial) {
if(correct_side(H)) {
poly_flags |= POLY_INFRONT, last_infront = false;
if(!knowgood || (spherespecial > 0 ? H[2]>goodpoint[2] : H[2]<goodpoint[2])) goodpoint = H, knowgood = true;
}
else if(poly_flags & POLY_ISSIDE) {
double curnorm = H[0]*H[0]+H[1]*H[1]+H[2]*H[2]; double curnorm = H[0]*H[0]+H[1]*H[1]+H[2]*H[2];
double horizon = curnorm / vid.alpha; double horizon = curnorm / vid.alpha;
if((spherespecial>0) ^ (H[2] <= -horizon)) poly_flags |= POLY_INFRONT, last_infront = false;
else {
poly_flags |= POLY_NOTINFRONT; poly_flags |= POLY_NOTINFRONT;
if(last_infront && nif_error_in(glcoords.back()[0], glcoords.back()[1], Hscr[0], Hscr[1])) if(last_infront && nif_error_in(glcoords.back()[0], glcoords.back()[1], H[0], H[1]))
poly_flags |= POLY_NIF_ERROR; poly_flags |= POLY_NIF_ERROR;
last_infront = true; last_infront = true;
double coef = z *=
(sqrt(curnorm - horizon*horizon) / (vid.alpha - horizon)) / (sqrt(curnorm - horizon*horizon) / (vid.alpha - horizon)) /
(sqrt(curnorm - H[2]*H[2]) / (vid.alpha+H[2])); (sqrt(curnorm - H[2]*H[2]) / (vid.alpha+H[2]));
}
// double coef = (vid.alpha + horizon) / (vid.alpha + H[2]); -< that one has a funny effect, seriously else {
Hscr[0] *= coef; poly_flags |= POLY_NOTINFRONT;
Hscr[1] *= coef; tofix.push_back(make_pair(glcoords.size(), H));
add1(H);
return;
} }
} }
hyperpoint Hscr;
applymodel(H, Hscr);
for(int i=0; i<3; i++) Hscr[i] *= z;
Hscr[1] *= vid.stretch;
add1(Hscr); add1(Hscr);
} }
} }
@ -233,6 +265,7 @@ void coords_to_poly() {
} }
void addpoly(const transmatrix& V, const vector<glvertex> &tab, int ofs, int cnt) { void addpoly(const transmatrix& V, const vector<glvertex> &tab, int ofs, int cnt) {
tofix.clear(); knowgood = false;
hyperpoint last = V * glhr::gltopoint(tab[ofs]); hyperpoint last = V * glhr::gltopoint(tab[ofs]);
bool last_behind = is_behind(last); bool last_behind = is_behind(last);
if(!last_behind) addpoint(last); if(!last_behind) addpoint(last);
@ -256,6 +289,30 @@ void addpoly(const transmatrix& V, const vector<glvertex> &tab, int ofs, int cnt
if(firstleave[0] * enter[0] + firstleave[1] * enter[1] < 0) poly_flags |= POLY_BEHIND; if(firstleave[0] * enter[0] + firstleave[1] * enter[1] < 0) poly_flags |= POLY_BEHIND;
else addpoint(firstleave); else addpoint(firstleave);
} }
if(knowgood && isize(tofix)) {
if(true) {
hyperpoint Hx = V * C0, Hy = goodpoint;
for(int i=0; i<20; i++) {
hyperpoint mid = midz(Hx, Hy);
if(correct_side(mid)) Hy = mid;
else Hx = mid;
}
using namespace hyperpoint_vec;
goodpoint = midz(Hy, goodpoint);
}
for(auto& p: tofix)
fixpoint(glcoords[p.first], p.second);
/*
hyperpoint Hscr;
applymodel(goodpoint, Hscr);
glcoords.push_back(make_array<GLfloat>(Hscr[0]*vid.radius+10, Hscr[1]*vid.radius*vid.stretch, Hscr[2]*vid.radius));
glcoords.push_back(make_array<GLfloat>(Hscr[0]*vid.radius, Hscr[1]*vid.radius*vid.stretch+10, Hscr[2]*vid.radius));
glcoords.push_back(make_array<GLfloat>(Hscr[0]*vid.radius-10, Hscr[1]*vid.radius*vid.stretch, Hscr[2]*vid.radius));
glcoords.push_back(make_array<GLfloat>(Hscr[0]*vid.radius, Hscr[1]*vid.radius*vid.stretch-10, Hscr[2]*vid.radius));
glcoords.push_back(make_array<GLfloat>(Hscr[0]*vid.radius+10, Hscr[1]*vid.radius*vid.stretch, Hscr[2]*vid.radius)); */
}
} }
#if CAP_SDLGFX #if CAP_SDLGFX