1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-01-11 09:50:34 +00:00

texture mode -- first commit

This commit is contained in:
Zeno Rogue 2017-12-09 02:20:10 +01:00
parent 87b6b8b372
commit ecf631976f
8 changed files with 357 additions and 34 deletions

View File

@ -71,6 +71,7 @@ bool inv::on;
#include "control.cpp"
#include "hud.cpp"
#include "hypgraph.cpp"
#include "textures.cpp"
#include "graph.cpp"
#include "sound.cpp"
#include "achievement.cpp"

View File

@ -2896,28 +2896,6 @@ void plainfloor(cell *c, bool warp, const transmatrix &V, int col, int prio) {
}
}
void fullplainfloor(cell *c, bool warp, const transmatrix &V, int col, int prio) {
if(warp) {
if(euclid) {
if(ishex1(c))
queuepolyat(V * pispin, shTriheptaFloor[0], col, prio);
else
queuepolyat(V, shTriheptaFloor[ctof(c)], col, prio);
}
else
queuepolyat(V * applyPatterndir(c), shTriheptaFloor[sphere ? ctof(c) : mapeditor::nopattern(c)], col, prio);
}
else if(c->land == laDual && !nontruncated) {
if(euclid && ishex1(c))
queuepolyat(V * pispin, shBigTriangle, col, prio);
else
queuepolyat(V, shBigTriangle, col, prio);
}
else {
queuepolyat(V, shFullFloor[ctof(c)], col, prio);
}
}
void qfloor_eswap(cell *c, const transmatrix& V, const hpcshape& sh, int col);
void qplainfloor(cell *c, bool warp, const transmatrix &V, int col) {
@ -2942,7 +2920,11 @@ int wavephase;
void warpfloor(cell *c, const transmatrix& V, int col, int prio, bool warp) {
if(shmup::on || nontruncated) warp = false;
if(wmescher && qfi.special)
if(qfi.tinf) {
queuetable(V*qfi.spin, &qfi.tinf->vertices[0], size(qfi.tinf->vertices) / 3, 0, col, prio);
lastptd().u.poly.tinf = qfi.tinf;
}
else if(wmescher && qfi.special)
queuepolyat(V*qfi.spin, *qfi.shape, col, prio);
else plainfloor(c, warp, V, col, prio);
}
@ -3013,7 +2995,7 @@ void placeSidewall(cell *c, int i, int sidepar, const transmatrix& V, bool warp,
// prio += c->cpdist - c->mov[i]->cpdist;
queuepolyat(V2,
(mirr?shMFloorSide:warp?shTriheptaSide:(c->land == laDual&&!nontruncated)?shBigTriSide:shFloorSide)[sidepar][ctof(c)], col, prio);
(qfi.tinf?shFullFloorSide:mirr?shMFloorSide:warp?shTriheptaSide:(c->land == laDual&&!nontruncated)?shBigTriSide:shFloorSide)[sidepar][ctof(c)], col, prio);
}
bool openorsafe(cell *c) {
@ -3143,7 +3125,7 @@ void qfloor_eswap(cell *c, const transmatrix& V, const hpcshape& sh, int col) {
else
qfloor(c, V, sh, col);
};
// how much to darken
int getfd(cell *c) {
switch(c->land) {
@ -3515,7 +3497,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
}
poly_outline = OUTLINE_DEFAULT;
if(!wmascii) {
// floor
@ -3558,6 +3540,8 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
shBigTriangle, darkena(fcol, fd, 0xFF));
}
#endif
else if(applyTextureMap(c, Vf, darkena(fcol, fd, 0xFF))) ;
else if(c->land == laMirrorWall) {
int d = mirror::mirrordir(c);

13
hyper.h
View File

@ -1902,6 +1902,13 @@ void drawqueue();
typedef float GLfloat;
#endif
struct textureinfo {
transmatrix M;
int texture_id;
vector<GLfloat> vertices;
vector<GLfloat> tvertices;
};
struct qpoly {
transmatrix V;
GLfloat *tab;
@ -1910,6 +1917,7 @@ struct qpoly {
int outline;
double minwidth;
int flags;
textureinfo *tinf;
};
struct qline {
@ -1930,7 +1938,7 @@ struct qcir {
int x, y, size;
};
enum eKind { pkPoly, pkLine, pkString, pkCircle, pkShape, pkResetModel };
enum eKind { pkPoly, pkLine, pkString, pkCircle, pkShape, pkResetModel, pkSpecial };
struct polytodraw {
eKind kind;
@ -2300,3 +2308,6 @@ int inpair(cell *c, int colorpair);
int snake_pair(cell *c);
extern const unsigned int nestcolors[8];
extern bool texture_on;
void showTextureMenu();

View File

@ -120,6 +120,10 @@
#define CAP_EDIT (CAP_FILES && !ISWEB && !ISMINI)
#endif
#ifndef CAP_TEXTURE
#define CAP_TEXTURE CAP_PNG
#endif
#ifndef CAP_MODEL
#define CAP_MODEL (!ISMOBWEB && !ISMINI && CAP_SDLGFX)
#endif

View File

@ -345,6 +345,11 @@ void showDisplayMode() {
dialog::addBoolItem(XLAT("vector graphics editor"), (false), 'g');
#endif
#if CAP_TEXTURE
dialog::addBoolItem(XLAT("texture mode"), texture_on, 't');
#endif
// display modes
#if CAP_RUG
dialog::addBoolItem(XLAT("hypersian rug mode"), (rug::rugged), 'u');
@ -367,6 +372,8 @@ void showDisplayMode() {
if(xuni == 'z') editScale();
if(xuni == 't') pushScreen(showTextureMenu);
if(xuni == 'm') { vid.monmode += 60 + (shiftmul > 0 ? 1 : -1); vid.monmode %= 6; }
if(xuni == '9') pushScreen(show3D);

View File

@ -677,7 +677,7 @@ int pattern_threecolor(cell *c) {
if(S7 == 3 && nontruncated)
return c->master->fiftyval;
if(euclid) return eupattern(c);
return ishept(c);
return !ishept(c);
}
// returns ishept in the normal tiling;

View File

@ -43,7 +43,6 @@ struct hpcshape {
int flags;
};
hpcshape *last = NULL;
vector<polytodraw> ptds;
@ -288,7 +287,15 @@ void glapplymatrix(const transmatrix& V) {
glMultMatrixf(mat);
}
void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline, int flags) {
void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline, int flags, textureinfo *tinf) {
if(tinf) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tinf->texture_id);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, &tinf->tvertices[0]);
}
for(int ed = vid.goteyes ? -1 : 0; ed<2; ed+=2) {
if(ed) selectEyeGL(ed);
bool draw = col;
@ -371,6 +378,12 @@ void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline
if(useV) glPopMatrix();
}
if(tinf) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
}
#endif
@ -491,8 +504,8 @@ void drawpolyline(polytodraw& p) {
if(currentvertices != pp.tab)
activateVertexArray(pp.tab, pq);
const int ps=0;
glLineWidth(linewidthat(tC0(pp.V), pp.minwidth));
gldraw(1, pp.V, ps, pq, p.col, pp.outline, 0);
glLineWidth(linewidthat(tC0(pp.V), pp.minwidth));
gldraw(1, pp.V, ps, pq, p.col, pp.outline, 0, pp.tinf);
return;
}
#endif
@ -570,7 +583,7 @@ void drawpolyline(polytodraw& p) {
if(vid.usingGL) {
// if(pmodel == 0) for(int i=0; i<qglcoords; i++) glcoords[i][2] = vid.scrdist;
activateGlcoords();
gldraw(3, Id, 0, qglcoords, p.col, pp.outline, poly_flags);
gldraw(3, Id, 0, qglcoords, p.col, pp.outline, poly_flags, pp.tinf);
continue;
}
#endif
@ -655,6 +668,7 @@ void prettyline(hyperpoint h1, hyperpoint h2, int col, int lev) {
p.col = 0;
pp.outline = col;
pp.flags = POLY_ISSIDE;
pp.tinf = NULL;
drawpolyline(p);
}
@ -662,6 +676,8 @@ vector<GLfloat> curvedata;
int curvestart = 0;
bool keep_curvedata = false;
hookset<void(polytodraw&)> *hooks_specialdraw;
void drawqueueitem(polytodraw& ptd) {
#if CAP_ROGUEVIZ
svg::info = ptd.info;
@ -669,6 +685,10 @@ void drawqueueitem(polytodraw& ptd) {
// if(ptd.prio == 46) printf("eye size %d\n", polyi);
if(ptd.kind == pkSpecial) {
callhooks(hooks_specialdraw, ptd);
}
if(ptd.kind == pkResetModel) {
pmodel = eModel(ptd.col);
return;
@ -748,7 +768,10 @@ ld xintval(const hyperpoint& h) {
ld backbrightness = .25;
purehookset hook_drawqueue;
void drawqueue() {
callhooks(hook_drawqueue);
int siz = size(ptds);
@ -868,7 +891,7 @@ void drawqueue() {
}
hpcshape
shFloorSide[SIDEPARS][2], shSemiFloorSide[SIDEPARS], shTriheptaSide[SIDEPARS][2], shMFloorSide[SIDEPARS][2],
shFloorSide[SIDEPARS][2], shSemiFloorSide[SIDEPARS], shTriheptaSide[SIDEPARS][2], shMFloorSide[SIDEPARS][2], shFullFloorSide[SIDEPARS][2],
shFullFloor[2],
shSeabed[2], shCloudSeabed[3], shCaveSeabed[3],
shWave[8][2],
@ -1296,6 +1319,14 @@ void buildpolys() {
for(int t=0; t<=1; t++) hpcpush(ddi(t*S12-S6, floorrad1) * C0);
chasmifyPoly(dlow, dhi, k);
bshape(shFullFloorSide[k][0], PPR_LAKEWALL);
for(int t=0; t<=1; t++) hpcpush(ddi(t*S14-S7, hexvdist) * C0);
chasmifyPoly(dlow, dhi, k);
bshape(shFullFloorSide[k][1], PPR_LAKEWALL);
for(int t=0; t<=1; t++) hpcpush(ddi(t*S12-S6, rhexf) * C0);
chasmifyPoly(dlow, dhi, k);
bshape(shSemiFloorSide[k], PPR_LAKEWALL);
for(int t=0; t<=3; t+=3) hpcpush(ddi(S7 + (3+t)*S14, floorrad0) * C0);
chasmifyPoly(dlow, dhi, k);
@ -2176,6 +2207,7 @@ void queuepolyat(const transmatrix& V, const hpcshape& h, int col, int prio) {
ptd.u.poly.outline = poly_outline;
ptd.u.poly.minwidth = minwidth_global;
ptd.u.poly.flags = h.flags;
ptd.u.poly.tinf = NULL;
}
void addfloats(vector<GLfloat>& v, hyperpoint h) {
@ -2201,6 +2233,7 @@ void queuetable(const transmatrix& V, GLfloat *f, int cnt, int linecol, int fill
ptd.u.poly.outline = linecol;
ptd.u.poly.minwidth = minwidth_global;
ptd.u.poly.flags = 0;
ptd.u.poly.tinf = NULL;
}
void queuepoly(const transmatrix& V, const hpcshape& h, int col) {
@ -2215,6 +2248,7 @@ struct qfloorinfo {
bool special;
transmatrix spin;
const hpcshape *shape;
textureinfo *tinf;
};
qfloorinfo qfi;
@ -2259,12 +2293,14 @@ void qfloor(cell *c, const transmatrix& V, const hpcshape& h, int col) {
qfloor0(c, V, h, col);
qfi.special = isSpecial(h);
qfi.shape = &h, qfi.spin = Id;
qfi.tinf = NULL;
}
void qfloor(cell *c, const transmatrix& V, const transmatrix& Vspin, const hpcshape& h, int col) {
qfloor0(c, V*Vspin, h, col);
qfi.special = isSpecial(h);
qfi.shape = &h, qfi.spin = Vspin;
qfi.tinf = NULL;
}
void curvepoint(const hyperpoint& H1) {

280
textures.cpp Normal file
View File

@ -0,0 +1,280 @@
#include <SDL/SDL_image.h>
glfont_t textures;
SDL_Surface *convertSurface(SDL_Surface* s) {
SDL_PixelFormat fmt;
// fmt.format = SDL_PIXELFORMAT_BGRA8888;
fmt.BitsPerPixel = 32;
fmt.BytesPerPixel = 4;
fmt.Ashift=24;
fmt.Rshift=16;
fmt.Gshift=8;
fmt.Bshift=0;
fmt.Amask=0xff<<24;
fmt.Rmask=0xff<<16;
fmt.Gmask=0xff<<8;
fmt.Bmask=0xff;
fmt.Aloss = fmt.Rloss = fmt.Gloss = fmt.Bloss = 0;
fmt.palette = NULL;
#ifndef SDL2
fmt.alpha = 0;
fmt.colorkey = 0x1ffffff;
#endif
return SDL_ConvertSurface(s, &fmt, SDL_SWSURFACE);
}
bool texture_read = false;
vector<int> expanded_data;
string texturename;
void sdltogl_bmp(SDL_Surface *txt, glfont_t& f, int ch) {
int dim = min(txt->w, txt->h);
int otwidth = dim;
int otheight = dim;
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);
}
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;
int NUMPICS = 2;
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]);
for(int ch=1; ch<NUMPICS; ch++) {
SDL_Surface *txt = IMG_Load(texturename.c_str());
auto txt2 = convertSurface(txt);
sdltogl_bmp(txt2, f, ch);
SDL_FreeSurface(txt);
SDL_FreeSurface(txt2);
}
//printf("init size=%d ok\n", size);
// GLERR("initfont");
}
ld iscale = 1;
ld irotate = 0;
unsigned int glc = 0xFFFFFFDD;
void mapTextureTriangle(textureinfo &mi, array<hyperpoint, 3> v) {
int tabid = 1;
glfont_t& f(textures);
float fx=f.tx[tabid];
float fy=f.ty[tabid];
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++)
mi.vertices.push_back(v[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);
mi.tvertices.push_back(0);
}
}
map<int, textureinfo> texture_map;
bool applyTextureMap(cell *c, const transmatrix &V, int col) {
using namespace mapeditor;
int t = subpattern(c, whichPattern);
try {
auto& mi = texture_map.at(t);
qfi.spin = Id;
int d = patterndir(c, whichPattern);
qfi.spin = qfi.spin * spin(-M_PI * 2 * d / c->type);
if(reflectPatternAt(c))
qfi.spin = qfi.spin * Mirror;
int n = mi.vertices.size() / 3;
qfi.special = false;
qfi.shape = &shFullFloor[ctof(c)];
qfi.tinf = &mi;
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);
}
else {
queuetable(V * qfi.spin, &mi.vertices[0], n, 0, col, PPR_FLOOR);
}
lastptd().u.poly.tinf = &mi;
return true;
}
catch(out_of_range) {
return false;
}
}
void perform_mapping() {
using namespace mapeditor;
if(!texture_read) readtexture();
texture_map.clear();
glfont_t& f(textures); int tabid = 1;
for(auto p: gmatrix) {
cell *c = p.first;
int t = subpattern(c, whichPattern);
bool replace = false;
if(!texture_map.count(t))
replace = true;
else if(p.second[2][2] < texture_map[t].M[2][2])
replace = true;
if(replace) {
auto& mi = texture_map[t];
mi.M = p.second;
mi.vertices.clear();
mi.tvertices.clear();
int d = patterndir(c, whichPattern);
if(d)
mi.M = mi.M * spin(-M_PI * 2 * d / c->type);
if(reflectPatternAt(c, whichPattern))
mi.M = mi.M * Mirror;
ld z = ctof(c) ? rhexf : hexvdist;
ld base = ctof(c) ? 0 : 0; // -hexshift;
if(!ctof(c)) 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];
}
}
}
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;
}
int forgeArgs() {
using namespace arg;
if(0) ;
else if(argis("-forge")) {
shift(); texturename = args();
}
else return 1;
return 0;
}
auto texture_hook =
addHook(hooks_args, 100, forgeArgs)
+ addHook(hooks_handleKey, 100, forge_handleKey);
bool texture_on = false;
void showTextureMenu() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen(0);
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');
if(texture_on) {
dialog::addSelItem(XLAT("texture scale"), fts(iscale), 's');
dialog::addSelItem(XLAT("texture rotation"), fts(irotate), 'p');
}
dialog::addItem(XLAT("help"), SDLK_F1);
dialog::addItem(XLAT("back"), '0');
dialog::display();
keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
if(uni == 'r')
pushScreen(mapeditor::showPattern);
else if(uni == 'f') {
mapeditor::cfileptr = &texturename;
mapeditor::filecaption = XLAT("texture to load:");
mapeditor::cfileext = ".png";
pushScreen(mapeditor::drawFileDialog);
}
else if(uni == 'm') {
texture_on = !texture_on;
if(texture_on) perform_mapping();
else 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 == 'p') {
dialog::editNumber(irotate, -360, 360, 0, 60, XLAT("texture rotation"),
XLAT("Texture rotation."));
dialog::reaction = perform_mapping;
}
else if(doexiton(sym, uni))
popScreen();
};
}