mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 14:02:59 +00:00 
			
		
		
		
	Triangle vizualization now includes the network
This commit is contained in:
		| @@ -12,10 +12,13 @@ | ||||
|  | ||||
| // ./hyper -geo Nil -nilwidth .9 -canvas x -tstep 1 -nilperiod 1 10 1 -triset 32 31 992 | ||||
|  | ||||
| // network of triangles: | ||||
|  | ||||
| // ./hyper -geo Nil -canvas x -tri-net | ||||
|  | ||||
| namespace hr { | ||||
|  | ||||
| // each color group (i.e., each face direction) is a different hpcshape | ||||
| hpcshape ptriangle[6]; | ||||
| bool net = false; | ||||
|  | ||||
| EX hyperpoint lerp(hyperpoint a0, hyperpoint a1, ld x) { | ||||
|   return a0 + (a1-a0) * x; | ||||
| @@ -35,20 +38,32 @@ int how1 = how - 1; | ||||
| // precision: number of substeps to simulate (best if divisible by how and how1) | ||||
| int isteps = 4 * 1024; | ||||
|  | ||||
| /* make the impossible triangle shape */ | ||||
| void make_shape() { | ||||
| struct triangledata { | ||||
|   hyperpoint at; | ||||
|   bool computed; | ||||
|   int tcolor; | ||||
|   int id; | ||||
|   // each color group (i.e., each face direction) is a different hpcshape | ||||
|   triangledata(hyperpoint h) : at(h), computed(false) { tcolor = 0; id = 0; } | ||||
|   }; | ||||
|  | ||||
|   static bool done = false; | ||||
|   if(done) return; | ||||
|   done = true; | ||||
| struct trianglemaker { | ||||
|  | ||||
|   // four main axes of the regular tetrahedron, rotated so that ds[3] points to (0,0,1) | ||||
|   map<cell*, vector<triangledata> > tds; | ||||
|  | ||||
|   array<hpcshape, 6> ptriangle; | ||||
|  | ||||
|   array<hpcshape, 6> pcube; | ||||
|    | ||||
|   hyperpoint ds[4], uds[4], dmoves[6]; | ||||
|    | ||||
|   ld scale; | ||||
|    | ||||
|   void init() { | ||||
|  | ||||
|     ld rest = sqrt(8/9.); | ||||
|     ld rex = sqrt(1 - 1/9. - pow(rest/2., 2)); | ||||
|    | ||||
|   hyperpoint ds[4]; | ||||
|    | ||||
|     ds[0] = point3(rex, -rest/2, -1/3.); | ||||
|     ds[1] = point3(0, rest, -1/3.); | ||||
|     ds[2] = point3(-rex, -rest/2, -1/3.); | ||||
| @@ -81,13 +96,8 @@ void make_shape() { | ||||
|       lastz = at[2]; lasta  =a; | ||||
|       } | ||||
|      | ||||
|   println(hlog, "ca = ", ca); | ||||
|    | ||||
|   ld scale = .2; | ||||
|    | ||||
|     // compute the shift between the cubes | ||||
|    | ||||
|   array<hyperpoint, 4> uds; | ||||
|     for(int d=0; d<3; d++) { | ||||
|       hyperpoint at = start; | ||||
|       for(int i=0; i<isteps/how; i++) { | ||||
| @@ -96,7 +106,7 @@ void make_shape() { | ||||
|       uds[d] = (at - start) / 2.; | ||||
|       } | ||||
|      | ||||
|   println(hlog, "uds = ", uds); | ||||
|     // println(hlog, "uds = ", uds); | ||||
|    | ||||
|     for(int a=0; a<3; a++) println(hlog, sqhypot_d(3, inverse_exp(start + ds[a] * ca, iTable, false))); | ||||
|    | ||||
| @@ -161,30 +171,9 @@ void make_shape() { | ||||
|         } | ||||
|       } | ||||
|        | ||||
|   scale = 1.; | ||||
|    | ||||
|   // build all the faces | ||||
|     scale = 1; | ||||
|  | ||||
|     for(int si=0; si<6; si++) { | ||||
|     cgi.bshape(ptriangle[si], PPR::WALL); | ||||
|     hyperpoint at = start; | ||||
|      | ||||
|     for(int d=0; d<3; d++) { | ||||
|        | ||||
|       int d1 = (d+1) % 3; | ||||
|       int d2 = (d+2) % 3; | ||||
|  | ||||
|       hyperpoint path[isteps+1]; | ||||
|       for(int i=0; i<isteps; i++) { | ||||
|         path[i] = at; | ||||
|         at = nisot::translate(at) * (start + ds[d] * ca); | ||||
|         } | ||||
|       path[isteps] = at; | ||||
|        | ||||
|       auto &u = uds[d]; | ||||
|       auto &v = uds[d1]; | ||||
|       auto &w = uds[d2]; | ||||
|        | ||||
|       auto textured_square = [&] (auto f) { | ||||
|         texture_order([&] (ld ix, ld iy) { f(.5 + ix/2 + iy/2, .5 + ix/2 - iy/2); }); | ||||
|         texture_order([&] (ld ix, ld iy) { f(.5 - ix/2 - iy/2, .5 - ix/2 + iy/2); }); | ||||
| @@ -192,6 +181,58 @@ void make_shape() { | ||||
|         texture_order([&] (ld ix, ld iy) { f(.5 - ix/2 + iy/2, .5 + ix/2 + iy/2); }); | ||||
|         }; | ||||
|    | ||||
|       auto cube_at = [&] (hyperpoint online) { | ||||
|    | ||||
|         auto sidesquare1 = [&] (hyperpoint a00, hyperpoint a01, hyperpoint a10, hyperpoint a11) { | ||||
|           textured_square( [&] (ld ix, ld iy) { | ||||
|             hyperpoint shf = lerp(lerp(a00, a01, ix), lerp(a10, a11, ix), iy); | ||||
|             if(scale) shf = shf * scale - start * (scale-1); | ||||
|             cgi.hpcpush(nisot::translate(online) * (shf)); | ||||
|             }); | ||||
|           }; | ||||
|              | ||||
|         if(si == 0) sidesquare1(verts[0], verts[2], verts[4], verts[6]); | ||||
|         if(si == 1) sidesquare1(verts[1], verts[3], verts[5], verts[7]); | ||||
|         if(si == 2) sidesquare1(verts[0], verts[1], verts[4], verts[5]); | ||||
|         if(si == 3) sidesquare1(verts[2], verts[3], verts[6], verts[7]); | ||||
|         if(si == 4) sidesquare1(verts[0], verts[1], verts[2], verts[3]); | ||||
|         if(si == 5) sidesquare1(verts[4], verts[5], verts[6], verts[7]); | ||||
|         }; | ||||
|        | ||||
|       scale = 2; | ||||
|       cgi.bshape(pcube[si], PPR::WALL); | ||||
|       cube_at(start); | ||||
|       cgi.last->flags |= POLY_TRIANGLES; | ||||
|       cgi.last->tinf = &floor_texture_vertices[0]; | ||||
|       cgi.last->texture_offset = 0; | ||||
|        | ||||
|       scale = 1; | ||||
|        | ||||
|       cgi.bshape(ptriangle[si], PPR::WALL); | ||||
|       hyperpoint at = start; | ||||
|        | ||||
|       vector<hyperpoint> atx = {start}; | ||||
|        | ||||
|       cube_at(start); | ||||
|    | ||||
|       for(int dx: {0, 1, 2}) { | ||||
|         int d = dx; | ||||
|         if(net) at = start; | ||||
|         else cube_at(at); | ||||
|         int d1 = (d+1) % 3; | ||||
|         int d2 = (d+2) % 3; | ||||
|    | ||||
|         hyperpoint path[isteps+1]; | ||||
|         for(int i=0; i<isteps; i++) { | ||||
|           path[i] = at; | ||||
|           at = nisot::translate(at) * (start + ds[d] * ca * (dx >= 3 ? -1 : 1)); | ||||
|           } | ||||
|         path[isteps] = at; | ||||
|          | ||||
|         auto &u = uds[d]; | ||||
|         auto &v = uds[d1]; | ||||
|         auto &w = uds[d2]; | ||||
|          | ||||
|         auto sidewall = [&] (hyperpoint wide, hyperpoint shift) { | ||||
|           textured_square( [&] (ld ix, ld iy) { | ||||
|             hyperpoint online = path[int(ix * isteps + .1)]; | ||||
| @@ -210,15 +251,6 @@ void make_shape() { | ||||
|             }); | ||||
|           }; | ||||
|          | ||||
|       auto sidesquare1 = [&] (hyperpoint a00, hyperpoint a01, hyperpoint a10, hyperpoint a11, ld p) { | ||||
|         hyperpoint online = path[int(p * isteps + .1)]; | ||||
|         textured_square( [&] (ld ix, ld iy) { | ||||
|           hyperpoint shf = lerp(lerp(a00, a01, ix), lerp(a10, a11, ix), iy); | ||||
|           shf *= scale; | ||||
|           cgi.hpcpush(nisot::translate(online) * (shf)); | ||||
|           }); | ||||
|         }; | ||||
|        | ||||
|         if(shape == 0) { | ||||
|           if(si == d2*2) sidewall(v, w); | ||||
|           if(si == d1*2) sidewall(w, v); | ||||
| @@ -231,26 +263,13 @@ void make_shape() { | ||||
|           if(si == d*2+1) sidesquare(w, v, -u, 0); | ||||
|           } | ||||
|          | ||||
|       if(shape == 1) for(int a=0; a<how1; a++) { | ||||
|         if(shape == 1) for(int a=1; a<how1; a++) { | ||||
|           ld c = a * 1. / how1; | ||||
|            | ||||
| /* | ||||
|         if(si == d*2) sidesquare(v, w, u, c); | ||||
|         if(si == d*2+1) sidesquare(w, v, -u, c); | ||||
|         if(si == d1*2) sidesquare(w, u, v, c); | ||||
|         if(si == d1*2+1) sidesquare(u, w, -v, c); | ||||
|         if(si == d2*2) sidesquare(u, v, w, c); | ||||
|         if(si == d2*2+1) sidesquare(v, u, -w, c); | ||||
| */ | ||||
|  | ||||
|         if(si == 0) sidesquare1(verts[0], verts[2], verts[4], verts[6], c); | ||||
|         if(si == 1) sidesquare1(verts[1], verts[3], verts[5], verts[7], c); | ||||
|         if(si == 2) sidesquare1(verts[0], verts[1], verts[4], verts[5], c); | ||||
|         if(si == 3) sidesquare1(verts[2], verts[3], verts[6], verts[7], c); | ||||
|         if(si == 4) sidesquare1(verts[0], verts[1], verts[2], verts[3], c); | ||||
|         if(si == 5) sidesquare1(verts[4], verts[5], verts[6], verts[7], c); | ||||
|          | ||||
|           cube_at(path[int(c * isteps + .1)]); | ||||
|           } | ||||
|          | ||||
|         dmoves[d] = at;         | ||||
|         } | ||||
|      | ||||
|       cgi.last->flags |= POLY_TRIANGLES; | ||||
| @@ -259,19 +278,191 @@ void make_shape() { | ||||
|       cgi.finishshape(); | ||||
|       cgi.extra_vertices(); | ||||
|       } | ||||
|  | ||||
|     tds[cwt.at].emplace_back(start); | ||||
|     dmoves[3] = inverse(nisot::translate(dmoves[0])) * C0; | ||||
|     dmoves[4] = inverse(nisot::translate(dmoves[1])) * C0; | ||||
|     dmoves[5] = inverse(nisot::translate(dmoves[2])) * C0; | ||||
|     } | ||||
|  | ||||
|   void compute(triangledata &td, cell *c) { | ||||
|     if(td.computed) return; | ||||
|     td.computed = true; | ||||
|     if(!net) return; | ||||
|  | ||||
|     hyperpoint at; | ||||
|      | ||||
|     for(int d=0; d<6; d++) { | ||||
|       hyperpoint at = nisot::translate(td.at) * dmoves[d]; | ||||
|       cell *c0 = c; | ||||
|       virtualRebase(c0, at); | ||||
|        | ||||
|       bool newat = true; | ||||
|       for(auto& td: tds[c0]) { | ||||
|         ld d = sqhypot_d(3, at - td.at); | ||||
|         if(d < .01) {       | ||||
|           if(d>1e-5) println(hlog, "d = ", d); | ||||
|           newat = false; | ||||
|           } | ||||
|         } | ||||
|        | ||||
|       if(newat) { | ||||
|         triangledata ntd = at; | ||||
|         ntd.id = td.id + 1; | ||||
|         tds[c0].push_back(ntd); | ||||
|         tds[c0].back().tcolor = (td.tcolor + (d < 3 ? 1 : 2)) % 3; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|      | ||||
|   }; | ||||
|  | ||||
| trianglemaker *mkr; | ||||
|  | ||||
| // Magic Cube (aka Rubik Cube) colors | ||||
|  | ||||
| color_t magiccolors[6] = { 0xFFFF00FF, 0xFFFFFFFF, 0x0000FFFF, 0x00FF00FF, 0xFF0000FF, 0xFF8000FF}; | ||||
|  | ||||
| bool draw_ptriangle(cell *c, const transmatrix& V) { | ||||
|   make_shape(); | ||||
| #define CTO (isize(cnts)) | ||||
|  | ||||
|   if(c == cwt.at) { | ||||
|   vector<int> cnts; | ||||
|   vector<ld> coef; | ||||
|   int valid_from; | ||||
|   int tested_to; | ||||
|   int coefficients_known; | ||||
|  | ||||
| bool verify(int id) { | ||||
|   if(id < isize(coef)) return false; | ||||
|   ld res = 0; | ||||
|   for(int t=0; t<isize(coef); t++) | ||||
|     res += coef[t] * cnts[id-t-1]; | ||||
|   return abs(res - cnts[id]) < .5; | ||||
|   } | ||||
|  | ||||
|  | ||||
| int valid(int v, int step) { | ||||
|   if(step < 0) return 0; | ||||
|   if(step+v+v+5 >= CTO) return 0; | ||||
|   ld matrix[100][128]; | ||||
|   for(int i=0; i<v; i++) | ||||
|   for(int j=0; j<v+1; j++) | ||||
|     matrix[i][j] = cnts[step+i+j]; | ||||
|    | ||||
|   for(int k=0; k<v; k++) { | ||||
|     int nextrow = k; | ||||
|     while(nextrow < v && std::abs(matrix[nextrow][k]) < 1e-6) | ||||
|       nextrow++; | ||||
|     if(nextrow == v) return 1; | ||||
|     if(nextrow != k) { | ||||
|       // printf("swap %d %d\n", k, nextrow); | ||||
|       for(int l=0; l<=v; l++) swap(matrix[k][l], matrix[nextrow][l]); | ||||
|       // display(); | ||||
|       } | ||||
|     ld divv = 1. / matrix[k][k]; | ||||
|     for(int k1=k; k1<=v; k1++) matrix[k][k1] *= divv; | ||||
|     // printf("divide %d\n", k); | ||||
|     // display(); | ||||
|     for(int k1=k+1; k1<v; k1++) if(matrix[k1][k] != 0) { | ||||
|       ld coef = -matrix[k1][k]; | ||||
|       for(int k2=k; k2<=v; k2++) matrix[k1][k2] += matrix[k][k2] * coef; | ||||
|       } | ||||
|     // printf("zeros below %d\n", k); | ||||
|     // display(); | ||||
|     } | ||||
|    | ||||
|   for(int k=v-1; k>=0; k--) | ||||
|   for(int l=k-1; l>=0; l--) | ||||
|     if(matrix[l][k]) matrix[l][v] -= matrix[l][k] * matrix[k][v]; | ||||
|    | ||||
|   coef.resize(v); | ||||
|   for(int i=0; i<v; i++) coef[i] = matrix[v-1-i][v]; | ||||
|      | ||||
|   println(hlog, "coef = ", coef); | ||||
|   for(int t=step+v; t<step+v+v+5; t++) { | ||||
|     println(hlog, "verify(", t, ") = ", verify(t)); | ||||
|     if(!verify(t)) return 2; | ||||
|     } | ||||
|   println(hlog, "got here"); | ||||
|   tested_to = step+v+v+5; | ||||
|   while(tested_to < CTO) { | ||||
|     if(!verify(tested_to)) return 2; | ||||
|     tested_to++; | ||||
|     } | ||||
|    | ||||
|   valid_from = step+v; | ||||
|   return 3; | ||||
|   } | ||||
|  | ||||
| void find_coefficients() { | ||||
|   if(coefficients_known) return; | ||||
|   for(int v=1; v<25; v++)  | ||||
|   for(int step=0; step<1000; step++) {  | ||||
|     int val = valid(v, step); | ||||
|     if(val == 0) break; | ||||
|     println(hlog, "v=", v, "step=", step, " val=", val); | ||||
|     if(val == 3) { coefficients_known = 2; return; } | ||||
|     } | ||||
|   coefficients_known = 1; | ||||
|   } | ||||
|  | ||||
| void growthrate() { | ||||
|   /* | ||||
|   for(int a=0; a<CTO; a++) { | ||||
|     int cnt = 0; | ||||
|     map<cell*, int> howmany; | ||||
|     for(auto& p: mkr->tds) cnt += (howmany[p.first] = isize(p.second)); | ||||
|     for(auto& p: howmany) for(int i=0; i<p.second; i++) { | ||||
|       // println(hlog, p.first, mkr->tds[p.first][i].at, mkr->tds[p.first][i].computed); | ||||
|       mkr->compute(mkr->tds[p.first][i], p.first); | ||||
|       } | ||||
|     println(hlog, "cnt = ", cnt, " / ", cnt / pow(1+a, 4)); | ||||
|     cnts[a] = cnt; | ||||
|     if(a >= 4) println(hlog, "D4 = ", cnts[a-4] - 4 * cnts[a-3] + 6 * cnts[a-2] - 4 * cnts[a-1] + cnts[a]); | ||||
|     println(hlog, "cnts = ", cnts); | ||||
|     }*/ | ||||
|    | ||||
|   cnts = {1,7,31,113,299,681,1363,2501,4181,6570,9874,14256,20027,27601,37171,48815,62993,79912,100181,123868,151680,184339,222347,265733,314523,369424,431221,500952,578350,665794,763300,871250,988488,1116635,1256293,1409165,1575969,1758327,1958977,2174877}; | ||||
|   find_coefficients(); | ||||
|    | ||||
|   println(hlog, "coefficients_known = ", coefficients_known); | ||||
|   if(coefficients_known == 2) { | ||||
|     string fmt = "a(d+" + its(isize(coef)) + ") = "; | ||||
|     bool first = true; | ||||
|     for(int i=0; i<isize(coef); i++) if(coef[i]) { | ||||
|       if(first && coef[i] == 1) ; | ||||
|       else if(first) fmt += its(coef[i]); | ||||
|       else if(coef[i] == 1) fmt += " + "; | ||||
|       else if(coef[i] == -1) fmt += " - "; | ||||
|       else if(coef[i] > 1) fmt += " + " + its(coef[i]); | ||||
|       else if(coef[i] < -1) fmt += " - " + its(-coef[i]); | ||||
|       fmt += "a(d"; | ||||
|       if(i != isize(coef) - 1) | ||||
|         fmt += "+" + its(isize(coef) - 1 - i); | ||||
|       fmt += ")"; | ||||
|       first = false; | ||||
|       } | ||||
|     fmt += " (d>" + its(valid_from-1) + ")"; | ||||
|     println(hlog, fmt); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| color_t tcolors[3] = { 0xFF0000FF, 0x00FF00FF, 0x0000FFFF }; | ||||
|  | ||||
|  | ||||
| bool draw_ptriangle(cell *c, const transmatrix& V) { | ||||
|    | ||||
|   if(!mkr) { mkr = new trianglemaker; mkr->init();  | ||||
|     growthrate(); | ||||
|     } | ||||
|    | ||||
|   for(auto& td: mkr->tds[c]) { | ||||
|     mkr->compute(td, c); | ||||
|     for(int side=0; side<6; side++) { | ||||
|       auto &s = queuepoly(V, ptriangle[side], magiccolors[side]); | ||||
|       auto &s = queuepoly(V * nisot::translate(td.at), mkr->ptriangle[side], magiccolors[side]); | ||||
|       ensure_vertex_number(*s.tinf, s.cnt); | ||||
|  | ||||
|       /* auto& s1 = queuepoly(V * nisot::translate(td.at), mkr->pcube[side], gradient(tcolors[td.tcolor], magiccolors[side], 0, .2, 1)); | ||||
|       ensure_vertex_number(*s1.tinf, s1.cnt); */ | ||||
|       } | ||||
|     } | ||||
|  | ||||
| @@ -290,6 +481,9 @@ auto hchook = addHook(hooks_drawcell, 100, draw_ptriangle) | ||||
|     shift(); how1 = argi(); | ||||
|     shift(); isteps = argi(); | ||||
|     } | ||||
|   else if(argis("-tri-net")) { | ||||
|     net = true; | ||||
|     } | ||||
|   else return 1; | ||||
|   return 0; | ||||
|   }); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue