3d:: textured walls

This commit is contained in:
Zeno Rogue 2019-03-11 18:46:34 +01:00
parent f3a166b928
commit 5db2cfbd1a
5 changed files with 267 additions and 97 deletions

View File

@ -715,5 +715,114 @@ auto floor_hook =
else return 1;
});
#endif
#endif
#if MAXMDIM >= 4
renderbuffer *floor_textures;
void draw_shape_for_texture(floorshape* sh, int& id) {
ld gx = (id % 8) * 1.5 - 3.5 * 1.5;
ld gy = (id / 8) * 1.5 - 3.5 * 1.5;
id++;
for(int a=-1; a<=1; a++)
for(int b=-1; b<=1; b++)
queuepoly(eupush(gx+a/2., gy+b/2.), sh->b[0], 0xFFFFFFFF);
if(1) {
dynamicval<ld> v(vid.linewidth, 8);
curvepoint(eupush(gx+.25, gy-.25) * C0);
curvepoint(eupush(gx+.25, gy+.25) * C0);
curvepoint(eupush(gx-.25, gy+.25) * C0);
curvepoint(eupush(gx-.25, gy-.25) * C0);
curvepoint(eupush(gx+.25, gy-.25) * C0);
queuecurve(0x404040C0, 0, PPR::LINE);
}
sh->tinf3.tvertices.clear();
sh->tinf3.texture_id = floor_textures->renderedTexture;
auto at = [&] (hyperpoint h, int a) {
hyperpoint inmodel;
applymodel(h, inmodel);
glvec2 v;
v[0] = (1 + inmodel[0] * vid.scale) / 2;
v[1] = (1 - inmodel[1] * vid.scale) / 2;
sh->tinf3.tvertices.push_back(glhr::makevertex(v[0], v[1], 0));
};
const int STEP = TEXTURE_STEP_3D;
using namespace hyperpoint_vec;
for(int a=0; a<8; a++)
for(int y=0; y<STEP; y++)
for(int x=0; x<STEP; x++) {
hyperpoint center = eupush(gx, gy) * C0;
hyperpoint v1 = hpxyz3(0.25, 0.25, 0, 0) / STEP;
hyperpoint v2 = hpxyz3(0.25, -0.25, 0, 0) / STEP;
if(x+y < STEP) {
at(center + v1 * x + v2 * y, 0);
at(center + v1 * (x+1) + v2 * y, 1);
at(center + v1 * x + v2 * (y+1), 2);
}
if(x+y <= STEP && x && y) {
at(center + v1 * x + v2 * y, 0);
at(center + v1 * (x-1) + v2 * y, 1);
at(center + v1 * x + v2 * (y-1), 2);
}
}
}
const int FLOORTEXTURESIZE = 4096;
void make_floor_textures() {
if(1) {
dynamicval<eGeometry> g(geometry, gEuclidSquare);
dynamicval<eVariation> va(variation, eVariation::pure);
dynamicval<bool> hq(inHighQual, true);
resetGeometry();
dynamicval<videopar> vi(vid, vid);
vid.xres = FLOORTEXTURESIZE;
vid.yres = FLOORTEXTURESIZE;
vid.scale = 0.25;
dynamicval<ld> lw(vid.linewidth, 2);
floor_textures = new renderbuffer(vid.xres, vid.yres, vid.usingGL);
resetbuffer rb;
auto cd = current_display;
cd->xtop = cd->ytop = 0;
cd->xsize = cd->ysize = FLOORTEXTURESIZE;
cd->xcenter = cd->ycenter = cd->scrsize = FLOORTEXTURESIZE/2;
cd->radius = cd->scrsize * vid.scale;
floor_textures->enable();
current_display->set_viewport(0);
current_display->set_projection(0, true);
current_display->set_mask(0);
floor_textures->clear(0xE8E8E8);
ptds.clear();
int id = 0;
poly_outline = 0xF0F0F0FF;
for(auto v: all_plain_floorshapes) draw_shape_for_texture(v, id);
for(auto v: all_escher_floorshapes) draw_shape_for_texture(v, id);
drawqueue();
SDL_Surface *sdark = floor_textures->render();
IMAGESAVE(sdark, "texture-test.png");
rb.reset();
}
need_reset_geometry = true;
}
#endif
}

View File

@ -4798,13 +4798,13 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
for(int a=0; a<c->type; a++)
if(c->move(a) && !isWall3(c->move(a), dummy)) {
if(a < 4 && binarytiling) {
if(celldistAlt(c) >= celldistAlt(viewctr.at->c7)) continue;
queuepoly(V, shWall3D[a], darkena(wcol - d * get_darkval(a), 0, 0xFF));
}
else {
queuepoly(V, shWall3D[a], darkena(wcol - d * get_darkval(a), 0, 0xFF));
if(a < 4 && binarytiling && celldistAlt(c) >= celldistAlt(viewctr.at->c7)) continue;
if(qfi.fshape && wmescher) {
auto& poly = queuepoly(V, shWall3D[a], darkena(wcol - d * get_darkval(a), 0, 0xFF));
poly.tinf = &qfi.fshape->tinf3;
}
else
queuepoly(V, shPlainWall3D[a], darkena(wcol - d * get_darkval(a), 0, 0xFF));
}
}
else {
@ -4812,7 +4812,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
color_t t = transcolor(c, c->move(a));
if(t) {
t = t - get_darkval(a) * ((t & 0xF0F0F000) >> 4);
auto& poly = queuepolyat(V, shWall3D[a], t, PPR::TRANSPARENT);
auto& poly = queuepolyat(V, shPlainWall3D[a], t, PPR::TRANSPARENT);
poly.subprio = celldistance(c, viewctr.at->c7) + celldistance(c->move(a), viewctr.at->c7);
}
}
@ -5341,7 +5341,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
if(binarytiling && !among(t, 5, 6, 8)) continue;
if(!binarytiling && c->move(t) < c) continue;
dynamicval<color_t> g(poly_outline, gridcolor(c, c->move(t)));
queuepoly(V, shWall3D[t], 0);
queuepoly(V, shWireframe3D[t], 0);
}
}
#endif
@ -5527,7 +5527,7 @@ void queuecircleat(cell *c, double rad, color_t col) {
if(DIM == 3) {
dynamicval<color_t> p(poly_outline, col);
for(int i=0; i<c->type; i++) {
queuepolyat(gmatrix[c], shWall3D[i], 0, PPR::SUPERLINE);
queuepolyat(gmatrix[c], shWireframe3D[i], 0, PPR::SUPERLINE);
}
return;
}
@ -6458,6 +6458,8 @@ auto graphcm = addHook(clearmemory, 0, [] () {
});
void resetGeometry() {
if(DIM == 3 && !floor_textures)
make_floor_textures();
precalc();
#if CAP_FIELD
if(hyperbolic && &currfp != &fieldpattern::fp_invalid) currfp.analyze();

16
hyper.h
View File

@ -2825,12 +2825,15 @@ struct texture_triangle {
texture_triangle(array<hyperpoint, 3> _v, array<hyperpoint, 3> _tv) : v(_v), tv(_tv) {}
};
struct textureinfo {
transmatrix M;
struct basic_textureinfo {
int texture_id;
vector<glvertex> tvertices;
};
struct textureinfo : basic_textureinfo {
transmatrix M;
vector<texture_triangle> triangles;
vector<glvertex> vertices;
vector<glvertex> tvertices;
cell *c;
vector<transmatrix> matrices;
@ -2858,7 +2861,7 @@ struct dqi_poly : drawqueueitem {
color_t outline;
double linewidth;
int flags;
textureinfo *tinf;
basic_textureinfo *tinf;
hyperpoint intester;
void draw();
void gldraw();
@ -3938,7 +3941,7 @@ struct floorshape;
struct qfloorinfo {
transmatrix spin;
const hpcshape *shape;
const floorshape *fshape;
floorshape *fshape;
textureinfo *tinf;
int usershape;
};
@ -4150,6 +4153,7 @@ struct floorshape {
int shapeid;
PPR prio;
vector<hpcshape> b, shadow, side[SIDEPARS], gpside[SIDEPARS][MAX_EDGE];
basic_textureinfo tinf3;
floorshape() { prio = PPR::FLOOR; }
};
@ -4937,5 +4941,7 @@ namespace subscreens {
bool split(reaction_t for_each_subscreen);
}
const int TEXTURE_STEP_3D=8;
}

View File

@ -531,8 +531,11 @@ void glapplymatrix(const transmatrix& V) {
int global_projection;
extern renderbuffer *floor_textures;
void dqi_poly::gldraw() {
auto& v = *tab;
int ioffset = offset;
#if MINIMIZE_GL_CALLS
if(current_display->stereo_active() == 0 && !tinf && (color == 0 || ((flags & (POLY_VCONVEX | POLY_CCONVEX)) && !(flags & (POLY_INVERSE | POLY_FORCE_INVERTED))))) {
@ -564,7 +567,9 @@ void dqi_poly::gldraw() {
#if CAP_TEXTURE
glhr::be_textured();
glBindTexture(GL_TEXTURE_2D, tinf->texture_id);
glhr::vertices_texture(v, tinf->tvertices);
current_display->set_projection(0, true);
glhr::vertices_texture(v, tinf->tvertices, offset);
ioffset = 0;
#endif
}
else {
@ -597,7 +602,7 @@ void dqi_poly::gldraw() {
if(flags & POLY_TRIANGLES) {
glhr::color2(color);
glhr::set_depthtest(model_needs_depth());
glDrawArrays(GL_TRIANGLES, offset, cnt);
glDrawArrays(GL_TRIANGLES, ioffset, cnt);
}
else {
glEnable(GL_STENCIL_TEST);
@ -896,7 +901,7 @@ void dqi_poly::draw() {
if(!any) return;
}
if(sphere && tinf && cnt > 3) {
if(sphere && tinf && DIM == 2 && cnt > 3) {
int i = cnt;
cnt = 3;
for(int j=0; j<i; j+=3) {
@ -1687,7 +1692,7 @@ hpcshape
shDodeca;
vector<hpcshape> shWall3D, shMiniWall3D;
vector<hpcshape> shPlainWall3D, shWireframe3D, shWall3D, shMiniWall3D;
#endif
@ -2310,97 +2315,151 @@ void procedural_shapes() {
}
#if CAP_BT && MAXMDIM >= 4
// Make a wall for horocycle-based honeycombs
// flags:
// 1 = first edge should be doubled
// 2 = use POLY_TRIANGLES
// 4 = this is is a triangular face; otherwise, the face is rectangular, and x1+x2-x0 is the fourth vertex
void make_wall(hpcshape& sh, ld x0, ld y0, ld z0, ld x1, ld y1, ld z1, ld x2, ld y2, ld z2, int flags) {
hyperpoint h0 = point3(x0,y0,z0);
hyperpoint h1 = point3(x1,y1,z1);
hyperpoint h2 = point3(x2,y2,z2);
void make_wall(int id, vector<hyperpoint> vertices, bool force_triangles = false) {
using namespace hyperpoint_vec;
hyperpoint h3 = h1 + h2 - h0;
bshape(sh, PPR::WALL);
// orient correctly
transmatrix T;
set_column(T, 0, vertices[0]);
set_column(T, 1, vertices[1]);
set_column(T, 2, vertices[2]);
set_column(T, 3, C0);
if(det(T) < 0)
reverse(vertices.begin(), vertices.end());
ld yy = log(2) / 2;
const int STEP=10;
auto at = [&] (hyperpoint h) {
if(!binarytiling) { hpcpush(normalize(h)); return; }
hyperpoint res = binary::parabolic3(h[0], h[1]) * xpush0(yy*h[2]);
hpcpush(res);
};
if(flags & 2) {
last->flags |= POLY_TRIANGLES;
const auto STEP = TEXTURE_STEP_3D;
const int n = isize(vertices);
bshape(shWall3D[id], PPR::WALL);
last->flags |= POLY_TRIANGLES;
hyperpoint center = Hypc;
for(auto v: vertices) center += v;
center /= n;
println(hlog, "vertices = ", vertices, " center = ", center);
for(int a=0; a<n; a++)
for(int y=0; y<STEP; y++)
for(int x=0; x<STEP; x++) {
int x1 = x + 1;
int y1 = y + 1;
if((flags & 4) && x+y >= STEP) continue;
at((h0 * (STEP-x -y ) + h1 * x + h2 * y ) / STEP);
at((h0 * (STEP-x1-y ) + h1 * x1 + h2 * y ) / STEP);
at((h0 * (STEP-x -y1) + h1 * x + h2 * y1) / STEP);
if((flags & 4) && x+y >= STEP-1) continue;
at((h0 * (STEP-x1-y ) + h1 * x1 + h2 * y ) / STEP);
at((h0 * (STEP-x -y1) + h1 * x + h2 * y1) / STEP);
at((h0 * (STEP-x1-y1) + h1 * x1 + h2 * y1) / STEP);
hyperpoint v1 = (vertices[a] - center) / STEP;
hyperpoint v2 = (vertices[(a+1)%n] - center) / STEP;
if(x+y < STEP) {
at(center + v1 * x + v2 * y);
at(center + v1 * (x+1) + v2 * y);
at(center + v1 * x + v2 * (y+1));
}
if(x+y <= STEP && x && y) {
at(center + v1 * x + v2 * y);
at(center + v1 * (x-1) + v2 * y);
at(center + v1 * x + v2 * (y-1));
}
}
bshape(shWireframe3D[id], PPR::WALL);
if(!binarytiling) {
for(auto v: vertices) hpcpush(v);
hpcpush(vertices[0]);
}
else {
int STP2 = ((flags == 1) ? 2 : 1) * STEP;
for(int t=0; t<STP2; t++) at((h0 * (STP2-t) + h1 * t) / STP2);
if(flags&4) {
for(int t=0; t<STEP; t++) at((h1 * (STEP-t) + h2 * t) / STEP);
}
else {
for(int t=0; t<STEP; t++) at((h1 * (STEP-t) + h3 * t) / STEP);
for(int t=0; t<STEP; t++) at((h3 * (STEP-t) + h2 * t) / STEP);
}
for(int t=0; t<STEP; t++) at((h2 * (STEP-t) + h0 * t) / STEP);
at(h0);
for(int a=0; a<n; a++) for(int y=0; y<STEP; y++)
at((vertices[a] * (STEP-y) + vertices[(a+1)%n] * y)/STEP);
at(vertices[0]);
}
finishshape();
shPlainWall3D[id] = force_triangles ? shWall3D[id] : shWireframe3D[id];
}
vector<hyperpoint> make4(hyperpoint a, hyperpoint b, hyperpoint c) {
using namespace hyperpoint_vec;
return {a, b, b+c-a, c};
}
vector<hyperpoint> make5(hyperpoint a, hyperpoint b, hyperpoint c) {
using namespace hyperpoint_vec;
return {a, (a+b)/2, b, b+c-a, c};
}
void create_wall3d() {
using namespace hyperpoint_vec;
shWall3D.resize(S7);
shPlainWall3D.resize(S7);
shWireframe3D.resize(S7);
if(DIM == 3 && binarytiling && geometry == gBinary3) {
make_wall(shWall3D[0], 0,0,-1, -1,0,-1, 0,-1,-1, 2);
make_wall(shWall3D[1], 0,0,-1, +1,0,-1, 0,-1,-1, 2);
make_wall(shWall3D[2], 0,0,-1, -1,0,-1, 0,+1,-1, 2);
make_wall(shWall3D[3], 0,0,-1, +1,0,-1, 0,+1,-1, 2);
make_wall(shWall3D[4], -1,-1,-1, -1,1,-1, -1,-1,+1, 1);
make_wall(shWall3D[5], +1,-1,-1, +1,1,-1, +1,-1,+1, 1);
make_wall(shWall3D[6], -1,-1,-1, 1,-1,-1, -1,-1,+1, 1);
make_wall(shWall3D[7], -1,+1,-1, 1,+1,-1, -1,+1,+1, 1);
make_wall(shWall3D[8], 1,1,+1, -1,1,+1, 1,-1,+1, 0);
hyperpoint h00 = point3(-1,-1,-1);
hyperpoint h01 = point3(-1,0,-1);
hyperpoint h02 = point3(-1,+1,-1);
hyperpoint h10 = point3(0,-1,-1);
hyperpoint h11 = point3(0,0,-1);
hyperpoint h12 = point3(0,+1,-1);
hyperpoint h20 = point3(+1,-1,-1);
hyperpoint h21 = point3(+1,0,-1);
hyperpoint h22 = point3(+1,+1,-1);
hyperpoint down = point3(0,0,2);
make_wall(0, make4(h11, h01, h10), true);
make_wall(1, make4(h11, h21, h10), true);
make_wall(2, make4(h11, h01, h12), true);
make_wall(3, make4(h11, h21, h12), true);
make_wall(4, make5(h00, h02, h00+down));
make_wall(5, make5(h20, h22, h20+down));
make_wall(6, make5(h00, h20, h00+down));
make_wall(7, make5(h02, h22, h02+down));
make_wall(8, make4(h22+down, h02+down, h20+down));
}
if(DIM == 3 && binarytiling && geometry == gHoroTris) {
ld r = sqrt(3)/6;
ld r1 = r;
ld r2 = r * 2;
ld r4 = r * 4;
make_wall(shWall3D[0], 0,-r2,-1, +.5, r1,-1,-.5, r1,-1, 2|4);
make_wall(shWall3D[1], 0, r4,-1, +.5, r1,-1,-.5, r1,-1, 2|4);
make_wall(shWall3D[2], 0,-r2,-1, -1,-r2,-1,-.5, r1,-1, 2|4);
make_wall(shWall3D[3], 0,-r2,-1, +.5, r1,-1, +1,-r2,-1, 2|4);
make_wall(shWall3D[4],-1,-r2,-1, 1,-r2,-1, -1,-r2, 1, 1);
make_wall(shWall3D[5], 1,-r2,-1, 0, r4,-1, 1,-r2, 1, 1);
make_wall(shWall3D[6],-1,-r2,-1, 0, r4,-1, -1,-r2, 1, 1);
make_wall(shWall3D[7], 1,-r2, 1, 0, r4, 1, -1,-r2, 1, 4);
hyperpoint t0 = point3(0,-r2,-1);
hyperpoint t1 = point3(+.5,r1,-1);
hyperpoint t2 = point3(-.5,r1,-1);
hyperpoint shift = point3(0,0,-3);
hyperpoint down = point3(0,0,2);
hyperpoint d0 = -2 * t0 + shift;
hyperpoint d1 = -2 * t1 + shift;
hyperpoint d2 = -2 * t2 + shift;
make_wall(0, {t0, t1, t2}, true);
make_wall(1, {d0, t1, t2}, true);
make_wall(2, {t0, d1, t2}, true);
make_wall(3, {t0, t1, d2});
make_wall(4, make5(d2, d1, d2 + down));
make_wall(5, make5(d0, d2, d0 + down));
make_wall(6, make5(d1, d0, d1 + down));
make_wall(7, {d0+down, d1+down, d2+down});
}
if(DIM == 3 && euclid && S7 == 6) {
for(int w=0; w<6; w++) {
bshape(shWall3D[w], PPR::WALL);
for(int a=0; a<=4; a++) {
vector<hyperpoint> vertices;
for(int a=0; a<4; a++) {
int t[3];
t[0] = (w>=3) ? -1 : 1;
t[1] = among(a, 0, 3, 4) ? -1 : 1;
t[1] = among(a, 0, 3) ? -1 : 1;
t[2] = among(a, 2, 3) ? -1 : 1;
int x = w%3;
int y = (x+2)%3;
int z = (y+2)%3;
hpcpush(hpxy3(t[x]/2., t[y]/2., t[z]/2.));
vertices.push_back(hpxy3(t[x]/2., t[y]/2., t[z]/2.));
}
make_wall(w, vertices, 0);
}
}
@ -2412,14 +2471,9 @@ void create_wall3d() {
vector<int> valid;
for(int c=0; c<3; c++) if(co[c]) valid.push_back(c);
int third = 3 - valid[1] - valid[0];
bshape(shWall3D[w], PPR::WALL);
hyperpoint v0 = cpush0(valid[0], co[valid[0]] > 0 ? 1 : -1);
hyperpoint v1 = cpush0(valid[1], co[valid[1]] > 0 ? 1 : -1);
hpcpush(v0);
hpcpush(v0/2 + v1/2 + cpush0(third, .5) - C0);
hpcpush(v1);
hpcpush(v0/2 + v1/2 + cpush0(third, -.5) - C0);
hpcpush(v0);
make_wall(w, {v0, v0/2 + v1/2 + cpush0(third, .5) - C0, v1, v0/2 + v1/2 + cpush0(third, -.5) - C0});
}
}
@ -2430,22 +2484,20 @@ void create_wall3d() {
bshape(shWall3D[w], PPR::WALL);
if(w%7 < 3) {
int z = w>=7?-1:1;
hpcpush(cpush0(w%7, z) + cpush0((w%7+1)%3, 1/2.) - C0);
hpcpush(cpush0(w%7, z) + cpush0((w%7+2)%3, 1/2.) - C0);
hpcpush(cpush0(w%7, z) + cpush0((w%7+1)%3,-1/2.) - C0);
hpcpush(cpush0(w%7, z) + cpush0((w%7+2)%3,-1/2.) - C0);
hpcpush(cpush0(w%7, z) + cpush0((w%7+1)%3, 1/2.) - C0);
make_wall(w, {
cpush0(w%7, z) + cpush0((w%7+1)%3, 1/2.) - C0,
cpush0(w%7, z) + cpush0((w%7+2)%3, 1/2.) - C0,
cpush0(w%7, z) + cpush0((w%7+1)%3,-1/2.) - C0,
cpush0(w%7, z) + cpush0((w%7+2)%3,-1/2.) - C0
});
}
else {
auto t = euclid3::getcoord(v[w]);
ld x = t[0], y = t[1], z = t[2];
hpcpush(hpxy3(x, y/2, 0));
hpcpush(hpxy3(x/2, y, 0));
hpcpush(hpxy3(0, y, z/2));
hpcpush(hpxy3(0, y/2, z));
hpcpush(hpxy3(x/2, 0, z));
hpcpush(hpxy3(x, 0, z/2));
hpcpush(hpxy3(x, y/2, 0));
make_wall(w, {
hpxy3(x, y/2, 0), hpxy3(x/2, y, 0), hpxy3(0, y, z/2),
hpxy3(0, y/2, z), hpxy3(x/2, 0, z), hpxy3(x, 0, z/2)
});
}
}
}
@ -2454,9 +2506,10 @@ void create_wall3d() {
reg3::generate();
int facesize = isize(reg3::cellshape) / S7;
for(int w=0; w<S7; w++) {
bshape(shWall3D[w], PPR::WALL);
for(int a=0; a<=facesize; a++)
hpcpush(reg3::cellshape[w*facesize+a%facesize]);
vector<hyperpoint> vertices;
for(int a=0; a<facesize; a++)
vertices.push_back(reg3::cellshape[w*facesize+a]);
make_wall(w, vertices, 0);
}
}

View File

@ -639,7 +639,7 @@ template<class T> void bindbuffer(T& v) {
#endif
void vertices(const vector<glvertex>& v) {
void vertices(const vector<glvertex>& v, int vshift = 0) {
#if CAP_VERTEXBUFFER
if(&v[0] == buffered_vertices) {
if(&v[0] == current_vertices) return;
@ -651,21 +651,21 @@ void vertices(const vector<glvertex>& v) {
bindbuffer(v);
glVertexAttribPointer(glhr::aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), 0);
#else
if(current_vertices == &v[0]) return;
current_vertices = &v[0];
if(current_vertices == &v[vshift]) return;
current_vertices = &v[vshift];
#if CAP_SHADER
glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), &v[0]);
glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), &v[vshift]);
#else
glVertexPointer(3, GL_FLOAT, sizeof(glvertex), &v[0]);
#endif
#endif
}
void vertices_texture(const vector<glvertex>& v, const vector<glvertex>& t) {
void vertices_texture(const vector<glvertex>& v, const vector<glvertex>& t, int vshift = 0) {
#if CAP_VERTEXBUFFER
// not implemented!
#else
vertices(v);
vertices(v, vshift);
#if CAP_SHADER
glVertexAttribPointer(aTexture, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), &t[0]);
#else