1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-06-26 07:02:49 +00:00

when loading textures in the texture mode, you can now tune individual triangles

This commit is contained in:
Zeno Rogue 2018-02-13 23:25:44 +01:00
parent 271b916174
commit c8d655184b
3 changed files with 188 additions and 26 deletions

View File

@ -2027,10 +2027,16 @@ typedef array<GLfloat, 3> glvec3;
typedef array<GLfloat, 4> glvec4; typedef array<GLfloat, 4> glvec4;
typedef glvec3 glvertex; typedef glvec3 glvertex;
struct texture_triangle {
array<hyperpoint, 3> v;
array<hyperpoint, 3> tv;
texture_triangle(array<hyperpoint, 3> _v, array<hyperpoint, 3> _tv) : v(_v), tv(_tv) {}
};
struct textureinfo { struct textureinfo {
transmatrix M; transmatrix M;
int texture_id; int texture_id;
vector<array<hyperpoint, 3>> triangles; vector<texture_triangle> triangles;
vector<glvertex> vertices; vector<glvertex> vertices;
vector<glvertex> tvertices; vector<glvertex> tvertices;
cell *c; cell *c;

View File

@ -40,10 +40,10 @@ namespace mapeditor {
} }
vid.scale *= z; vid.scale *= z;
printf("scale = " LDF "\n", vid.scale); // printf("scale = " LDF "\n", vid.scale);
#if CAP_TEXTURE #if CAP_TEXTURE
texture::itt = xyscale(texture::itt, 1/z); texture::itt = xyscale(texture::itt, 1/z);
display(texture::itt); // display(texture::itt);
if(texture::tstate) { if(texture::tstate) {
calcparam(); calcparam();
texture::perform_mapping(); texture::perform_mapping();

View File

@ -236,28 +236,29 @@ transmatrix itt = Id;
unsigned grid_color = 0; unsigned grid_color = 0;
unsigned mesh_color = 0; unsigned mesh_color = 0;
unsigned master_color = 0xFFFFFF10; unsigned master_color = 0xFFFFFF30;
unsigned slave_color = 0xFF000008; unsigned slave_color = 0xFF000008;
int color_alpha = 128; int color_alpha = 128;
int gsplits = 1; int gsplits = 1;
void mapTextureTriangle(textureinfo &mi, array<hyperpoint, 3> v, int splits = gsplits) { void mapTextureTriangle(textureinfo &mi, const array<hyperpoint, 3>& v, const array<hyperpoint, 3>& tv, int splits = gsplits) {
if(splits) { if(splits) {
array<hyperpoint, 3> v2 = make_array( mid(v[1], v[2]), mid(v[2], v[0]), mid(v[0], v[1]) ); array<hyperpoint, 3> v2 = make_array( mid(v[1], v[2]), mid(v[2], v[0]), mid(v[0], v[1]) );
mapTextureTriangle(mi, make_array(v[0], v2[2], v2[1]), splits-1); array<hyperpoint, 3> tv2 = make_array( mid(tv[1], tv[2]), mid(tv[2], tv[0]), mid(tv[0], tv[1]) );
mapTextureTriangle(mi, make_array(v[1], v2[0], v2[2]), splits-1); mapTextureTriangle(mi, make_array(v[0], v2[2], v2[1]), make_array(tv[0], tv2[2], tv2[1]), splits-1);
mapTextureTriangle(mi, make_array(v[2], v2[1], v2[0]), splits-1); mapTextureTriangle(mi, make_array(v[1], v2[0], v2[2]), make_array(tv[1], tv2[0], tv2[2]), splits-1);
mapTextureTriangle(mi, make_array(v2[0], v2[1], v2[2]), splits-1); mapTextureTriangle(mi, make_array(v[2], v2[1], v2[0]), make_array(tv[2], tv2[1], tv2[0]), splits-1);
mapTextureTriangle(mi, make_array(v2[0], v2[1], v2[2]), make_array(tv2[0], tv2[1], tv2[2]), splits-1);
return; return;
} }
for(int i=0; i<3; i++) { for(int i=0; i<3; i++) {
mi.vertices.push_back(glhr::pointtogl(v[i])); mi.vertices.push_back(glhr::pointtogl(v[i]));
hyperpoint inmodel; hyperpoint inmodel;
applymodel(mi.M * v[i], inmodel); applymodel(tv[i], inmodel);
inmodel = itt * inmodel; inmodel = itt * inmodel;
inmodel[0] *= vid.radius * 1. / vid.scrsize; inmodel[0] *= vid.radius * 1. / vid.scrsize;
inmodel[1] *= vid.radius * 1. / vid.scrsize; inmodel[1] *= vid.radius * 1. / vid.scrsize;
@ -265,10 +266,37 @@ void mapTextureTriangle(textureinfo &mi, array<hyperpoint, 3> v, int splits = gs
} }
} }
texture_triangle *edited_triangle;
textureinfo *edited_tinfo;
vector<hyperpoint*> tuned_vertices;
map<int, textureinfo> texture_map, texture_map_orig; map<int, textureinfo> texture_map, texture_map_orig;
set<cell*> models; set<cell*> models;
array<hyperpoint, 3> findTextureTriangle(cell *c, patterns::patterninfo& si, int i) {
// auto si = getpatterninfo0(c);
transmatrix M = shmup::ggmatrix(c) * applyPatterndir(c, si);
ld z = ctof(c) ? rhexf : hexvdist;
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;
return make_array(M * C0, M * h1, M * h2);
}
// using: mouseh, mouseouver
int getTriangleID(cell *c, patterns::patterninfo& si, hyperpoint h) {
// auto si = getpatterninfo0(c);
ld quality = 1e10;
int best = 0;
for(int i=0; i<c->type; i++) {
auto t = findTextureTriangle(c, si, i);
ld q = intval(t[1], h) + intval(t[2], h);
if(q < quality) quality = q, best = i;
}
return best;
}
void mapTexture(cell *c, textureinfo& mi, patterns::patterninfo &si, const transmatrix& T, int shift = 0) { void mapTexture(cell *c, textureinfo& mi, patterns::patterninfo &si, const transmatrix& T, int shift = 0) {
mi.c = c; mi.c = c;
mi.symmetries = si.symmetries; mi.symmetries = si.symmetries;
@ -283,7 +311,7 @@ void mapTexture(cell *c, textureinfo& mi, patterns::patterninfo &si, const trans
int i2 = i+shift; int i2 = i+shift;
hyperpoint h1 = spin(M_PI + M_PI * (2*i2 -1) / c->type) * xpush(z) * C0; hyperpoint h1 = spin(M_PI + M_PI * (2*i2 -1) / c->type) * xpush(z) * C0;
hyperpoint h2 = spin(M_PI + M_PI * (2*i2 +1) / c->type) * xpush(z) * C0; hyperpoint h2 = spin(M_PI + M_PI * (2*i2 +1) / c->type) * xpush(z) * C0;
mi.triangles.push_back(make_array(C0, h1, h2)); mi.triangles.emplace_back(make_array(C0, h1, h2), make_array(mi.M*C0, mi.M*h1, mi.M*h2));
} }
} }
@ -291,7 +319,7 @@ void mapTexture2(textureinfo& mi) {
mi.vertices.clear(); mi.vertices.clear();
mi.tvertices.clear(); mi.tvertices.clear();
for(auto& t: mi.triangles) for(auto& t: mi.triangles)
mapTextureTriangle(mi, t); mapTextureTriangle(mi, t.v, t.tv);
} }
int recolor(int col) { int recolor(int col) {
@ -376,7 +404,7 @@ void mark_triangles() {
for(auto& t: mi.second.triangles) { for(auto& t: mi.second.triangles) {
vector<hyperpoint> t2; vector<hyperpoint> t2;
for(int i=0; i<3; i++) for(int i=0; i<3; i++)
t2.push_back(mi.second.M * t[i]); t2.push_back(t.tv[i]);
prettypoly(t2, master_color, master_color, gsplits); prettypoly(t2, master_color, master_color, gsplits);
} }
} }
@ -388,11 +416,25 @@ static const auto current_texture_parameters = tie(geometry, nonbitrunc, pattern
texture_parameters orig_texture_parameters; texture_parameters orig_texture_parameters;
bool texture_tuned = false;
string texture_tuner;
void clear_texture_map() {
texture_map.clear();
edited_triangle = nullptr;
edited_tinfo = nullptr;
tuned_vertices.clear();
models.clear();
texture_tuned = false;
texture_tuner = "";
}
void perform_mapping() { void perform_mapping() {
if(gsplits < 0) gsplits = 0; if(gsplits < 0) gsplits = 0;
if(gsplits > 4) gsplits = 4; if(gsplits > 4) gsplits = 4;
using namespace patterns; using namespace patterns;
texture_map.clear();
clear_texture_map();
for(auto& p: gmatrix) { for(auto& p: gmatrix) {
cell *c = p.first; cell *c = p.first;
@ -413,11 +455,6 @@ void perform_mapping() {
} }
} }
if(tstate == tsActive)
for(auto& mi: texture_map)
mapTexture2(mi.second);
models.clear();
for(auto& t: texture_map) models.insert(t.second.c); for(auto& t: texture_map) models.insert(t.second.c);
for(auto& p: gmatrix) { for(auto& p: gmatrix) {
@ -436,7 +473,13 @@ void perform_mapping() {
texture::cgroup = patterns::cgroup; texture::cgroup = patterns::cgroup;
texture_map_orig = texture_map; texture_map_orig = texture_map;
orig_texture_parameters = current_texture_parameters; orig_texture_parameters = current_texture_parameters;
printf("texture_map has %d elements (S%d)\n", size(texture_map), tstate); // printf("texture_map has %d elements (S%d)\n", size(texture_map), tstate);
}
void finish_mapping() {
if(tstate == tsActive)
for(auto& mi: texture_map)
mapTexture2(mi.second);
} }
void saveFullTexture() { void saveFullTexture() {
@ -454,6 +497,7 @@ void saveFullTexture() {
itt = xyscale(Id, vid.scrsize * 1. / vid.radius); itt = xyscale(Id, vid.scrsize * 1. / vid.radius);
readtexture(); readtexture();
perform_mapping(); perform_mapping();
finish_mapping();
} }
bool newmove = false; bool newmove = false;
@ -611,7 +655,7 @@ void applyMagic() {
} }
} }
enum eTexturePanstate {tpsModel, tpsMove, tpsScale, tpsAffine, tpsZoom, tpsProjection}; enum eTexturePanstate {tpsModel, tpsMove, tpsScale, tpsAffine, tpsZoom, tpsProjection, tpsCell, tpsTriangle, tpsTune};
eTexturePanstate panstate; eTexturePanstate panstate;
void mousemovement() { void mousemovement() {
@ -670,6 +714,64 @@ void mousemovement() {
newmove = false; newmove = false;
} }
case tpsCell: {
cell *c = mouseover;
if(!c) break;
auto si = patterns::getpatterninfo0(c);
if(newmove) {
edited_tinfo = NULL;
if(texture_map.count(si.id)) {
edited_tinfo = &texture_map[si.id];
newmove = false;
}
}
if(edited_tinfo && size(edited_tinfo->triangles) == c->type) {
for(int i=0; i<c->type; i++)
edited_tinfo->triangles[i].tv = findTextureTriangle(c, si, i);
texture_tuned = true;
}
}
case tpsTriangle: {
cell *c = mouseover;
if(!c) break;
auto si = patterns::getpatterninfo0(c);
int i = getTriangleID(c, si, mouseh);
if(newmove) {
edited_triangle = NULL;
if(texture_map.count(si.id)) {
edited_triangle = &texture_map[si.id].triangles[i];
newmove = false;
}
}
if(edited_triangle) {
edited_triangle->tv = findTextureTriangle(c, si, i);
texture_tuned = true;
}
}
case tpsTune: {
ld tdist = 1e20;
if(newmove) {
tuned_vertices.clear();
for(auto& a: texture_map)
for(auto& t: a.second.triangles)
for(auto& v: t.tv)
if(intval(v, mouseh) < tdist)
tdist = intval(v, mouseh);
for(auto& a: texture_map)
for(auto& t: a.second.triangles)
for(auto& v: t.tv)
if(intval(v, mouseh) < tdist * (1.000001))
tuned_vertices.push_back(&v);
newmove = false;
}
for(auto v: tuned_vertices) {
*v = mouseh;
texture_tuned = true;
}
}
default: break; default: break;
} }
} }
@ -720,6 +822,7 @@ void init_textureconfig() {
addsaver(vid.scale, "scale", 1); addsaver(vid.scale, "scale", 1);
addsaver(texturename, "texture filename", ""); addsaver(texturename, "texture filename", "");
addsaver(texture_tuner, "texture tuning", "");
swap(texturesavers, savers); swap(texturesavers, savers);
} }
@ -729,6 +832,17 @@ bool save_textureconfig() {
FILE *f = fopen(configname.c_str(), "wt"); FILE *f = fopen(configname.c_str(), "wt");
if(!f) return false; if(!f) return false;
if(texture_tuned) {
texture_tuner = "";
for(auto& a: texture_map)
for(auto& t: a.second.triangles)
for(auto& v: t.tv)
for(int i=0; i<3; i++) {
texture_tuner += ftssmart(v[i]);
texture_tuner += ';';
}
}
targetgeometry = geometry; targetgeometry = geometry;
target_nonbitru = nonbitrunc; target_nonbitru = nonbitrunc;
@ -786,7 +900,37 @@ bool load_textureconfig() {
calcparam(); calcparam();
drawthemap(); drawthemap();
tstate = tstate_max = tsActive; tstate = tstate_max = tsActive;
string s = move(texture_tuner);
perform_mapping(); perform_mapping();
texture_tuner = move(s);
if(texture_tuner != "") {
texture_tuned = true;
vector<ld*> coords;
for(auto& a: texture_map)
for(auto& t: a.second.triangles)
for(auto& v: t.tv)
for(int i=0; i<3; i++)
coords.push_back(&v[i]);
int semicounter = 0;
for(char c: texture_tuner) if(c == ';') semicounter++;
if(semicounter != size(coords))
addMessage("Tuning error: wrong number");
else {
string cur = "";
int index = 0;
for(char c: texture_tuner)
if(c == ';') {
*(coords[index++]) = atof(cur.c_str());
cur = "";
}
else cur += c;
printf("index = %d semi = %d sc = %d\n", index, semicounter, size(coords));
}
}
finish_mapping();
return true; return true;
} }
@ -911,9 +1055,17 @@ void showMenu() {
dialog::addBoolItem(XLAT("affine transformations"), panstate == tpsAffine, 'y'); dialog::addBoolItem(XLAT("affine transformations"), panstate == tpsAffine, 'y');
dialog::addBoolItem(XLAT("magic"), false, 'A'); dialog::addBoolItem(XLAT("magic"), false, 'A');
dialog::addBreak(50);
dialog::addBoolItem(XLAT("select master cells"), panstate == tpsCell, 'C');
dialog::addBoolItem(XLAT("select master triangles"), panstate == tpsTriangle, 'T');
dialog::addBoolItem(XLAT("fine tune vertices"), panstate == tpsTune, 'F');
dialog::addColorItem(XLAT("grid color (master)"), master_color, 'M'); dialog::addColorItem(XLAT("grid color (master)"), master_color, 'M');
dialog::addColorItem(XLAT("grid color (copy)"), slave_color, 'C'); dialog::addColorItem(XLAT("grid color (copy)"), slave_color, 'C');
dialog::addBreak(50);
dialog::addSelItem(XLAT("precision"), its(gsplits), 'P'); dialog::addSelItem(XLAT("precision"), its(gsplits), 'P');
dialog::addItem(XLAT("save the raw texture"), 'S'); dialog::addItem(XLAT("save the raw texture"), 'S');
} }
@ -962,6 +1114,9 @@ void showMenu() {
else if(uni == 'y' && tstate == tsAdjusting) panstate = tpsAffine; else if(uni == 'y' && tstate == tsAdjusting) panstate = tpsAffine;
else if(uni == 'z' && tstate == tsAdjusting) panstate = tpsZoom; else if(uni == 'z' && tstate == tsAdjusting) panstate = tpsZoom;
else if(uni == 'p' && tstate == tsAdjusting) panstate = tpsProjection; else if(uni == 'p' && tstate == tsAdjusting) panstate = tpsProjection;
else if(uni == 'C' && tstate == tsAdjusting) panstate = tpsCell;
else if(uni == 'T' && tstate == tsAdjusting) panstate = tpsTriangle;
else if(uni == 'F' && tstate == tsAdjusting) panstate = tpsTune;
else if(uni == 'A' && tstate == tsAdjusting) else if(uni == 'A' && tstate == tsAdjusting)
pushScreen(showMagicMenu); pushScreen(showMagicMenu);
@ -987,6 +1142,7 @@ void showMenu() {
if(tstate_max == tsOff) tstate_max = tsAdjusting; if(tstate_max == tsOff) tstate_max = tsAdjusting;
tstate = tstate_max; tstate = tstate_max;
perform_mapping(); perform_mapping();
finish_mapping();
return true; return true;
} }
else return false; else return false;
@ -1008,6 +1164,7 @@ void showMenu() {
if(whitetexture() && loadTextureGL()) { if(whitetexture() && loadTextureGL()) {
tstate = tstate_max = tsActive; tstate = tstate_max = tsActive;
perform_mapping(); perform_mapping();
finish_mapping();
mapeditor::initdraw(cwt.c); mapeditor::initdraw(cwt.c);
pushScreen(mapeditor::showDrawEditor); pushScreen(mapeditor::showDrawEditor);
} }
@ -1018,7 +1175,7 @@ void showMenu() {
else if(uni == 't' && tstate == tsAdjusting) { else if(uni == 't' && tstate == tsAdjusting) {
tstate = tstate_max = tsActive; tstate = tstate_max = tsActive;
perform_mapping(); finish_mapping();
} }
else if(uni == 't' && tstate == tsActive) else if(uni == 't' && tstate == tsActive)
@ -1047,9 +1204,7 @@ void showMenu() {
else if(uni == 'P') { else if(uni == 'P') {
dialog::editNumber(gsplits, 0, 4, 1, 1, XLAT("precision"), dialog::editNumber(gsplits, 0, 4, 1, 1, XLAT("precision"),
XLAT("precision")); XLAT("precision"));
if(tstate == tsActive) dialog::reaction = [] () { if(tstate == tsActive) dialog::reaction = [] () { finish_mapping();
for(auto& mi: texture_map)
mapTexture2(mi.second);
}; };
} }
else if(uni == 'S' && tstate == tsAdjusting) else if(uni == 'S' && tstate == tsAdjusting)
@ -1242,7 +1397,7 @@ void drawLine(hyperpoint h1, hyperpoint h2, int col, int steps) {
} }
void remap(eTextureState old_tstate, eTextureState old_tstate_max) { void remap(eTextureState old_tstate, eTextureState old_tstate_max) {
texture_map.clear(); clear_texture_map();
if(old_tstate == tsActive && patterns::compatible(texture::cgroup, patterns::cgroup)) { if(old_tstate == tsActive && patterns::compatible(texture::cgroup, patterns::cgroup)) {
tstate = old_tstate; tstate = old_tstate;
@ -1290,6 +1445,7 @@ void remap(eTextureState old_tstate, eTextureState old_tstate_max) {
calcparam(); calcparam();
drawthemap(); drawthemap();
perform_mapping(); perform_mapping();
finish_mapping();
printf("texture_map size = %d\n", size(texture_map)); printf("texture_map size = %d\n", size(texture_map));
} }
} }