From 5db2cfbd1a1fb0ee8085da8bc370d01a8ccc05b4 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Mon, 11 Mar 2019 18:46:34 +0100 Subject: [PATCH] 3d:: textured walls --- floorshapes.cpp | 109 +++++++++++++++++++++++++ graph.cpp | 20 ++--- hyper.h | 16 ++-- polygons.cpp | 207 ++++++++++++++++++++++++++++++------------------ shaders.cpp | 12 +-- 5 files changed, 267 insertions(+), 97 deletions(-) diff --git a/floorshapes.cpp b/floorshapes.cpp index a2cb956e..e3948163 100644 --- a/floorshapes.cpp +++ b/floorshapes.cpp @@ -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 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 g(geometry, gEuclidSquare); + dynamicval va(variation, eVariation::pure); + dynamicval hq(inHighQual, true); + + resetGeometry(); + dynamicval vi(vid, vid); + vid.xres = FLOORTEXTURESIZE; + vid.yres = FLOORTEXTURESIZE; + vid.scale = 0.25; + dynamicval 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 } diff --git a/graph.cpp b/graph.cpp index db93bc2d..79b1d747 100644 --- a/graph.cpp +++ b/graph.cpp @@ -4798,13 +4798,13 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { for(int a=0; atype; 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 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 p(poly_outline, col); for(int i=0; itype; 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(); diff --git a/hyper.h b/hyper.h index 2dc2c32c..998fd605 100644 --- a/hyper.h +++ b/hyper.h @@ -2825,12 +2825,15 @@ struct texture_triangle { texture_triangle(array _v, array _tv) : v(_v), tv(_tv) {} }; -struct textureinfo { - transmatrix M; +struct basic_textureinfo { int texture_id; + vector tvertices; + }; + +struct textureinfo : basic_textureinfo { + transmatrix M; vector triangles; vector vertices; - vector tvertices; cell *c; vector 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 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; + } diff --git a/polygons.cpp b/polygons.cpp index 23461917..a9aa76aa 100644 --- a/polygons.cpp +++ b/polygons.cpp @@ -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 shWall3D, shMiniWall3D; +vector 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 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= 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 make4(hyperpoint a, hyperpoint b, hyperpoint c) { + using namespace hyperpoint_vec; + return {a, b, b+c-a, c}; + } + +vector 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 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 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 vertices; + for(int a=0; a void bindbuffer(T& v) { #endif -void vertices(const vector& v) { +void vertices(const vector& 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& 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& v, const vector& t) { +void vertices_texture(const vector& v, const vector& 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