mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-01-22 23:17:04 +00:00
relativistic projections added
This commit is contained in:
parent
7a6df6f060
commit
a7ca4c2902
@ -1007,9 +1007,9 @@ enum eModel : int {
|
||||
mdHorocyclic, mdQuadrant, mdAxial, mdAntiAxial,
|
||||
// 32..38
|
||||
mdWerner, mdAitoff, mdHammer, mdLoximuthal, mdMiller, mdGallStereographic, mdWinkelTripel,
|
||||
// 39..
|
||||
mdPoorMan, mdPanini, mdRetroCraig, mdRetroLittrow, mdRetroHammer, mdThreePoint, mdLiePerspective, mdLieOrthogonal,
|
||||
// 47..
|
||||
// 39..48
|
||||
mdPoorMan, mdPanini, mdRetroCraig, mdRetroLittrow, mdRetroHammer, mdThreePoint, mdLiePerspective, mdLieOrthogonal, mdRelPerspective, mdRelOrthogonal,
|
||||
// 49..
|
||||
mdGUARD, mdPixel, mdHyperboloidFlat, mdPolynomial, mdManual
|
||||
};
|
||||
#endif
|
||||
@ -1069,6 +1069,8 @@ EX vector<modelinfo> mdinf = {
|
||||
{X3("three-point equidistant"), mf::euc_boring, DEFAULTS},
|
||||
{X3("Lie perspective"), mf::euc_boring, DEFAULTS},
|
||||
{X3("Lie orthogonal"), mf::euc_boring, DEFAULTS},
|
||||
{X3("relativistic perspective"), mf::euc_boring, DEFAULTS},
|
||||
{X3("relativistic orthogonal"), mf::euc_boring, DEFAULTS},
|
||||
{X3("guard"), mf::technical, DEFAULTS},
|
||||
{X3("pixel"), mf::technical, DEFAULTS},
|
||||
{X3("hypflat"), mf::technical, DEFAULTS},
|
||||
|
@ -483,6 +483,8 @@ bool behind3(shiftpoint h) {
|
||||
return lp_apply(inverse_exp(h))[2] < 0;
|
||||
if(pmodel == mdLiePerspective)
|
||||
return lp_apply(lie_log(unshift(h)))[2] < 0;
|
||||
if(pmodel == mdRelPerspective)
|
||||
return lp_apply(rel_log(h))[2] < 0;
|
||||
return h[2] < 0;
|
||||
}
|
||||
|
||||
|
78
hypgraph.cpp
78
hypgraph.cpp
@ -551,6 +551,13 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
||||
return;
|
||||
}
|
||||
|
||||
case mdRelPerspective: {
|
||||
auto S = rel_log(H_orig); S[3] = 1;
|
||||
S = lp_apply(S);
|
||||
apply_perspective(S, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
case mdPixel:
|
||||
ret = H / current_display->radius;
|
||||
return;
|
||||
@ -796,6 +803,16 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
|
||||
break;
|
||||
}
|
||||
|
||||
case mdRelOrthogonal: {
|
||||
|
||||
ret = rel_log(H_orig);
|
||||
ret *= .5;
|
||||
ret[LDIM] = 1;
|
||||
|
||||
if(nonisotropic && !vrhr::rendering()) ret = lp_apply(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
case mdHemisphere: {
|
||||
|
||||
#if CAP_VR
|
||||
@ -2354,6 +2371,30 @@ EX void draw_model_elements() {
|
||||
dynamicval<ld> lw(vid.linewidth, vid.linewidth * vid.multiplier_ring);
|
||||
switch(pmodel) {
|
||||
|
||||
case mdRelOrthogonal:
|
||||
case mdRelPerspective: {
|
||||
constexpr ld cc = 3;
|
||||
if(sl2) for(ld dist: {-0.1, 0.1}) {
|
||||
transmatrix Lorentz = Id;
|
||||
Lorentz[0][0] = Lorentz[2][2] = cosh(cc);
|
||||
Lorentz[0][2] = Lorentz[2][0] = sinh(cc);
|
||||
hyperpoint h = Lorentz * cspin(3, 2, dist) * C0;
|
||||
for(int s=0; s<=360; s++)
|
||||
curvepoint(spin(s*degree) * h);
|
||||
queuecurve(shiftless(Id), ringcolor, 0, PPR::CIRCLE);
|
||||
}
|
||||
if(hyperbolic) for(ld dist: {-0.1, 0.1}) {
|
||||
transmatrix Lorentz = Id;
|
||||
Lorentz[0][0] = Lorentz[3][3] = cosh(cc);
|
||||
Lorentz[0][3] = Lorentz[3][0] = sinh(cc);
|
||||
hyperpoint h = Lorentz * hyperpoint(0, 0, cosh(dist), sinh(dist));
|
||||
for(int s=0; s<=360; s++)
|
||||
curvepoint(spin(s*degree) * h);
|
||||
queuecurve(shiftless(Id), ringcolor, 0, PPR::CIRCLE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case mdRotatedHyperboles: {
|
||||
queuestr(current_display->xcenter, current_display->ycenter + current_display->radius * pconf.alpha, 0, vid.fsize, "X", ringcolor, 1, 8);
|
||||
return;
|
||||
@ -3055,6 +3096,43 @@ EX hyperpoint lie_exp(hyperpoint h) {
|
||||
return h;
|
||||
}
|
||||
|
||||
EX hyperpoint rel_log(shiftpoint h) {
|
||||
if(sl2) {
|
||||
optimize_shift(h);
|
||||
ld cycles = floor(h.shift / (2*M_PI) + .5);
|
||||
hyperpoint h1 = unshift(h);
|
||||
ld choice = h1[2] * h1[2] - h1[0] * h1[0] - h1[1] * h1[1];
|
||||
ld r, z;
|
||||
if(choice > 0) {
|
||||
ld r = sqrt(choice);
|
||||
ld z = asin_clamp(r);
|
||||
if(h1[3] < 0) z = M_PI - z;
|
||||
z += cycles * 2 * M_PI;
|
||||
}
|
||||
else if(cycles || h1[3] < -1 || choice == 0) {
|
||||
/* impossible, or light-like */
|
||||
r = 1; z = 0;
|
||||
}
|
||||
else {
|
||||
r = sqrt(-choice);
|
||||
z = asinh(r);
|
||||
}
|
||||
h1 = h1 * z / r;
|
||||
h1[3] = 0;
|
||||
return h1;
|
||||
}
|
||||
if(hyperbolic && GDIM == 3) {
|
||||
hyperpoint h1 = h.h;
|
||||
ld choice = h1[3] * h1[3] - h1[0] * h1[0] - h1[1] * h1[1];
|
||||
ld r, z;
|
||||
if(choice > 0) { r = sqrt(choice); z = asinh(r); }
|
||||
else { r = sqrt(-choice); z = asin_clamp(r); if(h1[2] < 0) z = M_PI - z; }
|
||||
h1 = h1 * z / r; h1[2] = h1[3]; h1[3] = 0;
|
||||
return h1;
|
||||
}
|
||||
throw hr_exception("rel_log in wrong geometry");
|
||||
}
|
||||
|
||||
EX hyperpoint lie_log(hyperpoint h) {
|
||||
if(nil) {
|
||||
h[3] = 0;
|
||||
|
@ -192,7 +192,7 @@ EX namespace models {
|
||||
if(among(pm, mdBall, mdHemisphere)) return false;
|
||||
return PIU(model_available(pm));
|
||||
}
|
||||
if(sl2) return among(pm, mdGeodesic, mdEquidistant, mdHorocyclic, mdPerspective);
|
||||
if(sl2) return among(pm, mdGeodesic, mdEquidistant, mdRelPerspective, mdRelOrthogonal, mdHorocyclic, mdPerspective);
|
||||
if(nonisotropic) return among(pm, mdDisk, mdPerspective, mdHorocyclic, mdGeodesic, mdEquidistant, mdFisheye, mdLiePerspective, mdLieOrthogonal);
|
||||
if(sphere && (pm == mdHalfplane || pm == mdBall))
|
||||
return false;
|
||||
@ -230,7 +230,7 @@ EX namespace models {
|
||||
}
|
||||
|
||||
EX bool is_perspective(eModel m) {
|
||||
return among(m, mdPerspective, mdGeodesic, mdLiePerspective);
|
||||
return among(m, mdPerspective, mdGeodesic, mdLiePerspective, mdRelPerspective);
|
||||
}
|
||||
|
||||
EX bool is_3d(const projection_configuration& p) {
|
||||
@ -258,7 +258,7 @@ EX namespace models {
|
||||
if(m == mdHorocyclic && !sol) return XLAT("simple model: projection");
|
||||
if(m == mdPerspective) return XLAT("simple model: perspective");
|
||||
if(m == mdGeodesic) return XLAT("native perspective");
|
||||
if(among(m, mdEquidistant, mdFisheye, mdHorocyclic, mdLiePerspective, mdLieOrthogonal)) return XLAT(mdinf[m].name_hyperbolic);
|
||||
if(among(m, mdEquidistant, mdFisheye, mdHorocyclic, mdLiePerspective, mdLieOrthogonal, mdRelPerspective, mdRelOrthogonal)) return XLAT(mdinf[m].name_hyperbolic);
|
||||
}
|
||||
if(m == mdDisk && GDIM == 3) return XLAT("perspective in 4D");
|
||||
if(m == mdHalfplane && GDIM == 3 && hyperbolic) return XLAT("half-space");
|
||||
|
49
shaders.cpp
49
shaders.cpp
@ -110,6 +110,49 @@ EX string shader_lie_log() {
|
||||
}
|
||||
}
|
||||
|
||||
EX string shader_rel_log() {
|
||||
if(sl2) return
|
||||
"uniform mediump float uIndexSL;\n"
|
||||
"vec4 rel_log(vec4 h) {\n"
|
||||
"float shift = uIndexSL + atan2(h[2], h[3]); \n"
|
||||
"float ca = cos(uIndexSL); float sa = -sin(uIndexSL);\n"
|
||||
"vec4 h1 = h;\n"
|
||||
"h[2] = h1[2] * ca - h1[3] * sa; h[3] = h1[3] * ca + h1[2] * sa;\n"
|
||||
"h[0] = h1[0] * ca - h1[1] * sa; h[1] = h1[1] * ca + h1[0] * sa;\n"
|
||||
"h1 = h;"
|
||||
|
||||
"if(h1[3] <= 1. && h1[3] >= -1.) {\n"
|
||||
"float r = sqrt(h1[2]*h1[2] - h1[0]*h1[0] - h1[1]*h1[1]);\n"
|
||||
"float z = asin_clamp(r);\n"
|
||||
"if(h1[3] < 0.) z = PI - z;\n"
|
||||
"z += floor(shift / 2. / PI + .5) * 2. * PI;\n"
|
||||
"float scale = z/r;\n"
|
||||
"h1 = h1 * scale; h1[3] = 1.;\n"
|
||||
"} else if(shift > PI || shift < -PI || h1[3] < -1.) { return vec4(0,0,0,1); } else {\n"
|
||||
|
||||
"float r = sqrt(h1[0]*h1[0] + h1[1]*h1[1] - h1[2]*h1[2]);\n"
|
||||
"float z = asinh(r);\n"
|
||||
"float scale = z/r;\n"
|
||||
"h1 = h1 * scale; h1[3] = 1.;\n"
|
||||
"}\n"
|
||||
|
||||
"return h1;\n"
|
||||
"}\n";
|
||||
|
||||
if(hyperbolic && GDIM == 3) return
|
||||
"vec4 rel_log(vec4 h) {\n"
|
||||
" float choice = h[3] * h[3] - h[0] * h[0] - h[1] * h[1];\n"
|
||||
" float z, r;\n"
|
||||
" if(choice > 0.) { r = sqrt(choice); z = asinh(r); }\n"
|
||||
" else { r = sqrt(-choice); z = asin_clamp(r); if(h[2] < 0.) z = PI - z; }\n"
|
||||
" h = h * z / r; h[2] = h[3]; h[3] = 1.;\n"
|
||||
" return h;\n"
|
||||
" }\n";
|
||||
|
||||
println(hlog, "geometry is: ", geometry);
|
||||
throw hr_exception("shader_rel_log in wrong geometry");
|
||||
}
|
||||
|
||||
shared_ptr<glhr::GLprogram> write_shader(flagtype shader_flags) {
|
||||
string varying, vsh, fsh, vmain = "void main() {\n", fmain = "void main() {\n";
|
||||
|
||||
@ -270,6 +313,12 @@ shared_ptr<glhr::GLprogram> write_shader(flagtype shader_flags) {
|
||||
distfun = "length(t.xyz)";
|
||||
vsh += shader_lie_log();
|
||||
}
|
||||
else if(pmodel == mdRelPerspective) {
|
||||
shader_flags |= SF_PERS3 | SF_DIRECT;
|
||||
coordinator += "t = rel_log(t);\n";
|
||||
distfun = "length(t.xyz)";
|
||||
vsh += shader_rel_log();
|
||||
}
|
||||
else if(pmodel == mdGeodesic) {
|
||||
shader_flags |= SF_PERS3 | SF_DIRECT;
|
||||
coordinator += "t = inverse_exp(t);\n";
|
||||
|
Loading…
Reference in New Issue
Block a user