1 // HyperRogue -- user-defined shapes
2 // Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details
3 
4 /** \file usershapes.cpp
5  *  \brief user-defined shapes
6  */
7 
8 #include "hyper.h"
9 #if CAP_SHAPES
10 
11 namespace hr {
12 
13 EX int usershape_changes;
14 
15 EX array<map<int, usershape*>, mapeditor::USERSHAPEGROUPS> usershapes;
initShape(int sg,int id)16 EX void initShape(int sg, int id) {
17 
18   if(!usershapes[sg][id]) {
19     usershape *us = new usershape;
20     usershapes[sg][id] = us;
21 
22     for(int i=0; i<USERLAYERS; i++) {
23       us->d[i].prio = PPR((sg == 3 ? 1:50) + i);
24 
25       us->d[i].rots = 1;
26       us->d[i].sym = 0;
27       us->d[i].shift = C0;
28       us->d[i].spin = Cx1;
29       us->d[i].color = 0;
30       us->d[i].zlevel = 0;
31       }
32     }
33   }
34 
35 EX basic_textureinfo user_triangles_texture;
36 
pushShape(usershapelayer & ds)37 void geometry_information::pushShape(usershapelayer& ds) {
38 
39   if(ds.list.empty()) return;
40   if(GDIM == 3) last->flags |= POLY_TRIANGLES;
41 
42   transmatrix T = rgpushxto0(ds.shift) * rspintox(ds.spin);
43 
44   int z = GDIM == 3 ? 3 : 1;
45 
46   for(int r=0; r<ds.rots; r++) {
47     for(int i=0; i<isize(ds.list)/z*z; i++)
48       hpcpush(T * spin(2*M_PI*r/ds.rots) * ds.list[i]);
49 
50     if(ds.sym) {
51 
52       transmatrix mirrortrans = Id; mirrortrans[1][1] = -1;
53       for(int i=isize(ds.list)-1; i>=0; i--)
54         hpcpush(T * spin(2*M_PI*r/ds.rots) * mirrortrans * ds.list[i]);
55       }
56     }
57 
58   if(GDIM == 2) hpcpush(T * ds.list[0]);
59 
60   #if MAXMDIM >= 4 && CAP_GL
61   if(GDIM == 3) {
62     auto& utt = user_triangles_texture;
63     utt.texture_id = floor_textures->renderedTexture;
64     ds.texture_offset = isize(utt.tvertices);
65     for(int i=0; i<isize(ds.list)-2; i+=3) {
66       hyperpoint h = orthogonal_of_C0(ds.list[i], ds.list[i+1], ds.list[i+2]);
67       ld rad = hypot_d(3, h);
68       ld factor = 0.49 + (0.17 * h[2] + 0.13 * h[1] + 0.20 * h[0]) / rad;
69       for(int i=0; i<3; i++)
70         utt.tvertices.push_back(glhr::makevertex(-1, factor, 0));
71       }
72     }
73   #endif
74   }
75 
prepare_usershapes()76 void geometry_information::prepare_usershapes() {
77   hpc.resize(prehpc);
78   last = NULL;
79   DEBB(DF_POLY, ("hpc = ", prehpc));
80 
81   user_triangles_texture.tvertices.clear();
82 
83   for(int i=0; i<mapeditor::USERSHAPEGROUPS; i++) for(auto usp: usershapes[i]) {
84     auto us = usp.second;
85     if(!us) continue;
86     for(int l=0; l<USERLAYERS; l++) {
87       bshape(ushr[&us->d[l]], us->d[l].prio);
88       pushShape(us->d[l]);
89       finishshape();
90       }
91     }
92 
93   static int qhpc0;
94   int qhpc = isize(hpc);
95   if(qhpc != qhpc0 && (debugflags & (DF_GEOM | DF_POLY))) {
96     println(hlog, "qhpc = ", qhpc0=qhpc, " (", prehpc, "+", qhpc-prehpc, ")");
97     println(hlog, "shapes = ", isize(allshapes));
98     int inve=0, issi=0, vcon=0, ccon=0;
99     for(auto sh: allshapes) {
100       if(sh->flags & POLY_INVERSE) inve++;
101       if(sh->flags & POLY_ISSIDE) issi++;
102       if(sh->flags & POLY_VCONVEX) vcon++;
103       if(sh->flags & POLY_CCONVEX) ccon++;
104       }
105     println(hlog, format("inverse = %d isside = %d vcon = %d ccon = %d", inve, issi, vcon, ccon));
106     }
107 
108   initPolyForGL();
109   }
110 
111 }
112 #endif
113