diff --git a/3d-models.cpp b/3d-models.cpp index 8b60782a..aa721011 100644 --- a/3d-models.cpp +++ b/3d-models.cpp @@ -30,10 +30,15 @@ vector geometry_information::get_shape(hpcshape sh) { return res; } +hyperpoint normalize_flat(hyperpoint h) { + if(prod) return product_decompose(h).second; + return normalize(h); + } + hyperpoint get_center(const vector& vh) { hyperpoint h = Hypc; for(auto h1: vh) h = h + h1; - return normalize(h); + return normalize_flat(h); } ld zc(ld z) { @@ -125,7 +130,7 @@ void geometry_information::add_texture(hpcshape& sh) { vector scaleshape(const vector& vh, ld s) { vector 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; } @@ -326,8 +331,8 @@ void geometry_information::make_armor_3d(hpcshape& sh, int kind) { for(hyperpoint h: body) { array p; - p[0] = h[0] / h[3]; - p[1] = h[1] / h[3]; + p[0] = h[0] / h[LDIM]; + p[1] = h[1] / h[LDIM]; pts[0].emplace_back(p); } @@ -394,8 +399,8 @@ void geometry_information::make_head_3d(hpcshape& sh) { for(hyperpoint h: head) { array p; - p[0] = h[0] / h[3]; - p[1] = h[1] / h[3]; + p[0] = h[0] / h[LDIM]; + p[1] = h[1] / h[LDIM]; pts[0].emplace_back(p); } @@ -476,6 +481,11 @@ void geometry_information::make_skeletal(hpcshape& sh, ld 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) { auto body = get_shape(sh); 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 h1 = body[(i+1) % isize(body)]; for(int s=0; sflags |= POLY_TRIANGLES; @@ -537,7 +547,7 @@ void geometry_information::make_revolution_cut(hpcshape &sh, int each, ld push, for(int i=0; iflags |= POLY_TRIANGLES; @@ -600,26 +610,40 @@ void geometry_information::animate_bird(hpcshape& orig, hpcshape_animated& anima // 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) { dynamicval d(vid.texture_step, 8); texture_order([&] (ld x, ld y) { ld z = 1-x-y; - ld r = scalefactor * hcrossf7 * (0 + pow(max(x,max(y,z)), .3) * 0.8); - hyperpoint h = rspintox(a*x+b*y+c*z) * xpush0(r); + ld r = scalefactor * hcrossf7 * (0 + pow(max(x,max(y,z)), .3) * 0.8) * (prod ? .5 : 1); + hyperpoint h = dir_to_point(dir_setlength(a*x+b*y+c*z, r)); hpcpush(h); }); } void geometry_information::balltriangle(hyperpoint a, hyperpoint b, hyperpoint c, ld rad, int lev) { if(lev == 0) { - hpcpush(a); - hpcpush(b); - hpcpush(c); + hpcpush(dir_to_point(a)); + hpcpush(dir_to_point(b)); + hpcpush(dir_to_point(c)); } else { - hyperpoint cx = rspintox(mid(a,b)) * xpush0(rad); - hyperpoint ax = rspintox(mid(b,c)) * xpush0(rad); - hyperpoint bx = rspintox(mid(c,a)) * xpush0(rad); + auto midpoint = [&] (hyperpoint h1, hyperpoint h2) { + if(prod) return dir_setlength(h1+h2, 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, c , 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) { bshape(sh, sh.prio); sh.flags |= POLY_TRIANGLES; - hyperpoint tip = xpush0(rad); - hyperpoint atip = xpush0(-rad); + hyperpoint tip = forward_dir(rad); + hyperpoint atip = forward_dir(-rad); ld z = 63.43 * degree; for(int i=0; i<5; i++) { 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) { + if(prod) { + auto d = product_decompose(H); + d.second[2] = d.first; + return d.second; + } hyperpoint res; res[2] = asin_auto(H[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) { hyperpoint center = Hypc; for(int i=eye.s; i 0) center += hpc[i]; - center = normalize(center); + center = normalize_flat(center); // center /= (eye.e - eye.s); ld rad = 0; for(int i=eye.s; i 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); ld mindist = 1e9; - for(int i=0; i 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); if(d < mindist) mindist = d, pos = min(min(pss[i][2], pss[i+1][2]), pss[i+2][2]), qty++; qtyall++; @@ -1086,10 +1116,10 @@ void geometry_information::make_3d_models() { hyperpoint atip = xpush0(-1); ld z = 63.43 * degree; for(int i=0; i<5; i++) { - auto a = cspin(1, 2, (72 * i ) * degree) * spin(z) * xpush0(1); - auto b = cspin(1, 2, (72 * i-72) * degree) * spin(z) * xpush0(1); - auto c = 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) * 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) * forward_dir(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) * forward_dir(1); slimetriangle(tip, a, b, 1, 0); slimetriangle(a, b, c, 1, 0); slimetriangle(b, c, d, 1, 0); diff --git a/control.cpp b/control.cpp index 2b1cdc03..3bbdd7a9 100644 --- a/control.cpp +++ b/control.cpp @@ -113,7 +113,7 @@ EX void remission() { } 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()); // 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()); diff --git a/geometry.cpp b/geometry.cpp index 9e1c4e89..65e660c9 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -437,6 +437,20 @@ void geometry_information::prepare_basics() { 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) { rhexf = hexf = 0.378077; crossf = hcrossf = 0.620672; @@ -512,6 +526,8 @@ void geometry_information::prepare_basics() { if(binarytiling) binary::build_tmatrix(); #endif + prod_finish: + scalefactor = crossf / hcrossf7; orbsize = crossf; diff --git a/graph.cpp b/graph.cpp index 6b8e54d4..0f68c178 100644 --- a/graph.cpp +++ b/graph.cpp @@ -1345,7 +1345,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const transmatrix& V1, color_t char xch = minf[m].glyph; 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); @@ -2749,7 +2749,7 @@ bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, bool m else { // other monsters face the player - if(!nospins) { + if(!nospins && !prod) { if(WDIM == 2) { hyperpoint V0 = inverse(cwtV) * tC0(Vs); hyperpoint V1 = spintox(V0) * V0; diff --git a/hyperpoint.cpp b/hyperpoint.cpp index 9fc3badc..b2990eaf 100644 --- a/hyperpoint.cpp +++ b/hyperpoint.cpp @@ -132,8 +132,8 @@ const static transmatrix pispin = diag(-1,-1,1,1); // central symmetry 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 hpxyz3(ld x, ld y, ld z, ld w) { return GDIM == 2 ? hyperpoint(x,y,w,0) : hyperpoint(x,y,z,w); } +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 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 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); } @@ -450,7 +450,7 @@ EX transmatrix euaffine(hyperpoint h) { EX transmatrix cpush(int cid, ld alpha) { transmatrix T = Id; if(prod && cid == 2) - return mscale(Id, exp(alpha)); + return mscale(Id, alpha); if(nonisotropic) return eupush3(cid == 0 ? alpha : 0, cid == 1 ? alpha : 0, cid == 2 ? alpha : 0); 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 // 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) { + if(prod) return zshift(h, z); if(!hyperbolic) return rgpushxto0(h) * cpush(2, z) * C0; if(nil) return nisot::translate(h) * cpush0(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) { 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; if(sqhypot_d(GDIM, H) < 1e-12) return res; @@ -764,7 +765,7 @@ EX transmatrix inverse(const transmatrix& T) { EX pair product_decompose(hyperpoint 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 @@ -829,6 +830,7 @@ EX ld hdist(const hyperpoint& h1, const hyperpoint& h2) { EX hyperpoint mscale(const hyperpoint& t, double fac) { if(GDIM == 3 && !prod) return cpush(2, fac) * t; + if(prod) fac = exp(fac); hyperpoint res; for(int i=0; i abs(d.first)) dist = -d.first; - View = mscale(View, exp(dist)); + View = mscale(View, dist); aspd *= sqrt(R*R - d.first * d.first) / R; } @@ -1377,9 +1377,11 @@ EX void optimizeview() { if(prod) { ld z = zlevel(tC0(View)); - View = mscale(View, exp(-z)); + View = mscale(View, -z); 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; } @@ -1473,6 +1475,7 @@ EX void resetview() { else centerover = cwt; cwtV = View; nisot::local_perspective = Id; + if(prod) product::current_view_level = product::get_where(cwt.at).second; // SDL_LockSurface(s); // SDL_UnlockSurface(s); } diff --git a/nonisotropic.cpp b/nonisotropic.cpp index bd934689..d3cc7742 100644 --- a/nonisotropic.cpp +++ b/nonisotropic.cpp @@ -553,7 +553,6 @@ EX namespace product { underlying_cgip = cgip; geometry = gProduct; ginf[gProduct] = ginf[underlying]; - ginf[gProduct].sides += 2; ginf[gProduct].cclass = gcProduct; ginf[gProduct].flags |= qEXPERIMENTAL; pmodel = mdPerspective; @@ -561,6 +560,8 @@ EX namespace product { EX ld plevel = 1; + EX int current_view_level; + hrmap *pmap; geometry_information *pcgip; @@ -599,7 +600,7 @@ EX namespace product { cell* gamestart() override { return getCell(underlying_map->gamestart(), 0); } 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() { @@ -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); } + EX pair get_where(cell *c) { return ((hrmap_product*)currentmap)->where[c]; } + 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) { diff --git a/polygons.cpp b/polygons.cpp index 700f09c9..9ee225eb 100644 --- a/polygons.cpp +++ b/polygons.cpp @@ -755,7 +755,7 @@ vector make5(hyperpoint a, hyperpoint b, hyperpoint c) { void geometry_information::create_wall3d() { if(WDIM == 2) return; - int howmany = penrose ? 22 : S7; + int howmany = penrose ? 22 : prod ? S7+2 : S7; shWall3D.resize(howmany); shPlainWall3D.resize(howmany); shWireframe3D.resize(howmany); @@ -857,15 +857,15 @@ void geometry_information::create_wall3d() { if(prod) { cell model; - model.type = S7-2; - for(int i=0; i l; int z = a ? 1 : -1; - for(int i=0; i