// rendercubes.cpp: sits in between worldrender.cpp and rendergl.cpp and fills the vertex array for different cube surfaces. #include "cube.h" vector verts; void setarraypointers() { vertex *buf = verts.getbuf(); glVertexPointer(3, GL_FLOAT, sizeof(vertex), &buf->x); glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), &buf->r); glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), &buf->u); }; // generating the actual vertices is done dynamically every frame and sits at the // leaves of all these functions, and are part of the cpu bottleneck on really slow // machines, hence the macros. #define vert(v1, v2, v3, ls, t1, t2) { \ vertex &v = verts.add(); \ v.u = t1; v.v = t2; \ v.x = (float)(v1); v.y = (float)(v2); v.z = (float)(v3); \ v.r = ls->r; v.g = ls->g; v.b = ls->b; v.a = 255; \ }; int nquads; const float TEXTURESCALE = 32.0f; bool floorstrip = false, deltastrip = false; int oh, oy, ox, striptex; // the o* vars are used by the stripification int ol3r, ol3g, ol3b, ol4r, ol4g, ol4b; int firstindex; bool showm = false; void showmip() { showm = !showm; }; void mipstats(int a, int b, int c) { if(showm) conoutf("1x1/2x2/4x4: %d / %d / %d", a, b, c); }; COMMAND(showmip, ARG_NONE); VAR(mergestrips, 0, 1, 1); #define stripend() \ if(floorstrip || deltastrip) { \ int type = GL_TRIANGLE_STRIP, len = verts.length()-firstindex; \ if(mergestrips) switch(len) { \ case 3: type = GL_TRIANGLES; break; \ case 4: type = GL_QUADS; swap(vertex, verts.last(), verts[verts.length()-2]); break; \ }; \ addstrip(type, striptex, firstindex, len); \ floorstrip = deltastrip = false; \ }; void finishstrips() { stripend(); }; sqr sbright, sdark; VARP(lighterror,1,8,100); void render_flat(int wtex, int x, int y, int size, int h, sqr *l1, sqr *l2, sqr *l3, sqr *l4, bool isceil) // floor/ceil quads { if(showm) { l3 = l1 = &sbright; l4 = l2 = &sdark; }; int sx, sy; lookuptexture(wtex, sx, sy); float xf = TEXTURESCALE/sx; float yf = TEXTURESCALE/sy; float xs = size*xf; float ys = size*yf; float xo = xf*x; float yo = yf*y; bool first = !floorstrip || y!=oy+size || striptex!=wtex || h!=oh || x!=ox; if(first) // start strip here { stripend(); firstindex = verts.length(); striptex = wtex; oh = h; ox = x; floorstrip = true; if(isceil) { vert(x+size, h, y, l2, xo+xs, yo); vert(x, h, y, l1, xo, yo); } else { vert(x, h, y, l1, xo, yo); vert(x+size, h, y, l2, xo+xs, yo); }; ol3r = l1->r; ol3g = l1->g; ol3b = l1->b; ol4r = l2->r; ol4g = l2->g; ol4b = l2->b; } else // continue strip { int lighterr = lighterror*2; if((abs(ol3r-l3->r)r)g)g)b)b)r; ol3g = l1->g; ol3b = l1->b; ol4r = l2->r; ol4g = l2->g; ol4b = l2->b; }; if(isceil) { vert(x+size, h3, y+size, l3, xo+xs, yo+ys); vert(x, h4, y+size, l4, xo, yo+ys); } else { vert(x, h4, y+size, l4, xo, yo+ys); vert(x+size, h3, y+size, l3, xo+xs, yo+ys); }; oy = y; nquads++; }; void render_2tris(sqr *h, sqr *s, int x1, int y1, int x2, int y2, int x3, int y3, sqr *l1, sqr *l2, sqr *l3) // floor/ceil tris on a corner cube { stripend(); int sx, sy; lookuptexture(h->ftex, sx, sy); float xf = TEXTURESCALE/sx; float yf = TEXTURESCALE/sy; vert(x1, h->floor, y1, l1, xf*x1, yf*y1); vert(x2, h->floor, y2, l2, xf*x2, yf*y2); vert(x3, h->floor, y3, l3, xf*x3, yf*y3); addstrip(mergestrips ? GL_TRIANGLES : GL_TRIANGLE_STRIP, h->ftex, verts.length()-3, 3); lookuptexture(h->ctex, sx, sy); xf = TEXTURESCALE/sx; yf = TEXTURESCALE/sy; vert(x3, h->ceil, y3, l3, xf*x3, yf*y3); vert(x2, h->ceil, y2, l2, xf*x2, yf*y2); vert(x1, h->ceil, y1, l1, xf*x1, yf*y1); addstrip(mergestrips ? GL_TRIANGLES : GL_TRIANGLE_STRIP, h->ctex, verts.length()-3, 3); nquads++; }; void render_tris(int x, int y, int size, bool topleft, sqr *h1, sqr *h2, sqr *s, sqr *t, sqr *u, sqr *v) { if(topleft) { if(h1) render_2tris(h1, s, x+size, y+size, x, y+size, x, y, u, v, s); if(h2) render_2tris(h2, s, x, y, x+size, y, x+size, y+size, s, t, v); } else { if(h1) render_2tris(h1, s, x, y, x+size, y, x, y+size, s, t, u); if(h2) render_2tris(h2, s, x+size, y, x+size, y+size, x, y+size, t, u, v); }; }; void render_square(int wtex, float floor1, float floor2, float ceil1, float ceil2, int x1, int y1, int x2, int y2, int size, sqr *l1, sqr *l2, bool flip) // wall quads { stripend(); if(showm) { l1 = &sbright; l2 = &sdark; }; int sx, sy; lookuptexture(wtex, sx, sy); float xf = TEXTURESCALE/sx; float yf = TEXTURESCALE/sy; float xs = size*xf; float xo = xf*(x1==x2 ? min(y1,y2) : min(x1,x2)); if(!flip) { vert(x2, ceil2, y2, l2, xo+xs, -yf*ceil2); vert(x1, ceil1, y1, l1, xo, -yf*ceil1); if(mergestrips) vert(x1, floor1, y1, l1, xo, -floor1*yf); vert(x2, floor2, y2, l2, xo+xs, -floor2*yf); if(!mergestrips) vert(x1, floor1, y1, l1, xo, -floor1*yf); } else { vert(x1, ceil1, y1, l1, xo, -yf*ceil1); vert(x2, ceil2, y2, l2, xo+xs, -yf*ceil2); if(mergestrips) vert(x2, floor2, y2, l2, xo+xs, -floor2*yf); vert(x1, floor1, y1, l1, xo, -floor1*yf); if(!mergestrips) vert(x2, floor2, y2, l2, xo+xs, -floor2*yf); }; addstrip(mergestrips ? GL_QUADS : GL_TRIANGLE_STRIP, wtex, verts.length()-4, 4); nquads++; }; int wx1, wy1, wx2, wy2; VARP(watersubdiv, 1, 4, 64); VARF(waterlevel, -128, -128, 127, if(!noteditmode()) hdr.waterlevel = waterlevel); inline void vertw(int v1, float v2, int v3, float t1, float t2, float t) { glTexCoord2f(t1, t2); glVertex3f((float)v1, v2-sinf(v1*v3*0.1+t)*0.2f, (float)v3); }; inline float dx(float x) { return x+sinf(x*2+lastmillis/1000.0f)*0.04f; }; inline float dy(float x) { return x+sinf(x*2+lastmillis/900.0f+PI/5)*0.05f; }; // renders water for bounding rect area that contains water... simple but very inefficient int renderwater(float hf) { if(wx1<0) return nquads; glDepthMask(GL_FALSE); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_SRC_COLOR); int sx, sy; glBindTexture(GL_TEXTURE_2D, lookuptexture(DEFAULT_LIQUID, sx, sy)); wx1 &= ~(watersubdiv-1); wy1 &= ~(watersubdiv-1); float xf = TEXTURESCALE/sx; float yf = TEXTURESCALE/sy; float xs = watersubdiv*xf; float ys = watersubdiv*yf; float t1 = lastmillis/300.0f; float t2 = lastmillis/4000.0f; glColor3ub(255, 255, 255); for(int xx = wx1; xxwx2) wx2 = x2; if(y2>wy2) wy2 = y2; }; }; void resetcubes() { verts.setsizenodelete(0); floorstrip = deltastrip = false; wx1 = -1; nquads = 0; sbright.r = sbright.g = sbright.b = 255; sdark.r = sdark.g = sdark.b = 0; };