3d:: native perspective is now pmodel == mdPerspective, and other models work too

This commit is contained in:
Zeno Rogue 2019-03-20 02:10:53 +01:00
parent 1d1baf2207
commit 46ae64e945
9 changed files with 77 additions and 39 deletions

View File

@ -220,29 +220,29 @@ void display_data::set_projection(int ed, bool apply_models) {
if(vid.consider_shader_projection) {
if(pmodel == mdDisk && !spherespecial && !(hyperbolic && vid.alpha <= -1) && DIM == 2)
shaderside_projection = true;
if(pmodel == mdBand && hyperbolic && apply_models)
if(pmodel == mdBand && hyperbolic && apply_models && DIM == 2)
shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::band;
if(pmodel == mdHalfplane && hyperbolic && apply_models)
if(pmodel == mdHalfplane && hyperbolic && apply_models && DIM == 2)
shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::halfplane;
if(DIM == 3 && hyperbolic && apply_models)
if(DIM == 3 && hyperbolic && apply_models && pmodel == mdPerspective)
shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::standardH3;
if(DIM == 3 && euclid && apply_models)
if(DIM == 3 && euclid && apply_models && pmodel == mdPerspective)
shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::standardR3;
if(DIM == 3 && sphere && apply_models) {
if(DIM == 3 && sphere && apply_models && pmodel == mdPerspective) {
shaderside_projection = true;
if(spherephase == 0) glhr::new_shader_projection = glhr::shader_projection::standardS30;
if(spherephase == 1) glhr::new_shader_projection = glhr::shader_projection::standardS31;
if(spherephase == 2) glhr::new_shader_projection = glhr::shader_projection::standardS32;
if(spherephase == 3) glhr::new_shader_projection = glhr::shader_projection::standardS33;
}
if(DIM == 3 && apply_models) dim3 = true;
if(DIM == 3 && apply_models && shaderside_projection) dim3 = true;
}
start_projection(ed, shaderside_projection);
auto cd = current_display;
if(!shaderside_projection && DIM != 3) {
if(!shaderside_projection) {
glhr::projection_multiply(glhr::ortho(cd->xsize/2, -cd->ysize/2, abs(current_display->scrdist) + 30000));
if(ed) {
glhr::glmatrix m = glhr::id;

View File

@ -1822,6 +1822,7 @@ const modelinfo models[int(mdPolynomial)+1] = {
{X3("Joukowsky+inversion"), mf::hyper_only | mf::conformal},
{X3("rotated hyperboles"), mf::hyper_only},
{X3("spiral"), mf::hyper_or_torus | mf::quasiband},
{X3("native perspective"), 0},
{X3(""), 0},
{X3(""), 0},
{X3(""), 0},

View File

@ -283,7 +283,7 @@ enum eModel {
mdEquidistant, mdEquiarea, mdBall, mdHyperboloid,
mdHemisphere, mdBandEquidistant, mdBandEquiarea, mdSinusoidal, mdTwoPoint,
mdFisheye, mdJoukowsky, mdJoukowskyInverted,
mdRotatedHyperboles, mdSpiral,
mdRotatedHyperboles, mdSpiral, mdPerspective,
mdGUARD, mdUnchanged, mdHyperboloidFlat, mdPolynomial
};

View File

@ -584,6 +584,8 @@ namespace conformal {
bool model_available(eModel pm) {
if(sphere && (pm == mdHalfplane || pm == mdBall))
return false;
if(DIM == 2 && pm == mdPerspective) return false;
if(DIM == 3 && among(pm, mdBall, mdHyperboloid, mdFormula, mdPolygonal, mdRotatedHyperboles, mdSpiral, mdHemisphere)) return false;
return true;
}
@ -673,7 +675,7 @@ namespace conformal {
eModel m = eModel(i);
if(m == mdFormula && ISMOBILE) continue;
if(model_available(m)) {
dialog::addBoolItem(get_model_name(m), pmodel == m, "0123456789!@#$%^&*()" [m]);
dialog::addBoolItem(get_model_name(m), pmodel == m, "0123456789!@#$%^&*()]" [m]);
dialog::add_action([m] () {
if(m == mdFormula) {
edit_formula();
@ -697,7 +699,8 @@ namespace conformal {
dialog::lastItem().value += " " + its(rotation) + "°";
// if(pmodel == mdBand && sphere)
dialog::addSelItem(XLAT("scale factor"), fts(vid.scale), 'z');
if(pmodel != mdPerspective)
dialog::addSelItem(XLAT("scale factor"), fts(vid.scale), 'z');
if(abs(vid.alpha-1) > 1e-3 && pmodel != mdBall && pmodel != mdHyperboloid && pmodel != mdHemisphere && pmodel != mdDisk) {
dialog::addBreak(50);

View File

@ -677,13 +677,11 @@ void showEuclideanMenu() {
dialog::add_action([] { pushScreen(patterns::showPrePattern); });
validity_info();
if(DIM == 3) {
dialog::addItem(XLAT("3D configuration"), '1');
dialog::addItem(XLAT("3D configuration"), '9');
dialog::add_action([] { pushScreen(show3D); });
}
else {
dialog::addSelItem(XLAT("projection"), current_proj_name(), '1');
dialog::add_action([] { pushScreen(conformal::model_menu); });
}
dialog::addSelItem(XLAT("projection"), current_proj_name(), '1');
dialog::add_action([] { pushScreen(conformal::model_menu); });
#if CAP_CRYSTAL && MAXMDIM >= 4
crystal::add_crystal_transform('x');
#endif

View File

@ -4808,8 +4808,8 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
for(int a=0; a<c->type; a++)
if(c->move(a) && !isWall3(c->move(a), dummy)) {
if(a < 4 && among(geometry, gHoroTris, gBinary3) && celldistAlt(c) >= celldistAlt(viewctr.at->c7)) continue;
if(a < 2 && among(geometry, gHoroRec) && celldistAlt(c) >= celldistAlt(viewctr.at->c7)) continue;
if(a < 4 && pmodel == mdPerspective && among(geometry, gHoroTris, gBinary3) && celldistAlt(c) >= celldistAlt(viewctr.at->c7)) continue;
if(a < 2 && pmodel == mdPerspective && among(geometry, gHoroRec) && celldistAlt(c) >= celldistAlt(viewctr.at->c7)) continue;
if(qfi.fshape && wmescher) {
auto& poly = queuepoly(V, shWall3D[a], darkena(wcol - d * get_darkval(a), 0, 0xFF));
poly.tinf = &qfi.fshape->tinf3;
@ -5923,6 +5923,7 @@ void drawthemap() {
mmspatial = vid.monmode == 4 || vid.monmode == 5;
spatial_graphics = wmspatial || mmspatial;
spatial_graphics = spatial_graphics && DIM == 2;
#if CAP_RUG
if(rug::rugged && !rug::spatial_rug) spatial_graphics = false;
#endif
@ -6146,7 +6147,7 @@ void calcparam() {
}
cd->radius = vid.scale * cd->scrsize;
if(DIM == 3) cd->radius = cd->scrsize;
if(DIM == 3 && pmodel == mdPerspective) cd->radius = cd->scrsize;
realradius = min(realradius, cd->radius);
if(dronemode) { cd->ycenter -= cd->radius; cd->ycenter += vid.fsize/2; cd->ycenter += vid.fsize/2; cd->radius *= 2; }

View File

@ -69,7 +69,12 @@ hyperpoint space_to_perspective(hyperpoint z, ld alpha) {
ld s = 1 / (alpha + z[DIM]);
z[0] *= s;
z[1] *= s;
z[DIM] = 0;
if(DIM == 3) {
z[2] *= s;
z[3] = 0;
}
else
z[2] = 0;
return z;
}
@ -154,7 +159,7 @@ ld find_zlev(hyperpoint& H) {
}
ld get_tz(hyperpoint H) {
ld tz = euclid ? (1+vid.alpha) : vid.alpha+H[2];
ld tz = euclid ? (1+vid.alpha) : vid.alpha+H[DIM];
if(tz < BEHIND_LIMIT && tz > -BEHIND_LIMIT) tz = BEHIND_LIMIT;
return tz;
}
@ -163,9 +168,26 @@ ld atan2(hyperpoint h) {
return atan2(h[1], h[0]);
}
pair<ld, ld> move_z_to_y(hyperpoint& H) {
if(DIM == 2) return make_pair(0, 0);
ld R = hypot(H[1], H[2]);
pair<ld, ld> res = { H[1] / R, H[2] / R };
H[1] = R; H[2] = 0;
return res;
}
void move_y_to_z(hyperpoint& H, pair<ld, ld> coef) {
if(DIM == 3) {
H[2] = H[1] * coef.second;
H[1] = H[1] * coef.first;
H[3] = 1;
}
}
template<class T> void makeband(hyperpoint H, hyperpoint& ret, const T& f) {
ld zlev = find_zlev(H);
conformal::apply_orientation(H[0], H[1]);
auto r = move_z_to_y(H);
ld x, y, yf, zf=0;
y = asin_auto(H[1]);
@ -179,8 +201,9 @@ template<class T> void makeband(hyperpoint H, hyperpoint& ret, const T& f) {
f(x, y);
ld yzf = y * zf; y *= yf;
conformal::apply_orientation(y, x);
ret = hpxyz(x / M_PI, y / M_PI, 0);
move_y_to_z(ret, r);
conformal::apply_orientation(ret[1], ret[0]);
if(zlev != 1 && current_display->stereo_active())
apply_depth(ret, yzf / M_PI);
return;
@ -233,19 +256,19 @@ hyperpoint mobius(hyperpoint h, ld angle, ld scale = 1) {
void applymodel(hyperpoint H, hyperpoint& ret) {
if(DIM == 3) {
ld ratio = vid.xres / current_display->tanfov / current_display->radius / 2;
ret[0] = H[0]/H[2] * ratio;
ret[1] = H[1]/H[2] * ratio;
ret[2] = 1;
return;
}
using namespace hyperpoint_vec;
hyperpoint H_orig = H;
switch(pmodel) {
case mdPerspective: {
ld ratio = vid.xres / current_display->tanfov / current_display->radius / 2;
ret[0] = H[0]/H[2] * ratio;
ret[1] = H[1]/H[2] * ratio;
ret[2] = 1;
return;
}
case mdUnchanged:
ret = H / current_display->radius;
return;
@ -264,7 +287,9 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
if(!vid.camera_angle) {
ret[0] = H[0] / tz;
ret[1] = H[1] / tz;
ret[2] = vid.xres * current_display->eyewidth() / 2 / current_display->radius - vid.ipd / tz / 2;
if(DIM == 3) ret[2] = H[2] / tz;
else ret[2] = vid.xres * current_display->eyewidth() / 2 / current_display->radius - vid.ipd / tz / 2;
if(MAXMDIM == 4) ret[3] = 1;
}
else {
ld tx = H[0];
@ -289,7 +314,7 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
conformal::apply_orientation(H[0], H[1]);
H[1] += 1;
double rad = sqhypot_d(2, H);
double rad = sqhypot_d(DIM, H);
H /= -rad;
H[1] += .5;
@ -307,7 +332,8 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
H[1] += H[0] * conformal::osin * log(zlev);
}
ret[1] = conformal::ocos + H[1];
ret[2] = 0;
ret[2] = DIM == 3 ? H[2] : 0;
if(MAXMDIM == 4) ret[3] = 1;
if(zlev != 1 && current_display->stereo_active())
apply_depth(ret, -H[1] * geom3::factor_to_lev(zlev));
break;
@ -378,8 +404,8 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
case mdFisheye: {
ld zlev = find_zlev(H);
H = space_to_perspective(H);
H[2] = zlev;
ret = H / sqrt(1 + sqhypot_d(3, H));
H[DIM] = zlev;
ret = H / sqrt(1 + sqhypot_d(DIM+1, H));
break;
}
@ -409,6 +435,7 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
}
H = space_to_perspective(H);
auto yz = move_z_to_y(H);
ld r = hypot_d(2, H);
ld c = H[0] / r;
ld s = H[1] / r;
@ -422,11 +449,12 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
if(vid.skiprope)
ret = mobius(ret, vid.skiprope, 2);
if(pmodel == mdJoukowskyInverted) {
ld r2 = sqhypot_d(2, ret);
ret[0] = ret[0] / r2;
ret[1] = -ret[1] / r2;
move_y_to_z(ret, yz);
conformal::apply_orientation(ret[1], ret[0]);
/*
@ -439,7 +467,10 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
ret[0] = alpha;
ret[1] = log(mod); */
}
else conformal::apply_orientation(ret[0], ret[1]);
else {
move_y_to_z(ret, yz);
conformal::apply_orientation(ret[0], ret[1]);
}
break;
}
@ -511,7 +542,7 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
case mdEquidistant: case mdEquiarea: {
ld zlev = find_zlev(H);
ld rad = hypot_d(2, H);
ld rad = hypot_d(DIM, H);
if(rad == 0) rad = 1;
ld d = hdist0(H);
ld df, zf;
@ -525,7 +556,8 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
d = sqrt(2*(cosh(d) - 1)) / 1.5;
ret = H * (d * df / rad / M_PI);
ret[2] = 0;
if(DIM == 2) ret[2] = 0;
if(MAXMDIM == 4) ret[3] = 1;
if(zlev != 1 && current_display->stereo_active())
apply_depth(ret, d * zf / M_PI);

View File

@ -496,7 +496,7 @@ vector<glvertex> line_vertices;
void glapplymatrix(const transmatrix& V) {
GLfloat mat[16];
int id = 0;
if(DIM == 3) {
if(pmodel == mdPerspective && DIM == 3) {
if(elliptic && spherephase < 2) {
for(int y=0; y<4; y++) {
for(int x=0; x<4; x++) mat[id++] = -V[x][y];

View File

@ -1170,6 +1170,7 @@ void push_game() {
void set_geometry(eGeometry target) {
if(geometry != target) {
int old_DIM = DIM;
stop_game();
ors::reset();
geometry = target;
@ -1196,6 +1197,8 @@ void set_geometry(eGeometry target) {
#if CAP_BT
if(geometry == gBinaryTiling || DIM == 3) variation = eVariation::pure;
#endif
if(DIM == 3 && old_DIM == 3 && pmodel == mdDisk) pmodel = mdPerspective;
if(DIM == 2 && pmodel == mdPerspective) pmodel = mdDisk;
need_reset_geometry = true;
}