rotations are now represented as matrices, not angles

This commit is contained in:
Zeno Rogue 2023-08-08 16:27:52 +02:00
parent c896b3ecd6
commit 1554caa7b4
11 changed files with 244 additions and 172 deletions

View File

@ -119,6 +119,10 @@ EX namespace arg {
#endif
if(old != x && r) r();
}
EX void shift_arg_formula_matrix(struct hr::trans23& x) {
shift(); x = parsematrix23(args()); // TODO animate
}
#if HDR

View File

@ -925,13 +925,29 @@ ld period_at(ld y) {
}
}
void apply_ori_gl(glvertex& g) {
auto Ori = pconf.mori().v2;
tie(g[0], g[1]) = make_pair(
Ori[0][0] * g[0] + Ori[0][1] * g[1],
Ori[1][0] * g[0] + Ori[1][1] * g[1]
);
}
void apply_iori_gl(glvertex& g) {
auto Ori = pconf.mori().v2;
tie(g[0], g[1]) = make_pair(
Ori[0][0] * g[0] + Ori[1][0] * g[1],
Ori[0][1] * g[0] + Ori[1][1] * g[1]
);
}
void adjust(bool tinf) {
periods.resize(isize(glcoords));
if(!models::model_straight)
for(auto& g: glcoords)
models::apply_orientation(g[0], g[1]);
apply_ori_gl(g);
for(int i = 0; i<isize(glcoords); i++) periods[i] = period_at(glcoords[i][1]);
@ -989,7 +1005,7 @@ void adjust(bool tinf) {
if(abs(first - last) < 1e-6) {
if(!models::model_straight)
for(auto& g: glcoords)
models::apply_orientation(g[1], g[0]);
apply_iori_gl(g);
}
else {
if(tinf) {
@ -1020,7 +1036,7 @@ void adjust(bool tinf) {
}
if(!models::model_straight)
for(auto& g: glcoords)
models::apply_orientation(g[1], g[0]);
apply_iori_gl(g);
// we have already looped
loop_min = loop_max = 0;
}
@ -1667,7 +1683,7 @@ bool broken_projection(dqi_poly& p0) {
int fail = 0;
int last_fail;
for(auto& h: all) models::apply_orientation(h[0], h[1]);
for(auto& h: all) models::apply_ori(h);
auto break_in_xz = [&] (hyperpoint a, hyperpoint b, int xcoord, int zcoord) {
return a[xcoord] * b[xcoord] <= 0 && (a[xcoord] * (b[zcoord]+zlow) - b[xcoord] * (a[zcoord]+zlow)) * (a[xcoord] - b[xcoord]) < 0;
@ -1692,7 +1708,7 @@ bool broken_projection(dqi_poly& p0) {
/* we don't rotate h's back, just change p.V */
for(int i=0; i<3; i++)
models::apply_orientation(p.V.T[i][0], p.V.T[i][1]);
models::apply_ori(p.V.T[i]);
if(fail) {
if(p0.tinf) return true;
@ -1875,8 +1891,8 @@ void dqi_poly::draw() {
shiftpoint h2 = V * glhr::gltopoint((*tab)[offset+(i+1)%cnt]);
hyperpoint ah1 = h1.h, ah2 = h2.h;
models::apply_orientation(ah1[0], ah1[1]);
models::apply_orientation(ah2[0], ah2[1]);
models::apply_ori(ah1);
models::apply_ori(ah2);
if(ah1[1] * ah2[1] > 0) continue;
ld c1 = ah1[1], c2 = -ah2[1];
if(c1 < 0) c1 = -c1, c2 = -c2;
@ -2030,8 +2046,8 @@ void dqi_poly::draw() {
if(l || lastl) {
for(int i=0; i<isize(glcoords); i++) {
glcoords[i][0] += models::ocos * cyl::periods[i] * (l - lastl);
glcoords[i][1] += models::osin * cyl::periods[i] * (l - lastl);
glcoords[i][0] += pconf.mori().get()[0][0] * cyl::periods[i] * (l - lastl);
glcoords[i][1] += pconf.mori().get()[1][0] * cyl::periods[i] * (l - lastl);
}
lastl = l;
}

View File

@ -3400,11 +3400,12 @@ EX void drawaura() {
ld s = sin(rr);
if(joukowsky) {
ld c1 = c, s1 = s;
hyperpoint v(c, s, 0, 1);
if(inversion)
models::apply_orientation(s1, c1);
models::apply_iori(v);
else
models::apply_orientation(c1, s1);
models::apply_ori(v);
ld c1 = v[0], s1 = v[1];
ld& mt = pconf.model_transition;
ld mt2 = 1 - mt;

View File

@ -203,6 +203,25 @@ constexpr transmatrix Id = diag(1,1,1,1);
/** zero matrix */
constexpr transmatrix Zero = diag(0,0,0,0);
/** a transmatrix with 2D and 3D version, useful for configuration */
struct trans23 {
transmatrix v2, v3;
transmatrix& get() { return MDIM == 3 ? v2 : v3; }
trans23() { v2 = Id; v3 = Id; }
trans23(const transmatrix& T) { v2 = T; v3 = T; }
trans23(const transmatrix& T2, const transmatrix& T3) { v2 = T2; v3 = T3; }
trans23 operator * (trans23 T) {
trans23 t;
auto& dim = cginf.g.homogeneous_dimension;
dynamicval<int> d1(dim, dim);
dim = 3; t.v2 = v2 * T.v2;
dim = 4; t.v3 = v3 * T.v3;
return t;
}
};
inline trans23 *gen_trans23() { return new trans23; }
/** mirror image */
constexpr transmatrix Mirror = diag(1,-1,1,1);
@ -1167,6 +1186,16 @@ EX transmatrix iso_inverse(const transmatrix& T) {
return inverse(T);
}
/** inverse a guaranteed rotation */
EX transmatrix rot_inverse(const transmatrix& T) {
return transpose(T);
}
/** inverse a guaranteed rotation */
EX trans23 rot_inverse(const trans23& T) {
return trans23(rot_inverse(T.v2), rot_inverse(T.v3));
}
/** \brief T inverse a matrix T = O*S, where O is isometry and S is a scaling matrix (todo optimize) */
EX transmatrix z_inverse(const transmatrix& T) {
return inverse(T);

View File

@ -253,8 +253,7 @@ void move_y_to_z(hyperpoint& H, pair<ld, ld> coef) {
template<class T> void makeband(shiftpoint H, hyperpoint& ret, const T& f) {
ld zlev = find_zlev(H.h);
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H.h);
auto r = move_z_to_y(H.h);
ld x, y, yf, zf=0;
@ -272,8 +271,7 @@ template<class T> void makeband(shiftpoint H, hyperpoint& ret, const T& f) {
ld yzf = y * zf; y *= yf;
ret = hpxyz(x / M_PI, y / M_PI, 0);
move_y_to_z(ret, r);
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
models::apply_iori(ret);
if(zlev != 1 && use_z_coordinate())
apply_depth(ret, yzf / M_PI);
return;
@ -397,9 +395,9 @@ EX void apply_perspective(const hyperpoint& H, hyperpoint& ret) {
EX void apply_nil_rotation(hyperpoint& H) {
if(nil) {
nilv::convert_ref(H, nilv::model_used, nilv::nmSym);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
nilv::convert_ref(H, nilv::nmSym, pconf.rotational_nil);
models::apply_orientation(H[1], H[0]);
models::apply_iori(H);
}
}
@ -454,8 +452,7 @@ EX void threepoint_projection(const hyperpoint& H, hyperpoint& ret) {
hyperpoint H1 = H;
find_zlev(H1);
if(true) {
models::apply_orientation_yz(H1[1], H1[2]);
models::apply_orientation(H1[0], H1[1]);
models::apply_ori(H1);
}
auto p = pconf.twopoint_param;
@ -501,16 +498,14 @@ EX void threepoint_projection(const hyperpoint& H, hyperpoint& ret) {
geometry = gCubeTiling;
ret = sxy;
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
models::apply_iori(ret);
}
#endif
EX vector<hr::function<void(shiftpoint& H_orig, hyperpoint& H, hyperpoint& ret)>> extra_projections;
EX void make_axial(hyperpoint H, hyperpoint& ret, const hr::function<ld(hyperpoint)>& f) {
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
ret[0] = f(H);
ld axi = pconf.axial_angle;
@ -531,8 +526,7 @@ EX void make_axial(hyperpoint H, hyperpoint& ret, const hr::function<ld(hyperpoi
ret[3] = 1;
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
models::apply_iori(ret);
}
// according to https://github.com/cspersonal/peirce-quincuncial-projection/blob/master/peirceQuincuncialProjection.R
@ -655,8 +649,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
#endif
if(!computing_semidirect) S = lp_apply(S);
if(hyperbolic) {
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
models::apply_iori(ret);
}
apply_perspective(S, ret);
return;
@ -751,8 +744,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
ld zlev = find_zlev(H);
H = space_to_perspective(H);
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
H[1] += 1;
double rad = sqhypot_d(GDIM, H);
@ -766,26 +758,27 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
ret[1] = 1 + H[1];
ret[2] = H[2];
ret[3] = 1;
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
models::apply_iori(ret);
break;
}
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
H *= pconf.halfplane_scale;
ret[0] = -models::osin - H[0];
auto ocos = pconf.mori().get()[0][0];
auto osin = pconf.mori().get()[1][0];
ret[0] = -osin - H[0];
ld height = 0;
if(zlev != 1) {
if(abs(models::ocos) > 1e-9)
height += H[1] * (pow(zlev, models::ocos) - 1);
if(abs(models::ocos) > 1e-9 && models::osin)
height += H[0] * models::osin * (pow(zlev, models::ocos) - 1) / models::ocos;
else if(models::osin)
height += H[0] * models::osin * log(zlev);
if(abs(ocos) > 1e-9)
height += H[1] * (pow(zlev, ocos) - 1);
if(abs(ocos) > 1e-9 && osin)
height += H[0] * osin * (pow(zlev, ocos) - 1) / ocos;
else if(osin)
height += H[0] * osin * log(zlev);
}
ret[1] = models::ocos + H[1];
ret[1] = ocos + H[1];
ret[2] = GDIM == 3 ? H[2] : 0;
if(MAXMDIM == 4) ret[3] = 1;
if(zlev != 1 && use_z_coordinate())
@ -824,8 +817,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
case mdQuadrant: {
H = space_to_perspective(H);
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
tie(H[0], H[1]) = make_pair((H[0] + H[1]) / sqrt(2), (H[1] - H[0]) / sqrt(2));
@ -840,8 +832,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
ret[0] = -H[1] * x - 1;
ret[1] = H[1] / x + 1;
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
models::apply_iori(ret);
break;
}
@ -858,19 +849,13 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
apply_nil_rotation(H);
if(hyperbolic) {
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
}
if(hyperbolic) models::apply_ori(H);
ret = hyperbolic ? deparabolic13(H) : H;
ret *= .5;
ret[LDIM] = 1;
if(hyperbolic) {
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
}
if(hyperbolic) models::apply_iori(ret);
if(!vrhr::rendering()) ret = lp_apply(ret);
@ -879,32 +864,24 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
case mdHorocyclicEqa: {
if(hyperbolic) {
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
}
if(hyperbolic) models::apply_ori(H);
ret = hyperbolic ? deparabolic13(H) : H;
ret[0] = exp(-ret[0]) - 1;
ret *= .5;
ret[LDIM] = 1;
if(hyperbolic) {
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
}
if(hyperbolic) models::apply_iori(ret);
break;
}
case mdConformalSquare: {
find_zlev(H);
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
if(euclid) H[0] /= pconf.fisheye_param, H[1] /= pconf.fisheye_param;
ret = to_square(H);
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
models::apply_iori(ret);
break;
}
@ -914,10 +891,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
ret *= .5;
ret[LDIM] = 1;
if(hyperbolic) {
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
}
if(hyperbolic) models::apply_iori(ret);
if(!vrhr::rendering()) ret = lp_apply(ret);
@ -1080,8 +1054,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
}
case mdSimulatedPerspective: {
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
auto yz = move_z_to_y(H);
hyperpoint Hl = xpush(-pconf.twopoint_param) * H;
hyperpoint Hr = xpush(+pconf.twopoint_param) * H;
@ -1100,28 +1073,24 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
ret[0] = -ret[0]; ret[1] = -ret[1];
move_y_to_z(ret, yz);
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
models::apply_iori(ret);
break;
}
case mdTwoHybrid: {
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
auto yz = move_z_to_y(H);
ret = compute_hybrid(H, whateveri[0]);
move_y_to_z(ret, yz);
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
models::apply_iori(ret);
break;
}
case mdJoukowsky:
case mdJoukowskyInverted: {
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
// with equal speed skiprope: models::apply_orientation(H[1], H[0]);
if(pconf.skiprope) {
@ -1168,7 +1137,6 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
ret[0] = ret[0] / r2;
ret[1] = -ret[1] / r2;
move_y_to_z(ret, yz);
models::apply_orientation(ret[1], ret[0]);
/*
@ -1181,10 +1149,9 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
ret[1] = log(mod); */
}
else {
move_y_to_z(ret, yz);
models::apply_orientation(ret[0], ret[1]);
move_y_to_z(ret, yz);
}
models::apply_orientation_yz(ret[2], ret[1]);
models::apply_iori(ret);
break;
}
@ -1193,14 +1160,14 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
H = space_to_perspective(H);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
pair<long double, long double> p = polygonal::compute(H[0], H[1]);
models::apply_orientation(p.second, p.first);
ret[0] = p.first;
ret[1] = p.second;
ret[2] = 0;
models::apply_iori(ret);
break;
}
@ -1211,7 +1178,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
H = space_to_perspective(H);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
H[0] += 1;
double rad = H[0]*H[0] + H[1]*H[1];
@ -1232,7 +1199,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
ret[0] /= -(1-mt) * 90._deg;
ret[1] /= (1-mt) * 90._deg;
models::apply_orientation(ret[1], ret[0]);
models::apply_iori(ret);
}
else
makeband(H_orig, ret, band_conformal);
@ -1329,8 +1296,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
case mdWerner: {
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
find_zlev(H); // ignored for now
@ -1344,8 +1310,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
ret[2] = 0;
ret[3] = 1;
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
models::apply_iori(ret);
break;
}
@ -1417,7 +1382,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
case mdRotatedHyperboles: {
// ld zlev = <- not implemented
find_zlev(H); // + vid.depth;
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
ld y = asin_auto(H[1]);
ld x = asin_auto_clamp(H[0] / cos_auto(y));
@ -1532,8 +1497,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
case mdPanini: {
find_zlev(H);
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
ld proh = sqrt(H[2]*H[2] + curvature() * H[0] * H[0]);
H /= proh;
@ -1541,8 +1505,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
ret = H;
ret[2] = 0; ret[3] = 1;
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
models::apply_iori(ret);
break;
}
@ -1550,8 +1513,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
find_zlev(H);
H = space_to_perspective(H);
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
ld u = H[0], v = H[1];
if(abs(u) > 1e-3 && abs(v) > 1e-3) {
@ -1564,8 +1526,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) {
ret[2] = 0;
ret[3] = 1;
models::apply_orientation(ret[1], ret[0]);
models::apply_orientation_yz(ret[2], ret[1]);
models::apply_iori(ret);
break;
}
@ -2264,11 +2225,11 @@ EX void centerpc(ld aspd) {
}
if(set_multi && multi::two_focus) {
pconf.model_orientation = atan2(multi_point) / degree;
pconf.mori() = spin( atan2(multi_point) );
auto& d = pconf.twopoint_param;
d = hdist0(multi_point);
if(among(pmodel, mdJoukowsky, mdJoukowskyInverted)) {
pconf.model_orientation += 90;
pconf.mori() = pconf.mori() * spin90();
pconf.model_transition = sinh(d) / (1 + cosh(d));
pconf.dualfocus_autoscale = true;
}
@ -2603,8 +2564,7 @@ EX void draw_model_elements() {
hyperpoint H = xpush(p * pconf.twopoint_param) * ypush0(h);
hyperpoint res = compute_hybrid(H, 2 | mode);
models::apply_orientation(res[0], res[1]);
models::apply_orientation_yz(res[2], res[1]);
models::apply_iori(res);
curvepoint(res * current_display->radius);
}
queuecurve(shiftless(Id), ringcolor, 0, PPR::CIRCLE);
@ -2616,9 +2576,9 @@ EX void draw_model_elements() {
case mdTwoPoint: case mdSimulatedPerspective: fallthrough: {
if(set_multi) return; /* no need */
ld a = -pconf.model_orientation * degree;
put_x(shiftless(xspinpush(a, +pconf.twopoint_param)), ringcolor >> 8);
put_x(shiftless(xspinpush(a, -pconf.twopoint_param)), ringcolor >> 8);
auto T = rot_inverse(pconf.mori().get());
put_x(shiftless(T * xpush(+pconf.twopoint_param)), ringcolor >> 8);
put_x(shiftless(T * xpush(-pconf.twopoint_param)), ringcolor >> 8);
return;
}
@ -2626,8 +2586,7 @@ EX void draw_model_elements() {
vid.linewidth *= 5;
for(int i=0; i<=3; i++) {
hyperpoint h = xspinpush0(120._deg*i, pconf.twopoint_param);
models::apply_orientation(h[1], h[0]);
models::apply_orientation_yz(h[2], h[1]);
models::apply_iori(h);
curvepoint(h);
}
@ -2773,7 +2732,7 @@ EX void draw_boundary(int w) {
h[broken_coord] = -sin_auto(a*degree) * rem;
h[0] = sin_auto(a*degree) * eps * s;
h[unbroken_coord] = cos_auto(a*degree);
models::apply_orientation(h[1], h[0]);
models::apply_iori(h);
curvepoint(h);
}
queuecurve(shiftless(Id), periodcolor, 0, PPR::CIRCLE).flags |= POLY_FORCEWIDE;
@ -2793,13 +2752,14 @@ EX void draw_boundary(int w) {
ld x = sin(a * pconf.twopoint_param * b / 90);
ld y = 0;
ld z = -sqrt(1 - x*x);
models::apply_orientation(y, x);
hyperpoint h0 = hpxyz(x, y, z);
models::apply_iori(h0);
hyperpoint h1;
applymodel(shiftless(hpxyz(x,y,z)), h1);
applymodel(shiftless(h0), h1);
models::apply_orientation(h1[0], h1[1]);
models::apply_ori(h1);
h1[1] = abs(h1[1]) * b;
models::apply_orientation(h1[1], h1[0]);
models::apply_iori(h1);
curvepoint(h1);
}
@ -2814,7 +2774,7 @@ EX void draw_boundary(int w) {
if(GDIM == 3) return;
if(pmodel == mdBand && pconf.model_transition != 1) return;
bool bndband = (among(pmodel, mdBand, mdMiller, mdGallStereographic, mdCentralCyl) ? hyperbolic : sphere);
transmatrix T = spin(-pconf.model_orientation * degree);
transmatrix T = rot_inverse(pconf.mori().get());
ld right = 90._deg - 1e-5;
if(bndband)
queuestraight(T * ypush0(hyperbolic ? 10 : right), 2, lc, fc, p);
@ -2840,7 +2800,8 @@ EX void draw_boundary(int w) {
case mdHalfplane:
if(hyperbolic && GDIM == 2) {
queuestraight(xspinpush0(-pconf.model_orientation * degree - 90._deg, fakeinf), 1, lc, fc, p);
transmatrix Ori = rot_inverse(pconf.mori().get());
queuestraight(Ori * spin270() * xpush0(fakeinf), 1, lc, fc, p);
return;
}
break;
@ -2982,9 +2943,9 @@ EX void change_shift(shiftpoint& h, ld by) {
tie(h[0], h[1]) = make_pair(h[0] * ca - h[1] * sa, h[1] * ca + h[0] * sa);
}
else if((mdinf[pmodel].flags & mf::uses_bandshift) || (sphere && pmodel == mdSpiral)) {
h.h = spin(pconf.model_orientation * degree) * h.h;
h.h = pconf.mori().get() * h.h;
h.h = xpush(-by) * h.h;
h.h = spin(-pconf.model_orientation * degree) * h.h;
h.h = rot_inverse(pconf.mori().get()) * h.h;
}
}
@ -2999,10 +2960,10 @@ EX void change_shift(shiftmatrix& T, ld by) {
}
}
else if((mdinf[pmodel].flags & mf::uses_bandshift) || (sphere && pmodel == mdSpiral)) {
T.T = spin(pconf.model_orientation * degree) * T.T;
T.T = pconf.mori().get() * T.T;
T.T = xpush(-by) * T.T;
fixmatrix(T.T);
T.T = spin(-pconf.model_orientation * degree) * T.T;
T.T = rot_inverse(pconf.mori().get()) * T.T;
}
}
@ -3045,7 +3006,7 @@ EX void optimize_shift(shiftmatrix& T) {
}
else if(((mdinf[pmodel].flags & mf::uses_bandshift) && T[LDIM][LDIM] > 30) || (sphere && pmodel == mdSpiral)) {
T.T = spin(pconf.model_orientation * degree) * T.T;
T.T = pconf.mori().get() * T.T;
hyperpoint H = tC0(T.T);
find_zlev(H);
@ -3058,7 +3019,7 @@ EX void optimize_shift(shiftmatrix& T) {
T.shift += x;
T.T = xpush(-x) * T.T;
fixmatrix(T.T);
T.T = spin(-pconf.model_orientation * degree) * T.T;
T.T = rot_inverse(pconf.mori().get()) * T.T;
}
}
@ -3436,8 +3397,7 @@ EX hyperpoint lie_log(const shiftpoint h1) {
EX hyperpoint lie_log_correct(const shiftpoint H_orig, hyperpoint& H) {
find_zlev(H);
if(hyperbolic) {
models::apply_orientation_yz(H[1], H[2]);
models::apply_orientation(H[0], H[1]);
models::apply_ori(H);
return lie_log(shiftless(H));
}
return lie_log(H_orig);

View File

@ -953,7 +953,7 @@ EX void showStartMenu() {
specialland = racing::race_lands[rand() % isize(racing::race_lands)];
start_game();
pmodel = mdBand;
pconf.model_orientation = racing::race_angle;
pconf.mori() = racing::race_angle;
racing::race_advance = 1;
vid.yshift = 0;
pconf.camera_angle = 0;

View File

@ -119,18 +119,15 @@ EX namespace models {
EX ld rotation_xz = 90;
EX ld rotation_xy2 = 90;
EX int do_rotate = 1;
EX ld ocos, osin, ocos_yz, osin_yz;
EX ld cos_ball, sin_ball;
EX bool model_straight, model_straight_yz;
EX void apply_ori(hyperpoint& h) { if(!model_straight) h = pconf.mori().get() * h; }
EX void apply_iori(hyperpoint& h) { if(!model_straight) h = iso_inverse(pconf.mori().get()) * h; }
#if HDR
// screen coordinates to logical coordinates: apply_orientation(x,y)
// screen coordinates to logical coordinates: apply_orientation(x,y)
// logical coordinates back to screen coordinates: apply_orientation(y,x)
template<class A>
void apply_orientation(A& x, A& y) { if(!model_straight) tie(x,y) = make_pair(x*ocos + y*osin, y*ocos - x*osin); }
template<class A>
void apply_orientation_yz(A& x, A& y) { if(!model_straight_yz) tie(x,y) = make_pair(x*ocos_yz + y*osin_yz, y*ocos_yz - x*osin_yz); }
template<class A>
void apply_ball(A& x, A& y) { tie(x,y) = make_pair(x*cos_ball + y*sin_ball, y*cos_ball - x*sin_ball); }
#endif
@ -151,12 +148,8 @@ EX namespace models {
EX void configure() {
ld ball = -pconf.ballangle * degree;
cos_ball = cos(ball), sin_ball = sin(ball);
ocos = cos(pconf.model_orientation * degree);
osin = sin(pconf.model_orientation * degree);
ocos_yz = cos(pconf.model_orientation_yz * degree);
osin_yz = sin(pconf.model_orientation_yz * degree);
model_straight = (ocos > 1 - 1e-9);
model_straight_yz = GDIM == 2 || (ocos_yz > 1-1e-9);
model_straight = (pconf.mori().get()[0][0] > 1 - 1e-9);
model_straight_yz = GDIM == 2 || (pconf.mori().get()[2][2] > 1-1e-9);
if(history::on) history::apply();
if(!euclid) {
@ -474,7 +467,7 @@ EX namespace models {
add_edit(vpconf.alpha);
}
if(has_orientation(vpmodel)) {
/* TODO if(has_orientation(vpmodel)) {
dialog::addSelItem(XLAT("model orientation"), fts(vpconf.model_orientation) + "°", 'l');
dialog::add_action([] () {
dialog::editNumber(vpconf.model_orientation, 0, 360, 90, 0, XLAT("model orientation"), "");
@ -485,13 +478,13 @@ EX namespace models {
dialog::editNumber(vpconf.model_orientation_yz, 0, 360, 90, 0, XLAT("model orientation (y/z plane)"), "");
});
}
}
} */
if(among(vpmodel, mdPerspective, mdHorocyclic) && nil) {
dialog::addSelItem(XLAT("model orientation"), fts(vpconf.model_orientation) + "°", 'l');
/* TODO dialog::addSelItem(XLAT("model orientation"), fts(vpconf.model_orientation) + "°", 'l');
dialog::add_action([] () {
dialog::editNumber(vpconf.model_orientation, 0, 360, 90, 0, XLAT("model orientation"), "");
});
}); */
dialog::addSelItem(XLAT("rotational or Heisenberg"), fts(vpconf.rotational_nil), 'L');
dialog::add_action([] () {
dialog::editNumber(vpconf.rotational_nil, 0, 1, 1, 1, XLAT("1 = Heisenberg, 0 = rotational"), "");
@ -850,7 +843,7 @@ EX namespace models {
}
else if(argis("-mori")) {
PHASEFROM(2);
shift_arg_formula(vpconf.model_orientation);
shift_arg_formula_matrix(vpconf.mori());
}
else if(argis("-mets")) {
PHASEFROM(2);
@ -868,11 +861,6 @@ EX namespace models {
PHASEFROM(2);
shift_arg_formula(vpconf.rotational_nil);
}
else if(argis("-mori2")) {
PHASEFROM(2);
shift_arg_formula(vpconf.model_orientation);
shift_arg_formula(vpconf.model_orientation_yz);
}
else if(argis("-crot")) {
PHASEFROM(2);
shift_arg_formula(models::rotation);
@ -987,8 +975,8 @@ EX namespace models {
addsaverenum(p.model, pp+"used model", mdDisk);
if(&p.model == &pmodel) param_custom(pmodel, "projection|Poincare|Klein|half-plane|perspective", menuitem_projection, '1');
param_f(p.model_orientation, pp+"mori", sp+"model orientation", 0);
param_f(p.model_orientation_yz, pp+"mori_yz", sp+"model orientation-yz", 0);
// TODO param_f(p.model_orientation, pp+"mori", sp+"model orientation", 0);
// TODO param_f(p.model_orientation_yz, pp+"mori_yz", sp+"model orientation-yz", 0);
param_f(p.top_z, sp+"topz", 5)
-> editable(1, 20, .25, "maximum z coordinate to show", "maximum z coordinate to show", 'l');

View File

@ -698,7 +698,7 @@ EX void reset_race() {
bool inrec = false;
EX ld race_angle = 90;
EX trans23 race_angle = cspin90(0, 1);
EX bool force_standard_centering() {
return nonisotropic || mhybrid || quotient || closed_or_bounded;
@ -793,7 +793,7 @@ EX bool set_view() {
}
if(GDIM == 3 && WDIM == 2)
View = spin180() * cspin(2, 1, 90._deg + shmup::playerturny[multi::cpid]) * spin270() * View;
else if(GDIM == 2) View = spin(race_angle * degree) * View;
else if(GDIM == 2) View = race_angle.v2 * View;
return true;
}
@ -846,7 +846,7 @@ auto hook =
})
+ addHook(hooks_configfile, 100, [] {
param_f(racing::race_advance, "race_advance");
param_f(racing::race_angle, "race_angle");
// TODO param_f(racing::race_angle, "race_angle");
param_i(racing::ghosts_to_show, "race_ghosts_to_show");
param_i(racing::ghosts_to_save, "race_ghosts_to_save");
param_b(racing::guiding, "race_guiding");
@ -982,7 +982,7 @@ void race_projection() {
dialog::addBoolItem(XLAT("band"), pmodel == mdBand, '2');
dialog::add_action([] () {
pmodel = mdBand;
pconf.model_orientation = race_angle;
pconf.mori() = race_angle;
race_advance = 1;
vid.yshift = 0;
pconf.camera_angle = 0;
@ -996,7 +996,7 @@ void race_projection() {
dialog::addBoolItem(XLAT("half-plane"), pmodel == mdHalfplane, '3');
dialog::add_action([] () {
pmodel = mdHalfplane;
pconf.model_orientation = race_angle + 90;
pconf.mori() = race_angle * spin90();
race_advance = 0.5;
vid.yshift = 0;
pconf.camera_angle = 0;
@ -1035,11 +1035,11 @@ void race_projection() {
else dialog::addBreak(100);
if(GDIM == 2) {
dialog::addSelItem(XLAT("race angle"), fts(race_angle), 'a');
// TODO dialog::addSelItem(XLAT("race angle"), fts(race_angle), 'a');
dialog::add_action([] () {
dialog::editNumber(race_angle, 0, 360, 15, 90, XLAT("race angle"), "");
int q = pconf.model_orientation - race_angle;
dialog::reaction = [q] () { pconf.model_orientation = race_angle + q; };
// TODO dialog::editNumber(race_angle, 0, 360, 15, 90, XLAT("race angle"), "");
auto q = rot_inverse(race_angle) * pconf.mori();
dialog::reaction = [q] () { pconf.mori() = race_angle * q; };
});
}

View File

@ -1365,7 +1365,7 @@ EX void apply() {
if(ballangle_rotation) {
if(models::has_orientation(vpconf.model))
vpconf.model_orientation += ballangle_rotation * 360 * t / period;
vpconf.mori() = trans23(spin(ballangle_rotation * 360 * t / period)) * vpconf.mori();
else
vpconf.ballangle += ballangle_rotation * 360 * t / period;
}
@ -1925,7 +1925,7 @@ startanim null_animation { "", no_init, [] { gamescreen(); }};
#if CAP_STARTANIM
startanim joukowsky { "Joukowsky transform", no_init, [] {
dynamicval<eModel> dm(pmodel, mdJoukowskyInverted);
dynamicval<ld> dt(pconf.model_orientation, ticks / 25.);
dynamicval<trans23> dt(pconf.mori(), spin( ticks / 25. ));
dynamicval<int> dv(vid.use_smart_range, 2);
dynamicval<ld> ds(pconf.scale, 1/4.);
models::configure();
@ -1936,7 +1936,7 @@ startanim joukowsky { "Joukowsky transform", no_init, [] {
startanim bandspin { "spinning in the band model", no_init, [] {
dynamicval<eModel> dm(pmodel, mdBand);
dynamicval<ld> dt(pconf.model_orientation, ticks / 25.);
dynamicval<trans23> dt(pconf.mori(), spin( ticks / 25. ));
dynamicval<int> dv(vid.use_smart_range, 2);
models::configure();
gamescreen();

View File

@ -56,10 +56,12 @@ EX map<unsigned, shared_ptr<glhr::GLprogram>> matched_programs;
glhr::glmatrix model_orientation_gl() {
glhr::glmatrix s = glhr::id;
for(int a=0; a<GDIM; a++)
models::apply_orientation(s[a][1], s[a][0]);
if(GDIM == 3) for(int a=0; a<GDIM; a++)
models::apply_orientation_yz(s[a][2], s[a][1]);
for(int a=0; a<GDIM; a++) {
hyperpoint row;
for(int b=0; b<4; b++) row[b] = s[a][b];
models::apply_iori(row);
for(int b=0; b<4; b++) s[a][b] = row[b];
}
return s;
}
@ -769,8 +771,8 @@ void display_data::set_projection(int ed, ld shift) {
}
if(selected->uRotNil != -1) {
glUniform1f(selected->uRotCos, models::ocos);
glUniform1f(selected->uRotSin, models::osin);
glUniform1f(selected->uRotCos, pconf.mori().get()[0][0]);
glUniform1f(selected->uRotSin, pconf.mori().get()[1][0]);
glUniform1f(selected->uRotNil, pconf.rotational_nil);
}
@ -786,10 +788,12 @@ void display_data::set_projection(int ed, ld shift) {
pp = glhr::tmtogl_transpose(NLP) * pp;
if(get_shader_flags() & SF_ORIENT) {
if(GDIM == 3) for(int a=0; a<4; a++)
models::apply_orientation_yz(pp[a][1], pp[a][2]);
for(int a=0; a<4; a++)
models::apply_orientation(pp[a][0], pp[a][1]);
for(int a=0; a<4; a++) {
hyperpoint row;
for(int b=0; b<4; b++) row[b] = pp[a][b];
models::apply_ori(row);
for(int b=0; b<4; b++) pp[a][b] = row[b];
}
}
glUniformMatrix4fv(selected->uPP, 1, 0, pp.as_array());

View File

@ -129,6 +129,8 @@ struct exp_parser {
cld parse(int prio = 0);
transmatrix parsematrix(int prio = 0);
ld rparse(int prio = 0) { return validate_real(parse(prio)); }
int iparse(int prio = 0) { return int(floor(rparse(prio) + .5)); }
@ -470,12 +472,80 @@ cld exp_parser::parse(int prio) {
return res;
}
int coord_id(char ch) {
if(ch == 'x') return 0;
if(ch == 'y') return 1;
if(ch == 'z') return 2;
if(ch == 'w') return 3;
if(ch == 't') return MDIM-1;
return -1;
}
ld angle_unit(char ch) {
if(ch == 'r') return 1;
if(ch == 'd') return degree;
if(ch == 't') return TAU;
if(ch == 'l') return -1;
return 0;
}
transmatrix exp_parser::parsematrix(int prio) {
skip_white();
if(s[at] && s[at+1] && s[at+2] && s[at+3] == '(') {
ld unit = angle_unit(s[at]);
int c0 = coord_id(s[at+1]);
int c1 = coord_id(s[at+2]);
if(c0 >= 0 && c1 >= 0 && c0 != c1 && unit) {
at += 4;
ld angle = validate_real(parsepar());
if(unit == -1) return lorentz(c0, c1, angle);
else return cspin(c0, c1, angle);
}
}
transmatrix res;
if(next() == '(') {
at++;
res = parsematrix();
force_eat(")");
}
else {
string token = next_token();
if(token == "id") res = Id;
else if(token == "view") res = View;
else throw hr_parse_exception("unknown matrix: " + token);
}
while(true) {
skip_white();
if(next() == '*' && prio <= 20) at++, res = res * parsematrix(30);
}
return res;
}
EX ld parseld(const string& s) {
exp_parser ep;
ep.s = s;
return ep.rparse();
}
EX transmatrix parsematrix(const string& s) {
exp_parser ep;
ep.s = s;
return ep.parsematrix();
}
EX trans23 parsematrix23(const string& s) {
trans23 t;
#if MAXMDIM == 3
t.v2 = t.v3 = parsematrix(s);
#else
auto& dim = cginf.g.homogeneous_dimension;
dynamicval<int> d1(dim, dim);
dim = 3; t.v2 = parsematrix(s);
dim = 4; t.v3 = parsematrix(s);
#endif
return t;
}
EX int parseint(const string& s) {
exp_parser ep;
ep.s = s;