1 // Hyperbolic Rogue - Floor Shapes
2
3 // Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details
4
5 /** \file floorshapes.cpp
6 * \brief Adjusting the floor shapes to various geometries.
7 */
8
9 #include "hyper.h"
10 namespace hr {
11 #if CAP_SHAPES
12
13 #if HDR
14 struct qfloorinfo {
15 transmatrix spin;
16 const struct hpcshape *shape;
17 floorshape *fshape;
18 struct textureinfo *tinf;
19 int usershape;
20 };
21
22 extern qfloorinfo qfi;
23 #endif
24
25 EX vector<basic_textureinfo> floor_texture_vertices;
26 EX vector<glvertex> floor_texture_map;
27 EX struct renderbuffer *floor_textures;
28
init_floorshapes()29 void geometry_information::init_floorshapes() {
30 all_escher_floorshapes.clear();
31 all_plain_floorshapes = {
32 &shFloor, &shMFloor, &shMFloor2, &shMFloor3, &shMFloor4,
33 &shFullFloor, &shBigTriangle, &shTriheptaFloor, &shBigHepta
34 };
35
36 for(auto s: all_plain_floorshapes) s->is_plain = true;
37
38 auto init_escher = [this] (escher_floorshape& sh, int s0, int s1, int noft, int s2) {
39 sh.shapeid0 = s0;
40 sh.shapeid1 = s1;
41 sh.noftype = noft;
42 sh.shapeid2 = s2;
43 sh.scale = 1;
44 sh.is_plain = false;
45 all_escher_floorshapes.push_back(&sh);
46 };
47
48 init_escher(shStarFloor, 1, 2, 0, 0);
49 init_escher(shCloudFloor, 3, 4, 0, 0);
50 init_escher(shCrossFloor, 5, 6, 2, 54);
51 init_escher(shChargedFloor, 7, 385, 1, 10);
52 init_escher(shSStarFloor, 11, 12, 0, 0);
53 init_escher(shOverFloor, 13, 15, 1, 14);
54 init_escher(shTriFloor, 17, 18, 0, 385);
55 init_escher(shFeatherFloor, 19, 21, 1, 20);
56 init_escher(shBarrowFloor, 23, 24, 1, 25);
57 init_escher(shNewFloor, 26, 27, 2, 54);
58 init_escher(shTrollFloor, 28, 29, 0, 0);
59 init_escher(shButterflyFloor, 325, 326, 1, 178);
60 init_escher(shLavaFloor, 359, 360, 1, 178);
61 init_escher(shLavaSeabed, 386, 387, 1, 178);
62 init_escher(shSeabed, 334, 335, 0, 0);
63 init_escher(shCloudSeabed, 336, 337, 0, 0);
64 init_escher(shCaveSeabed, 338, 339, 2, 54);
65 init_escher(shPalaceFloor, 45, 46, 0, 385);
66 init_escher(shDemonFloor, 51, 50, 1, 178);
67 init_escher(shCaveFloor, 52, 53, 2, 54);
68 init_escher(shDesertFloor, 55, 56, 0, 4);
69 init_escher(shPowerFloor, 57, 58, 0, 12); /* dragon */
70 init_escher(shRoseFloor, 174, 175, 1, 173);
71 init_escher(shSwitchFloor, 377, 378, 1, 379);
72 init_escher(shTurtleFloor, 176, 177, 1, 178);
73 for(int i: {0,1,2})
74 init_escher(shRedRockFloor[i], 55, 56, 0, 0);
75 init_escher(shDragonFloor, 181, 182, 2, 183); /* dragon */
76
77 int ids = 0;
78 for(auto sh: all_plain_floorshapes) sh->id = ids++;
79 for(auto sh: all_escher_floorshapes) sh->id = ids++;
80 }
81
82 typedef pair<transmatrix, vector<transmatrix>> matrixitem;
83
84 struct mesher {
85 eGeometry g;
86 int sym;
87 ld bspi;
88 hyperpoint lcorner, rcorner, mfar[2], vfar[4];
89 };
90
msh(eGeometry g,int sym,ld main,ld v0,ld v1,ld bspi,ld scale)91 mesher msh(eGeometry g, int sym, ld main, ld v0, ld v1, ld bspi, ld scale) {
92 main *= scale; v0 *= scale; v1 *= scale;
93 mesher m;
94 m.sym = sym;
95 m.bspi = bspi;
96 dynamicval<eGeometry> dg(geometry, g);
97
98 hyperpoint rot = xpush(v0) * xspinpush0(M_PI - M_PI/sym, main);
99 hyperpoint bnlfar = xpush(v0) * spin(M_PI) * rspintox(rot) * rspintox(rot) * rspintox(rot) * xpush0(hdist0(rot));
100 hyperpoint bnrfar = xpush(v0) * spin(M_PI) * spintox(rot) * spintox(rot) * spintox(rot) * xpush0(hdist0(rot));
101
102 m.lcorner = xspinpush0 (bspi-M_PI/sym, main);
103 m.rcorner = xspinpush0 (bspi+M_PI/sym, main);
104 m.mfar[0] = xspinpush0 (bspi, v0);
105 m.mfar[1] = xspinpush0 (bspi, v1);
106 m.vfar[0] = spin(bspi) * bnlfar;
107 m.vfar[2] = spin(bspi) * bnrfar;
108 m.vfar[1] = spin(-2*M_PI/sym) * m.vfar[2];
109 m.vfar[3] = spin(+2*M_PI/sym) * m.vfar[0];
110
111 return m;
112 }
113
114 struct matrixlist {
115 mesher o, n;
116 vector<matrixitem> v;
117 };
118
genitem(const transmatrix & m1,const transmatrix & m2,int nsym)119 matrixitem genitem(const transmatrix& m1, const transmatrix& m2, int nsym) {
120 matrixitem mi;
121 mi.first = m1;
122 mi.second.resize(nsym);
123 for(int i=0; i<nsym; i++)
124 mi.second[i] = spin(2*M_PI*i/nsym) * m2;
125 return mi;
126 }
127
do_kleinize()128 bool do_kleinize() { return S3 >= OINF; }
129
kleinize(hyperpoint h)130 EX hyperpoint kleinize(hyperpoint h) {
131 if(GDIM == 2) return point3(h[0]/h[2], h[1]/h[2], 1);
132 else return point31(h[0]/h[3], h[1]/h[3], h[2]/h[3]);
133 }
134
may_kleinize(hyperpoint h)135 EX hyperpoint may_kleinize(hyperpoint h) {
136 if(do_kleinize()) return kleinize(h);
137 else return h;
138 }
139
addmatrix(matrixlist & matrices,hyperpoint o0,hyperpoint o1,hyperpoint o2,hyperpoint n0,hyperpoint n1,hyperpoint n2,int d,int osym,int nsym)140 void addmatrix(matrixlist& matrices, hyperpoint o0, hyperpoint o1, hyperpoint o2, hyperpoint n0, hyperpoint n1, hyperpoint n2, int d, int osym, int nsym) {
141 if(do_kleinize()) o0 = kleinize(o0), o1 = kleinize(o1), o2 = kleinize(o2), n0 = kleinize(n0), n1 = kleinize(n1), n2 = kleinize(n2);
142 matrices.v.push_back(genitem(inverse(spin(2*M_PI*d/osym)*build_matrix(o0, o1, o2,C02)), spin(2*M_PI*d/nsym)*build_matrix(n0, n1, n2,C02), nsym));
143 }
144
145 matrixlist hex_matrices, hept_matrices;
146
generate_matrices(matrixlist & matrices,const mesher & o,const mesher & n)147 void generate_matrices(matrixlist& matrices, const mesher& o, const mesher& n) {
148 matrices.v.clear();
149 matrices.o = o;
150 matrices.n = n;
151
152 for(int d=0; d<o.sym; d++) {
153 hyperpoint center = hpxy(0,0);
154 int d1 = d&1;
155 addmatrix(matrices, center, o.lcorner, o.rcorner, center, n.lcorner, n.rcorner, d, o.sym, n.sym);
156 addmatrix(matrices, o.mfar[d1], o.lcorner, o.rcorner, n.mfar[d1], n.lcorner, n.rcorner, d, o.sym, n.sym);
157 addmatrix(matrices, o.mfar[d1], o.lcorner, o.vfar[d1], n.mfar[d1], n.lcorner, n.vfar[d1], d, o.sym, n.sym);
158 addmatrix(matrices, o.mfar[d1], o.rcorner, o.vfar[d1+2], n.mfar[d1], n.rcorner, n.vfar[d1+2], d, o.sym, n.sym);
159 }
160 }
161
162 int nsym0;
163
generate_matrices_scale(ld scale,int noft)164 void generate_matrices_scale(ld scale, int noft) {
165 mesher ohex = msh(gNormal, 6, 0.329036, 0.566256, 0.620672, 0, 1);
166 mesher ohept = msh(gNormal, 7, hexf7, hcrossf7, hcrossf7, M_PI/7, 1);
167 if(!BITRUNCATED) {
168 mesher nall = msh(geometry, S7, cgi.rhexf, cgi.tessf, cgi.tessf, -M_PI, scale);
169 bool use = geosupport_football() < 2;
170 if(use && noft == 1) {
171 mesher opure = msh(gNormal, 7, 0.620672, 1.090550, 1.090550, M_PI/7, 1);
172 generate_matrices(hept_matrices, opure, nall);
173 }
174 else if(use && noft == 2) {
175 mesher oeuc = msh(gNormal, 6, sqrt(3)/6, .5, .5, 0, 1);
176 generate_matrices(hept_matrices, oeuc, nall);
177 }
178 else if(use && noft == 3) {
179 generate_matrices(hept_matrices, ohex, nall);
180 }
181 else {
182 generate_matrices(hex_matrices, ohex, nall);
183 generate_matrices(hept_matrices, ohept, nall);
184 }
185 }
186 else {
187 generate_matrices(hex_matrices, ohex, msh(geometry, S6, cgi.hexvdist, cgi.hexhexdist, cgi.hcrossf, (S3-3)*M_PI/S3, scale));
188 generate_matrices(hept_matrices, ohept, msh(geometry, S7, cgi.rhexf, cgi.hcrossf, cgi.hcrossf, M_PI/S7, scale));
189 }
190 }
191
bshape2(hpcshape & sh,PPR prio,int shapeid,matrixlist & m)192 void geometry_information::bshape2(hpcshape& sh, PPR prio, int shapeid, matrixlist& m) {
193 auto& matrices = m.v;
194 int osym = m.o.sym;
195 int nsym = m.n.sym;
196
197 int whereis = 0;
198 while(polydata[whereis] != NEWSHAPE || polydata[whereis+1] != shapeid) whereis++;
199 int rots = polydata[whereis+2]; int sym = polydata[whereis+3];
200 whereis += 4;
201 int qty = 0;
202 while(polydata[whereis + 2*qty] != NEWSHAPE) qty++;
203
204 vector<hyperpoint> lst;
205 for(int i=0; i<qty; i++) {
206 dynamicval<eGeometry> dg(geometry, gNormal);
207 lst.push_back(hpxy(polydata[whereis+2*i], polydata[whereis+2*i+1]));
208 }
209 if(sym == 2)
210 for(int i=qty-1; i>=0; i--) {
211 dynamicval<eGeometry> dg(geometry, gNormal);
212 lst.push_back(hpxy(polydata[whereis+2*i], -polydata[whereis+2*i+1]));
213 }
214
215 hyperpoint lstmid = hpxyz(0,0,0);
216 for(auto pp: lst) lstmid += pp;
217 transmatrix T = spin(-m.o.bspi);
218 while((spin(2*M_PI / rots) * T* lstmid)[0] < (T*lstmid)[0])
219 T = spin(2*M_PI / rots) * T;
220 while((spin(-2*M_PI / rots) * T* lstmid)[0] < (T*lstmid)[0])
221 T = spin(-2*M_PI / rots) * T;
222 T = spin(m.o.bspi) * T;
223 for(auto &pp: lst) pp = T * pp;
224
225 if(osym % rots && rots % osym) printf("warning: rotation oddity (shapeid %d, osym=%d rots=%d)\n", shapeid, osym, rots);
226
227 if(rots > osym && rots % osym == 0) {
228 int rep = rots / osym;
229 int s = lst.size();
230 for(int i=0; i<s*(rep-1); i++)
231 lst.push_back(spin(2*M_PI/rots) * lst[i]);
232 rots /= rep;
233 }
234
235 bshape(sh, prio);
236
237 for(int r=0; r<nsym; r+=osym/rots) {
238 for(hyperpoint h: lst) {
239 hyperpoint nh = may_kleinize(h);
240 int mapped = 0;
241 for(auto& m: matrices) {
242 hyperpoint z = m.first * h;
243 if(z[0] > -1e-5 && z[1] > -1e-5 && z[2] > -1e-5) {
244 nh = m.second[r] * z, mapped++;
245 }
246 }
247 if(mapped == 0) printf("warning: not mapped (shapeid %d)\n", shapeid);
248 hpcpush(mid(nh, nh));
249 }
250 }
251
252 hpcpush(hpc[last->s]);
253 }
254
sizeto(T & t,int n)255 template<class T> void sizeto(T& t, int n) {
256 if(isize(t) <= n) t.resize(n+1);
257 }
258
bshape_regular(floorshape & fsh,int id,int sides,ld shift,ld size,cell * c)259 void geometry_information::bshape_regular(floorshape &fsh, int id, int sides, ld shift, ld size, cell *c) {
260
261 sizeto(fsh.b, id);
262 sizeto(fsh.shadow, id);
263
264 #if CAP_BT
265 if(bt::in()) {
266
267 const int STEP = vid.texture_step;
268
269 for(int t=0; t<2; t++) {
270
271 if(t == 0)
272 bshape(fsh.b[id], fsh.prio);
273 if(t == 1)
274 bshape(fsh.shadow[id], fsh.prio);
275
276 for(int i=0; i<sides; i++) {
277 hyperpoint h0 = bt::get_corner_horo_coordinates(c, i) * size;
278 hyperpoint h1 = bt::get_corner_horo_coordinates(c, i+1) * size;
279 if(t) h0 *= SHADMUL, h1 *= SHADMUL;
280 hyperpoint hd = (h1 - h0) / STEP;
281 for(int j=0; j<STEP; j++) {
282 hpcpush(bt::get_horopoint(h0 + hd * j));
283 if(geometry == gBinary4 && among(i, 2, 4)) break;
284 if(geometry == gBinaryTiling && among(i, 0, 4)) break;
285 if(geometry == gTernary && among(i, 3, 5)) break;
286 }
287 }
288
289 hpcpush(hpc[last->s]);
290 }
291
292 for(int k=0; k<SIDEPARS; k++) {
293 if(isize(fsh.gpside[k]) < c->type)
294 fsh.gpside[k].resize(c->type);
295 for(int i=0; i<c->type; i++) {
296 sizeto(fsh.gpside[k][i], id);
297 bshape(fsh.gpside[k][i][id], PPR::LAKEWALL);
298 hyperpoint h0 = bt::get_corner_horo_coordinates(c, i) * size;
299 hyperpoint h1 = bt::get_corner_horo_coordinates(c, i+1) * size;
300 hyperpoint hd = (h1 - h0) / STEP;
301 for(int j=0; j<=STEP; j++)
302 hpcpush(iddspin_side(c, i) * bt::get_horopoint(h0 + hd * j));
303 chasmifyPoly(dlow_table[k], dhi_table[k], k);
304 }
305 }
306
307 return;
308 }
309 #endif
310
311 bshape(fsh.b[id], fsh.prio);
312 for(int t=0; t<=sides; t++)
313 hpcpush(xspinpush0(t*2 * M_PI / sides + shift * M_PI / S42, size));
314
315 bshape(fsh.shadow[id], fsh.prio);
316 for(int t=0; t<=sides; t++)
317 hpcpush(xspinpush0(t*2 * M_PI / sides + shift * M_PI / S42, size * SHADMUL));
318
319 for(int k=0; k<SIDEPARS; k++) {
320 fsh.side[k].resize(2);
321 bshape(fsh.side[k][id], PPR::LAKEWALL);
322 hpcpush(xspinpush0(+M_PI/sides, size));
323 hpcpush(xspinpush0(-M_PI/sides, size));
324 chasmifyPoly(dlow_table[k], dhi_table[k], k);
325 }
326 }
327
328 #if CAP_IRR
329 namespace irr { void generate_floorshapes(); }
330 #endif
331
332 // !siid equals pseudohept(c)
333
generate_floorshapes_for(int id,cell * c,int siid,int sidir)334 void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, int sidir) {
335 DEBBI(DF_POLY, ("generate_floorshapes_for ", id));
336
337 for(auto pfsh: all_plain_floorshapes) {
338 auto& fsh = *pfsh;
339
340 if(STDVAR && (standard_tiling() || bt::in())) {
341
342 ld hexside = fsh.rad0, heptside = fsh.rad1;
343
344 for(int k=0; k<SIDEPARS; k++) sizeto(fsh.side[k], id);
345
346 ld td = (PURE && !(S7&1)) ? S42+S6 : 0;
347 if(&fsh == &shBigHepta) td += S6;
348
349 if(S3 >= OINF && !(S7 & 1)) td = S42 * 1. / S7;
350
351 int b = 0;
352 if(S3 == 4 && BITRUNCATED) b += S14;
353
354 if(id)
355 bshape_regular(fsh, id, S7, td, heptside, c);
356
357 else if(PURE) {
358 if(&fsh == &shTriheptaFloor)
359 bshape_regular(fsh, 0, S7/2, 0, hexside, c);
360 else if(&fsh == &shBigTriangle)
361 bshape_regular(fsh, 0, S7/2, S12, hexside, c);
362 else
363 bshape_regular(fsh, 0, S7, td, heptside, c);
364 }
365 else if(&fsh == &shBigTriangle)
366 bshape_regular(fsh, 0, S3, b+S14, hexside, c);
367 else if(&fsh == &shTriheptaFloor)
368 bshape_regular(fsh, 0, S3, b, hexside, c);
369 else
370 bshape_regular(fsh, 0, S6, S7, hexside, c);
371
372
373 continue;
374 }
375
376 // special
377 ld sca = 3 * shFullFloor.rad0 / fsh.rad0;
378
379 vector<hyperpoint> cornerlist;
380
381 int cor = c->type;
382
383 if(&fsh == &shTriheptaFloor) {
384 if(!siid) {
385 for(int i=0; i<cor; i++)
386 cornerlist.push_back(midcorner(c, i, .49));
387 }
388 else {
389 for(int i=0; i<cor; i++) {
390 int ri = i;
391 if((i&1) == ((sidir+siid)&1)) ri--;
392 ri = c->c.fix(ri);
393 cornerlist.push_back(mid(get_corner_position(c, ri, 3.1), get_corner_position(c, c->c.fix(ri+1), 3.1)));
394 }
395 }
396 }
397
398 else if(&fsh == &shBigTriangle) {
399 if(!siid) {
400 for(int i=0; i<cor; i++) cornerlist.push_back(hpxy(0,0));
401 }
402 else if(geosupport_chessboard()) {
403 for(int i=0; i<cor; i++) {
404 hyperpoint nc = nearcorner(c, i);
405 cornerlist.push_back(mid_at(hpxy(0,0), nc, .94));
406 }
407 }
408 else {
409 for(int i=0; i<cor; i++) {
410 int ri = i;
411 if((i&1) != ((sidir+siid)&1)) ri--;
412 ri = c->c.fix(ri);
413 hyperpoint nc = nearcorner(c, ri);
414 cornerlist.push_back(mid_at(hpxy(0,0), nc, .94));
415 }
416 }
417 }
418
419 else if(&fsh == &shBigHepta) {
420 if(!siid) {
421 for(int i=0; i<cor; i++) {
422 hyperpoint nc = nearcorner(c, i);
423 cornerlist.push_back(mid_at(hpxy(0,0), nc, .94));
424 }
425 }
426 else {
427 for(int i=0; i<cor; i++) cornerlist.push_back(hpxy(0,0));
428 }
429 }
430
431 else if(arb::in()) {
432 vector<hyperpoint> actual;
433 for(int j=0; j<cor; j++)
434 actual.push_back(get_corner_position(c, j));
435
436 ld min_dist = 1e3;
437 for(int j=0; j<cor; j++)
438 for(int k=0; k<j; k++) {
439 ld dist = hdist(actual[j], actual[k]);
440 if(dist > 1e-6 && dist < min_dist)
441 min_dist = dist;
442 }
443
444 ld dist = min_dist * (1 - 3 / sca) * arb::current_or_slided().boundary_ratio;
445
446 ld area = 0;
447 for(int j=0; j<cor; j++) {
448 hyperpoint current = kleinize(actual[j]);
449 hyperpoint last = kleinize(actual[j?j-1:cor-1]);
450 area += current[0] * last[1] - last[0] * current[1];
451 }
452 if(area < 0) dist = -dist;
453
454 for(int j=0; j<cor; j++) {
455 hyperpoint last = actual[j?j-1:cor-1];
456 hyperpoint current = ypush(1e-6 * randd()) * xpush(1e-6) * actual[j];
457 hyperpoint next = actual[j<cor-1?j+1:0];
458 auto T = gpushxto0(current);
459 last = T * last;
460 next = T * next;
461 hyperpoint a = rspintox(last) * ypush0(dist);
462 hyperpoint b = rspintox(last) * xpush(hdist0(last)) * ypush0(dist);
463
464 hyperpoint c = rspintox(next) * ypush0(-dist);
465 hyperpoint d = rspintox(next) * xpush(hdist0(next)) * ypush0(-dist);
466
467 hyperpoint h = linecross(a, b, c, d);
468
469 cornerlist.push_back(rgpushxto0(current) * h);
470 }
471 }
472
473 else {
474 for(int j=0; j<cor; j++)
475 cornerlist.push_back(get_corner_position(c, j, sca));
476 }
477
478 sizeto(fsh.b, id);
479
480 bshape(fsh.b[id], fsh.prio);
481 if(cor == 2) {
482 /* give digons some width */
483 for(int i=0; i<cor; i++) hpcpush(spin(-.1) * cornerlist[i]), hpcpush(spin(+.1) * cornerlist[i]);
484 hpcpush(spin(-.1) * cornerlist[0]);
485 }
486 else if(&fsh == &shTriheptaFloor && cor == 4 && siid)
487 /* trihepta floors generate digons too */
488 for(int i=0; i<=cor; i++) hpcpush(spin((i&1) ? .1 : -.1) * cornerlist[i%cor]);
489 else
490 for(int i=0; i<=cor; i++) hpcpush(cornerlist[i%cor]);
491
492 sizeto(fsh.shadow, id);
493 bshape(fsh.shadow[id], fsh.prio);
494 for(int i=0; i<=cor; i++)
495 hpcpush(mid_at(hpxy(0,0), cornerlist[i%cor], SHADMUL));
496
497 for(int k=0; k<SIDEPARS; k++) {
498 if(isize(fsh.gpside[k]) < cor)
499 fsh.gpside[k].resize(cor);
500 for(int cid=0; cid<cor; cid++) {
501 sizeto(fsh.gpside[k][cid], id);
502 bshape(fsh.gpside[k][cid][id], fsh.prio);
503 hpcpush(iddspin_side(c, cid) * cornerlist[cid]);
504 hpcpush(iddspin_side(c, cid) * cornerlist[(cid+1)%cor]);
505 chasmifyPoly(dlow_table[k], dhi_table[k], k);
506 }
507 }
508 }
509
510 for(auto pfsh: all_escher_floorshapes) {
511
512 auto& fsh = *pfsh;
513
514 sizeto(fsh.b, id);
515 sizeto(fsh.shadow, id);
516
517 if(STDVAR && standard_tiling()) {
518 generate_matrices_scale(fsh.scale, fsh.noftype);
519 if(PURE && geosupport_football() < 2) {
520 bshape2(fsh.b[id], fsh.prio, fsh.shapeid2 ? fsh.shapeid2 : fsh.shapeid1, hept_matrices);
521 }
522 else {
523 if(id == 0) bshape2(fsh.b[0], fsh.prio, fsh.shapeid0, hex_matrices);
524 if(id == 1) bshape2(fsh.b[1], fsh.prio, fsh.shapeid1, hept_matrices);
525 }
526 generate_matrices_scale(fsh.scale * SHADMUL, fsh.noftype);
527 if(PURE && geosupport_football() < 2) {
528 bshape2(fsh.shadow[id], fsh.prio, fsh.shapeid2 ? fsh.shapeid2 : fsh.shapeid1, hept_matrices);
529 }
530 else {
531 if(id == 0) bshape2(fsh.shadow[0], fsh.prio, fsh.shapeid0, hex_matrices);
532 if(id == 1) bshape2(fsh.shadow[1], fsh.prio, fsh.shapeid1, hept_matrices);
533 }
534 }
535
536 else {
537 generate_matrices_scale(fsh.scale, fsh.noftype);
538
539 auto& m = (siid && geosupport_football() == 2) ? hex_matrices : hept_matrices;
540
541 int cor = c->type;
542
543 m.n.sym = cor;
544
545 int v = sidir+siid;
546 for(auto& mvi: m.v) mvi.second.resize(cor);
547
548 for(int ii=0; ii<2; ii++) {
549 int i = 0;
550 for(int d=0; d<m.o.sym; d++) {
551 hyperpoint center = hpxy(0,0);
552
553 for(int cid=0; cid<cor; cid++) {
554 hyperpoint nlcorner = get_corner_position(c, (d+cid+v+1) % cor, 3 / fsh.scale * (ii ? 1/SHADMUL : 1));
555 hyperpoint nrcorner = get_corner_position(c, (d+cid+v+2) % cor, 3 / fsh.scale * (ii ? 1/SHADMUL : 1));
556
557 hyperpoint nfar = nearcorner(c, (d+cid+v+1) % cor);
558
559 hyperpoint nlfar = farcorner(c, (d+cid+v+1) % cor, 0);
560 hyperpoint nrfar = farcorner(c, (d+cid+v+1) % cor, 1);
561 m.v[i].second[cid] = build_matrix(center, nlcorner, nrcorner,C02);
562 m.v[i+1].second[cid] = build_matrix(nfar, nlcorner, nrcorner,C02);
563 m.v[i+2].second[cid] = build_matrix(nfar, nlcorner, nlfar,C02);
564 m.v[i+3].second[cid] = build_matrix(nfar, nrcorner, nrfar,C02);
565 }
566
567 i += 4;
568 }
569
570 if(i != isize(m.v)) printf("warning: i=%d sm=%d\n", i, isize(m.v));
571 bshape2((ii?fsh.shadow:fsh.b)[id], fsh.prio, (fsh.shapeid2 && geosupport_football() < 2) ? fsh.shapeid2 : siid?fsh.shapeid0:fsh.shapeid1, m);
572 }
573 }
574 }
575
576 #if MAXMDIM >= 4
577 if(WDIM == 2 && GDIM == 3) {
578 finishshape();
579 for(auto pfsh: all_plain_floorshapes) {
580 auto& fsh = *pfsh;
581
582 for(int i=fsh.shadow[id].s; i<fsh.shadow[id].e; i++)
583 hpc[i] = orthogonal_move(hpc[i], FLOOR - human_height / 100);
584
585 for(int k=0; k<SIDEPARS; k++) {
586 sizeto(fsh.levels[k], id);
587 bshape(fsh.levels[k][id], fsh.prio);
588 last->flags |= POLY_TRIANGLES;
589 last->tinf = &floor_texture_vertices[fsh.id];
590 last->texture_offset = 0;
591
592 #if CAP_BT
593 if(bt::in())
594 for(int t=0; t<c->type; t++)
595 texture_order([&] (ld x, ld y) {
596 hyperpoint left = bt::get_corner_horo_coordinates(c, t);
597 hyperpoint right = bt::get_corner_horo_coordinates(c, t+1);
598 hpcpush(orthogonal_move(bt::get_horopoint(left * x + right * y), dfloor_table[k]));
599 });
600 else
601 #endif
602 if(1) {
603 int s = fsh.b[id].s;
604 int e = fsh.b[id].e-1;
605 for(int t=0; t<e-s; t++) {
606 hyperpoint v1 = may_kleinize(hpc[s+t]) - C0;
607 hyperpoint v2 = may_kleinize(hpc[s+t+1]) - C0;
608 texture_order([&] (ld x, ld y) {
609 hpcpush(
610 orthogonal_move(
611 normalize(C0 + v1 * x + v2 * y)
612 , dfloor_table[k])
613 );
614 });
615 }
616 }
617
618 finishshape();
619 ensure_vertex_number(fsh.levels[k][id]);
620 }
621
622 for(int co=0; co<2; co++) {
623 sizeto(fsh.cone[co], id);
624 bshape(fsh.cone[co][id], fsh.prio);
625 last->flags |= POLY_TRIANGLES;
626 last->tinf = &floor_texture_vertices[fsh.id];
627 last->texture_offset = 0;
628 ld h = (FLOOR - WALL) / (co+1);
629 ld top = co ? (FLOOR + WALL) / 2 : WALL;
630 #if CAP_BT
631 if(bt::in())
632 for(int t=0; t<c->type; t++)
633 texture_order([&] (ld x, ld y) {
634 hyperpoint left = bt::get_corner_horo_coordinates(c, t);
635 hyperpoint right = bt::get_corner_horo_coordinates(c, t+1);
636 hpcpush(orthogonal_move(bt::get_horopoint(left * x + right * y), top + h * (x+y)));
637 });
638 else
639 #endif
640 if(1) {
641 int s = fsh.b[id].s;
642 int e = fsh.b[id].e-1;
643 for(int t=0; t<e-s; t++) {
644 hyperpoint v1 = may_kleinize(hpc[s+t]) - C0;
645 hyperpoint v2 = may_kleinize(hpc[s+t+1]) - C0;
646 texture_order([&] (ld x, ld y) { hpcpush(orthogonal_move(normalize(C0 + v1 * x + v2 * y), top + h * (x+y))); });
647 }
648 }
649
650 finishshape();
651 ensure_vertex_number(fsh.cone[co][id]);
652 }
653
654 for(int l=0; l<SIDEPARS; l++) {
655 for(auto& li: fsh.side[l])
656 bind_floor_texture(li, fsh.id);
657 if(isize(fsh.gpside[l]) < c->type)
658 fsh.gpside[l].resize(c->type);
659 for(auto& gs: fsh.gpside[l]) {
660 for(auto& li: gs)
661 bind_floor_texture(li, fsh.id);
662 }
663 }
664 }
665
666 for(auto pfsh: all_escher_floorshapes) {
667 auto& fsh = *pfsh;
668
669 for(int l=0; l<SIDEPARS; l++) {
670 fsh.levels[l] = shFullFloor.levels[l];
671 fsh.shadow = shFullFloor.shadow;
672 for(auto& li: fsh.levels[l]) bind_floor_texture(li, fsh.id);
673 fsh.side[l] = shFullFloor.side[l];
674 for(auto& li: fsh.side[l]) bind_floor_texture(li, fsh.id);
675 if(isize(fsh.gpside[l]) < c->type)
676 fsh.gpside[l].resize(c->type);
677 for(int e=0; e<c->type; e++) {
678 fsh.gpside[l][e] = shFullFloor.gpside[l][e];
679 for(auto& li: fsh.gpside[l][e])
680 bind_floor_texture(li, fsh.id);
681 }
682 fsh.cone[0] = shFullFloor.cone[0];
683 fsh.cone[1] = shFullFloor.cone[1];
684 for(int c=0; c<2; c++)
685 for(auto& li: fsh.cone[c])
686 bind_floor_texture(li, fsh.id);
687 }
688 }
689 finishshape();
690 }
691 #endif
692 }
693
generate_floorshapes()694 void geometry_information::generate_floorshapes() {
695
696 DEBBI(DF_POLY, ("generate_floorshapes"));
697
698 heptagon modelh;
699 cell model;
700 model.master = &modelh;
701 modelh.c7 = &model;
702 model.type = modelh.type = S7;
703
704 auto mmerge1 = [&] (int i, int j) { model.c.setspin(i, j, false); modelh.c.setspin(i, j, false); };
705 auto mmerge = [&] (int i, int j) { mmerge1(i, j); mmerge1(j, i); };
706
707 for(int i=0; i<S7; i++) {
708 model.move(i) = &model;
709 modelh.move(i) = &modelh;
710 model.c.setspin(i, i, false);
711 modelh.c.setspin(i, i, false);
712 }
713
714 if(WDIM == 3) ;
715
716 #if CAP_IRR
717 else if(IRREGULAR) {
718 DEBBI(DF_POLY, ("generate_floorshapes: irregular"));
719
720 int cc = isize(irr::cells);
721
722 for(int id=0; id<cc; id++) {
723 irr::cellindex[&model] = id;
724 auto& vs = irr::cells[id];
725 model.type = isize(vs.vertices);
726 int siid = !vs.is_pseudohept;
727 int sidir = 0;
728 if(siid) sidir = irr::cells[vs.neid[0]].is_pseudohept;
729 generate_floorshapes_for(id, &model, !vs.is_pseudohept, sidir);
730 }
731
732 printf("done\n");
733 }
734 #endif
735
736 else if(GOLDBERG_INV) { /* will be generated on the fly */ }
737
738 else if(inforder::mixed()) { /* will be generated on the fly */ }
739
740 #if CAP_BT
741 else if(kite::in()) {
742 dynamicval<bool> ncor(approx_nearcorner, true);
743 for(int i=0; i<2; i++) {
744 modelh.s = hstate(i); /* kite/dart shape */
745 kite::no_adj = true;
746 generate_floorshapes_for(i, &model, 0, 0);
747 kite::no_adj = false;
748 }
749 }
750 #endif
751
752 #if CAP_ARCM
753 else if(arcm::in()) {
754 arcm::parent_index_of(&modelh) = 0;
755 auto &ac = arcm::current;
756 for(int i=0; i<2*ac.N + 2; i++) {
757 if(ac.regular && i>=2 && i < 2*ac.N) continue;
758 arcm::id_of(&modelh) = i;
759 model.type = isize(ac.triangles[i]);
760 if(DUAL) model.type /= 2, arcm::parent_index_of(&modelh) = !(i&1);
761
762 if(BITRUNCATED)
763 generate_floorshapes_for(i, &model, !arcm::pseudohept(&model), arcm::pseudohept(&model) ? 0 : 1^(i&1));
764 else if(geosupport_football() == 2)
765 generate_floorshapes_for(i, &model, !arcm::pseudohept(&model), i >= 4 ? 1 : 0);
766 else
767 generate_floorshapes_for(i, &model, 0, 0);
768 }
769 }
770 #endif
771
772 else if(arb::in()) {
773 auto& c = arb::current;
774 int n = isize(c.shapes);
775 vector<cell> models(n);
776 vector<heptagon> modelh(n);
777 for(int i=0; i<n; i++) {
778 auto &ms = models[i];
779 auto &mh = modelh[i];
780 mh.fieldval = -1;
781 for(auto& t: ms.c.move_table) t = nullptr;
782 for(auto& t: mh.c.move_table) t = nullptr;
783 }
784 for(int i=0; i<n; i++) {
785 auto &ms = models[i];
786 auto &mh = modelh[i];
787 ms.master = &mh;
788 mh.c7 = &ms;
789 mh.zebraval = i;
790 auto& sh = c.shapes[i];
791 ms.type = mh.type = sh.size();
792 }
793 for(int i=0; i<n; i++) {
794 auto &ms = models[i];
795 auto &mh = modelh[i];
796 auto& sh = c.shapes[i];
797 for(int j=0; j<sh.size(); j++) {
798 auto& co = sh.connections[j];
799 mh.c.connect(j, &modelh[co.sid], co.eid, co.mirror);
800 ms.c.connect(j, &models[co.sid], co.eid, co.mirror);
801 }
802 }
803 for(int i=0; i<n; i++) generate_floorshapes_for(i, &models[i], 0, 0);
804 }
805
806 else if(geometry == gBinary4) {
807 for(int i: {0,1}) {
808 modelh.zebraval = i;
809 mmerge(2, 4); mmerge(0, 3); mmerge(1, 3); mmerge(i, 3);
810 generate_floorshapes_for(i, &model, 1, 0);
811 }
812 }
813
814 else if(geometry == gTernary) {
815 for(int i: {0,1,2}) {
816 modelh.zebraval = i;
817 mmerge(3, 5); for(int a=0; a<3; a++) mmerge1(a, 4); mmerge(4, i);
818 generate_floorshapes_for(i, &model, 1, 0);
819 }
820 }
821
822 else if(PURE && geometry != gBinaryTiling && geosupport_football() < 2) {
823 generate_floorshapes_for(0, &model, 1, 0);
824 }
825
826 else if(bt::in()) {
827 dynamicval<hrmap*> c(currentmap, bt::new_alt_map(nullptr));
828 model.type = S6; generate_floorshapes_for(0, &model, 0, 0);
829 model.type = S7; generate_floorshapes_for(1, &model, 1, 0);
830 delete currentmap;
831 }
832
833 else {
834 static hrmap_standard stdmap;
835 dynamicval<hrmap*> c(currentmap, &stdmap);
836 // cell model;
837 model.type = S6; generate_floorshapes_for(0, &model, 0, 0);
838 model.type = S7; generate_floorshapes_for(1, &model, 0, 0);
839 }
840 }
841
842 #if CAP_GP
843 EX namespace gp {
844
clear_plainshapes()845 EX void clear_plainshapes() {
846 for(int m=0; m<3; m++)
847 for(int sd=0; sd<8; sd++)
848 for(int i=0; i<GOLDBERG_LIMIT; i++)
849 for(int j=0; j<GOLDBERG_LIMIT; j++)
850 for(int k=0; k<8; k++)
851 cgi.gpdata->pshid[m][sd][i][j][k] = -1;
852 cgi.gpdata->nextid = 0;
853 }
854
build_plainshape(int & id,gp::local_info & li,cell * c0,int siid,int sidir)855 void build_plainshape(int& id, gp::local_info& li, cell *c0, int siid, int sidir) {
856 cgi.require_shapes();
857 id = cgi.gpdata->nextid++;
858
859 bool master = !(li.relative.first||li.relative.second);
860 int cor = master ? S7 : SG6;
861 if(master) li.last_dir = -1;
862 DEBB(DF_GP, (format("last=%d at=%d,%d tot=%d siid=%d sidir=%d cor=%d id=%d\n", li.last_dir, li.relative.first, li.relative.second, li.total_dir, siid, sidir, cor, id)));
863
864 cgi.generate_floorshapes_for(id, c0, siid, sidir);
865
866 cgi.finishshape();
867 cgi.extra_vertices();
868 }
869
get_plainshape_id(cell * c)870 EX int get_plainshape_id(cell *c) {
871 if(li_for != c) {
872 li_for = c;
873 current_li = get_local_info(c);
874 }
875 int siid, sidir;
876 cell *c1 = c;
877 auto f = [&] {
878 if(geosupport_threecolor() == 2) {
879 auto si = patterns::getpatterninfo(c1, patterns::PAT_COLORING, patterns::SPF_NO_SUBCODES);
880 siid = si.id>>2;
881 // if(siid == 2) si.dir++;
882 // if(siid != pattern_threecolor(c)) printf("threecolor mismatch\n");
883 // if(pattern_threecolor(createMov(c, c->fixd(si.dir))) != (siid+1)%3) printf("threecolor mismatch direction\n");
884 sidir = c1->c.fix(si.dir);
885 }
886 else if(geosupport_football() == 2) {
887 siid = !pseudohept(c1);
888 sidir = !ishex1(c1);
889 }
890 else if(geosupport_chessboard()) {
891 siid = !chessvalue(c1);
892 sidir = 0;
893 }
894 else {
895 siid = 0;
896 sidir = 0;
897 }
898 };
899 if(INVERSE && gp::variation_for(gp::param) == eVariation::goldberg) {
900 c1 = gp::get_mapped(c);
901 UIU(f());
902 }
903 else if(INVERSE) {
904 siid = 0;
905 sidir = 0;
906 }
907 else f();
908 auto& id = cgi.gpdata->pshid[siid][sidir][current_li.relative.first&GOLDBERG_MASK][current_li.relative.second&GOLDBERG_MASK][gmod(current_li.total_dir, S6)];
909 if(id == -1 && sphere && isize(cgi.shFloor.b) > 0) {
910 forCellEx(c1, c) if(!gmatrix0.count(c1)) return 0;
911 }
912 if(id == -1) build_plainshape(id, current_li, c, siid, sidir);
913 return id;
914 }
915 EX }
916 #endif
917
918 qfloorinfo qfi;
919
set_no_floor()920 EX void set_no_floor() {
921 qfi.fshape = NULL;
922 qfi.shape = NULL;
923 qfi.tinf = NULL;
924 qfi.usershape = -1;
925 }
926
set_floor(floorshape & sh)927 EX void set_floor(floorshape& sh) {
928 qfi.fshape = &sh;
929 qfi.shape = NULL;
930 qfi.tinf = NULL;
931 qfi.usershape = -1;
932 }
933
set_floor(hpcshape & sh)934 EX void set_floor(hpcshape& sh) {
935 qfi.shape = &sh;
936 qfi.fshape = NULL;
937 qfi.spin = Id;
938 qfi.tinf = NULL;
939 qfi.usershape = -1;
940 }
941
set_floor(const transmatrix & spin,hpcshape & sh)942 EX void set_floor(const transmatrix& spin, hpcshape& sh) {
943 qfi.shape = &sh;
944 qfi.fshape = NULL;
945 qfi.spin = spin;
946 qfi.usershape = -1;
947 }
948
shvid(cell * c)949 EX int shvid(cell *c) {
950 return currentmap->shvid(c);
951 }
952
shvid(cell * c)953 int hrmap_standard::shvid(cell *c) {
954 if(GOLDBERG)
955 return gp::get_plainshape_id(c);
956 #if CAP_IRR
957 else if(IRREGULAR)
958 return irr::cellindex[c];
959 #endif
960 else if(geosupport_football() == 2)
961 return pseudohept(c);
962 else if(inforder::mixed()) {
963 int t = c->type;
964 static vector<bool> computed;
965 if(isize(computed) <= t) computed.resize(t+1);
966 if(!computed[t]) {
967 computed[t] = true;
968 cell model;
969 heptagon modelh;
970 model.type = t;
971 modelh.type = t;
972 S7 = t;
973 for(int i=0; i<S7; i++) {
974 model.move(i) = &model;
975 modelh.move(i) = &modelh;
976 model.c.setspin(i, i, false);
977 modelh.c.setspin(i, i, false);
978 }
979
980 cgi.tessf = edge_of_triangle_with_angles(0, M_PI/t, M_PI/t);
981 cgi.crossf = cgi.tessf;
982
983 cgi.require_shapes();
984 println(hlog, "generating floorshapes for ", t);
985 cgi.generate_floorshapes_for(t, &model, 0, 0);
986 cgi.finishshape();
987 cgi.extra_vertices();
988 }
989 return t;
990 }
991 else if(PURE)
992 return 0;
993 else
994 return ctof(c);
995 }
996
draw_shapevec(cell * c,const shiftmatrix & V,const vector<hpcshape> & shv,color_t col,PPR prio IS (PPR::DEFAULT))997 EX struct dqi_poly *draw_shapevec(cell *c, const shiftmatrix& V, const vector<hpcshape> &shv, color_t col, PPR prio IS(PPR::DEFAULT)) {
998 if(no_wall_rendering) return NULL;
999 if(!c) return &queuepolyat(V, shv[0], col, prio);
1000 else if(WDIM == 3) return NULL;
1001 else if(currentmap->strict_tree_rules()) return &queuepolyat(V, shv[shvid(c)], col, prio);
1002
1003 #if CAP_GP
1004 else if(GOLDBERG) {
1005 int id = gp::get_plainshape_id(c);
1006 if(isize(shv) > id) return &queuepolyat(V, shv[id], col, prio);
1007 return NULL;
1008 }
1009 #endif
1010 #if CAP_IRR
1011 else if(IRREGULAR) {
1012 int id = irr::cellindex[c];
1013 if(id < 0 || id >= isize(shv)) {
1014 return NULL;
1015 }
1016 return &queuepolyat(V, shv[id], col, prio);
1017 }
1018 #endif
1019 #if CAP_ARCM
1020 else if(arcm::in()) {
1021 return &queuepolyat(V, shv[shvid(c)], col, prio);
1022 }
1023 #endif
1024 else if(GOLDBERG && ishex1(c))
1025 return &queuepolyat(V * pispin, shv[0], col, prio);
1026 else if(!(S7&1) && PURE && !kite::in() && !a4) {
1027 auto si = patterns::getpatterninfo(c, patterns::PAT_COLORING, 0);
1028 if(si.id == 8) si.dir++;
1029 transmatrix D = applyPatterndir(c, si);
1030 return &queuepolyat(V*D, shv[shvid(c)], col, prio);
1031 }
1032 else
1033 return &queuepolyat(V, shv[shvid(c)], col, prio);
1034 }
1035
draw_floorshape(cell * c,const shiftmatrix & V,const floorshape & fsh,color_t col,PPR prio IS (PPR::DEFAULT))1036 EX void draw_floorshape(cell *c, const shiftmatrix& V, const floorshape &fsh, color_t col, PPR prio IS(PPR::DEFAULT)) {
1037 if(no_wall_rendering) return;
1038 draw_shapevec(c, V, fsh.b, col, prio);
1039 }
1040
draw_qfi(cell * c,const shiftmatrix & V,color_t col,PPR prio IS (PPR::DEFAULT),vector<hpcshape> floorshape::* tab IS (& floorshape::b))1041 EX void draw_qfi(cell *c, const shiftmatrix& V, color_t col, PPR prio IS(PPR::DEFAULT), vector<hpcshape> floorshape::* tab IS(&floorshape::b)) {
1042 if(no_wall_rendering) return;
1043 if(qfi.shape)
1044 queuepolyat(V * qfi.spin, *qfi.shape, col, prio);
1045 else if(qfi.usershape >= 0) {
1046 mapeditor::drawUserShape(V * qfi.spin, mapeditor::sgFloor, qfi.usershape, col, c);
1047 }
1048 else if(!qfi.fshape) ;
1049 #if CAP_TEXTURE
1050 else if(qfi.tinf) {
1051 auto& poly = queuetable(V * qfi.spin, qfi.tinf->vertices, isize(qfi.tinf->vertices), texture::config.mesh_color, texture::config.recolor(col), prio == PPR::DEFAULT ? PPR::FLOOR : prio);
1052 poly.tinf = qfi.tinf;
1053 poly.offset_texture = 0;
1054 poly.flags = POLY_INVERSE;
1055 }
1056 #endif
1057 else draw_shapevec(c, V, (qfi.fshape->*tab), col, prio);
1058 }
1059
1060 EX bool floorshape_debug;
viewmat()1061 EX void viewmat() {
1062 if(floorshape_debug) {
1063 shiftmatrix V = ggmatrix(cwt.at);
1064
1065 for(int i=0; i<cwt.at->type; i++) {
1066 shiftpoint ci = V * get_corner_position(cwt.at, i);
1067 shiftpoint ci1 = V * get_corner_position(cwt.at, (i+1) % cwt.at->type);
1068
1069 shiftpoint cn = V * nearcorner(cwt.at, i);
1070 shiftpoint cf0 = V * farcorner(cwt.at, i, 0);
1071 shiftpoint cf1 = V * farcorner(cwt.at, i, 1);
1072 queuestr(ci, 20, its(i), 0x0000FF, 1);
1073 if(vid.grid)
1074 queuestr(cn, 20, its(i), 0x00FF00, 1);
1075 else
1076 queuestr(V * currentmap->adj(cwt.at, i) * C0, 20, its(i), 0x00FFFF, 1);
1077 queueline(V * C0, ci, 0xFFFFFFFF, 3);
1078 queueline(ci, ci1, 0xFFFF00FF, 3);
1079 queueline(ci, cn, 0xFF00FFFF, 3);
1080 queueline(ci1, cn, 0xFF0000FF, 3);
1081 queueline(ci, cf0, 0x00FFFFFF, 3);
1082 queueline(cn, cf0, 0x00FF00FF, 3);
1083 queueline(cn, cf1, 0x0000FFFF, 3);
1084 }
1085 }
1086 }
1087
__anon60f1d2c30902null1088 auto floor_hook = arg::add1("-floordebug", [] { floorshape_debug = true; });
1089 #endif
1090
1091 #if MAXMDIM < 4 || !CAP_GL
ensure_vertex_number(basic_textureinfo & bti,int qty)1092 EX void ensure_vertex_number(basic_textureinfo& bti, int qty) {}
ensure_vertex_number(hpcshape & sh)1093 EX void ensure_vertex_number(hpcshape& sh) {}
bind_floor_texture(hpcshape & li,int id)1094 EX void bind_floor_texture(hpcshape& li, int id) {}
1095 #endif
1096
1097 #if MAXMDIM >= 4 && CAP_GL
1098
1099 EX ld floor_texture_square_size;
1100
draw_shape_for_texture(floorshape * sh)1101 void draw_shape_for_texture(floorshape* sh) {
1102
1103 int id = sh->id;
1104
1105 const ld s1 = 1;
1106 const ld s3 = 3 * s1;
1107 const ld sd = s1/2;
1108
1109 ld gx = (id % 8) * s3 - 3.5 * s3;
1110 ld gy = (id / 8) * s3 - 3.5 * s3;
1111
1112 if(1) {
1113 dynamicval<ld> v(vid.linewidth, 8);
1114 curvepoint(eupush(gx+s1, gy-s1) * C0);
1115 curvepoint(eupush(gx+s1, gy+s1) * C0);
1116 curvepoint(eupush(gx-s1, gy+s1) * C0);
1117 curvepoint(eupush(gx-s1, gy-s1) * C0);
1118 curvepoint(eupush(gx+s1, gy-s1) * C0);
1119 queuecurve(shiftless(Id), 0x000000FF, 0xFFFFFFFF - 0x1010100 * (sh->pstrength * 24/10), PPR::LAKELEV);
1120 }
1121
1122 poly_outline = 0xFFFFFFFF - 0x1010100 * (sh->pstrength * 3/2);
1123
1124 for(int a=-1; a<=1; a++)
1125 for(int b=-1; b<=1; b++)
1126 queuepoly(shiftless(eupush(gx+a, gy+b)), sh->b[0], 0xFFFFFFFF);
1127
1128 if(sh == &cgi.shCrossFloor) {
1129 queuepoly(shiftless(eupush(gx, gy) * spin(M_PI/4)), cgi.shCross, 0x808080FF);
1130 }
1131
1132 if(1) {
1133 dynamicval<ld> v(vid.linewidth, 8);
1134 curvepoint(eupush(gx+sd, gy-sd) * C0);
1135 curvepoint(eupush(gx+sd, gy+sd) * C0);
1136 curvepoint(eupush(gx-sd, gy+sd) * C0);
1137 curvepoint(eupush(gx-sd, gy-sd) * C0);
1138 curvepoint(eupush(gx+sd, gy-sd) * C0);
1139 queuecurve(shiftless(Id), 0x40404000 + sh->fstrength * 192/10, 0, PPR::LINE);
1140 }
1141
1142 for(int i=0; i<(ISMOBILE ? 10 : 1000); i++) {
1143 hyperpoint h1 = hpxy(sd * (6*randd()-3), sd * (6*randd()-3));
1144 hyperpoint h2 = hpxy(sd * (6*randd()-3), sd * (6*randd()-3));
1145 ld d = hdist(h1, h2);
1146 hyperpoint h3 = h1 + (h2-h1) /d * min(d, .1);
1147 for(int a=0; a<4; a++) {
1148 curvepoint(eupush(gx,gy) * eupush(spin(90*degree*a) * h1) * C0);
1149 curvepoint(eupush(gx,gy) * eupush(spin(90*degree*a) * h3) * C0);
1150 queuecurve(shiftless(Id), 0x10101010, 0, PPR::LINE);
1151 }
1152 }
1153
1154 auto& ftv = floor_texture_vertices[sh->id];
1155 ftv.tvertices.clear();
1156 ftv.texture_id = floor_textures->renderedTexture;
1157
1158 hyperpoint center = eupush(gx, gy) * C0;
1159 hyperpoint v1 = hpxyz3(sd, sd, 0, 0);
1160 hyperpoint v2 = hpxyz3(sd, -sd, 0, 0);
1161
1162 if(1) {
1163 hyperpoint inmodel;
1164 applymodel(shiftless(center), inmodel);
1165 glvertex tmap;
1166 tmap[0] = (1 + inmodel[0] * pconf.scale) / 2;
1167 tmap[1] = (1 - inmodel[1] * pconf.scale) / 2;
1168 applymodel(shiftless(center + v1), inmodel);
1169 tmap[2] = (1 + inmodel[0] * pconf.scale) / 2 - tmap[0];
1170 floor_texture_map[sh->id] = tmap;
1171 }
1172
1173 auto tvec_at = [&] (ld x, ld y) {
1174 hyperpoint h = center + v1 * x + v2 * y;
1175 hyperpoint inmodel;
1176 applymodel(shiftless(h), inmodel);
1177 glvec2 v;
1178 v[0] = (1 + inmodel[0] * pconf.scale) / 2;
1179 v[1] = (1 - inmodel[1] * pconf.scale) / 2;
1180 return v;
1181 };
1182
1183 // SL2 needs 6 times more
1184 texture_order([&] (ld x, ld y) {
1185 auto v = tvec_at(x, y);
1186 ftv.tvertices.push_back(glhr::makevertex(v[0], v[1], 0));
1187 });
1188
1189 floor_texture_square_size = 2 * (tvec_at(1, 0)[0] - tvec_at(0, 0)[0]);
1190 }
1191
1192 /** copy the texture vertices so that there are at least qty of them */
ensure_vertex_number(basic_textureinfo & bti,int qty)1193 EX void ensure_vertex_number(basic_textureinfo& bti, int qty) {
1194 int s = isize(bti.tvertices);
1195 if(!s) return;
1196 while(isize(bti.tvertices) <= qty) {
1197 for(int i=0; i<s; i++) bti.tvertices.push_back(bti.tvertices[i]);
1198 }
1199 }
1200
1201 /** ensure_vertex_number for a hpcshape */
ensure_vertex_number(hpcshape & sh)1202 EX void ensure_vertex_number(hpcshape& sh) {
1203 ensure_vertex_number(*sh.tinf, sh.e - sh.s);
1204 }
1205
bind_floor_texture(hpcshape & li,int id)1206 EX void bind_floor_texture(hpcshape& li, int id) {
1207 li.tinf = &floor_texture_vertices[id];
1208 ensure_vertex_number(li);
1209 }
1210
1211 #if HDR
1212 const int FLOORTEXTURESIZE = 4096;
1213 #endif
1214
make_floor_textures_here()1215 void geometry_information::make_floor_textures_here() {
1216 require_shapes();
1217
1218 dynamicval<videopar> vi(vid, vid);
1219 vid.xres = FLOORTEXTURESIZE;
1220 vid.yres = FLOORTEXTURESIZE;
1221 pconf.scale = 0.125;
1222 pconf.camera_angle = 0;
1223 pconf.alpha = 1;
1224 dynamicval<ld> lw(vid.linewidth, 2);
1225
1226 floor_textures = new renderbuffer(vid.xres, vid.yres, vid.usingGL);
1227 resetbuffer rb;
1228
1229 int q = isize(all_escher_floorshapes) + isize(all_plain_floorshapes);
1230 floor_texture_vertices.resize(q);
1231 floor_texture_map.resize(q);
1232
1233 auto cd = current_display;
1234 cd->xtop = cd->ytop = 0;
1235 cd->xsize = cd->ysize = FLOORTEXTURESIZE;
1236 cd->xcenter = cd->ycenter = cd->scrsize = FLOORTEXTURESIZE/2;
1237
1238 cd->radius = cd->scrsize * pconf.scale;
1239
1240 floor_textures->enable();
1241 #if CAP_VR
1242 dynamicval<int> i(vrhr::state, 0);
1243 #endif
1244 floor_textures->clear(0); // 0xE8E8E8 = 1
1245
1246 // gradient vertices
1247 vector<glhr::colored_vertex> gv;
1248 gv.emplace_back(-1, -1, 0, 0, 0);
1249 gv.emplace_back(+1, -1, 0, 0, 0);
1250 gv.emplace_back(+1, +1, 1, 1, 1);
1251 gv.emplace_back(-1, -1, 0, 0, 0);
1252 gv.emplace_back(+1, +1, 1, 1, 1);
1253 gv.emplace_back(-1, +1, 1, 1, 1);
1254
1255 #if CAP_RAY
1256 dynamicval<bool> riu(ray::in_use, false);
1257 #endif
1258
1259 if(1) {
1260 current_display->next_shader_flags = GF_VARCOLOR;
1261 dynamicval<eModel> m(pmodel, mdPixel);
1262 current_display->set_all(0,0);
1263 glhr::new_projection();
1264 glhr::id_modelview();
1265 glhr::prepare(gv);
1266 glhr::set_depthtest(false);
1267 glDrawArrays(GL_TRIANGLES, 0, isize(gv));
1268 }
1269
1270 shOverFloor.pstrength = 20;
1271 shFeatherFloor.pstrength = 40;
1272 shFeatherFloor.fstrength = 5;
1273 shTrollFloor.pstrength = 25;
1274 shCaveFloor.pstrength = 40;
1275 shCaveFloor.fstrength = 0;
1276 shDesertFloor.pstrength = 30;
1277 shDesertFloor.fstrength =10;
1278 shRoseFloor.pstrength = 30;
1279 shDragonFloor.pstrength = 30;
1280 shBarrowFloor.pstrength = 40;
1281
1282 // all using Tortoise
1283 for(auto v: all_escher_floorshapes) if(v->shapeid2 == 178) v->pstrength = 20;
1284
1285 ptds.clear();
1286
1287 for(auto v: all_plain_floorshapes) draw_shape_for_texture(v);
1288 for(auto v: all_escher_floorshapes) draw_shape_for_texture(v);
1289
1290 drawqueue();
1291
1292 /*
1293 SDL_Surface *sdark = floor_textures->render();
1294 IMAGESAVE(sdark, "texture-test.png");
1295 */
1296 rb.reset();
1297 last_texture_step = vid.texture_step;
1298 }
1299
make_floor_textures()1300 EX void make_floor_textures() {
1301 if(noGUI || !vid.usingGL) return;
1302 DEBBI(DF_POLY, ("make_floor_textures"));
1303 dynamicval<eGeometry> g(geometry, gEuclidSquare);
1304 dynamicval<eModel> gm(pmodel, mdDisk);
1305 dynamicval<eVariation> va(variation, eVariation::pure);
1306 dynamicval<geometryinfo1> gie(ginf[geometry].g, giEuclid2);
1307 dynamicval<geometryinfo1> gih(ginf[gNormal].g, giHyperb2);
1308 dynamicval<bool> a3(vid.always3, false);
1309 dynamicval<bool> hq(inHighQual, true);
1310 dynamicval<int> hd(darken, 0);
1311 dynamicval<ld> hll(levellines, 0);
1312 dynamicval<ld> gd(vid.depth, 1);
1313 dynamicval<ld> gc(vid.camera, 1);
1314 dynamicval<geometry_information*> dcgip(cgip, cgip);
1315 dynamicval<eStereo> gvs(vid.stereo_mode, sOFF);
1316 dynamicval<int> vgp(global_projection, 0);
1317 check_cgi();
1318 cgi.make_floor_textures_here();
1319 /* update texture ID in existing cgi's */
1320 for(auto& c: cgis) c.second.models_texture.texture_id = floor_textures->renderedTexture;
1321 }
1322
1323
1324 #endif
1325 }
1326