further work on textures

This commit is contained in:
Zeno Rogue 2017-12-14 02:53:29 +01:00
parent 45cc122927
commit 6c4538df69
6 changed files with 473 additions and 201 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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') {

View File

@ -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;

View File

@ -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