1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-23 21:07:17 +00:00

3d models in product space

This commit is contained in:
Zeno Rogue 2019-08-18 13:05:47 +02:00
parent 00f4f4fca5
commit fb0f5872c8
8 changed files with 111 additions and 56 deletions

View File

@ -30,10 +30,15 @@ vector<hyperpoint> geometry_information::get_shape(hpcshape sh) {
return res; return res;
} }
hyperpoint normalize_flat(hyperpoint h) {
if(prod) return product_decompose(h).second;
return normalize(h);
}
hyperpoint get_center(const vector<hyperpoint>& vh) { hyperpoint get_center(const vector<hyperpoint>& vh) {
hyperpoint h = Hypc; hyperpoint h = Hypc;
for(auto h1: vh) h = h + h1; for(auto h1: vh) h = h + h1;
return normalize(h); return normalize_flat(h);
} }
ld zc(ld z) { ld zc(ld z) {
@ -125,7 +130,7 @@ void geometry_information::add_texture(hpcshape& sh) {
vector<hyperpoint> scaleshape(const vector<hyperpoint>& vh, ld s) { vector<hyperpoint> scaleshape(const vector<hyperpoint>& vh, ld s) {
vector<hyperpoint> res; vector<hyperpoint> res;
for(hyperpoint h: vh) res.push_back(normalize(h * s + shcenter * (1-s))); for(hyperpoint h: vh) res.push_back(normalize_flat(h * s + shcenter * (1-s)));
return res; return res;
} }
@ -326,8 +331,8 @@ void geometry_information::make_armor_3d(hpcshape& sh, int kind) {
for(hyperpoint h: body) { for(hyperpoint h: body) {
array<ld, 2> p; array<ld, 2> p;
p[0] = h[0] / h[3]; p[0] = h[0] / h[LDIM];
p[1] = h[1] / h[3]; p[1] = h[1] / h[LDIM];
pts[0].emplace_back(p); pts[0].emplace_back(p);
} }
@ -394,8 +399,8 @@ void geometry_information::make_head_3d(hpcshape& sh) {
for(hyperpoint h: head) { for(hyperpoint h: head) {
array<ld, 2> p; array<ld, 2> p;
p[0] = h[0] / h[3]; p[0] = h[0] / h[LDIM];
p[1] = h[1] / h[3]; p[1] = h[1] / h[LDIM];
pts[0].emplace_back(p); pts[0].emplace_back(p);
} }
@ -476,6 +481,11 @@ void geometry_information::make_skeletal(hpcshape& sh, ld push) {
shift_last(-push); shift_last(-push);
} }
hyperpoint yzspin(ld alpha, hyperpoint h) {
if(prod) return product::direct_exp(cspin(1, 2, alpha) * product::inverse_exp(h));
else return cspin(1, 2, alpha) * h;
}
void geometry_information::make_revolution(hpcshape& sh, int mx, ld push) { void geometry_information::make_revolution(hpcshape& sh, int mx, ld push) {
auto body = get_shape(sh); auto body = get_shape(sh);
bshape(sh, PPR::MONSTER_BODY); bshape(sh, PPR::MONSTER_BODY);
@ -484,12 +494,12 @@ void geometry_information::make_revolution(hpcshape& sh, int mx, ld push) {
hyperpoint h0 = body[i]; hyperpoint h0 = body[i];
hyperpoint h1 = body[(i+1) % isize(body)]; hyperpoint h1 = body[(i+1) % isize(body)];
for(int s=0; s<mx; s+=step) { for(int s=0; s<mx; s+=step) {
hpcpush(cspin(1, 2, s * degree) * h0); hpcpush(yzspin(s * degree, h0));
hpcpush(cspin(1, 2, s * degree) * h1); hpcpush(yzspin(s * degree, h1));
hpcpush(cspin(1, 2, (s+step) * degree) * h0); hpcpush(yzspin((s+step) * degree, h0));
hpcpush(cspin(1, 2, s * degree) * h1); hpcpush(yzspin(s * degree, h1));
hpcpush(cspin(1, 2, (s+step) * degree) * h0); hpcpush(yzspin((s+step) * degree, h0));
hpcpush(cspin(1, 2, (s+step) * degree) * h1); hpcpush(yzspin((s+step) * degree, h1));
} }
} }
last->flags |= POLY_TRIANGLES; last->flags |= POLY_TRIANGLES;
@ -537,7 +547,7 @@ void geometry_information::make_revolution_cut(hpcshape &sh, int each, ld push,
for(int i=0; i<n; i++) if(!stillin[i] && !stillin[lastid[i]]) lastid[i] = lastid[lastid[i]]; for(int i=0; i<n; i++) if(!stillin[i] && !stillin[lastid[i]]) lastid[i] = lastid[lastid[i]];
for(int i=0; i<n; i++) { for(int i=0; i<n; i++) {
if(!stillin[i]) gbody[i] = normalize(gbody[lastid[i]] * (i - lastid[i]) + gbody[nextid[i]] * (nextid[i] - i)); if(!stillin[i]) gbody[i] = normalize_flat(gbody[lastid[i]] * (i - lastid[i]) + gbody[nextid[i]] * (nextid[i] - i));
} }
bshape(sh, PPR::MONSTER_BODY); bshape(sh, PPR::MONSTER_BODY);
@ -551,12 +561,12 @@ void geometry_information::make_revolution_cut(hpcshape &sh, int each, ld push,
hyperpoint h1 = tbody[i1]; hyperpoint h1 = tbody[i1];
hyperpoint hs0 = nbody[i]; hyperpoint hs0 = nbody[i];
hyperpoint hs1 = nbody[i1]; hyperpoint hs1 = nbody[i1];
hpcpush(cspin(1, 2, s * degree) * h0); hpcpush(yzspin(s * degree, h0));
hpcpush(cspin(1, 2, s * degree) * h1); hpcpush(yzspin(s * degree, h1));
hpcpush(cspin(1, 2, (s+step) * degree) * hs0); hpcpush(yzspin((s+step) * degree, hs0));
hpcpush(cspin(1, 2, s * degree) * h1); hpcpush(yzspin(s * degree, h1));
hpcpush(cspin(1, 2, (s+step) * degree) * hs0); hpcpush(yzspin((s+step) * degree, hs0));
hpcpush(cspin(1, 2, (s+step) * degree) * hs1); hpcpush(yzspin((s+step) * degree, hs1));
} }
} }
last->flags |= POLY_TRIANGLES; last->flags |= POLY_TRIANGLES;
@ -600,26 +610,40 @@ void geometry_information::animate_bird(hpcshape& orig, hpcshape_animated& anima
// shift_shape(orig, BIRD); // shift_shape(orig, BIRD);
} }
EX hyperpoint forward_dir(ld x) { return prod ? point3(x, 0, 0) : xpush0(x); }
EX hyperpoint dir_to_point(hyperpoint h) { return prod ? product::direct_exp(h) : h; }
EX hyperpoint dir_setlength(hyperpoint dir, ld length) {
if(dir[0] == 0 && dir[1] == 0 && dir[2] == 0) return dir;
if(prod) return dir * (length / hypot_d(3, dir));
return rspintox(dir) * xpush0(length);
}
void geometry_information::slimetriangle(hyperpoint a, hyperpoint b, hyperpoint c, ld rad, int lev) { void geometry_information::slimetriangle(hyperpoint a, hyperpoint b, hyperpoint c, ld rad, int lev) {
dynamicval<int> d(vid.texture_step, 8); dynamicval<int> d(vid.texture_step, 8);
texture_order([&] (ld x, ld y) { texture_order([&] (ld x, ld y) {
ld z = 1-x-y; ld z = 1-x-y;
ld r = scalefactor * hcrossf7 * (0 + pow(max(x,max(y,z)), .3) * 0.8); ld r = scalefactor * hcrossf7 * (0 + pow(max(x,max(y,z)), .3) * 0.8) * (prod ? .5 : 1);
hyperpoint h = rspintox(a*x+b*y+c*z) * xpush0(r); hyperpoint h = dir_to_point(dir_setlength(a*x+b*y+c*z, r));
hpcpush(h); hpcpush(h);
}); });
} }
void geometry_information::balltriangle(hyperpoint a, hyperpoint b, hyperpoint c, ld rad, int lev) { void geometry_information::balltriangle(hyperpoint a, hyperpoint b, hyperpoint c, ld rad, int lev) {
if(lev == 0) { if(lev == 0) {
hpcpush(a); hpcpush(dir_to_point(a));
hpcpush(b); hpcpush(dir_to_point(b));
hpcpush(c); hpcpush(dir_to_point(c));
} }
else { else {
hyperpoint cx = rspintox(mid(a,b)) * xpush0(rad); auto midpoint = [&] (hyperpoint h1, hyperpoint h2) {
hyperpoint ax = rspintox(mid(b,c)) * xpush0(rad); if(prod) return dir_setlength(h1+h2, rad);
hyperpoint bx = rspintox(mid(c,a)) * xpush0(rad); else return rspintox(mid(h1,h2)) * xpush0(rad);
};
hyperpoint cx = midpoint(a, b);
hyperpoint ax = midpoint(b, c);
hyperpoint bx = midpoint(c, a);
balltriangle(ax, bx, cx, rad, lev-1); balltriangle(ax, bx, cx, rad, lev-1);
balltriangle(ax, bx, c , rad, lev-1); balltriangle(ax, bx, c , rad, lev-1);
balltriangle(ax, b , cx, rad, lev-1); balltriangle(ax, b , cx, rad, lev-1);
@ -630,8 +654,8 @@ void geometry_information::balltriangle(hyperpoint a, hyperpoint b, hyperpoint c
void geometry_information::make_ball(hpcshape& sh, ld rad, int lev) { void geometry_information::make_ball(hpcshape& sh, ld rad, int lev) {
bshape(sh, sh.prio); bshape(sh, sh.prio);
sh.flags |= POLY_TRIANGLES; sh.flags |= POLY_TRIANGLES;
hyperpoint tip = xpush0(rad); hyperpoint tip = forward_dir(rad);
hyperpoint atip = xpush0(-rad); hyperpoint atip = forward_dir(-rad);
ld z = 63.43 * degree; ld z = 63.43 * degree;
for(int i=0; i<5; i++) { for(int i=0; i<5; i++) {
hyperpoint a = cspin(1, 2, (72 * i ) * degree) * spin(z) * tip; hyperpoint a = cspin(1, 2, (72 * i ) * degree) * spin(z) * tip;
@ -691,7 +715,13 @@ void geometry_information::make_euclidean_sky() {
); );
} }
/** res[0] and res[1] place H on the plane, while res[2] is the altitude */
hyperpoint psmin(hyperpoint H) { hyperpoint psmin(hyperpoint H) {
if(prod) {
auto d = product_decompose(H);
d.second[2] = d.first;
return d.second;
}
hyperpoint res; hyperpoint res;
res[2] = asin_auto(H[2]); res[2] = asin_auto(H[2]);
ld cs = pow(cos_auto(res[2]), 2); ld cs = pow(cos_auto(res[2]), 2);
@ -704,7 +734,7 @@ hyperpoint psmin(hyperpoint H) {
void geometry_information::adjust_eye(hpcshape& eye, hpcshape head, ld shift_eye, ld shift_head, int q, ld zoom) { void geometry_information::adjust_eye(hpcshape& eye, hpcshape head, ld shift_eye, ld shift_head, int q, ld zoom) {
hyperpoint center = Hypc; hyperpoint center = Hypc;
for(int i=eye.s; i<eye.e; i++) if(q == 1 || hpc[i][1] > 0) center += hpc[i]; for(int i=eye.s; i<eye.e; i++) if(q == 1 || hpc[i][1] > 0) center += hpc[i];
center = normalize(center); center = normalize_flat(center);
// center /= (eye.e - eye.s); // center /= (eye.e - eye.s);
ld rad = 0; ld rad = 0;
for(int i=eye.s; i<eye.e; i++) if(q == 1 || hpc[i][1] > 0) rad += hdist(center, hpc[i]); for(int i=eye.s; i<eye.e; i++) if(q == 1 || hpc[i][1] > 0) rad += hdist(center, hpc[i]);
@ -724,7 +754,7 @@ void geometry_information::adjust_eye(hpcshape& eye, hpcshape head, ld shift_eye
zmid /= isize(pss); zmid /= isize(pss);
ld mindist = 1e9; ld mindist = 1e9;
for(int i=0; i<isize(pss); i+=3) if(pss[i][2] < zmid || WDIM == 3) { for(int i=0; i<isize(pss); i+=3) if(prod ? pss[i][2] > zmid : (pss[i][2] < zmid || (WDIM == 3 && !prod))) {
ld d = sqhypot_d(2, pss[i]-pscenter) + sqhypot_d(2, pss[i+1]-pscenter) + sqhypot_d(2, pss[i+2]-pscenter); ld d = sqhypot_d(2, pss[i]-pscenter) + sqhypot_d(2, pss[i+1]-pscenter) + sqhypot_d(2, pss[i+2]-pscenter);
if(d < mindist) mindist = d, pos = min(min(pss[i][2], pss[i+1][2]), pss[i+2][2]), qty++; if(d < mindist) mindist = d, pos = min(min(pss[i][2], pss[i+1][2]), pss[i+2][2]), qty++;
qtyall++; qtyall++;
@ -1086,10 +1116,10 @@ void geometry_information::make_3d_models() {
hyperpoint atip = xpush0(-1); hyperpoint atip = xpush0(-1);
ld z = 63.43 * degree; ld z = 63.43 * degree;
for(int i=0; i<5; i++) { for(int i=0; i<5; i++) {
auto a = cspin(1, 2, (72 * i ) * degree) * spin(z) * xpush0(1); auto a = cspin(1, 2, (72 * i ) * degree) * spin(z) * forward_dir(1);
auto b = cspin(1, 2, (72 * i-72) * degree) * spin(z) * xpush0(1); auto b = cspin(1, 2, (72 * i-72) * degree) * spin(z) * forward_dir(1);
auto c = cspin(1, 2, (72 * i+36) * degree) * spin(M_PI-z) * xpush0(1); auto c = cspin(1, 2, (72 * i+36) * degree) * spin(M_PI-z) * forward_dir(1);
auto d = cspin(1, 2, (72 * i-36) * degree) * spin(M_PI-z) * xpush0(1); auto d = cspin(1, 2, (72 * i-36) * degree) * spin(M_PI-z) * forward_dir(1);
slimetriangle(tip, a, b, 1, 0); slimetriangle(tip, a, b, 1, 0);
slimetriangle(a, b, c, 1, 0); slimetriangle(a, b, c, 1, 0);
slimetriangle(b, c, d, 1, 0); slimetriangle(b, c, d, 1, 0);

View File

@ -113,7 +113,7 @@ EX void remission() {
} }
EX hyperpoint move_destination_vec(int d) { EX hyperpoint move_destination_vec(int d) {
hyperpoint Forward = prod ? hpxy3(1,0,0) : tC0(pushone()); hyperpoint Forward = prod ? forward_dir(1) : tC0(pushone());
if(WDIM == 2) return spin(-d * M_PI/4) * tC0(pushone()); if(WDIM == 2) return spin(-d * M_PI/4) * tC0(pushone());
// else if(WDIM == 2 && pmodel == mdPerspective) return cspin(0, 2, d * M_PI/4) * tC0(pushone()); // else if(WDIM == 2 && pmodel == mdPerspective) return cspin(0, 2, d * M_PI/4) * tC0(pushone());
// else if(WDIM == 2) return spin(-d * M_PI/4) * tC0(pushone()); // else if(WDIM == 2) return spin(-d * M_PI/4) * tC0(pushone());

View File

@ -437,6 +437,20 @@ void geometry_information::prepare_basics() {
goto finish; goto finish;
} }
if(prod) {
auto t = this;
product::in_underlying_geometry([&] {
t->rhexf = cgi.rhexf;
t->hexf = cgi.hexf;
t->crossf = cgi.crossf;
t->hcrossf = cgi.crossf;
t->tessf = cgi.tessf;
t->hexhexdist = cgi.hexhexdist;
t->base_distlimit = cgi.base_distlimit-1;
});
goto prod_finish;
}
if((sphere || hyperbolic) && WDIM == 3 && !binarytiling) { if((sphere || hyperbolic) && WDIM == 3 && !binarytiling) {
rhexf = hexf = 0.378077; rhexf = hexf = 0.378077;
crossf = hcrossf = 0.620672; crossf = hcrossf = 0.620672;
@ -512,6 +526,8 @@ void geometry_information::prepare_basics() {
if(binarytiling) binary::build_tmatrix(); if(binarytiling) binary::build_tmatrix();
#endif #endif
prod_finish:
scalefactor = crossf / hcrossf7; scalefactor = crossf / hcrossf7;
orbsize = crossf; orbsize = crossf;

View File

@ -1345,7 +1345,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t
char xch = minf[m].glyph; char xch = minf[m].glyph;
transmatrix V = V1; transmatrix V = V1;
if(WDIM == 3 && (classflag(m) & CF_FACE_UP) && where) V = V1 * cspin(0, 2, M_PI/2); if(WDIM == 3 && (classflag(m) & CF_FACE_UP) && where && !prod) V = V1 * cspin(0, 2, M_PI/2);
// if(GDIM == 3) V = V * cspin(0, 2, M_PI/2); // if(GDIM == 3) V = V * cspin(0, 2, M_PI/2);
@ -2749,7 +2749,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m
else { else {
// other monsters face the player // other monsters face the player
if(!nospins) { if(!nospins && !prod) {
if(WDIM == 2) { if(WDIM == 2) {
hyperpoint V0 = inverse(cwtV) * tC0(Vs); hyperpoint V0 = inverse(cwtV) * tC0(Vs);
hyperpoint V1 = spintox(V0) * V0; hyperpoint V1 = spintox(V0) * V0;

View File

@ -132,8 +132,8 @@ const static transmatrix pispin = diag(-1,-1,1,1);
// central symmetry // central symmetry
const static transmatrix centralsym = diag(-1,-1,-1,-1); const static transmatrix centralsym = diag(-1,-1,-1,-1);
inline hyperpoint hpxyz(ld x, ld y, ld z) { return GDIM == 2 ? hyperpoint(x,y,z,0) : hyperpoint(x,y,0,z); } inline hyperpoint hpxyz(ld x, ld y, ld z) { return MDIM == 3 ? hyperpoint(x,y,z,0) : hyperpoint(x,y,0,z); }
inline hyperpoint hpxyz3(ld x, ld y, ld z, ld w) { return GDIM == 2 ? hyperpoint(x,y,w,0) : hyperpoint(x,y,z,w); } inline hyperpoint hpxyz3(ld x, ld y, ld z, ld w) { return MDIM == 3 ? hyperpoint(x,y,w,0) : hyperpoint(x,y,z,w); }
inline hyperpoint point3(ld x, ld y, ld z) { return hyperpoint(x,y,z,0); } inline hyperpoint point3(ld x, ld y, ld z) { return hyperpoint(x,y,z,0); }
inline hyperpoint point31(ld x, ld y, ld z) { return hyperpoint(x,y,z,1); } inline hyperpoint point31(ld x, ld y, ld z) { return hyperpoint(x,y,z,1); }
inline hyperpoint point2(ld x, ld y) { return hyperpoint(x,y,0,0); } inline hyperpoint point2(ld x, ld y) { return hyperpoint(x,y,0,0); }
@ -450,7 +450,7 @@ EX transmatrix euaffine(hyperpoint h) {
EX transmatrix cpush(int cid, ld alpha) { EX transmatrix cpush(int cid, ld alpha) {
transmatrix T = Id; transmatrix T = Id;
if(prod && cid == 2) if(prod && cid == 2)
return mscale(Id, exp(alpha)); return mscale(Id, alpha);
if(nonisotropic) if(nonisotropic)
return eupush3(cid == 0 ? alpha : 0, cid == 1 ? alpha : 0, cid == 2 ? alpha : 0); return eupush3(cid == 0 ? alpha : 0, cid == 1 ? alpha : 0, cid == 2 ? alpha : 0);
T[LDIM][LDIM] = T[cid][cid] = cos_auto(alpha); T[LDIM][LDIM] = T[cid][cid] = cos_auto(alpha);
@ -473,6 +473,7 @@ EX bool eqmatrix(transmatrix A, transmatrix B, ld eps IS(.01)) {
#if MAXMDIM >= 4 #if MAXMDIM >= 4
// in the 3D space, move the point h orthogonally to the (x,y) plane by z units // in the 3D space, move the point h orthogonally to the (x,y) plane by z units
EX hyperpoint orthogonal_move(const hyperpoint& h, ld z) { EX hyperpoint orthogonal_move(const hyperpoint& h, ld z) {
if(prod) return zshift(h, z);
if(!hyperbolic) return rgpushxto0(h) * cpush(2, z) * C0; if(!hyperbolic) return rgpushxto0(h) * cpush(2, z) * C0;
if(nil) return nisot::translate(h) * cpush0(2, z); if(nil) return nisot::translate(h) * cpush0(2, z);
if(translatable) return hpxy3(h[0], h[1], h[2] + z); if(translatable) return hpxy3(h[0], h[1], h[2] + z);
@ -622,7 +623,7 @@ EX transmatrix ggpushxto0(const hyperpoint& H, ld co) {
} }
if(prod) { if(prod) {
auto d = product_decompose(H); auto d = product_decompose(H);
return mscale(PIU(ggpushxto0(d.second, co)), exp(d.first * co)); return mscale(PIU(ggpushxto0(d.second, co)), d.first * co);
} }
transmatrix res = Id; transmatrix res = Id;
if(sqhypot_d(GDIM, H) < 1e-12) return res; if(sqhypot_d(GDIM, H) < 1e-12) return res;
@ -764,7 +765,7 @@ EX transmatrix inverse(const transmatrix& T) {
EX pair<ld, hyperpoint> product_decompose(hyperpoint h) { EX pair<ld, hyperpoint> product_decompose(hyperpoint h) {
ld z = zlevel(h); ld z = zlevel(h);
return make_pair(z, mscale(h, exp(-z))); return make_pair(z, mscale(h, -z));
} }
// distance between mh and 0 // distance between mh and 0
@ -829,6 +830,7 @@ EX ld hdist(const hyperpoint& h1, const hyperpoint& h2) {
EX hyperpoint mscale(const hyperpoint& t, double fac) { EX hyperpoint mscale(const hyperpoint& t, double fac) {
if(GDIM == 3 && !prod) return cpush(2, fac) * t; if(GDIM == 3 && !prod) return cpush(2, fac) * t;
if(prod) fac = exp(fac);
hyperpoint res; hyperpoint res;
for(int i=0; i<MDIM; i++) for(int i=0; i<MDIM; i++)
res[i] = t[i] * fac; res[i] = t[i] * fac;
@ -840,6 +842,7 @@ EX transmatrix mscale(const transmatrix& t, double fac) {
// if(pmodel == mdFlatten) { transmatrix u = t; u[2][LDIM] -= fac; return u; } // if(pmodel == mdFlatten) { transmatrix u = t; u[2][LDIM] -= fac; return u; }
return t * cpush(2, fac); return t * cpush(2, fac);
} }
if(prod) fac = exp(fac);
transmatrix res; transmatrix res;
for(int i=0; i<MDIM; i++) for(int j=0; j<MDIM; j++) for(int i=0; i<MDIM; i++) for(int j=0; j<MDIM; j++)
res[i][j] = t[i][j] * fac; res[i][j] = t[i][j] * fac;
@ -912,7 +915,7 @@ EX hyperpoint orthogonal_of_C0(hyperpoint h0, hyperpoint h1, hyperpoint h2) {
EX hyperpoint zshift(hyperpoint x, ld z) { EX hyperpoint zshift(hyperpoint x, ld z) {
if(GDIM == 3 && WDIM == 2) return rgpushxto0(x) * cpush0(2, z); if(GDIM == 3 && WDIM == 2) return rgpushxto0(x) * cpush0(2, z);
else if(prod) return mscale(x, exp(z)); else if(prod) return mscale(x, z);
else return mscale(x, z); else return mscale(x, z);
} }

View File

@ -1353,7 +1353,7 @@ EX void centerpc(ld aspd) {
auto d = product_decompose(H); auto d = product_decompose(H);
ld dist = -d.first / R * aspd; ld dist = -d.first / R * aspd;
if(abs(dist) > abs(d.first)) dist = -d.first; if(abs(dist) > abs(d.first)) dist = -d.first;
View = mscale(View, exp(dist)); View = mscale(View, dist);
aspd *= sqrt(R*R - d.first * d.first) / R; aspd *= sqrt(R*R - d.first * d.first) / R;
} }
@ -1377,9 +1377,11 @@ EX void optimizeview() {
if(prod) { if(prod) {
ld z = zlevel(tC0(View)); ld z = zlevel(tC0(View));
View = mscale(View, exp(-z)); View = mscale(View, -z);
product::in_underlying_geometry(optimizeview); product::in_underlying_geometry(optimizeview);
View = mscale(View, exp(z)); if(z > product::plevel / 2) { product::current_view_level--; z -= product::plevel; }
if(z < -product::plevel / 2) { product::current_view_level++; z += product::plevel; }
View = mscale(View, z);
return; return;
} }
@ -1473,6 +1475,7 @@ EX void resetview() {
else centerover = cwt; else centerover = cwt;
cwtV = View; cwtV = View;
nisot::local_perspective = Id; nisot::local_perspective = Id;
if(prod) product::current_view_level = product::get_where(cwt.at).second;
// SDL_LockSurface(s); // SDL_LockSurface(s);
// SDL_UnlockSurface(s); // SDL_UnlockSurface(s);
} }

View File

@ -553,7 +553,6 @@ EX namespace product {
underlying_cgip = cgip; underlying_cgip = cgip;
geometry = gProduct; geometry = gProduct;
ginf[gProduct] = ginf[underlying]; ginf[gProduct] = ginf[underlying];
ginf[gProduct].sides += 2;
ginf[gProduct].cclass = gcProduct; ginf[gProduct].cclass = gcProduct;
ginf[gProduct].flags |= qEXPERIMENTAL; ginf[gProduct].flags |= qEXPERIMENTAL;
pmodel = mdPerspective; pmodel = mdPerspective;
@ -561,6 +560,8 @@ EX namespace product {
EX ld plevel = 1; EX ld plevel = 1;
EX int current_view_level;
hrmap *pmap; hrmap *pmap;
geometry_information *pcgip; geometry_information *pcgip;
@ -599,7 +600,7 @@ EX namespace product {
cell* gamestart() override { return getCell(underlying_map->gamestart(), 0); } cell* gamestart() override { return getCell(underlying_map->gamestart(), 0); }
transmatrix relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) override { transmatrix relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) override {
return in_underlying([&] { return calc_relative_matrix(where[c2].first, where[c1].first, point_hint); }) * mscale(Id, exp(plevel * (where[c2].second - where[c1].second))); return in_underlying([&] { return calc_relative_matrix(where[c2].first, where[c1].first, point_hint); }) * mscale(Id, plevel * (where[c2].second - where[c1].second));
} }
hrmap_product() { hrmap_product() {
@ -611,12 +612,14 @@ EX namespace product {
} }
}; };
cell *get_at(cell *base, int level) { EX cell *get_at(cell *base, int level) {
return ((hrmap_product*)currentmap)->getCell(base, level); return ((hrmap_product*)currentmap)->getCell(base, level);
} }
EX pair<cell*, int> get_where(cell *c) { return ((hrmap_product*)currentmap)->where[c]; }
void drawcell_stack(cell *c, transmatrix V, int spinv, bool mirrored) { void drawcell_stack(cell *c, transmatrix V, int spinv, bool mirrored) {
in_actual([&] { for(int z=-5; z<=5; z++) drawcell(get_at(c, z), V * mscale(Id, exp(plevel * z)), spinv, mirrored); }); in_actual([&] { for(int z=-5; z<=5; z++) drawcell(get_at(c, current_view_level+z), V * mscale(Id, plevel * z), spinv, mirrored); });
} }
void find_cell_connection(cell *c, int d) { void find_cell_connection(cell *c, int d) {

View File

@ -755,7 +755,7 @@ vector<hyperpoint> make5(hyperpoint a, hyperpoint b, hyperpoint c) {
void geometry_information::create_wall3d() { void geometry_information::create_wall3d() {
if(WDIM == 2) return; if(WDIM == 2) return;
int howmany = penrose ? 22 : S7; int howmany = penrose ? 22 : prod ? S7+2 : S7;
shWall3D.resize(howmany); shWall3D.resize(howmany);
shPlainWall3D.resize(howmany); shPlainWall3D.resize(howmany);
shWireframe3D.resize(howmany); shWireframe3D.resize(howmany);
@ -857,15 +857,15 @@ void geometry_information::create_wall3d() {
if(prod) { if(prod) {
cell model; cell model;
model.type = S7-2; model.type = S7;
for(int i=0; i<S7-2; i++) for(int i=0; i<S7; i++)
make_wall(i, {product::get_corner(&model, i, -1), product::get_corner(&model, i, +1), product::get_corner(&model, i+1, +1), product::get_corner(&model, i+1, -1)}); make_wall(i, {product::get_corner(&model, i, -1), product::get_corner(&model, i, +1), product::get_corner(&model, i+1, +1), product::get_corner(&model, i+1, -1)});
for(int a: {0,1}) { for(int a: {0,1}) {
vector<hyperpoint> l; vector<hyperpoint> l;
int z = a ? 1 : -1; int z = a ? 1 : -1;
for(int i=0; i<S7-2; i++) for(int i=0; i<S7; i++)
l.push_back(product::get_corner(&model, i, z)); l.push_back(product::get_corner(&model, i, z));
make_wall(S7-2+a, l); make_wall(S7+a, l);
} }
} }