mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-01-23 07:27:07 +00:00
further work on textures
This commit is contained in:
parent
45cc122927
commit
6c4538df69
13
graph.cpp
13
graph.cpp
@ -2912,7 +2912,7 @@ int wavephase;
|
||||
void warpfloor(cell *c, const transmatrix& V, int col, int prio, bool warp) {
|
||||
if(shmup::on || nontruncated) warp = false;
|
||||
if(qfi.tinf) {
|
||||
queuetable(V*qfi.spin, &qfi.tinf->vertices[0], size(qfi.tinf->vertices) / 3, 0, col, prio);
|
||||
queuetable(V*qfi.spin, &qfi.tinf->vertices[0], size(qfi.tinf->vertices) / 3, 0, texture::recolor(col), prio);
|
||||
lastptd().u.poly.tinf = qfi.tinf;
|
||||
}
|
||||
else if(wmescher && qfi.special)
|
||||
@ -3532,7 +3532,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
|
||||
}
|
||||
#endif
|
||||
|
||||
else if(applyTextureMap(c, Vf, darkena(fcol, fd, 0xFF))) ;
|
||||
else if(texture::apply(c, Vf, darkena(fcol, fd, 0xFF))) ;
|
||||
|
||||
else if(c->land == laMirrorWall) {
|
||||
int d = mirror::mirrordir(c);
|
||||
@ -3899,7 +3899,10 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
|
||||
|
||||
auto si = patterns::getpatterninfo(c, patterns::whichPattern, pf);
|
||||
|
||||
queuepoly(V * applyPatterndir(c,si), shAsymmetric, darkena(0x000000, 0, 0xC0));
|
||||
for(int i=0; i<c->type; i += si.symmetries) {
|
||||
queuepoly(V * applyPatterndir(c,si), shAsymmetric, darkena(0x000000, 0, 0xC0));
|
||||
si.dir += si.symmetries;
|
||||
}
|
||||
|
||||
string label = its(si.id);
|
||||
queuestr(V, .5, label, 0xFF000000 + forecolor);
|
||||
@ -5073,8 +5076,10 @@ void calcparam() {
|
||||
vid.ycenter = vid.yres / 2;
|
||||
|
||||
int realradius = min(vid.xcenter, vid.ycenter);
|
||||
|
||||
vid.scrsize = vid.ycenter - (ISANDROID ? 2 : ISIOS ? 40 : 40);
|
||||
|
||||
vid.radius = int(vid.scale * vid.ycenter) - (ISANDROID ? 2 : ISIOS ? 40 : 40);
|
||||
vid.radius = vid.scale * vid.scrsize;
|
||||
|
||||
realradius = min(realradius, vid.radius);
|
||||
|
||||
|
@ -150,13 +150,6 @@ const transmatrix MirrorX = {{{-1,0,0}, {0,1,0}, {0,0,1}}};
|
||||
// rotate by PI
|
||||
const transmatrix pispin = {{{-1,0,0}, {0,-1,0}, {0,0,1}}};
|
||||
|
||||
// T * C0, optimized
|
||||
inline hyperpoint tC0(const transmatrix &T) {
|
||||
hyperpoint z;
|
||||
z[0] = T[0][2]; z[1] = T[1][2]; z[2] = T[2][2];
|
||||
return z;
|
||||
}
|
||||
|
||||
// rotate by alpha degrees
|
||||
transmatrix spin(ld alpha) {
|
||||
transmatrix T = Id;
|
||||
@ -173,6 +166,29 @@ transmatrix eupush(ld x, ld y) {
|
||||
return T;
|
||||
}
|
||||
|
||||
transmatrix eupush(hyperpoint h) {
|
||||
transmatrix T = Id;
|
||||
T[0][2] = h[0];
|
||||
T[1][2] = h[1];
|
||||
return T;
|
||||
}
|
||||
|
||||
transmatrix euscalezoom(hyperpoint h) {
|
||||
transmatrix T = Id;
|
||||
T[0][0] = h[0];
|
||||
T[0][1] = -h[1];
|
||||
T[1][0] = h[1];
|
||||
T[1][1] = h[0];
|
||||
return T;
|
||||
}
|
||||
|
||||
transmatrix euaffine(hyperpoint h) {
|
||||
transmatrix T = Id;
|
||||
T[1][0] = h[0];
|
||||
T[1][2] = h[1];
|
||||
return T;
|
||||
}
|
||||
|
||||
// push alpha units to the right
|
||||
transmatrix xpush(ld alpha) {
|
||||
if(euclid) return eupush(alpha, 0);
|
||||
|
@ -346,7 +346,7 @@ void showDisplayMode() {
|
||||
#endif
|
||||
|
||||
#if CAP_TEXTURE
|
||||
dialog::addBoolItem(XLAT("texture mode"), texture_on, 't');
|
||||
dialog::addBoolItem(XLAT("texture mode"), texture::tstate == texture::tsActive, 't');
|
||||
#endif
|
||||
|
||||
|
||||
@ -372,8 +372,8 @@ void showDisplayMode() {
|
||||
|
||||
if(xuni == 'z') editScale();
|
||||
|
||||
if(xuni == 't') pushScreen(showTextureMenu);
|
||||
|
||||
if(xuni == 't') pushScreen(texture::showMenu);
|
||||
|
||||
if(xuni == 'm') { vid.monmode += 60 + (shiftmul > 0 ? 1 : -1); vid.monmode %= 6; }
|
||||
|
||||
if(xuni == '9') pushScreen(show3D);
|
||||
|
142
pattern2.cpp
142
pattern2.cpp
@ -552,77 +552,79 @@ namespace patterns {
|
||||
else si.symmetries = ctof(c) ? 1 : 2;
|
||||
}
|
||||
|
||||
void val_warped(cell *c, patterninfo& si, int sub) {
|
||||
void val_warped(cell *c, patterninfo& si) {
|
||||
int u = ishept(c)?1:0;
|
||||
int qhex = 0;
|
||||
for(int v=0; v<c->type; v++) if(c->mov[v] && !isWarped(c->mov[v])) {
|
||||
u += 2;
|
||||
if(!ishept(c->mov[v])) qhex++;
|
||||
}
|
||||
if(u == 8 && qhex == 2) si.id = 12;
|
||||
else if(u == 2 && qhex == 1) si.id = 8;
|
||||
else if(u == 6 && qhex == 2) si.id = 10;
|
||||
si.id = u;
|
||||
|
||||
if(u == 6) {
|
||||
for(int i=1; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
|
||||
si.dir = i;
|
||||
}
|
||||
|
||||
else if(u == 2 || u == 3 || u == 8) {
|
||||
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,i)))
|
||||
si.dir = i;
|
||||
}
|
||||
|
||||
else if(u == 4 || u == 10) {
|
||||
for(int i=0; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
|
||||
si.dir = i;
|
||||
if(u == 4)
|
||||
si.reflect = !isWarped(createMov(c, (si.dir+1)%6));
|
||||
}
|
||||
|
||||
else if(u == 6) {
|
||||
for(int i=1; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
|
||||
si.dir = i;
|
||||
}
|
||||
|
||||
else if(u == 5) {
|
||||
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,(i+3)%7)) && !isWarped(createMov(c,(i+4)%7)))
|
||||
si.dir = i;
|
||||
}
|
||||
|
||||
else if(u == 9) {
|
||||
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,(i+2)%7)) && !isWarped(createMov(c,(i+5)%7)))
|
||||
si.dir = i;
|
||||
}
|
||||
|
||||
else if(u == 11) {
|
||||
for(int i=0; i<c->type; i++) if(isWarped(createMov(c,(i)%7)) && isWarped(createMov(c,(i+1)%7)))
|
||||
si.dir = i;
|
||||
}
|
||||
|
||||
else if(u == 12) {
|
||||
for(int i=0; i<c->type; i+=2) if(isWarped(createMov(c,i))) {
|
||||
si.dir = i;
|
||||
si.reflect = !isWarped(createMov(c, (i+1)%6));
|
||||
}
|
||||
}
|
||||
|
||||
else if(u == 7) {
|
||||
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,(i+1)%7)) && !isWarped(createMov(c,(i+6)%7)))
|
||||
si.dir = i;
|
||||
}
|
||||
}
|
||||
|
||||
void val_nopattern(cell *c, patterninfo& si, int sub) {
|
||||
// use val_all for nicer rotation
|
||||
val_all(c, si, 0, 0);
|
||||
|
||||
// get id:
|
||||
if(stdhyperbolic && isWarped(c)) {
|
||||
int u = ishept(c)?1:0;
|
||||
int qhex = 0;
|
||||
for(int v=0; v<c->type; v++) if(c->mov[v] && !isWarped(c->mov[v])) {
|
||||
u += 2;
|
||||
if(!ishept(c->mov[v])) qhex++;
|
||||
}
|
||||
if(u == 8 && qhex == 2) si.id = 12;
|
||||
else if(u == 2 && qhex == 1) si.id = 8;
|
||||
else if(u == 6 && qhex == 2) si.id = 10;
|
||||
si.id = u;
|
||||
|
||||
if(u == 6) {
|
||||
for(int i=1; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
|
||||
si.dir = i;
|
||||
}
|
||||
|
||||
else if(u == 2 || u == 3 || u == 8) {
|
||||
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,i)))
|
||||
si.dir = i;
|
||||
}
|
||||
|
||||
else if(u == 4 || u == 10) {
|
||||
for(int i=0; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
|
||||
si.dir = i;
|
||||
if(u == 4)
|
||||
si.reflect = !isWarped(createMov(c, (si.dir+1)%6));
|
||||
}
|
||||
|
||||
else if(u == 6) {
|
||||
for(int i=1; i<c->type; i+=2) if(!isWarped(createMov(c,i)))
|
||||
si.dir = i;
|
||||
}
|
||||
|
||||
else if(u == 5) {
|
||||
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,(i+3)%7)) && !isWarped(createMov(c,(i+4)%7)))
|
||||
si.dir = i;
|
||||
}
|
||||
|
||||
else if(u == 9) {
|
||||
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,(i+2)%7)) && !isWarped(createMov(c,(i+5)%7)))
|
||||
si.dir = i;
|
||||
}
|
||||
|
||||
else if(u == 11) {
|
||||
for(int i=0; i<c->type; i++) if(isWarped(createMov(c,(i)%7)) && isWarped(createMov(c,(i+1)%7)))
|
||||
si.dir = i;
|
||||
}
|
||||
|
||||
else if(u == 12) {
|
||||
for(int i=0; i<c->type; i+=2) if(isWarped(createMov(c,i))) {
|
||||
si.dir = i;
|
||||
si.reflect = !isWarped(createMov(c, (i+1)%6));
|
||||
}
|
||||
}
|
||||
|
||||
else if(u == 7) {
|
||||
for(int i=0; i<c->type; i++) if(!isWarped(createMov(c,(i+1)%7)) && !isWarped(createMov(c,(i+6)%7)))
|
||||
si.dir = i;
|
||||
}
|
||||
|
||||
}
|
||||
if(stdhyperbolic && isWarped(c))
|
||||
val_warped(c, si);
|
||||
else {
|
||||
si.id = ishept(c) ? 1 : 0;
|
||||
if(euclid) {
|
||||
si.dir = ishex1(c) ? 3 : 0;
|
||||
si.dir = ishex1(c) ? 0 : 3;
|
||||
if(ctof(c)) si.symmetries = 3;
|
||||
if(subpattern_flags & SPF_EXTRASYM)
|
||||
si.symmetries /= 3;
|
||||
@ -803,7 +805,7 @@ namespace patterns {
|
||||
}
|
||||
|
||||
else
|
||||
val_warped(c, si, sub);
|
||||
val_nopattern(c, si, sub);
|
||||
|
||||
return si;
|
||||
}
|
||||
@ -870,7 +872,7 @@ int pattern_threecolor(cell *c) {
|
||||
}
|
||||
if(S7 == 3 && nontruncated)
|
||||
return c->master->fiftyval;
|
||||
if(euclid) return eupattern(c);
|
||||
if(euclid) return (eupattern(c)+1) % 3;
|
||||
return !ishept(c);
|
||||
}
|
||||
|
||||
@ -1099,7 +1101,7 @@ namespace patterns {
|
||||
}
|
||||
|
||||
if((euclid && whichPattern == PAT_COLORING) ||
|
||||
(a38 && nontruncated && whichPattern == PAT_COLORING) ||
|
||||
(a38 && whichPattern == PAT_COLORING) ||
|
||||
(S3 == 4 && nontruncated && whichPattern == PAT_COLORING))
|
||||
dialog::addBoolItem(XLAT("edit all three colors"), subpattern_flags & SPF_ROT, '0');
|
||||
|
||||
@ -1139,16 +1141,20 @@ namespace patterns {
|
||||
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
printf("uni = %c\n", uni);
|
||||
|
||||
if(among(uni, PAT_EMERALD, PAT_PALACE, PAT_ZEBRA, PAT_DOWN, PAT_FIELD, PAT_COLORING, PAT_SIBLING)) {
|
||||
if(whichPattern == uni) whichPattern = 0;
|
||||
else whichPattern = uni;
|
||||
mapeditor::modelcell.clear();
|
||||
}
|
||||
|
||||
else if(printf("not among\n"), 0) ;
|
||||
|
||||
else if(uni >= '0' && uni <= '5')
|
||||
subpattern_flags ^= (1 << (uni - '0'));
|
||||
|
||||
else if(uni >= '=')
|
||||
else if(uni == '=')
|
||||
subpattern_flags ^= SPF_EXTRASYM;
|
||||
|
||||
else if(uni == '6' || uni == '7' || uni == '8') {
|
||||
|
19
polygons.cpp
19
polygons.cpp
@ -340,7 +340,7 @@ void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline
|
||||
glStencilOp( GL_INVERT, GL_INVERT, GL_INVERT);
|
||||
glStencilFunc( GL_ALWAYS, 0x1, 0x1 );
|
||||
glColor4f(1,1,1,1);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, ps, pq);
|
||||
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, ps, pq);
|
||||
|
||||
if(flags & POLY_INVERSE) {
|
||||
selectEyeMask(ed);
|
||||
@ -356,7 +356,7 @@ void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline
|
||||
GLfloat *cur = currentvertices;
|
||||
activateVertexArray(scr, 4);
|
||||
if(useV) glPopMatrix();
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, 0, 4);
|
||||
activateVertexArray(cur, 0);
|
||||
draw = false; goto again;
|
||||
}
|
||||
@ -365,7 +365,7 @@ void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline
|
||||
glcolor2(col);
|
||||
glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO);
|
||||
glStencilFunc( GL_EQUAL, 1, 1);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, ps, pq);
|
||||
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, ps, pq);
|
||||
}
|
||||
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
@ -892,7 +892,7 @@ void drawqueue() {
|
||||
|
||||
hpcshape
|
||||
shFloorSide[SIDEPARS][2], shSemiFloorSide[SIDEPARS], shTriheptaSide[SIDEPARS][2], shMFloorSide[SIDEPARS][2], shFullFloorSide[SIDEPARS][2],
|
||||
shFullFloor[2],
|
||||
shFullFloor[2], shFullCross[2],
|
||||
shSeabed[2], shCloudSeabed[3], shCaveSeabed[3],
|
||||
shWave[8][2],
|
||||
shFloor[2], shBFloor[2], shMFloor2[2], shMFloor3[2], shMFloor4[2],
|
||||
@ -1270,6 +1270,17 @@ void buildpolys() {
|
||||
for(int t=0; t<=S7; t++) hpcpush(ddi(t*S12+td, x) * C0);
|
||||
}
|
||||
|
||||
{double x = hexvdist;
|
||||
bshape(shFullCross[0], PPR_FLOOR);
|
||||
x *= bscale6;
|
||||
for(int t=0; t<=S6; t++) { hpcpush(C0); if(t) hpcpush(ddi(S7 + t*S14, x) * C0); }
|
||||
|
||||
x = rhexf;
|
||||
x *= bscale7;
|
||||
bshape(shFullCross[1], PPR_FLOOR);
|
||||
for(int t=0; t<=S7; t++) { hpcpush(C0); if(t) hpcpush(ddi(t*S12+td, x) * C0); }
|
||||
}
|
||||
|
||||
bool strict = false;
|
||||
|
||||
if(a4 && nontruncated) fac94 *= 1.1;
|
||||
|
464
textures.cpp
464
textures.cpp
@ -1,6 +1,8 @@
|
||||
#include <SDL/SDL_image.h>
|
||||
|
||||
glfont_t textures;
|
||||
namespace texture {
|
||||
|
||||
GLuint textureid;
|
||||
|
||||
SDL_Surface *convertSurface(SDL_Surface* s) {
|
||||
SDL_PixelFormat fmt;
|
||||
@ -29,102 +31,201 @@ SDL_Surface *convertSurface(SDL_Surface* s) {
|
||||
|
||||
bool texture_read = false;
|
||||
|
||||
int twidth = 2048;
|
||||
|
||||
vector<int> expanded_data;
|
||||
|
||||
string texturename;
|
||||
|
||||
void sdltogl_bmp(SDL_Surface *txt, glfont_t& f, int ch) {
|
||||
eTextureState tstate;
|
||||
|
||||
int dim = min(txt->w, txt->h);
|
||||
int otwidth = dim;
|
||||
int otheight = dim;
|
||||
template<class T, class U> void scale_colorarray(int origdim, const T& src, const U& dest) {
|
||||
int ox = 0, tx = 0, partials[4];
|
||||
int omissing = twidth, tmissing = origdim;
|
||||
for(int p=0; p<4; p++) partials[p] = 0;
|
||||
|
||||
int twidth = next_p2( otwidth );
|
||||
int theight = next_p2( otheight );
|
||||
|
||||
expanded_data.resize(twidth * theight);
|
||||
|
||||
for(int j=0; j <theight;j++) for(int i=0; i < twidth; i++) {
|
||||
expanded_data[(i+j*twidth)] = qpixel(txt, i, j);
|
||||
while(tx < twidth) {
|
||||
int fv = min(omissing, tmissing);
|
||||
int c = src(ox);
|
||||
for(int p=0; p<4; p++)
|
||||
partials[p] += part(c, p) * fv;
|
||||
omissing -= fv; tmissing -= fv;
|
||||
if(omissing == 0) {
|
||||
ox++; omissing = twidth;
|
||||
}
|
||||
if(tmissing == 0) {
|
||||
int target;
|
||||
for(int p=0; p<4; p++) {
|
||||
part(target, p) = partials[p] / origdim;
|
||||
partials[p] = 0;
|
||||
}
|
||||
dest(tx++, target);
|
||||
tmissing = origdim;
|
||||
}
|
||||
}
|
||||
|
||||
f.widths[ch] = otwidth;
|
||||
f.heights[ch] = otheight;
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, f.textures[ch]);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
|
||||
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, twidth, theight, 0,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE,
|
||||
&expanded_data[0] );
|
||||
|
||||
float x=(float)otwidth / (float)twidth;
|
||||
float y=(float)otheight / (float)theight;
|
||||
f.tx[ch] = x;
|
||||
f.ty[ch] = y;
|
||||
}
|
||||
|
||||
void readtexture() {
|
||||
texture_read = true;
|
||||
|
||||
glfont_t& f = textures;
|
||||
glGenTextures(1, &textureid );
|
||||
|
||||
int NUMPICS = 2;
|
||||
SDL_Surface *txt = IMG_Load(texturename.c_str());
|
||||
auto txt2 = convertSurface(txt);
|
||||
|
||||
f.textures = new GLuint[NUMPICS];
|
||||
glGenTextures( NUMPICS, f.textures );
|
||||
if(0) for(int i=0; i<NUMPICS; i++)
|
||||
printf("pic %d = %d\n", i, f.textures[i]);
|
||||
int tx = txt->w, ty = txt->h;
|
||||
|
||||
SDL_FreeSurface(txt);
|
||||
|
||||
for(int ch=1; ch<NUMPICS; ch++) {
|
||||
SDL_Surface *txt = IMG_Load(texturename.c_str());
|
||||
auto txt2 = convertSurface(txt);
|
||||
vector<int> half_expanded(twidth * ty);
|
||||
expanded_data.resize(twidth * twidth);
|
||||
|
||||
int origdim = max(tx, ty);
|
||||
int base_x = tx/2 - origdim/2;
|
||||
int base_y = ty/2 - origdim/2;
|
||||
ZZ = 0;
|
||||
|
||||
sdltogl_bmp(txt2, f, ch);
|
||||
SDL_FreeSurface(txt);
|
||||
SDL_FreeSurface(txt2);
|
||||
}
|
||||
/* for(int y=0; y<twidth; y++)
|
||||
for(int x=0; x<twidth; x++)
|
||||
expanded_data[y*twidth+x] = qpixel(txt2, y%ty, x%tx); */
|
||||
|
||||
//printf("init size=%d ok\n", size);
|
||||
// GLERR("initfont");
|
||||
for(int y=0; y<ty; y++)
|
||||
scale_colorarray(origdim,
|
||||
[&] (int x) { return qpixel(txt2, base_x + x, y); },
|
||||
[&] (int x, int v) { half_expanded[twidth * y + x] = v; }
|
||||
);
|
||||
|
||||
SDL_FreeSurface(txt2);
|
||||
|
||||
for(int x=0; x<twidth; x++)
|
||||
scale_colorarray(origdim,
|
||||
[&] (int y) { return base_y+y < 0 || base_y+y >= ty ? 0 : half_expanded[x + (base_y + y) * twidth]; },
|
||||
[&] (int y, int v) { expanded_data[twidth * y + x] = v; }
|
||||
);
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, textureid);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
|
||||
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, twidth, twidth, 0,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE,
|
||||
&expanded_data[0] );
|
||||
|
||||
}
|
||||
|
||||
ld iscale = 1;
|
||||
ld irotate = 0;
|
||||
transmatrix itt = Id;
|
||||
|
||||
int grid_alpha = 0;
|
||||
int mesh_alpha = 0;
|
||||
int color_alpha = 0;
|
||||
|
||||
unsigned int glc = 0xFFFFFFDD;
|
||||
|
||||
void mapTextureTriangle(textureinfo &mi, array<hyperpoint, 3> v) {
|
||||
int gsplits = 1;
|
||||
|
||||
int tabid = 1;
|
||||
|
||||
glfont_t& f(textures);
|
||||
float fx=f.tx[tabid];
|
||||
float fy=f.ty[tabid];
|
||||
void mapTextureTriangle(textureinfo &mi, array<hyperpoint, 3> vview, array<hyperpoint, 3> vmap, int splits = gsplits) {
|
||||
|
||||
if(splits) {
|
||||
array<hyperpoint, 3> vview2 = { mid(vview[1], vview[2]), mid(vview[2], vview[0]), mid(vview[0], vview[1]) };
|
||||
array<hyperpoint, 3> vmap2 = { mid(vmap [1], vmap [2]), mid(vmap [2], vmap [0]), mid(vmap [0], vmap [1]) };
|
||||
mapTextureTriangle(mi, {vview[0], vview2[1], vview2[2]}, {vmap[0], vmap2[1], vmap2[2]}, splits-1);
|
||||
mapTextureTriangle(mi, {vview[1], vview2[2], vview2[0]}, {vmap[1], vmap2[2], vmap2[0]}, splits-1);
|
||||
mapTextureTriangle(mi, {vview[2], vview2[0], vview2[1]}, {vmap[2], vmap2[0], vmap2[1]}, splits-1);
|
||||
mapTextureTriangle(mi, {vview2[0], vview2[1], vview2[2]}, {vmap2[0], vmap2[1], vmap2[2]}, splits-1);
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i=0; i<3; i++) {
|
||||
for(int j=0; j<3; j++)
|
||||
mi.vertices.push_back(v[i][j]);
|
||||
mi.vertices.push_back(vview[i][j]);
|
||||
hyperpoint inmodel;
|
||||
applymodel(mi.M * v[i], inmodel);
|
||||
inmodel = spin(M_PI * irotate / 180) * inmodel;
|
||||
mi.tvertices.push_back(fx * (iscale * inmodel[0]+1)/2);
|
||||
mi.tvertices.push_back(fy * (iscale * inmodel[1]+1)/2);
|
||||
applymodel(mi.M * vmap[i], inmodel);
|
||||
inmodel = itt * inmodel;
|
||||
inmodel[0] *= vid.radius * 1. / vid.scrsize;
|
||||
inmodel[1] *= vid.radius * 1. / vid.scrsize;
|
||||
mi.tvertices.push_back((inmodel[0]+1)/2);
|
||||
mi.tvertices.push_back((inmodel[1]+1)/2);
|
||||
mi.tvertices.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
map<int, textureinfo> texture_map;
|
||||
set<cell*> models;
|
||||
|
||||
void mapTexture(cell *c, textureinfo& mi, patterns::patterninfo &si, const transmatrix& T) {
|
||||
mi.c = c;
|
||||
mi.vertices.clear();
|
||||
mi.tvertices.clear();
|
||||
mi.symmetries = si.symmetries;
|
||||
mi.current_type = c->type;
|
||||
mi.current_geometry = geometry;
|
||||
mi.current_trunc = nontruncated;
|
||||
|
||||
mi.M = T * applyPatterndir(c, si);
|
||||
|
||||
if(tstate == tsAdjusting) return;
|
||||
|
||||
ld z = ctof(c) ? rhexf : hexvdist;
|
||||
|
||||
int sym = si.symmetries;
|
||||
|
||||
for(int i=0; i<c->type; i++) {
|
||||
int is = i % sym;
|
||||
hyperpoint h1 = spin(M_PI + M_PI * (2*i +1) / c->type) * xpush(z) * C0;
|
||||
hyperpoint h2 = spin(M_PI + M_PI * (2*i -1) / c->type) * xpush(z) * C0;
|
||||
hyperpoint hm1 = spin(M_PI + M_PI * (2*is+1) / c->type) * xpush(z) * C0;
|
||||
hyperpoint hm2 = spin(M_PI + M_PI * (2*is-1) / c->type) * xpush(z) * C0;
|
||||
mapTextureTriangle(mi, {C0, h1, h2}, {C0, hm1, hm2});
|
||||
}
|
||||
}
|
||||
|
||||
int recolor(int col) {
|
||||
if(color_alpha == 0) return col;
|
||||
if(color_alpha == 255) return col | 0xFFFFFF00;
|
||||
for(int i=1; i<4; i++)
|
||||
part(col, i) = color_alpha + ((255-color_alpha) * part(col,i) + 127) / 255;
|
||||
return col;
|
||||
}
|
||||
|
||||
bool apply(cell *c, const transmatrix &V, int col) {
|
||||
if(tstate == tsOff) return false;
|
||||
|
||||
bool applyTextureMap(cell *c, const transmatrix &V, int col) {
|
||||
using namespace patterns;
|
||||
auto si = getpatterninfo0(c);
|
||||
|
||||
if(tstate == tsAdjusting) {
|
||||
queuepolyat(V, shFullCross[ctof(c)], 0, PPR_LINE);
|
||||
lastptd().u.poly.outline = models.count(c) ? 0xFFFFFF08 : 0xFF000008;
|
||||
queuepolyat(V, shFullFloor[ctof(c)], 0, PPR_LINE);
|
||||
lastptd().u.poly.outline = models.count(c) ? 0xFFFFFF10 : 0xFF000010;
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
auto& mi = texture_map.at(si.id);
|
||||
|
||||
qfi.spin = applyPatterndir(c, si);
|
||||
|
||||
int n = mi.vertices.size() / 3;
|
||||
|
||||
if(geometry != mi.current_geometry || nontruncated != mi.current_trunc) {
|
||||
// we can easily make it more symmetric
|
||||
mi.symmetries = gcd(mi.symmetries, si.symmetries);
|
||||
|
||||
printf("Redrawing tile #%d from %d to %d\n", si.id, mi.current_type, c->type);
|
||||
int nbase = n * mi.symmetries / mi.current_type;
|
||||
int ntarget = nbase * c->type / mi.symmetries;
|
||||
printf("n = %d nbase = %d ntarget = %d\n", n, nbase, ntarget);
|
||||
vector<GLfloat> new_tvertices = move(mi.tvertices);
|
||||
new_tvertices.resize(3*ntarget);
|
||||
for(int i=3*nbase; i<3*ntarget; i++) {
|
||||
new_tvertices[i] = new_tvertices[i - 3*nbase];
|
||||
}
|
||||
|
||||
mapTexture(c, mi, si, Id);
|
||||
mi.tvertices = move(new_tvertices);
|
||||
n = mi.vertices.size() / 3;
|
||||
printf("new n = %d\n", n);
|
||||
}
|
||||
|
||||
qfi.special = false;
|
||||
qfi.shape = &shFullFloor[ctof(c)];
|
||||
@ -133,74 +234,52 @@ bool applyTextureMap(cell *c, const transmatrix &V, int col) {
|
||||
if(chasmg == 2) return false;
|
||||
else if(chasmg && wmspatial) {
|
||||
if(detaillevel == 0) return false;
|
||||
queuetable(V * qfi.spin, &mi.vertices[0], n, 0, c->land == laCocytus ? 0x080808FF : 0x101010FF, PPR_LAKEBOTTOM);
|
||||
queuetable(V * qfi.spin, &mi.vertices[0], n, mesh_alpha, recolor(c->land == laCocytus ? 0x080808FF : 0x101010FF), PPR_LAKEBOTTOM);
|
||||
}
|
||||
else {
|
||||
queuetable(V * qfi.spin, &mi.vertices[0], n, 0, col, PPR_FLOOR);
|
||||
queuetable(V * qfi.spin, &mi.vertices[0], n, mesh_alpha, recolor(col), PPR_FLOOR);
|
||||
}
|
||||
|
||||
lastptd().u.poly.tinf = &mi;
|
||||
if(grid_alpha) {
|
||||
queuepolyat(V, shFullFloor[ctof(c)], 0, PPR_FLOOR);
|
||||
lastptd().u.poly.outline = grid_alpha;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch(out_of_range) {
|
||||
// printf("Ignoring tile #%d : not mapped\n", si.id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void perform_mapping() {
|
||||
if(gsplits < 0) gsplits = 0;
|
||||
if(gsplits > 4) gsplits = 4;
|
||||
using namespace patterns;
|
||||
if(!texture_read) readtexture();
|
||||
texture_map.clear();
|
||||
glfont_t& f(textures); int tabid = 1;
|
||||
for(auto p: gmatrix) {
|
||||
cell *c = p.first;
|
||||
auto si = getpatterninfo0(c);
|
||||
bool replace = false;
|
||||
|
||||
int sgn = sphere ? -1 : 1;
|
||||
// int sgn = sphere ? -1 : 1;
|
||||
|
||||
if(!texture_map.count(si.id))
|
||||
replace = true;
|
||||
else if(sgn * p.second[2][2] < sgn * texture_map[si.id].M[2][2])
|
||||
else if(hdist0(p.second*C0) < hdist0(texture_map[si.id].M * C0))
|
||||
replace = true;
|
||||
|
||||
if(replace) {
|
||||
auto& mi = texture_map[si.id];
|
||||
mi.M = p.second;
|
||||
mi.vertices.clear();
|
||||
mi.tvertices.clear();
|
||||
|
||||
mi.M = mi.M * applyPatterndir(c, si);
|
||||
|
||||
ld z = ctof(c) ? rhexf : hexvdist;
|
||||
ld base = ctof(c) ? 0 : 0; // -hexshift;
|
||||
if(!ctof(c) || nontruncated) base -= M_PI / c->type;
|
||||
|
||||
for(int i=0; i<c->type; i++) {
|
||||
hyperpoint h1 = spin(base + M_PI * (2*i) / c->type) * xpush(z) * C0;
|
||||
hyperpoint h2 = spin(base + M_PI * (2*i+2) / c->type) * xpush(z) * C0;
|
||||
mapTextureTriangle(mi, {C0, h1, h2});
|
||||
}
|
||||
|
||||
mi.texture_id = f.textures[tabid];
|
||||
}
|
||||
mapTexture(c, mi, si, p.second);
|
||||
mi.texture_id = textureid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool forge_handleKey(int sym, int uni) {
|
||||
|
||||
if(sym == SDLK_F4) {
|
||||
glc += 0x11;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(sym == SDLK_F5) {
|
||||
glc -= 0x11;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
models.clear();
|
||||
for(auto& t: texture_map) models.insert(t.second.c);
|
||||
}
|
||||
|
||||
int forgeArgs() {
|
||||
@ -211,55 +290,206 @@ int forgeArgs() {
|
||||
shift(); texturename = args();
|
||||
}
|
||||
|
||||
else if(argis("-fsp")) {
|
||||
shift(); gsplits = argf();
|
||||
}
|
||||
|
||||
else return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool newmove = false;
|
||||
|
||||
auto texture_hook =
|
||||
addHook(hooks_args, 100, forgeArgs)
|
||||
+ addHook(hooks_handleKey, 100, forge_handleKey);
|
||||
addHook(hooks_args, 100, forgeArgs);
|
||||
|
||||
bool texture_on = false;
|
||||
void drawRawTexture() {
|
||||
if(!texture_read) readtexture();
|
||||
glDisable(GL_LIGHTING);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glcolor2(0xFFFFFF20);
|
||||
glPushMatrix();
|
||||
glTranslatef(0, 0, vid.scrdist);
|
||||
glBindTexture(GL_TEXTURE_2D, textureid);
|
||||
vector<GLfloat> tver, sver;
|
||||
for(int i=0; i<4; i++) {
|
||||
int cx[4] = {1, -1, -1, 1};
|
||||
int cy[4] = {1, 1, -1, -1};
|
||||
int x = cx[i];
|
||||
int y = cy[i];
|
||||
hyperpoint inmodel = hpxyz(x, y, 1);
|
||||
inmodel = itt * inmodel;
|
||||
tver.push_back((inmodel[0]+1)/2);
|
||||
tver.push_back((inmodel[1]+1)/2);
|
||||
tver.push_back(0);
|
||||
sver.push_back(x * vid.scrsize);
|
||||
sver.push_back(y * vid.scrsize);
|
||||
sver.push_back(0);
|
||||
}
|
||||
activateVertexArray(&sver[0], 4);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(3, GL_FLOAT, 0, &tver[0]);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glPopMatrix();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void showTextureMenu() {
|
||||
cmode = sm::SIDE | sm::MAYDARK;
|
||||
enum eTexturePanstate {tpsModel, tpsMove, tpsScale, tpsAffine, tpsZoom, tpsProjection};
|
||||
eTexturePanstate panstate;
|
||||
|
||||
void showMenu() {
|
||||
cmode = sm::SIDE | sm::MAYDARK | sm::DIALOG_STRICT_X;
|
||||
gamescreen(0);
|
||||
|
||||
if(tstate == tsAdjusting)
|
||||
drawRawTexture();
|
||||
|
||||
dialog::init(XLAT("texture mode"));
|
||||
|
||||
dialog::addSelItem(XLAT("select the texture's pattern"), XLAT("..."), 'r');
|
||||
dialog::addSelItem(XLAT("texture file"), texturename, 'f');
|
||||
dialog::addBoolItem(XLAT("texture mode enabled"), texture_on, 'm');
|
||||
dialog::addSelItem(XLAT("texture mode enabled"), its(tstate), 't');
|
||||
|
||||
if(tstate == tsAdjusting) {
|
||||
dialog::addBoolItem(XLAT("move the model"), panstate == tpsModel, 'm');
|
||||
dialog::addBoolItem(XLAT("move the texture"), panstate == tpsMove, 'a');
|
||||
dialog::addBoolItem(XLAT("zoom/scale the texture"), panstate == tpsScale, 'x');
|
||||
dialog::addBoolItem(XLAT("zoom/scale the model"), panstate == tpsZoom, 'z');
|
||||
dialog::addBoolItem(XLAT("projection"), panstate == tpsProjection, 'p');
|
||||
dialog::addBoolItem(XLAT("affine transformations"), panstate == tpsAffine, 'y');
|
||||
}
|
||||
|
||||
if(texture_on) {
|
||||
dialog::addSelItem(XLAT("texture scale"), fts(iscale), 's');
|
||||
dialog::addSelItem(XLAT("texture rotation"), fts(irotate), 'p');
|
||||
if(tstate == tsActive) {
|
||||
/* dialog::addSelItem(XLAT("texture scale"), fts(iscale), 's');
|
||||
dialog::addSelItem(XLAT("texture angle"), fts(irotate), 'a');
|
||||
dialog::addSelItem(XLAT("texture position X"), fts(ix), 'x');
|
||||
dialog::addSelItem(XLAT("texture position Y"), fts(iy), 'y'); */
|
||||
dialog::addSelItem(XLAT("grid alpha"), its(grid_alpha), 'g');
|
||||
dialog::addSelItem(XLAT("mesh alpha"), its(mesh_alpha), 'm');
|
||||
dialog::addSelItem(XLAT("precision"), its(gsplits), 'p');
|
||||
dialog::addSelItem(XLAT("color alpha"), its(color_alpha), 'c');
|
||||
}
|
||||
|
||||
dialog::addItem(XLAT("help"), SDLK_F1);
|
||||
dialog::addItem(XLAT("back"), '0');
|
||||
|
||||
getcstat = '-';
|
||||
|
||||
dialog::display();
|
||||
|
||||
if(holdmouse) {
|
||||
static hyperpoint lastmouse;
|
||||
|
||||
hyperpoint mouseeu = hpxyz((mousex - vid.xcenter + .0) / vid.scrsize, (mousey - vid.ycenter + .0) / vid.scrsize, 1);
|
||||
bool nonzero = mouseeu[0] || mouseeu[1];
|
||||
|
||||
switch(panstate) {
|
||||
case tpsModel:
|
||||
if(!newmove && mouseh[2] < 50 && lastmouse[2] < 50) {
|
||||
panning(lastmouse, mouseh);
|
||||
perform_mapping();
|
||||
}
|
||||
lastmouse = mouseh; newmove = false;
|
||||
break;
|
||||
|
||||
case tpsMove: {
|
||||
if(!newmove)
|
||||
itt = itt * inverse(eupush(mouseeu)) * eupush(lastmouse);
|
||||
lastmouse = mouseeu; newmove = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case tpsScale: {
|
||||
if(nonzero && !newmove)
|
||||
itt = itt * inverse(euscalezoom(mouseeu)) * euscalezoom(lastmouse);
|
||||
if(nonzero) lastmouse = mouseeu;
|
||||
newmove = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case tpsAffine: {
|
||||
if(!newmove)
|
||||
itt = itt * inverse(euaffine(mouseeu)) * euaffine(lastmouse);
|
||||
lastmouse = mouseeu; newmove = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case tpsZoom: {
|
||||
// do not zoom in portrait!
|
||||
if(nonzero && !newmove) {
|
||||
View = View * inverse(spintox(mouseeu)) * spintox(lastmouse);
|
||||
vid.scale = vid.scale * sqrt(intvalxy(C0, mouseeu)) / sqrt(intvalxy(C0, lastmouse));
|
||||
}
|
||||
if(nonzero) lastmouse = mouseeu;
|
||||
newmove = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case tpsProjection: {
|
||||
if(nonzero && !newmove) {
|
||||
vid.alpha = vid.alpha * sqrt(intvalxy(C0, mouseeu)) / sqrt(intvalxy(C0, lastmouse));
|
||||
}
|
||||
if(nonzero) lastmouse = mouseeu;
|
||||
newmove = false;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
// handlePanning(sym, uni);
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if(uni == 'r')
|
||||
|
||||
if(uni == '-' && tstate == tsAdjusting) {
|
||||
if(!holdmouse) {
|
||||
holdmouse = true;
|
||||
newmove = true;
|
||||
}
|
||||
}
|
||||
|
||||
else if(uni == 'm' && tstate == tsAdjusting) panstate = tpsModel;
|
||||
else if(uni == 'a' && tstate == tsAdjusting) panstate = tpsMove;
|
||||
else if(uni == 'x' && tstate == tsAdjusting) panstate = tpsScale;
|
||||
else if(uni == 'y' && tstate == tsAdjusting) panstate = tpsAffine;
|
||||
else if(uni == 'z' && tstate == tsAdjusting) panstate = tpsZoom;
|
||||
else if(uni == 'p' && tstate == tsAdjusting) panstate = tpsProjection;
|
||||
|
||||
else if(uni == 'r')
|
||||
pushScreen(patterns::showPattern);
|
||||
else if(uni == 'f')
|
||||
dialog::openFileDialog(texturename, XLAT("texture to load:"), ".png");
|
||||
else if(uni == 'm') {
|
||||
texture_on = !texture_on;
|
||||
if(texture_on) perform_mapping();
|
||||
else texture_map.clear();
|
||||
else if(uni == 't') {
|
||||
if(tstate == tsOff) {
|
||||
tstate = tsAdjusting;
|
||||
perform_mapping();
|
||||
}
|
||||
else if(tstate == tsAdjusting) {
|
||||
tstate = tsActive;
|
||||
perform_mapping();
|
||||
}
|
||||
else {
|
||||
tstate = tsOff;
|
||||
texture_map.clear();
|
||||
}
|
||||
}
|
||||
else if(uni == 's') {
|
||||
dialog::editNumber(iscale, 0, 2, .01, 1, XLAT("texture scale"),
|
||||
XLAT("Texture scale."));
|
||||
dialog::reaction = perform_mapping;
|
||||
else if(uni == 'g') {
|
||||
dialog::editNumber(grid_alpha, 0, 255, 15, 0, XLAT("grid alpha"),
|
||||
XLAT("Grid alpha."));
|
||||
}
|
||||
else if(uni == 'm') {
|
||||
dialog::editNumber(mesh_alpha, 0, 255, 15, 0, XLAT("mesh alpha"),
|
||||
XLAT("Mesh alpha."));
|
||||
}
|
||||
else if(uni == 'c') {
|
||||
dialog::editNumber(color_alpha, 0, 255, 15, 0, XLAT("color alpha"),
|
||||
XLAT("The higher the value, the less important the color of underlying terrain is."));
|
||||
}
|
||||
else if(uni == 'p') {
|
||||
dialog::editNumber(irotate, -360, 360, 15, 0, XLAT("texture rotation"),
|
||||
XLAT("Texture rotation."));
|
||||
dialog::editNumber(gsplits, 0, 4, 1, 1, XLAT("precision"),
|
||||
XLAT("precision"));
|
||||
dialog::reaction = perform_mapping;
|
||||
}
|
||||
else if(doexiton(sym, uni))
|
||||
@ -267,3 +497,7 @@ void showTextureMenu() {
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
// - dual grid
|
||||
// todo save/load texture configuration
|
||||
// todo texture editor
|
||||
|
Loading…
Reference in New Issue
Block a user