mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-03-27 22:07:03 +00:00
3D effects in the new models. Also made the 3D effects in old models 'correct'
This commit is contained in:
parent
7c84280b73
commit
fa7822fdf8
@ -548,16 +548,9 @@ namespace conformal {
|
||||
}
|
||||
|
||||
bool model_available(eModel pm) {
|
||||
if(mdAzimuthalEqui() || pm == mdDisk || pm == mdPolynomial || pm == mdHyperboloid || pm == mdHemisphere ||
|
||||
pm == mdBandEquidistant || pm == mdBandEquiarea || pm == mdSinusoidal || pm == mdTwoPoint)
|
||||
return true;
|
||||
if(sphere && pm == mdBand)
|
||||
return true;
|
||||
if(euclid && (pm == mdHalfplane || pm == mdBall))
|
||||
return true;
|
||||
if(hyperbolic)
|
||||
return true;
|
||||
return false;
|
||||
if(sphere && (pm == mdHalfplane || pm == mdBall))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void model_menu() {
|
||||
|
@ -39,6 +39,42 @@ ld squar(ld x) { return x*x; }
|
||||
|
||||
int sig(int z) { return (sphere || z<2)?1:-1; }
|
||||
|
||||
int curvature() {
|
||||
switch(cgclass) {
|
||||
case gcEuclid: return 0;
|
||||
case gcHyperbolic: return -1;
|
||||
case gcSphere: return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ld sin_auto(ld x) {
|
||||
switch(cgclass) {
|
||||
case gcEuclid: return x;
|
||||
case gcHyperbolic: return sinh(x);
|
||||
case gcSphere: return sin(x);
|
||||
default: return x;
|
||||
}
|
||||
}
|
||||
|
||||
ld asin_auto(ld x) {
|
||||
switch(cgclass) {
|
||||
case gcEuclid: return x;
|
||||
case gcHyperbolic: return asinh(x);
|
||||
case gcSphere: return asin(x);
|
||||
default: return x;
|
||||
}
|
||||
}
|
||||
|
||||
ld cos_auto(ld x) {
|
||||
switch(cgclass) {
|
||||
case gcEuclid: return 1;
|
||||
case gcHyperbolic: return cosh(x);
|
||||
case gcSphere: return cos(x);
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// hyperbolic point:
|
||||
//===================
|
||||
|
||||
@ -120,6 +156,19 @@ char *display(const hyperpoint& H) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
ld hypot_auto(ld x, ld y) {
|
||||
switch(cgclass) {
|
||||
case gcEuclid:
|
||||
return hypot(x, y);
|
||||
case gcHyperbolic:
|
||||
return acosh(cosh(x) * cosh(y));
|
||||
case gcSphere:
|
||||
return acos(cos(x) * cos(y));
|
||||
default:
|
||||
return hypot(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
// get the center of the line segment from H1 to H2
|
||||
hyperpoint mid(const hyperpoint& H1, const hyperpoint& H2) {
|
||||
|
||||
|
119
hypgraph.cpp
119
hypgraph.cpp
@ -98,6 +98,32 @@ void apply_depth(hyperpoint &f, ld z) {
|
||||
}
|
||||
}
|
||||
|
||||
bool hypot_zlev(bool zlev_used, ld& d, ld zlev, ld& df, ld& zf, ld &z) {
|
||||
if(!zlev_used) {
|
||||
df = 1; zf = 0;
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// (0,0,1) -> (0, sin z, cos z) -> (sin d cos z, sin z, cos d cos z)
|
||||
ld z = geom3::factor_to_lev(zlev);
|
||||
ld tz = sin_auto(z);
|
||||
ld td = sin_auto(abs(d)) * cos_auto(z);
|
||||
ld h = hypot(td, tz);
|
||||
if(d > 0)
|
||||
d = hypot_auto(d, z);
|
||||
else
|
||||
d = -hypot_auto(d, z);
|
||||
zf = tz / h, df = td / h;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool hypot_zlev(bool zlev_used, ld& d, ld zlev, ld& df, ld& zf) {
|
||||
ld z;
|
||||
return hypot_zlev(zlev_used, d, zlev, df, zf, z);
|
||||
}
|
||||
|
||||
|
||||
void applymodel(hyperpoint H, hyperpoint& ret) {
|
||||
|
||||
ld tz = euclid ? (1+vid.alpha) : vid.alpha+H[2];
|
||||
@ -197,47 +223,59 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
|
||||
}
|
||||
|
||||
ld zlev = 1;
|
||||
bool zlev_used = false;
|
||||
|
||||
if(wmspatial || mmspatial) {
|
||||
zlev = zlevel(H);
|
||||
using namespace hyperpoint_vec;
|
||||
H = H / zlev;
|
||||
zlev_used = !((zlev > 1-1e-6 && zlev < 1+1e-6));
|
||||
if(zlev_used) H /= zlev;
|
||||
}
|
||||
|
||||
if(pmodel == mdTwoPoint || mdBandAny() || pmodel == mdSinusoidal) {
|
||||
// map to plane
|
||||
if(pmodel == mdTwoPoint) {
|
||||
if(false) {
|
||||
auto p = vid.twopoint_param;
|
||||
ld dleft = hdist(H, xpush(-p) * C0);
|
||||
ld dright = hdist(H, xpush(p) * C0);
|
||||
ld yf = 1, zf = 0;
|
||||
if(zlev_used) {
|
||||
ld y_orig = asin_auto(H[1]);
|
||||
ld z;
|
||||
hypot_zlev(true, y_orig, zlev, yf, zf, z);
|
||||
dleft = hypot_auto(dleft, z);
|
||||
dright = hypot_auto(dright, z);
|
||||
}
|
||||
ld x = (dright*dright-dleft*dleft) / 4 / p;
|
||||
ld y = sqrt(dleft * dleft - (x-p)*(x-p) + 1e-9);
|
||||
x = -x;
|
||||
if(H[1] < 0) y = -y;
|
||||
ret = hpxyz(x/M_PI, y/M_PI, 0);
|
||||
ret = hpxyz(x/M_PI, y*(H[1]<0?-1:1)*yf/M_PI, 0);
|
||||
if(zlev_used && stereo::active())
|
||||
apply_depth(ret, y * zf / M_PI);
|
||||
}
|
||||
else {
|
||||
ld x, y;
|
||||
switch(cgclass) {
|
||||
case gcHyperbolic:
|
||||
y = asinh(H[1]), x = asinh(H[0] / cosh(y));
|
||||
break;
|
||||
case gcSphere:
|
||||
y = asin(H[1]), x = asin(H[0] / cos(y));
|
||||
if(H[2] < 0 && x > 0) x = M_PI - x;
|
||||
else if(H[2] < 0 && x <= 0) x = -M_PI - x;
|
||||
break;
|
||||
case gcEuclid:
|
||||
y = H[1], x = H[0];
|
||||
break;
|
||||
ld x, y, yf, zf;
|
||||
y = asin_auto(H[1]);
|
||||
x = asin_auto(H[0] / cos_auto(y));
|
||||
if(sphere) {
|
||||
if(H[2] < 0 && x > 0) x = M_PI - x;
|
||||
else if(H[2] < 0 && x <= 0) x = -M_PI - x;
|
||||
}
|
||||
if(pmodel == mdBand) switch(cgclass) {
|
||||
hypot_zlev(zlev_used, y, zlev, yf, zf);
|
||||
if(pmodel == mdTwoPoint) {
|
||||
auto p = vid.twopoint_param;
|
||||
ld dleft = hypot_auto(x-p, y);
|
||||
ld dright = hypot_auto(x+p, y);
|
||||
x = (dright*dright-dleft*dleft) / 4 / p;
|
||||
y = (y>0?1:-1) * sqrt(dleft * dleft - (x-p)*(x-p) + 1e-9);
|
||||
}
|
||||
else if(pmodel == mdBand) switch(cgclass) {
|
||||
case gcSphere:
|
||||
y = atanh(sin(y) * zlev);
|
||||
y = atanh(sin(y));
|
||||
x *= 2; y *= 2;
|
||||
break;
|
||||
case gcHyperbolic:
|
||||
y = 2 * atan(tanh(y/2) * zlev);
|
||||
y = 2 * atan(tanh(y/2));
|
||||
x *= 2; y *= 2;
|
||||
break;
|
||||
case gcEuclid:
|
||||
@ -245,31 +283,14 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
|
||||
y *= 2; x *= 2;
|
||||
break;
|
||||
}
|
||||
if(pmodel == mdBandEquiarea) switch(cgclass) {
|
||||
case gcHyperbolic:
|
||||
y = sinh(y);
|
||||
break;
|
||||
case gcSphere:
|
||||
y = sin(y);
|
||||
break;
|
||||
default:
|
||||
y = y;
|
||||
break;
|
||||
}
|
||||
if(pmodel == mdSinusoidal) switch(cgclass) {
|
||||
case gcHyperbolic:
|
||||
x *= cosh(y);
|
||||
break;
|
||||
case gcSphere:
|
||||
x *= cos(y);
|
||||
break;
|
||||
default:
|
||||
x *= 1;
|
||||
break;
|
||||
}
|
||||
ret = hpxyz(x / M_PI, y / M_PI, 0);
|
||||
else if(pmodel == mdBandEquiarea)
|
||||
y = sin_auto(y);
|
||||
else if(pmodel == mdSinusoidal)
|
||||
x *= cos_auto(y);
|
||||
ret = hpxyz(x / M_PI, y * yf / M_PI, 0);
|
||||
if(zlev_used && stereo::active())
|
||||
apply_depth(ret, y * zf / M_PI);
|
||||
}
|
||||
apply_depth(ret, -geom3::factor_to_lev(zlev));
|
||||
ghcheck(ret, H);
|
||||
return;
|
||||
}
|
||||
@ -278,6 +299,8 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
|
||||
ld rad = sqrt(H[0] * H[0] + H[1] * H[1]);
|
||||
if(rad == 0) rad = 1;
|
||||
ld d = hdist0(H);
|
||||
ld yf, zf;
|
||||
hypot_zlev(zlev_used, d, zlev, yf, zf);
|
||||
|
||||
// 4 pi / 2pi = M_PI
|
||||
|
||||
@ -285,11 +308,11 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
|
||||
d = sqrt(2*(1 - cos(d))) * M_PI / 2;
|
||||
else if(pmodel == 6 && !euclid)
|
||||
d = sqrt(2*(cosh(d) - 1)) / 1.5;
|
||||
ret[0] = d * H[0] / rad / M_PI;
|
||||
ret[1] = d * H[1] / rad / M_PI;
|
||||
ret[0] = d * yf * H[0] / rad / M_PI;
|
||||
ret[1] = d * yf * H[1] / rad / M_PI;
|
||||
ret[2] = 0;
|
||||
if(zlev != 1 && stereo::active())
|
||||
apply_depth(ret, -geom3::factor_to_lev(zlev));
|
||||
if(zlev_used && stereo::active())
|
||||
apply_depth(ret, d * zf / M_PI);
|
||||
ghcheck(ret,H);
|
||||
|
||||
return;
|
||||
|
18
polygons.cpp
18
polygons.cpp
@ -589,12 +589,20 @@ void drawpolyline(polytodraw& p) {
|
||||
}
|
||||
|
||||
if(mdAzimuthalEqui() && (poly_flags & POLY_INVERSE)) {
|
||||
ld h = atan2(glcoords[0][0], glcoords[0][1]);
|
||||
for(int i=0; i<=360; i++) {
|
||||
ld a = i * M_PI / 180 + h;
|
||||
glcoords.push_back(make_array<GLfloat>(vid.radius * sin(a), vid.radius * cos(a), stereo::scrdist));
|
||||
if(abs(zlevel(pp.V * C0) - 1) < 1e-6) {
|
||||
// we should fill the other side
|
||||
ld h = atan2(glcoords[0][0], glcoords[0][1]);
|
||||
for(int i=0; i<=360; i++) {
|
||||
ld a = i * M_PI / 180 + h;
|
||||
glcoords.push_back(make_array<GLfloat>(vid.radius * sin(a), vid.radius * cos(a), stereo::scrdist));
|
||||
}
|
||||
poly_flags ^= POLY_INVERSE;
|
||||
}
|
||||
else {
|
||||
// If we are on a zlevel, the algorithm above will not work correctly.
|
||||
// It is hard to tell what to do in this case. Just fill neither side
|
||||
p.col = 0;
|
||||
}
|
||||
poly_flags ^= POLY_INVERSE;
|
||||
}
|
||||
|
||||
#if CAP_GL
|
||||
|
Loading…
x
Reference in New Issue
Block a user