From 5bb9d545b0e8eb8f5b6cb275c6552558c3685d7f Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Wed, 1 Nov 2017 01:02:40 +0100 Subject: [PATCH] fixed some missing ends; fixed many spherical glitches --- polygons.cpp | 331 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 243 insertions(+), 88 deletions(-) diff --git a/polygons.cpp b/polygons.cpp index 20e3eb14..b62a38fe 100644 --- a/polygons.cpp +++ b/polygons.cpp @@ -1,6 +1,22 @@ // HyperRogue, shapes used for the vector graphics // Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details +// draw the lines +static const int POLY_DRAWLINES = 1; +// draw the area +static const int POLY_DRAWAREA = 2; +// draw the inverse -- useful in stereographic projection +static const int POLY_INVERSE = 4; +// never draw in inverse +static const int POLY_ISSIDE = 8; + +// there are points behind the camera +static const int POLY_BEHIND = 16; +// some coordinates are too large -- best not to draw to avoid glitches +static const int POLY_TOOLARGE = 32; +// on the sphere (orthogonal projection), do not draw without any points in front +static const int POLY_INFRONT = 64; + #define QHPC 512000 int qhpc, prehpc; @@ -24,8 +40,10 @@ extern long double polydata[]; struct hpcshape { int s, e, prio; + int flags; }; + hpcshape *last = NULL; vector ptds; @@ -40,7 +58,7 @@ bool ptdsort(const polytodraw& p1, const polytodraw& p2) { void hpcpush(hyperpoint h) { if(sphere) h = mid(h,h); - if(vid.usingGL && !first && intval(hpc[qhpc-1], h) > (sphere ? .0001 : 0.25)) { + if(/*vid.usingGL && */!first && intval(hpc[qhpc-1], h) > (sphere ? .0001 : 0.25)) { hyperpoint md = mid(hpc[qhpc-1], h); hpcpush(md); hpcpush(h); @@ -70,6 +88,7 @@ void chasmifyPoly(double fac, double fac2, int k) { hpc[qhpc++] = H; } hpc[qhpc++] = hpc[last->s]; + last->flags |= POLY_ISSIDE; } void shift(hpcshape& sh, double dx, double dy, double dz) { @@ -148,56 +167,65 @@ int polyi; int polyx[POLYMAX], polyxr[POLYMAX], polyy[POLYMAX]; +int poly_flags; + hyperpoint gltopoint(GLfloat t[3]) { hyperpoint h; h[0] = t[0]; h[1] = t[1]; h[2] = t[2]; return h; } +void add1(const hyperpoint& H) { + for(int i=0; i<3; i++) glcoords[qglcoords][i] = H[i]; + } + +int spherespecial; + void addpoint(const hyperpoint& H) { -#if CAP_GL - if(vid.usingGL) { - if(polyi >= POLYMAX) return; - if(pmodel) { - hyperpoint Hscr; - applymodel(H, Hscr); - glcoords[qglcoords][0] = Hscr[0] * vid.radius; - glcoords[qglcoords][1] = Hscr[1] * vid.radius; - glcoords[qglcoords][2] = Hscr[2] * vid.radius; - } - else if(euclid) { - for(int i=0; i<3; i++) glcoords[qglcoords][i] = H[i]; - - glcoords[qglcoords][2] *= EUCSCALE; - glcoords[qglcoords][2] += vid.alpha; - // glcoords[qglcoords][2] = 1; // EUCSCALE; - } - else { - for(int i=0; i<3; i++) glcoords[qglcoords][i] = H[i]; - glcoords[qglcoords][2] += vid.alpha; - } - qglcoords++; - } -#else - if(0) {} -#endif - else { - if(polyi >= POLYMAX) return; - hyperpoint Hscr; + if(qglcoords >= POLYMAX) return; + + if(true) { + hyperpoint Hscr; applymodel(H, Hscr); - ld x = vid.xcenter + Hscr[0] * vid.radius; - ld y = vid.ycenter + Hscr[1] * vid.radius; + if(vid.alphax + H[2] <= BEHIND_LIMIT) poly_flags |= POLY_BEHIND; + + if(spherespecial) { + double curnorm = H[0]*H[0]+H[1]*H[1]+H[2]*H[2]; + double horizon = curnorm / vid.alphax; + + if((spherespecial>0) ^ (H[2] <= -horizon)) poly_flags |= POLY_INFRONT; + else { + double coef = + (sqrt(curnorm - horizon*horizon) / (vid.alpha - horizon)) / + (sqrt(curnorm - H[2]*H[2]) / (vid.alpha+H[2])); + +// double coef = (vid.alphax + horizon) / (vid.alphax + H[2]); -< that one has a funny effect, seriously + Hscr[0] *= coef; + Hscr[1] *= coef; + } + } + for(int i=0; i<3; i++) Hscr[i] *= vid.radius; + add1(Hscr); + } /* + else { + add1(H); + if(euclid) glcoords[qglcoords][2] *= EUCSCALE; + glcoords[qglcoords][2] += vid.alpha; + // glcoords[qglcoords][2] = 1; // EUCSCALE; + } */ + qglcoords++; + } - if(x < -vid.xres) x = -vid.xres; - if(y < -vid.yres) y = -vid.yres; - if(x > 2*vid.xres) x = 2*vid.xres; - if(y > 2*vid.yres) y = 2*vid.yres; - - ld xe = Hscr[2] * vid.radius * vid.eye; - polyx[polyi] = x-xe; - polyxr[polyi] = x+xe; - polyy[polyi] = y; - polyi++; +void coords_to_poly() { + polyi = qglcoords; + for(int i=0; i poly_limit || abs(glcoords[i][1]) > poly_limit) + return; // too large! + } + + if(sphere && vid.alphax > 1) { + if(!hiliteclick && !(poly_flags & POLY_INFRONT)) return; + } + + if(spherespecial > 0 && !(poly_flags & POLY_ISSIDE)) { + double rarea = 0; + for(int i=0; i0) + poly_flags ^= POLY_INVERSE; + + if(poly_flags & POLY_INVERSE) { + if(curradius < vid.alphax - 1e-6) return; + } + } + else poly_flags &=~ POLY_INVERSE; + +#if CAP_GL + if(vid.usingGL) { + if(pmodel == 0) for(int i=0; i 1 ? 1 : -1; + #ifndef STLSORT + for(int p: {PPR_REDWALLs, PPR_REDWALLs2, PPR_REDWALLs3, PPR_WALL3s, + PPR_LAKEWALL, PPR_INLAKEWALL, PPR_BELOWBOTTOM}) + reverse(&ptds2[qp0[p]], &ptds2[qp[p]]); + #endif + for(int i=siz-1; i>=0; i--) { + #ifdef STLSORT + polytodraw& ptd (ptds[i]); + #else + polytodraw& ptd (*ptds2[i]); + #endif + if(ptd.kind == pkPoly) { + unsigned c = ptd.col; + ptd.col = ((c & 0xFCFCFC00) >> 2) | (c & 0xFF); + drawqueueitem(ptd); + ptd.col = c; + } + } + #ifndef STLSORT + for(int p: {PPR_REDWALLs, PPR_REDWALLs2, PPR_REDWALLs3, PPR_WALL3s, + PPR_LAKEWALL, PPR_INLAKEWALL, PPR_BELOWBOTTOM}) + reverse(&ptds2[qp0[p]], &ptds2[qp[p]]); + #endif + spherespecial *= -1; + } for(int i=0; i=0; i--) hpcpush(ddi(S21*3, rad - var * sin(i * M_PI/divby)) * ddi(0, tlength * i/20.) * C0); + hpcpush(ddi(S21, rad + var * sin(0 * M_PI/divby)) * ddi(0, tlength * 0/20.) * C0); } hyperpoint hpxd(ld d, ld x, ld y, ld z) { @@ -729,10 +867,22 @@ hyperpoint turtlevertex(int u, double x, double y, double z) { } +void finishshape() { + last->e = qhpc; + double area = 0; + for(int i=last->s; ie-1; i++) + area += hpc[i][0] * hpc[i+1][1] - hpc[i+1][0] * hpc[i][1]; + if(area >= 0) last->flags |= POLY_INVERSE; + if(isnan(area)) ; + else if(intval(hpc[last->s], hpc[last->e-1]) > 1e-6) + printf("bad end\n"); + } + void bshape(hpcshape& sh, int p) { - if(last) last->e = qhpc; + if(last) finishshape(); last = &sh; last->s = qhpc, last->prio = p; + last->flags = 0; first = true; } @@ -820,7 +970,7 @@ void zoomShape(hpcshape& old, hpcshape& newsh, double factor, int lev) { } void bshapeend() { - if(last) last->e = qhpc; + if(last) finishshape(); last = NULL; } @@ -856,9 +1006,9 @@ void buildpolys() { qhpc = 0; bshape(shMovestar, PPR_MOVESTAR); - for(int i=0; i<8; i++) { + for(int i=0; i<=8; i++) { hpcpush(spin(M_PI * i/4) * xpush(crossf) * spin(M_PI * i/4) * C0); - hpcpush(spin(M_PI * i/4 + M_PI/8) * xpush(crossf/4) * spin(M_PI * i/4 + M_PI/8) * C0); + if(i != 8) hpcpush(spin(M_PI * i/4 + M_PI/8) * xpush(crossf/4) * spin(M_PI * i/4 + M_PI/8) * C0); } // scales @@ -964,7 +1114,7 @@ void buildpolys() { for(int t=0; t<=S6; t++) hpcpush(ddi(S7 + t*S14, floorrad0) * C0); bshape(shCircleFloor, PPR_FLOOR); - for(int t=0; t<=84; t+=2) hpcpush(ddi(t, shexf*.7*spzoom) * C0); + for(int t=0; t<=S84; t+=2) hpcpush(ddi(t, shexf*.7*spzoom) * C0); bshape(shFloor[1], PPR_FLOOR); for(int t=0; t<=S7; t++) hpcpush(ddi(t*S12 + td, floorrad1) * C0); @@ -1106,7 +1256,7 @@ void buildpolys() { bshape(shWall[0], PPR_WALL); for(int t=0; t<=S6; t++) { hpcpush(ddi(S7 + t*S14, shexf*fac80) * C0); - hpcpush(ddi(S14 + t*S14, shexf*.2) * C0); + if(t != S6) hpcpush(ddi(S14 + t*S14, shexf*.2) * C0); } bshape(shWall[1], PPR_WALL); @@ -1128,29 +1278,29 @@ void buildpolys() { bshape(shGem[0], PPR_ITEM); for(int t=0; t<=S6; t++) { hpcpush(ddi(S7 + t*S14, shexf*.4) * C0); - hpcpush(ddi(S14 + t*S14, shexf*.1) * C0); + if(t != S6) hpcpush(ddi(S14 + t*S14, shexf*.1) * C0); } bshape(shGem[1], PPR_ITEM); if(S7 == 6) { for(int t=0; t<=S6; t++) { hpcpush(ddi(S7 + t*S14, shexf*.4) * C0); - hpcpush(ddi(S14 + t*S14, shexf*.1) * C0); + if(t != S6) hpcpush(ddi(S14 + t*S14, shexf*.1) * C0); } } else for(int t=0; t<=S7; t++) hpcpush(ddi(t*S36, shexf*.5) * C0); bshape(shStar, PPR_ITEM); - for(int t=0; t& v, hyperpoint h) { @@ -1905,6 +2059,7 @@ void queuetable(const transmatrix& V, GLfloat *f, int cnt, int linecol, int fill ptd.prio = prio << PSHIFT; ptd.u.poly.outline = linecol; ptd.u.poly.minwidth = minwidth_global; + ptd.u.poly.flags = 0; } void queuepoly(const transmatrix& V, const hpcshape& h, int col) {