mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-06-06 08:24:06 +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) {
|
bool model_available(eModel pm) {
|
||||||
if(mdAzimuthalEqui() || pm == mdDisk || pm == mdPolynomial || pm == mdHyperboloid || pm == mdHemisphere ||
|
if(sphere && (pm == mdHalfplane || pm == mdBall))
|
||||||
pm == mdBandEquidistant || pm == mdBandEquiarea || pm == mdSinusoidal || pm == mdTwoPoint)
|
return false;
|
||||||
return true;
|
return true;
|
||||||
if(sphere && pm == mdBand)
|
|
||||||
return true;
|
|
||||||
if(euclid && (pm == mdHalfplane || pm == mdBall))
|
|
||||||
return true;
|
|
||||||
if(hyperbolic)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_menu() {
|
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 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:
|
// hyperbolic point:
|
||||||
//===================
|
//===================
|
||||||
|
|
||||||
@ -120,6 +156,19 @@ char *display(const hyperpoint& H) {
|
|||||||
return buf;
|
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
|
// get the center of the line segment from H1 to H2
|
||||||
hyperpoint mid(const hyperpoint& H1, const hyperpoint& 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) {
|
void applymodel(hyperpoint H, hyperpoint& ret) {
|
||||||
|
|
||||||
ld tz = euclid ? (1+vid.alpha) : vid.alpha+H[2];
|
ld tz = euclid ? (1+vid.alpha) : vid.alpha+H[2];
|
||||||
@ -197,47 +223,59 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ld zlev = 1;
|
ld zlev = 1;
|
||||||
|
bool zlev_used = false;
|
||||||
|
|
||||||
if(wmspatial || mmspatial) {
|
if(wmspatial || mmspatial) {
|
||||||
zlev = zlevel(H);
|
zlev = zlevel(H);
|
||||||
using namespace hyperpoint_vec;
|
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) {
|
if(pmodel == mdTwoPoint || mdBandAny() || pmodel == mdSinusoidal) {
|
||||||
// map to plane
|
// map to plane
|
||||||
if(pmodel == mdTwoPoint) {
|
if(false) {
|
||||||
auto p = vid.twopoint_param;
|
auto p = vid.twopoint_param;
|
||||||
ld dleft = hdist(H, xpush(-p) * C0);
|
ld dleft = hdist(H, xpush(-p) * C0);
|
||||||
ld dright = 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 x = (dright*dright-dleft*dleft) / 4 / p;
|
||||||
ld y = sqrt(dleft * dleft - (x-p)*(x-p) + 1e-9);
|
ld y = sqrt(dleft * dleft - (x-p)*(x-p) + 1e-9);
|
||||||
x = -x;
|
x = -x;
|
||||||
if(H[1] < 0) y = -y;
|
ret = hpxyz(x/M_PI, y*(H[1]<0?-1:1)*yf/M_PI, 0);
|
||||||
ret = hpxyz(x/M_PI, y/M_PI, 0);
|
if(zlev_used && stereo::active())
|
||||||
|
apply_depth(ret, y * zf / M_PI);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ld x, y;
|
ld x, y, yf, zf;
|
||||||
switch(cgclass) {
|
y = asin_auto(H[1]);
|
||||||
case gcHyperbolic:
|
x = asin_auto(H[0] / cos_auto(y));
|
||||||
y = asinh(H[1]), x = asinh(H[0] / cosh(y));
|
if(sphere) {
|
||||||
break;
|
if(H[2] < 0 && x > 0) x = M_PI - x;
|
||||||
case gcSphere:
|
else if(H[2] < 0 && x <= 0) x = -M_PI - x;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
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:
|
case gcSphere:
|
||||||
y = atanh(sin(y) * zlev);
|
y = atanh(sin(y));
|
||||||
x *= 2; y *= 2;
|
x *= 2; y *= 2;
|
||||||
break;
|
break;
|
||||||
case gcHyperbolic:
|
case gcHyperbolic:
|
||||||
y = 2 * atan(tanh(y/2) * zlev);
|
y = 2 * atan(tanh(y/2));
|
||||||
x *= 2; y *= 2;
|
x *= 2; y *= 2;
|
||||||
break;
|
break;
|
||||||
case gcEuclid:
|
case gcEuclid:
|
||||||
@ -245,31 +283,14 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
|
|||||||
y *= 2; x *= 2;
|
y *= 2; x *= 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(pmodel == mdBandEquiarea) switch(cgclass) {
|
else if(pmodel == mdBandEquiarea)
|
||||||
case gcHyperbolic:
|
y = sin_auto(y);
|
||||||
y = sinh(y);
|
else if(pmodel == mdSinusoidal)
|
||||||
break;
|
x *= cos_auto(y);
|
||||||
case gcSphere:
|
ret = hpxyz(x / M_PI, y * yf / M_PI, 0);
|
||||||
y = sin(y);
|
if(zlev_used && stereo::active())
|
||||||
break;
|
apply_depth(ret, y * zf / M_PI);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
apply_depth(ret, -geom3::factor_to_lev(zlev));
|
|
||||||
ghcheck(ret, H);
|
ghcheck(ret, H);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -278,6 +299,8 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
|
|||||||
ld rad = sqrt(H[0] * H[0] + H[1] * H[1]);
|
ld rad = sqrt(H[0] * H[0] + H[1] * H[1]);
|
||||||
if(rad == 0) rad = 1;
|
if(rad == 0) rad = 1;
|
||||||
ld d = hdist0(H);
|
ld d = hdist0(H);
|
||||||
|
ld yf, zf;
|
||||||
|
hypot_zlev(zlev_used, d, zlev, yf, zf);
|
||||||
|
|
||||||
// 4 pi / 2pi = M_PI
|
// 4 pi / 2pi = M_PI
|
||||||
|
|
||||||
@ -285,11 +308,11 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
|
|||||||
d = sqrt(2*(1 - cos(d))) * M_PI / 2;
|
d = sqrt(2*(1 - cos(d))) * M_PI / 2;
|
||||||
else if(pmodel == 6 && !euclid)
|
else if(pmodel == 6 && !euclid)
|
||||||
d = sqrt(2*(cosh(d) - 1)) / 1.5;
|
d = sqrt(2*(cosh(d) - 1)) / 1.5;
|
||||||
ret[0] = d * H[0] / rad / M_PI;
|
ret[0] = d * yf * H[0] / rad / M_PI;
|
||||||
ret[1] = d * H[1] / rad / M_PI;
|
ret[1] = d * yf * H[1] / rad / M_PI;
|
||||||
ret[2] = 0;
|
ret[2] = 0;
|
||||||
if(zlev != 1 && stereo::active())
|
if(zlev_used && stereo::active())
|
||||||
apply_depth(ret, -geom3::factor_to_lev(zlev));
|
apply_depth(ret, d * zf / M_PI);
|
||||||
ghcheck(ret,H);
|
ghcheck(ret,H);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
18
polygons.cpp
18
polygons.cpp
@ -589,12 +589,20 @@ void drawpolyline(polytodraw& p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(mdAzimuthalEqui() && (poly_flags & POLY_INVERSE)) {
|
if(mdAzimuthalEqui() && (poly_flags & POLY_INVERSE)) {
|
||||||
ld h = atan2(glcoords[0][0], glcoords[0][1]);
|
if(abs(zlevel(pp.V * C0) - 1) < 1e-6) {
|
||||||
for(int i=0; i<=360; i++) {
|
// we should fill the other side
|
||||||
ld a = i * M_PI / 180 + h;
|
ld h = atan2(glcoords[0][0], glcoords[0][1]);
|
||||||
glcoords.push_back(make_array<GLfloat>(vid.radius * sin(a), vid.radius * cos(a), stereo::scrdist));
|
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
|
#if CAP_GL
|
||||||
|
Loading…
x
Reference in New Issue
Block a user