diff options
| author | xolatile | 2025-08-06 22:54:55 +0200 |
|---|---|---|
| committer | xolatile | 2025-08-06 22:54:55 +0200 |
| commit | 0a1172b75f571685c264a8b9d8ee224bbf11381f (patch) | |
| tree | d041fdc68a60f0ebb48a3852bbcce6d9432f83d5 /src/engine | |
| parent | affde05dc07a94643f1fd2751b2b441f57f73d7d (diff) | |
| download | xolatile-badassbug-0a1172b75f571685c264a8b9d8ee224bbf11381f.tar.xz xolatile-badassbug-0a1172b75f571685c264a8b9d8ee224bbf11381f.tar.zst | |
Please do not hate me, it makes sense...
Diffstat (limited to 'src/engine')
49 files changed, 5432 insertions, 13741 deletions
diff --git a/src/engine/3dgui.cpp b/src/engine/3dgui.cpp index 1e17e78..201f9e3 100644 --- a/src/engine/3dgui.cpp +++ b/src/engine/3dgui.cpp @@ -36,75 +36,55 @@ VARP(guipreviewtime, 0, 15, 1000); static int lastpreview = 0; -static inline bool throttlepreview(bool loaded) -{ +static inline bool throttlepreview(bool loaded) { if(loaded) return true; if(totalmillis - lastpreview < guipreviewtime) return false; lastpreview = totalmillis; return true; } -struct gui : g3d_gui -{ - struct list - { +struct gui : g3d_gui { + struct list { int parent, w, h, springs, curspring, column; }; - int firstlist, nextlist; int columns[MAXCOLUMNS]; - static vector<list> lists; static float hitx, hity; static int curdepth, curlist, xsize, ysize, curx, cury; static bool shouldmergehits, shouldautotab; - - static void reset() - { + static void reset() { lists.setsize(0); } - static int ty, tx, tpos, *tcurrent, tcolor; //tracking tab size and position since uses different layout method... - - bool allowautotab(bool on) - { + bool allowautotab(bool on) { bool oldval = shouldautotab; shouldautotab = on; return oldval; } - - void autotab() - { - if(tcurrent) - { + void autotab() { + if(tcurrent) { if(layoutpass && !tpos) tcurrent = NULL; //disable tabs because you didn't start with one if(shouldautotab && !curdepth && (layoutpass ? 0 : cury) + ysize > guiautotab*FONTH) tab(NULL, tcolor); } } - - bool shouldtab() - { - if(tcurrent && shouldautotab) - { - if(layoutpass) - { + bool shouldtab() { + if(tcurrent && shouldautotab) { + if(layoutpass) { int space = guiautotab*FONTH - ysize; if(space < 0) return true; int l = lists[curlist].parent; - while(l >= 0) - { + while(l >= 0) { space -= lists[l].h; if(space < 0) return true; l = lists[l].parent; } } - else - { + else { int space = guiautotab*FONTH - cury; if(ysize > space) return true; int l = lists[curlist].parent; - while(l >= 0) - { + while(l >= 0) { if(lists[l].h > space) return true; l = lists[l].parent; } @@ -112,24 +92,19 @@ struct gui : g3d_gui } return false; } - bool visible() { return (!tcurrent || tpos==*tcurrent) && !layoutpass; } - //tab is always at top of page - void tab(const char *name, int color) - { + void tab(const char *name, int color) { if(curdepth != 0) return; if(color) tcolor = color; tpos++; if(!name) name = intstr(tpos); int w = max(text_width(name) - 2*INSERT, 0); - if(layoutpass) - { + if(layoutpass) { ty = max(ty, ysize); ysize = 0; } - else - { + else { cury = -ysize; int h = FONTH-2*INSERT, x1 = curx + tx, @@ -139,22 +114,16 @@ struct gui : g3d_gui bool hit = tcurrent && windowhit==this && hitx>=x1 && hity>=y1 && hitx<x2 && hity<y2; if(hit && (!guiclicktab || mousebuttons&G3D_DOWN)) *tcurrent = tpos; //roll-over to switch tab - drawskin(x1-skinx[visible()?2:6]*SKIN_SCALE, y1-skiny[1]*SKIN_SCALE, w, h, visible()?10:19, 9, gui2d ? 1 : 2, light, alpha); text_(name, x1 + (skinx[3]-skinx[2])*SKIN_SCALE - (w ? INSERT : INSERT/2), y1 + (skiny[2]-skiny[1])*SKIN_SCALE - INSERT, tcolor, visible()); } tx += w + ((skinx[5]-skinx[4]) + (skinx[3]-skinx[2]))*SKIN_SCALE; } - bool ishorizontal() const { return curdepth&1; } bool isvertical() const { return !ishorizontal(); } - - void pushlist() - { - if(layoutpass) - { - if(curlist>=0) - { + void pushlist() { + if(layoutpass) { + if(curlist>=0) { lists[curlist].w = xsize; lists[curlist].h = ysize; } @@ -165,11 +134,9 @@ struct gui : g3d_gui curlist = lists.length()-1; xsize = ysize = 0; } - else - { + else { curlist = nextlist++; - if(curlist >= lists.length()) // should never get here unless script code doesn't use same amount of lists in layout and render passes - { + if(curlist >= lists.length()) { // should never get here unless script code doesn't use same amount of lists in layout and render passes { list &l = lists.add(); l.parent = curlist; l.springs = 0; @@ -178,155 +145,121 @@ struct gui : g3d_gui } list &l = lists[curlist]; l.curspring = 0; - if(l.springs > 0) - { + if(l.springs > 0) { if(ishorizontal()) xsize = l.w; else ysize = l.h; } - else - { + else { xsize = l.w; ysize = l.h; } } curdepth++; } - - void poplist() - { + void poplist() { if(!lists.inrange(curlist)) return; list &l = lists[curlist]; - if(layoutpass) - { + if(layoutpass) { l.w = xsize; l.h = ysize; if(l.column >= 0) columns[l.column] = max(columns[l.column], ishorizontal() ? ysize : xsize); } curlist = l.parent; curdepth--; - if(lists.inrange(curlist)) - { + if(lists.inrange(curlist)) { int w = xsize, h = ysize; if(ishorizontal()) cury -= h; else curx -= w; list &p = lists[curlist]; xsize = p.w; ysize = p.h; - if(!layoutpass && p.springs > 0) - { + if(!layoutpass && p.springs > 0) { list &s = lists[p.parent]; if(ishorizontal()) xsize = s.w; else ysize = s.h; } layout(w, h); } } - int text (const char *text, int color, const char *icon) { autotab(); return button_(text, color, icon, false, false); } int button(const char *text, int color, const char *icon) { autotab(); return button_(text, color, icon, true, false); } int title (const char *text, int color, const char *icon) { autotab(); return button_(text, color, icon, false, true); } - void separator() { autotab(); line_(FONTH/3); } void progress(float percent) { autotab(); line_((FONTH*4)/5, percent); } - //use to set min size (useful when you have progress bars) void strut(float size) { layout(isvertical() ? int(size*FONTW) : 0, isvertical() ? 0 : int(size*FONTH)); } //add space between list items void space(float size) { layout(isvertical() ? 0 : int(size*FONTW), isvertical() ? int(size*FONTH) : 0); } - - void spring(int weight) - { + void spring(int weight) { if(curlist < 0) return; list &l = lists[curlist]; if(layoutpass) { if(l.parent >= 0) l.springs += weight; return; } int nextspring = min(l.curspring + weight, l.springs); if(nextspring <= l.curspring) return; - if(ishorizontal()) - { + if(ishorizontal()) { int w = xsize - l.w; layout((w*nextspring)/l.springs - (w*l.curspring)/l.springs, 0); } - else - { + else { int h = ysize - l.h; layout(0, (h*nextspring)/l.springs - (h*l.curspring)/l.springs); } l.curspring = nextspring; } - - void column(int col) - { + void column(int col) { if(curlist < 0 || !layoutpass || col < 0 || col >= MAXCOLUMNS) return; list &l = lists[curlist]; l.column = col; } - - int layout(int w, int h) - { - if(layoutpass) - { - if(ishorizontal()) - { + int layout(int w, int h) { + if(layoutpass) { + if(ishorizontal()) { xsize += w; ysize = max(ysize, h); } - else - { + else { xsize = max(xsize, w); ysize += h; } return 0; } - else - { + else { bool hit = ishit(w, h); if(ishorizontal()) curx += w; else cury += h; return (hit && visible()) ? mousebuttons|G3D_ROLLOVER : 0; } } - - bool mergehits(bool on) - { + bool mergehits(bool on) { bool oldval = shouldmergehits; shouldmergehits = on; return oldval; } - - bool ishit(int w, int h, int x = curx, int y = cury) - { + bool ishit(int w, int h, int x = curx, int y = cury) { if(shouldmergehits) return windowhit==this && (ishorizontal() ? hitx>=x && hitx<x+w : hity>=y && hity<y+h); if(ishorizontal()) h = ysize; else w = xsize; return windowhit==this && hitx>=x && hity>=y && hitx<x+w && hity<y+h; } - - int image(Texture *t, float scale, const char *overlaid) - { + int image(Texture *t, float scale, const char *overlaid) { autotab(); if(scale==0) scale = 1; int size = (int)(scale*2*FONTH)-SHADOW; if(visible()) icon_(t, overlaid!=NULL, curx, cury, size, ishit(size+SHADOW, size+SHADOW), overlaid); return layout(size+SHADOW, size+SHADOW); } - - int texture(VSlot &vslot, float scale, bool overlaid) - { + int texture(VSlot &vslot, float scale, bool overlaid) { autotab(); if(scale==0) scale = 1; int size = (int)(scale*2*FONTH)-SHADOW; if(visible()) previewslot(vslot, overlaid, curx, cury, size, ishit(size+SHADOW, size+SHADOW)); return layout(size+SHADOW, size+SHADOW); } - - int playerpreview(int model, int team, int weap, float sizescale, const char *overlaid) - { + int playerpreview(int model, int team, int weap, float sizescale, const char *overlaid) { autotab(); if(sizescale==0) sizescale = 1; int size = (int)(sizescale*2*FONTH)-SHADOW; - if(model>=0 && visible()) - { + if(model>=0 && visible()) { bool hit = ishit(size+SHADOW, size+SHADOW); float xs = size, ys = size, xi = curx, yi = cury; - if(overlaid && hit && actionon) - { + if(overlaid && hit && actionon) { hudnotextureshader->set(); gle::colorf(0, 0, 0, 0.75f); rect_(xi+SHADOW, yi+SHADOW, xs, ys); @@ -341,10 +274,8 @@ struct gui : g3d_gui hudshader->set(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - if(overlaid) - { - if(hit) - { + if(overlaid) { + if(hit) { hudnotextureshader->set(); glBlendFunc(GL_ZERO, GL_SRC_COLOR); gle::colorf(1, 0.5f, 0.5f); @@ -361,18 +292,14 @@ struct gui : g3d_gui } return layout(size+SHADOW, size+SHADOW); } - - int modelpreview(const char *name, int anim, float sizescale, const char *overlaid, bool throttle) - { + int modelpreview(const char *name, int anim, float sizescale, const char *overlaid, bool throttle) { autotab(); if(sizescale==0) sizescale = 1; int size = (int)(sizescale*2*FONTH)-SHADOW; - if(name[0] && visible() && (!throttle || throttlepreview(modelloaded(name)))) - { + if(name[0] && visible() && (!throttle || throttlepreview(modelloaded(name)))) { bool hit = ishit(size+SHADOW, size+SHADOW); float xs = size, ys = size, xi = curx, yi = cury; - if(overlaid && hit && actionon) - { + if(overlaid && hit && actionon) { hudnotextureshader->set(); gle::colorf(0, 0, 0, 0.75f); rect_(xi+SHADOW, yi+SHADOW, xs, ys); @@ -383,8 +310,7 @@ struct gui : g3d_gui glDisable(GL_BLEND); modelpreview::start(x1, y1, x2-x1, y2-y1, overlaid!=NULL); model *m = loadmodel(name); - if(m) - { + if(m) { entitylight light; light.color = vec(1, 1, 1); light.dir = vec(0, -1, 2).normalize(); @@ -398,10 +324,8 @@ struct gui : g3d_gui hudshader->set(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - if(overlaid) - { - if(hit) - { + if(overlaid) { + if(hit) { hudnotextureshader->set(); glBlendFunc(GL_ZERO, GL_SRC_COLOR); gle::colorf(1, 0.5f, 0.5f); @@ -418,18 +342,14 @@ struct gui : g3d_gui } return layout(size+SHADOW, size+SHADOW); } - - int prefabpreview(const char *prefab, const vec &color, float sizescale, const char *overlaid, bool throttle) - { + int prefabpreview(const char *prefab, const vec &color, float sizescale, const char *overlaid, bool throttle) { autotab(); if(sizescale==0) sizescale = 1; int size = (int)(sizescale*2*FONTH)-SHADOW; - if(prefab[0] && visible() && (!throttle || throttlepreview(prefabloaded(prefab)))) - { + if(prefab[0] && visible() && (!throttle || throttlepreview(prefabloaded(prefab)))) { bool hit = ishit(size+SHADOW, size+SHADOW); float xs = size, ys = size, xi = curx, yi = cury; - if(overlaid && hit && actionon) - { + if(overlaid && hit && actionon) { hudnotextureshader->set(); gle::colorf(0, 0, 0, 0.75f); rect_(xi+SHADOW, yi+SHADOW, xs, ys); @@ -444,10 +364,8 @@ struct gui : g3d_gui hudshader->set(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - if(overlaid) - { - if(hit) - { + if(overlaid) { + if(hit) { hudnotextureshader->set(); glBlendFunc(GL_ZERO, GL_SRC_COLOR); gle::colorf(1, 0.5f, 0.5f); @@ -464,37 +382,29 @@ struct gui : g3d_gui } return layout(size+SHADOW, size+SHADOW); } - - void slider(int &val, int vmin, int vmax, int color, const char *label) - { + void slider(int &val, int vmin, int vmax, int color, const char *label) { autotab(); int x = curx; int y = cury; line_((FONTH*2)/3); - if(visible()) - { + if(visible()) { if(!label) label = intstr(val); int w = text_width(label); - bool hit; int px, py, offset = vmin < vmax ? clamp(val, vmin, vmax) : clamp(val, vmax, vmin); - if(ishorizontal()) - { + if(ishorizontal()) { hit = ishit(FONTH, ysize, x, y); px = x + (FONTH-w)/2; py = y + (ysize-FONTH) - ((ysize-FONTH)*(offset-vmin))/((vmax==vmin) ? 1 : (vmax-vmin)); //vmin at bottom } - else - { + else { hit = ishit(xsize, FONTH, x, y); px = x + FONTH/2 - w/2 + ((xsize-w)*(offset-vmin))/((vmax==vmin) ? 1 : (vmax-vmin)); //vmin at left py = y; } - if(hit) color = 0xFF0000; text_(label, px, py, color, hit && actionon, hit); - if(hit && actionon) - { + if(hit && actionon) { int vnew = (vmin < vmax ? 1 : -1)+vmax-vmin; if(ishorizontal()) vnew = int((vnew*(y+ysize-FONTH/2-hity))/(ysize-FONTH)); else vnew = int((vnew*(hitx-x-FONTH/2))/(xsize-w)); @@ -504,32 +414,23 @@ struct gui : g3d_gui } } } - - char *field(const char *name, int color, int length, int height, const char *initval, int initmode) - { + char *field(const char *name, int color, int length, int height, const char *initval, int initmode) { return field_(name, color, length, height, initval, initmode, FIELDEDIT); } - - char *keyfield(const char *name, int color, int length, int height, const char *initval, int initmode) - { + char *keyfield(const char *name, int color, int length, int height, const char *initval, int initmode) { return field_(name, color, length, height, initval, initmode, FIELDKEY); } - - char *field_(const char *name, int color, int length, int height, const char *initval, int initmode, int fieldtype = FIELDEDIT) - { + char *field_(const char *name, int color, int length, int height, const char *initval, int initmode, int fieldtype = FIELDEDIT) { editor *e = useeditor(name, initmode, false, initval); // generate a new editor if necessary - if(layoutpass) - { - if(initval && e->mode==EDITORFOCUSED && (e!=currentfocus() || fieldmode == FIELDSHOW)) - { + if(layoutpass) { + if(initval && e->mode==EDITORFOCUSED && (e!=currentfocus() || fieldmode == FIELDSHOW)) { if(strcmp(e->lines[0].text, initval)) e->clear(initval); } e->linewrap = (length<0); e->maxx = (e->linewrap) ? -1 : length; e->maxy = (height<=0)?1:-1; e->pixelwidth = abs(length)*FONTW; - if(e->linewrap && e->maxy==1) - { + if(e->linewrap && e->maxy==1) { int temp; text_bounds(e->lines[0].text, temp, e->pixelheight, e->pixelwidth); //only single line editors can have variable height } @@ -538,20 +439,14 @@ struct gui : g3d_gui } int h = e->pixelheight; int w = e->pixelwidth + FONTW; - bool wasvertical = isvertical(); if(wasvertical && e->maxy != 1) pushlist(); - char *result = NULL; - if(visible() && !layoutpass) - { + if(visible() && !layoutpass) { e->rendered = true; - bool hit = ishit(w, h); - if(hit) - { - if(mousebuttons&G3D_DOWN) //mouse request focus - { + if(hit) { + if(mousebuttons&G3D_DOWN) { //mouse request focus { if(fieldtype==FIELDKEY) e->clear(); useeditor(name, initmode, true); e->mark(false); @@ -560,16 +455,13 @@ struct gui : g3d_gui } bool editing = (fieldmode != FIELDSHOW) && (e==currentfocus()); if(hit && editing && (mousebuttons&G3D_PRESSED)!=0 && fieldtype==FIELDEDIT) e->hit(int(floor(hitx-(curx+FONTW/2))), int(floor(hity-cury)), (mousebuttons&G3D_DRAGGED)!=0); //mouse request position - if(editing && ((fieldmode==FIELDCOMMIT) || (fieldmode==FIELDABORT) || !hit)) // commit field if user pressed enter or wandered out of focus - { + if(editing && ((fieldmode==FIELDCOMMIT) || (fieldmode==FIELDABORT) || !hit)) { // commit field if user pressed enter or wandered out of focus { if(fieldmode==FIELDCOMMIT || (fieldmode!=FIELDABORT && !hit)) result = e->currentline().text; e->active = (e->mode!=EDITORFOCUSED); fieldmode = FIELDSHOW; } else fieldsactive = true; - e->draw(curx+FONTW/2, cury, color, hit && editing); - hudnotextureshader->set(); glDisable(GL_BLEND); if(editing) gle::colorf(1, 0, 0); @@ -579,24 +471,18 @@ struct gui : g3d_gui hudshader->set(); } layout(w, h); - - if(e->maxy != 1) - { + if(e->maxy != 1) { int slines = e->limitscrolly(); - if(slines > 0) - { + if(slines > 0) { int pos = e->scrolly; slider(e->scrolly, slines, 0, color, NULL); if(pos != e->scrolly) e->cy = e->scrolly; } if(wasvertical) poplist(); } - return result; } - - void rect_(float x, float y, float w, float h, bool lines = false) - { + void rect_(float x, float y, float w, float h, bool lines = false) { gle::defvertex(2); gle::begin(lines ? GL_LINE_LOOP : GL_TRIANGLE_STRIP); gle::attribf(x, y); @@ -606,9 +492,7 @@ struct gui : g3d_gui if(!lines) gle::attribf(x + w, y + h); xtraverts += gle::end(); } - - void rect_(float x, float y, float w, float h, int usetc) - { + void rect_(float x, float y, float w, float h, int usetc) { gle::defvertex(2); gle::deftexcoord0(); gle::begin(GL_TRIANGLE_STRIP); @@ -619,29 +503,23 @@ struct gui : g3d_gui gle::attribf(x + w, y + h); gle::attrib(tc[usetc+2]); xtraverts += gle::end(); } - - void text_(const char *text, int x, int y, int color, bool shadow, bool force = false) - { + void text_(const char *text, int x, int y, int color, bool shadow, bool force = false) { if(shadow) draw_text(text, x+SHADOW, y+SHADOW, 0x00, 0x00, 0x00, -0xC0); draw_text(text, x, y, color>>16, (color>>8)&0xFF, color&0xFF, force ? -0xFF : 0xFF); } - - void background(int color, int inheritw, int inherith) - { + void background(int color, int inheritw, int inherith) { if(layoutpass) return; hudnotextureshader->set(); gle::colorub(color>>16, (color>>8)&0xFF, color&0xFF, 0x80); int w = xsize, h = ysize; - if(inheritw>0) - { + if(inheritw>0) { int parentw = curlist, parentdepth = 0; for(;parentdepth < inheritw && lists[parentw].parent>=0; parentdepth++) parentw = lists[parentw].parent; list &p = lists[parentw]; w = p.springs > 0 && (curdepth-parentdepth)&1 ? lists[p.parent].w : p.w; } - if(inherith>0) - { + if(inherith>0) { int parenth = curlist, parentdepth = 0; for(;parentdepth < inherith && lists[parenth].parent>=0; parentdepth++) parenth = lists[parenth].parent; @@ -651,25 +529,20 @@ struct gui : g3d_gui rect_(curx, cury, w, h); hudshader->set(); } - - void icon_(Texture *t, bool overlaid, int x, int y, int size, bool hit, const char *title = NULL) - { + void icon_(Texture *t, bool overlaid, int x, int y, int size, bool hit, const char *title = NULL) { float scale = float(size)/max(t->xs, t->ys); //scale and preserve aspect ratio float xs = t->xs*scale, ys = t->ys*scale; x += int((size-xs)/2); y += int((size-ys)/2); const vec &color = hit ? vec(1, 0.5f, 0.5f) : (overlaid ? vec(1, 1, 1) : light); glBindTexture(GL_TEXTURE_2D, t->id); - if(hit && actionon) - { + if(hit && actionon) { gle::colorf(0, 0, 0, 0.75f); rect_(x+SHADOW, y+SHADOW, xs, ys, 0); } gle::color(color); rect_(x, y, xs, ys, 0); - - if(overlaid) - { + if(overlaid) { if(!overlaytex) overlaytex = textureload("data/guioverlay.png", 3); glBindTexture(GL_TEXTURE_2D, overlaytex->id); gle::color(light); @@ -677,20 +550,15 @@ struct gui : g3d_gui if(title) text_(title, x + xs/12, y + ys - ys/12 - FONTH, hit ? 0xFF0000 : 0xFFFFFF, hit && actionon, hit); } } - - void previewslot(VSlot &vslot, bool overlaid, int x, int y, int size, bool hit) - { + void previewslot(VSlot &vslot, bool overlaid, int x, int y, int size, bool hit) { Slot &slot = *vslot.slot; if(slot.sts.empty()) return; VSlot *layer = NULL; Texture *t = NULL, *layertex = NULL; - if(slot.loaded) - { + if(slot.loaded) { t = slot.sts[0].t; if(t == notexture) return; - Slot &slot = *vslot.slot; - if(vslot.layer) - { + if(vslot.layer) { layer = &lookupvslot(vslot.layer); if(!layer->slot->sts.empty()) layertex = layer->slot->sts[0].t; } @@ -698,8 +566,7 @@ struct gui : g3d_gui else if(slot.thumbnail && slot.thumbnail != notexture) t = slot.thumbnail; else return; float xt = min(1.0f, t->xs/(float)t->ys), yt = min(1.0f, t->ys/(float)t->xs), xs = size, ys = size; - if(hit && actionon) - { + if(hit && actionon) { hudnotextureshader->set(); gle::colorf(0, 0, 0, 0.75f); rect_(x+SHADOW, y+SHADOW, xs, ys); @@ -711,8 +578,7 @@ struct gui : g3d_gui const vec &color = hit ? vec(1, 0.5f, 0.5f) : (overlaid ? vec(1, 1, 1) : light); vec2 tc[4] = { vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1) }; float xoff = vslot.offset.x, yoff = vslot.offset.y; - if(vslot.rotation) - { + if(vslot.rotation) { const texrotation &r = texrotations[vslot.rotation]; if(r.swapxy) { swap(xoff, yoff); loopk(4) swap(tc[k].x, tc[k].y); } if(r.flipx) { xoff *= -1; loopk(4) tc[k].x *= -1; } @@ -728,8 +594,7 @@ struct gui : g3d_gui gle::attribf(x, y+ys); gle::attrib(tc[3]); gle::attribf(x+xs, y+ys); gle::attrib(tc[2]); gle::end(); - if(layertex) - { + if(layertex) { glBindTexture(GL_TEXTURE_2D, layertex->id); gle::color(vec(color).mul(layer->colorscale)); gle::begin(GL_TRIANGLE_STRIP); @@ -739,25 +604,19 @@ struct gui : g3d_gui gle::attribf(x+xs, y+ys); gle::attrib(tc[2]); gle::end(); } - hudshader->set(); - if(overlaid) - { + if(overlaid) { if(!overlaytex) overlaytex = textureload("data/guioverlay.png", 3); glBindTexture(GL_TEXTURE_2D, overlaytex->id); gle::color(light); rect_(x, y, xs, ys, 0); } } - - void line_(int size, float percent = 1.0f) - { - if(visible()) - { + void line_(int size, float percent = 1.0f) { + if(visible()) { if(!slidertex) slidertex = textureload("data/guislider.png", 3); glBindTexture(GL_TEXTURE_2D, slidertex->id); - if(percent < 0.99f) - { + if(percent < 0.99f) { gle::colorf(light.x, light.y, light.z, 0.375f); if(ishorizontal()) rect_(curx + FONTH/2 - size/2, cury, size, ysize, 0); @@ -772,9 +631,7 @@ struct gui : g3d_gui } layout(ishorizontal() ? FONTH : 0, ishorizontal() ? 0 : FONTH); } - - void textbox(const char *text, int width, int height, int color) - { + void textbox(const char *text, int width, int height, int color) { width *= FONTW; height *= FONTH; int w, h; @@ -783,26 +640,19 @@ struct gui : g3d_gui if(visible()) draw_text(text, curx, cury, color>>16, (color>>8)&0xFF, color&0xFF, 0xFF, -1, width); layout(width, height); } - - int button_(const char *text, int color, const char *icon, bool clickable, bool center) - { + int button_(const char *text, int color, const char *icon, bool clickable, bool center) { const int padding = 10; int w = 0; if(icon) w += ICON_SIZE; if(icon && text) w += padding; if(text) w += text_width(text); - - if(visible()) - { + if(visible()) { bool hit = ishit(w, FONTH); if(hit && clickable) color = 0xFF0000; int x = curx; if(isvertical() && center) x += (xsize-w)/2; - - if(icon) - { - if(icon[0] != ' ') - { + if(icon) { + if(icon[0] != ' ') { const char *ext = strrchr(icon, '.'); defformatstring(tname, "packages/icons/%s%s", icon, ext ? "" : ".png"); icon_(textureload(tname, 3), false, x, cury, ICON_SIZE, clickable && hit); @@ -814,73 +664,57 @@ struct gui : g3d_gui } return layout(w, FONTH); } - static Texture *skintex, *overlaytex, *slidertex; static const int skinx[], skiny[]; static const struct patch { ushort left, right, top, bottom; uchar flags; } patches[]; - - static void drawskin(int x, int y, int gapw, int gaph, int start, int n, int passes = 1, const vec &light = vec(1, 1, 1), float alpha = 0.80f)//int vleft, int vright, int vtop, int vbottom, int start, int n) - { + static void drawskin(int x, int y, int gapw, int gaph, int start, int n, int passes = 1, const vec &light = vec(1, 1, 1), float alpha = 0.80f) {//int vleft, int vright, int vtop, int vbottom, int start, int n) { if(!skintex) skintex = textureload("data/guiskin.png", 3); glBindTexture(GL_TEXTURE_2D, skintex->id); int gapx1 = INT_MAX, gapy1 = INT_MAX, gapx2 = INT_MAX, gapy2 = INT_MAX; float wscale = 1.0f/(SKIN_W*SKIN_SCALE), hscale = 1.0f/(SKIN_H*SKIN_SCALE); - - loopj(passes) - { + loopj(passes) { bool quads = false; if(passes>1) glDepthFunc(j ? GL_LEQUAL : GL_GREATER); gle::color(j ? light : vec(1, 1, 1), passes<=1 || j ? alpha : alpha/2); //ghost when its behind something in depth - loopi(n) - { + loopi(n) { const patch &p = patches[start+i]; int left = skinx[p.left]*SKIN_SCALE, right = skinx[p.right]*SKIN_SCALE, top = skiny[p.top]*SKIN_SCALE, bottom = skiny[p.bottom]*SKIN_SCALE; float tleft = left*wscale, tright = right*wscale, ttop = top*hscale, tbottom = bottom*hscale; - if(p.flags&0x1) - { + if(p.flags&0x1) { gapx1 = left; gapx2 = right; } - else if(left >= gapx2) - { + else if(left >= gapx2) { left += gapw - (gapx2-gapx1); right += gapw - (gapx2-gapx1); } - if(p.flags&0x10) - { + if(p.flags&0x10) { gapy1 = top; gapy2 = bottom; } - else if(top >= gapy2) - { + else if(top >= gapy2) { top += gaph - (gapy2-gapy1); bottom += gaph - (gapy2-gapy1); } - //multiple tiled quads if necessary rather than a single stretched one int ystep = bottom-top; int yo = y+top; - while(ystep > 0) - { - if(p.flags&0x10 && yo+ystep-(y+top) > gaph) - { + while(ystep > 0) { + if(p.flags&0x10 && yo+ystep-(y+top) > gaph) { ystep = gaph+y+top-yo; tbottom = ttop+ystep*hscale; } int xstep = right-left; int xo = x+left; float tright2 = tright; - while(xstep > 0) - { - if(p.flags&0x01 && xo+xstep-(x+left) > gapw) - { + while(xstep > 0) { + if(p.flags&0x01 && xo+xstep-(x+left) > gapw) { xstep = gapw+x+left-xo; tright = tleft+xstep*wscale; } - if(!quads) - { + if(!quads) { quads = true; gle::defvertex(2); gle::deftexcoord0(); @@ -903,34 +737,26 @@ struct gui : g3d_gui } if(passes>1) glDepthFunc(GL_ALWAYS); } - vec origin, scale, *savedorigin; float dist; g3d_callback *cb; bool gui2d; - static float basescale, maxscale; static bool passthrough; static float alpha; static vec light; - - void adjustscale() - { + void adjustscale() { int w = xsize + (skinx[2]-skinx[1])*SKIN_SCALE + (skinx[10]-skinx[9])*SKIN_SCALE, h = ysize + (skiny[9]-skiny[7])*SKIN_SCALE; if(tcurrent) h += ((skiny[5]-skiny[1])-(skiny[3]-skiny[2]))*SKIN_SCALE + FONTH-2*INSERT; else h += (skiny[6]-skiny[3])*SKIN_SCALE; - float aspect = forceaspect ? 1.0f/forceaspect : float(screenh)/float(screenw), fit = 1.0f; if(w*aspect*basescale>1.0f) fit = 1.0f/(w*aspect*basescale); if(h*basescale*fit>maxscale) fit *= maxscale/(h*basescale*fit); origin = vec(0.5f-((w-xsize)/2 - (skinx[2]-skinx[1])*SKIN_SCALE)*aspect*scale.x*fit, 0.5f + (0.5f*h-(skiny[9]-skiny[7])*SKIN_SCALE)*scale.y*fit, 0); scale = vec(aspect*scale.x*fit, scale.y*fit, 1); } - - void start(int starttime, float initscale, int *tab, bool allowinput) - { - if(gui2d) - { + void start(int starttime, float initscale, int *tab, bool allowinput) { + if(gui2d) { initscale *= 0.025f; if(allowinput) hascursor = true; } @@ -946,53 +772,41 @@ struct gui : g3d_gui tcurrent = tab; tcolor = 0xFFFFFF; pushlist(); - if(layoutpass) - { + if(layoutpass) { firstlist = nextlist = curlist; memset(columns, 0, sizeof(columns)); } - else - { + else { if(tcurrent && !*tcurrent) tcurrent = NULL; cury = -ysize; curx = -xsize/2; - - if(gui2d) - { + if(gui2d) { hudmatrix.ortho(0, 1, 1, 0, -1, 1); hudmatrix.translate(origin); hudmatrix.scale(scale); - light = vec(1, 1, 1); } - else - { + else { float yaw = atan2f(origin.y-camera1->o.y, origin.x-camera1->o.x); hudmatrix = camprojmatrix; hudmatrix.translate(origin); hudmatrix.rotate_around_z(yaw - 90*RAD); hudmatrix.rotate_around_x(-90*RAD); hudmatrix.scale(-scale.x, scale.y, scale.z); - vec dir; lightreaching(origin, light, dir, false, 0, 0.5f); float intensity = vec(yaw, 0.0f).dot(dir); light.mul(1.0f + max(intensity, 0.0f)); } - resethudmatrix(); hudshader->set(); - drawskin(curx-skinx[2]*SKIN_SCALE, cury-skiny[6]*SKIN_SCALE, xsize, ysize, 0, 9, gui2d ? 1 : 2, light, alpha); if(!tcurrent) drawskin(curx-skinx[5]*SKIN_SCALE, cury-skiny[6]*SKIN_SCALE, xsize, 0, 9, 1, gui2d ? 1 : 2, light, alpha); } } - - void adjusthorizontalcolumn(int col, int i) - { + void adjusthorizontalcolumn(int col, int i) { int h = columns[col], dh = 0; - for(int d = 1; i >= 0; d ^= 1) - { + for(int d = 1; i >= 0; d ^= 1) { list &p = lists[i]; if(d&1) { dh = h - p.h; if(dh <= 0) break; p.h = h; } else { p.h += dh; h = p.h; } @@ -1000,12 +814,9 @@ struct gui : g3d_gui } ysize += max(dh, 0); } - - void adjustverticalcolumn(int col, int i) - { + void adjustverticalcolumn(int col, int i) { int w = columns[col], dw = 0; - for(int d = 0; i >= 0; d ^= 1) - { + for(int d = 0; i >= 0; d ^= 1) { list &p = lists[i]; if(d&1) { p.w += dw; w = p.w; } else { dw = w - p.w; if(dw <= 0) break; p.w = w; } @@ -1013,59 +824,45 @@ struct gui : g3d_gui } xsize = max(xsize, w); } - - void adjustcolumns() - { - if(lists.inrange(curlist)) - { + void adjustcolumns() { + if(lists.inrange(curlist)) { list &l = lists[curlist]; if(l.column >= 0) columns[l.column] = max(columns[l.column], ishorizontal() ? ysize : xsize); } int parent = -1, depth = 0; - for(int i = firstlist; i < lists.length(); i++) - { + for(int i = firstlist; i < lists.length(); i++) { list &l = lists[i]; if(l.parent > parent) { parent = l.parent; depth++; } - else if(l.parent < parent) - { - while(parent > l.parent && depth > 0) - { + else if(l.parent < parent) { + while(parent > l.parent && depth > 0) { parent = lists[parent].parent; depth--; } } - if(l.column >= 0) - { + if(l.column >= 0) { if(depth&1) adjusthorizontalcolumn(l.column, i); else adjustverticalcolumn(l.column, i); } } } - - void end() - { - if(layoutpass) - { + void end() { + if(layoutpass) { adjustcolumns(); xsize = max(tx, xsize); ysize = max(ty, ysize); ysize = max(ysize, (skiny[7]-skiny[6])*SKIN_SCALE); if(tcurrent) *tcurrent = max(1, min(*tcurrent, tpos)); if(gui2d) adjustscale(); - if(!windowhit && !passthrough) - { + if(!windowhit && !passthrough) { float dist = 0; - if(gui2d) - { + if(gui2d) { hitx = (cursorx - origin.x)/scale.x; hity = (cursory - origin.y)/scale.y; } - else - { + else { plane p; p.toplane(vec(origin).sub(camera1->o).set(2, 0).normalize(), origin); - if(p.rayintersect(camera1->o, camdir, dist) && dist>=0) - { + if(p.rayintersect(camera1->o, camdir, dist) && dist>=0) { vec hitpos(camdir); hitpos.mul(dist).add(camera1->o).sub(origin); hitx = vec(-p.y, p.x, 0).dot(hitpos)/scale.x; @@ -1073,22 +870,18 @@ struct gui : g3d_gui } } if((mousebuttons & G3D_PRESSED) && (fabs(hitx-firstx) > 2 || fabs(hity - firsty) > 2)) mousebuttons |= G3D_DRAGGED; - if(dist>=0 && hitx>=-xsize/2 && hitx<=xsize/2 && hity<=0) - { + if(dist>=0 && hitx>=-xsize/2 && hitx<=xsize/2 && hity<=0) { if(hity>=-ysize || (tcurrent && hity>=-ysize-(FONTH-2*INSERT)-((skiny[6]-skiny[1])-(skiny[3]-skiny[2]))*SKIN_SCALE && hitx<=tx-xsize/2)) windowhit = this; } } } - else - { + else { if(tcurrent && tx<xsize) drawskin(curx+tx-skinx[5]*SKIN_SCALE, -ysize-skiny[6]*SKIN_SCALE, xsize-tx, FONTH, 9, 1, gui2d ? 1 : 2, light, alpha); } poplist(); } - - void draw() - { + void draw() { cb->gui(*this, layoutpass); } }; @@ -1097,44 +890,39 @@ Texture *gui::skintex = NULL, *gui::overlaytex = NULL, *gui::slidertex = NULL; //chop skin into a grid const int gui::skiny[] = {0, 7, 21, 34, 43, 48, 56, 104, 111, 117, 128}, - gui::skinx[] = {0, 11, 23, 37, 105, 119, 137, 151, 215, 229, 246, 256}; + gui::skinx[] = {0, 11, 23, 37, 105, 119, 137, 151, 215, 229, 246, 256}; //Note: skinx[3]-skinx[2] = skinx[7]-skinx[6] // skinx[5]-skinx[4] = skinx[9]-skinx[8] -const gui::patch gui::patches[] = -{ //arguably this data can be compressed - it depends on what else needs to be skinned in the future - {1,2,3,6, 0}, // body - {2,9,5,6, 0x01}, - {9,10,3,6, 0}, - - {1,2,6,7, 0x10}, - {2,9,6,7, 0x11}, - {9,10,6,7, 0x10}, - - {1,2,7,9, 0}, - {2,9,7,9, 0x01}, - {9,10,7,9, 0}, - - {5,6,3,5, 0x01}, // top - - {2,3,1,2, 0}, // selected tab - {3,4,1,2, 0x01}, - {4,5,1,2, 0}, - {2,3,2,3, 0x10}, - {3,4,2,3, 0x11}, - {4,5,2,3, 0x10}, - {2,3,3,5, 0}, - {3,4,3,5, 0x01}, - {4,5,3,5, 0}, - - {6,7,1,2, 0}, // deselected tab - {7,8,1,2, 0x01}, - {8,9,1,2, 0}, - {6,7,2,3, 0x10}, - {7,8,2,3, 0x11}, - {8,9,2,3, 0x10}, - {6,7,3,5, 0}, - {7,8,3,5, 0x01}, - {8,9,3,5, 0}, +const gui::patch gui::patches[] = { + //arguably this data can be compressed - it depends on what else needs to be skinned in the future { + { 1,2,3,6, 0}, // body { + { 2,9,5,6, 0x01}, + { 9,10,3,6, 0}, + { 1,2,6,7, 0x10}, + { 2,9,6,7, 0x11}, + { 9,10,6,7, 0x10}, + { 1,2,7,9, 0}, + { 2,9,7,9, 0x01}, + { 9,10,7,9, 0}, + { 5,6,3,5, 0x01}, // top + { 2,3,1,2, 0}, // selected tab { + { 3,4,1,2, 0x01}, + { 4,5,1,2, 0}, + { 2,3,2,3, 0x10}, + { 3,4,2,3, 0x11}, + { 4,5,2,3, 0x10}, + { 2,3,3,5, 0}, + { 3,4,3,5, 0x01}, + { 4,5,3,5, 0}, + { 6,7,1,2, 0}, // deselected tab { + { 7,8,1,2, 0x01}, + { 8,9,1,2, 0}, + { 6,7,2,3, 0x10}, + { 7,8,2,3, 0x11}, + { 8,9,2,3, 0x10}, + { 6,7,3,5, 0}, + { 7,8,3,5, 0x01}, + { 8,9,3,5, 0}, }; vector<gui::list> gui::lists; @@ -1147,53 +935,40 @@ static vector<gui> guis2d, guis3d; VARP(guipushdist, 1, 4, 64); -bool g3d_input(const char *str, int len) -{ +bool g3d_input(const char *str, int len) { editor *e = currentfocus(); if(fieldmode == FIELDKEY || fieldmode == FIELDSHOW || !e) return false; - e->input(str, len); return true; } -bool g3d_key(int code, bool isdown) -{ +bool g3d_key(int code, bool isdown) { editor *e = currentfocus(); - if(fieldmode == FIELDKEY) - { - switch(code) - { + if(fieldmode == FIELDKEY) { + switch(code) { case SDLK_ESCAPE: if(isdown) fieldmode = FIELDCOMMIT; return true; } const char *keyname = getkeyname(code); - if(keyname && isdown) - { + if(keyname && isdown) { if(e->lines.length()!=1 || !e->lines[0].empty()) e->insert(" "); e->insert(keyname); } return true; } - if(code==-1 && g3d_windowhit(isdown, true)) return true; else if(code==-3 && g3d_windowhit(isdown, false)) return true; - - if(fieldmode == FIELDSHOW || !e) - { - if(windowhit) switch(code) - { + if(fieldmode == FIELDSHOW || !e) { + if(windowhit) switch(code) { case -4: // window "management" - if(isdown) - { - if(windowhit->gui2d) - { + if(isdown) { + if(windowhit->gui2d) { vec origin = *guis2d.last().savedorigin; int i = windowhit - &guis2d[0]; for(int j = guis2d.length()-1; j > i; j--) *guis2d[j].savedorigin = *guis2d[j-1].savedorigin; *windowhit->savedorigin = origin; - if(guis2d.length() > 1) - { + if(guis2d.length() > 1) { if(camera1->o.dist(*windowhit->savedorigin) <= camera1->o.dist(*guis2d.last().savedorigin)) windowhit->savedorigin->add(camdir); } @@ -1202,15 +977,12 @@ bool g3d_key(int code, bool isdown) } return true; case -5: - if(isdown) - { - if(windowhit->gui2d) - { + if(isdown) { + if(windowhit->gui2d) { vec origin = *guis2d[0].savedorigin; loopj(guis2d.length()-1) *guis2d[j].savedorigin = *guis2d[j + 1].savedorigin; *guis2d.last().savedorigin = origin; - if(guis2d.length() > 1) - { + if(guis2d.length() > 1) { if(camera1->o.dist(*guis2d.last().savedorigin) >= camera1->o.dist(*guis2d[0].savedorigin)) guis2d.last().savedorigin->sub(camdir); } @@ -1219,11 +991,9 @@ bool g3d_key(int code, bool isdown) } return true; } - return false; } - switch(code) - { + switch(code) { case SDLK_ESCAPE: //cancel editing without commit if(isdown) fieldmode = FIELDABORT; return true; @@ -1240,21 +1010,18 @@ bool g3d_key(int code, bool isdown) return true; } -void g3d_cursorpos(float &x, float &y) -{ +void g3d_cursorpos(float &x, float &y) { if(guis2d.length()) { x = cursorx; y = cursory; } else x = y = 0.5f; } -void g3d_resetcursor() -{ +void g3d_resetcursor() { cursorx = cursory = 0.5f; } FVARP(guisens, 1e-3f, 1, 1e3f); -bool g3d_movecursor(int dx, int dy) -{ +bool g3d_movecursor(int dx, int dy) { if(!guis2d.length() || !hascursor) return false; const float CURSORSCALE = 500.0f; cursorx = max(0.0f, min(1.0f, cursorx+guisens*dx*(screenh/(screenw*CURSORSCALE)))); @@ -1265,8 +1032,7 @@ bool g3d_movecursor(int dx, int dy) VARNP(guifollow, useguifollow, 0, 1, 1); VARNP(gui2d, usegui2d, 0, 1, 1); -void g3d_addgui(g3d_callback *cb, vec &origin, int flags) -{ +void g3d_addgui(g3d_callback *cb, vec &origin, int flags) { bool gui2d = flags&GUI_FORCE_2D || (flags&GUI_2D && usegui2d) || mainmenu; if(!gui2d && flags&GUI_FOLLOW && useguifollow) origin.z = player->o.z-(player->eyeheight-1); gui &g = (gui2d ? guis2d : guis3d).add(); @@ -1277,20 +1043,16 @@ void g3d_addgui(g3d_callback *cb, vec &origin, int flags) g.gui2d = gui2d; } -void g3d_limitscale(float scale) -{ +void g3d_limitscale(float scale) { gui::maxscale = scale; } static inline bool g3d_sort(const gui &a, const gui &b) { return a.dist < b.dist; } -bool g3d_windowhit(bool on, bool act) -{ +bool g3d_windowhit(bool on, bool act) { extern int cleargui(int n); - if(act) - { - if(actionon || windowhit) - { + if(act) { + if(actionon || windowhit) { if(on) { firstx = gui::hitx; firsty = gui::hity; } mousebuttons |= (actionon=on) ? G3D_DOWN : G3D_UP; } @@ -1298,76 +1060,55 @@ bool g3d_windowhit(bool on, bool act) return (guis2d.length() && hascursor) || (windowhit && !windowhit->gui2d); } -void g3d_render() -{ +void g3d_render() { windowhit = NULL; if(actionon) mousebuttons |= G3D_PRESSED; - gui::reset(); guis2d.shrink(0); guis3d.shrink(0); - // call all places in the engine that may want to render a gui from here, they call g3d_addgui() extern void g3d_texturemenu(); - if(!mainmenu) g3d_texturemenu(); g3d_mainmenu(); if(!mainmenu) game::g3d_gamemenus(); - guis2d.sort(g3d_sort); guis3d.sort(g3d_sort); - readyeditors(); fieldsactive = false; - hascursor = false; - layoutpass = true; loopv(guis2d) guis2d[i].draw(); loopv(guis3d) guis3d[i].draw(); layoutpass = false; - - if(guis3d.length()) - { + if(guis3d.length()) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); glDepthMask(GL_FALSE); - loopvrev(guis3d) guis3d[i].draw(); - glDepthFunc(GL_LESS); glDepthMask(GL_TRUE); glDisable(GL_DEPTH_TEST); - glDisable(GL_BLEND); } } -void g3d_render2d() -{ - if(guis2d.length()) - { +void g3d_render2d() { + if(guis2d.length()) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - loopvrev(guis2d) guis2d[i].draw(); - glDisable(GL_BLEND); } - flusheditors(); if(!fieldsactive) fieldmode = FIELDSHOW; //didn't draw any fields, so lose focus - mainly for menu closed textinput(fieldmode!=FIELDSHOW, TI_GUI); keyrepeat(fieldmode!=FIELDSHOW, KR_GUI); - mousebuttons = 0; } -void consolebox(int x1, int y1, int x2, int y2) -{ +void consolebox(int x1, int y1, int x2, int y2) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); float bw = x2 - x1, bh = y2 - y1, aspect = bw/bh, sh = bh, sw = sh*aspect; bw *= float(4*FONTH)/(SKIN_H*SKIN_SCALE); diff --git a/src/engine/animmodel.h b/src/engine/animmodel.h index 13705f4..51d09e8 100644 --- a/src/engine/animmodel.h +++ b/src/engine/animmodel.h @@ -1,93 +1,66 @@ -VARFP(bumpmodels, 0, 1, 1, preloadmodelshaders(true)); +VARFP(bumpmodels, 0, 1, 1, preloadmodelshaders()); VARP(fullbrightmodels, 0, 0, 200); -struct animmodel : model -{ - struct animspec - { +struct animmodel : model { + struct animspec { int frame, range; float speed; int priority; }; - - struct animpos - { + struct animpos { int anim, fr1, fr2; float t; - - void setframes(const animinfo &info) - { + void setframes(const animinfo &info) { anim = info.anim; - if(info.range<=1) - { + if(info.range<=1) { fr1 = 0; t = 0; } - else - { + else { int time = info.anim&ANIM_SETTIME ? info.basetime : lastmillis-info.basetime; fr1 = (int)(time/info.speed); // round to full frames t = (time-fr1*info.speed)/info.speed; // progress of the frame, value from 0.0f to 1.0f } - if(info.anim&ANIM_LOOP) - { + if(info.anim&ANIM_LOOP) { fr1 = fr1%info.range+info.frame; fr2 = fr1+1; if(fr2>=info.frame+info.range) fr2 = info.frame; } - else - { + else { fr1 = min(fr1, info.range-1)+info.frame; fr2 = min(fr1+1, info.frame+info.range-1); } - if(info.anim&ANIM_REVERSE) - { + if(info.anim&ANIM_REVERSE) { fr1 = (info.frame+info.range-1)-(fr1-info.frame); fr2 = (info.frame+info.range-1)-(fr2-info.frame); } } - bool operator==(const animpos &a) const { return fr1==a.fr1 && fr2==a.fr2 && (fr1==fr2 || t==a.t); } bool operator!=(const animpos &a) const { return fr1!=a.fr1 || fr2!=a.fr2 || (fr1!=fr2 && t!=a.t); } }; - struct part; - - struct animstate - { + struct animstate { part *owner; animpos cur, prev; float interp; - bool operator==(const animstate &a) const { return cur==a.cur && (interp<1 ? interp==a.interp && prev==a.prev : a.interp>=1); } bool operator!=(const animstate &a) const { return cur!=a.cur || (interp<1 ? interp!=a.interp || prev!=a.prev : a.interp<1); } }; - struct linkedpart; struct mesh; - - struct shaderparams - { + struct shaderparams { float spec, ambient, fullbright, scrollu, scrollv, alphatest; - shaderparams() : spec(1.0f), ambient(0.3f), fullbright(0), scrollu(0), scrollv(0), alphatest(0.9f) {} }; - - struct shaderparamskey - { + struct shaderparamskey { static hashtable<shaderparams, shaderparamskey> keys; static int firstversion, lastversion; - int version; - shaderparamskey() : version(-1) {} - - bool checkversion() - { + bool checkversion() { if(version >= firstversion) return true; version = lastversion; - if(++lastversion <= 0) - { + if(++lastversion <= 0) { enumerate(keys, shaderparamskey, key, key.version = -1); firstversion = 0; lastversion = 1; @@ -95,67 +68,47 @@ struct animmodel : model } return false; } - - static inline void invalidate() - { + static inline void invalidate() { firstversion = lastversion; } }; - - struct skin : shaderparams - { + struct skin : shaderparams { part *owner; Texture *tex, *masks, *normalmap; Shader *shader; bool alphablend, cullface; shaderparamskey *key; - skin() : owner(0), tex(notexture), masks(notexture), normalmap(NULL), shader(NULL), alphablend(true), cullface(true), key(NULL) {} - bool masked() const { return masks != notexture; } bool bumpmapped() { return normalmap && bumpmodels; } bool tangents() { return bumpmapped(); } bool alphatested() const { return alphatest > 0 && tex->type&Texture::ALPHA; } - - void setkey() - { + void setkey() { key = &shaderparamskey::keys[*this]; } - - void setshaderparams(mesh *m, const animstate *as) - { + void setshaderparams(mesh *m, const animstate *as) { if(!Shader::lastshader) return; - float mincolor = as->cur.anim&ANIM_FULLBRIGHT ? fullbrightmodels/100.0f : 0.0f; - if(fullbright) - { + if(fullbright) { gle::colorf(fullbright/2, fullbright/2, fullbright/2, transparent); } - else - { + else { gle::color(vec(lightcolor).max(mincolor), transparent); } - if(key->checkversion() && Shader::lastshader->owner == key) return; Shader::lastshader->owner = key; - if(alphatested()) LOCALPARAMF(alphatest, alphatest); - - if(fullbright) - { + if(fullbright) { LOCALPARAMF(lightscale, 0, 0, 2); } - else - { + else { float bias = max(mincolor-1.0f, 0.2f), scale = 0.5f*max(0.8f-bias, 0.0f), minshade = scale*max(ambient, mincolor); LOCALPARAMF(lightscale, scale - minshade, scale, minshade + bias); } LOCALPARAMF(texscroll, scrollu*lastmillis/1000.0f, scrollv*lastmillis/1000.0f); } - - Shader *loadshader() - { + Shader *loadshader() { #define DOMODELSHADER(name, body) \ do { \ static Shader *name##shader = NULL; \ @@ -165,7 +118,6 @@ struct animmodel : model #define LOADMODELSHADER(name) DOMODELSHADER(name, return name##shader) #define SETMODELSHADER(m, name) DOMODELSHADER(name, (m)->setshader(name##shader)) if(shader) return shader; - string opts; int optslen = 0; if(alphatested()) opts[optslen++] = 'a'; @@ -174,40 +126,27 @@ struct animmodel : model if(masked()) opts[optslen++] = 'm'; if(!fullbright && (masked() || spec>=0.01f)) opts[optslen++] = 's'; opts[optslen++] = '\0'; - defformatstring(name, "model%s", opts); shader = generateshader(name, "modelshader \"%s\"", opts); return shader; } - - void cleanup() - { + void cleanup() { if(shader && shader->standard) shader = NULL; } - - void preloadBIH() - { + void preloadBIH() { if(tex->type&Texture::ALPHA && !tex->alphamask) loadalphamask(tex); } - - void preloadshader(bool force) - { - if(force) cleanup(); + void preloadshader() { + //~if(force) cleanup(); loadshader(); } - - void setshader(mesh *m, const animstate *as) - { + void setshader(mesh *m, const animstate *as) { m->setshader(loadshader()); } - - void bind(mesh *b, const animstate *as) - { + void bind(mesh *b, const animstate *as) { if(!cullface && enablecullface) { glDisable(GL_CULL_FACE); enablecullface = false; } else if(cullface && !enablecullface) { glEnable(GL_CULL_FACE); enablecullface = true; } - - if(as->cur.anim&ANIM_NOSKIN) - { + if(as->cur.anim&ANIM_NOSKIN) { if(enablealphablend) { glDisable(GL_BLEND); enablealphablend = false; } if(shadowmapping) SETMODELSHADER(b, shadowmapcaster); else /*if(as->cur.anim&ANIM_SHADOW)*/ SETMODELSHADER(b, notexturemodel); @@ -216,24 +155,19 @@ struct animmodel : model setshader(b, as); setshaderparams(b, as); int activetmu = 0; - if(tex!=lasttex) - { + if(tex!=lasttex) { glBindTexture(GL_TEXTURE_2D, tex->id); lasttex = tex; } - if(bumpmapped() && normalmap !=lastnormalmap) - { + if(bumpmapped() && normalmap !=lastnormalmap) { glActiveTexture_(GL_TEXTURE3); activetmu = 3; glBindTexture(GL_TEXTURE_2D, normalmap->id); lastnormalmap = normalmap; } - if(tex->type&Texture::ALPHA) - { - if(alphablend) - { - if(!enablealphablend) - { + if(tex->type&Texture::ALPHA) { + if(alphablend) { + if(!enablealphablend) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); enablealphablend = true; @@ -242,8 +176,7 @@ struct animmodel : model else if(enablealphablend) { glDisable(GL_BLEND); enablealphablend = false; } } else if(enablealphablend && transparent>=1) { glDisable(GL_BLEND); enablealphablend = false; } - if(masked() && masks!=lastmasks) - { + if(masked() && masks!=lastmasks) { glActiveTexture_(GL_TEXTURE1); activetmu = 1; glBindTexture(GL_TEXTURE_2D, masks->id); @@ -252,29 +185,19 @@ struct animmodel : model if(activetmu != 0) glActiveTexture_(GL_TEXTURE0); } }; - struct meshgroup; - - struct mesh - { + struct mesh { meshgroup *group; char *name; bool noclip; - - mesh() : group(NULL), name(NULL), noclip(false) - { + mesh() : group(NULL), name(NULL), noclip(false) { } - - virtual ~mesh() - { + virtual ~mesh() { DELETEA(name); } - virtual void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) {} - virtual void genBIH(BIH::mesh &m) {} - void genBIH(skin &s, vector<BIH::mesh> &bih, const matrix4x3 &t) - { + void genBIH(skin &s, vector<BIH::mesh> &bih, const matrix4x3 &t) { BIH::mesh &m = bih.add(); m.xform = t; m.tex = s.tex; @@ -282,35 +205,28 @@ struct animmodel : model if(noclip) m.flags |= BIH::MESH_NOCLIP; if(s.cullface) m.flags |= BIH::MESH_CULLFACE; genBIH(m); - while(bih.last().numtris > BIH::mesh::MAXTRIS) - { + while(bih.last().numtris > BIH::mesh::MAXTRIS) { BIH::mesh &overflow = bih.dup(); overflow.tris += BIH::mesh::MAXTRIS; overflow.numtris -= BIH::mesh::MAXTRIS; bih[bih.length()-2].numtris = BIH::mesh::MAXTRIS; } } - - virtual void setshader(Shader *s) - { + virtual void setshader(Shader *s) { s->set(); } - - template<class V, class T> void smoothnorms(V *verts, int numverts, T *tris, int numtris, float limit, bool areaweight) - { + template<class V, class T> void smoothnorms(V *verts, int numverts, T *tris, int numtris, float limit, bool areaweight) { hashtable<vec, int> share; int *next = new int[numverts]; for(int i=0;i<numverts;++i)next[i]=-1; //~memset(next, -1, numverts*sizeof(int)); - loopi(numverts) - { + loopi(numverts) { V &v = verts[i]; v.norm = vec(0, 0, 0); int idx = share.access(v.pos, i); if(idx != i) { next[i] = next[idx]; next[idx] = i; } } - loopi(numtris) - { + loopi(numtris) { T &t = tris[i]; V &v1 = verts[t.vert[0]], &v2 = verts[t.vert[1]], &v3 = verts[t.vert[2]]; vec norm; @@ -323,18 +239,14 @@ struct animmodel : model vec *norms = new vec[numverts]; for(int i=0;i<numverts;++i)norms[i]=vec(0,0,0); //~memclear(norms, numverts); - loopi(numverts) - { + loopi(numverts) { V &v = verts[i]; norms[i].add(v.norm); - if(next[i] >= 0) - { + if(next[i] >= 0) { float vlimit = limit*v.norm.magnitude(); - for(int j = next[i]; j >= 0; j = next[j]) - { + for(int j = next[i]; j >= 0; j = next[j]) { V &o = verts[j]; - if(v.norm.dot(o.norm) >= vlimit*o.norm.magnitude()) - { + if(v.norm.dot(o.norm) >= vlimit*o.norm.magnitude()) { norms[i].add(o.norm); norms[j].add(v.norm); } @@ -345,12 +257,9 @@ struct animmodel : model delete[] next; delete[] norms; } - - template<class V, class T> void buildnorms(V *verts, int numverts, T *tris, int numtris, bool areaweight) - { + template<class V, class T> void buildnorms(V *verts, int numverts, T *tris, int numtris, bool areaweight) { loopi(numverts) verts[i].norm = vec(0, 0, 0); - loopi(numtris) - { + loopi(numtris) { T &t = tris[i]; V &v1 = verts[t.vert[0]], &v2 = verts[t.vert[1]], &v3 = verts[t.vert[2]]; vec norm; @@ -362,26 +271,19 @@ struct animmodel : model } loopi(numverts) verts[i].norm.normalize(); } - - template<class V, class T> void buildnorms(V *verts, int numverts, T *tris, int numtris, bool areaweight, int numframes) - { + template<class V, class T> void buildnorms(V *verts, int numverts, T *tris, int numtris, bool areaweight, int numframes) { if(!numverts) return; loopi(numframes) buildnorms(&verts[i*numverts], numverts, tris, numtris, areaweight); } - - static inline void fixqtangent(quat &q, float bt) - { + static inline void fixqtangent(quat &q, float bt) { static const float bias = -1.5f/65535, biasscale = sqrtf(1 - bias*bias); - if(bt < 0) - { + if(bt < 0) { if(q.w >= 0) q.neg(); if(q.w > bias) { q.mul3(biasscale); q.w = bias; } } else if(q.w < 0) q.neg(); } - - template<class V> static inline void calctangent(V &v, const vec &n, const vec &t, float bt) - { + template<class V> static inline void calctangent(V &v, const vec &n, const vec &t, float bt) { matrix3 m; m.c = n; m.a = t; @@ -390,18 +292,14 @@ struct animmodel : model fixqtangent(q, bt); v.tangent = q; } - - template<class B, class V, class TC, class T> void calctangents(B *bumpverts, V *verts, TC *tcverts, int numverts, T *tris, int numtris, bool areaweight) - { + template<class B, class V, class TC, class T> void calctangents(B *bumpverts, V *verts, TC *tcverts, int numverts, T *tris, int numtris, bool areaweight) { vec *tangent = new vec[2*numverts], *bitangent = tangent+numverts; for(int i=0;i<2*numverts;++i)tangent[i]=vec(0,0,0); //~memclear(tangent, 2*numverts); - loopi(numtris) - { + loopi(numtris) { const T &t = tris[i]; const vec &e0 = verts[t.vert[0]].pos; vec e1 = vec(verts[t.vert[1]].pos).sub(e0), e2 = vec(verts[t.vert[2]].pos).sub(e0); - const vec2 &tc0 = tcverts[t.vert[0]].tc, &tc1 = tcverts[t.vert[1]].tc, &tc2 = tcverts[t.vert[2]].tc; @@ -410,27 +308,20 @@ struct animmodel : model vec u(e2), v(e2); u.mul(v1).sub(vec(e1).mul(v2)); v.mul(u1).sub(vec(e1).mul(u2)); - - if(vec().cross(e2, e1).dot(vec().cross(v, u)) >= 0) - { + if(vec().cross(e2, e1).dot(vec().cross(v, u)) >= 0) { u.neg(); v.neg(); } - - if(!areaweight) - { + if(!areaweight) { u.normalize(); v.normalize(); } - - loopj(3) - { + loopj(3) { tangent[t.vert[j]].sub(u); bitangent[t.vert[j]].add(v); } } - loopi(numverts) - { + loopi(numverts) { const vec &n = verts[i].norm, &t = tangent[i], &bt = bitangent[i]; @@ -445,136 +336,97 @@ struct animmodel : model } delete[] tangent; } - - template<class B, class V, class TC, class T> void calctangents(B *bumpverts, V *verts, TC *tcverts, int numverts, T *tris, int numtris, bool areaweight, int numframes) - { + template<class B, class V, class TC, class T> void calctangents(B *bumpverts, V *verts, TC *tcverts, int numverts, T *tris, int numtris, bool areaweight, int numframes) { loopi(numframes) calctangents(&bumpverts[i*numverts], &verts[i*numverts], tcverts, numverts, tris, numtris, areaweight); } }; - - struct meshgroup - { + struct meshgroup { meshgroup *next; int shared; char *name; vector<mesh *> meshes; - - meshgroup() : next(NULL), shared(0), name(NULL) - { + meshgroup() : next(NULL), shared(0), name(NULL) { } - - virtual ~meshgroup() - { + virtual ~meshgroup() { DELETEA(name); meshes.deletecontents(); DELETEP(next); } - virtual int findtag(const char *name) { return -1; } virtual void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) {} - - void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) - { + void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) { loopv(meshes) meshes[i]->calcbb(bbmin, bbmax, m); } - - void genBIH(vector<skin> &skins, vector<BIH::mesh> &bih, const matrix4x3 &t) - { + void genBIH(vector<skin> &skins, vector<BIH::mesh> &bih, const matrix4x3 &t) { loopv(meshes) meshes[i]->genBIH(skins[i], bih, t); } - virtual void *animkey() { return this; } virtual int totalframes() const { return 1; } bool hasframe(int i) const { return i>=0 && i<totalframes(); } bool hasframes(int i, int n) const { return i>=0 && i+n<=totalframes(); } int clipframes(int i, int n) const { return min(n, totalframes() - i); } - virtual void cleanup() {} virtual void preload(part *p) {} virtual void render(const animstate *as, float pitch, const vec &axis, const vec &forward, dynent *d, part *p) {} - - void bindpos(GLuint ebuf, GLuint vbuf, void *v, int stride) - { - if(lastebuf!=ebuf) - { + void bindpos(GLuint ebuf, GLuint vbuf, void *v, int stride) { + if(lastebuf!=ebuf) { gle::bindebo(ebuf); lastebuf = ebuf; } - if(lastvbuf!=vbuf) - { + if(lastvbuf!=vbuf) { gle::bindvbo(vbuf); if(!lastvbuf) gle::enablevertex(); gle::vertexpointer(stride, v); lastvbuf = vbuf; } } - - void bindtc(void *v, int stride) - { - if(!enabletc) - { + void bindtc(void *v, int stride) { + if(!enabletc) { gle::enabletexcoord0(); enabletc = true; } - if(lasttcbuf!=lastvbuf) - { + if(lasttcbuf!=lastvbuf) { gle::texcoord0pointer(stride, v); lasttcbuf = lastvbuf; } } - - void bindnormals(void *v, int stride) - { - if(!enablenormals) - { + void bindnormals(void *v, int stride) { + if(!enablenormals) { gle::enablenormal(); enablenormals = true; } - if(lastnbuf!=lastvbuf) - { + if(lastnbuf!=lastvbuf) { gle::normalpointer(stride, v); lastnbuf = lastvbuf; } } - - void bindtangents(void *v, int stride) - { - if(!enabletangents) - { + void bindtangents(void *v, int stride) { + if(!enabletangents) { gle::enabletangent(); enabletangents = true; } - if(lastxbuf!=lastvbuf) - { + if(lastxbuf!=lastvbuf) { gle::tangentpointer(stride, v, GL_SHORT); lastxbuf = lastvbuf; } } - - void bindbones(void *wv, void *bv, int stride) - { - if(!enablebones) - { + void bindbones(void *wv, void *bv, int stride) { + if(!enablebones) { gle::enableboneweight(); gle::enableboneindex(); enablebones = true; } - if(lastbbuf!=lastvbuf) - { + if(lastbbuf!=lastvbuf) { gle::boneweightpointer(stride, wv); gle::boneindexpointer(stride, bv); lastbbuf = lastvbuf; } } }; - virtual meshgroup *loadmeshes(const char *name, va_list args) { return NULL; } - - meshgroup *sharemeshes(const char *name, ...) - { + meshgroup *sharemeshes(const char *name, ...) { static hashnameset<meshgroup *> meshgroups; - if(!meshgroups.access(name)) - { + if(!meshgroups.access(name)) { va_list args; va_start(args, name); meshgroup *group = loadmeshes(name, args); @@ -584,20 +436,15 @@ struct animmodel : model } return meshgroups[name]; } - - struct linkedpart - { + struct linkedpart { part *p; int tag, anim, basetime; vec translate; vec *pos; matrix4 matrix; - linkedpart() : p(NULL), tag(-1), anim(-1), basetime(0), translate(0, 0, 0), pos(NULL) {} }; - - struct part - { + struct part { animmodel *model; int index; meshgroup *meshes; @@ -607,57 +454,43 @@ struct animmodel : model int numanimparts; float pitchscale, pitchoffset, pitchmin, pitchmax; vec translate; - - part(animmodel *model, int index = 0) : model(model), index(index), meshes(NULL), numanimparts(1), pitchscale(1), pitchoffset(0), pitchmin(0), pitchmax(0), translate(0, 0, 0) - { + part(animmodel *model, int index = 0) : model(model), index(index), meshes(NULL), numanimparts(1), pitchscale(1), pitchoffset(0), pitchmin(0), pitchmax(0), translate(0, 0, 0) { loopk(MAXANIMPARTS) anims[k] = NULL; } - virtual ~part() - { + virtual ~part() { loopk(MAXANIMPARTS) DELETEA(anims[k]); } - - virtual void cleanup() - { + virtual void cleanup() { if(meshes) meshes->cleanup(); loopv(skins) skins[i].cleanup(); } - - void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) - { + void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) { matrix4x3 t = m; t.scale(model->scale); t.translate(translate); meshes->calcbb(bbmin, bbmax, t); - loopv(links) - { + loopv(links) { matrix4x3 n; meshes->concattagtransform(this, links[i].tag, m, n); n.translate(links[i].translate, model->scale); links[i].p->calcbb(bbmin, bbmax, n); } } - - void genBIH(vector<BIH::mesh> &bih, const matrix4x3 &m) - { + void genBIH(vector<BIH::mesh> &bih, const matrix4x3 &m) { matrix4x3 t = m; t.scale(model->scale); t.translate(translate); meshes->genBIH(skins, bih, t); - loopv(links) - { + loopv(links) { matrix4x3 n; meshes->concattagtransform(this, links[i].tag, m, n); n.translate(links[i].translate, model->scale); links[i].p->genBIH(bih, n); } } - - bool link(part *p, const char *tag, const vec &translate = vec(0, 0, 0), int anim = -1, int basetime = 0, vec *pos = NULL) - { + bool link(part *p, const char *tag, const vec &translate = vec(0, 0, 0), int anim = -1, int basetime = 0, vec *pos = NULL) { int i = meshes ? meshes->findtag(tag) : -1; - if(i<0) - { + if(i<0) { loopv(links) if(links[i].p && links[i].p->link(p, tag, translate, anim, basetime, pos)) return true; return false; } @@ -670,86 +503,62 @@ struct animmodel : model l.pos = pos; return true; } - - bool unlink(part *p) - { + bool unlink(part *p) { loopvrev(links) if(links[i].p==p) { links.remove(i, 1); return true; } loopv(links) if(links[i].p && links[i].p->unlink(p)) return true; return false; } - - void initskins(Texture *tex = notexture, Texture *masks = notexture, int limit = 0) - { - if(!limit) - { + void initskins(Texture *tex = notexture, Texture *masks = notexture, int limit = 0) { + if(!limit) { if(!meshes) return; limit = meshes->meshes.length(); } - while(skins.length() < limit) - { + while(skins.length() < limit) { skin &s = skins.add(); s.owner = this; s.tex = tex; s.masks = masks; } } - - bool tangents() - { + bool tangents() { loopv(skins) if(skins[i].tangents()) return true; return false; } - - void preloadBIH() - { + void preloadBIH() { loopv(skins) skins[i].preloadBIH(); } - - void preloadshaders(bool force) - { - loopv(skins) skins[i].preloadshader(force); + void preloadshaders() { + loopv(skins) skins[i].preloadshader(); } - - void preloadmeshes() - { + void preloadmeshes() { if(meshes) meshes->preload(this); } - - virtual void getdefaultanim(animinfo &info, int anim, uint varseed, dynent *d) - { + virtual void getdefaultanim(animinfo &info, int anim, uint varseed, dynent *d) { (void) anim; (void) varseed; (void) d; info.frame = 0; info.range = 1; } - - bool calcanim(int animpart, int anim, int basetime, int basetime2, dynent *d, int interp, animinfo &info, int &aitime) - { + bool calcanim(int animpart, int anim, int basetime, int basetime2, dynent *d, int interp, animinfo &info, int &aitime) { uint varseed = uint((size_t)d); info.anim = anim; info.basetime = basetime; info.varseed = varseed; info.speed = anim&ANIM_SETSPEED ? basetime2 : 100.0f; - if((anim&ANIM_INDEX)==ANIM_ALL) - { + if((anim&ANIM_INDEX)==ANIM_ALL) { info.frame = 0; info.range = meshes->totalframes(); } - else - { + else { animspec *spec = NULL; - if(anims[animpart]) - { + if(anims[animpart]) { int primaryidx = anim&ANIM_INDEX; - if(primaryidx < NUMANIMS) - { + if(primaryidx < NUMANIMS) { vector<animspec> &primary = anims[animpart][primaryidx]; if(primary.length()) spec = &primary[uint(varseed + basetime)%primary.length()]; } - if((anim>>ANIM_SECONDARY)&(ANIM_INDEX|ANIM_DIR)) - { + if((anim>>ANIM_SECONDARY)&(ANIM_INDEX|ANIM_DIR)) { int secondaryidx = (anim>>ANIM_SECONDARY)&ANIM_INDEX; - if(secondaryidx < NUMANIMS) - { + if(secondaryidx < NUMANIMS) { vector<animspec> &secondary = anims[animpart][secondaryidx]; if(secondary.length()) { @@ -764,54 +573,42 @@ struct animmodel : model } } } - if(spec) - { + if(spec) { info.frame = spec->frame; info.range = spec->range; if(spec->speed>0) info.speed = 1000.0f/spec->speed; } else getdefaultanim(info, anim, uint(varseed + info.basetime), d); } - info.anim &= (1<<ANIM_SECONDARY)-1; info.anim |= anim&ANIM_FLAGS; - if((info.anim&ANIM_CLAMP) != ANIM_CLAMP) - { - if(info.anim&(ANIM_LOOP|ANIM_START|ANIM_END)) - { + if((info.anim&ANIM_CLAMP) != ANIM_CLAMP) { + if(info.anim&(ANIM_LOOP|ANIM_START|ANIM_END)) { info.anim &= ~ANIM_SETTIME; if(!info.basetime) info.basetime = -((int)(size_t)d&0xFFF); } - if(info.anim&(ANIM_START|ANIM_END)) - { + if(info.anim&(ANIM_START|ANIM_END)) { if(info.anim&ANIM_END) info.frame += info.range-1; info.range = 1; } } - - if(!meshes->hasframes(info.frame, info.range)) - { + if(!meshes->hasframes(info.frame, info.range)) { if(!meshes->hasframe(info.frame)) return false; info.range = meshes->clipframes(info.frame, info.range); } - - if(d && interp>=0) - { + if(d && interp>=0) { animinterpinfo &ai = d->animinterp[interp]; if((info.anim&ANIM_CLAMP)==ANIM_CLAMP) aitime = min(aitime, int(info.range*info.speed*0.5e-3f)); void *ak = meshes->animkey(); - if(d->ragdoll && !(anim&ANIM_RAGDOLL)) - { + if(d->ragdoll && !(anim&ANIM_RAGDOLL)) { ai.prev.range = ai.cur.range = 0; ai.lastswitch = -1; } - else if(ai.lastmodel!=ak || ai.lastswitch<0 || lastmillis-d->lastrendered>aitime) - { + else if(ai.lastmodel!=ak || ai.lastswitch<0 || lastmillis-d->lastrendered>aitime) { ai.prev = ai.cur = info; ai.lastswitch = lastmillis-aitime*2; } - else if(ai.cur!=info) - { + else if(ai.cur!=info) { if(lastmillis-ai.lastswitch>aitime/2) ai.prev = ai.cur; ai.cur = info; ai.lastswitch = lastmillis; @@ -821,17 +618,12 @@ struct animmodel : model } return true; } - - void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d) - { + void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d) { animstate as[MAXANIMPARTS]; render(anim, basetime, basetime2, pitch, axis, forward, d, as); } - - void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d, animstate *as) - { - if(!(anim&ANIM_REUSE)) loopi(numanimparts) - { + void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d, animstate *as) { + if(!(anim&ANIM_REUSE)) loopi(numanimparts) { animinfo info; int interp = d && index+numanimparts<=MAXANIMPARTS ? index+i : -1, aitime = animationinterpolationtime; if(!calcanim(i, anim, basetime, basetime2, d, interp, info, aitime)) return; @@ -839,41 +631,33 @@ struct animmodel : model p.owner = this; p.cur.setframes(info); p.interp = 1; - if(interp>=0 && d->animinterp[interp].prev.range>0) - { + if(interp>=0 && d->animinterp[interp].prev.range>0) { int diff = lastmillis-d->animinterp[interp].lastswitch; - if(diff<aitime) - { + if(diff<aitime) { p.prev.setframes(d->animinterp[interp].prev); p.interp = diff/float(aitime); } } } - vec oaxis, oforward; matrixstack[matrixpos].transposedtransformnormal(axis, oaxis); float pitchamount = pitchscale*pitch + pitchoffset; if((pitchmin || pitchmax) && pitchmin <= pitchmax) pitchamount = clamp(pitchamount, pitchmin, pitchmax); if(as->cur.anim&ANIM_NOPITCH || (as->interp < 1 && as->prev.anim&ANIM_NOPITCH)) pitchamount *= (as->cur.anim&ANIM_NOPITCH ? 0 : as->interp) + (as->interp < 1 && as->prev.anim&ANIM_NOPITCH ? 0 : 1-as->interp); - if(pitchamount) - { + if(pitchamount) { ++matrixpos; matrixstack[matrixpos] = matrixstack[matrixpos-1]; matrixstack[matrixpos].rotate(pitchamount*RAD, oaxis); } matrixstack[matrixpos].transposedtransformnormal(forward, oforward); - - if(!(anim&ANIM_NORENDER)) - { + if(!(anim&ANIM_NORENDER)) { matrix4 modelmatrix; modelmatrix.mul(shadowmapping ? shadowmatrix : camprojmatrix, matrixstack[matrixpos]); if(model->scale!=1) modelmatrix.scale(model->scale); if(!translate.iszero()) modelmatrix.translate(translate); GLOBALPARAM(modelmatrix, modelmatrix); - - if(!(anim&ANIM_NOSKIN)) - { + if(!(anim&ANIM_NOSKIN)) { vec odir, ocampos; matrixstack[matrixpos].transposedtransformnormal(lightdir, odir); GLOBALPARAM(lightdir, odir); @@ -882,48 +666,33 @@ struct animmodel : model GLOBALPARAM(modelcamera, ocampos); } } - meshes->render(as, pitch, oaxis, oforward, d, this); - - if(!(anim&ANIM_REUSE)) - { - loopv(links) - { + if(!(anim&ANIM_REUSE)) { + loopv(links) { linkedpart &link = links[i]; link.matrix.translate(links[i].translate, model->scale); - matrixpos++; matrixstack[matrixpos].mul(matrixstack[matrixpos-1], link.matrix); - if(link.pos) *link.pos = matrixstack[matrixpos].gettranslation(); - - if(!link.p) - { + if(!link.p) { matrixpos--; continue; } - int nanim = anim, nbasetime = basetime, nbasetime2 = basetime2; - if(link.anim>=0) - { + if(link.anim>=0) { nanim = link.anim | (anim&ANIM_FLAGS); nbasetime = link.basetime; nbasetime2 = 0; } link.p->render(nanim, nbasetime, nbasetime2, pitch, axis, forward, d); - matrixpos--; } } - if(pitchamount) matrixpos--; } - - void setanim(int animpart, int num, int frame, int range, float speed, int priority = 0) - { + void setanim(int animpart, int num, int frame, int range, float speed, int priority = 0) { if(animpart<0 || animpart>=MAXANIMPARTS) return; - if(frame<0 || range<=0 || !meshes || !meshes->hasframes(frame, range)) - { + if(frame<0 || range<=0 || !meshes || !meshes->hasframes(frame, range)) { conoutf(CON_ERROR, "invalid frame %d, range %d in model %s", frame, range, model->name); return; } @@ -934,99 +703,73 @@ struct animmodel : model spec.speed = speed; spec.priority = priority; } - - virtual void loaded() - { + virtual void loaded() { meshes->shared++; loopv(skins) skins[i].setkey(); } }; - - enum - { + enum { LINK_TAG = 0, LINK_COOP, LINK_REUSE }; - virtual int linktype(animmodel *m) const { (void) m; return LINK_TAG; } - - void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d, modelattach *a) - { + void render(int anim, int basetime, int basetime2, float pitch, const vec &axis, const vec &forward, dynent *d, modelattach *a) { int numtags = 0; - if(a) - { + if(a) { int index = parts.last()->index + parts.last()->numanimparts; - for(int i = 0; a[i].tag; i++) - { + for(int i = 0; a[i].tag; i++) { numtags++; - animmodel *m = (animmodel *)a[i].m; - if(!m) - { + if(!m) { if(a[i].pos) link(NULL, a[i].tag, vec(0, 0, 0), 0, 0, a[i].pos); continue; } part *p = m->parts[0]; - switch(linktype(m)) - { + switch(linktype(m)) { case LINK_TAG: p->index = link(p, a[i].tag, vec(0, 0, 0), a[i].anim, a[i].basetime, a[i].pos) ? index : -1; break; - case LINK_COOP: p->index = index; break; - default: continue; } index += p->numanimparts; } } - animstate as[MAXANIMPARTS]; parts[0]->render(anim, basetime, basetime2, pitch, axis, forward, d, as); - - if(a) for(int i = numtags-1; i >= 0; i--) - { + if(a) for(int i = numtags-1; i >= 0; i--) { animmodel *m = (animmodel *)a[i].m; - if(!m) - { + if(!m) { if(a[i].pos) unlink(NULL); continue; } part *p = m->parts[0]; - switch(linktype(m)) - { + switch(linktype(m)) { case LINK_TAG: if(p->index >= 0) unlink(p); p->index = 0; break; - case LINK_COOP: p->render(anim, basetime, basetime2, pitch, axis, forward, d); p->index = 0; break; - case LINK_REUSE: p->render(anim | ANIM_REUSE, basetime, basetime2, pitch, axis, forward, d, as); break; } } } - - void render(int anim, int basetime, int basetime2, const vec &o, float yaw, float pitch, dynent *d, modelattach *a, const vec &color, const vec &dir, float trans) - { + void render(int anim, int basetime, int basetime2, const vec &o, float yaw, float pitch, dynent *d, modelattach *a, const vec &color, const vec &dir, float trans) { yaw += spinyaw*lastmillis/1000.0f; pitch += offsetpitch + spinpitch*lastmillis/1000.0f; - vec axis(0, -1, 0), forward(1, 0, 0); - matrixpos = 0; matrixstack[0].identity(); - if(!d || !d->ragdoll || anim&ANIM_RAGDOLL) - { + if(!d || !d->ragdoll || anim&ANIM_RAGDOLL) { matrixstack[0].settranslation(o); matrixstack[0].rotate_around_z(yaw*RAD); matrixstack[0].transformnormal(vec(axis), axis); @@ -1034,138 +777,96 @@ struct animmodel : model if(offsetyaw) matrixstack[0].rotate_around_z(offsetyaw*RAD); } else pitch = 0; - - if(anim&ANIM_NORENDER) - { + if(anim&ANIM_NORENDER) { render(anim, basetime, basetime2, pitch, axis, forward, d, a); if(d) d->lastrendered = lastmillis; return; } - - if(!(anim&ANIM_NOSKIN)) - { + if(!(anim&ANIM_NOSKIN)) { transparent = trans; lightdir = dir; lightcolor = color; } - - if(depthoffset && !enabledepthoffset) - { + if(depthoffset && !enabledepthoffset) { enablepolygonoffset(GL_POLYGON_OFFSET_FILL); enabledepthoffset = true; } - - if(transparent<1) - { - if(anim&ANIM_GHOST) - { + if(transparent<1) { + if(anim&ANIM_GHOST) { glDepthFunc(GL_GREATER); glDepthMask(GL_FALSE); } - else if(alphadepth) - { + else if(alphadepth) { glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); render(anim|ANIM_NOSKIN, basetime, basetime2, pitch, axis, forward, d, a); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthFunc(GL_LEQUAL); } - - if(!enablealphablend) - { + if(!enablealphablend) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); enablealphablend = true; } } - render(anim, basetime, basetime2, pitch, axis, forward, d, a); - - if(transparent<1 && (alphadepth || anim&ANIM_GHOST)) - { + if(transparent<1 && (alphadepth || anim&ANIM_GHOST)) { glDepthFunc(GL_LESS); if(anim&ANIM_GHOST) glDepthMask(GL_TRUE); } - if(d) d->lastrendered = lastmillis; } - vector<part *> parts; - - animmodel(const char *name) : model(name) - { + animmodel(const char *name) : model(name) { } - - ~animmodel() - { + ~animmodel() { parts.deletecontents(); } - - void cleanup() - { + void cleanup() { loopv(parts) parts[i]->cleanup(); } - virtual void flushpart() {} - - part &addpart() - { + part &addpart() { flushpart(); part *p = new part(this, parts.length()); parts.add(p); return *p; } - - void initmatrix(matrix4x3 &m) - { + void initmatrix(matrix4x3 &m) { m.identity(); if(offsetyaw) m.rotate_around_z(offsetyaw*RAD); if(offsetpitch) m.rotate_around_y(-offsetpitch*RAD); } - - void genBIH(vector<BIH::mesh> &bih) - { + void genBIH(vector<BIH::mesh> &bih) { if(parts.empty()) return; matrix4x3 m; initmatrix(m); parts[0]->genBIH(bih, m); } - - void preloadBIH() - { + void preloadBIH() { model::preloadBIH(); if(bih) loopv(parts) parts[i]->preloadBIH(); } - - BIH *setBIH() - { + BIH *setBIH() { if(bih) return bih; vector<BIH::mesh> meshes; genBIH(meshes); bih = new BIH(meshes); return bih; } - - bool link(part *p, const char *tag, const vec &translate = vec(0, 0, 0), int anim = -1, int basetime = 0, vec *pos = NULL) - { + bool link(part *p, const char *tag, const vec &translate = vec(0, 0, 0), int anim = -1, int basetime = 0, vec *pos = NULL) { if(parts.empty()) return false; return parts[0]->link(p, tag, translate, anim, basetime, pos); } - - bool unlink(part *p) - { + bool unlink(part *p) { if(parts.empty()) return false; return parts[0]->unlink(p); } - virtual bool flipy() const { return false; } virtual bool loadconfig() { return false; } virtual bool loaddefaultparts() { return false; } virtual void startload() {} virtual void endload() {} - - bool load() - { + bool load() { startload(); bool success = loadconfig() && parts.length(); // configured model, will call the model commands below if(!success) @@ -1173,68 +874,46 @@ struct animmodel : model flushpart(); endload(); if(flipy()) translate.y = -translate.y; - if(!success) return false; loopv(parts) if(!parts[i]->meshes) return false; - loaded(); return true; } - - void preloadshaders(bool force) - { - loopv(parts) parts[i]->preloadshaders(force); + void preloadshaders() { + loopv(parts) parts[i]->preloadshaders(); } - - void preloadmeshes() - { + void preloadmeshes() { loopv(parts) parts[i]->preloadmeshes(); } - - void setshader(Shader *shader) - { + void setshader(Shader *shader) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].shader = shader; } - - void setspec(float spec) - { + void setspec(float spec) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].spec = spec; } - - void setambient(float ambient) - { + void setambient(float ambient) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].ambient = ambient; } - - void setalphatest(float alphatest) - { + void setalphatest(float alphatest) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].alphatest = alphatest; } - - void setalphablend(bool alphablend) - { + void setalphablend(bool alphablend) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].alphablend = alphablend; } - - void setfullbright(float fullbright) - { + void setfullbright(float fullbright) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].fullbright = fullbright; } - - void setcullface(bool cullface) - { + void setcullface(bool cullface) { if(parts.empty()) loaddefaultparts(); loopv(parts) loopvj(parts[i]->skins) parts[i]->skins[j].cullface = cullface; } - - void calcbb(vec ¢er, vec &radius) - { + void calcbb(vec ¢er, vec &radius) { if(parts.empty()) return; vec bbmin(1e16f, 1e16f, 1e16f), bbmax(-1e16f, -1e16f, -1e16f); matrix4x3 m; @@ -1246,14 +925,11 @@ struct animmodel : model center = bbmin; center.add(radius); } - - virtual void loaded() - { + virtual void loaded() { scale /= 4; if(parts.length()) parts[0]->translate = translate; loopv(parts) parts[i]->loaded(); } - static bool enabletc, enablealphablend, enablecullface, enablenormals, enabletangents, enablebones, enabledepthoffset; static vec lightdir, lightcolor; static float transparent, lastalphatest; @@ -1261,9 +937,7 @@ struct animmodel : model static Texture *lasttex, *lastmasks, *lastnormalmap; static int matrixpos; static matrix4 matrixstack[64]; - - void startrender() - { + void startrender() { enabletc = enablealphablend = enablenormals = enabletangents = enablebones = enabledepthoffset = false; enablecullface = true; lastalphatest = -1; @@ -1272,37 +946,26 @@ struct animmodel : model transparent = 1; shaderparamskey::invalidate(); } - - static void disablebones() - { + static void disablebones() { gle::disableboneweight(); gle::disableboneindex(); enablebones = false; } - - static void disabletangents() - { + static void disabletangents() { gle::disabletangent(); enabletangents = false; } - - static void disabletc() - { + static void disabletc() { gle::disabletexcoord0(); enabletc = false; } - - static void disablenormals() - { + static void disablenormals() { gle::disablenormal(); enablenormals = false; } - - static void disablevbo() - { + static void disablevbo() { if(lastebuf) gle::clearebo(); - if(lastvbuf) - { + if(lastvbuf) { gle::clearvbo(); gle::disablevertex(); } @@ -1312,9 +975,7 @@ struct animmodel : model if(enablebones) disablebones(); lastvbuf = lasttcbuf = lastxbuf = lastnbuf = lastbbuf = lastebuf = 0; } - - void endrender() - { + void endrender() { if(lastvbuf || lastebuf) disablevbo(); if(enablealphablend) glDisable(GL_BLEND); if(!enablecullface) glEnable(GL_CULL_FACE); @@ -1333,45 +994,33 @@ Texture *animmodel::lasttex = NULL, *animmodel::lastmasks = NULL, *animmodel::la int animmodel::matrixpos = 0; matrix4 animmodel::matrixstack[64]; -static inline uint hthash(const animmodel::shaderparams &k) -{ +static inline uint hthash(const animmodel::shaderparams &k) { return memhash(&k, sizeof(k)); } -static inline bool htcmp(const animmodel::shaderparams &x, const animmodel::shaderparams &y) -{ +static inline bool htcmp(const animmodel::shaderparams &x, const animmodel::shaderparams &y) { return !memcmp(&x, &y, sizeof(animmodel::shaderparams)); } hashtable<animmodel::shaderparams, animmodel::shaderparamskey> animmodel::shaderparamskey::keys; int animmodel::shaderparamskey::firstversion = 0, animmodel::shaderparamskey::lastversion = 1; -template<class MDL, class BASE> struct modelloader : BASE -{ +template<class MDL, class BASE> struct modelloader : BASE { static MDL *loading; static string dir; - modelloader(const char *name) : BASE(name) {} - static bool animated() { return true; } static bool multiparted() { return true; } static bool multimeshed() { return true; } - - void startload() - { + void startload() { loading = (MDL *)this; } - - void endload() - { + void endload() { loading = NULL; } - - bool loadconfig() - { + bool loadconfig() { formatstring(dir, "packages/models/%s", BASE::name); defformatstring(cfgname, "packages/models/%s/%s.cfg", BASE::name, MDL::formatname()); - identflags &= ~IDF_PERSIST; bool success = execfile(cfgname, false); identflags |= IDF_PERSIST; @@ -1382,118 +1031,84 @@ template<class MDL, class BASE> struct modelloader : BASE template<class MDL, class BASE> MDL *modelloader<MDL, BASE>::loading = NULL; template<class MDL, class BASE> string modelloader<MDL, BASE>::dir = {'\0'}; // crashes clang if "" is used here -template<class MDL, class MESH> struct modelcommands -{ +template<class MDL, class MESH> struct modelcommands { typedef struct MDL::part part; typedef struct MDL::skin skin; - - static void setdir(char *name) - { + static void setdir(char *name) { if(!MDL::loading) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } formatstring(MDL::dir, "packages/models/%s", name); } - #define loopmeshes(meshname, m, body) \ if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } \ part &mdl = *MDL::loading->parts.last(); \ if(!mdl.meshes) return; \ - loopv(mdl.meshes->meshes) \ - { \ + loopv(mdl.meshes->meshes) { \ + \ MESH &m = *(MESH *)mdl.meshes->meshes[i]; \ - if(!strcmp(meshname, "*") || (m.name && !strcmp(m.name, meshname))) \ - { \ + if(!strcmp(meshname, "*") || (m.name && !strcmp(m.name, meshname))) { \ + \ body; \ } \ } - #define loopskins(meshname, s, body) loopmeshes(meshname, m, { skin &s = mdl.skins[i]; body; }) - - static void setskin(char *meshname, char *tex, char *masks, float *envmapmax, float *envmapmin) - {(void)envmapmax;(void)envmapmin; + static void setskin(char *meshname, char *tex, char *masks, float *envmapmax, float *envmapmin) { + (void)envmapmax;(void)envmapmin; loopskins(meshname, s, s.tex = textureload(makerelpath(MDL::dir, tex), 0, true, false); - if(*masks) - { + if(*masks) { s.masks = textureload(makerelpath(MDL::dir, masks), 0, true, false); } ); } - - static void setspec(char *meshname, int *percent) - { + static void setspec(char *meshname, int *percent) { float spec = 1.0f; if(*percent>0) spec = *percent/100.0f; else if(*percent<0) spec = 0.0f; loopskins(meshname, s, s.spec = spec); } - - static void setambient(char *meshname, int *percent) - { + static void setambient(char *meshname, int *percent) { float ambient = 0.3f; if(*percent>0) ambient = *percent/100.0f; else if(*percent<0) ambient = 0.0f; loopskins(meshname, s, s.ambient = ambient); } - - static void setalphatest(char *meshname, float *cutoff) - { + static void setalphatest(char *meshname, float *cutoff) { loopskins(meshname, s, s.alphatest = max(0.0f, min(1.0f, *cutoff))); } - - static void setalphablend(char *meshname, int *blend) - { + static void setalphablend(char *meshname, int *blend) { loopskins(meshname, s, s.alphablend = *blend!=0); } - - static void setcullface(char *meshname, int *cullface) - { + static void setcullface(char *meshname, int *cullface) { loopskins(meshname, s, s.cullface = *cullface!=0); } - - static void setbumpmap(char *meshname, char *normalmapfile) - { + static void setbumpmap(char *meshname, char *normalmapfile) { Texture *normalmaptex = textureload(makerelpath(MDL::dir, normalmapfile), 0, true, false); loopskins(meshname, s, s.normalmap = normalmaptex); } - - static void setfullbright(char *meshname, float *fullbright) - { + static void setfullbright(char *meshname, float *fullbright) { loopskins(meshname, s, s.fullbright = *fullbright); } - - static void setshader(char *meshname, char *shader) - { + static void setshader(char *meshname, char *shader) { loopskins(meshname, s, s.shader = lookupshaderbyname(shader)); } - - static void setscroll(char *meshname, float *scrollu, float *scrollv) - { + static void setscroll(char *meshname, float *scrollu, float *scrollv) { loopskins(meshname, s, { s.scrollu = *scrollu; s.scrollv = *scrollv; }); } - - static void setnoclip(char *meshname, int *noclip) - { + static void setnoclip(char *meshname, int *noclip) { loopmeshes(meshname, m, m.noclip = *noclip!=0); } - - static void setlink(int *parent, int *child, char *tagname, float *x, float *y, float *z) - { + static void setlink(int *parent, int *child, char *tagname, float *x, float *y, float *z) { if(!MDL::loading) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } if(!MDL::loading->parts.inrange(*parent) || !MDL::loading->parts.inrange(*child)) { conoutf(CON_ERROR, "no models loaded to link"); return; } if(!MDL::loading->parts[*parent]->link(MDL::loading->parts[*child], tagname, vec(*x, *y, *z))) conoutf(CON_ERROR, "could not link model %s", MDL::loading->name); } - - template<class F> void modelcommand(F *fun, const char *suffix, const char *args) - { + template<class F> void modelcommand(F *fun, const char *suffix, const char *args) { defformatstring(name, "%s%s", MDL::formatname(), suffix); addcommand(newstring(name), (void (*)())fun, args); } - - modelcommands() - { + modelcommands() { modelcommand(setdir, "dir", "s"); - if(MDL::multimeshed()) - { + if(MDL::multimeshed()) { modelcommand(setskin, "skin", "sssff"); modelcommand(setspec, "spec", "si"); modelcommand(setambient, "ambient", "si"); diff --git a/src/engine/bih.cpp b/src/engine/bih.cpp index c983805..e406008 100644 --- a/src/engine/bih.cpp +++ b/src/engine/bih.cpp @@ -1,13 +1,11 @@ #include "engine.h" -bool BIH::triintersect(const mesh &m, int tidx, const vec &mo, const vec &mray, float maxdist, float &dist, int mode) -{ +bool BIH::triintersect(const mesh &m, int tidx, const vec &mo, const vec &mray, float maxdist, float &dist, int mode) { const tri &t = m.tris[tidx]; vec a = m.getpos(t.vert[0]), b = m.getpos(t.vert[1]).sub(a), c = m.getpos(t.vert[2]).sub(a), n = vec().cross(b, c), r = vec(a).sub(mo), e = vec().cross(r, mray); float det = mray.dot(n), v, w, f; - if(det >= 0) - { + if(det >= 0) { if(!(mode&RAY_SHADOW) && m.flags&MESH_CULLFACE) return false; v = e.dot(c); if(v < 0 || v > det) return false; @@ -16,8 +14,7 @@ bool BIH::triintersect(const mesh &m, int tidx, const vec &mo, const vec &mray, f = r.dot(n)*m.scale; if(f < 0 || f > maxdist*det || !det) return false; } - else - { + else { v = e.dot(c); if(v > 0 || v < det) return false; w = -e.dot(b); @@ -26,8 +23,7 @@ bool BIH::triintersect(const mesh &m, int tidx, const vec &mo, const vec &mray, if(f > 0 || f < maxdist*det) return false; } float invdet = 1/det; - if(m.flags&MESH_ALPHA && (mode&RAY_ALPHAPOLY)==RAY_ALPHAPOLY && (m.tex->alphamask || (lightmapping <= 1 && loadalphamask(m.tex)))) - { + if(m.flags&MESH_ALPHA && (mode&RAY_ALPHAPOLY)==RAY_ALPHAPOLY && (m.tex->alphamask || (lightmapping <= 1 && loadalphamask(m.tex)))) { vec2 at = m.gettc(t.vert[0]), bt = m.gettc(t.vert[1]).sub(at).mul(v*invdet), ct = m.gettc(t.vert[2]).sub(at).mul(w*invdet); at.add(bt).add(ct); int si = clamp(int(m.tex->xs * at.x), 0, m.tex->xs-1), @@ -38,31 +34,24 @@ bool BIH::triintersect(const mesh &m, int tidx, const vec &mo, const vec &mray, return true; } -struct traversestate -{ +struct traversestate { BIH::node *node; float tmin, tmax; }; -inline bool BIH::traverse(const mesh &m, const vec &o, const vec &ray, const vec &invray, float maxdist, float &dist, int mode, node *curnode, float tmin, float tmax) -{ +inline bool BIH::traverse(const mesh &m, const vec &o, const vec &ray, const vec &invray, float maxdist, float &dist, int mode, node *curnode, float tmin, float tmax) { traversestate stack[128]; int stacksize = 0; ivec order(ray.x>0 ? 0 : 1, ray.y>0 ? 0 : 1, ray.z>0 ? 0 : 1); vec mo = m.invxform.transform(o), mray = m.invxformnorm.transform(ray); - for(;;) - { + for(;;) { int axis = curnode->axis(); int nearidx = order[axis], faridx = nearidx^1; float nearsplit = (curnode->split[nearidx] - o[axis])*invray[axis], farsplit = (curnode->split[faridx] - o[axis])*invray[axis]; - - if(nearsplit <= tmin) - { - if(farsplit < tmax) - { - if(!curnode->isleaf(faridx)) - { + if(nearsplit <= tmin) { + if(farsplit < tmax) { + if(!curnode->isleaf(faridx)) { curnode += curnode->childindex(faridx); tmin = max(tmin, farsplit); continue; @@ -70,13 +59,10 @@ inline bool BIH::traverse(const mesh &m, const vec &o, const vec &ray, const vec else if(triintersect(m, curnode->childindex(faridx), mo, mray, maxdist, dist, mode)) return true; } } - else if(curnode->isleaf(nearidx)) - { + else if(curnode->isleaf(nearidx)) { if(triintersect(m, curnode->childindex(nearidx), mo, mray, maxdist, dist, mode)) return true; - if(farsplit < tmax) - { - if(!curnode->isleaf(faridx)) - { + if(farsplit < tmax) { + if(!curnode->isleaf(faridx)) { curnode += curnode->childindex(faridx); tmin = max(tmin, farsplit); continue; @@ -84,21 +70,16 @@ inline bool BIH::traverse(const mesh &m, const vec &o, const vec &ray, const vec else if(triintersect(m, curnode->childindex(faridx), mo, mray, maxdist, dist, mode)) return true; } } - else - { - if(farsplit < tmax) - { - if(!curnode->isleaf(faridx)) - { - if(stacksize < int(sizeof(stack)/sizeof(stack[0]))) - { + else { + if(farsplit < tmax) { + if(!curnode->isleaf(faridx)) { + if(stacksize < int(sizeof(stack)/sizeof(stack[0]))) { traversestate &save = stack[stacksize++]; save.node = curnode + curnode->childindex(faridx); save.tmin = max(tmin, farsplit); save.tmax = tmax; } - else - { + else { if(traverse(m, o, ray, invray, maxdist, dist, mode, curnode + curnode->childindex(nearidx), tmin, min(tmax, nearsplit))) return true; curnode += curnode->childindex(faridx); tmin = max(tmin, farsplit); @@ -119,11 +100,9 @@ inline bool BIH::traverse(const mesh &m, const vec &o, const vec &ray, const vec } } -inline bool BIH::traverse(const vec &o, const vec &ray, float maxdist, float &dist, int mode) -{ +inline bool BIH::traverse(const vec &o, const vec &ray, float maxdist, float &dist, int mode) { vec invray(ray.x ? 1/ray.x : 1e16f, ray.y ? 1/ray.y : 1e16f, ray.z ? 1/ray.z : 1e16f); - loopi(nummeshes) - { + loopi(nummeshes) { mesh &m = meshes[i]; if(!(mode&RAY_SHADOW) && m.flags&MESH_NOCLIP) continue; float t1 = (m.bbmin.x - o.x)*invray.x, @@ -142,34 +121,28 @@ inline bool BIH::traverse(const vec &o, const vec &ray, float maxdist, float &di return false; } -void BIH::build(mesh &m, ushort *indices, int numindices, const ivec &vmin, const ivec &vmax) -{ +void BIH::build(mesh &m, ushort *indices, int numindices, const ivec &vmin, const ivec &vmax) { int axis = 2; loopk(2) if(vmax[k] - vmin[k] > vmax[axis] - vmin[axis]) axis = k; - ivec leftmin, leftmax, rightmin, rightmax; int splitleft, splitright; int left, right; - loopk(3) - { + loopk(3) { leftmin = rightmin = ivec(INT_MAX, INT_MAX, INT_MAX); leftmax = rightmax = ivec(INT_MIN, INT_MIN, INT_MIN); int split = (vmax[axis] + vmin[axis])/2; - for(left = 0, right = numindices, splitleft = SHRT_MIN, splitright = SHRT_MAX; left < right;) - { + for(left = 0, right = numindices, splitleft = SHRT_MIN, splitright = SHRT_MAX; left < right;) { const tribb &tri = m.tribbs[indices[left]]; ivec trimin = ivec(tri.center).sub(ivec(tri.radius)), trimax = ivec(tri.center).add(ivec(tri.radius)); int amin = trimin[axis], amax = trimax[axis]; - if(max(split - amin, 0) > max(amax - split, 0)) - { + if(max(split - amin, 0) > max(amax - split, 0)) { ++left; splitleft = max(splitleft, amax); leftmin.min(trimin); leftmax.max(trimax); } - else - { + else { --right; swap(indices[left], indices[right]); splitright = min(splitright, amin); @@ -180,68 +153,55 @@ void BIH::build(mesh &m, ushort *indices, int numindices, const ivec &vmin, cons if(left > 0 && right < numindices) break; axis = (axis+1)%3; } - - if(!left || right==numindices) - { + if(!left || right==numindices) { leftmin = rightmin = ivec(INT_MAX, INT_MAX, INT_MAX); leftmax = rightmax = ivec(INT_MIN, INT_MIN, INT_MIN); left = right = numindices/2; splitleft = SHRT_MIN; splitright = SHRT_MAX; - loopi(numindices) - { + loopi(numindices) { const tribb &tri = m.tribbs[indices[i]]; ivec trimin = ivec(tri.center).sub(ivec(tri.radius)), trimax = ivec(tri.center).add(ivec(tri.radius)); - if(i < left) - { + if(i < left) { splitleft = max(splitleft, trimax[axis]); leftmin.min(trimin); leftmax.max(trimax); } - else - { + else { splitright = min(splitright, trimin[axis]); rightmin.min(trimin); rightmax.max(trimax); } } } - int offset = m.numnodes++; node &curnode = m.nodes[offset]; curnode.split[0] = short(splitleft); curnode.split[1] = short(splitright); - if(left==1) curnode.child[0] = (axis<<14) | indices[0]; - else - { + else { curnode.child[0] = (axis<<14) | (m.numnodes - offset); build(m, indices, left, leftmin, leftmax); } - if(numindices-right==1) curnode.child[1] = (1<<15) | (left==1 ? 1<<14 : 0) | indices[right]; - else - { + else { curnode.child[1] = (left==1 ? 1<<14 : 0) | (m.numnodes - offset); build(m, &indices[right], numindices-right, rightmin, rightmax); } } BIH::BIH(vector<mesh> &buildmeshes) - : meshes(NULL), nummeshes(0), nodes(NULL), numnodes(0), tribbs(NULL), numtris(0), bbmin(1e16f, 1e16f, 1e16f), bbmax(-1e16f, -1e16f, -1e16f), center(0, 0, 0), radius(0), entradius(0) -{ + : meshes(NULL), nummeshes(0), nodes(NULL), numnodes(0), tribbs(NULL), numtris(0), bbmin(1e16f, 1e16f, 1e16f), bbmax(-1e16f, -1e16f, -1e16f), center(0, 0, 0), radius(0), entradius(0) { if(buildmeshes.empty()) return; loopv(buildmeshes) numtris += buildmeshes[i].numtris; if(!numtris) return; - nummeshes = buildmeshes.length(); meshes = new mesh[nummeshes]; memcpy(meshes, buildmeshes.getbuf(), sizeof(mesh)*buildmeshes.length()); tribbs = new tribb[numtris]; tribb *dsttri = tribbs; - loopi(nummeshes) - { + loopi(nummeshes) { mesh &m = meshes[i]; m.scale = m.xform.a.magnitude(); m.invscale = 1/m.scale; @@ -253,8 +213,7 @@ BIH::BIH(vector<mesh> &buildmeshes) m.tribbs = dsttri; const tri *srctri = m.tris; vec mmin(1e16f, 1e16f, 1e16f), mmax(-1e16f, -1e16f, -1e16f); - loopj(m.numtris) - { + loopj(m.numtris) { vec s0 = m.getpos(srctri->vert[0]), s1 = m.getpos(srctri->vert[1]), s2 = m.getpos(srctri->vert[2]), v0 = m.xform.transform(s0), v1 = m.xform.transform(s1), v2 = m.xform.transform(s2), vmin = vec(v0).min(v1).min(v2), @@ -267,8 +226,7 @@ BIH::BIH(vector<mesh> &buildmeshes) ++srctri; ++dsttri; } - loopk(3) if(fabs(mmax[k] - mmin[k]) < 0.125f) - { + loopk(3) if(fabs(mmax[k] - mmin[k]) < 0.125f) { float mid = (mmin[k] + mmax[k]) / 2; mmin[k] = mid - 0.0625f; mmax[k] = mid + 0.0625f; @@ -278,16 +236,13 @@ BIH::BIH(vector<mesh> &buildmeshes) bbmin.min(mmin); bbmax.max(mmax); } - center = vec(bbmin).add(bbmax).mul(0.5f); radius = vec(bbmax).sub(bbmin).mul(0.5f).magnitude(); entradius = max(bbmin.squaredlen(), bbmax.squaredlen()); - nodes = new node[numtris]; node *curnode = nodes; ushort *indices = new ushort[numtris]; - loopi(nummeshes) - { + loopi(nummeshes) { mesh &m = meshes[i]; m.nodes = curnode; loopj(m.numtris) indices[j] = j; @@ -298,19 +253,16 @@ BIH::BIH(vector<mesh> &buildmeshes) numnodes = int(curnode - nodes); } -BIH::~BIH() -{ +BIH::~BIH() { delete[] meshes; delete[] nodes; delete[] tribbs; } -bool mmintersect(const extentity &e, const vec &o, const vec &ray, float maxdist, int mode, float &dist) -{ +bool mmintersect(const extentity &e, const vec &o, const vec &ray, float maxdist, int mode, float &dist) { model *m = loadmapmodel(e.attr2); if(!m) return false; - if(mode&RAY_SHADOW) - { + if(mode&RAY_SHADOW) { if(!m->shadow || e.flags&EF_NOSHADOW) return false; } else if((mode&RAY_ENTS)!=RAY_ENTS && (!m->collide || e.flags&EF_NOCOLLIDE)) return false; @@ -319,8 +271,7 @@ bool mmintersect(const extentity &e, const vec &o, const vec &ray, float maxdist float v = mo.dot(mray), inside = m->bih->entradius - mo.squaredlen(); if((inside < 0 && v > 0) || inside + v*v < 0) return false; int yaw = e.attr1; - if(yaw != 0) - { + if(yaw != 0) { const vec2 &rot = sincosmod360(-yaw); mo.rotate_around_z(rot); mray.rotate_around_z(rot); diff --git a/src/engine/bih.h b/src/engine/bih.h index 16da278..ac49c66 100644 --- a/src/engine/bih.h +++ b/src/engine/bih.h @@ -1,38 +1,25 @@ -struct BIH -{ - struct node - { +struct BIH { + struct node { short split[2]; ushort child[2]; - int axis() const { return child[0]>>14; } int childindex(int which) const { return child[which]&0x3FFF; } bool isleaf(int which) const { return (child[1]&(1<<(14+which)))!=0; } }; - - struct tri - { + struct tri { ushort vert[3]; }; - - struct tribb - { + struct tribb { svec center, radius; - - bool outside(const ivec &bo, const ivec &br) const - { + bool outside(const ivec &bo, const ivec &br) const { return abs(bo.x - center.x) > br.x + radius.x || abs(bo.y - center.y) > br.y + radius.y || abs(bo.z - center.z) > br.z + radius.z; } }; - enum { MESH_NOCLIP = 1<<0, MESH_ALPHA = 1<<1, MESH_CULLFACE = 1<<2 }; - - struct mesh - { + struct mesh { enum { MAXTRIS = 1<<14 }; - matrix4x3 xform, invxform; matrix3 xformnorm, invxformnorm; float scale, invscale; @@ -46,13 +33,10 @@ struct BIH Texture *tex; int flags; vec bbmin, bbmax; - mesh() : numnodes(0), numtris(0), tex(NULL), flags(0) {} - vec getpos(int i) const { return *(const vec *)(pos + i*posstride); } vec2 gettc(int i) const { return *(const vec2 *)(tc + i*tcstride); } }; - mesh *meshes; int nummeshes; node *nodes; @@ -61,17 +45,12 @@ struct BIH int numtris; vec bbmin, bbmax, center; float radius, entradius; - BIH(vector<mesh> &buildmeshes); - ~BIH(); - void build(mesh &m, ushort *indices, int numindices, const ivec &vmin, const ivec &vmax); - bool traverse(const vec &o, const vec &ray, float maxdist, float &dist, int mode); bool traverse(const mesh &m, const vec &o, const vec &ray, const vec &invray, float maxdist, float &dist, int mode, node *curnode, float tmin, float tmax); bool triintersect(const mesh &m, int tidx, const vec &mo, const vec &mray, float maxdist, float &dist, int mode); - void preload(); }; diff --git a/src/engine/client.cpp b/src/engine/client.cpp index bd46b24..6ae6c27 100644 --- a/src/engine/client.cpp +++ b/src/engine/client.cpp @@ -6,15 +6,13 @@ ENetHost *clienthost = NULL; ENetPeer *curpeer = NULL, *connpeer = NULL; int connmillis = 0, connattempts = 0, discmillis = 0; -bool multiplayer(bool msg) -{ +bool multiplayer(bool msg) { bool val = curpeer || hasnonlocalclients(); if(val && msg) conoutf(CON_ERROR, "operation not available in multiplayer"); return val; } -void setrate(int rate) -{ +void setrate(int rate) { if(!curpeer) return; enet_host_bandwidth_limit(clienthost, rate*1024, rate*1024); } @@ -27,40 +25,34 @@ VARF(throttle_interval, 0, 5, 30, throttle()); VARF(throttle_accel, 0, 2, 32, throttle()); VARF(throttle_decel, 0, 2, 32, throttle()); -void throttle() -{ +void throttle() { if(!curpeer) return; ASSERT(ENET_PEER_PACKET_THROTTLE_SCALE==32); enet_peer_throttle_configure(curpeer, throttle_interval*1000, throttle_accel, throttle_decel); } -bool isconnected(bool attempt, bool local) -{ +bool isconnected(bool attempt, bool local) { return curpeer || (attempt && connpeer) || (local && haslocalclients()); } ICOMMAND(isconnected, "bb", (int *attempt, int *local), intret(isconnected(*attempt > 0, *local != 0) ? 1 : 0)); -const ENetAddress *connectedpeer() -{ +const ENetAddress *connectedpeer() { return curpeer ? &curpeer->address : NULL; } -ICOMMAND(connectedip, "", (), -{ +ICOMMAND(connectedip, "", (), { const ENetAddress *address = connectedpeer(); string hostname; result(address && enet_address_get_host_ip(address, hostname, sizeof(hostname)) >= 0 ? hostname : ""); }); -ICOMMAND(connectedport, "", (), -{ +ICOMMAND(connectedport, "", (), { const ENetAddress *address = connectedpeer(); intret(address ? address->port : -1); }); -void abortconnect() -{ +void abortconnect() { if(!connpeer) return; game::connectfail(); if(connpeer->state!=ENET_PEER_STATE_DISCONNECTED) enet_peer_reset(connpeer); @@ -73,81 +65,61 @@ void abortconnect() SVARP(connectname, ""); VARP(connectport, 0, 0, 0xFFFF); -void connectserv(const char *servername, int serverport, const char *serverpassword) -{ - if(connpeer) - { +void connectserv(const char *servername, int serverport, const char *serverpassword) { + if(connpeer) { conoutf("aborting connection attempt"); abortconnect(); } - if(serverport <= 0) serverport = server::serverport(); - ENetAddress address; address.port = serverport; - - if(servername) - { + if(servername) { if(strcmp(servername, connectname)) setsvar("connectname", servername); if(serverport != connectport) setvar("connectport", serverport); addserver(servername, serverport, serverpassword && serverpassword[0] ? serverpassword : NULL); conoutf("attempting to connect to %s:%d", servername, serverport); - if(!resolverwait(servername, &address)) - { + if(!resolverwait(servername, &address)) { conoutf(CON_ERROR, "\f3could not resolve server %s", servername); return; } } - else - { + else { setsvar("connectname", ""); setvar("connectport", 0); conoutf("attempting to connect over LAN"); address.host = ENET_HOST_BROADCAST; } - - if(!clienthost) - { + if(!clienthost) { clienthost = enet_host_create(NULL, 2, server::numchannels(), rate*1024, rate*1024); - if(!clienthost) - { + if(!clienthost) { conoutf(CON_ERROR, "\f3could not connect to server"); return; } clienthost->duplicatePeers = 0; } - connpeer = enet_host_connect(clienthost, &address, server::numchannels(), 0); enet_host_flush(clienthost); connmillis = totalmillis; connattempts = 0; - game::connectattempt(servername ? servername : "", serverpassword ? serverpassword : "", address); } -void reconnect(const char *serverpassword) -{ - if(!connectname[0] || connectport <= 0) - { +void reconnect(const char *serverpassword) { + if(!connectname[0] || connectport <= 0) { conoutf(CON_ERROR, "no previous connection"); return; } - connectserv(connectname, connectport, serverpassword); } -void disconnect(bool async, bool cleanup) -{ - if(curpeer) - { - if(!discmillis) - { +void disconnect(bool async, bool cleanup) { + if(curpeer) { + if(!discmillis) { enet_peer_disconnect(curpeer, DISC_NONE); enet_host_flush(clienthost); discmillis = totalmillis; } - if(curpeer->state!=ENET_PEER_STATE_DISCONNECTED) - { + if(curpeer->state!=ENET_PEER_STATE_DISCONNECTED) { if(async) return; enet_peer_reset(curpeer); } @@ -157,22 +129,18 @@ void disconnect(bool async, bool cleanup) game::gamedisconnect(cleanup); mainmenu = 1; } - if(!connpeer && clienthost) - { + if(!connpeer && clienthost) { enet_host_destroy(clienthost); clienthost = NULL; } } -void trydisconnect(bool local) -{ - if(connpeer) - { +void trydisconnect(bool local) { + if(connpeer) { conoutf("aborting connection attempt"); abortconnect(); } - else if(curpeer) - { + else if(curpeer) { conoutf("attempting to disconnect..."); disconnect(!discmillis); } @@ -187,50 +155,42 @@ ICOMMAND(disconnect, "b", (int *local), trydisconnect(*local != 0)); ICOMMAND(localconnect, "", (), { if(!isconnected()) localconnect(); }); ICOMMAND(localdisconnect, "", (), { if(haslocalclients()) localdisconnect(); }); -void sendclientpacket(ENetPacket *packet, int chan) -{ +void sendclientpacket(ENetPacket *packet, int chan) { if(curpeer) enet_peer_send(curpeer, chan, packet); else localclienttoserver(chan, packet); } -void flushclient() -{ +void flushclient() { if(clienthost) enet_host_flush(clienthost); } -void neterr(const char *s, bool disc) -{ +void neterr(const char *s, bool disc) { conoutf(CON_ERROR, "\f3illegal network message (%s)", s); if(disc) disconnect(); } -void localservertoclient(int chan, ENetPacket *packet) // processes any updates from the server -{ +void localservertoclient(int chan, ENetPacket *packet) { // processes any updates from the server { packetbuf p(packet); game::parsepacketclient(chan, p); } void clientkeepalive() { if(clienthost) enet_host_service(clienthost, NULL, 0); } -void gets2c() // get updates from the server -{ +void gets2c() { // get updates from the server { ENetEvent event; if(!clienthost) return; - if(connpeer && totalmillis/3000 > connmillis/3000) - { + if(connpeer && totalmillis/3000 > connmillis/3000) { conoutf("attempting to connect..."); connmillis = totalmillis; ++connattempts; - if(connattempts > 3) - { + if(connattempts > 3) { conoutf(CON_ERROR, "\f3could not connect to server"); abortconnect(); return; } } while(clienthost && enet_host_service(clienthost, &event, 0)>0) - switch(event.type) - { + switch(event.type) { case ENET_EVENT_TYPE_CONNECT: disconnect(false, false); localdisconnect(false); @@ -241,24 +201,19 @@ void gets2c() // get updates from the server if(rate) setrate(rate); game::gameconnect(true); break; - case ENET_EVENT_TYPE_RECEIVE: if(discmillis) conoutf("attempting to disconnect..."); else localservertoclient(event.channelID, event.packet); enet_packet_destroy(event.packet); break; - case ENET_EVENT_TYPE_DISCONNECT: if(event.data>=DISC_NUM) event.data = DISC_NONE; - if(event.peer==connpeer) - { + if(event.peer==connpeer) { conoutf(CON_ERROR, "\f3could not connect to server"); abortconnect(); } - else - { - if(!discmillis || event.data) - { + else { + if(!discmillis || event.data) { const char *msg = disconnectreason(event.data); if(msg) conoutf(CON_ERROR, "\f3server network error, disconnecting (%s) ...", msg); else conoutf(CON_ERROR, "\f3server network error, disconnecting..."); @@ -266,7 +221,6 @@ void gets2c() // get updates from the server disconnect(); } return; - default: break; } diff --git a/src/engine/command.cpp b/src/engine/command.cpp index 012b8c1..5248899 100644 --- a/src/engine/command.cpp +++ b/src/engine/command.cpp @@ -9,38 +9,31 @@ ident *dummyident = NULL; int identflags = 0; -enum -{ +enum { MAXARGS = 25, MAXCOMARGS = 12 }; VARN(numargs, _numargs, MAXARGS, 0, 0); -static inline void freearg(tagval &v) -{ - switch(v.type) - { +static inline void freearg(tagval &v) { + switch(v.type) { case VAL_STR: delete[] v.s; break; case VAL_CODE: if(v.code[-1] == CODE_START) delete[] (uchar *)&v.code[-1]; break; } } -static inline void forcenull(tagval &v) -{ - switch(v.type) - { +static inline void forcenull(tagval &v) { + switch(v.type) { case VAL_NULL: return; } freearg(v); v.setnull(); } -static inline float forcefloat(tagval &v) -{ +static inline float forcefloat(tagval &v) { float f = 0.0f; - switch(v.type) - { + switch(v.type) { case VAL_INT: f = v.i; break; case VAL_STR: f = parsefloat(v.s); break; case VAL_MACRO: f = parsefloat(v.s); break; @@ -51,11 +44,9 @@ static inline float forcefloat(tagval &v) return f; } -static inline int forceint(tagval &v) -{ +static inline int forceint(tagval &v) { int i = 0; - switch(v.type) - { + switch(v.type) { case VAL_FLOAT: i = v.f; break; case VAL_STR: i = parseint(v.s); break; case VAL_MACRO: i = parseint(v.s); break; @@ -66,11 +57,9 @@ static inline int forceint(tagval &v) return i; } -static inline const char *forcestr(tagval &v) -{ +static inline const char *forcestr(tagval &v) { const char *s = ""; - switch(v.type) - { + switch(v.type) { case VAL_FLOAT: s = floatstr(v.f); break; case VAL_INT: s = intstr(v.i); break; case VAL_STR: @@ -82,29 +71,23 @@ static inline const char *forcestr(tagval &v) return s; } -static inline void forcearg(tagval &v, int type) -{ - switch(type) - { +static inline void forcearg(tagval &v, int type) { + switch(type) { case RET_STR: if(v.type != VAL_STR) forcestr(v); break; case RET_INT: if(v.type != VAL_INT) forceint(v); break; case RET_FLOAT: if(v.type != VAL_FLOAT) forcefloat(v); break; } } -static inline ident *forceident(tagval &v) -{ - switch(v.type) - { +static inline ident *forceident(tagval &v) { + switch(v.type) { case VAL_IDENT: return v.id; - case VAL_MACRO: - { + case VAL_MACRO: { ident *id = newident(v.s, IDF_UNKNOWN); v.setident(id); return id; } - case VAL_STR: - { + case VAL_STR: { ident *id = newident(v.s, IDF_UNKNOWN); delete[] v.s; v.setident(id); @@ -116,39 +99,31 @@ static inline ident *forceident(tagval &v) return dummyident; } -void tagval::cleanup() -{ +void tagval::cleanup() { freearg(*this); } -static inline void freeargs(tagval *args, int &oldnum, int newnum) -{ +static inline void freeargs(tagval *args, int &oldnum, int newnum) { for(int i = newnum; i < oldnum; i++) freearg(args[i]); oldnum = newnum; } -static inline void cleancode(ident &id) -{ - if(id.code) - { +static inline void cleancode(ident &id) { + if(id.code) { id.code[0] -= 0x100; if(int(id.code[0]) < 0x100) delete[] id.code; id.code = NULL; } } -struct nullval : tagval -{ +struct nullval : tagval { nullval() { setnull(); } } nullval; tagval noret = nullval, *commandret = &noret; -void clear_command() -{ - enumerate(idents, ident, i, - { - if(i.type==ID_ALIAS) - { +void clear_command() { + enumerate(idents, ident, i, { + if(i.type==ID_ALIAS) { DELETEA(i.name); i.forcenull(); DELETEA(i.code); @@ -156,14 +131,11 @@ void clear_command() }); } -void clearoverride(ident &i) -{ +void clearoverride(ident &i) { if(!(i.flags&IDF_OVERRIDDEN)) return; - switch(i.type) - { + switch(i.type) { case ID_ALIAS: - if(i.valtype==VAL_STR) - { + if(i.valtype==VAL_STR) { if(!i.val.s[0]) break; delete[] i.val.s; } @@ -188,18 +160,15 @@ void clearoverride(ident &i) i.flags &= ~IDF_OVERRIDDEN; } -void clearoverrides() -{ +void clearoverrides() { enumerate(idents, ident, i, clearoverride(i)); } static bool initedidents = false; static vector<ident> *identinits = NULL; -static inline ident *addident(const ident &id) -{ - if(!initedidents) - { +static inline ident *addident(const ident &id) { + if(!initedidents) { if(!identinits) identinits = new vector<ident>; identinits->add(id); return NULL; @@ -209,17 +178,14 @@ static inline ident *addident(const ident &id) return identmap.add(&def); } -static bool initidents() -{ +static bool initidents() { initedidents = true; - for(int i = 0; i < MAXARGS; i++) - { + for(int i = 0; i < MAXARGS; i++) { defformatstring(argname, "arg%d", i+1); newident(argname, IDF_ARG); } dummyident = newident("//dummy", IDF_UNKNOWN); - if(identinits) - { + if(identinits) { loopv(*identinits) addident((*identinits)[i]); DELETEP(identinits); } @@ -229,17 +195,14 @@ UNUSED static bool forceinitidents = initidents(); static const char *sourcefile = NULL, *sourcestr = NULL; -static const char *debugline(const char *p, const char *fmt) -{ +static const char *debugline(const char *p, const char *fmt) { if(!sourcestr) return fmt; int num = 1; const char *line = sourcestr; - for(;;) - { + for(;;) { const char *end = strchr(line, '\n'); if(!end) end = line + strlen(line); - if(p >= line && p <= end) - { + if(p >= line && p <= end) { static string buf; if(sourcefile) formatstring(buf, "%s:%d: %s", sourcefile, num, fmt); else formatstring(buf, "%d: %s", num, fmt); @@ -252,8 +215,7 @@ static const char *debugline(const char *p, const char *fmt) return fmt; } -static struct identlink -{ +static struct identlink { ident *id; identlink *next; int usedargs; @@ -262,13 +224,11 @@ static struct identlink VAR(dbgalias, 0, 4, 1000); -static void debugalias() -{ +static void debugalias() { if(!dbgalias) return; int total = 0, depth = 0; for(identlink *l = aliasstack; l != &noalias; l = l->next) total++; - for(identlink *l = aliasstack; l != &noalias; l = l->next) - { + for(identlink *l = aliasstack; l != &noalias; l = l->next) { ident *id = l->id; ++depth; if(depth < dbgalias) conoutf(CON_ERROR, " %d) %s", total-depth+1, id->name); @@ -280,41 +240,33 @@ static int nodebug = 0; static void debugcode(const char *fmt, ...) PRINTFARGS(1, 2); -static void debugcode(const char *fmt, ...) -{ +static void debugcode(const char *fmt, ...) { if(nodebug) return; - va_list args; va_start(args, fmt); conoutfv(CON_ERROR, fmt, args); va_end(args); - debugalias(); } static void debugcodeline(const char *p, const char *fmt, ...) PRINTFARGS(2, 3); -static void debugcodeline(const char *p, const char *fmt, ...) -{ +static void debugcodeline(const char *p, const char *fmt, ...) { if(nodebug) return; - va_list args; va_start(args, fmt); conoutfv(CON_ERROR, debugline(p, fmt), args); va_end(args); - debugalias(); } ICOMMAND(nodebug, "e", (uint *body), { nodebug++; executeret(body, *commandret); nodebug--; }); -void addident(ident *id) -{ +void addident(ident *id) { addident(*id); } -static inline void pusharg(ident &id, const tagval &v, identstack &stack) -{ +static inline void pusharg(ident &id, const tagval &v, identstack &stack) { stack.val = id.val; stack.valtype = id.valtype; stack.next = id.stack; @@ -323,8 +275,7 @@ static inline void pusharg(ident &id, const tagval &v, identstack &stack) cleancode(id); } -static inline void poparg(ident &id) -{ +static inline void poparg(ident &id) { if(!id.stack) return; identstack *stack = id.stack; if(id.valtype == VAL_STR) delete[] id.val.s; @@ -333,8 +284,7 @@ static inline void poparg(ident &id) id.stack = stack->next; } -ICOMMAND(push, "rte", (ident *id, tagval *v, uint *code), -{ +ICOMMAND(push, "rte", (ident *id, tagval *v, uint *code), { if(id->type != ID_ALIAS || id->index < MAXARGS) return; identstack stack; pusharg(*id, *v, stack); @@ -344,40 +294,32 @@ ICOMMAND(push, "rte", (ident *id, tagval *v, uint *code), poparg(*id); }); -static inline void pushalias(ident &id, identstack &stack) -{ - if(id.type == ID_ALIAS && id.index >= MAXARGS) - { +static inline void pushalias(ident &id, identstack &stack) { + if(id.type == ID_ALIAS && id.index >= MAXARGS) { pusharg(id, nullval, stack); id.flags &= ~IDF_UNKNOWN; } } -static inline void popalias(ident &id) -{ +static inline void popalias(ident &id) { if(id.type == ID_ALIAS && id.index >= MAXARGS) poparg(id); } KEYWORD(local, ID_LOCAL); -static inline bool checknumber(const char *s) -{ +static inline bool checknumber(const char *s) { if(isdigit(s[0])) return true; - else switch(s[0]) - { + else switch(s[0]) { case '+': case '-': return isdigit(s[1]) || (s[1] == '.' && isdigit(s[2])); case '.': return isdigit(s[1]) != 0; default: return false; } } -ident *newident(const char *name, int flags) -{ +ident *newident(const char *name, int flags) { ident *id = idents.access(name); - if(!id) - { - if(checknumber(name)) - { + if(!id) { + if(checknumber(name)) { debugcode("number %s is not a valid identifier name", name); return dummyident; } @@ -386,27 +328,23 @@ ident *newident(const char *name, int flags) return id; } -ident *writeident(const char *name, int flags) -{ +ident *writeident(const char *name, int flags) { ident *id = newident(name, flags); - if(id->index < MAXARGS && !(aliasstack->usedargs&(1<<id->index))) - { + if(id->index < MAXARGS && !(aliasstack->usedargs&(1<<id->index))) { pusharg(*id, nullval, aliasstack->argstack[id->index]); aliasstack->usedargs |= 1<<id->index; } return id; } -ident *readident(const char *name) -{ +ident *readident(const char *name) { ident *id = idents.access(name); if(id && id->index < MAXARGS && !(aliasstack->usedargs&(1<<id->index))) return NULL; return id; } -void resetvar(char *name) -{ +void resetvar(char *name) { ident *id = idents.access(name); if(!id) return; if(id->flags&IDF_READONLY) debugcode("variable %s is read-only", id->name); @@ -415,89 +353,73 @@ void resetvar(char *name) COMMAND(resetvar, "s"); -static inline void setarg(ident &id, tagval &v) -{ - if(aliasstack->usedargs&(1<<id.index)) - { +static inline void setarg(ident &id, tagval &v) { + if(aliasstack->usedargs&(1<<id.index)) { if(id.valtype == VAL_STR) delete[] id.val.s; id.setval(v); cleancode(id); } - else - { + else { pusharg(id, v, aliasstack->argstack[id.index]); aliasstack->usedargs |= 1<<id.index; } } -static inline void setalias(ident &id, tagval &v) -{ +static inline void setalias(ident &id, tagval &v) { if(id.valtype == VAL_STR) delete[] id.val.s; id.setval(v); cleancode(id); id.flags = (id.flags & identflags) | identflags; } -static void setalias(const char *name, tagval &v) -{ +static void setalias(const char *name, tagval &v) { ident *id = idents.access(name); - if(id) - { - if(id->type == ID_ALIAS) - { + if(id) { + if(id->type == ID_ALIAS) { if(id->index < MAXARGS) setarg(*id, v); else setalias(*id, v); } - else - { + else { debugcode("cannot redefine builtin %s with an alias", id->name); freearg(v); } } - else if(checknumber(name)) - { + else if(checknumber(name)) { debugcode("cannot alias number %s", name); freearg(v); } - else - { + else { addident(ident(ID_ALIAS, newstring(name), v, identflags)); } } -void alias(const char *name, const char *str) -{ +void alias(const char *name, const char *str) { tagval v; v.setstr(newstring(str)); setalias(name, v); } -void alias(const char *name, tagval &v) -{ +void alias(const char *name, tagval &v) { setalias(name, v); } -ICOMMAND(alias, "st", (const char *name, tagval *v), -{ +ICOMMAND(alias, "st", (const char *name, tagval *v), { setalias(name, *v); v->type = VAL_NULL; }); // variable's and commands are registered through globals, see cube.h -int variable(const char *name, int min, int cur, int max, int *storage, identfun fun, int flags) -{ +int variable(const char *name, int min, int cur, int max, int *storage, identfun fun, int flags) { addident(ident(ID_VAR, name, min, max, storage, (void *)fun, flags)); return cur; } -float fvariable(const char *name, float min, float cur, float max, float *storage, identfun fun, int flags) -{ +float fvariable(const char *name, float min, float cur, float max, float *storage, identfun fun, int flags) { addident(ident(ID_FVAR, name, min, max, storage, (void *)fun, flags)); return cur; } -char *svariable(const char *name, const char *cur, char **storage, identfun fun, int flags) -{ +char *svariable(const char *name, const char *cur, char **storage, identfun fun, int flags) { addident(ident(ID_SVAR, name, storage, (void *)fun, flags)); return newstring(cur); } @@ -507,67 +429,59 @@ char *svariable(const char *name, const char *cur, char **storage, identfun fun, if(!id || id->type!=vartype) return retval; #define GETVAR(id, name, retval) _GETVAR(id, ID_VAR, name, retval) #define OVERRIDEVAR(errorval, saveval, resetval, clearval) \ - if(identflags&IDF_OVERRIDDEN || id->flags&IDF_OVERRIDE) \ - { \ - if(id->flags&IDF_PERSIST) \ - { \ + if(identflags&IDF_OVERRIDDEN || id->flags&IDF_OVERRIDE) { \ + \ + if(id->flags&IDF_PERSIST) { \ + \ debugcode("cannot override persistent variable %s", id->name); \ errorval; \ } \ if(!(id->flags&IDF_OVERRIDDEN)) { saveval; id->flags |= IDF_OVERRIDDEN; } \ else { clearval; } \ } \ - else \ - { \ + else { \ + \ if(id->flags&IDF_OVERRIDDEN) { resetval; id->flags &= ~IDF_OVERRIDDEN; } \ clearval; \ } -void setvar(const char *name, int i, bool dofunc, bool doclamp) -{ +void setvar(const char *name, int i, bool dofunc, bool doclamp) { GETVAR(id, name, ); OVERRIDEVAR(return, id->overrideval.i = *id->storage.i, , ) if(doclamp) *id->storage.i = clamp(i, id->minval, id->maxval); else *id->storage.i = i; if(dofunc) id->changed(); } -void setfvar(const char *name, float f, bool dofunc, bool doclamp) -{ +void setfvar(const char *name, float f, bool dofunc, bool doclamp) { _GETVAR(id, ID_FVAR, name, ); OVERRIDEVAR(return, id->overrideval.f = *id->storage.f, , ); if(doclamp) *id->storage.f = clamp(f, id->minvalf, id->maxvalf); else *id->storage.f = f; if(dofunc) id->changed(); } -void setsvar(const char *name, const char *str, bool dofunc) -{ +void setsvar(const char *name, const char *str, bool dofunc) { _GETVAR(id, ID_SVAR, name, ); OVERRIDEVAR(return, id->overrideval.s = *id->storage.s, delete[] id->overrideval.s, delete[] *id->storage.s); *id->storage.s = newstring(str); if(dofunc) id->changed(); } -int getvar(const char *name) -{ +int getvar(const char *name) { GETVAR(id, name, 0); return *id->storage.i; } -int getvarmin(const char *name) -{ +int getvarmin(const char *name) { GETVAR(id, name, 0); return id->minval; } -int getvarmax(const char *name) -{ +int getvarmax(const char *name) { GETVAR(id, name, 0); return id->maxval; } -float getfvarmin(const char *name) -{ +float getfvarmin(const char *name) { _GETVAR(id, ID_FVAR, name, 0); return id->minvalf; } -float getfvarmax(const char *name) -{ +float getfvarmax(const char *name) { _GETVAR(id, ID_FVAR, name, 0); return id->maxvalf; } @@ -580,11 +494,9 @@ ICOMMAND(getfvarmax, "s", (char *s), floatret(getfvarmax(s))); bool identexists(const char *name) { return idents.access(name)!=NULL; } ident *getident(const char *name) { return idents.access(name); } -void touchvar(const char *name) -{ +void touchvar(const char *name) { ident *id = idents.access(name); - if(id) switch(id->type) - { + if(id) switch(id->type) { case ID_VAR: case ID_FVAR: case ID_SVAR: @@ -593,16 +505,14 @@ void touchvar(const char *name) } } -const char *getalias(const char *name) -{ +const char *getalias(const char *name) { ident *i = idents.access(name); return i && i->type==ID_ALIAS && (i->index >= MAXARGS || aliasstack->usedargs&(1<<i->index)) ? i->getstr() : ""; } ICOMMAND(getalias, "s", (char *s), result(getalias(s))); -int clampvar(ident *id, int val, int minval, int maxval) -{ +int clampvar(ident *id, int val, int minval, int maxval) { if(val < minval) val = minval; else if(val > maxval) val = maxval; else return val; @@ -613,15 +523,13 @@ int clampvar(ident *id, int val, int minval, int maxval) return val; } -void setvarchecked(ident *id, int val) -{ +void setvarchecked(ident *id, int val) { if(id->flags&IDF_READONLY) debugcode("variable %s is read-only", id->name); #ifndef STANDALONE - else if(!(id->flags&IDF_OVERRIDE) || identflags&IDF_OVERRIDDEN || game::allowedittoggle()) + else if(!(id->flags&IDF_OVERRIDE) || identflags&IDF_OVERRIDDEN || game::allowedittoggle()) { #else - else + else { #endif - { OVERRIDEVAR(return, id->overrideval.i = *id->storage.i, , ) if(val < id->minval || val > id->maxval) val = clampvar(id, val, id->minval, id->maxval); *id->storage.i = val; @@ -632,19 +540,16 @@ void setvarchecked(ident *id, int val) } } -static inline void setvarchecked(ident *id, tagval *args, int numargs) -{ +static inline void setvarchecked(ident *id, tagval *args, int numargs) { int val = forceint(args[0]); - if(id->flags&IDF_HEX && numargs > 1) - { + if(id->flags&IDF_HEX && numargs > 1) { val = (val << 16) | (forceint(args[1])<<8); if(numargs > 2) val |= forceint(args[2]); } setvarchecked(id, val); } -float clampfvar(ident *id, float val, float minval, float maxval) -{ +float clampfvar(ident *id, float val, float minval, float maxval) { if(val < minval) val = minval; else if(val > maxval) val = maxval; else return val; @@ -652,15 +557,13 @@ float clampfvar(ident *id, float val, float minval, float maxval) return val; } -void setfvarchecked(ident *id, float val) -{ +void setfvarchecked(ident *id, float val) { if(id->flags&IDF_READONLY) debugcode("variable %s is read-only", id->name); #ifndef STANDALONE - else if(!(id->flags&IDF_OVERRIDE) || identflags&IDF_OVERRIDDEN || game::allowedittoggle()) + else if(!(id->flags&IDF_OVERRIDE) || identflags&IDF_OVERRIDDEN || game::allowedittoggle()) { #else - else + else { #endif - { OVERRIDEVAR(return, id->overrideval.f = *id->storage.f, , ); if(val < id->minvalf || val > id->maxvalf) val = clampfvar(id, val, id->minvalf, id->maxvalf); *id->storage.f = val; @@ -671,15 +574,13 @@ void setfvarchecked(ident *id, float val) } } -void setsvarchecked(ident *id, const char *val) -{ +void setsvarchecked(ident *id, const char *val) { if(id->flags&IDF_READONLY) debugcode("variable %s is read-only", id->name); #ifndef STANDALONE - else if(!(id->flags&IDF_OVERRIDE) || identflags&IDF_OVERRIDDEN || game::allowedittoggle()) + else if(!(id->flags&IDF_OVERRIDE) || identflags&IDF_OVERRIDDEN || game::allowedittoggle()) { #else - else + else { #endif - { OVERRIDEVAR(return, id->overrideval.s = *id->storage.s, delete[] id->overrideval.s, delete[] *id->storage.s); *id->storage.s = newstring(val); id->changed(); @@ -689,10 +590,8 @@ void setsvarchecked(ident *id, const char *val) } } -ICOMMAND(set, "rt", (ident *id, tagval *v), -{ - switch(id->type) - { +ICOMMAND(set, "rt", (ident *id, tagval *v), { + switch(id->type) { case ID_ALIAS: if(id->index < MAXARGS) setarg(*id, *v); else setalias(*id, *v); v->type = VAL_NULL; @@ -707,8 +606,7 @@ ICOMMAND(set, "rt", (ident *id, tagval *v), setsvarchecked(id, forcestr(*v)); break; case ID_COMMAND: - if(id->flags&IDF_EMUVAR) - { + if(id->flags&IDF_EMUVAR) { execute(id, v, 1); v->type = VAL_NULL; break; @@ -720,13 +618,11 @@ ICOMMAND(set, "rt", (ident *id, tagval *v), } }); -bool addcommand(const char *name, identfun fun, const char *args) -{ +bool addcommand(const char *name, identfun fun, const char *args) { uint argmask = 0; int numargs = 0, flags = 0; bool limit = true; - for(const char *fmt = args; *fmt; fmt++) switch(*fmt) - { + for(const char *fmt = args; *fmt; fmt++) switch(*fmt) { case 'i': case 'b': case 'f': case 't': case 'N': case 'D': if(numargs < MAXARGS) numargs++; break; case '$': flags |= IDF_EMUVAR; // fall through case 's': case 'e': case 'r': if(numargs < MAXARGS) { argmask |= 1<<numargs; numargs++; } break; @@ -739,16 +635,13 @@ bool addcommand(const char *name, identfun fun, const char *args) return false; } -bool addkeyword(int type, const char *name) -{ +bool addkeyword(int type, const char *name) { addident(ident(type, name, "", 0, 0, NULL)); return true; } -const char *parsestring(const char *p) -{ - for(; *p; p++) switch(*p) - { +const char *parsestring(const char *p) { + for(; *p; p++) switch(*p) { case '\r': case '\n': case '\"': @@ -760,18 +653,14 @@ const char *parsestring(const char *p) return p; } -int unescapestring(char *dst, const char *src, const char *end) -{ +int unescapestring(char *dst, const char *src, const char *end) { char *start = dst; - while(src < end) - { + while(src < end) { int c = *src++; - if(c == '^') - { + if(c == '^') { if(src >= end) break; int e = *src++; - switch(e) - { + switch(e) { case 'n': *dst++ = '\n'; break; case 't': *dst++ = '\t'; break; case 'f': *dst++ = '\f'; break; @@ -783,19 +672,15 @@ int unescapestring(char *dst, const char *src, const char *end) return dst - start; } -static char *conc(vector<char> &buf, tagval *v, int n, bool space, const char *prefix = NULL, int prefixlen = 0) -{ - if(prefix) - { +static char *conc(vector<char> &buf, tagval *v, int n, bool space, const char *prefix = NULL, int prefixlen = 0) { + if(prefix) { buf.put(prefix, prefixlen); if(space && n) buf.add(' '); } - loopi(n) - { + loopi(n) { const char *s = ""; int len = 0; - switch(v[i].type) - { + switch(v[i].type) { case VAL_INT: s = intstr(v[i].i); break; case VAL_FLOAT: s = floatstr(v[i].f); break; case VAL_STR: s = v[i].s; break; @@ -811,13 +696,11 @@ static char *conc(vector<char> &buf, tagval *v, int n, bool space, const char *p return buf.getbuf(); } -static char *conc(tagval *v, int n, bool space, const char *prefix, int prefixlen) -{ +static char *conc(tagval *v, int n, bool space, const char *prefix, int prefixlen) { static int vlen[MAXARGS]; static char numbuf[3*MAXSTRLEN]; int len = prefixlen, numlen = 0, i = 0; - for(; i < n; i++) switch(v[i].type) - { + for(; i < n; i++) switch(v[i].type) { case VAL_MACRO: len += (vlen[i] = v[i].code[-1]>>8); break; case VAL_STR: len += (vlen[i] = int(strlen(v[i].s))); break; case VAL_INT: @@ -836,16 +719,13 @@ overflow: if(space) len += max(prefix ? i : i-1, 0); char *buf = newstring(len + numlen); int offset = 0, numoffset = 0; - if(prefix) - { + if(prefix) { memcpy(buf, prefix, prefixlen); offset += prefixlen; if(space && i) buf[offset++] = ' '; } - loopj(i) - { - if(v[j].type == VAL_INT || v[j].type == VAL_FLOAT) - { + loopj(i) { + if(v[j].type == VAL_INT || v[j].type == VAL_FLOAT) { memcpy(&buf[offset], &numbuf[numoffset], vlen[j]); numoffset += vlen[j]; } @@ -855,8 +735,7 @@ overflow: if(space) buf[offset++] = ' '; } buf[offset] = '\0'; - if(i < n) - { + if(i < n) { char *morebuf = conc(&v[i], n-i, space, buf, offset); delete[] buf; return morebuf; @@ -864,28 +743,23 @@ overflow: return buf; } -static inline char *conc(tagval *v, int n, bool space) -{ +static inline char *conc(tagval *v, int n, bool space) { return conc(v, n, space, NULL, 0); } -static inline char *conc(tagval *v, int n, bool space, const char *prefix) -{ +static inline char *conc(tagval *v, int n, bool space, const char *prefix) { return conc(v, n, space, prefix, strlen(prefix)); } -static inline void skipcomments(const char *&p) -{ - for(;;) - { +static inline void skipcomments(const char *&p) { + for(;;) { p += strspn(p, " \t\r"); if(p[0]!='/' || p[1]!='/') break; p += strcspn(p, "\n\0"); } } -static inline char *cutstring(const char *&p, int &len) -{ +static inline char *cutstring(const char *&p, int &len) { p++; const char *end = parsestring(p); char *s = newstring(end - p); @@ -896,16 +770,13 @@ static inline char *cutstring(const char *&p, int &len) return s; } -static inline const char *parseword(const char *p) -{ +static inline const char *parseword(const char *p) { const int maxbrak = 100; static char brakstack[maxbrak]; int brakdepth = 0; - for(;; p++) - { + for(;; p++) { p += strcspn(p, "\"/;()[] \t\r\n\0"); - switch(p[0]) - { + switch(p[0]) { case '"': case ';': case ' ': case '\t': case '\r': case '\n': case '\0': return p; case '/': if(p[1] == '/') return p; break; case '[': case '(': if(brakdepth >= maxbrak) return p; brakstack[brakdepth++] = p[0]; break; @@ -916,8 +787,7 @@ static inline const char *parseword(const char *p) return p; } -static inline char *cutword(const char *&p, int &len) -{ +static inline char *cutword(const char *&p, int &len) { const char *word = p; p = parseword(p); len = p-word; @@ -925,10 +795,8 @@ static inline char *cutword(const char *&p, int &len) return newstring(word, len); } -static inline void compilestr(vector<uint> &code, const char *word, int len, bool macro = false) -{ - if(len <= 3 && !macro) - { +static inline void compilestr(vector<uint> &code, const char *word, int len, bool macro = false) { + if(len <= 3 && !macro) { uint op = CODE_VALI|RET_STR; for(int i = 0; i < len; i++) op |= uint(uchar(word[i]))<<((i+1)*8); code.add(op); @@ -937,8 +805,7 @@ static inline void compilestr(vector<uint> &code, const char *word, int len, boo code.add((macro ? CODE_MACRO : CODE_VAL|RET_STR)|(len<<8)); code.put((const uint *)word, len/sizeof(uint)); size_t endlen = len%sizeof(uint); - union - { + union { char c[sizeof(uint)]; uint u; } end; @@ -947,30 +814,25 @@ static inline void compilestr(vector<uint> &code, const char *word, int len, boo code.add(end.u); } -static inline void compilestr(vector<uint> &code, const char *word = NULL) -{ +static inline void compilestr(vector<uint> &code, const char *word = NULL) { if(!word) { code.add(CODE_VALI|RET_STR); return; } compilestr(code, word, int(strlen(word))); } -static inline void compileint(vector<uint> &code, int i) -{ +static inline void compileint(vector<uint> &code, int i) { if(i >= -0x800000 && i <= 0x7FFFFF) code.add(CODE_VALI|RET_INT|(i<<8)); - else - { + else { code.add(CODE_VAL|RET_INT); code.add(i); } } -static inline void compilenull(vector<uint> &code) -{ +static inline void compilenull(vector<uint> &code) { code.add(CODE_VALI|RET_NULL); } -static inline void compileblock(vector<uint> &code) -{ +static inline void compileblock(vector<uint> &code) { int start = code.length(); code.add(CODE_BLOCK); code.add(CODE_OFFSET|((start+2)<<8)); @@ -978,27 +840,22 @@ static inline void compileblock(vector<uint> &code) code[start] |= uint(code.length() - (start + 1))<<8; } -static inline void compileident(vector<uint> &code, ident *id) -{ +static inline void compileident(vector<uint> &code, ident *id) { code.add((id->index < MAXARGS ? CODE_IDENTARG : CODE_IDENT)|(id->index<<8)); } -static inline void compileident(vector<uint> &code, const char *word = NULL) -{ +static inline void compileident(vector<uint> &code, const char *word = NULL) { compileident(code, word ? newident(word, IDF_UNKNOWN) : dummyident); } -static inline void compileint(vector<uint> &code, const char *word = NULL) -{ +static inline void compileint(vector<uint> &code, const char *word = NULL) { return compileint(code, word ? parseint(word) : 0); } -static inline void compilefloat(vector<uint> &code, float f) -{ +static inline void compilefloat(vector<uint> &code, float f) { if(int(f) == f && f >= -0x800000 && f <= 0x7FFFFF) code.add(CODE_VALI|RET_FLOAT|(int(f)<<8)); - else - { + else { union { float f; uint u; } conv; conv.f = f; code.add(CODE_VAL|RET_FLOAT); @@ -1006,24 +863,20 @@ static inline void compilefloat(vector<uint> &code, float f) } } -static inline void compilefloat(vector<uint> &code, const char *word = NULL) -{ +static inline void compilefloat(vector<uint> &code, const char *word = NULL) { return compilefloat(code, word ? parsefloat(word) : 0.0f); } static bool compilearg(vector<uint> &code, const char *&p, int wordtype); static void compilestatements(vector<uint> &code, const char *&p, int rettype, int brak = '\0'); -static inline void compileval(vector<uint> &code, int wordtype, char *word, int wordlen) -{ - switch(wordtype) - { +static inline void compileval(vector<uint> &code, int wordtype, char *word, int wordlen) { + switch(wordtype) { case VAL_STR: compilestr(code, word, wordlen, true); break; case VAL_ANY: compilestr(code, word, wordlen); break; case VAL_FLOAT: compilefloat(code, word); break; case VAL_INT: compileint(code, word); break; - case VAL_CODE: - { + case VAL_CODE: { int start = code.length(); code.add(CODE_BLOCK); code.add(CODE_OFFSET|((start+2)<<8)); @@ -1041,12 +894,10 @@ static inline void compileval(vector<uint> &code, int wordtype, char *word, int static bool compileword(vector<uint> &code, const char *&p, int wordtype, char *&word, int &wordlen); -static void compilelookup(vector<uint> &code, const char *&p, int ltype) -{ +static void compilelookup(vector<uint> &code, const char *&p, int ltype) { char *lookup = NULL; int lookuplen = 0; - switch(*++p) - { + switch(*++p) { case '(': case '[': if(!compileword(code, p, VAL_STR, lookup, lookuplen)) goto invalid; @@ -1057,24 +908,20 @@ static void compilelookup(vector<uint> &code, const char *&p, int ltype) case '\"': lookup = cutstring(p, lookuplen); goto lookupid; - default: - { + default: { lookup = cutword(p, lookuplen); if(!lookup) goto invalid; lookupid: ident *id = newident(lookup, IDF_UNKNOWN); - if(id) switch(id->type) - { + if(id) switch(id->type) { case ID_VAR: code.add(CODE_IVAR|((ltype >= VAL_ANY ? VAL_INT : ltype)<<CODE_RET)|(id->index<<8)); goto done; case ID_FVAR: code.add(CODE_FVAR|((ltype >= VAL_ANY ? VAL_FLOAT : ltype)<<CODE_RET)|(id->index<<8)); goto done; case ID_SVAR: code.add(CODE_SVAR|((ltype >= VAL_ANY ? VAL_STR : ltype)<<CODE_RET)|(id->index<<8)); goto done; case ID_ALIAS: code.add((id->index < MAXARGS ? CODE_LOOKUPARG : CODE_LOOKUP)|((ltype >= VAL_ANY ? VAL_STR : ltype)<<CODE_RET)|(id->index<<8)); goto done; - case ID_COMMAND: - { + case ID_COMMAND: { int comtype = CODE_COM, numargs = 0; code.add(CODE_ENTER); - for(const char *fmt = id->args; *fmt; fmt++) switch(*fmt) - { + for(const char *fmt = id->args; *fmt; fmt++) switch(*fmt) { case 's': compilestr(code, NULL, 0, true); numargs++; break; case 'i': compileint(code); numargs++; break; case 'b': compileint(code, INT_MIN); numargs++; break; @@ -1105,37 +952,31 @@ static void compilelookup(vector<uint> &code, const char *&p, int ltype) code.add(CODE_LOOKUPU|((ltype < VAL_ANY ? ltype<<CODE_RET : 0))); done: delete[] lookup; - switch(ltype) - { + switch(ltype) { case VAL_CODE: code.add(CODE_COMPILE); break; case VAL_IDENT: code.add(CODE_IDENTU); break; } return; invalid: - switch(ltype) - { + switch(ltype) { case VAL_NULL: case VAL_ANY: compilenull(code); break; default: compileval(code, ltype, NULL, 0); break; } } -static bool compileblockstr(vector<uint> &code, const char *str, const char *end, bool macro) -{ +static bool compileblockstr(vector<uint> &code, const char *str, const char *end, bool macro) { int start = code.length(); code.add(macro ? CODE_MACRO : CODE_VAL|RET_STR); char *buf = (char *)code.reserve((end-str)/sizeof(uint)+1).buf; int len = 0; - while(str < end) - { + while(str < end) { int n = strcspn(str, "\r/\"@]\0"); memcpy(&buf[len], str, n); len += n; str += n; - switch(*str) - { + switch(*str) { case '\r': str++; break; - case '\"': - { + case '\"': { const char *start = str; str = parsestring(str+1); if(*str=='\"') str++; @@ -1144,11 +985,9 @@ static bool compileblockstr(vector<uint> &code, const char *str, const char *end break; } case '/': - if(str[1] == '/') - { + if(str[1] == '/') { size_t comment = strcspn(str, "\n\0"); - if (iscubepunct(str[2])) - { + if (iscubepunct(str[2])) { memcpy(&buf[len], str, comment); len += comment; } @@ -1171,12 +1010,10 @@ done: return true; } -static bool compileblocksub(vector<uint> &code, const char *&p) -{ +static bool compileblocksub(vector<uint> &code, const char *&p) { char *lookup = NULL; int lookuplen = 0; - switch(*p) - { + switch(*p) { case '(': if(!compilearg(code, p, VAL_STR)) return false; break; @@ -1187,9 +1024,8 @@ static bool compileblocksub(vector<uint> &code, const char *&p) case '\"': lookup = cutstring(p, lookuplen); goto lookupid; - default: - { - { + default: { + { const char *start = p; while(iscubealnum(*p) || *p=='_') p++; lookuplen = p-start; @@ -1198,8 +1034,7 @@ static bool compileblocksub(vector<uint> &code, const char *&p) } lookupid: ident *id = newident(lookup, IDF_UNKNOWN); - if(id) switch(id->type) - { + if(id) switch(id->type) { case ID_VAR: code.add(CODE_IVAR|RET_STR|(id->index<<8)); goto done; case ID_FVAR: code.add(CODE_FVAR|RET_STR|(id->index<<8)); goto done; case ID_SVAR: code.add(CODE_SVAR|RET_STR|(id->index<<8)); goto done; @@ -1215,16 +1050,13 @@ static bool compileblocksub(vector<uint> &code, const char *&p) return true; } -static void compileblock(vector<uint> &code, const char *&p, int wordtype) -{ +static void compileblock(vector<uint> &code, const char *&p, int wordtype) { const char *line = p, *start = p; int concs = 0; - for(int brak = 1; brak;) - { + for(int brak = 1; brak;) { p += strcspn(p, "@\"/[]\0"); int c = *p++; - switch(c) - { + switch(c) { case '\0': debugcodeline(line, "missing \"]\""); p--; @@ -1238,16 +1070,14 @@ static void compileblock(vector<uint> &code, const char *&p, int wordtype) break; case '[': brak++; break; case ']': brak--; break; - case '@': - { + case '@': { const char *esc = p; while(*p == '@') p++; int level = p - (esc - 1); if(brak > level) continue; else if(brak < level) debugcodeline(line, "too many @s"); if(!concs) code.add(CODE_ENTER); - if(concs + 2 > MAXARGS) - { + if(concs + 2 > MAXARGS) { code.add(CODE_CONCW|RET_STR|(concs<<8)); concs = 1; } @@ -1260,12 +1090,9 @@ static void compileblock(vector<uint> &code, const char *&p, int wordtype) } } done: - if(p-1 > start) - { - if(!concs) switch(wordtype) - { - case VAL_CODE: - { + if(p-1 > start) { + if(!concs) switch(wordtype) { + case VAL_CODE: { p = start; int inst = code.length(); code.add(CODE_BLOCK); @@ -1275,8 +1102,7 @@ done: code[inst] |= uint(code.length() - (inst + 1))<<8; return; } - case VAL_IDENT: - { + case VAL_IDENT: { char *name = newstring(start, p-1-start); compileident(code, name); delete[] name; @@ -1286,21 +1112,18 @@ done: compileblockstr(code, start, p-1, concs > 0); if(concs > 1) concs++; } - if(concs) - { + if(concs) { code.add(CODE_CONCM|(wordtype < VAL_ANY ? wordtype<<CODE_RET : RET_STR)|(concs<<8)); code.add(CODE_EXIT|(wordtype < VAL_ANY ? wordtype<<CODE_RET : RET_STR)); } - switch(wordtype) - { + switch(wordtype) { case VAL_CODE: if(!concs && p-1 <= start) compileblock(code); else code.add(CODE_COMPILE); break; case VAL_IDENT: if(!concs && p-1 <= start) compileident(code); else code.add(CODE_IDENTU); break; case VAL_STR: case VAL_NULL: case VAL_ANY: if(!concs && p-1 <= start) compilestr(code); break; default: - if(!concs) - { + if(!concs) { if(p-1 <= start) compileval(code, wordtype, NULL, 0); else code.add(CODE_FORCE|(wordtype<<CODE_RET)); } @@ -1308,11 +1131,9 @@ done: } } -static bool compileword(vector<uint> &code, const char *&p, int wordtype, char *&word, int &wordlen) -{ +static bool compileword(vector<uint> &code, const char *&p, int wordtype, char *&word, int &wordlen) { skipcomments(p); - switch(*p) - { + switch(*p) { case '\"': word = cutstring(p, wordlen); break; case '$': compilelookup(code, p, wordtype); return true; case '(': @@ -1320,8 +1141,7 @@ static bool compileword(vector<uint> &code, const char *&p, int wordtype, char * code.add(CODE_ENTER); compilestatements(code, p, VAL_ANY, ')'); code.add(CODE_EXIT|(wordtype < VAL_ANY ? wordtype<<CODE_RET : 0)); - switch(wordtype) - { + switch(wordtype) { case VAL_CODE: code.add(CODE_COMPILE); break; case VAL_IDENT: code.add(CODE_IDENTU); break; } @@ -1335,36 +1155,31 @@ static bool compileword(vector<uint> &code, const char *&p, int wordtype, char * return word!=NULL; } -static inline bool compilearg(vector<uint> &code, const char *&p, int wordtype) -{ +static inline bool compilearg(vector<uint> &code, const char *&p, int wordtype) { char *word = NULL; int wordlen = 0; bool more = compileword(code, p, wordtype, word, wordlen); if(!more) return false; - if(word) - { + if(word) { compileval(code, wordtype, word, wordlen); delete[] word; } return true; } -static void compilestatements(vector<uint> &code, const char *&p, int rettype, int brak) -{ +static void compilestatements(vector<uint> &code, const char *&p, int rettype, int brak) { const char *line = p; char *idname = NULL; int idlen = 0; ident *id = NULL; int numargs = 0; - for(;;) - { + for(;;) { skipcomments(p); idname = NULL; bool more = compileword(code, p, VAL_ANY, idname, idlen); if(!more) goto endstatement; skipcomments(p); - if(p[0] == '=') switch(p[1]) - { + if(p[0] == '=') switch(p[1]) { case '/': if(p[2] != '/') break; [[fallthrough]]; @@ -1380,11 +1195,9 @@ static void compilestatements(vector<uint> &code, const char *&p, int rettype, i [[fallthrough]]; case '\0': p++; - if(idname) - { + if(idname) { id = newident(idname, IDF_UNKNOWN); - if(id) switch(id->type) - { + if(id) switch(id->type) { case ID_ALIAS: if(!(more = compilearg(code, p, VAL_ANY))) compilestr(code); code.add((id->index < MAXARGS ? CODE_ALIASARG : CODE_ALIAS)|(id->index<<8)); @@ -1414,17 +1227,14 @@ static void compilestatements(vector<uint> &code, const char *&p, int rettype, i } compilecommand: numargs = 0; - if(!idname) - { + if(!idname) { noid: while(numargs < MAXARGS && (more = compilearg(code, p, VAL_ANY))) numargs++; code.add(CODE_CALLU); } - else - { + else { id = idents.access(idname); - if(!id) - { + if(!id) { if(!checknumber(idname)) { compilestr(code, idname, idlen); delete[] idname; goto noid; } char *end = idname; int val = int(strtoul(idname, &end, 0)); @@ -1432,28 +1242,23 @@ static void compilestatements(vector<uint> &code, const char *&p, int rettype, i else compileint(code, val); code.add(CODE_RESULT); } - else switch(id->type) - { + else switch(id->type) { case ID_ALIAS: while(numargs < MAXARGS && (more = compilearg(code, p, VAL_ANY))) numargs++; code.add((id->index < MAXARGS ? CODE_CALLARG : CODE_CALL)|(id->index<<8)); break; - case ID_COMMAND: - { + case ID_COMMAND: { int comtype = CODE_COM, fakeargs = 0; bool rep = false; - for(const char *fmt = id->args; *fmt; fmt++) switch(*fmt) - { + for(const char *fmt = id->args; *fmt; fmt++) switch(*fmt) { case 's': if(more) more = compilearg(code, p, VAL_STR); - if(!more) - { + if(!more) { if(rep) break; compilestr(code, NULL, 0, true); fakeargs++; } - else if(!fmt[1]) - { + else if(!fmt[1]) { int numconc = 0; while(numargs + numconc < MAXARGS && (more = compilearg(code, p, VAL_STR))) numconc++; if(numconc > 0) code.add(CODE_CONC|RET_STR|((numconc+1)<<8)); @@ -1474,8 +1279,7 @@ static void compilestatements(vector<uint> &code, const char *&p, int rettype, i case 'C': comtype = CODE_COMC; if(more) while(numargs < MAXARGS && (more = compilearg(code, p, VAL_ANY))) numargs++; numargs = 1; goto endfmt; case 'V': comtype = CODE_COMV; if(more) while(numargs < MAXARGS && (more = compilearg(code, p, VAL_ANY))) numargs++; numargs = 2; goto endfmt; case '1': case '2': case '3': case '4': - if(more && numargs < MAXARGS) - { + if(more && numargs < MAXARGS) { int numrep = *fmt-'0'+1; fmt -= numrep; rep = true; @@ -1504,8 +1308,7 @@ static void compilestatements(vector<uint> &code, const char *&p, int rettype, i break; case ID_SVAR: if(!(more = compilearg(code, p, VAL_STR))) code.add(CODE_PRINT|(id->index<<8)); - else - { + else { int numconc = 0; while(numconc+1 < MAXARGS && (more = compilearg(code, p, VAL_ANY))) numconc++; if(numconc > 0) code.add(CODE_CONC|RET_STR|((numconc+1)<<8)); @@ -1520,19 +1323,16 @@ static void compilestatements(vector<uint> &code, const char *&p, int rettype, i if(more) while(compilearg(code, p, VAL_ANY)) code.add(CODE_POP); p += strcspn(p, ")];/\n\0"); int c = *p++; - switch(c) - { + switch(c) { case '\0': if(c != brak) debugcodeline(line, "missing \"%c\"", brak); p--; return; - case ')': case ']': if(c == brak) return; debugcodeline(line, "unexpected \"%c\"", c); break; - case '/': if(*p == '/') p += strcspn(p, "\n\0"); goto endstatement; @@ -1540,15 +1340,13 @@ static void compilestatements(vector<uint> &code, const char *&p, int rettype, i } } -static void compilemain(vector<uint> &code, const char *p, int rettype = VAL_ANY) -{ +static void compilemain(vector<uint> &code, const char *p, int rettype = VAL_ANY) { code.add(CODE_START); compilestatements(code, p, VAL_ANY); code.add(CODE_EXIT|(rettype < VAL_ANY ? rettype<<CODE_RET : 0)); } -uint *compilecode(const char *p) -{ +uint *compilecode(const char *p) { vector<uint> buf; buf.reserve(64); compilemain(buf, p); @@ -1558,17 +1356,14 @@ uint *compilecode(const char *p) return code; } -void keepcode(uint *code) -{ +void keepcode(uint *code) { if(!code) return; - switch(*code&CODE_OP_MASK) - { + switch(*code&CODE_OP_MASK) { case CODE_START: *code += 0x100; return; } - switch(code[-1]&CODE_OP_MASK) - { + switch(code[-1]&CODE_OP_MASK) { case CODE_START: code[-1] += 0x100; break; @@ -1579,18 +1374,15 @@ void keepcode(uint *code) } } -void freecode(uint *code) -{ +void freecode(uint *code) { if(!code) return; - switch(*code&CODE_OP_MASK) - { + switch(*code&CODE_OP_MASK) { case CODE_START: *code -= 0x100; if(int(*code) < 0x100) delete[] code; return; } - switch(code[-1]&CODE_OP_MASK) - { + switch(code[-1]&CODE_OP_MASK) { case CODE_START: code[-1] -= 0x100; if(int(code[-1]) < 0x100) delete[] &code[-1]; @@ -1603,8 +1395,7 @@ void freecode(uint *code) } } -void printvar(ident *id, int i) -{ +void printvar(ident *id, int i) { if(i < 0) conoutf(CON_INFO, id->index, "%s = %d", id->name, i); else if(id->flags&IDF_HEX && id->maxval==0xFFFFFF) conoutf(CON_INFO, id->index, "%s = 0x%.6X (%d, %d, %d)", id->name, i, (i>>16)&0xFF, (i>>8)&0xFF, i&0xFF); @@ -1612,38 +1403,31 @@ void printvar(ident *id, int i) conoutf(CON_INFO, id->index, id->flags&IDF_HEX ? "%s = 0x%X" : "%s = %d", id->name, i); } -void printfvar(ident *id, float f) -{ +void printfvar(ident *id, float f) { conoutf(CON_INFO, id->index, "%s = %s", id->name, floatstr(f)); } -void printsvar(ident *id, const char *s) -{ +void printsvar(ident *id, const char *s) { conoutf(CON_INFO, id->index, strchr(s, '"') ? "%s = [%s]" : "%s = \"%s\"", id->name, s); } template <class V> -static void printvar(ident *id, int type, V &val) -{ - switch(type) - { +static void printvar(ident *id, int type, V &val) { + switch(type) { case VAL_INT: printvar(id, val.getint()); break; case VAL_FLOAT: printfvar(id, val.getfloat()); break; default: printsvar(id, val.getstr()); break; } } -void printvar(ident *id) -{ - switch(id->type) - { +void printvar(ident *id) { + switch(id->type) { case ID_VAR: printvar(id, *id->storage.i); break; case ID_FVAR: printfvar(id, *id->storage.f); break; case ID_SVAR: printsvar(id, *id->storage.s); break; case ID_ALIAS: printvar(id, id->valtype, *id); break; case ID_COMMAND: - if(id->flags&IDF_EMUVAR) - { + if(id->flags&IDF_EMUVAR) { tagval result; executeret(id, NULL, 0, true, result); printvar(id, result.type, result); @@ -1669,23 +1453,18 @@ typedef void (__cdecl *comfun11)(void *, void *, void *, void *, void *, void *, typedef void (__cdecl *comfun12)(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); typedef void (__cdecl *comfunv)(tagval *, int); -static const uint *skipcode(const uint *code, tagval &result) -{ +static const uint *skipcode(const uint *code, tagval &result) { int depth = 0; - for(;;) - { + for(;;) { uint op = *code++; - switch(op&0xFF) - { + switch(op&0xFF) { case CODE_MACRO: - case CODE_VAL|RET_STR: - { + case CODE_VAL|RET_STR: { uint len = op>>8; code += len/sizeof(uint) + 1; continue; } - case CODE_BLOCK: - { + case CODE_BLOCK: { uint len = op>>8; code += len; continue; @@ -1694,8 +1473,7 @@ static const uint *skipcode(const uint *code, tagval &result) ++depth; continue; case CODE_EXIT|RET_NULL: case CODE_EXIT|RET_STR: case CODE_EXIT|RET_INT: case CODE_EXIT|RET_FLOAT: - if(depth <= 0) - { + if(depth <= 0) { forcearg(result, op&CODE_RET_MASK); return code; } @@ -1705,27 +1483,23 @@ static const uint *skipcode(const uint *code, tagval &result) } } -static inline void callcommand(ident *id, tagval *args, int numargs, bool lookup = false) -{ +static inline void callcommand(ident *id, tagval *args, int numargs, bool lookup = false) { int i = -1, fakeargs = 0; bool rep = false; - for(const char *fmt = id->args; *fmt; fmt++) switch(*fmt) - { + for(const char *fmt = id->args; *fmt; fmt++) switch(*fmt) { case 'i': if(++i >= numargs) { if(rep) break; args[i].setint(0); fakeargs++; } else forceint(args[i]); break; case 'b': if(++i >= numargs) { if(rep) break; args[i].setint(INT_MIN); fakeargs++; } else forceint(args[i]); break; case 'f': if(++i >= numargs) { if(rep) break; args[i].setfloat(0.0f); fakeargs++; } else forcefloat(args[i]); break; case 's': if(++i >= numargs) { if(rep) break; args[i].setstr(newstring("")); fakeargs++; } else forcestr(args[i]); break; case 't': if(++i >= numargs) { if(rep) break; args[i].setnull(); fakeargs++; } break; case 'e': - if(++i >= numargs) - { + if(++i >= numargs) { if(rep) break; static uint buf[2] = { CODE_START + 0x100, CODE_EXIT }; args[i].setcode(buf); fakeargs++; } - else - { + else { vector<uint> buf; buf.reserve(64); compilemain(buf, numargs <= i ? "" : args[i].getstr()); @@ -1746,8 +1520,8 @@ static inline void callcommand(ident *id, tagval *args, int numargs, bool lookup } #define ARG(n) (id->argmask&(1<<n) ? (void *)args[n].s : (void *)&args[n].i) #define CALLCOM(n) \ - switch(n) \ - { \ + switch(n) { \ + \ case 0: ((comfun)id->fun)(); break; \ case 1: ((comfun1)id->fun)(ARG(0)); break; \ case 2: ((comfun2)id->fun)(ARG(0), ARG(1)); break; \ @@ -1772,11 +1546,9 @@ cleanup: #define MAXRUNDEPTH 255 static int rundepth = 0; -static const uint *runcode(const uint *code, tagval &result) -{ +static const uint *runcode(const uint *code, tagval &result) { result.setnull(); - if(rundepth >= MAXRUNDEPTH) - { + if(rundepth >= MAXRUNDEPTH) { debugcode("exceeded recursion limit"); return skipcode(code, result); } @@ -1785,13 +1557,10 @@ static const uint *runcode(const uint *code, tagval &result) int numargs = 0; tagval args[MAXARGS+1], *prevret = commandret; commandret = &result; - for(;;) - { + for(;;) { uint op = *code++; - switch(op&0xFF) - { + switch(op&0xFF) { case CODE_START: case CODE_OFFSET: continue; - case CODE_POP: freearg(args[--numargs]); continue; @@ -1804,8 +1573,7 @@ static const uint *runcode(const uint *code, tagval &result) case CODE_PRINT: printvar(identmap[op>>8]); continue; - case CODE_LOCAL: - { + case CODE_LOCAL: { identstack locals[MAXARGS]; freearg(result); loopi(numargs) pushalias(*args[i].id, locals[i]); @@ -1813,24 +1581,19 @@ static const uint *runcode(const uint *code, tagval &result) loopi(numargs) popalias(*args[i].id); goto exit; } - - case CODE_MACRO: - { + case CODE_MACRO: { uint len = op>>8; args[numargs++].setmacro(code); code += len/sizeof(uint) + 1; continue; } - - case CODE_VAL|RET_STR: - { + case CODE_VAL|RET_STR: { uint len = op>>8; args[numargs++].setstr(newstring((const char *)code, len)); code += len/sizeof(uint) + 1; continue; } - case CODE_VALI|RET_STR: - { + case CODE_VALI|RET_STR: { char s[4] = { char((op>>8)&0xFF), char((op>>16)&0xFF), char((op>>24)&0xFF), '\0' }; args[numargs++].setstr(newstring(s)); continue; @@ -1841,11 +1604,9 @@ static const uint *runcode(const uint *code, tagval &result) case CODE_VALI|RET_INT: args[numargs++].setint(int(op)>>8); continue; case CODE_VAL|RET_FLOAT: args[numargs++].setfloat(*(const float *)code++); continue; case CODE_VALI|RET_FLOAT: args[numargs++].setfloat(float(int(op)>>8)); continue; - case CODE_FORCE|RET_STR: forcestr(args[numargs-1]); continue; case CODE_FORCE|RET_INT: forceint(args[numargs-1]); continue; case CODE_FORCE|RET_FLOAT: forcefloat(args[numargs-1]); continue; - case CODE_RESULT|RET_NULL: case CODE_RESULT|RET_STR: case CODE_RESULT|RET_INT: case CODE_RESULT|RET_FLOAT: litval: freearg(result); @@ -1854,20 +1615,16 @@ static const uint *runcode(const uint *code, tagval &result) args[0].setnull(); freeargs(args, numargs, 0); continue; - - case CODE_BLOCK: - { + case CODE_BLOCK: { uint len = op>>8; args[numargs++].setcode(code+1); code += len; continue; } - case CODE_COMPILE: - { + case CODE_COMPILE: { tagval &arg = args[numargs-1]; vector<uint> buf; - switch(arg.type) - { + switch(arg.type) { case VAL_INT: buf.reserve(8); buf.add(CODE_START); compileint(buf, arg.i); buf.add(CODE_RESULT); buf.add(CODE_EXIT); break; case VAL_FLOAT: buf.reserve(8); buf.add(CODE_START); compilefloat(buf, arg.f); buf.add(CODE_RESULT); buf.add(CODE_EXIT); break; case VAL_STR: case VAL_MACRO: buf.reserve(64); compilemain(buf, arg.s); freearg(arg); break; @@ -1877,27 +1634,22 @@ static const uint *runcode(const uint *code, tagval &result) buf.disown(); continue; } - case CODE_IDENT: args[numargs++].setident(identmap[op>>8]); continue; - case CODE_IDENTARG: - { + case CODE_IDENTARG: { ident *id = identmap[op>>8]; - if(!(aliasstack->usedargs&(1<<id->index))) - { + if(!(aliasstack->usedargs&(1<<id->index))) { pusharg(*id, nullval, aliasstack->argstack[id->index]); aliasstack->usedargs |= 1<<id->index; } args[numargs++].setident(id); continue; } - case CODE_IDENTU: - { + case CODE_IDENTU: { tagval &arg = args[numargs-1]; ident *id = arg.type == VAL_STR || arg.type == VAL_MACRO ? newident(arg.s, IDF_UNKNOWN) : dummyident; - if(id->index < MAXARGS && !(aliasstack->usedargs&(1<<id->index))) - { + if(id->index < MAXARGS && !(aliasstack->usedargs&(1<<id->index))) { pusharg(*id, nullval, aliasstack->argstack[id->index]); aliasstack->usedargs |= 1<<id->index; } @@ -1905,14 +1657,13 @@ static const uint *runcode(const uint *code, tagval &result) arg.setident(id); continue; } - case CODE_LOOKUPU|RET_STR: #define LOOKUPU(aval, sval, ival, fval, nval) { \ tagval &arg = args[numargs-1]; \ if(arg.type != VAL_STR && arg.type != VAL_MACRO) continue; \ id = idents.access(arg.s); \ - if(id) switch(id->type) \ - { \ + if(id) switch(id->type) { \ + \ case ID_ALIAS: \ if(id->flags&IDF_UNKNOWN) break; \ freearg(arg); \ @@ -1922,8 +1673,8 @@ static const uint *runcode(const uint *code, tagval &result) case ID_SVAR: freearg(arg); sval; continue; \ case ID_VAR: freearg(arg); ival; continue; \ case ID_FVAR: freearg(arg); fval; continue; \ - case ID_COMMAND: \ - { \ + case ID_COMMAND: { \ + \ freearg(arg); \ arg.setnull(); \ commandret = &arg; \ @@ -1991,24 +1742,20 @@ static const uint *runcode(const uint *code, tagval &result) LOOKUP(id->getval(args[numargs++])); case CODE_LOOKUPARG|RET_NULL: LOOKUPARG(id->getval(args[numargs++]), args[numargs++].setnull()); - case CODE_SVAR|RET_STR: case CODE_SVAR|RET_NULL: args[numargs++].setstr(newstring(*identmap[op>>8]->storage.s)); continue; case CODE_SVAR|RET_INT: args[numargs++].setint(parseint(*identmap[op>>8]->storage.s)); continue; case CODE_SVAR|RET_FLOAT: args[numargs++].setfloat(parsefloat(*identmap[op>>8]->storage.s)); continue; case CODE_SVAR1: setsvarchecked(identmap[op>>8], args[0].s); freeargs(args, numargs, 0); continue; - case CODE_IVAR|RET_INT: case CODE_IVAR|RET_NULL: args[numargs++].setint(*identmap[op>>8]->storage.i); continue; case CODE_IVAR|RET_STR: args[numargs++].setstr(newstring(intstr(*identmap[op>>8]->storage.i))); continue; case CODE_IVAR|RET_FLOAT: args[numargs++].setfloat(float(*identmap[op>>8]->storage.i)); continue; case CODE_IVAR1: setvarchecked(identmap[op>>8], args[0].i); numargs = 0; continue; case CODE_IVAR2: setvarchecked(identmap[op>>8], (args[0].i<<16)|(args[1].i<<8)); numargs = 0; continue; case CODE_IVAR3: setvarchecked(identmap[op>>8], (args[0].i<<16)|(args[1].i<<8)|args[2].i); numargs = 0; continue; - case CODE_FVAR|RET_FLOAT: case CODE_FVAR|RET_NULL: args[numargs++].setfloat(*identmap[op>>8]->storage.f); continue; case CODE_FVAR|RET_STR: args[numargs++].setstr(newstring(floatstr(*identmap[op>>8]->storage.f))); continue; case CODE_FVAR|RET_INT: args[numargs++].setint(int(*identmap[op>>8]->storage.f)); continue; case CODE_FVAR1: setfvarchecked(identmap[op>>8], args[0].f); numargs = 0; continue; - case CODE_COM|RET_NULL: case CODE_COM|RET_STR: case CODE_COM|RET_FLOAT: case CODE_COM|RET_INT: id = identmap[op>>8]; #ifndef STANDALONE @@ -2034,17 +1781,14 @@ static const uint *runcode(const uint *code, tagval &result) goto forceresult; case CODE_COMC|RET_NULL: case CODE_COMC|RET_STR: case CODE_COMC|RET_FLOAT: case CODE_COMC|RET_INT: id = identmap[op>>8]; - forcenull(result); - { + forcenull(result); { vector<char> buf; buf.reserve(MAXSTRLEN); ((comfun1)id->fun)(conc(buf, args, numargs, true)); } goto forceresult; - case CODE_CONC|RET_NULL: case CODE_CONC|RET_STR: case CODE_CONC|RET_FLOAT: case CODE_CONC|RET_INT: - case CODE_CONCW|RET_NULL: case CODE_CONCW|RET_STR: case CODE_CONCW|RET_FLOAT: case CODE_CONCW|RET_INT: - { + case CODE_CONCW|RET_NULL: case CODE_CONCW|RET_STR: case CODE_CONCW|RET_FLOAT: case CODE_CONCW|RET_INT: { int numconc = op>>8; char *s = conc(&args[numargs-numconc], numconc, (op&CODE_OP_MASK)==CODE_CONC); freeargs(args, numargs, numargs-numconc); @@ -2052,9 +1796,7 @@ static const uint *runcode(const uint *code, tagval &result) forcearg(args[numargs-1], op&CODE_RET_MASK); continue; } - - case CODE_CONCM|RET_NULL: case CODE_CONCM|RET_STR: case CODE_CONCM|RET_FLOAT: case CODE_CONCM|RET_INT: - { + case CODE_CONCM|RET_NULL: case CODE_CONCM|RET_STR: case CODE_CONCM|RET_FLOAT: case CODE_CONCM|RET_INT: { int numconc = op>>8; char *s = conc(&args[numargs-numconc], numconc, false); freeargs(args, numargs, numargs-numconc); @@ -2062,7 +1804,6 @@ static const uint *runcode(const uint *code, tagval &result) forcearg(result, op&CODE_RET_MASK); continue; } - case CODE_ALIAS: setalias(*identmap[op>>8], args[--numargs]); freeargs(args, numargs, 0); @@ -2076,7 +1817,6 @@ static const uint *runcode(const uint *code, tagval &result) setalias(args[0].s, args[--numargs]); freeargs(args, numargs, 0); continue; - case CODE_CALL|RET_NULL: case CODE_CALL|RET_STR: case CODE_CALL|RET_FLOAT: case CODE_CALL|RET_INT: #define CALLALIAS(offset) { \ identstack argstack[MAXARGS]; \ @@ -2106,8 +1846,7 @@ static const uint *runcode(const uint *code, tagval &result) } forcenull(result); id = identmap[op>>8]; - if(id->flags&IDF_UNKNOWN) - { + if(id->flags&IDF_UNKNOWN) { debugcode("unknown command: %s", id->name); goto forceresult; } @@ -2119,12 +1858,10 @@ static const uint *runcode(const uint *code, tagval &result) if(!(aliasstack->usedargs&(1<<id->index))) goto forceresult; CALLALIAS(0); continue; - case CODE_CALLU|RET_NULL: case CODE_CALLU|RET_STR: case CODE_CALLU|RET_FLOAT: case CODE_CALLU|RET_INT: if(args[0].type != VAL_STR) goto litval; id = idents.access(args[0].s); - if(!id) - { + if(!id) { noid: if(checknumber(args[0].s)) goto litval; debugcode("unknown command: %s", args[0].s); @@ -2132,16 +1869,14 @@ static const uint *runcode(const uint *code, tagval &result) goto forceresult; } forcenull(result); - switch(id->type) - { + switch(id->type) { case ID_COMMAND: freearg(args[0]); callcommand(id, args+1, numargs-1); forcearg(result, op&CODE_RET_MASK); numargs = 0; continue; - case ID_LOCAL: - { + case ID_LOCAL: { identstack locals[MAXARGS]; freearg(args[0]); loopj(numargs-1) pushalias(*forceident(args[j+1]), locals[j]); @@ -2175,13 +1910,11 @@ exit: return code; } -void executeret(const uint *code, tagval &result) -{ +void executeret(const uint *code, tagval &result) { runcode(code, result); } -void executeret(const char *p, tagval &result) -{ +void executeret(const char *p, tagval &result) { vector<uint> code; code.reserve(64); compilemain(code, p, VAL_ANY); @@ -2189,21 +1922,18 @@ void executeret(const char *p, tagval &result) if(int(code[0]) >= 0x100) code.disown(); } -void executeret(ident *id, tagval *args, int numargs, bool lookup, tagval &result) -{ +void executeret(ident *id, tagval *args, int numargs, bool lookup, tagval &result) { result.setnull(); ++rundepth; tagval *prevret = commandret; commandret = &result; if(rundepth > MAXRUNDEPTH) debugcode("exceeded recursion limit"); - else if(id) switch(id->type) - { + else if(id) switch(id->type) { default: if(!id->fun) break; // fall-through case ID_COMMAND: - if(numargs < id->numargs) - { + if(numargs < id->numargs) { tagval buf[MAXARGS]; memcpy(buf, args, numargs*sizeof(tagval)); callcommand(id, buf, numargs, lookup); @@ -2233,8 +1963,7 @@ void executeret(ident *id, tagval *args, int numargs, bool lookup, tagval &resul --rundepth; } -char *executestr(const uint *code) -{ +char *executestr(const uint *code) { tagval result; runcode(code, result); if(result.type == VAL_NULL) return NULL; @@ -2242,8 +1971,7 @@ char *executestr(const uint *code) return result.s; } -char *executestr(const char *p) -{ +char *executestr(const char *p) { tagval result; executeret(p, result); if(result.type == VAL_NULL) return NULL; @@ -2251,8 +1979,7 @@ char *executestr(const char *p) return result.s; } -char *executestr(ident *id, tagval *args, int numargs, bool lookup) -{ +char *executestr(ident *id, tagval *args, int numargs, bool lookup) { tagval result; executeret(id, args, numargs, lookup, result); if(result.type == VAL_NULL) return NULL; @@ -2260,14 +1987,12 @@ char *executestr(ident *id, tagval *args, int numargs, bool lookup) return result.s; } -char *execidentstr(const char *name, bool lookup) -{ +char *execidentstr(const char *name, bool lookup) { ident *id = idents.access(name); return id ? executestr(id, NULL, 0, lookup) : NULL; } -int execute(const uint *code) -{ +int execute(const uint *code) { tagval result; runcode(code, result); int i = result.getint(); @@ -2275,8 +2000,7 @@ int execute(const uint *code) return i; } -int execute(const char *p) -{ +int execute(const char *p) { vector<uint> code; code.reserve(64); compilemain(code, p, VAL_INT); @@ -2288,8 +2012,7 @@ int execute(const char *p) return i; } -int execute(ident *id, tagval *args, int numargs, bool lookup) -{ +int execute(ident *id, tagval *args, int numargs, bool lookup) { tagval result; executeret(id, args, numargs, lookup, result); int i = result.getint(); @@ -2297,31 +2020,25 @@ int execute(ident *id, tagval *args, int numargs, bool lookup) return i; } -int execident(const char *name, int noid, bool lookup) -{ +int execident(const char *name, int noid, bool lookup) { ident *id = idents.access(name); return id ? execute(id, NULL, 0, lookup) : noid; } -static inline bool getbool(const char *s) -{ - switch(s[0]) - { +static inline bool getbool(const char *s) { + switch(s[0]) { case '+': case '-': - switch(s[1]) - { + switch(s[1]) { case '0': break; case '.': return !isdigit(s[2]) || parsefloat(s) != 0; default: return true; } // fall through - case '0': - { + case '0': { char *end; int val = int(strtoul((char *)s, &end, 0)); if(val) return true; - switch(*end) - { + switch(*end) { case 'e': case '.': return parsefloat(s) != 0; default: return false; } @@ -2332,10 +2049,8 @@ static inline bool getbool(const char *s) } } -static inline bool getbool(const tagval &v) -{ - switch(v.type) - { +static inline bool getbool(const tagval &v) { + switch(v.type) { case VAL_FLOAT: return v.f!=0; case VAL_INT: return v.i!=0; case VAL_STR: case VAL_MACRO: return getbool(v.s); @@ -2343,8 +2058,7 @@ static inline bool getbool(const tagval &v) } } -bool executebool(const uint *code) -{ +bool executebool(const uint *code) { tagval result; runcode(code, result); bool b = getbool(result); @@ -2352,8 +2066,7 @@ bool executebool(const uint *code) return b; } -bool executebool(const char *p) -{ +bool executebool(const char *p) { tagval result; executeret(p, result); bool b = getbool(result); @@ -2361,8 +2074,7 @@ bool executebool(const char *p) return b; } -bool executebool(ident *id, tagval *args, int numargs, bool lookup) -{ +bool executebool(ident *id, tagval *args, int numargs, bool lookup) { tagval result; executeret(id, args, numargs, lookup, result); bool b = getbool(result); @@ -2370,19 +2082,16 @@ bool executebool(ident *id, tagval *args, int numargs, bool lookup) return b; } -bool execidentbool(const char *name, bool noid, bool lookup) -{ +bool execidentbool(const char *name, bool noid, bool lookup) { ident *id = idents.access(name); return id ? executebool(id, NULL, 0, lookup) : noid; } -bool execfile(const char *cfgfile, bool msg) -{ +bool execfile(const char *cfgfile, bool msg) { string s; copystring(s, cfgfile); char *buf = loadfile(path(s), NULL); - if(!buf) - { + if(!buf) { if(msg) conoutf(CON_ERROR, "could not read \"%s\"", cfgfile); return false; } @@ -2397,16 +2106,14 @@ bool execfile(const char *cfgfile, bool msg) } ICOMMAND(exec, "sb", (char *file, int *msg), intret(execfile(file, *msg != 0) ? 1 : 0)); -const char *escapestring(const char *s) -{ +const char *escapestring(const char *s) { static vector<char> strbuf[3]; static int stridx = 0; stridx = (stridx + 1)%3; vector<char> &buf = strbuf[stridx]; buf.setsize(0); buf.add('"'); - for(; *s; s++) switch(*s) - { + for(; *s; s++) switch(*s) { case '\n': buf.put("^n", 2); break; case '\t': buf.put("^t", 2); break; case '\f': buf.put("^f", 2); break; @@ -2419,27 +2126,23 @@ const char *escapestring(const char *s) } ICOMMAND(escape, "s", (char *s), result(escapestring(s))); -ICOMMAND(unescape, "s", (char *s), -{ +ICOMMAND(unescape, "s", (char *s), { int len = strlen(s); char *d = newstring(len); d[unescapestring(d, s, &s[len])] = '\0'; stringret(d); }); -const char *escapeid(const char *s) -{ +const char *escapeid(const char *s) { const char *end = s + strcspn(s, "\"/;()[]@ \f\t\r\n\0"); return *end ? escapestring(s) : s; } -bool validateblock(const char *s) -{ +bool validateblock(const char *s) { const int maxbrak = 100; static char brakstack[maxbrak]; int brakdepth = 0; - for(; *s; s++) switch(*s) - { + for(; *s; s++) switch(*s) { case '[': case '(': if(brakdepth >= maxbrak) return false; brakstack[brakdepth++] = *s; break; case ']': if(brakdepth <= 0 || brakstack[--brakdepth] != '[') return false; break; case ')': if(brakdepth <= 0 || brakstack[--brakdepth] != '(') return false; break; @@ -2451,8 +2154,7 @@ bool validateblock(const char *s) } #ifndef STANDALONE -void writecfg(const char *name) -{ +void writecfg(const char *name) { stream *f = openutf8file(path(name && name[0] ? name : game::savedconfig(), true), "w"); if(!f) return; f->printf("// automatically written on exit, DO NOT MODIFY\n// delete this file to have %s overwrite these settings\n// modify settings in game, or put settings in %s to override anything\n\n", game::defaultconfig(), game::autoexec()); @@ -2462,11 +2164,9 @@ void writecfg(const char *name) vector<ident *> ids; enumerate(idents, ident, id, ids.add(&id)); ids.sortname(); - loopv(ids) - { + loopv(ids) { ident &id = *ids[i]; - if(id.flags&IDF_PERSIST) switch(id.type) - { + if(id.flags&IDF_PERSIST) switch(id.type) { case ID_VAR: f->printf("%s %d\n", escapeid(id), *id.storage.i); break; case ID_FVAR: f->printf("%s %s\n", escapeid(id), floatstr(*id.storage.f)); break; case ID_SVAR: f->printf("%s %s\n", escapeid(id), escapestring(*id.storage.s)); break; @@ -2475,11 +2175,9 @@ void writecfg(const char *name) f->printf("\n"); writebinds(f); f->printf("\n"); - loopv(ids) - { + loopv(ids) { ident &id = *ids[i]; - if(id.type==ID_ALIAS && id.flags&IDF_PERSIST && !(id.flags&IDF_OVERRIDDEN)) switch(id.valtype) - { + if(id.type==ID_ALIAS && id.flags&IDF_PERSIST && !(id.flags&IDF_OVERRIDDEN)) switch(id.valtype) { case VAL_STR: if(!id.val.s[0]) break; if(!validateblock(id.val.s)) { f->printf("%s = %s\n", escapeid(id), escapestring(id.val.s)); break; } @@ -2498,8 +2196,7 @@ void writecfg(const char *name) COMMAND(writecfg, "s"); #endif -void changedvars() -{ +void changedvars() { vector<ident *> ids; enumerate(idents, ident, id, if(id.flags&IDF_OVERRIDDEN) ids.add(&id)); ids.sortname(); @@ -2513,27 +2210,23 @@ COMMAND(changedvars, ""); static string retbuf[4]; static int retidx = 0; -const char *intstr(int v) -{ +const char *intstr(int v) { retidx = (retidx + 1)%4; intformat(retbuf[retidx], v); return retbuf[retidx]; } -void intret(int v) -{ +void intret(int v) { commandret->setint(v); } -const char *floatstr(float v) -{ +const char *floatstr(float v) { retidx = (retidx + 1)%4; floatformat(retbuf[retidx], v); return retbuf[retidx]; } -void floatret(float v) -{ +void floatret(float v) { commandret->setfloat(v); } @@ -2544,11 +2237,9 @@ ICOMMAND(do, "e", (uint *body), executeret(body, *commandret)); ICOMMAND(if, "tee", (tagval *cond, uint *t, uint *f), executeret(getbool(*cond) ? t : f, *commandret)); ICOMMAND(?, "ttt", (tagval *cond, tagval *t, tagval *f), result(*(getbool(*cond) ? t : f))); -ICOMMAND(pushif, "rte", (ident *id, tagval *v, uint *code), -{ +ICOMMAND(pushif, "rte", (ident *id, tagval *v, uint *code), { if(id->type != ID_ALIAS || id->index < MAXARGS) return; - if(getbool(*v)) - { + if(getbool(*v)) { identstack stack; pusharg(*id, *v, stack); v->type = VAL_NULL; @@ -2558,63 +2249,51 @@ ICOMMAND(pushif, "rte", (ident *id, tagval *v, uint *code), } }); -void loopiter(ident *id, identstack &stack, const tagval &v) -{ - if(id->stack != &stack) - { +void loopiter(ident *id, identstack &stack, const tagval &v) { + if(id->stack != &stack) { pusharg(*id, v, stack); id->flags &= ~IDF_UNKNOWN; } - else - { + else { if(id->valtype == VAL_STR) delete[] id->val.s; cleancode(*id); id->setval(v); } } -void loopend(ident *id, identstack &stack) -{ +void loopend(ident *id, identstack &stack) { if(id->stack == &stack) poparg(*id); } -static inline void setiter(ident &id, int i, identstack &stack) -{ - if(id.stack == &stack) - { - if(id.valtype != VAL_INT) - { +static inline void setiter(ident &id, int i, identstack &stack) { + if(id.stack == &stack) { + if(id.valtype != VAL_INT) { if(id.valtype == VAL_STR) delete[] id.val.s; cleancode(id); id.valtype = VAL_INT; } id.val.i = i; } - else - { + else { tagval t; t.setint(i); pusharg(id, t, stack); id.flags &= ~IDF_UNKNOWN; } } -ICOMMAND(loop, "rie", (ident *id, int *n, uint *body), -{ +ICOMMAND(loop, "rie", (ident *id, int *n, uint *body), { if(*n <= 0 || id->type!=ID_ALIAS) return; identstack stack; - loopi(*n) - { + loopi(*n) { setiter(*id, i, stack); execute(body); } poparg(*id); }); -ICOMMAND(loopwhile, "riee", (ident *id, int *n, uint *cond, uint *body), -{ +ICOMMAND(loopwhile, "riee", (ident *id, int *n, uint *cond, uint *body), { if(*n <= 0 || id->type!=ID_ALIAS) return; identstack stack; - loopi(*n) - { + loopi(*n) { setiter(*id, i, stack); if(!executebool(cond)) break; execute(body); @@ -2623,12 +2302,10 @@ ICOMMAND(loopwhile, "riee", (ident *id, int *n, uint *cond, uint *body), }); ICOMMAND(while, "ee", (uint *cond, uint *body), while(executebool(cond)) execute(body)); -char *loopconc(ident *id, int n, uint *body, bool space) -{ +char *loopconc(ident *id, int n, uint *body, bool space) { identstack stack; vector<char> s; - loopi(n) - { + loopi(n) { setiter(*id, i, stack); tagval v; executeret(body, v); @@ -2643,39 +2320,32 @@ char *loopconc(ident *id, int n, uint *body, bool space) return newstring(s.getbuf(), s.length()-1); } -ICOMMAND(loopconcat, "rie", (ident *id, int *n, uint *body), -{ +ICOMMAND(loopconcat, "rie", (ident *id, int *n, uint *body), { if(*n > 0 && id->type==ID_ALIAS) commandret->setstr(loopconc(id, *n, body, true)); }); -ICOMMAND(loopconcatword, "rie", (ident *id, int *n, uint *body), -{ +ICOMMAND(loopconcatword, "rie", (ident *id, int *n, uint *body), { if(*n > 0 && id->type==ID_ALIAS) commandret->setstr(loopconc(id, *n, body, false)); }); -void concat(tagval *v, int n) -{ +void concat(tagval *v, int n) { commandret->setstr(conc(v, n, true)); } COMMAND(concat, "V"); -void concatword(tagval *v, int n) -{ +void concatword(tagval *v, int n) { commandret->setstr(conc(v, n, false)); } COMMAND(concatword, "V"); -void append(ident *id, tagval *v, bool space) -{ +void append(ident *id, tagval *v, bool space) { if(id->type != ID_ALIAS || v->type == VAL_NULL) return; - if(id->valtype == VAL_NULL) - { + if(id->valtype == VAL_NULL) { noprefix: if(id->index < MAXARGS) setarg(*id, *v); else setalias(*id, *v); v->type = VAL_NULL; } - else - { + else { const char *prefix = id->getstr(); if(!prefix[0]) goto noprefix; tagval r; @@ -2686,40 +2356,32 @@ void append(ident *id, tagval *v, bool space) ICOMMAND(append, "rt", (ident *id, tagval *v), append(id, v, true)); ICOMMAND(appendword, "rt", (ident *id, tagval *v), append(id, v, false)); -void result(tagval &v) -{ +void result(tagval &v) { *commandret = v; v.type = VAL_NULL; } -void stringret(char *s) -{ +void stringret(char *s) { commandret->setstr(s); } -void result(const char *s) -{ +void result(const char *s) { commandret->setstr(newstring(s)); } -ICOMMAND(result, "t", (tagval *v), -{ +ICOMMAND(result, "t", (tagval *v), { *commandret = *v; v->type = VAL_NULL; }); -void format(tagval *args, int numargs) -{ +void format(tagval *args, int numargs) { vector<char> s; const char *f = args[0].getstr(); - while(*f) - { + while(*f) { int c = *f++; - if(c == '%') - { + if(c == '%') { int i = *f++; - if(i >= '1' && i <= '9') - { + if(i >= '1' && i <= '9') { i -= '0'; const char *sub = i < numargs ? args[i].getstr() : ""; while(*sub) s.add(*sub++); @@ -2735,31 +2397,25 @@ COMMAND(format, "V"); static const char *liststart = NULL, *listend = NULL, *listquotestart = NULL, *listquoteend = NULL; -static inline void skiplist(const char *&p) -{ - for(;;) - { +static inline void skiplist(const char *&p) { + for(;;) { p += strspn(p, " \t\r\n"); if(p[0]!='/' || p[1]!='/') break; p += strcspn(p, "\n\0"); } } -static bool parselist(const char *&s, const char *&start = liststart, const char *&end = listend, const char *"estart = listquotestart, const char *"eend = listquoteend) -{ +static bool parselist(const char *&s, const char *&start = liststart, const char *&end = listend, const char *"estart = listquotestart, const char *"eend = listquoteend) { skiplist(s); - switch(*s) - { + switch(*s) { case '"': quotestart = s++; start = s; s = parsestring(s); end = s; if(*s == '"') s++; quoteend = s; break; case '(': case '[': quotestart = s; start = s+1; - for(int braktype = *s++, brak = 1;;) - { + for(int braktype = *s++, brak = 1;;) { s += strcspn(s, "\"/;()[]\0"); int c = *s++; - switch(c) - { + switch(c) { case '\0': s--; quoteend = end = s; return true; case '"': s = parsestring(s); if(*s == '"') s++; break; case '/': if(*s == '/') s += strcspn(s, "\n\0"); break; @@ -2780,34 +2436,29 @@ static bool parselist(const char *&s, const char *&start = liststart, const char return true; } -void explodelist(const char *s, vector<char *> &elems, int limit) -{ +void explodelist(const char *s, vector<char *> &elems, int limit) { const char *start, *end; while((limit < 0 || elems.length() < limit) && parselist(s, start, end)) elems.add(newstring(start, end-start)); } -char *indexlist(const char *s, int pos) -{ +char *indexlist(const char *s, int pos) { loopi(pos) if(!parselist(s)) return newstring(""); const char *start, *end; return parselist(s, start, end) ? newstring(start, end-start) : newstring(""); } -int listlen(const char *s) -{ +int listlen(const char *s) { int n = 0; while(parselist(s)) n++; return n; } ICOMMAND(listlen, "s", (char *s), intret(listlen(s))); -void at(tagval *args, int numargs) -{ +void at(tagval *args, int numargs) { if(!numargs) return; const char *start = args[0].getstr(), *end = start + strlen(start); - for(int i = 1; i < numargs; i++) - { + for(int i = 1; i < numargs; i++) { const char *list = start; int pos = args[i].getint(); for(; pos > 0; pos--) if(!parselist(list)) break; @@ -2817,28 +2468,23 @@ void at(tagval *args, int numargs) } COMMAND(at, "si1V"); -void substr(char *s, int *start, int *count, int *numargs) -{ +void substr(char *s, int *start, int *count, int *numargs) { int len = strlen(s), offset = clamp(*start, 0, len); commandret->setstr(newstring(&s[offset], *numargs >= 3 ? clamp(*count, 0, len - offset) : len - offset)); } COMMAND(substr, "siiN"); -void chopstr(char *s, int *lim, char *ellipsis) -{ +void chopstr(char *s, int *lim, char *ellipsis) { int len = strlen(s), maxlen = abs(*lim); - if(len > maxlen) - { + if(len > maxlen) { int elen = strlen(ellipsis); maxlen = max(maxlen, elen); char *chopped = newstring(maxlen); - if(*lim < 0) - { + if(*lim < 0) { memcpy(chopped, ellipsis, elen); memcpy(&chopped[elen], &s[len - (maxlen - elen)], maxlen - elen); } - else - { + else { memcpy(chopped, s, maxlen - elen); memcpy(&chopped[maxlen - elen], ellipsis, elen); } @@ -2849,8 +2495,7 @@ void chopstr(char *s, int *lim, char *ellipsis) } COMMAND(chopstr, "sis"); -void sublist(const char *s, int *skip, int *count, int *numargs) -{ +void sublist(const char *s, int *skip, int *count, int *numargs) { int offset = max(*skip, 0), len = *numargs >= 3 ? max(*count, 0) : -1; loopi(offset) if(!parselist(s)) break; if(len < 0) { if(offset > 0) skiplist(s); commandret->setstr(newstring(s)); return; } @@ -2860,25 +2505,21 @@ void sublist(const char *s, int *skip, int *count, int *numargs) } COMMAND(sublist, "siiN"); -ICOMMAND(stripcolors, "s", (char *s), -{ +ICOMMAND(stripcolors, "s", (char *s), { int len = strlen(s); char *d = newstring(len); filtertext(d, s, true, false, len); stringret(d); }); -static inline void setiter(ident &id, char *val, identstack &stack) -{ - if(id.stack == &stack) - { +static inline void setiter(ident &id, char *val, identstack &stack) { + if(id.stack == &stack) { if(id.valtype == VAL_STR) delete[] id.val.s; else id.valtype = VAL_STR; cleancode(id); id.val.s = val; } - else - { + else { tagval t; t.setstr(val); pusharg(id, t, stack); @@ -2886,13 +2527,11 @@ static inline void setiter(ident &id, char *val, identstack &stack) } } -void listfind(ident *id, const char *list, const uint *body) -{ +void listfind(ident *id, const char *list, const uint *body) { if(id->type!=ID_ALIAS) { intret(-1); return; } identstack stack; int n = -1; - for(const char *s = list, *start, *end; parselist(s, start, end);) - { + for(const char *s = list, *start, *end; parselist(s, start, end);) { ++n; char *val = newstring(start, end-start); setiter(*id, val, stack); @@ -2904,13 +2543,11 @@ found: } COMMAND(listfind, "rse"); -void looplist(ident *id, const char *list, const uint *body) -{ +void looplist(ident *id, const char *list, const uint *body) { if(id->type!=ID_ALIAS) return; identstack stack; int n = 0; - for(const char *s = list, *start, *end; parselist(s, start, end); n++) - { + for(const char *s = list, *start, *end; parselist(s, start, end); n++) { char *val = newstring(start, end-start); setiter(*id, val, stack); execute(body); @@ -2919,13 +2556,11 @@ void looplist(ident *id, const char *list, const uint *body) } COMMAND(looplist, "rse"); -void loopsublist(ident *id, const char *list, int *skip, int *count, const uint *body) -{ +void loopsublist(ident *id, const char *list, int *skip, int *count, const uint *body) { if(id->type!=ID_ALIAS) return; identstack stack; int n = 0, offset = max(*skip, 0), len = *count < 0 ? INT_MAX : offset + *count; - for(const char *s = list, *start, *end; parselist(s, start, end) && n < len; n++) if(n >= offset) - { + for(const char *s = list, *start, *end; parselist(s, start, end) && n < len; n++) if(n >= offset) { char *val = newstring(start, end-start); setiter(*id, val, stack); execute(body); @@ -2934,19 +2569,15 @@ void loopsublist(ident *id, const char *list, int *skip, int *count, const uint } COMMAND(loopsublist, "rsiie"); -void looplistconc(ident *id, const char *list, const uint *body, bool space) -{ +void looplistconc(ident *id, const char *list, const uint *body, bool space) { if(id->type!=ID_ALIAS) return; identstack stack; vector<char> r; int n = 0; - for(const char *s = list, *start, *end; parselist(s, start, end); n++) - { + for(const char *s = list, *start, *end; parselist(s, start, end); n++) { char *val = newstring(start, end-start); setiter(*id, val, stack); - if(n && space) r.add(' '); - tagval v; executeret(body, v); const char *vstr = v.getstr(); @@ -2961,19 +2592,15 @@ void looplistconc(ident *id, const char *list, const uint *body, bool space) ICOMMAND(looplistconcat, "rse", (ident *id, char *list, uint *body), looplistconc(id, list, body, true)); ICOMMAND(looplistconcatword, "rse", (ident *id, char *list, uint *body), looplistconc(id, list, body, false)); -void listfilter(ident *id, const char *list, const uint *body) -{ +void listfilter(ident *id, const char *list, const uint *body) { if(id->type!=ID_ALIAS) return; identstack stack; vector<char> r; int n = 0; - for(const char *s = list, *start, *end, *quotestart, *quoteend; parselist(s, start, end, quotestart, quoteend); n++) - { + for(const char *s = list, *start, *end, *quotestart, *quoteend; parselist(s, start, end, quotestart, quoteend); n++) { char *val = newstring(start, end-start); setiter(*id, val, stack); - - if(executebool(body)) - { + if(executebool(body)) { if(r.length()) r.add(' '); r.put(quotestart, quoteend-quotestart); } @@ -2984,18 +2611,14 @@ void listfilter(ident *id, const char *list, const uint *body) } COMMAND(listfilter, "rse"); -void prettylist(const char *s, const char *conj) -{ +void prettylist(const char *s, const char *conj) { vector<char> p; const char *start, *end; - for(int len = listlen(s), n = 0; parselist(s, start, end); n++) - { + for(int len = listlen(s), n = 0; parselist(s, start, end); n++) { p.put(start, end - start); - if(n+1 < len) - { + if(n+1 < len) { if(len > 2 || !conj[0]) p.add(','); - if(n+2 == len && conj[0]) - { + if(n+2 == len && conj[0]) { p.add(' '); p.put(conj, strlen(conj)); } @@ -3007,11 +2630,9 @@ void prettylist(const char *s, const char *conj) } COMMAND(prettylist, "ss"); -int listincludes(const char *list, const char *needle, int needlelen) -{ +int listincludes(const char *list, const char *needle, int needlelen) { int offset = 0; - for(const char *s = list, *start, *end; parselist(s, start, end);) - { + for(const char *s = list, *start, *end; parselist(s, start, end);) { int len = end - start; if(needlelen == len && !strncmp(needle, start, len)) return offset; offset++; @@ -3020,13 +2641,10 @@ int listincludes(const char *list, const char *needle, int needlelen) } ICOMMAND(indexof, "ss", (char *list, char *elem), intret(listincludes(list, elem, strlen(elem)))); -char *listdel(const char *s, const char *del) -{ +char *listdel(const char *s, const char *del) { vector<char> p; - for(const char *start, *end, *qstart, *qend; parselist(s, start, end, qstart, qend);) - { - if(listincludes(del, start, end-start) < 0) - { + for(const char *start, *end, *qstart, *qend; parselist(s, start, end, qstart, qend);) { + if(listincludes(del, start, end-start) < 0) { if(!p.empty()) p.add(' '); p.put(qstart, qend-qstart); } @@ -3036,22 +2654,19 @@ char *listdel(const char *s, const char *del) } ICOMMAND(listdel, "ss", (char *list, char *del), commandret->setstr(listdel(list, del))); -void listsplice(const char *s, const char *vals, int *skip, int *count) -{ +void listsplice(const char *s, const char *vals, int *skip, int *count) { int offset = max(*skip, 0), len = max(*count, 0); const char *list = s, *start, *end, *qstart, *qend = s; loopi(offset) if(!parselist(s, start, end, qstart, qend)) break; vector<char> p; if(qend > list) p.put(list, qend-list); - if(*vals) - { + if(*vals) { if(!p.empty()) p.add(' '); p.put(vals, strlen(vals)); } loopi(len) if(!parselist(s)) break; skiplist(s); - switch(*s) - { + switch(*s) { case '\0': case ')': case ']': break; default: if(!p.empty()) p.add(' '); @@ -3063,30 +2678,25 @@ void listsplice(const char *s, const char *vals, int *skip, int *count) } COMMAND(listsplice, "ssii"); -ICOMMAND(loopfiles, "rsse", (ident *id, char *dir, char *ext, uint *body), -{ +ICOMMAND(loopfiles, "rsse", (ident *id, char *dir, char *ext, uint *body), { if(id->type!=ID_ALIAS) return; identstack stack; vector<char *> files; listfiles(dir, ext[0] ? ext : NULL, files); - loopvrev(files) - { + loopvrev(files) { char *file = files[i]; bool redundant = false; loopj(i) if(!strcmp(files[j], file)) { redundant = true; break; } if(redundant) delete[] files.removeunordered(i); } - loopv(files) - { + loopv(files) { char *file = files[i]; - if(i) - { + if(i) { if(id->valtype == VAL_STR) delete[] id->val.s; else id->valtype = VAL_STR; id->val.s = file; } - else - { + else { tagval t; t.setstr(file); pusharg(*id, t, stack); @@ -3097,8 +2707,7 @@ ICOMMAND(loopfiles, "rsse", (ident *id, char *dir, char *ext, uint *body), if(files.length()) poparg(*id); }); -void findfile_(char *name) -{ +void findfile_(char *name) { string fname; copystring(fname, name); path(fname); @@ -3111,18 +2720,14 @@ void findfile_(char *name) } COMMANDN(findfile, findfile_, "s"); -struct sortitem -{ +struct sortitem { const char *str, *quotestart, *quoteend; }; -struct sortfun -{ +struct sortfun { ident *x, *y; uint *body; - - bool operator()(const sortitem &xval, const sortitem &yval) - { + bool operator()(const sortitem &xval, const sortitem &yval) { if(x->valtype != VAL_MACRO) x->valtype = VAL_MACRO; cleancode(*x); x->val.code = (const uint *)xval.str; @@ -3133,43 +2738,33 @@ struct sortfun } }; -void sortlist(char *list, ident *x, ident *y, uint *body) -{ +void sortlist(char *list, ident *x, ident *y, uint *body) { if(x == y || x->type != ID_ALIAS || y->type != ID_ALIAS) return; - vector<sortitem> items; int macrolen = strlen(list), total = 0; char *macros = newstring(list, macrolen); const char *curlist = list, *start, *end, *quotestart, *quoteend; - while(parselist(curlist, start, end, quotestart, quoteend)) - { + while(parselist(curlist, start, end, quotestart, quoteend)) { macros[end - list] = '\0'; sortitem item = { ¯os[start - list], quotestart, quoteend }; items.add(item); total += int(quoteend - quotestart); } - identstack xstack, ystack; pusharg(*x, nullval, xstack); x->flags &= ~IDF_UNKNOWN; pusharg(*y, nullval, ystack); y->flags &= ~IDF_UNKNOWN; - sortfun f = { x, y, body }; items.sort(f); - poparg(*x); poparg(*y); - char *sorted = macros; int sortedlen = total + max(items.length() - 1, 0); - if(macrolen < sortedlen) - { + if(macrolen < sortedlen) { delete[] macros; sorted = newstring(sortedlen); } - int offset = 0; - loopv(items) - { + loopv(items) { sortitem &item = items[i]; int len = int(item.quoteend - item.quotestart); if(i) sorted[offset++] = ' '; @@ -3177,7 +2772,6 @@ void sortlist(char *list, ident *x, ident *y, uint *body) offset += len; } sorted[offset] = '\0'; - commandret->setstr(sorted); } COMMAND(sortlist, "srre"); @@ -3210,21 +2804,17 @@ ICOMMAND(&~, "ii", (int *a, int *b), intret(*a & ~*b)); ICOMMAND(|~, "ii", (int *a, int *b), intret(*a | ~*b)); ICOMMAND(<<, "ii", (int *a, int *b), intret(*b < 32 ? *a << max(*b, 0) : 0)); ICOMMAND(>>, "ii", (int *a, int *b), intret(*a >> clamp(*b, 0, 31))); -ICOMMAND(&&, "e1V", (tagval *args, int numargs), -{ +ICOMMAND(&&, "e1V", (tagval *args, int numargs), { if(!numargs) intret(1); - else loopi(numargs) - { + else loopi(numargs) { if(i) freearg(*commandret); executeret(args[i].code, *commandret); if(!getbool(*commandret)) break; } }); -ICOMMAND(||, "e1V", (tagval *args, int numargs), -{ +ICOMMAND(||, "e1V", (tagval *args, int numargs), { if(!numargs) intret(0); - else loopi(numargs) - { + else loopi(numargs) { if(i) freearg(*commandret); executeret(args[i].code, *commandret); if(getbool(*commandret)) break; @@ -3248,26 +2838,22 @@ ICOMMAND(loge, "f", (float *a), floatret(log(*a))); ICOMMAND(log2, "f", (float *a), floatret(log(*a)/M_LN2)); ICOMMAND(log10, "f", (float *a), floatret(log10(*a))); ICOMMAND(exp, "f", (float *a), floatret(exp(*a))); -ICOMMAND(min, "V", (tagval *args, int numargs), -{ +ICOMMAND(min, "V", (tagval *args, int numargs), { int val = numargs > 0 ? args[numargs - 1].getint() : 0; loopi(numargs - 1) val = min(val, args[i].getint()); intret(val); }); -ICOMMAND(max, "V", (tagval *args, int numargs), -{ +ICOMMAND(max, "V", (tagval *args, int numargs), { int val = numargs > 0 ? args[numargs - 1].getint() : 0; loopi(numargs - 1) val = max(val, args[i].getint()); intret(val); }); -ICOMMAND(minf, "V", (tagval *args, int numargs), -{ +ICOMMAND(minf, "V", (tagval *args, int numargs), { float val = numargs > 0 ? args[numargs - 1].getfloat() : 0.0f; loopi(numargs - 1) val = min(val, args[i].getfloat()); floatret(val); }); -ICOMMAND(maxf, "V", (tagval *args, int numargs), -{ +ICOMMAND(maxf, "V", (tagval *args, int numargs), { float val = numargs > 0 ? args[numargs - 1].getfloat() : 0.0f; loopi(numargs - 1) val = max(val, args[i].getfloat()); floatret(val); @@ -3277,12 +2863,10 @@ ICOMMAND(absf, "f", (float *n), floatret(fabs(*n))); ICOMMAND(floor, "f", (float *n), floatret(floor(*n))); ICOMMAND(ceil, "f", (float *n), floatret(ceil(*n))); -ICOMMAND(round, "ff", (float *n, float *k), -{ +ICOMMAND(round, "ff", (float *n, float *k), { double step = *k; double r = *n; - if(step > 0) - { + if(step > 0) { r += step * (r < 0 ? -0.5 : 0.5); r -= fmod(r, step); } @@ -3290,34 +2874,29 @@ ICOMMAND(round, "ff", (float *n, float *k), floatret(float(r)); }); -ICOMMAND(cond, "ee2V", (tagval *args, int numargs), -{ - for(int i = 0; i < numargs; i += 2) - { - if(i+1 < numargs) - { - if(executebool(args[i].code)) - { +ICOMMAND(cond, "ee2V", (tagval *args, int numargs), { + for(int i = 0; i < numargs; i += 2) { + if(i+1 < numargs) { + if(executebool(args[i].code)) { executeret(args[i+1].code, *commandret); break; } } - else - { + else { executeret(args[i].code, *commandret); break; } } }); #define CASECOMMAND(name, fmt, type, acc, compare) \ - ICOMMAND(name, fmt "te2V", (tagval *args, int numargs), \ - { \ + ICOMMAND(name, fmt "te2V", (tagval *args, int numargs), { \ + \ type val = acc; \ int i; \ - for(i = 1; i+1 < numargs; i += 2) \ - { \ - if(compare) \ - { \ + for(i = 1; i+1 < numargs; i += 2) { \ + \ + if(compare) { \ + \ executeret(args[i+1].code, *commandret); \ return; \ } \ @@ -3328,15 +2907,12 @@ CASECOMMAND(casef, "f", float, args[0].getfloat(), args[i].type == VAL_NULL || a CASECOMMAND(cases, "s", const char *, args[0].getstr(), args[i].type == VAL_NULL || !strcmp(args[i].getstr(), val)); ICOMMAND(rnd, "ii", (int *a, int *b), intret(*a - *b > 0 ? rnd(*a - *b) + *b : *b)); -ICOMMAND(rndstr, "i", (int *len), -{ +ICOMMAND(rndstr, "i", (int *len), { int n = clamp(*len, 0, 10000); char *s = newstring(n); - for(int i = 0; i < n;) - { + for(int i = 0; i < n;) { uint r = randomMT(); - for(int j = min(i + 4, n); i < j; i++) - { + for(int j = min(i + 4, n); i < j; i++) { s[i] = (r%255) + 1; r /= 255; } @@ -3361,15 +2937,12 @@ ICOMMAND(codestr, "i", (int *i), { char *s = newstring(1); s[0] = char(*i); s[1] ICOMMAND(struni, "si", (char *s, int *i), intret(*i > 0 ? (memchr(s, 0, *i) ? 0 : cube2uni(s[*i])) : cube2uni(s[0]))); ICOMMAND(unistr, "i", (int *i), { char *s = newstring(1); s[0] = uni2cube(*i); s[1] = '\0'; stringret(s); }); -int naturalsort(const char *a, const char *b) -{ - for(;;) - { +int naturalsort(const char *a, const char *b) { + for(;;) { int ac = *a, bc = *b; if(!ac) return bc ? -1 : 0; else if(!bc) return 1; - else if(isdigit(ac) && isdigit(bc)) - { + else if(isdigit(ac) && isdigit(bc)) { while(*a == '0') a++; while(*b == '0') b++; const char *a0 = a, *b0 = b; @@ -3388,8 +2961,8 @@ int naturalsort(const char *a, const char *b) ICOMMAND(naturalsort, "ss", (char *a, char *b), intret(naturalsort(a,b)<=0)); #define STRMAPCOMMAND(name, map) \ - ICOMMAND(name, "s", (char *s), \ - { \ + ICOMMAND(name, "s", (char *s), { \ + \ int len = strlen(s); \ char *m = newstring(len); \ loopi(len) m[i] = map(s[i]); \ @@ -3400,23 +2973,18 @@ ICOMMAND(naturalsort, "ss", (char *a, char *b), intret(naturalsort(a,b)<=0)); STRMAPCOMMAND(strlower, cubelower); STRMAPCOMMAND(strupper, cubeupper); -char *strreplace(const char *s, const char *oldval, const char *newval) -{ +char *strreplace(const char *s, const char *oldval, const char *newval) { vector<char> buf; - int oldlen = strlen(oldval); if(!oldlen) return newstring(s); - for(;;) - { + for(;;) { const char *found = strstr(s, oldval); - if(found) - { + if(found) { while(s < found) buf.add(*s++); for(const char *n = newval; *n; n++) buf.add(*n); s = found + oldlen; } - else - { + else { while(*s) buf.add(*s++); buf.add('\0'); return newstring(buf.getbuf(), buf.length()); @@ -3426,8 +2994,7 @@ char *strreplace(const char *s, const char *oldval, const char *newval) ICOMMAND(strreplace, "sss", (char *s, char *o, char *n), commandret->setstr(strreplace(s, o, n))); -void strsplice(const char *s, const char *vals, int *skip, int *count) -{ +void strsplice(const char *s, const char *vals, int *skip, int *count) { int slen = strlen(s), vlen = strlen(vals), offset = clamp(*skip, 0, slen), len = clamp(*count, 0, slen - offset); @@ -3443,15 +3010,13 @@ COMMAND(strsplice, "ssii"); #ifndef STANDALONE ICOMMAND(getmillis, "i", (int *total), intret(*total ? totalmillis : lastmillis)); -struct sleepcmd -{ +struct sleepcmd { int delay, millis, flags; char *command; }; vector<sleepcmd> sleepcmds; -void addsleep(int *msec, char *cmd) -{ +void addsleep(int *msec, char *cmd) { sleepcmd &s = sleepcmds.add(); s.delay = max(*msec, 1); s.millis = lastmillis; @@ -3461,13 +3026,10 @@ void addsleep(int *msec, char *cmd) COMMANDN(sleep, addsleep, "is"); -void checksleep(int millis) -{ - loopv(sleepcmds) - { +void checksleep(int millis) { + loopv(sleepcmds) { sleepcmd &s = sleepcmds[i]; - if(millis - s.millis >= s.delay) - { + if(millis - s.millis >= s.delay) { char *cmd = s.command; // execute might create more sleep commands s.command = NULL; int oldflags = identflags; @@ -3480,19 +3042,16 @@ void checksleep(int millis) } } -void clearsleep(bool clearoverrides) -{ +void clearsleep(bool clearoverrides) { int len = 0; - loopv(sleepcmds) if(sleepcmds[i].command) - { + loopv(sleepcmds) if(sleepcmds[i].command) { if(clearoverrides && !(sleepcmds[i].flags&IDF_OVERRIDDEN)) sleepcmds[len++] = sleepcmds[i]; else delete[] sleepcmds[i].command; } sleepcmds.shrink(len); } -void clearsleep_(int *clearoverrides) -{ +void clearsleep_(int *clearoverrides) { clearsleep(*clearoverrides!=0 || identflags&IDF_OVERRIDDEN); } diff --git a/src/engine/console.cpp b/src/engine/console.cpp index c979215..1386570 100644 --- a/src/engine/console.cpp +++ b/src/engine/console.cpp @@ -18,15 +18,12 @@ VARFP(maxcon, 10, 200, MAXCONLINES, { while(conlines.length() > maxcon) delete[] VARP(contags, 0, 3, 3); -void conline(int type, const char *sf) // add a line to the console buffer -{ +void conline(int type, const char *sf) { // add a line to the console buffer { char *buf = NULL; - if(type&CON_TAG_MASK) for(int i = conlines.length()-1; i >= max(conlines.length()-contags, 0); i--) - { + if(type&CON_TAG_MASK) for(int i = conlines.length()-1; i >= max(conlines.length()-contags, 0); i--) { int prev = conlines.removing(i).type; if(!(prev&CON_TAG_MASK)) break; - if(type == prev) - { + if(type == prev) { buf = conlines.remove(i).line; break; } @@ -39,8 +36,7 @@ void conline(int type, const char *sf) // add a line to the console buffer copystring(cl.line, sf, CONSTRLEN); } -void conoutfv(int type, const char *fmt, va_list args) -{ +void conoutfv(int type, const char *fmt, va_list args) { static char buf[CONSTRLEN]; vformatstring(buf, fmt, args, sizeof(buf)); conline(type, buf); @@ -50,10 +46,8 @@ void conoutfv(int type, const char *fmt, va_list args) VAR(fullconsole, 0, 0, 1); ICOMMAND(toggleconsole, "", (), { fullconsole ^= 1; }); -int rendercommand(int x, int y, int w) -{ +int rendercommand(int x, int y, int w) { if(commandmillis < 0) return 0; - defformatstring(s, "%s %s", commandprompt ? commandprompt : ">", commandbuf); int width, height; text_bounds(s, width, height, w); @@ -74,16 +68,13 @@ HVARP(miniconfilter, 0, 0, 0x7FFFFFF); int conskip = 0, miniconskip = 0; -void setconskip(int &skip, int filter, int n) -{ +void setconskip(int &skip, int filter, int n) { filter &= CON_FLAGS; int offset = abs(n), dir = n < 0 ? -1 : 1; skip = clamp(skip, 0, conlines.length()-1); - while(offset) - { + while(offset) { skip += dir; - if(!conlines.inrange(skip)) - { + if(!conlines.inrange(skip)) { skip = clamp(skip, 0, conlines.length()-1); return; } @@ -96,24 +87,18 @@ ICOMMAND(miniconskip, "i", (int *n), setconskip(miniconskip, miniconfilter, *n)) ICOMMAND(clearconsole, "", (), { while(conlines.length()) delete[] conlines.pop().line; }); -int drawconlines(int conskip, int confade, int conwidth, int conheight, int conoff, int filter, int y = 0, int dir = 1) -{ +int drawconlines(int conskip, int confade, int conwidth, int conheight, int conoff, int filter, int y = 0, int dir = 1) { filter &= CON_FLAGS; int numl = conlines.length(), offset = min(conskip, numl); - - if(confade) - { - if(!conskip) - { + if(confade) { + if(!conskip) { numl = 0; loopvrev(conlines) if(totalmillis-conlines[i].outtime < confade*1000) { numl = i+1; break; } } else offset--; } - int totalheight = 0; - loopi(numl) //determine visible height - { + loopi(numl) { //determine visible height { // shuffle backwards to fill if necessary int idx = offset+i < numl ? offset+i : --offset; if(!(conlines[idx].type&filter)) continue; @@ -124,8 +109,7 @@ int drawconlines(int conskip, int confade, int conwidth, int conheight, int cono totalheight += height; } if(dir > 0) y = conoff; - loopi(numl) - { + loopi(numl) { int idx = offset + (dir > 0 ? numl-i-1 : i); if(!(conlines[idx].type&filter)) continue; char *line = conlines[idx].line; @@ -138,16 +122,13 @@ int drawconlines(int conskip, int confade, int conwidth, int conheight, int cono return y+conoff; } -int renderconsole(int w, int h, int abovehud) // render buffer taking into account time & scrolling -{ +int renderconsole(int w, int h, int abovehud) { // render buffer taking into account time & scrolling { int conpad = fullconsole ? 0 : FONTH/4, conoff = fullconsole ? FONTH : FONTH/3, conheight = min(fullconsole ? ((h*fullconsize/100)/FONTH)*FONTH : FONTH*consize, h - 2*(conpad + conoff)), conwidth = w - 2*(conpad + conoff) - (fullconsole ? 0 : game::clipconsole(w, h)); - extern void consolebox(int x1, int y1, int x2, int y2); if(fullconsole) consolebox(conpad, conpad, conwidth+conpad+2*conoff, conheight+conpad+2*conoff); - int y = drawconlines(conskip, fullconsole ? 0 : confade, conwidth, conheight, conpad+conoff, fullconsole ? fullconfilter : confilter); if(!fullconsole && (miniconsize && miniconwidth)) drawconlines(miniconskip, miniconfade, (miniconwidth*(w - 2*(conpad + conoff)))/100, min(FONTH*miniconsize, abovehud - y), conpad+conoff, miniconfilter, abovehud, -1); @@ -156,29 +137,24 @@ int renderconsole(int w, int h, int abovehud) // render buffer taking into // keymap is defined externally in keymap.cfg -struct keym -{ - enum - { +struct keym { + enum { ACTION_DEFAULT = 0, ACTION_SPECTATOR, ACTION_EDITING, NUMACTIONS }; - int code; char *name; char *actions[NUMACTIONS]; bool pressed; - keym() : code(-1), name(NULL), pressed(false) { loopi(NUMACTIONS) actions[i] = newstring(""); } ~keym() { DELETEA(name); loopi(NUMACTIONS) DELETEA(actions[i]); } }; hashtable<int, keym> keyms(128); -void keymap(int *code, char *key) -{ +void keymap(int *code, char *key) { if(identflags&IDF_OVERRIDDEN) { conoutf(CON_ERROR, "cannot override keymap %d", *code); return; } keym &km = keyms[*code]; km.code = *code; @@ -191,19 +167,15 @@ COMMAND(keymap, "is"); keym *keypressed = NULL; char *keyaction = NULL; -const char *getkeyname(int code) -{ +const char *getkeyname(int code) { keym *km = keyms.access(code); return km ? km->name : NULL; } -void searchbinds(char *action, int type) -{ +void searchbinds(char *action, int type) { vector<char> names; - enumerate(keyms, keym, km, - { - if(!strcmp(km.actions[type], action)) - { + enumerate(keyms, keym, km, { + if(!strcmp(km.actions[type], action)) { if(names.length()) names.add(' '); names.put(km.name, strlen(km.name)); } @@ -212,23 +184,19 @@ void searchbinds(char *action, int type) result(names.getbuf()); } -keym *findbind(char *key) -{ - enumerate(keyms, keym, km, - { +keym *findbind(char *key) { + enumerate(keyms, keym, km, { if(!strcasecmp(km.name, key)) return &km; }); return NULL; } -void getbind(char *key, int type) -{ +void getbind(char *key, int type) { keym *km = findbind(key); result(km ? km->actions[type] : ""); } -void bindkey(char *key, char *action, int state, const char *cmd) -{ +void bindkey(char *key, char *action, int state, const char *cmd) { if(identflags&IDF_OVERRIDDEN) { conoutf(CON_ERROR, "cannot override %s \"%s\"", cmd, key); return; } keym *km = findbind(key); if(!km) { conoutf(CON_ERROR, "unknown key \"%s\"", key); return; } @@ -251,8 +219,7 @@ ICOMMAND(searchbinds, "s", (char *action), searchbinds(action, keym::ACTION_DEF ICOMMAND(searchspecbinds, "s", (char *action), searchbinds(action, keym::ACTION_SPECTATOR)); ICOMMAND(searcheditbinds, "s", (char *action), searchbinds(action, keym::ACTION_EDITING)); -void inputcommand(char *init, char *action = NULL, char *prompt = NULL, char *flags = NULL) // turns input to the command line on or off -{ +void inputcommand(char *init, char *action = NULL, char *prompt = NULL, char *flags = NULL) { // turns input to the command line on or off { commandmillis = init ? totalmillis : -1; textinput(commandmillis >= 0, TI_CONSOLE); keyrepeat(commandmillis >= 0, KR_CONSOLE); @@ -263,8 +230,7 @@ void inputcommand(char *init, char *action = NULL, char *prompt = NULL, char *fl if(action && action[0]) commandaction = newstring(action); if(prompt && prompt[0]) commandprompt = newstring(prompt); commandflags = 0; - if(flags) while(*flags) switch(*flags++) - { + if(flags) while(*flags) switch(*flags++) { case 'c': commandflags |= CF_COMPLETE; break; case 'x': commandflags |= CF_EXECUTE; break; case 's': commandflags |= CF_COMPLETE|CF_EXECUTE; break; @@ -275,8 +241,7 @@ void inputcommand(char *init, char *action = NULL, char *prompt = NULL, char *fl ICOMMAND(saycommand, "C", (char *init), inputcommand(init)); COMMAND(inputcommand, "ssss"); -void pasteconsole() -{ +void pasteconsole() { if(!SDL_HasClipboardText()) return; char *cb = SDL_GetClipboardText(); if(!cb) return; @@ -287,21 +252,16 @@ void pasteconsole() SDL_free(cb); } -struct hline -{ +struct hline { char *buf, *action, *prompt; int flags; - hline() : buf(NULL), action(NULL), prompt(NULL), flags(0) {} - ~hline() - { + ~hline() { DELETEA(buf); DELETEA(action); DELETEA(prompt); } - - void restore() - { + void restore() { copystring(commandbuf, buf); if(commandpos >= (int)strlen(commandbuf)) commandpos = -1; DELETEA(commandaction); @@ -310,28 +270,21 @@ struct hline if(prompt) commandprompt = newstring(prompt); commandflags = flags; } - - bool shouldsave() - { + bool shouldsave() { return strcmp(commandbuf, buf) || (commandaction ? !action || strcmp(commandaction, action) : action!=NULL) || (commandprompt ? !prompt || strcmp(commandprompt, prompt) : prompt!=NULL) || commandflags != flags; } - - void save() - { + void save() { buf = newstring(commandbuf); if(commandaction) action = newstring(commandaction); if(commandprompt) prompt = newstring(commandprompt); flags = commandflags; } - - void run() - { + void run() { if(flags&CF_EXECUTE && buf[0]=='/') execute(buf+1); - else if(action) - { + else if(action) { alias("commandbuf", buf); execute(action); } @@ -343,11 +296,9 @@ int histpos = 0; VARP(maxhistory, 0, 1000, 10000); -void history_(int *n) -{ +void history_(int *n) { static bool inhistory = false; - if(!inhistory && history.inrange(*n)) - { + if(!inhistory && history.inrange(*n)) { inhistory = true; history[history.length()-*n-1]->run(); inhistory = false; @@ -356,15 +307,13 @@ void history_(int *n) COMMANDN(history, history_, "i"); -struct releaseaction -{ +struct releaseaction { keym *key; char *action; }; vector<releaseaction> releaseactions; -const char *addreleaseaction(char *s) -{ +const char *addreleaseaction(char *s) { if(!keypressed) { delete[] s; return NULL; } releaseaction &ra = releaseactions.add(); ra.key = keypressed; @@ -372,30 +321,24 @@ const char *addreleaseaction(char *s) return keypressed->name; } -void onrelease(const char *s) -{ +void onrelease(const char *s) { addreleaseaction(newstring(s)); } COMMAND(onrelease, "s"); -void execbind(keym &k, bool isdown) -{ - loopv(releaseactions) - { +void execbind(keym &k, bool isdown) { + loopv(releaseactions) { releaseaction &ra = releaseactions[i]; - if(ra.key==&k) - { + if(ra.key==&k) { if(!isdown) execute(ra.action); delete[] ra.action; releaseactions.remove(i--); } } - if(isdown) - { + if(isdown) { int state = keym::ACTION_DEFAULT; - if(!mainmenu) - { + if(!mainmenu) { if(editmode) state = keym::ACTION_EDITING; else if(player->state==CS_SPECTATOR) state = keym::ACTION_SPECTATOR; } @@ -409,52 +352,39 @@ void execbind(keym &k, bool isdown) k.pressed = isdown; } -bool consoleinput(const char *str, int len) -{ +bool consoleinput(const char *str, int len) { if(commandmillis < 0) return false; - resetcomplete(); int cmdlen = (int)strlen(commandbuf), cmdspace = int(sizeof(commandbuf)) - (cmdlen+1); len = min(len, cmdspace); - if(commandpos<0) - { + if(commandpos<0) { memcpy(&commandbuf[cmdlen], str, len); } - else - { + else { memmove(&commandbuf[commandpos+len], &commandbuf[commandpos], cmdlen - commandpos); memcpy(&commandbuf[commandpos], str, len); commandpos += len; } commandbuf[cmdlen + len] = '\0'; - return true; } -bool consolekey(int code, bool isdown) -{ +bool consolekey(int code, bool isdown) { if(commandmillis < 0) return false; #define MOD_KEYS (KMOD_LCTRL|KMOD_RCTRL) - - if(isdown) - { - switch(code) - { + if(isdown) { + switch(code) { case SDLK_RETURN: case SDLK_KP_ENTER: break; - case SDLK_HOME: if(strlen(commandbuf)) commandpos = 0; break; - case SDLK_END: commandpos = -1; break; - - case SDLK_DELETE: - { + case SDLK_DELETE: { int len = (int)strlen(commandbuf); if(commandpos<0) break; memmove(&commandbuf[commandpos], &commandbuf[commandpos+1], len - commandpos); @@ -462,9 +392,7 @@ bool consolekey(int code, bool isdown) if(commandpos>=len-1) commandpos = -1; break; } - - case SDLK_BACKSPACE: - { + case SDLK_BACKSPACE: { int len = (int)strlen(commandbuf), i = commandpos>=0 ? commandpos : len; if(i<1) break; memmove(&commandbuf[i-1], &commandbuf[i], len - i + 1); @@ -473,49 +401,37 @@ bool consolekey(int code, bool isdown) else if(!commandpos && len<=1) commandpos = -1; break; } - case SDLK_LEFT: if(commandpos>0) commandpos--; else if(commandpos<0) commandpos = (int)strlen(commandbuf)-1; break; - case SDLK_RIGHT: if(commandpos>=0 && ++commandpos>=(int)strlen(commandbuf)) commandpos = -1; break; - case SDLK_UP: if(histpos > history.length()) histpos = history.length(); if(histpos > 0) history[--histpos]->restore(); break; - case SDLK_DOWN: if(histpos + 1 < history.length()) history[++histpos]->restore(); break; - case SDLK_TAB: - if(commandflags&CF_COMPLETE) - { + if(commandflags&CF_COMPLETE) { complete(commandbuf, sizeof(commandbuf), commandflags&CF_EXECUTE ? "/" : NULL); if(commandpos>=0 && commandpos>=(int)strlen(commandbuf)) commandpos = -1; } break; - case SDLK_v: if(SDL_GetModState()&MOD_KEYS) pasteconsole(); break; } } - else - { - if(code==SDLK_RETURN || code==SDLK_KP_ENTER) - { + else { + if(code==SDLK_RETURN || code==SDLK_KP_ENTER) { hline *h = NULL; - if(commandbuf[0]) - { - if(history.empty() || history.last()->shouldsave()) - { - if(maxhistory && history.length() >= maxhistory) - { + if(commandbuf[0]) { + if(history.empty() || history.last()->shouldsave()) { + if(maxhistory && history.length() >= maxhistory) { loopi(history.length()-maxhistory+1) delete history[i]; history.remove(0, history.length()-maxhistory+1); } @@ -527,59 +443,47 @@ bool consolekey(int code, bool isdown) inputcommand(NULL); if(h) h->run(); } - else if(code==SDLK_ESCAPE) - { + else if(code==SDLK_ESCAPE) { histpos = history.length(); inputcommand(NULL); } } - return true; } -void processtextinput(const char *str, int len) -{ +void processtextinput(const char *str, int len) { if(!g3d_input(str, len)) consoleinput(str, len); } -void processkey(int code, bool isdown, int modstate) -{ - switch(code) - { +void processkey(int code, bool isdown, int modstate) { + switch(code) { case SDLK_LGUI: case SDLK_RGUI: return; } keym *haskey = keyms.access(code); if(haskey && haskey->pressed) execbind(*haskey, isdown); // allow pressed keys to release - else if(!g3d_key(code, isdown)) // 3D GUI mouse button intercept - { - if(!consolekey(code, isdown)) - { + else if(!g3d_key(code, isdown)) { // 3D GUI mouse button intercept { + if(!consolekey(code, isdown)) { if(modstate&KMOD_GUI) return; if(haskey) execbind(*haskey, isdown); } } } -void clear_console() -{ +void clear_console() { keyms.clear(); } -void writebinds(stream *f) -{ +void writebinds(stream *f) { static const char * const cmds[3] = { "bind", "specbind", "editbind" }; vector<keym *> binds; enumerate(keyms, keym, km, binds.add(&km)); binds.sortname(); - loopj(3) - { - loopv(binds) - { + loopj(3) { + loopv(binds) { keym &km = *binds[i]; - if(*km.actions[j]) - { + if(*km.actions[j]) { if(validateblock(km.actions[j])) f->printf("%s %s [%s]\n", cmds[j], escapestring(km.name), km.actions[j]); else f->printf("%s %s %s\n", cmds[j], escapestring(km.name), escapestring(km.actions[j])); } @@ -591,42 +495,33 @@ void writebinds(stream *f) enum { FILES_DIR = 0, FILES_VAR, FILES_LIST }; -struct fileskey -{ +struct fileskey { int type; const char *dir, *ext; - fileskey() {} fileskey(int type, const char *dir, const char *ext) : type(type), dir(dir), ext(ext) {} }; -static void cleanfilesdir(char *dir) -{ +static void cleanfilesdir(char *dir) { int dirlen = (int)strlen(dir); while(dirlen > 0 && (dir[dirlen-1] == '/' || dir[dirlen-1] == '\\')) dir[--dirlen] = '\0'; } -struct filesval -{ +struct filesval { int type; char *dir, *ext; vector<char *> files; int millis; - filesval(int type, const char *dir, const char *ext) : type(type), dir(newstring(dir)), ext(ext && ext[0] ? newstring(ext) : NULL), millis(-1) {} ~filesval() { DELETEA(dir); DELETEA(ext); files.deletearrays(); } - - void update() - { + void update() { if((type!=FILES_DIR && type!=FILES_VAR) || millis >= commandmillis) return; files.deletearrays(); - if(type==FILES_VAR) - { + if(type==FILES_VAR) { string buf; buf[0] = '\0'; - if(ident *id = readident(dir)) switch(id->type) - { + if(ident *id = readident(dir)) switch(id->type) { case ID_SVAR: copystring(buf, *id->storage.s); break; case ID_ALIAS: copystring(buf, id->getstr()); break; } @@ -641,13 +536,11 @@ struct filesval } }; -static inline bool htcmp(const fileskey &x, const fileskey &y) -{ +static inline bool htcmp(const fileskey &x, const fileskey &y) { return x.type==y.type && !strcmp(x.dir, y.dir) && (x.ext == y.ext || (x.ext && y.ext && !strcmp(x.ext, y.ext))); } -static inline uint hthash(const fileskey &k) -{ +static inline uint hthash(const fileskey &k) { return hthash(k.dir); } @@ -659,29 +552,24 @@ char *lastcomplete = NULL; void resetcomplete() { completesize = 0; } -void addcomplete(char *command, int type, char *dir, char *ext) -{ - if(identflags&IDF_OVERRIDDEN) - { +void addcomplete(char *command, int type, char *dir, char *ext) { + if(identflags&IDF_OVERRIDDEN) { conoutf(CON_ERROR, "cannot override complete %s", command); return; } - if(!dir[0]) - { + if(!dir[0]) { filesval **hasfiles = completions.access(command); if(hasfiles) *hasfiles = NULL; return; } if(type==FILES_DIR) cleanfilesdir(dir); - if(ext) - { + if(ext) { if(strchr(ext, '*')) ext[0] = '\0'; if(!ext[0]) ext = NULL; } fileskey key(type, dir, ext); filesval **val = completefiles.access(key); - if(!val) - { + if(!val) { filesval *f = new filesval(type, dir, ext); if(type==FILES_LIST) explodelist(dir, f->files); val = &completefiles[fileskey(type, f->dir, f->ext)]; @@ -692,18 +580,15 @@ void addcomplete(char *command, int type, char *dir, char *ext) else completions[newstring(command)] = *val; } -void addfilecomplete(char *command, char *dir, char *ext) -{ +void addfilecomplete(char *command, char *dir, char *ext) { addcomplete(command, FILES_DIR, dir, ext); } -void addvarcomplete(char *command, char *var, char *ext) -{ +void addvarcomplete(char *command, char *var, char *ext) { addcomplete(command, FILES_VAR, var, ext); } -void addlistcomplete(char *command, char *list) -{ +void addlistcomplete(char *command, char *list) { addcomplete(command, FILES_LIST, list, NULL); } @@ -711,31 +596,24 @@ COMMANDN(complete, addfilecomplete, "sss"); COMMANDN(varcomplete, addvarcomplete, "sss"); COMMANDN(listcomplete, addlistcomplete, "ss"); -void complete(char *s, int maxlen, const char *cmdprefix) -{ +void complete(char *s, int maxlen, const char *cmdprefix) { int cmdlen = 0; - if(cmdprefix) - { + if(cmdprefix) { cmdlen = strlen(cmdprefix); if(strncmp(s, cmdprefix, cmdlen)) prependstring(s, cmdprefix, maxlen); } if(!s[cmdlen]) return; if(!completesize) { completesize = (int)strlen(&s[cmdlen]); DELETEA(lastcomplete); } - filesval *f = NULL; - if(completesize) - { + if(completesize) { char *end = strchr(&s[cmdlen], ' '); if(end) f = completions.find(stringslice(&s[cmdlen], end), NULL); } - const char *nextcomplete = NULL; - if(f) // complete using filenames - { + if(f) { // complete using filenames { int commandsize = strchr(&s[cmdlen], ' ')+1-s; f->update(); - loopv(f->files) - { + loopv(f->files) { if(strncmp(f->files[i], &s[commandsize], completesize+cmdlen-commandsize)==0 && (!lastcomplete || strcmp(f->files[i], lastcomplete) > 0) && (!nextcomplete || strcmp(f->files[i], nextcomplete) < 0)) nextcomplete = f->files[i]; @@ -743,8 +621,7 @@ void complete(char *s, int maxlen, const char *cmdprefix) cmdprefix = s; cmdlen = commandsize; } - else // complete using command names - { + else { // complete using command names { enumerate(idents, ident, id, if(strncmp(id.name, &s[cmdlen], completesize)==0 && (!lastcomplete || strcmp(id.name, lastcomplete) > 0) && (!nextcomplete || strcmp(id.name, nextcomplete) < 0)) @@ -752,8 +629,7 @@ void complete(char *s, int maxlen, const char *cmdprefix) ); } DELETEA(lastcomplete); - if(nextcomplete) - { + if(nextcomplete) { cmdlen = min(cmdlen, maxlen-1); if(cmdlen) memmove(s, cmdprefix, cmdlen); copystring(&s[cmdlen], nextcomplete, maxlen-cmdlen); @@ -761,17 +637,14 @@ void complete(char *s, int maxlen, const char *cmdprefix) } } -void writecompletions(stream *f) -{ +void writecompletions(stream *f) { vector<char *> cmds; enumeratekt(completions, char *, k, filesval *, v, { if(v) cmds.add(k); }); cmds.sort(); - loopv(cmds) - { + loopv(cmds) { char *k = cmds[i]; filesval *v = completions[k]; - if(v->type==FILES_LIST) - { + if(v->type==FILES_LIST) { if(validateblock(v->dir)) f->printf("listcomplete %s [%s]\n", escapeid(k), v->dir); else f->printf("listcomplete %s %s\n", escapeid(k), escapestring(v->dir)); } diff --git a/src/engine/decal.cpp b/src/engine/decal.cpp index 43ef667..bc39c1f 100644 --- a/src/engine/decal.cpp +++ b/src/engine/decal.cpp @@ -1,21 +1,18 @@ #include "engine.h" -struct decalvert -{ +struct decalvert { vec pos; bvec4 color; vec2 tc; }; -struct decalinfo -{ +struct decalinfo { int millis; bvec color; ushort startvert, endvert; }; -enum -{ +enum { DF_RND4 = 1<<0, DF_ROTATE = 1<<1, DF_INVMOD = 1<<2, @@ -27,8 +24,7 @@ enum VARFP(maxdecaltris, 1, 1024, 16384, initdecals()); VARP(decalfade, 1000, 10000, 60000); -struct decalrenderer -{ +struct decalrenderer { const char *texname; int flags, fadeintime, fadeouttime, timetolive; Texture *tex; @@ -38,7 +34,6 @@ struct decalrenderer int maxverts, startvert, endvert, lastvert, availverts; GLuint vbo; bool dirty; - decalrenderer(const char *texname, int flags = 0, int fadeintime = 0, int fadeouttime = 1000, int timetolive = -1) : texname(texname), flags(flags), fadeintime(fadeintime), fadeouttime(fadeouttime), timetolive(timetolive), @@ -46,25 +41,18 @@ struct decalrenderer decals(NULL), maxdecals(0), startdecal(0), enddecal(0), verts(NULL), maxverts(0), startvert(0), endvert(0), lastvert(0), availverts(0), vbo(0), dirty(false), - decalu(0), decalv(0) - { + decalu(0), decalv(0) { } - - ~decalrenderer() - { + ~decalrenderer() { DELETEA(decals); DELETEA(verts); } - - void init(int tris) - { - if(decals) - { + void init(int tris) { + if(decals) { DELETEA(decals); maxdecals = startdecal = enddecal = 0; } - if(verts) - { + if(verts) { DELETEA(verts); maxverts = startvert = endvert = lastvert = availverts = 0; } @@ -75,80 +63,59 @@ struct decalrenderer availverts = maxverts - 3; verts = new decalvert[maxverts]; } - - int hasdecals() - { + int hasdecals() { return enddecal < startdecal ? maxdecals - (startdecal - enddecal) : enddecal - startdecal; } - - void cleanup() - { + void cleanup() { if(vbo) { glDeleteBuffers_(1, &vbo); vbo = 0; } } - - void cleardecals() - { + void cleardecals() { startdecal = enddecal = 0; startvert = endvert = lastvert = 0; availverts = maxverts - 3; dirty = true; } - - int freedecal() - { + int freedecal() { if(startdecal==enddecal) return 0; - decalinfo &d = decals[startdecal]; startdecal++; if(startdecal >= maxdecals) startdecal = 0; - int removed = d.endvert < d.startvert ? maxverts - (d.startvert - d.endvert) : d.endvert - d.startvert; startvert = d.endvert; if(startvert==endvert) startvert = endvert = lastvert = 0; availverts += removed; - return removed; } - - void fadedecal(decalinfo &d, uchar alpha) - { + void fadedecal(decalinfo &d, uchar alpha) { bvec rgb; if(flags&DF_OVERBRIGHT) rgb = bvec(128, 128, 128); - else - { + else { rgb = d.color; if(flags&(DF_ADD|DF_INVMOD)) rgb.scale(alpha, 255); } bvec4 color(rgb, alpha); - decalvert *vert = &verts[d.startvert], *end = &verts[d.endvert < d.startvert ? maxverts : d.endvert]; - while(vert < end) - { + while(vert < end) { vert->color = color; vert++; } - if(d.endvert < d.startvert) - { + if(d.endvert < d.startvert) { vert = verts; end = &verts[d.endvert]; - while(vert < end) - { + while(vert < end) { vert->color = color; vert++; } } dirty = true; } - - void clearfadeddecals() - { + void clearfadeddecals() { int threshold = lastmillis - (timetolive>=0 ? timetolive : decalfade) - fadeouttime; decalinfo *d = &decals[startdecal], *end = &decals[enddecal < startdecal ? maxdecals : enddecal]; while(d < end && d->millis <= threshold) d++; - if(d >= end && enddecal < startdecal) - { + if(d >= end && enddecal < startdecal) { d = decals; end = &decals[enddecal]; while(d < end && d->millis <= threshold) d++; @@ -161,25 +128,20 @@ struct decalrenderer availverts = endvert < startvert ? startvert - endvert - 3 : maxverts - 3 - (endvert - startvert); dirty = true; } - - void fadeindecals() - { + void fadeindecals() { if(!fadeintime) return; decalinfo *d = &decals[enddecal], *end = &decals[enddecal < startdecal ? 0 : startdecal]; - while(d > end) - { + while(d > end) { d--; int fade = lastmillis - d->millis; if(fade >= fadeintime) return; fadedecal(*d, (fade<<8)/fadeintime); } - if(enddecal < startdecal) - { + if(enddecal < startdecal) { d = &decals[maxdecals]; end = &decals[startdecal]; - while(d > end) - { + while(d > end) { d--; int fade = lastmillis - d->millis; if(fade >= fadeintime) return; @@ -187,25 +149,20 @@ struct decalrenderer } } } - - void fadeoutdecals() - { + void fadeoutdecals() { decalinfo *d = &decals[startdecal], *end = &decals[enddecal < startdecal ? maxdecals : enddecal]; int offset = (timetolive>=0 ? timetolive : decalfade) + fadeouttime - lastmillis; - while(d < end) - { + while(d < end) { int fade = d->millis + offset; if(fade >= fadeouttime) return; fadedecal(*d, (fade<<8)/fadeouttime); d++; } - if(enddecal < startdecal) - { + if(enddecal < startdecal) { d = decals; end = &decals[enddecal]; - while(d < end) - { + while(d < end) { int fade = d->millis + offset; if(fade >= fadeouttime) return; fadedecal(*d, (fade<<8)/fadeouttime); @@ -213,84 +170,59 @@ struct decalrenderer } } } - - static void setuprenderstate() - { + static void setuprenderstate() { enablepolygonoffset(GL_POLYGON_OFFSET_FILL); - glDepthMask(GL_FALSE); glEnable(GL_BLEND); - gle::enablevertex(); gle::enabletexcoord0(); gle::enablecolor(); } - - static void cleanuprenderstate() - { + static void cleanuprenderstate() { gle::clearvbo(); - gle::disablevertex(); gle::disabletexcoord0(); gle::disablecolor(); - glDepthMask(GL_TRUE); glDisable(GL_BLEND); - disablepolygonoffset(GL_POLYGON_OFFSET_FILL); } - - void render() - { + void render() { if(startvert==endvert) return; - - if(flags&DF_OVERBRIGHT) - { + if(flags&DF_OVERBRIGHT) { glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); SETSHADER(overbrightdecal); } - else - { + else { if(flags&DF_INVMOD) { glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); } else if(flags&DF_ADD) { glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); } else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if(flags&DF_SATURATE) SETSHADER(saturatedecal); } - glBindTexture(GL_TEXTURE_2D, tex->id); - if(!vbo) { glGenBuffers_(1, &vbo); dirty = true; } gle::bindvbo(vbo); - int count = endvert < startvert ? maxverts - startvert : endvert - startvert; - if(dirty) - { + if(dirty) { glBufferData_(GL_ARRAY_BUFFER, maxverts*sizeof(decalvert), NULL, GL_STREAM_DRAW); glBufferSubData_(GL_ARRAY_BUFFER, 0, count*sizeof(decalvert), &verts[startvert]); - if(endvert < startvert) - { + if(endvert < startvert) { glBufferSubData_(GL_ARRAY_BUFFER, count*sizeof(decalvert), endvert*sizeof(decalvert), verts); count += endvert; } dirty = false; } else if(endvert < startvert) count += endvert; - const decalvert *ptr = 0; gle::vertexpointer(sizeof(decalvert), ptr->pos.v); gle::texcoord0pointer(sizeof(decalvert), ptr->tc.v); gle::colorpointer(sizeof(decalvert), ptr->color.v); - glDrawArrays(GL_TRIANGLES, 0, count); xtravertsva += count; - extern int intel_vertexarray_bug; if(intel_vertexarray_bug) glFlush(); } - - decalinfo &newdecal() - { + decalinfo &newdecal() { decalinfo &d = decals[enddecal]; int next = enddecal + 1; if(next>=maxdecals) next = 0; @@ -299,20 +231,15 @@ struct decalrenderer dirty = true; return d; } - ivec bbmin, bbmax; vec decalcenter, decalnormal, decaltangent, decalbitangent; float decalradius, decalu, decalv; bvec4 decalcolor; - - void adddecal(const vec ¢er, const vec &dir, float radius, const bvec &color, int info) - { + void adddecal(const vec ¢er, const vec &dir, float radius, const bvec &color, int info) { if(dir.iszero()) return; - int bbradius = int(ceil(radius)); bbmin = ivec(center).sub(bbradius); bbmax = ivec(center).add(bbradius); - decalcolor = bvec4(color, 255); decalcenter = center; decalradius = radius; @@ -326,46 +253,36 @@ struct decalrenderer if(flags&DF_ROTATE) decaltangent.rotate(rnd(360)*RAD, dir); decaltangent.normalize(); decalbitangent.cross(decaltangent, dir); - if(flags&DF_RND4) - { + if(flags&DF_RND4) { decalu = 0.5f*(info&1); decalv = 0.5f*((info>>1)&1); } - lastvert = endvert; gentris(worldroot, ivec(0, 0, 0), worldsize>>1); if(endvert==lastvert) return; - decalinfo &d = newdecal(); d.color = color; d.millis = lastmillis; d.startvert = lastvert; d.endvert = endvert; } - - static int clip(const vec *in, int numin, const vec &dir, float below, float above, vec *out) - { + static int clip(const vec *in, int numin, const vec &dir, float below, float above, vec *out) { int numout = 0; const vec *p = &in[numin-1]; float pc = dir.dot(*p); - loopi(numin) - { + loopi(numin) { const vec &v = in[i]; float c = dir.dot(v); - if(c < below) - { + if(c < below) { if(pc > above) out[numout++] = vec(*p).sub(v).mul((above - c)/(pc - c)).add(v); if(pc > below) out[numout++] = vec(*p).sub(v).mul((below - c)/(pc - c)).add(v); } - else if(c > above) - { + else if(c > above) { if(pc < below) out[numout++] = vec(*p).sub(v).mul((below - c)/(pc - c)).add(v); if(pc < above) out[numout++] = vec(*p).sub(v).mul((above - c)/(pc - c)).add(v); } - else - { - if(pc < below) - { + else { + if(pc < below) { if(c > below) out[numout++] = vec(*p).sub(v).mul((below - c)/(pc - c)).add(v); } else if(pc > above && c < above) out[numout++] = vec(*p).sub(v).mul((above - c)/(pc - c)).add(v); @@ -376,17 +293,13 @@ struct decalrenderer } return numout; } - - void gentris(cube &cu, int orient, const ivec &o, int size, materialsurface *mat = NULL, int vismask = 0) - { + void gentris(cube &cu, int orient, const ivec &o, int size, materialsurface *mat = NULL, int vismask = 0) { vec pos[MAXFACEVERTS+4] = { vec(0, 0, 0) }; int numverts = 0, numplanes = 1; vec planes[2] = { vec(0, 0, 0) }; - if(mat) - { + if(mat) { planes[0] = vec(0, 0, 0); - switch(orient) - { + switch(orient) { #define GENFACEORIENT(orient, v0, v1, v2, v3) \ case orient: \ planes[0][dimension(orient)] = dimcoord(orient) ? 1 : -1; \ @@ -399,21 +312,18 @@ struct decalrenderer #undef GENFACEVERT } } - else if(cu.ext && (numverts = cu.ext->surfaces[orient].numverts&MAXFACEVERTS)) - { + else if(cu.ext && (numverts = cu.ext->surfaces[orient].numverts&MAXFACEVERTS)) { vertinfo *verts = cu.ext->verts() + cu.ext->surfaces[orient].verts; ivec vo = ivec(o).mask(~0xFFF).shl(3); loopj(numverts) pos[j] = vec(verts[j].getxyz().add(vo)).mul(1/8.0f); planes[0].cross(pos[0], pos[1], pos[2]).normalize(); - if(numverts >= 4 && !(cu.merged&(1<<orient)) && !flataxisface(cu, orient) && faceconvexity(verts, numverts, size)) - { + if(numverts >= 4 && !(cu.merged&(1<<orient)) && !flataxisface(cu, orient) && faceconvexity(verts, numverts, size)) { planes[1].cross(pos[0], pos[2], pos[3]).normalize(); numplanes++; } } else if(cu.merged&(1<<orient)) return; - else if(!vismask || (vismask&0x40 && visibleface(cu, orient, o, size, MAT_AIR, (cu.material&MAT_ALPHA)^MAT_ALPHA, MAT_ALPHA))) - { + else if(!vismask || (vismask&0x40 && visibleface(cu, orient, o, size, MAT_AIR, (cu.material&MAT_ALPHA)^MAT_ALPHA, MAT_ALPHA))) { ivec v[4]; genfaceverts(cu, orient, v); int vis = 3, convex = faceconvexity(v, vis), order = convex < 0 ? 1 : 0; @@ -426,9 +336,7 @@ struct decalrenderer if(convex) { planes[1].cross(pos[0], pos[2], pos[3]).normalize(); numplanes++; } } else return; - - loopl(numplanes) - { + loopl(numplanes) { const vec &n = planes[l]; float facing = n.dot(decalnormal); if(facing <= 0) continue; @@ -455,14 +363,12 @@ struct decalrenderer vec v1[MAXFACEVERTS+4], v2[MAXFACEVERTS+4]; float ptc = pt.dot(pcenter), pbc = pb.dot(pcenter); int numv; - if(numplanes >= 2) - { + if(numplanes >= 2) { if(l) { pos[1] = pos[2]; pos[2] = pos[3]; } numv = clip(pos, 3, pt, ptc - decalradius, ptc + decalradius, v1); if(numv<3) continue; } - else - { + else { numv = clip(pos, numverts, pt, ptc - decalradius, ptc + decalradius, v1); if(numv<3) continue; } @@ -475,13 +381,11 @@ struct decalrenderer dv2 = { v2[1], decalcolor, vec2(pt.dot(v2[1]) + tu, pb.dot(v2[1]) + tv) }; int totalverts = 3*(numv-2); if(totalverts > maxverts-3) return; - while(availverts < totalverts) - { + while(availverts < totalverts) { if(!freedecal()) return; } availverts -= totalverts; - loopk(numv-2) - { + loopk(numv-2) { verts[endvert++] = dv1; verts[endvert++] = dv2; dv2.pos = v2[k+2]; @@ -491,25 +395,20 @@ struct decalrenderer } } } - - void findmaterials(vtxarray *va) - { + void findmaterials(vtxarray *va) { materialsurface *matbuf = va->matbuf; int matsurfs = va->matsurfs; - loopi(matsurfs) - { + loopi(matsurfs) { materialsurface &m = matbuf[i]; if(1) { i += m.skip; continue; } int dim = dimension(m.orient), dc = dimcoord(m.orient); if(dc ? decalnormal[dim] <= 0 : decalnormal[dim] >= 0) { i += m.skip; continue; } int c = C[dim], r = R[dim]; - for(;;) - { + for(;;) { materialsurface &m = matbuf[i]; if(m.o[dim] >= bbmin[dim] && m.o[dim] <= bbmax[dim] && m.o[c] + m.csize >= bbmin[c] && m.o[c] <= bbmax[c] && - m.o[r] + m.rsize >= bbmin[r] && m.o[r] <= bbmax[r]) - { + m.o[r] + m.rsize >= bbmin[r] && m.o[r] <= bbmax[r]) { static cube dummy; gentris(dummy, m.orient, m.o, max(m.csize, m.rsize), &m); } @@ -520,51 +419,38 @@ struct decalrenderer } } } - - void findescaped(cube *cu, const ivec &o, int size, int escaped) - { - loopi(8) - { - if(escaped&(1<<i)) - { + void findescaped(cube *cu, const ivec &o, int size, int escaped) { + loopi(8) { + if(escaped&(1<<i)) { ivec co(i, o, size); if(cu[i].children) findescaped(cu[i].children, co, size>>1, cu[i].escaped); - else - { + else { int vismask = cu[i].merged; if(vismask) loopj(6) if(vismask&(1<<j)) gentris(cu[i], j, co, size); } } } } - - void gentris(cube *cu, const ivec &o, int size, int escaped = 0) - { + void gentris(cube *cu, const ivec &o, int size, int escaped = 0) { int overlap = octaboxoverlap(o, size, bbmin, bbmax); - loopi(8) - { - if(overlap&(1<<i)) - { + loopi(8) { + if(overlap&(1<<i)) { ivec co(i, o, size); if(cu[i].ext && cu[i].ext->va && cu[i].ext->va->matsurfs) findmaterials(cu[i].ext->va); if(cu[i].children) gentris(cu[i].children, co, size>>1, cu[i].escaped); - else - { + else { int vismask = cu[i].visible; - if(vismask&0xC0) - { + if(vismask&0xC0) { if(vismask&0x80) loopj(6) gentris(cu[i], j, co, size, NULL, vismask); else loopj(6) if(vismask&(1<<j)) gentris(cu[i], j, co, size); } } } - else if(escaped&(1<<i)) - { + else if(escaped&(1<<i)) { ivec co(i, o, size); if(cu[i].children) findescaped(cu[i].children, co, size>>1, cu[i].escaped); - else - { + else { int vismask = cu[i].merged; if(vismask) loopj(6) if(vismask&(1<<j)) gentris(cu[i], j, co, size); } @@ -573,45 +459,37 @@ struct decalrenderer } }; -decalrenderer decals[] = -{ +decalrenderer decals[] = { decalrenderer("<grey>packages/particles/scorch.png", DF_ROTATE, 500), decalrenderer("<grey>packages/particles/blood.png", DF_RND4|DF_ROTATE|DF_INVMOD), decalrenderer("<grey>packages/particles/bullet.png", DF_OVERBRIGHT) }; -void initdecals() -{ +void initdecals() { loopi(sizeof(decals)/sizeof(decals[0])) decals[i].init(maxdecaltris); } -void cleardecals() -{ +void cleardecals() { loopi(sizeof(decals)/sizeof(decals[0])) decals[i].cleardecals(); } -void cleanupdecals() -{ +void cleanupdecals() { loopi(sizeof(decals)/sizeof(decals[0])) decals[i].cleanup(); } VARNP(decals, showdecals, 0, 1, 1); -void renderdecals(bool mainpass) -{ +void renderdecals(bool mainpass) { bool rendered = false; - loopi(sizeof(decals)/sizeof(decals[0])) - { + loopi(sizeof(decals)/sizeof(decals[0])) { decalrenderer &d = decals[i]; - if(mainpass) - { + if(mainpass) { d.clearfadeddecals(); d.fadeindecals(); d.fadeoutdecals(); } if(!showdecals || !d.hasdecals()) continue; - if(!rendered) - { + if(!rendered) { rendered = true; decalrenderer::setuprenderstate(); } @@ -623,8 +501,7 @@ void renderdecals(bool mainpass) VARP(maxdecaldistance, 1, 512, 10000); -void adddecal(int type, const vec ¢er, const vec &surface, float radius, const bvec &color, int info) -{ +void adddecal(int type, const vec ¢er, const vec &surface, float radius, const bvec &color, int info) { if(!showdecals || type<0 || (size_t)type>=sizeof(decals)/sizeof(decals[0]) || center.dist(camera1->o) - radius > maxdecaldistance) return; decalrenderer &d = decals[type]; d.adddecal(center, surface, radius, color, info); diff --git a/src/engine/dynlight.cpp b/src/engine/dynlight.cpp index d018480..0c2a08d 100644 --- a/src/engine/dynlight.cpp +++ b/src/engine/dynlight.cpp @@ -3,18 +3,14 @@ VARP(maxdynlights, 0, min(3, MAXDYNLIGHTS), MAXDYNLIGHTS); VARP(dynlightdist, 0, 1024, 10000); -struct dynlight -{ +struct dynlight { vec o, hud; float radius, initradius, curradius, dist; vec color, initcolor, curcolor; int fade, peak, expire, flags; physent *owner; - - void calcradius() - { - if(fade + peak > 0) - { + void calcradius() { + if(fade + peak > 0) { int remaining = expire - lastmillis; if(flags&DL_EXPAND) curradius = initradius + (radius - initradius) * (1.0f - remaining/float(fade + peak)); @@ -26,20 +22,15 @@ struct dynlight } else curradius = radius; } - - void calccolor() - { + void calccolor() { if(flags&DL_FLASH || peak <= 0) curcolor = color; - else - { + else { int peaking = expire - lastmillis - fade; if(peaking <= 0) curcolor = color; else curcolor.lerp(initcolor, color, 1.0f - float(peaking)/peak); } - float intensity = 1.0f; - if(fade > 0) - { + if(fade > 0) { int fading = expire - lastmillis; if(fading < fade) intensity = float(fading)/fade; } @@ -52,11 +43,9 @@ struct dynlight vector<dynlight> dynlights; vector<dynlight *> closedynlights; -void adddynlight(const vec &o, float radius, const vec &color, int fade, int peak, int flags, float initradius, const vec &initcolor, physent *owner) -{ +void adddynlight(const vec &o, float radius, const vec &color, int fade, int peak, int flags, float initradius, const vec &initcolor, physent *owner) { if(!maxdynlights) return; if(o.dist(camera1->o) > dynlightdist || radius <= 0) return; - int insert = 0, expire = fade + peak + lastmillis; loopvrev(dynlights) if(expire>=dynlights[i].expire) { insert = i+1; break; } dynlight d; @@ -73,26 +62,21 @@ void adddynlight(const vec &o, float radius, const vec &color, int fade, int pea dynlights.insert(insert, d); } -void cleardynlights() -{ +void cleardynlights() { int faded = -1; loopv(dynlights) if(lastmillis<dynlights[i].expire) { faded = i; break; } if(faded<0) dynlights.setsize(0); else if(faded>0) dynlights.remove(0, faded); } -void removetrackeddynlights(physent *owner) -{ +void removetrackeddynlights(physent *owner) { loopvrev(dynlights) if(owner ? dynlights[i].owner == owner : dynlights[i].owner != NULL) dynlights.remove(i); } -void updatedynlights() -{ +void updatedynlights() { cleardynlights(); game::adddynlights(); - - loopv(dynlights) - { + loopv(dynlights) { dynlight &d = dynlights[i]; if(d.owner) game::dynlighttrack(d.owner, d.o, d.hud); d.calcradius(); @@ -100,14 +84,12 @@ void updatedynlights() } } -int finddynlights() -{ +int finddynlights() { closedynlights.setsize(0); if(!maxdynlights) return 0; physent e; e.type = ENT_CAMERA; - loopvj(dynlights) - { + loopvj(dynlights) { dynlight &d = dynlights[j]; if(d.curradius <= 0) continue; d.dist = camera1->o.dist(d.o) - d.curradius; @@ -116,7 +98,6 @@ int finddynlights() e.o = d.o; e.radius = e.xradius = e.yradius = e.eyeheight = e.aboveeye = d.curradius; if(!collide(&e, vec(0, 0, 0), 0, false)) continue; - int insert = 0; loopvrev(closedynlights) if(d.dist >= closedynlights[i]->dist) { insert = i+1; break; } closedynlights.insert(insert, &d); @@ -125,8 +106,7 @@ int finddynlights() return closedynlights.length(); } -bool getdynlight(int n, vec &o, float &radius, vec &color) -{ +bool getdynlight(int n, vec &o, float &radius, vec &color) { if(!closedynlights.inrange(n)) return false; dynlight &d = *closedynlights[n]; o = d.o; @@ -135,31 +115,25 @@ bool getdynlight(int n, vec &o, float &radius, vec &color) return true; } -void dynlightreaching(const vec &target, vec &color, vec &dir, bool hud) -{ +void dynlightreaching(const vec &target, vec &color, vec &dir, bool hud) { vec dyncolor(0, 0, 0);//, dyndir(0, 0, 0); - loopv(dynlights) - { + loopv(dynlights) { dynlight &d = dynlights[i]; if(d.curradius<=0) continue; - vec ray(hud ? d.hud : d.o); ray.sub(target); float mag = ray.squaredlen(); if(mag >= d.curradius*d.curradius) continue; - vec color = d.curcolor; color.mul(1 - sqrtf(mag)/d.curradius); dyncolor.add(color); //dyndir.add(ray.mul(intensity/mag)); } #if 0 - if(!dyndir.iszero()) - { + if(!dyndir.iszero()) { dyndir.normalize(); float x = dyncolor.magnitude(), y = color.magnitude(); - if(x+y>0) - { + if(x+y>0) { dir.mul(x); dyndir.mul(y); dir.add(dyndir).div(x+y); @@ -171,15 +145,12 @@ void dynlightreaching(const vec &target, vec &color, vec &dir, bool hud) color.add(dyncolor); } -void calcdynlightmask(vtxarray *va) -{ +void calcdynlightmask(vtxarray *va) { uint mask = 0; int offset = 0; - loopv(closedynlights) - { + loopv(closedynlights) { dynlight &d = *closedynlights[i]; if(d.o.dist_to_bb(va->geommin, va->geommax) >= d.curradius) continue; - mask |= (i+1)<<offset; offset += DYNLIGHTBITS; if(offset >= maxdynlights*DYNLIGHTBITS) break; @@ -187,35 +158,24 @@ void calcdynlightmask(vtxarray *va) va->dynlightmask = mask; } -int setdynlights(vtxarray *va) -{ +int setdynlights(vtxarray *va) { if(closedynlights.empty() || !va->dynlightmask) return 0; - extern bool minimizedynlighttcusage(); - static vec4 posv[MAXDYNLIGHTS]; static vec colorv[MAXDYNLIGHTS]; - int index = 0; - for(uint mask = va->dynlightmask; mask; mask >>= DYNLIGHTBITS, index++) - { + for(uint mask = va->dynlightmask; mask; mask >>= DYNLIGHTBITS, index++) { dynlight &d = *closedynlights[(mask&DYNLIGHTMASK)-1]; - float scale = 1.0f/d.curradius; vec origin = vec(d.o).mul(-scale); - - if(index>0 && minimizedynlighttcusage()) - { + if(index>0 && minimizedynlighttcusage()) { scale /= posv[0].w; origin.sub(vec(posv[0]).mul(scale)); } - posv[index] = vec4(origin, scale); colorv[index] = d.curcolor; } - GLOBALPARAMV(dynlightpos, posv, index); GLOBALPARAMV(dynlightcolor, colorv, index); - return index; } diff --git a/src/engine/engine.h b/src/engine/engine.h index e37ac4f..7bc0ef1 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -34,18 +34,14 @@ extern int zpass; extern vector<int> entgroup; // rendertext -struct font -{ - struct charinfo - { +struct font { + struct charinfo { short x, y, w, h, offsetx, offsety, advance, tex; }; - char *name; vector<Texture *> texs; vector<charinfo> chars; int charoffset, defaultw, defaulth, scale; - font() : name(NULL) {} ~font() { DELETEA(name); } }; @@ -97,7 +93,6 @@ extern bool addshadowmapcaster(const vec &o, float xyrad, float zrad); extern bool isshadowmapreceiver(vtxarray *va); extern void rendershadowmap(); extern void pushshadowmap(); -extern void popshadowmap(); extern void rendershadowmapreceivers(); extern void guessshadowdir(); @@ -137,8 +132,7 @@ extern void screenquadoffset(float x, float y, float w, float h, float x2, float extern void hudquad(float x, float y, float w, float h, float tx = 0, float ty = 0, float tw = 1, float th = 1); extern void writecrosshairs(stream *f); -namespace modelpreview -{ +namespace modelpreview { extern void start(int x, int y, int w, int h, bool background = true); extern void end(); } @@ -195,8 +189,7 @@ extern void calcmerges(); extern int mergefaces(int orient, facebounds *m, int sz); extern void mincubeface(const cube &cu, int orient, const ivec &o, int size, const facebounds &orig, facebounds &cf, ushort nmat = MAT_AIR, ushort matmask = 0); -static inline cubeext &ext(cube &c) -{ +static inline cubeext &ext(cube &c) { return *(c.ext ? c.ext : newcubeext(c)); } @@ -336,8 +329,7 @@ extern void writebinds(stream *f); extern void writecompletions(stream *f); // main -enum -{ +enum { NOT_INITING = 0, INIT_GAME, INIT_LOAD, @@ -345,8 +337,7 @@ enum }; extern int initing, numcpus; -enum -{ +enum { CHANGE_GFX = 1<<0, CHANGE_SOUND = 1<<1 }; @@ -410,14 +401,12 @@ extern void loadskin(const char *dir, const char *altdir, Texture *&skin, Textur extern mapmodelinfo *getmminfo(int i); extern void startmodelquery(occludequery *query); extern void endmodelquery(); -extern void preloadmodelshaders(bool force = false); +extern void preloadmodelshaders(); extern void preloadusedmapmodels(bool msg = false, bool bih = false); -static inline model *loadmapmodel(int n) -{ +static inline model *loadmapmodel(int n) { extern vector<mapmodelinfo> mapmodels; - if(mapmodels.inrange(n)) - { + if(mapmodels.inrange(n)) { model *m = mapmodels[n].m; return m ? m : loadmodel(NULL, n); } diff --git a/src/engine/explosion.h b/src/engine/explosion.h deleted file mode 100644 index 819b0a3..0000000 --- a/src/engine/explosion.h +++ /dev/null @@ -1,179 +0,0 @@ -namespace sphere -{ - struct vert - { - vec pos; - ushort s, t; - } *verts = NULL; - GLushort *indices = NULL; - int numverts = 0, numindices = 0; - GLuint vbuf = 0, ebuf = 0; - - void init(int slices, int stacks) - { - numverts = (stacks+1)*(slices+1); - verts = new vert[numverts]; - float ds = 1.0f/slices, dt = 1.0f/stacks, t = 1.0f; - loopi(stacks+1) - { - float rho = M_PI*(1-t), s = 0.0f, sinrho = i && i < stacks ? sin(rho) : 0, cosrho = !i ? 1 : (i < stacks ? cos(rho) : -1); - loopj(slices+1) - { - float theta = j==slices ? 0 : 2*M_PI*s; - vert &v = verts[i*(slices+1) + j]; - v.pos = vec(-sin(theta)*sinrho, cos(theta)*sinrho, cosrho); - v.s = ushort(s*0xFFFF); - v.t = ushort(t*0xFFFF); - s += ds; - } - t -= dt; - } - - numindices = (stacks-1)*slices*3*2; - indices = new ushort[numindices]; - GLushort *curindex = indices; - loopi(stacks) - { - loopk(slices) - { - int j = i%2 ? slices-k-1 : k; - if(i) - { - *curindex++ = i*(slices+1)+j; - *curindex++ = (i+1)*(slices+1)+j; - *curindex++ = i*(slices+1)+j+1; - } - if(i+1 < stacks) - { - *curindex++ = i*(slices+1)+j+1; - *curindex++ = (i+1)*(slices+1)+j; - *curindex++ = (i+1)*(slices+1)+j+1; - } - } - } - - if(!vbuf) glGenBuffers_(1, &vbuf); - gle::bindvbo(vbuf); - glBufferData_(GL_ARRAY_BUFFER, numverts*sizeof(vert), verts, GL_STATIC_DRAW); - DELETEA(verts); - - if(!ebuf) glGenBuffers_(1, &ebuf); - gle::bindebo(ebuf); - glBufferData_(GL_ELEMENT_ARRAY_BUFFER, numindices*sizeof(GLushort), indices, GL_STATIC_DRAW); - DELETEA(indices); - } - - void enable() - { - if(!vbuf) init(12, 6); - - gle::bindvbo(vbuf); - gle::bindebo(ebuf); - - gle::vertexpointer(sizeof(vert), &verts->pos); - gle::texcoord0pointer(sizeof(vert), &verts->s, GL_UNSIGNED_SHORT, 2, GL_TRUE); - gle::enablevertex(); - gle::enabletexcoord0(); - } - - void draw() - { - glDrawRangeElements_(GL_TRIANGLES, 0, numverts-1, numindices, GL_UNSIGNED_SHORT, indices); - xtraverts += numindices; - glde++; - } - - void disable() - { - gle::disablevertex(); - gle::disabletexcoord0(); - - gle::clearvbo(); - gle::clearebo(); - } - - void cleanup() - { - if(vbuf) { glDeleteBuffers_(1, &vbuf); vbuf = 0; } - if(ebuf) { glDeleteBuffers_(1, &ebuf); ebuf = 0; } - } -} - -static const float WOBBLE = 1.25f; - -struct fireballrenderer : listrenderer -{ - fireballrenderer(const char *texname) - : listrenderer(texname, 0, PT_FIREBALL|PT_GLARE|PT_SHADER) - {} - - void startrender() - { - SETSHADER(explosion); - sphere::enable(); - } - - void endrender() - { - sphere::disable(); - } - - void cleanup() - { - sphere::cleanup(); - } - - void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity) - { - pe.maxfade = max(pe.maxfade, fade); - pe.extendbb(o, (size+1+pe.ent->attr2)*WOBBLE); - } - - void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) - { - float pmax = p->val, size = p->fade ? float(ts)/p->fade : 1, psize = p->size + pmax * size; - - vec dir = vec(o).sub(camera1->o), s, t; - float dist = dir.magnitude(); - bool inside = dist <= psize*WOBBLE; - if(inside) - { - s = camright; - t = camup; - } - else - { - float mag2 = dir.magnitude2(); - dir.x /= mag2; - dir.y /= mag2; - dir.z /= dist; - s = vec(dir.y, -dir.x, 0); - t = vec(dir.x*dir.z, dir.y*dir.z, -mag2/dist); - } - - matrix3 rot(lastmillis/1000.0f*143*RAD, vec(1/SQRT3, 1/SQRT3, 1/SQRT3)); - LOCALPARAM(texgenS, rot.transposedtransform(s)); - LOCALPARAM(texgenT, rot.transposedtransform(t)); - - matrix4 m(rot, o); - m.scale(psize, psize, inside ? -psize : psize); - m.mul(camprojmatrix, m); - LOCALPARAM(explosionmatrix, m); - - LOCALPARAM(center, o); - LOCALPARAMF(millis, lastmillis/1000.0f); - LOCALPARAMF(blendparams, inside ? 0.5f : 4, inside ? 0.25f : 0); - - int passes = inside ? 2 : 1; - loopi(passes) - { - gle::color(p->color, i ? blend/2 : blend); - if(i) glDepthFunc(GL_GEQUAL); - sphere::draw(); - if(i) glDepthFunc(GL_LESS); - } - } -}; - -static fireballrenderer fireballs("packages/particles/explosion.png"), bluefireballs("packages/particles/plasma.png"); - diff --git a/src/engine/iqm.h b/src/engine/iqm.h index e36a628..5e7323f 100644 --- a/src/engine/iqm.h +++ b/src/engine/iqm.h @@ -1,7 +1,6 @@ struct iqm; -struct iqmheader -{ +struct iqmheader { char magic[16]; uint version; uint filesize; @@ -18,16 +17,14 @@ struct iqmheader uint num_extensions, ofs_extensions; }; -struct iqmmesh -{ +struct iqmmesh { uint name; uint material; uint first_vertex, num_vertexes; uint first_triangle, num_triangles; }; -enum -{ +enum { IQM_POSITION = 0, IQM_TEXCOORD = 1, IQM_NORMAL = 2, @@ -38,8 +35,7 @@ enum IQM_CUSTOM = 0x10 }; -enum -{ +enum { IQM_BYTE = 0, IQM_UBYTE = 1, IQM_SHORT = 2, @@ -51,13 +47,11 @@ enum IQM_DOUBLE = 8, }; -struct iqmtriangle -{ +struct iqmtriangle { uint vertex[3]; }; -struct iqmjoint -{ +struct iqmjoint { uint name; int parent; vec pos; @@ -65,8 +59,7 @@ struct iqmjoint vec size; }; -struct iqmpose -{ +struct iqmpose { int parent; uint mask; vec offsetpos; @@ -77,16 +70,14 @@ struct iqmpose vec scalesize; }; -struct iqmanim -{ +struct iqmanim { uint name; uint first_frame, num_frames; float framerate; uint flags; }; -struct iqmvertexarray -{ +struct iqmvertexarray { uint type; uint flags; uint format; @@ -94,35 +85,25 @@ struct iqmvertexarray uint offset; }; -struct iqm : skelloader<iqm> -{ +struct iqm : skelloader<iqm> { iqm(const char *name) : skelloader(name) {} - static const char *formatname() { return "iqm"; } int type() const { return MDL_IQM; } - - struct iqmmeshgroup : skelmeshgroup - { - iqmmeshgroup() - { + struct iqmmeshgroup : skelmeshgroup { + iqmmeshgroup() { } - - bool loadiqmmeshes(const char *filename, const iqmheader &hdr, uchar *buf) - { + bool loadiqmmeshes(const char *filename, const iqmheader &hdr, uchar *buf) { lilswap((uint *)&buf[hdr.ofs_vertexarrays], hdr.num_vertexarrays*sizeof(iqmvertexarray)/sizeof(uint)); lilswap((uint *)&buf[hdr.ofs_triangles], hdr.num_triangles*sizeof(iqmtriangle)/sizeof(uint)); lilswap((uint *)&buf[hdr.ofs_meshes], hdr.num_meshes*sizeof(iqmmesh)/sizeof(uint)); lilswap((uint *)&buf[hdr.ofs_joints], hdr.num_joints*sizeof(iqmjoint)/sizeof(uint)); - const char *str = hdr.ofs_text ? (char *)&buf[hdr.ofs_text] : ""; float *vpos = NULL, *vnorm = NULL, *vtan = NULL, *vtc = NULL; uchar *vindex = NULL, *vweight = NULL; iqmvertexarray *vas = (iqmvertexarray *)&buf[hdr.ofs_vertexarrays]; - loopi(hdr.num_vertexarrays) - { + loopi(hdr.num_vertexarrays) { iqmvertexarray &va = vas[i]; - switch(va.type) - { + switch(va.type) { case IQM_POSITION: if(va.format != IQM_FLOAT || va.size != 3) return false; vpos = (float *)&buf[va.offset]; lilswap(vpos, 3*hdr.num_vertexes); break; case IQM_NORMAL: if(va.format != IQM_FLOAT || va.size != 3) return false; vnorm = (float *)&buf[va.offset]; lilswap(vnorm, 3*hdr.num_vertexes); break; case IQM_TANGENT: if(va.format != IQM_FLOAT || va.size != 4) return false; vtan = (float *)&buf[va.offset]; lilswap(vtan, 4*hdr.num_vertexes); break; @@ -132,25 +113,19 @@ struct iqm : skelloader<iqm> } } if(!vpos) return false; - iqmtriangle *tris = (iqmtriangle *)&buf[hdr.ofs_triangles]; iqmmesh *imeshes = (iqmmesh *)&buf[hdr.ofs_meshes]; iqmjoint *joints = (iqmjoint *)&buf[hdr.ofs_joints]; - - if(hdr.num_joints) - { - if(skel->numbones <= 0) - { + if(hdr.num_joints) { + if(skel->numbones <= 0) { skel->numbones = hdr.num_joints; skel->bones = new boneinfo[skel->numbones]; - loopi(hdr.num_joints) - { + loopi(hdr.num_joints) { iqmjoint &j = joints[i]; boneinfo &b = skel->bones[i]; if(!b.name) b.name = newstring(&str[j.name]); b.parent = j.parent; - if(skel->shared <= 1) - { + if(skel->shared <= 1) { j.pos.y = -j.pos.y; j.orient.x = -j.orient.x; j.orient.z = -j.orient.z; @@ -161,13 +136,10 @@ struct iqm : skelloader<iqm> } } } - if(skel->shared <= 1) skel->linkchildren(); } - - loopi(hdr.num_meshes) - { + loopi(hdr.num_meshes) { iqmmesh &im = imeshes[i]; skelmesh *m = new skelmesh; m->group = this; @@ -175,12 +147,10 @@ struct iqm : skelloader<iqm> m->name = newstring(&str[im.name]); m->numverts = im.num_vertexes; int noblend = -1; - if(m->numverts) - { + if(m->numverts) { m->verts = new vert[m->numverts]; if(vtan) m->bumpverts = new bumpvert[m->numverts]; - if(!vindex || !vweight) - { + if(!vindex || !vweight) { blendcombo c; c.finalize(0); noblend = m->addblendcombo(c); @@ -192,30 +162,25 @@ struct iqm : skelloader<iqm> *mtan = vtan ? vtan + 4*fv : NULL, *mtc = vtc ? vtc + 2*fv : NULL; uchar *mindex = vindex ? vindex + 4*fv : NULL, *mweight = vweight ? vweight + 4*fv : NULL; - loopj(im.num_vertexes) - { + loopj(im.num_vertexes) { vert &v = m->verts[j]; v.pos = vec(mpos[0], -mpos[1], mpos[2]); mpos += 3; - if(mtc) - { + if(mtc) { v.tc = vec2(mtc[0], mtc[1]); mtc += 2; } else v.tc = vec2(0, 0); - if(mnorm) - { + if(mnorm) { v.norm = vec(mnorm[0], -mnorm[1], mnorm[2]); mnorm += 3; - if(mtan) - { + if(mtan) { m->calctangent(m->bumpverts[j], v.norm, vec(mtan[0], -mtan[1], mtan[2]), mtan[3]); mtan += 4; } } else v.norm = vec(0, 0, 0); - if(noblend < 0) - { + if(noblend < 0) { blendcombo c; int sorted = 0; loopk(4) sorted = c.addweight(sorted, mweight[k], mindex[k]); @@ -229,39 +194,31 @@ struct iqm : skelloader<iqm> m->numtris = im.num_triangles; if(m->numtris) m->tris = new tri[m->numtris]; iqmtriangle *mtris = tris + im.first_triangle; - loopj(im.num_triangles) - { + loopj(im.num_triangles) { tri &t = m->tris[j]; t.vert[0] = mtris->vertex[0] - fv; t.vert[1] = mtris->vertex[1] - fv; t.vert[2] = mtris->vertex[2] - fv; ++mtris; } - if(!m->numtris || !m->numverts) - { + if(!m->numtris || !m->numverts) { conoutf(CON_WARN, "empty mesh in %s", filename); meshes.removeobj(m); delete m; } } - sortblendcombos(); - return true; } - - bool loadiqmanims(const char *filename, const iqmheader &hdr, uchar *buf) - { + bool loadiqmanims(const char *filename, const iqmheader &hdr, uchar *buf) { lilswap((uint *)&buf[hdr.ofs_poses], hdr.num_poses*sizeof(iqmpose)/sizeof(uint)); lilswap((uint *)&buf[hdr.ofs_anims], hdr.num_anims*sizeof(iqmanim)/sizeof(uint)); lilswap((ushort *)&buf[hdr.ofs_frames], hdr.num_frames*hdr.num_framechannels); - const char *str = hdr.ofs_text ? (char *)&buf[hdr.ofs_text] : ""; iqmpose *poses = (iqmpose *)&buf[hdr.ofs_poses]; iqmanim *anims = (iqmanim *)&buf[hdr.ofs_anims]; ushort *frames = (ushort *)&buf[hdr.ofs_frames]; - loopi(hdr.num_anims) - { + loopi(hdr.num_anims) { iqmanim &a = anims[i]; string name; copystring(name, filename); @@ -273,8 +230,7 @@ struct iqm : skelloader<iqm> sa->frame = skel->numframes; sa->range = a.num_frames; dualquat *animbones = new dualquat[(skel->numframes+a.num_frames)*skel->numbones]; - if(skel->bones) - { + if(skel->bones) { memcpy(animbones, skel->framebones, skel->numframes*skel->numbones*sizeof(dualquat)); delete[] skel->framebones; } @@ -282,11 +238,9 @@ struct iqm : skelloader<iqm> animbones += skel->numframes*skel->numbones; skel->numframes += a.num_frames; ushort *animdata = &frames[a.first_frame*hdr.num_framechannels]; - loopj(a.num_frames) - { + loopj(a.num_frames) { dualquat *frame = &animbones[j*skel->numbones]; - loopk(skel->numbones) - { + loopk(skel->numbones) { iqmpose &p = poses[k]; vec pos; quat orient; @@ -298,8 +252,7 @@ struct iqm : skelloader<iqm> orient.z = -p.offsetorient.z; if(p.mask&0x20) orient.z -= *animdata++ * p.scaleorient.z; orient.w = p.offsetorient.w; if(p.mask&0x40) orient.w += *animdata++ * p.scaleorient.w; orient.normalize(); - if(p.mask&0x380) - { + if(p.mask&0x380) { if(p.mask&0x80) animdata++; if(p.mask&0x100) animdata++; if(p.mask&0x200) animdata++; @@ -313,15 +266,11 @@ struct iqm : skelloader<iqm> } } } - return true; } - - bool loadiqm(const char *filename, bool doloadmesh, bool doloadanim) - { + bool loadiqm(const char *filename, bool doloadmesh, bool doloadanim) { stream *f = openfile(filename, "rb"); if(!f) return false; - uchar *buf = NULL; iqmheader hdr; if(f->read(&hdr, sizeof(hdr)) != sizeof(hdr) || memcmp(hdr.magic, "INTERQUAKEMODEL", sizeof(hdr.magic))) goto error; @@ -330,33 +279,24 @@ struct iqm : skelloader<iqm> if(hdr.filesize > (16<<20)) goto error; // sanity check... don't load files bigger than 16 MB buf = new (false) uchar[hdr.filesize]; if(!buf || f->read(buf + sizeof(hdr), hdr.filesize - sizeof(hdr)) != hdr.filesize - sizeof(hdr)) goto error; - if(doloadmesh && !loadiqmmeshes(filename, hdr, buf)) goto error; if(doloadanim && !loadiqmanims(filename, hdr, buf)) goto error; - delete[] buf; delete f; return true; - error: if(buf) delete[] buf; delete f; return false; } - - bool loadmesh(const char *filename) - { + bool loadmesh(const char *filename) { name = newstring(filename); - return loadiqm(filename, true, false); } - - skelanimspec *loadanim(const char *animname) - { + skelanimspec *loadanim(const char *animname) { const char *sep = strchr(animname, ':'); skelanimspec *sa = skel->findskelanim(animname, sep ? '\0' : ':'); - if(!sa) - { + if(!sa) { string filename; copystring(filename, animname); if(sep) filename[sep - animname] = '\0'; @@ -366,17 +306,13 @@ struct iqm : skelloader<iqm> return sa; } }; - - meshgroup *loadmeshes(const char *name, va_list args) - { + meshgroup *loadmeshes(const char *name, va_list args) { iqmmeshgroup *group = new iqmmeshgroup; group->shareskeleton(va_arg(args, char *)); if(!group->loadmesh(name)) { delete group; return NULL; } return group; } - - bool loaddefaultparts() - { + bool loaddefaultparts() { skelpart &mdl = addpart(); mdl.pitchscale = mdl.pitchoffset = mdl.pitchmin = mdl.pitchmax = 0; adjustments.setsize(0); @@ -393,4 +329,3 @@ struct iqm : skelloader<iqm> }; skelcommands<iqm> iqmcommands; - diff --git a/src/engine/lightmap.cpp b/src/engine/lightmap.cpp index a317dd5..1481de9 100644 --- a/src/engine/lightmap.cpp +++ b/src/engine/lightmap.cpp @@ -6,8 +6,7 @@ struct lightmapinfo; struct lightmaptask; -struct lightmapworker -{ +struct lightmapworker { uchar *buf; int bufstart, bufused; lightmapinfo *firstlightmap, *lastlightmap, *curlightmaps; @@ -25,19 +24,15 @@ struct lightmapworker bool needspace, doneworking; SDL_cond *spacecond; SDL_Thread *thread; - lightmapworker(); ~lightmapworker(); - void reset(); bool setupthread(); void cleanupthread(); - static int work(void *data); }; -struct lightmapinfo -{ +struct lightmapinfo { lightmapinfo *next; cube *c; uchar *colorbuf; @@ -46,8 +41,7 @@ struct lightmapinfo int type, w, h, bpp, bufsize, surface, layers; }; -struct lightmaptask -{ +struct lightmaptask { ivec o; int size, usefaces, progress; cube *c; @@ -56,8 +50,7 @@ struct lightmaptask lightmapworker *worker; }; -struct lightmapext -{ +struct lightmapext { cube *c; cubeext *ext; }; @@ -78,14 +71,12 @@ VARR(lighterror, 1, 8, 16); VARR(bumperror, 1, 3, 16); VARR(lightlod, 0, 0, 10); bvec ambientcolor(36, 24, 12); -HVARFR(ambient, 1, 0x191919, 0xFFFFFF, -{ +HVARFR(ambient, 1, 0x191919, 0xFFFFFF, { if(ambient <= 255) ambient |= (ambient<<8) | (ambient<<16); ambientcolor = bvec((ambient>>16)&0xFF, (ambient>>8)&0xFF, ambient&0xFF); }); -static const surfaceinfo brightsurfaces[6] = -{ +static const surfaceinfo brightsurfaces[6] = { brightsurface, brightsurface, brightsurface, @@ -94,28 +85,23 @@ static const surfaceinfo brightsurfaces[6] = brightsurface }; -void brightencube(cube &c) -{ +void brightencube(cube &c) { if(!c.ext) newcubeext(c, 0, false); memcpy(c.ext->surfaces, brightsurfaces, sizeof(brightsurfaces)); } -void setsurfaces(cube &c, const surfaceinfo *surfs, const vertinfo *verts, int numverts) -{ +void setsurfaces(cube &c, const surfaceinfo *surfs, const vertinfo *verts, int numverts) { if(!c.ext || c.ext->maxverts < numverts) newcubeext(c, numverts, false); memcpy(c.ext->surfaces, surfs, sizeof(c.ext->surfaces)); memcpy(c.ext->verts(), verts, numverts*sizeof(vertinfo)); } -void setsurface(cube &c, int orient, const surfaceinfo &src, const vertinfo *srcverts, int numsrcverts) -{ +void setsurface(cube &c, int orient, const surfaceinfo &src, const vertinfo *srcverts, int numsrcverts) { int dstoffset = 0; if(!c.ext) newcubeext(c, numsrcverts, true); - else - { + else { int numbefore = 0, beforeoffset = 0; - loopi(orient) - { + loopi(orient) { surfaceinfo &surf = c.ext->surfaces[i]; int numverts = surf.totalverts(); if(!numverts) continue; @@ -123,8 +109,7 @@ void setsurface(cube &c, int orient, const surfaceinfo &src, const vertinfo *src beforeoffset = surf.verts + numverts; } int numafter = 0, afteroffset = c.ext->maxverts; - for(int i = 5; i > orient; i--) - { + for(int i = 5; i > orient; i--) { surfaceinfo &surf = c.ext->surfaces[i]; int numverts = surf.totalverts(); if(!numverts) continue; @@ -132,22 +117,18 @@ void setsurface(cube &c, int orient, const surfaceinfo &src, const vertinfo *src afteroffset = surf.verts; } if(afteroffset - beforeoffset >= numsrcverts) dstoffset = beforeoffset; - else - { + else { cubeext *ext = c.ext; - if(numbefore + numsrcverts + numafter > c.ext->maxverts) - { + if(numbefore + numsrcverts + numafter > c.ext->maxverts) { ext = growcubeext(c.ext, numbefore + numsrcverts + numafter); memcpy(ext->surfaces, c.ext->surfaces, sizeof(ext->surfaces)); } int offset = 0; - if(numbefore == beforeoffset) - { + if(numbefore == beforeoffset) { if(numbefore && c.ext != ext) memcpy(ext->verts(), c.ext->verts(), numbefore*sizeof(vertinfo)); offset = numbefore; } - else loopi(orient) - { + else loopi(orient) { surfaceinfo &surf = ext->surfaces[i]; int numverts = surf.totalverts(); if(!numverts) continue; @@ -157,11 +138,9 @@ void setsurface(cube &c, int orient, const surfaceinfo &src, const vertinfo *src } dstoffset = offset; offset += numsrcverts; - if(numafter && offset > afteroffset) - { + if(numafter && offset > afteroffset) { offset += numafter; - for(int i = 5; i > orient; i--) - { + for(int i = 5; i > orient; i--) { surfaceinfo &surf = ext->surfaces[i]; int numverts = surf.totalverts(); if(!numverts) continue; @@ -192,30 +171,23 @@ static int progresstexticks = 0, progresslightmap = -1; bool calclight_canceled = false; volatile bool check_calclight_progress = false; -void check_calclight_canceled() -{ - if(interceptkey(SDLK_ESCAPE)) - { +void check_calclight_canceled() { + if(interceptkey(SDLK_ESCAPE)) { calclight_canceled = true; loopv(lightmapworkers) lightmapworkers[i]->doneworking = true; } if(!calclight_canceled) check_calclight_progress = false; } -void show_calclight_progress() -{ +void show_calclight_progress() { float bar1 = float(progress) / float(allocnodes); defformatstring(text1, "%d%% using %d textures", int(bar1 * 100), lightmaps.length()); - - if(LM_PACKW <= hwtexsize && !progresstex) - { + if(LM_PACKW <= hwtexsize && !progresstex) { glGenTextures(1, &progresstex); createtexture(progresstex, LM_PACKW, LM_PACKH, NULL, 3, 1, GL_RGB); } - // only update once a sec (4 * 250 ms ticks) to not kill performance - if(progresstex && !calclight_canceled && progresslightmap >= 0 && !(progresstexticks++ % 4)) - { + if(progresstex && !calclight_canceled && progresslightmap >= 0 && !(progresstexticks++ % 4)) { if(tasklock) SDL_LockMutex(tasklock); LightMap &lm = lightmaps[progresslightmap]; uchar *data = lm.data; @@ -231,56 +203,45 @@ void show_calclight_progress() #define CHECK_PROGRESS_LOCKED(exit, before, after) CHECK_CALCLIGHT_PROGRESS_LOCKED(exit, show_calclight_progress, before, after) #define CHECK_PROGRESS(exit) CHECK_PROGRESS_LOCKED(exit, , ) -bool PackNode::insert(ushort &tx, ushort &ty, ushort tw, ushort th) -{ +bool PackNode::insert(ushort &tx, ushort &ty, ushort tw, ushort th) { if((available < tw && available < th) || w < tw || h < th) return false; - if(child1) - { + if(child1) { bool inserted = child1->insert(tx, ty, tw, th) || child2->insert(tx, ty, tw, th); available = max(child1->available, child2->available); if(!available) clear(); return inserted; } - if(w == tw && h == th) - { + if(w == tw && h == th) { available = 0; tx = x; ty = y; return true; } - - if(w - tw > h - th) - { + if(w - tw > h - th) { child1 = new PackNode(x, y, tw, h); child2 = new PackNode(x + tw, y, w - tw, h); } - else - { + else { child1 = new PackNode(x, y, w, th); child2 = new PackNode(x, y + th, w, h - th); } - bool inserted = child1->insert(tx, ty, tw, th); available = max(child1->available, child2->available); return inserted; } -bool LightMap::insert(ushort &tx, ushort &ty, uchar *src, ushort tw, ushort th) -{ +bool LightMap::insert(ushort &tx, ushort &ty, uchar *src, ushort tw, ushort th) { if((type&LM_TYPE) != LM_BUMPMAP1 && !packroot.insert(tx, ty, tw, th)) return false; - copy(tx, ty, src, tw, th); return true; } -void LightMap::copy(ushort tx, ushort ty, uchar *src, ushort tw, ushort th) -{ +void LightMap::copy(ushort tx, ushort ty, uchar *src, ushort tw, ushort th) { uchar *dst = data + bpp * tx + ty * bpp * LM_PACKW; - loopi(th) - { + loopi(th) { memcpy(dst, src, bpp * tw); dst += bpp * LM_PACKW; src += bpp * tw; @@ -289,20 +250,16 @@ void LightMap::copy(ushort tx, ushort ty, uchar *src, ushort tw, ushort th) lumels += tw * th; } -static void insertunlit(int i) -{ +static void insertunlit(int i) { LightMap &l = lightmaps[i]; - if((l.type&LM_TYPE) == LM_BUMPMAP1) - { + if((l.type&LM_TYPE) == LM_BUMPMAP1) { l.unlitx = l.unlity = -1; return; } ushort x, y; uchar unlit[4] = { ambientcolor[0], ambientcolor[1], ambientcolor[2], 255 }; - if(l.insert(x, y, unlit, 1, 1)) - { - if((l.type&LM_TYPE) == LM_BUMPMAP0) - { + if(l.insert(x, y, unlit, 1, 1)) { + if((l.type&LM_TYPE) == LM_BUMPMAP0) { bvec front(128, 128, 255); ASSERT(lightmaps[i+1].insert(x, y, front.v, 1, 1)); } @@ -311,26 +268,20 @@ static void insertunlit(int i) } } -struct layoutinfo -{ +struct layoutinfo { ushort x, y, lmid; uchar w, h; }; -static void insertlightmap(lightmapinfo &li, layoutinfo &si) -{ - loopv(lightmaps) - { - if(lightmaps[i].type == li.type && lightmaps[i].insert(si.x, si.y, li.colorbuf, si.w, si.h)) - { +static void insertlightmap(lightmapinfo &li, layoutinfo &si) { + loopv(lightmaps) { + if(lightmaps[i].type == li.type && lightmaps[i].insert(si.x, si.y, li.colorbuf, si.w, si.h)) { si.lmid = i + LMID_RESERVED; if((li.type&LM_TYPE) == LM_BUMPMAP0) ASSERT(lightmaps[i+1].insert(si.x, si.y, (uchar *)li.raybuf, si.w, si.h)); return; } } - progresslightmap = lightmaps.length(); - si.lmid = lightmaps.length() + LMID_RESERVED; LightMap &l = lightmaps.add(); l.type = li.type; @@ -338,8 +289,7 @@ static void insertlightmap(lightmapinfo &li, layoutinfo &si) l.data = new uchar[li.bpp*LM_PACKW*LM_PACKH]; memset(l.data, 0, li.bpp*LM_PACKW*LM_PACKH); ASSERT(l.insert(si.x, si.y, li.colorbuf, si.w, si.h)); - if((li.type&LM_TYPE) == LM_BUMPMAP0) - { + if((li.type&LM_TYPE) == LM_BUMPMAP0) { LightMap &r = lightmaps.add(); r.type = LM_BUMPMAP1 | (li.type&~LM_TYPE); r.bpp = 3; @@ -349,8 +299,7 @@ static void insertlightmap(lightmapinfo &li, layoutinfo &si) } } -static inline bool htcmp(const lightmapinfo &k, const layoutinfo &v) -{ +static inline bool htcmp(const lightmapinfo &k, const layoutinfo &v) { int kw = k.w, kh = k.h; if(kw != v.w || kh != v.h) return false; LightMap &vlm = lightmaps[v.lmid - LMID_RESERVED]; @@ -358,16 +307,14 @@ static inline bool htcmp(const lightmapinfo &k, const layoutinfo &v) if(ktype != vlm.type) return false; int kbpp = k.bpp; const uchar *kcolor = k.colorbuf, *vcolor = vlm.data + kbpp*(v.x + v.y*LM_PACKW); - loopi(kh) - { + loopi(kh) { if(memcmp(kcolor, vcolor, kbpp*kw)) return false; kcolor += kbpp*kw; vcolor += kbpp*LM_PACKW; } if((ktype&LM_TYPE) != LM_BUMPMAP0) return true; const bvec *kdir = k.raybuf, *vdir = (const bvec *)lightmaps[v.lmid+1 - LMID_RESERVED].data + (v.x + v.y*LM_PACKW); - loopi(kh) - { + loopi(kh) { if(memcmp(kdir, vdir, kw*sizeof(bvec))) return false; kdir += kw; vdir += LM_PACKW; @@ -375,13 +322,11 @@ static inline bool htcmp(const lightmapinfo &k, const layoutinfo &v) return true; } -static inline uint hthash(const lightmapinfo &k) -{ +static inline uint hthash(const lightmapinfo &k) { int kw = k.w, kh = k.h, kbpp = k.bpp; uint hash = kw + (kh<<8); const uchar *color = k.colorbuf; - loopi(kw*kh) - { + loopi(kw*kh) { hash ^= color[0] + (color[1] << 4) + (color[2] << 8); color += kbpp; } @@ -392,20 +337,16 @@ static hashset<layoutinfo> compressed; VAR(lightcompress, 0, 3, 6); -static bool packlightmap(lightmapinfo &l, layoutinfo &surface) -{ +static bool packlightmap(lightmapinfo &l, layoutinfo &surface) { surface.w = l.w; surface.h = l.h; - if((int)l.w <= lightcompress && (int)l.h <= lightcompress) - { + if((int)l.w <= lightcompress && (int)l.h <= lightcompress) { layoutinfo *val = compressed.access(l); - if(!val) - { + if(!val) { insertlightmap(l, surface); compressed[l] = surface; } - else - { + else { surface.x = val->x; surface.y = val->y; surface.lmid = val->lmid; @@ -416,13 +357,11 @@ static bool packlightmap(lightmapinfo &l, layoutinfo &surface) return true; } -static uint generatelumel(lightmapworker *w, const float tolerance, uint lightmask, const vector<const extentity *> &lights, const vec &target, const vec &normal, vec &sample, int x, int y) -{ +static uint generatelumel(lightmapworker *w, const float tolerance, uint lightmask, const vector<const extentity *> &lights, const vec &target, const vec &normal, vec &sample, int x, int y) { vec avgray(0, 0, 0); float r = 0, g = 0, b = 0; uint lightused = 0; - loopv(lights) - { + loopv(lights) { if(lightmask&(1<<i)) continue; const extentity &light = *lights[i]; vec ray = target; @@ -430,30 +369,26 @@ static uint generatelumel(lightmapworker *w, const float tolerance, uint lightma float mag = ray.magnitude(); if(!mag) continue; float attenuation = 1; - if(light.attr1) - { + if(light.attr1) { attenuation -= mag / float(light.attr1); if(attenuation <= 0) continue; } ray.mul(1.0f / mag); float angle = -ray.dot(normal); if(angle <= 0) continue; - if(light.attached && light.attached->type==ET_SPOTLIGHT) - { + if(light.attached && light.attached->type==ET_SPOTLIGHT) { vec spot = vec(light.attached->o).sub(light.o).normalize(); float maxatten = sincos360[clamp(int(light.attached->attr1), 1, 89)].x, spotatten = (ray.dot(spot) - maxatten) / (1 - maxatten); if(spotatten <= 0) continue; attenuation *= spotatten; } - if(lmshadows && mag) - { + if(lmshadows && mag) { float dist = shadowray(w->shadowraycache, light.o, ray, mag - tolerance, RAY_SHADOW | (lmshadows > 1 ? RAY_ALPHAPOLY : 0)); if(dist < mag - tolerance) continue; } lightused |= 1<<i; float intensity; - switch(w->type&LM_TYPE) - { + switch(w->type&LM_TYPE) { case LM_BUMPMAP0: intensity = attenuation; avgray.add(ray.mul(-attenuation)); @@ -466,8 +401,7 @@ static uint generatelumel(lightmapworker *w, const float tolerance, uint lightma g += intensity * float(light.attr3); b += intensity * float(light.attr4); } - switch(w->type&LM_TYPE) - { + switch(w->type&LM_TYPE) { case LM_BUMPMAP0: if(avgray.iszero()) break; // transform to tangent space @@ -486,8 +420,7 @@ static uint generatelumel(lightmapworker *w, const float tolerance, uint lightma return lightused; } -static bool lumelsample(const vec &sample, int aasample, int stride) -{ +static bool lumelsample(const vec &sample, int aasample, int stride) { if(sample.x >= int(ambientcolor[0])+1 || sample.y >= int(ambientcolor[1])+1 || sample.z >= int(ambientcolor[2])+1) return true; #define NCHECK(n) \ if((n).x >= int(ambientcolor[0])+1 || (n).y >= int(ambientcolor[1])+1 || (n).z >= int(ambientcolor[2])+1) \ @@ -501,11 +434,9 @@ static bool lumelsample(const vec &sample, int aasample, int stride) return false; } -static inline void generatealpha(lightmapworker *w, float tolerance, const vec &pos, uchar &alpha) -{ +static inline void generatealpha(lightmapworker *w, float tolerance, const vec &pos, uchar &alpha) { alpha = 0; - if(w->slot->layermask) - { + if(w->slot->layermask) { static const int sdim[] = { 1, 0, 0 }, tdim[] = { 2, 2, 1 }; int dim = dimension(w->orient); float k = 8.0f/w->vslot->scale, @@ -520,8 +451,7 @@ static inline void generatealpha(lightmapworker *w, float tolerance, const vec & if(mx < 0) mx += mask.w; if(my < 0) my += mask.h; uchar maskval = mask.data[mask.bpp*(mx + 1) - 1 + mask.pitch*my]; - switch(w->slot->layermaskmode) - { + switch(w->slot->layermaskmode) { case 2: alpha = min(alpha, maskval); break; case 3: alpha = max(alpha, maskval); break; case 4: alpha = min(alpha, uchar(0xFF - maskval)); break; @@ -534,8 +464,7 @@ static inline void generatealpha(lightmapworker *w, float tolerance, const vec & VAR(edgetolerance, 1, 4, 64); VAR(adaptivesample, 0, 2, 2); -enum -{ +enum { NO_SURFACE = 0, SURFACE_AMBIENT_BOTTOM, SURFACE_AMBIENT_TOP, @@ -547,33 +476,29 @@ enum #define SURFACE_AMBIENT SURFACE_AMBIENT_BOTTOM #define SURFACE_LIGHTMAP SURFACE_LIGHTMAP_BOTTOM -static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, int numv, vec origin1, const vec &xstep1, const vec &ystep1, vec origin2, const vec &xstep2, const vec &ystep2, float side0, float sidestep) -{ - static const float aacoords[8][2] = - { - {0.0f, 0.0f}, - {-0.5f, -0.5f}, - {0.0f, -0.5f}, - {-0.5f, 0.0f}, - - {0.3f, -0.6f}, - {0.6f, 0.3f}, - {-0.3f, 0.6f}, - {-0.6f, -0.3f}, +static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, int numv, vec origin1, const vec &xstep1, const vec &ystep1, vec origin2, const vec &xstep2, const vec &ystep2, float side0, float sidestep) { + static const float aacoords[8][2] = { + { + 0.0f, 0.0f}, { + -0.5f, -0.5f}, { + 0.0f, -0.5f}, { + -0.5f, 0.0f}, + { + 0.3f, -0.6f}, { + 0.6f, 0.3f}, { + -0.3f, 0.6f}, { + -0.6f, -0.3f}, }; float tolerance = 0.5 / lpu; uint lightmask = 0, lightused = 0; vec offsets1[8], offsets2[8]; - loopi(8) - { + loopi(8) { offsets1[i] = vec(xstep1).mul(aacoords[i][0]).add(vec(ystep1).mul(aacoords[i][1])); offsets2[i] = vec(xstep2).mul(aacoords[i][0]).add(vec(ystep2).mul(aacoords[i][1])); } if((w->type&LM_TYPE) == LM_BUMPMAP0) memclear(w->raydata, (LM_MAXW + 4)*(LM_MAXH + 4)); - origin1.sub(vec(ystep1).add(xstep1).mul(0)); origin2.sub(vec(ystep2).add(xstep2).mul(0)); - int aasample = min(1 << lmaa, 4); int stride = aasample*(w->w+1); vec *sample = w->colordata; @@ -581,13 +506,10 @@ static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, i lerpbounds start, end; initlerpbounds(-0, -0, lv, numv, start, end); float sidex = side0 + 0*sidestep; - for(int y = 0; y < w->h; ++y, sidex += sidestep) - { + for(int y = 0; y < w->h; ++y, sidex += sidestep) { vec normal, nstep; lerpnormal(-0, y - 0, lv, numv, start, end, normal, nstep); - - for(int x = 0; x < w->w; ++x, normal.add(nstep), amb += w->bpp) - { + for(int x = 0; x < w->w; ++x, normal.add(nstep), amb += w->bpp) { #define EDGE_TOLERANCE(x, y) \ (x < 0 \ || x+1 > w->w - 0 \ @@ -605,28 +527,22 @@ static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, i sample = w->colordata; initlerpbounds(-0, -0, lv, numv, start, end); sidex = side0 + 0*sidestep; - for(int y = 0; y < w->h; ++y, sidex += sidestep) - { + for(int y = 0; y < w->h; ++y, sidex += sidestep) { vec normal, nstep; lerpnormal(-0, y - 0, lv, numv, start, end, normal, nstep); - - for(int x = 0; x < w->w; ++x, normal.add(nstep)) - { + for(int x = 0; x < w->w; ++x, normal.add(nstep)) { vec ¢er = *sample++; if(adaptivesample && x > 0 && x+1 < w->w && y > 0 && y+1 < w->h && !lumelsample(center, aasample, stride)) loopi(aasample-1) *sample++ = center; - else - { + else { #define AA_EDGE_TOLERANCE(x, y, i) EDGE_TOLERANCE(x + aacoords[i][0], y + aacoords[i][1]) vec u = x < sidex ? vec(xstep1).mul(x).add(vec(ystep1).mul(y)).add(origin1) : vec(xstep2).mul(x).add(vec(ystep2).mul(y)).add(origin2); const vec *offsets = x < sidex ? offsets1 : offsets2; vec n = vec(normal).normalize(); loopi(aasample-1) generatelumel(w, AA_EDGE_TOLERANCE(x, y, i+1) * tolerance, lightmask, w->lights, vec(u).add(offsets[i+1]), n, *sample++, x, y); - if(lmaa == 3) - { - loopi(4) - { + if(lmaa == 3) { + loopi(4) { vec s; generatelumel(w, AA_EDGE_TOLERANCE(x, y, i+4) * tolerance, lightmask, w->lights, vec(u).add(offsets[i+4]), n, s, x, y); center.add(s); @@ -635,8 +551,7 @@ static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, i } } } - if(aasample > 1) - { + if(aasample > 1) { vec u = w->w < sidex ? vec(xstep1).mul(w->w).add(vec(ystep1).mul(y)).add(origin1) : vec(xstep2).mul(w->w).add(vec(ystep2).mul(y)).add(origin2); const vec *offsets = w->w < sidex ? offsets1 : offsets2; vec n = vec(normal).normalize(); @@ -646,14 +561,10 @@ static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, i } sample += aasample; } - - if(aasample > 1) - { + if(aasample > 1) { vec normal, nstep; lerpnormal(-0, w->h - 0, lv, numv, start, end, normal, nstep); - - for(int x = 0; x <= w->w; ++x, normal.add(nstep)) - { + for(int x = 0; x <= w->w; ++x, normal.add(nstep)) { vec u = x < sidex ? vec(xstep1).mul(x).add(vec(ystep1).mul(w->h)).add(origin1) : vec(xstep2).mul(x).add(vec(ystep2).mul(w->h)).add(origin2); const vec *offsets = x < sidex ? offsets1 : offsets2; vec n = vec(normal).normalize(); @@ -666,8 +577,7 @@ static bool generatelightmap(lightmapworker *w, float lpu, const lerpvert *lv, i return true; } -static int finishlightmap(lightmapworker *w) -{ +static int finishlightmap(lightmapworker *w) { vec *sample = w->colordata; int aasample = min(1 << lmaa, 4), stride = aasample*(w->w+1); float weight = 1.0f / (1.0f + 4.0f*lmaa), @@ -677,26 +587,21 @@ static int finishlightmap(lightmapworker *w) uchar mincolor[4] = { 255, 255, 255, 255 }, maxcolor[4] = { 0, 0, 0, 0 }; bvec *dstray = 0 && (w->w > 1 || w->h > 1) ? (bvec *)w->raydata : w->raybuf; bvec minray(255, 255, 255), maxray(0, 0, 0); - loop(y, w->h) - { - loop(x, w->w) - { + loop(y, w->h) { + loop(x, w->w) { vec l(0, 0, 0); const vec ¢er = *sample++; loopi(aasample-1) l.add(*sample++); - if(aasample > 1) - { + if(aasample > 1) { l.add(sample[1]); if(aasample > 2) l.add(sample[3]); } vec *next = sample + stride - aasample; - if(aasample > 1) - { + if(aasample > 1) { l.add(next[1]); if(aasample > 2) l.add(next[2]); l.add(next[aasample+1]); } - int r = int(center.x*cweight + l.x*weight), g = int(center.y*cweight + l.y*weight), b = int(center.z*cweight + l.z*weight), @@ -704,30 +609,25 @@ static int finishlightmap(lightmapworker *w) dstcolor[0] = max(ar, r); dstcolor[1] = max(ag, g); dstcolor[2] = max(ab, b); - loopk(3) - { + loopk(3) { mincolor[k] = min(mincolor[k], dstcolor[k]); maxcolor[k] = max(maxcolor[k], dstcolor[k]); } - if(w->type&LM_ALPHA) - { + if(w->type&LM_ALPHA) { dstcolor[3] = 127;///TODO mincolor[3] = min(mincolor[3], dstcolor[3]); maxcolor[3] = max(maxcolor[3], dstcolor[3]); } - if((w->type&LM_TYPE) == LM_BUMPMAP0) - { + if((w->type&LM_TYPE) == LM_BUMPMAP0) { if(ray->iszero()) dstray[0] = bvec(128, 128, 255); - else - { + else { ray->normalize(); int l = max(r, max(g, b)), a = max(ar, max(ag, ab)); ray->mul(max(l-a, 0)); ray->z += a; dstray[0] = bvec(ray->normalize()); } - loopk(3) - { + loopk(3) { minray[k] = min(minray[k], dstray[0][k]); maxray[k] = max(maxray[k], dstray[0][k]); } @@ -741,8 +641,7 @@ static int finishlightmap(lightmapworker *w) if(int(maxcolor[0]) - int(mincolor[0]) <= lighterror && int(maxcolor[1]) - int(mincolor[1]) <= lighterror && int(maxcolor[2]) - int(mincolor[2]) <= lighterror && - mincolor[3] >= maxcolor[3]) - { + mincolor[3] >= maxcolor[3]) { uchar color[3]; loopk(3) color[k] = (int(maxcolor[k]) + int(mincolor[k])) / 2; if(color[0] <= int(ambientcolor[0]) + lighterror && @@ -754,12 +653,10 @@ static int finishlightmap(lightmapworker *w) (int(maxray.x) - int(minray.x) <= bumperror && int(maxray.y) - int(minray.z) <= bumperror && int(maxray.z) - int(minray.z) <= bumperror)) - - { + { memcpy(w->colorbuf, color, 3); if(w->type&LM_ALPHA) w->colorbuf[3] = mincolor[3]; - if((w->type&LM_TYPE) == LM_BUMPMAP0) - { + if((w->type&LM_TYPE) == LM_BUMPMAP0) { loopk(3) w->raybuf[0][k] = uchar((int(maxray[k])+int(minray[k]))/2); } w->lastlightmap->w = w->w = 1; @@ -771,17 +668,14 @@ static int finishlightmap(lightmapworker *w) else return SURFACE_LIGHTMAP_BLEND; } -static int previewlightmapalpha(lightmapworker *w, float lpu, const vec &origin1, const vec &xstep1, const vec &ystep1, const vec &origin2, const vec &xstep2, const vec &ystep2, float side0, float sidestep) -{ +static int previewlightmapalpha(lightmapworker *w, float lpu, const vec &origin1, const vec &xstep1, const vec &ystep1, const vec &origin2, const vec &xstep2, const vec &ystep2, float side0, float sidestep) { extern int fullbrightlevel; float tolerance = 0.5 / lpu; uchar *dst = w->colorbuf; uchar minalpha = 255, maxalpha = 0; float sidex = side0; - for(int y = 0; y < w->h; ++y, sidex += sidestep) - { - for(int x = 0; x < w->w; ++x, dst += 4) - { + for(int y = 0; y < w->h; ++y, sidex += sidestep) { + for(int x = 0; x < w->w; ++x, dst += 4) { vec u = x < sidex ? vec(xstep1).mul(x).add(vec(ystep1).mul(y)).add(origin1) : vec(xstep2).mul(x).add(vec(ystep2).mul(y)).add(origin2); @@ -798,25 +692,18 @@ static int previewlightmapalpha(lightmapworker *w, float lpu, const vec &origin1 return SURFACE_LIGHTMAP_BLEND; } -static void clearsurfaces(cube *c) -{ - loopi(8) - { - if(c[i].ext) - { - loopj(6) - { +static void clearsurfaces(cube *c) { + loopi(8) { + if(c[i].ext) { + loopj(6) { surfaceinfo &surf = c[i].ext->surfaces[j]; if(!surf.used()) continue; surf.clear(); int numverts = surf.numverts&MAXFACEVERTS; - if(numverts) - { + if(numverts) { if(!(c[i].merged&(1<<j))) { surf.numverts &= ~MAXFACEVERTS; continue; } - vertinfo *verts = c[i].ext->verts() + surf.verts; - loopk(numverts) - { + loopk(numverts) { vertinfo &v = verts[k]; v.u = 0; v.v = 0; @@ -831,8 +718,7 @@ static void clearsurfaces(cube *c) #define LIGHTCACHESIZE 1024 -static struct lightcacheentry -{ +static struct lightcacheentry { int x, y; vector<int> lights; } lightcache[LIGHTCACHESIZE]; @@ -841,17 +727,13 @@ static struct lightcacheentry VARF(lightcachesize, 4, 6, 12, clearlightcache()); -void clearlightcache(int id) -{ - if(id >= 0) - { +void clearlightcache(int id) { + if(id >= 0) { const extentity &light = *entities::getents()[id]; int radius = light.attr1; - if(radius) - { + if(radius) { for(int x = int(max(light.o.x-radius, 0.0f))>>lightcachesize, ex = int(min(light.o.x+radius, worldsize-1.0f))>>lightcachesize; x <= ex; x++) - for(int y = int(max(light.o.y-radius, 0.0f))>>lightcachesize, ey = int(min(light.o.y+radius, worldsize-1.0f))>>lightcachesize; y <= ey; y++) - { + for(int y = int(max(light.o.y-radius, 0.0f))>>lightcachesize, ey = int(min(light.o.y+radius, worldsize-1.0f))>>lightcachesize; y <= ey; y++) { lightcacheentry &lce = lightcache[LIGHTCACHEHASH(x, y)]; if(lce.x != x || lce.y != y) continue; lce.x = -1; @@ -860,34 +742,26 @@ void clearlightcache(int id) return; } } - - for(lightcacheentry *lce = lightcache; lce < &lightcache[LIGHTCACHESIZE]; lce++) - { + for(lightcacheentry *lce = lightcache; lce < &lightcache[LIGHTCACHESIZE]; lce++) { lce->x = -1; lce->lights.setsize(0); } } -const vector<int> &checklightcache(int x, int y) -{ +const vector<int> &checklightcache(int x, int y) { x >>= lightcachesize; y >>= lightcachesize; lightcacheentry &lce = lightcache[LIGHTCACHEHASH(x, y)]; if(lce.x == x && lce.y == y) return lce.lights; - lce.lights.setsize(0); int csize = 1<<lightcachesize, cx = x<<lightcachesize, cy = y<<lightcachesize; const vector<extentity *> &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { const extentity &light = *ents[i]; - switch(light.type) - { - case ET_LIGHT: - { + switch(light.type) { + case ET_LIGHT: { int radius = light.attr1; - if(radius > 0) - { + if(radius > 0) { if(light.o.x + radius < cx || light.o.x - radius > cx + csize || light.o.y + radius < cy || light.o.y - radius > cy + csize) continue; @@ -898,60 +772,48 @@ const vector<int> &checklightcache(int x, int y) } lce.lights.add(i); } - lce.x = x; lce.y = y; return lce.lights; } -static inline void addlight(lightmapworker *w, const extentity &light, int cx, int cy, int cz, int size, const vec *v, const vec *n, int numv) -{ +static inline void addlight(lightmapworker *w, const extentity &light, int cx, int cy, int cz, int size, const vec *v, const vec *n, int numv) { int radius = light.attr1; - if(radius > 0) - { + if(radius > 0) { if(light.o.x + radius < cx || light.o.x - radius > cx + size || light.o.y + radius < cy || light.o.y - radius > cy + size || light.o.z + radius < cz || light.o.z - radius > cz + size) return; } - - loopi(4) - { + loopi(4) { vec p(light.o); p.sub(v[i]); float dist = p.dot(n[i]); - if(dist >= 0 && (!radius || dist < radius)) - { + if(dist >= 0 && (!radius || dist < radius)) { w->lights.add(&light); break; } } } -static bool findlights(lightmapworker *w, int cx, int cy, int cz, int size, const vec *v, const vec *n, int numv, const Slot &slot, const VSlot &vslot) -{ +static bool findlights(lightmapworker *w, int cx, int cy, int cz, int size, const vec *v, const vec *n, int numv, const Slot &slot, const VSlot &vslot) { w->lights.setsize(0); const vector<extentity *> &ents = entities::getents(); static volatile bool usinglightcache = false; - if(size <= 1<<lightcachesize && (!lightlock || !usinglightcache)) - { + if(size <= 1<<lightcachesize && (!lightlock || !usinglightcache)) { if(lightlock) { SDL_LockMutex(lightlock); usinglightcache = true; } const vector<int> &lights = checklightcache(cx, cy); - loopv(lights) - { + loopv(lights) { const extentity &light = *ents[lights[i]]; - switch(light.type) - { + switch(light.type) { case ET_LIGHT: addlight(w, light, cx, cy, cz, size, v, n, numv); break; } } if(lightlock) { usinglightcache = false; SDL_UnlockMutex(lightlock); } } - else loopv(ents) - { + else loopv(ents) { const extentity &light = *ents[i]; - switch(light.type) - { + switch(light.type) { case ET_LIGHT: addlight(w, light, cx, cy, cz, size, v, n, numv); break; } } @@ -959,15 +821,12 @@ static bool findlights(lightmapworker *w, int cx, int cy, int cz, int size, cons return w->lights.length(); } -static int packlightmaps(lightmapworker *w = NULL) -{ +static int packlightmaps(lightmapworker *w = NULL) { int numpacked = 0; - for(; packidx < lightmaptasks[0].length(); packidx++, numpacked++) - { + for(; packidx < lightmaptasks[0].length(); packidx++, numpacked++) { lightmaptask &t = lightmaptasks[0][packidx]; if(!t.lightmaps) break; - if(t.ext && t.c->ext != t.ext) - { + if(t.ext && t.c->ext != t.ext) { lightmapext &e = lightmapexts.add(); e.c = t.c; e.ext = t.ext; @@ -976,8 +835,7 @@ static int packlightmaps(lightmapworker *w = NULL) lightmapinfo *l = t.lightmaps; if(l == (lightmapinfo *)-1) continue; int space = 0; - for(; l && l->c == t.c; l = l->next) - { + for(; l && l->c == t.c; l = l->next) { l->packed = true; space += l->bufsize; if(l->surface < 0 || !t.ext) continue; @@ -986,31 +844,26 @@ static int packlightmaps(lightmapworker *w = NULL) packlightmap(*l, layout); int numverts = surf.numverts&MAXFACEVERTS; vertinfo *verts = t.ext->verts() + surf.verts; - if(l->layers&LAYER_DUP) - { + if(l->layers&LAYER_DUP) { if(l->type&LM_ALPHA) surf.lmid[0] = layout.lmid; else { surf.lmid[1] = layout.lmid; verts += numverts; } } - else - { + else { if(l->layers&LAYER_TOP) surf.lmid[0] = layout.lmid; if(l->layers&LAYER_BOTTOM) surf.lmid[1] = layout.lmid; } ushort offsetx = layout.x*((USHRT_MAX+1)/LM_PACKW), offsety = layout.y*((USHRT_MAX+1)/LM_PACKH); - loopk(numverts) - { + loopk(numverts) { vertinfo &v = verts[k]; v.u += offsetx; v.v += offsety; } } - if(t.worker == w) - { + if(t.worker == w) { w->bufused -= space; w->bufstart = (w->bufstart + space)%LIGHTMAPBUFSIZE; w->firstlightmap = l; - if(!l) - { + if(!l) { w->lastlightmap = NULL; w->bufstart = w->bufused = 0; } @@ -1020,8 +873,7 @@ static int packlightmaps(lightmapworker *w = NULL) return numpacked; } -static lightmapinfo *alloclightmap(lightmapworker *w) -{ +static lightmapinfo *alloclightmap(lightmapworker *w) { int needspace1 = sizeof(lightmapinfo) + w->w*w->h*w->bpp, needspace2 = (w->type&LM_TYPE) == LM_BUMPMAP0 ? w->w*w->h*3 : 0, needspace = needspace1 + needspace2, @@ -1029,20 +881,16 @@ static lightmapinfo *alloclightmap(lightmapworker *w) availspace = LIGHTMAPBUFSIZE - w->bufused, availspace1 = min(availspace, LIGHTMAPBUFSIZE - bufend), availspace2 = min(availspace, w->bufstart); - if(availspace < needspace || (max(availspace1, availspace2) < needspace && (availspace1 < needspace1 || availspace2 < needspace2))) - { + if(availspace < needspace || (max(availspace1, availspace2) < needspace && (availspace1 < needspace1 || availspace2 < needspace2))) { if(tasklock) SDL_LockMutex(tasklock); - while(!w->doneworking) - { + while(!w->doneworking) { lightmapinfo *l = w->firstlightmap; - for(; l && l->packed; l = l->next) - { + for(; l && l->packed; l = l->next) { w->bufused -= l->bufsize; w->bufstart = (w->bufstart + l->bufsize)%LIGHTMAPBUFSIZE; } w->firstlightmap = l; - if(!l) - { + if(!l) { w->lastlightmap = NULL; w->bufstart = w->bufused = 0; } @@ -1061,20 +909,17 @@ static lightmapinfo *alloclightmap(lightmapworker *w) } int usedspace = needspace; lightmapinfo *l = NULL; - if(availspace1 >= needspace1) - { + if(availspace1 >= needspace1) { l = (lightmapinfo *)&w->buf[bufend]; w->colorbuf = (uchar *)(l + 1); if((w->type&LM_TYPE) != LM_BUMPMAP0) w->raybuf = NULL; else if(availspace1 >= needspace) w->raybuf = (bvec *)&w->buf[bufend + needspace1]; - else - { + else { w->raybuf = (bvec *)w->buf; usedspace += availspace1 - needspace1; } } - else if(availspace2 >= needspace) - { + else if(availspace2 >= needspace) { usedspace += availspace1; l = (lightmapinfo *)w->buf; w->colorbuf = (uchar *)(l + 1); @@ -1101,17 +946,14 @@ static lightmapinfo *alloclightmap(lightmapworker *w) return l; } -static void freelightmap(lightmapworker *w) -{ +static void freelightmap(lightmapworker *w) { lightmapinfo *l = w->lastlightmap; if(!l || l->surface >= 0) return; - if(w->firstlightmap == w->lastlightmap) - { + if(w->firstlightmap == w->lastlightmap) { w->firstlightmap = w->lastlightmap = w->curlightmaps = NULL; w->bufstart = w->bufused = 0; } - else - { + else { w->bufused -= l->bufsize - sizeof(lightmapinfo); l->bufsize = sizeof(lightmapinfo); l->packed = true; @@ -1119,11 +961,9 @@ static void freelightmap(lightmapworker *w) if(w->curlightmaps == l) w->curlightmaps = NULL; } -static int setupsurface(lightmapworker *w, plane planes[2], int numplanes, const vec *p, const vec *n, int numverts, vertinfo *litverts, bool preview = false) -{ +static int setupsurface(lightmapworker *w, plane planes[2], int numplanes, const vec *p, const vec *n, int numverts, vertinfo *litverts, bool preview = false) { vec u, v, t; vec2 c[MAXFACEVERTS]; - u = vec(p[2]).sub(p[0]).normalize(); v.cross(planes[0], u); c[0] = vec2(0, 0); @@ -1131,24 +971,20 @@ static int setupsurface(lightmapworker *w, plane planes[2], int numplanes, const vec r1 = vec(p[1]).sub(p[0]); c[1] = vec2(r1.dot(u), min(r1.dot(v), 0.0f)); c[2] = vec2(vec(p[2]).sub(p[0]).dot(u), 0); - for(int i = 3; i < numverts; i++) - { + for(int i = 3; i < numverts; i++) { vec r = vec(p[i]).sub(p[0]); c[i] = vec2(r.dot(u), max(r.dot(t), 0.0f)); } - float carea = 1e16f; vec2 cx(0, 0), cy(0, 0), co(0, 0), cmin(0, 0), cmax(0, 0); - loopi(numverts) - { + loopi(numverts) { vec2 px = vec2(c[i+1 < numverts ? i+1 : 0]).sub(c[i]); float len = px.squaredlen(); if(!len) continue; px.mul(1/sqrtf(len)); vec2 py(-px.y, px.x), pmin(0, 0), pmax(0, 0); if(numplanes >= 2 && (i == 0 || i >= 3)) px.neg(); - loopj(numverts) - { + loopj(numverts) { vec2 rj = vec2(c[j]).sub(c[i]), pj(rj.dot(px), rj.dot(py)); pmin.x = min(pmin.x, pj.x); pmin.y = min(pmin.y, pj.y); @@ -1158,29 +994,24 @@ static int setupsurface(lightmapworker *w, plane planes[2], int numplanes, const float area = (pmax.x-pmin.x)*(pmax.y-pmin.y); if(area < carea) { carea = area; cx = px; cy = py; co = c[i]; cmin = pmin; cmax = pmax; } } - int scale = int(min(cmax.x - cmin.x, cmax.y - cmin.y)); float lpu = 16.0f / float(lightlod && scale < (1 << lightlod) ? max(lightprecision / 2, 1) : lightprecision); int lw = clamp(int(ceil((cmax.x - cmin.x + 1)*lpu)), LM_MINW, LM_MAXW), lh = clamp(int(ceil((cmax.y - cmin.y + 1)*lpu)), LM_MINH, LM_MAXH); w->w = lw; w->h = lh; if(!alloclightmap(w)) return NO_SURFACE; - vec2 cscale = vec2(cmax).sub(cmin).div(vec2(lw-1, lh-1)), comin = vec2(cx).mul(cmin.x).add(vec2(cy).mul(cmin.y)).add(co); - loopi(numverts) - { + loopi(numverts) { vec2 ri = vec2(c[i]).sub(comin); c[i] = vec2(ri.dot(cx)/cscale.x, ri.dot(cy)/cscale.y); } - vec xstep1 = vec(v).mul(cx.y).add(vec(u).mul(cx.x)).mul(cscale.x), ystep1 = vec(v).mul(cy.y).add(vec(u).mul(cy.x)).mul(cscale.y), origin1 = vec(v).mul(comin.y).add(vec(u).mul(comin.x)).add(p[0]), xstep2 = xstep1, ystep2 = ystep1, origin2 = origin1; float side0 = LM_MAXW + 1, sidestep = 0; - if(numplanes >= 2) - { + if(numplanes >= 2) { xstep2 = vec(t).mul(cx.y).add(vec(u).mul(cx.x)).mul(cscale.x); ystep2 = vec(t).mul(cy.y).add(vec(u).mul(cy.x)).mul(cscale.y); origin2 = vec(t).mul(comin.y).add(vec(u).mul(comin.x)).add(p[0]); @@ -1188,41 +1019,33 @@ static int setupsurface(lightmapworker *w, plane planes[2], int numplanes, const else if(cy.y) { side0 = ceil(comin.y/-(cy.y*cscale.y))*(LM_MAXW + 1); sidestep = -(LM_MAXW + 1); if(cy.y < 0) { side0 = (LM_MAXW + 1) - side0; sidestep = -sidestep; } } else side0 = comin.y <= 0 ? LM_MAXW + 1 : -1; } - int surftype = NO_SURFACE; - if(preview) - { + if(preview) { surftype = previewlightmapalpha(w, lpu, origin1, xstep1, ystep1, origin2, xstep2, ystep2, side0, sidestep); } - else - { + else { lerpvert lv[MAXFACEVERTS]; int numv = numverts; calclerpverts(c, n, lv, numv); - if(!generatelightmap(w, lpu, lv, numv, origin1, xstep1, ystep1, origin2, xstep2, ystep2, side0, sidestep)) return NO_SURFACE; surftype = finishlightmap(w); } if(surftype<SURFACE_LIGHTMAP) return surftype; - vec2 texscale(float(USHRT_MAX+1)/LM_PACKW, float(USHRT_MAX+1)/LM_PACKH); if(lw != w->w) texscale.x *= float(w->w - 1) / (lw - 1); if(lh != w->h) texscale.y *= float(w->h - 1) / (lh - 1); - loopk(numverts) - { + loopk(numverts) { litverts[k].u = ushort(floor(clamp(c[k].x*texscale.x, 0.0f, float(USHRT_MAX)))); litverts[k].v = ushort(floor(clamp(c[k].y*texscale.y, 0.0f, float(USHRT_MAX)))); } return surftype; } -static void removelmalpha(lightmapworker *w) -{ +static void removelmalpha(lightmapworker *w) { if(!(w->type&LM_ALPHA)) return; for(uchar *dst = w->colorbuf, *src = w->colorbuf, *end = &src[w->w*w->h*4]; src < end; - dst += 3, src += 4) - { + dst += 3, src += 4) { dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; @@ -1233,60 +1056,48 @@ static void removelmalpha(lightmapworker *w) w->lastlightmap->bpp = w->bpp; } -static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) -{ +static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) { cube &c = *task.c; const ivec &co = task.o; int size = task.size, usefacemask = task.usefaces; - w->curlightmaps = NULL; w->c = &c; - surfaceinfo surfaces[6]; vertinfo litverts[6*2*MAXFACEVERTS]; int numlitverts = 0; memclear(surfaces); - loopi(6) - { + loopi(6) { int usefaces = usefacemask&0xF; usefacemask >>= 4; - if(!usefaces) - { + if(!usefaces) { if(!c.ext) continue; surfaceinfo &surf = surfaces[i]; surf = c.ext->surfaces[i]; int numverts = surf.totalverts(); - if(numverts) - { + if(numverts) { memcpy(&litverts[numlitverts], c.ext->verts() + surf.verts, numverts*sizeof(vertinfo)); surf.verts = numlitverts; numlitverts += numverts; } continue; } - VSlot &vslot = lookupvslot(c.texture[i], false), *layer = vslot.layer && !(c.material&MAT_ALPHA) ? &lookupvslot(vslot.layer, false) : NULL; Shader *shader = vslot.slot->shader; int shadertype = shader->type; if(layer) shadertype |= layer->slot->shader->type; - surfaceinfo &surf = surfaces[i]; vertinfo *curlitverts = &litverts[numlitverts]; int numverts = c.ext ? c.ext->surfaces[i].numverts&MAXFACEVERTS : 0; ivec mo(co); int msz = size, convex = 0; - if(numverts) - { + if(numverts) { vertinfo *verts = c.ext->verts() + c.ext->surfaces[i].verts; loopj(numverts) curlitverts[j].set(verts[j].getxyz()); - if(c.merged&(1<<i)) - { + if(c.merged&(1<<i)) { msz = 1<<calcmergedsize(i, mo, size, verts, numverts); mo.mask(~(msz-1)); - - if(!(surf.numverts&MAXFACEVERTS)) - { + if(!(surf.numverts&MAXFACEVERTS)) { surf.verts = numlitverts; surf.numverts |= numverts; numlitverts += numverts; @@ -1294,8 +1105,7 @@ static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) } else if(!flataxisface(c, i)) convex = faceconvexity(verts, numverts, size); } - else - { + else { ivec v[4]; genfaceverts(c, i, v); if(!flataxisface(c, i)) convex = faceconvexity(v); @@ -1306,16 +1116,13 @@ static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) curlitverts[numverts++].set(v[order+2].mul(size).add(vo)); if(usefaces&2) curlitverts[numverts++].set(v[(order+3)&3].mul(size).add(vo)); } - vec pos[MAXFACEVERTS], n[MAXFACEVERTS], po(ivec(co).mask(~0xFFF)); loopj(numverts) pos[j] = vec(curlitverts[j].getxyz()).mul(1.0f/8).add(po); - plane planes[2]; int numplanes = 0; planes[numplanes++].toplane(pos[0], pos[1], pos[2]); if(numverts < 4 || !convex) loopk(numverts) findnormal(pos[k], planes[0], n[k]); - else - { + else { planes[numplanes++].toplane(pos[0], pos[2], pos[3]); vec avg = vec(planes[0]).add(planes[1]).normalize(); findnormal(pos[0], avg, n[0]); @@ -1323,24 +1130,18 @@ static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) findnormal(pos[2], avg, n[2]); for(int k = 3; k < numverts; k++) findnormal(pos[k], planes[1], n[k]); } - - if(shadertype&SHADER_NORMALSLMS) - { + if(shadertype&SHADER_NORMALSLMS) { loopk(numverts) curlitverts[k].norm = encodenormal(n[k]); - if(!(surf.numverts&MAXFACEVERTS)) - { + if(!(surf.numverts&MAXFACEVERTS)) { surf.verts = numlitverts; surf.numverts |= numverts; numlitverts += numverts; } } - - if(!findlights(w, mo.x, mo.y, mo.z, msz, pos, n, numverts, *vslot.slot, vslot)) - { + if(!findlights(w, mo.x, mo.y, mo.z, msz, pos, n, numverts, *vslot.slot, vslot)) { if(surf.numverts&MAXFACEVERTS) surf.numverts |= LAYER_TOP; continue; } - w->slot = vslot.slot; w->vslot = &vslot; w->type = shader->type&SHADER_NORMALSLMS ? LM_BUMPMAP0 : LM_DIFFUSE; @@ -1349,30 +1150,24 @@ static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) w->orient = i; w->rotate = vslot.rotation; int surftype = setupsurface(w, planes, numplanes, pos, n, numverts, curlitverts); - switch(surftype) - { + switch(surftype) { case SURFACE_LIGHTMAP_BOTTOM: if((shader->type^layer->slot->shader->type)&SHADER_NORMALSLMS || - (shader->type&SHADER_NORMALSLMS && vslot.rotation!=layer->rotation)) - { + (shader->type&SHADER_NORMALSLMS && vslot.rotation!=layer->rotation)) { freelightmap(w); break; } // fall through case SURFACE_LIGHTMAP_BLEND: - case SURFACE_LIGHTMAP_TOP: - { - if(!(surf.numverts&MAXFACEVERTS)) - { + case SURFACE_LIGHTMAP_TOP: { + if(!(surf.numverts&MAXFACEVERTS)) { surf.verts = numlitverts; surf.numverts |= numverts; numlitverts += numverts; } - w->lastlightmap->surface = i; w->lastlightmap->layers = (surftype==SURFACE_LIGHTMAP_BOTTOM ? LAYER_BOTTOM : LAYER_TOP); - if(surftype==SURFACE_LIGHTMAP_BLEND) - { + if(surftype==SURFACE_LIGHTMAP_BLEND) { surf.numverts |= LAYER_BLEND; w->lastlightmap->layers = LAYER_TOP; if((shader->type^layer->slot->shader->type)&SHADER_NORMALSLMS || @@ -1380,15 +1175,12 @@ static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) break; w->lastlightmap->layers |= LAYER_BOTTOM; } - else - { - if(surftype==SURFACE_LIGHTMAP_BOTTOM) - { + else { + if(surftype==SURFACE_LIGHTMAP_BOTTOM) { surf.numverts |= LAYER_BOTTOM; w->lastlightmap->layers = LAYER_BOTTOM; } - else - { + else { surf.numverts |= LAYER_TOP; w->lastlightmap->layers = LAYER_TOP; } @@ -1396,44 +1188,35 @@ static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) } continue; } - case SURFACE_AMBIENT_BOTTOM: freelightmap(w); surf.numverts |= layer ? LAYER_BOTTOM : LAYER_TOP; continue; - case SURFACE_AMBIENT_TOP: freelightmap(w); surf.numverts |= LAYER_TOP; continue; - default: freelightmap(w); continue; } - w->slot = layer->slot; w->vslot = layer; w->type = layer->slot->shader->type&SHADER_NORMALSLMS ? LM_BUMPMAP0 : LM_DIFFUSE; w->bpp = 3; w->rotate = layer->rotation; vertinfo *blendverts = surf.numverts&MAXFACEVERTS ? &curlitverts[numverts] : curlitverts; - switch(setupsurface(w, planes, numplanes, pos, n, numverts, blendverts)) - { - case SURFACE_LIGHTMAP_TOP: - { - if(!(surf.numverts&MAXFACEVERTS)) - { + switch(setupsurface(w, planes, numplanes, pos, n, numverts, blendverts)) { + case SURFACE_LIGHTMAP_TOP: { + if(!(surf.numverts&MAXFACEVERTS)) { surf.verts = numlitverts; surf.numverts |= numverts; numlitverts += numverts; } - else if(!(surf.numverts&LAYER_DUP)) - { + else if(!(surf.numverts&LAYER_DUP)) { surf.numverts |= LAYER_DUP; w->lastlightmap->layers |= LAYER_DUP; - loopk(numverts) - { + loopk(numverts) { vertinfo &src = curlitverts[k]; vertinfo &dst = blendverts[k]; dst.setxyz(src.getxyz()); @@ -1443,26 +1226,20 @@ static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) } surf.numverts |= LAYER_BOTTOM; w->lastlightmap->layers |= LAYER_BOTTOM; - w->lastlightmap->surface = i; break; } - - case SURFACE_AMBIENT_TOP: - { + case SURFACE_AMBIENT_TOP: { freelightmap(w); surf.numverts |= LAYER_BOTTOM; break; } - default: freelightmap(w); break; } } - loopk(6) - { + loopk(6) { surfaceinfo &surf = surfaces[k]; - if(surf.used()) - { + if(surf.used()) { cubeext *ext = c.ext && c.ext->maxverts >= numlitverts ? c.ext : growcubeext(c.ext, numlitverts); memcpy(ext->surfaces, surfaces, sizeof(ext->surfaces)); memcpy(ext->verts(), litverts, numlitverts*sizeof(vertinfo)); @@ -1473,14 +1250,11 @@ static lightmapinfo *setupsurfaces(lightmapworker *w, lightmaptask &task) return w->curlightmaps ? w->curlightmaps : (lightmapinfo *)-1; } -int lightmapworker::work(void *data) -{ +int lightmapworker::work(void *data) { lightmapworker *w = (lightmapworker *)data; SDL_LockMutex(tasklock); - while(!w->doneworking) - { - if(allocidx < lightmaptasks[0].length()) - { + while(!w->doneworking) { + if(allocidx < lightmaptasks[0].length()) { lightmaptask &t = lightmaptasks[0][allocidx++]; t.worker = w; SDL_UnlockMutex(tasklock); @@ -1489,8 +1263,7 @@ int lightmapworker::work(void *data) t.lightmaps = l; packlightmaps(w); } - else - { + else { if(packidx >= lightmaptasks[0].length()) SDL_CondSignal(emptycond); SDL_CondWait(fullcond, tasklock); } @@ -1499,28 +1272,22 @@ int lightmapworker::work(void *data) return 0; } -static bool processtasks(bool finish = false) -{ +static bool processtasks(bool finish = false) { if(tasklock) SDL_LockMutex(tasklock); - while(finish || lightmaptasks[1].length()) - { - if(packidx >= lightmaptasks[0].length()) - { + while(finish || lightmaptasks[1].length()) { + if(packidx >= lightmaptasks[0].length()) { if(lightmaptasks[1].empty()) break; lightmaptasks[0].setsize(0); lightmaptasks[0].move(lightmaptasks[1]); packidx = allocidx = 0; if(fullcond) SDL_CondBroadcast(fullcond); } - else if(lightmapping > 1) - { + else if(lightmapping > 1) { SDL_CondWaitTimeout(emptycond, tasklock, 250); CHECK_PROGRESS_LOCKED({ SDL_UnlockMutex(tasklock); return false; }, SDL_UnlockMutex(tasklock), SDL_LockMutex(tasklock)); } - else - { - while(allocidx < lightmaptasks[0].length()) - { + else { + while(allocidx < lightmaptasks[0].length()) { lightmaptask &t = lightmaptasks[0][allocidx++]; t.worker = lightmapworkers[0]; t.lightmaps = setupsurfaces(lightmapworkers[0], t); @@ -1533,35 +1300,26 @@ static bool processtasks(bool finish = false) return true; } -static void generatelightmaps(cube *c, const ivec &co, int size) -{ +static void generatelightmaps(cube *c, const ivec &co, int size) { CHECK_PROGRESS(return); - taskprogress++; - - loopi(8) - { + loopi(8) { ivec o(i, co, size); if(c[i].children) generatelightmaps(c[i].children, o, size >> 1); - else if(!isempty(c[i])) - { - if(c[i].ext) - { - loopj(6) - { + else if(!isempty(c[i])) { + if(c[i].ext) { + loopj(6) { surfaceinfo &surf = c[i].ext->surfaces[j]; if(surf.lmid[0] >= LMID_RESERVED || surf.lmid[1] >= LMID_RESERVED) goto nextcube; surf.clear(); } } int usefacemask = 0; - loopj(6) if(!(c[i].merged&(1<<j)) || (c[i].ext && c[i].ext->surfaces[j].numverts&MAXFACEVERTS)) - { + loopj(6) if(!(c[i].merged&(1<<j)) || (c[i].ext && c[i].ext->surfaces[j].numverts&MAXFACEVERTS)) { usefacemask |= visibletris(c[i], j, o, size)<<(4*j); } - if(usefacemask) - { + if(usefacemask) { lightmaptask &t = lightmaptasks[1].add(); t.o = o; t.size = size; @@ -1577,10 +1335,8 @@ static void generatelightmaps(cube *c, const ivec &co, int size) } } -void cleanuplightmaps() -{ - loopv(lightmaps) - { +void cleanuplightmaps() { + loopv(lightmaps) { LightMap &lm = lightmaps[i]; lm.tex = lm.offsetx = lm.offsety = -1; } @@ -1589,8 +1345,7 @@ void cleanuplightmaps() if(progresstex) { glDeleteTextures(1, &progresstex); progresstex = 0; } } -void resetlightmaps(bool fullclean) -{ +void resetlightmaps(bool fullclean) { cleanuplightmaps(); lightmaps.shrink(0); compressed.clear(); @@ -1598,8 +1353,7 @@ void resetlightmaps(bool fullclean) if(fullclean) while(lightmapworkers.length()) delete lightmapworkers.pop(); } -lightmapworker::lightmapworker() -{ +lightmapworker::lightmapworker() { buf = new uchar[LIGHTMAPBUFSIZE]; bufstart = bufused = 0; firstlightmap = lastlightmap = curlightmaps = NULL; @@ -1613,8 +1367,7 @@ lightmapworker::lightmapworker() thread = NULL; } -lightmapworker::~lightmapworker() -{ +lightmapworker::~lightmapworker() { cleanupthread(); delete[] buf; delete[] ambient; @@ -1624,38 +1377,32 @@ lightmapworker::~lightmapworker() freeshadowraycache(shadowraycache); } -void lightmapworker::cleanupthread() -{ +void lightmapworker::cleanupthread() { if(spacecond) { SDL_DestroyCond(spacecond); spacecond = NULL; } thread = NULL; } -void lightmapworker::reset() -{ +void lightmapworker::reset() { bufstart = bufused = 0; firstlightmap = lastlightmap = curlightmaps = NULL; needspace = doneworking = false; resetshadowraycache(shadowraycache); } -bool lightmapworker::setupthread() -{ +bool lightmapworker::setupthread() { if(!spacecond) spacecond = SDL_CreateCond(); if(!spacecond) return false; thread = SDL_CreateThread(work, "lightmap worker", this); return thread!=NULL; } -static Uint32 calclighttimer(Uint32 interval, void *param) -{ +static Uint32 calclighttimer(Uint32 interval, void *param) { check_calclight_progress = true; return interval; } -bool setlightmapquality(int quality) -{ - switch(quality) - { +bool setlightmapquality(int quality) { + switch(quality) { case 1: lmshadows = 2; lmaa = 3; lerptjoints = 1; break; case 0: lmshadows = lmshadows_; lmaa = lmaa_; lerptjoints = lerptjoints_; break; case -1: lmshadows = 1; lmaa = 0; lerptjoints = 0; break; @@ -1669,30 +1416,26 @@ VARP(lightthreads, 0, 0, 16); #define ALLOCLOCK(name, init) { if(lightmapping > 1) name = init(); if(!name) lightmapping = 1; } #define FREELOCK(name, destroy) { if(name) { destroy(name); name = NULL; } } -static void cleanuplocks() -{ +static void cleanuplocks() { FREELOCK(lightlock, SDL_DestroyMutex); FREELOCK(tasklock, SDL_DestroyMutex); FREELOCK(fullcond, SDL_DestroyCond); FREELOCK(emptycond, SDL_DestroyCond); } -static void setupthreads(int numthreads) -{ +static void setupthreads(int numthreads) { loopi(2) lightmaptasks[i].setsize(0); lightmapexts.setsize(0); packidx = allocidx = 0; lightmapping = numthreads; - if(lightmapping > 1) - { + if(lightmapping > 1) { ALLOCLOCK(lightlock, SDL_CreateMutex); ALLOCLOCK(tasklock, SDL_CreateMutex); ALLOCLOCK(fullcond, SDL_CreateCond); ALLOCLOCK(emptycond, SDL_CreateCond); } while(lightmapworkers.length() < lightmapping) lightmapworkers.add(new lightmapworker); - loopi(lightmapping) - { + loopi(lightmapping) { lightmapworker *w = lightmapworkers[i]; w->reset(); if(lightmapping <= 1 || w->setupthread()) continue; @@ -1703,28 +1446,23 @@ static void setupthreads(int numthreads) if(lightmapping <= 1) cleanuplocks(); } -static void cleanupthreads() -{ +static void cleanupthreads() { processtasks(true); - if(lightmapping > 1) - { + if(lightmapping > 1) { SDL_LockMutex(tasklock); loopv(lightmapworkers) lightmapworkers[i]->doneworking = true; SDL_CondBroadcast(fullcond); - loopv(lightmapworkers) - { + loopv(lightmapworkers) { lightmapworker *w = lightmapworkers[i]; if(w->needspace && w->spacecond) SDL_CondSignal(w->spacecond); } SDL_UnlockMutex(tasklock); - loopv(lightmapworkers) - { + loopv(lightmapworkers) { lightmapworker *w = lightmapworkers[i]; if(w->thread) SDL_WaitThread(w->thread, NULL); } } - loopv(lightmapexts) - { + loopv(lightmapexts) { lightmapext &e = lightmapexts[i]; setcubeext(*e.c, e.ext); } @@ -1733,10 +1471,8 @@ static void cleanupthreads() lightmapping = 0; } -void calclight(int *quality) -{ - if(!setlightmapquality(*quality)) - { +void calclight(int *quality) { + if(!setlightmapquality(*quality)) { conoutf(CON_ERROR, "valid range for calclight quality is -1..1"); return; } @@ -1763,8 +1499,7 @@ void calclight(int *quality) Uint32 end = SDL_GetTicks(); if(timer) SDL_RemoveTimer(timer); uint total = 0, lumels = 0; - loopv(lightmaps) - { + loopv(lightmaps) { insertunlit(i); if(!editmode) lightmaps[i].finalize(); total += lightmaps[i].lightmaps; @@ -1786,8 +1521,7 @@ void calclight(int *quality) COMMAND(calclight, "i"); -void clearlightmaps() -{ +void clearlightmaps() { if(noedit(true)) return; renderprogress(0, "clearing lightmaps..."); resetlightmaps(false); @@ -1798,10 +1532,8 @@ void clearlightmaps() COMMAND(clearlightmaps, ""); -void setfullbrightlevel(int fullbrightlevel) -{ - if(lightmaptexs.length() > LMID_BRIGHT) - { +void setfullbrightlevel(int fullbrightlevel) { + if(lightmaptexs.length() > LMID_BRIGHT) { uchar bright[3] = { uchar(fullbrightlevel), uchar(fullbrightlevel), uchar(fullbrightlevel) }; createtexture(lightmaptexs[LMID_BRIGHT].id, 1, 1, bright, 0, 1); } @@ -1813,21 +1545,17 @@ VARF(fullbrightlevel, 0, 128, 255, setfullbrightlevel(fullbrightlevel)); vector<LightMapTexture> lightmaptexs; -static void copylightmap(LightMap &lm, uchar *dst, size_t stride) -{ +static void copylightmap(LightMap &lm, uchar *dst, size_t stride) { const uchar *c = lm.data; - loopi(LM_PACKH) - { + loopi(LM_PACKH) { memcpy(dst, c, lm.bpp*LM_PACKW); c += lm.bpp*LM_PACKW; dst += stride; } } -void genreservedlightmaptexs() -{ - while(lightmaptexs.length() < LMID_RESERVED) - { +void genreservedlightmaptexs() { + while(lightmaptexs.length() < LMID_RESERVED) { LightMapTexture &tex = lightmaptexs.add(); tex.type = lightmaptexs.length()&1 ? LM_DIFFUSE : LM_BUMPMAP1; glGenTextures(1, &tex.id); @@ -1844,30 +1572,24 @@ void genreservedlightmaptexs() createtexture(lightmaptexs[LMID_DARK1].id, 1, 1, &front, 0, 1); } -static void findunlit(int i) -{ +static void findunlit(int i) { LightMap &lm = lightmaps[i]; if(lm.unlitx>=0) return; - else if((lm.type&LM_TYPE)==LM_BUMPMAP0) - { + else if((lm.type&LM_TYPE)==LM_BUMPMAP0) { if(i+1>=lightmaps.length() || (lightmaps[i+1].type&LM_TYPE)!=LM_BUMPMAP1) return; } else if((lm.type&LM_TYPE)!=LM_DIFFUSE) return; uchar *data = lm.data; - loop(y, 2) loop(x, LM_PACKW) - { - if(!data[0] && !data[1] && !data[2]) - { + loop(y, 2) loop(x, LM_PACKW) { + if(!data[0] && !data[1] && !data[2]) { memcpy(data, ambientcolor.v, 3); if((lm.type&LM_TYPE)==LM_BUMPMAP0) ((bvec *)lightmaps[i+1].data)[y*LM_PACKW + x] = bvec(128, 128, 255); lm.unlitx = x; lm.unlity = y; return; } - if(data[0]==ambientcolor[0] && data[1]==ambientcolor[1] && data[2]==ambientcolor[2]) - { - if((lm.type&LM_TYPE)!=LM_BUMPMAP0 || ((bvec *)lightmaps[i+1].data)[y*LM_PACKW + x] == bvec(128, 128, 255)) - { + if(data[0]==ambientcolor[0] && data[1]==ambientcolor[1] && data[2]==ambientcolor[2]) { + if((lm.type&LM_TYPE)!=LM_BUMPMAP0 || ((bvec *)lightmaps[i+1].data)[y*LM_PACKW + x] == bvec(128, 128, 255)) { lm.unlitx = x; lm.unlity = y; return; @@ -1880,13 +1602,10 @@ static void findunlit(int i) VARF(roundlightmaptex, 0, 4, 16, { cleanuplightmaps(); initlights(); allchanged(); }); VARF(batchlightmaps, 0, 4, 256, { cleanuplightmaps(); initlights(); allchanged(); }); -void genlightmaptexs(int flagmask, int flagval) -{ +void genlightmaptexs(int flagmask, int flagval) { if(lightmaptexs.length() < LMID_RESERVED) genreservedlightmaptexs(); - int remaining[LM_TYPE+1] = { 0 }, total = 0; - loopv(lightmaps) - { + loopv(lightmaps) { LightMap &lm = lightmaps[i]; if(lm.tex >= 0 || (lm.type&flagmask)!=flagval) continue; int type = lm.type&LM_TYPE; @@ -1894,15 +1613,12 @@ void genlightmaptexs(int flagmask, int flagval) total++; if(lm.unlitx < 0) findunlit(i); } - int sizelimit = (maxtexsize ? min(maxtexsize, hwtexsize) : hwtexsize)/max(LM_PACKW, LM_PACKH); sizelimit = min(batchlightmaps, sizelimit*sizelimit); - while(total) - { + while(total) { int type = LM_DIFFUSE; LightMap *firstlm = NULL; - loopv(lightmaps) - { + loopv(lightmaps) { LightMap &lm = lightmaps[i]; if(lm.tex >= 0 || (lm.type&flagmask) != flagval) continue; type = lm.type&LM_TYPE; @@ -1915,8 +1631,7 @@ void genlightmaptexs(int flagmask, int flagval) used--; int oldval = remaining[type]; remaining[type] -= 1<<used; - if(remaining[type] && (2<<used) <= min(roundlightmaptex, sizelimit)) - { + if(remaining[type] && (2<<used) <= min(roundlightmaptex, sizelimit)) { remaining[type] -= min(remaining[type], 1<<used); used++; } @@ -1928,27 +1643,21 @@ void genlightmaptexs(int flagmask, int flagval) int bpp = firstlm->bpp; uchar *data = used ? new uchar[bpp*tex.w*tex.h] : NULL; int offsetx = 0, offsety = 0; - loopv(lightmaps) - { + loopv(lightmaps) { LightMap &lm = lightmaps[i]; if(lm.tex >= 0 || (lm.type&flagmask) != flagval || (lm.type&LM_TYPE) != type) continue; - lm.tex = lightmaptexs.length()-1; lm.offsetx = offsetx; lm.offsety = offsety; - if(tex.unlitx < 0 && lm.unlitx >= 0) - { + if(tex.unlitx < 0 && lm.unlitx >= 0) { tex.unlitx = offsetx + lm.unlitx; tex.unlity = offsety + lm.unlity; } - if(data) copylightmap(lm, &data[bpp*(offsety*tex.w + offsetx)], bpp*tex.w); - offsetx += LM_PACKW; if(offsetx >= tex.w) { offsetx = 0; offsety += LM_PACKH; } if(offsety >= tex.h) break; } - glGenTextures(1, &tex.id); createtexture(tex.id, tex.w, tex.h, data ? data : firstlm->data, 3, 1, bpp==4 ? GL_RGBA : GL_RGB); if(data) delete[] data; @@ -1957,29 +1666,24 @@ void genlightmaptexs(int flagmask, int flagval) bool brightengeom = false, shouldlightents = false; -void clearlights() -{ +void clearlights() { clearlightcache(); const vector<extentity *> &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; e.light.color = vec(1, 1, 1); e.light.dir = vec(0, 0, 1); } shouldlightents = false; - genlightmaptexs(LM_ALPHA, 0); genlightmaptexs(LM_ALPHA, LM_ALPHA); brightengeom = true; } -void lightent(extentity &e, float height) -{ +void lightent(extentity &e, float height) { if(e.type==ET_LIGHT) return; float ambient = 0.0f; - if(e.type==ET_MAPMODEL) - { + if(e.type==ET_MAPMODEL) { model *m = loadmodel(NULL, e.attr2); if(m) height = m->above()*0.75f; } @@ -1988,24 +1692,18 @@ void lightent(extentity &e, float height) lightreaching(target, e.light.color, e.light.dir, false, &e, ambient); } -void lightents(bool force) -{ +void lightents(bool force) { if(!force && !shouldlightents) return; - const vector<extentity *> &ents = entities::getents(); loopv(ents) lightent(*ents[i]); - shouldlightents = false; } -void initlights() -{ - if((fullbright && editmode) || lightmaps.empty()) - { +void initlights() { + if((fullbright && editmode) || lightmaps.empty()) { clearlights(); return; } - clearlightcache(); genlightmaptexs(LM_ALPHA, 0); genlightmaptexs(LM_ALPHA, LM_ALPHA); @@ -2013,49 +1711,39 @@ void initlights() shouldlightents = true; } -void lightreaching(const vec &target, vec &color, vec &dir, bool fast, extentity *t, float ambient) -{ - if((fullbright && editmode) || lightmaps.empty()) - { +void lightreaching(const vec &target, vec &color, vec &dir, bool fast, extentity *t, float ambient) { + if((fullbright && editmode) || lightmaps.empty()) { color = vec(1, 1, 1); dir = vec(0, 0, 1); return; } - color = dir = vec(0, 0, 0); const vector<extentity *> &ents = entities::getents(); const vector<int> &lights = checklightcache(int(target.x), int(target.y)); - loopv(lights) - { + loopv(lights) { extentity &e = *ents[lights[i]]; if(e.type != ET_LIGHT) continue; - vec ray(target); ray.sub(e.o); float mag = ray.magnitude(); if(e.attr1 && mag >= float(e.attr1)) continue; - if(mag < 1e-4f) ray = vec(0, 0, -1); - else - { + else { ray.div(mag); if(shadowray(e.o, ray, mag, RAY_SHADOW | RAY_POLY, t) < mag) continue; } - float intensity = 1; if(e.attr1) intensity -= mag / float(e.attr1); - if(e.attached && e.attached->type==ET_SPOTLIGHT) - { + if(e.attached && e.attached->type==ET_SPOTLIGHT) { vec spot = vec(e.attached->o).sub(e.o).normalize(); float maxatten = sincos360[clamp(int(e.attached->attr1), 1, 89)].x, spotatten = (ray.dot(spot) - maxatten) / (1 - maxatten); if(spotatten <= 0) continue; intensity *= spotatten; } - vec lightcol = vec(e.attr2, e.attr3, e.attr4).mul(1.0f/255); color.add(vec(lightcol).mul(intensity)); dir.add(vec(ray).mul(-intensity*lightcol.x*lightcol.y*lightcol.z)); @@ -2065,40 +1753,33 @@ void lightreaching(const vec &target, vec &color, vec &dir, bool fast, extentity else dir.normalize(); } -entity *brightestlight(const vec &target, const vec &dir) -{ +entity *brightestlight(const vec &target, const vec &dir) { const vector<extentity *> &ents = entities::getents(); const vector<int> &lights = checklightcache(int(target.x), int(target.y)); extentity *brightest = NULL; float bintensity = 0; - loopv(lights) - { + loopv(lights) { extentity &e = *ents[lights[i]]; if(e.type != ET_LIGHT || vec(e.o).sub(target).dot(dir)<0) continue; - vec ray(target); ray.sub(e.o); float mag = ray.magnitude(); if(e.attr1 && mag >= float(e.attr1)) continue; - ray.div(mag); if(shadowray(e.o, ray, mag, RAY_SHADOW | RAY_POLY) < mag) continue; float intensity = 1; if(e.attr1) intensity -= mag / float(e.attr1); - if(e.attached && e.attached->type==ET_SPOTLIGHT) - { + if(e.attached && e.attached->type==ET_SPOTLIGHT) { vec spot = vec(e.attached->o).sub(e.o).normalize(); float maxatten = sincos360[clamp(int(e.attached->attr1), 1, 89)].x, spotatten = (ray.dot(spot) - maxatten) / (1 - maxatten); if(spotatten <= 0) continue; intensity *= spotatten; } - - if(!brightest || intensity > bintensity) - { + if(!brightest || intensity > bintensity) { brightest = &e; bintensity = intensity; } @@ -2106,10 +1787,8 @@ entity *brightestlight(const vec &target, const vec &dir) return brightest; } -void dumplms() -{ - loopv(lightmaps) - { +void dumplms() { + loopv(lightmaps) { ImageData temp(LM_PACKW, LM_PACKH, lightmaps[i].bpp, lightmaps[i].data); const char *map = game::getclientmap(), *name = strrchr(map, '/'); defformatstring(buf, "lightmap_%s_%d.png", name ? name+1 : map, i); diff --git a/src/engine/lightmap.h b/src/engine/lightmap.h index 0f00d61..d15c6a7 100644 --- a/src/engine/lightmap.h +++ b/src/engine/lightmap.h @@ -5,81 +5,62 @@ #define LM_PACKW 512 #define LM_PACKH 512 -struct PackNode -{ +struct PackNode { PackNode *child1, *child2; ushort x, y, w, h; int available; - PackNode() : child1(0), child2(0), x(0), y(0), w(LM_PACKW), h(LM_PACKH), available(min(LM_PACKW, LM_PACKH)) {} PackNode(ushort x, ushort y, ushort w, ushort h) : child1(0), child2(0), x(x), y(y), w(w), h(h), available(min(w, h)) {} - - void clear() - { + void clear() { DELETEP(child1); DELETEP(child2); } - - ~PackNode() - { + ~PackNode() { clear(); } - bool insert(ushort &tx, ushort &ty, ushort tw, ushort th); }; -enum -{ +enum { LM_DIFFUSE = 0, LM_BUMPMAP0, LM_BUMPMAP1, LM_TYPE = 0x0F, - LM_ALPHA = 1<<4, LM_FLAGS = 0xF0 }; -struct LightMap -{ +struct LightMap { int type, bpp, tex, offsetx, offsety; PackNode packroot; uint lightmaps, lumels; int unlitx, unlity; uchar *data; - LightMap() : type(LM_DIFFUSE), bpp(3), tex(-1), offsetx(-1), offsety(-1), lightmaps(0), lumels(0), unlitx(-1), unlity(-1), - data(NULL) - { + data(NULL) { } - - ~LightMap() - { + ~LightMap() { if(data) delete[] data; } - - void finalize() - { + void finalize() { packroot.clear(); packroot.available = 0; } - void copy(ushort tx, ushort ty, uchar *src, ushort tw, ushort th); bool insert(ushort &tx, ushort &ty, uchar *src, ushort tw, ushort th); }; extern vector<LightMap> lightmaps; -struct LightMapTexture -{ +struct LightMapTexture { int w, h, type; GLuint id; int unlitx, unlity; - LightMapTexture() - : w(0), h(0), type(LM_DIFFUSE), id(0), unlitx(-1), unlity(-1) - {} + : w(0), h(0), type(LM_DIFFUSE), id(0), unlitx(-1), unlity(-1) { + } }; extern vector<LightMapTexture> lightmaptexs; @@ -95,17 +76,14 @@ extern void brightencube(cube &c); extern void setsurfaces(cube &c, const surfaceinfo *surfs, const vertinfo *verts, int numverts); extern void setsurface(cube &c, int orient, const surfaceinfo &surf, const vertinfo *verts, int numverts); -struct lerpvert -{ +struct lerpvert { vec normal; vec2 tc; - bool operator==(const lerpvert &l) const { return tc == l.tc;; } bool operator!=(const lerpvert &l) const { return tc != l.tc; } }; -struct lerpbounds -{ +struct lerpbounds { const lerpvert *min; const lerpvert *max; float u, ustep; @@ -121,10 +99,10 @@ extern void initlerpbounds(float u, float v, const lerpvert *lv, int numv, lerpb extern void lerpnormal(float u, float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end, vec &normal, vec &nstep); #define CHECK_CALCLIGHT_PROGRESS_LOCKED(exit, show_calclight_progress, before, after) \ - if(check_calclight_progress) \ - { \ - if(!calclight_canceled) \ - { \ + if(check_calclight_progress) { \ + \ + if(!calclight_canceled) { \ + \ before; \ show_calclight_progress(); \ check_calclight_canceled(); \ diff --git a/src/engine/lightning.h b/src/engine/lightning.h deleted file mode 100644 index cec993a..0000000 --- a/src/engine/lightning.h +++ /dev/null @@ -1,123 +0,0 @@ -#define MAXLIGHTNINGSTEPS 64 -#define LIGHTNINGSTEP 8 -int lnjitterx[2][MAXLIGHTNINGSTEPS], lnjittery[2][MAXLIGHTNINGSTEPS]; -int lnjitterframe = 0, lastlnjitter = 0; - -VAR(lnjittermillis, 0, 100, 1000); -VAR(lnjitterradius, 0, 4, 100); -FVAR(lnjitterscale, 0, 0.5f, 10); -VAR(lnscrollmillis, 1, 300, 5000); -FVAR(lnscrollscale, 0, 0.125f, 10); -FVAR(lnblendpower, 0, 0.25f, 1000); - -static void calclightningjitter(int frame) -{ - loopi(MAXLIGHTNINGSTEPS) - { - lnjitterx[lnjitterframe][i] = -lnjitterradius + rnd(2*lnjitterradius + 1); - lnjittery[lnjitterframe][i] = -lnjitterradius + rnd(2*lnjitterradius + 1); - } -} - -static void setuplightning() -{ - if(!lastlnjitter || lastmillis-lastlnjitter > lnjittermillis) - { - if(!lastlnjitter) calclightningjitter(lnjitterframe); - lastlnjitter = lastmillis - (lastmillis%lnjittermillis); - calclightningjitter(lnjitterframe ^= 1); - } -} - -static void renderlightning(Texture *tex, const vec &o, const vec &d, float sz) -{ - vec step(d); - step.sub(o); - float len = step.magnitude(); - int numsteps = clamp(int(ceil(len/LIGHTNINGSTEP)), 2, MAXLIGHTNINGSTEPS); - step.div(numsteps+1); - int jitteroffset = detrnd(int(d.x+d.y+d.z), MAXLIGHTNINGSTEPS); - vec cur(o), up, right; - up.orthogonal(step); - up.normalize(); - right.cross(up, step); - right.normalize(); - float scroll = -float(lastmillis%lnscrollmillis)/lnscrollmillis, - scrollscale = lnscrollscale*(LIGHTNINGSTEP*tex->ys)/(sz*tex->xs), - blend = pow(clamp(float(lastmillis - lastlnjitter)/lnjittermillis, 0.0f, 1.0f), lnblendpower), - jitter0 = (1-blend)*lnjitterscale*sz/lnjitterradius, jitter1 = blend*lnjitterscale*sz/lnjitterradius; - gle::begin(GL_TRIANGLE_STRIP); - loopj(numsteps) - { - vec next(cur); - next.add(step); - if(j+1==numsteps) next = d; - else - { - int lj = (j+jitteroffset)%MAXLIGHTNINGSTEPS; - next.add(vec(right).mul((jitter1*lnjitterx[lnjitterframe][lj] + jitter0*lnjitterx[lnjitterframe^1][lj]))); - next.add(vec(up).mul((jitter1*lnjittery[lnjitterframe][lj] + jitter0*lnjittery[lnjitterframe^1][lj]))); - } - vec dir1 = next, dir2 = next, across; - dir1.sub(cur); - dir2.sub(camera1->o); - across.cross(dir2, dir1).normalize().mul(sz); - gle::attribf(cur.x-across.x, cur.y-across.y, cur.z-across.z); - gle::attribf(scroll, 1); - gle::attribf(cur.x+across.x, cur.y+across.y, cur.z+across.z); - gle::attribf(scroll, 0); - scroll += scrollscale; - if(j+1==numsteps) - { - gle::attribf(next.x-across.x, next.y-across.y, next.z-across.z); - gle::attribf(scroll, 1); - gle::attribf(next.x+across.x, next.y+across.y, next.z+across.z); - gle::attribf(scroll, 0); - } - cur = next; - } - gle::end(); -} - -struct lightningrenderer : listrenderer -{ - lightningrenderer() - : listrenderer("packages/particles/lightning.png", 2, PT_LIGHTNING|PT_TRACK|PT_GLARE) - {} - - void startrender() - { - glDisable(GL_CULL_FACE); - gle::defattrib(gle::ATTRIB_VERTEX, 3, GL_FLOAT); - gle::defattrib(gle::ATTRIB_TEXCOORD0, 2, GL_FLOAT); - } - - void endrender() - { - glEnable(GL_CULL_FACE); - } - - void update() - { - setuplightning(); - } - - void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity) - { - pe.maxfade = max(pe.maxfade, fade); - pe.extendbb(o, size); - pe.extendbb(d, size); - } - - void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) - { - blend = min(blend<<2, 255); - if(type&PT_MOD) //multiply alpha into color - gle::colorub((p->color.r*blend)>>8, (p->color.g*blend)>>8, (p->color.b*blend)>>8); - else - gle::color(p->color, blend); - renderlightning(tex, o, d, p->size); - } -}; -static lightningrenderer lightnings; - diff --git a/src/engine/main.cpp b/src/engine/main.cpp index 5d264ed..a059c13 100644 --- a/src/engine/main.cpp +++ b/src/engine/main.cpp @@ -10,8 +10,7 @@ float speedmodifier = 0.0f; extern void cleargamma(); -void cleanup() -{ +void cleanup() { cleanupserver(); SDL_ShowCursor(SDL_TRUE); SDL_SetRelativeMouseMode(SDL_FALSE); @@ -28,8 +27,7 @@ void cleanup() extern void writeinitcfg(); -void quit() // normal exit -{ +void quit() { // normal exit { writeinitcfg(); writeservercfg(); abortconnect(); @@ -40,20 +38,14 @@ void quit() // normal exit exit(EXIT_SUCCESS); } -void fatal(const char *s, ...) // failure exit -{ +void fatal(const char *s, ...) { // failure exit { static int errors = 0; errors++; - - if(errors <= 2) // print up to one extra recursive error - { + if(errors <= 2) { // print up to one extra recursive error { defvformatstring(msg,s,s); logoutf("%s", msg); - - if(errors <= 1) // avoid recursion - { - if(SDL_WasInit(SDL_INIT_VIDEO)) - { + if(errors <= 1) { // avoid recursion { + if(SDL_WasInit(SDL_INIT_VIDEO)) { SDL_ShowCursor(SDL_TRUE); SDL_SetRelativeMouseMode(SDL_FALSE); if(screen) SDL_SetWindowGrab(screen, SDL_FALSE); @@ -63,7 +55,6 @@ void fatal(const char *s, ...) // failure exit SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Cube 2: Sauerbraten fatal error", msg, NULL); } } - exit(EXIT_FAILURE); } @@ -73,10 +64,8 @@ dynent *player = NULL; int initing = NOT_INITING; -bool initwarning(const char *desc, int level, int type) -{ - if(initing < level) - { +bool initwarning(const char *desc, int level, int type) { + if(initing < level) { addchange(desc, type); return true; } @@ -100,8 +89,7 @@ VARF(scr_h, SCR_MINH, -1, SCR_MAXH, initwarning("screen resolution")); VARF(depthbits, 0, 0, 32, initwarning("depth-buffer precision")); VARF(fsaa, -1, -1, 16, initwarning("anti-aliasing")); -void writeinitcfg() -{ +void writeinitcfg() { stream *f = openutf8file("init.cfg", "w"); if(!f) return; f->printf("// automatically written on exit, DO NOT MODIFY\n// modify settings in game\n"); @@ -124,8 +112,7 @@ void writeinitcfg() COMMAND(quit, ""); -static void getbackgroundres(int &w, int &h) -{ +static void getbackgroundres(int &w, int &h) { float wk = 1, hk = 1; if(w < 1024) wk = 1024.0f/w; if(h < 768) hk = 768.0f/h; @@ -139,31 +126,26 @@ Texture *backgroundmapshot = NULL; string backgroundmapname = ""; char *backgroundmapinfo = NULL; -void setbackgroundinfo(const char *caption = NULL, Texture *mapshot = NULL, const char *mapname = NULL, const char *mapinfo = NULL) -{ +void setbackgroundinfo(const char *caption = NULL, Texture *mapshot = NULL, const char *mapname = NULL, const char *mapinfo = NULL) { renderedframe = false; copystring(backgroundcaption, caption ? caption : ""); backgroundmapshot = mapshot; copystring(backgroundmapname, mapname ? mapname : ""); - if(mapinfo != backgroundmapinfo) - { + if(mapinfo != backgroundmapinfo) { DELETEA(backgroundmapinfo); if(mapinfo) backgroundmapinfo = newstring(mapinfo); } } -void restorebackground(bool force = false) -{ - if(renderedframe) - { +void restorebackground(bool force = false) { + if(renderedframe) { if(!force) return; setbackgroundinfo(); } renderbackground(backgroundcaption[0] ? backgroundcaption : NULL, backgroundmapshot, backgroundmapname[0] ? backgroundmapname : NULL, backgroundmapinfo, true); } -void bgquad(float x, float y, float w, float h, float tx = 0, float ty = 0, float tw = 1, float th = 1) -{ +void bgquad(float x, float y, float w, float h, float tx = 0, float ty = 0, float tw = 1, float th = 1) { gle::begin(GL_TRIANGLE_STRIP); gle::attribf(x, y); gle::attribf(tx, ty); gle::attribf(x+w, y); gle::attribf(tx + tw, ty); @@ -172,48 +154,36 @@ void bgquad(float x, float y, float w, float h, float tx = 0, float ty = 0, floa gle::end(); } -void renderbackground(const char *caption, Texture *mapshot, const char *mapname, const char *mapinfo, bool restore, bool force) -{ +void renderbackground(const char *caption, Texture *mapshot, const char *mapname, const char *mapinfo, bool restore, bool force) { if(!inbetweenframes && !force) return; - if(!restore || force) stopsounds(); // stop sounds while loading - int w = screenw, h = screenh; if(forceaspect) w = int(ceil(h*forceaspect)); getbackgroundres(w, h); gettextres(w, h); - static int lastupdate = -1, lastw = -1, lasth = -1; static int numdecals = 0; static struct decal { float x, y, size; int side; } decals[12]; - if((renderedframe && !mainmenu && lastupdate != lastmillis) || lastw != w || lasth != h) - { + if((renderedframe && !mainmenu && lastupdate != lastmillis) || lastw != w || lasth != h) { lastupdate = lastmillis; lastw = w; lasth = h; - numdecals = sizeof(decals)/sizeof(decals[0]); numdecals = numdecals/3 + rnd((numdecals*2)/3 + 1); float maxsize = min(w, h)/16.0f; - loopi(numdecals) - { + loopi(numdecals) { decal d = { rndscale(w), rndscale(h), maxsize/2 + rndscale(maxsize/2), rnd(2) }; decals[i] = d; } } else if(lastupdate != lastmillis) lastupdate = lastmillis; - - loopi(restore ? 1 : 3) - { + loopi(restore ? 1 : 3) { hudmatrix.ortho(0, w, h, 0, -1, 1); resethudmatrix(); - hudshader->set(); gle::colorf(1, 1, 1); - gle::defvertex(2); gle::deftexcoord0(); - settexture("background/daemex.png", 0); bgquad(0, 0, screenw, screenh, 0, 0, 1, 1); glEnable(GL_BLEND); @@ -221,8 +191,7 @@ void renderbackground(const char *caption, Texture *mapshot, const char *mapname lx = 0.5f*(w - lw), ly = 0.5f*(h*0.5f - lh); settexture((maxtexsize ? min(maxtexsize, hwtexsize) : hwtexsize) >= 1024 && (screenw > 1280 || screenh > 800) ? "data/logo_1024.png" : "data/logo.png", 3); bgquad(lx, ly, lw, lh); - if(caption) - { + if(caption) { int tw = text_width(caption); float tsz = 0.04f*min(w, h)/FONTH, tx = 0.5f*(w - tw*tsz), ty = h - 0.075f*1.5f*min(w, h) - 1.25f*FONTH*tsz; @@ -233,23 +202,19 @@ void renderbackground(const char *caption, Texture *mapshot, const char *mapname draw_text(caption, 0, 0); pophudmatrix(); } - if(mapshot || mapname) - { + if(mapshot || mapname) { int infowidth = 12*FONTH; float sz = 0.35f*min(w, h), msz = (0.75f*min(w, h) - sz)/(infowidth + FONTH), x = 0.5f*(w-sz), y = ly+lh - sz/15; - if(mapinfo) - { + if(mapinfo) { int mw, mh; text_bounds(mapinfo, mw, mh, infowidth); x -= 0.5f*(mw*msz + FONTH*msz); } - if(mapshot && mapshot!=notexture) - { + if(mapshot && mapshot!=notexture) { glBindTexture(GL_TEXTURE_2D, mapshot->id); bgquad(x, y, sz, sz); } - else - { + else { int qw, qh; text_bounds("?", qw, qh); float qsz = sz*0.5f/max(qw, qh); @@ -263,8 +228,7 @@ void renderbackground(const char *caption, Texture *mapshot, const char *mapname } settexture("data/mapshot_frame.png", 3); bgquad(x, y, sz, sz); - if(mapname) - { + if(mapname) { int tw = text_width(mapname); float tsz = sz/(8*FONTH), tx = 0.9f*sz - tw*tsz, ty = 0.9f*sz - FONTH*tsz; @@ -276,8 +240,7 @@ void renderbackground(const char *caption, Texture *mapshot, const char *mapname draw_text(mapname, 0, 0); pophudmatrix(); } - if(mapinfo) - { + if(mapinfo) { pushhudmatrix(); hudmatrix.translate(x+sz+FONTH*msz, y, 0); hudmatrix.scale(msz, msz, 1); @@ -289,7 +252,6 @@ void renderbackground(const char *caption, Texture *mapshot, const char *mapname glDisable(GL_BLEND); if(!restore) swapbuffers(false); } - if(!restore) setbackgroundinfo(caption, mapshot, mapname, mapinfo); } @@ -297,42 +259,31 @@ VAR(progressbackground, 0, 0, 1); float loadprogress = 0; -void renderprogress(float bar, const char *text, GLuint tex, bool background) // also used during loading -{ +void renderprogress(float bar, const char *text, GLuint tex, bool background) { // also used during loading { if(!inbetweenframes || drawtex) return; - extern int menufps, maxfps; int fps = menufps ? (maxfps ? min(maxfps, menufps) : menufps) : maxfps; - if(fps) - { + if(fps) { static int lastprogress = 0; int ticks = SDL_GetTicks(), diff = ticks - lastprogress; if(bar > 0 && diff >= 0 && diff < (1000 + fps-1)/fps) return; lastprogress = ticks; } - clientkeepalive(); // make sure our connection doesn't time out while loading maps etc. - SDL_PumpEvents(); // keep the event queue awake to avoid 'beachball' cursor - extern int mesa_swap_bug, curvsync; bool forcebackground = progressbackground || (mesa_swap_bug && (curvsync || totalmillis==1)); if(background || forcebackground) restorebackground(forcebackground); - int w = screenw, h = screenh; if(forceaspect) w = int(ceil(h*forceaspect)); getbackgroundres(w, h); gettextres(w, h); - hudmatrix.ortho(0, w, h, 0, -1, 1); resethudmatrix(); - hudshader->set(); gle::colorf(1, 1, 1); - gle::defvertex(2); gle::deftexcoord0(); - float fh = 0.075f*min(w, h), fw = fh*10, fx = renderedframe ? w - fw - fh/4 : 0.5f*(w - fw), fy = renderedframe ? fh/4 : h - fh*1.5f, @@ -340,10 +291,8 @@ void renderprogress(float bar, const char *text, GLuint tex, bool background) fv1 = 0/64.0f, fv2 = 52/64.0f; settexture("data/loading_frame.png", 3); bgquad(fx, fy, fw, fh, fu1, fv1, fu2-fu1, fv2-fv1); - glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - float bw = fw*(511 - 2*17)/511.0f, bh = fh*20/52.0f, bx = fx + fw*17/511.0f, by = fy + fh*16/52.0f, bv1 = 0/32.0f, bv2 = 20/32.0f, @@ -351,29 +300,24 @@ void renderprogress(float bar, const char *text, GLuint tex, bool background) eu1 = 23/32.0f, eu2 = 30/32.0f, ew = fw*7/511.0f, mw = bw - sw - ew, ex = bx+sw + max(mw*bar, fw*7/511.0f); - if(bar > 0) - { + if(bar > 0) { settexture("data/loading_bar.png", 3); gle::begin(GL_QUADS); gle::attribf(bx, by); gle::attribf(su1, bv1); gle::attribf(bx+sw, by); gle::attribf(su2, bv1); gle::attribf(bx+sw, by+bh); gle::attribf(su2, bv2); gle::attribf(bx, by+bh); gle::attribf(su1, bv2); - gle::attribf(bx+sw, by); gle::attribf(su2, bv1); gle::attribf(ex, by); gle::attribf(eu1, bv1); gle::attribf(ex, by+bh); gle::attribf(eu1, bv2); gle::attribf(bx+sw, by+bh); gle::attribf(su2, bv2); - gle::attribf(ex, by); gle::attribf(eu1, bv1); gle::attribf(ex+ew, by); gle::attribf(eu2, bv1); gle::attribf(ex+ew, by+bh); gle::attribf(eu2, bv2); gle::attribf(ex, by+bh); gle::attribf(eu1, bv2); gle::end(); } - - if(text) - { + if(text) { int tw = text_width(text); float tsz = bh*0.8f/FONTH; if(tw*tsz > mw) tsz = mw/tw; @@ -384,22 +328,17 @@ void renderprogress(float bar, const char *text, GLuint tex, bool background) draw_text(text, 0, 0); pophudmatrix(); } - glDisable(GL_BLEND); - - if(tex) - { + if(tex) { glBindTexture(GL_TEXTURE_2D, tex); float sz = 0.35f*min(w, h), x = 0.5f*(w-sz), y = 0.5f*min(w, h) - sz/15; bgquad(x, y, sz, sz); - glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); settexture("data/mapshot_frame.png", 3); bgquad(x, y, sz, sz); glDisable(GL_BLEND); } - swapbuffers(false); } @@ -407,25 +346,20 @@ int keyrepeatmask = 0, textinputmask = 0; Uint32 textinputtime = 0; VAR(textinputfilter, 0, 5, 1000); -void keyrepeat(bool on, int mask) -{ +void keyrepeat(bool on, int mask) { if(on) keyrepeatmask |= mask; else keyrepeatmask &= ~mask; } -void textinput(bool on, int mask) -{ - if(on) - { - if(!textinputmask) - { +void textinput(bool on, int mask) { + if(on) { + if(!textinputmask) { SDL_StartTextInput(); textinputtime = SDL_GetTicks(); } textinputmask |= mask; } - else if(textinputmask) - { + else if(textinputmask) { textinputmask &= ~mask; if(!textinputmask) SDL_StopTextInput(); } @@ -439,34 +373,27 @@ bool shouldgrab = false, grabinput = false, minimized = false, canrelativemouse VAR(sdl_xgrab_bug, 0, 0, 1); #endif -void inputgrab(bool on, bool delay = false) -{ +void inputgrab(bool on, bool delay = false) { #ifdef SDL_VIDEO_DRIVER_X11 bool wasrelativemouse = relativemouse; #endif - if(on) - { + if(on) { SDL_ShowCursor(SDL_FALSE); - if(canrelativemouse && userelativemouse) - { - if(SDL_SetRelativeMouseMode(SDL_TRUE) >= 0) - { + if(canrelativemouse && userelativemouse) { + if(SDL_SetRelativeMouseMode(SDL_TRUE) >= 0) { SDL_SetWindowGrab(screen, SDL_TRUE); relativemouse = true; } - else - { + else { SDL_SetWindowGrab(screen, SDL_FALSE); canrelativemouse = false; relativemouse = false; } } } - else - { + else { SDL_ShowCursor(SDL_TRUE); - if(relativemouse) - { + if(relativemouse) { SDL_SetWindowGrab(screen, SDL_FALSE); SDL_SetRelativeMouseMode(SDL_FALSE); relativemouse = false; @@ -475,15 +402,12 @@ void inputgrab(bool on, bool delay = false) shouldgrab = delay; #ifdef SDL_VIDEO_DRIVER_X11 - if((relativemouse || wasrelativemouse) && sdl_xgrab_bug) - { + if((relativemouse || wasrelativemouse) && sdl_xgrab_bug) { // Workaround for buggy SDL X11 pointer grabbing union { SDL_SysWMinfo info; uchar buf[sizeof(SDL_SysWMinfo) + 128]; }; SDL_GetVersion(&info.version); - if(SDL_GetWindowWMInfo(screen, &info) && info.subsystem == SDL_SYSWM_X11) - { - if(relativemouse) - { + if(SDL_GetWindowWMInfo(screen, &info) && info.subsystem == SDL_SYSWM_X11) { + if(relativemouse) { uint mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask; XGrabPointer(info.info.x11.display, info.info.x11.window, True, mask, GrabModeAsync, GrabModeAsync, info.info.x11.window, None, CurrentTime); } @@ -495,17 +419,14 @@ void inputgrab(bool on, bool delay = false) bool initwindowpos = false; -void setfullscreen(bool enable) -{ +void setfullscreen(bool enable) { if(!screen) return; //initwarning(enable ? "fullscreen" : "windowed"); extern int fullscreendesktop; SDL_SetWindowFullscreen(screen, enable ? (fullscreendesktop ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN) : 0); - if(!enable) - { + if(!enable) { SDL_SetWindowSize(screen, scr_w, scr_h); - if(initwindowpos) - { + if(initwindowpos) { int winx = SDL_WINDOWPOS_CENTERED, winy = SDL_WINDOWPOS_CENTERED; SDL_SetWindowPosition(screen, winx, winy); initwindowpos = false; @@ -519,74 +440,62 @@ VARF(fullscreen, 0, 0, 1, setfullscreen(fullscreen!=0)); VARF(fullscreen, 0, 1, 1, setfullscreen(fullscreen!=0)); #endif -void resetfullscreen() -{ +void resetfullscreen() { setfullscreen(false); setfullscreen(true); } VARF(fullscreendesktop, 0, 0, 1, if(fullscreen) resetfullscreen()); -void screenres(int w, int h) -{ +void screenres(int w, int h) { scr_w = clamp(w, SCR_MINW, SCR_MAXW); scr_h = clamp(h, SCR_MINH, SCR_MAXH); - if(screen) - { - if(fullscreendesktop) - { + if(screen) { + if(fullscreendesktop) { scr_w = min(scr_w, desktopw); scr_h = min(scr_h, desktoph); } - if(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN) - { + if(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN) { if(fullscreendesktop) gl_resize(); else resetfullscreen(); initwindowpos = true; } - else - { + else { SDL_SetWindowSize(screen, scr_w, scr_h); SDL_SetWindowPosition(screen, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); initwindowpos = false; } } - else - { + else { initwarning("screen resolution"); } } ICOMMAND(screenres, "ii", (int *w, int *h), screenres(*w, *h)); -static void setgamma(int val) -{ +static void setgamma(int val) { if(screen && SDL_SetWindowBrightness(screen, val/100.0f) < 0) conoutf(CON_ERROR, "Could not set gamma: %s", SDL_GetError()); } static int curgamma = 100; -VARFNP(gamma, reqgamma, 30, 100, 300, -{ +VARFNP(gamma, reqgamma, 30, 100, 300, { if(initing || reqgamma == curgamma) return; curgamma = reqgamma; setgamma(curgamma); }); -void restoregamma() -{ +void restoregamma() { if(initing || reqgamma == 100) return; curgamma = reqgamma; setgamma(curgamma); } -void cleargamma() -{ +void cleargamma() { if(curgamma != 100 && screen) SDL_SetWindowBrightness(screen, 1.0f); } int curvsync = -1; -void restorevsync() -{ +void restorevsync() { if(initing || !glcontext) return; extern int vsync, vsynctear; if(!SDL_GL_SetSwapInterval(vsync ? (vsynctear ? -1 : 1) : 0)) @@ -596,40 +505,31 @@ void restorevsync() VARFP(vsync, 0, 0, 1, restorevsync()); VARFP(vsynctear, 0, 0, 1, { if(vsync) restorevsync(); }); -void setupscreen() -{ - if(glcontext) - { +void setupscreen() { + if(glcontext) { SDL_GL_DeleteContext(glcontext); glcontext = NULL; } - if(screen) - { + if(screen) { SDL_DestroyWindow(screen); screen = NULL; } curvsync = -1; - SDL_Rect desktop; if(SDL_GetDisplayBounds(0, &desktop) < 0) fatal("failed querying desktop bounds: %s", SDL_GetError()); desktopw = desktop.w; desktoph = desktop.h; - if(scr_h < 0) scr_h = fullscreen ? desktoph : SCR_DEFAULTH; if(scr_w < 0) scr_w = (scr_h*desktopw)/desktoph; scr_w = clamp(scr_w, SCR_MINW, SCR_MAXW); scr_h = clamp(scr_h, SCR_MINH, SCR_MAXH); - if(fullscreendesktop) - { + if(fullscreendesktop) { scr_w = min(scr_w, desktopw); scr_h = min(scr_h, desktoph); } - int winx = SDL_WINDOWPOS_UNDEFINED, winy = SDL_WINDOWPOS_UNDEFINED, winw = scr_w, winh = scr_h, flags = SDL_WINDOW_RESIZABLE; - if(fullscreen) - { - if(fullscreendesktop) - { + if(fullscreen) { + if(fullscreendesktop) { winw = desktopw; winh = desktoph; flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; @@ -637,42 +537,35 @@ void setupscreen() else flags |= SDL_WINDOW_FULLSCREEN; initwindowpos = true; } - SDL_GL_ResetAttributes(); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - static const int configs[] = - { + static const int configs[] = { 0x3, /* try everything */ 0x2, 0x1, /* try disabling one at a time */ 0 /* try disabling everything */ }; int config = 0; if(!depthbits) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - if(!fsaa) - { + if(!fsaa) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); } - loopi(sizeof(configs)/sizeof(configs[0])) - { + loopi(sizeof(configs)/sizeof(configs[0])) { config = configs[i]; if(!depthbits && config&1) continue; if(fsaa<=0 && config&2) continue; if(depthbits) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, config&1 ? depthbits : 24); - if(fsaa>0) - { + if(fsaa>0) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, config&2 ? 1 : 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, config&2 ? fsaa : 0); } screen = SDL_CreateWindow("Cube 2: Sauerbraten", winx, winy, winw, winh, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS | flags); if(!screen) continue; - static const int glversions[] = { 33, 32, 31, 30, 20 }; - loopj(sizeof(glversions)/sizeof(glversions[0])) - { + loopj(sizeof(glversions)/sizeof(glversions[0])) { glcompat = glversions[j] <= 30 ? 1 : 0; SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, glversions[j] / 10); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, glversions[j] % 10); @@ -684,24 +577,18 @@ void setupscreen() } if(!screen) fatal("failed to create OpenGL window: %s", SDL_GetError()); else if(!glcontext) fatal("failed to create OpenGL context: %s", SDL_GetError()); - else - { + else { if(depthbits && (config&1)==0) conoutf(CON_WARN, "%d bit z-buffer not supported - disabling", depthbits); if(fsaa>0 && (config&2)==0) conoutf(CON_WARN, "%dx anti-aliasing not supported - disabling", fsaa); } - SDL_SetWindowMinimumSize(screen, SCR_MINW, SCR_MINH); SDL_SetWindowMaximumSize(screen, SCR_MAXW, SCR_MAXH); - SDL_GetWindowSize(screen, &screenw, &screenh); } -void resetgl() -{ +void resetgl() { clearchanges(CHANGE_GFX); - renderbackground("resetting OpenGL"); - extern void cleanupva(); extern void cleanupparticles(); extern void cleanupdecals(); @@ -719,11 +606,9 @@ void resetgl() cleanshadowmap(); cleanupshaders(); cleanupgl(); - setupscreen(); inputgrab(grabinput); gl_init(); - inbetweenframes = false; if(!reloadtexture(*notexture) || !reloadtexture("data/logo.png") || @@ -750,13 +635,10 @@ COMMAND(resetgl, ""); static queue<SDL_Event, 32> events; -static inline bool filterevent(const SDL_Event &event) -{ - switch(event.type) - { +static inline bool filterevent(const SDL_Event &event) { + switch(event.type) { case SDL_MOUSEMOTION: - if(grabinput && !relativemouse && !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) - { + if(grabinput && !relativemouse && !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) { if(event.motion.x == screenw / 2 && event.motion.y == screenh / 2) return false; // ignore any motion events generated by SDL_WarpMouse } @@ -765,10 +647,8 @@ static inline bool filterevent(const SDL_Event &event) return true; } -template <int SIZE> static inline bool pumpevents(queue<SDL_Event, SIZE> &events) -{ - while(events.empty()) - { +template <int SIZE> static inline bool pumpevents(queue<SDL_Event, SIZE> &events) { + while(events.empty()) { SDL_PumpEvents(); databuf<SDL_Event> buf = events.reserve(events.capacity()); int n = SDL_PeepEvents(buf.getbuf(), buf.remaining(), SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT); @@ -781,14 +661,11 @@ template <int SIZE> static inline bool pumpevents(queue<SDL_Event, SIZE> &events static int interceptkeysym = 0; -static int interceptevents(void *data, SDL_Event *event) -{ - switch(event->type) - { +static int interceptevents(void *data, SDL_Event *event) { + switch(event->type) { case SDL_MOUSEMOTION: return 0; case SDL_KEYDOWN: - if(event->key.keysym.sym == interceptkeysym) - { + if(event->key.keysym.sym == interceptkeysym) { interceptkeysym = -interceptkeysym; return 0; } @@ -797,20 +674,16 @@ static int interceptevents(void *data, SDL_Event *event) return 1; } -static void clearinterceptkey() -{ +static void clearinterceptkey() { SDL_DelEventWatch(interceptevents, NULL); interceptkeysym = 0; } -bool interceptkey(int sym) -{ - if(!interceptkeysym) - { +bool interceptkey(int sym) { + if(!interceptkeysym) { interceptkeysym = sym; SDL_FilterEvents(interceptevents, NULL); - if(interceptkeysym < 0) - { + if(interceptkeysym < 0) { interceptkeysym = 0; return true; } @@ -818,8 +691,7 @@ bool interceptkey(int sym) } else if(abs(interceptkeysym) != sym) interceptkeysym = sym; SDL_PumpEvents(); - if(interceptkeysym < 0) - { + if(interceptkeysym < 0) { clearinterceptkey(); interceptkeysym = sym; SDL_FilterEvents(interceptevents, NULL); @@ -829,24 +701,19 @@ bool interceptkey(int sym) return false; } -static void ignoremousemotion() -{ +static void ignoremousemotion() { SDL_PumpEvents(); SDL_FlushEvent(SDL_MOUSEMOTION); } -static void resetmousemotion() -{ - if(grabinput && !relativemouse && !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) - { +static void resetmousemotion() { + if(grabinput && !relativemouse && !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) { SDL_WarpMouseInWindow(screen, screenw / 2, screenh / 2); } } -static void checkmousemotion(int &dx, int &dy) -{ - while(pumpevents(events)) - { +static void checkmousemotion(int &dx, int &dy) { + while(pumpevents(events)) { SDL_Event &event = events.removing(); if(event.type != SDL_MOUSEMOTION) return; dx += event.motion.xrel; @@ -855,46 +722,35 @@ static void checkmousemotion(int &dx, int &dy) } } -void checkinput() -{ +void checkinput() { if(interceptkeysym) clearinterceptkey(); //int lasttype = 0, lastbut = 0; bool mousemoved = false; int focused = 0; - while(pumpevents(events)) - { + while(pumpevents(events)) { SDL_Event &event = events.remove(); - if(focused && event.type!=SDL_WINDOWEVENT) { if(grabinput != (focused>0)) inputgrab(grabinput = focused>0, shouldgrab); focused = 0; } - - switch(event.type) - { + switch(event.type) { case SDL_QUIT: quit(); return; - case SDL_TEXTINPUT: - if(textinputmask && int(event.text.timestamp-textinputtime) >= textinputfilter) - { + if(textinputmask && int(event.text.timestamp-textinputtime) >= textinputfilter) { uchar buf[SDL_TEXTINPUTEVENT_TEXT_SIZE+1]; size_t len = decodeutf8(buf, sizeof(buf)-1, (const uchar *)event.text.text, strlen(event.text.text)); if(len > 0) { buf[len] = '\0'; processtextinput((const char *)buf, len); } } break; - case SDL_KEYDOWN: case SDL_KEYUP: if(keyrepeatmask || !event.key.repeat) processkey(event.key.keysym.sym, event.key.state==SDL_PRESSED, event.key.keysym.mod | SDL_GetModState()); break; - case SDL_WINDOWEVENT: - switch(event.window.event) - { + switch(event.window.event) { case SDL_WINDOWEVENT_CLOSE: quit(); break; - case SDL_WINDOWEVENT_FOCUS_GAINED: shouldgrab = true; break; @@ -902,30 +758,23 @@ void checkinput() shouldgrab = false; focused = 1; break; - case SDL_WINDOWEVENT_LEAVE: case SDL_WINDOWEVENT_FOCUS_LOST: shouldgrab = false; focused = -1; break; - case SDL_WINDOWEVENT_MINIMIZED: minimized = true; break; - case SDL_WINDOWEVENT_MAXIMIZED: case SDL_WINDOWEVENT_RESTORED: minimized = false; break; - case SDL_WINDOWEVENT_RESIZED: break; - - case SDL_WINDOWEVENT_SIZE_CHANGED: - { + case SDL_WINDOWEVENT_SIZE_CHANGED: { SDL_GetWindowSize(screen, &screenw, &screenh); - if(!fullscreendesktop || !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) - { + if(!fullscreendesktop || !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) { scr_w = clamp(screenw, SCR_MINW, SCR_MAXW); scr_h = clamp(screenh, SCR_MINH, SCR_MAXH); } @@ -934,10 +783,8 @@ void checkinput() } } break; - case SDL_MOUSEMOTION: - if(grabinput) - { + if(grabinput) { int dx = event.motion.xrel, dy = event.motion.yrel; checkmousemotion(dx, dy); if(!g3d_movecursor(dx, dy)) mousemove(dx, dy); @@ -945,12 +792,10 @@ void checkinput() } else if(shouldgrab) inputgrab(grabinput = true); break; - case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: //if(lasttype==event.type && lastbut==event.button.button) break; // why?? get event twice without it - switch(event.button.button) - { + switch(event.button.button) { case SDL_BUTTON_LEFT: processkey(-1, event.button.state==SDL_PRESSED); break; case SDL_BUTTON_MIDDLE: processkey(-2, event.button.state==SDL_PRESSED); break; case SDL_BUTTON_RIGHT: processkey(-3, event.button.state==SDL_PRESSED); break; @@ -960,7 +805,6 @@ void checkinput() //lasttype = event.type; //lastbut = event.button.button; break; - case SDL_MOUSEWHEEL: if(event.wheel.y > 0) { processkey(-4, true); processkey(-4, false); } else if(event.wheel.y < 0) { processkey(-5, true); processkey(-5, false); } @@ -971,8 +815,7 @@ void checkinput() if(mousemoved) resetmousemotion(); } -void swapbuffers(bool overlay) -{ +void swapbuffers(bool overlay) { gle::disable(); SDL_GL_SwapWindow(screen); } @@ -980,23 +823,19 @@ void swapbuffers(bool overlay) VAR(menufps, 0, 60, 1000); VARP(maxfps, 0, 200, 1000); -void limitfps(int &millis, int curmillis) -{ +void limitfps(int &millis, int curmillis) { int limit = (mainmenu || minimized) && menufps ? (maxfps ? min(maxfps, menufps) : menufps) : maxfps; if(!limit) return; static int fpserror = 0; int delay = 1000/limit - (millis-curmillis); if(delay < 0) fpserror = 0; - else - { + else { fpserror += 1000%limit; - if(fpserror >= limit) - { + if(fpserror >= limit) { ++delay; fpserror -= limit; } - if(delay > 0) - { + if(delay > 0) { SDL_Delay(delay); millis += delay; } @@ -1007,36 +846,30 @@ void limitfps(int &millis, int curmillis) int fpspos = 0, fpshistory[MAXFPSHISTORY]; -void resetfpshistory() -{ +void resetfpshistory() { loopi(MAXFPSHISTORY) fpshistory[i] = 1; fpspos = 0; } -void updatefpshistory(int millis) -{ +void updatefpshistory(int millis) { fpshistory[fpspos++] = max(1, min(1000, millis)); if(fpspos>=MAXFPSHISTORY) fpspos = 0; } -void getfps(int &fps, int &bestdiff, int &worstdiff) -{ +void getfps(int &fps, int &bestdiff, int &worstdiff) { int total = fpshistory[MAXFPSHISTORY-1], best = total, worst = total; - loopi(MAXFPSHISTORY-1) - { + loopi(MAXFPSHISTORY-1) { int millis = fpshistory[i]; total += millis; if(millis < best) best = millis; if(millis > worst) worst = millis; } - fps = (1000*MAXFPSHISTORY)/total; bestdiff = 1000/best-fps; worstdiff = fps-1000/worst; } -void getfps_(int *raw) -{ +void getfps_(int *raw) { int fps, bestdiff, worstdiff; if(*raw) fps = 1000/fpshistory[(fpspos+MAXFPSHISTORY-1)%MAXFPSHISTORY]; else getfps(fps, bestdiff, worstdiff); @@ -1047,8 +880,7 @@ COMMANDN(getfps, getfps_, "i"); bool inbetweenframes = false, renderedframe = true; -static bool findarg(int argc, char **argv, const char *str) -{ +static bool findarg(int argc, char **argv, const char *str) { for(int i = 1; i<argc; i++) if(strstr(argv[i], str)==argv[i]) return true; return false; } @@ -1058,8 +890,7 @@ static void clockreset() { clockrealbase = SDL_GetTicks(); clockvirtbase = total VARFP(clockerror, 990000, 1000000, 1010000, clockreset()); VARFP(clockfix, 0, 0, 1, clockreset()); -int getclockmillis() -{ +int getclockmillis() { int millis = SDL_GetTicks() - clockrealbase; if(clockfix) millis = int(millis*(double(clockerror)/1000000)); millis += clockvirtbase; @@ -1068,33 +899,26 @@ int getclockmillis() VAR(numcpus, 1, 1, 16); -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { setlogfile(NULL); - int dedicated = 0; char *load = NULL, *initscript = NULL; - initing = INIT_RESET; // set home dir first for(int i = 1; i<argc; i++) if(argv[i][0]=='-' && argv[i][1] == 'q') { sethomedir(&argv[i][2]); break; } // set log after home dir, but before anything else - for(int i = 1; i<argc; i++) if(argv[i][0]=='-' && argv[i][1] == 'g') - { + for(int i = 1; i<argc; i++) if(argv[i][0]=='-' && argv[i][1] == 'g') { const char *file = argv[i][2] ? &argv[i][2] : "log.txt"; setlogfile(file); logoutf("Setting log file: %s", file); break; } execfile("init.cfg", false); - for(int i = 1; i<argc; i++) - { - if(argv[i][0]=='-') switch(argv[i][1]) - { + for(int i = 1; i<argc; i++) { + if(argv[i][0]=='-') switch(argv[i][1]) { case 'q': if(homedir[0]) logoutf("Using home directory: %s", homedir); break; case 'r': /* compat, ignore */ break; - case 'k': - { + case 'k': { const char *dir = addpackagedir(&argv[i][2]); if(dir) logoutf("Adding package directory: %s", dir); break; @@ -1110,8 +934,7 @@ int main(int argc, char **argv) case 't': fullscreen = atoi(&argv[i][2]); break; case 's': /* compat, ignore */ break; case 'f': /* compat, ignore */ break; - case 'l': - { + case 'l': { char pkgdir[] = "packages/"; load = strstr(path(&argv[i][2]), path(pkgdir)); if(load) load += sizeof(pkgdir)-1; @@ -1124,13 +947,9 @@ int main(int argc, char **argv) else gameargs.add(argv[i]); } initing = NOT_INITING; - numcpus = clamp(SDL_GetCPUCount(), 1, 16); - - if(dedicated <= 1) - { + if(dedicated <= 1) { logoutf("init: sdl"); - if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_AUDIO)<0) fatal("Unable to initialize SDL: %s", SDL_GetError()); #ifdef SDL_VIDEO_DRIVER_X11 @@ -1140,46 +959,37 @@ int main(int argc, char **argv) sdl_xgrab_bug = 1; #endif } - logoutf("init: net"); if(enet_initialize()<0) fatal("Unable to initialise network module"); atexit(enet_deinitialize); enet_time_set(0); - logoutf("init: game"); game::parseoptions(gameargs); initserver(dedicated>0, dedicated>1); // never returns if dedicated ASSERT(dedicated <= 1); game::initclient(); - logoutf("init: video"); SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "0"); SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); setupscreen(); SDL_ShowCursor(SDL_FALSE); SDL_StopTextInput(); // workaround for spurious text-input events getting sent on first text input toggle? - logoutf("init: gl"); gl_checkextensions(); gl_init(); notexture = textureload("packages/textures/texture_error.png"); if(!notexture) fatal("could not find core textures"); - logoutf("init: console"); if(!execfile("data/stdlib.cfg", false)) fatal("cannot find data files (you are running from the wrong folder, try .bat file in the main folder)"); // this is the first file we load. if(!execfile("packages/fonts/default.cfg", false)) fatal("cannot find font definitions"); if(!setfont("default")) fatal("no default font specified"); - inbetweenframes = true; renderbackground("initializing..."); - logoutf("init: world"); camera1 = player = game::iterdynents(0); emptymap(0, true, NULL, false); - logoutf("init: sound"); initsound(); - logoutf("init: cfg"); initing = INIT_LOAD; execfile("data/keymap.cfg"); @@ -1189,52 +999,35 @@ int main(int argc, char **argv) execfile("data/game.cfg"); execfile("data/custom_maps_menu.cfg"); if(game::savedservers()) execfile(game::savedservers(), false); - identflags |= IDF_PERSIST; - - if(!execfile(game::savedconfig(), false)) - { + if(!execfile(game::savedconfig(), false)) { execfile(game::defaultconfig()); writecfg(game::restoreconfig()); } execfile(game::autoexec(), false); - identflags &= ~IDF_PERSIST; - initing = INIT_GAME; game::loadconfigs(); - initing = NOT_INITING; - logoutf("init: render"); restoregamma(); restorevsync(); loadshaders(); initparticles(); initdecals(); - identflags |= IDF_PERSIST; - logoutf("init: mainloop"); - if(execfile("once.cfg", false)) remove(findfile("once.cfg", "rb")); - - if(load) - { + if(load) { logoutf("init: localconnect"); //localconnect(); game::changemap(load); } - if(initscript) execute(initscript); - resetfpshistory(); - inputgrab(grabinput = true); ignoremousemotion(); - - for(;;) - { + for(;;) { static int frames = 0; int millis = getclockmillis(); limitfps(millis, totalmillis); @@ -1248,37 +1041,26 @@ int main(int argc, char **argv) lastmillis += curtime; totalmillis = millis; updatetime(); - checkinput(); menuprocess(); tryedit(); - if(lastmillis) game::updateworld(); - checksleep(lastmillis); - serverslice(false, 0); - if(frames) updatefpshistory(elapsedtime); frames++; - // miscellaneous general game effects recomputecamera(); updateparticles(); updatesounds(); - if(minimized) continue; - inbetweenframes = false; - glClearColor(0,0,0,1);///TODO - if(mainmenu) gl_drawmainmenu(); else gl_drawframe(); swapbuffers(); renderedframe = inbetweenframes = true; } - ASSERT(0); return EXIT_FAILURE; } diff --git a/src/engine/master.cpp b/src/engine/master.cpp index 2bf1dba..c1d3e20 100644 --- a/src/engine/master.cpp +++ b/src/engine/master.cpp @@ -22,15 +22,13 @@ FILE *logfile = NULL; -struct userinfo -{ +struct userinfo { char *name; void *pubkey; }; hashnameset<userinfo> users; -void adduser(char *name, char *pubkey) -{ +void adduser(char *name, char *pubkey) { name = newstring(name); userinfo &u = users[name]; u.name = name; @@ -38,8 +36,7 @@ void adduser(char *name, char *pubkey) } COMMAND(adduser, "ss"); -void clearusers() -{ +void clearusers() { enumerate(users, userinfo, u, { delete[] u.name; freepubkey(u.pubkey); }); users.clear(); } @@ -47,16 +44,14 @@ COMMAND(clearusers, ""); vector<ipmask> bans, servbans, gbans; -void clearbans() -{ +void clearbans() { bans.shrink(0); servbans.shrink(0); gbans.shrink(0); } COMMAND(clearbans, ""); -void addban(vector<ipmask> &bans, const char *name) -{ +void addban(vector<ipmask> &bans, const char *name) { ipmask ban; ban.parse(name); bans.add(ban); @@ -65,21 +60,18 @@ ICOMMAND(ban, "s", (char *name), addban(bans, name)); ICOMMAND(servban, "s", (char *name), addban(servbans, name)); ICOMMAND(gban, "s", (char *name), addban(gbans, name)); -bool checkban(vector<ipmask> &bans, enet_uint32 host) -{ +bool checkban(vector<ipmask> &bans, enet_uint32 host) { loopv(bans) if(bans[i].check(host)) return true; return false; } -struct authreq -{ +struct authreq { enet_uint32 reqtime; uint id; void *answer; }; -struct gameserver -{ +struct gameserver { ENetAddress address; string ip; int port, numpings; @@ -87,30 +79,21 @@ struct gameserver }; vector<gameserver *> gameservers; -struct messagebuf -{ +struct messagebuf { vector<messagebuf *> &owner; vector<char> buf; int refs; - messagebuf(vector<messagebuf *> &owner) : owner(owner), refs(0) {} - const char *getbuf() { return buf.getbuf(); } int length() { return buf.length(); } void purge(); - - bool equals(const messagebuf &m) const - { + bool equals(const messagebuf &m) const { return buf.length() == m.buf.length() && !memcmp(buf.getbuf(), m.buf.getbuf(), buf.length()); } - - bool endswith(const messagebuf &m) const - { + bool endswith(const messagebuf &m) const { return buf.length() >= m.buf.length() && !memcmp(&buf[buf.length() - m.buf.length()], m.buf.getbuf(), m.buf.length()); } - - void concat(const messagebuf &m) - { + void concat(const messagebuf &m) { if(buf.length() && buf.last() == '\0') buf.pop(); buf.put(m.buf.getbuf(), m.buf.length()); } @@ -118,8 +101,7 @@ struct messagebuf vector<messagebuf *> gameserverlists, gbanlists; bool updateserverlist = true; -struct client -{ +struct client { ENetAddress address; ENetSocket socket; char input[INPUT_LIMIT]; @@ -132,7 +114,6 @@ struct client vector<authreq> authreqs; bool shouldpurge; bool registeredserver; - client() : message(NULL), inputpos(0), outputpos(0), servport(-1), lastauth(0), shouldpurge(false), registeredserver(false) {} }; vector<client *> clients; @@ -142,8 +123,7 @@ ENetSocket serversocket = ENET_SOCKET_NULL; time_t starttime; enet_uint32 servtime = 0; -void fatal(const char *fmt, ...) -{ +void fatal(const char *fmt, ...) { va_list args; va_start(args, fmt); vfprintf(logfile, fmt, args); @@ -152,14 +132,12 @@ void fatal(const char *fmt, ...) exit(EXIT_FAILURE); } -void conoutfv(int type, const char *fmt, va_list args) -{ +void conoutfv(int type, const char *fmt, va_list args) { vfprintf(logfile, fmt, args); fputc('\n', logfile); } -void purgeclient(int n) -{ +void purgeclient(int n) { client &c = *clients[n]; if(c.message) c.message->purge(); enet_socket_destroy(c.socket); @@ -167,27 +145,23 @@ void purgeclient(int n) clients.remove(n); } -void output(client &c, const char *msg, int len = 0) -{ +void output(client &c, const char *msg, int len = 0) { if(!len) len = strlen(msg); c.output.put(msg, len); } -void outputf(client &c, const char *fmt, ...) -{ +void outputf(client &c, const char *fmt, ...) { string msg; va_list args; va_start(args, fmt); vformatstring(msg, fmt, args); va_end(args); - output(c, msg); } ENetSocket pingsocket = ENET_SOCKET_NULL; -bool setuppingsocket(ENetAddress *address) -{ +bool setuppingsocket(ENetAddress *address) { if(pingsocket != ENET_SOCKET_NULL) return true; pingsocket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); if(pingsocket == ENET_SOCKET_NULL) return false; @@ -196,14 +170,11 @@ bool setuppingsocket(ENetAddress *address) return true; } -void setupserver(int port, const char *ip = NULL) -{ +void setupserver(int port, const char *ip = NULL) { ENetAddress address; address.host = ENET_HOST_ANY; address.port = port; - - if(ip) - { + if(ip) { if(enet_address_set_host(&address, ip)<0) fatal("failed to resolve server address: %s", ip); } @@ -217,23 +188,19 @@ void setupserver(int port, const char *ip = NULL) fatal("failed to make server socket non-blocking"); if(!setuppingsocket(&address)) fatal("failed to create ping socket"); - enet_time_set(0); - starttime = time(NULL); char *ct = ctime(&starttime); if(strchr(ct, '\n')) *strchr(ct, '\n') = '\0'; conoutf("*** Starting master server on %s %d at %s ***", ip ? ip : "localhost", port, ct); } -void genserverlist() -{ +void genserverlist() { if(!updateserverlist) return; while(gameserverlists.length() && gameserverlists.last()->refs<=0) delete gameserverlists.pop(); messagebuf *l = new messagebuf(gameserverlists); - loopv(gameservers) - { + loopv(gameservers) { gameserver &s = *gameservers[i]; if(!s.lastpong) continue; defformatstring(cmd, "addserver %s %d\n", s.ip, s.port); @@ -244,67 +211,56 @@ void genserverlist() updateserverlist = false; } -void gengbanlist() -{ +void gengbanlist() { messagebuf *l = new messagebuf(gbanlists); const char *header = "cleargbans\n"; l->buf.put(header, strlen(header)); string cmd = "addgban "; int cmdlen = strlen(cmd); - loopv(gbans) - { + loopv(gbans) { ipmask &b = gbans[i]; l->buf.put(cmd, cmdlen + b.print(&cmd[cmdlen])); l->buf.add('\n'); } - if(gbanlists.length() && gbanlists.last()->equals(*l)) - { + if(gbanlists.length() && gbanlists.last()->equals(*l)) { delete l; return; } while(gbanlists.length() && gbanlists.last()->refs<=0) delete gbanlists.pop(); - loopv(gbanlists) - { + loopv(gbanlists) { messagebuf *m = gbanlists[i]; if(m->refs > 0 && !m->endswith(*l)) m->concat(*l); } gbanlists.add(l); - loopv(clients) - { + loopv(clients) { client &c = *clients[i]; - if(c.servport >= 0 && !c.message) - { + if(c.servport >= 0 && !c.message) { c.message = l; c.message->refs++; } } } -void addgameserver(client &c) -{ +void addgameserver(client &c) { if(gameservers.length() >= SERVER_LIMIT) return; int dups = 0; - loopv(gameservers) - { + loopv(gameservers) { gameserver &s = *gameservers[i]; if(s.address.host != c.address.host) continue; ++dups; - if(s.port == c.servport) - { + if(s.port == c.servport) { s.lastping = 0; s.numpings = 0; return; } } - if(dups >= SERVER_DUP_LIMIT) - { + if(dups >= SERVER_DUP_LIMIT) { outputf(c, "failreg too many servers on ip\n"); return; } string hostname; - if(enet_address_get_host_ip(&c.address, hostname, sizeof(hostname)) < 0) - { + if(enet_address_get_host_ip(&c.address, hostname, sizeof(hostname)) < 0) { outputf(c, "failreg failed resolving ip\n"); return; } @@ -317,10 +273,8 @@ void addgameserver(client &c) s.lastping = s.lastpong = 0; } -client *findclient(gameserver &s) -{ - loopv(clients) - { +client *findclient(gameserver &s) { + loopv(clients) { client &c = *clients[i]; if(s.address.host == c.address.host && s.port == c.servport) return &c; @@ -328,37 +282,29 @@ client *findclient(gameserver &s) return NULL; } -void servermessage(gameserver &s, const char *msg) -{ +void servermessage(gameserver &s, const char *msg) { client *c = findclient(s); if(c) outputf(*c, msg); } -void checkserverpongs() -{ +void checkserverpongs() { ENetBuffer buf; ENetAddress addr; static uchar pong[MAXTRANS]; - for(;;) - { + for(;;) { buf.data = pong; buf.dataLength = sizeof(pong); int len = enet_socket_receive(pingsocket, &addr, &buf, 1); if(len <= 0) break; - loopv(gameservers) - { + loopv(gameservers) { gameserver &s = *gameservers[i]; - if(s.address.host == addr.host && s.address.port == addr.port) - { - if(s.lastping && (!s.lastpong || ENET_TIME_GREATER(s.lastping, s.lastpong))) - { + if(s.address.host == addr.host && s.address.port == addr.port) { + if(s.lastping && (!s.lastpong || ENET_TIME_GREATER(s.lastping, s.lastpong))) { client *c = findclient(s); - if(c) - { + if(c) { c->registeredserver = true; outputf(*c, "succreg\n"); - if(!c->message && gbanlists.length()) - { + if(!c->message && gbanlists.length()) { c->message = gbanlists.last(); c->message->refs++; } @@ -372,39 +318,30 @@ void checkserverpongs() } } -void bangameservers() -{ - loopvrev(gameservers) if(checkban(servbans, gameservers[i]->address.host)) - { +void bangameservers() { + loopvrev(gameservers) if(checkban(servbans, gameservers[i]->address.host)) { delete gameservers.remove(i); updateserverlist = true; } } -void checkgameservers() -{ +void checkgameservers() { ENetBuffer buf; - loopv(gameservers) - { + loopv(gameservers) { gameserver &s = *gameservers[i]; - if(s.lastping && s.lastpong && ENET_TIME_LESS_EQUAL(s.lastping, s.lastpong)) - { - if(ENET_TIME_DIFFERENCE(servtime, s.lastpong) > KEEPALIVE_TIME) - { + if(s.lastping && s.lastpong && ENET_TIME_LESS_EQUAL(s.lastping, s.lastpong)) { + if(ENET_TIME_DIFFERENCE(servtime, s.lastpong) > KEEPALIVE_TIME) { delete gameservers.remove(i--); updateserverlist = true; } } - else if(!s.lastping || ENET_TIME_DIFFERENCE(servtime, s.lastping) > PING_TIME) - { - if(s.numpings >= PING_RETRY) - { + else if(!s.lastping || ENET_TIME_DIFFERENCE(servtime, s.lastping) > PING_TIME) { + if(s.numpings >= PING_RETRY) { servermessage(s, "failreg failed pinging server\n"); delete gameservers.remove(i--); updateserverlist = true; } - else - { + else { static const uchar ping[] = { 1 }; buf.data = (void *)ping; buf.dataLength = sizeof(ping); @@ -416,23 +353,18 @@ void checkgameservers() } } -void messagebuf::purge() -{ +void messagebuf::purge() { refs = max(refs - 1, 0); - if(refs<=0 && owner.last()!=this) - { + if(refs<=0 && owner.last()!=this) { owner.removeobj(this); delete this; } } -void purgeauths(client &c) -{ +void purgeauths(client &c) { int expired = 0; - loopv(c.authreqs) - { - if(ENET_TIME_DIFFERENCE(servtime, c.authreqs[i].reqtime) >= AUTH_TIME) - { + loopv(c.authreqs) { + if(ENET_TIME_DIFFERENCE(servtime, c.authreqs[i].reqtime) >= AUTH_TIME) { outputf(c, "failauth %u\n", c.authreqs[i].id); freechallenge(c.authreqs[i].answer); expired = i + 1; @@ -442,40 +374,30 @@ void purgeauths(client &c) if(expired > 0) c.authreqs.remove(0, expired); } -void reqauth(client &c, uint id, char *name) -{ +void reqauth(client &c, uint id, char *name) { if(ENET_TIME_DIFFERENCE(servtime, c.lastauth) < AUTH_THROTTLE) return; - c.lastauth = servtime; - purgeauths(c); - time_t t = time(NULL); char *ct = ctime(&t); - if(ct) - { + if(ct) { char *newline = strchr(ct, '\n'); if(newline) *newline = '\0'; } string ip; if(enet_address_get_host_ip(&c.address, ip, sizeof(ip)) < 0) copystring(ip, "-"); conoutf("%s: attempting \"%s\" as %u from %s", ct ? ct : "-", name, id, ip); - userinfo *u = users.access(name); - if(!u) - { + if(!u) { outputf(c, "failauth %u\n", id); return; } - - if(c.authreqs.length() >= AUTH_LIMIT) - { + if(c.authreqs.length() >= AUTH_LIMIT) { outputf(c, "failauth %u\n", c.authreqs[0].id); freechallenge(c.authreqs[0].answer); c.authreqs.remove(0); } - authreq &a = c.authreqs.add(); a.reqtime = servtime; a.id = id; @@ -483,25 +405,19 @@ void reqauth(client &c, uint id, char *name) static vector<char> buf; buf.setsize(0); a.answer = genchallenge(u->pubkey, seed, sizeof(seed), buf); - outputf(c, "chalauth %u %s\n", id, buf.getbuf()); } -void confauth(client &c, uint id, const char *val) -{ +void confauth(client &c, uint id, const char *val) { purgeauths(c); - - loopv(c.authreqs) if(c.authreqs[i].id == id) - { + loopv(c.authreqs) if(c.authreqs[i].id == id) { string ip; if(enet_address_get_host_ip(&c.address, ip, sizeof(ip)) < 0) copystring(ip, "-"); - if(checkchallenge(val, c.authreqs[i].answer)) - { + if(checkchallenge(val, c.authreqs[i].answer)) { outputf(c, "succauth %u\n", id); conoutf("succeeded %u from %s", id, ip); } - else - { + else { outputf(c, "failauth %u\n", id); conoutf("failed %u from %s", id, ip); } @@ -512,20 +428,16 @@ void confauth(client &c, uint id, const char *val) outputf(c, "failauth %u\n", id); } -bool checkclientinput(client &c) -{ +bool checkclientinput(client &c) { if(c.inputpos<0) return true; char *end = (char *)memchr(c.input, '\n', c.inputpos); - while(end) - { + while(end) { *end++ = '\0'; c.lastinput = servtime; - int port; uint id; string user, val; - if(!strncmp(c.input, "list", 4) && (!c.input[4] || c.input[4] == '\n' || c.input[4] == '\r')) - { + if(!strncmp(c.input, "list", 4) && (!c.input[4] || c.input[4] == '\n' || c.input[4] == '\r')) { genserverlist(); if(gameserverlists.empty() || c.message) return false; c.message = gameserverlists.last(); @@ -535,27 +447,22 @@ bool checkclientinput(client &c) c.shouldpurge = true; return true; } - else if(sscanf(c.input, "regserv %d", &port) == 1) - { + else if(sscanf(c.input, "regserv %d", &port) == 1) { if(checkban(servbans, c.address.host)) return false; if(port < 0 || port > 0xFFFF-1 || (c.servport >= 0 && port != c.servport)) outputf(c, "failreg invalid port\n"); - else - { + else { c.servport = port; addgameserver(c); } } - else if(sscanf(c.input, "reqauth %u %100s", &id, user) == 2) - { + else if(sscanf(c.input, "reqauth %u %100s", &id, user) == 2) { reqauth(c, id, user); } - else if(sscanf(c.input, "confauth %u %100s", &id, val) == 2) - { + else if(sscanf(c.input, "confauth %u %100s", &id, val) == 2) { confauth(c, id, val); } c.inputpos = &c.input[c.inputpos] - end; memmove(c.input, end, c.inputpos); - end = (char *)memchr(c.input, '\n', c.inputpos); } return c.inputpos<(int)sizeof(c.input); @@ -563,16 +470,14 @@ bool checkclientinput(client &c) ENetSocketSet readset, writeset; -void checkclients() -{ +void checkclients() { ENetSocketSet readset, writeset; ENetSocket maxsock = max(serversocket, pingsocket); ENET_SOCKETSET_EMPTY(readset); ENET_SOCKETSET_EMPTY(writeset); ENET_SOCKETSET_ADD(readset, serversocket); ENET_SOCKETSET_ADD(readset, pingsocket); - loopv(clients) - { + loopv(clients) { client &c = *clients[i]; if(c.authreqs.length()) purgeauths(c); if(c.message || c.output.length()) ENET_SOCKETSET_ADD(writeset, c.socket); @@ -580,23 +485,18 @@ void checkclients() maxsock = max(maxsock, c.socket); } if(enet_socketset_select(maxsock, &readset, &writeset, 1000)<=0) return; - if(ENET_SOCKETSET_CHECK(readset, pingsocket)) checkserverpongs(); - if(ENET_SOCKETSET_CHECK(readset, serversocket)) - { + if(ENET_SOCKETSET_CHECK(readset, serversocket)) { ENetAddress address; ENetSocket clientsocket = enet_socket_accept(serversocket, &address); if(clients.length()>=CLIENT_LIMIT || checkban(bans, address.host)) enet_socket_destroy(clientsocket); - else if(clientsocket!=ENET_SOCKET_NULL) - { + else if(clientsocket!=ENET_SOCKET_NULL) { int dups = 0, oldest = -1; - loopv(clients) if(clients[i]->address.host == address.host) - { + loopv(clients) if(clients[i]->address.host == address.host) { dups++; if(oldest<0 || clients[i]->connecttime < clients[oldest]->connecttime) oldest = i; } if(dups >= DUP_LIMIT) purgeclient(oldest); - client *c = new client; c->address = address; c->socket = clientsocket; @@ -605,32 +505,25 @@ void checkclients() clients.add(c); } } - - loopv(clients) - { + loopv(clients) { client &c = *clients[i]; - if((c.message || c.output.length()) && ENET_SOCKETSET_CHECK(writeset, c.socket)) - { + if((c.message || c.output.length()) && ENET_SOCKETSET_CHECK(writeset, c.socket)) { const char *data = c.output.length() ? c.output.getbuf() : c.message->getbuf(); int len = c.output.length() ? c.output.length() : c.message->length(); ENetBuffer buf; buf.data = (void *)&data[c.outputpos]; buf.dataLength = len-c.outputpos; int res = enet_socket_send(c.socket, NULL, &buf, 1); - if(res>=0) - { + if(res>=0) { c.outputpos += res; - if(c.outputpos>=len) - { + if(c.outputpos>=len) { if(c.output.length()) c.output.setsize(0); - else - { + else { c.message->purge(); c.message = NULL; } c.outputpos = 0; - if(!c.message && c.output.empty() && c.shouldpurge) - { + if(!c.message && c.output.empty() && c.shouldpurge) { purgeclient(i--); continue; } @@ -638,14 +531,12 @@ void checkclients() } else { purgeclient(i--); continue; } } - if(ENET_SOCKETSET_CHECK(readset, c.socket)) - { + if(ENET_SOCKETSET_CHECK(readset, c.socket)) { ENetBuffer buf; buf.data = &c.input[c.inputpos]; buf.dataLength = sizeof(c.input) - c.inputpos; int res = enet_socket_receive(c.socket, NULL, &buf, 1); - if(res>0) - { + if(res>0) { c.inputpos += res; c.input[min(c.inputpos, (int)sizeof(c.input)-1)] = '\0'; if(!checkclientinput(c)) { purgeclient(i--); continue; } @@ -657,23 +548,19 @@ void checkclients() } } -void banclients() -{ +void banclients() { loopvrev(clients) if(checkban(bans, clients[i]->address.host)) purgeclient(i); } volatile int reloadcfg = 1; -void reloadsignal(int signum) -{ +void reloadsignal(int signum) { reloadcfg = 1; } -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { if(enet_initialize()<0) fatal("Unable to initialise network module"); atexit(enet_deinitialize); - const char *dir = "", *ip = NULL; int port = 28787; if(argc>=2) dir = argv[1]; @@ -688,10 +575,8 @@ int main(int argc, char **argv) setvbuf(logfile, NULL, _IOLBF, BUFSIZ); signal(SIGUSR1, reloadsignal); setupserver(port, ip); - for(;;) - { - if(reloadcfg) - { + for(;;) { + if(reloadcfg) { conoutf("reloading master.cfg"); execfile(cfgname); bangameservers(); @@ -699,12 +584,10 @@ int main(int argc, char **argv) gengbanlist(); reloadcfg = 0; } - servtime = enet_time_get(); checkclients(); checkgameservers(); } - return EXIT_SUCCESS; } diff --git a/src/engine/material.cpp b/src/engine/material.cpp index e29ccf5..55151a1 100644 --- a/src/engine/material.cpp +++ b/src/engine/material.cpp @@ -4,13 +4,9 @@ struct QuadNode { int x, y, size; uint filled; QuadNode *child[4]; - QuadNode(int x, int y, int size) : x(x), y(y), size(size), filled(0) { loopi(4) child[i] = 0; } - void clear() { loopi(4) DELETEP(child[i]); } - ~QuadNode() { clear(); } - void insert(int mx, int my, int msize) { if(size == msize) { filled = 0xF; @@ -25,15 +21,13 @@ struct QuadNode { } if(!child[i]) child[i] = new QuadNode(i&1 ? x+csize : x, i&2 ? y+csize : y, csize); child[i]->insert(mx, my, msize); - loopj(4) if(child[j]) - { + loopj(4) if(child[j]) { if(child[j]->filled == 0xF) { DELETEP(child[j]); filled |= (1 << j); } } } - void genmatsurf(ushort mat, uchar orient, uchar visible, int x, int y, int z, int size, materialsurface *&matbuf) { materialsurface &m = *matbuf++; m.material = mat; @@ -46,11 +40,9 @@ struct QuadNode { m.o[R[dim]] = y; m.o[dim] = z; } - void genmatsurfs(ushort mat, uchar orient, uchar flags, int z, materialsurface *&matbuf) { if(filled == 0xF) genmatsurf(mat, orient, flags, x, y, z, size, matbuf); - else if(filled) - { + else if(filled) { int csize = size>>1; loopi(4) if(filled & (1 << i)) genmatsurf(mat, orient, flags, i&1 ? x+csize : x, i&2 ? y+csize : y, z, csize, matbuf); @@ -68,21 +60,18 @@ static const bvec4 matnormals[6] = { bvec4(0, 0, 0x7F) }; -static void drawmaterial(const materialsurface &m, float offset, const bvec4 &color) -{ - if(gle::attribbuf.empty()) - { +static void drawmaterial(const materialsurface &m, float offset, const bvec4 &color) { + if(gle::attribbuf.empty()) { gle::defvertex(); gle::defcolor(4, GL_UNSIGNED_BYTE); gle::begin(GL_QUADS); } float x = m.o.x, y = m.o.y, z = m.o.z, csize = m.csize, rsize = m.rsize; - switch(m.orient) - { + switch(m.orient) { #define GENFACEORIENT(orient, v0, v1, v2, v3) \ case orient: v0 v1 v2 v3 break; - #define GENFACEVERT(orient, vert, mx,my,mz, sx,sy,sz) \ - { \ + #define GENFACEVERT(orient, vert, mx,my,mz, sx,sy,sz) { \ + \ gle::attribf(mx sx, my sy, mz sz); \ gle::attrib(color); \ } @@ -92,45 +81,38 @@ static void drawmaterial(const materialsurface &m, float offset, const bvec4 &co } } -const struct material -{ +const struct material { const char *name; ushort id; -} materials[] = -{ - {"air", MAT_AIR}, - {"clip", MAT_CLIP}, - {"noclip", MAT_NOCLIP}, - {"gameclip", MAT_GAMECLIP}, - {"death", MAT_DEATH}, - {"alpha", MAT_ALPHA} +} materials[] = { + { + "air", MAT_AIR}, { + "clip", MAT_CLIP}, { + "noclip", MAT_NOCLIP}, { + "gameclip", MAT_GAMECLIP}, { + "death", MAT_DEATH}, { + "alpha", MAT_ALPHA} }; -int findmaterial(const char *name) -{ - loopi(sizeof(materials)/sizeof(material)) - { +int findmaterial(const char *name) { + loopi(sizeof(materials)/sizeof(material)) { if(!strcmp(materials[i].name, name)) return materials[i].id; } return -1; } -const char *findmaterialname(int mat) -{ +const char *findmaterialname(int mat) { loopi(sizeof(materials)/sizeof(materials[0])) if(materials[i].id == mat) return materials[i].name; return NULL; } -const char *getmaterialdesc(int mat, const char *prefix) -{ +const char *getmaterialdesc(int mat, const char *prefix) { static const ushort matmasks[] = { MATF_INDEX, MATF_CLIP, MAT_DEATH, MAT_ALPHA }; static string desc; desc[0] = '\0'; - loopi(sizeof(matmasks)/sizeof(matmasks[0])) if(mat&matmasks[i]) - { + loopi(sizeof(matmasks)/sizeof(matmasks[0])) if(mat&matmasks[i]) { const char *matname = findmaterialname(mat&matmasks[i]); - if(matname) - { + if(matname) { concatstring(desc, desc[0] ? ", " : prefix); concatstring(desc, matname); } @@ -138,14 +120,11 @@ const char *getmaterialdesc(int mat, const char *prefix) return desc; } -int visiblematerial(const cube &c, int orient, const ivec &co, int size, ushort matmask) -{ +int visiblematerial(const cube &c, int orient, const ivec &co, int size, ushort matmask) { ushort mat = c.material&matmask; - switch(mat) - { + switch(mat) { case MAT_AIR: break; - default: if(visibleface(c, orient, co, size, mat, MAT_AIR, matmask)) return MATSURF_EDIT_ONLY; @@ -154,17 +133,13 @@ int visiblematerial(const cube &c, int orient, const ivec &co, int size, ushort return MATSURF_NOT_VISIBLE; } -void genmatsurfs(const cube &c, const ivec &co, int size, vector<materialsurface> &matsurfs) -{ - loopi(6) - { +void genmatsurfs(const cube &c, const ivec &co, int size, vector<materialsurface> &matsurfs) { + loopi(6) { static const ushort matmasks[] = { MATF_INDEX, MATF_CLIP, MAT_DEATH, MAT_ALPHA }; - loopj(sizeof(matmasks)/sizeof(matmasks[0])) - { + loopj(sizeof(matmasks)/sizeof(matmasks[0])) { int matmask = matmasks[j]; int vis = visiblematerial(c, i, co, size, matmask&~MATF_INDEX); - if(vis != MATSURF_NOT_VISIBLE) - { + if(vis != MATSURF_NOT_VISIBLE) { materialsurface m; m.material = c.material&matmask; m.orient = i; @@ -179,22 +154,18 @@ void genmatsurfs(const cube &c, const ivec &co, int size, vector<materialsurface } } -static inline bool mergematcmp(const materialsurface &x, const materialsurface &y) -{ +static inline bool mergematcmp(const materialsurface &x, const materialsurface &y) { int dim = dimension(x.orient), c = C[dim], r = R[dim]; if(x.o[r] + x.rsize < y.o[r] + y.rsize) return true; if(x.o[r] + x.rsize > y.o[r] + y.rsize) return false; return x.o[c] < y.o[c]; } -static int mergematr(materialsurface *m, int sz, materialsurface &n) -{ +static int mergematr(materialsurface *m, int sz, materialsurface &n) { int dim = dimension(n.orient), c = C[dim], r = R[dim]; - for(int i = sz-1; i >= 0; --i) - { + for(int i = sz-1; i >= 0; --i) { if(m[i].o[r] + m[i].rsize < n.o[r]) break; - if(m[i].o[r] + m[i].rsize == n.o[r] && m[i].o[c] == n.o[c] && m[i].csize == n.csize) - { + if(m[i].o[r] + m[i].rsize == n.o[r] && m[i].o[c] == n.o[c] && m[i].csize == n.csize) { n.o[r] = m[i].o[r]; n.rsize += m[i].rsize; memmove(&m[i], &m[i+1], (sz - (i+1)) * sizeof(materialsurface)); @@ -204,11 +175,9 @@ static int mergematr(materialsurface *m, int sz, materialsurface &n) return 0; } -static int mergematc(materialsurface &m, materialsurface &n) -{ +static int mergematc(materialsurface &m, materialsurface &n) { int dim = dimension(n.orient), c = C[dim], r = R[dim]; - if(m.o[r] == n.o[r] && m.rsize == n.rsize && m.o[c] + m.csize == n.o[c]) - { + if(m.o[r] == n.o[r] && m.rsize == n.rsize && m.o[c] + m.csize == n.o[c]) { n.o[c] = m.o[c]; n.csize += m.csize; return 1; @@ -216,10 +185,8 @@ static int mergematc(materialsurface &m, materialsurface &n) return 0; } -static int mergemat(materialsurface *m, int sz, materialsurface &n) -{ - for(bool merged = false; sz; merged = true) - { +static int mergemat(materialsurface *m, int sz, materialsurface &n) { + for(bool merged = false; sz; merged = true) { int rmerged = mergematr(m, sz, n); sz -= rmerged; if(!rmerged && merged) break; @@ -232,17 +199,14 @@ static int mergemat(materialsurface *m, int sz, materialsurface &n) return sz; } -static int mergemats(materialsurface *m, int sz) -{ +static int mergemats(materialsurface *m, int sz) { quicksort(m, sz, mergematcmp); - int nsz = 0; loopi(sz) nsz = mergemat(m, nsz, m[i]); return nsz; } -static inline bool optmatcmp(const materialsurface &x, const materialsurface &y) -{ +static inline bool optmatcmp(const materialsurface &x, const materialsurface &y) { if(x.material < y.material) return true; if(x.material > y.material) return false; if(x.orient > y.orient) return true; @@ -253,13 +217,11 @@ static inline bool optmatcmp(const materialsurface &x, const materialsurface &y) VARF(optmats, 0, 1, 1, allchanged()); -int optimizematsurfs(materialsurface *matbuf, int matsurfs) -{ +int optimizematsurfs(materialsurface *matbuf, int matsurfs) { quicksort(matbuf, matsurfs, optmatcmp); if(!optmats) return matsurfs; materialsurface *cur = matbuf, *end = matbuf+matsurfs; - while(cur < end) - { + while(cur < end) { materialsurface *start = cur++; int dim = dimension(start->orient); while(cur < end && @@ -288,17 +250,14 @@ int optimizematsurfs(materialsurface *matbuf, int matsurfs) return matsurfs - (end-matbuf); } -void setupmaterials(int start, int len) -{ +void setupmaterials(int start, int len) { int hasmat = 0; unionfind uf; if(!len) len = valist.length(); - for(int i = start; i < len; i++) - { + for(int i = start; i < len; i++) { vtxarray *va = valist[i]; materialsurface *skip = NULL; - loopj(va->matsurfs) - { + loopj(va->matsurfs) { materialsurface &m = va->matbuf[j]; int matvol = 0; if(matvol) hasmat |= 1<<m.material; @@ -317,12 +276,10 @@ static int sortdim[3]; static ivec sortorigin; static bool sortedit; -static inline bool vismatcmp(const materialsurface *xm, const materialsurface *ym) -{ +static inline bool vismatcmp(const materialsurface *xm, const materialsurface *ym) { const materialsurface &x = *xm, &y = *ym; int xdim = dimension(x.orient), ydim = dimension(y.orient); - loopi(3) - { + loopi(3) { int dim = sortdim[i], xmin, xmax, ymin, ymax; xmin = xmax = x.o[dim]; if(dim==C[xdim]) xmax += x.csize; @@ -346,8 +303,7 @@ static inline bool vismatcmp(const materialsurface *xm, const materialsurface *y return false; } -void sortmaterials(vector<materialsurface *> &vismats) -{ +void sortmaterials(vector<materialsurface *> &vismats) { sortorigin = ivec(camera1->o); vec dir; vecfromyawpitch(camera1->yaw, camera1->pitch, 1, 0, dir); @@ -355,15 +311,11 @@ void sortmaterials(vector<materialsurface *> &vismats) if(dir[sortdim[2]] > dir[sortdim[1]]) swap(sortdim[2], sortdim[1]); if(dir[sortdim[1]] > dir[sortdim[0]]) swap(sortdim[1], sortdim[0]); if(dir[sortdim[2]] > dir[sortdim[1]]) swap(sortdim[2], sortdim[1]); - - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->matsurfs || va->occluded >= OCCLUDE_BB) continue; - loopi(va->matsurfs) - { + loopi(va->matsurfs) { materialsurface &m = va->matbuf[i]; - if(!editmode || !showmat || drawtex) - { + if(!editmode || !showmat || drawtex) { if(m.visible == MATSURF_EDIT_ONLY) { i += m.skip; continue; } } vismats.add(&m); @@ -373,19 +325,15 @@ void sortmaterials(vector<materialsurface *> &vismats) vismats.sort(vismatcmp); } -void rendermatgrid(vector<materialsurface *> &vismats) -{ +void rendermatgrid(vector<materialsurface *> &vismats) { enablepolygonoffset(GL_POLYGON_OFFSET_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); int lastmat = -1; bvec4 color(0, 0, 0, 0); - loopvrev(vismats) - { + loopvrev(vismats) { materialsurface &m = *vismats[i]; - if(m.material != lastmat) - { - switch(m.material&~MATF_INDEX) - { + if(m.material != lastmat) { + switch(m.material&~MATF_INDEX) { case MAT_CLIP: color = bvec4(85, 0, 0, 255); break; // red case MAT_NOCLIP: color = bvec4( 0, 85, 0, 255); break; // green case MAT_GAMECLIP: color = bvec4(85, 85, 0, 255); break; // yellow @@ -402,31 +350,22 @@ void rendermatgrid(vector<materialsurface *> &vismats) disablepolygonoffset(GL_POLYGON_OFFSET_LINE); } -void rendermaterials() -{ +void rendermaterials() { vector<materialsurface *> vismats; sortmaterials(vismats); if(vismats.empty()) return; - glDisable(GL_CULL_FACE); - int lastorient = -1, lastmat = -1; bool depth = true, blended = false; - GLOBALPARAM(camera, camera1->o); - - if(editmode && showmat && !drawtex) - { + if(editmode && showmat && !drawtex) { glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); glEnable(GL_BLEND); blended = true; bvec4 color(0, 0, 0, 0); - loopv(vismats) - { + loopv(vismats) { const materialsurface &m = *vismats[i]; - if(lastmat!=m.material) - { - switch(m.material&~MATF_INDEX) - { + if(lastmat!=m.material) { + switch(m.material&~MATF_INDEX) { case MAT_CLIP: color = bvec4( 0, 255, 255, 255); break; // red case MAT_NOCLIP: color = bvec4(255, 0, 255, 255); break; // green case MAT_GAMECLIP: color = bvec4( 0, 0, 255, 255); break; // yellow @@ -440,16 +379,13 @@ void rendermaterials() } xtraverts += gle::end(); } - if(lastorient >= 0) if(lastmat&~MATF_INDEX) xtraverts += gle::end(); - if(!depth) glDepthMask(GL_TRUE); if(blended) glDisable(GL_BLEND); extern int wireframe; if(editmode && showmat && !drawtex && !wireframe) rendermatgrid(vismats); - glEnable(GL_CULL_FACE); } diff --git a/src/engine/md3.h b/src/engine/md3.h deleted file mode 100644 index 7296055..0000000 --- a/src/engine/md3.h +++ /dev/null @@ -1,183 +0,0 @@ -struct md3; - -struct md3frame -{ - vec bbmin, bbmax, origin; - float radius; - uchar name[16]; -}; - -struct md3tag -{ - char name[64]; - float translation[3]; - float rotation[3][3]; -}; - -struct md3vertex -{ - short vertex[3]; - short normal; -}; - -struct md3triangle -{ - int vertexindices[3]; -}; - -struct md3header -{ - char id[4]; - int version; - char name[64]; - int flags; - int numframes, numtags, nummeshes, numskins; - int ofs_frames, ofs_tags, ofs_meshes, ofs_eof; // offsets -}; - -struct md3meshheader -{ - char id[4]; - char name[64]; - int flags; - int numframes, numshaders, numvertices, numtriangles; - int ofs_triangles, ofs_shaders, ofs_uv, ofs_vertices, meshsize; // offsets -}; - -struct md3 : vertloader<md3> -{ - md3(const char *name) : vertloader(name) {} - - static const char *formatname() { return "md3"; } - bool flipy() const { return true; } - int type() const { return MDL_MD3; } - - struct md3meshgroup : vertmeshgroup - { - bool load(const char *path) - { - stream *f = openfile(path, "rb"); - if(!f) return false; - md3header header; - f->read(&header, sizeof(md3header)); - lilswap(&header.version, 1); - lilswap(&header.flags, 9); - if(strncmp(header.id, "IDP3", 4) != 0 || header.version != 15) // header check - { - delete f; - conoutf(CON_ERROR, "md3: corrupted header"); - return false; - } - - name = newstring(path); - - numframes = header.numframes; - - int mesh_offset = header.ofs_meshes; - loopi(header.nummeshes) - { - vertmesh &m = *new vertmesh; - m.group = this; - meshes.add(&m); - - md3meshheader mheader; - f->seek(mesh_offset, SEEK_SET); - f->read(&mheader, sizeof(md3meshheader)); - lilswap(&mheader.flags, 10); - - m.name = newstring(mheader.name); - - m.numtris = mheader.numtriangles; - m.tris = new tri[m.numtris]; - f->seek(mesh_offset + mheader.ofs_triangles, SEEK_SET); - loopj(m.numtris) - { - md3triangle tri = { 0 }; - f->read(&tri, sizeof(md3triangle)); // read the triangles - lilswap(tri.vertexindices, 3); - loopk(3) m.tris[j].vert[k] = (ushort)tri.vertexindices[k]; - } - - m.numverts = mheader.numvertices; - m.tcverts = new tcvert[m.numverts]; - f->seek(mesh_offset + mheader.ofs_uv , SEEK_SET); - f->read(m.tcverts, m.numverts*2*sizeof(float)); // read the UV data - lilswap(&m.tcverts[0].tc.x, 2*m.numverts); - - m.verts = new vert[numframes*m.numverts]; - f->seek(mesh_offset + mheader.ofs_vertices, SEEK_SET); - loopj(numframes*m.numverts) - { - md3vertex v = { {0}, 0 }; - f->read(&v, sizeof(md3vertex)); // read the vertices - lilswap(v.vertex, 4); - - m.verts[j].pos = vec(v.vertex[0]/64.0f, -v.vertex[1]/64.0f, v.vertex[2]/64.0f); - - float lng = (v.normal&0xFF)*2*M_PI/255.0f; // decode vertex normals - float lat = ((v.normal>>8)&0xFF)*2*M_PI/255.0f; - m.verts[j].norm = vec(cosf(lat)*sinf(lng), -sinf(lat)*sinf(lng), cosf(lng)); - } - - mesh_offset += mheader.meshsize; - } - - numtags = header.numtags; - if(numtags) - { - tags = new tag[numframes*numtags]; - f->seek(header.ofs_tags, SEEK_SET); - md3tag tag; - - loopi(header.numframes*header.numtags) - { - f->read(&tag, sizeof(md3tag)); - lilswap(tag.translation, 12); - if(tag.name[0] && i<header.numtags) tags[i].name = newstring(tag.name); - matrix4x3 &m = tags[i].transform; - tag.translation[1] *= -1; - // undo the -y - loopj(3) tag.rotation[1][j] *= -1; - // then restore it - loopj(3) tag.rotation[j][1] *= -1; - m.a = vec(tag.rotation[0]); - m.b = vec(tag.rotation[1]); - m.c = vec(tag.rotation[2]); - m.d = vec(tag.translation); - } - } - - delete f; - return true; - } - }; - - meshgroup *loadmeshes(const char *name, va_list args) - { - md3meshgroup *group = new md3meshgroup; - if(!group->load(name)) { delete group; return NULL; } - return group; - } - - bool loaddefaultparts() - { - const char *pname = parentdir(name); - part &mdl = addpart(); - defformatstring(name1, "packages/models/%s/tris.md3", name); - mdl.meshes = sharemeshes(path(name1)); - if(!mdl.meshes) - { - defformatstring(name2, "packages/models/%s/tris.md3", pname); // try md3 in parent folder (vert sharing) - mdl.meshes = sharemeshes(path(name2)); - if(!mdl.meshes) return false; - } - Texture *tex, *masks; - loadskin(name, pname, tex, masks); - mdl.initskins(tex, masks); - if(tex==notexture) conoutf(CON_ERROR, "could not load model skin for %s", name1); - return true; - } -}; - -vertcommands<md3> md3commands; - diff --git a/src/engine/md5.h b/src/engine/md5.h index d948ccf..e508cb3 100644 --- a/src/engine/md5.h +++ b/src/engine/md5.h @@ -1,66 +1,48 @@ struct md5; -struct md5joint -{ +struct md5joint { vec pos; quat orient; }; -struct md5weight -{ +struct md5weight { int joint; float bias; vec pos; }; -struct md5vert -{ +struct md5vert { vec2 tc; ushort start, count; }; -struct md5hierarchy -{ +struct md5hierarchy { string name; int parent, flags, start; }; -struct md5 : skelloader<md5> -{ +struct md5 : skelloader<md5> { md5(const char *name) : skelloader(name) {} - static const char *formatname() { return "md5"; } int type() const { return MDL_MD5; } - - struct md5mesh : skelmesh - { + struct md5mesh : skelmesh { md5weight *weightinfo; int numweights; md5vert *vertinfo; - - md5mesh() : weightinfo(NULL), numweights(0), vertinfo(NULL) - { + md5mesh() : weightinfo(NULL), numweights(0), vertinfo(NULL) { } - - ~md5mesh() - { + ~md5mesh() { cleanup(); } - - void cleanup() - { + void cleanup() { DELETEA(weightinfo); DELETEA(vertinfo); } - - void buildverts(vector<md5joint> &joints) - { - loopi(numverts) - { + void buildverts(vector<md5joint> &joints) { + loopi(numverts) { md5vert &v = vertinfo[i]; vec pos(0, 0, 0); - loopk(v.count) - { + loopk(v.count) { md5weight &w = weightinfo[v.start+k]; md5joint &j = joints[w.joint]; vec wpos = j.orient.rotate(w.pos); @@ -71,11 +53,9 @@ struct md5 : skelloader<md5> vert &vv = verts[i]; vv.pos = pos; vv.tc = v.tc; - blendcombo c; int sorted = 0; - loopj(v.count) - { + loopj(v.count) { md5weight &w = weightinfo[v.start+j]; sorted = c.addweight(sorted, w.bias, w.joint); } @@ -83,29 +63,22 @@ struct md5 : skelloader<md5> vv.blend = addblendcombo(c); } } - - void load(stream *f, char *buf, size_t bufsize) - { + void load(stream *f, char *buf, size_t bufsize) { md5weight w; md5vert v; tri t; int index; - - while(f->getline(buf, bufsize) && buf[0]!='}') - { - if(strstr(buf, "// meshes:")) - { + while(f->getline(buf, bufsize) && buf[0]!='}') { + if(strstr(buf, "// meshes:")) { char *start = strchr(buf, ':')+1; if(*start==' ') start++; char *end = start + strlen(start)-1; while(end >= start && isspace(*end)) end--; name = newstring(start, end+1-start); } - else if(strstr(buf, "shader")) - { + else if(strstr(buf, "shader")) { char *start = strchr(buf, '"'), *end = start ? strchr(start+1, '"') : NULL; - if(start && end) - { + if(start && end) { char *texname = newstring(start+1, end-(start+1)); part *p = loading->parts.last(); p->initskins(notexture, notexture, group->meshes.length()); @@ -114,86 +87,66 @@ struct md5 : skelloader<md5> delete[] texname; } } - else if(sscanf(buf, " numverts %d", &numverts)==1) - { + else if(sscanf(buf, " numverts %d", &numverts)==1) { numverts = max(numverts, 0); - if(numverts) - { + if(numverts) { vertinfo = new md5vert[numverts]; verts = new vert[numverts]; } } - else if(sscanf(buf, " numtris %d", &numtris)==1) - { + else if(sscanf(buf, " numtris %d", &numtris)==1) { numtris = max(numtris, 0); if(numtris) tris = new tri[numtris]; } - else if(sscanf(buf, " numweights %d", &numweights)==1) - { + else if(sscanf(buf, " numweights %d", &numweights)==1) { numweights = max(numweights, 0); if(numweights) weightinfo = new md5weight[numweights]; } - else if(sscanf(buf, " vert %d ( %f %f ) %hu %hu", &index, &v.tc.x, &v.tc.y, &v.start, &v.count)==5) - { + else if(sscanf(buf, " vert %d ( %f %f ) %hu %hu", &index, &v.tc.x, &v.tc.y, &v.start, &v.count)==5) { if(index>=0 && index<numverts) vertinfo[index] = v; } - else if(sscanf(buf, " tri %d %hu %hu %hu", &index, &t.vert[0], &t.vert[1], &t.vert[2])==4) - { + else if(sscanf(buf, " tri %d %hu %hu %hu", &index, &t.vert[0], &t.vert[1], &t.vert[2])==4) { if(index>=0 && index<numtris) tris[index] = t; } - else if(sscanf(buf, " weight %d %d %f ( %f %f %f ) ", &index, &w.joint, &w.bias, &w.pos.x, &w.pos.y, &w.pos.z)==6) - { + else if(sscanf(buf, " weight %d %d %f ( %f %f %f ) ", &index, &w.joint, &w.bias, &w.pos.x, &w.pos.y, &w.pos.z)==6) { w.pos.y = -w.pos.y; if(index>=0 && index<numweights) weightinfo[index] = w; } } } }; - - struct md5meshgroup : skelmeshgroup - { - md5meshgroup() - { + struct md5meshgroup : skelmeshgroup { + md5meshgroup() { } - - bool loadmesh(const char *filename, float smooth) - { + bool loadmesh(const char *filename, float smooth) { stream *f = openfile(filename, "r"); if(!f) return false; - char buf[512]; vector<md5joint> basejoints; - while(f->getline(buf, sizeof(buf))) - { + while(f->getline(buf, sizeof(buf))) { int tmp; - if(sscanf(buf, " MD5Version %d", &tmp)==1) - { + if(sscanf(buf, " MD5Version %d", &tmp)==1) { if(tmp!=10) { delete f; return false; } } - else if(sscanf(buf, " numJoints %d", &tmp)==1) - { + else if(sscanf(buf, " numJoints %d", &tmp)==1) { if(tmp<1) { delete f; return false; } if(skel->numbones>0) continue; skel->numbones = tmp; skel->bones = new boneinfo[skel->numbones]; } - else if(sscanf(buf, " numMeshes %d", &tmp)==1) - { + else if(sscanf(buf, " numMeshes %d", &tmp)==1) { if(tmp<1) { delete f; return false; } } - else if(strstr(buf, "joints {")) - { + else if(strstr(buf, "joints {")) { string name; int parent; md5joint j; - while(f->getline(buf, sizeof(buf)) && buf[0]!='}') - { + while(f->getline(buf, sizeof(buf)) && buf[0]!='}') { char *curbuf = buf, *curname = name; bool allowspace = false; while(*curbuf && isspace(*curbuf)) curbuf++; if(*curbuf == '"') { curbuf++; allowspace = true; } - while(*curbuf && curname < &name[sizeof(name)-1]) - { + while(*curbuf && curname < &name[sizeof(name)-1]) { char c = *curbuf++; if(c == '"') break; if(isspace(c) && !allowspace) break; @@ -202,8 +155,7 @@ struct md5 : skelloader<md5> *curname = '\0'; if(sscanf(curbuf, " %d ( %f %f %f ) ( %f %f %f )", &parent, &j.pos.x, &j.pos.y, &j.pos.z, - &j.orient.x, &j.orient.y, &j.orient.z)==7) - { + &j.orient.x, &j.orient.y, &j.orient.z)==7) { j.pos.y = -j.pos.y; j.orient.x = -j.orient.x; j.orient.z = -j.orient.z; @@ -219,101 +171,77 @@ struct md5 : skelloader<md5> } if(basejoints.length()!=skel->numbones) { delete f; return false; } } - else if(strstr(buf, "mesh {")) - { + else if(strstr(buf, "mesh {")) { md5mesh *m = new md5mesh; m->group = this; meshes.add(m); m->load(f, buf, sizeof(buf)); - if(!m->numtris || !m->numverts) - { + if(!m->numtris || !m->numverts) { conoutf(CON_WARN, "empty mesh in %s", filename); meshes.removeobj(m); delete m; } } } - - if(skel->shared <= 1) - { + if(skel->shared <= 1) { skel->linkchildren(); - loopv(basejoints) - { + loopv(basejoints) { boneinfo &b = skel->bones[i]; b.base = dualquat(basejoints[i].orient, basejoints[i].pos); (b.invbase = b.base).invert(); } } - - loopv(meshes) - { + loopv(meshes) { md5mesh &m = *(md5mesh *)meshes[i]; m.buildverts(basejoints); if(smooth <= 1) m.smoothnorms(smooth); else m.buildnorms(); m.cleanup(); } - sortblendcombos(); - delete f; return true; } - - skelanimspec *loadanim(const char *filename) - { + skelanimspec *loadanim(const char *filename) { skelanimspec *sa = skel->findskelanim(filename); if(sa) return sa; - stream *f = openfile(filename, "r"); if(!f) return NULL; - vector<md5hierarchy> hierarchy; vector<md5joint> basejoints; int animdatalen = 0, animframes = 0; float *animdata = NULL; dualquat *animbones = NULL; char buf[512]; - while(f->getline(buf, sizeof(buf))) - { + while(f->getline(buf, sizeof(buf))) { int tmp; - if(sscanf(buf, " MD5Version %d", &tmp)==1) - { + if(sscanf(buf, " MD5Version %d", &tmp)==1) { if(tmp!=10) { delete f; return NULL; } } - else if(sscanf(buf, " numJoints %d", &tmp)==1) - { + else if(sscanf(buf, " numJoints %d", &tmp)==1) { if(tmp!=skel->numbones) { delete f; return NULL; } } - else if(sscanf(buf, " numFrames %d", &animframes)==1) - { + else if(sscanf(buf, " numFrames %d", &animframes)==1) { if(animframes<1) { delete f; return NULL; } } else if(sscanf(buf, " frameRate %d", &tmp)==1); - else if(sscanf(buf, " numAnimatedComponents %d", &animdatalen)==1) - { + else if(sscanf(buf, " numAnimatedComponents %d", &animdatalen)==1) { if(animdatalen>0) animdata = new float[animdatalen]; } - else if(strstr(buf, "bounds {")) - { + else if(strstr(buf, "bounds {")) { while(f->getline(buf, sizeof(buf)) && buf[0]!='}'); } - else if(strstr(buf, "hierarchy {")) - { - while(f->getline(buf, sizeof(buf)) && buf[0]!='}') - { + else if(strstr(buf, "hierarchy {")) { + while(f->getline(buf, sizeof(buf)) && buf[0]!='}') { md5hierarchy h; if(sscanf(buf, " %100s %d %d %d", h.name, &h.parent, &h.flags, &h.start)==4) hierarchy.add(h); } } - else if(strstr(buf, "baseframe {")) - { - while(f->getline(buf, sizeof(buf)) && buf[0]!='}') - { + else if(strstr(buf, "baseframe {")) { + while(f->getline(buf, sizeof(buf)) && buf[0]!='}') { md5joint j; - if(sscanf(buf, " ( %f %f %f ) ( %f %f %f )", &j.pos.x, &j.pos.y, &j.pos.z, &j.orient.x, &j.orient.y, &j.orient.z)==6) - { + if(sscanf(buf, " ( %f %f %f ) ( %f %f %f )", &j.pos.x, &j.pos.y, &j.pos.z, &j.orient.x, &j.orient.y, &j.orient.z)==6) { j.pos.y = -j.pos.y; j.orient.x = -j.orient.x; j.orient.z = -j.orient.z; @@ -323,37 +251,29 @@ struct md5 : skelloader<md5> } if(basejoints.length()!=skel->numbones) { delete f; if(animdata) delete[] animdata; return NULL; } animbones = new dualquat[(skel->numframes+animframes)*skel->numbones]; - if(skel->framebones) - { + if(skel->framebones) { memcpy(animbones, skel->framebones, skel->numframes*skel->numbones*sizeof(dualquat)); delete[] skel->framebones; } skel->framebones = animbones; animbones += skel->numframes*skel->numbones; - sa = &skel->addskelanim(filename); sa->frame = skel->numframes; sa->range = animframes; - skel->numframes += animframes; } - else if(sscanf(buf, " frame %d", &tmp)==1) - { - for(int numdata = 0; f->getline(buf, sizeof(buf)) && buf[0]!='}';) - { - for(char *src = buf, *next = src; numdata < animdatalen; numdata++, src = next) - { + else if(sscanf(buf, " frame %d", &tmp)==1) { + for(int numdata = 0; f->getline(buf, sizeof(buf)) && buf[0]!='}';) { + for(char *src = buf, *next = src; numdata < animdatalen; numdata++, src = next) { animdata[numdata] = strtod(src, &next); if(next <= src) break; } } dualquat *frame = &animbones[tmp*skel->numbones]; - loopv(basejoints) - { + loopv(basejoints) { md5hierarchy &h = hierarchy[i]; md5joint j = basejoints[i]; - if(h.start < animdatalen && h.flags) - { + if(h.start < animdatalen && h.flags) { float *jdata = &animdata[h.start]; if(h.flags&1) j.pos.x = *jdata++; if(h.flags&2) j.pos.y = -*jdata++; @@ -371,33 +291,23 @@ struct md5 : skelloader<md5> } } } - if(animdata) delete[] animdata; delete f; - return sa; } - - bool load(const char *meshfile, float smooth) - { + bool load(const char *meshfile, float smooth) { name = newstring(meshfile); - if(!loadmesh(meshfile, smooth)) return false; - return true; } }; - - meshgroup *loadmeshes(const char *name, va_list args) - { + meshgroup *loadmeshes(const char *name, va_list args) { md5meshgroup *group = new md5meshgroup; group->shareskeleton(va_arg(args, char *)); if(!group->load(name, va_arg(args, double))) { delete group; return NULL; } return group; } - - bool loaddefaultparts() - { + bool loaddefaultparts() { skelpart &mdl = addpart(); mdl.pitchscale = mdl.pitchoffset = mdl.pitchmin = mdl.pitchmax = 0; adjustments.setsize(0); diff --git a/src/engine/menus.cpp b/src/engine/menus.cpp index 805a79b..e2bd266 100644 --- a/src/engine/menus.cpp +++ b/src/engine/menus.cpp @@ -12,17 +12,13 @@ static g3d_gui *cgui = NULL; VAR(guitabnum, 1, 0, 0); -struct menu : g3d_callback -{ +struct menu : g3d_callback { char *name, *header; uint *contents, *init, *onclear; bool showtab, keeptab; int menutab; - menu() : name(NULL), header(NULL), contents(NULL), init(NULL), onclear(NULL), showtab(true), keeptab(false), menutab(1) {} - - void gui(g3d_gui &g, bool firstpass) - { + void gui(g3d_gui &g, bool firstpass) { cgui = &g; guitabnum = menutab; cgui->start(menustart, 0.03f, showtab ? &menutab : NULL); @@ -32,75 +28,57 @@ struct menu : g3d_callback cgui = NULL; guitabnum = 0; } - - virtual void clear() - { + virtual void clear() { if(onclear) { freecode(onclear); onclear = NULL; } } }; -struct delayedupdate -{ - enum - { +struct delayedupdate { + enum { INT, FLOAT, STRING, ACTION } type; ident *id; - union - { + union { int i; float f; char *s; } val; delayedupdate() : type(ACTION), id(NULL) { val.s = NULL; } ~delayedupdate() { if(type == STRING || type == ACTION) DELETEA(val.s); } - void schedule(const char *s) { type = ACTION; val.s = newstring(s); } void schedule(ident *var, int i) { type = INT; id = var; val.i = i; } void schedule(ident *var, float f) { type = FLOAT; id = var; val.f = f; } void schedule(ident *var, char *s) { type = STRING; id = var; val.s = newstring(s); } - - int getint() const - { - switch(type) - { + int getint() const { + switch(type) { case INT: return val.i; case FLOAT: return int(val.f); case STRING: return int(strtol(val.s, NULL, 0)); default: return 0; } } - - float getfloat() const - { - switch(type) - { + float getfloat() const { + switch(type) { case INT: return float(val.i); case FLOAT: return val.f; case STRING: return float(parsefloat(val.s)); default: return 0; } } - - const char *getstring() const - { - switch(type) - { + const char *getstring() const { + switch(type) { case INT: return intstr(val.i); case FLOAT: return intstr(int(floor(val.f))); case STRING: return val.s; default: return ""; } } - - void run() - { + void run() { if(type == ACTION) { if(val.s) execute(val.s); } - else if(id) switch(id->type) - { + else if(id) switch(id->type) { case ID_VAR: setvarchecked(id, getint()); break; case ID_FVAR: setfvarchecked(id, getfloat()); break; case ID_SVAR: setsvarchecked(id, getstring()); break; @@ -117,8 +95,7 @@ static bool shouldclearmenu = true, clearlater = false; VARP(menudistance, 16, 40, 256); VARP(menuautoclose, 32, 120, 4096); -vec menuinfrontofplayer() -{ +vec menuinfrontofplayer() { vec dir; vecfromyawpitch(camera1->yaw, 0, 1, 0, dir); dir.mul(menudistance).add(camera1->o); @@ -126,48 +103,40 @@ vec menuinfrontofplayer() return dir; } -void popgui() -{ +void popgui() { menu *m = guistack.pop(); m->clear(); } -void removegui(menu *m) -{ - loopv(guistack) if(guistack[i]==m) - { +void removegui(menu *m) { + loopv(guistack) if(guistack[i]==m) { guistack.remove(i); m->clear(); return; } } -void pushgui(menu *m, int pos = -1) -{ - if(guistack.empty()) - { +void pushgui(menu *m, int pos = -1) { + if(guistack.empty()) { menupos = menuinfrontofplayer(); g3d_resetcursor(); } if(pos < 0) guistack.add(m); else guistack.insert(pos, m); - if(pos < 0 || pos==guistack.length()-1) - { + if(pos < 0 || pos==guistack.length()-1) { if(!m->keeptab) m->menutab = 1; menustart = totalmillis; } if(m->init) execute(m->init); } -void restoregui(int pos) -{ +void restoregui(int pos) { int clear = guistack.length()-pos-1; loopi(clear) popgui(); menustart = totalmillis; } -void showgui(const char *name) -{ +void showgui(const char *name) { menu *m = guis.access(name); if(!m) return; int pos = guistack.find(m); @@ -175,17 +144,14 @@ void showgui(const char *name) else restoregui(pos); } -void hidegui(const char *name) -{ +void hidegui(const char *name) { menu *m = guis.access(name); if(m) removegui(m); } -int cleargui(int n) -{ +int cleargui(int n) { int clear = guistack.length(); - if(mainmenu && !isconnected(true) && clear > 0 && guistack[0]->name && !strcmp(guistack[0]->name, "main")) - { + if(mainmenu && !isconnected(true) && clear > 0 && guistack[0]->name && !strcmp(guistack[0]->name, "main")) { clear--; if(!clear) return 1; } @@ -195,14 +161,12 @@ int cleargui(int n) return clear; } -void clearguis(int level = -1) -{ +void clearguis(int level = -1) { if(level < 0) level = guistack.length(); - loopvrev(guistack) - { + loopvrev(guistack) { menu *m = guistack[i]; if(m->onclear) - { + { uint *action = m->onclear; m->onclear = NULL; execute(action); @@ -212,32 +176,28 @@ void clearguis(int level = -1) cleargui(level); } -void guionclear(char *action) -{ +void guionclear(char *action) { if(guistack.empty()) return; menu *m = guistack.last(); if(m->onclear) { freecode(m->onclear); m->onclear = NULL; } if(action[0]) m->onclear = compilecode(action); } -void guistayopen(uint *contents) -{ +void guistayopen(uint *contents) { bool oldclearmenu = shouldclearmenu; shouldclearmenu = false; execute(contents); shouldclearmenu = oldclearmenu; } -void guinoautotab(uint *contents) -{ +void guinoautotab(uint *contents) { if(!cgui) return; bool oldval = cgui->allowautotab(false); execute(contents); cgui->allowautotab(oldval); } -void guimerge(uint *contents) -{ +void guimerge(uint *contents) { if(!cgui) return; bool oldval = cgui->mergehits(true); execute(contents); @@ -245,114 +205,92 @@ void guimerge(uint *contents) } //@DOC name and icon are optional -void guibutton(char *name, char *action, char *icon) -{ +void guibutton(char *name, char *action, char *icon) { if(!cgui) return; bool hideicon = !strcmp(icon, "0"); int ret = cgui->button(name, GUI_BUTTON_COLOR, hideicon ? NULL : (icon[0] ? icon : (strstr(action, "showgui") ? "menu" : "action"))); - if(ret&G3D_UP) - { + if(ret&G3D_UP) { updatelater.add().schedule(action[0] ? action : name); if(shouldclearmenu) clearlater = true; } - else if(ret&G3D_ROLLOVER) - { + else if(ret&G3D_ROLLOVER) { alias("guirollovername", name); alias("guirolloveraction", action); } } -void guiimage(char *path, char *action, float *scale, int *overlaid, char *alt, char *title) -{ +void guiimage(char *path, char *action, float *scale, int *overlaid, char *alt, char *title) { if(!cgui) return; Texture *t = textureload(path, 0, true, false); - if(t==notexture) - { + if(t==notexture) { if(alt[0]) t = textureload(alt, 0, true, false); if(t==notexture) return; } int ret = cgui->image(t, *scale, *overlaid!=0 ? title : NULL); - if(ret&G3D_UP) - { - if(*action) - { + if(ret&G3D_UP) { + if(*action) { updatelater.add().schedule(action); if(shouldclearmenu) clearlater = true; } } - else if(ret&G3D_ROLLOVER) - { + else if(ret&G3D_ROLLOVER) { alias("guirolloverimgpath", path); alias("guirolloverimgaction", action); } } -void guicolor(int *color) -{ - if(cgui) - { +void guicolor(int *color) { + if(cgui) { defformatstring(desc, "0x%06X", *color); cgui->text(desc, *color, NULL); } } -void guitextbox(char *text, int *width, int *height, int *color) -{ +void guitextbox(char *text, int *width, int *height, int *color) { if(cgui && text[0]) cgui->textbox(text, *width ? *width : 12, *height ? *height : 1, *color ? *color : 0xFFFFFF); } -void guitext(char *name, char *icon) -{ +void guitext(char *name, char *icon) { bool hideicon = !strcmp(icon, "0"); if(cgui) cgui->text(name, !hideicon && icon[0] ? GUI_BUTTON_COLOR : GUI_TEXT_COLOR, hideicon ? NULL : (icon[0] ? icon : "info")); } -void guititle(char *name) -{ +void guititle(char *name) { if(cgui) cgui->title(name, GUI_TITLE_COLOR); } -void guitab(char *name) -{ +void guitab(char *name) { if(cgui) cgui->tab(name, GUI_TITLE_COLOR); } -void guibar() -{ +void guibar() { if(cgui) cgui->separator(); } -void guistrut(float *strut, int *alt) -{ - if(cgui) - { +void guistrut(float *strut, int *alt) { + if(cgui) { if(*alt) cgui->strut(*strut); else cgui->space(*strut); } } -void guispring(int *weight) -{ +void guispring(int *weight) { if(cgui) cgui->spring(max(*weight, 1)); } -void guicolumn(int *col) -{ +void guicolumn(int *col) { if(cgui) cgui->column(*col); } -template<class T> static void updateval(char *var, T val, char *onchange) -{ +template<class T> static void updateval(char *var, T val, char *onchange) { ident *id = writeident(var); updatelater.add().schedule(id, val); if(onchange[0]) updatelater.add().schedule(onchange); } -static int getval(char *var) -{ +static int getval(char *var) { ident *id = readident(var); if(!id) return 0; - switch(id->type) - { + switch(id->type) { case ID_VAR: return *id->storage.i; case ID_FVAR: return int(*id->storage.f); case ID_SVAR: return parseint(*id->storage.s); @@ -361,12 +299,10 @@ static int getval(char *var) } } -static float getfval(char *var) -{ +static float getfval(char *var) { ident *id = readident(var); if(!id) return 0; - switch(id->type) - { + switch(id->type) { case ID_VAR: return *id->storage.i; case ID_FVAR: return *id->storage.f; case ID_SVAR: return parsefloat(*id->storage.s); @@ -375,12 +311,10 @@ static float getfval(char *var) } } -static const char *getsval(char *var) -{ +static const char *getsval(char *var) { ident *id = readident(var); if(!id) return ""; - switch(id->type) - { + switch(id->type) { case ID_VAR: return intstr(*id->storage.i); case ID_FVAR: return floatstr(*id->storage.f); case ID_SVAR: return *id->storage.s; @@ -389,21 +323,18 @@ static const char *getsval(char *var) } } -void guislider(char *var, int *min, int *max, char *onchange) -{ +void guislider(char *var, int *min, int *max, char *onchange) { if(!cgui) return; int oldval = getval(var), val = oldval, vmin = *max > INT_MIN ? *min : getvarmin(var), vmax = *max > INT_MIN ? *max : getvarmax(var); cgui->slider(val, vmin, vmax, GUI_TITLE_COLOR); if(val != oldval) updateval(var, val, onchange); } -void guilistslider(char *var, char *list, char *onchange) -{ +void guilistslider(char *var, char *list, char *onchange) { if(!cgui) return; vector<int> vals; list += strspn(list, "\n\t "); - while(*list) - { + while(*list) { vals.add(parseint(list)); list += strcspn(list, "\n\t \0"); list += strspn(list, "\n\t "); @@ -415,13 +346,11 @@ void guilistslider(char *var, char *list, char *onchange) if(offset != oldoffset) updateval(var, vals[offset], onchange); } -void guinameslider(char *var, char *names, char *list, char *onchange) -{ +void guinameslider(char *var, char *names, char *list, char *onchange) { if(!cgui) return; vector<int> vals; list += strspn(list, "\n\t "); - while(*list) - { + while(*list) { vals.add(parseint(list)); list += strcspn(list, "\n\t \0"); list += strspn(list, "\n\t "); @@ -435,37 +364,30 @@ void guinameslider(char *var, char *names, char *list, char *onchange) delete[] label; } -void guicheckbox(char *name, char *var, float *on, float *off, char *onchange) -{ +void guicheckbox(char *name, char *var, float *on, float *off, char *onchange) { bool enabled = getfval(var)!=*off; - if(cgui && cgui->button(name, GUI_BUTTON_COLOR, enabled ? "checkbox_on" : "checkbox_off")&G3D_UP) - { + if(cgui && cgui->button(name, GUI_BUTTON_COLOR, enabled ? "checkbox_on" : "checkbox_off")&G3D_UP) { updateval(var, enabled ? *off : (*on || *off ? *on : 1.0f), onchange); } } -void guiradio(char *name, char *var, float *n, char *onchange) -{ +void guiradio(char *name, char *var, float *n, char *onchange) { bool enabled = getfval(var)==*n; - if(cgui && cgui->button(name, GUI_BUTTON_COLOR, enabled ? "radio_on" : "radio_off")&G3D_UP) - { + if(cgui && cgui->button(name, GUI_BUTTON_COLOR, enabled ? "radio_on" : "radio_off")&G3D_UP) { if(!enabled) updateval(var, *n, onchange); } } -void guibitfield(char *name, char *var, int *mask, char *onchange) -{ +void guibitfield(char *name, char *var, int *mask, char *onchange) { int val = getval(var); bool enabled = (val & *mask) != 0; - if(cgui && cgui->button(name, GUI_BUTTON_COLOR, enabled ? "checkbox_on" : "checkbox_off")&G3D_UP) - { + if(cgui && cgui->button(name, GUI_BUTTON_COLOR, enabled ? "checkbox_on" : "checkbox_off")&G3D_UP) { updateval(var, enabled ? val & ~*mask : val | *mask, onchange); } } //-ve length indicates a wrapped text field of any (approx 260 chars) length, |length| is the field width -void guifield(char *var, int *maxlength, char *onchange) -{ +void guifield(char *var, int *maxlength, char *onchange) { if(!cgui) return; const char *initval = getsval(var); char *result = cgui->field(var, GUI_BUTTON_COLOR, *maxlength ? *maxlength : 12, 0, initval); @@ -473,16 +395,14 @@ void guifield(char *var, int *maxlength, char *onchange) } //-ve maxlength indicates a wrapped text field of any (approx 260 chars) length, |maxlength| is the field width -void guieditor(char *name, int *maxlength, int *height, int *mode) -{ +void guieditor(char *name, int *maxlength, int *height, int *mode) { if(!cgui) return; cgui->field(name, GUI_BUTTON_COLOR, *maxlength ? *maxlength : 12, *height, NULL, *mode<=0 ? EDITORFOREVER : *mode); //returns a non-NULL pointer (the currentline) when the user commits, could then manipulate via text* commands } //-ve length indicates a wrapped text field of any (approx 260 chars) length, |length| is the field width -void guikeyfield(char *var, int *maxlength, char *onchange) -{ +void guikeyfield(char *var, int *maxlength, char *onchange) { if(!cgui) return; const char *initval = getsval(var); char *result = cgui->keyfield(var, GUI_BUTTON_COLOR, *maxlength ? *maxlength : -8, 0, initval); @@ -492,16 +412,14 @@ void guikeyfield(char *var, int *maxlength, char *onchange) //use text<action> to do more... -void guilist(uint *contents) -{ +void guilist(uint *contents) { if(!cgui) return; cgui->pushlist(); execute(contents); cgui->poplist(); } -void guialign(int *align, uint *contents) -{ +void guialign(int *align, uint *contents) { if(!cgui) return; cgui->pushlist(); if(*align >= 0) cgui->spring(); @@ -510,38 +428,31 @@ void guialign(int *align, uint *contents) cgui->poplist(); } -void newgui(char *name, char *contents, char *header, char *init) -{ +void newgui(char *name, char *contents, char *header, char *init) { menu *m = guis.access(name); - if(!m) - { + if(!m) { name = newstring(name); m = &guis[name]; m->name = name; } - else - { + else { DELETEA(m->header); freecode(m->contents); freecode(m->init); } - if(header && header[0]) - { + if(header && header[0]) { char *end = NULL; int val = strtol(header, &end, 0); - if(end && !*end) - { + if(end && !*end) { m->header = NULL; m->showtab = val != 0; } - else - { + else { m->header = newstring(header); m->showtab = true; } } - else - { + else { m->header = NULL; m->showtab = true; } @@ -551,14 +462,11 @@ void newgui(char *name, char *contents, char *header, char *init) menu *guiserversmenu = NULL; -void guiservers(uint *header, int *pagemin, int *pagemax) -{ +void guiservers(uint *header, int *pagemin, int *pagemax) { extern const char *showservers(g3d_gui *cgui, uint *header, int pagemin, int pagemax); - if(cgui) - { + if(cgui) { const char *command = showservers(cgui, header, *pagemin, *pagemax > 0 ? *pagemax : INT_MAX); - if(command) - { + if(command) { updatelater.add().schedule(command); if(shouldclearmenu) clearlater = true; guiserversmenu = clearlater || guistack.empty() ? NULL : guistack.last(); @@ -566,10 +474,8 @@ void guiservers(uint *header, int *pagemin, int *pagemax) } } -void notifywelcome() -{ - if(guiserversmenu) - { +void notifywelcome() { + if(guiserversmenu) { if(guistack.length() && guistack.last() == guiserversmenu) clearguis(); guiserversmenu = NULL; } @@ -608,14 +514,11 @@ COMMAND(guieditor, "siii"); COMMAND(guicolor, "i"); COMMAND(guitextbox, "siii"); -void guiplayerpreview(int *model, int *team, int *weap, char *action, float *scale, int *overlaid, char *title) -{ +void guiplayerpreview(int *model, int *team, int *weap, char *action, float *scale, int *overlaid, char *title) { if(!cgui) return; int ret = cgui->playerpreview(*model, *team, *weap, *scale, *overlaid!=0 ? title : NULL); - if(ret&G3D_UP) - { - if(*action) - { + if(ret&G3D_UP) { + if(*action) { updatelater.add().schedule(action); if(shouldclearmenu) clearlater = true; } @@ -623,84 +526,68 @@ void guiplayerpreview(int *model, int *team, int *weap, char *action, float *sca } COMMAND(guiplayerpreview, "iiisfis"); -void guimodelpreview(char *model, char *animspec, char *action, float *scale, int *overlaid, char *title, int *throttle) -{ +void guimodelpreview(char *model, char *animspec, char *action, float *scale, int *overlaid, char *title, int *throttle) { if(!cgui) return; int anim = ANIM_ALL; - if(animspec[0]) - { - if(isdigit(animspec[0])) - { + if(animspec[0]) { + if(isdigit(animspec[0])) { anim = parseint(animspec); if(anim >= 0) anim %= ANIM_INDEX; else anim = ANIM_ALL; } - else - { + else { vector<int> anims; findanims(animspec, anims); if(anims.length()) anim = anims[0]; } } int ret = cgui->modelpreview(model, anim|ANIM_LOOP, *scale, *overlaid!=0 ? title : NULL, *throttle!=0); - if(ret&G3D_UP) - { - if(*action) - { + if(ret&G3D_UP) { + if(*action) { updatelater.add().schedule(action); if(shouldclearmenu) clearlater = true; } } - else if(ret&G3D_ROLLOVER) - { + else if(ret&G3D_ROLLOVER) { alias("guirolloverpreviewname", model); alias("guirolloverpreviewaction", action); } } COMMAND(guimodelpreview, "sssfisi"); -void guiprefabpreview(char *prefab, int *color, char *action, float *scale, int *overlaid, char *title, int *throttle) -{ +void guiprefabpreview(char *prefab, int *color, char *action, float *scale, int *overlaid, char *title, int *throttle) { if(!cgui) return; int ret = cgui->prefabpreview(prefab, vec::hexcolor(*color), *scale, *overlaid!=0 ? title : NULL, *throttle!=0); - if(ret&G3D_UP) - { - if(*action) - { + if(ret&G3D_UP) { + if(*action) { updatelater.add().schedule(action); if(shouldclearmenu) clearlater = true; } } - else if(ret&G3D_ROLLOVER) - { + else if(ret&G3D_ROLLOVER) { alias("guirolloverpreviewname", prefab); alias("guirolloverpreviewaction", action); } } COMMAND(guiprefabpreview, "sisfisi"); -struct change -{ +struct change { int type; const char *desc; - change() {} change(int type, const char *desc) : type(type), desc(desc) {} }; static vector<change> needsapply; -static struct applymenu : menu -{ - void gui(g3d_gui &g, bool firstpass) - { +static struct applymenu : menu { + void gui(g3d_gui &g, bool firstpass) { if(guistack.empty()) return; g.start(menustart, 0.03f); g.text("the following settings have changed:", GUI_TEXT_COLOR, "info"); loopv(needsapply) g.text(needsapply[i].desc, GUI_TEXT_COLOR, "info"); g.separator(); g.text("apply changes now?", GUI_TEXT_COLOR, "info"); - if(g.button("yes", GUI_BUTTON_COLOR, "action")&G3D_UP) - { + if(g.button("yes", GUI_BUTTON_COLOR, "action")&G3D_UP) { int changetypes = 0; loopv(needsapply) changetypes |= needsapply[i].type; if(changetypes&CHANGE_GFX) updatelater.add().schedule("resetgl"); @@ -711,9 +598,7 @@ static struct applymenu : menu clearlater = true; g.end(); } - - void clear() - { + void clear() { menu::clear(); needsapply.shrink(0); } @@ -723,8 +608,7 @@ VARP(applydialog, 0, 1, 1); static bool processingmenu = false; -void addchange(const char *desc, int type) -{ +void addchange(const char *desc, int type) { if(!applydialog) return; loopv(needsapply) if(!strcmp(needsapply[i].desc, desc)) return; needsapply.add(change(type, desc)); @@ -732,12 +616,9 @@ void addchange(const char *desc, int type) pushgui(&applymenu, processingmenu ? max(guistack.length()-1, 0) : -1); } -void clearchanges(int type) -{ - loopv(needsapply) - { - if(needsapply[i].type&type) - { +void clearchanges(int type) { + loopv(needsapply) { + if(needsapply[i].type&type) { needsapply[i].type &= ~type; if(!needsapply[i].type) needsapply.remove(i--); } @@ -745,14 +626,12 @@ void clearchanges(int type) if(needsapply.empty()) removegui(&applymenu); } -void menuprocess() -{ +void menuprocess() { processingmenu = true; int wasmain = mainmenu, level = guistack.length(); loopv(updatelater) updatelater[i].run(); updatelater.shrink(0); - if(wasmain > mainmenu || clearlater) - { + if(wasmain > mainmenu || clearlater) { if(wasmain > mainmenu || level==guistack.length()) clearguis(level); clearlater = false; } @@ -762,19 +641,15 @@ void menuprocess() VAR(mainmenu, 1, 1, 0); -void clearmainmenu() -{ - if(mainmenu && isconnected()) - { +void clearmainmenu() { + if(mainmenu && isconnected()) { mainmenu = 0; if(!processingmenu) cleargui(); } } -void g3d_mainmenu() -{ - if(!guistack.empty()) - { +void g3d_mainmenu() { + if(!guistack.empty()) { extern int usegui2d; if(!mainmenu && !usegui2d && camera1->o.dist(menupos) > menuautoclose) cleargui(); else g3d_addgui(guistack.last(), menupos, GUI_2D | GUI_FOLLOW); diff --git a/src/engine/model.h b/src/engine/model.h index 82aea40..16f1629 100644 --- a/src/engine/model.h +++ b/src/engine/model.h @@ -1,7 +1,6 @@ -enum { MDL_MD3, MDL_MD5, MDL_IQM, NUMMODELTYPES }; +enum { MDL_MD5, MDL_IQM, NUMMODELTYPES }; -struct model -{ +struct model { char *name; float spinyaw, spinpitch, offsetyaw, offsetpitch; bool collide, ellipsecollide, shadow, alphadepth, depthoffset; @@ -11,7 +10,6 @@ struct model vec bbcenter, bbradius, bbextend, collidecenter, collideradius; float rejectradius, eyeheight, collidexyradius, collideheight; int batch; - model(const char *name) : name(name ? newstring(name) : NULL), spinyaw(0), spinpitch(0), offsetyaw(0), offsetpitch(0), collide(true), ellipsecollide(false), shadow(true), alphadepth(true), depthoffset(false), scale(1.0f), translate(0, 0, 0), bih(0), bbcenter(0, 0, 0), bbradius(-1, -1, -1), bbextend(0, 0, 0), collidecenter(0, 0, 0), collideradius(-1, -1, -1), rejectradius(-1), eyeheight(0.9f), collidexyradius(0), collideheight(0), batch(-1) {} virtual ~model() { DELETEA(name); DELETEP(bih); } virtual void calcbb(vec ¢er, vec &radius) = 0; @@ -20,46 +18,35 @@ struct model virtual int type() const = 0; virtual BIH *setBIH() { return 0; } virtual bool skeletal() const { return false; } - - virtual void setshader(Shader *shader) {} - virtual void setspec(float spec) {} - virtual void setambient(float ambient) {} - virtual void setalphatest(float alpha) {} - virtual void setalphablend(bool blend) {} - virtual void setfullbright(float fullbright) {} - virtual void setcullface(bool cullface) {} - + virtual void setshader(Shader *) {} + virtual void setspec(float) {} + virtual void setambient(float) {} + virtual void setalphatest(float) {} + virtual void setalphablend(bool) {} + virtual void setfullbright(float) {} + virtual void setcullface(bool) {} virtual void preloadBIH() { if(!bih) setBIH(); } - virtual void preloadshaders(bool force = false) {} + virtual void preloadshaders() {} virtual void preloadmeshes() {} virtual void cleanup() {} - virtual void startrender() {} virtual void endrender() {} - - void boundbox(vec ¢er, vec &radius) - { - if(bbradius.x < 0) - { + void boundbox(vec ¢er, vec &radius) { + if(bbradius.x < 0) { calcbb(bbcenter, bbradius); bbradius.add(bbextend); } center = bbcenter; radius = bbradius; } - - float collisionbox(vec ¢er, vec &radius) - { - if(collideradius.x < 0) - { + float collisionbox(vec ¢er, vec &radius) { + if(collideradius.x < 0) { boundbox(collidecenter, collideradius); - if(collidexyradius) - { + if(collidexyradius) { collidecenter.x = collidecenter.y = 0; collideradius.x = collideradius.y = collidexyradius; } - if(collideheight) - { + if(collideheight) { collidecenter.z = collideradius.z = collideheight/2; } rejectradius = vec(collidecenter).abs().add(collideradius).magnitude(); @@ -68,16 +55,12 @@ struct model radius = collideradius; return rejectradius; } - - float boundsphere(vec ¢er) - { + float boundsphere(vec ¢er) { vec radius; boundbox(center, radius); return radius.magnitude(); } - - float above() - { + float above() { vec center, radius; boundbox(center, radius); return center.z+radius.z; diff --git a/src/engine/mpr.h b/src/engine/mpr.h index 6288e4f..6c20869 100644 --- a/src/engine/mpr.h +++ b/src/engine/mpr.h @@ -1,41 +1,28 @@ // This code is based off the Minkowski Portal Refinement algorithm by Gary Snethen in XenoCollide & Game Programming Gems 7. -namespace mpr -{ - struct CubePlanes - { +namespace mpr { + struct CubePlanes { const clipplanes &p; - CubePlanes(const clipplanes &p) : p(p) {} - vec center() const { return p.o; } - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { int besti = 7; float bestd = n.dot(p.v[7]); - loopi(7) - { + loopi(7) { float d = n.dot(p.v[i]); if(d > bestd) { besti = i; bestd = d; } } return p.v[besti]; } }; - - struct SolidCube - { + struct SolidCube { vec o; int size; - SolidCube(float x, float y, float z, int size) : o(x, y, z), size(size) {} SolidCube(const vec &o, int size) : o(o), size(size) {} SolidCube(const ivec &o, int size) : o(o), size(size) {} - vec center() const { return vec(o).add(size/2); } - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { vec p(o); if(n.x > 0) p.x += size; if(n.y > 0) p.y += size; @@ -43,36 +30,24 @@ namespace mpr return p; } }; - - struct Ent - { + struct Ent { physent *ent; - Ent(physent *ent) : ent(ent) {} - vec center() const { return vec(ent->o.x, ent->o.y, ent->o.z + (ent->aboveeye - ent->eyeheight)/2); } }; - - struct EntOBB : Ent - { + struct EntOBB : Ent { matrix3 orient; float zmargin; - - EntOBB(physent *ent, float zmargin = 0) : Ent(ent), zmargin(zmargin) - { + EntOBB(physent *ent, float zmargin = 0) : Ent(ent), zmargin(zmargin) { orient.setyaw(ent->yaw*RAD); } - vec center() const { return vec(ent->o.x, ent->o.y, ent->o.z + (ent->aboveeye - ent->eyeheight - zmargin)/2); } - - vec contactface(const vec &wn, const vec &wdir) const - { + vec contactface(const vec &wn, const vec &wdir) const { vec n = orient.transform(wn).div(vec(ent->xradius, ent->yradius, (ent->aboveeye + ent->eyeheight + zmargin)/2)), dir = orient.transform(wdir), an(fabs(n.x), fabs(n.y), dir.z ? fabs(n.z) : 0), fn(0, 0, 0); - if(an.x > an.y) - { + if(an.x > an.y) { if(an.x > an.z) fn.x = n.x*dir.x < 0 ? (n.x > 0 ? 1 : -1) : 0; else if(an.z > 0) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0; } @@ -80,28 +55,20 @@ namespace mpr else if(an.z > 0) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0; return orient.transposedtransform(fn); } - - vec localsupportpoint(const vec &ln) const - { + vec localsupportpoint(const vec &ln) const { return vec(ln.x > 0 ? ent->xradius : -ent->xradius, ln.y > 0 ? ent->yradius : -ent->yradius, ln.z > 0 ? ent->aboveeye : -ent->eyeheight - zmargin); } - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { return orient.transposedtransform(localsupportpoint(orient.transform(n))).add(ent->o); } - - float supportcoordneg(float a, float b, float c) const - { + float supportcoordneg(float a, float b, float c) const { return localsupportpoint(vec(-a, -b, -c)).dot(vec(a, b, c)); } - float supportcoord(float a, float b, float c) const - { + float supportcoord(float a, float b, float c) const { return localsupportpoint(vec(a, b, c)).dot(vec(a, b, c)); } - float left() const { return supportcoordneg(orient.a.x, orient.b.x, orient.c.x) + ent->o.x; } float right() const { return supportcoord(orient.a.x, orient.b.x, orient.c.x) + ent->o.x; } float back() const { return supportcoordneg(orient.a.y, orient.b.y, orient.c.y) + ent->o.y; } @@ -109,11 +76,8 @@ namespace mpr float bottom() const { return ent->o.z - ent->eyeheight - zmargin; } float top() const { return ent->o.z + ent->aboveeye; } }; - - struct EntFuzzy : Ent - { + struct EntFuzzy : Ent { EntFuzzy(physent *ent) : Ent(ent) {} - float left() const { return ent->o.x - ent->radius; } float right() const { return ent->o.x + ent->radius; } float back() const { return ent->o.y - ent->radius; } @@ -121,38 +85,27 @@ namespace mpr float bottom() const { return ent->o.z - ent->eyeheight; } float top() const { return ent->o.z + ent->aboveeye; } }; - - struct EntCylinder : EntFuzzy - { + struct EntCylinder : EntFuzzy { float zmargin; - EntCylinder(physent *ent, float zmargin = 0) : EntFuzzy(ent), zmargin(zmargin) {} - vec center() const { return vec(ent->o.x, ent->o.y, ent->o.z + (ent->aboveeye - ent->eyeheight - zmargin)/2); } - float bottom() const { return ent->o.z - ent->eyeheight - zmargin; } - - vec contactface(const vec &n, const vec &dir) const - { + vec contactface(const vec &n, const vec &dir) const { float dxy = n.dot2(n)/(ent->radius*ent->radius), dz = n.z*n.z*4/(ent->aboveeye + ent->eyeheight + zmargin); vec fn(0, 0, 0); if(dz > dxy && dir.z) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0; - else if(n.dot2(dir) < 0) - { + else if(n.dot2(dir) < 0) { fn.x = n.x; fn.y = n.y; fn.normalize(); } return fn; } - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { vec p(ent->o); if(n.z > 0) p.z += ent->aboveeye; else p.z -= ent->eyeheight + zmargin; - if(n.x || n.y) - { + if(n.x || n.y) { float r = ent->radius / n.magnitude2(); p.x += n.x*r; p.y += n.y*r; @@ -160,13 +113,9 @@ namespace mpr return p; } }; - - struct EntCapsule : EntFuzzy - { + struct EntCapsule : EntFuzzy { EntCapsule(physent *ent) : EntFuzzy(ent) {} - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { vec p(ent->o); if(n.z > 0) p.z += ent->aboveeye - ent->radius; else p.z -= ent->eyeheight - ent->radius; @@ -174,13 +123,9 @@ namespace mpr return p; } }; - - struct EntEllipsoid : EntFuzzy - { + struct EntEllipsoid : EntFuzzy { EntEllipsoid(physent *ent) : EntFuzzy(ent) {} - - vec supportpoint(const vec &dir) const - { + vec supportpoint(const vec &dir) const { vec p(ent->o), n = vec(dir).normalize(); p.x += ent->radius*n.x; p.y += ent->radius*n.y; @@ -188,34 +133,24 @@ namespace mpr return p; } }; - - struct Model - { + struct Model { vec o, radius; matrix3 orient; - - Model(const vec &ent, const vec ¢er, const vec &radius, int yaw) : o(ent), radius(radius) - { + Model(const vec &ent, const vec ¢er, const vec &radius, int yaw) : o(ent), radius(radius) { orient.setyaw(yaw*RAD); o.add(orient.transposedtransform(center)); } - vec center() const { return o; } }; - - struct ModelOBB : Model - { + struct ModelOBB : Model { ModelOBB(const vec &ent, const vec ¢er, const vec &radius, int yaw) : - Model(ent, center, radius, yaw) - {} - - vec contactface(const vec &wn, const vec &wdir) const - { + Model(ent, center, radius, yaw) { + } + vec contactface(const vec &wn, const vec &wdir) const { vec n = orient.transform(wn).div(radius), dir = orient.transform(wdir), an(fabs(n.x), fabs(n.y), dir.z ? fabs(n.z) : 0), fn(0, 0, 0); - if(an.x > an.y) - { + if(an.x > an.y) { if(an.x > an.z) fn.x = n.x*dir.x < 0 ? (n.x > 0 ? 1 : -1) : 0; else if(an.z > 0) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0; } @@ -223,9 +158,7 @@ namespace mpr else if(an.z > 0) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0; return orient.transposedtransform(fn); } - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { vec ln = orient.transform(n), p(0, 0, 0); if(ln.x > 0) p.x += radius.x; else p.x -= radius.x; @@ -236,35 +169,27 @@ namespace mpr return orient.transposedtransform(p).add(o); } }; - - struct ModelEllipse : Model - { + struct ModelEllipse : Model { ModelEllipse(const vec &ent, const vec ¢er, const vec &radius, int yaw) : - Model(ent, center, radius, yaw) - {} - - vec contactface(const vec &wn, const vec &wdir) const - { + Model(ent, center, radius, yaw) { + } + vec contactface(const vec &wn, const vec &wdir) const { vec n = orient.transform(wn).div(radius), dir = orient.transform(wdir); float dxy = n.dot2(n), dz = n.z*n.z; vec fn(0, 0, 0); if(dz > dxy && dir.z) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0; - else if(n.dot2(dir) < 0) - { + else if(n.dot2(dir) < 0) { fn.x = n.x*radius.y; fn.y = n.y*radius.x; fn.normalize(); } return orient.transposedtransform(fn); } - - vec supportpoint(const vec &n) const - { + vec supportpoint(const vec &n) const { vec ln = orient.transform(n), p(0, 0, 0); if(ln.z > 0) p.z += radius.z; else p.z -= radius.z; - if(ln.x || ln.y) - { + if(ln.x || ln.y) { float r = ln.magnitude2(); p.x += ln.x*radius.x/r; p.y += ln.y*radius.y/r; @@ -272,83 +197,60 @@ namespace mpr return orient.transposedtransform(p).add(o); } }; - const float boundarytolerance = 1e-3f; - template<class T, class U> - bool collide(const T &p1, const U &p2) - { + bool collide(const T &p1, const U &p2) { // v0 = center of Minkowski difference vec v0 = p2.center().sub(p1.center()); if(v0.iszero()) return true; // v0 and origin overlap ==> hit - // v1 = support in direction of origin vec n = vec(v0).neg(); vec v1 = p2.supportpoint(n).sub(p1.supportpoint(vec(n).neg())); if(v1.dot(n) <= 0) return false; // origin outside v1 support plane ==> miss - // v2 = support perpendicular to plane containing origin, v0 and v1 n.cross(v1, v0); if(n.iszero()) return true; // v0, v1 and origin colinear (and origin inside v1 support plane) == > hit vec v2 = p2.supportpoint(n).sub(p1.supportpoint(vec(n).neg())); if(v2.dot(n) <= 0) return false; // origin outside v2 support plane ==> miss - // v3 = support perpendicular to plane containing v0, v1 and v2 n.cross(v0, v1, v2); - // If the origin is on the - side of the plane, reverse the direction of the plane - if(n.dot(v0) > 0) - { + if(n.dot(v0) > 0) { swap(v1, v2); n.neg(); } - /// // Phase One: Find a valid portal - - loopi(100) - { + loopi(100) { // Obtain the next support point vec v3 = p2.supportpoint(n).sub(p1.supportpoint(vec(n).neg())); if(v3.dot(n) <= 0) return false; // origin outside v3 support plane ==> miss - // If origin is outside (v1,v0,v3), then portal is invalid -- eliminate v2 and find new support outside face vec v3xv0; v3xv0.cross(v3, v0); - if(v1.dot(v3xv0) < 0) - { + if(v1.dot(v3xv0) < 0) { v2 = v3; n.cross(v0, v1, v3); continue; } - // If origin is outside (v3,v0,v2), then portal is invalid -- eliminate v1 and find new support outside face - if(v2.dot(v3xv0) > 0) - { + if(v2.dot(v3xv0) > 0) { v1 = v3; n.cross(v0, v3, v2); continue; } - /// // Phase Two: Refine the portal - - for(int j = 0;; j++) - { + for(int j = 0;; j++) { // Compute outward facing normal of the portal n.cross(v1, v2, v3); - // If the origin is inside the portal, we have a hit if(n.dot(v1) >= 0) return true; - n.normalize(); - // Find the support point in the direction of the portal's normal vec v4 = p2.supportpoint(n).sub(p1.supportpoint(vec(n).neg())); - // If the origin is outside the support plane or the boundary is thin enough, we have a miss if(v4.dot(n) <= 0 || vec(v4).sub(v3).dot(n) <= boundarytolerance || j > 100) return false; - // Test origin against the three planes that separate the new portal candidates: (v1,v4,v0) (v2,v4,v0) (v3,v4,v0) // Note: We're taking advantage of the triple product identities here as an optimization // (v1 % v4) * v0 == v1 * (v4 % v0) > 0 if origin inside (v1, v4, v0) @@ -356,13 +258,11 @@ namespace mpr // (v3 % v4) * v0 == v3 * (v4 % v0) > 0 if origin inside (v3, v4, v0) vec v4xv0; v4xv0.cross(v4, v0); - if(v1.dot(v4xv0) > 0) - { + if(v1.dot(v4xv0) > 0) { if(v2.dot(v4xv0) > 0) v1 = v4; // Inside v1 & inside v2 ==> eliminate v1 else v3 = v4; // Inside v1 & outside v2 ==> eliminate v3 } - else - { + else { if(v3.dot(v4xv0) > 0) v2 = v4; // Outside v1 & inside v3 ==> eliminate v2 else v1 = v4; // Outside v1 & outside v3 ==> eliminate v1 } @@ -370,33 +270,26 @@ namespace mpr } return false; } - template<class T, class U> - bool collide(const T &p1, const U &p2, vec *contactnormal, vec *contactpoint1, vec *contactpoint2) - { + bool collide(const T &p1, const U &p2, vec *contactnormal, vec *contactpoint1, vec *contactpoint2) { // v0 = center of Minkowski sum vec v01 = p1.center(); vec v02 = p2.center(); vec v0 = vec(v02).sub(v01); - // Avoid case where centers overlap -- any direction is fine in this case if(v0.iszero()) v0 = vec(0, 0, 1e-5f); - // v1 = support in direction of origin vec n = vec(v0).neg(); vec v11 = p1.supportpoint(vec(n).neg()); vec v12 = p2.supportpoint(n); vec v1 = vec(v12).sub(v11); - if(v1.dot(n) <= 0) - { + if(v1.dot(n) <= 0) { if(contactnormal) *contactnormal = n; return false; } - // v2 - support perpendicular to v1,v0 n.cross(v1, v0); - if(n.iszero()) - { + if(n.iszero()) { n = vec(v1).sub(v0); n.normalize(); if(contactnormal) *contactnormal = n; @@ -407,97 +300,74 @@ namespace mpr vec v21 = p1.supportpoint(vec(n).neg()); vec v22 = p2.supportpoint(n); vec v2 = vec(v22).sub(v21); - if(v2.dot(n) <= 0) - { + if(v2.dot(n) <= 0) { if(contactnormal) *contactnormal = n; return false; } - // Determine whether origin is on + or - side of plane (v1,v0,v2) n.cross(v0, v1, v2); ASSERT( !n.iszero() ); // If the origin is on the - side of the plane, reverse the direction of the plane - if(n.dot(v0) > 0) - { + if(n.dot(v0) > 0) { swap(v1, v2); swap(v11, v21); swap(v12, v22); n.neg(); } - /// // Phase One: Identify a portal - - loopi(100) - { + loopi(100) { // Obtain the support point in a direction perpendicular to the existing plane // Note: This point is guaranteed to lie off the plane vec v31 = p1.supportpoint(vec(n).neg()); vec v32 = p2.supportpoint(n); vec v3 = vec(v32).sub(v31); - if(v3.dot(n) <= 0) - { + if(v3.dot(n) <= 0) { if(contactnormal) *contactnormal = n; return false; } - // If origin is outside (v1,v0,v3), then eliminate v2 and loop vec v3xv0; v3xv0.cross(v3, v0); - if(v1.dot(v3xv0) < 0) - { + if(v1.dot(v3xv0) < 0) { v2 = v3; v21 = v31; v22 = v32; n.cross(v0, v1, v3); continue; } - // If origin is outside (v3,v0,v2), then eliminate v1 and loop - if(v2.dot(v3xv0) > 0) - { + if(v2.dot(v3xv0) > 0) { v1 = v3; v11 = v31; v12 = v32; n.cross(v0, v3, v2); continue; } - bool hit = false; - /// // Phase Two: Refine the portal - // We are now inside of a wedge... - for(int j = 0;; j++) - { + for(int j = 0;; j++) { // Compute normal of the wedge face n.cross(v1, v2, v3); - // Can this happen??? Can it be handled more cleanly? - if(n.iszero()) - { + if(n.iszero()) { ASSERT(0); return true; } - n.normalize(); - // If the origin is inside the wedge, we have a hit - if(n.dot(v1) >= 0 && !hit) - { + if(n.dot(v1) >= 0 && !hit) { if(contactnormal) *contactnormal = n; - // Compute the barycentric coordinates of the origin - if(contactpoint1 || contactpoint2) - { + if(contactpoint1 || contactpoint2) { float b0 = v3.scalartriple(v1, v2), b1 = v0.scalartriple(v3, v2), b2 = v3.scalartriple(v0, v1), b3 = v0.scalartriple(v2, v1), sum = b0 + b1 + b2 + b3; - if(sum <= 0) - { + if(sum <= 0) { b0 = 0; b1 = n.scalartriple(v2, v3); b2 = n.scalartriple(v3, v1); @@ -509,23 +379,18 @@ namespace mpr if(contactpoint2) *contactpoint2 = (vec(v02).mul(b0).add(vec(v12).mul(b1)).add(vec(v22).mul(b2)).add(vec(v32).mul(b3))).mul(1.0f/sum); } - // HIT!!! hit = true; } - // Find the support point in the direction of the wedge face vec v41 = p1.supportpoint(vec(n).neg()); vec v42 = p2.supportpoint(n); vec v4 = vec(v42).sub(v41); - // If the boundary is thin enough or the origin is outside the support plane for the newly discovered vertex, then we can terminate - if(v4.dot(n) <= 0 || vec(v4).sub(v3).dot(n) <= boundarytolerance || j > 100) - { + if(v4.dot(n) <= 0 || vec(v4).sub(v3).dot(n) <= boundarytolerance || j > 100) { if(contactnormal) *contactnormal = n; return hit; } - // Test origin against the three planes that separate the new portal candidates: (v1,v4,v0) (v2,v4,v0) (v3,v4,v0) // Note: We're taking advantage of the triple product identities here as an optimization // (v1 % v4) * v0 == v1 * (v4 % v0) > 0 if origin inside (v1, v4, v0) @@ -533,34 +398,28 @@ namespace mpr // (v3 % v4) * v0 == v3 * (v4 % v0) > 0 if origin inside (v3, v4, v0) vec v4xv0; v4xv0.cross(v4, v0); - if(v1.dot(v4xv0) > 0) // Compute the tetrahedron dividing face d1 = (v4,v0,v1) - { - if(v2.dot(v4xv0) > 0) // Compute the tetrahedron dividing face d2 = (v4,v0,v2) - { + if(v1.dot(v4xv0) > 0) { // Compute the tetrahedron dividing face d1 = (v4,v0,v1) { + if(v2.dot(v4xv0) > 0) { // Compute the tetrahedron dividing face d2 = (v4,v0,v2) { // Inside d1 & inside d2 ==> eliminate v1 v1 = v4; v11 = v41; v12 = v42; } - else - { + else { // Inside d1 & outside d2 ==> eliminate v3 v3 = v4; v31 = v41; v32 = v42; } } - else - { - if(v3.dot(v4xv0) > 0) // Compute the tetrahedron dividing face d3 = (v4,v0,v3) - { + else { + if(v3.dot(v4xv0) > 0) { // Compute the tetrahedron dividing face d3 = (v4,v0,v3) { // Outside d1 & inside d3 ==> eliminate v2 v2 = v4; v21 = v41; v22 = v42; } - else - { + else { // Outside d1 & outside d3 ==> eliminate v1 v1 = v4; v11 = v41; @@ -572,4 +431,3 @@ namespace mpr return false; } } - diff --git a/src/engine/normal.cpp b/src/engine/normal.cpp index cba6777..64c21c6 100644 --- a/src/engine/normal.cpp +++ b/src/engine/normal.cpp @@ -1,24 +1,20 @@ #include "engine.h" -struct normalgroup -{ +struct normalgroup { vec pos; int flat, normals, tnormals; - normalgroup() : flat(0), normals(-1), tnormals(-1) {} normalgroup(const vec &pos) : pos(pos), flat(0), normals(-1), tnormals(-1) {} }; static inline bool htcmp(const vec &v, const normalgroup &n) { return v == n.pos; } -struct normal -{ +struct normal { int next; vec surface; }; -struct tnormal -{ +struct tnormal { int next; float offset; int normals[2]; @@ -34,8 +30,7 @@ VARR(lerpangle, 0, 44, 180); static float lerpthreshold = 0; static bool usetnormals = true; -static int addnormal(const vec &key, const vec &surface) -{ +static int addnormal(const vec &key, const vec &surface) { normalgroup &g = normalgroups.access(key, key); normal &n = normals.add(); n.next = g.normals; @@ -43,8 +38,7 @@ static int addnormal(const vec &key, const vec &surface) return g.normals = normals.length()-1; } -static void addtnormal(const vec &key, float offset, int normal1, int normal2, normalgroup *group1, normalgroup *group2) -{ +static void addtnormal(const vec &key, float offset, int normal1, int normal2, normalgroup *group1, normalgroup *group2) { normalgroup &g = normalgroups.access(key, key); tnormal &n = tnormals.add(); n.next = g.tnormals; @@ -56,15 +50,13 @@ static void addtnormal(const vec &key, float offset, int normal1, int normal2, n g.tnormals = tnormals.length()-1; } -static int addnormal(const vec &key, int axis) -{ +static int addnormal(const vec &key, int axis) { normalgroup &g = normalgroups.access(key, key); g.flat += 1<<(4*axis); return axis - 6; } -static inline void findnormal(const normalgroup &g, const vec &surface, vec &v) -{ +static inline void findnormal(const normalgroup &g, const vec &surface, vec &v) { v = vec(0, 0, 0); int total = 0; if(surface.x >= lerpthreshold) { int n = (g.flat>>4)&0xF; v.x += n; total += n; } @@ -73,11 +65,9 @@ static inline void findnormal(const normalgroup &g, const vec &surface, vec &v) else if(surface.y <= -lerpthreshold) { int n = (g.flat>>8)&0xF; v.y -= n; total += n; } if(surface.z >= lerpthreshold) { int n = (g.flat>>20)&0xF; v.z += n; total += n; } else if(surface.z <= -lerpthreshold) { int n = (g.flat>>16)&0xF; v.z -= n; total += n; } - for(int cur = g.normals; cur >= 0;) - { + for(int cur = g.normals; cur >= 0;) { normal &o = normals[cur]; - if(o.surface.dot(surface) >= lerpthreshold) - { + if(o.surface.dot(surface) >= lerpthreshold) { v.add(o.surface); total++; } @@ -87,12 +77,10 @@ static inline void findnormal(const normalgroup &g, const vec &surface, vec &v) else if(!total) v = surface; } -static inline bool findtnormal(const normalgroup &g, const vec &surface, vec &v) -{ +static inline bool findtnormal(const normalgroup &g, const vec &surface, vec &v) { float bestangle = lerpthreshold; tnormal *bestnorm = NULL; - for(int cur = g.tnormals; cur >= 0;) - { + for(int cur = g.tnormals; cur >= 0;) { tnormal &o = tnormals[cur]; static const vec flats[6] = { vec(-1, 0, 0), vec(1, 0, 0), vec(0, -1, 0), vec(0, 1, 0), vec(0, 0, -1), vec(0, 0, 1) }; vec n1 = o.normals[0] < 0 ? flats[o.normals[0]+6] : normals[o.normals[0]].surface, @@ -100,8 +88,7 @@ static inline bool findtnormal(const normalgroup &g, const vec &surface, vec &v) nt; nt.lerp(n1, n2, o.offset).normalize(); float tangle = nt.dot(surface); - if(tangle >= bestangle) - { + if(tangle >= bestangle) { bestangle = tangle; bestnorm = &o; } @@ -115,8 +102,7 @@ static inline bool findtnormal(const normalgroup &g, const vec &surface, vec &v) return true; } -void findnormal(const vec &key, const vec &surface, vec &v) -{ +void findnormal(const vec &key, const vec &surface, vec &v) { const normalgroup *g = normalgroups.access(key); if(!g) v = surface; else if(g->tnormals < 0 || !findtnormal(*g, surface, v)) @@ -128,48 +114,38 @@ VARR(lerpsubdivsize, 4, 4, 128); static uint progress = 0; -void show_addnormals_progress() -{ +void show_addnormals_progress() { float bar1 = float(progress) / float(allocnodes); renderprogress(bar1, "computing normals..."); } -void addnormals(cube &c, const ivec &o, int size) -{ +void addnormals(cube &c, const ivec &o, int size) { CHECK_CALCLIGHT_PROGRESS(return, show_addnormals_progress); - - if(c.children) - { + if(c.children) { progress++; size >>= 1; loopi(8) addnormals(c.children[i], ivec(i, o, size), size); return; } else if(isempty(c)) return; - vec pos[MAXFACEVERTS]; int norms[MAXFACEVERTS]; int tj = usetnormals && c.ext ? c.ext->tjoints : -1, vis; - loopi(6) if((vis = visibletris(c, i, o, size))) - { + loopi(6) if((vis = visibletris(c, i, o, size))) { CHECK_CALCLIGHT_PROGRESS(return, show_addnormals_progress); - vec planes[2]; int numverts = c.ext ? c.ext->surfaces[i].numverts&MAXFACEVERTS : 0, convex = 0, numplanes = 0; - if(numverts) - { + if(numverts) { vertinfo *verts = c.ext->verts() + c.ext->surfaces[i].verts; vec vo(ivec(o).mask(~0xFFF)); - loopj(numverts) - { + loopj(numverts) { vertinfo &v = verts[j]; pos[j] = vec(v.x, v.y, v.z).mul(1.0f/8).add(vo); } if(!(c.merged&(1<<i)) && !flataxisface(c, i)) convex = faceconvexity(verts, numverts, size); } else if(c.merged&(1<<i)) continue; - else - { + else { ivec v[4]; genfaceverts(c, i, v); if(!flataxisface(c, i)) convex = faceconvexity(v); @@ -180,27 +156,21 @@ void addnormals(cube &c, const ivec &o, int size) pos[numverts++] = vec(v[order+2]).mul(size/8.0f).add(vo); if(vis&2) pos[numverts++] = vec(v[(order+3)&3]).mul(size/8.0f).add(vo); } - - if(!flataxisface(c, i)) - { + if(!flataxisface(c, i)) { planes[numplanes++].cross(pos[0], pos[1], pos[2]).normalize(); if(convex) planes[numplanes++].cross(pos[0], pos[2], pos[3]).normalize(); } - if(!numplanes) loopk(numverts) norms[k] = addnormal(pos[k], i); else if(numplanes==1) loopk(numverts) norms[k] = addnormal(pos[k], planes[0]); - else - { + else { vec avg = vec(planes[0]).add(planes[1]).normalize(); norms[0] = addnormal(pos[0], avg); norms[1] = addnormal(pos[1], planes[0]); norms[2] = addnormal(pos[2], avg); for(int k = 3; k < numverts; k++) norms[k] = addnormal(pos[k], planes[1]); } - while(tj >= 0 && tjoints[tj].edge < i*(MAXFACEVERTS+1)) tj = tjoints[tj].next; - while(tj >= 0 && tjoints[tj].edge < (i+1)*(MAXFACEVERTS+1)) - { + while(tj >= 0 && tjoints[tj].edge < (i+1)*(MAXFACEVERTS+1)) { int edge = tjoints[tj].edge, e1 = edge%(MAXFACEVERTS+1), e2 = (e1+1)%numverts; const vec &v1 = pos[e1], &v2 = pos[e2]; ivec d(vec(v2).sub(v1).mul(8)); @@ -212,9 +182,7 @@ void addnormals(cube &c, const ivec &o, int size) offset2 = (int(v2[axis]*8) - origin) / d[axis]; vec o = vec(v1).sub(vec(d).mul(offset1/8.0f)), n1, n2; float doffset = 1.0f / (offset2 - offset1); - - while(tj >= 0) - { + while(tj >= 0) { tjoint &t = tjoints[tj]; if(t.edge != edge) break; float offset = (t.offset - offset1) * doffset; @@ -226,8 +194,7 @@ void addnormals(cube &c, const ivec &o, int size) } } -void calcnormals(bool lerptjoints) -{ +void calcnormals(bool lerptjoints) { if(!lerpangle) return; usetnormals = lerptjoints; if(usetnormals) findtjoints(); @@ -236,20 +203,16 @@ void calcnormals(bool lerptjoints) loopi(8) addnormals(worldroot[i], ivec(i, ivec(0, 0, 0), worldsize/2), worldsize/2); } -void clearnormals() -{ +void clearnormals() { normalgroups.clear(); normals.setsize(0); tnormals.setsize(0); } -void calclerpverts(const vec2 *c, const vec *n, lerpvert *lv, int &numv) -{ +void calclerpverts(const vec2 *c, const vec *n, lerpvert *lv, int &numv) { int i = 0; - loopj(numv) - { - if(j) - { + loopj(numv) { + if(j) { if(c[j] == c[j-1] && n[j] == n[j-1]) continue; if(j == numv-1 && c[j] == c[0] && n[j] == n[0]) continue; } @@ -260,14 +223,11 @@ void calclerpverts(const vec2 *c, const vec *n, lerpvert *lv, int &numv) numv = i; } -void setlerpstep(float v, lerpbounds &bounds) -{ - if(bounds.min->tc.y + 1 > bounds.max->tc.y) - { +void setlerpstep(float v, lerpbounds &bounds) { + if(bounds.min->tc.y + 1 > bounds.max->tc.y) { bounds.nstep = vec(0, 0, 0); bounds.normal = bounds.min->normal; - if(bounds.min->normal != bounds.max->normal) - { + if(bounds.min->normal != bounds.max->normal) { bounds.normal.add(bounds.max->normal); bounds.normal.normalize(); } @@ -275,70 +235,55 @@ void setlerpstep(float v, lerpbounds &bounds) bounds.u = bounds.min->tc.x; return; } - bounds.nstep = bounds.max->normal; bounds.nstep.sub(bounds.min->normal); bounds.nstep.div(bounds.max->tc.y-bounds.min->tc.y); - bounds.normal = bounds.nstep; bounds.normal.mul(v - bounds.min->tc.y); bounds.normal.add(bounds.min->normal); - bounds.ustep = (bounds.max->tc.x-bounds.min->tc.x) / (bounds.max->tc.y-bounds.min->tc.y); bounds.u = bounds.ustep * (v-bounds.min->tc.y) + bounds.min->tc.x; } -void initlerpbounds(float u, float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end) -{ +void initlerpbounds(float u, float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end) { const lerpvert *first = &lv[0], *second = NULL; - loopi(numv-1) - { + loopi(numv-1) { if(lv[i+1].tc.y < first->tc.y) { second = first; first = &lv[i+1]; } else if(!second || lv[i+1].tc.y < second->tc.y) second = &lv[i+1]; } - if(int(first->tc.y) < int(second->tc.y)) { start.min = end.min = first; } else if(first->tc.x > second->tc.x) { start.min = second; end.min = first; } else { start.min = first; end.min = second; } - - if((lv[1].tc.x - lv->tc.x)*(lv[2].tc.y - lv->tc.y) > (lv[1].tc.y - lv->tc.y)*(lv[2].tc.x - lv->tc.x)) - { + if((lv[1].tc.x - lv->tc.x)*(lv[2].tc.y - lv->tc.y) > (lv[1].tc.y - lv->tc.y)*(lv[2].tc.x - lv->tc.x)) { start.winding = end.winding = 1; start.max = (start.min == lv ? &lv[numv-1] : start.min-1); end.max = (end.min == &lv[numv-1] ? lv : end.min+1); } - else - { + else { start.winding = end.winding = -1; start.max = (start.min == &lv[numv-1] ? lv : start.min+1); end.max = (end.min == lv ? &lv[numv-1] : end.min-1); } - setlerpstep(v, start); setlerpstep(v, end); } -void updatelerpbounds(float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end) -{ - if(v >= start.max->tc.y) - { +void updatelerpbounds(float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end) { + if(v >= start.max->tc.y) { const lerpvert *next = start.winding > 0 ? (start.max == lv ? &lv[numv-1] : start.max-1) : (start.max == &lv[numv-1] ? lv : start.max+1); - if(next->tc.y > start.max->tc.y) - { + if(next->tc.y > start.max->tc.y) { start.min = start.max; start.max = next; setlerpstep(v, start); } } - if(v >= end.max->tc.y) - { + if(v >= end.max->tc.y) { const lerpvert *next = end.winding > 0 ? (end.max == &lv[numv-1] ? lv : end.max+1) : (end.max == lv ? &lv[numv-1] : end.max-1); - if(next->tc.y > end.max->tc.y) - { + if(next->tc.y > end.max->tc.y) { end.min = end.max; end.max = next; setlerpstep(v, end); @@ -346,36 +291,28 @@ void updatelerpbounds(float v, const lerpvert *lv, int numv, lerpbounds &start, } } -void lerpnormal(float u, float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end, vec &normal, vec &nstep) -{ +void lerpnormal(float u, float v, const lerpvert *lv, int numv, lerpbounds &start, lerpbounds &end, vec &normal, vec &nstep) { updatelerpbounds(v, lv, numv, start, end); - - if(start.u + 1 > end.u) - { + if(start.u + 1 > end.u) { nstep = vec(0, 0, 0); normal = start.normal; normal.add(end.normal); normal.normalize(); } - else - { + else { vec nstart(start.normal), nend(end.normal); nstart.normalize(); nend.normalize(); - nstep = nend; nstep.sub(nstart); nstep.div(end.u-start.u); - normal = nstep; normal.mul(u-start.u); normal.add(nstart); normal.normalize(); } - start.normal.add(start.nstep); start.u += start.ustep; - end.normal.add(end.nstep); end.u += end.ustep; } diff --git a/src/engine/octa.cpp b/src/engine/octa.cpp index 3d47cd3..21a3938 100644 --- a/src/engine/octa.cpp +++ b/src/engine/octa.cpp @@ -5,17 +5,14 @@ cube *worldroot = newcubes(F_SOLID); int allocnodes = 0; -cubeext *growcubeext(cubeext *old, int maxverts) -{ +cubeext *growcubeext(cubeext *old, int maxverts) { cubeext *ext = (cubeext *)new uchar[sizeof(cubeext) + maxverts*sizeof(vertinfo)]; - if(old) - { + if(old) { ext->va = old->va; ext->ents = old->ents; ext->tjoints = old->tjoints; } - else - { + else { ext->va = NULL; ext->ents = NULL; ext->tjoints = -1; @@ -24,22 +21,18 @@ cubeext *growcubeext(cubeext *old, int maxverts) return ext; } -void setcubeext(cube &c, cubeext *ext) -{ +void setcubeext(cube &c, cubeext *ext) { cubeext *old = c.ext; if(old == ext) return; c.ext = ext; if(old) delete[] (uchar *)old; } -cubeext *newcubeext(cube &c, int maxverts, bool init) -{ +cubeext *newcubeext(cube &c, int maxverts, bool init) { if(c.ext && c.ext->maxverts >= maxverts) return c.ext; cubeext *ext = growcubeext(c.ext, maxverts); - if(init) - { - if(c.ext) - { + if(init) { + if(c.ext) { memcpy(ext->surfaces, c.ext->surfaces, sizeof(ext->surfaces)); memcpy(ext->verts(), c.ext->verts(), c.ext->maxverts*sizeof(vertinfo)); } @@ -49,11 +42,9 @@ cubeext *newcubeext(cube &c, int maxverts, bool init) return ext; } -cube *newcubes(uint face, int mat) -{ +cube *newcubes(uint face, int mat) { cube *c = new cube[8]; - loopi(8) - { + loopi(8) { c->children = NULL; c->ext = NULL; c->visible = 0; @@ -67,53 +58,44 @@ cube *newcubes(uint face, int mat) return c-8; } -int familysize(const cube &c) -{ +int familysize(const cube &c) { int size = 1; if(c.children) loopi(8) size += familysize(c.children[i]); return size; } -void freeocta(cube *c) -{ +void freeocta(cube *c) { if(!c) return; loopi(8) discardchildren(c[i]); delete[] c; allocnodes--; } -void freecubeext(cube &c) -{ - if(c.ext) - { +void freecubeext(cube &c) { + if(c.ext) { delete[] (uchar *)c.ext; c.ext = NULL; } } -void discardchildren(cube &c, bool fixtex, int depth) -{ +void discardchildren(cube &c, bool fixtex, int depth) { c.material = MAT_AIR; c.visible = 0; c.merged = 0; - if(c.ext) - { + if(c.ext) { if(c.ext->va) destroyva(c.ext->va); c.ext->va = NULL; c.ext->tjoints = -1; freeoctaentities(c); freecubeext(c); } - if(c.children) - { + if(c.children) { uint filled = F_EMPTY; - loopi(8) - { + loopi(8) { discardchildren(c.children[i], fixtex, depth+1); filled |= c.children[i].faces[0]; } - if(fixtex) - { + if(fixtex) { loopi(6) c.texture[i] = getmippedtexture(c, i); if(depth > 0 && filled != F_EMPTY) c.faces[0] = F_SOLID; } @@ -122,44 +104,36 @@ void discardchildren(cube &c, bool fixtex, int depth) } } -void getcubevector(cube &c, int d, int x, int y, int z, ivec &p) -{ +void getcubevector(cube &c, int d, int x, int y, int z, ivec &p) { ivec v(d, x, y, z); - loopi(3) p[i] = edgeget(cubeedge(c, i, v[R[i]], v[C[i]]), v[D[i]]); } -void setcubevector(cube &c, int d, int x, int y, int z, const ivec &p) -{ +void setcubevector(cube &c, int d, int x, int y, int z, const ivec &p) { ivec v(d, x, y, z); - loopi(3) edgeset(cubeedge(c, i, v[R[i]], v[C[i]]), v[D[i]], p[i]); } -static inline void getcubevector(cube &c, int i, ivec &p) -{ +static inline void getcubevector(cube &c, int i, ivec &p) { p.x = edgeget(cubeedge(c, 0, (i>>R[0])&1, (i>>C[0])&1), (i>>D[0])&1); p.y = edgeget(cubeedge(c, 1, (i>>R[1])&1, (i>>C[1])&1), (i>>D[1])&1); p.z = edgeget(cubeedge(c, 2, (i>>R[2])&1, (i>>C[2])&1), (i>>D[2])&1); } -static inline void setcubevector(cube &c, int i, const ivec &p) -{ +static inline void setcubevector(cube &c, int i, const ivec &p) { edgeset(cubeedge(c, 0, (i>>R[0])&1, (i>>C[0])&1), (i>>D[0])&1, p.x); edgeset(cubeedge(c, 1, (i>>R[1])&1, (i>>C[1])&1), (i>>D[1])&1, p.y); edgeset(cubeedge(c, 2, (i>>R[2])&1, (i>>C[2])&1), (i>>D[2])&1, p.z); } -void optiface(uchar *p, cube &c) -{ +void optiface(uchar *p, cube &c) { uint f = *(uint *)p; if(((f>>4)&0x0F0F0F0FU) == (f&0x0F0F0F0FU)) emptyfaces(c); } -void printcube() -{ +void printcube() { cube &c = lookupcube(lu); // assume this is cube being pointed at conoutf(CON_DEBUG, "= %p = (%d, %d, %d) @ %d", (void *)&c, lu.x, lu.y, lu.z, lusize); conoutf(CON_DEBUG, " x %.8x", c.faces[0]); @@ -169,43 +143,33 @@ void printcube() COMMAND(printcube, ""); -bool isvalidcube(const cube &c) -{ +bool isvalidcube(const cube &c) { clipplanes p; genclipplanes(c, ivec(0, 0, 0), 256, p); - loopi(8) // test that cube is convex - { + loopi(8) { // test that cube is convex { vec v = p.v[i]; loopj(p.size) if(p.p[j].dist(v)>1e-3f) return false; } return true; } -void validatec(cube *c, int size) -{ - loopi(8) - { - if(c[i].children) - { - if(size<=1) - { +void validatec(cube *c, int size) { + loopi(8) { + if(c[i].children) { + if(size<=1) { solidfaces(c[i]); discardchildren(c[i], true); } else validatec(c[i].children, size>>1); } - else if(size > 0x1000) - { + else if(size > 0x1000) { subdividecube(c[i], true, false); validatec(c[i].children, size>>1); } - else - { - loopj(3) - { + else { + loopj(3) { uint f = c[i].faces[j], e0 = f&0x0F0F0F0FU, e1 = (f>>4)&0x0F0F0F0FU; - if(e0 == e1 || ((e1+0x07070707U)|(e1-e0))&0xF0F0F0F0U) - { + if(e0 == e1 || ((e1+0x07070707U)|(e1-e0))&0xF0F0F0F0U) { emptyfaces(c[i]); break; } @@ -216,19 +180,15 @@ void validatec(cube *c, int size) ivec lu; int lusize; -cube &lookupcube(const ivec &to, int tsize, ivec &ro, int &rsize) -{ +cube &lookupcube(const ivec &to, int tsize, ivec &ro, int &rsize) { int tx = clamp(to.x, 0, worldsize-1), ty = clamp(to.y, 0, worldsize-1), tz = clamp(to.z, 0, worldsize-1); int scale = worldscale-1, csize = abs(tsize); cube *c = &worldroot[octastep(tx, ty, tz, scale)]; - if(!(csize>>scale)) do - { - if(!c->children) - { - if(tsize > 0) do - { + if(!(csize>>scale)) do { + if(!c->children) { + if(tsize > 0) do { subdividecube(*c); scale--; c = &c->children[octastep(tx, ty, tz, scale)]; @@ -243,14 +203,12 @@ cube &lookupcube(const ivec &to, int tsize, ivec &ro, int &rsize) return *c; } -int lookupmaterial(const vec &v) -{ +int lookupmaterial(const vec &v) { ivec o(v); if(!insideworld(o)) return MAT_AIR; int scale = worldscale-1; cube *c = &worldroot[octastep(o.x, o.y, o.z, scale)]; - while(c->children) - { + while(c->children) { scale--; c = &c->children[octastep(o.x, o.y, o.z, scale)]; } @@ -260,8 +218,7 @@ int lookupmaterial(const vec &v) const cube *neighbourstack[32]; int neighbourdepth = -1; -const cube &neighbourcube(const cube &c, int orient, const ivec &co, int size, ivec &ro, int &rsize) -{ +const cube &neighbourcube(const cube &c, int orient, const ivec &co, int size, ivec &ro, int &rsize) { ivec n = co; int dim = dimension(orient); uint diff = n[dim]; @@ -270,8 +227,7 @@ const cube &neighbourcube(const cube &c, int orient, const ivec &co, int size, i if(diff >= uint(worldsize)) { ro = n; rsize = size; return c; } int scale = worldscale; const cube *nc = worldroot; - if(neighbourdepth >= 0) - { + if(neighbourdepth >= 0) { scale -= neighbourdepth + 1; diff >>= scale; do { scale++; diff >>= 1; } while(diff); @@ -279,8 +235,7 @@ const cube &neighbourcube(const cube &c, int orient, const ivec &co, int size, i } scale--; nc = &nc[octastep(n.x, n.y, n.z, scale)]; - if(!(size>>scale) && nc->children) do - { + if(!(size>>scale) && nc->children) do { scale--; nc = &nc->children[octastep(n.x, n.y, n.z, scale)]; } while(!(size>>scale) && nc->children); @@ -291,15 +246,12 @@ const cube &neighbourcube(const cube &c, int orient, const ivec &co, int size, i ////////// (re)mip ////////// -int getmippedtexture(const cube &p, int orient) -{ +int getmippedtexture(const cube &p, int orient) { cube *c = p.children; int d = dimension(orient), dc = dimcoord(orient), texs[4] = { -1, -1, -1, -1 }, numtexs = 0; - loop(x, 2) loop(y, 2) - { + loop(x, 2) loop(y, 2) { int n = octaindex(d, x, y, dc); - if(isempty(c[n])) - { + if(isempty(c[n])) { n = oppositeocta(d, n); if(isempty(c[n])) continue; @@ -312,16 +264,12 @@ int getmippedtexture(const cube &p, int orient) return DEFAULT_GEOM; } -void forcemip(cube &c, bool fixtex) -{ +void forcemip(cube &c, bool fixtex) { cube *ch = c.children; emptyfaces(c); - - loopi(8) loopj(8) - { + loopi(8) loopj(8) { int n = i^(j==3 ? 4 : (j==4 ? 3 : j)); - if(!isempty(ch[n])) // breadth first search for cube near vert - { + if(!isempty(ch[n])) { // breadth first search for cube near vert { ivec v; getcubevector(ch[n], i, v); // adjust vert to parent size @@ -329,13 +277,11 @@ void forcemip(cube &c, bool fixtex) break; } } - if(fixtex) loopj(6) c.texture[j] = getmippedtexture(c, j); } -static int midedge(const ivec &a, const ivec &b, int xd, int yd, bool &perfect) -{ +static int midedge(const ivec &a, const ivec &b, int xd, int yd, bool &perfect) { int ax = a[xd], ay = a[yd], bx = b[xd], by = b[yd]; if(ay==by) return ay; if(ax==bx) { perfect = false; return ay; } @@ -353,23 +299,19 @@ static int midedge(const ivec &a, const ivec &b, int xd, int yd, bool &perfect) return crossy ? 8 : min(max(y, 0), 16); } -static inline bool crosscenter(const ivec &a, const ivec &b, int xd, int yd) -{ +static inline bool crosscenter(const ivec &a, const ivec &b, int xd, int yd) { int ax = a[xd], ay = a[yd], bx = b[xd], by = b[yd]; return (((ax <= 8 && bx <= 8) || (ax >= 8 && bx >= 8)) && ((ay <= 8 && by <= 8) || (ay >= 8 && by >= 8))) || (ax + bx == 16 && ay + by == 16); } -bool subdividecube(cube &c, bool fullcheck, bool brighten) -{ +bool subdividecube(cube &c, bool fullcheck, bool brighten) { if(c.children) return true; if(c.ext) memset(c.ext->surfaces, 0, sizeof(c.ext->surfaces)); - if(isempty(c) || isentirelysolid(c)) - { + if(isempty(c) || isentirelysolid(c)) { c.children = newcubes(isempty(c) ? F_EMPTY : F_SOLID, c.material); - loopi(8) - { + loopi(8) { loopl(6) c.children[i].texture[l] = c.texture[l]; if(brighten && !isempty(c)) brightencube(c.children[i]); } @@ -378,14 +320,11 @@ bool subdividecube(cube &c, bool fullcheck, bool brighten) cube *ch = c.children = newcubes(F_SOLID, c.material); bool perfect = true; ivec v[8]; - loopi(8) - { + loopi(8) { getcubevector(c, i, v[i]); v[i].mul(2); } - - loopj(6) - { + loopj(6) { int d = dimension(j), z = dimcoord(j); const ivec &v00 = v[octaindex(d, 0, 0, z)], &v10 = v[octaindex(d, 1, 0, z)], @@ -406,19 +345,15 @@ bool subdividecube(cube &c, bool fullcheck, bool brighten) bool p1 = perfect, p2 = perfect; int c1 = midedge(v00, v11, R[d], d, p1); int c2 = midedge(v01, v10, R[d], d, p2); - if(z ? c1 > c2 : c1 < c2) - { + if(z ? c1 > c2 : c1 < c2) { e[1][1] = c1; perfect = p1 && (c1 == c2 || crosscenter(v00, v11, C[d], R[d])); } - else - { + else { e[1][1] = c2; perfect = p2 && (c1 == c2 || crosscenter(v01, v10, C[d], R[d])); } - - loopi(8) - { + loopi(8) { ch[i].texture[j] = c.texture[j]; int rd = (i>>R[d])&1, cd = (i>>C[d])&1, dd = (i>>D[d])&1; edgeset(cubeedge(ch[i], d, 0, 0), z, clamp(e[rd][cd] - dd*8, 0, 8)); @@ -427,10 +362,8 @@ bool subdividecube(cube &c, bool fullcheck, bool brighten) edgeset(cubeedge(ch[i], d, 1, 1), z, clamp(e[1+rd][1+cd] - dd*8, 0, 8)); } } - validatec(ch); - if(fullcheck) loopi(8) if(!isvalidcube(ch[i])) // not so good... - { + if(fullcheck) loopi(8) if(!isvalidcube(ch[i])) { // not so good... { emptyfaces(ch[i]); perfect=false; } @@ -440,14 +373,11 @@ bool subdividecube(cube &c, bool fullcheck, bool brighten) bool crushededge(uchar e, int dc) { return dc ? e==0 : e==0x88; } -int visibleorient(const cube &c, int orient) -{ - loopi(2) - { +int visibleorient(const cube &c, int orient) { + loopi(2) { int a = faceedgesidx[orient][i*2 + 0]; int b = faceedgesidx[orient][i*2 + 1]; - loopj(2) - { + loopj(2) { if(crushededge(c.edges[a],j) && crushededge(c.edges[b],j) && touchingface(c, orient)) return ((a>>2)<<1) + j; @@ -460,85 +390,66 @@ VAR(mipvis, 0, 0, 1); static int remipprogress = 0, remiptotal = 0; -bool remip(cube &c, const ivec &co, int size) -{ +bool remip(cube &c, const ivec &co, int size) { cube *ch = c.children; - if(!ch) - { + if(!ch) { if(size<<1 <= 0x1000) return true; subdividecube(c); ch = c.children; } else if((remipprogress++&0xFFF)==1) renderprogress(float(remipprogress)/remiptotal, "remipping..."); - bool perfect = true; - loopi(8) - { + loopi(8) { ivec o(i, co, size); if(!remip(ch[i], o, size>>1)) perfect = false; } - solidfaces(c); // so texmip is more consistent loopj(6) c.texture[j] = getmippedtexture(c, j); // parents get child texs regardless - if(!perfect) return false; if(size<<1 > 0x1000) return false; - ushort mat = MAT_AIR; - loopi(8) - { + loopi(8) { mat = ch[i].material; - if((mat&MATF_CLIP) == MAT_NOCLIP || mat&MAT_ALPHA) - { + if((mat&MATF_CLIP) == MAT_NOCLIP || mat&MAT_ALPHA) { if(i > 0) return false; while(++i < 8) if(ch[i].material != mat) return false; break; } - else if(!isentirelysolid(ch[i])) - { - while(++i < 8) - { + else if(!isentirelysolid(ch[i])) { + while(++i < 8) { int omat = ch[i].material; if(isentirelysolid(ch[i]) ? (omat&MATF_CLIP) == MAT_NOCLIP || omat&MAT_ALPHA : mat != omat) return false; } break; } } - cube n = c; n.ext = NULL; forcemip(n); n.children = NULL; - if(!subdividecube(n, false, false)) - { freeocta(n.children); return false; } - + if(!subdividecube(n, false, false)) { + freeocta(n.children); return false; } cube *nh = n.children; uchar vis[6] = {0, 0, 0, 0, 0, 0}; - loopi(8) - { + loopi(8) { if(ch[i].faces[0] != nh[i].faces[0] || ch[i].faces[1] != nh[i].faces[1] || - ch[i].faces[2] != nh[i].faces[2]) - { freeocta(nh); return false; } - + ch[i].faces[2] != nh[i].faces[2]) { + freeocta(nh); return false; } if(isempty(ch[i]) && isempty(nh[i])) continue; - ivec o(i, co, size); loop(orient, 6) - if(visibleface(ch[i], orient, o, size, MAT_AIR, (mat&MAT_ALPHA)^MAT_ALPHA, MAT_ALPHA)) - { + if(visibleface(ch[i], orient, o, size, MAT_AIR, (mat&MAT_ALPHA)^MAT_ALPHA, MAT_ALPHA)) { if(ch[i].texture[orient] != n.texture[orient]) { freeocta(nh); return false; } vis[orient] |= 1<<i; } } - if(mipvis) loop(orient, 6) - { + if(mipvis) loop(orient, 6) { int mask = 0; loop(x, 2) loop(y, 2) mask |= 1<<octaindex(dimension(orient), x, y, dimcoord(orient)); if(vis[orient]&mask && (vis[orient]&mask)!=mask) { freeocta(nh); return false; } } - freeocta(nh); discardchildren(c); loopi(3) c.faces[i] = n.faces[i]; @@ -549,14 +460,12 @@ bool remip(cube &c, const ivec &co, int size) return true; } -void mpremip(bool local) -{ +void mpremip(bool local) { extern selinfo sel; if(local) game::edittrigger(sel, EDIT_REMIP); remipprogress = 1; remiptotal = allocnodes; - loopi(8) - { + loopi(8) { ivec o(i, ivec(0, 0, 0), worldsize>>1); remip(worldroot[i], o, worldsize>>2); } @@ -564,36 +473,30 @@ void mpremip(bool local) if(!local) allchanged(); } -void remip_() -{ +void remip_() { mpremip(true); allchanged(); } COMMANDN(remip, remip_, ""); -static inline int edgeval(cube &c, const ivec &p, int dim, int coord) -{ +static inline int edgeval(cube &c, const ivec &p, int dim, int coord) { return edgeget(cubeedge(c, dim, p[R[dim]]>>3, p[C[dim]]>>3), coord); } -void genvertp(cube &c, ivec &p1, ivec &p2, ivec &p3, plane &pl, bool solid = false) -{ +void genvertp(cube &c, ivec &p1, ivec &p2, ivec &p3, plane &pl, bool solid = false) { int dim = 0; if(p1.y==p2.y && p2.y==p3.y) dim = 1; else if(p1.z==p2.z && p2.z==p3.z) dim = 2; - int coord = p1[dim]; ivec v1(p1), v2(p2), v3(p3); v1[dim] = solid ? coord*8 : edgeval(c, p1, dim, coord); v2[dim] = solid ? coord*8 : edgeval(c, p2, dim, coord); v3[dim] = solid ? coord*8 : edgeval(c, p3, dim, coord); - pl.toplane(vec(v1), vec(v2), vec(v3)); } -static bool threeplaneintersect(plane &pl1, plane &pl2, plane &pl3, vec &dest) -{ +static bool threeplaneintersect(plane &pl1, plane &pl2, plane &pl3, vec &dest) { vec &t1 = dest, t2, t3, t4; t1.cross(pl1, pl2); t4 = t1; t1.mul(pl3.offset); t2.cross(pl3, pl1); t2.mul(pl2.offset); @@ -607,12 +510,10 @@ static bool threeplaneintersect(plane &pl1, plane &pl2, plane &pl3, vec &dest) return true; } -static void genedgespanvert(ivec &p, cube &c, vec &v) -{ +static void genedgespanvert(ivec &p, cube &c, vec &v) { ivec p1(8-p.x, p.y, p.z); ivec p2(p.x, 8-p.y, p.z); ivec p3(p.x, p.y, 8-p.z); - plane plane1, plane2, plane3; genvertp(c, p, p1, p2, plane1); genvertp(c, p, p2, p3, plane2); @@ -620,7 +521,6 @@ static void genedgespanvert(ivec &p, cube &c, vec &v) if(plane1==plane2) genvertp(c, p, p1, p2, plane1, true); if(plane1==plane3) genvertp(c, p, p1, p2, plane1, true); if(plane2==plane3) genvertp(c, p, p2, p3, plane2, true); - ASSERT(threeplaneintersect(plane1, plane2, plane3, v)); //ASSERT(v.x>=0 && v.x<=8); //ASSERT(v.y>=0 && v.y<=8); @@ -630,34 +530,28 @@ static void genedgespanvert(ivec &p, cube &c, vec &v) v.z = max(0.0f, min(8.0f, v.z)); } -void edgespan2vectorcube(cube &c) -{ +void edgespan2vectorcube(cube &c) { if(isentirelysolid(c) || isempty(c)) return; cube o = c; - loop(x, 2) loop(y, 2) loop(z, 2) - { + loop(x, 2) loop(y, 2) loop(z, 2) { ivec p(8*x, 8*y, 8*z); vec v; genedgespanvert(p, o, v); - edgeset(cubeedge(c, 0, y, z), x, int(v.x+0.49f)); edgeset(cubeedge(c, 1, z, x), y, int(v.y+0.49f)); edgeset(cubeedge(c, 2, x, y), z, int(v.z+0.49f)); } } -const ivec cubecoords[8] = // verts of bounding cube -{ +const ivec cubecoords[8] = {// verts of bounding cube { #define GENCUBEVERT(n, x, y, z) ivec(x, y, z), GENCUBEVERTS(0, 8, 0, 8, 0, 8) #undef GENCUBEVERT }; template<class T> -static inline void gencubevert(const cube &c, int i, T &v) -{ - switch(i) - { +static inline void gencubevert(const cube &c, int i, T &v) { + switch(i) { default: #define GENCUBEVERT(n, x, y, z) \ case n: \ @@ -670,10 +564,8 @@ static inline void gencubevert(const cube &c, int i, T &v) } } -void genfaceverts(const cube &c, int orient, ivec v[4]) -{ - switch(orient) - { +void genfaceverts(const cube &c, int orient, ivec v[4]) { + switch(orient) { default: #define GENFACEORIENT(o, v0, v1, v2, v3) \ case o: v0 v1 v2 v3 break; @@ -687,10 +579,9 @@ void genfaceverts(const cube &c, int orient, ivec v[4]) } } -const ivec facecoords[6][4] = -{ -#define GENFACEORIENT(o, v0, v1, v2, v3) \ - { v0, v1, v2, v3 }, +const ivec facecoords[6][4] = { +#define GENFACEORIENT(o, v0, v1, v2, v3) { \ + v0, v1, v2, v3 }, #define GENFACEVERT(o, n, x,y,z, xv,yv,zv) \ ivec(x,y,z) GENFACEVERTS(0, 8, 0, 8, 0, 8, , , , , , ) @@ -698,8 +589,7 @@ const ivec facecoords[6][4] = #undef GENFACEVERT }; -const uchar fv[6][4] = // indexes for cubecoords, per each vert of a face orientation -{ +const uchar fv[6][4] = { // indexes for cubecoords, per each vert of a face orientation { { 2, 1, 6, 5 }, { 3, 4, 7, 0 }, { 4, 5, 6, 7 }, @@ -708,8 +598,7 @@ const uchar fv[6][4] = // indexes for cubecoords, per each vert of a face orient { 5, 4, 3, 2 }, }; -const uchar fvmasks[64] = // mask of verts used given a mask of visible face orientations -{ +const uchar fvmasks[64] = { // mask of verts used given a mask of visible face orientations { 0x00, 0x66, 0x99, 0xFF, 0xF0, 0xF6, 0xF9, 0xFF, 0x0F, 0x6F, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xE7, 0xDB, 0xFF, 0xF3, 0xF7, 0xFB, 0xFF, @@ -720,8 +609,8 @@ const uchar fvmasks[64] = // mask of verts used given a mask of visible face ori 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; -const uchar faceedgesidx[6][4] = // ordered edges surrounding each orient -{//0..1 = row edges, 2..3 = column edges +const uchar faceedgesidx[6][4] = { // ordered edges surrounding each orient { +//0..1 = row edges, 2..3 = column edges { { 4, 5, 8, 10 }, { 6, 7, 9, 11 }, { 8, 9, 0, 2 }, @@ -730,17 +619,14 @@ const uchar faceedgesidx[6][4] = // ordered edges surrounding each orient { 2, 3, 5, 7 }, }; -bool flataxisface(const cube &c, int orient) -{ +bool flataxisface(const cube &c, int orient) { uint face = c.faces[dimension(orient)]; if(dimcoord(orient)) face >>= 4; return (face&0x0F0F0F0F) == 0x01010101*(face&0x0F); } -bool collideface(const cube &c, int orient) -{ - if(flataxisface(c, orient)) - { +bool collideface(const cube &c, int orient) { + if(flataxisface(c, orient)) { uchar r1 = c.edges[faceedgesidx[orient][0]], r2 = c.edges[faceedgesidx[orient][1]]; if(uchar((r1>>4)|(r2&0xF0)) == uchar((r1&0x0F)|(r2<<4))) return false; uchar c1 = c.edges[faceedgesidx[orient][2]], c2 = c.edges[faceedgesidx[orient][3]]; @@ -749,35 +635,30 @@ bool collideface(const cube &c, int orient) return true; } -bool touchingface(const cube &c, int orient) -{ +bool touchingface(const cube &c, int orient) { uint face = c.faces[dimension(orient)]; return dimcoord(orient) ? (face&0xF0F0F0F0)==0x80808080 : (face&0x0F0F0F0F)==0; } -bool notouchingface(const cube &c, int orient) -{ +bool notouchingface(const cube &c, int orient) { uint face = c.faces[dimension(orient)]; return dimcoord(orient) ? (face&0x80808080)==0 : ((0x88888888-face)&0x08080808) == 0; } -int faceconvexity(const ivec v[4]) -{ +int faceconvexity(const ivec v[4]) { ivec n; n.cross(ivec(v[1]).sub(v[0]), ivec(v[2]).sub(v[0])); return ivec(v[0]).sub(v[3]).dot(n); // 1 if convex, -1 if concave, 0 if flat } -int faceconvexity(const vertinfo *verts, int numverts, int size) -{ +int faceconvexity(const vertinfo *verts, int numverts, int size) { if(numverts < 4) return 0; ivec v0 = verts[0].getxyz(), e1 = verts[1].getxyz().sub(v0), e2 = verts[2].getxyz().sub(v0), n; - if(size >= (8<<5)) - { + if(size >= (8<<5)) { if(size >= (8<<10)) n.cross(e1.shr(10), e2.shr(10)); else n.cross(e1, e2).shr(10); } @@ -785,13 +666,11 @@ int faceconvexity(const vertinfo *verts, int numverts, int size) return verts[3].getxyz().sub(v0).dot(n); } -int faceconvexity(const ivec v[4], int &vis) -{ +int faceconvexity(const ivec v[4], int &vis) { ivec e1, e2, e3, n; n.cross((e1 = v[1]).sub(v[0]), (e2 = v[2]).sub(v[0])); int convex = (e3 = v[0]).sub(v[3]).dot(n); - if(!convex) - { + if(!convex) { if(ivec().cross(e3, e2).iszero()) { if(!n.iszero()) vis = 1; } else if(n.iszero()) { vis = 2; } return 0; @@ -799,46 +678,39 @@ int faceconvexity(const ivec v[4], int &vis) return convex; } -int faceconvexity(const cube &c, int orient) -{ +int faceconvexity(const cube &c, int orient) { if(flataxisface(c, orient)) return 0; ivec v[4]; genfaceverts(c, orient, v); return faceconvexity(v); } -int faceorder(const cube &c, int orient) // gets above 'fv' so that each face is convex -{ +int faceorder(const cube &c, int orient) { // gets above 'fv' so that each face is convex { return faceconvexity(c, orient)<0 ? 1 : 0; } -static inline void faceedges(const cube &c, int orient, uchar edges[4]) -{ +static inline void faceedges(const cube &c, int orient, uchar edges[4]) { loopk(4) edges[k] = c.edges[faceedgesidx[orient][k]]; } -uint faceedges(const cube &c, int orient) -{ +uint faceedges(const cube &c, int orient) { union { uchar edges[4]; uint face; } u; faceedges(c, orient, u.edges); return u.face; } -static inline int genfacevecs(const cube &cu, int orient, const ivec &pos, int size, bool solid, ivec2 *fvecs, const ivec *v = NULL) -{ +static inline int genfacevecs(const cube &cu, int orient, const ivec &pos, int size, bool solid, ivec2 *fvecs, const ivec *v = NULL) { int i = 0; - if(solid) - { - switch(orient) - { + if(solid) { + switch(orient) { #define GENFACEORIENT(orient, v0, v1, v2, v3) \ - case orient: \ - { \ + case orient: { \ + \ if(dimcoord(orient)) { v0 v1 v2 v3 } else { v3 v2 v1 v0 } \ break; \ } - #define GENFACEVERT(orient, vert, xv,yv,zv, x,y,z) \ - { ivec2 &f = fvecs[i]; x ((xv)<<3); y ((yv)<<3); z ((zv)<<3); i++; } + #define GENFACEVERT(orient, vert, xv,yv,zv, x,y,z) { \ + ivec2 &f = fvecs[i]; x ((xv)<<3); y ((yv)<<3); z ((zv)<<3); i++; } GENFACEVERTS(pos.x, pos.x+size, pos.y, pos.y+size, pos.z, pos.z+size, f.x = , f.x = , f.y = , f.y = , (void), (void)) #undef GENFACEVERT } @@ -847,15 +719,14 @@ static inline int genfacevecs(const cube &cu, int orient, const ivec &pos, int s ivec buf[4]; if(!v) { genfaceverts(cu, orient, buf); v = buf; } ivec2 prev(INT_MAX, INT_MAX); - switch(orient) - { - #define GENFACEVERT(orient, vert, sx,sy,sz, dx,dy,dz) \ - { \ + switch(orient) { + #define GENFACEVERT(orient, vert, sx,sy,sz, dx,dy,dz) { \ + \ const ivec &e = v[vert]; \ ivec ef; \ ef.dx = e.sx; ef.dy = e.sy; ef.dz = e.sz; \ - if(ef.z == dimcoord(orient)*8) \ - { \ + if(ef.z == dimcoord(orient)*8) { \ + \ ivec2 &f = fvecs[i]; \ ivec pf; \ pf.dx = pos.sx; pf.dy = pos.sy; pf.dz = pos.sz; \ @@ -871,66 +742,51 @@ static inline int genfacevecs(const cube &cu, int orient, const ivec &pos, int s return i; } -static inline int clipfacevecy(const ivec2 &o, const ivec2 &dir, int cx, int cy, int size, ivec2 &r) -{ - if(dir.x >= 0) - { +static inline int clipfacevecy(const ivec2 &o, const ivec2 &dir, int cx, int cy, int size, ivec2 &r) { + if(dir.x >= 0) { if(cx <= o.x || cx >= o.x+dir.x) return 0; } else if(cx <= o.x+dir.x || cx >= o.x) return 0; - int t = (o.y-cy) + (cx-o.x)*dir.y/dir.x; if(t <= 0 || t >= size) return 0; - r.x = cx; r.y = cy + t; return 1; } -static inline int clipfacevecx(const ivec2 &o, const ivec2 &dir, int cx, int cy, int size, ivec2 &r) -{ - if(dir.y >= 0) - { +static inline int clipfacevecx(const ivec2 &o, const ivec2 &dir, int cx, int cy, int size, ivec2 &r) { + if(dir.y >= 0) { if(cy <= o.y || cy >= o.y+dir.y) return 0; } else if(cy <= o.y+dir.y || cy >= o.y) return 0; - int t = (o.x-cx) + (cy-o.y)*dir.x/dir.y; if(t <= 0 || t >= size) return 0; - r.x = cx + t; r.y = cy; return 1; } -static inline int clipfacevec(const ivec2 &o, const ivec2 &dir, int cx, int cy, int size, ivec2 *rvecs) -{ +static inline int clipfacevec(const ivec2 &o, const ivec2 &dir, int cx, int cy, int size, ivec2 *rvecs) { int r = 0; - if(o.x >= cx && o.x <= cx+size && o.y >= cy && o.y <= cy+size && - ((o.x != cx && o.x != cx+size) || (o.y != cy && o.y != cy+size))) - { + ((o.x != cx && o.x != cx+size) || (o.y != cy && o.y != cy+size))) { rvecs[0].x = o.x; rvecs[0].y = o.y; r++; } - r += clipfacevecx(o, dir, cx, cy, size, rvecs[r]); r += clipfacevecx(o, dir, cx, cy+size, size, rvecs[r]); r += clipfacevecy(o, dir, cx, cy, size, rvecs[r]); r += clipfacevecy(o, dir, cx+size, cy, size, rvecs[r]); - ASSERT(r <= 2); return r; } -static inline bool insideface(const ivec2 *p, int nump, const ivec2 *o, int numo) -{ +static inline bool insideface(const ivec2 *p, int nump, const ivec2 *o, int numo) { int bounds = 0; ivec2 prev = o[numo-1]; - loopi(numo) - { + loopi(numo) { const ivec2 &cur = o[i]; ivec2 dir(cur.x-prev.x, cur.y-prev.y); int offset = dir.x*prev.y - dir.y*prev.x; @@ -941,16 +797,13 @@ static inline bool insideface(const ivec2 *p, int nump, const ivec2 *o, int numo return bounds>=3; } -static inline int clipfacevecs(const ivec2 *o, int numo, int cx, int cy, int size, ivec2 *rvecs) -{ +static inline int clipfacevecs(const ivec2 *o, int numo, int cx, int cy, int size, ivec2 *rvecs) { cx <<= 3; cy <<= 3; size <<= 3; - int r = 0; ivec2 prev = o[numo-1]; - loopi(numo) - { + loopi(numo) { const ivec2 &cur = o[i]; r += clipfacevec(prev, ivec2(cur.x-prev.x, cur.y-prev.y), cx, cy, size, &rvecs[r]); prev = cur; @@ -961,8 +814,7 @@ static inline int clipfacevecs(const ivec2 *o, int numo, int cx, int cy, int siz return r; } -bool collapsedface(const cube &c, int orient) -{ +bool collapsedface(const cube &c, int orient) { int e0 = c.edges[faceedgesidx[orient][0]], e1 = c.edges[faceedgesidx[orient][1]], e2 = c.edges[faceedgesidx[orient][2]], e3 = c.edges[faceedgesidx[orient][3]], face = dimension(orient)*4, @@ -978,11 +830,9 @@ bool collapsedface(const cube &c, int orient) ivec().cross(v2, v3.sub(v0)).iszero(); } -static inline bool occludesface(const cube &c, int orient, const ivec &o, int size, const ivec &vo, int vsize, ushort vmat, ushort nmat, ushort matmask, const ivec2 *vf, int numv) -{ +static inline bool occludesface(const cube &c, int orient, const ivec &o, int size, const ivec &vo, int vsize, ushort vmat, ushort nmat, ushort matmask, const ivec2 *vf, int numv) { int dim = dimension(orient); - if(!c.children) - { + if(!c.children) { if(nmat != MAT_AIR && (c.material&matmask) == nmat) { ivec2 nf[8]; @@ -999,42 +849,32 @@ static inline bool occludesface(const cube &c, int orient, const ivec &o, int si int numo = genfacevecs(c, orient, o, size, false, of); return numo >= 3 && insideface(cf, numc, of, numo); } - size >>= 1; int coord = dimcoord(orient); - loopi(8) if(octacoord(dim, i) == coord) - { + loopi(8) if(octacoord(dim, i) == coord) { if(!occludesface(c.children[i], orient, ivec(i, o, size), size, vo, vsize, vmat, nmat, matmask, vf, numv)) return false; } - return true; } -bool visibleface(const cube &c, int orient, const ivec &co, int size, ushort mat, ushort nmat, ushort matmask) -{ - if(mat != MAT_AIR) - { +bool visibleface(const cube &c, int orient, const ivec &co, int size, ushort mat, ushort nmat, ushort matmask) { + if(mat != MAT_AIR) { if(faceedges(c, orient)==F_SOLID && touchingface(c, orient)) return false; } - else - { + else { if(collapsedface(c, orient)) return false; if(!touchingface(c, orient)) return true; } - ivec no; int nsize; const cube &o = neighbourcube(c, orient, co, size, no, nsize); if(&o==&c) return false; - int opp = opposite(orient); - if(nsize > size || (nsize == size && !o.children)) - { + if(nsize > size || (nsize == size && !o.children)) { if(nmat != MAT_AIR && (o.material&matmask) == nmat) return true; if(isentirelysolid(o)) return false; if(isempty(o) || notouchingface(o, opp)) return true; if(touchingface(o, opp) && faceedges(o, opp) == F_SOLID) return false; - ivec vo = ivec(co).mask(0xFFF); no.mask(0xFFF); ivec2 cf[4], of[4]; @@ -1043,7 +883,6 @@ bool visibleface(const cube &c, int orient, const ivec &co, int size, ushort mat return numo < 3 || !insideface(cf, numc, of, numo); } - ivec vo = ivec(co).mask(0xFFF); no.mask(0xFFF); ivec2 cf[4]; @@ -1051,26 +890,21 @@ bool visibleface(const cube &c, int orient, const ivec &co, int size, ushort mat return !occludesface(o, opp, no, nsize, vo, size, mat, nmat, matmask, cf, numc); } -int classifyface(const cube &c, int orient, const ivec &co, int size) -{ +int classifyface(const cube &c, int orient, const ivec &co, int size) { if(collapsedface(c, orient)) return 0; int vismask = (c.material&MATF_CLIP) == MAT_NOCLIP ? 1 : 3; if(!touchingface(c, orient)) return vismask; - ivec no; int nsize; const cube &o = neighbourcube(c, orient, co, size, no, nsize); if(&o==&c) return 0; - int vis = 0, opp = opposite(orient); - if(nsize > size || (nsize == size && !o.children)) - { + if(nsize > size || (nsize == size && !o.children)) { if((~c.material & o.material) & MAT_ALPHA) vis |= 1; if((o.material&MATF_CLIP) == MAT_NOCLIP) vis |= vismask&2; if(vis == vismask || isentirelysolid(o)) return vis; if(isempty(o) || notouchingface(o, opp)) return vismask; if(touchingface(o, opp) && faceedges(o, opp) == F_SOLID) return vis; - ivec vo = ivec(co).mask(0xFFF); no.mask(0xFFF); ivec2 cf[4], of[4]; @@ -1079,7 +913,6 @@ int classifyface(const cube &c, int orient, const ivec &co, int size) if(numo < 3 || !insideface(cf, numc, of, numo)) return vismask; return vis; } - ivec vo = ivec(co).mask(0xFFF); no.mask(0xFFF); ivec2 cf[4]; @@ -1090,79 +923,67 @@ int classifyface(const cube &c, int orient, const ivec &co, int size) } // more expensive version that checks both triangles of a face independently -int visibletris(const cube &c, int orient, const ivec &co, int size, ushort nmat, ushort matmask) -{ +int visibletris(const cube &c, int orient, const ivec &co, int size, ushort nmat, ushort matmask) { int vis = 3, touching = 0xF; ivec v[4], e1, e2, e3, n; genfaceverts(c, orient, v); n.cross((e1 = v[1]).sub(v[0]), (e2 = v[2]).sub(v[0])); int convex = (e3 = v[0]).sub(v[3]).dot(n); - if(!convex) - { + if(!convex) { if(ivec().cross(e3, e2).iszero() || v[1] == v[3]) { if(n.iszero()) return 0; vis = 1; touching = 0xF&~(1<<3); } else if(n.iszero()) { vis = 2; touching = 0xF&~(1<<1); } } - int dim = dimension(orient), coord = dimcoord(orient); if(v[0][dim] != coord*8) touching &= ~(1<<0); if(v[1][dim] != coord*8) touching &= ~(1<<1); if(v[2][dim] != coord*8) touching &= ~(1<<2); if(v[3][dim] != coord*8) touching &= ~(1<<3); - static const int notouchmasks[2][16] = // mask of triangles not touching - { // order 0: flat or convex - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - { 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 1, 3, 0 }, - // order 1: concave - { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 2, 0 }, + static const int notouchmasks[2][16] = { // mask of triangles not touching { + // order 0: flat or convex + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 { + { 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 1, 3, 0 }, + // order 1: concave { + { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 2, 0 }, }; int order = convex < 0 ? 1 : 0, notouch = notouchmasks[order][touching]; if((vis¬ouch)==vis) return vis; - ivec no; int nsize; const cube &o = neighbourcube(c, orient, co, size, no, nsize); if(&o==&c) return 0; - if((c.material&matmask) == nmat) nmat = MAT_AIR; - ivec vo = ivec(co).mask(0xFFF); no.mask(0xFFF); ivec2 cf[4], of[4]; int opp = opposite(orient), numo = 0, numc; - if(nsize > size || (nsize == size && !o.children)) - { + if(nsize > size || (nsize == size && !o.children)) { if(isempty(o) || notouchingface(o, opp)) return vis; if(nmat != MAT_AIR && (o.material&matmask) == nmat) return vis; if(isentirelysolid(o) || (touchingface(o, opp) && faceedges(o, opp) == F_SOLID)) return vis¬ouch; - numc = genfacevecs(c, orient, vo, size, false, cf, v); numo = genfacevecs(o, opp, no, nsize, false, of); if(numo < 3) return vis; if(insideface(cf, numc, of, numo)) return vis¬ouch; } - else - { + else { numc = genfacevecs(c, orient, vo, size, false, cf, v); if(occludesface(o, opp, no, nsize, vo, size, MAT_AIR, nmat, matmask, cf, numc)) return vis¬ouch; } if(vis != 3 || notouch) return vis; - - static const int triverts[2][2][2][3] = - { // order - { // coord - { { 1, 2, 3 }, { 0, 1, 3 } }, // verts - { { 0, 1, 2 }, { 0, 2, 3 } } - }, - { // coord - { { 0, 1, 2 }, { 3, 0, 2 } }, // verts - { { 1, 2, 3 }, { 1, 3, 0 } } + static const int triverts[2][2][2][3] = { + // order { + // coord { + { + { { 1, 2, 3 }, { 0, 1, 3 } }, // verts { + { { 0, 1, 2 }, { 0, 2, 3 } } + }, { + // coord { + { { 0, 1, 2 }, { 3, 0, 2 } }, // verts { + { { 1, 2, 3 }, { 1, 3, 0 } } } }; - - do - { - loopi(2) - { + do { + loopi(2) { const int *verts = triverts[order][coord][i]; ivec2 tf[3] = { cf[verts[0]], cf[verts[1]], cf[verts[2]] }; if(numo > 0) { if(!insideface(tf, 3, of, numo)) continue; } @@ -1171,12 +992,10 @@ int visibletris(const cube &c, int orient, const ivec &co, int size, ushort nmat } vis |= 4; } while(++order <= 1); - return 3; } -void calcvert(const cube &c, const ivec &co, int size, ivec &v, int i, bool solid) -{ +void calcvert(const cube &c, const ivec &co, int size, ivec &v, int i, bool solid) { if(solid) v = cubecoords[i]; else gencubevert(c, i, v); // avoid overflow if(size>=8) v.mul(size/8); @@ -1184,14 +1003,12 @@ void calcvert(const cube &c, const ivec &co, int size, ivec &v, int i, bool soli v.add(ivec(co).shl(3)); } -void calcvert(const cube &c, const ivec &co, int size, vec &v, int i, bool solid) -{ +void calcvert(const cube &c, const ivec &co, int size, vec &v, int i, bool solid) { if(solid) v = vec(cubecoords[i]); else gencubevert(c, i, v); v.mul(size/8.0f).add(vec(co)); } -int genclipplane(const cube &c, int orient, vec *v, plane *clip) -{ +int genclipplane(const cube &c, int orient, vec *v, plane *clip) { int planes = 0, convex = faceconvexity(c, orient), order = convex < 0 ? 1 : 0; const vec &v0 = v[fv[orient][order]], &v1 = v[fv[orient][order+1]], &v2 = v[fv[orient][order+2]], &v3 = v[fv[orient][(order+3)&3]]; if(v0==v2) return 0; @@ -1200,31 +1017,24 @@ int genclipplane(const cube &c, int orient, vec *v, plane *clip) return planes; } -void genclipplanes(const cube &c, const ivec &co, int size, clipplanes &p, bool collide) -{ +void genclipplanes(const cube &c, const ivec &co, int size, clipplanes &p, bool collide) { // generate tight bounding box calcvert(c, co, size, p.v[0], 0); vec mx = p.v[0], mn = p.v[0]; - for(int i = 1; i < 8; i++) - { + for(int i = 1; i < 8; i++) { calcvert(c, co, size, p.v[i], i); mx.max(p.v[i]); mn.min(p.v[i]); } - p.r = mx.sub(mn).mul(0.5f); p.o = mn.add(p.r); - p.size = 0; p.visible = 0; - if(collide || (c.visible&0xC0) == 0x40) - { - loopi(6) if(c.visible&(1<<i)) - { + if(collide || (c.visible&0xC0) == 0x40) { + loopi(6) if(c.visible&(1<<i)) { int vis; if(flataxisface(c, i)) p.visible |= 1<<i; - else if((vis = visibletris(c, i, co, size, MAT_NOCLIP, MATF_CLIP))) - { + else if((vis = visibletris(c, i, co, size, MAT_NOCLIP, MATF_CLIP))) { int convex = faceconvexity(c, i), order = vis&4 || convex < 0 ? 1 : 0; const vec &v0 = p.v[fv[i][order]], &v1 = p.v[fv[i][order+1]], &v2 = p.v[fv[i][order+2]], &v3 = p.v[fv[i][(order+3)&3]]; if(vis&1) { p.side[p.size] = i; p.p[p.size++].toplane(v0, v1, v2); } @@ -1232,14 +1042,11 @@ void genclipplanes(const cube &c, const ivec &co, int size, clipplanes &p, bool } } } - else if(c.visible&0x80) - { + else if(c.visible&0x80) { int vis; - loopi(6) if((vis = visibletris(c, i, co, size))) - { + loopi(6) if((vis = visibletris(c, i, co, size))) { if(flataxisface(c, i)) p.visible |= 1<<i; - else - { + else { int convex = faceconvexity(c, i), order = vis&4 || convex < 0 ? 1 : 0; const vec &v0 = p.v[fv[i][order]], &v1 = p.v[fv[i][order+1]], &v2 = p.v[fv[i][order+2]], &v3 = p.v[fv[i][(order+3)&3]]; if(vis&1) { p.side[p.size] = i; p.p[p.size++].toplane(v0, v1, v2); } @@ -1249,8 +1056,7 @@ void genclipplanes(const cube &c, const ivec &co, int size, clipplanes &p, bool } } -static inline bool mergefacecmp(const facebounds &x, const facebounds &y) -{ +static inline bool mergefacecmp(const facebounds &x, const facebounds &y) { if(x.v2 < y.v2) return true; if(x.v2 > y.v2) return false; if(x.u1 < y.u1) return true; @@ -1258,13 +1064,10 @@ static inline bool mergefacecmp(const facebounds &x, const facebounds &y) return false; } -static int mergefacev(int orient, facebounds *m, int sz, facebounds &n) -{ - for(int i = sz-1; i >= 0; --i) - { +static int mergefacev(int orient, facebounds *m, int sz, facebounds &n) { + for(int i = sz-1; i >= 0; --i) { if(m[i].v2 < n.v1) break; - if(m[i].v2 == n.v1 && m[i].u1 == n.u1 && m[i].u2 == n.u2) - { + if(m[i].v2 == n.v1 && m[i].u1 == n.u1 && m[i].u2 == n.u2) { n.v1 = m[i].v1; memmove(&m[i], &m[i+1], (sz - (i+1)) * sizeof(facebounds)); return 1; @@ -1273,20 +1076,16 @@ static int mergefacev(int orient, facebounds *m, int sz, facebounds &n) return 0; } -static int mergefaceu(int orient, facebounds &m, facebounds &n) -{ - if(m.v1 == n.v1 && m.v2 == n.v2 && m.u2 == n.u1) - { +static int mergefaceu(int orient, facebounds &m, facebounds &n) { + if(m.v1 == n.v1 && m.v2 == n.v2 && m.u2 == n.u1) { n.u1 = m.u1; return 1; } return 0; } -static int mergeface(int orient, facebounds *m, int sz, facebounds &n) -{ - for(bool merged = false; sz; merged = true) - { +static int mergeface(int orient, facebounds *m, int sz, facebounds &n) { + for(bool merged = false; sz; merged = true) { int vmerged = mergefacev(orient, m, sz, n); sz -= vmerged; if(!vmerged && merged) break; @@ -1299,38 +1098,31 @@ static int mergeface(int orient, facebounds *m, int sz, facebounds &n) return sz; } -int mergefaces(int orient, facebounds *m, int sz) -{ +int mergefaces(int orient, facebounds *m, int sz) { quicksort(m, sz, mergefacecmp); - int nsz = 0; loopi(sz) nsz = mergeface(orient, m, nsz, m[i]); return nsz; } -struct cfkey -{ +struct cfkey { uchar orient; ushort material, tex; ivec n; int offset; }; -static inline bool htcmp(const cfkey &x, const cfkey &y) -{ +static inline bool htcmp(const cfkey &x, const cfkey &y) { return x.orient == y.orient && x.tex == y.tex && x.n == y.n && x.offset == y.offset && x.material==y.material; } -static inline uint hthash(const cfkey &k) -{ +static inline uint hthash(const cfkey &k) { return hthash(k.n)^k.offset^k.tex^k.orient^k.material; } -void mincubeface(const cube &cu, int orient, const ivec &o, int size, const facebounds &orig, facebounds &cf, ushort nmat, ushort matmask) -{ +void mincubeface(const cube &cu, int orient, const ivec &o, int size, const facebounds &orig, facebounds &cf, ushort nmat, ushort matmask) { int dim = dimension(orient); - if(cu.children) - { + if(cu.children) { size >>= 1; int coord = dimcoord(orient); loopi(8) if(octacoord(dim, i) == coord) @@ -1344,8 +1136,7 @@ void mincubeface(const cube &cu, int orient, const ivec &o, int size, const face uc2 = min(uc2, orig.u2); vc1 = max(vc1, orig.v1); vc2 = min(vc2, orig.v2); - if(!isempty(cu) && touchingface(cu, orient) && !(nmat!=MAT_AIR && (cu.material&matmask)==nmat)) - { + if(!isempty(cu) && touchingface(cu, orient) && !(nmat!=MAT_AIR && (cu.material&matmask)==nmat)) { uchar r1 = cu.edges[faceedgesidx[orient][0]], r2 = cu.edges[faceedgesidx[orient][1]], c1 = cu.edges[faceedgesidx[orient][2]], c2 = cu.edges[faceedgesidx[orient][3]]; ushort u1 = max(c1&0xF, c2&0xF)*size+uco, u2 = min(c1>>4, c2>>4)*size+uco, @@ -1354,14 +1145,12 @@ void mincubeface(const cube &cu, int orient, const ivec &o, int size, const face u2 = min(u2, orig.u2); v1 = max(v1, orig.v1); v2 = min(v2, orig.v2); - if(v2-v1==vc2-vc1) - { + if(v2-v1==vc2-vc1) { if(u2-u1==uc2-uc1) return; if(u1==uc1) uc1 = u2; if(u2==uc2) uc2 = u1; } - else if(u2-u1==uc2-uc1) - { + else if(u2-u1==uc2-uc1) { if(v1==vc1) vc1 = v2; if(v2==vc2) vc2 = v1; } @@ -1373,8 +1162,7 @@ void mincubeface(const cube &cu, int orient, const ivec &o, int size, const face cf.v2 = max(cf.v2, vc2); } -bool mincubeface(const cube &cu, int orient, const ivec &co, int size, facebounds &orig) -{ +bool mincubeface(const cube &cu, int orient, const ivec &co, int size, facebounds &orig) { ivec no; int nsize; const cube &nc = neighbourcube(cu, orient, co, size, no, nsize); @@ -1395,24 +1183,18 @@ bool mincubeface(const cube &cu, int orient, const ivec &co, int size, facebound VAR(maxmerge, 0, 6, 12); VAR(minface, 0, 4, 12); -struct pvert -{ +struct pvert { ushort x, y; - pvert() {} pvert(ushort x, ushort y) : x(x), y(y) {} - bool operator==(const pvert &o) const { return x == o.x && y == o.y; } bool operator!=(const pvert &o) const { return x != o.x || y != o.y; } }; -struct pedge -{ +struct pedge { pvert from, to; - pedge() {} pedge(const pvert &from, const pvert &to) : from(from), to(to) {} - bool operator==(const pedge &o) const { return from == o.from && to == o.to; } bool operator!=(const pedge &o) const { return from != o.from || to != o.to; } }; @@ -1420,35 +1202,28 @@ struct pedge static inline uint hthash(const pedge &x) { return uint(x.from.x)^(uint(x.from.y)<<8); } static inline bool htcmp(const pedge &x, const pedge &y) { return x == y; } -struct poly -{ +struct poly { cube *c; int numverts; bool merged; pvert verts[MAXFACEVERTS]; }; -bool clippoly(poly &p, const facebounds &b) -{ +bool clippoly(poly &p, const facebounds &b) { pvert verts1[MAXFACEVERTS+4], verts2[MAXFACEVERTS+4]; int numverts1 = 0, numverts2 = 0, px = p.verts[p.numverts-1].x, py = p.verts[p.numverts-1].y; - loopi(p.numverts) - { + loopi(p.numverts) { int x = p.verts[i].x, y = p.verts[i].y; - if(x < b.u1) - { + if(x < b.u1) { if(px > b.u2) verts1[numverts1++] = pvert(b.u2, y + ((y - py)*(b.u2 - x))/(x - px)); if(px > b.u1) verts1[numverts1++] = pvert(b.u1, y + ((y - py)*(b.u1 - x))/(x - px)); } - else if(x > b.u2) - { + else if(x > b.u2) { if(px < b.u1) verts1[numverts1++] = pvert(b.u1, y + ((y - py)*(b.u1 - x))/(x - px)); if(px < b.u2) verts1[numverts1++] = pvert(b.u2, y + ((y - py)*(b.u2 - x))/(x - px)); } - else - { - if(px < b.u1) - { + else { + if(px < b.u1) { if(x > b.u1) verts1[numverts1++] = pvert(b.u1, y + ((y - py)*(b.u1 - x))/(x - px)); } else if(px > b.u2 && x < b.u2) verts1[numverts1++] = pvert(b.u2, y + ((y - py)*(b.u2 - x))/(x - px)); @@ -1460,23 +1235,18 @@ bool clippoly(poly &p, const facebounds &b) if(numverts1 < 3) return false; px = verts1[numverts1-1].x; py = verts1[numverts1-1].y; - loopi(numverts1) - { + loopi(numverts1) { int x = verts1[i].x, y = verts1[i].y; - if(y < b.v1) - { + if(y < b.v1) { if(py > b.v2) verts2[numverts2++] = pvert(x + ((x - px)*(b.v2 - y))/(y - py), b.v2); if(py > b.v1) verts2[numverts2++] = pvert(x + ((x - px)*(b.v1 - y))/(y - py), b.v1); } - else if(y > b.v2) - { + else if(y > b.v2) { if(py < b.v1) verts2[numverts2++] = pvert(x + ((x - px)*(b.v1 - y))/(y - py), b.v1); if(py < b.v2) verts2[numverts2++] = pvert(x + ((x - px)*(b.v2 - y))/(y - py), b.v2); } - else - { - if(py < b.v1) - { + else { + if(py < b.v1) { if(y > b.v1) verts2[numverts2++] = pvert(x + ((x - px)*(b.v1 - y))/(y - py), b.v1); } else if(py > b.v2 && y < b.v2) verts2[numverts2++] = pvert(x + ((x - px)*(b.v2 - y))/(y - py), b.v2); @@ -1492,47 +1262,38 @@ bool clippoly(poly &p, const facebounds &b) return true; } -bool genpoly(cube &cu, int orient, const ivec &o, int size, int vis, ivec &n, int &offset, poly &p) -{ +bool genpoly(cube &cu, int orient, const ivec &o, int size, int vis, ivec &n, int &offset, poly &p) { int dim = dimension(orient), coord = dimcoord(orient); ivec v[4]; genfaceverts(cu, orient, v); - if(flataxisface(cu, orient)) - { + if(flataxisface(cu, orient)) { n = ivec(0, 0, 0); n[dim] = coord ? 1 : -1; } - else - { + else { if(faceconvexity(v)) return false; n.cross(ivec(v[1]).sub(v[0]), ivec(v[2]).sub(v[0])); if(n.iszero()) n.cross(ivec(v[2]).sub(v[0]), ivec(v[3]).sub(v[0])); reduceslope(n); } - ivec po = ivec(o).mask(0xFFF).shl(3); loopk(4) v[k].mul(size).add(po); offset = -n.dot(v[3]); - int r = R[dim], c = C[dim], order = vis&4 ? 1 : 0; p.numverts = 0; - if(coord) - { + if(coord) { const ivec &v0 = v[order]; p.verts[p.numverts++] = pvert(v0[c], v0[r]); if(vis&1) { const ivec &v1 = v[order+1]; p.verts[p.numverts++] = pvert(v1[c], v1[r]); } const ivec &v2 = v[order+2]; p.verts[p.numverts++] = pvert(v2[c], v2[r]); if(vis&2) { const ivec &v3 = v[(order+3)&3]; p.verts[p.numverts++] = pvert(v3[c], v3[r]); } } - else - { + else { if(vis&2) { const ivec &v3 = v[(order+3)&3]; p.verts[p.numverts++] = pvert(v3[c], v3[r]); } const ivec &v2 = v[order+2]; p.verts[p.numverts++] = pvert(v2[c], v2[r]); if(vis&1) { const ivec &v1 = v[order+1]; p.verts[p.numverts++] = pvert(v1[c], v1[r]); } const ivec &v0 = v[order]; p.verts[p.numverts++] = pvert(v0[c], v0[r]); } - - if(faceedges(cu, orient)!=F_SOLID) - { + if(faceedges(cu, orient)!=F_SOLID) { int px = int(p.verts[p.numverts-2].x) - int(p.verts[p.numverts-3].x), py = int(p.verts[p.numverts-2].y) - int(p.verts[p.numverts-3].y), cx = int(p.verts[p.numverts-1].x) - int(p.verts[p.numverts-2].x), cy = int(p.verts[p.numverts-1].y) - int(p.verts[p.numverts-2].y), dir = px*cy - py*cx; @@ -1554,17 +1315,13 @@ bool genpoly(cube &cu, int orient, const ivec &o, int size, int vis, ivec &n, in if(dir > 0) return false; if(!dir) { if(p.numverts < 4) return false; p.verts[1] = p.verts[2]; p.verts[2] = p.verts[3]; p.numverts--; } } - p.c = &cu; p.merged = false; - - if(minface && size >= 1<<minface && touchingface(cu, orient)) - { + if(minface && size >= 1<<minface && touchingface(cu, orient)) { facebounds b; b.u1 = b.u2 = p.verts[0].x; b.v1 = b.v2 = p.verts[0].y; - for(int i = 1; i < p.numverts; i++) - { + for(int i = 1; i < p.numverts; i++) { const pvert &v = p.verts[i]; b.u1 = min(b.u1, v.x); b.u2 = max(b.u2, v.x); @@ -1574,22 +1331,17 @@ bool genpoly(cube &cu, int orient, const ivec &o, int size, int vis, ivec &n, in if(mincubeface(cu, orient, o, size, b) && clippoly(p, b)) p.merged = true; } - return true; } -struct plink : pedge -{ +struct plink : pedge { int polys[2]; - plink() { clear(); } plink(const pedge &p) : pedge(p) { clear(); } - void clear() { polys[0] = polys[1] = -1; } }; -bool mergepolys(int orient, hashset<plink> &links, vector<plink *> &queue, int owner, poly &p, poly &q, const pedge &e) -{ +bool mergepolys(int orient, hashset<plink> &links, vector<plink *> &queue, int owner, poly &p, poly &q, const pedge &e) { int pe = -1, qe = -1; loopi(p.numverts) if(p.verts[i] == e.from) { pe = i; break; } loopi(q.numverts) if(q.verts[i] == e.to) { qe = i; break; } @@ -1604,15 +1356,13 @@ bool mergepolys(int orient, hashset<plink> &links, vector<plink *> &queue, int o */ pvert verts[2*MAXFACEVERTS]; int numverts = 0, index = pe+2; // starts at A = T+1, ends at F = T+p.numverts - loopi(p.numverts-1) - { + loopi(p.numverts-1) { if(index >= p.numverts) index -= p.numverts; verts[numverts++] = p.verts[index++]; } index = qe+2; // starts at C = T+2 = F+1, ends at T = T+q.numverts int px = int(verts[numverts-1].x) - int(verts[numverts-2].x), py = int(verts[numverts-1].y) - int(verts[numverts-2].y); - loopi(q.numverts-1) - { + loopi(q.numverts-1) { if(index >= q.numverts) index -= q.numverts; pvert &src = q.verts[index++]; int cx = int(src.x) - int(verts[numverts-1].x), cy = int(src.y) - int(verts[numverts-1].y), @@ -1627,19 +1377,14 @@ bool mergepolys(int orient, hashset<plink> &links, vector<plink *> &queue, int o dir = px*cy - py*cx; if(dir > 0) return false; if(!dir) numverts--; - if(numverts > MAXFACEVERTS) return false; - q.merged = true; q.numverts = 0; - p.merged = true; p.numverts = numverts; memcpy(p.verts, verts, numverts*sizeof(pvert)); - int prev = p.numverts-1; - loopj(p.numverts) - { + loopj(p.numverts) { pedge e(p.verts[prev], p.verts[j]); int order = e.from.x > e.to.x || (e.from.x == e.to.x && e.from.y > e.to.y) ? 1 : 0; if(order) swap(e.from, e.to); @@ -1649,15 +1394,12 @@ bool mergepolys(int orient, hashset<plink> &links, vector<plink *> &queue, int o if(shouldqueue) queue.add(&l); prev = j; } - return true; } -void addmerge(cube &cu, int orient, const ivec &co, const ivec &n, int offset, poly &p) -{ +void addmerge(cube &cu, int orient, const ivec &co, const ivec &n, int offset, poly &p) { cu.merged |= 1<<orient; - if(!p.numverts) - { + if(!p.numverts) { if(cu.ext) cu.ext->surfaces[orient] = ambientsurface; return; } @@ -1665,8 +1407,7 @@ void addmerge(cube &cu, int orient, const ivec &co, const ivec &n, int offset, p vertinfo verts[MAXFACEVERTS]; surf.numverts |= p.numverts; int dim = dimension(orient), coord = dimcoord(orient), c = C[dim], r = R[dim]; - loopk(p.numverts) - { + loopk(p.numverts) { pvert &src = p.verts[coord ? k : p.numverts-1-k]; vertinfo &dst = verts[k]; ivec v; @@ -1675,18 +1416,14 @@ void addmerge(cube &cu, int orient, const ivec &co, const ivec &n, int offset, p v[dim] = -(offset + n[c]*src.x + n[r]*src.y)/n[dim]; dst.set(v); } - if(cu.ext) - { + if(cu.ext) { const surfaceinfo &oldsurf = cu.ext->surfaces[orient]; int numverts = oldsurf.numverts&MAXFACEVERTS; - if(numverts == p.numverts) - { + if(numverts == p.numverts) { ivec v0 = verts[0].getxyz(); const vertinfo *oldverts = cu.ext->verts() + oldsurf.verts; - loopj(numverts) if(v0 == oldverts[j].getxyz()) - { - for(int k = 1; k < numverts; k++) - { + loopj(numverts) if(v0 == oldverts[j].getxyz()) { + for(int k = 1; k < numverts; k++) { if(++j >= numverts) j = 0; if(verts[k].getxyz() != oldverts[j].getxyz()) goto nomatch; } @@ -1698,36 +1435,29 @@ void addmerge(cube &cu, int orient, const ivec &co, const ivec &n, int offset, p setsurface(cu, orient, surf, verts, p.numverts); } -static inline void clearmerge(cube &c, int orient) -{ - if(c.merged&(1<<orient)) - { +static inline void clearmerge(cube &c, int orient) { + if(c.merged&(1<<orient)) { c.merged &= ~(1<<orient); if(c.ext) c.ext->surfaces[orient] = brightsurface; } } -void addmerges(int orient, const ivec &co, const ivec &n, int offset, vector<poly> &polys) -{ - loopv(polys) - { +void addmerges(int orient, const ivec &co, const ivec &n, int offset, vector<poly> &polys) { + loopv(polys) { poly &p = polys[i]; if(p.merged) addmerge(*p.c, orient, co, n, offset, p); else clearmerge(*p.c, orient); } } -void mergepolys(int orient, const ivec &co, const ivec &n, int offset, vector<poly> &polys) -{ +void mergepolys(int orient, const ivec &co, const ivec &n, int offset, vector<poly> &polys) { if(polys.length() <= 1) { addmerges(orient, co, n, offset, polys); return; } hashset<plink> links(polys.length() <= 32 ? 128 : 1024); vector<plink *> queue; - loopv(polys) - { + loopv(polys) { poly &p = polys[i]; int prev = p.numverts-1; - loopj(p.numverts) - { + loopj(p.numverts) { pedge e(p.verts[prev], p.verts[j]); int order = e.from.x > e.to.x || (e.from.x == e.to.x && e.from.y > e.to.y) ? 1 : 0; if(order) swap(e.from, e.to); @@ -1738,10 +1468,8 @@ void mergepolys(int orient, const ivec &co, const ivec &n, int offset, vector<po } } vector<plink *> nextqueue; - while(queue.length()) - { - loopv(queue) - { + while(queue.length()) { + loopv(queue) { plink &l = *queue[i]; if(l.polys[0] >= 0 && l.polys[1] >= 0) mergepolys(orient, links, nextqueue, l.polys[0], polys[l.polys[0]], polys[l.polys[1]], l); @@ -1754,30 +1482,24 @@ void mergepolys(int orient, const ivec &co, const ivec &n, int offset, vector<po static int genmergeprogress = 0; -struct cfpolys -{ +struct cfpolys { vector<poly> polys; }; static hashtable<cfkey, cfpolys> cpolys; -void genmerges(cube *c = worldroot, const ivec &o = ivec(0, 0, 0), int size = worldsize>>1) -{ +void genmerges(cube *c = worldroot, const ivec &o = ivec(0, 0, 0), int size = worldsize>>1) { if((genmergeprogress++&0xFFF)==0) renderprogress(float(genmergeprogress)/allocnodes, "merging faces..."); neighbourstack[++neighbourdepth] = c; - loopi(8) - { + loopi(8) { ivec co(i, o, size); int vis; if(c[i].children) genmerges(c[i].children, co, size>>1); - else if(!isempty(c[i])) loopj(6) if((vis = visibletris(c[i], j, co, size))) - { + else if(!isempty(c[i])) loopj(6) if((vis = visibletris(c[i], j, co, size))) { cfkey k; poly p; - if(size < 1<<maxmerge && c != worldroot) - { - if(genpoly(c[i], j, co, size, vis, k.n, k.offset, p)) - { + if(size < 1<<maxmerge && c != worldroot) { + if(genpoly(c[i], j, co, size, vis, k.n, k.offset, p)) { k.orient = j; k.tex = c[i].texture[j]; k.material = c[i].material&MAT_ALPHA; @@ -1785,20 +1507,16 @@ void genmerges(cube *c = worldroot, const ivec &o = ivec(0, 0, 0), int size = wo continue; } } - else if(minface && size >= 1<<minface && touchingface(c[i], j)) - { - if(genpoly(c[i], j, co, size, vis, k.n, k.offset, p) && p.merged) - { + else if(minface && size >= 1<<minface && touchingface(c[i], j)) { + if(genpoly(c[i], j, co, size, vis, k.n, k.offset, p) && p.merged) { addmerge(c[i], j, co, k.n, k.offset, p); continue; } } clearmerge(c[i], j); } - if((size == 1<<maxmerge || c == worldroot) && cpolys.numelems) - { - enumeratekt(cpolys, cfkey, key, cfpolys, val, - { + if((size == 1<<maxmerge || c == worldroot) && cpolys.numelems) { + enumeratekt(cpolys, cfkey, key, cfpolys, val, { mergepolys(key.orient, co, key.n, key.offset, val.polys); }); cpolys.clear(); @@ -1807,12 +1525,10 @@ void genmerges(cube *c = worldroot, const ivec &o = ivec(0, 0, 0), int size = wo --neighbourdepth; } -int calcmergedsize(int orient, const ivec &co, int size, const vertinfo *verts, int numverts) -{ +int calcmergedsize(int orient, const ivec &co, int size, const vertinfo *verts, int numverts) { ushort x1 = verts[0].x, y1 = verts[0].y, z1 = verts[0].z, x2 = x1, y2 = y1, z2 = z1; - for(int i = 1; i < numverts; i++) - { + for(int i = 1; i < numverts; i++) { const vertinfo &v = verts[i]; x1 = min(x1, v.x); x2 = max(x2, v.x); @@ -1827,8 +1543,7 @@ int calcmergedsize(int orient, const ivec &co, int size, const vertinfo *verts, ivec mo(co); mo.mask(0xFFF); mo.shl(3); - while(bits<15) - { + while(bits<15) { mo.mask(~((1<<bits)-1)); if(mo.x <= x1 && mo.x + (1<<bits) >= x2 && mo.y <= y1 && mo.y + (1<<bits) >= y2 && @@ -1839,17 +1554,13 @@ int calcmergedsize(int orient, const ivec &co, int size, const vertinfo *verts, return bits-3; } -static void invalidatemerges(cube &c) -{ - if(c.merged) - { +static void invalidatemerges(cube &c) { + if(c.merged) { brightencube(c); c.merged = 0; } - if(c.ext) - { - if(c.ext->va) - { + if(c.ext) { + if(c.ext->va) { if(!(c.ext->va->hasmerges&(MERGE_PART | MERGE_ORIGIN))) return; destroyva(c.ext->va); c.ext->va = NULL; @@ -1861,18 +1572,15 @@ static void invalidatemerges(cube &c) static int invalidatedmerges = 0; -void invalidatemerges(cube &c, const ivec &co, int size, bool msg) -{ - if(msg && invalidatedmerges!=totalmillis) - { +void invalidatemerges(cube &c, const ivec &co, int size, bool msg) { + if(msg && invalidatedmerges!=totalmillis) { renderprogress(0, "invalidating merged surfaces..."); invalidatedmerges = totalmillis; } invalidatemerges(c); } -void calcmerges() -{ +void calcmerges() { genmergeprogress = 0; genmerges(); } diff --git a/src/engine/octa.h b/src/engine/octa.h index 9452ad0..d8a2c45 100644 --- a/src/engine/octa.h +++ b/src/engine/octa.h @@ -1,34 +1,28 @@ // 6-directional octree heightfield map format -struct elementset -{ +struct elementset { ushort texture, lmid; uchar dim, layer; ushort length[2], minvert[2], maxvert[2]; }; -struct materialsurface -{ +struct materialsurface { ivec o; ushort csize, rsize; ushort material, skip; uchar orient, visible; - union - { + union { short index; short depth; }; - union - { + union { entity *light; uchar ends; }; }; -struct vertinfo -{ +struct vertinfo { ushort x, y, z, u, v, norm; - void setxyz(ushort a, ushort b, ushort c) { x = a; y = b; z = c; } void setxyz(const ivec &v) { setxyz(v.x, v.y, v.z); } void set(ushort a, ushort b, ushort c, ushort s = 0, ushort t = 0, ushort n = 0) { setxyz(a, b, c); u = s; v = t; norm = n; } @@ -36,24 +30,19 @@ struct vertinfo ivec getxyz() const { return ivec(x, y, z); } }; -enum -{ +enum { LAYER_TOP = (1<<5), LAYER_BOTTOM = (1<<6), LAYER_DUP = (1<<7), - LAYER_BLEND = LAYER_TOP|LAYER_BOTTOM, - MAXFACEVERTS = 15 }; enum { LMID_AMBIENT = 0, LMID_AMBIENT1, LMID_BRIGHT, LMID_BRIGHT1, LMID_DARK, LMID_DARK1, LMID_RESERVED }; -struct surfaceinfo -{ +struct surfaceinfo { uchar lmid[2]; uchar verts, numverts; - int totalverts() const { return numverts&LAYER_DUP ? (numverts&MAXFACEVERTS)*2 : numverts&MAXFACEVERTS; } bool used() const { return lmid[0] != LMID_AMBIENT || lmid[1] != LMID_AMBIENT || numverts&~LAYER_TOP; } void clear() { lmid[0] = LMID_AMBIENT; lmid[1] = LMID_AMBIENT; numverts = (numverts&MAXFACEVERTS) | LAYER_TOP; } @@ -64,8 +53,7 @@ static const surfaceinfo ambientsurface = {{LMID_AMBIENT, LMID_AMBIENT}, 0, LAYE static const surfaceinfo brightsurface = {{LMID_BRIGHT, LMID_AMBIENT}, 0, LAYER_TOP}; static const surfaceinfo brightbottomsurface = {{LMID_AMBIENT, LMID_BRIGHT}, 0, LAYER_BOTTOM}; -struct occludequery -{ +struct occludequery { void *owner; GLuint id; int fragments; @@ -73,8 +61,7 @@ struct occludequery struct vtxarray; -struct octaentities -{ +struct octaentities { vector<int> mapmodels; vector<int> other; occludequery *query; @@ -83,30 +70,25 @@ struct octaentities ivec o; int size; ivec bbmin, bbmax; - - octaentities(const ivec &o, int size) : query(0), o(o), size(size), bbmin(o), bbmax(o) - { + octaentities(const ivec &o, int size) : query(0), o(o), size(size), bbmin(o), bbmax(o) { bbmin.add(size); } }; -enum -{ +enum { OCCLUDE_NOTHING = 0, OCCLUDE_GEOM, OCCLUDE_BB, OCCLUDE_PARENT }; -enum -{ +enum { MERGE_ORIGIN = 1<<0, MERGE_PART = 1<<1, MERGE_USE = 1<<2 }; -struct vtxarray -{ +struct vtxarray { vtxarray *parent; vector<vtxarray *> children; vtxarray *next, *rnext; // linked list of visible VOBs @@ -134,8 +116,7 @@ struct vtxarray struct cube; -struct clipplanes -{ +struct clipplanes { vec o, r, v[8]; plane p[12]; uchar side[12]; @@ -144,37 +125,30 @@ struct clipplanes int version; }; -struct facebounds -{ +struct facebounds { ushort u1, u2, v1, v2; - bool empty() const { return u1 >= u2 || v1 >= v2; } }; -struct tjoint -{ +struct tjoint { int next; ushort offset; uchar edge; }; -struct cubeext -{ +struct cubeext { vtxarray *va; // vertex array for children, or NULL octaentities *ents; // map entities inside cube surfaceinfo surfaces[6]; // render info for each surface int tjoints; // linked list of t-joints uchar maxverts; // allocated space for verts - vertinfo *verts() { return (vertinfo *)(this+1); } }; -struct cube -{ +struct cube { cube *children; // points to 8 cube structures which are its children, or NULL. -Z first, then -Y, -X cubeext *ext; // extended info for the cube - union - { + union { uchar edges[12]; // edges of the cube, each uchar is 2 4bit values denoting the range. // see documentation jpgs for more info. uint faces[3]; // 4 edges of each dimension together representing 2 perpendicular faces @@ -182,38 +156,32 @@ struct cube ushort texture[6]; // one for each face. same order as orient. ushort material; // empty-space material uchar merged; // merged faces of the cube - union - { + union { uchar escaped; // mask of which children have escaped merges uchar visible; // visibility info for faces }; }; -struct block3 -{ +struct block3 { ivec o, s; int grid, orient; block3() {} block3(const selinfo &sel) : o(sel.o), s(sel.s), grid(sel.grid), orient(sel.orient) {} - cube *c() { return (cube *)(this+1); } + cube *c() { return (cube *)(this+1); } int size() const { return s.x*s.y*s.z; } }; -struct editinfo -{ +struct editinfo { block3 *copy; editinfo() : copy(NULL) {} }; -struct undoent { int i; entity e; }; -struct undoblock // undo header, all data sits in payload -{ +struct undoent { int i; entity e; }; +struct undoblock { // undo header, all data sits in payload { undoblock *prev, *next; int size, timestamp, numents; // if numents is 0, is a cube undo record, otherwise an entity undo record - block3 *block() { return (block3 *)(this + 1); } - uchar *gridmap() - { + uchar *gridmap() { block3 *ub = block(); return (uchar *)(ub->c() + ub->size()); } @@ -245,8 +213,7 @@ const uint F_SOLID = 0x80808080; // all edges in the range (0,8) #define octaindex(d,x,y,z) (((z)<<D[d])+((y)<<C[d])+((x)<<R[d])) #define octastep(x, y, z, scale) (((((z)>>(scale))&1)<<2) | ((((y)>>(scale))&1)<<1) | (((x)>>(scale))&1)) -static inline uchar octaboxoverlap(const ivec &o, int size, const ivec &bbmin, const ivec &bbmax) -{ +static inline uchar octaboxoverlap(const ivec &o, int size, const ivec &bbmin, const ivec &bbmax) { uchar p = 0xFF; // bitmask of possible collisions with octants. 0 bit = 0 octant, etc ivec mid = ivec(o).add(size); if(mid.z <= bbmin.z) p &= 0xF0; // not in a -ve Z octant @@ -261,8 +228,7 @@ static inline uchar octaboxoverlap(const ivec &o, int size, const ivec &bbmin, c #define loopoctabox(o, size, bbmin, bbmax) uchar possible = octaboxoverlap(o, size, bbmin, bbmax); loopi(8) if(possible&(1<<i)) #define loopoctaboxsize(o, size, bborigin, bbsize) uchar possible = octaboxoverlap(o, size, bborigin, ivec(bborigin).add(bbsize)); loopi(8) if(possible&(1<<i)) -enum -{ +enum { O_LEFT = 0, O_RIGHT, O_BACK, @@ -275,8 +241,7 @@ enum #define dimcoord(orient) ((orient)&1) #define opposite(orient) ((orient)^1) -enum -{ +enum { VFC_FULL_VISIBLE = 0, VFC_PART_VISIBLE, VFC_NOT_VISIBLE, diff --git a/src/engine/octaedit.cpp b/src/engine/octaedit.cpp index fb37088..0da305d 100644 --- a/src/engine/octaedit.cpp +++ b/src/engine/octaedit.cpp @@ -4,21 +4,16 @@ extern int outline; bool boxoutline = false; -void boxs(int orient, vec o, const vec &s, float size) -{ +void boxs(int orient, vec o, const vec &s, float size) { int d = dimension(orient), dc = dimcoord(orient); float f = boxoutline ? (dc>0 ? 0.2f : -0.2f) : 0; o[D[d]] += dc * s[D[d]] + f; - vec r(0, 0, 0), c(0, 0, 0); r[R[d]] = s[R[d]]; c[C[d]] = s[C[d]]; - vec v1 = o, v2 = vec(o).add(r), v3 = vec(o).add(r).add(c), v4 = vec(o).add(c); - r[R[d]] = 0.5f*size; c[C[d]] = 0.5f*size; - gle::defvertex(); gle::begin(GL_TRIANGLE_STRIP); gle::attrib(vec(v1).sub(r).sub(c)); @@ -34,53 +29,43 @@ void boxs(int orient, vec o, const vec &s, float size) xtraverts += gle::end(); } -void boxs(int orient, vec o, const vec &s) -{ +void boxs(int orient, vec o, const vec &s) { int d = dimension(orient), dc = dimcoord(orient); float f = boxoutline ? (dc>0 ? 0.2f : -0.2f) : 0; o[D[d]] += dc * s[D[d]] + f; - gle::defvertex(); gle::begin(GL_LINE_LOOP); - gle::attrib(o); o[R[d]] += s[R[d]]; gle::attrib(o); o[C[d]] += s[C[d]]; gle::attrib(o); o[R[d]] -= s[R[d]]; gle::attrib(o); - xtraverts += gle::end(); } -void boxs3D(const vec &o, vec s, int g) -{ +void boxs3D(const vec &o, vec s, int g) { s.mul(g); loopi(6) boxs(i, o, s); } -void boxsgrid(int orient, vec o, vec s, int g) -{ +void boxsgrid(int orient, vec o, vec s, int g) { int d = dimension(orient), dc = dimcoord(orient); float ox = o[R[d]], oy = o[C[d]], xs = s[R[d]], ys = s[C[d]], f = boxoutline ? (dc>0 ? 0.2f : -0.2f) : 0; - o[D[d]] += dc * s[D[d]]*g + f; - gle::defvertex(); gle::begin(GL_LINES); - loop(x, xs) - { + loop(x, xs) { o[R[d]] += g; gle::attrib(o); o[C[d]] += ys*g; gle::attrib(o); o[C[d]] = oy; } - loop(y, ys) - { + loop(y, ys) { o[C[d]] += g; o[R[d]] = ox; gle::attrib(o); @@ -112,18 +97,15 @@ VARF(dragging, 0, 0, 1, ); int moving = 0; -ICOMMAND(moving, "b", (int *n), -{ - if(*n >= 0) - { +ICOMMAND(moving, "b", (int *n), { + if(*n >= 0) { if(!*n || (moving<=1 && !pointinsel(sel, vec(cur).add(1)))) moving = 0; else if(!moving) moving = 1; } intret(moving); }); -VARF(gridpower, 0, 3, 12, -{ +VARF(gridpower, 0, 3, 12, { if(dragging) return; gridsize = 1<<gridpower; if(gridsize>=worldsize) gridsize = worldsize/2; @@ -136,35 +118,29 @@ VAR(selectcorners, 0, 0, 1); void forcenextundo() { lastsel.orient = -1; } -void cubecancel() -{ +void cubecancel() { havesel = false; moving = dragging = passthroughsel = 0; forcenextundo(); } -void cancelsel() -{ +void cancelsel() { cubecancel(); entcancel(); } -void toggleedit(bool force) -{ - if(!force) - { +void toggleedit(bool force) { + if(!force) { if(!isconnected()) return; if(player->state!=CS_ALIVE && player->state!=CS_DEAD && player->state!=CS_EDITING) return; // do not allow dead players to edit to avoid state confusion if(!game::allowedittoggle()) return; // not in most multiplayer modes } - if(!(editmode = !editmode)) - { + if(!(editmode = !editmode)) { player->state = player->editstate; player->o.z -= player->eyeheight; // entinmap wants feet pos entinmap(player); // find spawn closest to current floating pos } - else - { + else { game::resetgamestate(); player->editstate = player->state; player->state = CS_EDITING; @@ -179,8 +155,7 @@ void toggleedit(bool force) VARP(editinview, 0, 1, 1); -bool noedit(bool view, bool msg) -{ +bool noedit(bool view, bool msg) { if(!editmode) { if(msg) conoutf(CON_ERROR, "operation only allowed in edit mode"); return true; } if(view || haveselent()) return false; float r = 1.0f; @@ -194,8 +169,7 @@ bool noedit(bool view, bool msg) return true; } -void reorient() -{ +void reorient() { sel.cx = 0; sel.cy = 0; sel.cxs = sel.s[R[dimension(orient)]]*2; @@ -203,18 +177,14 @@ void reorient() sel.orient = orient; } -void selextend() -{ +void selextend() { if(noedit(true)) return; - loopi(3) - { - if(cur[i]<sel.o[i]) - { + loopi(3) { + if(cur[i]<sel.o[i]) { sel.s[i] += (sel.o[i]-cur[i])/sel.grid; sel.o[i] = cur[i]; } - else if(cur[i]>=sel.o[i]+sel.s[i]*sel.grid) - { + else if(cur[i]>=sel.o[i]+sel.s[i]*sel.grid) { sel.s[i] = (cur[i]-sel.o[i])/sel.grid+1; } } @@ -232,23 +202,20 @@ ICOMMAND(selsave, "", (), { if(noedit(true)) return; savedsel = sel; }); ICOMMAND(selrestore, "", (), { if(noedit(true)) return; sel = savedsel; }); ICOMMAND(selswap, "", (), { if(noedit(true)) return; swap(sel, savedsel); }); -ICOMMAND(getselpos, "", (), -{ +ICOMMAND(getselpos, "", (), { if(noedit(true)) return; defformatstring(pos, "%s %s %s", floatstr(sel.o.x), floatstr(sel.o.y), floatstr(sel.o.z)); result(pos); }); -void setselpos(int *x, int *y, int *z) -{ +void setselpos(int *x, int *y, int *z) { if(noedit(moving!=0)) return; havesel = true; sel.o = ivec(*x, *y, *z).mask(~(gridsize-1)); } COMMAND(setselpos, "iii"); -void movesel(int *dir, int *dim) -{ +void movesel(int *dir, int *dim) { if(noedit(moving!=0)) return; if(*dim < 0 || *dim > 2) return; sel.o[*dim] += *dir * sel.grid; @@ -257,8 +224,7 @@ COMMAND(movesel, "ii"); ///////// selection support ///////////// -cube &blockcube(int x, int y, int z, const block3 &b, int rgrid) // looks up a world cube, based on coordinates mapped by the block -{ +cube &blockcube(int x, int y, int z, const block3 &b, int rgrid) { // looks up a world cube, based on coordinates mapped by the block { int dim = dimension(b.orient), dc = dimcoord(b.orient); ivec s(dim, x*b.grid, y*b.grid, dc*(b.s[dim]-1)*b.grid); s.add(b.o); @@ -277,18 +243,14 @@ int selchildcount = 0, selchildmat = -1; ICOMMAND(havesel, "", (), intret(havesel ? selchildcount : 0)); -void countselchild(cube *c, const ivec &cor, int size) -{ +void countselchild(cube *c, const ivec &cor, int size) { ivec ss = ivec(sel.s).mul(sel.grid); - loopoctaboxsize(cor, size, sel.o, ss) - { + loopoctaboxsize(cor, size, sel.o, ss) { ivec o(i, cor, size); if(c[i].children) countselchild(c[i].children, o, size/2); - else - { + else { selchildcount++; - if(c[i].material != MAT_AIR && selchildmat != MAT_AIR) - { + if(c[i].material != MAT_AIR && selchildmat != MAT_AIR) { if(selchildmat < 0) selchildmat = c[i].material; else if(selchildmat != c[i].material) selchildmat = MAT_AIR; } @@ -296,16 +258,13 @@ void countselchild(cube *c, const ivec &cor, int size) } } -void normalizelookupcube(const ivec &o) -{ - if(lusize>gridsize) - { +void normalizelookupcube(const ivec &o) { + if(lusize>gridsize) { lu.x += (o.x-lu.x)/gridsize*gridsize; lu.y += (o.y-lu.y)/gridsize*gridsize; lu.z += (o.z-lu.z)/gridsize*gridsize; } - else if(gridsize>lusize) - { + else if(gridsize>lusize) { lu.x &= ~(gridsize-1); lu.y &= ~(gridsize-1); lu.z &= ~(gridsize-1); @@ -313,8 +272,7 @@ void normalizelookupcube(const ivec &o) lusize = gridsize; } -void updateselection() -{ +void updateselection() { sel.o.x = min(lastcur.x, cur.x); sel.o.y = min(lastcur.y, cur.y); sel.o.z = min(lastcur.z, cur.z); @@ -323,13 +281,11 @@ void updateselection() sel.s.z = abs(lastcur.z-cur.z)/sel.grid+1; } -bool editmoveplane(const vec &o, const vec &ray, int d, float off, vec &handle, vec &dest, bool first) -{ +bool editmoveplane(const vec &o, const vec &ray, int d, float off, vec &handle, vec &dest, bool first) { plane pl(d, off); float dist = 0.0f; if(!pl.rayintersect(player->o, ray, dist)) return false; - dest = vec(ray).mul(dist).add(player->o); if(first) handle = vec(dest).sub(o); dest.sub(handle); @@ -338,7 +294,7 @@ bool editmoveplane(const vec &o, const vec &ray, int d, float off, vec &handle, extern void entdrag(const vec &ray); extern bool hoveringonent(int ent, int orient); -extern void renderentselection(const vec &o, const vec &ray, bool entmoving); +extern void renderentselection(const vec &o, bool entmoving); extern float rayent(const vec &o, const vec &ray, float radius, int mode, int size, int &orient, int &ent); VAR(gridlookup, 0, 0, 1); @@ -346,21 +302,15 @@ VAR(passthroughcube, 0, 1, 1); VAR(passthroughent, 0, 1, 1); VARF(passthrough, 0, 0, 1, { passthroughsel = passthrough; entcancel(); }); -void rendereditcursor() -{ +void rendereditcursor() { int d = dimension(sel.orient), od = dimension(orient), odc = dimcoord(orient); - bool hidecursor = g3d_windowhit(true, false), hovering = false; - - if(moving) - { + if(moving) { static vec dest, handle; - if(editmoveplane(vec(sel.o), camdir, od, sel.o[D[od]]+odc*sel.grid*sel.s[D[od]], handle, dest, moving==1)) - { - if(moving==1) - { + if(editmoveplane(vec(sel.o), camdir, od, sel.o[D[od]]+odc*sel.grid*sel.s[D[od]], handle, dest, moving==1)) { + if(moving==1) { dest.add(handle); handle = vec(ivec(handle).mask(~(sel.grid-1))); dest.sub(handle); @@ -372,50 +322,40 @@ void rendereditcursor() } } else - if(entmoving) - { + if(entmoving) { entdrag(camdir); } - else - { + else { ivec w; float sdist = 0, wdist = 0, t; int entorient = 0, ent = -1; - wdist = rayent(player->o, camdir, 1e16f, (editmode && showmat ? RAY_EDITMAT : 0) // select cubes first | (!dragging && entediting && (!passthrough || !passthroughent) ? RAY_ENTS : 0) | RAY_SKIPFIRST | (passthroughcube || passthrough ? RAY_PASS : 0), gridsize, entorient, ent); - if((havesel || dragging) && !passthroughsel) // now try selecting the selection - if(rayboxintersect(vec(sel.o), vec(sel.s).mul(sel.grid), player->o, camdir, sdist, orient)) - { // and choose the nearest of the two - if(sdist < wdist) - { + if(rayboxintersect(vec(sel.o), vec(sel.s).mul(sel.grid), player->o, camdir, sdist, orient)) { + // and choose the nearest of the two + if(sdist < wdist) { wdist = sdist; ent = -1; } } - - if((hovering = hoveringonent(hidecursor ? -1 : ent, entorient))) - { + if((hovering = hoveringonent(hidecursor ? -1 : ent, entorient))) { if(!havesel) - { + { selchildcount = 0; selchildmat = -1; sel.s = ivec(0, 0, 0); } } - else - { + else { vec w = vec(camdir).mul(wdist+0.05f).add(player->o); - if(!insideworld(w)) - { + if(!insideworld(w)) { loopi(3) wdist = min(wdist, ((camdir[i] > 0 ? worldsize : 0) - player->o[i]) / camdir[i]); w = vec(camdir).mul(wdist-0.05f).add(player->o); - if(!insideworld(w)) - { + if(!insideworld(w)) { wdist = 0; loopi(3) w[i] = clamp(player->o[i], 0.0f, float(worldsize)); } @@ -429,17 +369,13 @@ void rendereditcursor() cor = ivec(vec(w).mul(2).div(gridsize)); od = dimension(orient); d = dimension(sel.orient); - - if(dragging) - { + if(dragging) { updateselection(); sel.cx = min(cor[R[d]], lastcor[R[d]]); sel.cy = min(cor[C[d]], lastcor[C[d]]); sel.cxs = max(cor[R[d]], lastcor[R[d]]); sel.cys = max(cor[C[d]], lastcor[C[d]]); - - if(!selectcorners) - { + if(!selectcorners) { sel.cx &= ~1; sel.cy &= ~1; sel.cxs &= ~1; @@ -447,18 +383,15 @@ void rendereditcursor() sel.cxs -= sel.cx-2; sel.cys -= sel.cy-2; } - else - { + else { sel.cxs -= sel.cx-1; sel.cys -= sel.cy-1; } - sel.cx &= 1; sel.cy &= 1; havesel = true; } - else if(!havesel) - { + else if(!havesel) { sel.o = lu; sel.s.x = sel.s.y = sel.s.z = 1; sel.cx = sel.cy = 0; @@ -467,41 +400,29 @@ void rendereditcursor() sel.orient = orient; d = od; } - sel.corner = (cor[R[d]]-(lu[R[d]]*2)/gridsize)+(cor[C[d]]-(lu[C[d]]*2)/gridsize)*2; selchildcount = 0; selchildmat = -1; countselchild(worldroot, ivec(0, 0, 0), worldsize/2); - if(mag>=1 && selchildcount==1) - { + if(mag>=1 && selchildcount==1) { selchildmat = c->material; if(mag>1) selchildcount = -mag; } } } - glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); - // cursors - notextureshader->set(); - - renderentselection(player->o, camdir, entmoving!=0); - + renderentselection(player->o, entmoving!=0); boxoutline = outline!=0; - enablepolygonoffset(GL_POLYGON_OFFSET_LINE); - - if(!moving && !hovering && !hidecursor) - { + if(!moving && !hovering && !hidecursor) { gle::colorub(120,120,120); boxs(orient, vec(lu), vec(lusize)); } - // selections - if(havesel || moving) - { + if(havesel || moving) { d = dimension(sel.orient); gle::colorub(50,50,50); // grid boxsgrid(sel.orient, vec(sel.o), vec(sel.s), sel.grid); @@ -518,16 +439,12 @@ void rendereditcursor() gle::colorub(0,0,120); boxs3D(vec(sel.o), vec(sel.s), sel.grid); } - disablepolygonoffset(GL_POLYGON_OFFSET_LINE); - boxoutline = false; - glDisable(GL_BLEND); } -void tryedit() -{ +void tryedit() { extern int hidehud; if(!editmode || hidehud || mainmenu) return; } @@ -536,15 +453,11 @@ void tryedit() static bool haschanged = false; -void readychanges(const ivec &bbmin, const ivec &bbmax, cube *c, const ivec &cor, int size) -{ - loopoctabox(cor, size, bbmin, bbmax) - { +void readychanges(const ivec &bbmin, const ivec &bbmax, cube *c, const ivec &cor, int size) { + loopoctabox(cor, size, bbmin, bbmax) { ivec o(i, cor, size); - if(c[i].ext) - { - if(c[i].ext->va) // removes va s so that octarender will recreate - { + if(c[i].ext) { + if(c[i].ext->va) { // removes va s so that octarender will recreate { int hasmerges = c[i].ext->va->hasmerges; destroyva(c[i].ext->va); c[i].ext->va = NULL; @@ -553,10 +466,8 @@ void readychanges(const ivec &bbmin, const ivec &bbmax, cube *c, const ivec &cor freeoctaentities(c[i]); c[i].ext->tjoints = -1; } - if(c[i].children) - { - if(size<=1) - { + if(c[i].children) { + if(size<=1) { solidfaces(c[i]); discardchildren(c[i], true); brightencube(c[i]); @@ -567,11 +478,9 @@ void readychanges(const ivec &bbmin, const ivec &bbmax, cube *c, const ivec &cor } } -void commitchanges(bool force) -{ +void commitchanges(bool force) { if(!force && !haschanged) return; haschanged = false; - int oldlen = valist.length(); resetclipplanes(); entitiesinoctanodes(); @@ -582,44 +491,37 @@ void commitchanges(bool force) updatevabbs(); } -void changed(const block3 &sel, bool commit = true) -{ +void changed(const block3 &sel, bool commit = true) { if(sel.s.iszero()) return; readychanges(ivec(sel.o).sub(1), ivec(sel.s).mul(sel.grid).add(sel.o).add(1), worldroot, ivec(0, 0, 0), worldsize/2); haschanged = true; - if(commit) commitchanges(); } //////////// copy and undo ///////////// -static inline void copycube(const cube &src, cube &dst) -{ +static inline void copycube(const cube &src, cube &dst) { dst = src; dst.visible = 0; dst.merged = 0; dst.ext = NULL; // src cube is responsible for va destruction - if(src.children) - { + if(src.children) { dst.children = newcubes(F_EMPTY); loopi(8) copycube(src.children[i], dst.children[i]); } } -static inline void pastecube(const cube &src, cube &dst) -{ +static inline void pastecube(const cube &src, cube &dst) { discardchildren(dst); copycube(src, dst); } -void blockcopy(const block3 &s, int rgrid, block3 *b) -{ +void blockcopy(const block3 &s, int rgrid, block3 *b) { *b = s; cube *q = b->c(); loopxyz(s, rgrid, copycube(c, *q++)); } -block3 *blockcopy(const block3 &s, int rgrid) -{ +block3 *blockcopy(const block3 &s, int rgrid) { int bsize = sizeof(block3)+sizeof(cube)*s.size(); if(bsize <= 0 || bsize > (100<<20)) return NULL; block3 *b = (block3 *)new (false) uchar[bsize]; @@ -627,41 +529,34 @@ block3 *blockcopy(const block3 &s, int rgrid) return b; } -void freeblock(block3 *b, bool alloced = true) -{ +void freeblock(block3 *b, bool alloced = true) { cube *q = b->c(); loopi(b->size()) discardchildren(*q++); if(alloced) delete[] b; } -void selgridmap(selinfo &sel, uchar *g) // generates a map of the cube sizes at each grid point -{ +void selgridmap(selinfo &sel, uchar *g) { // generates a map of the cube sizes at each grid point { loopxyz(sel, -sel.grid, (*g++ = bitscan(lusize), (void)c)); } -void freeundo(undoblock *u) -{ +void freeundo(undoblock *u) { if(!u->numents) freeblock(u->block(), false); delete[] (uchar *)u; } -void pasteundoblock(block3 *b, uchar *g) -{ +void pasteundoblock(block3 *b, uchar *g) { cube *s = b->c(); loopxyz(*b, 1<<min(int(*g++), worldscale-1), pastecube(*s++, c)); } -void pasteundo(undoblock *u) -{ +void pasteundo(undoblock *u) { if(u->numents) pasteundoents(u); else pasteundoblock(u->block(), u->gridmap()); } -static inline int undosize(undoblock *u) -{ +static inline int undosize(undoblock *u) { if(u->numents) return u->numents*sizeof(undoent); - else - { + else { block3 *b = u->block(); cube *q = b->c(); int size = b->size(), total = size; @@ -670,37 +565,27 @@ static inline int undosize(undoblock *u) } } -struct undolist -{ +struct undolist { undoblock *first, *last; - undolist() : first(NULL), last(NULL) {} - bool empty() { return !first; } - - void add(undoblock *u) - { + void add(undoblock *u) { u->next = NULL; u->prev = last; if(!first) first = last = u; - else - { + else { last->next = u; last = u; } } - - undoblock *popfirst() - { + undoblock *popfirst() { undoblock *u = first; first = first->next; if(first) first->prev = NULL; else last = NULL; return u; } - - undoblock *poplast() - { + undoblock *poplast() { undoblock *u = last; last = last->prev; if(last) last->next = NULL; @@ -713,17 +598,14 @@ undolist undos, redos; VARP(undomegs, 0, 8, 100); // bounded by n megs int totalundos = 0; -void pruneundos(int maxremain) // bound memory -{ - while(totalundos > maxremain && !undos.empty()) - { +void pruneundos(int maxremain) { // bound memory { + while(totalundos > maxremain && !undos.empty()) { undoblock *u = undos.popfirst(); totalundos -= u->size; freeundo(u); } //conoutf(CON_DEBUG, "undo: %d of %d(%%%d)", totalundos, undomegs<<20, totalundos*100/(undomegs<<20)); - while(!redos.empty()) - { + while(!redos.empty()) { undoblock *u = redos.popfirst(); totalundos -= u->size; freeundo(u); @@ -734,8 +616,7 @@ void clearundos() { pruneundos(0); } COMMAND(clearundos, ""); -undoblock *newundocube(selinfo &s) -{ +undoblock *newundocube(selinfo &s) { int ssize = s.size(), selgridsize = ssize, blocksize = sizeof(block3)+ssize*sizeof(cube); @@ -750,8 +631,7 @@ undoblock *newundocube(selinfo &s) return u; } -void addundo(undoblock *u) -{ +void addundo(undoblock *u) { u->size = undosize(u); u->timestamp = totalmillis; undos.add(u); @@ -761,21 +641,18 @@ void addundo(undoblock *u) VARP(nompedit, 0, 1, 1); -void makeundo(selinfo &s) -{ +void makeundo(selinfo &s) { undoblock *u = newundocube(s); if(u) addundo(u); } -void makeundo() // stores state of selected cubes before editing -{ +void makeundo() { // stores state of selected cubes before editing { if(lastsel==sel || sel.s.iszero()) return; lastsel=sel; makeundo(sel); } -static inline int countblock(cube *c, int n = 8) -{ +static inline int countblock(cube *c, int n = 8) { int r = 0; loopi(n) if(c[i].children) r += countblock(c[i].children); else ++r; return r; @@ -783,20 +660,16 @@ static inline int countblock(cube *c, int n = 8) static int countblock(block3 *b) { return countblock(b->c(), b->size()); } -void swapundo(undolist &a, undolist &b, int op) -{ +void swapundo(undolist &a, undolist &b, int op) { if(noedit()) return; if(a.empty()) { conoutf(CON_WARN, "nothing more to %s", op == EDIT_REDO ? "redo" : "undo"); return; } int ts = a.last->timestamp; - if(multiplayer(false)) - { + if(multiplayer(false)) { int n = 0, ops = 0; - for(undoblock *u = a.last; u && ts==u->timestamp; u = u->prev) - { + for(undoblock *u = a.last; u && ts==u->timestamp; u = u->prev) { ++ops; n += u->numents ? u->numents : countblock(u->block()); - if(ops > 10 || n > 2500) - { + if(ops > 10 || n > 2500) { conoutf(CON_WARN, "undo too big for multiplayer"); if(nompedit) { multiplayer(); return; } op = -1; @@ -805,13 +678,11 @@ void swapundo(undolist &a, undolist &b, int op) } } selinfo l = sel; - while(!a.empty() && ts==a.last->timestamp) - { + while(!a.empty() && ts==a.last->timestamp) { if(op >= 0) game::edittrigger(sel, op); undoblock *u = a.poplast(), *r; if(u->numents) r = copyundoents(u); - else - { + else { block3 *ub = u->block(); l.o = ub->o; l.s = ub->s; @@ -819,8 +690,7 @@ void swapundo(undolist &a, undolist &b, int op) l.orient = ub->orient; r = newundocube(l); } - if(r) - { + if(r) { r->size = u->size; r->timestamp = totalmillis; b.add(r); @@ -845,15 +715,12 @@ vector<editinfo *> editinfos; editinfo *localedit = NULL; template<class B> -static void packcube(cube &c, B &buf) -{ - if(c.children) - { +static void packcube(cube &c, B &buf) { + if(c.children) { buf.put(0xFF); loopi(8) packcube(c.children[i], buf); } - else - { + else { cube data = c; lilswap(data.texture, 6); buf.put(c.material&0xFF); @@ -864,8 +731,7 @@ static void packcube(cube &c, B &buf) } template<class B> -static bool packblock(block3 &b, B &buf) -{ +static bool packblock(block3 &b, B &buf) { if(b.size() <= 0 || b.size() > (1<<20)) return false; block3 hdr = b; lilswap(hdr.o.v, 3); @@ -878,23 +744,18 @@ static bool packblock(block3 &b, B &buf) return true; } -struct vslothdr -{ +struct vslothdr { ushort index; ushort slot; }; -static void packvslots(cube &c, vector<uchar> &buf, vector<ushort> &used) -{ - if(c.children) - { +static void packvslots(cube &c, vector<uchar> &buf, vector<ushort> &used) { + if(c.children) { loopi(8) packvslots(c.children[i], buf, used); } - else loopi(6) - { + else loopi(6) { ushort index = c.texture[i]; - if(vslots.inrange(index) && vslots[index]->changed && used.find(index) < 0) - { + if(vslots.inrange(index) && vslots[index]->changed && used.find(index) < 0) { used.add(index); VSlot &vs = *vslots[index]; vslothdr &hdr = *(vslothdr *)buf.pad(sizeof(vslothdr)); @@ -906,8 +767,7 @@ static void packvslots(cube &c, vector<uchar> &buf, vector<ushort> &used) } } -static void packvslots(block3 &b, vector<uchar> &buf) -{ +static void packvslots(block3 &b, vector<uchar> &buf) { vector<ushort> used; cube *c = b.c(); loopi(b.size()) packvslots(c[i], buf, used); @@ -915,16 +775,13 @@ static void packvslots(block3 &b, vector<uchar> &buf) } template<class B> -static void unpackcube(cube &c, B &buf) -{ +static void unpackcube(cube &c, B &buf) { int mat = buf.get(); - if(mat == 0xFF) - { + if(mat == 0xFF) { c.children = newcubes(F_EMPTY); loopi(8) unpackcube(c.children[i], buf); } - else - { + else { c.material = mat | (buf.get()<<8); buf.get(c.edges, sizeof(c.edges)); buf.get((uchar *)c.texture, sizeof(c.texture)); @@ -933,8 +790,7 @@ static void unpackcube(cube &c, B &buf) } template<class B> -static bool unpackblock(block3 *&b, B &buf) -{ +static bool unpackblock(block3 *&b, B &buf) { if(b) { freeblock(b); b = NULL; } block3 hdr; if(buf.get((uchar *)&hdr, sizeof(hdr)) < int(sizeof(hdr))) return false; @@ -952,33 +808,26 @@ static bool unpackblock(block3 *&b, B &buf) return true; } -struct vslotmap -{ +struct vslotmap { int index; VSlot *vslot; - vslotmap() {} vslotmap(int index, VSlot *vslot) : index(index), vslot(vslot) {} }; static vector<vslotmap> unpackingvslots; -static void unpackvslots(cube &c, ucharbuf &buf) -{ - if(c.children) - { +static void unpackvslots(cube &c, ucharbuf &buf) { + if(c.children) { loopi(8) unpackvslots(c.children[i], buf); } - else loopi(6) - { + else loopi(6) { ushort tex = c.texture[i]; loopvj(unpackingvslots) if(unpackingvslots[j].index == tex) { c.texture[i] = unpackingvslots[j].vslot->index; break; } } } -static void unpackvslots(block3 &b, ucharbuf &buf) -{ - while(buf.remaining() >= int(sizeof(vslothdr))) - { +static void unpackvslots(block3 &b, ucharbuf &buf) { + while(buf.remaining() >= int(sizeof(vslothdr))) { vslothdr &hdr = *(vslothdr *)buf.pad(sizeof(vslothdr)); lilswap(&hdr.index, 2); if(!hdr.index) break; @@ -989,20 +838,16 @@ static void unpackvslots(block3 &b, ucharbuf &buf) VSlot *edit = editvslot(vs, ds); unpackingvslots.add(vslotmap(hdr.index, edit ? edit : &vs)); } - cube *c = b.c(); loopi(b.size()) unpackvslots(c[i], buf); - unpackingvslots.setsize(0); } -static bool compresseditinfo(const uchar *inbuf, int inlen, uchar *&outbuf, int &outlen) -{ +static bool compresseditinfo(const uchar *inbuf, int inlen, uchar *&outbuf, int &outlen) { uLongf len = compressBound(inlen); if(len > (1<<20)) return false; outbuf = new (false) uchar[len]; - if(!outbuf || compress2((Bytef *)outbuf, &len, (const Bytef *)inbuf, inlen, Z_BEST_COMPRESSION) != Z_OK || len > (1<<16)) - { + if(!outbuf || compress2((Bytef *)outbuf, &len, (const Bytef *)inbuf, inlen, Z_BEST_COMPRESSION) != Z_OK || len > (1<<16)) { delete[] outbuf; outbuf = NULL; return false; @@ -1011,13 +856,11 @@ static bool compresseditinfo(const uchar *inbuf, int inlen, uchar *&outbuf, int return true; } -static bool uncompresseditinfo(const uchar *inbuf, int inlen, uchar *&outbuf, int &outlen) -{ +static bool uncompresseditinfo(const uchar *inbuf, int inlen, uchar *&outbuf, int &outlen) { if(compressBound(outlen) > (1<<20)) return false; uLongf len = outlen; outbuf = new (false) uchar[len]; - if(!outbuf || uncompress((Bytef *)outbuf, &len, (const Bytef *)inbuf, inlen) != Z_OK) - { + if(!outbuf || uncompress((Bytef *)outbuf, &len, (const Bytef *)inbuf, inlen) != Z_OK) { delete[] outbuf; outbuf = NULL; return false; @@ -1026,8 +869,7 @@ static bool uncompresseditinfo(const uchar *inbuf, int inlen, uchar *&outbuf, in return true; } -bool packeditinfo(editinfo *e, int &inlen, uchar *&outbuf, int &outlen) -{ +bool packeditinfo(editinfo *e, int &inlen, uchar *&outbuf, int &outlen) { vector<uchar> buf; if(!e || !e->copy || !packblock(*e->copy, buf)) return false; packvslots(*e->copy, buf); @@ -1035,15 +877,13 @@ bool packeditinfo(editinfo *e, int &inlen, uchar *&outbuf, int &outlen) return compresseditinfo(buf.getbuf(), buf.length(), outbuf, outlen); } -bool unpackeditinfo(editinfo *&e, const uchar *inbuf, int inlen, int outlen) -{ +bool unpackeditinfo(editinfo *&e, const uchar *inbuf, int inlen, int outlen) { if(e && e->copy) { freeblock(e->copy); e->copy = NULL; } uchar *outbuf = NULL; if(!uncompresseditinfo(inbuf, inlen, outbuf, outlen)) return false; ucharbuf buf(outbuf, outlen); if(!e) e = editinfos.add(new editinfo); - if(!unpackblock(e->copy, buf)) - { + if(!unpackblock(e->copy, buf)) { delete[] outbuf; return false; } @@ -1052,8 +892,7 @@ bool unpackeditinfo(editinfo *&e, const uchar *inbuf, int inlen, int outlen) return true; } -void freeeditinfo(editinfo *&e) -{ +void freeeditinfo(editinfo *&e) { if(!e) return; editinfos.removeobj(e); if(e->copy) freeblock(e->copy); @@ -1061,16 +900,13 @@ void freeeditinfo(editinfo *&e) e = NULL; } -bool packundo(undoblock *u, int &inlen, uchar *&outbuf, int &outlen) -{ +bool packundo(undoblock *u, int &inlen, uchar *&outbuf, int &outlen) { vector<uchar> buf; buf.reserve(512); *(ushort *)buf.pad(2) = lilswap(ushort(u->numents)); - if(u->numents) - { + if(u->numents) { undoent *ue = u->ents(); - loopi(u->numents) - { + loopi(u->numents) { *(ushort *)buf.pad(2) = lilswap(ushort(ue[i].i)); entity &e = *(entity *)buf.pad(sizeof(entity)); e = ue[i].e; @@ -1078,8 +914,7 @@ bool packundo(undoblock *u, int &inlen, uchar *&outbuf, int &outlen) lilswap(&e.attr1, 5); } } - else - { + else { block3 &b = *u->block(); if(!packblock(b, buf)) return false; buf.put(u->gridmap(), b.size()); @@ -1089,26 +924,21 @@ bool packundo(undoblock *u, int &inlen, uchar *&outbuf, int &outlen) return compresseditinfo(buf.getbuf(), buf.length(), outbuf, outlen); } -bool unpackundo(const uchar *inbuf, int inlen, int outlen) -{ +bool unpackundo(const uchar *inbuf, int inlen, int outlen) { uchar *outbuf = NULL; if(!uncompresseditinfo(inbuf, inlen, outbuf, outlen)) return false; ucharbuf buf(outbuf, outlen); - if(buf.remaining() < 2) - { + if(buf.remaining() < 2) { delete[] outbuf; return false; } int numents = lilswap(*(const ushort *)buf.pad(2)); - if(numents) - { - if(buf.remaining() < numents*int(2 + sizeof(entity))) - { + if(numents) { + if(buf.remaining() < numents*int(2 + sizeof(entity))) { delete[] outbuf; return false; } - loopi(numents) - { + loopi(numents) { int idx = lilswap(*(const ushort *)buf.pad(2)); entity &e = *(entity *)buf.pad(sizeof(entity)); lilswap(&e.o.x, 3); @@ -1116,11 +946,9 @@ bool unpackundo(const uchar *inbuf, int inlen, int outlen) pasteundoent(idx, e); } } - else - { + else { block3 *b = NULL; - if(!unpackblock(b, buf) || b->grid >= worldsize || buf.remaining() < b->size()) - { + if(!unpackblock(b, buf) || b->grid >= worldsize || buf.remaining() < b->size()) { freeblock(b); delete[] outbuf; return false; @@ -1136,33 +964,26 @@ bool unpackundo(const uchar *inbuf, int inlen, int outlen) return true; } -bool packundo(int op, int &inlen, uchar *&outbuf, int &outlen) -{ - switch(op) - { +bool packundo(int op, int &inlen, uchar *&outbuf, int &outlen) { + switch(op) { case EDIT_UNDO: return !undos.empty() && packundo(undos.last, inlen, outbuf, outlen); case EDIT_REDO: return !redos.empty() && packundo(redos.last, inlen, outbuf, outlen); default: return false; } } -struct prefabheader -{ +struct prefabheader { char magic[4]; int version; }; -struct prefab : editinfo -{ +struct prefab : editinfo { char *name; GLuint ebo, vbo; int numtris, numverts; - prefab() : name(NULL), ebo(0), vbo(0), numtris(0), numverts(0) {} ~prefab() { DELETEA(name); if(copy) freeblock(copy); } - - void cleanup() - { + void cleanup() { if(ebo) { glDeleteBuffers_(1, &ebo); ebo = 0; } if(vbo) { glDeleteBuffers_(1, &vbo); vbo = 0; } numtris = numverts = 0; @@ -1171,16 +992,13 @@ struct prefab : editinfo static hashnameset<prefab> prefabs; -void cleanupprefabs() -{ +void cleanupprefabs() { enumerate(prefabs, prefab, p, p.cleanup()); } -void delprefab(char *name) -{ +void delprefab(char *name) { prefab *p = prefabs.access(name); - if(p) - { + if(p) { p->cleanup(); prefabs.remove(name); conoutf("deleted prefab %s", name); @@ -1188,12 +1006,10 @@ void delprefab(char *name) } COMMAND(delprefab, "s"); -void saveprefab(char *name) -{ +void saveprefab(char *name) { if(!name[0] || noedit(true) || (nompedit && multiplayer())) return; prefab *b = prefabs.access(name); - if(!b) - { + if(!b) { b = &prefabs[name]; b->name = newstring(name); } @@ -1216,8 +1032,7 @@ void saveprefab(char *name) } COMMAND(saveprefab, "s"); -void pasteblock(block3 &b, selinfo &sel, bool local) -{ +void pasteblock(block3 &b, selinfo &sel, bool local) { sel.s = b.s; int o = sel.orient; sel.orient = b.orient; @@ -1226,13 +1041,11 @@ void pasteblock(block3 &b, selinfo &sel, bool local) sel.orient = o; } -bool prefabloaded(const char *name) -{ +bool prefabloaded(const char *name) { return prefabs.access(name) != NULL; } -prefab *loadprefab(const char *name, bool msg = true) -{ +prefab *loadprefab(const char *name, bool msg = true) { prefab *b = prefabs.access(name); if(b) return b; @@ -1256,31 +1069,24 @@ prefab *loadprefab(const char *name, bool msg = true) return b; } -void pasteprefab(char *name) -{ +void pasteprefab(char *name) { if(!name[0] || noedit() || (nompedit && multiplayer())) return; prefab *b = loadprefab(name, true); if(b) pasteblock(*b->copy, sel, true); } COMMAND(pasteprefab, "s"); -struct prefabmesh -{ +struct prefabmesh { struct vertex { vec pos; bvec4 norm; }; - static const int SIZE = 1<<9; int table[SIZE]; vector<vertex> verts; vector<int> chain; vector<ushort> tris; - prefabmesh() { memset(table, -1, sizeof(table)); } - - int addvert(const vertex &v) - { + int addvert(const vertex &v) { uint h = hthash(v.pos)&(SIZE-1); - for(int i = table[h]; i>=0; i = chain[i]) - { + for(int i = table[h]; i>=0; i = chain[i]) { const vertex &c = verts[i]; if(c.pos==v.pos && c.norm==v.norm) return i; } @@ -1289,28 +1095,21 @@ struct prefabmesh chain.add(table[h]); return table[h] = verts.length()-1; } - - int addvert(const vec &pos, const bvec &norm) - { + int addvert(const vec &pos, const bvec &norm) { vertex vtx; vtx.pos = pos; vtx.norm = norm; return addvert(vtx); } - - void setup(prefab &p) - { + void setup(prefab &p) { if(tris.empty()) return; - p.cleanup(); - loopv(verts) verts[i].norm.flip(); if(!p.vbo) glGenBuffers_(1, &p.vbo); gle::bindvbo(p.vbo); glBufferData_(GL_ARRAY_BUFFER, verts.length()*sizeof(vertex), verts.getbuf(), GL_STATIC_DRAW); gle::clearvbo(); p.numverts = verts.length(); - if(!p.ebo) glGenBuffers_(1, &p.ebo); gle::bindebo(p.ebo); glBufferData_(GL_ELEMENT_ARRAY_BUFFER, tris.length()*sizeof(ushort), tris.getbuf(), GL_STATIC_DRAW); @@ -1320,23 +1119,18 @@ struct prefabmesh }; -static void genprefabmesh(prefabmesh &r, cube &c, const ivec &co, int size) -{ - if(c.children) - { +static void genprefabmesh(prefabmesh &r, cube &c, const ivec &co, int size) { + if(c.children) { neighbourstack[++neighbourdepth] = c.children; - loopi(8) - { + loopi(8) { ivec o(i, co, size/2); genprefabmesh(r, c.children[i], o, size/2); } --neighbourdepth; } - else if(!isempty(c)) - { + else if(!isempty(c)) { int vis; - loopi(6) if((vis = visibletris(c, i, co, size))) - { + loopi(6) if((vis = visibletris(c, i, co, size))) { ivec v[4]; genfaceverts(c, i, v); int convex = 0; @@ -1350,8 +1144,7 @@ static void genprefabmesh(prefabmesh &r, cube &c, const ivec &co, int size) guessnormals(pos, numverts, norm); int index[4]; loopj(numverts) index[j] = r.addvert(pos[j], bvec(norm[j])); - loopj(numverts-2) if(index[0]!=index[j+1] && index[j+1]!=index[j+2] && index[j+2]!=index[0]) - { + loopj(numverts-2) if(index[0]!=index[j+1] && index[j+1]!=index[j+2] && index[j+2]!=index[0]) { r.tris.add(index[0]); r.tris.add(index[j+1]); r.tris.add(index[j+2]); @@ -1360,53 +1153,40 @@ static void genprefabmesh(prefabmesh &r, cube &c, const ivec &co, int size) } } -void genprefabmesh(prefab &p) -{ +void genprefabmesh(prefab &p) { block3 b = *p.copy; b.o = ivec(0, 0, 0); - cube *oldworldroot = worldroot; int oldworldscale = worldscale, oldworldsize = worldsize; - worldroot = newcubes(); worldscale = 1; worldsize = 2; - while(worldsize < max(max(b.s.x, b.s.y), b.s.z)*b.grid) - { + while(worldsize < max(max(b.s.x, b.s.y), b.s.z)*b.grid) { worldscale++; worldsize *= 2; } - cube *s = p.copy->c(); loopxyz(b, b.grid, if(!isempty(*s) || s->children) pastecube(*s, c); s++); - prefabmesh r; neighbourstack[++neighbourdepth] = worldroot; loopi(8) genprefabmesh(r, worldroot[i], ivec(i, ivec(0, 0, 0), worldsize/2), worldsize/2); --neighbourdepth; r.setup(p); - freeocta(worldroot); - worldroot = oldworldroot; worldscale = oldworldscale; worldsize = oldworldsize; - useshaderbyname("prefab"); } extern int outlinecolour; -static void renderprefab(prefab &p, const vec &o, float yaw, float pitch, float roll, float size, const vec &color) -{ - if(!p.numtris) - { +static void renderprefab(prefab &p, const vec &o, float yaw, float pitch, float roll, float size, const vec &color) { + if(!p.numtris) { genprefabmesh(p); if(!p.numtris) return; } - block3 &b = *p.copy; - matrix4 m; m.identity(); m.settranslation(o); @@ -1416,7 +1196,6 @@ static void renderprefab(prefab &p, const vec &o, float yaw, float pitch, float matrix3 w(m); if(size > 0 && size != 1) m.scale(size); m.translate(vec(b.s).mul(-b.grid*0.5f)); - gle::bindvbo(p.vbo); gle::bindebo(p.ebo); gle::enablevertex(); @@ -1424,7 +1203,6 @@ static void renderprefab(prefab &p, const vec &o, float yaw, float pitch, float prefabmesh::vertex *v = (prefabmesh::vertex *)0; gle::vertexpointer(sizeof(prefabmesh::vertex), v->pos.v); gle::normalpointer(sizeof(prefabmesh::vertex), v->norm.v, GL_BYTE); - matrix4 pm; pm.mul(camprojmatrix, m); GLOBALPARAM(prefabmatrix, pm); @@ -1432,36 +1210,29 @@ static void renderprefab(prefab &p, const vec &o, float yaw, float pitch, float SETSHADER(prefab); gle::color(color); glDrawRangeElements_(GL_TRIANGLES, 0, p.numverts-1, p.numtris*3, GL_UNSIGNED_SHORT, (ushort *)0); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); enablepolygonoffset(GL_POLYGON_OFFSET_LINE); - pm.mul(camprojmatrix, m); GLOBALPARAM(prefabmatrix, pm); SETSHADER(prefab); gle::color(vec::hexcolor(outlinecolour)); glDrawRangeElements_(GL_TRIANGLES, 0, p.numverts-1, p.numtris*3, GL_UNSIGNED_SHORT, (ushort *)0); - disablepolygonoffset(GL_POLYGON_OFFSET_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - gle::disablevertex(); gle::disablenormal(); gle::clearebo(); gle::clearvbo(); } -void renderprefab(const char *name, const vec &o, float yaw, float pitch, float roll, float size, const vec &color) -{ +void renderprefab(const char *name, const vec &o, float yaw, float pitch, float roll, float size, const vec &color) { prefab *p = loadprefab(name, false); if(p) renderprefab(*p, o, yaw, pitch, roll, size, color); } -void previewprefab(const char *name, const vec &color) -{ +void previewprefab(const char *name, const vec &color) { prefab *p = loadprefab(name, false); - if(p) - { + if(p) { block3 &b = *p->copy; float yaw; vec o = calcmodelpreviewpos(vec(b.s).mul(b.grid*0.5f), yaw); @@ -1469,8 +1240,7 @@ void previewprefab(const char *name, const vec &color) } } -void mpcopy(editinfo *&e, selinfo &sel, bool local) -{ +void mpcopy(editinfo *&e, selinfo &sel, bool local) { if(local) game::edittrigger(sel, EDIT_COPY); if(e==NULL) e = editinfos.add(new editinfo); if(e->copy) freeblock(e->copy); @@ -1479,29 +1249,25 @@ void mpcopy(editinfo *&e, selinfo &sel, bool local) changed(sel); } -void mppaste(editinfo *&e, selinfo &sel, bool local) -{ +void mppaste(editinfo *&e, selinfo &sel, bool local) { if(e==NULL) return; if(local) game::edittrigger(sel, EDIT_PASTE); if(e->copy) pasteblock(*e->copy, sel, local); } -void copy() -{ +void copy() { if(noedit(true)) return; mpcopy(localedit, sel, true); } -void pastehilite() -{ +void pastehilite() { if(!localedit) return; sel.s = localedit->copy->s; reorient(); havesel = true; } -void paste() -{ +void paste() { if(noedit(true)) return; mppaste(localedit, sel, true); } @@ -1513,19 +1279,16 @@ COMMANDN(undo, editundo, ""); COMMANDN(redo, editredo, ""); static vector<int *> editingvslots; -struct vslotref -{ +struct vslotref { vslotref(int &index) { editingvslots.add(&index); } ~vslotref() { editingvslots.pop(); } }; #define editingvslot(...) vslotref vslotrefs[] = { __VA_ARGS__ }; (void)vslotrefs; -void compacteditvslots() -{ +void compacteditvslots() { loopv(editingvslots) if(*editingvslots[i]) compactvslot(*editingvslots[i]); loopv(unpackingvslots) compactvslot(*unpackingvslots[i].vslot); - loopv(editinfos) - { + loopv(editinfos) { editinfo *e = editinfos[i]; compactvslots(e->copy->c(), e->copy->size()); } @@ -1541,31 +1304,25 @@ void compacteditvslots() int bounded(int n) { return n<0 ? 0 : (n>8 ? 8 : n); } -void pushedge(uchar &edge, int dir, int dc) -{ +void pushedge(uchar &edge, int dir, int dc) { int ne = bounded(edgeget(edge, dc)+dir); edgeset(edge, dc, ne); int oe = edgeget(edge, 1-dc); if((dir<0 && dc && oe>ne) || (dir>0 && dc==0 && oe<ne)) edgeset(edge, 1-dc, ne); } -void linkedpush(cube &c, int d, int x, int y, int dc, int dir) -{ +void linkedpush(cube &c, int d, int x, int y, int dc, int dir) { ivec v, p; getcubevector(c, d, x, y, dc, v); - - loopi(2) loopj(2) - { + loopi(2) loopj(2) { getcubevector(c, d, i, j, dc, p); if(v==p) pushedge(cubeedge(c, d, i, j), dir, dc); } } -static ushort getmaterial(cube &c) -{ - if(c.children) - { +static ushort getmaterial(cube &c) { + if(c.children) { ushort mat = getmaterial(c.children[7]); loopi(7) if(mat != getmaterial(c.children[i])) return MAT_AIR; return mat; @@ -1575,35 +1332,27 @@ static ushort getmaterial(cube &c) VAR(invalidcubeguard, 0, 1, 1); -void mpeditface(int dir, int mode, selinfo &sel, bool local) -{ +void mpeditface(int dir, int mode, selinfo &sel, bool local) { if(mode==1 && (sel.cx || sel.cy || sel.cxs&1 || sel.cys&1)) mode = 0; int d = dimension(sel.orient); int dc = dimcoord(sel.orient); int seldir = dc ? -dir : dir; - if(local) game::edittrigger(sel, EDIT_FACE, dir, mode); - - if(mode==1) - { + if(mode==1) { int h = sel.o[d]+dc*sel.grid; if(((dir>0) == dc && h<=0) || ((dir<0) == dc && h>=worldsize)) return; if(dir<0) sel.o[d] += sel.grid * seldir; } - if(dc) sel.o[d] += sel.us(d)-sel.grid; sel.s[d] = 1; - loopselxyz( if(c.children) solidfaces(c); ushort mat = getmaterial(c); discardchildren(c, true); c.material = mat; - if(mode==1) // fill command - { - if(dir<0) - { + if(mode==1) { // fill command { + if(dir<0) { solidfaces(c); cube &o = blockcube(x, y, 1, sel, -sel.grid); loopi(6) @@ -1612,35 +1361,27 @@ void mpeditface(int dir, int mode, selinfo &sel, bool local) else emptyfaces(c); } - else - { + else { uint bak = c.faces[d]; uchar *p = (uchar *)&c.faces[d]; - if(mode==2) linkedpush(c, d, sel.corner&1, sel.corner>>1, dc, seldir); // corner command - else - { - loop(mx,2) loop(my,2) // pull/push edges command - { + else { + loop(mx,2) loop(my,2) { // pull/push edges command { if(x==0 && mx==0 && sel.cx) continue; if(y==0 && my==0 && sel.cy) continue; if(x==sel.s[R[d]]-1 && mx==1 && (sel.cx+sel.cxs)&1) continue; if(y==sel.s[C[d]]-1 && my==1 && (sel.cy+sel.cys)&1) continue; if(p[mx+my*2] != ((uchar *)&bak)[mx+my*2]) continue; - linkedpush(c, d, mx, my, dc, seldir); } } - optiface(p, c); - if(invalidcubeguard==1 && !isvalidcube(c)) - { + if(invalidcubeguard==1 && !isvalidcube(c)) { uint newbak = c.faces[d]; uchar *m = (uchar *)&bak; uchar *n = (uchar *)&newbak; - loopk(4) if(n[k] != m[k]) // tries to find partial edit that is valid - { + loopk(4) if(n[k] != m[k]) { // tries to find partial edit that is valid { c.faces[d] = bak; c.edges[d*4+k] = n[k]; if(isvalidcube(c)) @@ -1654,35 +1395,30 @@ void mpeditface(int dir, int mode, selinfo &sel, bool local) sel.o[d] += sel.grid * seldir; } -void editface(int *dir, int *mode) -{ +void editface(int *dir, int *mode) { if(noedit(moving!=0)) return; mpeditface(*dir, *mode, sel, true); } VAR(selectionsurf, 0, 0, 1); -void pushsel(int *dir) -{ +void pushsel(int *dir) { if(noedit(moving!=0)) return; int d = dimension(orient); int s = dimcoord(orient) ? -*dir : *dir; sel.o[d] += s*sel.grid; - if(selectionsurf==1) - { + if(selectionsurf==1) { player->o[d] += s*sel.grid; player->resetinterp(); } } -void mpdelcube(selinfo &sel, bool local) -{ +void mpdelcube(selinfo &sel, bool local) { if(local) game::edittrigger(sel, EDIT_DELCUBE); loopselxyz(discardchildren(c, true); emptyfaces(c)); } -void delcube() -{ +void delcube() { if(noedit(true)) return; mpdelcube(sel, true); } @@ -1697,11 +1433,9 @@ int curtexindex = -1, lasttex = 0, lasttexmillis = -1; int texpaneltimer = 0; vector<ushort> texmru; -void tofronttex() // maintain most recently used of the texture lists when applying texture -{ +void tofronttex() { // maintain most recently used of the texture lists when applying texture { int c = curtexindex; - if(texmru.inrange(c)) - { + if(texmru.inrange(c)) { texmru.insert(0, texmru.remove(c)); curtexindex = -1; } @@ -1714,14 +1448,12 @@ static vector<vslotmap> remappedvslots; VAR(usevdelta, 1, 0, 0); -static VSlot *remapvslot(int index, bool delta, const VSlot &ds) -{ +static VSlot *remapvslot(int index, bool delta, const VSlot &ds) { loopv(remappedvslots) if(remappedvslots[i].index == index) return remappedvslots[i].vslot; VSlot &vs = lookupvslot(index, false); if(vs.index < 0) return NULL; VSlot *edit = NULL; - if(delta) - { + if(delta) { VSlot ms; mergevslot(ms, vs, ds); edit = ms.changed ? editvslot(vs, ms) : vs.slot->variants; @@ -1732,31 +1464,24 @@ static VSlot *remapvslot(int index, bool delta, const VSlot &ds) return edit; } -static void remapvslots(cube &c, bool delta, const VSlot &ds, int orient, bool &findrep, VSlot *&findedit) -{ - if(c.children) - { +static void remapvslots(cube &c, bool delta, const VSlot &ds, int orient, bool &findrep, VSlot *&findedit) { + if(c.children) { loopi(8) remapvslots(c.children[i], delta, ds, orient, findrep, findedit); return; } static VSlot ms; - if(orient<0) loopi(6) - { + if(orient<0) loopi(6) { VSlot *edit = remapvslot(c.texture[i], delta, ds); - if(edit) - { + if(edit) { c.texture[i] = edit->index; if(!findedit) findedit = edit; } } - else - { + else { int i = visibleorient(c, orient); VSlot *edit = remapvslot(c.texture[i], delta, ds); - if(edit) - { - if(findrep) - { + if(edit) { + if(findrep) { if(reptex < 0) reptex = c.texture[i]; else if(reptex != c.texture[i]) findrep = false; } @@ -1766,14 +1491,11 @@ static void remapvslots(cube &c, bool delta, const VSlot &ds, int orient, bool & } } -void edittexcube(cube &c, int tex, int orient, bool &findrep) -{ +void edittexcube(cube &c, int tex, int orient, bool &findrep) { if(orient<0) loopi(6) c.texture[i] = tex; - else - { + else { int i = visibleorient(c, orient); - if(findrep) - { + if(findrep) { if(reptex < 0) reptex = c.texture[i]; else if(reptex != c.texture[i]) findrep = false; } @@ -1784,10 +1506,8 @@ void edittexcube(cube &c, int tex, int orient, bool &findrep) VAR(allfaces, 0, 0, 1); -void mpeditvslot(int delta, VSlot &ds, int allfaces, selinfo &sel, bool local) -{ - if(local) - { +void mpeditvslot(int delta, VSlot &ds, int allfaces, selinfo &sel, bool local) { + if(local) { game::edittrigger(sel, EDIT_VSLOT, delta, allfaces, 0, &ds); if(!(lastsel==sel)) tofronttex(); if(allfaces || !(repsel == sel)) reptex = -1; @@ -1797,21 +1517,18 @@ void mpeditvslot(int delta, VSlot &ds, int allfaces, selinfo &sel, bool local) VSlot *findedit = NULL; loopselxyz(remapvslots(c, delta != 0, ds, allfaces ? -1 : sel.orient, findrep, findedit)); remappedvslots.setsize(0); - if(local && findedit) - { + if(local && findedit) { lasttex = findedit->index; lasttexmillis = totalmillis; curtexindex = texmru.find(lasttex); - if(curtexindex < 0) - { + if(curtexindex < 0) { curtexindex = texmru.length(); texmru.add(lasttex); } } } -bool mpeditvslot(int delta, int allfaces, selinfo &sel, ucharbuf &buf) -{ +bool mpeditvslot(int delta, int allfaces, selinfo &sel, ucharbuf &buf) { VSlot ds; if(!unpackvslot(buf, ds, delta != 0)) return false; editingvslot(ds.layer); @@ -1819,8 +1536,7 @@ bool mpeditvslot(int delta, int allfaces, selinfo &sel, ucharbuf &buf) return true; } -void vdelta(char *body) -{ +void vdelta(char *body) { if(noedit()) return; usevdelta++; execute(body); @@ -1828,8 +1544,7 @@ void vdelta(char *body) } COMMAND(vdelta, "s"); -void vrotate(int *n) -{ +void vrotate(int *n) { if(noedit()) return; VSlot ds; ds.changed = 1<<VSLOT_ROTATION; @@ -1839,8 +1554,7 @@ void vrotate(int *n) COMMAND(vrotate, "i"); ICOMMAND(getvrotate, "i", (int *tex), intret(lookupvslot(*tex, false).rotation)); -void voffset(int *x, int *y) -{ +void voffset(int *x, int *y) { if(noedit()) return; VSlot ds; ds.changed = 1<<VSLOT_OFFSET; @@ -1848,15 +1562,13 @@ void voffset(int *x, int *y) mpeditvslot(usevdelta, ds, allfaces, sel, true); } COMMAND(voffset, "ii"); -ICOMMAND(getvoffset, "i", (int *tex), -{ +ICOMMAND(getvoffset, "i", (int *tex), { VSlot &vslot = lookupvslot(*tex, false); defformatstring(str, "%d %d", vslot.offset.x, vslot.offset.y); result(str); }); -void vscroll(float *s, float *t) -{ +void vscroll(float *s, float *t) { if(noedit()) return; VSlot ds; ds.changed = 1<<VSLOT_SCROLL; @@ -1864,15 +1576,13 @@ void vscroll(float *s, float *t) mpeditvslot(usevdelta, ds, allfaces, sel, true); } COMMAND(vscroll, "ff"); -ICOMMAND(getvscroll, "i", (int *tex), -{ +ICOMMAND(getvscroll, "i", (int *tex), { VSlot &vslot = lookupvslot(*tex, false); defformatstring(str, "%s %s", floatstr(vslot.scroll.x), floatstr(vslot.scroll.y)); result(str); }); -void vscale(float *scale) -{ +void vscale(float *scale) { if(noedit()) return; VSlot ds; ds.changed = 1<<VSLOT_SCALE; @@ -1882,13 +1592,11 @@ void vscale(float *scale) COMMAND(vscale, "f"); ICOMMAND(getvscale, "i", (int *tex), floatret(lookupvslot(*tex, false).scale)); -void vlayer(int *n) -{ +void vlayer(int *n) { if(noedit()) return; VSlot ds; ds.changed = 1<<VSLOT_LAYER; - if(vslots.inrange(*n)) - { + if(vslots.inrange(*n)) { ds.layer = *n; if(vslots[ds.layer]->changed && nompedit && multiplayer()) return; } @@ -1898,8 +1606,7 @@ void vlayer(int *n) COMMAND(vlayer, "i"); ICOMMAND(getvlayer, "i", (int *tex), intret(lookupvslot(*tex, false).layer)); -void valpha(float *front, float *back) -{ +void valpha(float *front, float *back) { if(noedit()) return; VSlot ds; ds.changed = 1<<VSLOT_ALPHA; @@ -1908,15 +1615,13 @@ void valpha(float *front, float *back) mpeditvslot(usevdelta, ds, allfaces, sel, true); } COMMAND(valpha, "ff"); -ICOMMAND(getvalpha, "i", (int *tex), -{ +ICOMMAND(getvalpha, "i", (int *tex), { VSlot &vslot = lookupvslot(*tex, false); defformatstring(str, "%s %s", floatstr(vslot.alphafront), floatstr(vslot.alphaback)); result(str); }); -void vcolor(float *r, float *g, float *b) -{ +void vcolor(float *r, float *g, float *b) { if(noedit()) return; VSlot ds; ds.changed = 1<<VSLOT_COLOR; @@ -1924,54 +1629,45 @@ void vcolor(float *r, float *g, float *b) mpeditvslot(usevdelta, ds, allfaces, sel, true); } COMMAND(vcolor, "fff"); -ICOMMAND(getvcolor, "i", (int *tex), -{ +ICOMMAND(getvcolor, "i", (int *tex), { VSlot &vslot = lookupvslot(*tex, false); defformatstring(str, "%s %s %s", floatstr(vslot.colorscale.r), floatstr(vslot.colorscale.g), floatstr(vslot.colorscale.b)); result(str); }); -void vreset() -{ +void vreset() { if(noedit()) return; VSlot ds; mpeditvslot(usevdelta, ds, allfaces, sel, true); } COMMAND(vreset, ""); -void vshaderparam(const char *name, float *x, float *y, float *z, float *w) -{ +void vshaderparam(const char *name, float *x, float *y, float *z, float *w) { if(noedit()) return; VSlot ds; ds.changed = 1<<VSLOT_SHPARAM; - if(name[0]) - { + if(name[0]) { SlotShaderParam p = { getshaderparamname(name), -1, {*x, *y, *z, *w} }; ds.params.add(p); } mpeditvslot(usevdelta, ds, allfaces, sel, true); } COMMAND(vshaderparam, "sffff"); -ICOMMAND(getvshaderparam, "is", (int *tex, const char *name), -{ +ICOMMAND(getvshaderparam, "is", (int *tex, const char *name), { VSlot &vslot = lookupvslot(*tex, false); - loopv(vslot.params) - { + loopv(vslot.params) { SlotShaderParam &p = vslot.params[i]; - if(!strcmp(p.name, name)) - { + if(!strcmp(p.name, name)) { defformatstring(str, "%s %s %s %s", floatstr(p.val[0]), floatstr(p.val[1]), floatstr(p.val[2]), floatstr(p.val[3])); result(str); return; } } }); -ICOMMAND(getvshaderparamnames, "i", (int *tex), -{ +ICOMMAND(getvshaderparamnames, "i", (int *tex), { VSlot &vslot = lookupvslot(*tex, false); vector<char> str; - loopv(vslot.params) - { + loopv(vslot.params) { SlotShaderParam &p = vslot.params[i]; if(i) str.put(' '); str.put(p.name, strlen(p.name)); @@ -1980,10 +1676,8 @@ ICOMMAND(getvshaderparamnames, "i", (int *tex), stringret(newstring(str.getbuf(), str.length()-1)); }); -void mpedittex(int tex, int allfaces, selinfo &sel, bool local) -{ - if(local) - { +void mpedittex(int tex, int allfaces, selinfo &sel, bool local) { + if(local) { game::edittrigger(sel, EDIT_TEX, tex, allfaces); if(allfaces || !(repsel == sel)) reptex = -1; repsel = sel; @@ -1992,8 +1686,7 @@ void mpedittex(int tex, int allfaces, selinfo &sel, bool local) loopselxyz(edittexcube(c, tex, allfaces ? -1 : sel.orient, findrep)); } -static int unpacktex(int &tex, ucharbuf &buf, bool insert = true) -{ +static int unpacktex(int &tex, ucharbuf &buf, bool insert = true) { if(tex < 0x10000) return true; VSlot ds; if(!unpackvslot(buf, ds, false)) return false; @@ -2005,10 +1698,8 @@ static int unpacktex(int &tex, ucharbuf &buf, bool insert = true) return true; } -int shouldpacktex(int index) -{ - if(vslots.inrange(index)) - { +int shouldpacktex(int index) { + if(vslots.inrange(index)) { VSlot &vs = *vslots[index]; if(vs.changed) return 0x10000 + vs.slot->index; } @@ -2016,19 +1707,15 @@ int shouldpacktex(int index) } -bool mpedittex(int tex, int allfaces, selinfo &sel, ucharbuf &buf) -{ +bool mpedittex(int tex, int allfaces, selinfo &sel, ucharbuf &buf) { if(!unpacktex(tex, buf)) return false; mpedittex(tex, allfaces, sel, false); return true; } -void filltexlist() -{ - if(texmru.length()!=vslots.length()) - { - loopvrev(texmru) if(texmru[i]>=vslots.length()) - { +void filltexlist() { + if(texmru.length()!=vslots.length()) { + loopvrev(texmru) if(texmru[i]>=vslots.length()) { if(curtexindex > i) curtexindex--; else if(curtexindex == i) curtexindex = -1; texmru.remove(i); @@ -2037,16 +1724,12 @@ void filltexlist() } } -void compactmruvslots() -{ +void compactmruvslots() { remappedvslots.setsize(0); - loopvrev(texmru) - { - if(vslots.inrange(texmru[i])) - { + loopvrev(texmru) { + if(vslots.inrange(texmru[i])) { VSlot &vs = *vslots[texmru[i]]; - if(vs.index >= 0) - { + if(vs.index >= 0) { texmru[i] = vs.index; continue; } @@ -2055,8 +1738,7 @@ void compactmruvslots() else if(curtexindex == i) curtexindex = -1; texmru.remove(i); } - if(vslots.inrange(lasttex)) - { + if(vslots.inrange(lasttex)) { VSlot &vs = *vslots[lasttex]; lasttex = vs.index >= 0 ? vs.index : 0; } @@ -2064,19 +1746,16 @@ void compactmruvslots() reptex = vslots.inrange(reptex) ? vslots[reptex]->index : -1; } -void edittex(int i, bool save = true) -{ +void edittex(int i, bool save = true) { lasttex = i; lasttexmillis = totalmillis; - if(save) - { + if(save) { loopvj(texmru) if(texmru[j]==lasttex) { curtexindex = j; break; } } mpedittex(i, allfaces, sel, true); } -void edittex_(int *dir) -{ +void edittex_(int *dir) { if(noedit()) return; filltexlist(); if(texmru.empty()) return; @@ -2086,22 +1765,19 @@ void edittex_(int *dir) edittex(texmru[curtexindex], false); } -void gettex() -{ +void gettex() { if(noedit(true)) return; filltexlist(); int tex = -1; loopxyz(sel, sel.grid, tex = c.texture[sel.orient]); - loopv(texmru) if(texmru[i]==tex) - { + loopv(texmru) if(texmru[i]==tex) { curtexindex = i; tofronttex(); return; } } -void getcurtex() -{ +void getcurtex() { if(noedit(true)) return; filltexlist(); int index = curtexindex < 0 ? 0 : curtexindex; @@ -2109,16 +1785,14 @@ void getcurtex() intret(texmru[index]); } -void getseltex() -{ +void getseltex() { if(noedit(true)) return; cube &c = lookupcube(sel.o, -sel.grid); if(c.children || isempty(c)) return; intret(c.texture[sel.orient]); } -void gettexname(int *tex, int *subslot) -{ +void gettexname(int *tex, int *subslot) { if(noedit(true) || *tex<0) return; VSlot &vslot = lookupvslot(*tex, false); Slot &slot = *vslot.slot; @@ -2126,8 +1800,7 @@ void gettexname(int *tex, int *subslot) result(slot.sts[*subslot].name); } -void getslottex(int *idx) -{ +void getslottex(int *idx) { if(*idx < 0 || !slots.inrange(*idx)) { intret(-1); return; } Slot &slot = lookupslot(*idx, false); intret(slot.variants->index); @@ -2144,28 +1817,23 @@ ICOMMAND(numslots, "", (), intret(slots.length())); COMMAND(getslottex, "i"); ICOMMAND(texloaded, "i", (int *tex), intret(slots.inrange(*tex) && slots[*tex]->loaded ? 1 : 0)); -void replacetexcube(cube &c, int oldtex, int newtex) -{ +void replacetexcube(cube &c, int oldtex, int newtex) { loopi(6) if(c.texture[i] == oldtex) c.texture[i] = newtex; if(c.children) loopi(8) replacetexcube(c.children[i], oldtex, newtex); } -void mpreplacetex(int oldtex, int newtex, bool insel, selinfo &sel, bool local) -{ +void mpreplacetex(int oldtex, int newtex, bool insel, selinfo &sel, bool local) { if(local) game::edittrigger(sel, EDIT_REPLACE, oldtex, newtex, insel ? 1 : 0); - if(insel) - { + if(insel) { loopselxyz(replacetexcube(c, oldtex, newtex)); } - else - { + else { loopi(8) replacetexcube(worldroot[i], oldtex, newtex); } allchanged(); } -bool mpreplacetex(int oldtex, int newtex, bool insel, selinfo &sel, ucharbuf &buf) -{ +bool mpreplacetex(int oldtex, int newtex, bool insel, selinfo &sel, ucharbuf &buf) { if(!unpacktex(oldtex, buf, false)) return false; editingvslot(oldtex); if(!unpacktex(newtex, buf)) return false; @@ -2173,8 +1841,7 @@ bool mpreplacetex(int oldtex, int newtex, bool insel, selinfo &sel, ucharbuf &bu return true; } -void replace(bool insel) -{ +void replace(bool insel) { if(noedit()) return; if(reptex < 0) { conoutf(CON_ERROR, "can only replace after a texture edit"); return; } mpreplacetex(reptex, lasttex, insel, sel, true); @@ -2189,37 +1856,30 @@ uint cflip(uint face) { return ((face&0xFF00FF00)>>8) | ((face&0x00FF00FF)<<8); uint rflip(uint face) { return ((face&0xFFFF0000)>>16)| ((face&0x0000FFFF)<<16); } uint mflip(uint face) { return (face&0xFF0000FF) | ((face&0x00FF0000)>>8) | ((face&0x0000FF00)<<8); } -void flipcube(cube &c, int d) -{ +void flipcube(cube &c, int d) { swap(c.texture[d*2], c.texture[d*2+1]); c.faces[D[d]] = dflip(c.faces[D[d]]); c.faces[C[d]] = cflip(c.faces[C[d]]); c.faces[R[d]] = rflip(c.faces[R[d]]); - if(c.children) - { + if(c.children) { loopi(8) if(i&octadim(d)) swap(c.children[i], c.children[i-octadim(d)]); loopi(8) flipcube(c.children[i], d); } } -void rotatequad(cube &a, cube &b, cube &c, cube &d) -{ +void rotatequad(cube &a, cube &b, cube &c, cube &d) { cube t = a; a = b; b = c; c = d; d = t; } -void rotatecube(cube &c, int d) // rotates cube clockwise. see pics in cvs for help. -{ +void rotatecube(cube &c, int d) { // rotates cube clockwise. see pics in cvs for help. { c.faces[D[d]] = cflip (mflip(c.faces[D[d]])); c.faces[C[d]] = dflip (mflip(c.faces[C[d]])); c.faces[R[d]] = rflip (mflip(c.faces[R[d]])); swap(c.faces[R[d]], c.faces[C[d]]); - swap(c.texture[2*R[d]], c.texture[2*C[d]+1]); swap(c.texture[2*C[d]], c.texture[2*R[d]+1]); swap(c.texture[2*C[d]], c.texture[2*C[d]+1]); - - if(c.children) - { + if(c.children) { int row = octadim(R[d]); int col = octadim(C[d]); for(int i=0; i<=octadim(d); i+=octadim(d)) rotatequad @@ -2233,19 +1893,15 @@ void rotatecube(cube &c, int d) // rotates cube clockwise. see pics in cvs for } } -void mpflip(selinfo &sel, bool local) -{ - if(local) - { +void mpflip(selinfo &sel, bool local) { + if(local) { game::edittrigger(sel, EDIT_FLIP); makeundo(); } int zs = sel.s[dimension(sel.orient)]; - loopxy(sel) - { + loopxy(sel) { loop(z,zs) flipcube(selcube(x, y, z), dimension(sel.orient)); - loop(z,zs/2) - { + loop(z,zs/2) { cube &a = selcube(x, y, z); cube &b = selcube(x, y, zs-z-1); swap(a, b); @@ -2254,22 +1910,19 @@ void mpflip(selinfo &sel, bool local) changed(sel); } -void flip() -{ +void flip() { if(noedit()) return; mpflip(sel, true); } -void mprotate(int cw, selinfo &sel, bool local) -{ +void mprotate(int cw, selinfo &sel, bool local) { if(local) game::edittrigger(sel, EDIT_ROTATE, cw); int d = dimension(sel.orient); if(!dimcoord(sel.orient)) cw = -cw; int m = sel.s[C[d]] < sel.s[R[d]] ? C[d] : R[d]; int ss = sel.s[m] = max(sel.s[R[d]], sel.s[C[d]]); if(local) makeundo(); - loop(z,sel.s[D[d]]) loopi(cw>0 ? 1 : 3) - { + loop(z,sel.s[D[d]]) loopi(cw>0 ? 1 : 3) { loopxy(sel) rotatecube(selcube(x,y,z), d); loop(y,ss/2) loop(x,ss-1-y*2) rotatequad ( @@ -2282,8 +1935,7 @@ void mprotate(int cw, selinfo &sel, bool local) changed(sel); } -void rotate(int *cw) -{ +void rotate(int *cw) { if(noedit()) return; mprotate(*cw, sel, true); } @@ -2292,29 +1944,25 @@ COMMAND(flip, ""); COMMAND(rotate, "i"); enum { EDITMATF_EMPTY = 0x10000, EDITMATF_NOTEMPTY = 0x20000, EDITMATF_SOLID = 0x30000, EDITMATF_NOTSOLID = 0x40000 }; -static const struct { const char *name; int filter; } editmatfilters[] = -{ - { "empty", EDITMATF_EMPTY }, - { "notempty", EDITMATF_NOTEMPTY }, - { "solid", EDITMATF_SOLID }, - { "notsolid", EDITMATF_NOTSOLID } +static const struct { const char *name; int filter; } editmatfilters[] = { + { + "empty", EDITMATF_EMPTY }, { + "notempty", EDITMATF_NOTEMPTY }, { + "solid", EDITMATF_SOLID }, { + "notsolid", EDITMATF_NOTSOLID } }; -void setmat(cube &c, ushort mat, ushort matmask, ushort filtermat, ushort filtermask, int filtergeom) -{ +void setmat(cube &c, ushort mat, ushort matmask, ushort filtermat, ushort filtermask, int filtergeom) { if(c.children) loopi(8) setmat(c.children[i], mat, matmask, filtermat, filtermask, filtergeom); - else if((c.material&filtermask) == filtermat) - { - switch(filtergeom) - { + else if((c.material&filtermask) == filtermat) { + switch(filtergeom) { case EDITMATF_EMPTY: if(isempty(c)) break; return; case EDITMATF_NOTEMPTY: if(!isempty(c)) break; return; case EDITMATF_SOLID: if(isentirelysolid(c)) break; return; case EDITMATF_NOTSOLID: if(!isentirelysolid(c)) break; return; } - if(mat!=MAT_AIR) - { + if(mat!=MAT_AIR) { c.material &= matmask; c.material |= mat; } @@ -2322,47 +1970,38 @@ void setmat(cube &c, ushort mat, ushort matmask, ushort filtermat, ushort filter } } -void mpeditmat(int matid, int filter, selinfo &sel, bool local) -{ +void mpeditmat(int matid, int filter, selinfo &sel, bool local) { if(local) game::edittrigger(sel, EDIT_MAT, matid, filter); - ushort filtermat = 0, filtermask = 0, matmask; int filtergeom = 0; - if(filter >= 0) - { + if(filter >= 0) { filtermat = filter&0xFFFF; filtermask = filtermat&(MATF_INDEX) ? (int) MATF_INDEX : (filtermat&MATF_CLIP ? (int) MATF_CLIP : (int) filtermat); filtergeom = filter&~0xFFFF; } - if(matid < 0) - { + if(matid < 0) { matid = 0; matmask = filtermask; } - else - { + else { matmask = matid&MATF_INDEX ? 0 : (matid&MATF_CLIP ? ~MATF_CLIP : ~matid); } loopselxyz(setmat(c, matid, matmask, filtermat, filtermask, filtergeom)); } -void editmat(char *name, char *filtername) -{ +void editmat(char *name, char *filtername) { if(noedit()) return; int filter = -1; - if(filtername[0]) - { + if(filtername[0]) { loopi(sizeof(editmatfilters)/sizeof(editmatfilters[0])) if(!strcmp(editmatfilters[i].name, filtername)) { filter = editmatfilters[i].filter; break; } if(filter < 0) filter = findmaterial(filtername); - if(filter < 0) - { + if(filter < 0) { conoutf(CON_ERROR, "unknown material \"%s\"", filtername); return; } } int id = -1; - if(name[0] || filter < 0) - { + if(name[0] || filter < 0) { id = findmaterial(name); if(id<0) { conoutf(CON_ERROR, "unknown material \"%s\"", name); return; } } @@ -2384,39 +2023,30 @@ static int lastthumbnail = 0; VARP(texgui2d, 0, 1, 1); VAR(texguinum, 1, -1, 0); -struct texturegui : g3d_callback -{ +struct texturegui : g3d_callback { bool menuon; vec menupos; int menustart, menutab; - texturegui() : menustart(-1) {} - - void gui(g3d_gui &g, bool firstpass) - { + void gui(g3d_gui &g, bool firstpass) { int origtab = menutab, numtabs = max((slots.length() + texguiwidth*texguiheight - 1)/(texguiwidth*texguiheight), 1); if(!firstpass) texguinum = -1; g.start(menustart, 0.04f, &menutab); bool oldautotab = g.allowautotab(false); - loopi(numtabs) - { + loopi(numtabs) { g.tab(!i ? "Textures" : NULL, 0xFFDD88); if(i+1 != origtab) continue; //don't load textures on non-visible tabs! Slot *rollover = NULL; - loop(h, texguiheight) - { + loop(h, texguiheight) { g.pushlist(); - loop(w, texguiwidth) - { + loop(w, texguiwidth) { extern VSlot dummyvslot; int ti = (i*texguiheight+h)*texguiwidth+w; - if(ti<slots.length()) - { + if(ti<slots.length()) { Slot &slot = lookupslot(ti, false); VSlot &vslot = *slot.variants; if(slot.sts.empty()) continue; - else if(!slot.loaded && !slot.thumbnail) - { + else if(!slot.loaded && !slot.thumbnail) { if(totalmillis-lastthumbnail<texguitime) { g.texture(dummyvslot, texguiscale, false); //create an empty space @@ -2427,23 +2057,19 @@ struct texturegui : g3d_callback } int ret = g.texture(vslot, texguiscale, true); if(ret&G3D_ROLLOVER) { rollover = &slot; texguinum = ti; } - if(ret&G3D_UP && (slot.loaded || slot.thumbnail!=notexture)) - { + if(ret&G3D_UP && (slot.loaded || slot.thumbnail!=notexture)) { edittex(vslot.index); hudshader->set(); } } - else - { + else { g.texture(dummyvslot, texguiscale, false); //create an empty space } } g.poplist(); } - if(texguiname) - { - if(rollover) - { + if(texguiname) { + if(rollover) { defformatstring(name, "%d \f7:\fc %s", texguinum, rollover->sts[0].name); g.title(name, 0xFFDD88); } @@ -2453,12 +2079,9 @@ struct texturegui : g3d_callback g.allowautotab(oldautotab); g.end(); } - - void showtextures(bool on) - { + void showtextures(bool on) { if(on == menuon) return; - if((menuon = on)) - { + if((menuon = on)) { if(menustart <= lasttexmillis) menutab = 1+clamp(lookupvslot(lasttex, false).slot->index, 0, slots.length()-1)/(texguiwidth*texguiheight); menupos = menuinfrontofplayer(); @@ -2466,9 +2089,7 @@ struct texturegui : g3d_callback } else texguinum = -1; } - - void show() - { + void show() { if(!menuon) return; filltexlist(); extern int usegui2d; @@ -2477,13 +2098,11 @@ struct texturegui : g3d_callback } } gui; -void g3d_texturemenu() -{ +void g3d_texturemenu() { gui.show(); } -void showtexgui(int *n) -{ +void showtexgui(int *n) { if(!editmode) { conoutf(CON_ERROR, "operation only allowed in edit mode"); return; } gui.showtextures(*n==0 ? !gui.menuon : *n==1); } @@ -2491,47 +2110,36 @@ void showtexgui(int *n) // 0/noargs = toggle, 1 = on, other = off - will autoclose if too far away or exit editmode COMMAND(showtexgui, "i"); -bool cleartexgui() -{ +bool cleartexgui() { if(!gui.menuon) return false; gui.showtextures(false); return true; } ICOMMAND(cleartexgui, "", (), intret(cleartexgui() ? 1 : 0)); -void rendertexturepanel(int w, int h) -{ - if((texpaneltimer -= curtime)>0 && editmode) - { +void rendertexturepanel(int w, int h) { + if((texpaneltimer -= curtime)>0 && editmode) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - pushhudmatrix(); hudmatrix.scale(h/1800.0f, h/1800.0f, 1); flushhudmatrix(false); SETSHADER(hudrgb); - int y = 50, gap = 10; - gle::defvertex(2); gle::deftexcoord0(); - - loopi(7) - { + loopi(7) { int s = (i == 3 ? 285 : 220), ti = curtexindex+i-3; - if(texmru.inrange(ti)) - { - VSlot &vslot = lookupvslot(texmru[ti]), *layer = NULL; + if(texmru.inrange(ti)) { + VSlot &vslot = lookupvslot(texmru[ti]), *layer = NULL; (void) layer; Slot &slot = *vslot.slot; Texture *tex = slot.sts.empty() ? notexture : slot.sts[0].t; - if(vslot.layer) - { + if(vslot.layer) { layer = &lookupvslot(vslot.layer); } float sx = min(1.0f, tex->xs/(float)tex->ys), sy = min(1.0f, tex->ys/(float)tex->xs); vec2 tc[4] = { vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1) }; float xoff = vslot.offset.x, yoff = vslot.offset.y; - if(vslot.rotation) - { + if(vslot.rotation) { const texrotation &r = texrotations[vslot.rotation]; if(r.swapxy) { swap(xoff, yoff); loopk(4) swap(tc[k].x, tc[k].y); } if(r.flipx) { xoff *= -1; loopk(4) tc[k].x *= -1; } @@ -2542,7 +2150,6 @@ void rendertexturepanel(int w, int h) } y += s+gap; } - pophudmatrix(true, false); hudshader->set(); } diff --git a/src/engine/octarender.cpp b/src/engine/octarender.cpp index 6b8a5b5..afbc7b2 100644 --- a/src/engine/octarender.cpp +++ b/src/engine/octarender.cpp @@ -2,8 +2,7 @@ #include "engine.h" -struct vboinfo -{ +struct vboinfo { int uses; }; @@ -12,8 +11,7 @@ hashtable<GLuint, vboinfo> vbos; VAR(printvbo, 0, 0, 1); VARFN(vbosize, maxvbosize, 0, 1<<14, 1<<16, allchanged()); -enum -{ +enum { VBO_VBUF = 0, VBO_EBUF, NUMVBO @@ -23,41 +21,32 @@ static vector<uchar> vbodata[NUMVBO]; static vector<vtxarray *> vbovas[NUMVBO]; static int vbosize[NUMVBO]; -void destroyvbo(GLuint vbo) -{ +void destroyvbo(GLuint vbo) { vboinfo *exists = vbos.access(vbo); if(!exists) return; vboinfo &vbi = *exists; if(vbi.uses <= 0) return; vbi.uses--; - if(!vbi.uses) - { + if(!vbi.uses) { glDeleteBuffers_(1, &vbo); vbos.remove(vbo); } } -void genvbo(int type, void *buf, int len, vtxarray **vas, int numva) -{ +void genvbo(int type, void *buf, int len, vtxarray **vas, int numva) { gle::disable(); - GLuint vbo; glGenBuffers_(1, &vbo); GLenum target = type==VBO_VBUF ? GL_ARRAY_BUFFER : GL_ELEMENT_ARRAY_BUFFER; glBindBuffer_(target, vbo); glBufferData_(target, len, buf, GL_STATIC_DRAW); glBindBuffer_(target, 0); - vboinfo &vbi = vbos[vbo]; vbi.uses = numva; - if(printvbo) conoutf(CON_DEBUG, "vbo %d: type %d, size %d, %d uses", vbo, type, len, numva); - - loopi(numva) - { + loopi(numva) { vtxarray *va = vas[i]; - switch(type) - { + switch(type) { case VBO_VBUF: va->vbuf = vbo; break; @@ -68,31 +57,24 @@ void genvbo(int type, void *buf, int len, vtxarray **vas, int numva) } } -bool readva(vtxarray *va, ushort *&edata, vertex *&vdata) -{ +bool readva(vtxarray *va, ushort *&edata, vertex *&vdata) { if(!va->vbuf || !va->ebuf) return false; - edata = new ushort[3*va->tris]; vdata = new vertex[va->verts]; - gle::bindebo(va->ebuf); glGetBufferSubData_(GL_ELEMENT_ARRAY_BUFFER, (size_t)va->edata, 3*va->tris*sizeof(ushort), edata); gle::clearebo(); - gle::bindvbo(va->vbuf); glGetBufferSubData_(GL_ARRAY_BUFFER, va->voffset*sizeof(vertex), va->verts*sizeof(vertex), vdata); gle::clearvbo(); return true; } -void flushvbo(int type = -1) -{ - if(type < 0) - { +void flushvbo(int type = -1) { + if(type < 0) { loopi(NUMVBO) flushvbo(i); return; } - vector<uchar> &data = vbodata[type]; if(data.empty()) return; vector<vtxarray *> &vas = vbovas[type]; @@ -102,42 +84,31 @@ void flushvbo(int type = -1) vbosize[type] = 0; } -uchar *addvbo(vtxarray *va, int type, int numelems, int elemsize) -{ +uchar *addvbo(vtxarray *va, int type, int numelems, int elemsize) { vbosize[type] += numelems; - vector<uchar> &data = vbodata[type]; vector<vtxarray *> &vas = vbovas[type]; - vas.add(va); - int len = numelems*elemsize; uchar *buf = data.reserve(len).buf; data.advance(len); return buf; } -struct verthash -{ +struct verthash { static const int SIZE = 1<<13; int table[SIZE]; vector<vertex> verts; vector<int> chain; - verthash() { clearverts(); } - - void clearverts() - { + void clearverts() { memset(table, -1, sizeof(table)); chain.setsize(0); verts.setsize(0); } - - int addvert(const vertex &v) - { + int addvert(const vertex &v) { uint h = hthash(v.pos)&(SIZE-1); - for(int i = table[h]; i>=0; i = chain[i]) - { + for(int i = table[h]; i>=0; i = chain[i]) { const vertex &c = verts[i]; if(c.pos==v.pos && c.tc==v.tc && c.norm==v.norm && c.tangent==v.tangent && (v.lm.iszero() || c.lm==v.lm)) return i; @@ -147,9 +118,7 @@ struct verthash chain.add(table[h]); return table[h] = verts.length()-1; } - - int addvert(const vec &pos, const vec2 &tc = vec2(0, 0), const svec2 &lm = svec2(0, 0), const bvec &norm = bvec(128, 128, 128), const bvec4 &tangent = bvec4(128, 128, 128, 128)) - { + int addvert(const vec &pos, const vec2 &tc = vec2(0, 0), const svec2 &lm = svec2(0, 0), const bvec &norm = bvec(128, 128, 128), const bvec4 &tangent = bvec4(128, 128, 128, 128)) { vertex vtx; vtx.pos = pos; vtx.tc = tc; @@ -160,46 +129,37 @@ struct verthash } }; -enum -{ +enum { NO_ALPHA = 0, ALPHA_BACK, ALPHA_FRONT }; -struct sortkey -{ +struct sortkey { ushort tex, lmid; uchar dim, layer, alpha; - sortkey() {} sortkey(ushort tex, ushort lmid, uchar dim, uchar layer = LAYER_TOP, uchar alpha = NO_ALPHA) : tex(tex), lmid(lmid), dim(dim), layer(layer), alpha(alpha) {} - bool operator==(const sortkey &o) const { return tex==o.tex && lmid==o.lmid && dim==o.dim && layer==o.layer && alpha==o.alpha; } }; -struct sortval -{ +struct sortval { int unlit; vector<ushort> tris[2]; - sortval() : unlit(0) {} }; -static inline bool htcmp(const sortkey &x, const sortkey &y) -{ +static inline bool htcmp(const sortkey &x, const sortkey &y) { return x == y; } -static inline uint hthash(const sortkey &k) -{ +static inline uint hthash(const sortkey &k) { return k.tex + k.lmid*9741; } -struct vacollect : verthash -{ +struct vacollect : verthash { ivec origin; int size; hashtable<sortkey, sortval> indices; @@ -207,9 +167,7 @@ struct vacollect : verthash vector<materialsurface> matsurfs; vector<octaentities *> mapmodels; int worldtris; - - void clear() - { + void clear() { clearverts(); worldtris = 0; indices.clear(); @@ -217,47 +175,38 @@ struct vacollect : verthash mapmodels.setsize(0); texs.setsize(0); } - - void remapunlit(vector<sortkey> &remap) - { + void remapunlit(vector<sortkey> &remap) { uint lastlmid[8] = { LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT }, firstlmid[8] = { LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT, LMID_AMBIENT }; int firstlit[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; - loopv(texs) - { + loopv(texs) { sortkey &k = texs[i]; - if(k.lmid>=LMID_RESERVED) - { + if(k.lmid>=LMID_RESERVED) { LightMapTexture &lmtex = lightmaptexs[k.lmid]; int type = lmtex.type&LM_TYPE; if(k.layer==LAYER_BLEND) type += 2; else if(k.alpha) type += 4 + 2*(k.alpha-1); lastlmid[type] = lmtex.unlitx>=0 ? (int) k.lmid : (int) LMID_AMBIENT; - if(firstlmid[type]==LMID_AMBIENT && lastlmid[type]!=LMID_AMBIENT) - { + if(firstlmid[type]==LMID_AMBIENT && lastlmid[type]!=LMID_AMBIENT) { firstlit[type] = i; firstlmid[type] = lastlmid[type]; } } - else if(k.lmid==LMID_AMBIENT) - { + else if(k.lmid==LMID_AMBIENT) { Shader *s = lookupvslot(k.tex, false).slot->shader; int type = s->type&SHADER_NORMALSLMS ? LM_BUMPMAP0 : LM_DIFFUSE; if(k.layer==LAYER_BLEND) type += 2; else if(k.alpha) type += 4 + 2*(k.alpha-1); - if(lastlmid[type]!=LMID_AMBIENT) - { + if(lastlmid[type]!=LMID_AMBIENT) { sortval &t = indices[k]; if(t.unlit<=0) t.unlit = lastlmid[type]; } } } - loopj(2) - { + loopj(2) { int offset = 2*j; if(firstlmid[offset]==LMID_AMBIENT && firstlmid[offset+1]==LMID_AMBIENT) continue; - loopi(max(firstlit[offset], firstlit[offset+1])) - { + loopi(max(firstlit[offset], firstlit[offset+1])) { sortkey &k = texs[i]; if((j ? k.layer!=LAYER_BLEND : k.layer==LAYER_BLEND) || k.alpha) continue; if(k.lmid!=LMID_AMBIENT) continue; @@ -267,12 +216,10 @@ struct vacollect : verthash indices[k].unlit = firstlmid[type]; } } - loopj(2) - { + loopj(2) { int offset = 4 + 2*j; if(firstlmid[offset]==LMID_AMBIENT && firstlmid[offset+1]==LMID_AMBIENT) continue; - loopi(max(firstlit[offset], firstlit[offset+1])) - { + loopi(max(firstlit[offset], firstlit[offset+1])) { sortkey &k = texs[i]; if(k.alpha != j+1) continue; if(k.lmid!=LMID_AMBIENT) continue; @@ -282,20 +229,17 @@ struct vacollect : verthash indices[k].unlit = firstlmid[type]; } } - loopv(remap) - { + loopv(remap) { sortkey &k = remap[i]; sortval &t = indices[k]; if(t.unlit<=0) continue; LightMapTexture &lm = lightmaptexs[t.unlit]; svec2 lmtc(short(ceil((lm.unlitx + 0.5f) * SHRT_MAX/lm.w)), short(ceil((lm.unlity + 0.5f) * SHRT_MAX/lm.h))); - loopl(2) loopvj(t.tris[l]) - { + loopl(2) loopvj(t.tris[l]) { vertex &vtx = verts[t.tris[l][j]]; if(vtx.lm.iszero()) vtx.lm = lmtc; - else if(vtx.lm != lmtc) - { + else if(vtx.lm != lmtc) { vertex vtx2 = vtx; vtx2.lm = lmtc; t.tris[l][j] = addvert(vtx2); @@ -305,26 +249,20 @@ struct vacollect : verthash if(dst) loopl(2) loopvj(t.tris[l]) dst->tris[l].add(t.tris[l][j]); } } - - void optimize() - { + void optimize() { vector<sortkey> remap; enumeratekt(indices, sortkey, k, sortval, t, - loopl(2) if(t.tris[l].length() && t.unlit<=0) - { - if(k.lmid>=LMID_RESERVED && lightmaptexs[k.lmid].unlitx>=0) - { + loopl(2) if(t.tris[l].length() && t.unlit<=0) { + if(k.lmid>=LMID_RESERVED && lightmaptexs[k.lmid].unlitx>=0) { sortkey ukey(k.tex, LMID_AMBIENT, k.dim, k.layer, k.alpha); sortval *uval = indices.access(ukey); - if(uval && uval->unlit<=0) - { + if(uval && uval->unlit<=0) { if(uval->unlit<0) texs.removeobj(ukey); else remap.add(ukey); uval->unlit = k.lmid; } } - else if(k.lmid==LMID_AMBIENT) - { + else if(k.lmid==LMID_AMBIENT) { remap.add(k); t.unlit = -1; } @@ -333,20 +271,15 @@ struct vacollect : verthash } ); texs.sort(texsort); - remapunlit(remap); - matsurfs.shrink(optimizematsurfs(matsurfs.getbuf(), matsurfs.length())); } - - static inline bool texsort(const sortkey &x, const sortkey &y) - { + static inline bool texsort(const sortkey &x, const sortkey &y) { if(x.alpha < y.alpha) return true; if(x.alpha > y.alpha) return false; if(x.layer < y.layer) return true; if(x.layer > y.layer) return false; - if(x.tex == y.tex) - { + if(x.tex == y.tex) { if(x.lmid < y.lmid) return true; if(x.lmid > y.lmid) return false; if(x.dim < y.dim) return true; @@ -362,24 +295,20 @@ struct vacollect : verthash else return false; } -#define GENVERTS(type, ptr, body) do \ - { \ +#define GENVERTS(type, ptr, body) do { \ + \ type *f = (type *)ptr; \ - loopv(verts) \ - { \ + loopv(verts) { \ + \ const vertex &v = verts[i]; \ body; \ f++; \ } \ } while(0) - - void genverts(void *buf) - { + void genverts(void *buf) { GENVERTS(vertex, buf, { *f = v; f->norm.flip(); f->tangent.flip(); }); } - - void setupdata(vtxarray *va) - { + void setupdata(vtxarray *va) { va->verts = verts.length(); va->tris = worldtris/3; va->vbuf = 0; @@ -387,27 +316,22 @@ struct vacollect : verthash va->minvert = 0; va->maxvert = va->verts-1; va->voffset = 0; - if(va->verts) - { + if(va->verts) { if(vbosize[VBO_VBUF] + verts.length() > maxvbosize || vbosize[VBO_EBUF] + worldtris > USHRT_MAX) flushvbo(); - va->voffset = vbosize[VBO_VBUF]; uchar *vdata = addvbo(va, VBO_VBUF, va->verts, sizeof(vertex)); genverts(vdata); va->minvert += va->voffset; va->maxvert += va->voffset; } - va->matbuf = NULL; va->matsurfs = matsurfs.length(); - if(va->matsurfs) - { + if(va->matsurfs) { va->matbuf = new materialsurface[matsurfs.length()]; memcpy(va->matbuf, matsurfs.getbuf(), matsurfs.length()*sizeof(materialsurface)); } - va->eslist = NULL; va->texs = texs.length(); va->blendtris = 0; @@ -419,13 +343,11 @@ struct vacollect : verthash va->ebuf = 0; va->edata = 0; va->texmask = 0; - if(va->texs) - { + if(va->texs) { va->eslist = new elementset[va->texs]; va->edata += vbosize[VBO_EBUF]; ushort *edata = (ushort *)addvbo(va, VBO_EBUF, worldtris, sizeof(ushort)), *curbuf = edata; - loopv(texs) - { + loopv(texs) { const sortkey &k = texs[i]; const sortval &t = indices[k]; elementset &e = va->eslist[i]; @@ -434,22 +356,16 @@ struct vacollect : verthash e.dim = k.dim; e.layer = k.layer; ushort *startbuf = curbuf; - loopl(2) - { + loopl(2) { e.minvert[l] = USHRT_MAX; e.maxvert[l] = 0; - - if(t.tris[l].length()) - { + if(t.tris[l].length()) { memcpy(curbuf, t.tris[l].getbuf(), t.tris[l].length() * sizeof(ushort)); - - loopvj(t.tris[l]) - { + loopvj(t.tris[l]) { curbuf[j] += va->voffset; e.minvert[l] = min(e.minvert[l], curbuf[j]); e.maxvert[l] = max(e.maxvert[l], curbuf[j]); } - curbuf += t.tris[l].length(); } e.length[l] = curbuf-startbuf; @@ -457,19 +373,14 @@ struct vacollect : verthash if(k.layer==LAYER_BLEND) { va->texs--; va->tris -= e.length[1]/3; va->blends++; va->blendtris += e.length[1]/3; } else if(k.alpha==ALPHA_BACK) { va->texs--; va->tris -= e.length[1]/3; va->alphaback++; va->alphabacktris += e.length[1]/3; } else if(k.alpha==ALPHA_FRONT) { va->texs--; va->tris -= e.length[1]/3; va->alphafront++; va->alphafronttris += e.length[1]/3; } - Slot &slot = *lookupvslot(k.tex, false).slot; loopvj(slot.sts) va->texmask |= 1<<slot.sts[j].type; } } - va->alphatris = va->alphabacktris + va->alphafronttris; - if(mapmodels.length()) va->mapmodels.put(mapmodels.getbuf(), mapmodels.length()); } - - bool emptyva() - { + bool emptyva() { return verts.empty() && matsurfs.empty() && mapmodels.empty(); } } vc; @@ -481,24 +392,20 @@ vector<tjoint> tjoints; vec shadowmapmin, shadowmapmax; -int calcshadowmask(vec *pos, int numpos) -{ +int calcshadowmask(vec *pos, int numpos) { extern vec shadowdir; int mask = 0, used = 1; vec pe = vec(pos[1]).sub(pos[0]); - loopk(numpos-2) - { + loopk(numpos-2) { vec e = vec(pos[k+2]).sub(pos[0]); - if(vec().cross(pe, e).dot(shadowdir)>0) - { + if(vec().cross(pe, e).dot(shadowdir)>0) { mask |= 1<<k; used |= 6<<k; } pe = e; } if(!mask) return 0; - loopk(numpos) if(used&(1<<k)) - { + loopk(numpos) if(used&(1<<k)) { const vec &v = pos[k]; shadowmapmin.min(v); shadowmapmax.max(v); @@ -508,14 +415,11 @@ int calcshadowmask(vec *pos, int numpos) VARFP(filltjoints, 0, 1, 1, allchanged()); -void reduceslope(ivec &n) -{ +void reduceslope(ivec &n) { int mindim = -1, minval = 64; - loopi(3) if(n[i]) - { + loopi(3) if(n[i]) { int val = abs(n[i]); - if(mindim < 0 || val < minval) - { + if(mindim < 0 || val < minval) { mindim = i; minval = val; } @@ -525,49 +429,44 @@ void reduceslope(ivec &n) } // [rotation][dimension] -extern const vec orientation_tangent[8][3] = -{ - { vec(0, 1, 0), vec( 1, 0, 0), vec( 1, 0, 0) }, - { vec(0, 0, -1), vec( 0, 0, -1), vec( 0, 1, 0) }, - { vec(0, -1, 0), vec(-1, 0, 0), vec(-1, 0, 0) }, - { vec(0, 0, 1), vec( 0, 0, 1), vec( 0, -1, 0) }, - { vec(0, -1, 0), vec(-1, 0, 0), vec(-1, 0, 0) }, - { vec(0, 1, 0), vec( 1, 0, 0), vec( 1, 0, 0) }, - { vec(0, 0, -1), vec( 0, 0, -1), vec( 0, 1, 0) }, - { vec(0, 0, 1), vec( 0, 0, 1), vec( 0, -1, 0) }, +extern const vec orientation_tangent[8][3] = { + { + vec(0, 1, 0), vec( 1, 0, 0), vec( 1, 0, 0) }, { + vec(0, 0, -1), vec( 0, 0, -1), vec( 0, 1, 0) }, { + vec(0, -1, 0), vec(-1, 0, 0), vec(-1, 0, 0) }, { + vec(0, 0, 1), vec( 0, 0, 1), vec( 0, -1, 0) }, { + vec(0, -1, 0), vec(-1, 0, 0), vec(-1, 0, 0) }, { + vec(0, 1, 0), vec( 1, 0, 0), vec( 1, 0, 0) }, { + vec(0, 0, -1), vec( 0, 0, -1), vec( 0, 1, 0) }, { + vec(0, 0, 1), vec( 0, 0, 1), vec( 0, -1, 0) }, }; -extern const vec orientation_bitangent[8][3] = -{ - { vec(0, 0, -1), vec( 0, 0, -1), vec( 0, 1, 0) }, - { vec(0, -1, 0), vec(-1, 0, 0), vec(-1, 0, 0) }, - { vec(0, 0, 1), vec( 0, 0, 1), vec( 0, -1, 0) }, - { vec(0, 1, 0), vec( 1, 0, 0), vec( 1, 0, 0) }, - { vec(0, 0, -1), vec( 0, 0, -1), vec( 0, 1, 0) }, - { vec(0, 0, 1), vec( 0, 0, 1), vec( 0, -1, 0) }, - { vec(0, 1, 0), vec( 1, 0, 0), vec( 1, 0, 0) }, - { vec(0, -1, 0), vec(-1, 0, 0), vec(-1, 0, 0) }, +extern const vec orientation_bitangent[8][3] = { + { + vec(0, 0, -1), vec( 0, 0, -1), vec( 0, 1, 0) }, { + vec(0, -1, 0), vec(-1, 0, 0), vec(-1, 0, 0) }, { + vec(0, 0, 1), vec( 0, 0, 1), vec( 0, -1, 0) }, { + vec(0, 1, 0), vec( 1, 0, 0), vec( 1, 0, 0) }, { + vec(0, 0, -1), vec( 0, 0, -1), vec( 0, 1, 0) }, { + vec(0, 0, 1), vec( 0, 0, 1), vec( 0, -1, 0) }, { + vec(0, 1, 0), vec( 1, 0, 0), vec( 1, 0, 0) }, { + vec(0, -1, 0), vec(-1, 0, 0), vec(-1, 0, 0) }, }; -void addtris(const sortkey &key, int orient, vertex *verts, int *index, int numverts, int convex, int shadowmask, int tj) -{ +void addtris(const sortkey &key, int orient, vertex *verts, int *index, int numverts, int convex, int shadowmask, int tj) { int &total = vc.worldtris; int edge = orient*(MAXFACEVERTS+1); - loopi(numverts-2) if(index[0]!=index[i+1] && index[i+1]!=index[i+2] && index[i+2]!=index[0]) - { + loopi(numverts-2) if(index[0]!=index[i+1] && index[i+1]!=index[i+2] && index[i+2]!=index[0]) { vector<ushort> &idxs = vc.indices[key].tris[(shadowmask>>i)&1]; int left = index[0], mid = index[i+1], right = index[i+2], start = left, i0 = left, i1 = -1; - loopk(4) - { + loopk(4) { int i2 = -1, ctj = -1, cedge = -1; - switch(k) - { + switch(k) { case 1: i1 = i2 = mid; cedge = edge+i+1; break; case 2: if(i1 != mid || i0 == left) { i0 = i1; i1 = right; } i2 = right; if(i+1 == numverts-2) cedge = edge+i+2; break; case 3: if(i0 == start) { i0 = i1; i1 = left; } i2 = left; // fall-through default: if(!i) cedge = edge; break; } - if(i1 != i2) - { + if(i1 != i2) { if(total + 3 > USHRT_MAX) return; total += 3; idxs.add(i0); @@ -575,18 +474,15 @@ void addtris(const sortkey &key, int orient, vertex *verts, int *index, int numv idxs.add(i2); i1 = i2; } - if(cedge >= 0) - { - for(ctj = tj;;) - { + if(cedge >= 0) { + for(ctj = tj;;) { if(ctj < 0) break; if(tjoints[ctj].edge < cedge) { ctj = tjoints[ctj].next; continue; } if(tjoints[ctj].edge != cedge) ctj = -1; break; } } - if(ctj >= 0) - { + if(ctj >= 0) { int e1 = cedge%(MAXFACEVERTS+1), e2 = (e1+1)%numverts; vertex &v1 = verts[e1], &v2 = verts[e2]; ivec d(vec(v2.pos).sub(v1.pos).mul(8)); @@ -598,15 +494,12 @@ void addtris(const sortkey &key, int orient, vertex *verts, int *index, int numv offset2 = (int(v2.pos[axis]*8) - origin) / d[axis]; vec o = vec(v1.pos).sub(vec(d).mul(offset1/8.0f)); float doffset = 1.0f / (offset2 - offset1); - - if(i1 < 0) for(;;) - { + if(i1 < 0) for(;;) { tjoint &t = tjoints[ctj]; if(t.next < 0 || tjoints[t.next].edge != cedge) break; ctj = t.next; } - while(ctj >= 0) - { + while(ctj >= 0) { tjoint &t = tjoints[ctj]; if(t.edge != cedge) break; float offset = (t.offset - offset1) * doffset; @@ -619,8 +512,7 @@ void addtris(const sortkey &key, int orient, vertex *verts, int *index, int numv vt.tangent.lerp(v1.tangent, v2.tangent, offset); int i2 = vc.addvert(vt); if(i2 < 0) return; - if(i1 >= 0) - { + if(i1 >= 0) { if(total + 3 > USHRT_MAX) return; total += 3; idxs.add(i0); @@ -636,8 +528,7 @@ void addtris(const sortkey &key, int orient, vertex *verts, int *index, int numv } } -static inline void calctexgen(VSlot &vslot, int dim, vec4 &sgen, vec4 &tgen) -{ +static inline void calctexgen(VSlot &vslot, int dim, vec4 &sgen, vec4 &tgen) { Texture *tex = vslot.slot->sts.empty() ? notexture : vslot.slot->sts[0].t; const texrotation &r = texrotations[vslot.rotation]; float k = TEX_SCALE/vslot.scale, @@ -650,53 +541,45 @@ static inline void calctexgen(VSlot &vslot, int dim, vec4 &sgen, vec4 &tgen) int sdim = si[dim], tdim = ti[dim]; sgen = vec4(0, 0, 0, soff); tgen = vec4(0, 0, 0, toff); - if(r.swapxy) - { + if(r.swapxy) { sgen[tdim] = (dim <= 1 ? -sk : sk); tgen[sdim] = tk; } - else - { + else { sgen[sdim] = sk; tgen[tdim] = (dim <= 1 ? -tk : tk); } } -ushort encodenormal(const vec &n) -{ +ushort encodenormal(const vec &n) { if(n.iszero()) return 0; int yaw = int(-atan2(n.x, n.y)/RAD), pitch = int(asin(n.z)/RAD); return ushort(clamp(pitch + 90, 0, 180)*360 + (yaw < 0 ? yaw%360 + 360 : yaw%360) + 1); } -vec decodenormal(ushort norm) -{ +vec decodenormal(ushort norm) { if(!norm) return vec(0, 0, 1); norm--; const vec2 &yaw = sincos360[norm%360], &pitch = sincos360[norm/360+270]; return vec(-yaw.y*pitch.x, yaw.x*pitch.x, pitch.y); } -void guessnormals(const vec *pos, int numverts, vec *normals) -{ +void guessnormals(const vec *pos, int numverts, vec *normals) { vec n1, n2; n1.cross(pos[0], pos[1], pos[2]); - if(numverts != 4) - { + if(numverts != 4) { n1.normalize(); loopk(numverts) normals[k] = n1; return; } n2.cross(pos[0], pos[2], pos[3]); - if(n1.iszero()) - { + if(n1.iszero()) { n2.normalize(); loopk(4) normals[k] = n2; return; } else n1.normalize(); - if(n2.iszero()) - { + if(n2.iszero()) { loopk(4) normals[k] = n1; return; } @@ -708,16 +591,13 @@ void guessnormals(const vec *pos, int numverts, vec *normals) normals[3] = n2; } -void addcubeverts(VSlot &vslot, int orient, int size, vec *pos, int convex, ushort texture, ushort lmid, vertinfo *vinfo, int numverts, int tj = -1, int grassy = 0, bool alpha = false, int layer = LAYER_TOP) -{ +void addcubeverts(VSlot &vslot, int orient, int size, vec *pos, int convex, ushort texture, ushort lmid, vertinfo *vinfo, int numverts, int tj = -1, int grassy = 0, bool alpha = false, int layer = LAYER_TOP) { (void) grassy; int dim = dimension(orient); int shadowmask = alpha ? 0 : calcshadowmask(pos, numverts); - LightMap *lm = NULL; LightMapTexture *lmtex = NULL; - if(lightmaps.inrange(lmid-LMID_RESERVED)) - { + if(lightmaps.inrange(lmid-LMID_RESERVED)) { lm = &lightmaps[lmid-LMID_RESERVED]; if((lm->type&LM_TYPE)==LM_DIFFUSE || ((lm->type&LM_TYPE)==LM_BUMPMAP0 && @@ -726,70 +606,58 @@ void addcubeverts(VSlot &vslot, int orient, int size, vec *pos, int convex, usho lmtex = &lightmaptexs[lm->tex]; else lm = NULL; } - vec4 sgen, tgen; calctexgen(vslot, dim, sgen, tgen); vertex verts[MAXFACEVERTS]; int index[MAXFACEVERTS]; - loopk(numverts) - { + loopk(numverts) { vertex &v = verts[k]; v.pos = pos[k]; v.tc = vec2(sgen.dot(v.pos), tgen.dot(v.pos)); - if(lmtex) - { + if(lmtex) { v.lm = svec2(short(ceil((lm->offsetx + vinfo[k].u*(float(LM_PACKW)/float(USHRT_MAX+1)) + 0.5f) * float(SHRT_MAX)/lmtex->w)), short(ceil((lm->offsety + vinfo[k].v*(float(LM_PACKH)/float(USHRT_MAX+1)) + 0.5f) * float(SHRT_MAX)/lmtex->h))); } else v.lm = svec2(0, 0); - if(vinfo && vinfo[k].norm) - { + if(vinfo && vinfo[k].norm) { vec n = decodenormal(vinfo[k].norm), t = orientation_tangent[vslot.rotation][dim]; t.project(n).normalize(); v.norm = bvec(n); v.tangent = bvec4(bvec(t), orientation_bitangent[vslot.rotation][dim].scalartriple(n, t) < 0 ? 0 : 255); } - else - { + else { v.norm = bvec(128, 128, 255); v.tangent = bvec4(255, 128, 128, 255); } index[k] = vc.addvert(v); if(index[k] < 0) return; } - if(lmid >= LMID_RESERVED) lmid = lm ? lm->tex : LMID_AMBIENT; - sortkey key(texture, lmid, !vslot.scroll.iszero() ? dim : 3, layer == LAYER_BLEND ? LAYER_BLEND : LAYER_TOP, alpha ? (vslot.alphaback ? ALPHA_BACK : (vslot.alphafront ? ALPHA_FRONT : NO_ALPHA)) : NO_ALPHA); addtris(key, orient, verts, index, numverts, convex, shadowmask, tj); } -struct edgegroup -{ +struct edgegroup { ivec slope, origin; int axis; }; -static uint hthash(const edgegroup &g) -{ +static uint hthash(const edgegroup &g) { return g.slope.x^(g.slope.y<<2)^(g.slope.z<<4)^g.origin.x^g.origin.y^g.origin.z; } -static bool htcmp(const edgegroup &x, const edgegroup &y) -{ +static bool htcmp(const edgegroup &x, const edgegroup &y) { return x.slope==y.slope && x.origin==y.origin; } -enum -{ +enum { CE_START = 1<<0, CE_END = 1<<1, CE_FLIP = 1<<2, CE_DUP = 1<<3 }; -struct cubeedge -{ +struct cubeedge { cube *c; int next, offset; ushort size; @@ -799,26 +667,21 @@ struct cubeedge vector<cubeedge> cubeedges; hashtable<edgegroup, int> edgegroups(1<<13); -void gencubeedges(cube &c, const ivec &co, int size) -{ +void gencubeedges(cube &c, const ivec &co, int size) { ivec pos[MAXFACEVERTS]; int vis; - loopi(6) if((vis = visibletris(c, i, co, size))) - { + loopi(6) if((vis = visibletris(c, i, co, size))) { int numverts = c.ext ? c.ext->surfaces[i].numverts&MAXFACEVERTS : 0; - if(numverts) - { + if(numverts) { vertinfo *verts = c.ext->verts() + c.ext->surfaces[i].verts; ivec vo = ivec(co).mask(~0xFFF).shl(3); - loopj(numverts) - { + loopj(numverts) { vertinfo &v = verts[j]; pos[j] = ivec(v.x, v.y, v.z).add(vo); } } else if(c.merged&(1<<i)) continue; - else - { + else { ivec v[4]; genfaceverts(c, i, v); int order = vis&4 || (!flataxisface(c, i) && faceconvexity(v) < 0) ? 1 : 0; @@ -828,20 +691,17 @@ void gencubeedges(cube &c, const ivec &co, int size) pos[numverts++] = v[order+2].mul(size).add(vo); if(vis&2) pos[numverts++] = v[(order+3)&3].mul(size).add(vo); } - loopj(numverts) - { + loopj(numverts) { int e1 = j, e2 = j+1 < numverts ? j+1 : 0; ivec d = pos[e2]; d.sub(pos[e1]); if(d.iszero()) continue; int axis = abs(d.x) > abs(d.y) ? (abs(d.x) > abs(d.z) ? 0 : 2) : (abs(d.y) > abs(d.z) ? 1 : 2); - if(d[axis] < 0) - { + if(d[axis] < 0) { d.neg(); swap(e1, e2); } reduceslope(d); - int t1 = pos[e1][axis]/d[axis], t2 = pos[e2][axis]/d[axis]; edgegroup g; @@ -855,22 +715,17 @@ void gencubeedges(cube &c, const ivec &co, int size) ce.index = i*(MAXFACEVERTS+1)+j; ce.flags = CE_START | CE_END | (e1!=j ? CE_FLIP : 0); ce.next = -1; - bool insert = true; int *exists = edgegroups.access(g); - if(exists) - { + if(exists) { int prev = -1, cur = *exists; - while(cur >= 0) - { + while(cur >= 0) { cubeedge &p = cubeedges[cur]; - if(ce.offset <= p.offset+p.size) - { + if(ce.offset <= p.offset+p.size) { if(ce.offset < p.offset) break; if(p.flags&CE_DUP ? ce.offset+ce.size <= p.offset+p.size : - ce.offset==p.offset && ce.size==p.size) - { + ce.offset==p.offset && ce.size==p.size) { p.flags |= CE_DUP; insert = false; break; @@ -880,11 +735,9 @@ void gencubeedges(cube &c, const ivec &co, int size) prev = cur; cur = p.next; } - if(insert) - { + if(insert) { ce.next = cur; - while(cur >= 0) - { + while(cur >= 0) { cubeedge &p = cubeedges[cur]; if(ce.offset+ce.size==p.offset) { ce.flags &= ~CE_END; break; } cur = p.next; @@ -894,18 +747,15 @@ void gencubeedges(cube &c, const ivec &co, int size) } } else edgegroups[g] = cubeedges.length(); - if(insert) cubeedges.add(ce); } } } -void gencubeedges(cube *c = worldroot, const ivec &co = ivec(0, 0, 0), int size = worldsize>>1) -{ +void gencubeedges(cube *c = worldroot, const ivec &co = ivec(0, 0, 0), int size = worldsize>>1) { progress("fixing t-joints..."); neighbourstack[++neighbourdepth] = c; - loopi(8) - { + loopi(8) { ivec o(i, co, size); if(c[i].ext) c[i].ext->tjoints = -1; if(c[i].children) gencubeedges(c[i].children, o, size>>1); @@ -914,29 +764,23 @@ void gencubeedges(cube *c = worldroot, const ivec &co = ivec(0, 0, 0), int size --neighbourdepth; } -void gencubeverts(cube &c, const ivec &co, int size, int csi) -{ +void gencubeverts(cube &c, const ivec &co, int size, int csi) { if(!(c.visible&0xC0)) return; - int vismask = ~c.merged & 0x3F; if(!(c.visible&0x80)) vismask &= c.visible; if(!vismask) return; - int tj = filltjoints && c.ext ? c.ext->tjoints : -1, vis; - loopi(6) if(vismask&(1<<i) && (vis = visibletris(c, i, co, size))) - { + loopi(6) if(vismask&(1<<i) && (vis = visibletris(c, i, co, size))) { vec pos[MAXFACEVERTS]; vertinfo *verts = NULL; int numverts = c.ext ? c.ext->surfaces[i].numverts&MAXFACEVERTS : 0, convex = 0; - if(numverts) - { + if(numverts) { verts = c.ext->verts() + c.ext->surfaces[i].verts; vec vo(ivec(co).mask(~0xFFF)); loopj(numverts) pos[j] = vec(verts[j].getxyz()).mul(1.0f/8).add(vo); if(!flataxisface(c, i)) convex = faceconvexity(verts, numverts, size); } - else - { + else { ivec v[4]; genfaceverts(c, i, v); if(!flataxisface(c, i)) convex = faceconvexity(v); @@ -947,15 +791,13 @@ void gencubeverts(cube &c, const ivec &co, int size, int csi) pos[numverts++] = vec(v[order+2]).mul(size/8.0f).add(vo); if(vis&2) pos[numverts++] = vec(v[(order+3)&3]).mul(size/8.0f).add(vo); } - VSlot &vslot = lookupvslot(c.texture[i], true), *layer = vslot.layer && !(c.material&MAT_ALPHA) ? &lookupvslot(vslot.layer, true) : NULL; while(tj >= 0 && tjoints[tj].edge < i*(MAXFACEVERTS+1)) tj = tjoints[tj].next; int hastj = tj >= 0 && tjoints[tj].edge < (i+1)*(MAXFACEVERTS+1) ? tj : -1; if(!c.ext) addcubeverts(vslot, i, size, pos, convex, c.texture[i], LMID_AMBIENT, NULL, numverts, hastj, 0, (c.material&MAT_ALPHA)!=0); - else - { + else { const surfaceinfo &surf = c.ext->surfaces[i]; if(!surf.numverts || surf.numverts&LAYER_TOP) addcubeverts(vslot, i, size, pos, convex, c.texture[i], surf.lmid[0], verts, numverts, hastj, 0, (c.material&MAT_ALPHA)!=0, LAYER_TOP|(surf.numverts&LAYER_BLEND)); @@ -971,10 +813,8 @@ int allocva = 0; int wtris = 0, wverts = 0, vtris = 0, vverts = 0, glde = 0, gbatches = 0; vector<vtxarray *> valist, varoot; -vtxarray *newva(const ivec &co, int size) -{ +vtxarray *newva(const ivec &co, int size) { vc.optimize(); - vtxarray *va = new vtxarray; va->parent = NULL; va->o = co; @@ -986,29 +826,23 @@ vtxarray *newva(const ivec &co, int size) va->bbmax = ivec(-1, -1, -1); va->hasmerges = 0; va->mergelevel = -1; - vc.setupdata(va); - wverts += va->verts; wtris += va->tris + va->blends + va->alphatris; allocva++; valist.add(va); - return va; } -void destroyva(vtxarray *va, bool reparent) -{ +void destroyva(vtxarray *va, bool reparent) { wverts -= va->verts; wtris -= va->tris + va->blends + va->alphatris; allocva--; valist.removeobj(va); if(!va->parent) varoot.removeobj(va); - if(reparent) - { + if(reparent) { if(va->parent) va->parent->children.removeobj(va); - loopv(va->children) - { + loopv(va->children) { vtxarray *child = va->children[i]; child->parent = va->parent; if(child->parent) child->parent->children.add(child); @@ -1021,12 +855,9 @@ void destroyva(vtxarray *va, bool reparent) delete va; } -void clearvas(cube *c) -{ - loopi(8) - { - if(c[i].ext) - { +void clearvas(cube *c) { + loopi(8) { + if(c[i].ext) { if(c[i].ext->va) destroyva(c[i].ext->va, false); c[i].ext->va = NULL; c[i].ext->tjoints = -1; @@ -1035,23 +866,19 @@ void clearvas(cube *c) } } -void updatevabb(vtxarray *va, bool force) -{ +void updatevabb(vtxarray *va, bool force) { if(!force && va->bbmin.x >= 0) return; - va->bbmin = va->geommin; va->bbmax = va->geommax; va->bbmin.min(va->matmin); va->bbmax.max(va->matmax); - loopv(va->children) - { + loopv(va->children) { vtxarray *child = va->children[i]; updatevabb(child, force); va->bbmin.min(child->bbmin); va->bbmax.max(child->bbmax); } - loopv(va->mapmodels) - { + loopv(va->mapmodels) { octaentities *oe = va->mapmodels[i]; va->bbmin.min(oe->bbmin); va->bbmax.max(oe->bbmax); @@ -1060,13 +887,11 @@ void updatevabb(vtxarray *va, bool force) va->bbmax.min(ivec(va->o).add(va->size)); } -void updatevabbs(bool force) -{ +void updatevabbs(bool force) { loopv(varoot) updatevabb(varoot[i], force); } -struct mergedface -{ +struct mergedface { uchar orient, lmid, numverts; ushort mat, tex; vertinfo *verts; @@ -1077,16 +902,13 @@ struct mergedface static int vahasmerges = 0, vamergemax = 0; static vector<mergedface> vamerges[MAXMERGELEVEL+1]; -int genmergedfaces(cube &c, const ivec &co, int size, int minlevel = -1) -{ +int genmergedfaces(cube &c, const ivec &co, int size, int minlevel = -1) { if(!c.ext || isempty(c)) return -1; int tj = c.ext->tjoints, maxlevel = -1; - loopi(6) if(c.merged&(1<<i)) - { + loopi(6) if(c.merged&(1<<i)) { surfaceinfo &surf = c.ext->surfaces[i]; int numverts = surf.numverts&MAXFACEVERTS; - if(!numverts) - { + if(!numverts) { if(minlevel < 0) vahasmerges |= MERGE_PART; continue; } @@ -1099,18 +921,13 @@ int genmergedfaces(cube &c, const ivec &co, int size, int minlevel = -1) mf.verts = c.ext->verts() + surf.verts; mf.tjoints = -1; int level = calcmergedsize(i, co, size, mf.verts, mf.numverts&MAXFACEVERTS); - if(level > minlevel) - { + if(level > minlevel) { maxlevel = max(maxlevel, level); - while(tj >= 0 && tjoints[tj].edge < i*(MAXFACEVERTS+1)) tj = tjoints[tj].next; if(tj >= 0 && tjoints[tj].edge < (i+1)*(MAXFACEVERTS+1)) mf.tjoints = tj; - VSlot &vslot = lookupvslot(mf.tex, true); - if(surf.numverts&LAYER_TOP) vamerges[level].add(mf); - if(surf.numverts&LAYER_BOTTOM) - { + if(surf.numverts&LAYER_BOTTOM) { mf.tex = vslot.layer; mf.lmid = surf.lmid[1]; mf.numverts &= ~LAYER_TOP; @@ -1119,22 +936,18 @@ int genmergedfaces(cube &c, const ivec &co, int size, int minlevel = -1) } } } - if(maxlevel >= 0) - { + if(maxlevel >= 0) { vamergemax = max(vamergemax, maxlevel); vahasmerges |= MERGE_ORIGIN; } return maxlevel; } -int findmergedfaces(cube &c, const ivec &co, int size, int csi, int minlevel) -{ +int findmergedfaces(cube &c, const ivec &co, int size, int csi, int minlevel) { if(c.ext && c.ext->va && !(c.ext->va->hasmerges&MERGE_ORIGIN)) return c.ext->va->mergelevel; - else if(c.children) - { + else if(c.children) { int maxlevel = -1; - loopi(8) - { + loopi(8) { ivec o(i, co, size/2); int level = findmergedfaces(c.children[i], o, size/2, csi-1, minlevel); maxlevel = max(maxlevel, level); @@ -1145,18 +958,15 @@ int findmergedfaces(cube &c, const ivec &co, int size, int csi, int minlevel) else return -1; } -void addmergedverts(int level, const ivec &o) -{ +void addmergedverts(int level, const ivec &o) { vector<mergedface> &mfl = vamerges[level]; if(mfl.empty()) return; vec vo(ivec(o).mask(~0xFFF)); vec pos[MAXFACEVERTS]; - loopv(mfl) - { + loopv(mfl) { mergedface &mf = mfl[i]; int numverts = mf.numverts&MAXFACEVERTS; - loopi(numverts) - { + loopi(numverts) { vertinfo &v = mf.verts[i]; pos[i] = vec(v.x, v.y, v.z).mul(1.0f/8).add(vo); } @@ -1167,21 +977,16 @@ void addmergedverts(int level, const ivec &o) mfl.setsize(0); } -void rendercube(cube &c, const ivec &co, int size, int csi, int &maxlevel) // creates vertices and indices ready to be put into a va -{ +void rendercube(cube &c, const ivec &co, int size, int csi, int &maxlevel) { // creates vertices and indices ready to be put into a va { //if(size<=16) return; - if(c.ext && c.ext->va) - { + if(c.ext && c.ext->va) { maxlevel = max(maxlevel, c.ext->va->mergelevel); return; // don't re-render } - - if(c.children) - { + if(c.children) { neighbourstack[++neighbourdepth] = c.children; c.escaped = 0; - loopi(8) - { + loopi(8) { ivec o(i, co, size/2); int level = -1; rendercube(c.children[i], o, size/2, csi-1, level); @@ -1190,91 +995,65 @@ void rendercube(cube &c, const ivec &co, int size, int csi, int &maxlevel) // c maxlevel = max(maxlevel, level); } --neighbourdepth; - if(csi <= MAXMERGELEVEL && vamerges[csi].length()) addmergedverts(csi, co); - - if(c.ext) - { + if(c.ext) { if(c.ext->ents && c.ext->ents->mapmodels.length()) vc.mapmodels.add(c.ext->ents); } return; } - - if(!isempty(c)) - { + if(!isempty(c)) { gencubeverts(c, co, size, csi); if(c.merged) maxlevel = max(maxlevel, genmergedfaces(c, co, size)); } if(c.material != MAT_AIR) genmatsurfs(c, co, size, vc.matsurfs); - - if(c.ext) - { + if(c.ext) { if(c.ext->ents && c.ext->ents->mapmodels.length()) vc.mapmodels.add(c.ext->ents); } - if(csi <= MAXMERGELEVEL && vamerges[csi].length()) addmergedverts(csi, co); } -void calcgeombb(const ivec &co, int size, ivec &bbmin, ivec &bbmax) -{ +void calcgeombb(const ivec &co, int size, ivec &bbmin, ivec &bbmax) { vec vmin(co), vmax = vmin; vmin.add(size); - - loopv(vc.verts) - { + loopv(vc.verts) { const vec &v = vc.verts[i].pos; vmin.min(v); vmax.max(v); } - bbmin = ivec(vmin.mul(8)).shr(3); bbmax = ivec(vmax.mul(8)).add(7).shr(3); } -void calcmatbb(const ivec &co, int size, ivec &bbmin, ivec &bbmax) -{ +void calcmatbb(const ivec &co, int size, ivec &bbmin, ivec &bbmax) { bbmax = co; (bbmin = bbmax).add(size); - loopv(vc.matsurfs) - { + loopv(vc.matsurfs) { materialsurface &m = vc.matsurfs[i]; - int dim = dimension(m.orient), r = R[dim], c = C[dim]; bbmin[dim] = min(bbmin[dim], m.o[dim]); bbmax[dim] = max(bbmax[dim], m.o[dim]); - bbmin[r] = min(bbmin[r], m.o[r]); bbmax[r] = max(bbmax[r], m.o[r] + m.rsize); - bbmin[c] = min(bbmin[c], m.o[c]); bbmax[c] = max(bbmax[c], m.o[c] + m.csize); } } -void setva(cube &c, const ivec &co, int size, int csi) -{ +void setva(cube &c, const ivec &co, int size, int csi) { ASSERT(size <= 0x1000); - int vamergeoffset[MAXMERGELEVEL+1]; loopi(MAXMERGELEVEL+1) vamergeoffset[i] = vamerges[i].length(); - vc.origin = co; vc.size = size; - shadowmapmin = vec(co).add(size); shadowmapmax = vec(co); - int maxlevel = -1; rendercube(c, co, size, csi, maxlevel); - ivec bbmin, bbmax; - calcgeombb(co, size, bbmin, bbmax); - - if(size == min(0x1000, worldsize/2) || !vc.emptyva()) - { + if(size == min(0x1000, worldsize/2) || !vc.emptyva()) { vtxarray *va = newva(co, size); ext(c).va = va; va->geommin = bbmin; @@ -1285,29 +1064,22 @@ void setva(cube &c, const ivec &co, int size, int csi) va->hasmerges = vahasmerges; va->mergelevel = vamergemax; } - else - { + else { loopi(MAXMERGELEVEL+1) vamerges[i].setsize(vamergeoffset[i]); } - vc.clear(); } -static inline int setcubevisibility(cube &c, const ivec &co, int size) -{ +static inline int setcubevisibility(cube &c, const ivec &co, int size) { int numvis = 0, vismask = 0, collidemask = 0, checkmask = 0; - loopi(6) - { + loopi(6) { int facemask = classifyface(c, i, co, size); - if(facemask&1) - { + if(facemask&1) { vismask |= 1<<i; - if(c.merged&(1<<i)) - { + if(c.merged&(1<<i)) { if(c.ext && c.ext->surfaces[i].numverts&MAXFACEVERTS) numvis++; } - else - { + else { numvis++; if(!(c.ext && c.ext->surfaces[i].numverts&MAXFACEVERTS)) checkmask |= 1<<i; } @@ -1322,45 +1094,36 @@ VARF(vafacemax, 64, 384, 256*256, allchanged()); VARF(vafacemin, 0, 96, 256*256, allchanged()); VARF(vacubesize, 32, 128, 0x1000, allchanged()); -int updateva(cube *c, const ivec &co, int size, int csi) -{ +int updateva(cube *c, const ivec &co, int size, int csi) { progress("recalculating geometry..."); int ccount = 0, cmergemax = vamergemax, chasmerges = vahasmerges; neighbourstack[++neighbourdepth] = c; - loopi(8) // counting number of semi-solid/solid children cubes - { + loopi(8) { // counting number of semi-solid/solid children cubes { int count = 0, childpos = varoot.length(); ivec o(i, co, size); vamergemax = 0; vahasmerges = 0; - if(c[i].ext && c[i].ext->va) - { + if(c[i].ext && c[i].ext->va) { varoot.add(c[i].ext->va); if(c[i].ext->va->hasmerges&MERGE_ORIGIN) findmergedfaces(c[i], o, size, csi, csi); } - else - { + else { if(c[i].children) count += updateva(c[i].children, o, size/2, csi-1); - else - { + else { if(!isempty(c[i])) count += setcubevisibility(c[i], o, size); } int tcount = count + (csi <= MAXMERGELEVEL ? vamerges[csi].length() : 0); - if(tcount > vafacemax || (tcount >= vafacemin && size >= vacubesize) || size == min(0x1000, worldsize/2)) - { + if(tcount > vafacemax || (tcount >= vafacemin && size >= vacubesize) || size == min(0x1000, worldsize/2)) { loadprogress = clamp(recalcprogress/float(allocnodes), 0.0f, 1.0f); setva(c[i], o, size, csi); - if(c[i].ext && c[i].ext->va) - { - while(varoot.length() > childpos) - { + if(c[i].ext && c[i].ext->va) { + while(varoot.length() > childpos) { vtxarray *child = varoot.pop(); c[i].ext->va->children.add(child); child->parent = c[i].ext->va; } varoot.add(c[i].ext->va); - if(vamergemax > size) - { + if(vamergemax > size) { cmergemax = max(cmergemax, vamergemax); chasmerges |= vahasmerges&~MERGE_USE; } @@ -1377,58 +1140,46 @@ int updateva(cube *c, const ivec &co, int size, int csi) --neighbourdepth; vamergemax = cmergemax; vahasmerges = chasmerges; - return ccount; } -void addtjoint(const edgegroup &g, const cubeedge &e, int offset) -{ +void addtjoint(const edgegroup &g, const cubeedge &e, int offset) { int vcoord = (g.slope[g.axis]*offset + g.origin[g.axis]) & 0x7FFF; tjoint &tj = tjoints.add(); tj.offset = vcoord / g.slope[g.axis]; tj.edge = e.index; - int prev = -1, cur = ext(*e.c).tjoints; - while(cur >= 0) - { + while(cur >= 0) { tjoint &o = tjoints[cur]; if(tj.edge < o.edge || (tj.edge==o.edge && (e.flags&CE_FLIP ? tj.offset > o.offset : tj.offset < o.offset))) break; prev = cur; cur = o.next; } - tj.next = cur; if(prev < 0) e.c->ext->tjoints = tjoints.length()-1; else tjoints[prev].next = tjoints.length()-1; } -void findtjoints(int cur, const edgegroup &g) -{ +void findtjoints(int cur, const edgegroup &g) { int active = -1; - while(cur >= 0) - { + while(cur >= 0) { cubeedge &e = cubeedges[cur]; int prevactive = -1, curactive = active; - while(curactive >= 0) - { + while(curactive >= 0) { cubeedge &a = cubeedges[curactive]; - if(a.offset+a.size <= e.offset) - { + if(a.offset+a.size <= e.offset) { if(prevactive >= 0) cubeedges[prevactive].next = a.next; else active = a.next; } - else - { + else { prevactive = curactive; - if(!(a.flags&CE_DUP)) - { + if(!(a.flags&CE_DUP)) { if(e.flags&CE_START && e.offset > a.offset && e.offset < a.offset+a.size) addtjoint(g, a, e.offset); if(e.flags&CE_END && e.offset+e.size > a.offset && e.offset+e.size < a.offset+a.size) addtjoint(g, a, e.offset+e.size); } - if(!(e.flags&CE_DUP)) - { + if(!(e.flags&CE_DUP)) { if(a.flags&CE_START && a.offset > e.offset && a.offset < e.offset+e.size) addtjoint(g, e, a.offset); if(a.flags&CE_END && a.offset+a.size > e.offset && a.offset+a.size < e.offset+e.size) @@ -1444,8 +1195,7 @@ void findtjoints(int cur, const edgegroup &g) } } -void findtjoints() -{ +void findtjoints() { recalcprogress = 0; gencubeedges(); tjoints.setsize(0); @@ -1454,38 +1204,31 @@ void findtjoints() edgegroups.clear(); } -void octarender() // creates va s for all leaf cubes that don't already have them -{ +void octarender() { // creates va s for all leaf cubes that don't already have them { int csi = 0; while(1<<csi < worldsize) csi++; - recalcprogress = 0; varoot.setsize(0); updateva(worldroot, ivec(0, 0, 0), worldsize/2, csi-1); loadprogress = 0; flushvbo(); - visibleva = NULL; } -void precachetextures() -{ +void precachetextures() { vector<int> texs; - loopv(valist) - { + loopv(valist) { vtxarray *va = valist[i]; loopj(va->texs + va->blends) if(texs.find(va->eslist[j].texture) < 0) texs.add(va->eslist[j].texture); } - loopv(texs) - { + loopv(texs) { loadprogress = float(i+1)/texs.length(); lookupvslot(texs[i]); } loadprogress = 0; } -void allchanged(bool load) -{ +void allchanged(bool load) { renderprogress(0, "clearing vertex arrays..."); clearvas(worldroot); resetqueries(); @@ -1499,15 +1242,13 @@ void allchanged(bool load) setupmaterials(); updatevabbs(true); lightents(); - if(load) - { + if(load) { seedparticles(); drawtextures(); } } -void recalc() -{ +void recalc() { allchanged(true); } diff --git a/src/engine/physics.cpp b/src/engine/physics.cpp index b1b800a..a43e8b4 100644 --- a/src/engine/physics.cpp +++ b/src/engine/physics.cpp @@ -10,11 +10,9 @@ const int MAXCLIPPLANES = 1024; static clipplanes clipcache[MAXCLIPPLANES]; static int clipcacheversion = -2; -static inline clipplanes &getclipplanes(const cube &c, const ivec &o, int size, bool collide = true, int offset = 0) -{ +static inline clipplanes &getclipplanes(const cube &c, const ivec &o, int size, bool collide = true, int offset = 0) { clipplanes &p = clipcache[int(&c - worldroot)&(MAXCLIPPLANES-1)]; - if(p.owner != &c || p.version != clipcacheversion+offset) - { + if(p.owner != &c || p.version != clipcacheversion+offset) { p.owner = &c; p.version = clipcacheversion+offset; genclipplanes(c, o, size, p, collide); @@ -22,11 +20,9 @@ static inline clipplanes &getclipplanes(const cube &c, const ivec &o, int size, return p; } -void resetclipplanes() -{ +void resetclipplanes() { clipcacheversion += 2; - if(!clipcacheversion) - { + if(!clipcacheversion) { memclear(clipcache); clipcacheversion = 2; } @@ -36,24 +32,24 @@ void resetclipplanes() #define INTERSECTPLANES(setentry, exit) \ float enterdist = -1e16f, exitdist = 1e16f; \ - loopi(p.size) \ - { \ + loopi(p.size) { \ + \ float pdist = p.p[i].dist(v), facing = ray.dot(p.p[i]); \ - if(facing < 0) \ - { \ + if(facing < 0) { \ + \ pdist /= -facing; \ - if(pdist > enterdist) \ - { \ + if(pdist > enterdist) { \ + \ if(pdist > exitdist) exit; \ enterdist = pdist; \ setentry; \ } \ } \ - else if(facing > 0) \ - { \ + else if(facing > 0) { \ + \ pdist /= -facing; \ - if(pdist < exitdist) \ - { \ + if(pdist < exitdist) { \ + \ if(pdist < enterdist) exit; \ exitdist = pdist; \ } \ @@ -62,19 +58,19 @@ void resetclipplanes() } #define INTERSECTBOX(setentry, exit) \ - loop(i, 3) \ - { \ - if(ray[i]) \ - { \ + loop(i, 3) { \ + \ + if(ray[i]) { \ + \ float prad = fabs(p.r[i] * invray[i]), pdist = (p.o[i] - v[i]) * invray[i], pmin = pdist - prad, pmax = pdist + prad; \ - if(pmin > enterdist) \ - { \ + if(pmin > enterdist) { \ + \ if(pmin > exitdist) exit; \ enterdist = pmin; \ setentry; \ } \ - if(pmax < exitdist) \ - { \ + if(pmax < exitdist) { \ + \ if(pmax < enterdist) exit; \ exitdist = pmax; \ } \ @@ -84,8 +80,7 @@ void resetclipplanes() vec hitsurface; -static inline bool raycubeintersect(const clipplanes &p, const cube &c, const vec &v, const vec &ray, const vec &invray, float &dist) -{ +static inline bool raycubeintersect(const clipplanes &p, const cube &c, const vec &v, const vec &ray, const vec &invray, float &dist) { int entry = -1, bbentry = -1; INTERSECTPLANES(entry = i, return false); INTERSECTBOX(bbentry = i, return false); @@ -100,59 +95,50 @@ extern void entselectionbox(const entity &e, vec &eo, vec &es); float hitentdist; int hitent, hitorient; -static float disttoent(octaentities *oc, const vec &o, const vec &ray, float radius, int mode, extentity *t) -{ +static float disttoent(octaentities *oc, const vec &o, const vec &ray, float radius, int mode, extentity *t) { vec eo, es; int orient = -1; float dist = radius, f = 0.0f; const vector<extentity *> &ents = entities::getents(); - #define entintersect(mask, type, func) {\ - if((mode&(mask))==(mask)) loopv(oc->type) \ - { \ + if((mode&(mask))==(mask)) loopv(oc->type) { \ + \ extentity &e = *ents[oc->type[i]]; \ if(!(e.flags&EF_OCTA) || &e==t) continue; \ func; \ - if(f<dist && f>0 && vec(ray).mul(f).add(o).insidebb(oc->o, oc->size)) \ - { \ + if(f<dist && f>0 && vec(ray).mul(f).add(o).insidebb(oc->o, oc->size)) { \ + \ hitentdist = dist = f; \ hitent = oc->type[i]; \ hitorient = orient; \ } \ } \ } - entintersect(RAY_POLY, mapmodels, if(!mmintersect(e, o, ray, radius, mode, f)) continue; ); - entintersect(RAY_ENTS, other, entselectionbox(e, eo, es); if(!rayboxintersect(eo, es, o, ray, f, orient)) continue; ); - entintersect(RAY_ENTS, mapmodels, entselectionbox(e, eo, es); if(!rayboxintersect(eo, es, o, ray, f, orient)) continue; ); - return dist; } -static float disttooutsideent(const vec &o, const vec &ray, float radius, int mode, extentity *t) -{ +static float disttooutsideent(const vec &o, const vec &ray, float radius, int mode, extentity *t) { vec eo, es; int orient; float dist = radius, f = 0.0f; const vector<extentity *> &ents = entities::getents(); - loopv(outsideents) - { + loopv(outsideents) { extentity &e = *ents[outsideents[i]]; if(!(e.flags&EF_OCTA) || &e==t) continue; entselectionbox(e, eo, es); if(!rayboxintersect(eo, es, o, ray, f, orient)) continue; - if(f<dist && f>0) - { + if(f<dist && f>0) { hitentdist = dist = f; hitent = outsideents[i]; hitorient = orient; @@ -162,12 +148,10 @@ static float disttooutsideent(const vec &o, const vec &ray, float radius, int mo } // optimized shadow version -static float shadowent(octaentities *oc, const vec &o, const vec &ray, float radius, int mode, extentity *t) -{ +static float shadowent(octaentities *oc, const vec &o, const vec &ray, float radius, int mode, extentity *t) { float dist = radius, f = 0.0f; const vector<extentity *> &ents = entities::getents(); - loopv(oc->mapmodels) - { + loopv(oc->mapmodels) { extentity &e = *ents[oc->mapmodels[i]]; if(!(e.flags&EF_OCTA) || &e==t) continue; if(!mmintersect(e, o, ray, radius, mode, f)) continue; @@ -185,14 +169,14 @@ static float shadowent(octaentities *oc, const vec &o, const vec &ray, float rad ivec lsizemask(invray.x>0 ? 1 : 0, invray.y>0 ? 1 : 0, invray.z>0 ? 1 : 0); \ #define CHECKINSIDEWORLD \ - if(!insideworld(o)) \ - { \ + if(!insideworld(o)) { \ + \ float disttoworld = 0, exitworld = 1e16f; \ - loopi(3) \ - { \ + loopi(3) { \ + \ float c = v[i]; \ - if(c<0 || c>=worldsize) \ - { \ + if(c<0 || c>=worldsize) { \ + \ float d = ((invray[i]>0?0:worldsize)-c)*invray[i]; \ if(d<0) return (radius>0?radius:-1); \ disttoworld = max(disttoworld, 0.1f + d); \ @@ -207,15 +191,15 @@ static float shadowent(octaentities *oc, const vec &o, const vec &ray, float rad #define DOWNOCTREE(disttoent, earlyexit) \ cube *lc = levels[lshift]; \ - for(;;) \ - { \ + for(;;) { \ + \ lshift--; \ lc += octastep(x, y, z, lshift); \ - if(lc->ext && lc->ext->ents && lshift < elvl) \ - { \ + if(lc->ext && lc->ext->ents && lshift < elvl) { \ + \ float edist = disttoent(lc->ext->ents, o, ray, dent, mode, t); \ - if(edist < dent) \ - { \ + if(edist < dent) { \ + \ earlyexit return min(edist, dist); \ elvl = lshift; \ dent = min(dent, edist); \ @@ -246,103 +230,76 @@ static float shadowent(octaentities *oc, const vec &o, const vec &ray, float rad if(diff >= uint(worldsize)) exitworld; \ diff >>= lshift; \ if(!diff) exitworld; \ - do \ - { \ + do { \ + \ lshift++; \ diff >>= 1; \ } while(diff); -float raycube(const vec &o, const vec &ray, float radius, int mode, int size, extentity *t) -{ +float raycube(const vec &o, const vec &ray, float radius, int mode, int size, extentity *t) { if(ray.iszero()) return 0; - INITRAYCUBE; CHECKINSIDEWORLD; - int closest = -1, x = int(v.x), y = int(v.y), z = int(v.z); - for(;;) - { + for(;;) { DOWNOCTREE(disttoent, if(mode&RAY_SHADOW)); - int lsize = 1<<lshift; - cube &c = *lc; if((dist>0 || !(mode&RAY_SKIPFIRST)) && (((mode&RAY_EDITMAT) && c.material != MAT_AIR) || (!(mode&RAY_PASS) && lsize==size && !isempty(c)) || isentirelysolid(c) || - dent < dist)) - { + dent < dist)) { if(closest >= 0) { hitsurface = vec(0, 0, 0); hitsurface[closest] = ray[closest]>0 ? -1 : 1; } return min(dent, dist); } - ivec lo(x&(~0U<<lshift), y&(~0U<<lshift), z&(~0U<<lshift)); - - if(!isempty(c)) - { + if(!isempty(c)) { const clipplanes &p = getclipplanes(c, lo, lsize, false, 1); float f = 0; if(raycubeintersect(p, c, v, ray, invray, f) && (dist+f>0 || !(mode&RAY_SKIPFIRST))) return min(dent, dist+f); } - FINDCLOSEST(closest = 0, closest = 1, closest = 2); - if(radius>0 && dist>=radius) return min(dent, dist); - UPOCTREE(return min(dent, radius>0 ? radius : dist)); } } // optimized version for lightmap shadowing... every cycle here counts!!! -float shadowray(const vec &o, const vec &ray, float radius, int mode, extentity *t) -{ +float shadowray(const vec &o, const vec &ray, float radius, int mode, extentity *t) { INITRAYCUBE; CHECKINSIDEWORLD; - - int side = O_BOTTOM, x = int(v.x), y = int(v.y), z = int(v.z); - for(;;) - { + int side = O_BOTTOM, x = int(v.x), y = int(v.y), z = int(v.z); (void) side; + for(;;) { DOWNOCTREE(shadowent, ); - cube &c = *lc; ivec lo(x&(~0U<<lshift), y&(~0U<<lshift), z&(~0U<<lshift)); - - if(!isempty(c) && !(c.material&MAT_ALPHA)) - { - if(isentirelysolid(c)) - { + if(!isempty(c) && !(c.material&MAT_ALPHA)) { + if(isentirelysolid(c)) { return dist; } - else - { + else { const clipplanes &p = getclipplanes(c, lo, 1<<lshift, false, 1); INTERSECTPLANES(side = p.side[i], goto nextcube); INTERSECTBOX(side = (i<<1) + 1 - lsizemask[i], goto nextcube); - if(exitdist >= 0) - { + if(exitdist >= 0) { return dist+max(enterdist+0.1f, 0.0f); } } } - nextcube: FINDCLOSEST(side = O_RIGHT - lsizemask.x, side = O_FRONT - lsizemask.y, side = O_TOP - lsizemask.z); - if(dist>=radius) return dist; - UPOCTREE(return radius); } } // thread safe version -struct ShadowRayCache -{ +struct ShadowRayCache { clipplanes clipcache[MAXCLIPPLANES]; int version; - ShadowRayCache() : version(-1) {} }; @@ -350,65 +307,49 @@ ShadowRayCache *newshadowraycache() { return new ShadowRayCache; } void freeshadowraycache(ShadowRayCache *&cache) { delete cache; cache = NULL; } -void resetshadowraycache(ShadowRayCache *cache) -{ +void resetshadowraycache(ShadowRayCache *cache) { cache->version++; - if(!cache->version) - { + if(!cache->version) { memclear(cache->clipcache); cache->version = 1; } } -float shadowray(ShadowRayCache *cache, const vec &o, const vec &ray, float radius, int mode, extentity *t) -{ +float shadowray(ShadowRayCache *cache, const vec &o, const vec &ray, float radius, int mode, extentity *t) { INITRAYCUBE; CHECKINSIDEWORLD; - - int side = O_BOTTOM, x = int(v.x), y = int(v.y), z = int(v.z); - for(;;) - { + int side = O_BOTTOM, x = int(v.x), y = int(v.y), z = int(v.z); (void) side; + for(;;) { DOWNOCTREE(shadowent, ); - cube &c = *lc; ivec lo(x&(~0U<<lshift), y&(~0U<<lshift), z&(~0U<<lshift)); - - if(!isempty(c) && !(c.material&MAT_ALPHA)) - { - if(isentirelysolid(c)) - { + if(!isempty(c) && !(c.material&MAT_ALPHA)) { + if(isentirelysolid(c)) { return dist; } - else - { + else { clipplanes &p = cache->clipcache[int(&c - worldroot)&(MAXCLIPPLANES-1)]; if(p.owner != &c || p.version != cache->version) { p.owner = &c; p.version = cache->version; genclipplanes(c, lo, 1<<lshift, p, false); } INTERSECTPLANES(side = p.side[i], goto nextcube); INTERSECTBOX(side = (i<<1) + 1 - lsizemask[i], goto nextcube); - if(exitdist >= 0) - { + if(exitdist >= 0) { return dist+max(enterdist+0.1f, 0.0f); } } } - nextcube: FINDCLOSEST(side = O_RIGHT - lsizemask.x, side = O_FRONT - lsizemask.y, side = O_TOP - lsizemask.z); - if(dist>=radius) return dist; - UPOCTREE(return radius); } } -float rayent(const vec &o, const vec &ray, float radius, int mode, int size, int &orient, int &ent) -{ +float rayent(const vec &o, const vec &ray, float radius, int mode, int size, int &orient, int &ent) { hitent = -1; hitentdist = radius; hitorient = -1; float dist = raycube(o, ray, radius, mode, size); - if((mode&RAY_ENTS) == RAY_ENTS) - { + if((mode&RAY_ENTS) == RAY_ENTS) { float dent = disttooutsideent(o, ray, dist < 0 ? 1e16f : dist, mode, NULL); if(dent < 1e15f && (dist < 0 || dent < dist)) dist = dent; } @@ -417,8 +358,7 @@ float rayent(const vec &o, const vec &ray, float radius, int mode, int size, int return dist; } -float raycubepos(const vec &o, const vec &ray, vec &hitpos, float radius, int mode, int size) -{ +float raycubepos(const vec &o, const vec &ray, vec &hitpos, float radius, int mode, int size) { hitpos = ray; float dist = raycube(o, ray, radius, mode, size); if(radius>0 && dist>=radius) dist = radius; @@ -426,8 +366,7 @@ float raycubepos(const vec &o, const vec &ray, vec &hitpos, float radius, int mo return dist; } -bool raycubelos(const vec &o, const vec &dest, vec &hitpos) -{ +bool raycubelos(const vec &o, const vec &dest, vec &hitpos) { vec ray(dest); ray.sub(o); float mag = ray.magnitude(); @@ -436,8 +375,7 @@ bool raycubelos(const vec &o, const vec &dest, vec &hitpos) return distance >= mag; } -float rayfloor(const vec &o, vec &floor, int mode, float radius) -{ +float rayfloor(const vec &o, vec &floor, int mode, float radius) { if(o.z<=0) return -1; hitsurface = vec(0, 0, 1); float dist = raycube(o, vec(0, 0, -1), radius, mode); @@ -460,53 +398,42 @@ const float WALLZ = 0.2f; extern const float JUMPVEL = 125.0f; extern const float GRAVITY = 200.0f; -bool ellipseboxcollide(physent *d, const vec &dir, const vec &o, const vec ¢er, float yaw, float xr, float yr, float hi, float lo) -{ +bool ellipseboxcollide(physent *d, const vec &dir, const vec &o, const vec ¢er, float yaw, float xr, float yr, float hi, float lo) { float below = (o.z+center.z-lo) - (d->o.z+d->aboveeye), above = (d->o.z-d->eyeheight) - (o.z+center.z+hi); if(below>=0 || above>=0) return false; - vec yo(d->o); yo.sub(o); yo.rotate_around_z(-yaw*RAD); yo.sub(center); - float dx = clamp(yo.x, -xr, xr) - yo.x, dy = clamp(yo.y, -yr, yr) - yo.y, dist = sqrtf(dx*dx + dy*dy) - d->radius; - if(dist < 0) - { + if(dist < 0) { int sx = yo.x <= -xr ? -1 : (yo.x >= xr ? 1 : 0), sy = yo.y <= -yr ? -1 : (yo.y >= yr ? 1 : 0); - if(dist > (yo.z < 0 ? below : above) && (sx || sy)) - { + if(dist > (yo.z < 0 ? below : above) && (sx || sy)) { vec ydir(dir); ydir.rotate_around_z(-yaw*RAD); - if(sx*yo.x - xr > sy*yo.y - yr) - { - if(dir.iszero() || sx*ydir.x < -1e-6f) - { + if(sx*yo.x - xr > sy*yo.y - yr) { + if(dir.iszero() || sx*ydir.x < -1e-6f) { collidewall = vec(sx, 0, 0); collidewall.rotate_around_z(yaw*RAD); return true; } } - else if(dir.iszero() || sy*ydir.y < -1e-6f) - { + else if(dir.iszero() || sy*ydir.y < -1e-6f) { collidewall = vec(0, sy, 0); collidewall.rotate_around_z(yaw*RAD); return true; } } - if(yo.z < 0) - { - if(dir.iszero() || (dir.z > 0 && (d->type>=ENT_INANIMATE || below >= d->zmargin-(d->eyeheight+d->aboveeye)/4.0f))) - { + if(yo.z < 0) { + if(dir.iszero() || (dir.z > 0 && (d->type>=ENT_INANIMATE || below >= d->zmargin-(d->eyeheight+d->aboveeye)/4.0f))) { collidewall = vec(0, 0, -1); return true; } } - else if(dir.iszero() || (dir.z < 0 && (d->type>=ENT_INANIMATE || above >= d->zmargin-(d->eyeheight+d->aboveeye)/3.0f))) - { + else if(dir.iszero() || (dir.z < 0 && (d->type>=ENT_INANIMATE || above >= d->zmargin-(d->eyeheight+d->aboveeye)/3.0f))) { collidewall = vec(0, 0, 1); return true; } @@ -515,8 +442,7 @@ bool ellipseboxcollide(physent *d, const vec &dir, const vec &o, const vec ¢ return false; } -bool ellipsecollide(physent *d, const vec &dir, const vec &o, const vec ¢er, float yaw, float xr, float yr, float hi, float lo) -{ +bool ellipsecollide(physent *d, const vec &dir, const vec &o, const vec ¢er, float yaw, float xr, float yr, float hi, float lo) { float below = (o.z+center.z-lo) - (d->o.z+d->aboveeye), above = (d->o.z-d->eyeheight) - (o.z+center.z+hi); if(below>=0 || above>=0) return false; @@ -528,24 +454,19 @@ bool ellipsecollide(physent *d, const vec &dir, const vec &o, const vec ¢er, float dx = d->xradius*cosf(dangle), dy = d->yradius*sinf(dangle); float ex = xr*cosf(eangle), ey = yr*sinf(eangle); float dist = sqrtf(x*x + y*y) - sqrtf(dx*dx + dy*dy) - sqrtf(ex*ex + ey*ey); - if(dist < 0) - { - if(dist > (d->o.z < yo.z ? below : above) && (dir.iszero() || x*dir.x + y*dir.y > 0)) - { + if(dist < 0) { + if(dist > (d->o.z < yo.z ? below : above) && (dir.iszero() || x*dir.x + y*dir.y > 0)) { collidewall = vec(-x, -y, 0); if(!collidewall.iszero()) collidewall.normalize(); return true; } - if(d->o.z < yo.z) - { - if(dir.iszero() || (dir.z > 0 && (d->type>=ENT_INANIMATE || below >= d->zmargin-(d->eyeheight+d->aboveeye)/4.0f))) - { + if(d->o.z < yo.z) { + if(dir.iszero() || (dir.z > 0 && (d->type>=ENT_INANIMATE || below >= d->zmargin-(d->eyeheight+d->aboveeye)/4.0f))) { collidewall = vec(0, 0, -1); return true; } } - else if(dir.iszero() || (dir.z < 0 && (d->type>=ENT_INANIMATE || above >= d->zmargin-(d->eyeheight+d->aboveeye)/3.0f))) - { + else if(dir.iszero() || (dir.z < 0 && (d->type>=ENT_INANIMATE || above >= d->zmargin-(d->eyeheight+d->aboveeye)/3.0f))) { collidewall = vec(0, 0, 1); return true; } @@ -558,15 +479,13 @@ bool ellipsecollide(physent *d, const vec &dir, const vec &o, const vec ¢er, static uint dynentframe = 0; -static struct dynentcacheentry -{ +static struct dynentcacheentry { int x, y; uint frame; vector<physent *> dynents; } dynentcache[DYNENTCACHESIZE]; -void cleardynentcache() -{ +void cleardynentcache() { dynentframe++; if(!dynentframe || dynentframe == 1) loopi(DYNENTCACHESIZE) dynentcache[i].frame = 0; if(!dynentframe) dynentframe = 1; @@ -576,8 +495,7 @@ VARF(dynentsize, 4, 7, 12, cleardynentcache()); #define DYNENTHASH(x, y) (((((x)^(y))<<5) + (((x)^(y))>>5)) & (DYNENTCACHESIZE - 1)) -const vector<physent *> &checkdynentcache(int x, int y) -{ +const vector<physent *> &checkdynentcache(int x, int y) { dynentcacheentry &dec = dynentcache[DYNENTHASH(x, y)]; if(dec.x == x && dec.y == y && dec.frame == dynentframe) return dec.dynents; dec.x = x; @@ -585,8 +503,7 @@ const vector<physent *> &checkdynentcache(int x, int y) dec.frame = dynentframe; dec.dynents.shrink(0); int numdyns = game::numdynents(), dsize = 1<<dynentsize, dx = x<<dynentsize, dy = y<<dynentsize; - loopi(numdyns) - { + loopi(numdyns) { dynent *d = game::iterdynents(i); if(d->state != CS_ALIVE || d->o.x+d->radius <= dx || d->o.x-d->radius >= dx+dsize || @@ -601,23 +518,18 @@ const vector<physent *> &checkdynentcache(int x, int y) for(int curx = max(int(o.x-radius), 0)>>dynentsize, endx = min(int(o.x+radius), worldsize-1)>>dynentsize; curx <= endx; curx++) \ for(int cury = max(int(o.y-radius), 0)>>dynentsize, endy = min(int(o.y+radius), worldsize-1)>>dynentsize; cury <= endy; cury++) -void updatedynentcache(physent *d) -{ - loopdynentcache(x, y, d->o, d->radius) - { +void updatedynentcache(physent *d) { + loopdynentcache(x, y, d->o, d->radius) { dynentcacheentry &dec = dynentcache[DYNENTHASH(x, y)]; if(dec.x != x || dec.y != y || dec.frame != dynentframe || dec.dynents.find(d) >= 0) continue; dec.dynents.add(d); } } -bool overlapsdynent(const vec &o, float radius) -{ - loopdynentcache(x, y, o, radius) - { +bool overlapsdynent(const vec &o, float radius) { + loopdynentcache(x, y, o, radius) { const vector<physent *> &dynents = checkdynentcache(x, y); - loopv(dynents) - { + loopv(dynents) { physent *d = dynents[i]; if(o.dist(d->o)-d->radius < radius) return true; } @@ -626,13 +538,11 @@ bool overlapsdynent(const vec &o, float radius) } template<class E, class O> -static inline bool plcollide(physent *d, const vec &dir, physent *o) -{ +static inline bool plcollide(physent *d, const vec &dir, physent *o) { E entvol(d); O obvol(o); vec cp; - if(mpr::collide(entvol, obvol, NULL, NULL, &cp)) - { + if(mpr::collide(entvol, obvol, NULL, NULL, &cp)) { vec wn = vec(cp).sub(obvol.center()); collidewall = obvol.contactface(wn, dir.iszero() ? vec(wn).neg() : dir); if(!collidewall.iszero()) return true; @@ -641,10 +551,8 @@ static inline bool plcollide(physent *d, const vec &dir, physent *o) return false; } -static inline bool plcollide(physent *d, const vec &dir, physent *o) -{ - switch(d->collidetype) - { +static inline bool plcollide(physent *d, const vec &dir, physent *o) { + switch(d->collidetype) { case COLLIDE_ELLIPSE: case COLLIDE_ELLIPSE_PRECISE: if(o->collidetype == COLLIDE_OBB) return ellipseboxcollide(d, dir, o->o, vec(0, 0, 0), o->yaw, o->xradius, o->yradius, o->aboveeye, o->eyeheight); @@ -656,33 +564,27 @@ static inline bool plcollide(physent *d, const vec &dir, physent *o) } } -bool plcollide(physent *d, const vec &dir, bool insideplayercol) // collide with player or monster -{ +bool plcollide(physent *d, const vec &dir, bool insideplayercol) { // collide with player or monster { if(d->type==ENT_CAMERA || d->state!=CS_ALIVE) return false; int lastinside = collideinside; physent *insideplayer = NULL; - loopdynentcache(x, y, d->o, d->radius) - { + loopdynentcache(x, y, d->o, d->radius) { const vector<physent *> &dynents = checkdynentcache(x, y); - loopv(dynents) - { + loopv(dynents) { physent *o = dynents[i]; if(o==d || d->o.reject(o->o, d->radius+o->radius)) continue; - if(plcollide(d, dir, o)) - { + if(plcollide(d, dir, o)) { collideplayer = o; game::dynentcollide(d, o, collidewall); return true; } - if(collideinside > lastinside) - { + if(collideinside > lastinside) { lastinside = collideinside; insideplayer = o; } } } - if(insideplayer && insideplayercol) - { + if(insideplayer && insideplayercol) { collideplayer = insideplayer; game::dynentcollide(d, insideplayer, vec(0, 0, 0)); return true; @@ -690,8 +592,7 @@ bool plcollide(physent *d, const vec &dir, bool insideplayercol) // collide with return false; } -void rotatebb(vec ¢er, vec &radius, int yaw) -{ +void rotatebb(vec ¢er, vec &radius, int yaw) { if(yaw < 0) yaw = 360 + yaw%360; else if(yaw >= 360) yaw %= 360; const vec2 &rot = sincos360[yaw]; @@ -703,13 +604,11 @@ void rotatebb(vec ¢er, vec &radius, int yaw) } template<class E, class M> -static inline bool mmcollide(physent *d, const vec &dir, const extentity &e, const vec ¢er, const vec &radius, float yaw) -{ +static inline bool mmcollide(physent *d, const vec &dir, const extentity &e, const vec ¢er, const vec &radius, float yaw) { E entvol(d); M mdlvol(e.o, center, radius, yaw); vec cp; - if(mpr::collide(entvol, mdlvol, NULL, NULL, &cp)) - { + if(mpr::collide(entvol, mdlvol, NULL, NULL, &cp)) { vec wn = vec(cp).sub(mdlvol.center()); collidewall = mdlvol.contactface(wn, dir.iszero() ? vec(wn).neg() : dir); if(!collidewall.iszero()) return true; @@ -718,34 +617,27 @@ static inline bool mmcollide(physent *d, const vec &dir, const extentity &e, con return false; } -bool mmcollide(physent *d, const vec &dir, octaentities &oc) // collide with a mapmodel -{ +bool mmcollide(physent *d, const vec &dir, octaentities &oc) { // collide with a mapmodel { const vector<extentity *> &ents = entities::getents(); - loopv(oc.mapmodels) - { + loopv(oc.mapmodels) { extentity &e = *ents[oc.mapmodels[i]]; if(e.flags&EF_NOCOLLIDE) continue; model *m = loadmapmodel(e.attr2); if(!m || !m->collide) continue; - vec center, radius; float rejectradius = m->collisionbox(center, radius); if(d->o.reject(e.o, d->radius + rejectradius)) continue; - float yaw = e.attr1; - switch(d->collidetype) - { + switch(d->collidetype) { case COLLIDE_ELLIPSE: case COLLIDE_ELLIPSE_PRECISE: - if(m->ellipsecollide) - { + if(m->ellipsecollide) { if(ellipsecollide(d, dir, e.o, center, yaw, radius.x, radius.y, radius.z, radius.z)) return true; } else if(ellipseboxcollide(d, dir, e.o, center, yaw, radius.x, radius.y, radius.z, radius.z)) return true; break; case COLLIDE_OBB: - if(m->ellipsecollide) - { + if(m->ellipsecollide) { if(mmcollide<mpr::EntOBB, mpr::ModelEllipse>(d, dir, e, center, radius, yaw)) return true; } else if(mmcollide<mpr::EntOBB, mpr::ModelOBB>(d, dir, e, center, radius, yaw)) return true; @@ -757,24 +649,22 @@ bool mmcollide(physent *d, const vec &dir, octaentities &oc) // collide wit } template<class E> -static bool fuzzycollidesolid(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) // collide with solid cube geometry -{ +static bool fuzzycollidesolid(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) { // collide with solid cube geometry { int crad = size/2; if(fabs(d->o.x - co.x - crad) > d->radius + crad || fabs(d->o.y - co.y - crad) > d->radius + crad || d->o.z + d->aboveeye < co.z || d->o.z - d->eyeheight > co.z + size) return false; - E entvol(d); collidewall = vec(0, 0, 0); float bestdist = -1e10f; int visible = isentirelysolid(c) ? c.visible : 0xFF; - #define CHECKSIDE(side, distval, dotval, margin, normal) if(visible&(1<<side)) do \ - { \ + #define CHECKSIDE(side, distval, dotval, margin, normal) if(visible&(1<<side)) do { \ + \ float dist = distval; \ if(dist > 0) return false; \ if(dist <= bestdist) continue; \ - if(!dir.iszero()) \ - { \ + if(!dir.iszero()) { \ + \ if(dotval >= -cutoff*dir.magnitude()) continue; \ if(d->type<ENT_CAMERA && dotval < 0 && dist < margin) continue; \ } \ @@ -787,9 +677,7 @@ static bool fuzzycollidesolid(physent *d, const vec &dir, float cutoff, const cu CHECKSIDE(O_FRONT, d->o.y - d->radius - (co.y + size), dir.y, -d->radius, vec(0, 1, 0)); CHECKSIDE(O_BOTTOM, co.z - (d->o.z + d->aboveeye), -dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/4.0f, vec(0, 0, -1)); CHECKSIDE(O_TOP, d->o.z - d->eyeheight - (co.z + size), dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/3.0f, vec(0, 0, 1)); - - if(collidewall.iszero()) - { + if(collidewall.iszero()) { collideinside++; return false; } @@ -797,24 +685,20 @@ static bool fuzzycollidesolid(physent *d, const vec &dir, float cutoff, const cu } template<class E> -static inline bool clampcollide(const clipplanes &p, const E &entvol, const plane &w, const vec &pw) -{ - if(w.x && (w.y || w.z) && fabs(pw.x - p.o.x) > p.r.x) - { +static inline bool clampcollide(const clipplanes &p, const E &entvol, const plane &w, const vec &pw) { + if(w.x && (w.y || w.z) && fabs(pw.x - p.o.x) > p.r.x) { vec c = entvol.center(); float fv = pw.x < p.o.x ? p.o.x-p.r.x : p.o.x+p.r.x, fdist = (w.x*fv + w.y*c.y + w.z*c.z + w.offset) / (w.y*w.y + w.z*w.z); vec fdir(fv - c.x, -w.y*fdist, -w.z*fdist); if((pw.y-c.y-fdir.y)*w.y + (pw.z-c.z-fdir.z)*w.z >= 0 && entvol.supportpoint(fdir).squaredist(c) < fdir.squaredlen()) return true; } - if(w.y && (w.x || w.z) && fabs(pw.y - p.o.y) > p.r.y) - { + if(w.y && (w.x || w.z) && fabs(pw.y - p.o.y) > p.r.y) { vec c = entvol.center(); float fv = pw.y < p.o.y ? p.o.y-p.r.y : p.o.y+p.r.y, fdist = (w.x*c.x + w.y*fv + w.z*c.z + w.offset) / (w.x*w.x + w.z*w.z); vec fdir(-w.x*fdist, fv - c.y, -w.z*fdist); if((pw.x-c.x-fdir.x)*w.x + (pw.z-c.z-fdir.z)*w.z >= 0 && entvol.supportpoint(fdir).squaredist(c) < fdir.squaredlen()) return true; } - if(w.z && (w.x || w.y) && fabs(pw.z - p.o.z) > p.r.z) - { + if(w.z && (w.x || w.y) && fabs(pw.z - p.o.z) > p.r.z) { vec c = entvol.center(); float fv = pw.z < p.o.z ? p.o.z-p.r.z : p.o.z+p.r.z, fdist = (w.x*c.x + w.y*c.y + w.z*fv + w.offset) / (w.x*w.x + w.y*w.y); vec fdir(-w.x*fdist, -w.y*fdist, fv - c.z); @@ -824,14 +708,11 @@ static inline bool clampcollide(const clipplanes &p, const E &entvol, const plan } template<class E> -static bool fuzzycollideplanes(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) // collide with deformed cube geometry -{ +static bool fuzzycollideplanes(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) { // collide with deformed cube geometry { const clipplanes &p = getclipplanes(c, co, size); - if(fabs(d->o.x - p.o.x) > p.r.x + d->radius || fabs(d->o.y - p.o.y) > p.r.y + d->radius || d->o.z + d->aboveeye < p.o.z - p.r.z || d->o.z - d->eyeheight > p.o.z + p.r.z) return false; - collidewall = vec(0, 0, 0); float bestdist = -1e10f; int visible = p.visible; @@ -841,11 +722,9 @@ static bool fuzzycollideplanes(physent *d, const vec &dir, float cutoff, const c CHECKSIDE(O_FRONT, d->o.y - d->radius - (p.o.y + p.r.y), dir.y, -d->radius, vec(0, 1, 0)); CHECKSIDE(O_BOTTOM, p.o.z - p.r.z - (d->o.z + d->aboveeye), -dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/4.0f, vec(0, 0, -1)); CHECKSIDE(O_TOP, d->o.z - d->eyeheight - (p.o.z + p.r.z), dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/3.0f, vec(0, 0, 1)); - E entvol(d); int bestplane = -1; - loopi(p.size) - { + loopi(p.size) { const plane &w = p.p[i]; vec pw = entvol.supportpoint(vec(w).neg()); float dist = w.dist(pw); @@ -853,8 +732,7 @@ static bool fuzzycollideplanes(physent *d, const vec &dir, float cutoff, const c if(dist <= bestdist) continue; bestplane = -1; bestdist = dist; - if(!dir.iszero()) - { + if(!dir.iszero()) { if(w.dot(dir) >= -cutoff*dir.magnitude()) continue; if(d->type<ENT_CAMERA && dist < (dir.z*w.z < 0 ? @@ -866,8 +744,7 @@ static bool fuzzycollideplanes(physent *d, const vec &dir, float cutoff, const c bestplane = i; } if(bestplane >= 0) collidewall = p.p[bestplane]; - else if(collidewall.iszero()) - { + else if(collidewall.iszero()) { collideinside++; return false; } @@ -875,17 +752,14 @@ static bool fuzzycollideplanes(physent *d, const vec &dir, float cutoff, const c } template<class E> -static bool cubecollidesolid(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) // collide with solid cube geometry -{ +static bool cubecollidesolid(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) { // collide with solid cube geometry { int crad = size/2; if(fabs(d->o.x - co.x - crad) > d->radius + crad || fabs(d->o.y - co.y - crad) > d->radius + crad || d->o.z + d->aboveeye < co.z || d->o.z - d->eyeheight > co.z + size) return false; - E entvol(d); bool collided = mpr::collide(mpr::SolidCube(co, size), entvol); if(!collided) return false; - collidewall = vec(0, 0, 0); float bestdist = -1e10f; int visible = isentirelysolid(c) ? c.visible : 0xFF; @@ -895,9 +769,7 @@ static bool cubecollidesolid(physent *d, const vec &dir, float cutoff, const cub CHECKSIDE(O_FRONT, entvol.back() - (co.y + size), dir.y, -d->radius, vec(0, 1, 0)); CHECKSIDE(O_BOTTOM, co.z - entvol.top(), -dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/4.0f, vec(0, 0, -1)); CHECKSIDE(O_TOP, entvol.bottom() - (co.z + size), dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/3.0f, vec(0, 0, 1)); - - if(collidewall.iszero()) - { + if(collidewall.iszero()) { collideinside++; return false; } @@ -905,18 +777,14 @@ static bool cubecollidesolid(physent *d, const vec &dir, float cutoff, const cub } template<class E> -static bool cubecollideplanes(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) // collide with deformed cube geometry -{ +static bool cubecollideplanes(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size) { // collide with deformed cube geometry { const clipplanes &p = getclipplanes(c, co, size); - if(fabs(d->o.x - p.o.x) > p.r.x + d->radius || fabs(d->o.y - p.o.y) > p.r.y + d->radius || d->o.z + d->aboveeye < p.o.z - p.r.z || d->o.z - d->eyeheight > p.o.z + p.r.z) return false; - E entvol(d); bool collided = mpr::collide(mpr::CubePlanes(p), entvol); if(!collided) return false; - collidewall = vec(0, 0, 0); float bestdist = -1e10f; int visible = p.visible; @@ -926,18 +794,15 @@ static bool cubecollideplanes(physent *d, const vec &dir, float cutoff, const cu CHECKSIDE(O_FRONT, entvol.back() - (p.o.y + p.r.y), dir.y, -d->radius, vec(0, 1, 0)); CHECKSIDE(O_BOTTOM, p.o.z - p.r.z - entvol.top(), -dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/4.0f, vec(0, 0, -1)); CHECKSIDE(O_TOP, entvol.bottom() - (p.o.z + p.r.z), dir.z, d->zmargin-(d->eyeheight+d->aboveeye)/3.0f, vec(0, 0, 1)); - int bestplane = -1; - loopi(p.size) - { + loopi(p.size) { const plane &w = p.p[i]; vec pw = entvol.supportpoint(vec(w).neg()); float dist = w.dist(pw); if(dist <= bestdist) continue; bestplane = -1; bestdist = dist; - if(!dir.iszero()) - { + if(!dir.iszero()) { if(w.dot(dir) >= -cutoff*dir.magnitude()) continue; if(d->type<ENT_CAMERA && dist < (dir.z*w.z < 0 ? @@ -949,18 +814,15 @@ static bool cubecollideplanes(physent *d, const vec &dir, float cutoff, const cu bestplane = i; } if(bestplane >= 0) collidewall = p.p[bestplane]; - else if(collidewall.iszero()) - { + else if(collidewall.iszero()) { collideinside++; return false; } return true; } -static inline bool cubecollide(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size, bool solid) -{ - switch(d->collidetype) - { +static inline bool cubecollide(physent *d, const vec &dir, float cutoff, const cube &c, const ivec &co, int size, bool solid) { + switch(d->collidetype) { case COLLIDE_OBB: if(isentirelysolid(c) || solid) return cubecollidesolid<mpr::EntOBB>(d, dir, cutoff, c, co, size); else return cubecollideplanes<mpr::EntOBB>(d, dir, cutoff, c, co, size); @@ -974,21 +836,16 @@ static inline bool cubecollide(physent *d, const vec &dir, float cutoff, const c } } -static inline bool octacollide(physent *d, const vec &dir, float cutoff, const ivec &bo, const ivec &bs, const cube *c, const ivec &cor, int size) // collide with octants -{ - loopoctabox(cor, size, bo, bs) - { +static inline bool octacollide(physent *d, const vec &dir, float cutoff, const ivec &bo, const ivec &bs, const cube *c, const ivec &cor, int size) { // collide with octants { + loopoctabox(cor, size, bo, bs) { if(c[i].ext && c[i].ext->ents) if(mmcollide(d, dir, *c[i].ext->ents)) return true; ivec o(i, cor, size); - if(c[i].children) - { + if(c[i].children) { if(octacollide(d, dir, cutoff, bo, bs, c[i].children, o, size>>1)) return true; } - else - { + else { bool solid = false; - switch(c[i].material&MATF_CLIP) - { + switch(c[i].material&MATF_CLIP) { case MAT_NOCLIP: continue; case MAT_GAMECLIP: if(d->type==ENT_AI) solid = true; break; case MAT_CLIP: if(d->type<ENT_CAMERA) solid = true; break; @@ -1000,8 +857,7 @@ static inline bool octacollide(physent *d, const vec &dir, float cutoff, const i return false; } -static inline bool octacollide(physent *d, const vec &dir, float cutoff, const ivec &bo, const ivec &bs) -{ +static inline bool octacollide(physent *d, const vec &dir, float cutoff, const ivec &bo, const ivec &bs) { int diff = (bo.x^bs.x) | (bo.y^bs.y) | (bo.z^bs.z), scale = worldscale-1; if(diff&~((1<<scale)-1) || uint(bo.x|bo.y|bo.z|bs.x|bs.y|bs.z) >= uint(worldsize)) @@ -1009,16 +865,14 @@ static inline bool octacollide(physent *d, const vec &dir, float cutoff, const i const cube *c = &worldroot[octastep(bo.x, bo.y, bo.z, scale)]; if(c->ext && c->ext->ents && mmcollide(d, dir, *c->ext->ents)) return true; scale--; - while(c->children && !(diff&(1<<scale))) - { + while(c->children && !(diff&(1<<scale))) { c = &c->children[octastep(bo.x, bo.y, bo.z, scale)]; if(c->ext && c->ext->ents && mmcollide(d, dir, *c->ext->ents)) return true; scale--; } if(c->children) return octacollide(d, dir, cutoff, bo, bs, c->children, ivec(bo).mask(~((2<<scale)-1)), 1<<scale); bool solid = false; - switch(c->material&MATF_CLIP) - { + switch(c->material&MATF_CLIP) { case MAT_NOCLIP: return false; case MAT_GAMECLIP: if(d->type==ENT_AI) solid = true; break; case MAT_CLIP: if(d->type<ENT_CAMERA) solid = true; break; @@ -1029,8 +883,7 @@ static inline bool octacollide(physent *d, const vec &dir, float cutoff, const i } // all collision happens here -bool collide(physent *d, const vec &dir, float cutoff, bool playercol, bool insideplayercol) -{ +bool collide(physent *d, const vec &dir, float cutoff, bool playercol, bool insideplayercol) { collideinside = 0; collideplayer = NULL; collidewall = vec(0, 0, 0); @@ -1040,11 +893,9 @@ bool collide(physent *d, const vec &dir, float cutoff, bool playercol, bool insi return octacollide(d, dir, cutoff, bo, bs) || (playercol && plcollide(d, dir, insideplayercol)); } -void recalcdir(physent *d, const vec &oldvel, vec &dir) -{ +void recalcdir(physent *d, const vec &oldvel, vec &dir) { float speed = oldvel.magnitude(); - if(speed > 1e-6f) - { + if(speed > 1e-6f) { float step = dir.magnitude(); dir = d->vel; dir.add(d->falling); @@ -1052,11 +903,9 @@ void recalcdir(physent *d, const vec &oldvel, vec &dir) } } -void slideagainst(physent *d, vec &dir, const vec &obstacle, bool foundfloor, bool slidecollide) -{ +void slideagainst(physent *d, vec &dir, const vec &obstacle, bool foundfloor, bool slidecollide) { vec wall(obstacle); - if(foundfloor ? wall.z > 0 : slidecollide) - { + if(foundfloor ? wall.z > 0 : slidecollide) { wall.z = 0; if(!wall.iszero()) wall.normalize(); } @@ -1067,14 +916,11 @@ void slideagainst(physent *d, vec &dir, const vec &obstacle, bool foundfloor, bo recalcdir(d, oldvel, dir); } -void switchfloor(physent *d, vec &dir, const vec &floor) -{ +void switchfloor(physent *d, vec &dir, const vec &floor) { if(floor.z >= FLOORZ) d->falling = vec(0, 0, 0); - vec oldvel(d->vel); oldvel.add(d->falling); - if(dir.dot(floor) >= 0) - { + if(dir.dot(floor) >= 0) { if(d->physstate < PHYS_SLIDE || fabs(dir.dot(d->floor)) > 0.01f*dir.magnitude()) return; d->vel.projectxy(floor, 0.0f); } @@ -1083,57 +929,46 @@ void switchfloor(physent *d, vec &dir, const vec &floor) recalcdir(d, oldvel, dir); } -bool trystepup(physent *d, vec &dir, const vec &obstacle, float maxstep, const vec &floor) -{ +bool trystepup(physent *d, vec &dir, const vec &obstacle, float maxstep, const vec &floor) { vec old(d->o), stairdir = (obstacle.z >= 0 && obstacle.z < SLOPEZ ? vec(-obstacle.x, -obstacle.y, 0) : vec(dir.x, dir.y, 0)).rescale(1); bool cansmooth = true; /* check if there is space atop the stair to move to */ - if(d->physstate != PHYS_STEP_UP) - { + if(d->physstate != PHYS_STEP_UP) { vec checkdir = stairdir; checkdir.mul(0.1f); checkdir.z += maxstep + 0.1f; d->o.add(checkdir); - if(collide(d)) - { + if(collide(d)) { d->o = old; if(!collide(d, vec(0, 0, -1), SLOPEZ)) return false; cansmooth = false; } } - - if(cansmooth) - { + if(cansmooth) { vec checkdir = stairdir; checkdir.z += 1; checkdir.mul(maxstep); d->o = old; d->o.add(checkdir); int scale = 2; - if(collide(d, checkdir)) - { - if(!collide(d, vec(0, 0, -1), SLOPEZ)) - { + if(collide(d, checkdir)) { + if(!collide(d, vec(0, 0, -1), SLOPEZ)) { d->o = old; return false; } d->o.add(checkdir); if(collide(d, vec(0, 0, -1), SLOPEZ)) scale = 1; } - if(scale != 1) - { + if(scale != 1) { d->o = old; d->o.sub(checkdir.mul(vec(2, 2, 1))); if(!collide(d, vec(0, 0, -1), SLOPEZ)) scale = 1; } - d->o = old; vec smoothdir(dir.x, dir.y, 0); float magxy = smoothdir.magnitude(); - if(magxy > 1e-9f) - { - if(magxy > scale*dir.z) - { + if(magxy > 1e-9f) { + if(magxy > scale*dir.z) { smoothdir.mul(1/magxy); smoothdir.z = 1.0f/scale; smoothdir.mul(dir.magnitude()/smoothdir.magnitude()); @@ -1141,11 +976,9 @@ bool trystepup(physent *d, vec &dir, const vec &obstacle, float maxstep, const v else smoothdir.z = dir.z; d->o.add(smoothdir); d->o.z += maxstep + 0.1f; - if(!collide(d, smoothdir)) - { + if(!collide(d, smoothdir)) { d->o.z -= maxstep + 0.1f; - if(d->physstate == PHYS_FALL || d->floor != floor) - { + if(d->physstate == PHYS_FALL || d->floor != floor) { d->timeinair = 0; d->floor = floor; switchfloor(d, dir, d->floor); @@ -1155,14 +988,11 @@ bool trystepup(physent *d, vec &dir, const vec &obstacle, float maxstep, const v } } } - /* try stepping up */ d->o = old; d->o.z += dir.magnitude(); - if(!collide(d, vec(0, 0, 1))) - { - if(d->physstate == PHYS_FALL || d->floor != floor) - { + if(!collide(d, vec(0, 0, 1))) { + if(d->physstate == PHYS_FALL || d->floor != floor) { d->timeinair = 0; d->floor = floor; switchfloor(d, dir, d->floor); @@ -1174,34 +1004,28 @@ bool trystepup(physent *d, vec &dir, const vec &obstacle, float maxstep, const v return false; } -bool trystepdown(physent *d, vec &dir, float step, float xy, float z, bool init = false) -{ +bool trystepdown(physent *d, vec &dir, float step, float xy, float z, bool init = false) { vec stepdir(dir.x, dir.y, 0); stepdir.z = -stepdir.magnitude2()*z/xy; if(!stepdir.z) return false; stepdir.normalize(); - vec old(d->o); d->o.add(vec(stepdir).mul(STAIRHEIGHT/fabs(stepdir.z))).z -= STAIRHEIGHT; d->zmargin = -STAIRHEIGHT; - if(collide(d, vec(0, 0, -1), SLOPEZ)) - { + if(collide(d, vec(0, 0, -1), SLOPEZ)) { d->o = old; d->o.add(vec(stepdir).mul(step)); d->zmargin = 0; - if(!collide(d, vec(0, 0, -1))) - { + if(!collide(d, vec(0, 0, -1))) { vec stepfloor(stepdir); stepfloor.mul(-stepfloor.z).z += 1; stepfloor.normalize(); - if(d->physstate >= PHYS_SLOPE && d->floor != stepfloor) - { + if(d->physstate >= PHYS_SLOPE && d->floor != stepfloor) { // prevent alternating step-down/step-up states if player would keep bumping into the same floor vec stepped(d->o); d->o.z -= 0.5f; d->zmargin = -0.5f; - if(collide(d, stepdir) && collidewall == d->floor) - { + if(collide(d, stepdir) && collidewall == d->floor) { d->o = old; if(!init) { d->o.x += dir.x; d->o.y += dir.y; if(dir.z <= 0 || collide(d, dir)) d->o.z += dir.z; } d->zmargin = 0; @@ -1225,14 +1049,12 @@ bool trystepdown(physent *d, vec &dir, float step, float xy, float z, bool init return false; } -bool trystepdown(physent *d, vec &dir, bool init = false) -{ +bool trystepdown(physent *d, vec &dir, bool init = false) { if((!d->move && !d->strafe) || !game::allowmove(d)) return false; vec old(d->o); d->o.z -= STAIRHEIGHT; d->zmargin = -STAIRHEIGHT; - if(!collide(d, vec(0, 0, -1), SLOPEZ)) - { + if(!collide(d, vec(0, 0, -1), SLOPEZ)) { d->o = old; d->zmargin = 0; return false; @@ -1251,10 +1073,8 @@ bool trystepdown(physent *d, vec &dir, bool init = false) return false; } -void falling(physent *d, vec &dir, const vec &floor) -{ - if(floor.z > 0.0f && floor.z < SLOPEZ) - { +void falling(physent *d, vec &dir, const vec &floor) { + if(floor.z > 0.0f && floor.z < SLOPEZ) { if(floor.z >= WALLZ) switchfloor(d, dir, floor); d->timeinair = 0; d->physstate = PHYS_SLIDE; @@ -1264,11 +1084,9 @@ void falling(physent *d, vec &dir, const vec &floor) d->physstate = PHYS_FALL; } -void landing(physent *d, vec &dir, const vec &floor, bool collided) -{ +void landing(physent *d, vec &dir, const vec &floor, bool collided) { #if 0 - if(d->physstate == PHYS_FALL) - { + if(d->physstate == PHYS_FALL) { d->timeinair = 0; if(dir.z < 0.0f) dir.z = d->vel.z = 0.0f; } @@ -1280,40 +1098,32 @@ void landing(physent *d, vec &dir, const vec &floor, bool collided) d->floor = floor; } -bool findfloor(physent *d, bool collided, const vec &obstacle, bool &slide, vec &floor) -{ +bool findfloor(physent *d, bool collided, const vec &obstacle, bool &slide, vec &floor) { bool found = false; vec moved(d->o); d->o.z -= 0.1f; - if(collide(d, vec(0, 0, -1), d->physstate == PHYS_SLOPE || d->physstate == PHYS_STEP_DOWN ? SLOPEZ : FLOORZ)) - { + if(collide(d, vec(0, 0, -1), d->physstate == PHYS_SLOPE || d->physstate == PHYS_STEP_DOWN ? SLOPEZ : FLOORZ)) { floor = collidewall; found = true; } - else if(collided && obstacle.z >= SLOPEZ) - { + else if(collided && obstacle.z >= SLOPEZ) { floor = obstacle; found = true; slide = false; } - else if(d->physstate == PHYS_STEP_UP || d->physstate == PHYS_SLIDE) - { - if(collide(d, vec(0, 0, -1)) && collidewall.z > 0.0f) - { + else if(d->physstate == PHYS_STEP_UP || d->physstate == PHYS_SLIDE) { + if(collide(d, vec(0, 0, -1)) && collidewall.z > 0.0f) { floor = collidewall; if(floor.z >= SLOPEZ) found = true; } } - else if(d->physstate >= PHYS_SLOPE && d->floor.z < 1.0f) - { - if(collide(d, vec(d->floor).neg(), 0.95f) || collide(d, vec(0, 0, -1))) - { + else if(d->physstate >= PHYS_SLOPE && d->floor.z < 1.0f) { + if(collide(d, vec(d->floor).neg(), 0.95f) || collide(d, vec(0, 0, -1))) { floor = collidewall; if(floor.z >= SLOPEZ && floor.z < 1.0f) found = true; } } - if(collided && (!found || obstacle.z > floor.z)) - { + if(collided && (!found || obstacle.z > floor.z)) { floor = obstacle; slide = !found && (floor.z < WALLZ || floor.z >= SLOPEZ); } @@ -1321,49 +1131,41 @@ bool findfloor(physent *d, bool collided, const vec &obstacle, bool &slide, vec return found; } -bool move(physent *d, vec &dir) -{ +bool move(physent *d, vec &dir) { vec old(d->o); bool collided = false, slidecollide = false; vec obstacle = vec(0, 0, 0); d->o.add(dir); - if(collide(d, dir) || ((d->type==ENT_AI || d->type==ENT_INANIMATE) && collide(d, vec(0, 0, 0), 0, false))) - { + if(collide(d, dir) || ((d->type==ENT_AI || d->type==ENT_INANIMATE) && collide(d, vec(0, 0, 0), 0, false))) { obstacle = collidewall; /* check to see if there is an obstacle that would prevent this one from being used as a floor (or ceiling bump) */ - if(d->type==ENT_PLAYER && ((collidewall.z>=SLOPEZ && dir.z<0) || (collidewall.z<=-SLOPEZ && dir.z>0)) && (dir.x || dir.y) && collide(d, vec(dir.x, dir.y, 0))) - { + if(d->type==ENT_PLAYER && ((collidewall.z>=SLOPEZ && dir.z<0) || (collidewall.z<=-SLOPEZ && dir.z>0)) && (dir.x || dir.y) && collide(d, vec(dir.x, dir.y, 0))) { if(collidewall.dot(dir) >= 0) slidecollide = true; obstacle = collidewall; } d->o = old; d->o.z -= STAIRHEIGHT; d->zmargin = -STAIRHEIGHT; - if(d->physstate == PHYS_SLOPE || d->physstate == PHYS_FLOOR || (collide(d, vec(0, 0, -1), SLOPEZ) && (d->physstate==PHYS_STEP_UP || d->physstate==PHYS_STEP_DOWN || collidewall.z>=FLOORZ))) - { + if(d->physstate == PHYS_SLOPE || d->physstate == PHYS_FLOOR || (collide(d, vec(0, 0, -1), SLOPEZ) && (d->physstate==PHYS_STEP_UP || d->physstate==PHYS_STEP_DOWN || collidewall.z>=FLOORZ))) { d->o = old; d->zmargin = 0; if(trystepup(d, dir, obstacle, STAIRHEIGHT, d->physstate == PHYS_SLOPE || d->physstate == PHYS_FLOOR ? d->floor : vec(collidewall))) return true; } - else - { + else { d->o = old; d->zmargin = 0; } /* can't step over the obstacle, so just slide against it */ collided = true; } - else if(d->physstate == PHYS_STEP_UP) - { - if(collide(d, vec(0, 0, -1), SLOPEZ)) - { + else if(d->physstate == PHYS_STEP_UP) { + if(collide(d, vec(0, 0, -1), SLOPEZ)) { d->o = old; if(trystepup(d, dir, vec(0, 0, 1), STAIRHEIGHT, vec(collidewall))) return true; d->o.add(dir); } } - else if(d->physstate == PHYS_STEP_DOWN && dir.dot(d->floor) <= 1e-6f) - { + else if(d->physstate == PHYS_STEP_DOWN && dir.dot(d->floor) <= 1e-6f) { vec moved(d->o); d->o = old; if(trystepdown(d, dir)) return true; @@ -1372,8 +1174,7 @@ bool move(physent *d, vec &dir) vec floor(0, 0, 0); bool slide = collided, found = findfloor(d, collided, obstacle, slide, floor); - if(slide || (!collided && floor.z > 0 && floor.z < WALLZ)) - { + if(slide || (!collided && floor.z > 0 && floor.z < WALLZ)) { slideagainst(d, dir, slide ? obstacle : floor, found, slidecollide); //if(d->type == ENT_AI || d->type == ENT_INANIMATE) d->blocked = true; @@ -1383,21 +1184,17 @@ bool move(physent *d, vec &dir) return !collided; } -bool bounce(physent *d, float secs, float elasticity, float grav) -{ +bool bounce(physent *d, float secs, float elasticity, float grav) { // make sure bouncers don't start inside geometry if(d->physstate!=PHYS_BOUNCE && collide(d, vec(0, 0, 0), 0, false)) return true; d->vel.z -= grav*GRAVITY*secs; vec old(d->o); - loopi(2) - { + loopi(2) { vec dir(d->vel); dir.mul(secs); d->o.add(dir); - if(!collide(d, dir, 0, true, true)) - { - if(collideinside) - { + if(!collide(d, dir, 0, true, true)) { + if(collideinside) { d->o = old; d->vel.mul(-elasticity); } @@ -1411,8 +1208,7 @@ bool bounce(physent *d, float secs, float elasticity, float grav) d->vel.mul(k); d->vel.sub(vec(collidewall).mul(elasticity*2.0f*c)); } - if(d->physstate!=PHYS_BOUNCE) - { + if(d->physstate!=PHYS_BOUNCE) { // make sure bouncers don't start inside geometry if(d->o == old) return !collideplayer; d->physstate = PHYS_BOUNCE; @@ -1420,8 +1216,7 @@ bool bounce(physent *d, float secs, float elasticity, float grav) return collideplayer!=NULL; } -void avoidcollision(physent *d, const vec &dir, physent *obstacle, float space) -{ +void avoidcollision(physent *d, const vec &dir, physent *obstacle, float space) { float rad = obstacle->radius+d->radius; vec bbmin(obstacle->o); bbmin.x -= rad; @@ -1433,31 +1228,24 @@ void avoidcollision(physent *d, const vec &dir, physent *obstacle, float space) bbmax.y += rad; bbmax.z += obstacle->aboveeye+d->eyeheight; bbmax.add(space); - loopi(3) if(d->o[i] <= bbmin[i] || d->o[i] >= bbmax[i]) return; - float mindist = 1e16f; - loopi(3) if(dir[i] != 0) - { + loopi(3) if(dir[i] != 0) { float dist = ((dir[i] > 0 ? bbmax[i] : bbmin[i]) - d->o[i]) / dir[i]; mindist = min(mindist, dist); } if(mindist >= 0.0f && mindist < 1e15f) d->o.add(vec(dir).mul(mindist)); } -bool movecamera(physent *pl, const vec &dir, float dist, float stepdist) -{ +bool movecamera(physent *pl, const vec &dir, float dist, float stepdist) { int steps = (int)ceil(dist/stepdist); if(steps <= 0) return true; - vec d(dir); d.mul(dist/steps); - loopi(steps) - { + loopi(steps) { vec oldpos(pl->o); pl->o.add(d); - if(collide(pl, vec(0, 0, 0), 0, false)) - { + if(collide(pl, vec(0, 0, 0), 0, false)) { pl->o = oldpos; return false; } @@ -1465,22 +1253,18 @@ bool movecamera(physent *pl, const vec &dir, float dist, float stepdist) return true; } -void dropenttofloor(entity *e) -{ +void dropenttofloor(entity *e) { float radius = 1.0f; float height = 4.0f; vec o = e->o; - static struct dropent : physent - { - dropent() - { + static struct dropent : physent { + dropent() { type = ENT_BOUNCE; vel = vec(0, 0, -1); } } d; d.o = o; - if(!insideworld(d.o)) - { + if(!insideworld(d.o)) { if(d.o.z < worldsize) return; d.o.z = worldsize - 1e-3f; if(!insideworld(d.o)) return; @@ -1495,35 +1279,27 @@ void dropenttofloor(entity *e) o = d.o; } -void vecfromyawpitch(float yaw, float pitch, int move, int strafe, vec &m) -{ - if(move) - { +void vecfromyawpitch(float yaw, float pitch, int move, int strafe, vec &m) { + if(move) { m.x = move*-sinf(RAD*yaw); m.y = move*cosf(RAD*yaw); } else m.x = m.y = 0; - - if(pitch) - { + if(pitch) { m.x *= cosf(RAD*pitch); m.y *= cosf(RAD*pitch); m.z = move*sinf(RAD*pitch); } else m.z = 0; - - if(strafe) - { + if(strafe) { m.x += strafe*cosf(RAD*yaw); m.y += strafe*sinf(RAD*yaw); } } -void vectoyawpitch(const vec &v, float &yaw, float &pitch) -{ +void vectoyawpitch(const vec &v, float &yaw, float &pitch) { if(v.iszero()) yaw = pitch = 0; - else - { + else { yaw = -atan2(v.x, v.y)/RAD; pitch = asin(v.z/v.magnitude())/RAD; } @@ -1536,51 +1312,36 @@ FVAR(straferoll, 0, 0.033f, 90); FVAR(faderoll, 0, 0.95f, 1); VAR(floatspeed, 1, 100, 10000); -void modifyvelocity(physent *pl, bool local, bool floating, int curtime) -{ +void modifyvelocity(physent *pl, bool local, bool floating, int curtime) { bool allowmove = game::allowmove(pl); - if(floating) - { - if(pl->jumping && allowmove) - { + if(floating) { + if(pl->jumping && allowmove) { pl->jumping = false; pl->vel.z = max(pl->vel.z, JUMPVEL); } } - else if(pl->physstate >= PHYS_SLOPE) - { + else if(pl->physstate >= PHYS_SLOPE) { if(!pl->inwater) pl->vel.div(8); - if(pl->jumping && allowmove) - { + if(pl->jumping && allowmove) { pl->jumping = false; - pl->vel.z = max(pl->vel.z, JUMPVEL); // physics impulse upwards - game::physicstrigger(pl, local, 1); } } if(!floating && pl->physstate == PHYS_FALL) pl->timeinair = min(pl->timeinair + curtime, 1000); - vec m(0.0f, 0.0f, 0.0f); - if((pl->move || pl->strafe) && allowmove) - { + if((pl->move || pl->strafe) && allowmove) { vecfromyawpitch(pl->yaw, floating || pl->type==ENT_CAMERA ? pl->pitch : 0, pl->move, pl->strafe, m); - if(!floating && pl->physstate >= PHYS_SLOPE) m.z = -(m.x*pl->floor.x + m.y*pl->floor.y)/pl->floor.z; // move up or down slopes in air - m.normalize(); } - vec d(m); speedmodifier*=(pl->physstate!=PHYS_FLOOR)*(speedmodifier>0); speedmodifier=(speedmodifier>100.0f)?100.0f:speedmodifier; d.mul(pl->maxspeed + speedmodifier); - - if(pl->type==ENT_PLAYER) - { - if(floating) - { + if(pl->type==ENT_PLAYER) { + if(floating) { if(pl==player) d.mul(floatspeed/100.0f); } else if(allowmove) d.mul((pl->move && !pl->strafe ? 1.3f : 1.0f) * (pl->physstate < PHYS_SLOPE ? 1.3f : 1.0f)); @@ -1589,22 +1350,18 @@ void modifyvelocity(physent *pl, bool local, bool floating, int curtime) pl->vel.lerp(d, pl->vel, pow(1 - 1/fric, curtime/20.0f)); } -void modifygravity(physent *pl, int curtime) -{ +void modifygravity(physent *pl, int curtime) { float secs = curtime/1000.0f; vec g(0, 0, 0); if(pl->physstate == PHYS_FALL) g.z -= GRAVITY*secs; - else if(pl->floor.z > 0 && pl->floor.z < FLOORZ) - { + else if(pl->floor.z > 0 && pl->floor.z < FLOORZ) { g.z = -1; g.project(pl->floor); g.normalize(); g.mul(GRAVITY*secs); } if(!game::allowmove(pl) || (!pl->move && !pl->strafe)) pl->falling.add(g); - - if(pl->physstate >= PHYS_SLOPE) - { + if(pl->physstate >= PHYS_SLOPE) { float fric = 6.0f, c = clamp((pl->floor.z - SLOPEZ)/(FLOORZ-SLOPEZ), 0.0f, 1.0f); pl->falling.mul(pow(1 - c/fric, curtime/20.0f)); @@ -1615,71 +1372,53 @@ void modifygravity(physent *pl, int curtime) // moveres indicated the physics precision (which is lower for monsters and multiplayer prediction) // local is false for multiplayer prediction -bool moveplayer(physent *pl, int moveres, bool local, int curtime) -{ +bool moveplayer(physent *pl, int moveres, bool local, int curtime) { int material = lookupmaterial(vec(pl->o.x, pl->o.y, pl->o.z + (3*pl->aboveeye - pl->eyeheight)/4)); bool floating = pl->type==ENT_PLAYER && (pl->state==CS_EDITING || pl->state==CS_SPECTATOR); float secs = curtime/1000.f; - // apply gravity if(!floating) modifygravity(pl, curtime); // apply any player generated changes in velocity modifyvelocity(pl, local, floating, curtime); - vec d(pl->vel); if(!floating) d.mul(0.5f); d.add(pl->falling); d.mul(secs); - pl->blocked = false; - - if(floating) // just apply velocity - { - if(pl->physstate != PHYS_FLOAT) - { + if(floating) { // just apply velocity { + if(pl->physstate != PHYS_FLOAT) { pl->physstate = PHYS_FLOAT; pl->timeinair = 0; pl->falling = vec(0, 0, 0); } pl->o.add(d); } - else // apply velocity with collision - { + else { // apply velocity with collision { const float f = 1.0f/moveres; const int timeinair = pl->timeinair; int collisions = 0; - d.mul(f); loopi(moveres) if(!move(pl, d) && ++collisions<5) i--; // discrete steps collision detection & sliding - if(timeinair > 800 && !pl->timeinair) // if we land after long time must have been a high jump, make thud sound - { + if(timeinair > 800 && !pl->timeinair) { // if we land after long time must have been a high jump, make thud sound { game::physicstrigger(pl, local, -1); } } - if(pl->state==CS_ALIVE) updatedynentcache(pl); - // automatically apply smooth roll when strafing - if(pl->strafe && maxroll) pl->roll = clamp(pl->roll - pow(clamp(1.0f + pl->strafe*pl->roll/maxroll, 0.0f, 1.0f), 0.33f)*pl->strafe*curtime*straferoll, -maxroll, maxroll); else pl->roll *= curtime == PHYSFRAMETIME ? faderoll : pow(faderoll, curtime/float(PHYSFRAMETIME)); - if(pl->inwater) game::physicstrigger(pl, local, 0, pl->inwater); pl->inwater = MAT_AIR; - if(pl->state==CS_ALIVE && (pl->o.z < 0 || material&MAT_DEATH)) game::suicide(pl); - return true; } int physsteps = 0, physframetime = PHYSFRAMETIME, lastphysframe = 0; -void physicsframe() // optimally schedule physics frames inside the graphics frames -{ +void physicsframe() { // optimally schedule physics frames inside the graphics frames { int diff = lastmillis - lastphysframe; if(diff <= 0) physsteps = 0; - else - { + else { physframetime = clamp(game::scaletime(PHYSFRAMETIME)/100, 1, PHYSFRAMETIME); physsteps = (diff + physframetime - 1)/physframetime; lastphysframe += physsteps * physframetime; @@ -1689,50 +1428,39 @@ void physicsframe() // optimally schedule physics frames inside the graphics VAR(physinterp, 0, 1, 1); -void interppos(physent *pl) -{ +void interppos(physent *pl) { pl->o = pl->newpos; - int diff = lastphysframe - lastmillis; if(diff <= 0 || !physinterp) return; - vec deltapos(pl->deltapos); deltapos.mul(min(diff, physframetime)/float(physframetime)); pl->o.add(deltapos); } -void moveplayer(physent *pl, int moveres, bool local) -{ - if(physsteps <= 0) - { +void moveplayer(physent *pl, int moveres, bool local) { + if(physsteps <= 0) { if(local) interppos(pl); return; } - if(local) pl->o = pl->newpos; loopi(physsteps-1) moveplayer(pl, moveres, local, physframetime); if(local) pl->deltapos = pl->o; moveplayer(pl, moveres, local, physframetime); - if(local) - { + if(local) { pl->newpos = pl->o; pl->deltapos.sub(pl->newpos); interppos(pl); } } -bool bounce(physent *d, float elasticity, float grav) -{ - if(physsteps <= 0) - { +bool bounce(physent *d, float elasticity, float grav) { + if(physsteps <= 0) { interppos(d); return false; } - d->o = d->newpos; bool hitplayer = false; - loopi(physsteps-1) - { + loopi(physsteps-1) { if(bounce(d, physframetime/1000.0f, elasticity, grav)) hitplayer = true; } d->deltapos = d->o; @@ -1743,8 +1471,7 @@ bool bounce(physent *d, float elasticity, float grav) return hitplayer; } -void updatephysstate(physent *d) -{ +void updatephysstate(physent *d) { if(d->physstate == PHYS_FALL) return; d->timeinair = 0; vec old(d->o); @@ -1752,8 +1479,7 @@ void updatephysstate(physent *d) * May be inaccurate since movement collisions are not considered. * If good floor is not found, just keep the old floor and hope it's correct enough. */ - switch(d->physstate) - { + switch(d->physstate) { case PHYS_SLOPE: case PHYS_FLOOR: case PHYS_STEP_DOWN: @@ -1761,13 +1487,11 @@ void updatephysstate(physent *d) if(collide(d, vec(0, 0, -1), d->physstate == PHYS_SLOPE || d->physstate == PHYS_STEP_DOWN ? SLOPEZ : FLOORZ)) d->floor = collidewall; break; - case PHYS_STEP_UP: d->o.z -= STAIRHEIGHT+0.15f; if(collide(d, vec(0, 0, -1), SLOPEZ)) d->floor = collidewall; break; - case PHYS_SLIDE: d->o.z -= 0.15f; if(collide(d, vec(0, 0, -1)) && collidewall.z < SLOPEZ) @@ -1788,30 +1512,23 @@ dir(right, strafe, -1, k_right, k_left); ICOMMAND(jump, "D", (int *down), { if(!*down || game::canjump()) player->jumping = *down!=0; }); ICOMMAND(attack, "D", (int *down), { game::doattack(*down!=0); }); -bool entinmap(dynent *d, bool avoidplayers) // brute force but effective way to find a free spawn spot in the map -{ +bool entinmap(dynent *d, bool avoidplayers) { // brute force but effective way to find a free spawn spot in the map { d->o.z += d->eyeheight; // pos specified is at feet vec orig = d->o; - loopi(100) // try max 100 times - { - if(i) - { + loopi(100) { // try max 100 times { + if(i) { d->o = orig; d->o.x += (rnd(21)-10)*i/5; // increasing distance d->o.y += (rnd(21)-10)*i/5; d->o.z += (rnd(21)-10)*i/5; } - - if(!collide(d) && !collideinside) - { - if(collideplayer) - { + if(!collide(d) && !collideinside) { + if(collideplayer) { if(!avoidplayers) continue; d->o = orig; d->resetinterp(); return false; } - d->resetinterp(); return true; } diff --git a/src/engine/ragdoll.h b/src/engine/ragdoll.h index 4dac48c..915076e 100644 --- a/src/engine/ragdoll.h +++ b/src/engine/ragdoll.h @@ -1,53 +1,36 @@ -struct ragdollskel -{ - struct vert - { +struct ragdollskel { + struct vert { vec pos; float radius, weight; }; - - struct tri - { + struct tri { int vert[3]; - - bool shareverts(const tri &t) const - { + bool shareverts(const tri &t) const { loopi(3) loopj(3) if(vert[i] == t.vert[j]) return true; return false; } }; - - struct distlimit - { + struct distlimit { int vert[2]; float mindist, maxdist; }; - - struct rotlimit - { + struct rotlimit { int tri[2]; float maxangle; matrix3 middle; }; - - struct rotfriction - { + struct rotfriction { int tri[2]; matrix3 middle; }; - - struct joint - { + struct joint { int bone, tri, vert[3]; float weight; matrix4x3 orient; }; - - struct reljoint - { + struct reljoint { int bone, parent; }; - bool loaded, animjoints; int eye; vector<vert> verts; @@ -57,26 +40,20 @@ struct ragdollskel vector<rotfriction> rotfrictions; vector<joint> joints; vector<reljoint> reljoints; - ragdollskel() : loaded(false), animjoints(false), eye(-1) {} - - void setupjoints() - { + void setupjoints() { loopv(verts) verts[i].weight = 0; - loopv(joints) - { + loopv(joints) { joint &j = joints[i]; j.weight = 0; vec pos(0, 0, 0); - loopk(3) if(j.vert[k]>=0) - { + loopk(3) if(j.vert[k]>=0) { pos.add(verts[j.vert[k]].pos); j.weight++; verts[j.vert[k]].weight++; } if(j.weight) j.weight = 1/j.weight; pos.mul(j.weight); - tri &t = tris[j.tri]; matrix4x3 &m = j.orient; const vec &v1 = verts[t.vert[0]].pos, @@ -91,45 +68,33 @@ struct ragdollskel loopv(verts) if(verts[i].weight) verts[i].weight = 1/verts[i].weight; reljoints.shrink(0); } - - void setuprotfrictions() - { + void setuprotfrictions() { rotfrictions.shrink(0); - loopv(tris) for(int j = i+1; j < tris.length(); j++) if(tris[i].shareverts(tris[j])) - { + loopv(tris) for(int j = i+1; j < tris.length(); j++) if(tris[i].shareverts(tris[j])) { rotfriction &r = rotfrictions.add(); r.tri[0] = i; r.tri[1] = j; } } - - void setup() - { + void setup() { setupjoints(); setuprotfrictions(); - loaded = true; } - - void addreljoint(int bone, int parent) - { + void addreljoint(int bone, int parent) { reljoint &r = reljoints.add(); r.bone = bone; r.parent = parent; } }; -struct ragdolldata -{ - struct vert - { +struct ragdolldata { + struct vert { vec oldpos, pos, newpos; float weight; bool collided, stuck; - vert() : pos(0, 0, 0), newpos(0, 0, 0), weight(0), collided(false), stuck(true) {} }; - ragdollskel *skel; int millis, collidemillis, collisions, floating, lastmove, unsticks; vec offset, center; @@ -138,7 +103,6 @@ struct ragdolldata matrix3 *tris; matrix4x3 *animjoints; dualquat *reljoints; - ragdolldata(ragdollskel *skel, float scale = 1) : skel(skel), millis(lastmillis), @@ -153,26 +117,20 @@ struct ragdolldata verts(new vert[skel->verts.length()]), tris(new matrix3[skel->tris.length()]), animjoints(!skel->animjoints || skel->joints.empty() ? NULL : new matrix4x3[skel->joints.length()]), - reljoints(skel->reljoints.empty() ? NULL : new dualquat[skel->reljoints.length()]) - { + reljoints(skel->reljoints.empty() ? NULL : new dualquat[skel->reljoints.length()]) { } - - ~ragdolldata() - { + ~ragdolldata() { delete[] verts; delete[] tris; if(animjoints) delete[] animjoints; if(reljoints) delete[] reljoints; } - - void calcanimjoint(int i, const matrix4x3 &anim) - { + void calcanimjoint(int i, const matrix4x3 &anim) { if(!animjoints) return; ragdollskel::joint &j = skel->joints[i]; vec pos(0, 0, 0); loopk(3) if(j.vert[k]>=0) pos.add(verts[j.vert[k]].pos); pos.mul(j.weight); - ragdollskel::tri &t = skel->tris[j.tri]; matrix4x3 m; const vec &v1 = verts[t.vert[0]].pos, @@ -184,11 +142,8 @@ struct ragdolldata m.d = pos; animjoints[i].transposemul(m, anim); } - - void calctris() - { - loopv(skel->tris) - { + void calctris() { + loopv(skel->tris) { ragdollskel::tri &t = skel->tris[i]; matrix3 &m = tris[i]; const vec &v1 = verts[t.vert[0]].pos, @@ -199,30 +154,24 @@ struct ragdolldata m.b.cross(m.c, m.a); } } - - void calcboundsphere() - { + void calcboundsphere() { center = vec(0, 0, 0); loopv(skel->verts) center.add(verts[i].pos); center.div(skel->verts.length()); radius = 0; loopv(skel->verts) radius = max(radius, verts[i].pos.dist(center)); } - - void init(dynent *d) - { + void init(dynent *d) { extern int ragdolltimestepmin; float ts = ragdolltimestepmin/1000.0f; loopv(skel->verts) (verts[i].oldpos = verts[i].pos).sub(vec(d->vel).add(d->falling).mul(ts)); timestep = ts; - calctris(); calcboundsphere(); offset = d->o; offset.sub(skel->eye >= 0 ? verts[skel->eye].pos : center); offset.z += (d->eyeheight + d->aboveeye)/2; } - void move(dynent *pl, float ts); void updatepos(); void constrain(); @@ -232,13 +181,9 @@ struct ragdolldata void calcrotfriction(); void applyrotfriction(float ts); void tryunstick(float speed); - - static inline bool collidevert(const vec &pos, const vec &dir, float radius) - { - static struct vertent : physent - { - vertent() - { + static inline bool collidevert(const vec &pos, const vec &dir, float radius) { + static struct vertent : physent { + vertent() { type = ENT_BOUNCE; radius = xradius = yradius = eyeheight = aboveeye = 1; } @@ -255,11 +200,9 @@ struct ragdolldata parented transform = parent{invert(curtri) * origtrig} * (invert(parent{base2anim}) * base2anim) */ -void ragdolldata::constraindist() -{ +void ragdolldata::constraindist() { float invscale = 1.0f/scale; - loopv(skel->distlimits) - { + loopv(skel->distlimits) { ragdollskel::distlimit &d = skel->distlimits[i]; vert &v1 = verts[d.vert[0]], &v2 = verts[d.vert[1]]; vec dir = vec(v2.pos).sub(v1.pos); @@ -277,8 +220,7 @@ void ragdolldata::constraindist() } } -inline void ragdolldata::applyrotlimit(ragdollskel::tri &t1, ragdollskel::tri &t2, float angle, const vec &axis) -{ +inline void ragdolldata::applyrotlimit(ragdollskel::tri &t1, ragdollskel::tri &t2, float angle, const vec &axis) { vert &v1a = verts[t1.vert[0]], &v1b = verts[t1.vert[1]], &v1c = verts[t1.vert[2]], &v2a = verts[t2.vert[0]], &v2b = verts[t2.vert[1]], &v2c = verts[t2.vert[2]]; vec m1 = vec(v1a.pos).add(v1b.pos).add(v1c.pos).div(3), @@ -308,22 +250,18 @@ inline void ragdolldata::applyrotlimit(ragdollskel::tri &t1, ragdollskel::tri &t v2c.weight++; } -void ragdolldata::constrainrot() -{ - loopv(skel->rotlimits) - { +void ragdolldata::constrainrot() { + loopv(skel->rotlimits) { ragdollskel::rotlimit &r = skel->rotlimits[i]; matrix3 rot; rot.mul(tris[r.tri[0]], r.middle); rot.multranspose(tris[r.tri[1]]); - vec axis; float angle; if(!rot.calcangleaxis(angle, axis)) continue; angle = r.maxangle - fabs(angle); if(angle >= 0) continue; angle += 1e-3f; - applyrotlimit(skel->tris[r.tri[0]], skel->tris[r.tri[1]], angle, axis); } } @@ -333,36 +271,29 @@ VAR(ragdolltimestepmax, 1, 10, 50); FVAR(ragdollrotfric, 0, 0.85f, 1); FVAR(ragdollrotfricstop, 0, 0.1f, 1); -void ragdolldata::calcrotfriction() -{ - loopv(skel->rotfrictions) - { +void ragdolldata::calcrotfriction() { + loopv(skel->rotfrictions) { ragdollskel::rotfriction &r = skel->rotfrictions[i]; r.middle.transposemul(tris[r.tri[0]], tris[r.tri[1]]); } } -void ragdolldata::applyrotfriction(float ts) -{ +void ragdolldata::applyrotfriction(float ts) { calctris(); float stopangle = 2*M_PI*ts*ragdollrotfricstop, rotfric = 1.0f - pow(ragdollrotfric, ts*1000.0f/ragdolltimestepmin); - loopv(skel->rotfrictions) - { + loopv(skel->rotfrictions) { ragdollskel::rotfriction &r = skel->rotfrictions[i]; matrix3 rot; rot.mul(tris[r.tri[0]], r.middle); rot.multranspose(tris[r.tri[1]]); - vec axis; float angle; - if(rot.calcangleaxis(angle, axis)) - { + if(rot.calcangleaxis(angle, axis)) { angle *= -(fabs(angle) >= stopangle ? rotfric : 1.0f); applyrotlimit(skel->tris[r.tri[0]], skel->tris[r.tri[1]], angle, axis); } } - loopv(skel->verts) - { + loopv(skel->verts) { vert &v = verts[i]; if(v.weight) v.pos = v.newpos.div(v.weight); v.newpos = vec(0, 0, 0); @@ -370,15 +301,12 @@ void ragdolldata::applyrotfriction(float ts) } } -void ragdolldata::tryunstick(float speed) -{ +void ragdolldata::tryunstick(float speed) { vec unstuck(0, 0, 0); int stuck = 0; - loopv(skel->verts) - { + loopv(skel->verts) { vert &v = verts[i]; - if(v.stuck) - { + if(v.stuck) { if(collidevert(v.pos, vec(0, 0, 0), skel->verts[i].radius)) { stuck++; continue; } v.stuck = false; } @@ -387,28 +315,22 @@ void ragdolldata::tryunstick(float speed) unsticks = 0; if(!stuck || stuck >= skel->verts.length()) return; unstuck.div(skel->verts.length() - stuck); - loopv(skel->verts) - { + loopv(skel->verts) { vert &v = verts[i]; - if(v.stuck) - { + if(v.stuck) { v.pos.add(vec(unstuck).sub(v.pos).rescale(speed)); unsticks++; } } } -void ragdolldata::updatepos() -{ - loopv(skel->verts) - { +void ragdolldata::updatepos() { + loopv(skel->verts) { vert &v = verts[i]; - if(v.weight) - { + if(v.weight) { v.newpos.div(v.weight); if(!collidevert(v.newpos, vec(v.newpos).sub(v.pos), skel->verts[i].radius)) v.pos = v.newpos; - else - { + else { vec dir = vec(v.newpos).sub(v.oldpos); if(dir.dot(collidewall) < 0) v.oldpos = vec(v.pos).sub(dir.reflect(collidewall)); v.collided = true; @@ -421,13 +343,10 @@ void ragdolldata::updatepos() VAR(ragdollconstrain, 1, 5, 100); -void ragdolldata::constrain() -{ - loopi(ragdollconstrain) - { +void ragdolldata::constrain() { + loopi(ragdollconstrain) { constraindist(); updatepos(); - calctris(); constrainrot(); updatepos(); @@ -441,19 +360,15 @@ FVAR(ragdollairfric, 0, 0.996f, 1); FVAR(ragdollunstick, 0, 10, 1e3f); VAR(ragdollexpireoffset, 0, 1500, 30000); -void ragdolldata::move(dynent *pl, float ts) -{ +void ragdolldata::move(dynent *pl, float ts) { extern const float GRAVITY; if(collidemillis && lastmillis > collidemillis) return; - pl->inwater = MAT_AIR; - calcrotfriction(); float tsfric = timestep ? ts/timestep : 1, airfric = ragdollairfric + min((ragdollbodyfricscale*collisions)/skel->verts.length(), 1.0f)*(ragdollbodyfric - ragdollairfric); collisions = 0; - loopv(skel->verts) - { + loopv(skel->verts) { vert &v = verts[i]; vec dpos = vec(v.pos).sub(v.oldpos); dpos.z -= GRAVITY*ts*ts; @@ -462,30 +377,24 @@ void ragdolldata::move(dynent *pl, float ts) v.pos.add(dpos); } applyrotfriction(ts); - loopv(skel->verts) - { + loopv(skel->verts) { vert &v = verts[i]; if(v.pos.z < 0) { v.pos.z = 0; v.oldpos = v.pos; collisions++; } vec dir = vec(v.pos).sub(v.oldpos); v.collided = collidevert(v.pos, dir, skel->verts[i].radius); - if(v.collided) - { + if(v.collided) { v.pos = v.oldpos; v.oldpos.sub(dir.reflect(collidewall)); collisions++; } } - if(unsticks && ragdollunstick) tryunstick(ts*ragdollunstick); - timestep = ts; - if(collisions) - { + if(collisions) { floating = 0; if(!collidemillis) collidemillis = lastmillis + ragdollexpireoffset; } else if(++floating > 1 && lastmillis < collidemillis) collidemillis = 0; - constrain(); calctris(); calcboundsphere(); @@ -494,28 +403,22 @@ void ragdolldata::move(dynent *pl, float ts) FVAR(ragdolleyesmooth, 0, 0.5f, 1); VAR(ragdolleyesmoothmillis, 1, 250, 10000); -void moveragdoll(dynent *d) -{ +void moveragdoll(dynent *d) { if(!curtime || !d->ragdoll) return; - - if(!d->ragdoll->collidemillis || lastmillis < d->ragdoll->collidemillis) - { + if(!d->ragdoll->collidemillis || lastmillis < d->ragdoll->collidemillis) { int lastmove = d->ragdoll->lastmove; - while(d->ragdoll->lastmove + (lastmove == d->ragdoll->lastmove ? ragdolltimestepmin : ragdolltimestepmax) <= lastmillis) - { + while(d->ragdoll->lastmove + (lastmove == d->ragdoll->lastmove ? ragdolltimestepmin : ragdolltimestepmax) <= lastmillis) { int timestep = min(ragdolltimestepmax, lastmillis - d->ragdoll->lastmove); d->ragdoll->move(d, timestep/1000.0f); d->ragdoll->lastmove += timestep; } } - vec eye = d->ragdoll->skel->eye >= 0 ? d->ragdoll->verts[d->ragdoll->skel->eye].pos : d->ragdoll->center; eye.add(d->ragdoll->offset); float k = pow(ragdolleyesmooth, float(curtime)/ragdolleyesmoothmillis); d->o.mul(k).add(eye.mul(1-k)); } -void cleanragdoll(dynent *d) -{ +void cleanragdoll(dynent *d) { DELETEP(d->ragdoll); } diff --git a/src/engine/rendergl.cpp b/src/engine/rendergl.cpp index 7489ff5..b8b28c5 100644 --- a/src/engine/rendergl.cpp +++ b/src/engine/rendergl.cpp @@ -143,8 +143,7 @@ PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays_ = NULL; PFNGLGENVERTEXARRAYSPROC glGenVertexArrays_ = NULL; PFNGLISVERTEXARRAYPROC glIsVertexArray_ = NULL; -void *getprocaddress(const char *name) -{ +void *getprocaddress(const char *name) { return SDL_GL_GetProcAddress(name); } @@ -162,23 +161,18 @@ VAR(rtsharefb, 0, 1, 1); hashset<const char *> glexts; -void parseglexts() -{ - if(glversion >= 300) - { +void parseglexts() { + if(glversion >= 300) { GLint numexts = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &numexts); - loopi(numexts) - { + loopi(numexts) { const char *ext = (const char *)glGetStringi_(GL_EXTENSIONS, i); glexts.add(newstring(ext)); } } - else - { + else { const char *exts = (const char *)glGetString(GL_EXTENSIONS); - for(;;) - { + for(;;) { while(*exts == ' ') exts++; if(!*exts) break; const char *ext = exts; @@ -188,47 +182,35 @@ void parseglexts() } } -bool hasext(const char *ext) -{ +bool hasext(const char *ext) { return glexts.access(ext)!=NULL; } -void gl_checkextensions() -{ +void gl_checkextensions() { const char *vendor = (const char *)glGetString(GL_VENDOR); const char *renderer = (const char *)glGetString(GL_RENDERER); const char *version = (const char *)glGetString(GL_VERSION); conoutf(CON_INIT, "Renderer: %s (%s)", renderer, vendor); conoutf(CON_INIT, "Driver: %s", version); - - bool mesa = false, intel = false, ati = false, nvidia = false; - if(strstr(renderer, "Mesa") || strstr(version, "Mesa")) - { + bool mesa = false, ati = false, nvidia = false; + if(strstr(renderer, "Mesa") || strstr(version, "Mesa")) { mesa = true; - if(strstr(renderer, "Intel")) intel = true; } else if(strstr(vendor, "NVIDIA")) nvidia = true; else if(strstr(vendor, "ATI") || strstr(vendor, "Advanced Micro Devices")) ati = true; - else if(strstr(vendor, "Intel")) - intel = true; - uint glmajorversion, glminorversion; if(sscanf(version, " %u.%u", &glmajorversion, &glminorversion) != 2) glversion = 100; else glversion = glmajorversion*100 + glminorversion*10; - if(glversion < 200) fatal("OpenGL 2.0 or greater is required!"); - glMultiDrawArrays_ = (PFNGLMULTIDRAWARRAYSPROC) getprocaddress("glMultiDrawArrays"); glMultiDrawElements_ = (PFNGLMULTIDRAWELEMENTSPROC) getprocaddress("glMultiDrawElements"); - glBlendFuncSeparate_ = (PFNGLBLENDFUNCSEPARATEPROC) getprocaddress("glBlendFuncSeparate"); glBlendEquationSeparate_ = (PFNGLBLENDEQUATIONSEPARATEPROC) getprocaddress("glBlendEquationSeparate"); glStencilOpSeparate_ = (PFNGLSTENCILOPSEPARATEPROC) getprocaddress("glStencilOpSeparate"); glStencilFuncSeparate_ = (PFNGLSTENCILFUNCSEPARATEPROC) getprocaddress("glStencilFuncSeparate"); glStencilMaskSeparate_ = (PFNGLSTENCILMASKSEPARATEPROC) getprocaddress("glStencilMaskSeparate"); - glGenBuffers_ = (PFNGLGENBUFFERSPROC) getprocaddress("glGenBuffers"); glBindBuffer_ = (PFNGLBINDBUFFERPROC) getprocaddress("glBindBuffer"); glMapBuffer_ = (PFNGLMAPBUFFERPROC) getprocaddress("glMapBuffer"); @@ -237,7 +219,6 @@ void gl_checkextensions() glBufferSubData_ = (PFNGLBUFFERSUBDATAPROC) getprocaddress("glBufferSubData"); glDeleteBuffers_ = (PFNGLDELETEBUFFERSPROC) getprocaddress("glDeleteBuffers"); glGetBufferSubData_ = (PFNGLGETBUFFERSUBDATAPROC) getprocaddress("glGetBufferSubData"); - glGetQueryiv_ = (PFNGLGETQUERYIVPROC) getprocaddress("glGetQueryiv"); glGenQueries_ = (PFNGLGENQUERIESPROC) getprocaddress("glGenQueries"); glDeleteQueries_ = (PFNGLDELETEQUERIESPROC) getprocaddress("glDeleteQueries"); @@ -245,7 +226,6 @@ void gl_checkextensions() glEndQuery_ = (PFNGLENDQUERYPROC) getprocaddress("glEndQuery"); glGetQueryObjectiv_ = (PFNGLGETQUERYOBJECTIVPROC) getprocaddress("glGetQueryObjectiv"); glGetQueryObjectuiv_ = (PFNGLGETQUERYOBJECTUIVPROC) getprocaddress("glGetQueryObjectuiv"); - glCreateProgram_ = (PFNGLCREATEPROGRAMPROC) getprocaddress("glCreateProgram"); glDeleteProgram_ = (PFNGLDELETEPROGRAMPROC) getprocaddress("glDeleteProgram"); glUseProgram_ = (PFNGLUSEPROGRAMPROC) getprocaddress("glUseProgram"); @@ -283,7 +263,6 @@ void gl_checkextensions() glGetActiveUniform_ = (PFNGLGETACTIVEUNIFORMPROC) getprocaddress("glGetActiveUniform"); glEnableVertexAttribArray_ = (PFNGLENABLEVERTEXATTRIBARRAYPROC) getprocaddress("glEnableVertexAttribArray"); glDisableVertexAttribArray_ = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) getprocaddress("glDisableVertexAttribArray"); - glVertexAttrib1f_ = (PFNGLVERTEXATTRIB1FPROC) getprocaddress("glVertexAttrib1f"); glVertexAttrib1fv_ = (PFNGLVERTEXATTRIB1FVPROC) getprocaddress("glVertexAttrib1fv"); glVertexAttrib1s_ = (PFNGLVERTEXATTRIB1SPROC) getprocaddress("glVertexAttrib1s"); @@ -312,44 +291,31 @@ void gl_checkextensions() glVertexAttrib4Nuiv_ = (PFNGLVERTEXATTRIB4NUIVPROC) getprocaddress("glVertexAttrib4Nuiv"); glVertexAttrib4Nusv_ = (PFNGLVERTEXATTRIB4NUSVPROC) getprocaddress("glVertexAttrib4Nusv"); glVertexAttribPointer_ = (PFNGLVERTEXATTRIBPOINTERPROC) getprocaddress("glVertexAttribPointer"); - glDrawBuffers_ = (PFNGLDRAWBUFFERSPROC) getprocaddress("glDrawBuffers"); - - if(glversion >= 300) - { + if(glversion >= 300) { glGetStringi_ = (PFNGLGETSTRINGIPROC) getprocaddress("glGetStringi"); glBindFragDataLocation_ = (PFNGLBINDFRAGDATALOCATIONPROC)getprocaddress("glBindFragDataLocation"); } - const char *glslstr = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); uint glslmajorversion, glslminorversion; if(glslstr && sscanf(glslstr, " %u.%u", &glslmajorversion, &glslminorversion) == 2) glslversion = glslmajorversion*100 + glslminorversion; - if(glslversion < 120) fatal("GLSL 1.20 or greater is required!"); - parseglexts(); - GLint val; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &val); hwtexsize = val; glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &val); hwcubetexsize = val; - - if(glversion >= 300 || hasext("GL_ARB_texture_float") || hasext("GL_ATI_texture_float")) - { + if(glversion >= 300 || hasext("GL_ARB_texture_float") || hasext("GL_ATI_texture_float")) { hasTF = true; shadowmap = 1; extern int smoothshadowmappeel; smoothshadowmappeel = 1; } - - if(glversion >= 300 || hasext("GL_ARB_texture_rg")) - { + if(glversion >= 300 || hasext("GL_ARB_texture_rg")) { hasTRG = true; } - - if(glversion >= 300 || hasext("GL_ARB_framebuffer_object")) - { + if(glversion >= 300 || hasext("GL_ARB_framebuffer_object")) { glBindRenderbuffer_ = (PFNGLBINDRENDERBUFFERPROC) getprocaddress("glBindRenderbuffer"); glDeleteRenderbuffers_ = (PFNGLDELETERENDERBUFFERSPROC) getprocaddress("glDeleteRenderbuffers"); glGenRenderbuffers_ = (PFNGLGENFRAMEBUFFERSPROC) getprocaddress("glGenRenderbuffers"); @@ -364,8 +330,7 @@ void gl_checkextensions() glBlitFramebuffer_ = (PFNGLBLITFRAMEBUFFERPROC) getprocaddress("glBlitFramebuffer"); hasAFBO = hasFBO = hasFBB = hasDS = true; } - else if(hasext("GL_EXT_framebuffer_object")) - { + else if(hasext("GL_EXT_framebuffer_object")) { glBindRenderbuffer_ = (PFNGLBINDRENDERBUFFERPROC) getprocaddress("glBindRenderbufferEXT"); glDeleteRenderbuffers_ = (PFNGLDELETERENDERBUFFERSPROC) getprocaddress("glDeleteRenderbuffersEXT"); glGenRenderbuffers_ = (PFNGLGENFRAMEBUFFERSPROC) getprocaddress("glGenRenderbuffersEXT"); @@ -378,49 +343,36 @@ void gl_checkextensions() glFramebufferRenderbuffer_ = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)getprocaddress("glFramebufferRenderbufferEXT"); glGenerateMipmap_ = (PFNGLGENERATEMIPMAPPROC) getprocaddress("glGenerateMipmapEXT"); hasFBO = true; - - if(hasext("GL_EXT_framebuffer_blit")) - { + if(hasext("GL_EXT_framebuffer_blit")) { glBlitFramebuffer_ = (PFNGLBLITFRAMEBUFFERPROC) getprocaddress("glBlitFramebufferEXT"); hasFBB = true; } - - if(hasext("GL_EXT_packed_depth_stencil") || hasext("GL_NV_packed_depth_stencil")) - { + if(hasext("GL_EXT_packed_depth_stencil") || hasext("GL_NV_packed_depth_stencil")) { hasDS = true; } } else fatal("Framebuffer object support is required!"); - - if(ati) - { + if(ati) { minimizetcusage = 1; // On Catalyst 10.2, issuing an occlusion query on the first draw using a given cubemap texture causes a nasty crash ati_cubemap_bug = 1; } - else if(nvidia) - { + else if(nvidia) { reservevpparams = 10; rtsharefb = 0; // work-around for strange driver stalls involving when using many FBOs extern int filltjoints; if(glversion < 300 && !hasext("GL_EXT_gpu_shader4")) filltjoints = 0; // DX9 or less NV cards seem to not cause many sparklies } - else - { + else { reservevpparams = 20; - if(mesa) mesa_swap_bug = 1; } - - if(glversion >= 300 || hasext("GL_ARB_map_buffer_range")) - { + if(glversion >= 300 || hasext("GL_ARB_map_buffer_range")) { glMapBufferRange_ = (PFNGLMAPBUFFERRANGEPROC) getprocaddress("glMapBufferRange"); glFlushMappedBufferRange_ = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)getprocaddress("glFlushMappedBufferRange"); hasMBR = true; } - - if(glversion >= 310 || hasext("GL_ARB_uniform_buffer_object")) - { + if(glversion >= 310 || hasext("GL_ARB_uniform_buffer_object")) { glGetUniformIndices_ = (PFNGLGETUNIFORMINDICESPROC) getprocaddress("glGetUniformIndices"); glGetActiveUniformsiv_ = (PFNGLGETACTIVEUNIFORMSIVPROC) getprocaddress("glGetActiveUniformsiv"); glGetUniformBlockIndex_ = (PFNGLGETUNIFORMBLOCKINDEXPROC) getprocaddress("glGetUniformBlockIndex"); @@ -428,66 +380,50 @@ void gl_checkextensions() glUniformBlockBinding_ = (PFNGLUNIFORMBLOCKBINDINGPROC) getprocaddress("glUniformBlockBinding"); glBindBufferBase_ = (PFNGLBINDBUFFERBASEPROC) getprocaddress("glBindBufferBase"); glBindBufferRange_ = (PFNGLBINDBUFFERRANGEPROC) getprocaddress("glBindBufferRange"); - useubo = 1; hasUBO = true; } - - if(glversion >= 300 || hasext("GL_ARB_vertex_array_object")) - { + if(glversion >= 300 || hasext("GL_ARB_vertex_array_object")) { glBindVertexArray_ = (PFNGLBINDVERTEXARRAYPROC) getprocaddress("glBindVertexArray"); glDeleteVertexArrays_ = (PFNGLDELETEVERTEXARRAYSPROC)getprocaddress("glDeleteVertexArrays"); glGenVertexArrays_ = (PFNGLGENVERTEXARRAYSPROC) getprocaddress("glGenVertexArrays"); glIsVertexArray_ = (PFNGLISVERTEXARRAYPROC) getprocaddress("glIsVertexArray"); hasVAO = true; } - else if(hasext("GL_APPLE_vertex_array_object")) - { + else if(hasext("GL_APPLE_vertex_array_object")) { glBindVertexArray_ = (PFNGLBINDVERTEXARRAYPROC) getprocaddress("glBindVertexArrayAPPLE"); glDeleteVertexArrays_ = (PFNGLDELETEVERTEXARRAYSPROC)getprocaddress("glDeleteVertexArraysAPPLE"); glGenVertexArrays_ = (PFNGLGENVERTEXARRAYSPROC) getprocaddress("glGenVertexArraysAPPLE"); glIsVertexArray_ = (PFNGLISVERTEXARRAYPROC) getprocaddress("glIsVertexArrayAPPLE"); hasVAO = true; } - - if(glversion >= 330 || hasext("GL_ARB_texture_swizzle") || hasext("GL_EXT_texture_swizzle")) - { + if(glversion >= 330 || hasext("GL_ARB_texture_swizzle") || hasext("GL_EXT_texture_swizzle")) { hasTSW = true; } - - if(hasext("GL_EXT_texture_compression_s3tc")) - { + if(hasext("GL_EXT_texture_compression_s3tc")) { hasS3TC = true; if(!mesa) usetexcompress = 2; } - else if(hasext("GL_EXT_texture_compression_dxt1") && hasext("GL_ANGLE_texture_compression_dxt3") && hasext("GL_ANGLE_texture_compression_dxt5")) - { + else if(hasext("GL_EXT_texture_compression_dxt1") && hasext("GL_ANGLE_texture_compression_dxt3") && hasext("GL_ANGLE_texture_compression_dxt5")) { hasS3TC = true; } - if(hasext("GL_3DFX_texture_compression_FXT1")) - { + if(hasext("GL_3DFX_texture_compression_FXT1")) { hasFXT1 = true; if(mesa) usetexcompress = max(usetexcompress, 1); } - if(hasext("GL_EXT_texture_compression_latc")) - { + if(hasext("GL_EXT_texture_compression_latc")) { hasLATC = true; } - if(glversion >= 300 || hasext("GL_ARB_texture_compression_rgtc") || hasext("GL_EXT_texture_compression_rgtc")) - { + if(glversion >= 300 || hasext("GL_ARB_texture_compression_rgtc") || hasext("GL_EXT_texture_compression_rgtc")) { hasRGTC = true; } - - if(hasext("GL_EXT_texture_filter_anisotropic")) - { + if(hasext("GL_EXT_texture_filter_anisotropic")) { GLint val; glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &val); hwmaxaniso = val; hasAF = true; } - - if(glversion >= 300 || hasext("GL_EXT_gpu_shader4")) - { + if(glversion >= 300 || hasext("GL_EXT_gpu_shader4")) { // on DX10 or above class cards (i.e. GF8 or RadeonHD) enable expensive features extern int maxdynlights, texcompress; maxdynlights = MAXDYNLIGHTS; @@ -495,37 +431,28 @@ void gl_checkextensions() } } -void glext(char *ext) -{ +void glext(char *ext) { intret(hasext(ext) ? 1 : 0); } COMMAND(glext, "s"); -void gl_resize() -{ +void gl_resize() { glViewport(0, 0, screenw, screenh); } -void gl_init() -{ +void gl_init() { glClearColor(0, 0, 0, 0); glClearDepth(1); glDepthFunc(GL_LESS); glDisable(GL_DEPTH_TEST); - glEnable(GL_LINE_SMOOTH); //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glFrontFace(GL_CW); glCullFace(GL_BACK); glDisable(GL_CULL_FACE); - gle::setup(); - setupshaders(); - setuptexcompress(); - gl_resize(); } @@ -534,95 +461,76 @@ VAR(wireframe, 0, 0, 1); ICOMMAND(getcamyaw, "", (), floatret(camera1->yaw)); ICOMMAND(getcampitch, "", (), floatret(camera1->pitch)); ICOMMAND(getcamroll, "", (), floatret(camera1->roll)); -ICOMMAND(getcampos, "", (), -{ +ICOMMAND(getcampos, "", (), { defformatstring(pos, "%s %s %s", floatstr(camera1->o.x), floatstr(camera1->o.y), floatstr(camera1->o.z)); result(pos); }); vec worldpos, camdir, camright, camup; -void setcammatrix() -{ +void setcammatrix() { // move from RH to Z-up LH quake style worldspace cammatrix = viewmatrix; cammatrix.rotate_around_y(camera1->roll*RAD); cammatrix.rotate_around_x(camera1->pitch*-RAD); cammatrix.rotate_around_z(camera1->yaw*-RAD); cammatrix.translate(vec(camera1->o).neg()); - cammatrix.transposedtransformnormal(vec(viewmatrix.b), camdir); cammatrix.transposedtransformnormal(vec(viewmatrix.a).neg(), camright); cammatrix.transposedtransformnormal(vec(viewmatrix.c), camup); - - if(!drawtex) - { + if(!drawtex) { if(raycubepos(camera1->o, camdir, worldpos, 0, RAY_CLIPMAT|RAY_SKIPFIRST) == -1) worldpos = vec(camdir).mul(2*worldsize).add(camera1->o); // if nothing is hit, just far away in the view direction } } -void setcamprojmatrix(bool init = true, bool flush = false) -{ - if(init) - { +void setcamprojmatrix(bool init = true, bool flush = false) { + if(init) { setcammatrix(); } - camprojmatrix.muld(projmatrix, cammatrix); - - if(init) - { + if(init) { invcammatrix.invert(cammatrix); invcamprojmatrix.invert(camprojmatrix); } - GLOBALPARAM(camprojmatrix, camprojmatrix); - if(flush && Shader::lastshader) Shader::lastshader->flushparams(); } matrix4 hudmatrix, hudmatrixstack[64]; int hudmatrixpos = 0; -void resethudmatrix() -{ +void resethudmatrix() { hudmatrixpos = 0; GLOBALPARAM(hudmatrix, hudmatrix); } -void pushhudmatrix() -{ +void pushhudmatrix() { if(hudmatrixpos >= 0 && hudmatrixpos < int(sizeof(hudmatrixstack)/sizeof(hudmatrixstack[0]))) hudmatrixstack[hudmatrixpos] = hudmatrix; ++hudmatrixpos; } -void flushhudmatrix(bool flushparams) -{ +void flushhudmatrix(bool flushparams) { GLOBALPARAM(hudmatrix, hudmatrix); if(flushparams && Shader::lastshader) Shader::lastshader->flushparams(); } -void pophudmatrix(bool flush, bool flushparams) -{ +void pophudmatrix(bool flush, bool flushparams) { --hudmatrixpos; - if(hudmatrixpos >= 0 && hudmatrixpos < int(sizeof(hudmatrixstack)/sizeof(hudmatrixstack[0]))) - { + if(hudmatrixpos >= 0 && hudmatrixpos < int(sizeof(hudmatrixstack)/sizeof(hudmatrixstack[0]))) { hudmatrix = hudmatrixstack[hudmatrixpos]; if(flush) flushhudmatrix(flushparams); } } -void pushhudscale(float sx, float sy) -{ +void pushhudscale(float sx, float sy) { if(!sy) sy = sx; pushhudmatrix(); hudmatrix.scale(sx, sy, 1); flushhudmatrix(); } -void pushhudtranslate(float tx, float ty, float sx, float sy) -{ +void pushhudtranslate(float tx, float ty, float sx, float sy) { if(!sy) sy = sx; pushhudmatrix(); hudmatrix.translate(tx, ty, 0); @@ -644,18 +552,15 @@ FVARNP(aspect, forceaspect, 0, 0, 1e3f); static float zoomprogress = 0; VAR(zoom, -1, 0, 1); -void disablezoom() -{ +void disablezoom() { zoom = 0; zoomprogress = 0; } -void computezoom() -{ +void computezoom() { if(!zoom) { zoomprogress = 0; curfov = fov; curavatarfov = avatarfov; return; } if(zoom > 0) zoomprogress = zoominvel ? min(zoomprogress + float(elapsedtime) / zoominvel, 1.0f) : 1; - else - { + else { zoomprogress = zoomoutvel ? max(zoomprogress - float(elapsedtime) / zoomoutvel, 0.0f) : 0; if(zoomprogress <= 0) zoom = 0; } @@ -679,8 +584,7 @@ physent *camera1 = NULL; bool detachedcamera = false; bool isthirdperson() { return player!=camera1 || detachedcamera; } -void fixcamerarange() -{ +void fixcamerarange() { const float MAXPITCH = 90.0f; if(camera1->pitch>MAXPITCH) camera1->pitch = MAXPITCH; if(camera1->pitch<-MAXPITCH) camera1->pitch = -MAXPITCH; @@ -688,19 +592,15 @@ void fixcamerarange() while(camera1->yaw>=360.0f) camera1->yaw -= 360.0f; } -void mousemove(int dx, int dy) -{ +void mousemove(int dx, int dy) { if(!game::allowmouselook()) return; float cursens = sensitivity, curaccel = mouseaccel; - if(zoom) - { - if(zoomautosens) - { + if(zoom) { + if(zoomautosens) { cursens = float(sensitivity*zoomfov)/fov; curaccel = float(mouseaccel*zoomfov)/fov; } - else - { + else { cursens = zoomsens; curaccel = zoomaccel; } @@ -710,33 +610,27 @@ void mousemove(int dx, int dy) camera1->yaw += dx*cursens; camera1->pitch -= dy*cursens*(invmouse ? -1 : 1); fixcamerarange(); - if(camera1!=player && !detachedcamera) - { + if(camera1!=player && !detachedcamera) { player->yaw = camera1->yaw; player->pitch = camera1->pitch; } speedmodifier += abs(dx)-abs(dy); } -void recomputecamera() -{ +void recomputecamera() { game::setupcamera(); computezoom(); - bool allowthirdperson = game::allowthirdperson(); bool shoulddetach = (allowthirdperson && thirdperson > 1) || game::detachcamera(); - if((!allowthirdperson || !thirdperson) && !shoulddetach) - { + if((!allowthirdperson || !thirdperson) && !shoulddetach) { camera1 = player; detachedcamera = false; } - else - { + else { static physent tempcamera; camera1 = &tempcamera; if(detachedcamera && shoulddetach) camera1->o = player->o; - else - { + else { *camera1 = *player; detachedcamera = shoulddetach; } @@ -744,28 +638,23 @@ void recomputecamera() camera1->type = ENT_CAMERA; camera1->move = -1; camera1->eyeheight = camera1->aboveeye = camera1->radius = camera1->xradius = camera1->yradius = 2; - matrix3 orient; orient.identity(); orient.rotate_around_z(camera1->yaw*RAD); orient.rotate_around_x(camera1->pitch*RAD); orient.rotate_around_y(camera1->roll*-RAD); vec dir = vec(orient.b).neg(), side = vec(orient.a).neg(), up = orient.c; - - if(game::collidecamera()) - { + if(game::collidecamera()) { movecamera(camera1, dir, thirdpersondistance, 1); movecamera(camera1, dir, clamp(thirdpersondistance - camera1->o.dist(player->o), 0.0f, 1.0f), 0.1f); - if(thirdpersonup) - { + if(thirdpersonup) { vec pos = camera1->o; float dist = fabs(thirdpersonup); if(thirdpersonup < 0) up.neg(); movecamera(camera1, up, dist, 1); movecamera(camera1, up, clamp(dist - camera1->o.dist(pos), 0.0f, 1.0f), 0.1f); } - if(thirdpersonside) - { + if(thirdpersonside) { vec pos = camera1->o; float dist = fabs(thirdpersonside); if(thirdpersonside < 0) side.neg(); @@ -773,8 +662,7 @@ void recomputecamera() movecamera(camera1, side, clamp(dist - camera1->o.dist(pos), 0.0f, 1.0f), 0.1f); } } - else - { + else { camera1->o.add(vec(dir).mul(thirdpersondistance)); if(thirdpersonup) camera1->o.add(vec(up).mul(thirdpersonup)); if(thirdpersonside) camera1->o.add(vec(side).mul(thirdpersonside)); @@ -787,8 +675,7 @@ matrix4 cammatrix, projmatrix, camprojmatrix, invcammatrix, invcamprojmatrix; FVAR(nearplane, 0.01f, 0.54f, 2.0f); -vec calcavatarpos(const vec &pos, float dist) -{ +vec calcavatarpos(const vec &pos, float dist) { vec eyepos; cammatrix.transform(pos, eyepos); GLdouble ydist = nearplane * tan(curavatarfov/2*RAD), xdist = ydist * aspect; @@ -797,7 +684,6 @@ vec calcavatarpos(const vec &pos, float dist) scrpos.y = eyepos.y*nearplane/ydist; scrpos.z = (eyepos.z*(farplane + nearplane) - 2*nearplane*farplane) / (farplane - nearplane); scrpos.w = -eyepos.z; - vec worldpos = invcamprojmatrix.perspectivetransform(scrpos); vec dir = vec(worldpos).sub(camera1->o).rescale(dist); return dir.add(camera1->o); @@ -805,17 +691,13 @@ vec calcavatarpos(const vec &pos, float dist) matrix4 clipmatrix, noclipmatrix; -void renderavatar() -{ +void renderavatar() { if(isthirdperson()) return; - matrix4 oldprojmatrix = projmatrix; projmatrix.perspective(curavatarfov, aspect, nearplane, farplane); projmatrix.scalez(avatardepth); setcamprojmatrix(false); - game::renderavatar(); - projmatrix = oldprojmatrix; setcamprojmatrix(false); } @@ -826,36 +708,28 @@ FVAR(depthoffset, -1e4f, 0.01f, 1e4f); matrix4 nooffsetmatrix; -void enablepolygonoffset(GLenum type) -{ - if(!depthoffset) - { +void enablepolygonoffset(GLenum type) { + if(!depthoffset) { glPolygonOffset(polygonoffsetfactor, polygonoffsetunits); glEnable(type); return; } - bool clipped = false; - nooffsetmatrix = projmatrix; projmatrix.d.z += depthoffset * (clipped ? noclipmatrix.c.z : projmatrix.c.z); setcamprojmatrix(false, true); } -void disablepolygonoffset(GLenum type) -{ - if(!depthoffset) - { +void disablepolygonoffset(GLenum type) { + if(!depthoffset) { glDisable(type); return; } - projmatrix = nooffsetmatrix; setcamprojmatrix(false, true); } -void calcspherescissor(const vec ¢er, float size, float &sx1, float &sy1, float &sx2, float &sy2) -{ +void calcspherescissor(const vec ¢er, float size, float &sx1, float &sy1, float &sx2, float &sy2) { vec worldpos(center), e; cammatrix.transform(worldpos, e); if(e.z > 2*size) { sx1 = sy1 = 1; sx2 = sy2 = -1; return; } @@ -868,22 +742,20 @@ void calcspherescissor(const vec ¢er, float size, float &sx1, float &sy1, fl do { \ float nzc = (cz*cz + 1) / (cz dir drt) - cz, \ pz = (d##c)/(nzc*e.c - e.z); \ - if(pz > 0) \ - { \ + if(pz > 0) { \ + \ float c = (focaldist)*nzc, \ pc = pz*nzc; \ if(pc < e.c) low = c; \ else if(pc > e.c) high = c; \ } \ } while(0) - if(dx > 0) - { + if(dx > 0) { float cz = e.x/e.z, drt = sqrtf(dx)/size; CHECKPLANE(x, -, focaldist/aspect, sx1, sx2); CHECKPLANE(x, +, focaldist/aspect, sx1, sx2); } - if(dy > 0) - { + if(dy > 0) { float cz = e.y/e.z, drt = sqrtf(dy)/size; CHECKPLANE(y, -, focaldist, sy1, sy2); CHECKPLANE(y, +, focaldist, sy1, sy2); @@ -893,17 +765,13 @@ void calcspherescissor(const vec ¢er, float size, float &sx1, float &sy1, fl static int scissoring = 0; static GLint oldscissor[4]; -int pushscissor(float sx1, float sy1, float sx2, float sy2) -{ +int pushscissor(float sx1, float sy1, float sx2, float sy2) { scissoring = 0; - if(sx1 <= -1 && sy1 <= -1 && sx2 >= 1 && sy2 >= 1) return 0; - sx1 = max(sx1, -1.0f); sy1 = max(sy1, -1.0f); sx2 = min(sx2, 1.0f); sy2 = min(sy2, 1.0f); - GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); int sx = viewport[0] + int(floor((sx1+1)*0.5f*viewport[2])), @@ -911,9 +779,7 @@ int pushscissor(float sx1, float sy1, float sx2, float sy2) sw = viewport[0] + int(ceil((sx2+1)*0.5f*viewport[2])) - sx, sh = viewport[1] + int(ceil((sy2+1)*0.5f*viewport[3])) - sy; if(sw <= 0 || sh <= 0) return 0; - - if(glIsEnabled(GL_SCISSOR_TEST)) - { + if(glIsEnabled(GL_SCISSOR_TEST)) { glGetIntegerv(GL_SCISSOR_BOX, oldscissor); sw += sx; sh += sy; @@ -925,15 +791,12 @@ int pushscissor(float sx1, float sy1, float sx2, float sy2) scissoring = 2; } else scissoring = 1; - glScissor(sx, sy, sw, sh); if(scissoring<=1) glEnable(GL_SCISSOR_TEST); - return scissoring; } -void popscissor() -{ +void popscissor() { if(scissoring>1) glScissor(oldscissor[0], oldscissor[1], oldscissor[2], oldscissor[3]); else if(scissoring) glDisable(GL_SCISSOR_TEST); scissoring = 0; @@ -941,10 +804,8 @@ void popscissor() static GLuint screenquadvbo = 0; -static void setupscreenquad() -{ - if(!screenquadvbo) - { +static void setupscreenquad() { + if(!screenquadvbo) { glGenBuffers_(1, &screenquadvbo); gle::bindvbo(screenquadvbo); vec2 verts[4] = { vec2(1, -1), vec2(-1, -1), vec2(1, 1), vec2(-1, 1) }; @@ -953,13 +814,11 @@ static void setupscreenquad() } } -static void cleanupscreenquad() -{ +static void cleanupscreenquad() { if(screenquadvbo) { glDeleteBuffers_(1, &screenquadvbo); screenquadvbo = 0; } } -void screenquad() -{ +void screenquad() { setupscreenquad(); gle::bindvbo(screenquadvbo); gle::enablevertex(); @@ -971,38 +830,32 @@ void screenquad() static LocalShaderParam screentexcoord[2] = { LocalShaderParam("screentexcoord0"), LocalShaderParam("screentexcoord1") }; -static inline void setscreentexcoord(int i, float w, float h, float x = 0, float y = 0) -{ +static inline void setscreentexcoord(int i, float w, float h, float x = 0, float y = 0) { screentexcoord[i].setf(w*0.5f, h*0.5f, x + w*0.5f, y + fabs(h)*0.5f); } -void screenquad(float sw, float sh) -{ +void screenquad(float sw, float sh) { setscreentexcoord(0, sw, sh); screenquad(); } -void screenquadflipped(float sw, float sh) -{ +void screenquadflipped(float sw, float sh) { setscreentexcoord(0, sw, -sh); screenquad(); } -void screenquad(float sw, float sh, float sw2, float sh2) -{ +void screenquad(float sw, float sh, float sw2, float sh2) { setscreentexcoord(0, sw, sh); setscreentexcoord(1, sw2, sh2); screenquad(); } -void screenquadoffset(float x, float y, float w, float h) -{ +void screenquadoffset(float x, float y, float w, float h) { setscreentexcoord(0, w, h, x, y); screenquad(); } -void screenquadoffset(float x, float y, float w, float h, float x2, float y2, float w2, float h2) -{ +void screenquadoffset(float x, float y, float w, float h, float x2, float y2, float w2, float h2) { setscreentexcoord(0, w, h, x, y); setscreentexcoord(1, w2, h2, x2, y2); screenquad(); @@ -1019,15 +872,13 @@ void screenquadoffset(float x, float y, float w, float h, float x2, float y2, fl gle::end(); \ } -void hudquad(float x, float y, float w, float h, float tx, float ty, float tw, float th) -{ +void hudquad(float x, float y, float w, float h, float tx, float ty, float tw, float th) { HUDQUAD(x, y, x+w, y+h, tx, ty, tx+tw, ty+th); } bool renderedgame = false; -void rendergame(bool mainpass) -{ +void rendergame(bool mainpass) { game::rendergame(mainpass); if(!shadowmapping) renderedgame = true; } @@ -1037,23 +888,17 @@ int drawtex = 0; VAR(modelpreviewfov, 10, 20, 100); VAR(modelpreviewpitch, -90, -15, 90); -namespace modelpreview -{ +namespace modelpreview { physent *oldcamera; physent camera; - float oldaspect, oldfovy, oldfov; int oldfarplane; matrix4 oldprojmatrix; - - void start(int x, int y, int w, int h, bool background) - { + void start(int x, int y, int w, int h, bool background) { drawtex = DRAWTEX_MODELPREVIEW; - glViewport(x, y, w, h); glScissor(x, y, w, h); glEnable(GL_SCISSOR_TEST); - oldcamera = camera1; camera = *camera1; camera.reset(); @@ -1063,52 +908,39 @@ namespace modelpreview camera.pitch = modelpreviewpitch; camera.roll = 0; camera1 = &camera; - oldaspect = aspect; oldfovy = fovy; oldfov = curfov; oldfarplane = farplane; oldprojmatrix = projmatrix; - aspect = w/float(h); fovy = modelpreviewfov; curfov = 2*atan2(tan(fovy/2*RAD), 1/aspect)/RAD; farplane = 1024; - glClearColor(0, 0, 0, 1); - glClear((background ? GL_COLOR_BUFFER_BIT : 0) | GL_DEPTH_BUFFER_BIT); - projmatrix.perspective(fovy, aspect, nearplane, farplane); setcamprojmatrix(); - glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); } - - void end() - { + void end() { glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); - aspect = oldaspect; fovy = oldfovy; curfov = oldfov; farplane = oldfarplane; - camera1 = oldcamera; drawtex = 0; - glDisable(GL_SCISSOR_TEST); glViewport(0, 0, screenw, screenh); - projmatrix = oldprojmatrix; setcamprojmatrix(); } } -vec calcmodelpreviewpos(const vec &radius, float &yaw) -{ +vec calcmodelpreviewpos(const vec &radius, float &yaw) { yaw = fmod(lastmillis/10000.0f*360.0f, 360.0f); float dist = 1.15f*max(radius.magnitude2()/aspect, radius.magnitude())/sinf(fovy/2*RAD); return vec(0, dist, 0).rotate_around_x(camera1->pitch*RAD); @@ -1116,70 +948,47 @@ vec calcmodelpreviewpos(const vec &radius, float &yaw) bool deferdrawtextures = false; -void drawtextures() -{ +void drawtextures() { if(minimized) { deferdrawtextures = true; return; } deferdrawtextures = false; } int xtraverts, xtravertsva; -void gl_drawframe() -{ +void gl_drawframe() { if(deferdrawtextures) drawtextures(); - updatedynlights(); - int w = screenw, h = screenh; aspect = forceaspect ? forceaspect : w/float(h); fovy = 2*atan2(tan(curfov/2*RAD), aspect)/RAD; - farplane = worldsize*2; - projmatrix.perspective(fovy, aspect, nearplane, farplane); setcamprojmatrix(); - glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); - xtravertsva = xtraverts = glde = gbatches = 0; - visiblecubes(); - glClear(GL_DEPTH_BUFFER_BIT|(wireframe && editmode ? GL_COLOR_BUFFER_BIT : 0)); - if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - rendergeom(); - extern int outline; if(!wireframe && editmode && outline) renderoutline(); - renderdecals(true); - rendermapmodels(); rendergame(true); renderavatar(); - if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - rendermaterials(); renderalphageom(); - if(wireframe && editmode) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - renderparticles(true); - glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); - gl_drawhud(); - renderedgame = false; } -void gl_drawmainmenu() -{ +void gl_drawmainmenu() { xtravertsva = xtraverts = glde = gbatches = 0; renderbackground(NULL, NULL, NULL, NULL, true, true); gl_drawhud(); @@ -1194,14 +1003,12 @@ VARP(damagecompassmax, 1, 200, 1000); float damagedirs[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -void damagecompass(int n, const vec &loc) -{ +void damagecompass(int n, const vec &loc) { if(!usedamagecompass || minimized) return; vec delta(loc); delta.sub(camera1->o); float yaw = 0, pitch; - if(delta.magnitude() > 4) - { + if(delta.magnitude() > 4) { vectoyawpitch(delta, yaw, pitch); yaw -= camera1->yaw; } @@ -1212,23 +1019,18 @@ void damagecompass(int n, const vec &loc) if(damagedirs[dir]>1) damagedirs[dir] = 1; } -void drawdamagecompass(int w, int h) -{ +void drawdamagecompass(int w, int h) { hudnotextureshader->set(); - int dirs = 0; float size = damagecompasssize/100.0f*min(h, w)/2.0f; - loopi(8) if(damagedirs[i]>0) - { - if(!dirs) - { + loopi(8) if(damagedirs[i]>0) { + if(!dirs) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gle::colorf(1, 0, 0, damagecompassalpha/100.0f); gle::defvertex(); gle::begin(GL_TRIANGLES); } dirs++; - float logscale = 32, scale = log(1 + (logscale - 1)*damagedirs[i]) / log(logscale), offset = -size/2.0f-min(h, w)/4.0f; @@ -1238,11 +1040,9 @@ void drawdamagecompass(int w, int h) m.rotate_around_z(i*45*RAD); m.translate(0, offset, 0); m.scale(size*scale); - gle::attrib(m.transform(vec2(1, 1))); gle::attrib(m.transform(vec2(-1, 1))); gle::attrib(m.transform(vec2(0, 0))); - // fade in log space so short blips don't disappear too quickly scale -= float(curtime)/damagecompassfade; damagedirs[i] = scale > 0 ? (pow(logscale, scale) - 1) / (logscale - 1) : 0; @@ -1261,68 +1061,57 @@ VARP(crosshaircolors, 0, 1, 1); #define MAXCROSSHAIRS 4 static Texture *crosshairs[MAXCROSSHAIRS] = { NULL, NULL, NULL, NULL }; -void loadcrosshair(const char *name, int i) -{ +void loadcrosshair(const char *name, int i) { if(i < 0 || i >= MAXCROSSHAIRS) return; crosshairs[i] = name ? textureload(name, 3, true) : notexture; - if(crosshairs[i] == notexture) - { + if(crosshairs[i] == notexture) { name = game::defaultcrosshair(i); if(!name) name = "data/crosshair.png"; crosshairs[i] = textureload(name, 3, true); } } -void loadcrosshair_(const char *name, int *i) -{ +void loadcrosshair_(const char *name, int *i) { loadcrosshair(name, *i); } COMMANDN(loadcrosshair, loadcrosshair_, "si"); -ICOMMAND(getcrosshair, "i", (int *i), -{ +ICOMMAND(getcrosshair, "i", (int *i), { const char *name = ""; - if(*i >= 0 && *i < MAXCROSSHAIRS) - { + if(*i >= 0 && *i < MAXCROSSHAIRS) { name = crosshairs[*i] ? crosshairs[*i]->name : game::defaultcrosshair(*i); if(!name) name = "data/crosshair.png"; } result(name); }); -void writecrosshairs(stream *f) -{ +void writecrosshairs(stream *f) { loopi(MAXCROSSHAIRS) if(crosshairs[i] && crosshairs[i]!=notexture) f->printf("loadcrosshair %s %d\n", escapestring(crosshairs[i]->name), i); f->printf("\n"); } -void drawcrosshair(int w, int h) -{ +void drawcrosshair(int w, int h) { bool windowhit = g3d_windowhit(true, false); if(!windowhit && (hidehud || mainmenu)) return; //(hidehud || player->state==CS_SPECTATOR || player->state==CS_DEAD)) return; - vec color(1, 1, 1); float cx = 0.5f, cy = 0.5f, chsize; Texture *crosshair; - if(windowhit) - { + if(windowhit) { static Texture *cursor = NULL; if(!cursor) cursor = textureload("data/guicursor.png", 3, true); crosshair = cursor; chsize = cursorsize*w/900.0f; g3d_cursorpos(cx, cy); } - else - { + else { int index = game::selectcrosshair(color); if(index < 0) return; if(!crosshairfx) index = 0; if(!crosshairfx || !crosshaircolors) color = vec(1, 1, 1); crosshair = crosshairs[index]; - if(!crosshair) - { + if(!crosshair) { loadcrosshair(NULL, index); crosshair = crosshairs[index]; } @@ -1333,7 +1122,6 @@ void drawcrosshair(int w, int h) float x = cx*w - (windowhit ? 0 : chsize/2.0f); float y = cy*h - (windowhit ? 0 : chsize/2.0f); glBindTexture(GL_TEXTURE_2D, crosshair->id); - hudshader->set(); gle::color(color); hudquad(x, y, chsize, chsize); @@ -1346,55 +1134,36 @@ VAR(statrate, 1, 200, 1000); FVARP(conscale, 1e-3f, 0.33f, 1e3f); -void gl_drawhud() -{ +void gl_drawhud() { g3d_render(); - int w = screenw, h = screenh; if(forceaspect) w = int(ceil(h*forceaspect)); - - if(editmode && !hidehud && !mainmenu) - { + if(editmode && !hidehud && !mainmenu) { glEnable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - rendereditcursor(); - glDepthMask(GL_TRUE); glDisable(GL_DEPTH_TEST); } - gettextres(w, h); - hudmatrix.ortho(0, w, h, 0, -1, 1); resethudmatrix(); - gle::colorf(1, 1, 1); - glEnable(GL_BLEND); - - if(!mainmenu) - { + if(!mainmenu) { drawdamagecompass(w, h); } - hudshader->set(); - int conw = int(w/conscale), conh = int(h/conscale), abovehud = conh - FONTH, limitgui = abovehud; - if(!hidehud && !mainmenu) - { - if(!hidestats) - { + if(!hidehud && !mainmenu) { + if(!hidestats) { pushhudmatrix(); hudmatrix.scale(conscale, conscale, 1); flushhudmatrix(); - int roffset = 0; - if(showfps) - { + if(showfps) { static int lastfps = 0, prevfps[3] = { 0, 0, 0 }, curfps[3] = { 0, 0, 0 }; - if(totalmillis - lastfps >= statrate) - { + if(totalmillis - lastfps >= statrate) { memcpy(prevfps, curfps, sizeof(prevfps)); lastfps = totalmillis - (totalmillis%statrate); } @@ -1405,17 +1174,13 @@ void gl_drawhud() else draw_textf("fps %d", conw-5*FONTH, conh-FONTH*3/2, curfps[0]); roffset += FONTH; } - - if(editmode || showeditstats) - { + if(editmode || showeditstats) { static int laststats = 0, prevstats[8] = { 0, 0, 0, 0, 0, 0, 0 }, curstats[8] = { 0, 0, 0, 0, 0, 0, 0 }; - if(totalmillis - laststats >= statrate) - { + if(totalmillis - laststats >= statrate) { memcpy(prevstats, curstats, sizeof(prevstats)); laststats = totalmillis - (totalmillis%statrate); } - int nextstats[8] = - { + int nextstats[8] = { vtris*100/max(wtris, 1), vverts*100/max(wverts, 1), xtraverts/1024, @@ -1425,22 +1190,16 @@ void gl_drawhud() getnumqueries() }; loopi(8) if(prevstats[i]==curstats[i]) curstats[i] = nextstats[i]; - abovehud -= 2*FONTH; draw_textf("wtr:%dk(%d%%) wvt:%dk(%d%%) evt:%dk eva:%dk", FONTH/2, abovehud, wtris/1024, curstats[0], wverts/1024, curstats[1], curstats[2], curstats[3]); draw_textf("ond:%d va:%d gl:%d(%d) oq:%d lm:%d rp:%d", FONTH/2, abovehud+FONTH, allocnodes*8, allocva, curstats[4], curstats[5], curstats[6], lightmaps.length(), curstats[7]); limitgui = abovehud; } - - if(editmode) - { + if(editmode) { abovehud -= FONTH; draw_textf("cube %s%d%s", FONTH/2, abovehud, selchildcount<0 ? "1/" : "", abs(selchildcount), showmat && selchildmat > 0 ? getmaterialdesc(selchildmat, ": ") : ""); - - if(char *editinfo = execidentstr("edithud")) - { - if(editinfo[0]) - { + if(char *editinfo = execidentstr("edithud")) { + if(editinfo[0]) { int tw, th; text_bounds(editinfo, tw, th); th += FONTH-1; th -= th%FONTH; @@ -1450,10 +1209,8 @@ void gl_drawhud() DELETEA(editinfo); } } - else if(char *gameinfo = execidentstr("gamehud")) - { - if(gameinfo[0]) - { + else if(char *gameinfo = execidentstr("gamehud")) { + if(gameinfo[0]) { int tw, th; text_bounds(gameinfo, tw, th); th += FONTH-1; th -= th%FONTH; @@ -1462,30 +1219,21 @@ void gl_drawhud() } DELETEA(gameinfo); } - pophudmatrix(); } - - if(hidestats || (!editmode && !showeditstats)) - { + if(hidestats || (!editmode && !showeditstats)) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); game::gameplayhud(w, h); limitgui = abovehud = min(abovehud, int(conh*game::abovegameplayhud(w, h))); } - rendertexturepanel(w, h); } - glDisable(GL_BLEND); - g3d_limitscale((2*limitgui - conh) / float(conh)); g3d_render2d(); - glEnable(GL_BLEND); - hudmatrix.ortho(0, w, h, 0, -1, 1); resethudmatrix(); - pushhudmatrix(); hudmatrix.scale(conscale, conscale, 1); flushhudmatrix(); @@ -1493,16 +1241,12 @@ void gl_drawhud() extern int fullconsole; if(!hidehud || fullconsole) renderconsole(conw, conh, abovehud - FONTH/2); pophudmatrix(); - drawcrosshair(w, h); - glDisable(GL_BLEND); } -void cleanupgl() -{ +void cleanupgl() { cleanupscreenquad(); - gle::cleanup(); } diff --git a/src/engine/rendermodel.cpp b/src/engine/rendermodel.cpp index 9f2aba9..bc93caa 100644 --- a/src/engine/rendermodel.cpp +++ b/src/engine/rendermodel.cpp @@ -7,60 +7,52 @@ model *loadingmodel = NULL; #include "ragdoll.h" #include "animmodel.h" -#include "vertmodel.h" #include "skelmodel.h" static model *(__cdecl *modeltypes[NUMMODELTYPES])(const char *); -static int addmodeltype(int type, model *(__cdecl *loader)(const char *)) -{ +static int addmodeltype(int type, model *(__cdecl *loader)(const char *)) { modeltypes[type] = loader; return type; } #define MODELTYPE(modeltype, modelclass) \ -static model *__loadmodel__##modelclass(const char *filename) \ -{ \ +static model *__loadmodel__##modelclass(const char *filename) { \ + \ return new modelclass(filename); \ } \ UNUSED static int __dummy__##modelclass = addmodeltype((modeltype), __loadmodel__##modelclass); -#include "md3.h" #include "md5.h" #include "iqm.h" -MODELTYPE(MDL_MD3, md3); MODELTYPE(MDL_MD5, md5); MODELTYPE(MDL_IQM, iqm); #define checkmdl if(!loadingmodel) { conoutf(CON_ERROR, "not loading a model"); return; } -void mdlcullface(int *cullface) -{ +void mdlcullface(int *cullface) { checkmdl; loadingmodel->setcullface(*cullface!=0); } COMMAND(mdlcullface, "i"); -void mdlcollide(int *collide) -{ +void mdlcollide(int *collide) { checkmdl; loadingmodel->collide = *collide!=0; } COMMAND(mdlcollide, "i"); -void mdlellipsecollide(int *collide) -{ +void mdlellipsecollide(int *collide) { checkmdl; loadingmodel->ellipsecollide = *collide!=0; } COMMAND(mdlellipsecollide, "i"); -void mdlspec(int *percent) -{ +void mdlspec(int *percent) { checkmdl; float spec = 1.0f; if(*percent>0) spec = *percent/100.0f; @@ -70,8 +62,7 @@ void mdlspec(int *percent) COMMAND(mdlspec, "i"); -void mdlambient(int *percent) -{ +void mdlambient(int *percent) { checkmdl; float ambient = 0.3f; if(*percent>0) ambient = *percent/100.0f; @@ -81,56 +72,49 @@ void mdlambient(int *percent) COMMAND(mdlambient, "i"); -void mdlalphatest(float *cutoff) -{ +void mdlalphatest(float *cutoff) { checkmdl; loadingmodel->setalphatest(max(0.0f, min(1.0f, *cutoff))); } COMMAND(mdlalphatest, "f"); -void mdlalphablend(int *blend) -{ +void mdlalphablend(int *blend) { checkmdl; loadingmodel->setalphablend(*blend!=0); } COMMAND(mdlalphablend, "i"); -void mdlalphadepth(int *depth) -{ +void mdlalphadepth(int *depth) { checkmdl; loadingmodel->alphadepth = *depth!=0; } COMMAND(mdlalphadepth, "i"); -void mdldepthoffset(int *offset) -{ +void mdldepthoffset(int *offset) { checkmdl; loadingmodel->depthoffset = *offset!=0; } COMMAND(mdldepthoffset, "i"); -void mdlfullbright(float *fullbright) -{ +void mdlfullbright(float *fullbright) { checkmdl; loadingmodel->setfullbright(*fullbright); } COMMAND(mdlfullbright, "f"); -void mdlshader(char *shader) -{ +void mdlshader(char *shader) { checkmdl; loadingmodel->setshader(lookupshaderbyname(shader)); } COMMAND(mdlshader, "s"); -void mdlspin(float *yaw, float *pitch) -{ +void mdlspin(float *yaw, float *pitch) { checkmdl; loadingmodel->spinyaw = *yaw; loadingmodel->spinpitch = *pitch; @@ -138,8 +122,7 @@ void mdlspin(float *yaw, float *pitch) COMMAND(mdlspin, "ff"); -void mdlscale(int *percent) -{ +void mdlscale(int *percent) { checkmdl; float scale = 1.0f; if(*percent>0) scale = *percent/100.0f; @@ -148,40 +131,35 @@ void mdlscale(int *percent) COMMAND(mdlscale, "i"); -void mdltrans(float *x, float *y, float *z) -{ +void mdltrans(float *x, float *y, float *z) { checkmdl; loadingmodel->translate = vec(*x, *y, *z); } COMMAND(mdltrans, "fff"); -void mdlyaw(float *angle) -{ +void mdlyaw(float *angle) { checkmdl; loadingmodel->offsetyaw = *angle; } COMMAND(mdlyaw, "f"); -void mdlpitch(float *angle) -{ +void mdlpitch(float *angle) { checkmdl; loadingmodel->offsetpitch = *angle; } COMMAND(mdlpitch, "f"); -void mdlshadow(int *shadow) -{ +void mdlshadow(int *shadow) { checkmdl; loadingmodel->shadow = *shadow!=0; } COMMAND(mdlshadow, "i"); -void mdlbb(float *rad, float *h, float *eyeheight) -{ +void mdlbb(float *rad, float *h, float *eyeheight) { checkmdl; loadingmodel->collidexyradius = *rad; loadingmodel->collideheight = *h; @@ -190,16 +168,14 @@ void mdlbb(float *rad, float *h, float *eyeheight) COMMAND(mdlbb, "fff"); -void mdlextendbb(float *x, float *y, float *z) -{ +void mdlextendbb(float *x, float *y, float *z) { checkmdl; loadingmodel->bbextend = vec(*x, *y, *z); } COMMAND(mdlextendbb, "fff"); -void mdlname() -{ +void mdlname() { checkmdl; result(loadingmodel->name); } @@ -219,8 +195,7 @@ COMMAND(mdlname, ""); if(ragdoll->loaded) return; -void rdvert(float *x, float *y, float *z, float *radius) -{ +void rdvert(float *x, float *y, float *z, float *radius) { checkragdoll; ragdollskel::vert &v = ragdoll->verts.add(); v.pos = vec(*x, *y, *z); @@ -228,15 +203,13 @@ void rdvert(float *x, float *y, float *z, float *radius) } COMMAND(rdvert, "ffff"); -void rdeye(int *v) -{ +void rdeye(int *v) { checkragdoll; ragdoll->eye = *v; } COMMAND(rdeye, "i"); -void rdtri(int *v1, int *v2, int *v3) -{ +void rdtri(int *v1, int *v2, int *v3) { checkragdoll; ragdollskel::tri &t = ragdoll->tris.add(); t.vert[0] = *v1; @@ -245,8 +218,7 @@ void rdtri(int *v1, int *v2, int *v3) } COMMAND(rdtri, "iii"); -void rdjoint(int *n, int *t, int *v1, int *v2, int *v3) -{ +void rdjoint(int *n, int *t, int *v1, int *v2, int *v3) { checkragdoll; if(*n < 0 || *n >= skel->numbones) return; ragdollskel::joint &j = ragdoll->joints.add(); @@ -258,8 +230,7 @@ void rdjoint(int *n, int *t, int *v1, int *v2, int *v3) } COMMAND(rdjoint, "iibbb"); -void rdlimitdist(int *v1, int *v2, float *mindist, float *maxdist) -{ +void rdlimitdist(int *v1, int *v2, float *mindist, float *maxdist) { checkragdoll; ragdollskel::distlimit &d = ragdoll->distlimits.add(); d.vert[0] = *v1; @@ -269,8 +240,7 @@ void rdlimitdist(int *v1, int *v2, float *mindist, float *maxdist) } COMMAND(rdlimitdist, "iiff"); -void rdlimitrot(int *t1, int *t2, float *maxangle, float *qx, float *qy, float *qz, float *qw) -{ +void rdlimitrot(int *t1, int *t2, float *maxangle, float *qx, float *qy, float *qz, float *qw) { checkragdoll; ragdollskel::rotlimit &r = ragdoll->rotlimits.add(); r.tri[0] = *t1; @@ -280,8 +250,7 @@ void rdlimitrot(int *t1, int *t2, float *maxangle, float *qx, float *qy, float * } COMMAND(rdlimitrot, "iifffff"); -void rdanimjoints(int *on) -{ +void rdanimjoints(int *on) { checkragdoll; ragdoll->animjoints = *on!=0; } @@ -291,20 +260,17 @@ COMMAND(rdanimjoints, "i"); vector<mapmodelinfo> mapmodels; -void mmodel(char *name) -{ +void mmodel(char *name) { mapmodelinfo &mmi = mapmodels.add(); copystring(mmi.name, name); mmi.m = NULL; } -void mapmodelcompat(int *rad, int *h, int *tex, char *name, char *shadow) -{ +void mapmodelcompat(int *rad, int *h, int *tex, char *name, char *shadow) { mmodel(name); } -void mapmodelreset(int *n) -{ +void mapmodelreset(int *n) { if(!(identflags&IDF_OVERRIDDEN) && !game::allowedittoggle()) return; mapmodels.shrink(clamp(*n, 0, mapmodels.length())); } @@ -325,21 +291,17 @@ ICOMMAND(mapmodelfind, "s", (char *name), { int found = -1; loopv(mapmodels) if( hashnameset<model *> models; vector<const char *> preloadmodels; -void preloadmodel(const char *name) -{ +void preloadmodel(const char *name) { if(!name || !name[0] || models.access(name)) return; preloadmodels.add(newstring(name)); } -void flushpreloadedmodels(bool msg) -{ - loopv(preloadmodels) - { +void flushpreloadedmodels(bool msg) { + loopv(preloadmodels) { loadprogress = float(i+1)/preloadmodels.length(); model *m = loadmodel(preloadmodels[i], -1, msg); if(!m) { if(msg) conoutf(CON_WARN, "could not load model: %s", preloadmodels[i]); } - else - { + else { m->preloadmeshes(); } } @@ -347,25 +309,20 @@ void flushpreloadedmodels(bool msg) loadprogress = 0; } -void preloadusedmapmodels(bool msg, bool bih) -{ +void preloadusedmapmodels(bool msg, bool bih) { vector<extentity *> &ents = entities::getents(); vector<int> mapmodels; - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; if(e.type==ET_MAPMODEL && e.attr2 >= 0 && mapmodels.find(e.attr2) < 0) mapmodels.add(e.attr2); } - - loopv(mapmodels) - { + loopv(mapmodels) { loadprogress = float(i+1)/mapmodels.length(); int mmindex = mapmodels[i]; mapmodelinfo *mmi = getmminfo(mmindex); if(!mmi) { if(msg) conoutf(CON_WARN, "could not find map model: %d", mmindex); } else if(mmi->name[0] && !loadmodel(NULL, mmindex, msg)) { if(msg) conoutf(CON_WARN, "could not load model: %s", mmi->name); } - else if(mmi->m) - { + else if(mmi->m) { if(bih) mmi->m->preloadBIH(); mmi->m->preloadmeshes(); } @@ -373,15 +330,12 @@ void preloadusedmapmodels(bool msg, bool bih) loadprogress = 0; } -bool modelloaded(const char *name) -{ +bool modelloaded(const char *name) { return models.find(name, NULL) != NULL; } -model *loadmodel(const char *name, int i, bool msg) -{ - if(!name) - { +model *loadmodel(const char *name, int i, bool msg) { + if(!name) { if(!mapmodels.inrange(i)) return NULL; mapmodelinfo &mmi = mapmodels[i]; if(mmi.m) return mmi.m; @@ -390,16 +344,13 @@ model *loadmodel(const char *name, int i, bool msg) model **mm = models.access(name); model *m; if(mm) m = *mm; - else - { + else { if(!name[0] || loadingmodel || lightmapping > 1) return NULL; - if(msg) - { + if(msg) { defformatstring(filename, "packages/models/%s", name); renderprogress(loadprogress, filename); } - loopi(NUMMODELTYPES) - { + loopi(NUMMODELTYPES) { m = modeltypes[i](name); if(!m) continue; loadingmodel = m; @@ -415,24 +366,20 @@ model *loadmodel(const char *name, int i, bool msg) return m; } -void preloadmodelshaders(bool force) -{ +void preloadmodelshaders() { if(initing) return; - enumerate(models, model *, m, m->preloadshaders(force)); + enumerate(models, model *, m, m->preloadshaders()); } -void clear_mdls() -{ +void clear_mdls() { enumerate(models, model *, m, delete m); } -void cleanupmodels() -{ +void cleanupmodels() { enumerate(models, model *, m, m->cleanup()); } -void clearmodel(char *name) -{ +void clearmodel(char *name) { model **m = models.access(name); if(!m) { conoutf(CON_WARN, "model %s is not loaded", name); return; } loopv(mapmodels) if(mapmodels[i].m==*m) mapmodels[i].m = NULL; @@ -444,16 +391,14 @@ void clearmodel(char *name) COMMAND(clearmodel, "s"); -bool modeloccluded(const vec ¢er, float radius) -{ +bool modeloccluded(const vec ¢er, float radius) { ivec bbmin(vec(center).sub(radius)), bbmax(ivec(center).add(radius+1)); return bboccluded(bbmin, bbmax); } VAR(showboundingbox, 0, 0, 2); -void render2dbox(vec &o, float x, float y, float z) -{ +void render2dbox(vec &o, float x, float y, float z) { gle::begin(GL_LINE_LOOP); gle::attribf(o.x, o.y, o.z); gle::attribf(o.x, o.y, o.z+z); @@ -462,8 +407,7 @@ void render2dbox(vec &o, float x, float y, float z) xtraverts += gle::end(); } -void render3dbox(vec &o, float tofloor, float toceil, float xradius, float yradius) -{ +void render3dbox(vec &o, float tofloor, float toceil, float xradius, float yradius) { if(yradius<=0) yradius = xradius; vec c = o; c.sub(vec(xradius, yradius, tofloor)); @@ -478,21 +422,18 @@ void render3dbox(vec &o, float tofloor, float toceil, float xradius, float yradi render2dbox(c, 0, -ysz, h); } -void renderellipse(vec &o, float xradius, float yradius, float yaw) -{ +void renderellipse(vec &o, float xradius, float yradius, float yaw) { gle::colorf(0.5f, 0.5f, 0.5f); gle::defvertex(); gle::begin(GL_LINE_LOOP); - loopi(15) - { + loopi(15) { const vec2 &sc = sincos360[i*(360/15)]; gle::attrib(vec(xradius*sc.x, yradius*sc.y, 0).rotate_around_z((yaw+90)*RAD).add(o)); } xtraverts += gle::end(); } -struct batchedmodel -{ +struct batchedmodel { vec pos, color, dir; int anim; float yaw, pitch, transparent; @@ -501,8 +442,7 @@ struct batchedmodel int attached; occludequery *query; }; -struct modelbatch -{ +struct modelbatch { model *m; int flags; vector<batchedmodel> batched; @@ -512,20 +452,16 @@ static vector<modelattach> modelattached; static int numbatches = -1; static occludequery *modelquery = NULL; -void startmodelbatches() -{ +void startmodelbatches() { numbatches = 0; modelattached.setsize(0); } -modelbatch &addbatchedmodel(model *m) -{ +modelbatch &addbatchedmodel(model *m) { modelbatch *b = NULL; if(m->batch>=0 && m->batch<numbatches && batches[m->batch]->m==m) b = batches[m->batch]; - else - { - if(numbatches<batches.length()) - { + else { + if(numbatches<batches.length()) { b = batches[numbatches]; b->batched.setsize(0); } @@ -537,75 +473,59 @@ modelbatch &addbatchedmodel(model *m) return *b; } -void renderbatchedmodel(model *m, batchedmodel &b) -{ +void renderbatchedmodel(model *m, batchedmodel &b) { modelattach *a = NULL; if(b.attached>=0) a = &modelattached[b.attached]; - int anim = b.anim; - if(shadowmapping) - { + if(shadowmapping) { anim |= ANIM_NOSKIN; GLOBALPARAMF(shadowintensity, b.transparent); } - else - { + else { if(b.flags&MDL_FULLBRIGHT) anim |= ANIM_FULLBRIGHT; if(b.flags&MDL_GHOST) anim |= ANIM_GHOST; } - m->render(anim, b.basetime, b.basetime2, b.pos, b.yaw, b.pitch, b.d, a, b.color, b.dir, b.transparent); } -struct transparentmodel -{ +struct transparentmodel { model *m; batchedmodel *batched; float dist; }; -static inline bool sorttransparentmodels(const transparentmodel &x, const transparentmodel &y) -{ +static inline bool sorttransparentmodels(const transparentmodel &x, const transparentmodel &y) { return x.dist < y.dist; } -void endmodelbatches() -{ +void endmodelbatches() { vector<transparentmodel> transparent; - loopi(numbatches) - { + loopi(numbatches) { modelbatch &b = *batches[i]; if(b.batched.empty()) continue; - bool rendered = false; occludequery *query = NULL; - if(b.flags&MDL_GHOST) - { - loopvj(b.batched) - { + if(b.flags&MDL_GHOST) { + loopvj(b.batched) { batchedmodel &bm = b.batched[j]; if((bm.flags&(MDL_CULL_VFC|MDL_GHOST))!=MDL_GHOST || bm.query) continue; if(!rendered) { b.m->startrender(); rendered = true; } renderbatchedmodel(b.m, bm); } - if(rendered) - { + if(rendered) { b.m->endrender(); rendered = false; } } - loopvj(b.batched) - { + loopvj(b.batched) { batchedmodel &bm = b.batched[j]; if(bm.flags&(MDL_CULL_VFC|MDL_GHOST)) continue; - if(bm.query!=query) - { + if(bm.query!=query) { if(query) endquery(query); query = bm.query; if(query) startquery(query); } - if(bm.transparent < 1 && (!query || query->owner==bm.d) && !shadowmapping) - { + if(bm.transparent < 1 && (!query || query->owner==bm.d) && !shadowmapping) { transparentmodel &tm = transparent.add(); tm.m = b.m; tm.batched = &bm; @@ -618,21 +538,17 @@ void endmodelbatches() if(query) endquery(query); if(rendered) b.m->endrender(); } - if(transparent.length()) - { + if(transparent.length()) { transparent.sort(sorttransparentmodels); model *lastmodel = NULL; occludequery *query = NULL; - loopv(transparent) - { + loopv(transparent) { transparentmodel &tm = transparent[i]; - if(lastmodel!=tm.m) - { + if(lastmodel!=tm.m) { if(lastmodel) lastmodel->endrender(); (lastmodel = tm.m)->startrender(); } - if(query!=tm.batched->query) - { + if(query!=tm.batched->query) { if(query) endquery(query); query = tm.batched->query; if(query) startquery(query); @@ -645,35 +561,29 @@ void endmodelbatches() numbatches = -1; } -void startmodelquery(occludequery *query) -{ +void startmodelquery(occludequery *query) { modelquery = query; } -void endmodelquery() -{ +void endmodelquery() { int querybatches = 0; - loopi(numbatches) - { + loopi(numbatches) { modelbatch &b = *batches[i]; if(b.batched.empty() || b.batched.last().query!=modelquery) continue; querybatches++; } - if(querybatches<=1) - { + if(querybatches<=1) { if(!querybatches) modelquery->fragments = 0; modelquery = NULL; return; } int minattached = modelattached.length(); startquery(modelquery); - loopi(numbatches) - { + loopi(numbatches) { modelbatch &b = *batches[i]; if(b.batched.empty() || b.batched.last().query!=modelquery) continue; b.m->startrender(); - do - { + do { batchedmodel &bm = b.batched.pop(); if(bm.attached>=0) minattached = min(minattached, bm.attached); renderbatchedmodel(b.m, bm); @@ -688,17 +598,14 @@ void endmodelquery() VAR(maxmodelradiusdistance, 10, 200, 1000); -static inline void enablecullmodelquery() -{ +static inline void enablecullmodelquery() { startbb(); } -static inline void rendercullmodelquery(model *m, dynent *d, const vec ¢er, float radius) -{ +static inline void rendercullmodelquery(model *m, dynent *d, const vec ¢er, float radius) { if(fabs(camera1->o.x-center.x) < radius+1 && fabs(camera1->o.y-center.y) < radius+1 && - fabs(camera1->o.z-center.z) < radius+1) - { + fabs(camera1->o.z-center.z) < radius+1) { d->query = NULL; return; } @@ -710,95 +617,73 @@ static inline void rendercullmodelquery(model *m, dynent *d, const vec ¢er, endquery(d->query); } -static inline void disablecullmodelquery() -{ +static inline void disablecullmodelquery() { endbb(); } -static inline int cullmodel(model *m, const vec ¢er, float radius, int flags, dynent *d = NULL, bool shadow = false) -{ +static inline int cullmodel(model *m, const vec ¢er, float radius, int flags, dynent *d = NULL, bool shadow = false) { if(flags&MDL_CULL_DIST && center.dist(camera1->o)/radius>maxmodelradiusdistance) return MDL_CULL_DIST; - if(flags&MDL_CULL_VFC) - { + if(flags&MDL_CULL_VFC) { if(shadowmapping && !isshadowmapcaster(center, radius)) return MDL_CULL_VFC; } - if(shadowmapping) - { - if(d) - { + if(shadowmapping) { + if(d) { if(flags&MDL_CULL_OCCLUDED && d->occluded>=OCCLUDE_PARENT) return MDL_CULL_OCCLUDED; if(flags&MDL_CULL_QUERY && d->occluded+1>=OCCLUDE_BB && d->query && d->query->owner==d && checkquery(d->query)) return MDL_CULL_QUERY; } if(!addshadowmapcaster(center, radius, radius)) return MDL_CULL_VFC; } - else if(flags&MDL_CULL_OCCLUDED && modeloccluded(center, radius)) - { + else if(flags&MDL_CULL_OCCLUDED && modeloccluded(center, radius)) { if(d) d->occluded = OCCLUDE_PARENT; return MDL_CULL_OCCLUDED; } - else if(flags&MDL_CULL_QUERY && d->query && d->query->owner==d && checkquery(d->query)) - { + else if(flags&MDL_CULL_QUERY && d->query && d->query->owner==d && checkquery(d->query)) { if(d->occluded<OCCLUDE_BB) d->occluded++; return MDL_CULL_QUERY; } return 0; } -void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, float yaw, float pitch, int flags, dynent *d, modelattach *a, int basetime, int basetime2, float trans) -{ +void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, float yaw, float pitch, int flags, dynent *d, modelattach *a, int basetime, int basetime2, float trans) { if(shadowmapping && !(flags&(MDL_SHADOW|MDL_DYNSHADOW))) return; model *m = loadmodel(mdl); if(!m) return; vec center(0, 0, 0), bbradius(0, 0, 0); float radius = 0; bool shadow = !shadowmap && (flags&(MDL_SHADOW|MDL_DYNSHADOW)); - - if(flags&(MDL_CULL_VFC|MDL_CULL_DIST|MDL_CULL_OCCLUDED|MDL_CULL_QUERY|MDL_SHADOW|MDL_DYNSHADOW)) - { - if(flags&MDL_CULL_QUERY) - { + if(flags&(MDL_CULL_VFC|MDL_CULL_DIST|MDL_CULL_OCCLUDED|MDL_CULL_QUERY|MDL_SHADOW|MDL_DYNSHADOW)) { + if(flags&MDL_CULL_QUERY) { if(!oqfrags || !oqdynent || !d) flags &= ~MDL_CULL_QUERY; } - m->boundbox(center, bbradius); radius = bbradius.magnitude(); - if(d && d->ragdoll) - { + if(d && d->ragdoll) { radius = max(radius, d->ragdoll->radius); center = d->ragdoll->center; } - else - { + else { center.rotate_around_z(yaw*RAD); center.add(o); } - int culled = cullmodel(m, center, radius, flags, d, shadow); - if(culled) - { - if(culled&(MDL_CULL_OCCLUDED|MDL_CULL_QUERY) && flags&MDL_CULL_QUERY) - { + if(culled) { + if(culled&(MDL_CULL_OCCLUDED|MDL_CULL_QUERY) && flags&MDL_CULL_QUERY) { enablecullmodelquery(); rendercullmodelquery(m, d, center, radius); disablecullmodelquery(); } return; } - if(shadowmapping) flags &= ~MDL_CULL_QUERY; } - if(flags&MDL_NORENDER) anim |= ANIM_NORENDER; - else if(showboundingbox && !shadowmapping && editmode) - { + else if(showboundingbox && !shadowmapping && editmode) { notextureshader->set(); - if(d && showboundingbox==1) - { + if(d && showboundingbox==1) { render3dbox(d->o, d->eyeheight, d->aboveeye, d->radius); renderellipse(d->o, d->xradius, d->yradius, d->yaw); } - else - { + else { vec center, radius; if(showboundingbox==1) m->collisionbox(center, radius); else m->boundbox(center, radius); @@ -807,19 +692,14 @@ void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, fl render3dbox(center, radius.z, radius.z, radius.x, radius.y); } } - vec lightcolor(1, 1, 1), lightdir(0, 0, 1); - if(!shadowmapping) - { + if(!shadowmapping) { vec pos = o; - if(d) - { + if(d) { d->occluded = OCCLUDE_NOTHING; if(!light) light = &d->light; - if(flags&MDL_LIGHT && light->millis!=lastmillis) - { - if(d->ragdoll) - { + if(flags&MDL_LIGHT && light->millis!=lastmillis) { + if(d->ragdoll) { pos = d->ragdoll->center; pos.z += radius/2; } @@ -830,15 +710,12 @@ void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, fl light->millis = lastmillis; } } - else if(flags&MDL_LIGHT) - { - if(!light) - { + else if(flags&MDL_LIGHT) { + if(!light) { lightreaching(pos, lightcolor, lightdir, (flags&MDL_LIGHT_FAST)!=0); dynlightreaching(pos, lightcolor, lightdir, (flags&MDL_HUD)!=0); } - else if(light->millis!=lastmillis) - { + else if(light->millis!=lastmillis) { lightreaching(pos, light->color, light->dir, (flags&MDL_LIGHT_FAST)!=0); dynlightreaching(pos, light->color, light->dir, (flags&MDL_HUD)!=0); light->millis = lastmillis; @@ -847,15 +724,11 @@ void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, fl if(light) { lightcolor = light->color; lightdir = light->dir; } if(flags&MDL_DYNLIGHT) dynlightreaching(pos, lightcolor, lightdir, (flags&MDL_HUD)!=0); } - - if(a) for(int i = 0; a[i].tag; i++) - { + if(a) for(int i = 0; a[i].tag; i++) { if(a[i].name) a[i].m = loadmodel(a[i].name); //if(a[i].m && a[i].m->type()!=m->type()) a[i].m = NULL; } - - if(numbatches>=0) - { + if(numbatches>=0) { modelbatch &mb = addbatchedmodel(m); batchedmodel &b = mb.batched.add(); b.query = modelquery; @@ -869,8 +742,7 @@ void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, fl b.basetime2 = basetime2; b.transparent = trans; b.flags = flags & ~(MDL_CULL_VFC | MDL_CULL_DIST | MDL_CULL_OCCLUDED); - if(!shadow) - { + if(!shadow) { b.flags &= ~(MDL_SHADOW|MDL_DYNSHADOW); if(flags&MDL_CULL_VFC) b.flags |= MDL_CULL_VFC; } @@ -881,52 +753,38 @@ void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, fl if(flags&MDL_CULL_QUERY) d->query = b.query = newquery(d); return; } - m->startrender(); - - if(shadowmapping) - { + if(shadowmapping) { anim |= ANIM_NOSKIN; GLOBALPARAMF(shadowintensity, trans); } - else - { + else { if(flags&MDL_FULLBRIGHT) anim |= ANIM_FULLBRIGHT; if(flags&MDL_GHOST) anim |= ANIM_GHOST; } - - if(flags&MDL_CULL_QUERY) - { + if(flags&MDL_CULL_QUERY) { d->query = newquery(d); if(d->query) startquery(d->query); } - m->render(anim, basetime, basetime2, o, yaw, pitch, d, a, lightcolor, lightdir, trans); - if(flags&MDL_CULL_QUERY && d->query) endquery(d->query); - m->endrender(); } -void abovemodel(vec &o, const char *mdl) -{ +void abovemodel(vec &o, const char *mdl) { model *m = loadmodel(mdl); if(!m) return; o.z += m->above(); } -bool matchanim(const char *name, const char *pattern) -{ - for(;; pattern++) - { +bool matchanim(const char *name, const char *pattern) { + for(;; pattern++) { const char *s = name; char c; - for(;; pattern++) - { + for(;; pattern++) { c = *pattern; if(!c || c=='|') break; - else if(c=='*') - { + else if(c=='*') { if(!*s || iscubespace(*s)) break; do s++; while(*s && !iscubespace(*s)); } @@ -940,19 +798,16 @@ bool matchanim(const char *name, const char *pattern) return false; } -void findanims(const char *pattern, vector<int> &anims) -{ +void findanims(const char *pattern, vector<int> &anims) { loopi(sizeof(animnames)/sizeof(animnames[0])) if(matchanim(animnames[i], pattern)) anims.add(i); } -ICOMMAND(findanims, "s", (char *name), -{ +ICOMMAND(findanims, "s", (char *name), { vector<int> anims; findanims(name, anims); vector<char> buf; string num; - loopv(anims) - { + loopv(anims) { formatstring(num, "%d", anims[i]); if(i > 0) buf.add(' '); buf.put(num, strlen(num)); @@ -961,21 +816,19 @@ ICOMMAND(findanims, "s", (char *name), result(buf.getbuf()); }); -void loadskin(const char *dir, const char *altdir, Texture *&skin, Texture *&masks) // model skin sharing -{ +void loadskin(const char *dir, const char *altdir, Texture *&skin, Texture *&masks) { // model skin sharing { #define ifnoload(tex, path) if((tex = textureload(path, 0, true, false))==notexture) #define tryload(tex, prefix, cmd, name) \ - ifnoload(tex, makerelpath(mdir, name ".jpg", prefix, cmd)) \ - { \ - ifnoload(tex, makerelpath(mdir, name ".png", prefix, cmd)) \ - { \ - ifnoload(tex, makerelpath(maltdir, name ".jpg", prefix, cmd)) \ - { \ + ifnoload(tex, makerelpath(mdir, name ".jpg", prefix, cmd)) { \ + \ + ifnoload(tex, makerelpath(mdir, name ".png", prefix, cmd)) { \ + \ + ifnoload(tex, makerelpath(maltdir, name ".jpg", prefix, cmd)) { \ + \ ifnoload(tex, makerelpath(maltdir, name ".png", prefix, cmd)) return; \ } \ } \ } - defformatstring(mdir, "packages/models/%s", dir); defformatstring(maltdir, "packages/models/%s", altdir); masks = notexture; @@ -989,22 +842,18 @@ VAR(animoverride, -1, 0, NUMANIMS-1); VAR(testanims, 0, 0, 1); VAR(testpitch, -90, 0, 90); -void renderclient(dynent *d, const char *mdlname, modelattach *attachments, int hold, int attack, int attackdelay, int lastaction, int lastpain, float fade, bool ragdoll) -{ +void renderclient(dynent *d, const char *mdlname, modelattach *attachments, int hold, int attack, int attackdelay, int lastaction, int lastpain, float fade, bool ragdoll) { int anim = hold ? hold : ANIM_IDLE|ANIM_LOOP; float yaw = testanims && d==player ? 0 : d->yaw+90, pitch = testpitch && d==player ? testpitch : d->pitch; vec o = d->feetpos(); int basetime = 0; if(animoverride) anim = (animoverride<0 ? ANIM_ALL : animoverride)|ANIM_LOOP; - else if(d->state==CS_DEAD) - { + else if(d->state==CS_DEAD) { anim = ANIM_DYING|ANIM_NOPITCH; basetime = lastpain; - if(ragdoll) - { - if(!d->ragdoll || d->ragdoll->millis < basetime) - { + if(ragdoll) { + if(!d->ragdoll || d->ragdoll->millis < basetime) { DELETEP(d->ragdoll); anim |= ANIM_RAGDOLL; } @@ -1013,32 +862,25 @@ void renderclient(dynent *d, const char *mdlname, modelattach *attachments, int } else if(d->state==CS_EDITING || d->state==CS_SPECTATOR) anim = ANIM_EDIT|ANIM_LOOP; else if(d->state==CS_LAGGED) anim = ANIM_LAG|ANIM_LOOP; - else - { - if(lastmillis-lastpain < 300) - { + else { + if(lastmillis-lastpain < 300) { anim = ANIM_PAIN; basetime = lastpain; } - else if(lastpain < lastaction && (attack < 0 || (d->type != ENT_AI && lastmillis-lastaction < attackdelay))) - { + else if(lastpain < lastaction && (attack < 0 || (d->type != ENT_AI && lastmillis-lastaction < attackdelay))) { anim = attack < 0 ? -attack : attack; basetime = lastaction; } - if(d->inwater && d->physstate<=PHYS_FALL) anim |= (((game::allowmove(d) && (d->move || d->strafe)) || d->vel.z+d->falling.z>0 ? ANIM_SWIM : ANIM_SINK)|ANIM_LOOP)<<ANIM_SECONDARY; else if(d->timeinair>100) anim |= (ANIM_JUMP|ANIM_END)<<ANIM_SECONDARY; - else if(game::allowmove(d) && (d->move || d->strafe)) - { + else if(game::allowmove(d) && (d->move || d->strafe)) { if(d->move>0) anim |= (ANIM_FORWARD|ANIM_LOOP)<<ANIM_SECONDARY; - else if(d->strafe) - { + else if(d->strafe) { if(d->move<0) anim |= ((d->strafe>0 ? ANIM_RIGHT : ANIM_LEFT)|ANIM_REVERSE|ANIM_LOOP)<<ANIM_SECONDARY; else anim |= ((d->strafe>0 ? ANIM_LEFT : ANIM_RIGHT)|ANIM_LOOP)<<ANIM_SECONDARY; } else if(d->move<0) anim |= (ANIM_BACKWARD|ANIM_LOOP)<<ANIM_SECONDARY; } - if((anim&ANIM_INDEX)==ANIM_IDLE && (anim>>ANIM_SECONDARY)&ANIM_INDEX) anim >>= ANIM_SECONDARY; } if(d->ragdoll && (!ragdoll || (anim&ANIM_INDEX)!=ANIM_DYING)) DELETEP(d->ragdoll); @@ -1053,8 +895,7 @@ void renderclient(dynent *d, const char *mdlname, modelattach *attachments, int rendermodel(NULL, mdlname, anim, o, yaw, pitch, flags, d, attachments, basetime, 0, fade); } -void setbbfrommodel(dynent *d, const char *mdl) -{ +void setbbfrommodel(dynent *d, const char *mdl) { model *m = loadmodel(mdl); if(!m) return; vec center, radius; @@ -1066,8 +907,7 @@ void setbbfrommodel(dynent *d, const char *mdl) d->radius = d->collidetype==COLLIDE_OBB ? sqrtf(d->xradius*d->xradius + d->yradius*d->yradius) : max(d->xradius, d->yradius); d->eyeheight = (center.z-radius.z) + radius.z*2*m->eyeheight; d->aboveeye = radius.z*2*(1.0f-m->eyeheight); - if (d->aboveeye + d->eyeheight <= 0.5f) - { + if (d->aboveeye + d->eyeheight <= 0.5f) { float zrad = (0.5f - (d->aboveeye + d->eyeheight)) / 2; d->aboveeye += zrad; d->eyeheight += zrad; diff --git a/src/engine/renderparticles.cpp b/src/engine/renderparticles.cpp index 392e943..dbdf855 100644 --- a/src/engine/renderparticles.cpp +++ b/src/engine/renderparticles.cpp @@ -11,8 +11,7 @@ VARP(emitmillis, 1, 17, 1000); static int lastemitframe = 0, emitoffset = 0; static bool canemit = false, regenemitters = false, canstep = false; -static bool canemitparticles() -{ +static bool canemitparticles() { return canemit || emitoffset; } @@ -21,29 +20,23 @@ VAR(cullparticles, 0, 1, 1); VAR(replayparticles, 0, 1, 1); VARN(seedparticles, seedmillis, 0, 3000, 10000); -struct particleemitter -{ +struct particleemitter { extentity *ent; vec bbmin, bbmax; vec center; float radius; ivec cullmin, cullmax; int maxfade, lastemit, lastcull; - particleemitter(extentity *ent) - : ent(ent), bbmin(ent->o), bbmax(ent->o), maxfade(-1), lastemit(0), lastcull(0) - {} - - void finalize() - { + : ent(ent), bbmin(ent->o), bbmax(ent->o), maxfade(-1), lastemit(0), lastcull(0) { + } + void finalize() { center = vec(bbmin).add(bbmax).mul(0.5f); radius = bbmin.dist(bbmax)/2; cullmin = ivec(int(floor(bbmin.x)), int(floor(bbmin.y)), int(floor(bbmin.z))); cullmax = ivec(int(ceil(bbmax.x)), int(ceil(bbmax.y)), int(ceil(bbmax.z))); } - - void extendbb(const vec &o, float size = 0) - { + void extendbb(const vec &o, float size = 0) { bbmin.x = min(bbmin.x, o.x - size); bbmin.y = min(bbmin.y, o.y - size); bbmin.z = min(bbmin.z, o.z - size); @@ -51,9 +44,7 @@ struct particleemitter bbmax.y = max(bbmax.y, o.y + size); bbmax.z = max(bbmax.z, o.z + size); } - - void extendbb(float z, float size = 0) - { + void extendbb(float z, float size = 0) { bbmin.z = min(bbmin.z, z - size); bbmax.z = max(bbmax.z, z + size); } @@ -62,18 +53,15 @@ struct particleemitter static vector<particleemitter> emitters; static particleemitter *seedemitter = NULL; -void clearparticleemitters() -{ +void clearparticleemitters() { emitters.setsize(0); regenemitters = true; } -void addparticleemitters() -{ +void addparticleemitters() { emitters.setsize(0); const vector<extentity *> &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; if(e.type != ET_PARTICLES) continue; emitters.add(particleemitter(&e)); @@ -81,8 +69,7 @@ void addparticleemitters() regenemitters = false; } -enum -{ +enum { PT_PART = 0, PT_TAPE, PT_TRAIL, @@ -90,10 +77,7 @@ enum PT_TEXTICON, PT_METER, PT_METERVS, - PT_FIREBALL, - PT_LIGHTNING, PT_FLARE, - PT_MOD = 1<<8, PT_RND4 = 1<<9, PT_LERP = 1<<10, // use very sparingly - order of blending issues @@ -111,30 +95,26 @@ enum PT_FLIP = PT_HFLIP | PT_VFLIP | PT_ROT }; -const char *partnames[] = { "part", "tape", "trail", "text", "texticon", "meter", "metervs", "fireball", "lightning", "flare" }; +const char *partnames[] = { "part", "tape", "trail", "text", "texticon", "meter", "metervs", "flare" }; -struct particle -{ +struct particle { vec o, d; int gravity, fade, millis; bvec color; uchar flags; float size; - union - { + union { const char *text; float val; physent *owner; - struct - { + struct { uchar color2[3]; uchar progress; }; }; }; -struct partvert -{ +struct partvert { vec pos; bvec4 color; vec2 tc; @@ -143,27 +123,21 @@ struct partvert #define COLLIDERADIUS 8.0f #define COLLIDEERROR 1.0f -struct partrenderer -{ +struct partrenderer { Texture *tex; const char *texname; int texclamp; uint type; int collide; string info; - partrenderer(const char *texname, int texclamp, int type, int collide = 0) - : tex(NULL), texname(texname), texclamp(texclamp), type(type), collide(collide) - { + : tex(NULL), texname(texname), texclamp(texclamp), type(type), collide(collide) { } partrenderer(int type, int collide = 0) - : tex(NULL), texname(NULL), texclamp(0), type(type), collide(collide) - { + : tex(NULL), texname(NULL), texclamp(0), type(type), collide(collide) { } - virtual ~partrenderer() - { + virtual ~partrenderer() { } - virtual void init(int n) { } virtual void reset() = 0; virtual void resettracked(physent *owner) { } @@ -172,44 +146,34 @@ struct partrenderer virtual void render() = 0; virtual bool haswork() = 0; virtual void cleanup() {} - - virtual void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity) - { + virtual void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity) { } - //blend = 0 => remove it - void calc(particle *p, int &blend, int &ts, vec &o, vec &d, bool step = true) - { + void calc(particle *p, int &blend, int &ts, vec &o, vec &d, bool step = true) { o = p->o; d = p->d; if(type&PT_TRACK && p->owner) game::particletrack(p->owner, o, d); - if(p->fade <= 5) - { + if(p->fade <= 5) { ts = 1; blend = 255; } - else - { + else { ts = lastmillis-p->millis; blend = max(255 - (ts<<8)/p->fade, 0); - if(p->gravity) - { + if(p->gravity) { if(ts > p->fade) ts = p->fade; float t = ts; o.add(vec(d).mul(t/5000.0f)); o.z -= t*t/(2.0f * 5000.0f * p->gravity); } - if(collide && o.z < p->val && step) - { - if(collide >= 0) - { + if(collide && o.z < p->val && step) { + if(collide >= 0) { vec surface; float floorz = rayfloor(vec(o.x, o.y, p->val), surface, RAY_CLIPMAT, COLLIDERADIUS); float collidez = floorz<0 ? o.z-COLLIDERADIUS : p->val - floorz; if(o.z >= collidez+COLLIDEERROR) p->val = collidez+COLLIDEERROR; - else - { + else { adddecal(collide, vec(o.x, o.y, collidez), vec(p->o).sub(o).normalize(), 2*p->size, p->color, type&PT_RND4 ? (p->flags>>5)&3 : 0); blend = 0; } @@ -220,41 +184,29 @@ struct partrenderer } }; -struct listparticle : particle -{ +struct listparticle : particle { listparticle *next; }; VARP(outlinemeters, 0, 0, 1); -struct listrenderer : partrenderer -{ +struct listrenderer : partrenderer { static listparticle *parempty; listparticle *list; - listrenderer(const char *texname, int texclamp, int type, int collide = 0) - : partrenderer(texname, texclamp, type, collide), list(NULL) - { + : partrenderer(texname, texclamp, type, collide), list(NULL) { } listrenderer(int type, int collide = 0) - : partrenderer(type, collide), list(NULL) - { + : partrenderer(type, collide), list(NULL) { } - - virtual ~listrenderer() - { + virtual ~listrenderer() { } - - virtual void killpart(listparticle *p) - { + virtual void killpart(listparticle *p) { } - - void reset() - { + void reset() { if(!list) return; listparticle *p = list; - for(;;) - { + for(;;) { killpart(p); if(p->next) p = p->next; else break; @@ -263,14 +215,10 @@ struct listrenderer : partrenderer parempty = list; list = NULL; } - - void resettracked(physent *owner) - { + void resettracked(physent *owner) { if(!(type&PT_TRACK)) return; - for(listparticle **prev = &list, *cur = list; cur; cur = *prev) - { - if(!owner || cur->owner==owner) - { + for(listparticle **prev = &list, *cur = list; cur; cur = *prev) { + if(!owner || cur->owner==owner) { *prev = cur->next; cur->next = parempty; parempty = cur; @@ -278,11 +226,8 @@ struct listrenderer : partrenderer else prev = &cur->next; } } - - particle *addpart(const vec &o, const vec &d, int fade, int color, float size, int gravity) - { - if(!parempty) - { + particle *addpart(const vec &o, const vec &d, int fade, int color, float size, int gravity) { + if(!parempty) { listparticle *ps = new listparticle[256]; loopi(255) ps[i].next = &ps[i+1]; ps[255].next = parempty; @@ -303,44 +248,31 @@ struct listrenderer : partrenderer p->flags = 0; return p; } - - int count() - { + int count() { int num = 0; listparticle *lp; for(lp = list; lp; lp = lp->next) num++; return num; } - - bool haswork() - { + bool haswork() { return (list != NULL); } - virtual void startrender() = 0; virtual void endrender() = 0; virtual void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) = 0; - - void render() - { + void render() { startrender(); - if(texname) - { + if(texname) { if(!tex) tex = textureload(texname, texclamp); glBindTexture(GL_TEXTURE_2D, tex->id); } - - for(listparticle **prev = &list, *p = list; p; p = *prev) - { + for(listparticle **prev = &list, *p = list; p; p = *prev) { vec o, d; int blend, ts; calc(p, blend, ts, o, d, canstep); - if(blend > 0) - { + if(blend > 0) { renderpart(p, o, d, blend, ts); - - if(p->fade > 5 || !canstep) - { + if(p->fade > 5 || !canstep) { prev = &p->next; continue; } @@ -351,44 +283,33 @@ struct listrenderer : partrenderer killpart(p); parempty = p; } - endrender(); } }; listparticle *listrenderer::parempty = NULL; -struct meterrenderer : listrenderer -{ +struct meterrenderer : listrenderer { meterrenderer(int type) - : listrenderer(type|PT_NOTEX|PT_LERP) - {} - - void startrender() - { + : listrenderer(type|PT_NOTEX|PT_LERP) { + } + void startrender() { glDisable(GL_BLEND); gle::defvertex(); } - - void endrender() - { + void endrender() { glEnable(GL_BLEND); } - - void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) - { + void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) { int basetype = type&0xFF; float scale = FONTH*p->size/80.0f, right = 8, left = p->progress/100.0f*right; matrix4x3 m(camright, vec(camup).neg(), vec(camdir).neg(), o); m.scale(scale); m.translate(-right/2.0f, 0, 0); - - if(outlinemeters) - { + if(outlinemeters) { gle::colorf(0, 0.8f, 0); gle::begin(GL_TRIANGLE_STRIP); - loopk(10) - { + loopk(10) { const vec2 &sc = sincos360[k*(180/(10-1))]; float c = (0.5f + 0.1f)*sc.y, s = 0.5f - (0.5f + 0.1f)*sc.x; gle::attrib(m.transform(vec2(-c, s))); @@ -396,36 +317,29 @@ struct meterrenderer : listrenderer } gle::end(); } - if(basetype==PT_METERVS) gle::colorub(p->color2[0], p->color2[1], p->color2[2]); else gle::colorf(0, 0, 0); gle::begin(GL_TRIANGLE_STRIP); - loopk(10) - { + loopk(10) { const vec2 &sc = sincos360[k*(180/(10-1))]; float c = 0.5f*sc.y, s = 0.5f - 0.5f*sc.x; gle::attrib(m.transform(vec2(left + c, s))); gle::attrib(m.transform(vec2(right + c, s))); } gle::end(); - - if(outlinemeters) - { + if(outlinemeters) { gle::colorf(0, 0.8f, 0); gle::begin(GL_TRIANGLE_FAN); - loopk(10) - { + loopk(10) { const vec2 &sc = sincos360[k*(180/(10-1))]; float c = (0.5f + 0.1f)*sc.y, s = 0.5f - (0.5f + 0.1f)*sc.x; gle::attrib(m.transform(vec2(left + c, s))); } gle::end(); } - gle::color(p->color); gle::begin(GL_TRIANGLE_STRIP); - loopk(10) - { + loopk(10) { const vec2 &sc = sincos360[k*(180/(10-1))]; float c = 0.5f*sc.y, s = 0.5f - 0.5f*sc.x; gle::attrib(m.transform(vec2(-c, s))); @@ -436,33 +350,22 @@ struct meterrenderer : listrenderer }; static meterrenderer meters(PT_METER), metervs(PT_METERVS); -struct textrenderer : listrenderer -{ +struct textrenderer : listrenderer { textrenderer(int type) - : listrenderer(type) - {} - - void startrender() - { + : listrenderer(type) { } - - void endrender() - { + void startrender() { } - - void killpart(listparticle *p) - { + void endrender() { + } + void killpart(listparticle *p) { if(p->text && p->flags&1) delete[] p->text; } - - void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) - { + void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) { float scale = p->size/80.0f, xoff = -(text_width(p->text) + ((p->flags>>1)&7)*FONTH)/2, yoff = 0; - matrix4x3 m(camright, vec(camup).neg(), vec(camdir).neg(), o); m.scale(scale); m.translate(xoff, yoff, 50); - textmatrix = &m; draw_text(p->text, 0, 0, p->color.r, p->color.g, p->color.b, blend); textmatrix = NULL; @@ -470,35 +373,25 @@ struct textrenderer : listrenderer }; static textrenderer texts(PT_TEXT|PT_LERP); -struct texticonrenderer : listrenderer -{ +struct texticonrenderer : listrenderer { texticonrenderer(const char *texname, int type) - : listrenderer(texname, 3, type) - {} - - void startrender() - { + : listrenderer(texname, 3, type) { + } + void startrender() { gle::defvertex(); gle::deftexcoord0(); gle::defcolor(4, GL_UNSIGNED_BYTE); gle::begin(GL_QUADS); } - - void endrender() - { + void endrender() { gle::end(); } - - void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) - { + void renderpart(listparticle *p, const vec &o, const vec &d, int blend, int ts) { float scale = p->size/80.0f, xoff = p->val, yoff = 0; - matrix4x3 m(camright, vec(camup).neg(), vec(camdir).neg(), o); m.scale(scale); m.translate(xoff, yoff, 50); - float tx = 0.25f*(p->flags&3), ty = 0.25f*((p->flags>>2)&3); - gle::attrib(m.transform(vec2(0, 0))); gle::attrib(tx, ty); gle::attrib(p->color, blend); @@ -516,19 +409,16 @@ struct texticonrenderer : listrenderer static texticonrenderer texticons("packages/hud/items.png", PT_TEXTICON|PT_LERP); template<int T> -static inline void modifyblend(const vec &o, int &blend) -{ +static inline void modifyblend(const vec &o, int &blend) { blend = min(blend<<2, 255); } template<> -inline void modifyblend<PT_TAPE>(const vec &o, int &blend) -{ +inline void modifyblend<PT_TAPE>(const vec &o, int &blend) { } template<int T> -static inline void genpos(const vec &o, const vec &d, float size, int grav, int ts, partvert *vs) -{ +static inline void genpos(const vec &o, const vec &d, float size, int grav, int ts, partvert *vs) { vec udir = vec(camup).sub(camright).mul(size); vec vdir = vec(camup).add(camright).mul(size); vs[0].pos = vec(o.x + udir.x, o.y + udir.y, o.z + udir.z); @@ -538,8 +428,7 @@ static inline void genpos(const vec &o, const vec &d, float size, int grav, int } template<> -inline void genpos<PT_TAPE>(const vec &o, const vec &d, float size, int ts, int grav, partvert *vs) -{ +inline void genpos<PT_TAPE>(const vec &o, const vec &d, float size, int ts, int grav, partvert *vs) { vec dir1 = d, dir2 = d, c; dir1.sub(o); dir2.sub(camera1->o); @@ -551,8 +440,7 @@ inline void genpos<PT_TAPE>(const vec &o, const vec &d, float size, int ts, int } template<> -inline void genpos<PT_TRAIL>(const vec &o, const vec &d, float size, int ts, int grav, partvert *vs) -{ +inline void genpos<PT_TRAIL>(const vec &o, const vec &d, float size, int ts, int grav, partvert *vs) { vec e = d; if(grav) e.z -= float(ts)/grav; e.div(-75.0f).add(o); @@ -560,8 +448,7 @@ inline void genpos<PT_TRAIL>(const vec &o, const vec &d, float size, int ts, int } template<int T> -static inline void genrotpos(const vec &o, const vec &d, float size, int grav, int ts, partvert *vs, int rot) -{ +static inline void genrotpos(const vec &o, const vec &d, float size, int grav, int ts, partvert *vs, int rot) { genpos<T>(o, d, size, grav, ts, vs); } @@ -571,8 +458,7 @@ static inline void genrotpos(const vec &o, const vec &d, float size, int grav, i vec( 1, -1, 0).rotate_around_z(n*2*M_PI/32.0f), \ vec(-1, -1, 0).rotate_around_z(n*2*M_PI/32.0f) \ } -static const vec rotcoeffs[32][4] = -{ +static const vec rotcoeffs[32][4] = { ROTCOEFFS(0), ROTCOEFFS(1), ROTCOEFFS(2), ROTCOEFFS(3), ROTCOEFFS(4), ROTCOEFFS(5), ROTCOEFFS(6), ROTCOEFFS(7), ROTCOEFFS(8), ROTCOEFFS(9), ROTCOEFFS(10), ROTCOEFFS(11), ROTCOEFFS(12), ROTCOEFFS(13), ROTCOEFFS(14), ROTCOEFFS(15), ROTCOEFFS(16), ROTCOEFFS(17), ROTCOEFFS(18), ROTCOEFFS(19), ROTCOEFFS(20), ROTCOEFFS(21), ROTCOEFFS(22), ROTCOEFFS(7), @@ -580,8 +466,7 @@ static const vec rotcoeffs[32][4] = }; template<> -inline void genrotpos<PT_PART>(const vec &o, const vec &d, float size, int grav, int ts, partvert *vs, int rot) -{ +inline void genrotpos<PT_PART>(const vec &o, const vec &d, float size, int grav, int ts, partvert *vs, int rot) { const vec *coeffs = rotcoeffs[rot]; (vs[0].pos = o).add(vec(camright).mul(coeffs[0].x*size)).add(vec(camup).mul(coeffs[0].y*size)); (vs[1].pos = o).add(vec(camright).mul(coeffs[1].x*size)).add(vec(camup).mul(coeffs[1].y*size)); @@ -590,30 +475,25 @@ inline void genrotpos<PT_PART>(const vec &o, const vec &d, float size, int grav, } template<int T> -static inline void seedpos(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int grav) -{ - if(grav) - { +static inline void seedpos(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int grav) { + if(grav) { vec end(o); float t = fade; end.add(vec(d).mul(t/5000.0f)); end.z -= t*t/(2.0f * 5000.0f * grav); pe.extendbb(end, size); - float tpeak = d.z*grav; if(tpeak > 0 && tpeak < fade) pe.extendbb(o.z + 1.5f*d.z*tpeak/5000.0f, size); } } template<> -inline void seedpos<PT_TAPE>(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int grav) -{ +inline void seedpos<PT_TAPE>(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int grav) { pe.extendbb(d, size); } template<> -inline void seedpos<PT_TRAIL>(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int grav) -{ +inline void seedpos<PT_TRAIL>(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int grav) { vec e = d; if(grav) e.z -= float(fade)/grav; e.div(-75.0f).add(o); @@ -621,30 +501,23 @@ inline void seedpos<PT_TRAIL>(particleemitter &pe, const vec &o, const vec &d, i } template<int T> -struct varenderer : partrenderer -{ +struct varenderer : partrenderer { partvert *verts; particle *parts; int maxparts, numparts, lastupdate, rndmask; GLuint vbo; - varenderer(const char *texname, int type, int collide = 0) : partrenderer(texname, 3, type, collide), - verts(NULL), parts(NULL), maxparts(0), numparts(0), lastupdate(-1), rndmask(0), vbo(0) - { + verts(NULL), parts(NULL), maxparts(0), numparts(0), lastupdate(-1), rndmask(0), vbo(0) { if(type & PT_HFLIP) rndmask |= 0x01; if(type & PT_VFLIP) rndmask |= 0x02; if(type & PT_ROT) rndmask |= 0x1F<<2; if(type & PT_RND4) rndmask |= 0x03<<5; } - - void cleanup() - { + void cleanup() { if(vbo) { glDeleteBuffers_(1, &vbo); vbo = 0; } } - - void init(int n) - { + void init(int n) { DELETEA(parts); DELETEA(verts); parts = new particle[n]; @@ -653,36 +526,25 @@ struct varenderer : partrenderer numparts = 0; lastupdate = -1; } - - void reset() - { + void reset() { numparts = 0; lastupdate = -1; } - - void resettracked(physent *owner) - { + void resettracked(physent *owner) { if(!(type&PT_TRACK)) return; - loopi(numparts) - { + loopi(numparts) { particle *p = parts+i; if(!owner || (p->owner == owner)) p->fade = -1; } lastupdate = -1; } - - int count() - { + int count() { return numparts; } - - bool haswork() - { + bool haswork() { return (numparts > 0); } - - particle *addpart(const vec &o, const vec &d, int fade, int color, float size, int gravity) - { + particle *addpart(const vec &o, const vec &d, int fade, int color, float size, int gravity) { particle *p = parts + (numparts < maxparts ? numparts++ : rnd(maxparts)); //next free slot, or kill a random kitten p->o = o; p->d = d; @@ -696,42 +558,30 @@ struct varenderer : partrenderer lastupdate = -1; return p; } - - void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity) - { + void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity) { pe.maxfade = max(pe.maxfade, fade); size *= SQRT2; pe.extendbb(o, size); - seedpos<T>(pe, o, d, fade, size, gravity); if(!gravity) return; - vec end(o); float t = fade; end.add(vec(d).mul(t/5000.0f)); end.z -= t*t/(2.0f * 5000.0f * gravity); pe.extendbb(end, size); - float tpeak = d.z*gravity; if(tpeak > 0 && tpeak < fade) pe.extendbb(o.z + 1.5f*d.z*tpeak/5000.0f, size); } - - void genverts(particle *p, partvert *vs, bool regen) - { + void genverts(particle *p, partvert *vs, bool regen) { vec o, d; int blend, ts; - calc(p, blend, ts, o, d); if(blend <= 1 || p->fade <= 5) p->fade = -1; //mark to remove on next pass (i.e. after render) - modifyblend<T>(o, blend); - - if(regen) - { + if(regen) { p->flags &= ~0x80; - - #define SETTEXCOORDS(u1c, u2c, v1c, v2c, body) \ - { \ + #define SETTEXCOORDS(u1c, u2c, v1c, v2c, body) { \ + \ float u1 = u1c, u2 = u2c, v1 = v1c, v2 = v2c; \ body; \ vs[0].tc = vec2(u1, v1); \ @@ -739,22 +589,18 @@ struct varenderer : partrenderer vs[2].tc = vec2(u2, v2); \ vs[3].tc = vec2(u1, v2); \ } - if(type&PT_RND4) - { + if(type&PT_RND4) { float tx = 0.5f*((p->flags>>5)&1), ty = 0.5f*((p->flags>>6)&1); - SETTEXCOORDS(tx, tx + 0.5f, ty, ty + 0.5f, - { + SETTEXCOORDS(tx, tx + 0.5f, ty, ty + 0.5f, { if(p->flags&0x01) swap(u1, u2); if(p->flags&0x02) swap(v1, v2); }); } - else if(type&PT_ICON) - { + else if(type&PT_ICON) { float tx = 0.25f*(p->flags&3), ty = 0.25f*((p->flags>>2)&3); SETTEXCOORDS(tx, tx + 0.25f, ty, ty + 0.25f, {}); } else SETTEXCOORDS(0, 1, 0, 1, {}); - #define SETCOLOR(r, g, b, a) \ do { \ bvec4 col(r, g, b, a); \ @@ -766,21 +612,15 @@ struct varenderer : partrenderer } else if(type&PT_MOD) SETMODCOLOR; else loopi(4) vs[i].color.a = blend; - if(type&PT_ROT) genrotpos<T>(o, d, p->size, ts, p->gravity, vs, (p->flags>>2)&0x1F); else genpos<T>(o, d, p->size, ts, p->gravity, vs); } - - void genverts() - { - loopi(numparts) - { + void genverts() { + loopi(numparts) { particle *p = &parts[i]; partvert *vs = &verts[i*4]; - if(p->fade < 0) - { - do - { + if(p->fade < 0) { + do { --numparts; if(numparts <= i) return; } @@ -791,26 +631,19 @@ struct varenderer : partrenderer else genverts(p, vs, (p->flags&0x80)!=0); } } - - void update() - { + void update() { if(lastmillis == lastupdate && vbo) return; lastupdate = lastmillis; - genverts(); - if(!vbo) glGenBuffers_(1, &vbo); gle::bindvbo(vbo); glBufferData_(GL_ARRAY_BUFFER, maxparts*4*sizeof(partvert), NULL, GL_STREAM_DRAW); glBufferSubData_(GL_ARRAY_BUFFER, 0, numparts*4*sizeof(partvert), verts); gle::clearvbo(); } - - void render() - { + void render() { if(!tex) tex = textureload(texname, texclamp); glBindTexture(GL_TEXTURE_2D, tex->id); - gle::bindvbo(vbo); const partvert *ptr = 0; gle::vertexpointer(sizeof(partvert), ptr->pos.v); @@ -820,9 +653,7 @@ struct varenderer : partrenderer gle::enabletexcoord0(); gle::enablecolor(); gle::enablequads(); - gle::drawquads(0, numparts); - gle::disablequads(); gle::disablevertex(); gle::disabletexcoord0(); @@ -830,35 +661,24 @@ struct varenderer : partrenderer gle::clearvbo(); } }; + typedef varenderer<PT_PART> quadrenderer; typedef varenderer<PT_TAPE> taperenderer; typedef varenderer<PT_TRAIL> trailrenderer; -#include "explosion.h" -#include "lightning.h" - -struct softquadrenderer : quadrenderer -{ +struct softquadrenderer : quadrenderer { softquadrenderer(const char *texname, int type, int collide = 0) - : quadrenderer(texname, type|PT_SOFT, collide) - { + : quadrenderer(texname, type|PT_SOFT, collide) { } }; -static partrenderer *parts[] = -{ +static partrenderer *parts[] = { new quadrenderer("<grey>packages/particles/blood.png", PT_PART|PT_FLIP|PT_MOD|PT_RND4, DECAL_BLOOD), // blood spats (note: rgb is inverted) new trailrenderer("packages/particles/base.png", PT_TRAIL|PT_LERP), // water, entity new quadrenderer("<grey>packages/particles/smoke.png", PT_PART|PT_FLIP|PT_LERP), // smoke new quadrenderer("<grey>packages/particles/steam.png", PT_PART|PT_FLIP), // steam new quadrenderer("<grey>packages/particles/flames.png", PT_PART|PT_HFLIP|PT_RND4|PT_GLARE), // flame on - no flipping please, they have orientation - new quadrenderer("packages/particles/ball1.png", PT_PART|PT_FEW|PT_GLARE), // fireball1 - new quadrenderer("packages/particles/ball2.png", PT_PART|PT_FEW|PT_GLARE), // fireball2 - new quadrenderer("packages/particles/ball3.png", PT_PART|PT_FEW|PT_GLARE), // fireball3 new taperenderer("packages/particles/flare.png", PT_TAPE|PT_GLARE), // streak - &lightnings, // lightning - &fireballs, // explosion fireball - &bluefireballs, // bluish explosion fireball new quadrenderer("packages/particles/spark.png", PT_PART|PT_FLIP|PT_GLARE), // sparks new quadrenderer("packages/particles/base.png", PT_PART|PT_FLIP|PT_GLARE), // edit mode entities new quadrenderer("<grey>packages/particles/snow.png", PT_PART|PT_FLIP|PT_RND4, -1), // colliding snow @@ -876,73 +696,54 @@ static partrenderer *parts[] = VARFP(maxparticles, 10, 4000, 40000, initparticles()); VARFP(fewparticles, 10, 100, 40000, initparticles()); -void initparticles() -{ +void initparticles() { if(!particleshader) particleshader = lookupshaderbyname("particle"); if(!particlenotextureshader) particlenotextureshader = lookupshaderbyname("particlenotexture"); loopi(sizeof(parts)/sizeof(parts[0])) parts[i]->init(parts[i]->type&PT_FEW ? min(fewparticles, maxparticles) : maxparticles); } -void clearparticles() -{ +void clearparticles() { loopi(sizeof(parts)/sizeof(parts[0])) parts[i]->reset(); clearparticleemitters(); } -void cleanupparticles() -{ +void cleanupparticles() { loopi(sizeof(parts)/sizeof(parts[0])) parts[i]->cleanup(); } -void removetrackedparticles(physent *owner) -{ +void removetrackedparticles(physent *owner) { loopi(sizeof(parts)/sizeof(parts[0])) parts[i]->resettracked(owner); } -void renderparticles(bool mainpass) -{ +void renderparticles(bool mainpass) { canstep = mainpass; - - loopi(sizeof(parts)/sizeof(parts[0])) - { + loopi(sizeof(parts)/sizeof(parts[0])) { parts[i]->update(); } - bool rendered = false; uint lastflags = PT_LERP|PT_SHADER, flagmask = PT_LERP|PT_MOD|PT_SHADER|PT_NOTEX; - - loopi(sizeof(parts)/sizeof(parts[0])) - { + loopi(sizeof(parts)/sizeof(parts[0])) { partrenderer *p = parts[i]; if(!(p->type&PT_GLARE)) continue; if(!p->haswork()) continue; - - if(!rendered) - { + if(!rendered) { rendered = true; glDepthMask(GL_FALSE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - GLOBALPARAMF(colorscale, 1, 1, 1, 1); } - uint flags = p->type & flagmask, changedbits = (flags ^ lastflags); - if(changedbits) - { - if(changedbits&(PT_LERP|PT_MOD)) - { + if(changedbits) { + if(changedbits&(PT_LERP|PT_MOD)) { if(flags&PT_LERP) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); else if(flags&PT_MOD) glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); else glBlendFunc(GL_SRC_ALPHA, GL_ONE); } - if(!(flags&PT_SHADER)) - { - if(changedbits&(PT_SOFT|PT_SHADER|PT_NOTEX|PT_LERP)) - { - if(flags&PT_SOFT) - { + if(!(flags&PT_SHADER)) { + if(changedbits&(PT_SOFT|PT_SHADER|PT_NOTEX|PT_LERP)) { + if(flags&PT_SOFT) { SETSHADER(particlesoft); } else if(flags&PT_NOTEX) particlenotextureshader->set(); @@ -953,9 +754,7 @@ void renderparticles(bool mainpass) } p->render(); } - - if(rendered) - { + if(rendered) { if(lastflags&(PT_LERP|PT_MOD)) glBlendFunc(GL_SRC_ALPHA, GL_ONE); glDisable(GL_BLEND); glDepthMask(GL_TRUE); @@ -964,11 +763,9 @@ void renderparticles(bool mainpass) static int addedparticles = 0; -static inline particle *newparticle(const vec &o, const vec &d, int fade, int type, int color, float size, int gravity = 0) -{ +static inline particle *newparticle(const vec &o, const vec &d, int fade, int type, int color, float size, int gravity = 0) { static particle dummy; - if(seedemitter) - { + if(seedemitter) { parts[type]->seedemitter(*seedemitter, o, d, fade, size, gravity); return &dummy; } @@ -979,17 +776,14 @@ static inline particle *newparticle(const vec &o, const vec &d, int fade, int ty VARP(maxparticledistance, 256, 1024, 4096); -static void splash(int type, int color, int radius, int num, int fade, const vec &p, float size, int gravity) -{ +static void splash(int type, int color, int radius, int num, int fade, const vec &p, float size, int gravity) { if(camera1->o.dist(p) > maxparticledistance && !seedemitter) return; float collidez = parts[type]->collide ? p.z - raycube(p, vec(0, 0, -1), COLLIDERADIUS, RAY_CLIPMAT) + (parts[type]->collide >= 0 ? COLLIDEERROR : 0) : -1; int fmin = 1; int fmax = fade*3; - loopi(num) - { + loopi(num) { int x, y, z; - do - { + do { x = rnd(radius*2)-radius; y = rnd(radius*2)-radius; z = rnd(radius*2)-radius; @@ -1001,41 +795,35 @@ static void splash(int type, int color, int radius, int num, int fade, const vec } } -static void regularsplash(int type, int color, int radius, int num, int fade, const vec &p, float size, int gravity, int delay = 0) -{ +static void regularsplash(int type, int color, int radius, int num, int fade, const vec &p, float size, int gravity, int delay = 0) { if(!canemitparticles() || (delay > 0 && rnd(delay) != 0)) return; splash(type, color, radius, num, fade, p, size, gravity); } -bool canaddparticles() -{ +bool canaddparticles() { return !renderedgame && !shadowmapping && !minimized; } -void regular_particle_splash(int type, int num, int fade, const vec &p, int color, float size, int radius, int gravity, int delay) -{ +void regular_particle_splash(int type, int num, int fade, const vec &p, int color, float size, int radius, int gravity, int delay) { if(!canaddparticles()) return; regularsplash(type, color, radius, num, fade, p, size, gravity, delay); } -void particle_splash(int type, int num, int fade, const vec &p, int color, float size, int radius, int gravity) -{ +void particle_splash(int type, int num, int fade, const vec &p, int color, float size, int radius, int gravity) { if(!canaddparticles()) return; splash(type, color, radius, num, fade, p, size, gravity); } VARP(maxtrail, 1, 500, 10000); -void particle_trail(int type, int fade, const vec &s, const vec &e, int color, float size, int gravity) -{ +void particle_trail(int type, int fade, const vec &s, const vec &e, int color, float size, int gravity) { if(!canaddparticles()) return; vec v; float d = e.dist(s, v); int steps = clamp(int(d*2), 1, maxtrail); v.div(steps); vec p = s; - loopi(steps) - { + loopi(steps) { p.add(v); vec tmp = vec(float(rnd(11)-5), float(rnd(11)-5), float(rnd(11)-5)); newparticle(p, tmp, rnd(fade)+fade, type, color, size, gravity); @@ -1045,8 +833,7 @@ void particle_trail(int type, int fade, const vec &s, const vec &e, int color, f VARP(particletext, 0, 1, 1); VARP(maxparticletextdistance, 0, 128, 10000); -void particle_text(const vec &s, const char *t, int type, int fade, int color, float size, int gravity, int icons) -{ +void particle_text(const vec &s, const char *t, int type, int fade, int color, float size, int gravity, int icons) { if(!canaddparticles()) return; if(!particletext || camera1->o.dist(s) > maxparticletextdistance) return; particle *p = newparticle(s, vec(0, 0, 1), fade, type, color, size, gravity); @@ -1054,8 +841,7 @@ void particle_text(const vec &s, const char *t, int type, int fade, int color, f p->flags = icons<<1; } -void particle_textcopy(const vec &s, const char *t, int type, int fade, int color, float size, int gravity) -{ +void particle_textcopy(const vec &s, const char *t, int type, int fade, int color, float size, int gravity) { if(!canaddparticles()) return; if(!particletext || camera1->o.dist(s) > maxparticletextdistance) return; particle *p = newparticle(s, vec(0, 0, 1), fade, type, color, size, gravity); @@ -1063,8 +849,7 @@ void particle_textcopy(const vec &s, const char *t, int type, int fade, int colo p->flags = 1; } -void particle_texticon(const vec &s, int ix, int iy, float offset, int type, int fade, int color, float size, int gravity) -{ +void particle_texticon(const vec &s, int ix, int iy, float offset, int type, int fade, int color, float size, int gravity) { if(!canaddparticles()) return; if(!particletext || camera1->o.dist(s) > maxparticletextdistance) return; particle *p = newparticle(s, vec(0, 0, 1), fade, type, color, size, gravity); @@ -1072,15 +857,13 @@ void particle_texticon(const vec &s, int ix, int iy, float offset, int type, int p->val = offset; } -void particle_icon(const vec &s, int ix, int iy, int type, int fade, int color, float size, int gravity) -{ +void particle_icon(const vec &s, int ix, int iy, int type, int fade, int color, float size, int gravity) { if(!canaddparticles()) return; particle *p = newparticle(s, vec(0, 0, 1), fade, type, color, size, gravity); p->flags |= ix | (iy<<2); } -void particle_meter(const vec &s, float val, int type, int fade, int color, int color2, float size) -{ +void particle_meter(const vec &s, float val, int type, int fade, int color, int color2, float size) { if(!canaddparticles()) return; particle *p = newparticle(s, vec(0, 0, 1), fade, type, color, size); p->color2[0] = color2>>16; @@ -1089,31 +872,20 @@ void particle_meter(const vec &s, float val, int type, int fade, int color, int p->progress = clamp(int(val*100), 0, 100); } -void particle_flare(const vec &p, const vec &dest, int fade, int type, int color, float size, physent *owner) -{ +void particle_flare(const vec &p, const vec &dest, int fade, int type, int color, float size, physent *owner) { if(!canaddparticles()) return; newparticle(p, dest, fade, type, color, size)->owner = owner; } -void particle_fireball(const vec &dest, float maxsize, int type, int fade, int color, float size) -{ - if(!canaddparticles()) return; - float growth = maxsize - size; - if(fade < 0) fade = int(growth*20); - newparticle(dest, vec(0, 0, 1), fade, type, color, size)->val = growth; -} - //dir = 0..6 where 0=up -static inline vec offsetvec(vec o, int dir, int dist) -{ +static inline vec offsetvec(vec o, int dir, int dist) { vec v = vec(o); v[(2+dir)%3] += (dir>2)?(-dist):dist; return v; } //converts a 16bit color to 24bit -static inline int colorfromattr(int attr) -{ +static inline int colour_from_attribute(int attr) { return (((attr&0xF)<<4) | ((attr&0xF0)<<8) | ((attr&0xF00)<<12)) + 0x0F0F0F; } @@ -1128,19 +900,15 @@ static inline int colorfromattr(int attr) * 24..26 flat plane * +32 to inverse direction */ -void regularshape(int type, int radius, int color, int dir, int num, int fade, const vec &p, float size, int gravity, int vel = 200) -{ +void regularshape(int type, int radius, int color, int dir, int num, int fade, const vec &p, float size, int gravity, int vel = 200) { if(!canemitparticles()) return; - int basetype = parts[type]->type&0xFF; - bool flare = (basetype == PT_TAPE) || (basetype == PT_LIGHTNING), + bool flare = (basetype == PT_TAPE), inv = (dir&0x20)!=0, taper = (dir&0x40)!=0 && !seedemitter; dir &= 0x1F; - loopi(num) - { + loopi(num) { vec to, from; - if(dir < 12) - { + if(dir < 12) { const vec2 &sc = sincos360[rnd(360)]; to[dir%3] = sc.y*radius; to[(dir+1)%3] = sc.x*radius; @@ -1148,20 +916,17 @@ void regularshape(int type, int radius, int color, int dir, int num, int fade, c to.add(p); if(dir < 3) //circle from = p; - else if(dir < 6) //cylinder - { + else if(dir < 6) { //cylinder { from = to; to[(dir+2)%3] += radius; from[(dir+2)%3] -= radius; } - else //cone - { + else { //cone { from = p; to[(dir+2)%3] += (dir < 9)?radius:(-radius); } } - else if(dir < 15) //plane - { + else if(dir < 15) { //plane { to[dir%3] = float(rnd(radius<<4)-(radius<<3))/8.0; to[(dir+1)%3] = float(rnd(radius<<4)-(radius<<3))/8.0; to[(dir+2)%3] = radius; @@ -1169,15 +934,12 @@ void regularshape(int type, int radius, int color, int dir, int num, int fade, c from = to; from[(dir+2)%3] -= 2*radius; } - else if(dir < 21) //line - { - if(dir < 18) - { + else if(dir < 21) { //line { + if(dir < 18) { to[dir%3] = float(rnd(radius<<4)-(radius<<3))/8.0; to[(dir+1)%3] = 0.0; } - else - { + else { to[dir%3] = 0.0; to[(dir+1)%3] = float(rnd(radius<<4)-(radius<<3))/8.0; } @@ -1186,14 +948,12 @@ void regularshape(int type, int radius, int color, int dir, int num, int fade, c from = to; to[(dir+2)%3] += radius; } - else if(dir < 24) //sphere - { + else if(dir < 24) { //sphere { to = vec(2*M_PI*float(rnd(1000))/1000.0, M_PI*float(rnd(1000)-500)/1000.0).mul(radius); to.add(p); from = p; } - else if(dir < 27) // flat plane - { + else if(dir < 27) { // flat plane { to[dir%3] = float(rndscale(2*radius)-radius); to[(dir+1)%3] = float(rndscale(2*radius)-radius); to[(dir+2)%3] = 0.0; @@ -1201,23 +961,17 @@ void regularshape(int type, int radius, int color, int dir, int num, int fade, c from = to; } else from = to = p; - if(inv) swap(from, to); - - if(taper) - { + if(taper) { float dist = clamp(from.dist2(camera1->o)/maxparticledistance, 0.0f, 1.0f); - if(dist > 0.2f) - { + if(dist > 0.2f) { dist = 1 - (dist - 0.2f)/0.8f; if(rnd(0x10000) > dist*dist*0xFFFF) continue; } } - if(flare) newparticle(from, to, rnd(fade*3)+1, type, color, size, gravity); - else - { + else { vec d = vec(to).sub(from).rescale(vel); //velocity particle *n = newparticle(from, d, rnd(fade*3)+1, type, color, size, gravity); if(parts[type]->collide) @@ -1226,14 +980,11 @@ void regularshape(int type, int radius, int color, int dir, int num, int fade, c } } -static void regularflame(int type, const vec &p, float radius, float height, int color, int density = 3, float scale = 2.0f, float speed = 200.0f, float fade = 600.0f, int gravity = -15) -{ +static void regularflame(int type, const vec &p, float radius, float height, int color, int density = 3, float scale = 2.0f, float speed = 200.0f, float fade = 600.0f, int gravity = -15) { if(!canemitparticles()) return; - float size = scale * min(radius, height); vec v(0, 0, min(1.0f, height)*speed); - loopi(density) - { + loopi(density) { vec s = p; s.x += rndscale(radius*2.0f)-radius; s.y += rndscale(radius*2.0f)-radius; @@ -1241,65 +992,48 @@ static void regularflame(int type, const vec &p, float radius, float height, int } } -void regular_particle_flame(int type, const vec &p, float radius, float height, int color, int density, float scale, float speed, float fade, int gravity) -{ +void regular_particle_flame(int type, const vec &p, float radius, float height, int color, int density, float scale, float speed, float fade, int gravity) { if(!canaddparticles()) return; regularflame(type, p, radius, height, color, density, scale, speed, fade, gravity); } -static void makeparticles(entity &e) -{ - switch(e.attr1) - { - case 0: //fire and smoke - <radius> <height> <rgb> - 0 values default to compat for old maps - { - //regularsplash(PART_FIREBALL1, 0xFFC8C8, 150, 1, 40, e.o, 4.8f); - //regularsplash(PART_SMOKE, 0x897661, 50, 1, 200, vec(e.o.x, e.o.y, e.o.z+3.0f), 2.4f, -20, 3); +static void makeparticles(entity &e) { + switch(e.attr1) { + case 0: { //fire and smoke - <radius> <height> <rgb> - 0 values default to compat for old maps { float radius = e.attr2 ? float(e.attr2)/100.0f : 1.5f, height = e.attr3 ? float(e.attr3)/100.0f : radius/3; - regularflame(PART_FLAME, e.o, radius, height, e.attr4 ? colorfromattr(e.attr4) : 0x903020, 3, 2.0f); + regularflame(PART_FLAME, e.o, radius, height, e.attr4 ? colour_from_attribute(e.attr4) : 0x903020, 3, 2.0f); regularflame(PART_SMOKE, vec(e.o.x, e.o.y, e.o.z + 4.0f*min(radius, height)), radius, height, 0x303020, 1, 4.0f, 100.0f, 2000.0f, -20); break; } case 1: //steam vent - <dir> regularsplash(PART_STEAM, 0x897661, 50, 1, 200, offsetvec(e.o, e.attr2, rnd(10)), 2.4f, -20); break; - case 2: //water fountain - <dir> - { + case 2: { //water fountain - <dir> { int color; - if(e.attr3 > 0) color = colorfromattr(e.attr3); - else - { - int mat = clamp(-e.attr3, 0, 3); - color = 0xff7700; - } + if(e.attr3 > 0) color = colour_from_attribute(e.attr3); + else color = 0xff7700; regularsplash(PART_WATER, color, 150, 4, 200, offsetvec(e.o, e.attr2, rnd(10)), 0.6f, 2); break; } - case 3: //fire ball - <size> <rgb> - newparticle(e.o, vec(0, 0, 1), 1, PART_EXPLOSION, colorfromattr(e.attr3), 4.0f)->val = 1+e.attr2; - break; - case 4: //tape - <dir> <length> <rgb> - case 7: //lightning case 9: //steam + case 4: //tape - <dir> <length> <rgb> case 10: //water - case 13: //snow - { - static const int typemap[] = { PART_STREAK, -1, -1, PART_LIGHTNING, -1, PART_STEAM, PART_WATER, -1, -1, PART_SNOW }; - static const float sizemap[] = { 0.28f, 0.0f, 0.0f, 1.0f, 0.0f, 2.4f, 0.60f, 0.0f, 0.0f, 0.5f }; + case 13: { //snow { + static const int typemap[] = { PART_STREAK, -1, -1, -1, -1, PART_STEAM, PART_WATER, -1, -1, PART_SNOW }; + static const float sizemap[] = { 0.28f, 0.0f, 0.0f, 0.0f, 0.0f, 2.4f, 0.60f, 0.0f, 0.0f, 0.5f }; static const int gravmap[] = { 0, 0, 0, 0, 0, -20, 2, 0, 0, 20 }; int type = typemap[e.attr1-4]; float size = sizemap[e.attr1-4]; int gravity = gravmap[e.attr1-4]; - if(e.attr2 >= 256) regularshape(type, max(1+e.attr3, 1), colorfromattr(e.attr4), e.attr2-256, 5, e.attr5 > 0 ? min(int(e.attr5), 10000) : 200, e.o, size, gravity); - else newparticle(e.o, offsetvec(e.o, e.attr2, max(1+e.attr3, 0)), 1, type, colorfromattr(e.attr4), size, gravity); + if(e.attr2 >= 256) regularshape(type, max(1+e.attr3, 1), colour_from_attribute(e.attr4), e.attr2-256, 5, e.attr5 > 0 ? min(int(e.attr5), 10000) : 200, e.o, size, gravity); + else newparticle(e.o, offsetvec(e.o, e.attr2, max(1+e.attr3, 0)), 1, type, colour_from_attribute(e.attr4), size, gravity); break; } case 5: //meter, metervs - <percent> <rgb> <rgb2> - case 6: - { - particle *p = newparticle(e.o, vec(0, 0, 1), 1, e.attr1==5 ? PART_METER : PART_METER_VS, colorfromattr(e.attr3), 2.0f); - int color2 = colorfromattr(e.attr4); + case 6: { + particle *p = newparticle(e.o, vec(0, 0, 1), 1, e.attr1==5 ? PART_METER : PART_METER_VS, colour_from_attribute(e.attr3), 2.0f); + int color2 = colour_from_attribute(e.attr4); p->color2[0] = color2>>16; p->color2[1] = (color2>>8)&0xFF; p->color2[2] = color2&0xFF; @@ -1307,10 +1041,10 @@ static void makeparticles(entity &e) break; } case 11: // flame <radius> <height> <rgb> - radius=100, height=100 is the classic size - regularflame(PART_FLAME, e.o, float(e.attr2)/100.0f, float(e.attr3)/100.0f, colorfromattr(e.attr4), 3, 2.0f); + regularflame(PART_FLAME, e.o, float(e.attr2)/100.0f, float(e.attr3)/100.0f, colour_from_attribute(e.attr4), 3, 2.0f); break; case 12: // smoke plume <radius> <height> <rgb> - regularflame(PART_SMOKE, e.o, float(e.attr2)/100.0f, float(e.attr3)/100.0f, colorfromattr(e.attr4), 1, 4.0f, 100.0f, 2000.0f, -20); + regularflame(PART_SMOKE, e.o, float(e.attr2)/100.0f, float(e.attr3)/100.0f, colour_from_attribute(e.attr4), 1, 4.0f, 100.0f, 2000.0f, -20); break; case 32: //lens flares - plain/sparkle/sun/sparklesun <red> <green> <blue> case 33: @@ -1318,8 +1052,7 @@ static void makeparticles(entity &e) case 35: break; default: - if(!editmode) - { + if(!editmode) { defformatstring(ds, "particles %d?", e.attr1); particle_textcopy(e.o, ds, PART_TEXT, 1, 0x6496FF, 2.0f); } @@ -1327,10 +1060,8 @@ static void makeparticles(entity &e) } } -bool printparticles(extentity &e, char *buf, int len) -{ - switch(e.attr1) - { +bool printparticles(extentity &e, char *buf, int len) { + switch(e.attr1) { case 0: case 4: case 7: case 8: case 9: case 10: case 11: case 12: case 13: nformatstring(buf, len, "%s %d %d %d 0x%.3hX %d", entities::entname(e.type), e.attr1, e.attr2, e.attr3, e.attr4, e.attr5); return true; @@ -1344,13 +1075,11 @@ bool printparticles(extentity &e, char *buf, int len) return false; } -void seedparticles() -{ +void seedparticles() { renderprogress(0, "seeding particles"); addparticleemitters(); canemit = true; - loopv(emitters) - { + loopv(emitters) { particleemitter &pe = emitters[i]; extentity &e = *pe.ent; seedemitter = &pe; @@ -1362,34 +1091,25 @@ void seedparticles() } } -void updateparticles() -{ +void updateparticles() { if(regenemitters) addparticleemitters(); - if(minimized) { canemit = false; return; } - - if(lastmillis - lastemitframe >= emitmillis) - { + if(lastmillis - lastemitframe >= emitmillis) { canemit = true; lastemitframe = lastmillis - (lastmillis%emitmillis); } else canemit = false; - - if(!editmode || showparticles) - { + if(!editmode || showparticles) { int emitted = 0, replayed = 0; addedparticles = 0; - loopv(emitters) - { + loopv(emitters) { particleemitter &pe = emitters[i]; extentity &e = *pe.ent; if(e.o.dist(camera1->o) > maxparticledistance) { pe.lastemit = lastmillis; continue; } makeparticles(e); emitted++; - if(replayparticles && pe.maxfade > 5 && pe.lastcull > pe.lastemit) - { - for(emitoffset = max(pe.lastemit + emitmillis - lastmillis, -pe.maxfade); emitoffset < 0; emitoffset += emitmillis) - { + if(replayparticles && pe.maxfade > 5 && pe.lastcull > pe.lastemit) { + for(emitoffset = max(pe.lastemit + emitmillis - lastmillis, -pe.maxfade); emitoffset < 0; emitoffset += emitmillis) { makeparticles(e); replayed++; } @@ -1398,17 +1118,14 @@ void updateparticles() pe.lastemit = lastmillis; } } - if(editmode) // show sparkly thingies for map entities in edit mode - { + if(editmode) { // show sparkly thingies for map entities in edit mode { const vector<extentity *> &ents = entities::getents(); // note: order matters in this case as particles of the same type are drawn in the reverse order that they are added - loopv(entgroup) - { + loopv(entgroup) { entity &e = *ents[entgroup[i]]; particle_textcopy(e.o, entname(e), PART_TEXT, 1, 0xFF4B19, 2.0f); } - loopv(ents) - { + loopv(ents) { entity &e = *ents[i]; if(e.type==ET_EMPTY) continue; particle_textcopy(e.o, entname(e), PART_TEXT, 1, 0x1EC850, 2.0f); diff --git a/src/engine/rendertarget.h b/src/engine/rendertarget.h index a22298b..e89393a 100644 --- a/src/engine/rendertarget.h +++ b/src/engine/rendertarget.h @@ -1,7 +1,6 @@ extern int rtsharefb, rtscissor, blurtile; -struct rendertarget -{ +struct rendertarget { int texw, texh, vieww, viewh; GLenum colorfmt, depthfmt; GLuint rendertex, renderfb, renderdb, blurtex, blurfb, blurdb; @@ -9,70 +8,49 @@ struct rendertarget float blursigma; float blurweights[MAXBLURRADIUS+1], bluroffsets[MAXBLURRADIUS+1]; float bluryweights[MAXBLURRADIUS+1], bluryoffsets[MAXBLURRADIUS+1]; - float scissorx1, scissory1, scissorx2, scissory2; #define BLURTILES 32 #define BLURTILEMASK (0xFFFFFFFFU>>(32-BLURTILES)) uint blurtiles[BLURTILES+1]; - bool initialized; - - rendertarget() : texw(0), texh(0), vieww(0), viewh(0), colorfmt(GL_FALSE), depthfmt(GL_FALSE), rendertex(0), renderfb(0), renderdb(0), blurtex(0), blurfb(0), blurdb(0), blursize(0), blurysize(0), blursigma(0), initialized(false) - { + rendertarget() : texw(0), texh(0), vieww(0), viewh(0), colorfmt(GL_FALSE), depthfmt(GL_FALSE), rendertex(0), renderfb(0), renderdb(0), blurtex(0), blurfb(0), blurdb(0), blursize(0), blurysize(0), blursigma(0), initialized(false) { } - virtual ~rendertarget() {} - - virtual GLenum attachment() const - { + virtual GLenum attachment() const { return GL_COLOR_ATTACHMENT0; } - - virtual const GLenum *colorformats() const - { + virtual const GLenum *colorformats() const { static const GLenum colorfmts[] = { GL_RGB, GL_RGB8, GL_FALSE }; return colorfmts; } - - virtual const GLenum *depthformats() const - { + virtual const GLenum *depthformats() const { static const GLenum depthfmts[] = { GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT32, GL_FALSE }; return depthfmts; } - virtual bool depthtest() const { return true; } - - void cleanup(bool fullclean = false) - { + void cleanup(bool fullclean = false) { if(renderfb) { glDeleteFramebuffers_(1, &renderfb); renderfb = 0; } if(renderdb) { glDeleteRenderbuffers_(1, &renderdb); renderdb = 0; } if(rendertex) { glDeleteTextures(1, &rendertex); rendertex = 0; } texw = texh = 0; cleanupblur(); - if(fullclean) colorfmt = depthfmt = GL_FALSE; } - - void cleanupblur() - { + void cleanupblur() { if(blurfb) { glDeleteFramebuffers_(1, &blurfb); blurfb = 0; } if(blurtex) { glDeleteTextures(1, &blurtex); blurtex = 0; } if(blurdb) { glDeleteRenderbuffers_(1, &blurdb); blurdb = 0; } blursize = blurysize = 0; blursigma = 0.0f; } - - void setupblur() - { + void setupblur() { if(!blurtex) glGenTextures(1, &blurtex); createtexture(blurtex, texw, texh, NULL, 3, 1, colorfmt); - if(!swaptexs() || rtsharefb) return; if(!blurfb) glGenFramebuffers_(1, &blurfb); glBindFramebuffer_(GL_FRAMEBUFFER, blurfb); glFramebufferTexture2D_(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blurtex, 0); - if(depthtest()) - { + if(depthtest()) { if(!blurdb) glGenRenderbuffers_(1, &blurdb); glGenRenderbuffers_(1, &blurdb); glBindRenderbuffer_(GL_RENDERBUFFER, blurdb); @@ -81,39 +59,30 @@ struct rendertarget } glBindFramebuffer_(GL_FRAMEBUFFER, 0); } - - void setup(int w, int h) - { + void setup(int w, int h) { if(!renderfb) glGenFramebuffers_(1, &renderfb); glBindFramebuffer_(GL_FRAMEBUFFER, renderfb); if(!rendertex) glGenTextures(1, &rendertex); - GLenum attach = attachment(); - if(attach == GL_DEPTH_ATTACHMENT) - { + if(attach == GL_DEPTH_ATTACHMENT) { glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); } - const GLenum *colorfmts = colorformats(); int find = 0; - do - { + do { createtexture(rendertex, w, h, NULL, 3, filter() ? 1 : 0, colorfmt ? colorfmt : colorfmts[find]); glFramebufferTexture2D_(GL_FRAMEBUFFER, attach, GL_TEXTURE_2D, rendertex, 0); if(glCheckFramebufferStatus_(GL_FRAMEBUFFER)==GL_FRAMEBUFFER_COMPLETE) break; } while(!colorfmt && colorfmts[++find]); if(!colorfmt) colorfmt = colorfmts[find]; - - if(attach != GL_DEPTH_ATTACHMENT && depthtest()) - { + if(attach != GL_DEPTH_ATTACHMENT && depthtest()) { if(!renderdb) { glGenRenderbuffers_(1, &renderdb); depthfmt = GL_FALSE; } if(!depthfmt) glBindRenderbuffer_(GL_RENDERBUFFER, renderdb); const GLenum *depthfmts = depthformats(); find = 0; - do - { + do { if(!depthfmt) glRenderbufferStorage_(GL_RENDERBUFFER, depthfmts[find], w, h); glFramebufferRenderbuffer_(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderdb); if(glCheckFramebufferStatus_(GL_FRAMEBUFFER)==GL_FRAMEBUFFER_COMPLETE) break; @@ -121,72 +90,53 @@ struct rendertarget while(!depthfmt && depthfmts[++find]); if(!depthfmt) depthfmt = depthfmts[find]; } - glBindFramebuffer_(GL_FRAMEBUFFER, 0); - texw = w; texh = h; initialized = false; } - - bool addblurtiles(float x1, float y1, float x2, float y2, float blurmargin = 0) - { + bool addblurtiles(float x1, float y1, float x2, float y2, float blurmargin = 0) { if(x1 >= 1 || y1 >= 1 || x2 <= -1 || y2 <= -1) return false; - scissorx1 = min(scissorx1, max(x1, -1.0f)); scissory1 = min(scissory1, max(y1, -1.0f)); scissorx2 = max(scissorx2, min(x2, 1.0f)); scissory2 = max(scissory2, min(y2, 1.0f)); - float blurerror = 2.0f*float(2*blursize + blurmargin); int tx1 = max(0, min(BLURTILES - 1, int((x1-blurerror/vieww + 1)/2 * BLURTILES))), ty1 = max(0, min(BLURTILES - 1, int((y1-blurerror/viewh + 1)/2 * BLURTILES))), tx2 = max(0, min(BLURTILES - 1, int((x2+blurerror/vieww + 1)/2 * BLURTILES))), ty2 = max(0, min(BLURTILES - 1, int((y2+blurerror/viewh + 1)/2 * BLURTILES))); - uint mask = (BLURTILEMASK>>(BLURTILES - (tx2+1))) & (BLURTILEMASK<<tx1); for(int y = ty1; y <= ty2; y++) blurtiles[y] |= mask; return true; } - - bool checkblurtiles(float x1, float y1, float x2, float y2, float blurmargin = 0) - { + bool checkblurtiles(float x1, float y1, float x2, float y2, float blurmargin = 0) { float blurerror = 2.0f*float(2*blursize + blurmargin); if(x2+blurerror/vieww < scissorx1 || y2+blurerror/viewh < scissory1 || x1-blurerror/vieww > scissorx2 || y1-blurerror/viewh > scissory2) return false; - if(!blurtile) return true; - int tx1 = max(0, min(BLURTILES - 1, int((x1 + 1)/2 * BLURTILES))), ty1 = max(0, min(BLURTILES - 1, int((y1 + 1)/2 * BLURTILES))), tx2 = max(0, min(BLURTILES - 1, int((x2 + 1)/2 * BLURTILES))), ty2 = max(0, min(BLURTILES - 1, int((y2 + 1)/2 * BLURTILES))); - uint mask = (BLURTILEMASK>>(BLURTILES - (tx2+1))) & (BLURTILEMASK<<tx1); for(int y = ty1; y <= ty2; y++) if(blurtiles[y] & mask) return true; - return false; } - - void rendertiles() - { + void rendertiles() { float wscale = vieww/float(texw), hscale = viewh/float(texh); - if(blurtile && scissorx1 < scissorx2 && scissory1 < scissory2) - { + if(blurtile && scissorx1 < scissorx2 && scissory1 < scissory2) { uint tiles[sizeof(blurtiles)/sizeof(uint)]; memcpy(tiles, blurtiles, sizeof(blurtiles)); - LOCALPARAMF(screentexcoord0, wscale*0.5f, hscale*0.5f, wscale*0.5f, hscale*0.5f); gle::defvertex(2); gle::begin(GL_QUADS); float tsz = 1.0f/BLURTILES; - loop(y, BLURTILES+1) - { + loop(y, BLURTILES+1) { uint mask = tiles[y]; int x = 0; - while(mask) - { + while(mask) { while(!(mask&0xFF)) { mask >>= 8; x += 8; } while(!(mask&1)) { mask >>= 1; x++; } int xstart = x; @@ -207,71 +157,49 @@ struct rendertarget } gle::end(); } - else - { + else { screenquad(wscale, hscale); } } - - void blur(int wantsblursize, float wantsblursigma, int wantsblurysize, int x, int y, int w, int h, bool scissor) - { + void blur(int wantsblursize, float wantsblursigma, int wantsblurysize, int x, int y, int w, int h, bool scissor) { if(!blurtex) setupblur(); - if(blursize!=wantsblursize || blurysize != wantsblurysize || (wantsblursize && blursigma!=wantsblursigma)) - { + if(blursize!=wantsblursize || blurysize != wantsblurysize || (wantsblursize && blursigma!=wantsblursigma)) { setupblurkernel(wantsblursize, wantsblursigma, blurweights, bluroffsets); if(wantsblurysize != wantsblursize) setupblurkernel(wantsblurysize, wantsblursigma, bluryweights, bluryoffsets); blursize = wantsblursize; blursigma = wantsblursigma; blurysize = wantsblurysize; } - glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); - - if(scissor) - { + if(scissor) { glScissor(x, y, w, h); glEnable(GL_SCISSOR_TEST); } - - loopi(2) - { + loopi(2) { if(i && blurysize != blursize) setblurshader(i, texh, blurysize, bluryweights, bluryoffsets); else setblurshader(i, i ? texh : texw, blursize, blurweights, bluroffsets); - if(!swaptexs() || rtsharefb) glFramebufferTexture2D_(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, i ? rendertex : blurtex, 0); else glBindFramebuffer_(GL_FRAMEBUFFER, i ? renderfb : blurfb); glBindTexture(GL_TEXTURE_2D, i ? blurtex : rendertex); - rendertiles(); } - if(scissor) glDisable(GL_SCISSOR_TEST); - glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); } - virtual bool swaptexs() const { return false; } - virtual bool dorender() { return true; } - virtual bool shouldrender() { return true; } - - virtual void doblur(int blursize, float blursigma, int blurysize) - { + virtual void doblur(int blursize, float blursigma, int blurysize) { int sx, sy, sw, sh; bool scissoring = rtscissor && scissorblur(sx, sy, sw, sh) && sw > 0 && sh > 0; if(!scissoring) { sx = sy = 0; sw = vieww; sh = viewh; } blur(blursize, blursigma, blurysize, sx, sy, sw, sh, scissoring); } - - virtual bool scissorrender(int &x, int &y, int &w, int &h) - { - if(scissorx1 >= scissorx2 || scissory1 >= scissory2) - { - if(vieww < texw || viewh < texh) - { + virtual bool scissorrender(int &x, int &y, int &w, int &h) { + if(scissorx1 >= scissorx2 || scissory1 >= scissory2) { + if(vieww < texw || viewh < texh) { x = y = 0; w = vieww; h = viewh; @@ -285,13 +213,9 @@ struct rendertarget h = min(int(ceil((scissory2+1)/2*viewh)) + 2*blursize, viewh) - y; return true; } - - virtual bool scissorblur(int &x, int &y, int &w, int &h) - { - if(scissorx1 >= scissorx2 || scissory1 >= scissory2) - { - if(vieww < texw || viewh < texh) - { + virtual bool scissorblur(int &x, int &y, int &w, int &h) { + if(scissorx1 >= scissorx2 || scissory1 >= scissory2) { + if(vieww < texw || viewh < texh) { x = y = 0; w = vieww; h = viewh; @@ -305,45 +229,32 @@ struct rendertarget h = min(int(ceil((scissory2+1)/2*viewh)), viewh) - y; return true; } - virtual void doclear() {} - virtual bool screenrect() const { return false; } virtual bool filter() const { return true; } - - void render(int w, int h, int blursize = 0, float blursigma = 0, int blurysize = 0) - { + void render(int w, int h, int blursize = 0, float blursigma = 0, int blurysize = 0) { w = min(w, hwtexsize); h = min(h, hwtexsize); - if(screenrect()) - { + if(screenrect()) { if(w > screenw) w = screenw; if(h > screenh) h = screenh; } vieww = w; viewh = h; if(w!=texw || h!=texh || (swaptexs() && !rtsharefb ? !blurfb : blurfb)) cleanup(); - - if(!filter()) - { + if(!filter()) { if(blurtex) cleanupblur(); blursize = blurysize = 0; } - if(!rendertex) setup(w, h); - scissorx2 = scissory2 = -1; scissorx1 = scissory1 = 1; memset(blurtiles, 0, sizeof(blurtiles)); - if(!shouldrender()) return; - if(blursize && !blurtex) setupblur(); - if(swaptexs() && blursize) - { + if(swaptexs() && blursize) { swap(rendertex, blurtex); - if(!rtsharefb) - { + if(!rtsharefb) { swap(renderfb, blurfb); swap(renderdb, blurdb); } @@ -352,38 +263,26 @@ struct rendertarget if(swaptexs() && blursize && rtsharefb) glFramebufferTexture2D_(GL_FRAMEBUFFER, attachment(), GL_TEXTURE_2D, rendertex, 0); glViewport(0, 0, vieww, viewh); - doclear(); - int sx, sy, sw, sh; bool scissoring = rtscissor && scissorrender(sx, sy, sw, sh) && sw > 0 && sh > 0; - if(scissoring) - { + if(scissoring) { glScissor(sx, sy, sw, sh); glEnable(GL_SCISSOR_TEST); } - else - { + else { sx = sy = 0; sw = vieww; sh = viewh; } - if(!depthtest()) glDisable(GL_DEPTH_TEST); - bool succeeded = dorender(); - if(!depthtest()) glEnable(GL_DEPTH_TEST); - if(scissoring) glDisable(GL_SCISSOR_TEST); - - if(succeeded) - { + if(succeeded) { initialized = true; - if(blursize) doblur(blursize, blursigma, blurysize ? blurysize : blursize); } - glBindFramebuffer_(GL_FRAMEBUFFER, 0); glViewport(0, 0, screenw, screenh); } diff --git a/src/engine/rendertext.cpp b/src/engine/rendertext.cpp index 925e1a8..3fd4dc8 100644 --- a/src/engine/rendertext.cpp +++ b/src/engine/rendertext.cpp @@ -7,8 +7,7 @@ static int fontdeftex = 0; font *curfont = NULL; int curfonttex = 0; -void newfont(char *name, char *tex, int *defaultw, int *defaulth) -{ +void newfont(char *name, char *tex, int *defaultw, int *defaulth) { font *f = &fonts[name]; if(!f->name) f->name = newstring(name); f->texs.shrink(0); @@ -18,39 +17,30 @@ void newfont(char *name, char *tex, int *defaultw, int *defaulth) f->defaultw = *defaultw; f->defaulth = *defaulth; f->scale = f->defaulth; - fontdef = f; fontdeftex = 0; } -void fontoffset(char *c) -{ +void fontoffset(char *c) { if(!fontdef) return; - fontdef->charoffset = c[0]; } -void fontscale(int *scale) -{ +void fontscale(int *scale) { if(!fontdef) return; - fontdef->scale = *scale > 0 ? *scale : fontdef->defaulth; } -void fonttex(char *s) -{ +void fonttex(char *s) { if(!fontdef) return; - Texture *t = textureload(s); loopv(fontdef->texs) if(fontdef->texs[i] == t) { fontdeftex = i; return; } fontdeftex = fontdef->texs.length(); fontdef->texs.add(t); } -void fontchar(int *x, int *y, int *w, int *h, int *offsetx, int *offsety, int *advance) -{ +void fontchar(int *x, int *y, int *w, int *h, int *offsetx, int *offsety, int *advance) { if(!fontdef) return; - font::charinfo &c = fontdef->chars.add(); c.x = *x; c.y = *y; @@ -62,11 +52,9 @@ void fontchar(int *x, int *y, int *w, int *h, int *offsetx, int *offsety, int *a c.tex = fontdeftex; } -void fontskip(int *n) -{ +void fontskip(int *n) { if(!fontdef) return; - loopi(max(*n, 1)) - { + loopi(max(*n, 1)) { font::charinfo &c = fontdef->chars.add(); c.x = c.y = c.w = c.h = c.offsetx = c.offsety = c.advance = c.tex = 0; } @@ -79,8 +67,7 @@ COMMAND(fonttex, "s"); COMMAND(fontchar, "iiiiiii"); COMMAND(fontskip, "i"); -void fontalias(const char *dst, const char *src) -{ +void fontalias(const char *dst, const char *src) { font *s = fonts.access(src); if(!s) return; font *d = &fonts[dst]; @@ -91,15 +78,13 @@ void fontalias(const char *dst, const char *src) d->defaultw = s->defaultw; d->defaulth = s->defaulth; d->scale = s->scale; - fontdef = d; fontdeftex = d->texs.length()-1; } COMMAND(fontalias, "ss"); -bool setfont(const char *name) -{ +bool setfont(const char *name) { font *f = fonts.access(name); if(!f) return false; curfont = f; @@ -108,37 +93,30 @@ bool setfont(const char *name) static vector<font *> fontstack; -void pushfont() -{ +void pushfont() { fontstack.add(curfont); } -bool popfont() -{ +bool popfont() { if(fontstack.empty()) return false; curfont = fontstack.pop(); return true; } -void gettextres(int &w, int &h) -{ - if(w < MINRESW || h < MINRESH) - { - if(MINRESW > w*MINRESH/h) - { +void gettextres(int &w, int &h) { + if(w < MINRESW || h < MINRESH) { + if(MINRESW > w*MINRESH/h) { h = h*MINRESW/w; w = MINRESW; } - else - { + else { w = w*MINRESH/h; h = MINRESH; } } } -float text_widthf(const char *str) -{ +float text_widthf(const char *str) { float width, height; text_boundsf(str, width, height); return width; @@ -147,8 +125,7 @@ float text_widthf(const char *str) #define FONTTAB (4*FONTW) #define TEXTTAB(x) ((int((x)/FONTTAB)+1.0f)*FONTTAB) -void tabify(const char *str, int *numtabs) -{ +void tabify(const char *str, int *numtabs) { int tw = max(*numtabs, 0)*FONTTAB-1, tabs = 0; for(float w = text_widthf(str); w <= tw; w = TEXTTAB(w)) ++tabs; int len = strlen(str); @@ -161,24 +138,20 @@ void tabify(const char *str, int *numtabs) COMMAND(tabify, "si"); -void draw_textf(const char *fstr, int left, int top, ...) -{ +void draw_textf(const char *fstr, int left, int top, ...) { defvformatstring(str, top, fstr); draw_text(str, left, top); } const matrix4x3 *textmatrix = NULL; -static float draw_char(Texture *&tex, int c, float x, float y, float scale) -{ +static float draw_char(Texture *&tex, int c, float x, float y, float scale) { font::charinfo &info = curfont->chars[c-curfont->charoffset]; - if(tex != curfont->texs[info.tex]) - { + if(tex != curfont->texs[info.tex]) { xtraverts += gle::end(); tex = curfont->texs[info.tex]; glBindTexture(GL_TEXTURE_2D, tex->id); } - float x1 = x + scale*info.offsetx, y1 = y + scale*info.offsety, x2 = x + scale*(info.offsetx + info.w), @@ -187,40 +160,31 @@ static float draw_char(Texture *&tex, int c, float x, float y, float scale) ty1 = info.y / float(tex->ys), tx2 = (info.x + info.w) / float(tex->xs), ty2 = (info.y + info.h) / float(tex->ys); - - if(textmatrix) - { + if(textmatrix) { gle::attrib(textmatrix->transform(vec2(x1, y1))); gle::attribf(tx1, ty1); gle::attrib(textmatrix->transform(vec2(x2, y1))); gle::attribf(tx2, ty1); gle::attrib(textmatrix->transform(vec2(x2, y2))); gle::attribf(tx2, ty2); gle::attrib(textmatrix->transform(vec2(x1, y2))); gle::attribf(tx1, ty2); } - else - { + else { gle::attribf(x1, y1); gle::attribf(tx1, ty1); gle::attribf(x2, y1); gle::attribf(tx2, ty1); gle::attribf(x2, y2); gle::attribf(tx2, ty2); gle::attribf(x1, y2); gle::attribf(tx1, ty2); } - return scale*info.advance; } //stack[sp] is current color index -static void text_color(char c, char *stack, int size, int &sp, bvec color, int a) -{ - if(c=='s') // save color - { +static void text_color(char c, char *stack, int size, int &sp, bvec color, int a) { + if(c=='s') { // save color { c = stack[sp]; if(sp<size-1) stack[++sp] = c; - } - else - { + } else { xtraverts += gle::end(); if(c=='r') { if(sp > 0) --sp; c = stack[sp]; } // restore color else stack[sp] = c; - switch(c) - { + switch(c) { case '0': color = bvec( 64, 255, 128); break; // green: player talk case '1': color = bvec( 96, 160, 255); break; // blue: "echo" command case '2': color = bvec(255, 192, 64); break; // yellow: gameplay messages @@ -239,24 +203,21 @@ static void text_color(char c, char *stack, int size, int &sp, bvec color, int a #define TEXTSKELETON \ float y = 0, x = 0, scale = curfont->scale/float(curfont->defaulth);\ int i;\ - for(i = 0; str[i]; i++)\ - {\ + for(i = 0; str[i]; i++) { \ TEXTINDEX(i)\ int c = uchar(str[i]);\ - if(c=='\t') { x = TEXTTAB(x); TEXTWHITE(i) }\ - else if(c==' ') { x += scale*curfont->defaultw; TEXTWHITE(i) }\ + if(c=='\t') { x = TEXTTAB(x); TEXTWHITE(i) }\ + else if(c==' ') { x += scale*curfont->defaultw; TEXTWHITE(i) }\ else if(c=='\n') { TEXTLINE(i) x = 0; y += FONTH; }\ else if(c=='\f') { if(str[i+1]) { i++; TEXTCOLOR(i) }}\ - else if(curfont->chars.inrange(c-curfont->charoffset))\ - {\ + else if(curfont->chars.inrange(c-curfont->charoffset)) {\ float cw = scale*curfont->chars[c-curfont->charoffset].advance;\ if(cw <= 0) continue;\ - if(maxwidth != -1)\ - {\ + if(maxwidth != -1) {\ int j = i;\ float w = cw;\ - for(; str[i+1]; i++)\ - {\ + for(; str[i+1]; i++) {\ + \ int c = uchar(str[i+1]);\ if(c=='\f') { if(str[i+2]) i++; continue; }\ if(i-j > 16) break;\ @@ -268,15 +229,15 @@ static void text_color(char c, char *stack, int size, int &sp, bvec color, int a if(x + w > maxwidth && j!=0) { TEXTLINE(j-1) x = 0; y += FONTH; }\ TEXTWORD\ }\ - else\ - { TEXTCHAR(i) }\ + else{ \ + TEXTCHAR(i) }\ }\ } //all the chars are guaranteed to be either drawable or color commands #define TEXTWORDSKELETON \ - for(; j <= i; j++)\ - {\ + for(; j <= i; j++){ \ + \ TEXTINDEX(j)\ int c = uchar(str[j]);\ if(c=='\f') { if(str[j+1]) { j++; TEXTCOLOR(j) }}\ @@ -285,8 +246,7 @@ static void text_color(char c, char *stack, int size, int &sp, bvec color, int a #define TEXTEND(cursor) if(cursor >= i) { do { TEXTINDEX(cursor); } while(0); } -int text_visible(const char *str, float hitx, float hity, int maxwidth) -{ +int text_visible(const char *str, float hitx, float hity, int maxwidth) { #define TEXTINDEX(idx) #define TEXTWHITE(idx) if(y+FONTH > hity && x >= hitx) return idx; #define TEXTLINE(idx) if(y+FONTH > hity) return idx; @@ -304,8 +264,7 @@ int text_visible(const char *str, float hitx, float hity, int maxwidth) } //inverse of text_visible -void text_posf(const char *str, int cursor, float &cx, float &cy, int maxwidth) -{ +void text_posf(const char *str, int cursor, float &cx, float &cy, int maxwidth) { #define TEXTINDEX(idx) if(idx == cursor) { cx = x; cy = y; break; } #define TEXTWHITE(idx) #define TEXTLINE(idx) @@ -323,8 +282,7 @@ void text_posf(const char *str, int cursor, float &cx, float &cy, int maxwidth) #undef TEXTWORD } -void text_boundsf(const char *str, float &width, float &height, int maxwidth) -{ +void text_boundsf(const char *str, float &width, float &height, int maxwidth) { #define TEXTINDEX(idx) #define TEXTWHITE(idx) #define TEXTLINE(idx) if(x > width) width = x; @@ -343,8 +301,7 @@ void text_boundsf(const char *str, float &width, float &height, int maxwidth) #undef TEXTWORD } -void draw_text(const char *str, int left, int top, int r, int g, int b, int a, int cursor, int maxwidth) -{ +void draw_text(const char *str, int left, int top, int r, int g, int b, int a, int cursor, int maxwidth) { #define TEXTINDEX(idx) if(idx == cursor) { cx = x; cy = y; } #define TEXTWHITE(idx) #define TEXTLINE(idx) @@ -368,8 +325,7 @@ void draw_text(const char *str, int left, int top, int r, int g, int b, int a, i TEXTSKELETON TEXTEND(cursor) xtraverts += gle::end(); - if(cursor >= 0 && (totalmillis/250)&1) - { + if(cursor >= 0 && (totalmillis/250)&1) { gle::color(color, a); if(maxwidth != -1 && cx >= maxwidth) { cx = 0; cy += FONTH; } draw_char(tex, '_', left+cx, top+cy, scale); @@ -383,8 +339,7 @@ void draw_text(const char *str, int left, int top, int r, int g, int b, int a, i #undef TEXTWORD } -void reloadfonts() -{ +void reloadfonts() { enumerate(fonts, font, f, loopv(f.texs) if(!reloadtexture(*f.texs[i])) fatal("failed to reload font texture"); ); diff --git a/src/engine/renderva.cpp b/src/engine/renderva.cpp index 1e33702..cc0b65d 100644 --- a/src/engine/renderva.cpp +++ b/src/engine/renderva.cpp @@ -2,14 +2,12 @@ #include "engine.h" -static inline void drawtris(GLsizei numindices, const GLvoid *indices, ushort minvert, ushort maxvert) -{ +static inline void drawtris(GLsizei numindices, const GLvoid *indices, ushort minvert, ushort maxvert) { glDrawRangeElements_(GL_TRIANGLES, minvert, maxvert, numindices, GL_UNSIGNED_SHORT, indices); glde++; } -static inline void drawvatris(vtxarray *va, GLsizei numindices, const GLvoid *indices) -{ +static inline void drawvatris(vtxarray *va, GLsizei numindices, const GLvoid *indices) { drawtris(numindices, indices, va->minvert, va->maxvert); } @@ -20,48 +18,36 @@ float vfcDnear[5], vfcDfar[5]; vtxarray *visibleva; -int isvisiblesphere(float rad, const vec &cv) -{ +int isvisiblesphere(float rad, const vec &cv) { int v = VFC_FULL_VISIBLE; float dist; - - loopi(5) - { + loopi(5) { dist = vfcP[i].dist(cv); if(dist < -rad) return VFC_NOT_VISIBLE; if(dist < rad) v = VFC_PART_VISIBLE; } - if(dist > -rad) v = VFC_PART_VISIBLE; - return v; } -static inline int ishiddencube(const ivec &o, int size) -{ +static inline int ishiddencube(const ivec &o, int size) { loopi(5) if(o.dist(vfcP[i]) < -vfcDfar[i]*size) return true; return false; } -int isvisiblecube(const ivec &o, int size) -{ +int isvisiblecube(const ivec &o, int size) { int v = VFC_FULL_VISIBLE; float dist; - - loopi(5) - { + loopi(5) { dist = o.dist(vfcP[i]); if(dist < -vfcDfar[i]*size) return VFC_NOT_VISIBLE; if(dist < -vfcDnear[i]*size) v = VFC_PART_VISIBLE; } - if(dist > -vfcDfar[4]*size) v = VFC_PART_VISIBLE; - return v; } -float vadist(vtxarray *va, const vec &p) -{ +float vadist(vtxarray *va, const vec &p) { return p.dist_to_bb(va->bbmin, va->bbmax); } @@ -69,30 +55,23 @@ float vadist(vtxarray *va, const vec &p) static vtxarray *vasort[VASORTSIZE]; -void addvisibleva(vtxarray *va) -{ +void addvisibleva(vtxarray *va) { float dist = vadist(va, camera1->o); va->distance = int(dist); /*cv.dist(camera1->o) - va->size*SQRT3/2*/ - int hash = clamp(int(dist*VASORTSIZE/worldsize), 0, VASORTSIZE-1); vtxarray **prev = &vasort[hash], *cur = vasort[hash]; - - while(cur && va->distance >= cur->distance) - { + while(cur && va->distance >= cur->distance) { prev = &cur->next; cur = cur->next; } - va->next = *prev; *prev = va; } -void sortvisiblevas() -{ +void sortvisiblevas() { visibleva = NULL; vtxarray **last = &visibleva; - loopi(VASORTSIZE) if(vasort[i]) - { + loopi(VASORTSIZE) if(vasort[i]) { vtxarray *va = vasort[i]; *last = va; while(va->next) va = va->next; @@ -100,19 +79,15 @@ void sortvisiblevas() } } -void findvisiblevas(vector<vtxarray *> &vas, bool resetocclude = false) -{ - loopv(vas) - { +void findvisiblevas(vector<vtxarray *> &vas, bool resetocclude = false) { + loopv(vas) { vtxarray &v = *vas[i]; int prevvfc = resetocclude ? (int) VFC_NOT_VISIBLE : (int) v.curvfc; v.curvfc = isvisiblecube(v.o, v.size); - if(v.curvfc!=VFC_NOT_VISIBLE) - { + if(v.curvfc!=VFC_NOT_VISIBLE) { addvisibleva(&v); if(v.children.length()) findvisiblevas(v.children, prevvfc>=VFC_NOT_VISIBLE); - if(prevvfc>=VFC_NOT_VISIBLE) - { + if(prevvfc>=VFC_NOT_VISIBLE) { v.occluded = !v.texs ? OCCLUDE_GEOM : OCCLUDE_NOTHING; v.query = NULL; } @@ -120,10 +95,8 @@ void findvisiblevas(vector<vtxarray *> &vas, bool resetocclude = false) } } -void calcvfcD() -{ - loopi(5) - { +void calcvfcD() { + loopi(5) { plane &p = vfcP[i]; vfcDnear[i] = vfcDfar[i] = 0; loopk(3) if(p[k] > 0) vfcDfar[i] += p[k]; @@ -131,8 +104,7 @@ void calcvfcD() } } -void setvfcP(float z, const vec &bbmin, const vec &bbmax) -{ +void setvfcP(float z, const vec &bbmin, const vec &bbmax) { vec4 px = camprojmatrix.rowx(), py = camprojmatrix.rowy(), pz = camprojmatrix.rowz(), pw = camprojmatrix.roww(); vfcP[0] = plane(vec4(pw).mul(-bbmin.x).add(px)).normalize(); // left plane vfcP[1] = plane(vec4(pw).mul(bbmax.x).sub(px)).normalize(); // right plane @@ -140,41 +112,33 @@ void setvfcP(float z, const vec &bbmin, const vec &bbmax) vfcP[3] = plane(vec4(pw).mul(bbmax.y).sub(py)).normalize(); // top plane vfcP[4] = plane(vec4(pw).add(pz)).normalize(); // near/far planes if(z >= 0) loopi(5) vfcP[i].reflectz(z); - calcvfcD(); } plane oldvfcP[5]; -void savevfcP() -{ +void savevfcP() { memcpy(oldvfcP, vfcP, sizeof(vfcP)); } -void restorevfcP() -{ +void restorevfcP() { memcpy(vfcP, oldvfcP, sizeof(vfcP)); calcvfcD(); } -void visiblecubes(bool cull) -{ +void visiblecubes(bool cull) { memclear(vasort); - - if(cull) - { + if(cull) { setvfcP(); findvisiblevas(varoot); sortvisiblevas(); } - else - { + else { memclear(vfcP); memclear(vfcDnear); memclear(vfcDfar); visibleva = NULL; - loopv(valist) - { + loopv(valist) { vtxarray *va = valist[i]; va->distance = 0; va->curvfc = VFC_FULL_VISIBLE; @@ -186,8 +150,7 @@ void visiblecubes(bool cull) } } -static inline bool insideva(const vtxarray *va, const vec &v, int margin = 2) -{ +static inline bool insideva(const vtxarray *va, const vec &v, int margin = 2) { int size = va->size + margin; return v.x>=va->o.x-margin && v.y>=va->o.y-margin && v.z>=va->o.z-margin && v.x<=va->o.x+size && v.y<=va->o.y+size && v.z<=va->o.z+size; @@ -198,19 +161,13 @@ static inline bool insideva(const vtxarray *va, const vec &v, int margin = 2) #define MAXQUERY 2048 #define MAXQUERYFRAMES 2 -struct queryframe -{ +struct queryframe { int cur, max; occludequery queries[MAXQUERY]; - queryframe() : cur(0), max(0) {} - void flip() { loopi(cur) queries[i].owner = NULL; cur = 0; } - - occludequery *newquery(void *owner) - { - if(cur >= max) - { + occludequery *newquery(void *owner) { + if(cur >= max) { if(max >= MAXQUERY) return NULL; glGenQueries_(1, &queries[max++].id); } @@ -219,13 +176,9 @@ struct queryframe query->fragments = -1; return query; } - void reset() { loopi(max) queries[i].owner = NULL; } - - void cleanup() - { - loopi(max) - { + void cleanup() { + loopi(max) { glDeleteQueries_(1, &queries[i].id); queries[i].owner = NULL; } @@ -236,53 +189,43 @@ struct queryframe static queryframe queryframes[MAXQUERYFRAMES]; static uint flipquery = 0; -int getnumqueries() -{ +int getnumqueries() { return queryframes[flipquery].cur; } -void flipqueries() -{ +void flipqueries() { flipquery = (flipquery + 1) % MAXQUERYFRAMES; queryframes[flipquery].flip(); } -occludequery *newquery(void *owner) -{ +occludequery *newquery(void *owner) { return queryframes[flipquery].newquery(owner); } -void resetqueries() -{ +void resetqueries() { loopi(MAXQUERYFRAMES) queryframes[i].reset(); } -void clearqueries() -{ +void clearqueries() { loopi(MAXQUERYFRAMES) queryframes[i].cleanup(); } VAR(oqfrags, 0, 8, 64); VAR(oqwait, 0, 1, 1); -void startquery(occludequery *query) -{ +void startquery(occludequery *query) { glBeginQuery_(GL_SAMPLES_PASSED, query->id); } -void endquery(occludequery *query) -{ +void endquery(occludequery *query) { glEndQuery_(GL_SAMPLES_PASSED); } -bool checkquery(occludequery *query, bool nowait) -{ +bool checkquery(occludequery *query, bool nowait) { GLuint fragments; if(query->fragments >= 0) fragments = query->fragments; - else - { - if(nowait || !oqwait) - { + else { + if(nowait || !oqwait) { GLint avail; glGetQueryObjectiv_(query->id, GL_QUERY_RESULT_AVAILABLE, &avail); if(!avail) return false; @@ -295,10 +238,8 @@ bool checkquery(occludequery *query, bool nowait) static GLuint bbvbo = 0, bbebo = 0; -static void setupbb() -{ - if(!bbvbo) - { +static void setupbb() { + if(!bbvbo) { glGenBuffers_(1, &bbvbo); gle::bindvbo(bbvbo); vec verts[8]; @@ -306,8 +247,7 @@ static void setupbb() glBufferData_(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); gle::clearvbo(); } - if(!bbebo) - { + if(!bbebo) { glGenBuffers_(1, &bbebo); gle::bindebo(bbebo); GLushort tris[3*2*6]; @@ -329,41 +269,35 @@ static void setupbb() } } -static void cleanupbb() -{ +static void cleanupbb() { if(bbvbo) { glDeleteBuffers_(1, &bbvbo); bbvbo = 0; } if(bbebo) { glDeleteBuffers_(1, &bbebo); bbebo = 0; } } -void startbb(bool mask) -{ +void startbb(bool mask) { setupbb(); gle::bindvbo(bbvbo); gle::bindebo(bbebo); gle::vertexpointer(sizeof(vec), (const vec *)0); gle::enablevertex(); SETSHADER(bbquery); - if(mask) - { + if(mask) { glDepthMask(GL_FALSE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } } -void endbb(bool mask) -{ +void endbb(bool mask) { gle::disablevertex(); gle::clearvbo(); gle::clearebo(); - if(mask) - { + if(mask) { glDepthMask(GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } } -void drawbb(const ivec &bo, const ivec &br) -{ +void drawbb(const ivec &bo, const ivec &br) { LOCALPARAMF(bborigin, bo.x, bo.y, bo.z); LOCALPARAMF(bbsize, br.x, br.y, br.z); glDrawRangeElements_(GL_TRIANGLES, 0, 8-1, 3*2*6, GL_UNSIGNED_SHORT, (ushort *)0); @@ -374,53 +308,40 @@ extern int octaentsize; static octaentities *visiblemms, **lastvisiblemms; -static inline bool insideoe(const octaentities *oe, const vec &v, int margin = 1) -{ +static inline bool insideoe(const octaentities *oe, const vec &v, int margin = 1) { return v.x>=oe->bbmin.x-margin && v.y>=oe->bbmin.y-margin && v.z>=oe->bbmin.z-margin && v.x<=oe->bbmax.x+margin && v.y<=oe->bbmax.y+margin && v.z<=oe->bbmax.z+margin; } -void findvisiblemms(const vector<extentity *> &ents, bool doquery) -{ +void findvisiblemms(const vector<extentity *> &ents, bool doquery) { visiblemms = NULL; lastvisiblemms = &visiblemms; - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(va->mapmodels.empty() || va->occluded >= OCCLUDE_BB) continue; - loopv(va->mapmodels) - { + loopv(va->mapmodels) { octaentities *oe = va->mapmodels[i]; - bool occluded = doquery && oe->query && oe->query->owner == oe && checkquery(oe->query); - if(occluded) - { + if(occluded) { oe->distance = -1; - oe->next = NULL; *lastvisiblemms = oe; lastvisiblemms = &oe->next; } - else - { + else { int visible = 0; - loopv(oe->mapmodels) - { + loopv(oe->mapmodels) { extentity &e = *ents[oe->mapmodels[i]]; if(e.flags&EF_NOVIS) continue; e.flags |= EF_RENDER; ++visible; } if(!visible) continue; - oe->distance = int(camera1->o.dist_to_bb(oe->o, oe->size)); - octaentities **prev = &visiblemms, *cur = visiblemms; - while(cur && cur->distance >= 0 && oe->distance > cur->distance) - { + while(cur && cur->distance >= 0 && oe->distance > cur->distance) { prev = &cur->next; cur = cur->next; } - if(*prev == NULL) lastvisiblemms = &oe->next; oe->next = *prev; *prev = oe; @@ -431,30 +352,24 @@ void findvisiblemms(const vector<extentity *> &ents, bool doquery) VAR(oqmm, 0, 4, 8); -void rendermapmodel(extentity &e) -{ +void rendermapmodel(extentity &e) { int anim = ANIM_MAPMODEL|ANIM_LOOP, basetime = 0; mapmodelinfo *mmi = getmminfo(e.attr2); if(mmi) rendermodel(&e.light, mmi->name, anim, e.o, e.attr1, 0, MDL_CULL_VFC | MDL_CULL_DIST | MDL_DYNLIGHT, NULL, NULL, basetime); } -void rendermapmodels() -{ +void rendermapmodels() { static int skipoq = 0; bool doquery = !drawtex && oqfrags && oqmm; const vector<extentity *> &ents = entities::getents(); findvisiblemms(ents, doquery); - startmodelbatches(); - for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance>=0) - { + for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance>=0) { bool rendered = false; - loopv(oe->mapmodels) - { + loopv(oe->mapmodels) { extentity &e = *ents[oe->mapmodels[i]]; if(!(e.flags&EF_RENDER)) continue; - if(!rendered) - { + if(!rendered) { rendered = true; oe->query = doquery && oe->distance>0 && !(++skipoq%oqmm) ? newquery(oe) : NULL; if(oe->query) startmodelquery(oe->query); @@ -465,14 +380,11 @@ void rendermapmodels() if(rendered && oe->query) endmodelquery(); } endmodelbatches(); - bool queried = true; - for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance<0) - { + for(octaentities *oe = visiblemms; oe; oe = oe->next) if(oe->distance<0) { oe->query = doquery && !insideoe(oe, camera1->o) ? newquery(oe) : NULL; if(!oe->query) continue; - if(queried) - { + if(queried) { startbb(); queried = false; } @@ -480,25 +392,20 @@ void rendermapmodels() drawbb(oe->bbmin, ivec(oe->bbmax).sub(oe->bbmin)); endquery(oe->query); } - if(!queried) - { + if(!queried) { endbb(); } } -static inline bool bbinsideva(const ivec &bo, const ivec &br, vtxarray *va) -{ +static inline bool bbinsideva(const ivec &bo, const ivec &br, vtxarray *va) { return bo.x >= va->bbmin.x && bo.y >= va->bbmin.y && bo.z >= va->bbmin.z && br.x <= va->bbmax.x && br.y <= va->bbmax.y && br.z <= va->bbmax.z; } -static inline bool bboccluded(const ivec &bo, const ivec &br, cube *c, const ivec &o, int size) -{ - loopoctabox(o, size, bo, br) - { +static inline bool bboccluded(const ivec &bo, const ivec &br, cube *c, const ivec &o, int size) { + loopoctabox(o, size, bo, br) { ivec co(i, o, size); - if(c[i].ext && c[i].ext->va) - { + if(c[i].ext && c[i].ext->va) { vtxarray *va = c[i].ext->va; if(va->occluded >= OCCLUDE_BB && bbinsideva(bo, br, va)) continue; } @@ -508,24 +415,20 @@ static inline bool bboccluded(const ivec &bo, const ivec &br, cube *c, const ive return true; } -bool bboccluded(const ivec &bo, const ivec &br) -{ +bool bboccluded(const ivec &bo, const ivec &br) { int diff = (bo.x^br.x) | (bo.y^br.y) | (bo.z^br.z); if(diff&~((1<<worldscale)-1)) return false; int scale = worldscale-1; if(diff&(1<<scale)) return bboccluded(bo, br, worldroot, ivec(0, 0, 0), 1<<scale); cube *c = &worldroot[octastep(bo.x, bo.y, bo.z, scale)]; - if(c->ext && c->ext->va) - { + if(c->ext && c->ext->va) { vtxarray *va = c->ext->va; if(va->occluded >= OCCLUDE_BB && bbinsideva(bo, br, va)) return true; } scale--; - while(c->children && !(diff&(1<<scale))) - { + while(c->children && !(diff&(1<<scale))) { c = &c->children[octastep(bo.x, bo.y, bo.z, scale)]; - if(c->ext && c->ext->va) - { + if(c->ext && c->ext->va) { vtxarray *va = c->ext->va; if(va->occluded >= OCCLUDE_BB && bbinsideva(bo, br, va)) return true; } @@ -539,103 +442,71 @@ VAR(outline, 0, 0, 1); HVARP(outlinecolour, 0, 0, 0xFFFFFF); VAR(dtoutline, 0, 1, 1); -void renderoutline() -{ +void renderoutline() { notextureshader->set(); - gle::enablevertex(); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); gle::color(vec::hexcolor(outlinecolour)); - enablepolygonoffset(GL_POLYGON_OFFSET_LINE); - if(!dtoutline) glDisable(GL_DEPTH_TEST); - vtxarray *prev = NULL; - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(va->occluded >= OCCLUDE_BB) continue; if(!va->alphaback && !va->alphafront && (!va->texs || va->occluded >= OCCLUDE_GEOM)) continue; - - if(!prev || va->vbuf != prev->vbuf) - { + if(!prev || va->vbuf != prev->vbuf) { gle::bindvbo(va->vbuf); gle::bindebo(va->ebuf); const vertex *ptr = 0; gle::vertexpointer(sizeof(vertex), ptr->pos.v); } - - if(va->texs && va->occluded < OCCLUDE_GEOM) - { + if(va->texs && va->occluded < OCCLUDE_GEOM) { drawvatris(va, 3*va->tris, va->edata); xtravertsva += va->verts; } - if(va->alphatris) - { + if(va->alphatris) { drawvatris(va, 3*va->alphatris, &va->edata[3*(va->tris + va->blendtris)]); xtravertsva += 3*va->alphatris; } - prev = va; } - if(!dtoutline) glEnable(GL_DEPTH_TEST); - disablepolygonoffset(GL_POLYGON_OFFSET_LINE); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - gle::clearvbo(); gle::clearebo(); gle::disablevertex(); } -void rendershadowmapreceivers() -{ +void rendershadowmapreceivers() { SETSHADER(shadowmapreceiver); - gle::enablevertex(); - glCullFace(GL_FRONT); glDepthMask(GL_FALSE); glDepthFunc(GL_GREATER); - extern int ati_minmax_bug; if(!ati_minmax_bug) glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE); - glEnable(GL_BLEND); glBlendEquation_(GL_MAX); glBlendFunc(GL_ONE, GL_ONE); - vtxarray *prev = NULL; - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->texs || !isshadowmapreceiver(va)) continue; - - if(!prev || va->vbuf != prev->vbuf) - { + if(!prev || va->vbuf != prev->vbuf) { gle::bindvbo(va->vbuf); gle::bindebo(va->ebuf); const vertex *ptr = 0; gle::vertexpointer(sizeof(vertex), ptr->pos.v); } - drawvatris(va, 3*va->tris, va->edata); xtravertsva += va->verts; - prev = va; } - glDisable(GL_BLEND); glBlendEquation_(GL_FUNC_ADD); - glCullFace(GL_BACK); glDepthMask(GL_TRUE); glDepthFunc(GL_LESS); - if(!ati_minmax_bug) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - gle::clearvbo(); gle::clearebo(); gle::disablevertex(); @@ -645,8 +516,7 @@ VAR(oqdist, 0, 256, 1024); VAR(zpass, 0, 1, 1); VAR(envpass, 0, 1, 1); -struct renderstate -{ +struct renderstate { bool colormask, depthmask, blending; int alphaing; GLuint vbuf; @@ -660,68 +530,54 @@ struct renderstate int texgendim; int visibledynlights; uint dynlightmask; - - renderstate() : colormask(true), depthmask(true), blending(false), alphaing(0), vbuf(0), vattribs(false), vquery(false), colorscale(1, 1, 1), alphascale(0), slot(NULL), texgenslot(NULL), vslot(NULL), texgenvslot(NULL), texgenscroll(0, 0), texgendim(-1), visibledynlights(0), dynlightmask(0) - { + renderstate() : colormask(true), depthmask(true), blending(false), alphaing(0), vbuf(0), vattribs(false), vquery(false), colorscale(1, 1, 1), alphascale(0), slot(NULL), texgenslot(NULL), vslot(NULL), texgenvslot(NULL), texgenscroll(0, 0), texgendim(-1), visibledynlights(0), dynlightmask(0) { loopk(8) textures[k] = 0; } }; -static inline void disablevbuf(renderstate &cur) -{ +static inline void disablevbuf(renderstate &cur) { gle::clearvbo(); gle::clearebo(); cur.vbuf = 0; } -static inline void enablevquery(renderstate &cur) -{ +static inline void enablevquery(renderstate &cur) { if(cur.colormask) { cur.colormask = false; glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } if(cur.depthmask) { cur.depthmask = false; glDepthMask(GL_FALSE); } startbb(false); cur.vquery = true; } -static inline void disablevquery(renderstate &cur) -{ +static inline void disablevquery(renderstate &cur) { endbb(false); cur.vquery = false; } -static void renderquery(renderstate &cur, occludequery *query, vtxarray *va, bool full = true) -{ +static void renderquery(renderstate &cur, occludequery *query, vtxarray *va, bool full = true) { if(!cur.vquery) enablevquery(cur); - startquery(query); - if(full) drawbb(ivec(va->bbmin).sub(1), ivec(va->bbmax).sub(va->bbmin).add(2)); else drawbb(va->geommin, ivec(va->geommax).sub(va->geommin)); - endquery(query); } -enum -{ +enum { RENDERPASS_LIGHTMAP = 0, RENDERPASS_Z, RENDERPASS_LIGHTMAP_BLEND }; -struct geombatch -{ +struct geombatch { const elementset &es; VSlot &vslot; ushort *edata; vtxarray *va; int next, batch; - geombatch(const elementset &es, ushort *edata, vtxarray *va) : es(es), vslot(lookupvslot(es.texture)), edata(edata), va(va), - next(-1), batch(-1) - {} - - int compare(const geombatch &b) const - { + next(-1), batch(-1) { + } + int compare(const geombatch &b) const { if(va->vbuf < b.va->vbuf) return -1; if(va->vbuf > b.va->vbuf) return 1; if(va->dynlightmask < b.va->dynlightmask) return -1; @@ -743,73 +599,59 @@ struct geombatch static vector<geombatch> geombatches; static int firstbatch = -1, numbatches = 0; -static void mergetexs(renderstate &cur, vtxarray *va, elementset *texs = NULL, int numtexs = 0, ushort *edata = NULL) -{ - if(!texs) - { +static void mergetexs(renderstate &cur, vtxarray *va, elementset *texs = NULL, int numtexs = 0, ushort *edata = NULL) { + if(!texs) { texs = va->eslist; numtexs = va->texs; edata = va->edata; - if(cur.alphaing) - { + if(cur.alphaing) { texs += va->texs + va->blends; edata += 3*(va->tris + va->blendtris); numtexs = va->alphaback; if(cur.alphaing > 1) numtexs += va->alphafront; } } - - if(firstbatch < 0) - { + if(firstbatch < 0) { firstbatch = geombatches.length(); numbatches = numtexs; - loopi(numtexs-1) - { + loopi(numtexs-1) { geombatches.add(geombatch(texs[i], edata, va)).next = i+1; edata += texs[i].length[1]; } geombatches.add(geombatch(texs[numtexs-1], edata, va)); return; } - int prevbatch = -1, curbatch = firstbatch, curtex = 0; - do - { + do { geombatch &b = geombatches.add(geombatch(texs[curtex], edata, va)); edata += texs[curtex].length[1]; int dir = -1; - while(curbatch >= 0) - { + while(curbatch >= 0) { dir = b.compare(geombatches[curbatch]); if(dir <= 0) break; prevbatch = curbatch; curbatch = geombatches[curbatch].next; } - if(!dir) - { + if(!dir) { int last = curbatch, next; - for(;;) - { + for(;;) { next = geombatches[last].batch; if(next < 0) break; last = next; } - if(last==curbatch) - { + if(last==curbatch) { b.batch = curbatch; b.next = geombatches[curbatch].next; if(prevbatch < 0) firstbatch = geombatches.length()-1; else geombatches[prevbatch].next = geombatches.length()-1; curbatch = geombatches.length()-1; } - else - { + else { b.batch = next; geombatches[last].batch = geombatches.length()-1; } } - else - { + else { numbatches++; b.next = curbatch; if(prevbatch < 0) firstbatch = geombatches.length()-1; @@ -820,11 +662,9 @@ static void mergetexs(renderstate &cur, vtxarray *va, elementset *texs = NULL, i while(++curtex < numtexs); } -static inline void enablevattribs(renderstate &cur, bool all = true) -{ +static inline void enablevattribs(renderstate &cur, bool all = true) { gle::enablevertex(); - if(all) - { + if(all) { gle::enabletexcoord0(); gle::enabletexcoord1(); gle::enablenormal(); @@ -833,11 +673,9 @@ static inline void enablevattribs(renderstate &cur, bool all = true) cur.vattribs = true; } -static inline void disablevattribs(renderstate &cur, bool all = true) -{ +static inline void disablevattribs(renderstate &cur, bool all = true) { gle::disablevertex(); - if(all) - { + if(all) { gle::disabletexcoord0(); gle::disabletexcoord1(); gle::disablenormal(); @@ -846,17 +684,13 @@ static inline void disablevattribs(renderstate &cur, bool all = true) cur.vattribs = false; } -static void changevbuf(renderstate &cur, int pass, vtxarray *va) -{ +static void changevbuf(renderstate &cur, int pass, vtxarray *va) { gle::bindvbo(va->vbuf); gle::bindebo(va->ebuf); cur.vbuf = va->vbuf; - vertex *vdata = (vertex *)0; gle::vertexpointer(sizeof(vertex), vdata->pos.v); - - if(pass==RENDERPASS_LIGHTMAP) - { + if(pass==RENDERPASS_LIGHTMAP) { gle::normalpointer(sizeof(vertex), vdata->norm.v, GL_BYTE); gle::texcoord0pointer(sizeof(vertex), vdata->tc.v); gle::texcoord1pointer(sizeof(vertex), vdata->lm.v, GL_SHORT); @@ -864,86 +698,68 @@ static void changevbuf(renderstate &cur, int pass, vtxarray *va) } } -static void changebatchtmus(renderstate &cur, int pass, geombatch &b) -{ +static void changebatchtmus(renderstate &cur, int pass, geombatch &b) { bool changed = false; extern bool brightengeom; extern int fullbright; int lmid = brightengeom && (b.es.lmid < LMID_RESERVED || (fullbright && editmode)) ? (int) LMID_BRIGHT : (int) b.es.lmid; - if(cur.textures[1]!=lightmaptexs[lmid].id) - { + if(cur.textures[1]!=lightmaptexs[lmid].id) { glActiveTexture_(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, cur.textures[1] = lightmaptexs[lmid].id); changed = true; } int tmu = 2; - if(b.vslot.slot->shader->type&SHADER_NORMALSLMS) - { - if(cur.textures[tmu]!=lightmaptexs[lmid+1].id) - { + if(b.vslot.slot->shader->type&SHADER_NORMALSLMS) { + if(cur.textures[tmu]!=lightmaptexs[lmid+1].id) { glActiveTexture_(GL_TEXTURE0+tmu); glBindTexture(GL_TEXTURE_2D, cur.textures[tmu] = lightmaptexs[lmid+1].id); changed = true; } tmu++; } - if(changed) glActiveTexture_(GL_TEXTURE0); - - if(cur.dynlightmask != b.va->dynlightmask) - { + if(cur.dynlightmask != b.va->dynlightmask) { cur.visibledynlights = setdynlights(b.va); cur.dynlightmask = b.va->dynlightmask; } } -static void changeslottmus(renderstate &cur, int pass, Slot &slot, VSlot &vslot) -{ - if(pass==RENDERPASS_LIGHTMAP) - { +static void changeslottmus(renderstate &cur, int pass, Slot &slot, VSlot &vslot) { + if(pass==RENDERPASS_LIGHTMAP) { GLuint diffusetex = slot.sts.empty() ? notexture->id : slot.sts[0].t->id; if(cur.textures[0]!=diffusetex) glBindTexture(GL_TEXTURE_2D, cur.textures[0] = diffusetex); } - - if(cur.alphaing) - { + if(cur.alphaing) { float alpha = cur.alphaing > 1 ? vslot.alphafront : vslot.alphaback; - if(cur.colorscale != vslot.colorscale || cur.alphascale != alpha) - { + if(cur.colorscale != vslot.colorscale || cur.alphascale != alpha) { cur.colorscale = vslot.colorscale; cur.alphascale = alpha; GLOBALPARAMF(colorparams, 2*alpha*vslot.colorscale.x, 2*alpha*vslot.colorscale.y, 2*alpha*vslot.colorscale.z, alpha); } } - else if(cur.colorscale != vslot.colorscale) - { + else if(cur.colorscale != vslot.colorscale) { cur.colorscale = vslot.colorscale; GLOBALPARAMF(colorparams, 2*vslot.colorscale.x, 2*vslot.colorscale.y, 2*vslot.colorscale.z, 1); } int tmu = 2; if(slot.shader->type&SHADER_NORMALSLMS) tmu++; - loopvj(slot.sts) - { + loopvj(slot.sts) { Slot::Tex &t = slot.sts[j]; if(t.type==TEX_DIFFUSE || t.combined>=0) continue; - if(cur.textures[tmu]!=t.t->id) - { + if(cur.textures[tmu]!=t.t->id) { glActiveTexture_(GL_TEXTURE0+tmu); glBindTexture(GL_TEXTURE_2D, cur.textures[tmu] = t.t->id); } if(++tmu >= 8) break; } glActiveTexture_(GL_TEXTURE0); - cur.slot = &slot; cur.vslot = &vslot; } -static void changeshader(renderstate &cur, Shader *s, Slot &slot, VSlot &vslot, bool shadowed) -{ - if(!cur.blending && !cur.alphaing) - { +static void changeshader(renderstate &cur, Shader *s, Slot &slot, VSlot &vslot, bool shadowed) { + if(!cur.blending && !cur.alphaing) { if(shadowed) s->setvariant(cur.visibledynlights, 3, slot, vslot); else s->setvariant(cur.visibledynlights, 2, slot, vslot); } @@ -952,17 +768,14 @@ static void changeshader(renderstate &cur, Shader *s, Slot &slot, VSlot &vslot, else s->setvariant(cur.visibledynlights-1, 0, slot, vslot); } -static void changetexgen(renderstate &cur, int dim, Slot &slot, VSlot &vslot) -{ - if(cur.texgenslot != &slot || cur.texgenvslot != &vslot) - { +static void changetexgen(renderstate &cur, int dim, Slot &slot, VSlot &vslot) { + if(cur.texgenslot != &slot || cur.texgenvslot != &vslot) { Texture *curtex = !cur.texgenslot || cur.texgenslot->sts.empty() ? notexture : cur.texgenslot->sts[0].t, *tex = slot.sts.empty() ? notexture : slot.sts[0].t; if(!cur.texgenvslot || slot.sts.empty() || (curtex->xs != tex->xs || curtex->ys != tex->ys || cur.texgenvslot->rotation != vslot.rotation || cur.texgenvslot->scale != vslot.scale || - cur.texgenvslot->offset != vslot.offset || cur.texgenvslot->scroll != vslot.scroll)) - { + cur.texgenvslot->offset != vslot.offset || cur.texgenvslot->scroll != vslot.scroll)) { const texrotation &r = texrotations[vslot.rotation]; float xs = r.flipx ? -tex->xs : tex->xs, ys = r.flipy ? -tex->ys : tex->ys; @@ -970,8 +783,7 @@ static void changetexgen(renderstate &cur, int dim, Slot &slot, VSlot &vslot) if(r.swapxy) swap(scroll.x, scroll.y); scroll.x *= lastmillis*tex->xs/xs; scroll.y *= lastmillis*tex->ys/ys; - if(cur.texgenscroll != scroll) - { + if(cur.texgenscroll != scroll) { cur.texgenscroll = scroll; cur.texgendim = -1; } @@ -979,23 +791,18 @@ static void changetexgen(renderstate &cur, int dim, Slot &slot, VSlot &vslot) cur.texgenslot = &slot; cur.texgenvslot = &vslot; } - if(cur.texgendim == dim) return; GLOBALPARAM(texgenscroll, cur.texgenscroll); cur.texgendim = dim; } -static void renderbatch(renderstate &cur, int pass, geombatch &b) -{ +static void renderbatch(renderstate &cur, int pass, geombatch &b) { geombatch *shadowed = NULL; int rendered = -1; - for(geombatch *curbatch = &b;; curbatch = &geombatches[curbatch->batch]) - { + for(geombatch *curbatch = &b;; curbatch = &geombatches[curbatch->batch]) { ushort len = curbatch->es.length[curbatch->va->shadowed ? 0 : 1]; - if(len) - { - if(rendered < 0) - { + if(len) { + if(rendered < 0) { changeshader(cur, b.vslot.slot->shader, *b.vslot.slot, b.vslot, false); rendered = 0; gbatches++; @@ -1008,12 +815,9 @@ static void renderbatch(renderstate &cur, int pass, geombatch &b) if(curbatch->es.length[1] > len && !shadowed) shadowed = curbatch; if(curbatch->batch < 0) break; } - if(shadowed) for(geombatch *curbatch = shadowed;; curbatch = &geombatches[curbatch->batch]) - { - if(curbatch->va->shadowed && curbatch->es.length[1] > curbatch->es.length[0]) - { - if(rendered < 1) - { + if(shadowed) for(geombatch *curbatch = shadowed;; curbatch = &geombatches[curbatch->batch]) { + if(curbatch->va->shadowed && curbatch->es.length[1] > curbatch->es.length[0]) { + if(rendered < 1) { changeshader(cur, b.vslot.slot->shader, *b.vslot.slot, b.vslot, true); rendered = 1; gbatches++; @@ -1026,56 +830,44 @@ static void renderbatch(renderstate &cur, int pass, geombatch &b) } } -static void resetbatches() -{ +static void resetbatches() { geombatches.setsize(0); firstbatch = -1; numbatches = 0; } -static void renderbatches(renderstate &cur, int pass) -{ +static void renderbatches(renderstate &cur, int pass) { cur.slot = NULL; cur.vslot = NULL; int curbatch = firstbatch; - if(curbatch >= 0) - { - if(cur.alphaing) - { + if(curbatch >= 0) { + if(cur.alphaing) { if(cur.depthmask) { cur.depthmask = false; glDepthMask(GL_FALSE); } } else if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); } if(!cur.colormask) { cur.colormask = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, cur.alphaing ? GL_FALSE : GL_TRUE); } - if(!cur.vattribs) - { + if(!cur.vattribs) { if(cur.vquery) disablevquery(cur); enablevattribs(cur); } } - while(curbatch >= 0) - { + while(curbatch >= 0) { geombatch &b = geombatches[curbatch]; curbatch = b.next; - if(cur.vbuf != b.va->vbuf) changevbuf(cur, pass, b.va); - if(cur.vslot != &b.vslot) - { + if(cur.vslot != &b.vslot) { changeslottmus(cur, pass, *b.vslot.slot, b.vslot); if(cur.texgendim != b.es.dim || (cur.texgendim <= 2 && cur.texgenvslot != &b.vslot)) changetexgen(cur, b.es.dim, *b.vslot.slot, b.vslot); } else if(cur.texgendim != b.es.dim) changetexgen(cur, b.es.dim, *b.vslot.slot, b.vslot); if(pass == RENDERPASS_LIGHTMAP) changebatchtmus(cur, pass, b); - renderbatch(cur, pass, b); } - resetbatches(); } -void renderzpass(renderstate &cur, vtxarray *va) -{ - if(!cur.vattribs) - { +void renderzpass(renderstate &cur, vtxarray *va) { + if(!cur.vattribs) { if(cur.vquery) disablevquery(cur); enablevattribs(cur, false); } @@ -1084,8 +876,7 @@ void renderzpass(renderstate &cur, vtxarray *va) if(cur.colormask) { cur.colormask = false; glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } int firsttex = 0, numtris = va->tris; ushort *edata = va->edata; - if(cur.alphaing) - { + if(cur.alphaing) { firsttex += va->texs + va->blends; edata += 3*(va->tris + va->blendtris); numtris = va->alphatris; @@ -1098,8 +889,8 @@ void renderzpass(renderstate &cur, vtxarray *va) #define startvaquery(va, flush) \ do { \ - if(va->query) \ - { \ + if(va->query) { \ + \ flush; \ startquery(va->query); \ } \ @@ -1108,8 +899,8 @@ void renderzpass(renderstate &cur, vtxarray *va) #define endvaquery(va, flush) \ do { \ - if(va->query) \ - { \ + if(va->query) { \ + \ flush; \ endquery(va->query); \ } \ @@ -1117,16 +908,13 @@ void renderzpass(renderstate &cur, vtxarray *va) VAR(batchgeom, 0, 1, 1); -void renderva(renderstate &cur, vtxarray *va, int pass = RENDERPASS_LIGHTMAP, bool doquery = false) -{ - switch(pass) - { +void renderva(renderstate &cur, vtxarray *va, int pass = RENDERPASS_LIGHTMAP, bool doquery = false) { + switch(pass) { case RENDERPASS_LIGHTMAP: if(!cur.alphaing) vverts += va->verts; va->shadowed = false; va->dynlightmask = 0; - if(!drawtex && !cur.alphaing) - { + if(!drawtex && !cur.alphaing) { va->shadowed = isshadowmapreceiver(va); calcdynlightmask(va); } @@ -1135,16 +923,13 @@ void renderva(renderstate &cur, vtxarray *va, int pass = RENDERPASS_LIGHTMAP, bo if(doquery) endvaquery(va, { if(geombatches.length()) renderbatches(cur, pass); }); else if(!batchgeom && geombatches.length()) renderbatches(cur, pass); break; - - case RENDERPASS_LIGHTMAP_BLEND: - { + case RENDERPASS_LIGHTMAP_BLEND: { if(doquery) startvaquery(va, { if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); }); mergetexs(cur, va, &va->eslist[va->texs], va->blends, va->edata + 3*va->tris); if(doquery) endvaquery(va, { if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); }); else if(!batchgeom && geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); break; } - case RENDERPASS_Z: if(doquery) startvaquery(va, ); renderzpass(cur, va); @@ -1153,62 +938,49 @@ void renderva(renderstate &cur, vtxarray *va, int pass = RENDERPASS_LIGHTMAP, bo } } -void cleanupva() -{ +void cleanupva() { clearvas(worldroot); clearqueries(); cleanupbb(); } -void setupgeom(renderstate &cur) -{ +void setupgeom(renderstate &cur) { GLOBALPARAMF(colorparams, 2, 2, 2, 1); GLOBALPARAM(camera, camera1->o); GLOBALPARAMF(ambient, ambientcolor.x/255.0f, ambientcolor.y/255.0f, ambientcolor.z/255.0f); GLOBALPARAMF(millis, lastmillis/1000.0f); - glActiveTexture_(GL_TEXTURE0); } -void cleanupgeom(renderstate &cur) -{ +void cleanupgeom(renderstate &cur) { if(cur.vattribs) disablevattribs(cur); if(cur.vbuf) disablevbuf(cur); } VAR(oqgeom, 0, 1, 1); -void rendergeom(void) -{ +void rendergeom(void) { bool mainpass = !drawtex, doOQ = oqfrags && oqgeom && mainpass, doZP = doOQ && zpass, doSM = shadowmap && !drawtex; renderstate cur; - if(mainpass) - { + if(mainpass) { flipqueries(); vtris = vverts = 0; } - if(!doZP) - { + if(!doZP) { if(shadowmap && mainpass) rendershadowmap(); setupgeom(cur); if(doSM) pushshadowmap(); } - finddynlights(); - resetbatches(); - int blends = 0; - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->texs) continue; - if(doOQ && (zpass || va->distance > oqdist) && !insideva(va, camera1->o)) - { - if(va->parent && va->parent->occluded >= OCCLUDE_BB) - { + if(doOQ && (zpass || va->distance > oqdist) && !insideva(va, camera1->o)) { + if(va->parent && va->parent->occluded >= OCCLUDE_BB) { va->query = NULL; va->occluded = OCCLUDE_PARENT; continue; @@ -1217,10 +989,8 @@ void rendergeom(void) va->query = newquery(va); if((!va->query && zpass) || !va->occluded) va->occluded = OCCLUDE_NOTHING; - if(va->occluded >= OCCLUDE_GEOM) - { - if(va->query) - { + if(va->occluded >= OCCLUDE_GEOM) { + if(va->query) { if(!zpass && geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); if(cur.vattribs) disablevattribs(cur, !doZP); if(cur.vbuf) disablevbuf(cur); @@ -1229,117 +999,85 @@ void rendergeom(void) continue; } } - else - { + else { va->query = NULL; va->occluded = OCCLUDE_NOTHING; } - if(!doZP) blends += va->blends; renderva(cur, va, doZP ? RENDERPASS_Z : RENDERPASS_LIGHTMAP, doOQ); } - if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); - if(cur.vquery) disablevquery(cur); if(cur.vattribs) disablevattribs(cur, !doZP); if(cur.vbuf) disablevbuf(cur); - if(!cur.colormask) { cur.colormask = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); } - bool multipassing = false; - - if(doZP) - { + if(doZP) { glFlush(); - if(shadowmap && mainpass) rendershadowmap(); setupgeom(cur); if(doSM) pushshadowmap(); - if(!multipassing) { multipassing = true; glDepthFunc(GL_LEQUAL); } cur.texgendim = -1; - - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->texs || va->occluded >= OCCLUDE_GEOM) continue; blends += va->blends; renderva(cur, va, RENDERPASS_LIGHTMAP); } if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->texs || va->occluded < OCCLUDE_GEOM) continue; else if((va->parent && va->parent->occluded >= OCCLUDE_BB) || - (va->query && checkquery(va->query))) - { + (va->query && checkquery(va->query))) { va->occluded = OCCLUDE_BB; continue; } - blends += va->blends; renderva(cur, va, RENDERPASS_LIGHTMAP); } if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); } - - if(blends) - { + if(blends) { if(cur.vbuf) disablevbuf(cur); - if(!multipassing) { multipassing = true; glDepthFunc(GL_LEQUAL); } glDepthMask(GL_FALSE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); - cur.texgendim = -1; cur.blending = true; - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->blends) continue; if(va->occluded >= OCCLUDE_GEOM) continue; renderva(cur, va, RENDERPASS_LIGHTMAP_BLEND); } if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); cur.blending = false; - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDisable(GL_BLEND); glDepthMask(GL_TRUE); } - - if(doSM) popshadowmap(); - if(cur.vattribs) disablevattribs(cur); - if(multipassing) glDepthFunc(GL_LESS); - cleanupgeom(cur); } -void renderalphageom(void) -{ +void renderalphageom(void) { static vector<vtxarray *> alphavas; alphavas.setsize(0); bool hasback = false; - for(vtxarray *va = visibleva; va; va = va->next) - { + for(vtxarray *va = visibleva; va; va = va->next) { if(!va->alphatris) continue; if(va->occluded >= OCCLUDE_BB) continue; alphavas.add(va); if(va->alphabacktris) hasback = true; } if(alphavas.empty()) return; - resetbatches(); - renderstate cur; cur.alphaing = 1; - - loop(front, 2) if(front || hasback) - { + loop(front, 2) if(front || hasback) { cur.alphaing = front+1; if(!front) glCullFace(GL_FRONT); cur.vbuf = 0; @@ -1348,12 +1086,9 @@ void renderalphageom(void) if(cur.depthmask) { cur.depthmask = false; glDepthMask(GL_FALSE); } cur.colormask = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); - if(cur.vattribs) disablevattribs(cur, false); if(cur.vbuf) disablevbuf(cur); - setupgeom(cur); - glDepthFunc(GL_LEQUAL); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); @@ -1363,14 +1098,11 @@ void renderalphageom(void) cur.alphascale = -1; loopv(alphavas) if(front || alphavas[i]->alphabacktris) renderva(cur, alphavas[i], RENDERPASS_LIGHTMAP); if(geombatches.length()) renderbatches(cur, RENDERPASS_LIGHTMAP); - cleanupgeom(cur); - if(!cur.depthmask) { cur.depthmask = true; glDepthMask(GL_TRUE); } glDisable(GL_BLEND); glDepthFunc(GL_LESS); if(!front) glCullFace(GL_BACK); } - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } diff --git a/src/engine/server.cpp b/src/engine/server.cpp index 7e338b3..29761e1 100644 --- a/src/engine/server.cpp +++ b/src/engine/server.cpp @@ -7,25 +7,20 @@ static FILE *logfile = NULL; -void closelogfile() -{ - if(logfile) - { +void closelogfile() { + if(logfile) { fclose(logfile); logfile = NULL; } } -FILE *getlogfile() -{ +FILE *getlogfile() { return logfile ? logfile : stdout; } -void setlogfile(const char *fname) -{ +void setlogfile(const char *fname) { closelogfile(); - if(fname && fname[0]) - { + if(fname && fname[0]) { fname = findfile(fname, "w"); if(fname) logfile = fopen(fname, "w"); } @@ -33,8 +28,7 @@ void setlogfile(const char *fname) if(f) setvbuf(f, NULL, _IOLBF, BUFSIZ); } -void logoutf(const char *fmt, ...) -{ +void logoutf(const char *fmt, ...) { va_list args; va_start(args, fmt); logoutfv(fmt, args); @@ -42,28 +36,24 @@ void logoutf(const char *fmt, ...) } -static void writelog(FILE *file, const char *buf) -{ +static void writelog(FILE *file, const char *buf) { static uchar ubuf[512]; size_t len = strlen(buf), carry = 0; - while(carry < len) - { + while(carry < len) { size_t numu = encodeutf8(ubuf, sizeof(ubuf)-1, &((const uchar *)buf)[carry], len - carry, &carry); if(carry >= len) ubuf[numu++] = '\n'; fwrite(ubuf, 1, numu, file); } } -static void writelogv(FILE *file, const char *fmt, va_list args) -{ +static void writelogv(FILE *file, const char *fmt, va_list args) { static char buf[LOGSTRLEN]; vformatstring(buf, fmt, args, sizeof(buf)); writelog(file, buf); } #ifdef STANDALONE -void fatal(const char *fmt, ...) -{ +void fatal(const char *fmt, ...) { void cleanupserver(); cleanupserver(); defvformatstring(msg,fmt,fmt); @@ -73,8 +63,7 @@ void fatal(const char *fmt, ...) exit(EXIT_FAILURE); } -void conoutfv(int type, const char *fmt, va_list args) -{ +void conoutfv(int type, const char *fmt, va_list args) { logoutfv(fmt, args); } #endif @@ -83,8 +72,7 @@ void conoutfv(int type, const char *fmt, va_list args) enum { ST_EMPTY, ST_LOCAL, ST_TCPIP }; -struct client // server side version of "dynent" type -{ +struct client { // server side version of "dynent" type { int type; int num; ENetPeer *peer; @@ -103,53 +91,44 @@ int localclients = 0, nonlocalclients = 0; bool hasnonlocalclients() { return nonlocalclients!=0; } bool haslocalclients() { return localclients!=0; } -client &addclient(int type) -{ +client &addclient(int type) { client *c = NULL; - loopv(clients) if(clients[i]->type==ST_EMPTY) - { + loopv(clients) if(clients[i]->type==ST_EMPTY) { c = clients[i]; break; } - if(!c) - { + if(!c) { c = new client; c->num = clients.length(); clients.add(c); } c->info = server::newclientinfo(); c->type = type; - switch(type) - { + switch(type) { case ST_TCPIP: nonlocalclients++; break; case ST_LOCAL: localclients++; break; } return *c; } -void delclient(client *c) -{ +void delclient(client *c) { if(!c) return; - switch(c->type) - { + switch(c->type) { case ST_TCPIP: nonlocalclients--; if(c->peer) c->peer->data = NULL; break; case ST_LOCAL: localclients--; break; case ST_EMPTY: return; } c->type = ST_EMPTY; c->peer = NULL; - if(c->info) - { + if(c->info) { server::deleteclientinfo(c->info); c->info = NULL; } } -void cleanupserver() -{ +void cleanupserver() { if(serverhost) enet_host_destroy(serverhost); serverhost = NULL; - if(pongsock != ENET_SOCKET_NULL) enet_socket_destroy(pongsock); if(lansock != ENET_SOCKET_NULL) enet_socket_destroy(lansock); pongsock = lansock = ENET_SOCKET_NULL; @@ -167,18 +146,14 @@ ENetPeer *getclientpeer(int i) { return clients.inrange(i) && clients[i]->type== int getnumclients() { return clients.length(); } uint getclientip(int n) { return clients.inrange(n) && clients[n]->type==ST_TCPIP ? clients[n]->peer->address.host : 0; } -void sendpacket(int n, int chan, ENetPacket *packet, int exclude) -{ - if(n<0) - { +void sendpacket(int n, int chan, ENetPacket *packet, int exclude) { + if(n<0) { server::recordpacket(chan, packet->data, packet->dataLength); loopv(clients) if(i!=exclude && server::allowbroadcast(i)) sendpacket(i, chan, packet); return; } - switch(clients[n]->type) - { - case ST_TCPIP: - { + switch(clients[n]->type) { + case ST_TCPIP: { enet_peer_send(clients[n]->peer, chan, packet); break; } @@ -191,43 +166,35 @@ void sendpacket(int n, int chan, ENetPacket *packet, int exclude) } } -ENetPacket *sendf(int cn, int chan, const char *format, ...) -{ +ENetPacket *sendf(int cn, int chan, const char *format, ...) { int exclude = -1; bool reliable = false; if(*format=='r') { reliable = true; ++format; } packetbuf p(MAXTRANS, reliable ? ENET_PACKET_FLAG_RELIABLE : 0); va_list args; va_start(args, format); - while(*format) switch(*format++) - { + while(*format) switch(*format++) { case 'x': exclude = va_arg(args, int); break; - - case 'v': - { + case 'v': { int n = va_arg(args, int); int *v = va_arg(args, int *); loopi(n) putint(p, v[i]); break; } - - case 'i': - { + case 'i': { int n = isdigit(*format) ? *format++-'0' : 1; loopi(n) putint(p, va_arg(args, int)); break; } - case 'f': - { + case 'f': { int n = isdigit(*format) ? *format++-'0' : 1; loopi(n) putfloat(p, (float)va_arg(args, double)); break; } case 's': sendstring(va_arg(args, const char *), p); break; - case 'm': - { + case 'm': { int n = va_arg(args, int); p.put(va_arg(args, uchar *), n); break; @@ -239,26 +206,20 @@ ENetPacket *sendf(int cn, int chan, const char *format, ...) return packet->referenceCount > 0 ? packet : NULL; } -ENetPacket *sendfile(int cn, int chan, stream *file, const char *format, ...) -{ - if(cn < 0) - { +ENetPacket *sendfile(int cn, int chan, stream *file, const char *format, ...) { + if(cn < 0) { #ifdef STANDALONE return NULL; #endif } else if(!clients.inrange(cn)) return NULL; - int len = (int)min(file->size(), stream::offset(INT_MAX)); if(len <= 0 || len > 16<<20) return NULL; - packetbuf p(MAXTRANS+len, ENET_PACKET_FLAG_RELIABLE); va_list args; va_start(args, format); - while(*format) switch(*format++) - { - case 'i': - { + while(*format) switch(*format++) { + case 'i': { int n = isdigit(*format) ? *format++-'0' : 1; loopi(n) putint(p, va_arg(args, int)); break; @@ -267,10 +228,8 @@ ENetPacket *sendfile(int cn, int chan, stream *file, const char *format, ...) case 'l': putint(p, len); break; } va_end(args); - file->seek(0, SEEK_SET); file->read(p.subbuf(len).buf, len); - ENetPacket *packet = p.finalize(); if(cn >= 0) sendpacket(cn, chan, packet, -1); #ifndef STANDALONE @@ -279,10 +238,8 @@ ENetPacket *sendfile(int cn, int chan, stream *file, const char *format, ...) return packet->referenceCount > 0 ? packet : NULL; } -const char *disconnectreason(int reason) -{ - switch(reason) - { +const char *disconnectreason(int reason) { + switch(reason) { case DISC_EOP: return "end of packet"; case DISC_LOCAL: return "server is in local mode"; case DISC_KICK: return "kicked/banned"; @@ -297,8 +254,7 @@ const char *disconnectreason(int reason) } } -void disconnect_client(int n, int reason) -{ +void disconnect_client(int n, int reason) { if(!clients.inrange(n) || clients[n]->type!=ST_TCPIP) return; enet_peer_disconnect(clients[n]->peer, reason); server::clientdisconnect(n); @@ -311,33 +267,28 @@ void disconnect_client(int n, int reason) server::sendservmsg(s); } -void kicknonlocalclients(int reason) -{ +void kicknonlocalclients(int reason) { loopv(clients) if(clients[i]->type==ST_TCPIP) disconnect_client(i, reason); } -void process(ENetPacket *packet, int sender, int chan) // sender may be -1 -{ +void process(ENetPacket *packet, int sender, int chan) { // sender may be -1 { packetbuf p(packet); server::parsepacket(sender, chan, p); if(p.overread()) { disconnect_client(sender, DISC_EOP); return; } } -void localclienttoserver(int chan, ENetPacket *packet) -{ +void localclienttoserver(int chan, ENetPacket *packet) { client *c = NULL; loopv(clients) if(clients[i]->type==ST_LOCAL) { c = clients[i]; break; } if(c) process(packet, c->num, chan); } #ifdef STANDALONE -bool resolverwait(const char *name, ENetAddress *address) -{ +bool resolverwait(const char *name, ENetAddress *address) { return enet_address_set_host(address, name) >= 0; } -int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress &remoteaddress) -{ +int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress &remoteaddress) { return enet_socket_connect(sock, &remoteaddress); } #endif @@ -349,48 +300,38 @@ vector<char> masterout, masterin; int masteroutpos = 0, masterinpos = 0; VARN(updatemaster, allowupdatemaster, 0, 1, 1); -void disconnectmaster() -{ - if(mastersock != ENET_SOCKET_NULL) - { +void disconnectmaster() { + if(mastersock != ENET_SOCKET_NULL) { server::masterdisconnected(); enet_socket_destroy(mastersock); mastersock = ENET_SOCKET_NULL; } - masterout.setsize(0); masterin.setsize(0); masteroutpos = masterinpos = 0; - masteraddress.host = ENET_HOST_ANY; masteraddress.port = ENET_PORT_ANY; - lastupdatemaster = masterconnecting = masterconnected = 0; } SVARF(mastername, server::defaultmaster(), disconnectmaster()); VARF(masterport, 1, server::masterport(), 0xFFFF, disconnectmaster()); -ENetSocket connectmaster(bool wait) -{ +ENetSocket connectmaster(bool wait) { if(!mastername[0]) return ENET_SOCKET_NULL; - if(masteraddress.host == ENET_HOST_ANY) - { + if(masteraddress.host == ENET_HOST_ANY) { if(isdedicatedserver()) logoutf("looking up %s...", mastername); masteraddress.port = masterport; if(!resolverwait(mastername, &masteraddress)) return ENET_SOCKET_NULL; } ENetSocket sock = enet_socket_create(ENET_SOCKET_TYPE_STREAM); - if(sock == ENET_SOCKET_NULL) - { + if(sock == ENET_SOCKET_NULL) { if(isdedicatedserver()) logoutf("could not open master server socket"); return ENET_SOCKET_NULL; } - if(wait || serveraddress.host == ENET_HOST_ANY || !enet_socket_bind(sock, &serveraddress)) - { + if(wait || serveraddress.host == ENET_HOST_ANY || !enet_socket_bind(sock, &serveraddress)) { enet_socket_set_option(sock, ENET_SOCKOPT_NONBLOCK, 1); - if(wait) - { + if(wait) { if(!connectwithtimeout(sock, mastername, masteraddress)) return sock; } else if(!enet_socket_connect(sock, &masteraddress)) return sock; @@ -400,78 +341,60 @@ ENetSocket connectmaster(bool wait) return ENET_SOCKET_NULL; } -bool requestmaster(const char *req) -{ - if(mastersock == ENET_SOCKET_NULL) - { +bool requestmaster(const char *req) { + if(mastersock == ENET_SOCKET_NULL) { mastersock = connectmaster(false); if(mastersock == ENET_SOCKET_NULL) return false; lastconnectmaster = masterconnecting = totalmillis ? totalmillis : 1; } - if(masterout.length() >= 4096) return false; - masterout.put(req, strlen(req)); return true; } -bool requestmasterf(const char *fmt, ...) -{ +bool requestmasterf(const char *fmt, ...) { defvformatstring(req, fmt, fmt); return requestmaster(req); } -void processmasterinput() -{ +void processmasterinput() { if(masterinpos >= masterin.length()) return; - char *input = &masterin[masterinpos], *end = (char *)memchr(input, '\n', masterin.length() - masterinpos); - while(end) - { + while(end) { *end = '\0'; - const char *args = input; while(args < end && !iscubespace(*args)) args++; int cmdlen = args - input; while(args < end && iscubespace(*args)) args++; - if(matchstring(input, cmdlen, "failreg")) conoutf(CON_ERROR, "master server registration failed: %s", args); else if(matchstring(input, cmdlen, "succreg")) conoutf("master server registration succeeded"); - else server::processmasterinput(input, cmdlen, args); - + else server::processmasterinput(input, cmdlen); end++; masterinpos = end - masterin.getbuf(); input = end; end = (char *)memchr(input, '\n', masterin.length() - masterinpos); } - - if(masterinpos >= masterin.length()) - { + if(masterinpos >= masterin.length()) { masterin.setsize(0); masterinpos = 0; } } -void flushmasteroutput() -{ - if(masterconnecting && totalmillis - masterconnecting >= 60000) - { +void flushmasteroutput() { + if(masterconnecting && totalmillis - masterconnecting >= 60000) { logoutf("could not connect to master server"); disconnectmaster(); } if(masterout.empty() || !masterconnected) return; - ENetBuffer buf; buf.data = &masterout[masteroutpos]; buf.dataLength = masterout.length() - masteroutpos; int sent = enet_socket_send(mastersock, NULL, &buf, 1); - if(sent >= 0) - { + if(sent >= 0) { masteroutpos += sent; - if(masteroutpos >= masterout.length()) - { + if(masteroutpos >= masterout.length()) { masterout.setsize(0); masteroutpos = 0; } @@ -479,17 +402,14 @@ void flushmasteroutput() else disconnectmaster(); } -void flushmasterinput() -{ +void flushmasterinput() { if(masterin.length() >= masterin.capacity()) masterin.reserve(4096); - ENetBuffer buf; buf.data = masterin.getbuf() + masterin.length(); buf.dataLength = masterin.capacity() - masterin.length(); int recv = enet_socket_receive(mastersock, NULL, &buf, 1); - if(recv > 0) - { + if(recv > 0) { masterin.advance(recv); processmasterinput(); } @@ -498,8 +418,7 @@ void flushmasterinput() static ENetAddress pongaddr; -void sendserverinforeply(ucharbuf &p) -{ +void sendserverinforeply(ucharbuf &p) { ENetBuffer buf; buf.data = p.buf; buf.dataLength = p.length(); @@ -508,33 +427,27 @@ void sendserverinforeply(ucharbuf &p) #define MAXPINGDATA 32 -void checkserversockets() // reply all server info requests -{ +void checkserversockets() { // reply all server info requests { static ENetSocketSet readset, writeset; ENET_SOCKETSET_EMPTY(readset); ENET_SOCKETSET_EMPTY(writeset); ENetSocket maxsock = pongsock; ENET_SOCKETSET_ADD(readset, pongsock); - if(mastersock != ENET_SOCKET_NULL) - { + if(mastersock != ENET_SOCKET_NULL) { maxsock = max(maxsock, mastersock); ENET_SOCKETSET_ADD(readset, mastersock); if(!masterconnected) ENET_SOCKETSET_ADD(writeset, mastersock); } - if(lansock != ENET_SOCKET_NULL) - { + if(lansock != ENET_SOCKET_NULL) { maxsock = max(maxsock, lansock); ENET_SOCKETSET_ADD(readset, lansock); } if(enet_socketset_select(maxsock, &readset, &writeset, 0) <= 0) return; - ENetBuffer buf; uchar pong[MAXTRANS]; - loopi(2) - { + loopi(2) { ENetSocket sock = i ? lansock : pongsock; if(sock == ENET_SOCKET_NULL || !ENET_SOCKETSET_CHECK(readset, sock)) continue; - buf.data = pong; buf.dataLength = sizeof(pong); int len = enet_socket_receive(sock, &pongaddr, &buf, 1); @@ -543,21 +456,15 @@ void checkserversockets() // reply all server info requests p.len += len; server::serverinforeply(req, p); } - - if(mastersock != ENET_SOCKET_NULL) - { - if(!masterconnected) - { - if(ENET_SOCKETSET_CHECK(readset, mastersock) || ENET_SOCKETSET_CHECK(writeset, mastersock)) - { + if(mastersock != ENET_SOCKET_NULL) { + if(!masterconnected) { + if(ENET_SOCKETSET_CHECK(readset, mastersock) || ENET_SOCKETSET_CHECK(writeset, mastersock)) { int error = 0; - if(enet_socket_get_option(mastersock, ENET_SOCKOPT_ERROR, &error) < 0 || error) - { + if(enet_socket_get_option(mastersock, ENET_SOCKOPT_ERROR, &error) < 0 || error) { logoutf("could not connect to master server"); disconnectmaster(); } - else - { + else { masterconnecting = 0; masterconnected = totalmillis ? totalmillis : 1; server::masterconnected(); @@ -576,8 +483,7 @@ VARF(serverport, 0, server::serverport(), 0xFFFF-1, { if(!serverport) serverport int curtime = 0, lastmillis = 0, elapsedtime = 0, totalmillis = 0; #endif -void updatemasterserver() -{ +void updatemasterserver() { if(!masterconnected && lastconnectmaster && totalmillis-lastconnectmaster <= 5*60*1000) return; if(mastername[0] && allowupdatemaster) requestmasterf("regserv %d\n", serverport); lastupdatemaster = totalmillis ? totalmillis : 1; @@ -585,30 +491,23 @@ void updatemasterserver() uint totalsecs = 0; -void updatetime() -{ +void updatetime() { static int lastsec = 0; - if(totalmillis - lastsec >= 1000) - { + if(totalmillis - lastsec >= 1000) { int cursecs = (totalmillis - lastsec) / 1000; totalsecs += cursecs; lastsec += cursecs * 1000; } } -void serverslice(bool dedicated, uint timeout) // main server update, called from main loop in sp, or from below in dedicated server -{ - if(!serverhost) - { +void serverslice(bool dedicated, uint timeout) { // main server update, called from main loop in sp, or from below in dedicated server { + if(!serverhost) { server::serverupdate(); server::sendpackets(); return; } - // below is network only - - if(dedicated) - { + if(dedicated) { int millis = (int)enet_time_get(); elapsedtime = millis - totalmillis; static int timeerr = 0; @@ -621,33 +520,24 @@ void serverslice(bool dedicated, uint timeout) // main server update, called f updatetime(); } server::serverupdate(); - flushmasteroutput(); checkserversockets(); - if(!lastupdatemaster || totalmillis-lastupdatemaster>60*60*1000) // send alive signal to masterserver every hour of uptime updatemasterserver(); - - if(totalmillis-laststatus>60*1000) // display bandwidth stats, useful for server ops - { + if(totalmillis-laststatus>60*1000) { // display bandwidth stats, useful for server ops { laststatus = totalmillis; if(nonlocalclients || serverhost->totalSentData || serverhost->totalReceivedData) logoutf("status: %d remote clients, %.1f send, %.1f rec (K/sec)", nonlocalclients, serverhost->totalSentData/60.0f/1024, serverhost->totalReceivedData/60.0f/1024); serverhost->totalSentData = serverhost->totalReceivedData = 0; } - ENetEvent event; bool serviced = false; - while(!serviced) - { - if(enet_host_check_events(serverhost, &event) <= 0) - { + while(!serviced) { + if(enet_host_check_events(serverhost, &event) <= 0) { if(enet_host_service(serverhost, &event, timeout) <= 0) break; serviced = true; } - switch(event.type) - { - case ENET_EVENT_TYPE_CONNECT: - { + switch(event.type) { + case ENET_EVENT_TYPE_CONNECT: { client &c = addclient(ST_TCPIP); c.peer = event.peer; c.peer->data = &c; @@ -658,15 +548,13 @@ void serverslice(bool dedicated, uint timeout) // main server update, called f if(reason) disconnect_client(c.num, reason); break; } - case ENET_EVENT_TYPE_RECEIVE: - { + case ENET_EVENT_TYPE_RECEIVE: { client *c = (client *)event.peer->data; if(c) process(event.packet, c->num, event.channelID); if(event.packet->referenceCount==0) enet_packet_destroy(event.packet); break; } - case ENET_EVENT_TYPE_DISCONNECT: - { + case ENET_EVENT_TYPE_DISCONNECT: { client *c = (client *)event.peer->data; if(!c) break; logoutf("disconnected client (%s)", c->hostname); @@ -681,17 +569,14 @@ void serverslice(bool dedicated, uint timeout) // main server update, called f if(server::sendpackets()) enet_host_flush(serverhost); } -void flushserver(bool force) -{ +void flushserver(bool force) { if(server::sendpackets(force) && serverhost) enet_host_flush(serverhost); } #ifndef STANDALONE -void localdisconnect(bool cleanup) -{ +void localdisconnect(bool cleanup) { bool disconnected = false; - loopv(clients) if(clients[i]->type==ST_LOCAL) - { + loopv(clients) if(clients[i]->type==ST_LOCAL) { server::localdisconnect(i); delclient(clients[i]); disconnected = true; @@ -701,8 +586,7 @@ void localdisconnect(bool cleanup) mainmenu = 1; } -void localconnect() -{ +void localconnect() { if(initing) return; client &c = addclient(ST_LOCAL); copystring(c.hostname, "local"); @@ -711,8 +595,7 @@ void localconnect() } #endif -void logoutfv(const char *fmt, va_list args) -{ +void logoutfv(const char *fmt, va_list args) { FILE *f = getlogfile(); if(f) writelogv(f, fmt, args); } @@ -721,19 +604,17 @@ static bool dedicatedserver = false; bool isdedicatedserver() { return dedicatedserver; } -void rundedicatedserver() -{ +void rundedicatedserver() { dedicatedserver = true; logoutf("dedicated server started, waiting for clients..."); for(;;) serverslice(true, 5); dedicatedserver = false; } -bool servererror(bool dedicated, const char *desc) -{ +bool servererror(bool dedicated, const char *desc) { + (void) dedicated; #ifndef STANDALONE - if(!dedicated) - { + if(!dedicated) { conoutf(CON_ERROR, "%s", desc); cleanupserver(); } @@ -743,11 +624,9 @@ bool servererror(bool dedicated, const char *desc) return false; } -bool setuplistenserver(bool dedicated) -{ +bool setuplistenserver(bool dedicated) { ENetAddress address = { ENET_HOST_ANY, enet_uint16(serverport <= 0 ? server::serverport() : serverport) }; - if(*serverip) - { + if(*serverip) { if(enet_address_set_host(&address, serverip)<0) conoutf(CON_WARN, "WARNING: server ip not resolved"); else serveraddress.host = address.host; } @@ -756,8 +635,7 @@ bool setuplistenserver(bool dedicated) serverhost->duplicatePeers = maxdupclients ? maxdupclients : MAXCLIENTS; address.port = server::serverinfoport(serverport > 0 ? serverport : -1); pongsock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); - if(pongsock != ENET_SOCKET_NULL && enet_socket_bind(pongsock, &address) < 0) - { + if(pongsock != ENET_SOCKET_NULL && enet_socket_bind(pongsock, &address) < 0) { enet_socket_destroy(pongsock); pongsock = ENET_SOCKET_NULL; } @@ -765,8 +643,7 @@ bool setuplistenserver(bool dedicated) else enet_socket_set_option(pongsock, ENET_SOCKOPT_NONBLOCK, 1); address.port = server::laninfoport(); lansock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); - if(lansock != ENET_SOCKET_NULL && (enet_socket_set_option(lansock, ENET_SOCKOPT_REUSEADDR, 1) < 0 || enet_socket_bind(lansock, &address) < 0)) - { + if(lansock != ENET_SOCKET_NULL && (enet_socket_set_option(lansock, ENET_SOCKOPT_REUSEADDR, 1) < 0 || enet_socket_bind(lansock, &address) < 0)) { enet_socket_destroy(lansock); lansock = ENET_SOCKET_NULL; } @@ -775,16 +652,11 @@ bool setuplistenserver(bool dedicated) return true; } -void initserver(bool listen, bool dedicated) -{ +void initserver(bool listen, bool dedicated) { execfile("server-init.cfg", false); - if(listen) setuplistenserver(dedicated); - server::serverinit(); - - if(listen) - { + if(listen) { dedicatedserver = dedicated; updatemasterserver(); if(dedicated) rundedicatedserver(); // never returns @@ -795,37 +667,27 @@ void initserver(bool listen, bool dedicated) } #ifndef STANDALONE -void startlistenserver(int *usemaster) -{ +void startlistenserver(int *usemaster) { if(serverhost) { conoutf(CON_ERROR, "listen server is already running"); return; } - allowupdatemaster = *usemaster>0 ? 1 : 0; - if(!setuplistenserver(false)) return; - updatemasterserver(); - conoutf("listen server started for %d clients%s", maxclients, allowupdatemaster ? " and listed with master server" : ""); } COMMAND(startlistenserver, "i"); -void stoplistenserver() -{ +void stoplistenserver() { if(!serverhost) { conoutf(CON_ERROR, "listen server is not running"); return; } - kicknonlocalclients(); enet_host_flush(serverhost); cleanupserver(); - conoutf("listen server stopped"); } COMMAND(stoplistenserver, ""); #endif -bool serveroption(char *opt) -{ - switch(opt[1]) - { +bool serveroption(char *opt) { + switch(opt[1]) { case 'u': setvar("serveruprate", atoi(opt+2)); return true; case 'c': setvar("maxclients", atoi(opt+2)); return true; case 'i': setsvar("serverip", opt+2); return true; @@ -843,8 +705,7 @@ bool serveroption(char *opt) vector<const char *> gameargs; #ifdef STANDALONE -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { setlogfile(NULL); if(enet_initialize()<0) fatal("Unable to initialise network module"); atexit(enet_deinitialize); diff --git a/src/engine/serverbrowser.cpp b/src/engine/serverbrowser.cpp index 85109bf..a839c35 100644 --- a/src/engine/serverbrowser.cpp +++ b/src/engine/serverbrowser.cpp @@ -4,15 +4,13 @@ #define PROTOCOL_VERSION 260 // bump when protocol changes, dpulicate -struct resolverthread -{ +struct resolverthread { SDL_Thread *thread; const char *query; int starttime; }; -struct resolverresult -{ +struct resolverresult { const char *query; ENetAddress address; }; @@ -26,28 +24,23 @@ SDL_cond *querycond, *resultcond; #define RESOLVERTHREADS 2 #define RESOLVERLIMIT 3000 -int resolverloop(void * data) -{ +int resolverloop(void * data) { resolverthread *rt = (resolverthread *)data; SDL_LockMutex(resolvermutex); SDL_Thread *thread = rt->thread; SDL_UnlockMutex(resolvermutex); if(!thread || SDL_GetThreadID(thread) != SDL_ThreadID()) return 0; - while(thread == rt->thread) - { + while(thread == rt->thread) { SDL_LockMutex(resolvermutex); while(resolverqueries.empty()) SDL_CondWait(querycond, resolvermutex); rt->query = resolverqueries.pop(); rt->starttime = totalmillis; SDL_UnlockMutex(resolvermutex); - ENetAddress address = { ENET_HOST_ANY, ENET_PORT_ANY }; enet_address_set_host(&address, rt->query); - SDL_LockMutex(resolvermutex); - if(rt->query && thread == rt->thread) - { + if(rt->query && thread == rt->thread) { resolverresult &rr = resolverresults.add(); rr.query = rt->query; rr.address = address; @@ -60,15 +53,12 @@ int resolverloop(void * data) return 0; } -void resolverinit() -{ +void resolverinit() { resolvermutex = SDL_CreateMutex(); querycond = SDL_CreateCond(); resultcond = SDL_CreateCond(); - SDL_LockMutex(resolvermutex); - loopi(RESOLVERTHREADS) - { + loopi(RESOLVERTHREADS) { resolverthread &rt = resolverthreads.add(); rt.query = NULL; rt.starttime = 0; @@ -77,11 +67,9 @@ void resolverinit() SDL_UnlockMutex(resolvermutex); } -void resolverstop(resolverthread &rt) -{ +void resolverstop(resolverthread &rt) { SDL_LockMutex(resolvermutex); - if(rt.query) - { + if(rt.query) { #if SDL_VERSION_ATLEAST(2, 0, 2) SDL_DetachThread(rt.thread); #endif @@ -92,47 +80,38 @@ void resolverstop(resolverthread &rt) SDL_UnlockMutex(resolvermutex); } -void resolverclear() -{ +void resolverclear() { if(resolverthreads.empty()) return; - SDL_LockMutex(resolvermutex); resolverqueries.shrink(0); resolverresults.shrink(0); - loopv(resolverthreads) - { + loopv(resolverthreads) { resolverthread &rt = resolverthreads[i]; resolverstop(rt); } SDL_UnlockMutex(resolvermutex); } -void resolverquery(const char *name) -{ +void resolverquery(const char *name) { if(resolverthreads.empty()) resolverinit(); - SDL_LockMutex(resolvermutex); resolverqueries.add(name); SDL_CondSignal(querycond); SDL_UnlockMutex(resolvermutex); } -bool resolvercheck(const char **name, ENetAddress *address) -{ +bool resolvercheck(const char **name, ENetAddress *address) { bool resolved = false; SDL_LockMutex(resolvermutex); - if(!resolverresults.empty()) - { + if(!resolverresults.empty()) { resolverresult &rr = resolverresults.pop(); *name = rr.query; address->host = rr.address.host; resolved = true; } - else loopv(resolverthreads) - { + else loopv(resolverthreads) { resolverthread &rt = resolverthreads[i]; - if(rt.query && totalmillis - rt.starttime > RESOLVERLIMIT) - { + if(rt.query && totalmillis - rt.starttime > RESOLVERLIMIT) { resolverstop(rt); *name = rt.query; resolved = true; @@ -142,39 +121,31 @@ bool resolvercheck(const char **name, ENetAddress *address) return resolved; } -bool resolverwait(const char *name, ENetAddress *address) -{ +bool resolverwait(const char *name, ENetAddress *address) { if(resolverthreads.empty()) resolverinit(); - defformatstring(text, "resolving %s... (esc to abort)", name); renderprogress(0, text); - SDL_LockMutex(resolvermutex); resolverqueries.add(name); SDL_CondSignal(querycond); int starttime = SDL_GetTicks(), timeout = 0; bool resolved = false; - for(;;) - { + for(;;) { SDL_CondWaitTimeout(resultcond, resolvermutex, 250); - loopv(resolverresults) if(resolverresults[i].query == name) - { + loopv(resolverresults) if(resolverresults[i].query == name) { address->host = resolverresults[i].address.host; resolverresults.remove(i); resolved = true; break; } if(resolved) break; - timeout = SDL_GetTicks() - starttime; renderprogress(min(float(timeout)/RESOLVERLIMIT, 1.0f), text); if(interceptkey(SDLK_ESCAPE)) timeout = RESOLVERLIMIT + 1; if(timeout > RESOLVERLIMIT) break; } - if(!resolved && timeout > RESOLVERLIMIT) - { - loopv(resolverthreads) - { + if(!resolved && timeout > RESOLVERLIMIT) { + loopv(resolverthreads) { resolverthread &rt = resolverthreads[i]; if(rt.query == name) { resolverstop(rt); break; } } @@ -185,24 +156,19 @@ bool resolverwait(const char *name, ENetAddress *address) #define CONNLIMIT 20000 -int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress &address) -{ +int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress &address) { defformatstring(text, "connecting to %s... (esc to abort)", hostname); renderprogress(0, text); - ENetSocketSet readset, writeset; - if(!enet_socket_connect(sock, &address)) for(int starttime = SDL_GetTicks(), timeout = 0; timeout <= CONNLIMIT;) - { + if(!enet_socket_connect(sock, &address)) for(int starttime = SDL_GetTicks(), timeout = 0; timeout <= CONNLIMIT;) { ENET_SOCKETSET_EMPTY(readset); ENET_SOCKETSET_EMPTY(writeset); ENET_SOCKETSET_ADD(readset, sock); ENET_SOCKETSET_ADD(writeset, sock); int result = enet_socketset_select(sock, &readset, &writeset, 250); if(result < 0) break; - else if(result > 0) - { - if(ENET_SOCKETSET_CHECK(readset, sock) || ENET_SOCKETSET_CHECK(writeset, sock)) - { + else if(result > 0) { + if(ENET_SOCKETSET_CHECK(readset, sock) || ENET_SOCKETSET_CHECK(writeset, sock)) { int error = 0; if(enet_socket_get_option(sock, ENET_SOCKOPT_ERROR, &error) < 0 || error) break; return 0; @@ -212,45 +178,30 @@ int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress renderprogress(min(float(timeout)/CONNLIMIT, 1.0f), text); if(interceptkey(SDLK_ESCAPE)) break; } - return -1; } -struct pingattempts -{ +struct pingattempts { enum { MAXATTEMPTS = 2 }; - int offset, attempts[MAXATTEMPTS]; - pingattempts() : offset(0) { clearattempts(); } - void clearattempts() { memset(attempts, 0, sizeof(attempts)); } - void setoffset() { offset = 1 + rnd(0xFFFFFF); } - - int encodeping(int millis) - { + int encodeping(int millis) { millis += offset; return millis ? millis : 1; } - - int decodeping(int val) - { + int decodeping(int val) { return val - offset; } - - int addattempt(int millis) - { + int addattempt(int millis) { int val = encodeping(millis); loopk(MAXATTEMPTS-1) attempts[k+1] = attempts[k]; attempts[0] = val; return val; } - - bool checkattempt(int val, bool del = true) - { - if(val) loopk(MAXATTEMPTS) if(attempts[k] == val) - { + bool checkattempt(int val, bool del = true) { + if(val) loopk(MAXATTEMPTS) if(attempts[k] == val) { if(del) attempts[k] = 0; return true; } @@ -261,15 +212,11 @@ struct pingattempts enum { UNRESOLVED = 0, RESOLVING, RESOLVED }; -struct serverinfo : pingattempts -{ - enum - { +struct serverinfo : pingattempts { + enum { WAITING = INT_MAX, - MAXPINGS = 3 }; - string name, map, sdesc; int port, numplayers, resolved, ping, lastping, nextping; int pings[MAXPINGS]; @@ -277,65 +224,47 @@ struct serverinfo : pingattempts ENetAddress address; bool keep; const char *password; - serverinfo() - : port(-1), numplayers(0), resolved(UNRESOLVED), keep(false), password(NULL) - { + : port(-1), numplayers(0), resolved(UNRESOLVED), keep(false), password(NULL) { name[0] = map[0] = sdesc[0] = '\0'; clearpings(); setoffset(); } - - ~serverinfo() - { + ~serverinfo() { DELETEA(password); } - - void clearpings() - { + void clearpings() { ping = WAITING; loopk(MAXPINGS) pings[k] = WAITING; nextping = 0; lastping = -1; clearattempts(); } - - void cleanup() - { + void cleanup() { clearpings(); attr.setsize(0); numplayers = 0; } - - void reset() - { + void reset() { lastping = -1; } - - void checkdecay(int decay) - { + void checkdecay(int decay) { if(lastping >= 0 && totalmillis - lastping >= decay) cleanup(); if(lastping < 0) lastping = totalmillis; } - - void calcping() - { + void calcping() { int numpings = 0, totalpings = 0; loopk(MAXPINGS) if(pings[k] != WAITING) { totalpings += pings[k]; numpings++; } ping = numpings ? totalpings/numpings : WAITING; } - - void addping(int rtt, int millis) - { + void addping(int rtt, int millis) { if(millis >= lastping) lastping = -1; pings[nextping] = rtt; nextping = (nextping+1)%MAXPINGS; calcping(); } - - static bool compare(serverinfo *a, serverinfo *b) - { + static bool compare(serverinfo *a, serverinfo *b) { bool ac = (a->attr.length() != 0) && (a->attr[0]==PROTOCOL_VERSION); bool bc = (b->attr.length() != 0) && (b->attr[0]==PROTOCOL_VERSION); if(ac > bc) return true; @@ -358,36 +287,27 @@ vector<serverinfo *> servers; ENetSocket pingsock = ENET_SOCKET_NULL; int lastinfo = 0; -static serverinfo *newserver(const char *name, int port, uint ip = ENET_HOST_ANY) -{ +static serverinfo *newserver(const char *name, int port, uint ip = ENET_HOST_ANY) { serverinfo *si = new serverinfo; si->address.host = ip; si->address.port = server::serverinfoport(port); if(ip!=ENET_HOST_ANY) si->resolved = RESOLVED; - si->port = port; if(name) copystring(si->name, name); - else if(ip==ENET_HOST_ANY || enet_address_get_host_ip(&si->address, si->name, sizeof(si->name)) < 0) - { + else if(ip==ENET_HOST_ANY || enet_address_get_host_ip(&si->address, si->name, sizeof(si->name)) < 0) { delete si; return NULL; - } - servers.add(si); - return si; } -void addserver(const char *name, int port, const char *password, bool keep) -{ +void addserver(const char *name, int port, const char *password, bool keep) { if(port <= 0) port = server::serverport(); - loopv(servers) - { + loopv(servers) { serverinfo *s = servers[i]; if(strcmp(s->name, name) || s->port != port) continue; - if(password && (!s->password || strcmp(s->password, password))) - { + if(password && (!s->password || strcmp(s->password, password))) { DELETEA(s->password); s->password = newstring(password); } @@ -407,47 +327,37 @@ VARP(maxservpings, 0, 10, 1000); pingattempts lanpings; -template<size_t N> static inline void buildping(ENetBuffer &buf, uchar (&ping)[N], pingattempts &a) -{ +template<size_t N> static inline void buildping(ENetBuffer &buf, uchar (&ping)[N], pingattempts &a) { ucharbuf p(ping, N); putint(p, a.addattempt(totalmillis)); buf.data = ping; buf.dataLength = p.length(); } -void pingservers() -{ - if(pingsock == ENET_SOCKET_NULL) - { +void pingservers() { + if(pingsock == ENET_SOCKET_NULL) { pingsock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); - if(pingsock == ENET_SOCKET_NULL) - { + if(pingsock == ENET_SOCKET_NULL) { lastinfo = totalmillis; return; } enet_socket_set_option(pingsock, ENET_SOCKOPT_NONBLOCK, 1); enet_socket_set_option(pingsock, ENET_SOCKOPT_BROADCAST, 1); - lanpings.setoffset(); } - ENetBuffer buf; uchar ping[MAXTRANS]; - static int lastping = 0; if(lastping >= servers.length()) lastping = 0; - loopi(maxservpings ? min(servers.length(), maxservpings) : servers.length()) - { + loopi(maxservpings ? min(servers.length(), maxservpings) : servers.length()) { serverinfo &si = *servers[lastping]; if(++lastping >= servers.length()) lastping = 0; if(si.address.host == ENET_HOST_ANY) continue; buildping(buf, ping, si); enet_socket_send(pingsock, &si.address, &buf, 1); - si.checkdecay(servpingdecay); } - if(searchlan) - { + if(searchlan) { ENetAddress address; address.host = ENET_HOST_BROADCAST; address.port = server::laninfoport(); @@ -457,31 +367,24 @@ void pingservers() lastinfo = totalmillis; } -void checkresolver() -{ +void checkresolver() { int resolving = 0; - loopv(servers) - { + loopv(servers) { serverinfo &si = *servers[i]; if(si.resolved == RESOLVED) continue; - if(si.address.host == ENET_HOST_ANY) - { + if(si.address.host == ENET_HOST_ANY) { if(si.resolved == UNRESOLVED) { si.resolved = RESOLVING; resolverquery(si.name); } resolving++; } } if(!resolving) return; - const char *name = NULL; - for(;;) - { + for(;;) { ENetAddress addr = { ENET_HOST_ANY, ENET_PORT_ANY }; if(!resolvercheck(&name, &addr)) break; - loopv(servers) - { + loopv(servers) { serverinfo &si = *servers[i]; - if(name == si.name) - { + if(name == si.name) { si.resolved = RESOLVED; si.address.host = addr.host; break; @@ -492,8 +395,7 @@ void checkresolver() static int lastreset = 0; -void checkpings() -{ +void checkpings() { if(pingsock==ENET_SOCKET_NULL) return; enet_uint32 events = ENET_SOCKET_WAIT_RECEIVE; ENetBuffer buf; @@ -502,22 +404,19 @@ void checkpings() char text[MAXTRANS]; buf.data = ping; buf.dataLength = sizeof(ping); - while(enet_socket_wait(pingsock, &events, 0) >= 0 && events) - { + while(enet_socket_wait(pingsock, &events, 0) >= 0 && events) { int len = enet_socket_receive(pingsock, &addr, &buf, 1); if(len <= 0) return; ucharbuf p(ping, len); int millis = getint(p); serverinfo *si = NULL; loopv(servers) if(addr.host == servers[i]->address.host && addr.port == servers[i]->address.port) { si = servers[i]; break; } - if(si) - { + if(si) { if(!si->checkattempt(millis)) continue; millis = si->decodeping(millis); } else if(!searchlan || !lanpings.checkattempt(millis, false)) continue; - else - { + else { si = newserver(NULL, server::serverport(addr.port), addr.host); millis = lanpings.decodeping(millis); } @@ -534,8 +433,7 @@ void checkpings() } } -void sortservers() -{ +void sortservers() { servers.sort(serverinfo::compare); } COMMAND(sortservers, ""); @@ -543,17 +441,14 @@ COMMAND(sortservers, ""); VARP(autosortservers, 0, 1, 1); VARP(autoupdateservers, 0, 1, 1); -void refreshservers() -{ +void refreshservers() { static int lastrefresh = 0; if(lastrefresh==totalmillis) return; - if(totalmillis - lastrefresh > 1000) - { + if(totalmillis - lastrefresh > 1000) { loopv(servers) servers[i]->reset(); lastreset = totalmillis; } lastrefresh = totalmillis; - checkresolver(); checkpings(); if(totalmillis - lastinfo >= servpingrate/(maxservpings ? max(1, (servers.length() + maxservpings - 1) / maxservpings) : 1)) pingservers(); @@ -562,26 +457,21 @@ void refreshservers() serverinfo *selectedserver = NULL; -const char *showservers(g3d_gui *cgui, uint *header, int pagemin, int pagemax) -{ +const char *showservers(g3d_gui *cgui, uint *header, int pagemin, int pagemax) { refreshservers(); - if(servers.empty()) - { + if(servers.empty()) { if(header) execute(header); return NULL; } serverinfo *sc = NULL; - for(int start = 0; start < servers.length();) - { + for(int start = 0; start < servers.length();) { if(start > 0) cgui->tab(); if(header) execute(header); int end = servers.length(); cgui->pushlist(); - loopi(10) - { + loopi(10) { if(!game::serverinfostartcolumn(cgui, i)) break; - for(int j = start; j < end; j++) - { + for(int j = start; j < end; j++) { if(!i && j+1 - start >= pagemin && (j+1 - start >= pagemax || cgui->shouldtab())) { end = j; break; } serverinfo &si = *servers[j]; const char *sdesc = si.sdesc; @@ -600,8 +490,7 @@ const char *showservers(g3d_gui *cgui, uint *header, int pagemin, int pagemax) return "connectselected"; } -void connectselected() -{ +void connectselected() { if(!selectedserver) return; connectserv(selectedserver->name, selectedserver->port, selectedserver->password); selectedserver = NULL; @@ -609,8 +498,7 @@ void connectselected() COMMAND(connectselected, ""); -void clearservers(bool full = false) -{ +void clearservers(bool full = false) { resolverclear(); if(full) servers.deletecontents(); else loopvrev(servers) if(!servers[i]->keep) delete servers.remove(i); @@ -619,24 +507,19 @@ void clearservers(bool full = false) #define RETRIEVELIMIT 20000 -void retrieveservers(vector<char> &data) -{ +void retrieveservers(vector<char> &data) { ENetSocket sock = connectmaster(true); if(sock == ENET_SOCKET_NULL) return; - extern char *mastername; defformatstring(text, "retrieving servers from %s... (esc to abort)", mastername); renderprogress(0, text); - int starttime = SDL_GetTicks(), timeout = 0; const char *req = "list\n"; int reqlen = strlen(req); ENetBuffer buf; - while(reqlen > 0) - { + while(reqlen > 0) { enet_uint32 events = ENET_SOCKET_WAIT_SEND; - if(enet_socket_wait(sock, &events, 250) >= 0 && events) - { + if(enet_socket_wait(sock, &events, 250) >= 0 && events) { buf.data = (void *)req; buf.dataLength = reqlen; int sent = enet_socket_send(sock, NULL, &buf, 1); @@ -650,12 +533,9 @@ void retrieveservers(vector<char> &data) if(interceptkey(SDLK_ESCAPE)) timeout = RETRIEVELIMIT + 1; if(timeout > RETRIEVELIMIT) break; } - - if(reqlen <= 0) for(;;) - { + if(reqlen <= 0) for(;;) { enet_uint32 events = ENET_SOCKET_WAIT_RECEIVE; - if(enet_socket_wait(sock, &events, 250) >= 0 && events) - { + if(enet_socket_wait(sock, &events, 250) >= 0 && events) { if(data.length() >= data.capacity()) data.reserve(4096); buf.data = data.getbuf() + data.length(); buf.dataLength = data.capacity() - data.length(); @@ -668,39 +548,31 @@ void retrieveservers(vector<char> &data) if(interceptkey(SDLK_ESCAPE)) timeout = RETRIEVELIMIT + 1; if(timeout > RETRIEVELIMIT) break; } - if(data.length()) data.add('\0'); enet_socket_destroy(sock); } bool updatedservers = false; -void updatefrommaster() -{ +void updatefrommaster() { vector<char> data; retrieveservers(data); if(data.empty()) conoutf(CON_ERROR, "master server not replying"); - else - { + else { clearservers(); char *line = data.getbuf(); - while(char *end = (char *)memchr(line, '\n', data.length() - (line - data.getbuf()))) - { + while(char *end = (char *)memchr(line, '\n', data.length() - (line - data.getbuf()))) { *end = '\0'; - const char *args = line; while(args < end && !iscubespace(*args)) args++; int cmdlen = args - line; while(args < end && iscubespace(*args)) args++; - - if(matchstring(line, cmdlen, "addserver")) - { + if(matchstring(line, cmdlen, "addserver")) { string ip; int port; if(sscanf(args, "%100s %d", ip, &port) == 2) addserver(ip, port); } else if(matchstring(line, cmdlen, "echo")) conoutf("\f1%s", args); - line = end + 1; } } @@ -708,8 +580,7 @@ void updatefrommaster() updatedservers = true; } -void initservers() -{ +void initservers() { selectedserver = NULL; if(autoupdateservers && !updatedservers) updatefrommaster(); } @@ -720,17 +591,14 @@ ICOMMAND(clearservers, "i", (int *full), clearservers(*full!=0)); COMMAND(updatefrommaster, ""); COMMAND(initservers, ""); -void writeservercfg() -{ +void writeservercfg() { if(!game::savedservers()) return; stream *f = openutf8file(path(game::savedservers(), true), "w"); if(!f) return; int kept = 0; - loopv(servers) - { + loopv(servers) { serverinfo *s = servers[i]; - if(s->keep) - { + if(s->keep) { if(!kept) f->printf("// servers that should never be cleared from the server list\n\n"); if(s->password) f->printf("keepserver %s %d %s\n", escapeid(s->name), s->port, escapestring(s->password)); else f->printf("keepserver %s %d\n", escapeid(s->name), s->port); @@ -739,11 +607,9 @@ void writeservercfg() } if(kept) f->printf("\n"); f->printf("// servers connected to are added here automatically\n\n"); - loopv(servers) - { + loopv(servers) { serverinfo *s = servers[i]; - if(!s->keep) - { + if(!s->keep) { if(s->password) f->printf("addserver %s %d %s\n", escapeid(s->name), s->port, escapestring(s->password)); else f->printf("addserver %s %d\n", escapeid(s->name), s->port); } diff --git a/src/engine/shader.cpp b/src/engine/shader.cpp index 67b9e42..8f5e9b7 100644 --- a/src/engine/shader.cpp +++ b/src/engine/shader.cpp @@ -18,41 +18,32 @@ VAR(maxvsuniforms, 1, 0, 0); VAR(maxfsuniforms, 1, 0, 0); VAR(maxvaryings, 1, 0, 0); -void loadshaders() -{ +void loadshaders() { standardshaders = true; execfile("data/glsl.cfg"); standardshaders = false; - nullshader = lookupshaderbyname("null"); hudshader = lookupshaderbyname("hud"); hudnotextureshader = lookupshaderbyname("hudnotexture"); stdworldshader = lookupshaderbyname("stdworld"); if(!nullshader || !hudshader || !hudnotextureshader || !stdworldshader) fatal("cannot find shader definitions"); - dummyslot.shader = stdworldshader; - textureshader = lookupshaderbyname("texture"); notextureshader = lookupshaderbyname("notexture"); nocolorshader = lookupshaderbyname("nocolor"); - nullshader->set(); - loadedshaders = true; } -Shader *lookupshaderbyname(const char *name) -{ +Shader *lookupshaderbyname(const char *name) { Shader *s = shaders.access(name); return s && s->loaded() ? s : NULL; } -Shader *generateshader(const char *name, const char *fmt, ...) -{ +Shader *generateshader(const char *name, const char *fmt, ...) { if(!loadedshaders) return NULL; Shader *s = name ? lookupshaderbyname(name) : NULL; - if(!s) - { + if(!s) { defvformatstring(cmd, fmt, fmt); bool wasstandard = standardshaders; standardshaders = true; @@ -64,29 +55,24 @@ Shader *generateshader(const char *name, const char *fmt, ...) return s; } -static void showglslinfo(GLenum type, GLuint obj, const char *name, const char **parts = NULL, int numparts = 0) -{ +static void showglslinfo(GLenum type, GLuint obj, const char *name, const char **parts = NULL, int numparts = 0) { GLint length = 0; if(type) glGetShaderiv_(obj, GL_INFO_LOG_LENGTH, &length); else glGetProgramiv_(obj, GL_INFO_LOG_LENGTH, &length); - if(length > 1) - { + if(length > 1) { conoutf(CON_ERROR, "GLSL ERROR (%s:%s)", type == GL_VERTEX_SHADER ? "VS" : (type == GL_FRAGMENT_SHADER ? "FS" : "PROG"), name); FILE *l = getlogfile(); - if(l) - { + if(l) { GLchar *log = new GLchar[length]; if(type) glGetShaderInfoLog_(obj, length, &length, log); else glGetProgramInfoLog_(obj, length, &length, log); fprintf(l, "%s\n", log); bool partlines = log[0] != '0'; int line = 0; - loopi(numparts) - { + loopi(numparts) { const char *part = parts[i]; int startline = line; - while(*part) - { + while(*part) { const char *next = strchr(part, '\n'); if(++line > 1000) goto done; if(partlines) fprintf(l, "%d(%d): ", i, line - startline); else fprintf(l, "%d: ", line); @@ -101,30 +87,26 @@ static void showglslinfo(GLenum type, GLuint obj, const char *name, const char * } } -static void compileglslshader(GLenum type, GLuint &obj, const char *def, const char *name, bool msg = true) -{ +static void compileglslshader(GLenum type, GLuint &obj, const char *def, const char *name, bool msg = true) { const char *source = def + strspn(def, " \t\r\n"); const char *parts[16]; int numparts = 0; - static const struct { int version; const char * const header; } glslversions[] = - { - { 330, "#version 330\n" }, - { 150, "#version 150\n" }, - { 130, "#version 130\n" }, - { 120, "#version 120\n" } + static const struct { int version; const char * const header; } glslversions[] = { + { + 330, "#version 330\n" }, { + 150, "#version 150\n" }, { + 130, "#version 130\n" }, { + 120, "#version 120\n" } }; - loopi(sizeof(glslversions)/sizeof(glslversions[0])) if(glslversion >= glslversions[i].version) - { + loopi(sizeof(glslversions)/sizeof(glslversions[0])) if(glslversion >= glslversions[i].version) { parts[numparts++] = glslversions[i].header; break; } - if(glslversion >= 130) - { + if(glslversion >= 130) { if(type == GL_VERTEX_SHADER) parts[numparts++] = "#define attribute in\n" "#define varying out\n"; - else if(type == GL_FRAGMENT_SHADER) - { + else if(type == GL_FRAGMENT_SHADER) { parts[numparts++] = "#define varying in\n"; if(glslversion < 150) parts[numparts++] = "precision highp float;\n"; if(glversion >= 300) parts[numparts++] = @@ -137,35 +119,30 @@ static void compileglslshader(GLenum type, GLuint &obj, const char *def, const c "#define textureCube(sampler, coords) texture(sampler, coords)\n"; } parts[numparts++] = source; - obj = glCreateShader_(type); glShaderSource_(obj, numparts, (const GLchar **)parts, NULL); glCompileShader_(obj); GLint success; glGetShaderiv_(obj, GL_COMPILE_STATUS, &success); - if(!success) - { + if(!success) { if(msg) showglslinfo(type, obj, name, parts, numparts); glDeleteShader_(obj); obj = 0; } } -static void bindglsluniform(Shader &s, UniformLoc &u) -{ +static void bindglsluniform(Shader &s, UniformLoc &u) { u.loc = glGetUniformLocation_(s.program, u.name); if(!u.blockname || !hasUBO) return; GLuint bidx = glGetUniformBlockIndex_(s.program, u.blockname); GLuint uidx = GL_INVALID_INDEX; glGetUniformIndices_(s.program, 1, &u.name, &uidx); - if(bidx != GL_INVALID_INDEX && uidx != GL_INVALID_INDEX) - { + if(bidx != GL_INVALID_INDEX && uidx != GL_INVALID_INDEX) { GLint sizeval = 0, offsetval = 0, strideval = 0; glGetActiveUniformBlockiv_(s.program, bidx, GL_UNIFORM_BLOCK_DATA_SIZE, &sizeval); if(sizeval <= 0) return; glGetActiveUniformsiv_(s.program, 1, &uidx, GL_UNIFORM_OFFSET, &offsetval); - if(u.stride > 0) - { + if(u.stride > 0) { glGetActiveUniformsiv_(s.program, 1, &uidx, GL_UNIFORM_ARRAY_STRIDE, &strideval); if(strideval > u.stride) return; } @@ -175,69 +152,57 @@ static void bindglsluniform(Shader &s, UniformLoc &u) } } -static void linkglslprogram(Shader &s, bool msg = true) -{ +static void linkglslprogram(Shader &s, bool msg = true) { s.program = s.vsobj && s.psobj ? glCreateProgram_() : 0; GLint success = 0; - if(s.program) - { + if(s.program) { glAttachShader_(s.program, s.vsobj); glAttachShader_(s.program, s.psobj); uint attribs = 0; - loopv(s.attriblocs) - { + loopv(s.attriblocs) { AttribLoc &a = s.attriblocs[i]; glBindAttribLocation_(s.program, a.loc, a.name); attribs |= 1<<a.loc; } loopi(gle::MAXATTRIBS) if(!(attribs&(1<<i))) glBindAttribLocation_(s.program, i, gle::attribnames[i]); - if(glversion >= 300) - { + if(glversion >= 300) { glBindFragDataLocation_(s.program, 0, "cube2_FragColor"); } glLinkProgram_(s.program); glGetProgramiv_(s.program, GL_LINK_STATUS, &success); } - if(success) - { + if(success) { glUseProgram_(s.program); - loopi(8) - { + loopi(8) { static const char * const texnames[8] = { "tex0", "tex1", "tex2", "tex3", "tex4", "tex5", "tex6", "tex7" }; GLint loc = glGetUniformLocation_(s.program, texnames[i]); if(loc != -1) glUniform1i_(loc, i); } - loopv(s.defaultparams) - { + loopv(s.defaultparams) { SlotShaderParamState ¶m = s.defaultparams[i]; param.loc = glGetUniformLocation_(s.program, param.name); } loopv(s.uniformlocs) bindglsluniform(s, s.uniformlocs[i]); glUseProgram_(0); } - else if(s.program) - { + else if(s.program) { if(msg) showglslinfo(GL_FALSE, s.program, s.name); glDeleteProgram_(s.program); s.program = 0; } } -int getlocalparam(const char *name) -{ +int getlocalparam(const char *name) { return localparams.access(name, int(localparams.numelems)); } -static int addlocalparam(Shader &s, const char *name, int loc, int size, GLenum format) -{ +static int addlocalparam(Shader &s, const char *name, int loc, int size, GLenum format) { int idx = getlocalparam(name); - if(idx >= s.localparamremap.length()) - { + if(idx >= s.localparamremap.length()) { int n = idx + 1 - s.localparamremap.length(); memset(s.localparamremap.pad(n), 0xFF, n); } s.localparamremap[idx] = s.localparams.length(); - LocalShaderParamState &l = s.localparams.add(); l.name = name; l.loc = loc; @@ -246,11 +211,9 @@ static int addlocalparam(Shader &s, const char *name, int loc, int size, GLenum return idx; } -GlobalShaderParamState *getglobalparam(const char *name) -{ +GlobalShaderParamState *getglobalparam(const char *name) { GlobalShaderParamState *param = globalparams.access(name); - if(!param) - { + if(!param) { param = &globalparams[name]; param->name = name; memset(param->buf, -1, sizeof(param->buf)); @@ -259,8 +222,7 @@ GlobalShaderParamState *getglobalparam(const char *name) return param; } -static GlobalShaderParamUse *addglobalparam(Shader &s, GlobalShaderParamState *param, int loc, int size, GLenum format) -{ +static GlobalShaderParamUse *addglobalparam(Shader &s, GlobalShaderParamState *param, int loc, int size, GLenum format) { GlobalShaderParamUse &g = s.globalparams.add(); g.param = param; g.version = -2; @@ -270,10 +232,8 @@ static GlobalShaderParamUse *addglobalparam(Shader &s, GlobalShaderParamState *p return &g; } -static void setglsluniformformat(Shader &s, const char *name, GLenum format, int size) -{ - switch(format) - { +static void setglsluniformformat(Shader &s, const char *name, GLenum format, int size) { + switch(format) { case GL_FLOAT: case GL_FLOAT_VEC2: case GL_FLOAT_VEC3: @@ -294,31 +254,26 @@ static void setglsluniformformat(Shader &s, const char *name, GLenum format, int return; } if(!strncmp(name, "gl_", 3)) return; - int loc = glGetUniformLocation_(s.program, name); if(loc < 0) return; - loopvj(s.defaultparams) if(s.defaultparams[j].loc == loc) - { + loopvj(s.defaultparams) if(s.defaultparams[j].loc == loc) { s.defaultparams[j].format = format; return; } loopvj(s.uniformlocs) if(s.uniformlocs[j].loc == loc) return; loopvj(s.globalparams) if(s.globalparams[j].loc == loc) return; loopvj(s.localparams) if(s.localparams[j].loc == loc) return; - name = getshaderparamname(name); GlobalShaderParamState *param = globalparams.access(name); if(param) addglobalparam(s, param, loc, size, format); else addlocalparam(s, name, loc, size, format); } -static void allocglslactiveuniforms(Shader &s) -{ +static void allocglslactiveuniforms(Shader &s) { GLint numactive = 0; glGetProgramiv_(s.program, GL_ACTIVE_UNIFORMS, &numactive); string name; - loopi(numactive) - { + loopi(numactive) { GLsizei namelen = 0; GLint size = 0; GLenum format = GL_FLOAT_VEC4; @@ -332,19 +287,16 @@ static void allocglslactiveuniforms(Shader &s) } } -void Shader::allocparams(Slot *slot) -{ - if(slot) - { -#define UNIFORMTEX(name, tmu) \ - { \ +void Shader::allocparams(Slot *slot) { + if(slot) { +#define UNIFORMTEX(name, tmu) { \ + \ loc = glGetUniformLocation_(program, name); \ int val = tmu; \ if(loc != -1) glUniform1i_(loc, val); \ } int loc, tmu = 2; - if(type & SHADER_NORMALSLMS) - { + if(type & SHADER_NORMALSLMS) { UNIFORMTEX("lmcolor", 1); UNIFORMTEX("lmdir", 2); tmu++; @@ -352,19 +304,16 @@ void Shader::allocparams(Slot *slot) else UNIFORMTEX("lightmap", 1); UNIFORMTEX("shadowmap", 7); int stex = 0; - loopv(slot->sts) - { + loopv(slot->sts) { Slot::Tex &t = slot->sts[i]; - switch(t.type) - { + switch(t.type) { case TEX_DIFFUSE: UNIFORMTEX("diffusemap", 0); break; case TEX_NORMAL: UNIFORMTEX("normalmap", tmu++); break; case TEX_DECAL: UNIFORMTEX("decal", tmu++); break; case TEX_SPEC: if(t.combined<0) UNIFORMTEX("specmap", tmu++); break; case TEX_DEPTH: if(t.combined<0) UNIFORMTEX("depthmap", tmu++); break; case TEX_ALPHA: if(t.combined<0) UNIFORMTEX("alphamap", tmu++); break; - case TEX_UNKNOWN: - { + case TEX_UNKNOWN: { defformatstring(sname, "stex%d", stex++); UNIFORMTEX(sname, tmu++); break; @@ -377,32 +326,25 @@ void Shader::allocparams(Slot *slot) int GlobalShaderParamState::nextversion = 0; -void GlobalShaderParamState::resetversions() -{ - enumerate(shaders, Shader, s, - { - loopv(s.globalparams) - { +void GlobalShaderParamState::resetversions() { + enumerate(shaders, Shader, s, { + loopv(s.globalparams) { GlobalShaderParamUse &u = s.globalparams[i]; if(u.version != u.param->version) u.version = -2; } }); nextversion = 0; enumerate(globalparams, GlobalShaderParamState, g, { g.version = ++nextversion; }); - enumerate(shaders, Shader, s, - { - loopv(s.globalparams) - { + enumerate(shaders, Shader, s, { + loopv(s.globalparams) { GlobalShaderParamUse &u = s.globalparams[i]; if(u.version >= 0) u.version = u.param->version; } }); } -static inline void setslotparam(SlotShaderParamState &l, const float *val) -{ - switch(l.format) - { +static inline void setslotparam(SlotShaderParamState &l, const float *val) { + switch(l.format) { case GL_BOOL: case GL_FLOAT: glUniform1fv_(l.loc, 1, val); break; case GL_BOOL_VEC2: @@ -426,52 +368,46 @@ static inline void setslotparam(SlotShaderParamState &l, const float *val) } while(0) #define SETSLOTPARAMS(slotparams) \ - loopv(slotparams) \ - { \ + loopv(slotparams) { \ + \ SlotShaderParam &p = slotparams[i]; \ if(!defaultparams.inrange(p.loc)) continue; \ SlotShaderParamState &l = defaultparams[p.loc]; \ SETSLOTPARAM(l, unimask, p.loc, p.val); \ } #define SETDEFAULTPARAMS \ - loopv(defaultparams) \ - { \ + loopv(defaultparams) { \ + \ SlotShaderParamState &l = defaultparams[i]; \ SETSLOTPARAM(l, unimask, i, l.val); \ } -void Shader::setslotparams(Slot &slot) -{ +void Shader::setslotparams(Slot &slot) { uint unimask = 0; SETSLOTPARAMS(slot.params) SETDEFAULTPARAMS } -void Shader::setslotparams(Slot &slot, VSlot &vslot) -{ +void Shader::setslotparams(Slot &slot, VSlot &vslot) { uint unimask = 0; - if(vslot.slot == &slot) - { + if(vslot.slot == &slot) { SETSLOTPARAMS(vslot.params) SETSLOTPARAMS(slot.params) SETDEFAULTPARAMS } - else - { + else { SETSLOTPARAMS(slot.params) SETDEFAULTPARAMS } } -void Shader::bindprograms() -{ +void Shader::bindprograms() { if(this == lastshader || type&(SHADER_DEFERRED|SHADER_INVALID)) return; glUseProgram_(program); lastshader = this; } -bool Shader::compile() -{ +bool Shader::compile() { if(!vsstr) vsobj = !reusevs || reusevs->invalid() ? 0 : reusevs->vsobj; else compileglslshader(GL_VERTEX_SHADER, vsobj, vsstr, name, !variantshader); if(!psstr) psobj = !reuseps || reuseps->invalid() ? 0 : reuseps->psobj; @@ -480,8 +416,7 @@ bool Shader::compile() return program!=0; } -void Shader::cleanup(bool invalid) -{ +void Shader::cleanup(bool invalid) { detailshader = NULL; used = false; if(vsobj) { if(!reusevs) glDeleteShader_(vsobj); vsobj = 0; } @@ -490,8 +425,7 @@ void Shader::cleanup(bool invalid) localparams.setsize(0); localparamremap.setsize(0); globalparams.setsize(0); - if(standard || invalid) - { + if(standard || invalid) { type = SHADER_INVALID; DELETEA(vsstr); DELETEA(psstr); @@ -511,28 +445,24 @@ void Shader::cleanup(bool invalid) bool Shader::isnull(const Shader *s) { return !s; } -static void genattriblocs(Shader &s, const char *vs, const char *ps, Shader *reusevs, Shader *reuseps) -{ +static void genattriblocs(Shader &s, const char *vs, const char *ps, Shader *reusevs, Shader *reuseps) { static int len = strlen("//:attrib"); string name; int loc; if(reusevs) s.attriblocs = reusevs->attriblocs; - else while((vs = strstr(vs, "//:attrib"))) - { + else while((vs = strstr(vs, "//:attrib"))) { if(sscanf(vs, "//:attrib %100s %d", name, &loc) == 2) s.attriblocs.add(AttribLoc(getshaderparamname(name), loc)); vs += len; } } -static void genuniformlocs(Shader &s, const char *vs, const char *ps, Shader *reusevs, Shader *reuseps) -{ +static void genuniformlocs(Shader &s, const char *vs, const char *ps, Shader *reusevs, Shader *reuseps) { static int len = strlen("//:uniform"); string name, blockname; int binding, stride; if(reusevs) s.uniformlocs = reusevs->uniformlocs; - else while((vs = strstr(vs, "//:uniform"))) - { + else while((vs = strstr(vs, "//:uniform"))) { int numargs = sscanf(vs, "//:uniform %100s %100s %d %d", name, blockname, &binding, &stride); if(numargs >= 3) s.uniformlocs.add(UniformLoc(getshaderparamname(name), getshaderparamname(blockname), binding, numargs >= 4 ? stride : 0)); else if(numargs >= 1) s.uniformlocs.add(UniformLoc(getshaderparamname(name))); @@ -540,14 +470,11 @@ static void genuniformlocs(Shader &s, const char *vs, const char *ps, Shader *re } } -Shader *newshader(int type, const char *name, const char *vs, const char *ps, Shader *variant = NULL, int row = 0) -{ - if(Shader::lastshader) - { +Shader *newshader(int type, const char *name, const char *vs, const char *ps, Shader *variant = NULL, int row = 0) { + if(Shader::lastshader) { glUseProgram_(0); Shader::lastshader = NULL; } - Shader *exists = shaders.access(name); char *rname = exists ? exists->name : newstring(name); Shader &s = shaders[rname]; @@ -560,17 +487,14 @@ Shader *newshader(int type, const char *name, const char *vs, const char *ps, Sh s.standard = standardshaders; if(forceshaders) s.forced = true; s.reusevs = s.reuseps = NULL; - if(variant) - { + if(variant) { int row = 0, col = 0; - if(!vs[0] || sscanf(vs, "%d , %d", &row, &col) >= 1) - { + if(!vs[0] || sscanf(vs, "%d , %d", &row, &col) >= 1) { DELETEA(s.vsstr); s.reusevs = !vs[0] ? variant : variant->getvariant(col, row); } row = col = 0; - if(!ps[0] || sscanf(ps, "%d , %d", &row, &col) >= 1) - { + if(!ps[0] || sscanf(ps, "%d , %d", &row, &col) >= 1) { DELETEA(s.psstr); s.reuseps = !ps[0] ? variant : variant->getvariant(col, row); } @@ -581,8 +505,7 @@ Shader *newshader(int type, const char *name, const char *vs, const char *ps, Sh s.uniformlocs.setsize(0); genattriblocs(s, vs, ps, s.reusevs, s.reuseps); genuniformlocs(s, vs, ps, s.reusevs, s.reuseps); - if(!s.compile()) - { + if(!s.compile()) { s.cleanup(true); if(variant) shaders.remove(rname); return NULL; @@ -592,19 +515,16 @@ Shader *newshader(int type, const char *name, const char *vs, const char *ps, Sh return &s; } -void setupshaders() -{ +void setupshaders() { GLint val; glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &val); maxvsuniforms = val/4; glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &val); maxfsuniforms = val/4; - if(glversion < 300) - { + if(glversion < 300) { glGetIntegerv(GL_MAX_VARYING_COMPONENTS, &val); maxvaryings = val; } - standardshaders = true; nullshader = newshader(0, "<init>null", "attribute vec4 vvertex;\n" @@ -644,38 +564,31 @@ void setupshaders() " gl_FragColor = color;\n" "}\n"); standardshaders = false; - if(!nullshader || !hudshader || !hudnotextureshader) fatal("failed to setup shaders"); - dummyslot.shader = nullshader; } -static const char *findglslmain(const char *s) -{ +static const char *findglslmain(const char *s) { const char *main = strstr(s, "main"); if(!main) return NULL; for(; main >= s; main--) switch(*main) { case '\r': case '\n': case ';': return main + 1; } return s; } -static void gengenericvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 0) -{ +static void gengenericvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 0) { int rowoffset = 0; bool vschanged = false, pschanged = false; vector<char> vsv, psv; vsv.put(vs, strlen(vs)+1); psv.put(ps, strlen(ps)+1); - static const int len = strlen("//:variant"), olen = strlen("override"); - for(char *vspragma = vsv.getbuf();; vschanged = true) - { + for(char *vspragma = vsv.getbuf();; vschanged = true) { vspragma = strstr(vspragma, "//:variant"); if(!vspragma) break; if(sscanf(vspragma + len, "row %d", &rowoffset) == 1) continue; memset(vspragma, ' ', len); vspragma += len; - if(!strncmp(vspragma, "override", olen)) - { + if(!strncmp(vspragma, "override", olen)) { memset(vspragma, ' ', olen); vspragma += olen; char *end = vspragma + strcspn(vspragma, "\n\r"); @@ -684,15 +597,13 @@ static void gengenericvariant(Shader &s, const char *sname, const char *vs, cons memset(end, ' ', endlen); } } - for(char *pspragma = psv.getbuf();; pschanged = true) - { + for(char *pspragma = psv.getbuf();; pschanged = true) { pspragma = strstr(pspragma, "//:variant"); if(!pspragma) break; if(sscanf(pspragma + len, "row %d", &rowoffset) == 1) continue; memset(pspragma, ' ', len); pspragma += len; - if(!strncmp(pspragma, "override", olen)) - { + if(!strncmp(pspragma, "override", olen)) { memset(pspragma, ' ', olen); pspragma += olen; char *end = pspragma + strcspn(pspragma, "\n\r"); @@ -713,52 +624,38 @@ static void gengenericvariant(Shader &s, const char *sname, const char *vs, cons bool minimizedynlighttcusage() { return glversion < 300 && maxvaryings < 48; } -static void gendynlightvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 0) -{ +static void gendynlightvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 0) { int numlights = minimizedynlighttcusage() ? 1 : MAXDYNLIGHTS; - const char *vspragma = strstr(vs, "//:dynlight"), *pspragma = strstr(ps, "//:dynlight"); if(!vspragma || !pspragma) return; - string pslight; vspragma += strcspn(vspragma, "\n"); if(*vspragma) vspragma++; - if(sscanf(pspragma, "//:dynlight %100s", pslight)!=1) return; - pspragma += strcspn(pspragma, "\n"); if(*pspragma) pspragma++; - const char *vsmain = findglslmain(vs), *psmain = findglslmain(ps); if(vsmain > vspragma) vsmain = vs; if(psmain > pspragma) psmain = ps; - vector<char> vsdl, psdl; - loopi(MAXDYNLIGHTS) - { + loopi(MAXDYNLIGHTS) { vsdl.setsize(0); psdl.setsize(0); if(vsmain >= vs) vsdl.put(vs, vsmain - vs); if(psmain >= ps) psdl.put(ps, psmain - ps); - defformatstring(pos, "uniform vec4 dynlightpos[%d];\n", i+1); vsdl.put(pos, strlen(pos)); psdl.put(pos, strlen(pos)); defformatstring(color, "uniform vec3 dynlightcolor[%d];\n", i+1); psdl.put(color, strlen(color)); - - loopk(min(i+1, numlights)) - { + loopk(min(i+1, numlights)) { defformatstring(dir, "%sdynlight%ddir%s", !k ? "varying vec3 " : " ", k, k==i || k+1==numlights ? ";\n" : ","); vsdl.put(dir, strlen(dir)); psdl.put(dir, strlen(dir)); } - vsdl.put(vsmain, vspragma-vsmain); psdl.put(psmain, pspragma-psmain); - - loopk(i+1) - { + loopk(i+1) { defformatstring(tc, k<numlights ? "dynlight%ddir = vvertex.xyz*dynlightpos[%d].w + dynlightpos[%d].xyz;\n" : @@ -766,58 +663,45 @@ static void gendynlightvariant(Shader &s, const char *sname, const char *vs, con k, k, k); if(k < numlights) vsdl.put(tc, strlen(tc)); else psdl.put(tc, strlen(tc)); - defformatstring(dl, "%s.rgb += dynlightcolor[%d] * (1.0 - clamp(dot(dynlight%ddir, dynlight%ddir), 0.0, 1.0));\n", pslight, k, k, k); psdl.put(dl, strlen(dl)); } - vsdl.put(vspragma, strlen(vspragma)+1); psdl.put(pspragma, strlen(pspragma)+1); - defformatstring(name, "<dynlight %d>%s", i+1, sname); Shader *variant = newshader(s.type, name, vsdl.getbuf(), psdl.getbuf(), &s, row); if(!variant) return; } } -static void genshadowmapvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 1) -{ +static void genshadowmapvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 1) { const char *vspragma = strstr(vs, "//:shadowmap"), *pspragma = strstr(ps, "//:shadowmap"); if(!vspragma || !pspragma) return; - string pslight; vspragma += strcspn(vspragma, "\n"); if(*vspragma) vspragma++; - if(sscanf(pspragma, "//:shadowmap %100s", pslight)!=1) return; - pspragma += strcspn(pspragma, "\n"); if(*pspragma) pspragma++; - const char *vsmain = findglslmain(vs), *psmain = findglslmain(ps); if(vsmain > vspragma) vsmain = vs; if(psmain > pspragma) psmain = ps; - vector<char> vssm, pssm; if(vsmain >= vs) vssm.put(vs, vsmain - vs); if(psmain >= ps) pssm.put(ps, psmain - ps); - const char *vsdecl = "uniform mat4 shadowmapproject;\n" "varying vec3 shadowmaptc;\n"; vssm.put(vsdecl, strlen(vsdecl)); - const char *psdecl = "uniform sampler2D shadowmap;\n" "uniform vec4 shadowmapambient;\n" "varying vec3 shadowmaptc;\n"; pssm.put(psdecl, strlen(psdecl)); - vssm.put(vsmain, vspragma-vsmain); pssm.put(psmain, pspragma-psmain); - extern int smoothshadowmappeel; const char *tcgen = "shadowmaptc = vec3(shadowmapproject * vvertex);\n"; @@ -827,7 +711,6 @@ static void genshadowmapvariant(Shader &s, const char *sname, const char *vs, co "vec4 smvals = texture2D(shadowmap, shadowmaptc.xy);\n" "vec2 smdiff = clamp(smvals.xz - shadowmaptc.zz*smvals.y, 0.0, 1.0);\n" "float shadowed = clamp((smdiff.x > 0.0 ? smvals.w : 0.0) - 8.0*smdiff.y, 0.0, 1.0);\n" : - "vec4 smvals = texture2D(shadowmap, shadowmaptc.xy);\n" "float smtest = shadowmaptc.z*smvals.y;\n" "float shadowed = smtest < smvals.x && smtest > smvals.z ? smvals.w : 0.0;\n"; @@ -836,32 +719,26 @@ static void genshadowmapvariant(Shader &s, const char *sname, const char *vs, co "%s.rgb -= shadowed*clamp(%s.rgb - shadowmapambient.rgb, 0.0, 1.0);\n", pslight, pslight); pssm.put(smlight, strlen(smlight)); - vssm.put(vspragma, strlen(vspragma)+1); pssm.put(pspragma, strlen(pspragma)+1); - defformatstring(name, "<shadowmap>%s", sname); Shader *variant = newshader(s.type, name, vssm.getbuf(), pssm.getbuf(), &s, row); if(!variant) return; - if(strstr(vs, "//:dynlight")) gendynlightvariant(s, name, vssm.getbuf(), pssm.getbuf(), row); } -static void genuniformdefs(vector<char> &vsbuf, vector<char> &psbuf, const char *vs, const char *ps, Shader *variant = NULL) -{ +static void genuniformdefs(vector<char> &vsbuf, vector<char> &psbuf, const char *vs, const char *ps, Shader *variant = NULL) { if(variant ? variant->defaultparams.empty() : slotparams.empty()) return; const char *vsmain = findglslmain(vs), *psmain = findglslmain(ps); if(!vsmain || !psmain) return; vsbuf.put(vs, vsmain - vs); psbuf.put(ps, psmain - ps); - if(variant) loopv(variant->defaultparams) - { + if(variant) loopv(variant->defaultparams) { defformatstring(uni, "\nuniform vec4 %s;\n", variant->defaultparams[i].name); vsbuf.put(uni, strlen(uni)); psbuf.put(uni, strlen(uni)); } - else loopv(slotparams) - { + else loopv(slotparams) { defformatstring(uni, "\nuniform vec4 %s;\n", slotparams[i].name); vsbuf.put(uni, strlen(uni)); psbuf.put(uni, strlen(uni)); @@ -872,8 +749,7 @@ static void genuniformdefs(vector<char> &vsbuf, vector<char> &psbuf, const char VAR(defershaders, 0, 1, 1); -void defershader(int *type, const char *name, const char *contents) -{ +void defershader(int *type, const char *name, const char *contents) { Shader *exists = shaders.access(name); if(exists && !exists->invalid()) return; if(!defershaders) { execute(contents); return; } @@ -886,10 +762,8 @@ void defershader(int *type, const char *name, const char *contents) s.standard = standardshaders; } -void Shader::force() -{ +void Shader::force() { if(!deferred() || !defer) return; - char *cmd = defer; defer = NULL; bool wasstandard = standardshaders, wasforcing = forceshaders; @@ -903,24 +777,20 @@ void Shader::force() forceshaders = wasforcing; standardshaders = wasstandard; delete[] cmd; - - if(deferred()) - { + if(deferred()) { DELETEA(defer); type = SHADER_INVALID; } } -void fixshaderdetail() -{ +void fixshaderdetail() { // must null out separately because fixdetailshader can recursively set it enumerate(shaders, Shader, s, { if(!s.forced) s.detailshader = NULL; }); enumerate(shaders, Shader, s, { if(s.forced) s.fixdetailshader(); }); linkslotshaders(); } -int Shader::uniformlocversion() -{ +int Shader::uniformlocversion() { static int version = 0; if(++version >= 0) return version; version = 0; @@ -930,28 +800,23 @@ int Shader::uniformlocversion() VARFP(shaderdetail, 0, MAXSHADERDETAIL, MAXSHADERDETAIL, fixshaderdetail()); -void Shader::fixdetailshader(bool shouldforce, bool recurse) -{ +void Shader::fixdetailshader(bool shouldforce, bool recurse) { Shader *alt = this; detailshader = NULL; - do - { + do { Shader *cur = shaderdetail < MAXSHADERDETAIL ? alt->fastshader[shaderdetail] : alt; if(cur->deferred() && shouldforce) cur->force(); - if(!cur->invalid()) - { + if(!cur->invalid()) { if(cur->deferred()) break; detailshader = cur; break; } alt = alt->altshader; } while(alt && alt!=this); - if(recurse && detailshader) loopv(detailshader->variants) detailshader->variants[i]->fixdetailshader(shouldforce, false); } -Shader *useshaderbyname(const char *name) -{ +Shader *useshaderbyname(const char *name) { Shader *s = shaders.access(name); if(!s) return NULL; if(!s->detailshader) s->fixdetailshader(); @@ -959,17 +824,14 @@ Shader *useshaderbyname(const char *name) return s; } -void shader(int *type, char *name, char *vs, char *ps) -{ +void shader(int *type, char *name, char *vs, char *ps) { if(lookupshaderbyname(name)) return; - defformatstring(info, "shader %s", name); renderprogress(loadprogress, info); - vector<char> vsbuf, psbuf, vsbak, psbak; #define GENSHADER(cond, body) \ - if(cond) \ - { \ + if(cond) { \ + \ if(vsbuf.length()) { vsbak.setsize(0); vsbak.put(vs, strlen(vs)+1); vs = vsbak.getbuf(); vsbuf.setsize(0); } \ if(psbuf.length()) { psbak.setsize(0); psbak.put(ps, strlen(ps)+1); ps = psbak.getbuf(); psbuf.setsize(0); } \ body; \ @@ -978,78 +840,63 @@ void shader(int *type, char *name, char *vs, char *ps) } GENSHADER(slotparams.length(), genuniformdefs(vsbuf, psbuf, vs, ps)); Shader *s = newshader(*type, name, vs, ps); - if(s) - { + if(s) { if(strstr(vs, "//:shadowmap")) genshadowmapvariant(*s, s->name, vs, ps); if(strstr(vs, "//:dynlight")) gendynlightvariant(*s, s->name, vs, ps); } slotparams.shrink(0); } -void variantshader(int *type, char *name, int *row, char *vs, char *ps) -{ - if(*row < 0) - { +void variantshader(int *type, char *name, int *row, char *vs, char *ps) { + if(*row < 0) { shader(type, name, vs, ps); return; } else if(*row >= MAXVARIANTROWS) return; - Shader *s = lookupshaderbyname(name); if(!s) return; - defformatstring(varname, "<variant:%d,%d>%s", s->numvariants(*row), *row, name); //defformatstring(info, "shader %s", varname); //renderprogress(loadprogress, info); vector<char> vsbuf, psbuf, vsbak, psbak; GENSHADER(s->defaultparams.length(), genuniformdefs(vsbuf, psbuf, vs, ps, s)); Shader *v = newshader(*type, varname, vs, ps, s, *row); - if(v) - { + if(v) { if(strstr(vs, "//:dynlight")) gendynlightvariant(*s, varname, vs, ps, *row); if(strstr(ps, "//:variant") || strstr(vs, "//:variant")) gengenericvariant(*s, varname, vs, ps, *row); } } -void setshader(char *name) -{ +void setshader(char *name) { slotparams.shrink(0); Shader *s = shaders.access(name); - if(!s) - { + if(!s) { conoutf(CON_ERROR, "no such shader: %s", name); } else slotshader = s; } -void resetslotshader() -{ +void resetslotshader() { slotshader = NULL; slotparams.shrink(0); } -void setslotshader(Slot &s) -{ +void setslotshader(Slot &s) { s.shader = slotshader; - if(!s.shader) - { + if(!s.shader) { s.shader = stdworldshader; return; } loopv(slotparams) s.params.add(slotparams[i]); } -static void linkslotshaderparams(vector<SlotShaderParam> ¶ms, Shader *sh, bool load) -{ - if(sh) loopv(params) - { +static void linkslotshaderparams(vector<SlotShaderParam> ¶ms, Shader *sh, bool load) { + if(sh) loopv(params) { int loc = -1; SlotShaderParam ¶m = params[i]; - loopv(sh->defaultparams) - { + loopv(sh->defaultparams) { SlotShaderParamState &dparam = sh->defaultparams[i]; - if(dparam.name==param.name) - { + if(dparam.name==param.name) { if(memcmp(param.val, dparam.val, sizeof(param.val))) loc = i; break; } @@ -1059,35 +906,27 @@ static void linkslotshaderparams(vector<SlotShaderParam> ¶ms, Shader *sh, bo else if(load) loopv(params) params[i].loc = -1; } -void linkslotshader(Slot &s, bool load) -{ +void linkslotshader(Slot &s, bool load) { if(!s.shader) return; - if(load && !s.shader->detailshader) s.shader->fixdetailshader(); - linkslotshaderparams(s.params, s.shader->detailshader, load); } -void linkvslotshader(VSlot &s, bool load) -{ +void linkvslotshader(VSlot &s, bool load) { if(!s.slot->shader) return; - Shader *sh = s.slot->shader->detailshader; linkslotshaderparams(s.params, sh, load); - if(!sh) return; } -void altshader(char *origname, char *altname) -{ +void altshader(char *origname, char *altname) { Shader *orig = shaders.access(origname), *alt = shaders.access(altname); if(!orig || !alt) return; orig->altshader = alt; orig->fixdetailshader(false); } -void fastshader(char *nice, char *fast, int *detail) -{ +void fastshader(char *nice, char *fast, int *detail) { Shader *ns = shaders.access(nice), *fs = shaders.access(fast); if(!ns || !fs) return; loopi(min(*detail+1, MAXSHADERDETAIL)) ns->fastshader[i] = fs; @@ -1106,21 +945,17 @@ ICOMMAND(isshaderdefined, "s", (char *name), intret(lookupshaderbyname(name) ? 1 static hashset<const char *> shaderparamnames(256); -const char *getshaderparamname(const char *name, bool insert) -{ +const char *getshaderparamname(const char *name, bool insert) { const char *exists = shaderparamnames.find(name, NULL); if(exists || !insert) return exists; return shaderparamnames.add(newstring(name)); } -void addslotparam(const char *name, float x, float y, float z, float w) -{ +void addslotparam(const char *name, float x, float y, float z, float w) { if(name) name = getshaderparamname(name); - loopv(slotparams) - { + loopv(slotparams) { SlotShaderParam ¶m = slotparams[i]; - if(param.name==name) - { + if(param.name==name) { param.val[0] = x; param.val[1] = y; param.val[2] = z; @@ -1136,8 +971,7 @@ ICOMMAND(setuniformparam, "sffff", (char *name, float *x, float *y, float *z, fl ICOMMAND(setshaderparam, "sffff", (char *name, float *x, float *y, float *z, float *w), addslotparam(name, *x, *y, *z, *w)); ICOMMAND(defuniformparam, "sffff", (char *name, float *x, float *y, float *z, float *w), addslotparam(name, *x, *y, *z, *w)); -void cleanupshaders() -{ +void cleanupshaders() { loadedshaders = false; nullshader = hudshader = hudnotextureshader = textureshader = notextureshader = nocolorshader = stdworldshader = NULL; enumerate(shaders, Shader, s, s.cleanup()); @@ -1145,21 +979,17 @@ void cleanupshaders() glUseProgram_(0); } -void reloadshaders() -{ +void reloadshaders() { identflags &= ~IDF_PERSIST; loadshaders(); identflags |= IDF_PERSIST; linkslotshaders(); - enumerate(shaders, Shader, s, - { - if(!s.standard && !(s.type&(SHADER_DEFERRED|SHADER_INVALID)) && !s.variantshader) - { + enumerate(shaders, Shader, s, { + if(!s.standard && !(s.type&(SHADER_DEFERRED|SHADER_INVALID)) && !s.variantshader) { defformatstring(info, "shader %s", s.name); renderprogress(0.0, info); if(!s.compile()) s.cleanup(true); - loopv(s.variants) - { + loopv(s.variants) { Shader *v = s.variants[i]; if((v->reusevs && v->reusevs->invalid()) || (v->reuseps && v->reuseps->invalid()) || @@ -1171,8 +1001,7 @@ void reloadshaders() }); } -void setupblurkernel(int radius, float sigma, float *weights, float *offsets) -{ +void setupblurkernel(int radius, float sigma, float *weights, float *offsets) { if(radius<1 || radius>MAXBLURRADIUS) return; sigma *= 2*radius; float total = 1.0f/sigma; @@ -1180,8 +1009,7 @@ void setupblurkernel(int radius, float sigma, float *weights, float *offsets) offsets[0] = 0; // rely on bilinear filtering to sample 2 pixels at once // transforms a*X + b*Y into (u+v)*[X*u/(u+v) + Y*(1 - u/(u+v))] - loopi(radius) - { + loopi(radius) { float weight1 = exp(-((2*i)*(2*i)) / (2*sigma*sigma)) / sigma, weight2 = exp(-((2*i+1)*(2*i+1)) / (2*sigma*sigma)) / sigma, scale = weight1 + weight2, @@ -1194,13 +1022,11 @@ void setupblurkernel(int radius, float sigma, float *weights, float *offsets) for(int i = radius+1; i <= MAXBLURRADIUS; i++) weights[i] = offsets[i] = 0; } -void setblurshader(int pass, int size, int radius, float *weights, float *offsets) -{ +void setblurshader(int pass, int size, int radius, float *weights, float *offsets) { if(radius<1 || radius>MAXBLURRADIUS) return; static Shader *blurshader[7][2] = { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; Shader *&s = blurshader[radius-1][pass]; - if(!s) - { + if(!s) { defformatstring(name, "blur%c%d", 'x'+pass, radius); s = lookupshaderbyname(name); } diff --git a/src/engine/shadowmap.cpp b/src/engine/shadowmap.cpp index 24a6fe5..1eefe4b 100644 --- a/src/engine/shadowmap.cpp +++ b/src/engine/shadowmap.cpp @@ -11,8 +11,7 @@ VARP(shadowmapdist, 128, 256, 512); VARFP(fpshadowmap, 0, 0, 1, cleanshadowmap()); VARFP(shadowmapprecision, 0, 0, 1, cleanshadowmap()); bvec shadowmapambientcolor(0, 0, 0); -HVARFR(shadowmapambient, 0, 0, 0xFFFFFF, -{ +HVARFR(shadowmapambient, 0, 0, 0xFFFFFF, { if(shadowmapambient <= 255) shadowmapambient |= (shadowmapambient<<8) | (shadowmapambient<<16); shadowmapambientcolor = bvec((shadowmapambient>>16)&0xFF, (shadowmapambient>>8)&0xFF, shadowmapambient&0xFF); }); @@ -27,36 +26,29 @@ vec shadowoffset(0, 0, 0), shadowfocus(0, 0, 0), shadowdir(0, SHADOWSKEW, 1); VAR(shadowmapcasters, 1, 0, 0); float shadowmapmaxz = 0; -void setshadowdir(int angle) -{ +void setshadowdir(int angle) { shadowdir = vec(0, SHADOWSKEW, 1); shadowdir.rotate_around_z(angle*RAD); } VARFR(shadowmapangle, 0, 0, 360, setshadowdir(shadowmapangle)); -void guessshadowdir() -{ +void guessshadowdir() { if(shadowmapangle) return; - vec dir; - { + vec dir; { vec lightpos(0, 0, 0), casterpos(0, 0, 0); int numlights = 0, numcasters = 0; const vector<extentity *> &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; - switch(e.type) - { + switch(e.type) { case ET_LIGHT: if(!e.attr1) { lightpos.add(e.o); numlights++; } break; - case ET_MAPMODEL: casterpos.add(e.o); numcasters++; break; - default: if(e.type<ET_GAMESPECIFIC) break; casterpos.add(e.o); @@ -86,148 +78,112 @@ VARP(shadowmappeelbias, 0, 20, 1024); VAR(smdepthpeel, 0, 1, 1); VAR(smoothshadowmappeel, 1, 0, 0); -static struct shadowmaptexture : rendertarget -{ - const GLenum *colorformats() const - { +static struct shadowmaptexture : rendertarget { + const GLenum *colorformats() const { static const GLenum rgbafmts[] = { GL_RGBA16F, GL_RGBA16, GL_RGBA, GL_RGBA8, GL_FALSE }; return &rgbafmts[fpshadowmap && hasTF ? 0 : (shadowmapprecision ? 1 : 2)]; } - bool swaptexs() const { return true; } - - bool scissorblur(int &x, int &y, int &w, int &h) - { + bool scissorblur(int &x, int &y, int &w, int &h) { x = max(int(floor((scissorx1+1)/2*vieww)) - 2*blursize, 2); y = max(int(floor((scissory1+1)/2*viewh)) - 2*blursize, 2); w = min(int(ceil((scissorx2+1)/2*vieww)) + 2*blursize, vieww-2) - x; h = min(int(ceil((scissory2+1)/2*viewh)) + 2*blursize, viewh-2) - y; return true; } - - bool scissorrender(int &x, int &y, int &w, int &h) - { + bool scissorrender(int &x, int &y, int &w, int &h) { x = y = 2; w = vieww - 2*2; h = viewh - 2*2; return true; } - - void doclear() - { + void doclear() { glClearColor(0, 0, 0, 0); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); } - - bool dorender() - { + bool dorender() { vec skewdir(shadowdir); skewdir.rotate_around_z(-camera1->yaw*RAD); - vec dir; vecfromyawpitch(camera1->yaw, camera1->pitch, 1, 0, dir); dir.z = 0; dir.mul(shadowmapradius); - vec dirx, diry; vecfromyawpitch(camera1->yaw, 0, 0, 1, dirx); vecfromyawpitch(camera1->yaw, 0, 1, 0, diry); shadowoffset.x = -fmod(dirx.dot(camera1->o) - skewdir.x*camera1->o.z, 2.0f*shadowmapradius/vieww); shadowoffset.y = -fmod(diry.dot(camera1->o) - skewdir.y*camera1->o.z, 2.0f*shadowmapradius/viewh); - shadowmatrix.ortho(-shadowmapradius, shadowmapradius, -shadowmapradius, shadowmapradius, -shadowmapdist, shadowmapdist); shadowmatrix.mul(matrix3(vec(1, 0, 0), vec(0, 1, 0), vec(skewdir.x, skewdir.y, 1))); shadowmatrix.translate(skewdir.x*shadowmapheight + shadowoffset.x, skewdir.y*shadowmapheight + shadowoffset.y + dir.magnitude(), -shadowmapheight); shadowmatrix.rotate_around_z((camera1->yaw+180)*-RAD); shadowmatrix.translate(vec(camera1->o).neg()); GLOBALPARAM(shadowmatrix, shadowmatrix); - shadowfocus = camera1->o; shadowfocus.add(dir); shadowfocus.add(vec(shadowdir).mul(shadowmapheight)); shadowfocus.add(dirx.mul(shadowoffset.x)); shadowfocus.add(diry.mul(shadowoffset.y)); - gle::colorf(0, 0, 0); - GLOBALPARAMF(shadowmapbias, -shadowmapbias/float(shadowmapdist), 1 - (shadowmapbias + (smoothshadowmappeel ? 0 : shadowmappeelbias))/float(shadowmapdist)); - shadowmapcasters = 0; shadowmapmaxz = shadowfocus.z - shadowmapdist; shadowmapping = true; rendergame(); shadowmapping = false; shadowmapmaxz = min(shadowmapmaxz, shadowfocus.z); - - if(shadowmapcasters && smdepthpeel) - { + if(shadowmapcasters && smdepthpeel) { int sx, sy, sw, sh; bool scissoring = rtscissor && scissorblur(sx, sy, sw, sh) && sw > 0 && sh > 0; if(scissoring) glScissor(sx, sy, sw, sh); if(!rtscissor || scissoring) rendershadowmapreceivers(); } - return shadowmapcasters>0; } } shadowmaptex; -void cleanshadowmap() -{ +void cleanshadowmap() { shadowmaptex.cleanup(true); } -void calcshadowmapbb(const vec &o, float xyrad, float zrad, float &x1, float &y1, float &x2, float &y2) -{ +void calcshadowmapbb(const vec &o, float xyrad, float zrad, float &x1, float &y1, float &x2, float &y2) { vec skewdir(shadowdir); skewdir.rotate_around_z(-camera1->yaw*RAD); - vec ro(o); ro.sub(camera1->o); ro.rotate_around_z(-(camera1->yaw+180)*RAD); ro.x += ro.z * skewdir.x + shadowoffset.x; ro.y += ro.z * skewdir.y + shadowmapradius * cosf(camera1->pitch*RAD) + shadowoffset.y; - vec high(ro), low(ro); high.x += zrad * skewdir.x; high.y += zrad * skewdir.y; low.x -= zrad * skewdir.x; low.y -= zrad * skewdir.y; - x1 = (min(high.x, low.x) - xyrad) / shadowmapradius; y1 = (min(high.y, low.y) - xyrad) / shadowmapradius; x2 = (max(high.x, low.x) + xyrad) / shadowmapradius; y2 = (max(high.y, low.y) + xyrad) / shadowmapradius; } -bool addshadowmapcaster(const vec &o, float xyrad, float zrad) -{ +bool addshadowmapcaster(const vec &o, float xyrad, float zrad) { if(o.z + zrad <= shadowfocus.z - shadowmapdist || o.z - zrad >= shadowfocus.z) return false; - shadowmapmaxz = max(shadowmapmaxz, o.z + zrad); - float x1, y1, x2, y2; calcshadowmapbb(o, xyrad, zrad, x1, y1, x2, y2); - if(!shadowmaptex.addblurtiles(x1, y1, x2, y2, 2)) return false; - shadowmapcasters++; return true; } -bool isshadowmapreceiver(vtxarray *va) -{ +bool isshadowmapreceiver(vtxarray *va) { if(!shadowmap || !shadowmapcasters) return false; - if(va->shadowmapmax.z <= shadowfocus.z - shadowmapdist || va->shadowmapmin.z >= shadowmapmaxz) return false; - float xyrad = SQRT2*0.5f*max(va->shadowmapmax.x-va->shadowmapmin.x, va->shadowmapmax.y-va->shadowmapmin.y), zrad = 0.5f*(va->shadowmapmax.z-va->shadowmapmin.z), x1, y1, x2, y2; if(xyrad<0 || zrad<0) return false; - vec center = vec(va->shadowmapmin).add(vec(va->shadowmapmax)).mul(0.5f); calcshadowmapbb(center, xyrad, zrad, x1, y1, x2, y2); - return shadowmaptex.checkblurtiles(x1, y1, x2, y2, 2); #if 0 @@ -244,8 +200,7 @@ bool isshadowmapreceiver(vtxarray *va) #endif } -bool isshadowmapcaster(const vec &o, float rad) -{ +bool isshadowmapcaster(const vec &o, float rad) { // cheaper inexact test float dz = o.z - shadowfocus.z; float cx = shadowfocus.x + dz*shadowdir.x, cy = shadowfocus.y + dz*shadowdir.y; @@ -258,22 +213,16 @@ bool isshadowmapcaster(const vec &o, float rad) return true; } -void pushshadowmap() -{ +void pushshadowmap() { if(!shadowmap || !shadowmaptex.rendertex) return; - glActiveTexture_(GL_TEXTURE7); glBindTexture(GL_TEXTURE_2D, shadowmaptex.rendertex); - matrix4 m = shadowmatrix; m.projective(-1, 1-shadowmapbias/float(shadowmapdist)); GLOBALPARAM(shadowmapproject, m); - glActiveTexture_(GL_TEXTURE0); - float r, g, b; - if(!shadowmapambient) - { + if(!shadowmapambient) { r = max(25.0f, 2.0f*ambientcolor[0]); g = max(25.0f, 2.0f*ambientcolor[1]); b = max(25.0f, 2.0f*ambientcolor[2]); @@ -282,14 +231,7 @@ void pushshadowmap() GLOBALPARAMF(shadowmapambient, r/255.0f, g/255.0f, b/255.0f); } -void popshadowmap() -{ - if(!shadowmap || !shadowmaptex.rendertex) return; -} - -void rendershadowmap() -{ +void rendershadowmap() { if(!shadowmap) return; - shadowmaptex.render(1<<shadowmapsize, 1<<shadowmapsize, blurshadowmap, blursmsigma/100.0f); } diff --git a/src/engine/skelmodel.h b/src/engine/skelmodel.h index c8d14d0..e823337 100644 --- a/src/engine/skelmodel.h +++ b/src/engine/skelmodel.h @@ -7,8 +7,7 @@ VAR(testtags, 0, 0, 1); #define BONEMASK_END 0xFFFF #define BONEMASK_BONE 0x7FFF -struct skelmodel : animmodel -{ +struct skelmodel : animmodel { struct vert { vec pos, norm; vec2 tc; int blend, interpindex; }; struct vvert { vec pos; vec2 tc; }; struct vvertn : vvert { vec norm; }; @@ -18,37 +17,25 @@ struct skelmodel : animmodel struct vvertbumpw : vvertbump, vvertw {}; struct bumpvert { quat tangent; }; struct tri { ushort vert[3]; }; - - struct blendcombo - { + struct blendcombo { int uses, interpindex; float weights[4]; uchar bones[4], interpbones[4]; - - blendcombo() : uses(1) - { + blendcombo() : uses(1) { } - - bool operator==(const blendcombo &c) const - { + bool operator==(const blendcombo &c) const { loopk(4) if(bones[k] != c.bones[k]) return false; loopk(4) if(weights[k] != c.weights[k]) return false; return true; } - - int size() const - { + int size() const { int i = 1; while(i < 4 && weights[i]) i++; return i; } - - static bool sortcmp(const blendcombo &x, const blendcombo &y) - { - loopi(4) - { - if(x.weights[i]) - { + static bool sortcmp(const blendcombo &x, const blendcombo &y) { + loopi(4) { + if(x.weights[i]) { if(!y.weights[i]) return true; } else if(y.weights[i]) return false; @@ -56,14 +43,10 @@ struct skelmodel : animmodel } return false; } - - int addweight(int sorted, float weight, int bone) - { + int addweight(int sorted, float weight, int bone) { if(weight <= 1e-3f) return sorted; - loopk(sorted) if(weight > weights[k]) - { - for(int l = min(sorted-1, 2); l >= k; l--) - { + loopk(sorted) if(weight > weights[k]) { + for(int l = min(sorted-1, 2); l >= k; l--) { weights[l+1] = weights[l]; bones[l+1] = bones[l]; } @@ -76,9 +59,7 @@ struct skelmodel : animmodel bones[sorted] = bone; return sorted+1; } - - void finalize(int sorted) - { + void finalize(int sorted) { loopj(4-sorted) { weights[sorted+j] = 0; bones[sorted+j] = 0; } if(sorted <= 0) return; float total = 0; @@ -86,26 +67,20 @@ struct skelmodel : animmodel total = 1.0f/total; loopj(sorted) weights[j] *= total; } - - void serialize(vvertw &v) - { - if(interpindex >= 0) - { + void serialize(vvertw &v) { + if(interpindex >= 0) { v.weights[0] = 255; loopk(3) v.weights[k+1] = 0; v.bones[0] = 2*interpindex; loopk(3) v.bones[k+1] = v.bones[0]; } - else - { + else { int total = 0; loopk(4) total += (v.weights[k] = uchar(0.5f + weights[k]*255)); - while(total > 255) - { + while(total > 255) { loopk(4) if(v.weights[k] > 0 && total > 255) { v.weights[k]--; total--; } } - while(total < 255) - { + while(total < 255) { loopk(4) if(v.weights[k] < 255 && total < 255) { v.weights[k]++; total++; } } loopk(4) v.bones[k] = 2*interpbones[k]; @@ -113,118 +88,79 @@ struct skelmodel : animmodel } }; - - struct animcacheentry - { + struct animcacheentry { animstate as[MAXANIMPARTS]; float pitch; int millis; uchar *partmask; ragdolldata *ragdoll; - - animcacheentry() : ragdoll(NULL) - { + animcacheentry() : ragdoll(NULL) { loopk(MAXANIMPARTS) as[k].cur.fr1 = as[k].prev.fr1 = -1; } - - bool operator==(const animcacheentry &c) const - { + bool operator==(const animcacheentry &c) const { loopi(MAXANIMPARTS) if(as[i]!=c.as[i]) return false; return pitch==c.pitch && partmask==c.partmask && ragdoll==c.ragdoll && (!ragdoll || min(millis, c.millis) >= ragdoll->lastmove); } }; - - struct vbocacheentry : animcacheentry - { + struct vbocacheentry : animcacheentry { GLuint vbuf; int owner; - vbocacheentry() : vbuf(0), owner(-1) {} }; - - struct skelcacheentry : animcacheentry - { + struct skelcacheentry : animcacheentry { dualquat *bdata; int version; bool dirty; - skelcacheentry() : bdata(NULL), version(-1), dirty(false) {} - - void nextversion() - { + void nextversion() { version = Shader::uniformlocversion(); dirty = true; } }; - - struct blendcacheentry : skelcacheentry - { + struct blendcacheentry : skelcacheentry { int owner; - blendcacheentry() : owner(-1) {} }; - struct skelmeshgroup; - - struct skelmesh : mesh - { + struct skelmesh : mesh { vert *verts; bumpvert *bumpverts; tri *tris; int numverts, numtris, maxweights; - int voffset, eoffset, elen; ushort minvert, maxvert; - - skelmesh() : verts(NULL), bumpverts(NULL), tris(NULL), numverts(0), numtris(0), maxweights(0) - { + skelmesh() : verts(NULL), bumpverts(NULL), tris(NULL), numverts(0), numtris(0), maxweights(0) { } - - virtual ~skelmesh() - { + virtual ~skelmesh() { DELETEA(verts); DELETEA(bumpverts); DELETEA(tris); } - - int addblendcombo(const blendcombo &c) - { + int addblendcombo(const blendcombo &c) { maxweights = max(maxweights, c.size()); return ((skelmeshgroup *)group)->addblendcombo(c); } - - void smoothnorms(float limit = 0, bool areaweight = true) - { + void smoothnorms(float limit = 0, bool areaweight = true) { mesh::smoothnorms(verts, numverts, tris, numtris, limit, areaweight); } - - void buildnorms(bool areaweight = true) - { + void buildnorms(bool areaweight = true) { mesh::buildnorms(verts, numverts, tris, numtris, areaweight); } - - void calctangents(bool areaweight = true) - { + void calctangents(bool areaweight = true) { if(bumpverts) return; bumpverts = new bumpvert[numverts]; mesh::calctangents(bumpverts, verts, verts, numverts, tris, numtris, areaweight); } - - void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) - { - loopj(numverts) - { + void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) { + loopj(numverts) { vec v = m.transform(verts[j].pos); - loopi(3) - { + loopi(3) { bbmin[i] = min(bbmin[i], v[i]); bbmax[i] = max(bbmax[i], v[i]); } } } - - void genBIH(BIH::mesh &m) - { + void genBIH(BIH::mesh &m) { m.tris = (const BIH::tri *)tris; m.numtris = numtris; m.pos = (const uchar *)&verts->pos; @@ -232,44 +168,33 @@ struct skelmodel : animmodel m.tc = (const uchar *)&verts->tc; m.tcstride = sizeof(vert); } - - static inline void assignvert(vvertn &vv, int j, vert &v, blendcombo &c) - { + static inline void assignvert(vvertn &vv, int j, vert &v, blendcombo &c) { vv.pos = v.pos; vv.norm = v.norm; vv.tc = v.tc; } - - inline void assignvert(vvertbump &vv, int j, vert &v, blendcombo &c) - { + inline void assignvert(vvertbump &vv, int j, vert &v, blendcombo &c) { vv.pos = v.pos; vv.tc = v.tc; vv.tangent = bumpverts[j].tangent; } - - static inline void assignvert(vvertnw &vv, int j, vert &v, blendcombo &c) - { + static inline void assignvert(vvertnw &vv, int j, vert &v, blendcombo &c) { vv.pos = v.pos; vv.norm = v.norm; vv.tc = v.tc; c.serialize(vv); } - - inline void assignvert(vvertbumpw &vv, int j, vert &v, blendcombo &c) - { + inline void assignvert(vvertbumpw &vv, int j, vert &v, blendcombo &c) { vv.pos = v.pos; vv.tc = v.tc; vv.tangent = bumpverts[j].tangent; c.serialize(vv); } - template<class T> - int genvbo(vector<ushort> &idxs, int offset, vector<T> &vverts) - { + int genvbo(vector<ushort> &idxs, int offset, vector<T> &vverts) { voffset = offset; eoffset = idxs.length(); - loopi(numverts) - { + loopi(numverts) { vert &v = verts[i]; assignvert(vverts.add(), i, v, ((skelmeshgroup *)group)->blendcombos[v.blend]); } @@ -279,25 +204,20 @@ struct skelmodel : animmodel maxvert = voffset + numverts-1; return numverts; } - template<class T> - int genvbo(vector<ushort> &idxs, int offset, vector<T> &vverts, int *htdata, int htlen) - { + int genvbo(vector<ushort> &idxs, int offset, vector<T> &vverts, int *htdata, int htlen) { voffset = offset; eoffset = idxs.length(); minvert = 0xFFFF; - loopi(numtris) - { + loopi(numtris) { tri &t = tris[i]; - loopj(3) - { + loopj(3) { int index = t.vert[j]; vert &v = verts[index]; T vv; assignvert(vv, index, v, ((skelmeshgroup *)group)->blendcombos[v.blend]); int htidx = hthash(v.pos)&(htlen-1); - loopk(htlen) - { + loopk(htlen) { int &vidx = htdata[(htidx+k)&(htlen-1)]; if(vidx < 0) { vidx = idxs.add(ushort(vverts.length())); vverts.add(vv); break; } else if(!memcmp(&vverts[vidx], &vv, sizeof(vv))) { minvert = min(minvert, idxs.add(ushort(vidx))); break; } @@ -309,15 +229,11 @@ struct skelmodel : animmodel maxvert = max(minvert, ushort(vverts.length()-1)); return vverts.length()-voffset; } - - int genvbo(vector<ushort> &idxs, int offset) - { + int genvbo(vector<ushort> &idxs, int offset) { loopi(numverts) verts[i].interpindex = ((skelmeshgroup *)group)->remapblend(verts[i].blend); - voffset = offset; eoffset = idxs.length(); - loopi(numtris) - { + loopi(numtris) { tri &t = tris[i]; loopj(3) idxs.add(voffset+t.vert[j]); } @@ -326,28 +242,21 @@ struct skelmodel : animmodel elen = idxs.length()-eoffset; return numverts; } - template<class T> - static inline void fillvert(T &vv, int j, vert &v) - { + static inline void fillvert(T &vv, int j, vert &v) { vv.tc = v.tc; } - template<class T> - void fillverts(T *vdata) - { + void fillverts(T *vdata) { vdata += voffset; loopi(numverts) fillvert(vdata[i], i, verts[i]); } - - void interpverts(const dualquat * RESTRICT bdata1, const dualquat * RESTRICT bdata2, bool tangents, void * RESTRICT vdata, skin &s) - { + void interpverts(const dualquat * RESTRICT bdata1, const dualquat * RESTRICT bdata2, bool tangents, void * RESTRICT vdata, skin &s) { const int blendoffset = ((skelmeshgroup *)group)->skel->numgpubones; bdata2 -= blendoffset; - #define IPLOOP(type, dosetup, dotransform) \ - loopi(numverts) \ - { \ + loopi(numverts) { \ + \ const vert &src = verts[i]; \ type &dst = ((type * RESTRICT)vdata)[i]; \ dosetup; \ @@ -355,36 +264,26 @@ struct skelmodel : animmodel dst.pos = b.transform(src.pos); \ dotransform; \ } - - if(tangents) - { - IPLOOP(vvertbump, bumpvert &bsrc = bumpverts[i], - { + if(tangents) { + IPLOOP(vvertbump, bumpvert &bsrc = bumpverts[i], { quat q = b.transform(bsrc.tangent); fixqtangent(q, bsrc.tangent.w); dst.tangent = q; }); } - else - { - IPLOOP(vvertn, , - { + else { + IPLOOP(vvertn, , { dst.norm = b.transformnormal(src.norm); }); } - #undef IPLOOP } - - void setshader(Shader *s) - { + void setshader(Shader *s) { skelmeshgroup *g = (skelmeshgroup *)group; if(!g->skel->usegpuskel) s->set(); else s->setvariant(min(maxweights, g->vweights)-1, 0); } - - void render(const animstate *as, skin &s, vbocacheentry &vc) - { + void render(const animstate *as, skin &s, vbocacheentry &vc) { if(!Shader::lastshader) return; glDrawRangeElements_(GL_TRIANGLES, minvert, maxvert, elen, GL_UNSIGNED_SHORT, &((skelmeshgroup *)group)->edata[eoffset]); glde++; @@ -392,73 +291,50 @@ struct skelmodel : animmodel } }; - - struct tag - { + struct tag { char *name; int bone; matrix4x3 matrix; - tag() : name(NULL) {} ~tag() { DELETEA(name); } }; - - struct skelanimspec - { + struct skelanimspec { char *name; int frame, range; - skelanimspec() : name(NULL), frame(0), range(0) {} - ~skelanimspec() - { + ~skelanimspec() { DELETEA(name); } }; - - struct boneinfo - { + struct boneinfo { const char *name; int parent, children, next, group, scheduled, interpindex, interpparent, ragdollindex, correctindex; float pitchscale, pitchoffset, pitchmin, pitchmax; dualquat base, invbase; - boneinfo() : name(NULL), parent(-1), children(-1), next(-1), group(INT_MAX), scheduled(-1), interpindex(-1), interpparent(-1), ragdollindex(-1), correctindex(-1), pitchscale(0), pitchoffset(0), pitchmin(0), pitchmax(0) {} - ~boneinfo() - { + ~boneinfo() { DELETEA(name); } }; - - struct antipode - { + struct antipode { int parent, child; - antipode(int parent, int child) : parent(parent), child(child) {} }; - - struct pitchdep - { + struct pitchdep { int bone, parent; dualquat pose; }; - - struct pitchtarget - { + struct pitchtarget { int bone, frame, corrects, deps; float pitchmin, pitchmax, deviated; dualquat pose; }; - - struct pitchcorrect - { + struct pitchcorrect { int bone, target, parent; float pitchmin, pitchmax, pitchscale, pitchangle, pitchtotal; - pitchcorrect() : parent(-1), pitchangle(0), pitchtotal(0) {} }; - - struct skeleton - { + struct skeleton { char *name; int shared; vector<skelmeshgroup *> users; @@ -472,36 +348,25 @@ struct skelmodel : animmodel vector<pitchdep> pitchdeps; vector<pitchtarget> pitchtargets; vector<pitchcorrect> pitchcorrects; - bool usegpuskel; vector<skelcacheentry> skelcache; hashtable<GLuint, int> blendoffsets; - - skeleton() : name(NULL), shared(0), bones(NULL), numbones(0), numinterpbones(0), numgpubones(0), numframes(0), framebones(NULL), ragdoll(NULL), usegpuskel(false), blendoffsets(32) - { + skeleton() : name(NULL), shared(0), bones(NULL), numbones(0), numinterpbones(0), numgpubones(0), numframes(0), framebones(NULL), ragdoll(NULL), usegpuskel(false), blendoffsets(32) { } - - ~skeleton() - { + ~skeleton() { DELETEA(name); DELETEA(bones); DELETEA(framebones); DELETEP(ragdoll); - loopv(skelcache) - { + loopv(skelcache) { DELETEA(skelcache[i].bdata); } } - - skelanimspec *findskelanim(const char *name, char sep = '\0') - { + skelanimspec *findskelanim(const char *name, char sep = '\0') { int len = sep ? strlen(name) : 0; - loopv(skelanims) - { - if(skelanims[i].name) - { - if(sep) - { + loopv(skelanims) { + if(skelanims[i].name) { + if(sep) { const char *end = strchr(skelanims[i].name, ':'); if(end && end - skelanims[i].name == len && !memcmp(name, skelanims[i].name, len)) return &skelanims[i]; } @@ -510,38 +375,28 @@ struct skelmodel : animmodel } return NULL; } - - skelanimspec &addskelanim(const char *name) - { + skelanimspec &addskelanim(const char *name) { skelanimspec &sa = skelanims.add(); sa.name = name ? newstring(name) : NULL; return sa; } - - int findbone(const char *name) - { + int findbone(const char *name) { loopi(numbones) if(bones[i].name && !strcmp(bones[i].name, name)) return i; return -1; } - - int findtag(const char *name) - { + int findtag(const char *name) { loopv(tags) if(!strcmp(tags[i].name, name)) return i; return -1; } - - bool addtag(const char *name, int bone, const matrix4x3 &matrix) - { + bool addtag(const char *name, int bone, const matrix4x3 &matrix) { int idx = findtag(name); - if(idx >= 0) - { + if(idx >= 0) { if(!testtags) return false; tag &t = tags[idx]; t.bone = bone; t.matrix = matrix; } - else - { + else { tag &t = tags.add(); t.name = newstring(name); t.bone = bone; @@ -549,67 +404,52 @@ struct skelmodel : animmodel } return true; } - - void calcantipodes() - { + void calcantipodes() { antipodes.shrink(0); vector<int> schedule; - loopi(numbones) - { - if(bones[i].group >= numbones) - { + loopi(numbones) { + if(bones[i].group >= numbones) { bones[i].scheduled = schedule.length(); schedule.add(i); } else bones[i].scheduled = -1; } - loopv(schedule) - { + loopv(schedule) { int bone = schedule[i]; const boneinfo &info = bones[bone]; - loopj(numbones) if(abs(bones[j].group) == bone && bones[j].scheduled < 0) - { + loopj(numbones) if(abs(bones[j].group) == bone && bones[j].scheduled < 0) { antipodes.add(antipode(info.interpindex, bones[j].interpindex)); bones[j].scheduled = schedule.length(); schedule.add(j); } - if(i + 1 == schedule.length()) - { + if(i + 1 == schedule.length()) { int conflict = INT_MAX; loopj(numbones) if(bones[j].group < numbones && bones[j].scheduled < 0) conflict = min(conflict, abs(bones[j].group)); - if(conflict < numbones) - { + if(conflict < numbones) { bones[conflict].scheduled = schedule.length(); schedule.add(conflict); } } } } - - void remapbones() - { - loopi(numbones) - { + void remapbones() { + loopi(numbones) { boneinfo &info = bones[i]; info.interpindex = -1; info.ragdollindex = -1; } numgpubones = 0; - loopv(users) - { + loopv(users) { skelmeshgroup *group = users[i]; - loopvj(group->blendcombos) - { + loopvj(group->blendcombos) { blendcombo &c = group->blendcombos[j]; - loopk(4) - { + loopk(4) { if(!c.weights[k]) { c.interpbones[k] = k > 0 ? c.interpbones[k-1] : 0; continue; } boneinfo &info = bones[c.bones[k]]; if(info.interpindex < 0) info.interpindex = numgpubones++; c.interpbones[k] = info.interpindex; if(info.group < 0) continue; - loopl(4) - { + loopl(4) { if(!c.weights[l]) break; if(l == k) continue; int parent = c.bones[l]; @@ -623,41 +463,33 @@ struct skelmodel : animmodel } } numinterpbones = numgpubones; - loopv(tags) - { + loopv(tags) { boneinfo &info = bones[tags[i].bone]; if(info.interpindex < 0) info.interpindex = numinterpbones++; } - if(ragdoll) - { - loopv(ragdoll->joints) - { + if(ragdoll) { + loopv(ragdoll->joints) { boneinfo &info = bones[ragdoll->joints[i].bone]; if(info.interpindex < 0) info.interpindex = numinterpbones++; info.ragdollindex = i; } } - loopi(numbones) - { + loopi(numbones) { boneinfo &info = bones[i]; if(info.interpindex < 0) continue; for(int parent = info.parent; parent >= 0 && bones[parent].interpindex < 0; parent = bones[parent].parent) bones[parent].interpindex = numinterpbones++; } - loopi(numbones) - { + loopi(numbones) { boneinfo &info = bones[i]; if(info.interpindex < 0) continue; info.interpparent = info.parent >= 0 ? bones[info.parent].interpindex : -1; } - if(ragdoll) - { - loopi(numbones) - { + if(ragdoll) { + loopi(numbones) { boneinfo &info = bones[i]; if(info.interpindex < 0 || info.ragdollindex >= 0) continue; - for(int parent = info.parent; parent >= 0; parent = bones[parent].parent) - { + for(int parent = info.parent; parent >= 0; parent = bones[parent].parent) { if(bones[parent].ragdollindex >= 0) { ragdoll->addreljoint(i, bones[parent].ragdollindex); break; } } } @@ -665,19 +497,14 @@ struct skelmodel : animmodel calcantipodes(); } - - void addpitchdep(int bone, int frame) - { - for(; bone >= 0; bone = bones[bone].parent) - { + void addpitchdep(int bone, int frame) { + for(; bone >= 0; bone = bones[bone].parent) { int pos = pitchdeps.length(); - loopvj(pitchdeps) if(bone <= pitchdeps[j].bone) - { + loopvj(pitchdeps) if(bone <= pitchdeps[j].bone) { if(bone == pitchdeps[j].bone) goto nextbone; pos = j; break; - } - { + } { pitchdep d; d.bone = bone; d.parent = -1; @@ -687,66 +514,51 @@ struct skelmodel : animmodel nextbone:; } } - - int findpitchdep(int bone) - { + int findpitchdep(int bone) { loopv(pitchdeps) if(bone <= pitchdeps[i].bone) return bone == pitchdeps[i].bone ? i : -1; return -1; } - - int findpitchcorrect(int bone) - { + int findpitchcorrect(int bone) { loopv(pitchcorrects) if(bone <= pitchcorrects[i].bone) return bone == pitchcorrects[i].bone ? i : -1; return -1; } - - void initpitchdeps() - { + void initpitchdeps() { pitchdeps.setsize(0); if(pitchtargets.empty()) return; - loopv(pitchtargets) - { + loopv(pitchtargets) { pitchtarget &t = pitchtargets[i]; t.deps = -1; addpitchdep(t.bone, t.frame); } - loopv(pitchdeps) - { + loopv(pitchdeps) { pitchdep &d = pitchdeps[i]; int parent = bones[d.bone].parent; - if(parent >= 0) - { + if(parent >= 0) { int j = findpitchdep(parent); - if(j >= 0) - { + if(j >= 0) { d.parent = j; d.pose.mul(pitchdeps[j].pose, dualquat(d.pose)); } } } - loopv(pitchtargets) - { + loopv(pitchtargets) { pitchtarget &t = pitchtargets[i]; int j = findpitchdep(t.bone); - if(j >= 0) - { + if(j >= 0) { t.deps = j; t.pose = pitchdeps[j].pose; } t.corrects = -1; - for(int parent = t.bone; parent >= 0; parent = bones[parent].parent) - { + for(int parent = t.bone; parent >= 0; parent = bones[parent].parent) { t.corrects = findpitchcorrect(parent); if(t.corrects >= 0) break; } } - loopv(pitchcorrects) - { + loopv(pitchcorrects) { pitchcorrect &c = pitchcorrects[i]; bones[c.bone].correctindex = i; c.parent = -1; - for(int parent = c.bone;;) - { + for(int parent = c.bone;;) { parent = bones[parent].parent; if(parent < 0) break; c.parent = findpitchcorrect(parent); @@ -754,56 +566,42 @@ struct skelmodel : animmodel } } } - - void optimize() - { + void optimize() { cleanup(); if(ragdoll) ragdoll->setup(); remapbones(); initpitchdeps(); } - - void expandbonemask(uchar *expansion, int bone, int val) - { + void expandbonemask(uchar *expansion, int bone, int val) { expansion[bone] = val; bone = bones[bone].children; while(bone>=0) { expandbonemask(expansion, bone, val); bone = bones[bone].next; } } - - void applybonemask(ushort *mask, uchar *partmask, int partindex) - { + void applybonemask(ushort *mask, uchar *partmask, int partindex) { if(!mask || *mask==BONEMASK_END) return; uchar *expansion = new uchar[numbones]; memset(expansion, *mask&BONEMASK_NOT ? 1 : 0, numbones); - while(*mask!=BONEMASK_END) - { + while(*mask!=BONEMASK_END) { expandbonemask(expansion, *mask&BONEMASK_BONE, *mask&BONEMASK_NOT ? 0 : 1); mask++; } loopi(numbones) if(expansion[i]) partmask[i] = partindex; delete[] expansion; } - - void linkchildren() - { - loopi(numbones) - { + void linkchildren() { + loopi(numbones) { boneinfo &b = bones[i]; b.children = -1; if(b.parent<0) b.next = -1; - else - { + else { b.next = bones[b.parent].children; bones[b.parent].children = i; } } } - int availgpubones() const { return min(maxvsuniforms - reservevpparams - 10, maxskelanimdata) / 2; } bool gpuaccelerate() const { return numframes && gpuskel && numgpubones<=availgpubones(); } - - float calcdeviation(const vec &axis, const vec &forward, const dualquat &pose1, const dualquat &pose2) - { + float calcdeviation(const vec &axis, const vec &forward, const dualquat &pose1, const dualquat &pose2) { vec forward1 = pose1.transformnormal(forward).project(axis).normalize(), forward2 = pose2.transformnormal(forward).project(axis).normalize(), daxis = vec().cross(forward1, forward2); @@ -811,35 +609,28 @@ struct skelmodel : animmodel if(daxis.dot(axis) < 0) dy = -dy; return atan2f(dy, dx)/RAD; } - - void calcpitchcorrects(float pitch, const vec &axis, const vec &forward) - { - loopv(pitchtargets) - { + void calcpitchcorrects(float pitch, const vec &axis, const vec &forward) { + loopv(pitchtargets) { pitchtarget &t = pitchtargets[i]; t.deviated = calcdeviation(axis, forward, t.pose, pitchdeps[t.deps].pose); } - loopv(pitchcorrects) - { + loopv(pitchcorrects) { pitchcorrect &c = pitchcorrects[i]; c.pitchangle = c.pitchtotal = 0; } - loopvj(pitchtargets) - { + loopvj(pitchtargets) { pitchtarget &t = pitchtargets[j]; float tpitch = pitch - t.deviated; for(int parent = t.corrects; parent >= 0; parent = pitchcorrects[parent].parent) tpitch -= pitchcorrects[parent].pitchangle; if(t.pitchmin || t.pitchmax) tpitch = clamp(tpitch, t.pitchmin, t.pitchmax); - loopv(pitchcorrects) - { + loopv(pitchcorrects) { pitchcorrect &c = pitchcorrects[i]; if(c.target != j) continue; float total = c.parent >= 0 ? pitchcorrects[c.parent].pitchtotal : 0, avail = tpitch - total, used = tpitch*c.pitchscale; - if(c.pitchmin || c.pitchmax) - { + if(c.pitchmin || c.pitchmax) { if(used < 0) used = clamp(c.pitchmin, used, 0.0f); else used = clamp(c.pitchmax, 0.0f, used); } @@ -850,39 +641,32 @@ struct skelmodel : animmodel } } } - #define INTERPBONE(bone) \ const animstate &s = as[partmask[bone]]; \ const framedata &f = partframes[partmask[bone]]; \ dualquat d; \ (d = f.fr1[bone]).mul((1-s.cur.t)*s.interp); \ d.accumulate(f.fr2[bone], s.cur.t*s.interp); \ - if(s.interp<1) \ - { \ + if(s.interp<1) { \ + \ d.accumulate(f.pfr1[bone], (1-s.prev.t)*(1-s.interp)); \ d.accumulate(f.pfr2[bone], s.prev.t*(1-s.interp)); \ } - - void interpbones(const animstate *as, float pitch, const vec &axis, const vec &forward, int numanimparts, const uchar *partmask, skelcacheentry &sc) - { + void interpbones(const animstate *as, float pitch, const vec &axis, const vec &forward, int numanimparts, const uchar *partmask, skelcacheentry &sc) { if(!sc.bdata) sc.bdata = new dualquat[numinterpbones]; sc.nextversion(); - struct framedata - { + struct framedata { const dualquat *fr1, *fr2, *pfr1, *pfr2; } partframes[MAXANIMPARTS]; - loopi(numanimparts) - { + loopi(numanimparts) { partframes[i].fr1 = &framebones[as[i].cur.fr1*numbones]; partframes[i].fr2 = &framebones[as[i].cur.fr2*numbones]; - if(as[i].interp<1) - { + if(as[i].interp<1) { partframes[i].pfr1 = &framebones[as[i].prev.fr1*numbones]; partframes[i].pfr2 = &framebones[as[i].prev.fr2*numbones]; } } - loopv(pitchdeps) - { + loopv(pitchdeps) { pitchdep &p = pitchdeps[i]; INTERPBONE(p.bone); d.normalize(); @@ -890,8 +674,7 @@ struct skelmodel : animmodel else p.pose = d; } calcpitchcorrects(pitch, axis, forward); - loopi(numbones) if(bones[i].interpindex>=0) - { + loopi(numbones) if(bones[i].interpindex>=0) { INTERPBONE(i); const boneinfo &b = bones[i]; d.normalize(); @@ -907,49 +690,39 @@ struct skelmodel : animmodel } loopv(antipodes) sc.bdata[antipodes[i].child].fixantipodal(sc.bdata[antipodes[i].parent]); } - - void initragdoll(ragdolldata &d, skelcacheentry &sc, part *p) - { + void initragdoll(ragdolldata &d, skelcacheentry &sc, part *p) { const dualquat *bdata = sc.bdata; - loopv(ragdoll->joints) - { + loopv(ragdoll->joints) { const ragdollskel::joint &j = ragdoll->joints[i]; const boneinfo &b = bones[j.bone]; const dualquat &q = bdata[b.interpindex]; - loopk(3) if(j.vert[k] >= 0) - { + loopk(3) if(j.vert[k] >= 0) { ragdollskel::vert &v = ragdoll->verts[j.vert[k]]; ragdolldata::vert &dv = d.verts[j.vert[k]]; dv.pos.add(q.transform(v.pos).mul(v.weight)); } } - if(ragdoll->animjoints) loopv(ragdoll->joints) - { + if(ragdoll->animjoints) loopv(ragdoll->joints) { const ragdollskel::joint &j = ragdoll->joints[i]; const boneinfo &b = bones[j.bone]; const dualquat &q = bdata[b.interpindex]; d.calcanimjoint(i, matrix4x3(q)); } - loopv(ragdoll->verts) - { + loopv(ragdoll->verts) { ragdolldata::vert &dv = d.verts[i]; matrixstack[matrixpos].transform(vec(dv.pos).add(p->translate).mul(p->model->scale), dv.pos); } - loopv(ragdoll->reljoints) - { + loopv(ragdoll->reljoints) { const ragdollskel::reljoint &r = ragdoll->reljoints[i]; const ragdollskel::joint &j = ragdoll->joints[r.parent]; const boneinfo &br = bones[r.bone], &bj = bones[j.bone]; d.reljoints[i].mul(dualquat(bdata[bj.interpindex]).invert(), bdata[br.interpindex]); } } - - void genragdollbones(ragdolldata &d, skelcacheentry &sc, part *p) - { + void genragdollbones(ragdolldata &d, skelcacheentry &sc, part *p) { if(!sc.bdata) sc.bdata = new dualquat[numinterpbones]; sc.nextversion(); - loopv(ragdoll->joints) - { + loopv(ragdoll->joints) { const ragdollskel::joint &j = ragdoll->joints[i]; const boneinfo &b = bones[j.bone]; vec pos(0, 0, 0); @@ -959,8 +732,7 @@ struct skelmodel : animmodel m.mul(d.tris[j.tri], pos, d.animjoints ? d.animjoints[i] : j.orient); sc.bdata[b.interpindex] = dualquat(m); } - loopv(ragdoll->reljoints) - { + loopv(ragdoll->reljoints) { const ragdollskel::reljoint &r = ragdoll->reljoints[i]; const ragdollskel::joint &j = ragdoll->joints[r.parent]; const boneinfo &br = bones[r.bone], &bj = bones[j.bone]; @@ -968,19 +740,14 @@ struct skelmodel : animmodel } loopv(antipodes) sc.bdata[antipodes[i].child].fixantipodal(sc.bdata[antipodes[i].parent]); } - - void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) - { + void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) { matrix4x3 t; t.mul(bones[tags[i].bone].base, tags[i].matrix); t.posttranslate(p->translate, p->model->scale); n.mul(m, t); } - - void calctags(part *p, skelcacheentry *sc = NULL) - { - loopv(p->links) - { + void calctags(part *p, skelcacheentry *sc = NULL) { + loopv(p->links) { linkedpart &l = p->links[i]; tag &t = tags[l.tag]; dualquat q; @@ -992,11 +759,8 @@ struct skelmodel : animmodel l.matrix = m; } } - - void cleanup(bool full = true) - { - loopv(skelcache) - { + void cleanup(bool full = true) { + loopv(skelcache) { skelcacheentry &sc = skelcache[i]; loopj(MAXANIMPARTS) sc.as[j].cur.fr1 = -1; DELETEA(sc.bdata); @@ -1005,31 +769,22 @@ struct skelmodel : animmodel blendoffsets.clear(); if(full) loopv(users) users[i]->cleanup(); } - bool canpreload() { return !numframes || gpuaccelerate(); } - - void preload() - { + void preload() { if(!numframes) return; - if(skelcache.empty()) - { + if(skelcache.empty()) { usegpuskel = gpuaccelerate(); } } - - skelcacheentry &checkskelcache(part *p, const animstate *as, float pitch, const vec &axis, const vec &forward, ragdolldata *rdata) - { - if(skelcache.empty()) - { + skelcacheentry &checkskelcache(part *p, const animstate *as, float pitch, const vec &axis, const vec &forward, ragdolldata *rdata) { + if(skelcache.empty()) { usegpuskel = gpuaccelerate(); } - int numanimparts = ((skelpart *)as->owner)->numanimparts; uchar *partmask = ((skelpart *)as->owner)->partmask; skelcacheentry *sc = NULL; bool match = false; - loopv(skelcache) - { + loopv(skelcache) { skelcacheentry &c = skelcache[i]; loopj(numanimparts) if(c.as[j]!=as[j]) goto mismatch; if(c.pitch != pitch || c.partmask != partmask || c.ragdoll != rdata || (rdata && c.millis < rdata->lastmove)) goto mismatch; @@ -1040,8 +795,7 @@ struct skelmodel : animmodel if(c.millis < lastmillis) { sc = &c; break; } } if(!sc) sc = &skelcache.add(); - if(!match) - { + if(!match) { loopi(numanimparts) sc->as[i] = as[i]; sc->pitch = pitch; sc->partmask = partmask; @@ -1052,101 +806,73 @@ struct skelmodel : animmodel sc->millis = lastmillis; return *sc; } - - int getblendoffset(UniformLoc &u) - { + int getblendoffset(UniformLoc &u) { int &offset = blendoffsets.access(Shader::lastshader->program, -1); - if(offset < 0) - { + if(offset < 0) { defformatstring(offsetname, "%s[%d]", u.name, 2*numgpubones); offset = glGetUniformLocation_(Shader::lastshader->program, offsetname); } return offset; } - - void setglslbones(UniformLoc &u, skelcacheentry &sc, skelcacheentry &bc, int count) - { + void setglslbones(UniformLoc &u, skelcacheentry &sc, skelcacheentry &bc, int count) { if(u.version == bc.version && u.data == bc.bdata) return; glUniform4fv_(u.loc, 2*numgpubones, sc.bdata[0].real.v); - if(count > 0) - { + if(count > 0) { int offset = getblendoffset(u); if(offset >= 0) glUniform4fv_(offset, 2*count, bc.bdata[0].real.v); } u.version = bc.version; u.data = bc.bdata; } - - void setgpubones(skelcacheentry &sc, blendcacheentry *bc, int count) - { + void setgpubones(skelcacheentry &sc, blendcacheentry *bc, int count) { if(!Shader::lastshader) return; if(Shader::lastshader->uniformlocs.length() < 1) return; UniformLoc &u = Shader::lastshader->uniformlocs[0]; setglslbones(u, sc, bc ? *bc : sc, count); } - - bool shouldcleanup() const - { + bool shouldcleanup() const { return numframes && (skelcache.empty() || gpuaccelerate()!=usegpuskel); } }; - - struct skelmeshgroup : meshgroup - { + struct skelmeshgroup : meshgroup { skeleton *skel; - vector<blendcombo> blendcombos; int numblends[4]; - static const int MAXBLENDCACHE = 16; blendcacheentry blendcache[MAXBLENDCACHE]; - static const int MAXVBOCACHE = 16; vbocacheentry vbocache[MAXVBOCACHE]; - ushort *edata; GLuint ebuf; bool vtangents; int vlen, vertsize, vblends, vweights; uchar *vdata; - - skelmeshgroup() : skel(NULL), edata(NULL), ebuf(0), vtangents(false), vlen(0), vertsize(0), vblends(0), vweights(0), vdata(NULL) - { + skelmeshgroup() : skel(NULL), edata(NULL), ebuf(0), vtangents(false), vlen(0), vertsize(0), vblends(0), vweights(0), vdata(NULL) { memset(numblends, 0, sizeof(numblends)); } - - virtual ~skelmeshgroup() - { - if(skel) - { + virtual ~skelmeshgroup() { + if(skel) { if(skel->shared) skel->users.removeobj(this); else DELETEP(skel); } if(ebuf) glDeleteBuffers_(1, &ebuf); - loopi(MAXBLENDCACHE) - { + loopi(MAXBLENDCACHE) { DELETEA(blendcache[i].bdata); } - loopi(MAXVBOCACHE) - { + loopi(MAXVBOCACHE) { if(vbocache[i].vbuf) glDeleteBuffers_(1, &vbocache[i].vbuf); } DELETEA(vdata); } - - void shareskeleton(char *name) - { - if(!name) - { + void shareskeleton(char *name) { + if(!name) { skel = new skeleton; skel->users.add(this); return; } - static hashnameset<skeleton *> skeletons; if(skeletons.access(name)) skel = skeletons[name]; - else - { + else { skel = new skeleton; skel->name = newstring(name); skeletons.add(skel); @@ -1154,38 +880,26 @@ struct skelmodel : animmodel skel->users.add(this); skel->shared++; } - - int findtag(const char *name) - { + int findtag(const char *name) { return skel->findtag(name); } - void *animkey() { return skel; } int totalframes() const { return max(skel->numframes, 1); } - virtual skelanimspec *loadanim(const char *filename) { (void) filename; return NULL; } - - void genvbo(bool tangents, vbocacheentry &vc) - { + void genvbo(bool tangents, vbocacheentry &vc) { if(!vc.vbuf) glGenBuffers_(1, &vc.vbuf); if(ebuf) return; - vector<ushort> idxs; - if(tangents) loopv(meshes) ((skelmesh *)meshes[i])->calctangents(); - vtangents = tangents; vlen = 0; vblends = 0; - if(skel->numframes && !skel->usegpuskel) - { + if(skel->numframes && !skel->usegpuskel) { vweights = 1; - loopv(blendcombos) - { + loopv(blendcombos) { blendcombo &c = blendcombos[i]; c.interpindex = c.weights[1] ? skel->numgpubones + vblends++ : -1; } - vertsize = tangents ? sizeof(vvertbump) : sizeof(vvertn); loopv(meshes) vlen += ((skelmesh *)meshes[i])->genvbo(idxs, vlen); DELETEA(vdata); @@ -1197,25 +911,20 @@ struct skelmodel : animmodel else FILLVDATA(vvertn); #undef FILLVDATA } - else - { - if(skel->numframes) - { + else { + if(skel->numframes) { vweights = 4; int availbones = skel->availgpubones() - skel->numgpubones; while(vweights > 1 && availbones >= numblends[vweights-1]) availbones -= numblends[--vweights]; - loopv(blendcombos) - { + loopv(blendcombos) { blendcombo &c = blendcombos[i]; c.interpindex = c.size() > vweights ? skel->numgpubones + vblends++ : -1; } } - else - { + else { vweights = 0; loopv(blendcombos) blendcombos[i].interpindex = -1; } - gle::bindvbo(vc.vbuf); #define GENVBO(type, args) do { \ vertsize = sizeof(type); \ @@ -1225,13 +934,11 @@ struct skelmodel : animmodel } while(0) #define GENVBOANIM(type) GENVBO(type, (idxs, vlen, vverts)) #define GENVBOSTAT(type) GENVBO(type, (idxs, vlen, vverts, htdata, htlen)) - if(skel->numframes) - { + if(skel->numframes) { if(tangents) GENVBOANIM(vvertbumpw); else GENVBOANIM(vvertnw); } - else - { + else { int numverts = 0, htlen = 128; loopv(meshes) numverts += ((skelmesh *)meshes[i])->numverts; while(htlen < numverts) htlen *= 2; @@ -1247,68 +954,51 @@ struct skelmodel : animmodel #undef GENVBOSTAT gle::clearvbo(); } - glGenBuffers_(1, &ebuf); gle::bindebo(ebuf); glBufferData_(GL_ELEMENT_ARRAY_BUFFER, idxs.length()*sizeof(ushort), idxs.getbuf(), GL_STATIC_DRAW); gle::clearebo(); } - - void bindvbo(const animstate *as, vbocacheentry &vc, skelcacheentry *sc = NULL, blendcacheentry *bc = NULL) - { + void bindvbo(const animstate *as, vbocacheentry &vc, skelcacheentry *sc = NULL, blendcacheentry *bc = NULL) { vvert *vverts = 0; bindpos(ebuf, vc.vbuf, &vverts->pos, vertsize); - if(as->cur.anim&ANIM_NOSKIN) - { + if(as->cur.anim&ANIM_NOSKIN) { if(enabletc) disabletc(); if(enablenormals) disablenormals(); if(enabletangents) disabletangents(); } - else - { - if(vtangents) - { + else { + if(vtangents) { if(enablenormals) disablenormals(); vvertbump *vvertbumps = 0; bindtangents(&vvertbumps->tangent, vertsize); } - else - { + else { if(enabletangents) disabletangents(); vvertn *vvertns = 0; bindnormals(&vvertns->norm, vertsize); } - bindtc(&vverts->tc, vertsize); } - if(!sc || !skel->usegpuskel) - { + if(!sc || !skel->usegpuskel) { if(enablebones) disablebones(); } - else - { - if(vtangents) - { + else { + if(vtangents) { vvertbumpw *vvertbumpws = 0; bindbones(vvertbumpws->weights, vvertbumpws->bones, vertsize); } - else - { + else { vvertnw *vvertnws = 0; bindbones(vvertnws->weights, vvertnws->bones, vertsize); } } } - - void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) - { + void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) { skel->concattagtransform(p, i, m, n); } - - int addblendcombo(const blendcombo &c) - { - loopv(blendcombos) if(blendcombos[i]==c) - { + int addblendcombo(const blendcombo &c) { + loopv(blendcombos) if(blendcombos[i]==c) { blendcombos[i].uses += c.uses; return i; } @@ -1316,50 +1006,38 @@ struct skelmodel : animmodel blendcombo &a = blendcombos.add(c); return a.interpindex = blendcombos.length()-1; } - - void sortblendcombos() - { + void sortblendcombos() { blendcombos.sort(blendcombo::sortcmp); int *remap = new int[blendcombos.length()]; loopv(blendcombos) remap[blendcombos[i].interpindex] = i; - loopv(meshes) - { + loopv(meshes) { skelmesh *m = (skelmesh *)meshes[i]; - loopj(m->numverts) - { + loopj(m->numverts) { vert &v = m->verts[j]; v.blend = remap[v.blend]; } } delete[] remap; } - - int remapblend(int blend) - { + int remapblend(int blend) { const blendcombo &c = blendcombos[blend]; return c.weights[1] ? c.interpindex : c.interpbones[0]; } - - static inline void blendbones(dualquat &d, const dualquat *bdata, const blendcombo &c) - { + static inline void blendbones(dualquat &d, const dualquat *bdata, const blendcombo &c) { d = bdata[c.interpbones[0]]; d.mul(c.weights[0]); d.accumulate(bdata[c.interpbones[1]], c.weights[1]); - if(c.weights[2]) - { + if(c.weights[2]) { d.accumulate(bdata[c.interpbones[2]], c.weights[2]); if(c.weights[3]) d.accumulate(bdata[c.interpbones[3]], c.weights[3]); } } - - void blendbones(const skelcacheentry &sc, blendcacheentry &bc) - { + void blendbones(const skelcacheentry &sc, blendcacheentry &bc) { bc.nextversion(); if(!bc.bdata) bc.bdata = new dualquat[vblends]; dualquat *dst = bc.bdata - skel->numgpubones; bool normalize = !skel->usegpuskel || vweights<=1; - loopv(blendcombos) - { + loopv(blendcombos) { const blendcombo &c = blendcombos[i]; if(c.interpindex<0) break; dualquat &d = dst[c.interpindex]; @@ -1367,17 +1045,13 @@ struct skelmodel : animmodel if(normalize) d.normalize(); } } - - void cleanup() - { - loopi(MAXBLENDCACHE) - { + void cleanup() { + loopi(MAXBLENDCACHE) { blendcacheentry &c = blendcache[i]; DELETEA(c.bdata); c.owner = -1; } - loopi(MAXVBOCACHE) - { + loopi(MAXVBOCACHE) { vbocacheentry &c = vbocache[i]; if(c.vbuf) { glDeleteBuffers_(1, &c.vbuf); c.vbuf = 0; } c.owner = -1; @@ -1385,38 +1059,31 @@ struct skelmodel : animmodel if(ebuf) { glDeleteBuffers_(1, &ebuf); ebuf = 0; } if(skel) skel->cleanup(false); } - #define SEARCHCACHE(cachesize, cacheentry, cache, reusecheck) \ - loopi(cachesize) \ - { \ + loopi(cachesize) { \ + \ cacheentry &c = cache[i]; \ - if(c.owner==owner) \ - { \ + if(c.owner==owner) { \ + \ if(c==sc) return c; \ else c.owner = -1; \ break; \ } \ } \ - loopi(cachesize-1) \ - { \ + loopi(cachesize-1) { \ + \ cacheentry &c = cache[i]; \ if(reusecheck c.owner < 0 || c.millis < lastmillis) \ return c; \ } \ return cache[cachesize-1]; - - vbocacheentry &checkvbocache(skelcacheentry &sc, int owner) - { + vbocacheentry &checkvbocache(skelcacheentry &sc, int owner) { SEARCHCACHE(MAXVBOCACHE, vbocacheentry, vbocache, !c.vbuf || ); } - - blendcacheentry &checkblendcache(skelcacheentry &sc, int owner) - { + blendcacheentry &checkblendcache(skelcacheentry &sc, int owner) { SEARCHCACHE(MAXBLENDCACHE, blendcacheentry, blendcache, ) } - - void preload(part *p) - { + void preload(part *p) { if(!skel->canpreload()) return; bool tangents = false; loopv(p->skins) if(p->skins[i].tangents()) tangents = true; @@ -1425,22 +1092,16 @@ struct skelmodel : animmodel skel->preload(); if(!vbocache->vbuf) genvbo(tangents, *vbocache); } - - void render(const animstate *as, float pitch, const vec &axis, const vec &forward, dynent *d, part *p) - { + void render(const animstate *as, float pitch, const vec &axis, const vec &forward, dynent *d, part *p) { bool tangents = false; loopv(p->skins) if(p->skins[i].tangents()) tangents = true; if(skel->shouldcleanup()) { skel->cleanup(); disablevbo(); } else if(tangents!=vtangents) { cleanup(); disablevbo(); } - - if(!skel->numframes) - { - if(!(as->cur.anim&ANIM_NORENDER)) - { + if(!skel->numframes) { + if(!(as->cur.anim&ANIM_NORENDER)) { if(!vbocache->vbuf) genvbo(tangents, *vbocache); bindvbo(as, *vbocache); - loopv(meshes) - { + loopv(meshes) { skelmesh *m = (skelmesh *)meshes[i]; p->skins[i].bind(m, as); m->render(as, p->skins[i], *vbocache); @@ -1449,153 +1110,110 @@ struct skelmodel : animmodel skel->calctags(p); return; } - skelcacheentry &sc = skel->checkskelcache(p, as, pitch, axis, forward, as->cur.anim&ANIM_RAGDOLL || !d || !d->ragdoll || d->ragdoll->skel != skel->ragdoll ? NULL : d->ragdoll); - if(!(as->cur.anim&ANIM_NORENDER)) - { + if(!(as->cur.anim&ANIM_NORENDER)) { int owner = &sc-&skel->skelcache[0]; vbocacheentry &vc = skel->usegpuskel ? *vbocache : checkvbocache(sc, owner); vc.millis = lastmillis; if(!vc.vbuf) genvbo(tangents, vc); blendcacheentry *bc = NULL; - if(vblends) - { + if(vblends) { bc = &checkblendcache(sc, owner); bc->millis = lastmillis; - if(bc->owner!=owner) - { + if(bc->owner!=owner) { bc->owner = owner; *(animcacheentry *)bc = sc; blendbones(sc, *bc); } } - if(!skel->usegpuskel && vc.owner!=owner) - { + if(!skel->usegpuskel && vc.owner!=owner) { vc.owner = owner; (animcacheentry &)vc = sc; - loopv(meshes) - { + loopv(meshes) { skelmesh &m = *(skelmesh *)meshes[i]; m.interpverts(sc.bdata, bc ? bc->bdata : NULL, tangents, vdata + m.voffset*vertsize, p->skins[i]); } gle::bindvbo(vc.vbuf); glBufferData_(GL_ARRAY_BUFFER, vlen*vertsize, vdata, GL_STREAM_DRAW); } - bindvbo(as, vc, &sc, bc); - loopv(meshes) - { + loopv(meshes) { skelmesh *m = (skelmesh *)meshes[i]; p->skins[i].bind(m, as); if(skel->usegpuskel) skel->setgpubones(sc, bc, vblends); m->render(as, p->skins[i], vc); } } - skel->calctags(p, &sc); - - if(as->cur.anim&ANIM_RAGDOLL && skel->ragdoll && !d->ragdoll) - { + if(as->cur.anim&ANIM_RAGDOLL && skel->ragdoll && !d->ragdoll) { d->ragdoll = new ragdolldata(skel->ragdoll, p->model->scale); skel->initragdoll(*d->ragdoll, sc, p); d->ragdoll->init(d); } } }; - - struct animpartmask - { + struct animpartmask { animpartmask *next; int numbones; uchar bones[1]; }; - - struct skelpart : part - { + struct skelpart : part { animpartmask *buildingpartmask; - uchar *partmask; - - skelpart(animmodel *model, int index = 0) : part(model, index), buildingpartmask(NULL), partmask(NULL) - { + skelpart(animmodel *model, int index = 0) : part(model, index), buildingpartmask(NULL), partmask(NULL) { } - - virtual ~skelpart() - { + virtual ~skelpart() { DELETEA(buildingpartmask); } - - uchar *sharepartmask(animpartmask *o) - { + uchar *sharepartmask(animpartmask *o) { static animpartmask *partmasks = NULL; animpartmask *p = partmasks; - for(; p; p = p->next) if(p->numbones==o->numbones && !memcmp(p->bones, o->bones, p->numbones)) - { + for(; p; p = p->next) if(p->numbones==o->numbones && !memcmp(p->bones, o->bones, p->numbones)) { delete[] (uchar *)o; return p->bones; } - o->next = p; partmasks = o; return o->bones; } - - animpartmask *newpartmask() - { + animpartmask *newpartmask() { animpartmask *p = (animpartmask *)new uchar[sizeof(animpartmask) + ((skelmeshgroup *)meshes)->skel->numbones-1]; p->numbones = ((skelmeshgroup *)meshes)->skel->numbones; memset(p->bones, 0, p->numbones); return p; } - - void initanimparts() - { + void initanimparts() { DELETEA(buildingpartmask); buildingpartmask = newpartmask(); } - - bool addanimpart(ushort *bonemask) - { + bool addanimpart(ushort *bonemask) { if(!buildingpartmask || numanimparts>=MAXANIMPARTS) return false; ((skelmeshgroup *)meshes)->skel->applybonemask(bonemask, buildingpartmask->bones, numanimparts); numanimparts++; return true; } - - void endanimparts() - { - if(buildingpartmask) - { + void endanimparts() { + if(buildingpartmask) { partmask = sharepartmask(buildingpartmask); buildingpartmask = NULL; } - ((skelmeshgroup *)meshes)->skel->optimize(); } - - void loaded() - { + void loaded() { endanimparts(); part::loaded(); } }; - - skelmodel(const char *name) : animmodel(name) - { + skelmodel(const char *name) : animmodel(name) { } - - int linktype(animmodel *m) const - { + int linktype(animmodel *m) const { return type()==m->type() && ((skelmeshgroup *)parts[0]->meshes)->skel == ((skelmeshgroup *)m->parts[0]->meshes)->skel ? LINK_REUSE : LINK_TAG; } - bool skeletal() const { return true; } - - skelpart &addpart() - { + skelpart &addpart() { flushpart(); skelpart *p = new skelpart(this, parts.length()); parts.add(p); @@ -1603,15 +1221,11 @@ struct skelmodel : animmodel } }; -struct skeladjustment -{ +struct skeladjustment { float yaw, pitch, roll; vec translate; - skeladjustment(float yaw, float pitch, float roll, const vec &translate) : yaw(yaw), pitch(pitch), roll(roll), translate(translate) {} - - void adjust(dualquat &dq) - { + void adjust(dualquat &dq) { if(yaw) dq.mulorient(quat(vec(0, 0, 1), yaw*RAD)); if(pitch) dq.mulorient(quat(vec(0, -1, 0), pitch*RAD)); if(roll) dq.mulorient(quat(vec(-1, 0, 0), roll*RAD)); @@ -1619,22 +1233,17 @@ struct skeladjustment } }; -template<class MDL> struct skelloader : modelloader<MDL, skelmodel> -{ +template<class MDL> struct skelloader : modelloader<MDL, skelmodel> { static vector<skeladjustment> adjustments; - skelloader(const char *name) : modelloader<MDL, skelmodel>(name) {} - - void flushpart() - { + void flushpart() { adjustments.setsize(0); } }; template<class MDL> vector<skeladjustment> skelloader<MDL>::adjustments; -template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmesh> -{ +template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmesh> { typedef modelcommands<MDL, struct MDL::skelmesh> commands; typedef struct MDL::skeleton skeleton; typedef struct MDL::skelmeshgroup meshgroup; @@ -1645,29 +1254,23 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes typedef struct MDL::pitchdep pitchdep; typedef struct MDL::pitchtarget pitchtarget; typedef struct MDL::pitchcorrect pitchcorrect; - - static void loadpart(char *meshfile, char *skelname, float *smooth) - { + static void loadpart(char *meshfile, char *skelname, float *smooth) { if(!MDL::loading) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } defformatstring(filename, "%s/%s", MDL::dir, meshfile); part &mdl = MDL::loading->addpart(); mdl.pitchscale = mdl.pitchoffset = mdl.pitchmin = mdl.pitchmax = 0; mdl.meshes = MDL::loading->sharemeshes(path(filename), skelname[0] ? skelname : NULL, double(*smooth > 0 ? cos(clamp(*smooth, 0.0f, 180.0f)*RAD) : 2)); if(!mdl.meshes) conoutf(CON_ERROR, "could not load %s", filename); - else - { + else { mdl.initanimparts(); mdl.initskins(); } } - - static void settag(char *name, char *tagname, float *tx, float *ty, float *tz, float *rx, float *ry, float *rz) - { + static void settag(char *name, char *tagname, float *tx, float *ty, float *tz, float *rx, float *ry, float *rz) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); int i = mdl.meshes ? ((meshgroup *)mdl.meshes)->skel->findbone(name) : -1; - if(i >= 0) - { + if(i >= 0) { float cx = *rx ? cosf(*rx/2*RAD) : 1, sx = *rx ? sinf(*rx/2*RAD) : 0, cy = *ry ? cosf(*ry/2*RAD) : 1, sy = *ry ? sinf(*ry/2*RAD) : 0, cz = *rz ? cosf(*rz/2*RAD) : 1, sz = *rz ? sinf(*rz/2*RAD) : 0; @@ -1678,27 +1281,20 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes } conoutf(CON_ERROR, "could not find bone %s for tag %s", name, tagname); } - - static void setpitch(char *name, float *pitchscale, float *pitchoffset, float *pitchmin, float *pitchmax) - { + static void setpitch(char *name, float *pitchscale, float *pitchoffset, float *pitchmin, float *pitchmax) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); - - if(name[0]) - { + if(name[0]) { int i = mdl.meshes ? ((meshgroup *)mdl.meshes)->skel->findbone(name) : -1; - if(i>=0) - { + if(i>=0) { boneinfo &b = ((meshgroup *)mdl.meshes)->skel->bones[i]; b.pitchscale = *pitchscale; b.pitchoffset = *pitchoffset; - if(*pitchmin || *pitchmax) - { + if(*pitchmin || *pitchmax) { b.pitchmin = *pitchmin; b.pitchmax = *pitchmax; } - else - { + else { b.pitchmin = -360*fabs(b.pitchscale) + b.pitchoffset; b.pitchmax = 360*fabs(b.pitchscale) + b.pitchoffset; } @@ -1707,23 +1303,18 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes conoutf(CON_ERROR, "could not find bone %s to pitch", name); return; } - mdl.pitchscale = *pitchscale; mdl.pitchoffset = *pitchoffset; - if(*pitchmin || *pitchmax) - { + if(*pitchmin || *pitchmax) { mdl.pitchmin = *pitchmin; mdl.pitchmax = *pitchmax; } - else - { + else { mdl.pitchmin = -360*fabs(mdl.pitchscale) + mdl.pitchoffset; mdl.pitchmax = 360*fabs(mdl.pitchscale) + mdl.pitchoffset; } } - - static void setpitchtarget(char *name, char *animfile, int *frameoffset, float *pitchmin, float *pitchmax) - { + static void setpitchtarget(char *name, char *animfile, int *frameoffset, float *pitchmin, float *pitchmax) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); if(!mdl.meshes) return; @@ -1732,8 +1323,7 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes if(!sa) { conoutf(CON_ERROR, "could not load %s anim file %s", MDL::formatname(), filename); return; } skeleton *skel = ((meshgroup *)mdl.meshes)->skel; int bone = skel ? skel->findbone(name) : -1; - if(bone < 0) - { + if(bone < 0) { conoutf(CON_ERROR, "could not find bone %s to pitch target", name); return; } @@ -1744,24 +1334,20 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes t.pitchmin = *pitchmin; t.pitchmax = *pitchmax; } - - static void setpitchcorrect(char *name, char *targetname, float *scale, float *pitchmin, float *pitchmax) - { + static void setpitchcorrect(char *name, char *targetname, float *scale, float *pitchmin, float *pitchmax) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); if(!mdl.meshes) return; skeleton *skel = ((meshgroup *)mdl.meshes)->skel; int bone = skel ? skel->findbone(name) : -1; - if(bone < 0) - { + if(bone < 0) { conoutf(CON_ERROR, "could not find bone %s to pitch correct", name); return; } if(skel->findpitchcorrect(bone) >= 0) return; int targetbone = skel->findbone(targetname), target = -1; if(targetbone >= 0) loopv(skel->pitchtargets) if(skel->pitchtargets[i].bone == targetbone) { target = i; break; } - if(target < 0) - { + if(target < 0) { conoutf(CON_ERROR, "could not find pitch target %s to pitch correct %s", targetname, name); return; } @@ -1775,23 +1361,18 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes loopv(skel->pitchcorrects) if(bone <= skel->pitchcorrects[i].bone) { pos = i; break; } skel->pitchcorrects.insert(pos, c); } - - static void setanim(char *anim, char *animfile, float *speed, int *priority, int *startoffset, int *endoffset) - { + static void setanim(char *anim, char *animfile, float *speed, int *priority, int *startoffset, int *endoffset) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } - vector<int> anims; findanims(anim, anims); if(anims.empty()) conoutf(CON_ERROR, "could not find animation %s", anim); - else - { + else { part *p = (part *)MDL::loading->parts.last(); if(!p->meshes) return; defformatstring(filename, "%s/%s", MDL::dir, animfile); animspec *sa = ((meshgroup *)p->meshes)->loadanim(path(filename)); if(!sa) conoutf(CON_ERROR, "could not load %s anim file %s", MDL::formatname(), filename); - else loopv(anims) - { + else loopv(anims) { int start = sa->frame, end = sa->range; if(*startoffset > 0) start += min(*startoffset, end-1); else if(*startoffset < 0) start += max(end + *startoffset, 0); @@ -1802,18 +1383,13 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes } } } - - static void setanimpart(char *maskstr) - { + static void setanimpart(char *maskstr) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } - part *p = (part *)MDL::loading->parts.last(); - vector<char *> bonestrs; explodelist(maskstr, bonestrs); vector<ushort> bonemask; - loopv(bonestrs) - { + loopv(bonestrs) { char *bonestr = bonestrs[i]; int bone = p->meshes ? ((meshgroup *)p->meshes)->skel->findbone(bonestr[0]=='!' ? bonestr+1 : bonestr) : -1; if(bone<0) { conoutf(CON_ERROR, "could not find bone %s for anim part mask [%s]", bonestr, maskstr); bonestrs.deletearrays(); return; } @@ -1822,31 +1398,24 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes bonestrs.deletearrays(); bonemask.sort(); if(bonemask.length()) bonemask.add(BONEMASK_END); - if(!p->addanimpart(bonemask.getbuf())) conoutf(CON_ERROR, "too many animation parts"); } - - static void setadjust(char *name, float *yaw, float *pitch, float *roll, float *tx, float *ty, float *tz) - { + static void setadjust(char *name, float *yaw, float *pitch, float *roll, float *tx, float *ty, float *tz) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); - if(!name[0]) return; int i = mdl.meshes ? ((meshgroup *)mdl.meshes)->skel->findbone(name) : -1; if(i < 0) { conoutf(CON_ERROR, "could not find bone %s to adjust", name); return; } while(!MDL::adjustments.inrange(i)) MDL::adjustments.add(skeladjustment(0, 0, 0, vec(0, 0, 0))); MDL::adjustments[i] = skeladjustment(*yaw, *pitch, *roll, vec(*tx/4, *ty/4, *tz/4)); } - - skelcommands() - { + skelcommands() { if(MDL::multiparted()) this->modelcommand(loadpart, "load", "ssf"); this->modelcommand(settag, "tag", "ssffffff"); this->modelcommand(setpitch, "pitch", "sffff"); this->modelcommand(setpitchtarget, "pitchtarget", "ssiff"); this->modelcommand(setpitchcorrect, "pitchcorrect", "ssfff"); - if(MDL::animated()) - { + if(MDL::animated()) { this->modelcommand(setanim, "anim", "ssfiii"); this->modelcommand(setanimpart, "animpart", "s"); this->modelcommand(setadjust, "adjust", "sffffff"); diff --git a/src/engine/sound.cpp b/src/engine/sound.cpp index d10386d..62cab3e 100644 --- a/src/engine/sound.cpp +++ b/src/engine/sound.cpp @@ -5,44 +5,34 @@ bool nosound = true; -struct soundsample -{ +struct soundsample { char *name; Mix_Chunk *chunk; - soundsample() : name(NULL), chunk(NULL) {} ~soundsample() { DELETEA(name); } - void cleanup() { if(chunk) { Mix_FreeChunk(chunk); chunk = NULL; } } bool load(bool msg = false); }; -struct soundslot -{ +struct soundslot { soundsample *sample; int volume; }; -struct soundconfig -{ +struct soundconfig { int slots, numslots; int maxuses; - - bool hasslot(const soundslot *p, const vector<soundslot> &v) const - { + bool hasslot(const soundslot *p, const vector<soundslot> &v) const { return p >= v.getbuf() + slots && p < v.getbuf() + slots+numslots && slots+numslots < v.length(); } - - int chooseslot(int flags) const - { + int chooseslot(int flags) const { if(flags&SND_NO_ALT || numslots <= 1) return slots; if(flags&SND_USE_ALT) return slots + 1 + rnd(numslots - 1); return slots + rnd(numslots); } }; -struct soundchannel -{ +struct soundchannel { int id; bool inuse; vec loc; @@ -50,14 +40,10 @@ struct soundchannel extentity *ent; int radius, volume, pan, flags; bool dirty; - soundchannel(int id) : id(id) { reset(); } - bool hasloc() const { return loc.x >= -1e15f; } void clearloc() { loc = vec(-1e16f, -1e16f, -1e16f); } - - void reset() - { + void reset() { inuse = false; clearloc(); slot = NULL; @@ -72,10 +58,8 @@ struct soundchannel vector<soundchannel> channels; int maxchannels = 0; -soundchannel &newchannel(int n, soundslot *slot, const vec *loc = NULL, extentity *ent = NULL, int flags = 0, int radius = 0) -{ - if(ent) - { +soundchannel &newchannel(int n, soundslot *slot, const vec *loc = NULL, extentity *ent = NULL, int flags = 0, int radius = 0) { + if(ent) { loc = &ent->o; ent->flags |= EF_SOUND; } @@ -91,26 +75,22 @@ soundchannel &newchannel(int n, soundslot *slot, const vec *loc = NULL, extentit return chan; } -void freechannel(int n) -{ +void freechannel(int n) { if(!channels.inrange(n) || !channels[n].inuse) return; soundchannel &chan = channels[n]; chan.inuse = false; if(chan.ent) chan.ent->flags &= ~EF_SOUND; } -void syncchannel(soundchannel &chan) -{ +void syncchannel(soundchannel &chan) { if(!chan.dirty) return; if(!Mix_FadingChannel(chan.id)) Mix_Volume(chan.id, chan.volume); Mix_SetPanning(chan.id, 255-chan.pan, chan.pan); chan.dirty = false; } -void stopchannels() -{ - loopv(channels) - { +void stopchannels() { + loopv(channels) { soundchannel &chan = channels[i]; if(!chan.inuse) continue; Mix_HaltChannel(i); @@ -121,8 +101,7 @@ void stopchannels() void setmusicvol(int musicvol); extern int musicvol; static int curvol = 0; -VARFP(soundvol, 0, 255, 255, -{ +VARFP(soundvol, 0, 255, 255, { if(!soundvol) { stopchannels(); setmusicvol(0); } else if(!curvol) setmusicvol(musicvol); curvol = soundvol; @@ -135,19 +114,16 @@ Mix_Music *music = NULL; SDL_RWops *musicrw = NULL; stream *musicstream = NULL; -void setmusicvol(int musicvol) -{ +void setmusicvol(int musicvol) { if(nosound) return; if(music) Mix_VolumeMusic((musicvol*MIX_MAX_VOLUME)/255); } -void stopmusic() -{ +void stopmusic() { if(nosound) return; DELETEA(musicfile); DELETEA(musicdonecmd); - if(music) - { + if(music) { Mix_HaltMusic(); Mix_FreeMusic(music); music = NULL; @@ -163,34 +139,28 @@ VARF(soundchans, 1, 32, 128, initwarning("sound configuration", INIT_RESET, CHAN VARF(soundfreq, 0, MIX_DEFAULT_FREQUENCY, 48000, initwarning("sound configuration", INIT_RESET, CHANGE_SOUND)); VARF(soundbufferlen, 128, 1024, 4096, initwarning("sound configuration", INIT_RESET, CHANGE_SOUND)); -bool initaudio() -{ +bool initaudio() { static string fallback = ""; static bool initfallback = true; static bool restorefallback = false; - if(initfallback) - { + if(initfallback) { initfallback = false; if(char *env = SDL_getenv("SDL_AUDIODRIVER")) copystring(fallback, env); } - if(!fallback[0] && audiodriver[0]) - { + if(!fallback[0] && audiodriver[0]) { vector<char*> drivers; explodelist(audiodriver, drivers); - loopv(drivers) - { + loopv(drivers) { restorefallback = true; SDL_setenv("SDL_AUDIODRIVER", drivers[i], 1); - if(SDL_InitSubSystem(SDL_INIT_AUDIO) >= 0) - { + if(SDL_InitSubSystem(SDL_INIT_AUDIO) >= 0) { drivers.deletearrays(); return true; } } drivers.deletearrays(); } - if(restorefallback) - { + if(restorefallback) { restorefallback = false; unsetenv("SDL_AUDIODRIVER"); } @@ -199,30 +169,23 @@ bool initaudio() return false; } -void initsound() -{ +void initsound() { SDL_version version; SDL_GetVersion(&version); - if(version.major == 2 && version.minor == 0 && version.patch == 6) - { + if(version.major == 2 && version.minor == 0 && version.patch == 6) { nosound = true; if(usesound) conoutf(CON_ERROR, "audio is broken in SDL 2.0.6"); return; } - - if(shouldinitaudio) - { + if(shouldinitaudio) { shouldinitaudio = false; if(SDL_WasInit(SDL_INIT_AUDIO)) SDL_QuitSubSystem(SDL_INIT_AUDIO); - if(!usesound || !initaudio()) - { + if(!usesound || !initaudio()) { nosound = true; return; } } - - if(Mix_OpenAudio(soundfreq, MIX_DEFAULT_FORMAT, 2, soundbufferlen)<0) - { + if(Mix_OpenAudio(soundfreq, MIX_DEFAULT_FORMAT, 2, soundbufferlen)<0) { nosound = true; conoutf(CON_ERROR, "sound init failed (SDL_mixer): %s", Mix_GetError()); return; @@ -232,8 +195,7 @@ void initsound() nosound = false; } -void musicdone() -{ +void musicdone() { if(music) { Mix_HaltMusic(); Mix_FreeMusic(music); music = NULL; } if(musicrw) { SDL_FreeRW(musicrw); musicrw = NULL; } DELETEP(musicstream); @@ -245,34 +207,28 @@ void musicdone() delete[] cmd; } -Mix_Music *loadmusic(const char *name) -{ +Mix_Music *loadmusic(const char *name) { if(!musicstream) musicstream = openzipfile(name, "rb"); - if(musicstream) - { + if(musicstream) { if(!musicrw) musicrw = musicstream->rwops(); if(!musicrw) DELETEP(musicstream); } if(musicrw) music = Mix_LoadMUSType_RW(musicrw, MUS_NONE, 0); else music = Mix_LoadMUS(findfile(name, "rb")); - if(!music) - { + if(!music) { if(musicrw) { SDL_FreeRW(musicrw); musicrw = NULL; } DELETEP(musicstream); } return music; } -void startmusic(char *name, char *cmd) -{ +void startmusic(char *name, char *cmd) { if(nosound) return; stopmusic(); - if(soundvol && musicvol && *name) - { + if(soundvol && musicvol && *name) { defformatstring(file, "packages/%s", name); path(file); - if(loadmusic(file)) - { + if(loadmusic(file)) { DELETEA(musicfile); DELETEA(musicdonecmd); musicfile = newstring(file); @@ -281,8 +237,7 @@ void startmusic(char *name, char *cmd) Mix_VolumeMusic((musicvol*MIX_MAX_VOLUME)/255); intret(1); } - else - { + else { conoutf(CON_ERROR, "could not play music: %s", file); intret(0); } @@ -291,15 +246,12 @@ void startmusic(char *name, char *cmd) COMMANDN(music, startmusic, "ss"); -static Mix_Chunk *loadwav(const char *name) -{ +static Mix_Chunk *loadwav(const char *name) { Mix_Chunk *c = NULL; stream *z = openzipfile(name, "rb"); - if(z) - { + if(z) { SDL_RWops *rw = z->rwops(); - if(rw) - { + if(rw) { c = Mix_LoadWAV_RW(rw, 0); SDL_FreeRW(rw); } @@ -309,47 +261,39 @@ static Mix_Chunk *loadwav(const char *name) return c; } -template<class T> static void scalewav(T* dst, T* src, size_t len, int scale) -{ +template<class T> static void scalewav(T* dst, T* src, size_t len, int scale) { len /= sizeof(T); const T* end = src + len; - if(scale==2) for(; src < end; src++, dst += scale) - { + if(scale==2) for(; src < end; src++, dst += scale) { T s = src[0]; dst[0] = s; dst[1] = s; } - else if(scale==4) for(; src < end; src++, dst += scale) - { + else if(scale==4) for(; src < end; src++, dst += scale) { T s = src[0]; dst[0] = s; dst[1] = s; dst[2] = s; dst[3] = s; } - else for(; src < end; src++) - { + else for(; src < end; src++) { T s = src[0]; loopi(scale) *dst++ = s; } } -static Mix_Chunk *loadwavscaled(const char *name) -{ +static Mix_Chunk *loadwavscaled(const char *name) { int mixerfreq = 0; Uint16 mixerformat = 0; int mixerchannels = 0; if(!Mix_QuerySpec(&mixerfreq, &mixerformat, &mixerchannels)) return NULL; - SDL_AudioSpec spec; Uint8 *audiobuf = NULL; Uint32 audiolen = 0; stream *z = openzipfile(name, "rb"); - if(z) - { + if(z) { SDL_RWops *rw = z->rwops(); - if(rw) - { + if(rw) { SDL_LoadWAV_RW(rw, 0, &spec, &audiobuf, &audiolen); SDL_FreeRW(rw); } @@ -359,21 +303,17 @@ static Mix_Chunk *loadwavscaled(const char *name) if(!audiobuf) return NULL; int samplesize = ((spec.format&0xFF)/8) * spec.channels; int scale = mixerfreq / spec.freq; - if(scale >= 2) - { + if(scale >= 2) { Uint8 *scalebuf = (Uint8*)SDL_malloc(audiolen * scale); - if(scalebuf) - { - switch(samplesize) - { + if(scalebuf) { + switch(samplesize) { case 1: scalewav((uchar*)scalebuf, (uchar*)audiobuf, audiolen, scale); break; case 2: scalewav((ushort*)scalebuf, (ushort*)audiobuf, audiolen, scale); break; case 4: scalewav((uint*)scalebuf, (uint*)audiobuf, audiolen, scale); break; case 8: scalewav((ullong*)scalebuf, (ullong*)audiobuf, audiolen, scale); break; default: SDL_free(scalebuf); scalebuf = NULL; break; } - if(scalebuf) - { + if(scalebuf) { SDL_free(audiobuf); audiobuf = scalebuf; audiolen *= scale; @@ -381,16 +321,13 @@ static Mix_Chunk *loadwavscaled(const char *name) } } } - if(spec.freq != mixerfreq || spec.format != mixerformat || spec.channels != mixerchannels) - { + if(spec.freq != mixerfreq || spec.format != mixerformat || spec.channels != mixerchannels) { SDL_AudioCVT cvt; - if(SDL_BuildAudioCVT(&cvt, spec.format, spec.channels, spec.freq, mixerformat, mixerchannels, mixerfreq) < 0) - { + if(SDL_BuildAudioCVT(&cvt, spec.format, spec.channels, spec.freq, mixerformat, mixerchannels, mixerfreq) < 0) { SDL_free(audiobuf); return NULL; } - if(cvt.filters[0]) - { + if(cvt.filters[0]) { cvt.len = audiolen & ~(samplesize-1); cvt.buf = (Uint8*)SDL_malloc(cvt.len * cvt.len_mult); if(!cvt.buf) { SDL_free(audiobuf); return NULL; } @@ -409,23 +346,18 @@ static Mix_Chunk *loadwavscaled(const char *name) VARFP(fixwav, 0, 1, 1, initwarning("sound configuration", INIT_LOAD, CHANGE_SOUND)); -bool soundsample::load(bool msg) -{ +bool soundsample::load(bool msg) { if(chunk) return true; if(!name[0]) return false; - static const char * const exts[] = { "", ".wav", ".ogg" }; string filename; - loopi(sizeof(exts)/sizeof(exts[0])) - { + loopi(sizeof(exts)/sizeof(exts[0])) { formatstring(filename, "packages/sounds/%s%s", name, exts[i]); if(msg && !i) renderprogress(0, filename); path(filename); - if(fixwav) - { + if(fixwav) { size_t len = strlen(filename); - if(len >= 4 && !strcasecmp(filename + len - 4, ".wav")) - { + if(len >= 4 && !strcasecmp(filename + len - 4, ".wav")) { chunk = loadwavscaled(filename); if(chunk) return true; } @@ -433,42 +365,32 @@ bool soundsample::load(bool msg) chunk = loadwav(filename); if(chunk) return true; } - conoutf(CON_ERROR, "failed to load sample: packages/sounds/%s", name); return false; } static hashnameset<soundsample> samples; -static void cleanupsamples() -{ +static void cleanupsamples() { enumerate(samples, soundsample, s, s.cleanup()); } -static struct soundtype -{ +static struct soundtype { vector<soundslot> slots; vector<soundconfig> configs; - - int findsound(const char *name, int vol) - { - loopv(configs) - { + int findsound(const char *name, int vol) { + loopv(configs) { soundconfig &s = configs[i]; - loopj(s.numslots) - { + loopj(s.numslots) { soundslot &c = slots[s.slots+j]; if(!strcmp(c.sample->name, name) && (!vol || c.volume==vol)) return i; } } return -1; } - - int addslot(const char *name, int vol) - { + int addslot(const char *name, int vol) { soundsample *s = samples.access(name); - if(!s) - { + if(!s) { char *n = newstring(name); s = &samples[n]; s->name = n; @@ -478,8 +400,7 @@ static struct soundtype int oldlen = slots.length(); soundslot &slot = slots.add(); // soundslots.add() may relocate slot pointers - if(slots.getbuf() != oldslots) loopv(channels) - { + if(slots.getbuf() != oldslots) loopv(channels) { soundchannel &chan = channels[i]; if(chan.inuse && chan.slot >= oldslots && chan.slot < &oldslots[oldlen]) chan.slot = &slots[chan.slot - oldslots]; @@ -488,52 +409,38 @@ static struct soundtype slot.volume = vol ? vol : 100; return oldlen; } - - int addsound(const char *name, int vol, int maxuses = 0) - { + int addsound(const char *name, int vol, int maxuses = 0) { soundconfig &s = configs.add(); s.slots = addslot(name, vol); s.numslots = 1; s.maxuses = maxuses; return configs.length()-1; } - - void addalt(const char *name, int vol) - { + void addalt(const char *name, int vol) { if(configs.empty()) return; addslot(name, vol); configs.last().numslots++; } - - void clear() - { + void clear() { slots.setsize(0); configs.setsize(0); } - - void reset() - { - loopv(channels) - { + void reset() { + loopv(channels) { soundchannel &chan = channels[i]; - if(chan.inuse && slots.inbuf(chan.slot)) - { + if(chan.inuse && slots.inbuf(chan.slot)) { Mix_HaltChannel(i); freechannel(i); } } clear(); } - - void preloadsound(int n) - { + void preloadsound(int n) { if(nosound || !configs.inrange(n)) return; soundconfig &config = configs[n]; loopk(config.numslots) slots[config.slots+k].sample->load(true); } - - bool playing(const soundchannel &chan, const soundconfig &config) const - { + bool playing(const soundchannel &chan, const soundconfig &config) const { return chan.inuse && config.hasslot(chan.slot, slots); } } gamesounds, mapsounds; @@ -553,29 +460,24 @@ COMMAND(altmapsound, "si"); ICOMMAND(numsounds, "", (), intret(gamesounds.configs.length())); ICOMMAND(nummapsounds, "", (), intret(mapsounds.configs.length())); -void soundreset() -{ +void soundreset() { gamesounds.reset(); } COMMAND(soundreset, ""); -void mapsoundreset() -{ +void mapsoundreset() { mapsounds.reset(); } COMMAND(mapsoundreset, ""); -void resetchannels() -{ +void resetchannels() { loopv(channels) if(channels[i].inuse) freechannel(i); channels.shrink(0); } -void clear_sound() -{ +void clear_sound() { if(nosound) return; stopmusic(); - cleanupsamples(); gamesounds.clear(); mapsounds.clear(); @@ -584,43 +486,34 @@ void clear_sound() resetchannels(); } -void stopmapsounds() -{ - loopv(channels) if(channels[i].inuse && channels[i].ent) - { +void stopmapsounds() { + loopv(channels) if(channels[i].inuse && channels[i].ent) { Mix_HaltChannel(i); freechannel(i); } } -void clearmapsounds() -{ +void clearmapsounds() { stopmapsounds(); mapsounds.clear(); } -void stopmapsound(extentity *e) -{ - loopv(channels) - { +void stopmapsound(extentity *e) { + loopv(channels) { soundchannel &chan = channels[i]; - if(chan.inuse && chan.ent == e) - { + if(chan.inuse && chan.ent == e) { Mix_HaltChannel(i); freechannel(i); } } } -void checkmapsounds() -{ +void checkmapsounds() { const vector<extentity *> &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; if(e.type!=ET_SOUND) continue; - if(camera1->o.dist(e.o) < e.attr2) - { + if(camera1->o.dist(e.o) < e.attr2) { if(!(e.flags&EF_SOUND)) playsound(e.attr1, NULL, &e, SND_MAP, -1); } else if(e.flags&EF_SOUND) stopmapsound(&e); @@ -629,28 +522,23 @@ void checkmapsounds() VAR(stereo, 0, 1, 1); -bool updatechannel(soundchannel &chan) -{ +bool updatechannel(soundchannel &chan) { if(!chan.slot) return false; int vol = soundvol, pan = 255/2; - if(chan.hasloc()) - { + if(chan.hasloc()) { vec v; float dist = chan.loc.dist(camera1->o, v); int rad = 0; - if(chan.ent) - { + if(chan.ent) { rad = chan.ent->attr2; - if(chan.ent->attr3) - { + if(chan.ent->attr3) { rad -= chan.ent->attr3; dist -= chan.ent->attr3; } } else if(chan.radius > 0) rad = chan.radius; if(rad > 0) vol -= int(clamp(dist/rad, 0.0f, 1.0f)*soundvol); // simple mono distance attenuation - if(stereo && (v.x != 0 || v.y != 0) && dist>0) - { + if(stereo && (v.x != 0 || v.y != 0) && dist>0) { v.rotate_around_z(-camera1->yaw*RAD); pan = int(255.9f*(0.5f - 0.5f*v.x/v.magnitude2())); // range is from 0 (left) to 255 (right) } @@ -664,19 +552,15 @@ bool updatechannel(soundchannel &chan) return true; } -void reclaimchannels() -{ - loopv(channels) - { +void reclaimchannels() { + loopv(channels) { soundchannel &chan = channels[i]; if(chan.inuse && !Mix_Playing(i)) freechannel(i); } } -void syncchannels() -{ - loopv(channels) - { +void syncchannels() { + loopv(channels) { soundchannel &chan = channels[i]; if(chan.inuse && chan.hasloc() && updatechannel(chan)) syncchannel(chan); } @@ -684,19 +568,16 @@ void syncchannels() VARP(minimizedsounds, 0, 0, 1); -void updatesounds() -{ +void updatesounds() { if(nosound) return; if(minimized && !minimizedsounds) stopsounds(); - else - { + else { reclaimchannels(); if(mainmenu) stopmapsounds(); else checkmapsounds(); syncchannels(); } - if(music) - { + if(music) { if(!Mix_PlayingMusic()) musicdone(); else if(Mix_PausedMusic()) Mix_ResumeMusic(); } @@ -704,91 +585,70 @@ void updatesounds() VARP(maxsoundsatonce, 0, 7, 100); -void preloadsound(int n) -{ +void preloadsound(int n) { gamesounds.preloadsound(n); } -void preloadmapsound(int n) -{ +void preloadmapsound(int n) { mapsounds.preloadsound(n); } -void preloadmapsounds() -{ +void preloadmapsounds() { const vector<extentity *> &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; if(e.type==ET_SOUND) mapsounds.preloadsound(e.attr1); } } -int playsound(int n, const vec *loc, extentity *ent, int flags, int loops, int fade, int chanid, int radius, int expire) -{ +int playsound(int n, const vec *loc, extentity *ent, int flags, int loops, int fade, int chanid, int radius, int expire) { if(nosound || !soundvol || (minimized && !minimizedsounds)) return -1; - soundtype &sounds = ent || flags&SND_MAP ? mapsounds : gamesounds; if(!sounds.configs.inrange(n)) { conoutf(CON_WARN, "unregistered sound: %d", n); return -1; } soundconfig &config = sounds.configs[n]; - - if(loc) - { + if(loc) { // cull sounds that are unlikely to be heard int maxrad = game::maxsoundradius(n); if(radius <= 0 || maxrad < radius) radius = maxrad; - if(camera1->o.dist(*loc) > 1.5f*radius) - { - if(channels.inrange(chanid) && sounds.playing(channels[chanid], config)) - { + if(camera1->o.dist(*loc) > 1.5f*radius) { + if(channels.inrange(chanid) && sounds.playing(channels[chanid], config)) { Mix_HaltChannel(chanid); freechannel(chanid); } return -1; } } - - if(chanid < 0) - { - if(config.maxuses) - { + if(chanid < 0) { + if(config.maxuses) { int uses = 0; loopv(channels) if(sounds.playing(channels[i], config) && ++uses >= config.maxuses) return -1; } - // avoid bursts of sounds with heavy packetloss and in sp static int soundsatonce = 0, lastsoundmillis = 0; if(totalmillis == lastsoundmillis) soundsatonce++; else soundsatonce = 1; lastsoundmillis = totalmillis; if(maxsoundsatonce && soundsatonce > maxsoundsatonce) return -1; } - - if(channels.inrange(chanid)) - { + if(channels.inrange(chanid)) { soundchannel &chan = channels[chanid]; - if(sounds.playing(chan, config)) - { + if(sounds.playing(chan, config)) { if(loc) chan.loc = *loc; else if(chan.hasloc()) chan.clearloc(); return chanid; } } if(fade < 0) return -1; - soundslot &slot = sounds.slots[config.chooseslot(flags)]; if(!slot.sample->chunk && !slot.sample->load()) return -1; - chanid = -1; loopv(channels) if(!channels[i].inuse) { chanid = i; break; } if(chanid < 0 && channels.length() < maxchannels) chanid = channels.length(); if(chanid < 0) loopv(channels) if(!channels[i].volume) { chanid = i; break; } if(chanid < 0) return -1; - soundchannel &chan = newchannel(chanid, &slot, loc, ent, flags, radius); updatechannel(chan); int playing = -1; - if(fade) - { + if(fade) { Mix_Volume(chanid, chan.volume); playing = expire >= 0 ? Mix_FadeInChannelTimed(chanid, slot.sample->chunk, loops, fade, expire) : Mix_FadeInChannel(chanid, slot.sample->chunk, loops, fade); } @@ -798,28 +658,23 @@ int playsound(int n, const vec *loc, extentity *ent, int flags, int loops, int f return playing; } -void stopsounds() -{ - loopv(channels) if(channels[i].inuse) - { +void stopsounds() { + loopv(channels) if(channels[i].inuse) { Mix_HaltChannel(i); freechannel(i); } } -bool stopsound(int n, int chanid, int fade) -{ +bool stopsound(int n, int chanid, int fade) { if(!gamesounds.configs.inrange(n) || !channels.inrange(chanid) || !channels[chanid].inuse || !gamesounds.playing(channels[chanid], gamesounds.configs[n])) return false; - if(!fade || !Mix_FadeOutChannel(chanid, fade)) - { + if(!fade || !Mix_FadeOutChannel(chanid, fade)) { Mix_HaltChannel(chanid); freechannel(chanid); } return true; } -int playsoundname(const char *s, const vec *loc, int vol, int flags, int loops, int fade, int chanid, int radius, int expire) -{ +int playsoundname(const char *s, const vec *loc, int vol, int flags, int loops, int fade, int chanid, int radius, int expire) { if(!vol) vol = 100; int id = gamesounds.findsound(s, vol); if(id < 0) id = gamesounds.addsound(s, vol); @@ -828,14 +683,11 @@ int playsoundname(const char *s, const vec *loc, int vol, int flags, int loops, ICOMMAND(sound, "i", (int *n), playsound(*n)); -void resetsound() -{ +void resetsound() { clearchanges(CHANGE_SOUND); - if(!nosound) - { + if(!nosound) { cleanupsamples(); - if(music) - { + if(music) { Mix_HaltMusic(); Mix_FreeMusic(music); } @@ -844,21 +696,18 @@ void resetsound() } initsound(); resetchannels(); - if(nosound) - { + if(nosound) { DELETEA(musicfile); DELETEA(musicdonecmd); music = NULL; cleanupsamples(); return; } - if(music && loadmusic(musicfile)) - { + if(music && loadmusic(musicfile)) { Mix_PlayMusic(music, musicdonecmd ? 0 : -1); Mix_VolumeMusic((musicvol*MIX_MAX_VOLUME)/255); } - else - { + else { DELETEA(musicfile); DELETEA(musicdonecmd); } diff --git a/src/engine/textedit.h b/src/engine/textedit.h index 0dcda1d..742fd33 100644 --- a/src/engine/textedit.h +++ b/src/engine/textedit.h @@ -1,31 +1,21 @@ -struct editline -{ +struct editline { enum { CHUNKSIZE = 256 }; - char *text; int len, maxlen; - editline() : text(NULL), len(0), maxlen(0) {} - editline(const char *init) : text(NULL), len(0), maxlen(0) - { + editline(const char *init) : text(NULL), len(0), maxlen(0) { set(init); } - bool empty() { return len <= 0; } - - void clear() - { + void clear() { DELETEA(text); len = maxlen = 0; } - - bool grow(int total, const char *fmt = "", ...) - { + bool grow(int total, const char *fmt = "", ...) { if(total + 1 <= maxlen) return false; maxlen = (total + CHUNKSIZE) - total%CHUNKSIZE; char *newtext = new char[maxlen]; - if(fmt) - { + if(fmt) { va_list args; va_start(args, fmt); vformatstring(newtext, fmt, args, maxlen); @@ -36,69 +26,52 @@ struct editline text = newtext; return true; } - - void set(const char *str, int slen = -1) - { - if(slen < 0) - { + void set(const char *str, int slen = -1) { + if(slen < 0) { slen = strlen(str); if(!grow(slen, "%s", str)) memcpy(text, str, slen + 1); } - else - { + else { grow(slen); memcpy(text, str, slen); text[slen] = '\0'; } len = slen; } - - void prepend(const char *str) - { + void prepend(const char *str) { int slen = strlen(str); - if(!grow(slen + len, "%s%s", str, text ? text : "")) - { + if(!grow(slen + len, "%s%s", str, text ? text : "")) { memmove(&text[slen], text, len + 1); memcpy(text, str, slen + 1); } len += slen; } - - void append(const char *str) - { + void append(const char *str) { int slen = strlen(str); if(!grow(len + slen, "%s%s", text ? text : "", str)) memcpy(&text[len], str, slen + 1); len += slen; } - - bool read(stream *f, int chop = -1) - { + bool read(stream *f, int chop = -1) { if(chop < 0) chop = INT_MAX; else chop++; set(""); - while(len + 1 < chop && f->getline(&text[len], min(maxlen, chop) - len)) - { + while(len + 1 < chop && f->getline(&text[len], min(maxlen, chop) - len)) { len += strlen(&text[len]); - if(len > 0 && text[len-1] == '\n') - { + if(len > 0 && text[len-1] == '\n') { text[--len] = '\0'; return true; } if(len + 1 >= maxlen && len + 1 < chop) grow(len + CHUNKSIZE, "%s", text); } - if(len + 1 >= chop) - { + if(len + 1 >= chop) { char buf[CHUNKSIZE]; - while(f->getline(buf, sizeof(buf))) - { + while(f->getline(buf, sizeof(buf))) { int blen = strlen(buf); if(blen > 0 && buf[blen-1] == '\n') return true; } } return len > 0; } - - void del(int start, int count) - { + void del(int start, int count) { if(!text) return; if(start < 0) { count += start; start = 0; } if(count <= 0 || start >= len) return; @@ -106,16 +79,12 @@ struct editline memmove(&text[start], &text[start+count], len + 1 - (start + count)); len -= count; } - - void chop(int newlen) - { + void chop(int newlen) { if(!text) return; len = clamp(newlen, 0, len); text[len] = '\0'; } - - void insert(char *str, int start, int count = 0) - { + void insert(char *str, int start, int count = 0) { if(count <= 0) count = strlen(str); start = clamp(start, 0, len); grow(len + count, "%s", text ? text : ""); @@ -123,12 +92,9 @@ struct editline memcpy(&text[start], str, count); len += count; } - - void combinelines(vector<editline> &src) - { + void combinelines(vector<editline> &src) { if(src.empty()) set(""); - else loopv(src) - { + else loopv(src) { if(i) append("\n"); if(!i) set(src[i].text, src[i].len); else insert(src[i].text, len, src[i].len); @@ -136,102 +102,77 @@ struct editline } }; -struct editor -{ +struct editor { int mode; //editor mode - 1= keep while focused, 2= keep while used in gui, 3= keep forever (i.e. until mode changes) bool active, rendered; const char *name; const char *filename; - int cx, cy; // cursor position - ensured to be valid after a region() or currentline() int mx, my; // selection mark, mx=-1 if following cursor - avoid direct access, instead use region() int maxx, maxy; // maxy=-1 if unlimited lines, 1 if single line editor - int scrolly; // vertical scroll offset - bool linewrap; int pixelwidth; // required for up/down/hit/draw/bounds int pixelheight; // -1 for variable sized, i.e. from bounds() - vector<editline> lines; // MUST always contain at least one line! - editor(const char *name, int mode, const char *initval) : mode(mode), active(true), rendered(false), name(newstring(name)), filename(NULL), - cx(0), cy(0), mx(-1), maxx(-1), maxy(-1), scrolly(0), linewrap(false), pixelwidth(-1), pixelheight(-1) - { + cx(0), cy(0), mx(-1), maxx(-1), maxy(-1), scrolly(0), linewrap(false), pixelwidth(-1), pixelheight(-1) { //printf("editor %08x '%s'\n", this, name); lines.add().set(initval ? initval : ""); } - - ~editor() - { + ~editor() { //printf("~editor %08x '%s'\n", this, name); DELETEA(name); DELETEA(filename); clear(NULL); } - - void clear(const char *init = "") - { + void clear(const char *init = "") { cx = cy = 0; mark(false); loopv(lines) lines[i].clear(); lines.shrink(0); if(init) lines.add().set(init); } - - void setfile(const char *fname) - { + void setfile(const char *fname) { DELETEA(filename); if(fname) filename = newstring(fname); } - - void load() - { + void load() { if(!filename) return; clear(NULL); stream *file = openutf8file(filename, "r"); - if(file) - { + if(file) { while(lines.add().read(file, maxx) && (maxy < 0 || lines.length() <= maxy)); lines.pop().clear(); delete file; } if(lines.empty()) lines.add().set(""); } - - void save() - { + void save() { if(!filename) return; stream *file = openutf8file(filename, "w"); if(!file) return; loopv(lines) file->putline(lines[i].text); delete file; } - - void mark(bool enable) - { + void mark(bool enable) { mx = (enable) ? cx : -1; my = cy; } - - void selectall() - { + void selectall() { mx = my = INT_MAX; cx = cy = 0; } - // constrain results to within buffer - s=start, e=end, return true if a selection range // also ensures that cy is always within lines[] and cx is valid - bool region(int &sx, int &sy, int &ex, int &ey) - { + bool region(int &sx, int &sy, int &ex, int &ey) { int n = lines.length(); ASSERT(n != 0); if(cy < 0) cy = 0; else if(cy >= n) cy = n-1; int len = lines[cy].len; if(cx < 0) cx = 0; else if(cx > len) cx = len; - if(mx >= 0) - { + if(mx >= 0) { if(my < 0) my = 0; else if(my >= n) my = n-1; len = lines[my].len; if(mx > len) mx = len; @@ -244,34 +185,26 @@ struct editor else if(sy==ey && sx > ex) swap(sx, ex); return (sx != ex) || (sy != ey); } - bool region() { int sx, sy, ex, ey; return region(sx, sy, ex, ey); } - // also ensures that cy is always within lines[] and cx is valid - editline ¤tline() - { + editline ¤tline() { int n = lines.length(); ASSERT(n != 0); if(cy < 0) cy = 0; else if(cy >= n) cy = n-1; if(cx < 0) cx = 0; else if(cx > lines[cy].len) cx = lines[cy].len; return lines[cy]; } - - void copyselectionto(editor *b) - { + void copyselectionto(editor *b) { if(b==this) return; - b->clear(NULL); int sx, sy, ex, ey; region(sx, sy, ex, ey); - loopi(1+ey-sy) - { + loopi(1+ey-sy) { if(b->maxy != -1 && b->lines.length() >= b->maxy) break; int y = sy+i; char *line = lines[y].text; int len = lines[y].len; - if(y == sy && y == ey) - { + if(y == sy && y == ey) { line += sx; len = ex - sx; } @@ -281,15 +214,12 @@ struct editor } if(b->lines.empty()) b->lines.add().set(""); } - - char *tostring() - { + char *tostring() { int len = 0; loopv(lines) len += lines[i].len + 1; char *str = newstring(len); int offset = 0; - loopv(lines) - { + loopv(lines) { editline &l = lines[i]; memcpy(&str[offset], l.text, l.len); offset += l.len; @@ -298,19 +228,15 @@ struct editor str[offset] = '\0'; return str; } - - char *selectiontostring() - { + char *selectiontostring() { vector<char> buf; int sx, sy, ex, ey; region(sx, sy, ex, ey); - loopi(1+ey-sy) - { + loopi(1+ey-sy) { int y = sy+i; char *line = lines[y].text; int len = lines[y].len; - if(y == sy && y == ey) - { + if(y == sy && y == ey) { line += sx; len = ex - sx; } @@ -322,28 +248,21 @@ struct editor buf.add('\0'); return newstring(buf.getbuf(), buf.length()-1); } - - void removelines(int start, int count) - { + void removelines(int start, int count) { loopi(count) lines[start+i].clear(); lines.remove(start, count); } - - bool del() // removes the current selection (if any) - { + bool del() { // removes the current selection (if any) { int sx, sy, ex, ey; - if(!region(sx, sy, ex, ey)) - { + if(!region(sx, sy, ex, ey)) { mark(false); return false; } - if(sy == ey) - { + if(sy == ey) { if(sx == 0 && ex == lines[ey].len) removelines(sy, 1); else lines[sy].del(sx, ex - sx); } - else - { + else { if(ey > sy+1) { removelines(sy+1, ey-(sy+1)); ey = sy+1; } if(ex == lines[ey].len) removelines(ey, 1); else lines[ey].del(0, ex); if(sx == 0) removelines(sy, 1); else lines[sy].del(sx, lines[sy].len - sx); @@ -353,22 +272,17 @@ struct editor cx = sx; cy = sy; editline ¤t = currentline(); - if(cx >= current.len && cy < lines.length() - 1) - { + if(cx >= current.len && cy < lines.length() - 1) { current.append(lines[cy+1].text); removelines(cy + 1, 1); } return true; } - - void insert(char ch) - { + void insert(char ch) { del(); editline ¤t = currentline(); - if(ch == '\n') - { - if(maxy == -1 || cy < maxy-1) - { + if(ch == '\n') { + if(maxy == -1 || cy < maxy-1) { editline newline(¤t.text[cx]); current.chop(cx); cy = min(lines.length(), cy+1); @@ -377,49 +291,36 @@ struct editor else current.chop(cx); cx = 0; } - else - { + else { int len = current.len; if(maxx >= 0 && len > maxx-1) len = maxx-1; if(cx <= len) current.insert(&ch, cx++, 1); } } - - void insert(const char *s) - { + void insert(const char *s) { while(*s) insert(*s++); } - - void insertallfrom(editor *b) - { + void insertallfrom(editor *b) { if(b==this) return; - del(); - - if(b->lines.length() == 1 || maxy == 1) - { + if(b->lines.length() == 1 || maxy == 1) { editline ¤t = currentline(); char *str = b->lines[0].text; int slen = b->lines[0].len; if(maxx >= 0 && b->lines[0].len + cx > maxx) slen = maxx-cx; - if(slen > 0) - { + if(slen > 0) { int len = current.len; if(maxx >= 0 && slen + cx + len > maxx) len = max(0, maxx-(cx+slen)); current.insert(str, cx, slen); cx += slen; } } - else - { - loopv(b->lines) - { - if(!i) - { + else { + loopv(b->lines) { + if(!i) { lines[cy++].append(b->lines[i].text); } - else if(i >= b->lines.length()) - { + else if(i >= b->lines.length()) { cx = b->lines[i].len; lines[cy].prepend(b->lines[i].text); } @@ -427,14 +328,10 @@ struct editor } } } - - void key(int code) - { - switch(code) - { + void key(int code) { + switch(code) { case SDLK_UP: - if(linewrap) - { + if(linewrap) { int x, y; char *str = currentline().text; text_pos(str, cx+1, x, y, pixelwidth); @@ -443,8 +340,7 @@ struct editor cy--; break; case SDLK_DOWN: - if(linewrap) - { + if(linewrap) { int x, y, width, height; char *str = currentline().text; text_pos(str, cx, x, y, pixelwidth); @@ -479,24 +375,22 @@ struct editor cx++; break; case SDLK_DELETE: - if(!del()) - { + if(!del()) { editline ¤t = currentline(); if(cx < current.len) current.del(cx, 1); - else if(cy < lines.length()-1) - { //combine with next line + else if(cy < lines.length()-1) { + //combine with next line current.append(lines[cy+1].text); removelines(cy+1, 1); } } break; case SDLK_BACKSPACE: - if(!del()) - { + if(!del()) { editline ¤t = currentline(); if(cx > 0) current.del(--cx, 1); - else if(cy > 0) - { //combine with previous line + else if(cy > 0) { + //combine with previous line cx = lines[cy-1].len; lines[cy-1].append(current.text); removelines(cy--, 1); @@ -514,24 +408,17 @@ struct editor break; } } - - void input(const char *str, int len) - { + void input(const char *str, int len) { loopi(len) insert(str[i]); } - - void hit(int hitx, int hity, bool dragged) - { + void hit(int hitx, int hity, bool dragged) { int maxwidth = linewrap?pixelwidth:-1; int h = 0; - for(int i = scrolly; i < lines.length(); i++) - { + for(int i = scrolly; i < lines.length(); i++) { int width, height; text_bounds(lines[i].text, width, height, maxwidth); if(h + height > pixelheight) break; - - if(hity >= h && hity <= h+height) - { + if(hity >= h && hity <= h+height) { int x = text_visible(lines[i].text, hitx, hity-h, maxwidth); if(dragged) { mx = x; my = i; } else { cx = x; cy = i; }; break; @@ -539,13 +426,10 @@ struct editor h+=height; } } - - int limitscrolly() - { + int limitscrolly() { int maxwidth = linewrap?pixelwidth:-1; int slines = lines.length(); - for(int ph = pixelheight; slines > 0 && ph > 0;) - { + for(int ph = pixelheight; slines > 0 && ph > 0;) { int width, height; text_bounds(lines[slines-1].text, width, height, maxwidth); if(height > ph) break; @@ -554,39 +438,30 @@ struct editor } return slines; } - - void draw(int x, int y, int color, bool hit) - { + void draw(int x, int y, int color, bool hit) { int maxwidth = linewrap?pixelwidth:-1; - int sx, sy, ex, ey; bool selection = region(sx, sy, ex, ey); - // fix scrolly so that <cx, cy> is always on screen if(cy < scrolly) scrolly = cy; - else - { + else { if(scrolly < 0) scrolly = 0; int h = 0; - for(int i = cy; i >= scrolly; i--) - { + for(int i = cy; i >= scrolly; i--) { int width, height; text_bounds(lines[i].text, width, height, maxwidth); if(h + height > pixelheight) { scrolly = i+1; break; } h += height; } } - - if(selection) - { + if(selection) { // convert from cursor coords into pixel coords int psx, psy, pex, pey; text_pos(lines[sy].text, sx, psx, psy, maxwidth); text_pos(lines[ey].text, ex, pex, pey, maxwidth); int maxy = lines.length(); int h = 0; - for(int i = scrolly; i < maxy; i++) - { + for(int i = scrolly; i < maxy; i++) { int width, height; text_bounds(lines[i].text, width, height, maxwidth); if(h + height > pixelheight) { maxy = i; break; } @@ -595,31 +470,26 @@ struct editor h += height; } maxy--; - - if(ey >= scrolly && sy <= maxy) - { + if(ey >= scrolly && sy <= maxy) { // crop top/bottom within window if(sy < scrolly) { sy = scrolly; psy = 0; psx = 0; } if(ey > maxy) { ey = maxy; pey = pixelheight - FONTH; pex = pixelwidth; } - hudnotextureshader->set(); gle::colorub(0xA0, 0x80, 0x80); gle::defvertex(2); gle::begin(GL_QUADS); - if(psy == pey) - { + if(psy == pey) { gle::attribf(x+psx, y+psy); gle::attribf(x+pex, y+psy); gle::attribf(x+pex, y+pey+FONTH); gle::attribf(x+psx, y+pey+FONTH); } - else - { gle::attribf(x+psx, y+psy); + else { + gle::attribf(x+psx, y+psy); gle::attribf(x+psx, y+psy+FONTH); gle::attribf(x+pixelwidth, y+psy+FONTH); gle::attribf(x+pixelwidth, y+psy); - if(pey-psy > FONTH) - { + if(pey-psy > FONTH) { gle::attribf(x, y+psy+FONTH); gle::attribf(x+pixelwidth, y+psy+FONTH); gle::attribf(x+pixelwidth, y+pey); @@ -634,17 +504,13 @@ struct editor hudshader->set(); } } - int h = 0; - for(int i = scrolly; i < lines.length(); i++) - { + for(int i = scrolly; i < lines.length(); i++) { int width, height; text_bounds(lines[i].text, width, height, maxwidth); if(h + height > pixelheight) break; - draw_text(lines[i].text, x, y+h, color>>16, (color>>8)&0xFF, color&0xFF, 0xFF, hit&&(cy==i)?cx:-1, maxwidth); - if(linewrap && height > FONTH) // line wrap indicator - { + if(linewrap && height > FONTH) { // line wrap indicator { hudnotextureshader->set(); gle::colorub(0x80, 0xA0, 0x80); gle::defvertex(2); @@ -666,24 +532,19 @@ static vector <editor*> editors; static editor *currentfocus() { return editors.length() ? editors.last() : NULL; } -static void readyeditors() -{ +static void readyeditors() { loopv(editors) editors[i]->active = (editors[i]->mode==EDITORFOREVER); } -static void flusheditors() -{ - loopvrev(editors) if(!editors[i]->active) - { +static void flusheditors() { + loopvrev(editors) if(!editors[i]->active) { editor *e = editors.remove(i); DELETEP(e); } } -static editor *useeditor(const char *name, int mode, bool focus, const char *initval = NULL) -{ - loopv(editors) if(strcmp(editors[i]->name, name) == 0) - { +static editor *useeditor(const char *name, int mode, bool focus, const char *initval = NULL) { + loopv(editors) if(strcmp(editors[i]->name, name) == 0) { editor *e = editors[i]; if(focus) { editors.add(e); editors.remove(i); } // re-position as last e->active = true; @@ -703,8 +564,7 @@ static editor *useeditor(const char *name, int mode, bool focus, const char *ini ICOMMAND(textlist, "", (), // @DEBUG return list of all the editors vector<char> s; - loopv(editors) - { + loopv(editors) { if(i > 0) s.put(", ", 2); s.put(editors[i]->name, strlen(editors[i]->name)); } @@ -731,19 +591,16 @@ TEXTCOMMAND(textsave, "s", (char *file), // saves the topmost (filename is opti top->save(); ); TEXTCOMMAND(textload, "s", (char *file), // loads into the topmost editor, returns filename if no args - if(*file) - { + if(*file) { top->setfile(path(file, true)); top->load(); } else if(top->filename) result(top->filename); ); -TEXTCOMMAND(textinit, "sss", (char *name, char *file, char *initval), // loads into named editor if no file assigned and editor has been rendered -{ +TEXTCOMMAND(textinit, "sss", (char *name, char *file, char *initval), { // loads into named editor if no file assigned and editor has been rendered { editor *e = NULL; loopv(editors) if(!strcmp(editors[i]->name, name)) { e = editors[i]; break; } - if(e && e->rendered && !e->filename && *file && (e->lines.empty() || (e->lines.length() == 1 && !strcmp(e->lines[0].text, initval)))) - { + if(e && e->rendered && !e->filename && *file && (e->lines.empty() || (e->lines.length() == 1 && !strcmp(e->lines[0].text, initval)))) { e->setfile(path(file, true)); e->load(); } diff --git a/src/engine/texture.cpp b/src/engine/texture.cpp index 7f391a9..0f7a5df 100644 --- a/src/engine/texture.cpp +++ b/src/engine/texture.cpp @@ -8,33 +8,26 @@ (SDL_VERSIONNUM(SDL_IMAGE_MAJOR_VERSION, SDL_IMAGE_MINOR_VERSION, SDL_IMAGE_PATCHLEVEL) >= SDL_VERSIONNUM(X, Y, Z)) #endif -template<int BPP> static void halvetexture(uchar * RESTRICT src, uint sw, uint sh, uint stride, uchar * RESTRICT dst) -{ - for(uchar *yend = &src[sh*stride]; src < yend;) - { - for(uchar *xend = &src[sw*BPP], *xsrc = src; xsrc < xend; xsrc += 2*BPP, dst += BPP) - { +template<int BPP> static void halvetexture(uchar * RESTRICT src, uint sw, uint sh, uint stride, uchar * RESTRICT dst) { + for(uchar *yend = &src[sh*stride]; src < yend;) { + for(uchar *xend = &src[sw*BPP], *xsrc = src; xsrc < xend; xsrc += 2*BPP, dst += BPP) { loopi(BPP) dst[i] = (uint(xsrc[i]) + uint(xsrc[i+BPP]) + uint(xsrc[stride+i]) + uint(xsrc[stride+i+BPP]))>>2; } src += 2*stride; } } -template<int BPP> static void shifttexture(uchar * RESTRICT src, uint sw, uint sh, uint stride, uchar * RESTRICT dst, uint dw, uint dh) -{ +template<int BPP> static void shifttexture(uchar * RESTRICT src, uint sw, uint sh, uint stride, uchar * RESTRICT dst, uint dw, uint dh) { uint wfrac = sw/dw, hfrac = sh/dh, wshift = 0, hshift = 0; while(dw<<wshift < sw) wshift++; while(dh<<hshift < sh) hshift++; uint tshift = wshift + hshift; - for(uchar *yend = &src[sh*stride]; src < yend;) - { - for(uchar *xend = &src[sw*BPP], *xsrc = src; xsrc < xend; xsrc += wfrac*BPP, dst += BPP) - { + for(uchar *yend = &src[sh*stride]; src < yend;) { + for(uchar *xend = &src[sw*BPP], *xsrc = src; xsrc < xend; xsrc += wfrac*BPP, dst += BPP) { uint t[BPP] = {0}; for(uchar *ycur = xsrc, *xend = &ycur[wfrac*BPP], *yend = &src[hfrac*stride]; ycur < yend; - ycur += stride, xend += stride) - { + ycur += stride, xend += stride) { for(uchar *xcur = ycur; xcur < xend; xcur += BPP) loopi(BPP) t[i] += xcur[i]; } @@ -44,8 +37,7 @@ template<int BPP> static void shifttexture(uchar * RESTRICT src, uint sw, uint s } } -template<int BPP> static void scaletexture(uchar * RESTRICT src, uint sw, uint sh, uint stride, uchar * RESTRICT dst, uint dw, uint dh) -{ +template<int BPP> static void scaletexture(uchar * RESTRICT src, uint sw, uint sh, uint stride, uchar * RESTRICT dst, uint dw, uint dh) { uint wfrac = (sw<<12)/dw, hfrac = (sh<<12)/dh, darea = dw*dh, sarea = sw*sh; int over, under; for(over = 0; (darea>>over) > sarea; over++); @@ -56,24 +48,20 @@ template<int BPP> static void scaletexture(uchar * RESTRICT src, uint sw, uint s area = ((ullong)darea<<ascale)/sarea; dw *= wfrac; dh *= hfrac; - for(uint y = 0; y < dh; y += hfrac) - { + for(uint y = 0; y < dh; y += hfrac) { const uint yn = y + hfrac - 1, yi = y>>12, h = (yn>>12) - yi, ylow = ((yn|(-int(h)>>24))&0xFFFU) + 1 - (y&0xFFFU), yhigh = (yn&0xFFFU) + 1; const uchar *ysrc = &src[yi*stride]; - for(uint x = 0; x < dw; x += wfrac, dst += BPP) - { + for(uint x = 0; x < dw; x += wfrac, dst += BPP) { const uint xn = x + wfrac - 1, xi = x>>12, w = (xn>>12) - xi, xlow = ((w+0xFFFU)&0x1000U) - (x&0xFFFU), xhigh = (xn&0xFFFU) + 1; const uchar *xsrc = &ysrc[xi*BPP], *xend = &xsrc[w*BPP]; uint t[BPP] = {0}; for(const uchar *xcur = &xsrc[BPP]; xcur < xend; xcur += BPP) loopi(BPP) t[i] += xcur[i]; loopi(BPP) t[i] = (ylow*(t[i] + ((xsrc[i]*xlow + xend[i]*xhigh)>>12)))>>cscale; - if(h) - { + if(h) { xsrc += stride; xend += stride; - for(uint hcur = h; --hcur; xsrc += stride, xend += stride) - { + for(uint hcur = h; --hcur; xsrc += stride, xend += stride) { uint c[BPP] = {0}; for(const uchar *xcur = &xsrc[BPP]; xcur < xend; xcur += BPP) loopi(BPP) c[i] += xcur[i]; @@ -89,32 +77,25 @@ template<int BPP> static void scaletexture(uchar * RESTRICT src, uint sw, uint s } } -static void scaletexture(uchar * RESTRICT src, uint sw, uint sh, uint bpp, uint pitch, uchar * RESTRICT dst, uint dw, uint dh) -{ - if(sw == dw*2 && sh == dh*2) - { - switch(bpp) - { +static void scaletexture(uchar * RESTRICT src, uint sw, uint sh, uint bpp, uint pitch, uchar * RESTRICT dst, uint dw, uint dh) { + if(sw == dw*2 && sh == dh*2) { + switch(bpp) { case 1: return halvetexture<1>(src, sw, sh, pitch, dst); case 2: return halvetexture<2>(src, sw, sh, pitch, dst); case 3: return halvetexture<3>(src, sw, sh, pitch, dst); case 4: return halvetexture<4>(src, sw, sh, pitch, dst); } } - else if(sw < dw || sh < dh || sw&(sw-1) || sh&(sh-1) || dw&(dw-1) || dh&(dh-1)) - { - switch(bpp) - { + else if(sw < dw || sh < dh || sw&(sw-1) || sh&(sh-1) || dw&(dw-1) || dh&(dh-1)) { + switch(bpp) { case 1: return scaletexture<1>(src, sw, sh, pitch, dst, dw, dh); case 2: return scaletexture<2>(src, sw, sh, pitch, dst, dw, dh); case 3: return scaletexture<3>(src, sw, sh, pitch, dst, dw, dh); case 4: return scaletexture<4>(src, sw, sh, pitch, dst, dw, dh); } } - else - { - switch(bpp) - { + else { + switch(bpp) { case 1: return shifttexture<1>(src, sw, sh, pitch, dst, dw, dh); case 2: return shifttexture<2>(src, sw, sh, pitch, dst, dw, dh); case 3: return shifttexture<3>(src, sw, sh, pitch, dst, dw, dh); @@ -123,17 +104,14 @@ static void scaletexture(uchar * RESTRICT src, uint sw, uint sh, uint bpp, uint } } -static void reorientnormals(uchar * RESTRICT src, int sw, int sh, int bpp, int stride, uchar * RESTRICT dst, bool flipx, bool flipy, bool swapxy) -{ +static void reorientnormals(uchar * RESTRICT src, int sw, int sh, int bpp, int stride, uchar * RESTRICT dst, bool flipx, bool flipy, bool swapxy) { int stridex = bpp, stridey = bpp; if(swapxy) stridex *= sh; else stridey *= sw; if(flipx) { dst += (sw-1)*stridex; stridex = -stridex; } if(flipy) { dst += (sh-1)*stridey; stridey = -stridey; } uchar *srcrow = src; - loopi(sh) - { - for(uchar *curdst = dst, *src = srcrow, *end = &srcrow[sw*bpp]; src < end;) - { + loopi(sh) { + for(uchar *curdst = dst, *src = srcrow, *end = &srcrow[sw*bpp]; src < end;) { uchar nx = *src++, ny = *src++; if(flipx) nx = 255-nx; if(flipy) ny = 255-ny; @@ -150,17 +128,14 @@ static void reorientnormals(uchar * RESTRICT src, int sw, int sh, int bpp, int s } template<int BPP> -static inline void reorienttexture(uchar * RESTRICT src, int sw, int sh, int stride, uchar * RESTRICT dst, bool flipx, bool flipy, bool swapxy) -{ +static inline void reorienttexture(uchar * RESTRICT src, int sw, int sh, int stride, uchar * RESTRICT dst, bool flipx, bool flipy, bool swapxy) { int stridex = BPP, stridey = BPP; if(swapxy) stridex *= sh; else stridey *= sw; if(flipx) { dst += (sw-1)*stridex; stridex = -stridex; } if(flipy) { dst += (sh-1)*stridey; stridey = -stridey; } uchar *srcrow = src; - loopi(sh) - { - for(uchar *curdst = dst, *src = srcrow, *end = &srcrow[sw*BPP]; src < end;) - { + loopi(sh) { + for(uchar *curdst = dst, *src = srcrow, *end = &srcrow[sw*BPP]; src < end;) { loopk(BPP) curdst[k] = *src++; curdst += stridex; } @@ -169,10 +144,8 @@ static inline void reorienttexture(uchar * RESTRICT src, int sw, int sh, int str } } -static void reorienttexture(uchar * RESTRICT src, int sw, int sh, int bpp, int stride, uchar * RESTRICT dst, bool flipx, bool flipy, bool swapxy) -{ - switch(bpp) - { +static void reorienttexture(uchar * RESTRICT src, int sw, int sh, int bpp, int stride, uchar * RESTRICT dst, bool flipx, bool flipy, bool swapxy) { + switch(bpp) { case 1: return reorienttexture<1>(src, sw, sh, stride, dst, flipx, flipy, swapxy); case 2: return reorienttexture<2>(src, sw, sh, stride, dst, flipx, flipy, swapxy); case 3: return reorienttexture<3>(src, sw, sh, stride, dst, flipx, flipy, swapxy); @@ -180,23 +153,18 @@ static void reorienttexture(uchar * RESTRICT src, int sw, int sh, int bpp, int s } } -static void reorients3tc(GLenum format, int blocksize, int w, int h, uchar *src, uchar *dst, bool flipx, bool flipy, bool swapxy, bool normals = false) -{ +static void reorients3tc(GLenum format, int blocksize, int w, int h, uchar *src, uchar *dst, bool flipx, bool flipy, bool swapxy, bool normals = false) { int bx1 = 0, by1 = 0, bx2 = min(w, 4), by2 = min(h, 4), bw = (w+3)/4, bh = (h+3)/4, stridex = blocksize, stridey = blocksize; if(swapxy) stridex *= bw; else stridey *= bh; if(flipx) { dst += (bw-1)*stridex; stridex = -stridex; bx1 += 4-bx2; bx2 = 4; } if(flipy) { dst += (bh-1)*stridey; stridey = -stridey; by1 += 4-by2; by2 = 4; } - loopi(bh) - { - for(uchar *curdst = dst, *end = &src[bw*blocksize]; src < end; src += blocksize, curdst += stridex) - { - if(format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) - { + loopi(bh) { + for(uchar *curdst = dst, *end = &src[bw*blocksize]; src < end; src += blocksize, curdst += stridex) { + if(format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) { ullong salpha = lilswap(*(const ullong *)src), dalpha = 0; uint xmask = flipx ? 15 : 0, ymask = flipy ? 15 : 0, xshift = 2, yshift = 4; if(swapxy) swap(xshift, yshift); - for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) - { + for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) { dalpha |= ((salpha&15) << (((xmask^x)<<xshift) + ((ymask^y)<<yshift))); salpha >>= 4; } @@ -204,14 +172,12 @@ static void reorients3tc(GLenum format, int blocksize, int w, int h, uchar *src, src += 8; curdst += 8; } - else if(format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) - { + else if(format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) { uchar alpha1 = src[0], alpha2 = src[1]; ullong salpha = lilswap(*(const ushort *)&src[2]) + ((ullong)lilswap(*(const uint *)&src[4]) << 16), dalpha = 0; uint xmask = flipx ? 7 : 0, ymask = flipy ? 7 : 0, xshift = 0, yshift = 2; if(swapxy) swap(xshift, yshift); - for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) - { + for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) { dalpha |= ((salpha&7) << (3*((xmask^x)<<xshift) + ((ymask^y)<<yshift))); salpha >>= 3; } @@ -223,24 +189,19 @@ static void reorients3tc(GLenum format, int blocksize, int w, int h, uchar *src, src += 8; curdst += 8; } - ushort color1 = lilswap(*(const ushort *)src), color2 = lilswap(*(const ushort *)&src[2]); uint sbits = lilswap(*(const uint *)&src[4]); - if(normals) - { + if(normals) { ushort ncolor1 = color1, ncolor2 = color2; - if(flipx) - { + if(flipx) { ncolor1 = (ncolor1 & ~0xF800) | (0xF800 - (ncolor1 & 0xF800)); ncolor2 = (ncolor2 & ~0xF800) | (0xF800 - (ncolor2 & 0xF800)); } - if(flipy) - { + if(flipy) { ncolor1 = (ncolor1 & ~0x7E0) | (0x7E0 - (ncolor1 & 0x7E0)); ncolor2 = (ncolor2 & ~0x7E0) | (0x7E0 - (ncolor2 & 0x7E0)); } - if(swapxy) - { + if(swapxy) { ncolor1 = (ncolor1 & 0x1F) | (((((ncolor1 >> 11) & 0x1F) * 0x3F) / 0x1F) << 5) | (((((ncolor1 >> 5) & 0x3F) * 0x1F) / 0x3F) << 11); ncolor2 = (ncolor2 & 0x1F) | (((((ncolor2 >> 11) & 0x1F) * 0x3F) / 0x1F) << 5) | (((((ncolor2 >> 5) & 0x3F) * 0x1F) / 0x3F) << 11); } @@ -249,40 +210,33 @@ static void reorients3tc(GLenum format, int blocksize, int w, int h, uchar *src, } uint dbits = 0, xmask = flipx ? 3 : 0, ymask = flipy ? 3 : 0, xshift = 1, yshift = 3; if(swapxy) swap(xshift, yshift); - for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) - { + for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) { dbits |= ((sbits&3) << (((xmask^x)<<xshift) + ((ymask^y)<<yshift))); sbits >>= 2; } *(ushort *)curdst = lilswap(color1); *(ushort *)&curdst[2] = lilswap(color2); *(uint *)&curdst[4] = lilswap(dbits); - if(blocksize > 8) { src -= 8; curdst -= 8; } } dst += stridey; } } -static void reorientrgtc(GLenum format, int blocksize, int w, int h, uchar *src, uchar *dst, bool flipx, bool flipy, bool swapxy) -{ +static void reorientrgtc(GLenum format, int blocksize, int w, int h, uchar *src, uchar *dst, bool flipx, bool flipy, bool swapxy) { int bx1 = 0, by1 = 0, bx2 = min(w, 4), by2 = min(h, 4), bw = (w+3)/4, bh = (h+3)/4, stridex = blocksize, stridey = blocksize; if(swapxy) stridex *= bw; else stridey *= bh; if(flipx) { dst += (bw-1)*stridex; stridex = -stridex; bx1 += 4-bx2; bx2 = 4; } if(flipy) { dst += (bh-1)*stridey; stridey = -stridey; by1 += 4-by2; by2 = 4; } stridex -= blocksize; - loopi(bh) - { - for(uchar *curdst = dst, *end = &src[bw*blocksize]; src < end; curdst += stridex) - { - loopj(blocksize/8) - { + loopi(bh) { + for(uchar *curdst = dst, *end = &src[bw*blocksize]; src < end; curdst += stridex) { + loopj(blocksize/8) { uchar val1 = src[0], val2 = src[1]; ullong sval = lilswap(*(const ushort *)&src[2]) + ((ullong)lilswap(*(const uint *)&src[4] )<< 16), dval = 0; uint xmask = flipx ? 7 : 0, ymask = flipy ? 7 : 0, xshift = 0, yshift = 2; if(swapxy) swap(xshift, yshift); - for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) - { + for(int y = by1; y < by2; y++) for(int x = bx1; x < bx2; x++) { dval |= ((sval&7) << (3*((xmask^x)<<xshift) + ((ymask^y)<<yshift))); sval >>= 3; } @@ -299,26 +253,26 @@ static void reorientrgtc(GLenum format, int blocksize, int w, int h, uchar *src, } } -#define writetex(t, body) do \ - { \ +#define writetex(t, body) do { \ + \ uchar *dstrow = t.data; \ - loop(y, t.h) \ - { \ - for(uchar *dst = dstrow, *end = &dstrow[t.w*t.bpp]; dst < end; dst += t.bpp) \ - { \ + loop(y, t.h) { \ + \ + for(uchar *dst = dstrow, *end = &dstrow[t.w*t.bpp]; dst < end; dst += t.bpp) { \ + \ body; \ } \ dstrow += t.pitch; \ } \ } while(0) -#define readwritetex(t, s, body) do \ - { \ +#define readwritetex(t, s, body) do { \ + \ uchar *dstrow = t.data, *srcrow = s.data; \ - loop(y, t.h) \ - { \ - for(uchar *dst = dstrow, *src = srcrow, *end = &srcrow[s.w*s.bpp]; src < end; dst += t.bpp, src += s.bpp) \ - { \ + loop(y, t.h) { \ + \ + for(uchar *dst = dstrow, *src = srcrow, *end = &srcrow[s.w*s.bpp]; src < end; dst += t.bpp, src += s.bpp) { \ + \ body; \ } \ dstrow += t.pitch; \ @@ -326,13 +280,13 @@ static void reorientrgtc(GLenum format, int blocksize, int w, int h, uchar *src, } \ } while(0) -#define read2writetex(t, s1, src1, s2, src2, body) do \ - { \ +#define read2writetex(t, s1, src1, s2, src2, body) do { \ + \ uchar *dstrow = t.data, *src1row = s1.data, *src2row = s2.data; \ - loop(y, t.h) \ - { \ - for(uchar *dst = dstrow, *end = &dstrow[t.w*t.bpp], *src1 = src1row, *src2 = src2row; dst < end; dst += t.bpp, src1 += s1.bpp, src2 += s2.bpp) \ - { \ + loop(y, t.h) { \ + \ + for(uchar *dst = dstrow, *end = &dstrow[t.w*t.bpp], *src1 = src1row, *src2 = src2row; dst < end; dst += t.bpp, src1 += s1.bpp, src2 += s2.bpp) { \ + \ body; \ } \ dstrow += t.pitch; \ @@ -341,30 +295,29 @@ static void reorientrgtc(GLenum format, int blocksize, int w, int h, uchar *src, } \ } while(0) -#define readwritergbtex(t, s, body) \ - { \ +#define readwritergbtex(t, s, body) { \ + \ if(t.bpp >= 3) readwritetex(t, s, body); \ - else \ - { \ + else { \ + \ ImageData rgb(t.w, t.h, 3); \ read2writetex(rgb, t, orig, s, src, { dst[0] = dst[1] = dst[2] = orig[0]; body; }); \ t.replace(rgb); \ } \ } -void forcergbimage(ImageData &s) -{ +void forcergbimage(ImageData &s) { if(s.bpp >= 3) return; ImageData d(s.w, s.h, 3); readwritetex(d, s, { dst[0] = dst[1] = dst[2] = src[0]; }); s.replace(d); } -#define readwritergbatex(t, s, body) \ - { \ +#define readwritergbatex(t, s, body) { \ + \ if(t.bpp >= 4) { readwritetex(t, s, body); } \ - else \ - { \ + else { \ + \ ImageData rgba(t.w, t.h, 4); \ if(t.bpp==3) read2writetex(rgba, t, orig, s, src, { dst[0] = orig[0]; dst[1] = orig[1]; dst[2] = orig[2]; body; }); \ else read2writetex(rgba, t, orig, s, src, { dst[0] = dst[1] = dst[2] = orig[0]; body; }); \ @@ -372,8 +325,7 @@ void forcergbimage(ImageData &s) } \ } -void forcergbaimage(ImageData &s) -{ +void forcergbaimage(ImageData &s) { if(s.bpp >= 4) return; ImageData d(s.w, s.h, 4); if(s.bpp==3) readwritetex(d, s, { dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; }); @@ -381,38 +333,31 @@ void forcergbaimage(ImageData &s) s.replace(d); } -void swizzleimage(ImageData &s) -{ - if(s.bpp==2) - { +void swizzleimage(ImageData &s) { + if(s.bpp==2) { ImageData d(s.w, s.h, 4); readwritetex(d, s, { dst[0] = dst[1] = dst[2] = src[0]; dst[3] = src[1]; }); s.replace(d); } - else if(s.bpp==1) - { + else if(s.bpp==1) { ImageData d(s.w, s.h, 3); readwritetex(d, s, { dst[0] = dst[1] = dst[2] = src[0]; }); s.replace(d); } } -void texreorient(ImageData &s, bool flipx, bool flipy, bool swapxy, int type = TEX_DIFFUSE) -{ +void texreorient(ImageData &s, bool flipx, bool flipy, bool swapxy, int type = TEX_DIFFUSE) { ImageData d(swapxy ? s.h : s.w, swapxy ? s.w : s.h, s.bpp, s.levels, s.align, s.compressed); - switch(s.compressed) - { + switch(s.compressed) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: [[fallthrough]]; case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: [[fallthrough]]; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: [[fallthrough]]; - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - { + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: { uchar *dst = d.data, *src = s.data; - loopi(s.levels) - { + loopi(s.levels) { reorients3tc(s.compressed, s.bpp, max(s.w>>i, 1), max(s.h>>i, 1), src, dst, flipx, flipy, swapxy, type==TEX_NORMAL); src += s.calclevelsize(i); dst += d.calclevelsize(i); @@ -425,11 +370,9 @@ void texreorient(ImageData &s, bool flipx, bool flipy, bool swapxy, int type = T [[fallthrough]]; case GL_COMPRESSED_LUMINANCE_LATC1_EXT: [[fallthrough]]; - case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: - { + case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: { uchar *dst = d.data, *src = s.data; - loopi(s.levels) - { + loopi(s.levels) { reorientrgtc(s.compressed, s.bpp, max(s.w>>i, 1), max(s.h>>i, 1), src, dst, flipx, flipy, swapxy); src += s.calclevelsize(i); dst += d.calclevelsize(i); @@ -444,29 +387,25 @@ void texreorient(ImageData &s, bool flipx, bool flipy, bool swapxy, int type = T s.replace(d); } -extern const texrotation texrotations[8] = -{ - { false, false, false }, // 0: default - { false, true, true }, // 1: 90 degrees - { true, true, false }, // 2: 180 degrees - { true, false, true }, // 3: 270 degrees - { true, false, false }, // 4: flip X - { false, true, false }, // 5: flip Y - { false, false, true }, // 6: transpose +extern const texrotation texrotations[8] = { + { false, false, false }, // 0: default { + { false, true, true }, // 1: 90 degrees { + { true, true, false }, // 2: 180 degrees { + { true, false, true }, // 3: 270 degrees { + { true, false, false }, // 4: flip X { + { false, true, false }, // 5: flip Y { + { false, false, true }, // 6: transpose { { true, true, true }, // 7: flipped transpose }; -void texrotate(ImageData &s, int numrots, int type = TEX_DIFFUSE) -{ - if(numrots>=1 && numrots<=7) - { +void texrotate(ImageData &s, int numrots, int type = TEX_DIFFUSE) { + if(numrots>=1 && numrots<=7) { const texrotation &r = texrotations[numrots]; texreorient(s, r.flipx, r.flipy, r.swapxy, type); } } -void texoffset(ImageData &s, int xoffset, int yoffset) -{ +void texoffset(ImageData &s, int xoffset, int yoffset) { xoffset = max(xoffset, 0); xoffset %= s.w; yoffset = max(yoffset, 0); @@ -474,8 +413,7 @@ void texoffset(ImageData &s, int xoffset, int yoffset) if(!xoffset && !yoffset) return; ImageData d(s.w, s.h, s.bpp); uchar *src = s.data; - loop(y, s.h) - { + loop(y, s.h) { uchar *dst = (uchar *)d.data+((y+yoffset)%d.h)*d.pitch; memcpy(dst+xoffset*s.bpp, src, (s.w-xoffset)*s.bpp); memcpy(dst, src+(s.w-xoffset)*s.bpp, xoffset*s.bpp); @@ -484,8 +422,7 @@ void texoffset(ImageData &s, int xoffset, int yoffset) s.replace(d); } -void texmad(ImageData &s, const vec &mul, const vec &add) -{ +void texmad(ImageData &s, const vec &mul, const vec &add) { if(s.bpp < 3 && (mul.x != mul.y || mul.y != mul.z || add.x != add.y || add.y != add.z)) swizzleimage(s); int maxk = min(int(s.bpp), 3); @@ -494,8 +431,7 @@ void texmad(ImageData &s, const vec &mul, const vec &add) ); } -void texcolorify(ImageData &s, const vec &color, vec weights) -{ +void texcolorify(ImageData &s, const vec &color, vec weights) { if(s.bpp < 3) return; if(weights.iszero()) weights = vec(0.21f, 0.72f, 0.07f); writetex(s, @@ -504,8 +440,7 @@ void texcolorify(ImageData &s, const vec &color, vec weights) ); } -void texcolormask(ImageData &s, const vec &color1, const vec &color2) -{ +void texcolormask(ImageData &s, const vec &color1, const vec &color2) { if(s.bpp < 4) return; ImageData d(s.w, s.h, 3); readwritetex(d, s, @@ -516,20 +451,17 @@ void texcolormask(ImageData &s, const vec &color1, const vec &color2) s.replace(d); } -void texdup(ImageData &s, int srcchan, int dstchan) -{ +void texdup(ImageData &s, int srcchan, int dstchan) { if(srcchan==dstchan || max(srcchan, dstchan) >= s.bpp) return; writetex(s, dst[dstchan] = dst[srcchan]); } -void texmix(ImageData &s, int c1, int c2, int c3, int c4) -{ +void texmix(ImageData &s, int c1, int c2, int c3, int c4) { int numchans = c1 < 0 ? 0 : (c2 < 0 ? 1 : (c3 < 0 ? 2 : (c4 < 0 ? 3 : 4))); if(numchans <= 0) return; ImageData d(s.w, s.h, numchans); readwritetex(d, s, - switch(numchans) - { + switch(numchans) { case 4: dst[3] = src[c4]; [[fallthrough]]; case 3: dst[2] = src[c3]; @@ -543,28 +475,23 @@ void texmix(ImageData &s, int c1, int c2, int c3, int c4) s.replace(d); } -void texgrey(ImageData &s) -{ +void texgrey(ImageData &s) { if(s.bpp <= 2) return; ImageData d(s.w, s.h, s.bpp >= 4 ? 2 : 1); - if(s.bpp >= 4) - { + if(s.bpp >= 4) { readwritetex(d, s, dst[0] = src[0]; dst[1] = src[3]; ); } - else - { + else { readwritetex(d, s, dst[0] = src[0]); } s.replace(d); } -void texpremul(ImageData &s) -{ - switch(s.bpp) - { +void texpremul(ImageData &s) { + switch(s.bpp) { case 2: writetex(s, dst[0] = uchar((uint(dst[0])*uint(dst[1]))/255); @@ -581,30 +508,25 @@ void texpremul(ImageData &s) } } -void texagrad(ImageData &s, float x2, float y2, float x1, float y1) -{ +void texagrad(ImageData &s, float x2, float y2, float x1, float y1) { if(s.bpp != 2 && s.bpp != 4) return; y1 = 1 - y1; y2 = 1 - y2; float minx = 1, miny = 1, maxx = 1, maxy = 1; - if(x1 != x2) - { + if(x1 != x2) { minx = (0 - x1) / (x2 - x1); maxx = (1 - x1) / (x2 - x1); } - if(y1 != y2) - { + if(y1 != y2) { miny = (0 - y1) / (y2 - y1); maxy = (1 - y1) / (y2 - y1); } float dx = (maxx - minx)/max(s.w-1, 1), dy = (maxy - miny)/max(s.h-1, 1), cury = miny; - for(uchar *dstrow = s.data + s.bpp - 1, *endrow = dstrow + s.h*s.pitch; dstrow < endrow; dstrow += s.pitch) - { + for(uchar *dstrow = s.data + s.bpp - 1, *endrow = dstrow + s.h*s.pitch; dstrow < endrow; dstrow += s.pitch) { float curx = minx; - for(uchar *dst = dstrow, *end = &dstrow[s.w*s.bpp]; dst < end; dst += s.bpp) - { + for(uchar *dst = dstrow, *end = &dstrow[s.w*s.bpp]; dst < end; dst += s.bpp) { dst[0] = uchar(dst[0]*clamp(curx, 0.0f, 1.0f)*clamp(cury, 0.0f, 1.0f)); curx += dx; } @@ -626,23 +548,18 @@ VARFP(aniso, 0, 0, 16, initwarning("texture filtering", INIT_LOAD)); extern int usetexcompress; -void setuptexcompress() -{ +void setuptexcompress() { if(!usetexcompress) return; - GLenum hint = GL_DONT_CARE; - switch(texcompressquality) - { + switch(texcompressquality) { case 1: hint = GL_NICEST; break; case 0: hint = GL_FASTEST; break; } glHint(GL_TEXTURE_COMPRESSION_HINT, hint); } -GLenum compressedformat(GLenum format, int w, int h, int force = 0) -{ - if(usetexcompress && texcompress && force >= 0 && (force || max(w, h) >= texcompress)) switch(format) - { +GLenum compressedformat(GLenum format, int w, int h, int force = 0) { + if(usetexcompress && texcompress && force >= 0 && (force || max(w, h) >= texcompress)) switch(format) { case GL_RGB5: case GL_RGB8: case GL_RGB: return usetexcompress > 1 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGB; @@ -660,10 +577,8 @@ GLenum compressedformat(GLenum format, int w, int h, int force = 0) return format; } -GLenum uncompressedformat(GLenum format) -{ - switch(format) - { +GLenum uncompressedformat(GLenum format) { + switch(format) { case GL_COMPRESSED_ALPHA: return GL_ALPHA; case GL_COMPRESSED_LUMINANCE: @@ -690,10 +605,8 @@ GLenum uncompressedformat(GLenum format) return GL_FALSE; } -int formatsize(GLenum format) -{ - switch(format) - { +int formatsize(GLenum format) { + switch(format) { case GL_RED: case GL_LUMINANCE: case GL_ALPHA: return 1; @@ -707,61 +620,51 @@ int formatsize(GLenum format) VARFP(usenp2, 0, 0, 1, initwarning("texture quality", INIT_LOAD)); -void resizetexture(int w, int h, bool mipmap, bool canreduce, GLenum target, int compress, int &tw, int &th) -{ +void resizetexture(int w, int h, bool mipmap, bool canreduce, GLenum target, int compress, int &tw, int &th) { int hwlimit = target==GL_TEXTURE_CUBE_MAP ? hwcubetexsize : hwtexsize, sizelimit = mipmap && maxtexsize ? min(maxtexsize, hwlimit) : hwlimit; - if(compress > 0 && !usetexcompress) - { + if(compress > 0 && !usetexcompress) { w = max(w/compress, 1); h = max(h/compress, 1); } - if(canreduce && texreduce) - { + if(canreduce && texreduce) { w = max(w>>texreduce, 1); h = max(h>>texreduce, 1); } w = min(w, sizelimit); h = min(h, sizelimit); - if(!usenp2 && (w&(w-1) || h&(h-1))) - { + if(!usenp2 && (w&(w-1) || h&(h-1))) { tw = th = 1; while(tw < w) tw *= 2; while(th < h) th *= 2; if(w < tw - tw/4) tw /= 2; if(h < th - th/4) th /= 2; } - else - { + else { tw = w; th = h; } } -void uploadtexture(int tnum, GLenum target, GLenum internal, int tw, int th, GLenum format, GLenum type, void *pixels, int pw, int ph, int pitch, bool mipmap) -{ +void uploadtexture(int tnum, GLenum target, GLenum internal, int tw, int th, GLenum format, GLenum type, void *pixels, int pw, int ph, int pitch, bool mipmap) { int bpp = formatsize(format), row = 0, rowalign = 0; if(!pitch) pitch = pw*bpp; uchar *buf = NULL; - if(pw!=tw || ph!=th) - { + if(pw!=tw || ph!=th) { buf = new uchar[tw*th*bpp]; scaletexture((uchar *)pixels, pw, ph, bpp, pitch, buf, tw, th); } - else if(tw*bpp != pitch) - { + else if(tw*bpp != pitch) { row = pitch/bpp; rowalign = texalign(pixels, pitch, 1); while(rowalign > 0 && ((row*bpp + rowalign - 1)/rowalign)*rowalign != pitch) rowalign >>= 1; - if(!rowalign) - { + if(!rowalign) { row = 0; buf = new uchar[tw*th*bpp]; loopi(th) memcpy(&buf[i*tw*bpp], &((uchar *)pixels)[i*pitch], tw*bpp); } } - for(int level = 0, align = 0, mw = tw, mh = th;; level++) - { + for(int level = 0, align = 0, mw = tw, mh = th;; level++) { uchar *src = buf ? buf : (uchar *)pixels; if(buf) pitch = mw*bpp; int srcalign = row > 0 ? rowalign : texalign(src, pitch, 1); @@ -773,8 +676,7 @@ void uploadtexture(int tnum, GLenum target, GLenum internal, int tw, int th, GLe int srcw = mw, srch = mh; if(mw > 1) mw /= 2; if(mh > 1) mh /= 2; - if(src) - { + if(src) { if(!buf) buf = new uchar[mw*mh*bpp]; scaletexture(src, srcw, srch, bpp, pitch, buf, mw, mh); } @@ -782,16 +684,13 @@ void uploadtexture(int tnum, GLenum target, GLenum internal, int tw, int th, GLe if(buf) delete[] buf; } -void uploadcompressedtexture(GLenum target, GLenum subtarget, GLenum format, int w, int h, uchar *data, int align, int blocksize, int levels, bool mipmap) -{ +void uploadcompressedtexture(GLenum target, GLenum subtarget, GLenum format, int w, int h, uchar *data, int align, int blocksize, int levels, bool mipmap) { int hwlimit = target==GL_TEXTURE_CUBE_MAP ? hwcubetexsize : hwtexsize, sizelimit = levels > 1 && maxtexsize ? min(maxtexsize, hwlimit) : hwlimit; int level = 0; - loopi(levels) - { + loopi(levels) { int size = ((w + align-1)/align) * ((h + align-1)/align) * blocksize; - if(w <= sizelimit && h <= sizelimit) - { + if(w <= sizelimit && h <= sizelimit) { glCompressedTexImage2D_(subtarget, level, format, w, h, 0, size, data); level++; if(!mipmap) break; @@ -803,10 +702,8 @@ void uploadcompressedtexture(GLenum target, GLenum subtarget, GLenum format, int } } -GLenum textarget(GLenum subtarget) -{ - switch(subtarget) - { +GLenum textarget(GLenum subtarget) { + switch(subtarget) { case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: @@ -818,20 +715,17 @@ GLenum textarget(GLenum subtarget) return subtarget; } -const GLint *swizzlemask(GLenum format) -{ +const GLint *swizzlemask(GLenum format) { static const GLint luminance[4] = { GL_RED, GL_RED, GL_RED, GL_ONE }; static const GLint luminancealpha[4] = { GL_RED, GL_RED, GL_RED, GL_GREEN }; - switch(format) - { + switch(format) { case GL_RED: return luminance; case GL_RG: return luminancealpha; } return NULL; } -void setuptexparameters(int tnum, void *pixels, int clamp, int filter, GLenum format, GLenum target, bool swizzle) -{ +void setuptexparameters(int tnum, void *pixels, int clamp, int filter, GLenum format, GLenum target, bool swizzle) { glBindTexture(target, tnum); glTexParameteri(target, GL_TEXTURE_WRAP_S, clamp&1 ? GL_CLAMP_TO_EDGE : (clamp&0x100 ? GL_MIRRORED_REPEAT : GL_REPEAT)); glTexParameteri(target, GL_TEXTURE_WRAP_T, clamp&2 ? GL_CLAMP_TO_EDGE : (clamp&0x200 ? GL_MIRRORED_REPEAT : GL_REPEAT)); @@ -843,48 +737,40 @@ void setuptexparameters(int tnum, void *pixels, int clamp, int filter, GLenum fo (bilinear ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_LINEAR) : (bilinear ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_NEAREST)) : (filter && bilinear ? GL_LINEAR : GL_NEAREST)); - if(swizzle && hasTRG && hasTSW) - { + if(swizzle && hasTRG && hasTSW) { const GLint *mask = swizzlemask(format); if(mask) glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, mask); } } -static GLenum textype(GLenum &component, GLenum &format) -{ +static GLenum textype(GLenum &component, GLenum &format) { GLenum type = GL_UNSIGNED_BYTE; - switch(component) - { + switch(component) { case GL_R16F: case GL_R32F: if(!format) format = GL_RED; type = GL_FLOAT; break; - case GL_RG16F: case GL_RG32F: if(!format) format = GL_RG; type = GL_FLOAT; break; - case GL_RGB16F: case GL_RGB32F: if(!format) format = GL_RGB; type = GL_FLOAT; break; - case GL_RGBA16F: case GL_RGBA32F: if(!format) format = GL_RGBA; type = GL_FLOAT; break; - case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32: if(!format) format = GL_DEPTH_COMPONENT; break; - case GL_RGB5: case GL_RGB8: case GL_RGB10: @@ -893,7 +779,6 @@ static GLenum textype(GLenum &component, GLenum &format) case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: if(!format) format = GL_RGB; break; - case GL_RGB5_A1: case GL_RGBA8: case GL_RGB10_A2: @@ -904,41 +789,35 @@ static GLenum textype(GLenum &component, GLenum &format) case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: if(!format) format = GL_RGBA; break; - case GL_DEPTH_STENCIL: case GL_DEPTH24_STENCIL8: if(!format) format = GL_DEPTH_STENCIL; type = GL_UNSIGNED_INT_24_8; break; - case GL_R8: case GL_R16: case GL_COMPRESSED_RED: case GL_COMPRESSED_RED_RGTC1: if(!format) format = GL_RED; break; - case GL_RG8: case GL_RG16: case GL_COMPRESSED_RG: case GL_COMPRESSED_RG_RGTC2: if(!format) format = GL_RG; break; - case GL_LUMINANCE8: case GL_LUMINANCE16: case GL_COMPRESSED_LUMINANCE: case GL_COMPRESSED_LUMINANCE_LATC1_EXT: if(!format) format = GL_LUMINANCE; break; - case GL_LUMINANCE8_ALPHA8: case GL_LUMINANCE16_ALPHA16: case GL_COMPRESSED_LUMINANCE_ALPHA: case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: if(!format) format = GL_LUMINANCE_ALPHA; break; - case GL_ALPHA8: case GL_ALPHA16: case GL_COMPRESSED_ALPHA: @@ -949,24 +828,21 @@ static GLenum textype(GLenum &component, GLenum &format) return type; } -void createtexture(int tnum, int w, int h, void *pixels, int clamp, int filter, GLenum component, GLenum subtarget, int pw, int ph, int pitch, bool resize, GLenum format, bool swizzle) -{ +void createtexture(int tnum, int w, int h, void *pixels, int clamp, int filter, GLenum component, GLenum subtarget, int pw, int ph, int pitch, bool resize, GLenum format, bool swizzle) { GLenum target = textarget(subtarget), type = textype(component, format); if(filter >= 0 && clamp >= 0) setuptexparameters(tnum, pixels, clamp, filter, format, target, swizzle); if(!pw) pw = w; if(!ph) ph = h; int tw = w, th = h; bool mipmap = filter > 1 && pixels; - if(resize && pixels) - { + if(resize && pixels) { resizetexture(w, h, mipmap, false, target, 0, tw, th); if(mipmap) component = compressedformat(component, tw, th); } uploadtexture(tnum, subtarget, component, tw, th, format, type, pixels, pw, ph, pitch, mipmap); } -void createcompressedtexture(int tnum, int w, int h, uchar *data, int align, int blocksize, int levels, int clamp, int filter, GLenum format, GLenum subtarget, bool swizzle = false) -{ +void createcompressedtexture(int tnum, int w, int h, uchar *data, int align, int blocksize, int levels, int clamp, int filter, GLenum format, GLenum subtarget, bool swizzle = false) { GLenum target = textarget(subtarget); if(filter >= 0 && clamp >= 0) setuptexparameters(tnum, data, clamp, filter, format, target); uploadcompressedtexture(target, subtarget, format, w, h, data, align, blocksize, levels, filter > 1); @@ -976,10 +852,8 @@ hashnameset<Texture> textures; Texture *notexture = NULL; // used as default, ensured to be loaded -static GLenum texformat(int bpp, bool swizzle = false) -{ - switch(bpp) - { +static GLenum texformat(int bpp, bool swizzle = false) { + switch(bpp) { case 1: return hasTRG && (hasTSW || !glcompat || !swizzle) ? GL_RED : GL_LUMINANCE; case 2: return hasTRG && (hasTSW || !glcompat || !swizzle) ? GL_RG : GL_LUMINANCE_ALPHA; case 3: return GL_RGB; @@ -988,10 +862,8 @@ static GLenum texformat(int bpp, bool swizzle = false) } } -static bool alphaformat(GLenum format) -{ - switch(format) - { +static bool alphaformat(GLenum format) { + switch(format) { case GL_ALPHA: case GL_LUMINANCE_ALPHA: case GL_RG: @@ -1002,49 +874,40 @@ static bool alphaformat(GLenum format) } } -int texalign(const void *data, int w, int bpp) -{ +int texalign(const void *data, int w, int bpp) { int stride = w*bpp; if(stride&1) return 1; if(stride&2) return 2; return 4; } -static Texture *newtexture(Texture *t, const char *rname, ImageData &s, int clamp = 0, bool mipit = true, bool canreduce = false, bool transient = false, int compress = 0) -{ - if(!t) - { +static Texture *newtexture(Texture *t, const char *rname, ImageData &s, int clamp = 0, bool mipit = true, bool canreduce = false, bool transient = false, int compress = 0) { + if(!t) { char *key = newstring(rname); t = &textures[key]; t->name = key; } - t->clamp = clamp; t->mipmap = mipit; t->type = Texture::IMAGE; if(transient) t->type |= Texture::TRANSIENT; if(clamp&0x300) t->type |= Texture::MIRROR; - if(!s.data) - { + if(!s.data) { t->type |= Texture::STUB; t->w = t->h = t->xs = t->ys = t->bpp = 0; return t; } - bool swizzle = !(clamp&0x10000); GLenum format; - if(s.compressed) - { + if(s.compressed) { format = uncompressedformat(s.compressed); t->bpp = formatsize(format); t->type |= Texture::COMPRESSED; } - else - { + else { format = texformat(s.bpp, swizzle); t->bpp = s.bpp; - if(swizzle && hasTRG && !hasTSW && swizzlemask(format)) - { + if(swizzle && hasTRG && !hasTSW && swizzlemask(format)) { swizzleimage(s); format = texformat(s.bpp, swizzle); t->bpp = s.bpp; @@ -1053,23 +916,19 @@ static Texture *newtexture(Texture *t, const char *rname, ImageData &s, int clam if(alphaformat(format)) t->type |= Texture::ALPHA; t->w = t->xs = s.w; t->h = t->ys = s.h; - int filter = !canreduce || reducefilter ? (mipit ? 2 : 1) : 0; glGenTextures(1, &t->id); - if(s.compressed) - { + if(s.compressed) { uchar *data = s.data; int levels = s.levels, level = 0; - if(canreduce && texreduce) loopi(min(texreduce, s.levels-1)) - { + if(canreduce && texreduce) loopi(min(texreduce, s.levels-1)) { data += s.calclevelsize(level++); levels--; if(t->w > 1) t->w /= 2; if(t->h > 1) t->h /= 2; } int sizelimit = mipit && maxtexsize ? min(maxtexsize, hwtexsize) : hwtexsize; - while(t->w > sizelimit || t->h > sizelimit) - { + while(t->w > sizelimit || t->h > sizelimit) { data += s.calclevelsize(level++); levels--; if(t->w > 1) t->w /= 2; @@ -1077,8 +936,7 @@ static Texture *newtexture(Texture *t, const char *rname, ImageData &s, int clam } createcompressedtexture(t->id, t->w, t->h, data, s.align, s.bpp, levels, clamp, filter, s.compressed, GL_TEXTURE_2D, swizzle); } - else - { + else { resizetexture(t->w, t->h, mipit, canreduce, GL_TEXTURE_2D, compress, t->w, t->h); GLenum component = compressedformat(format, t->w, t->h, compress); createtexture(t->id, t->w, t->h, s.data, clamp, filter, component, GL_TEXTURE_2D, t->xs, t->ys, s.pitch, false, format, swizzle); @@ -1094,29 +952,24 @@ static Texture *newtexture(Texture *t, const char *rname, ImageData &s, int clam #define RGBMASKS 0x0000ff, 0x00ff00, 0xff0000, 0 #endif -SDL_Surface *wrapsurface(void *data, int width, int height, int bpp) -{ - switch(bpp) - { +SDL_Surface *wrapsurface(void *data, int width, int height, int bpp) { + switch(bpp) { case 3: return SDL_CreateRGBSurfaceFrom(data, width, height, 8*bpp, bpp*width, RGBMASKS); case 4: return SDL_CreateRGBSurfaceFrom(data, width, height, 8*bpp, bpp*width, RGBAMASKS); } return NULL; } -SDL_Surface *creatergbsurface(SDL_Surface *os) -{ +SDL_Surface *creatergbsurface(SDL_Surface *os) { SDL_Surface *ns = SDL_CreateRGBSurface(SDL_SWSURFACE, os->w, os->h, 24, RGBMASKS); if(ns) SDL_BlitSurface(os, NULL, ns, NULL); SDL_FreeSurface(os); return ns; } -SDL_Surface *creatergbasurface(SDL_Surface *os) -{ +SDL_Surface *creatergbasurface(SDL_Surface *os) { SDL_Surface *ns = SDL_CreateRGBSurface(SDL_SWSURFACE, os->w, os->h, 32, RGBAMASKS); - if(ns) - { + if(ns) { SDL_SetSurfaceBlendMode(os, SDL_BLENDMODE_NONE); SDL_BlitSurface(os, NULL, ns, NULL); } @@ -1124,11 +977,9 @@ SDL_Surface *creatergbasurface(SDL_Surface *os) return ns; } -bool checkgrayscale(SDL_Surface *s) -{ +bool checkgrayscale(SDL_Surface *s) { // gray scale images have 256 levels, no colorkey, and the palette is a ramp - if(s->format->palette) - { + if(s->format->palette) { if(s->format->palette->ncolors != 256 || SDL_GetColorKey(s, NULL) >= 0) return false; const SDL_Color *colors = s->format->palette->colors; loopi(256) if(colors[i].r != i || colors[i].g != i || colors[i].b != i) return false; @@ -1136,17 +987,14 @@ bool checkgrayscale(SDL_Surface *s) return true; } -SDL_Surface *fixsurfaceformat(SDL_Surface *s) -{ +SDL_Surface *fixsurfaceformat(SDL_Surface *s) { if(!s) return NULL; - if(!s->pixels || min(s->w, s->h) <= 0 || s->format->BytesPerPixel <= 0) - { + if(!s->pixels || min(s->w, s->h) <= 0 || s->format->BytesPerPixel <= 0) { SDL_FreeSurface(s); return NULL; } static const uint rgbmasks[] = { RGBMASKS }, rgbamasks[] = { RGBAMASKS }; - switch(s->format->BytesPerPixel) - { + switch(s->format->BytesPerPixel) { case 1: if(!checkgrayscale(s)) return SDL_GetColorKey(s, NULL) >= 0 ? creatergbasurface(s) : creatergbsurface(s); break; @@ -1162,12 +1010,10 @@ SDL_Surface *fixsurfaceformat(SDL_Surface *s) return s; } -void texflip(ImageData &s) -{ +void texflip(ImageData &s) { ImageData d(s.w, s.h, s.bpp); uchar *dst = d.data, *src = &s.data[s.pitch*s.h]; - loopi(s.h) - { + loopi(s.h) { src -= s.pitch; memcpy(dst, src, s.bpp*s.w); dst += d.pitch; @@ -1175,12 +1021,10 @@ void texflip(ImageData &s) s.replace(d); } -void texnormal(ImageData &s, int emphasis) -{ +void texnormal(ImageData &s, int emphasis) { ImageData d(s.w, s.h, 3); uchar *src = s.data, *dst = d.data; - loop(y, s.h) loop(x, s.w) - { + loop(y, s.h) loop(x, s.w) { vec normal(0.0f, 0.0f, 255.0f/emphasis); normal.x += src[y*s.pitch + ((x+s.w-1)%s.w)*s.bpp]; normal.x -= src[y*s.pitch + ((x+1)%s.w)*s.bpp]; @@ -1195,16 +1039,13 @@ void texnormal(ImageData &s, int emphasis) } template<int n, int bpp, bool normals> -static void blurtexture(int w, int h, uchar *dst, const uchar *src, int margin) -{ - static const int weights3x3[9] = - { +static void blurtexture(int w, int h, uchar *dst, const uchar *src, int margin) { + static const int weights3x3[9] = { 0x10, 0x20, 0x10, 0x20, 0x40, 0x20, 0x10, 0x20, 0x10 }; - static const int weights5x5[25] = - { + static const int weights5x5[25] = { 0x05, 0x05, 0x09, 0x05, 0x05, 0x05, 0x0A, 0x14, 0x0A, 0x05, 0x09, 0x14, 0x28, 0x14, 0x09, @@ -1219,15 +1060,12 @@ static void blurtexture(int w, int h, uchar *dst, const uchar *src, int margin) nextoffset1 = stride + mstride*bpp, nextoffset2 = stride - mstride*bpp; src += margin*(stride + bpp); - for(int y = margin; y < h-margin; y++) - { - for(int x = margin; x < w-margin; x++) - { + for(int y = margin; y < h-margin; y++) { + for(int x = margin; x < w-margin; x++) { int dr = 0, dg = 0, db = 0; const uchar *p = src - startoffset; const int *m = mat + mstartoffset; - for(int t = y; t >= y-n; t--, p -= nextoffset1, m -= mstride) - { + for(int t = y; t >= y-n; t--, p -= nextoffset1, m -= mstride) { if(t < 0) p += stride; int a = 0; if(n > 1) { a += m[-2]; if(x >= 2) { dr += p[0] * a; dg += p[1] * a; db += p[2] * a; a = 0; } p += bpp; } @@ -1238,8 +1076,7 @@ static void blurtexture(int w, int h, uchar *dst, const uchar *src, int margin) } p = src - startoffset + stride; m = mat + mstartoffset + mstride; - for(int t = y+1; t <= y+n; t++, p += nextoffset2, m += mstride) - { + for(int t = y+1; t <= y+n; t++, p += nextoffset2, m += mstride) { if(t >= h) p -= stride; int a = 0; if(n > 1) { a += m[-2]; if(x >= 2) { dr += p[0] * a; dg += p[1] * a; db += p[2] * a; a = 0; } p += bpp; } @@ -1248,16 +1085,14 @@ static void blurtexture(int w, int h, uchar *dst, const uchar *src, int margin) if(x+1 < w) { cr = p[0]; cg = p[1]; cb = p[2]; } dr += cr * m[1]; dg += cg * m[1]; db += cb * m[1]; p += bpp; if(n > 1) { if(x+2 < w) { cr = p[0]; cg = p[1]; cb = p[2]; } dr += cr * m[2]; dg += cg * m[2]; db += cb * m[2]; p += bpp; } } - if(normals) - { + if(normals) { vec v(dr-0x7F80, dg-0x7F80, db-0x7F80); float mag = 127.5f/v.magnitude(); dst[0] = uchar(v.x*mag + 127.5f); dst[1] = uchar(v.y*mag + 127.5f); dst[2] = uchar(v.z*mag + 127.5f); } - else - { + else { dst[0] = dr>>8; dst[1] = dg>>8; dst[2] = db>>8; @@ -1270,10 +1105,8 @@ static void blurtexture(int w, int h, uchar *dst, const uchar *src, int margin) } } -void blurtexture(int n, int bpp, int w, int h, uchar *dst, const uchar *src, int margin) -{ - switch((clamp(n, 1, 2)<<4) | bpp) - { +void blurtexture(int n, int bpp, int w, int h, uchar *dst, const uchar *src, int margin) { + switch((clamp(n, 1, 2)<<4) | bpp) { case 0x13: blurtexture<1, 3, false>(w, h, dst, src, margin); break; case 0x23: blurtexture<2, 3, false>(w, h, dst, src, margin); break; case 0x14: blurtexture<1, 4, false>(w, h, dst, src, margin); break; @@ -1281,50 +1114,41 @@ void blurtexture(int n, int bpp, int w, int h, uchar *dst, const uchar *src, int } } -void blurnormals(int n, int w, int h, bvec *dst, const bvec *src, int margin) -{ - switch(clamp(n, 1, 2)) - { +void blurnormals(int n, int w, int h, bvec *dst, const bvec *src, int margin) { + switch(clamp(n, 1, 2)) { case 1: blurtexture<1, 3, true>(w, h, dst->v, src->v, margin); break; case 2: blurtexture<2, 3, true>(w, h, dst->v, src->v, margin); break; } } -void texblur(ImageData &s, int n, int r) -{ +void texblur(ImageData &s, int n, int r) { if(s.bpp < 3) return; - loopi(r) - { + loopi(r) { ImageData d(s.w, s.h, s.bpp); blurtexture(n, s.bpp, s.w, s.h, d.data, s.data); s.replace(d); } } -void scaleimage(ImageData &s, int w, int h) -{ +void scaleimage(ImageData &s, int w, int h) { ImageData d(w, h, s.bpp); scaletexture(s.data, s.w, s.h, s.bpp, s.pitch, d.data, w, h); s.replace(d); } -bool canloadsurface(const char *name) -{ +bool canloadsurface(const char *name) { stream *f = openfile(name, "rb"); if(!f) return false; delete f; return true; } -SDL_Surface *loadsurface(const char *name) -{ +SDL_Surface *loadsurface(const char *name) { SDL_Surface *s = NULL; stream *z = openzipfile(name, "rb"); - if(z) - { + if(z) { SDL_RWops *rw = z->rwops(); - if(rw) - { + if(rw) { char *ext = (char *)strrchr(name, '.'); if(ext) ++ext; s = IMG_LoadTyped_RW(rw, 0, ext); @@ -1336,12 +1160,10 @@ SDL_Surface *loadsurface(const char *name) return fixsurfaceformat(s); } -static vec parsevec(const char *arg) -{ +static vec parsevec(const char *arg) { vec v(0, 0, 0); int i = 0; - for(; arg[0] && (!i || arg[0]=='/') && i<3; arg += strcspn(arg, "/,><"), i++) - { + for(; arg[0] && (!i || arg[0]=='/') && i<3; arg += strcspn(arg, "/,><"), i++) { if(i) arg++; v[i] = atof(arg); } @@ -1349,38 +1171,30 @@ static vec parsevec(const char *arg) return v; } -static bool texturedata(ImageData &d, const char *tname, Slot::Tex *tex = NULL, bool msg = true, int *compress = NULL, int *wrap = NULL) -{ +static bool texturedata(ImageData &d, const char *tname, Slot::Tex *tex = NULL, bool msg = true, int *compress = NULL, int *wrap = NULL) { const char *cmds = NULL, *file = tname; - - if(!tname) - { + if(!tname) { if(!tex) return false; - if(tex->name[0]=='<') - { + if(tex->name[0]=='<') { cmds = tex->name; file = strrchr(tex->name, '>'); if(!file) { if(msg) conoutf(CON_ERROR, "could not load texture packages/%s", tex->name); return false; } file++; } else file = tex->name; - static string pname; formatstring(pname, "packages/%s", file); file = path(pname); } - else if(tname[0]=='<') - { + else if(tname[0]=='<') { cmds = tname; file = strrchr(tname, '>'); if(!file) { if(msg) conoutf(CON_ERROR, "could not load texture %s", tname); return false; } file++; } - int flen = strlen(file); - bool raw = !compress, guess = false; - for(const char *pcmds = cmds; pcmds;) - { + bool guess = false; + for(const char *pcmds = cmds; pcmds;) { #define PARSETEXCOMMANDS(cmds) \ const char *cmd = NULL, *end = NULL, *arg[4] = { NULL, NULL, NULL, NULL }; \ cmd = &cmds[1]; \ @@ -1388,32 +1202,25 @@ static bool texturedata(ImageData &d, const char *tname, Slot::Tex *tex = NULL, if(!end) break; \ cmds = strchr(cmd, '<'); \ size_t len = strcspn(cmd, ":,><"); \ - loopi(4) \ - { \ + loopi(4) { \ + \ arg[i] = strchr(i ? arg[i-1] : cmd, i ? ',' : ':'); \ if(!arg[i] || arg[i] >= end) arg[i] = ""; \ else arg[i]++; \ } PARSETEXCOMMANDS(pcmds); - if(matchstring(cmd, len, "thumbnail")) - { - raw = true; + if(matchstring(cmd, len, "thumbnail")) { guess = flen >= 4 && !strchr(file+flen-4, '.'); } else if(matchstring(cmd, len, "stub")) return canloadsurface(file); } - if(msg) renderprogress(loadprogress, file); - - if(!d.data) - { + if(!d.data) { SDL_Surface *s = NULL; - if(guess) - { + if(guess) { static const char *exts[] = {".jpg", ".png"}; string ext; - loopi(sizeof(exts)/sizeof(exts[0])) - { + loopi(sizeof(exts)/sizeof(exts[0])) { copystring(ext, file); concatstring(ext, exts[i]); s = loadsurface(ext); @@ -1427,16 +1234,13 @@ static bool texturedata(ImageData &d, const char *tname, Slot::Tex *tex = NULL, if(max(s->w, s->h) > (1<<12)) { SDL_FreeSurface(s); conoutf(CON_ERROR, "texture size exceeded %dx%d pixels: %s", 1<<12, 1<<12, file); return false; } d.wrap(s); } - - while(cmds) - { + while(cmds) { PARSETEXCOMMANDS(cmds); if(d.compressed) goto compressed; if(matchstring(cmd, len, "mad")) texmad(d, parsevec(arg[0]), parsevec(arg[1])); else if(matchstring(cmd, len, "colorify")) texcolorify(d, parsevec(arg[0]), parsevec(arg[1])); else if(matchstring(cmd, len, "colormask")) texcolormask(d, parsevec(arg[0]), *arg[1] ? parsevec(arg[1]) : vec(1, 1, 1)); - else if(matchstring(cmd, len, "normal")) - { + else if(matchstring(cmd, len, "normal")) { int emphasis = atoi(arg[0]); texnormal(d, emphasis > 0 ? emphasis : 3); } @@ -1446,25 +1250,21 @@ static bool texturedata(ImageData &d, const char *tname, Slot::Tex *tex = NULL, else if(matchstring(cmd, len, "reorient")) texreorient(d, atoi(arg[0])>0, atoi(arg[1])>0, atoi(arg[2])>0, tex ? tex->type : TEX_DIFFUSE); else if(matchstring(cmd, len, "mix")) texmix(d, *arg[0] ? atoi(arg[0]) : -1, *arg[1] ? atoi(arg[1]) : -1, *arg[2] ? atoi(arg[2]) : -1, *arg[3] ? atoi(arg[3]) : -1); else if(matchstring(cmd, len, "grey")) texgrey(d); - else if(matchstring(cmd, len, "blur")) - { + else if(matchstring(cmd, len, "blur")) { int emphasis = atoi(arg[0]), repeat = atoi(arg[1]); texblur(d, emphasis > 0 ? clamp(emphasis, 1, 2) : 1, repeat > 0 ? repeat : 1); } else if(matchstring(cmd, len, "premul")) texpremul(d); else if(matchstring(cmd, len, "agrad")) texagrad(d, atof(arg[0]), atof(arg[1]), atof(arg[2]), atof(arg[3])); - else if(matchstring(cmd, len, "compress")) - { + else if(matchstring(cmd, len, "compress")) { int scale = atoi(arg[0]); if(scale <= 0) scale = 2; if(compress) *compress = scale; } - else if(matchstring(cmd, len, "nocompress")) - { + else if(matchstring(cmd, len, "nocompress")) { if(compress) *compress = -1; } - else if(matchstring(cmd, len, "thumbnail")) - { + else if(matchstring(cmd, len, "thumbnail")) { int w = atoi(arg[0]), h = atoi(arg[1]); if(w <= 0 || w > (1<<12)) w = 64; if(h <= 0 || h > (1<<12)) h = w; @@ -1472,32 +1272,26 @@ static bool texturedata(ImageData &d, const char *tname, Slot::Tex *tex = NULL, } else compressed: - if(matchstring(cmd, len, "mirror")) - { + if(matchstring(cmd, len, "mirror")) { if(wrap) *wrap |= 0x300; } - else if(matchstring(cmd, len, "noswizzle")) - { + else if(matchstring(cmd, len, "noswizzle")) { if(wrap) *wrap |= 0x10000; } } - return true; } -uchar *loadalphamask(Texture *t) -{ +uchar *loadalphamask(Texture *t) { if(t->alphamask) return t->alphamask; if(!(t->type&Texture::ALPHA)) return NULL; ImageData s; if(!texturedata(s, t->name, NULL, false) || !s.data || s.compressed) return NULL; t->alphamask = new uchar[s.h * ((s.w+7)/8)]; uchar *srcrow = s.data, *dst = t->alphamask-1; - loop(y, s.h) - { + loop(y, s.h) { uchar *src = srcrow+s.bpp-1; - loop(x, s.w) - { + loop(x, s.w) { int offset = x%8; if(!offset) *++dst = 0; if(*src) *dst |= 1<<offset; @@ -1508,8 +1302,7 @@ uchar *loadalphamask(Texture *t) return t->alphamask; } -Texture *textureload(const char *name, int clamp, bool mipit, bool msg) -{ +Texture *textureload(const char *name, int clamp, bool mipit, bool msg) { string tname; copystring(tname, name); Texture *t = textures.access(path(tname)); @@ -1520,8 +1313,7 @@ Texture *textureload(const char *name, int clamp, bool mipit, bool msg) return notexture; } -bool settexture(const char *name, int clamp) -{ +bool settexture(const char *name, int clamp) { Texture *t = textureload(name, clamp, true, false); glBindTexture(GL_TEXTURE_2D, t->id); return t != notexture; @@ -1532,20 +1324,17 @@ vector<Slot *> slots; Slot dummyslot; VSlot dummyvslot(&dummyslot); -void texturereset(int *n) -{ +void texturereset(int *n) { if(!(identflags&IDF_OVERRIDDEN) && !game::allowedittoggle()) return; resetslotshader(); int limit = clamp(*n, 0, slots.length()); - for(int i = limit; i < slots.length(); i++) - { + for(int i = limit; i < slots.length(); i++) { Slot *s = slots[i]; for(VSlot *vs = s->variants; vs; vs = vs->next) vs->slot = &dummyslot; delete s; } slots.setsize(limit); - while(vslots.length()) - { + while(vslots.length()) { VSlot *vs = vslots.last(); if(vs->slot != &dummyslot || vs->changed) break; delete vslots.pop(); @@ -1557,8 +1346,7 @@ COMMAND(texturereset, "i"); static int compactedvslots = 0, compactvslotsprogress = 0, clonedvslots = 0; static bool markingvslots = false; -void clearslots() -{ +void clearslots() { resetslotshader(); slots.deletecontents(); vslots.deletecontents(); @@ -1567,44 +1355,35 @@ void clearslots() static void assignvslot(VSlot &vs); -static inline void assignvslotlayer(VSlot &vs) -{ - if(vs.layer && vslots.inrange(vs.layer)) - { +static inline void assignvslotlayer(VSlot &vs) { + if(vs.layer && vslots.inrange(vs.layer)) { VSlot &layer = *vslots[vs.layer]; if(layer.index < 0) assignvslot(layer); } } -static void assignvslot(VSlot &vs) -{ +static void assignvslot(VSlot &vs) { vs.index = compactedvslots++; assignvslotlayer(vs); } -void compactvslot(int &index) -{ - if(vslots.inrange(index)) - { +void compactvslot(int &index) { + if(vslots.inrange(index)) { VSlot &vs = *vslots[index]; if(vs.index < 0) assignvslot(vs); if(!markingvslots) index = vs.index; } } -void compactvslot(VSlot &vs) -{ +void compactvslot(VSlot &vs) { if(vs.index < 0) assignvslot(vs); } -void compactvslots(cube *c, int n) -{ +void compactvslots(cube *c, int n) { if((compactvslotsprogress++&0xFFF)==0) renderprogress(min(float(compactvslotsprogress)/allocnodes, 1.0f), markingvslots ? "marking slots..." : "compacting slots..."); - loopi(n) - { + loopi(n) { if(c[i].children) compactvslots(c[i].children); - else loopj(6) if(vslots.inrange(c[i].texture[j])) - { + else loopj(6) if(vslots.inrange(c[i].texture[j])) { VSlot &vs = *vslots[c[i].texture[j]]; if(vs.index < 0) assignvslot(vs); if(!markingvslots) c[i].texture[j] = vs.index; @@ -1612,8 +1391,7 @@ void compactvslots(cube *c, int n) } } -int compactvslots() -{ +int compactvslots() { clonedvslots = 0; markingvslots = false; compactedvslots = 0; @@ -1621,38 +1399,31 @@ int compactvslots() loopv(vslots) vslots[i]->index = -1; loopv(slots) slots[i]->variants->index = compactedvslots++; loopv(slots) assignvslotlayer(*slots[i]->variants); - loopv(vslots) - { + loopv(vslots) { VSlot &vs = *vslots[i]; if(!vs.changed && vs.index < 0) { markingvslots = true; break; } } compactvslots(worldroot); int total = compactedvslots; compacteditvslots(); - loopv(vslots) - { + loopv(vslots) { VSlot *vs = vslots[i]; if(vs->changed) continue; - while(vs->next) - { + while(vs->next) { if(vs->next->index < 0) vs->next = vs->next->next; else vs = vs->next; } } - if(markingvslots) - { + if(markingvslots) { markingvslots = false; compactedvslots = 0; compactvslotsprogress = 0; int lastdiscard = 0; - loopv(vslots) - { + loopv(vslots) { VSlot &vs = *vslots[i]; if(vs.changed || (vs.index < 0 && !vs.next)) vs.index = -1; - else - { - while(lastdiscard < i) - { + else { + while(lastdiscard < i) { VSlot &ds = *vslots[lastdiscard++]; if(!ds.changed && ds.index < 0) ds.index = compactedvslots++; } @@ -1664,13 +1435,11 @@ int compactvslots() compacteditvslots(); } compactmruvslots(); - loopv(vslots) - { + loopv(vslots) { VSlot &vs = *vslots[i]; if(vs.index >= 0 && vs.layer && vslots.inrange(vs.layer)) vs.layer = vslots[vs.layer]->index; } - loopv(vslots) - { + loopv(vslots) { while(vslots[i]->index >= 0 && vslots[i]->index != i) swap(vslots[i], vslots[vslots[i]->index]); } @@ -1679,8 +1448,7 @@ int compactvslots() return total; } -ICOMMAND(compactvslots, "", (), -{ +ICOMMAND(compactvslots, "", (), { extern int nompedit; if(nompedit && multiplayer()) return; compactvslots(); @@ -1689,11 +1457,9 @@ ICOMMAND(compactvslots, "", (), static Slot &loadslot(Slot &s, bool forceload); -static void clampvslotoffset(VSlot &dst, Slot *slot = NULL) -{ +static void clampvslotoffset(VSlot &dst, Slot *slot = NULL) { if(!slot) slot = dst.slot; - if(slot && slot->sts.inrange(0)) - { + if(slot && slot->sts.inrange(0)) { if(!slot->loaded) loadslot(*slot, false); Texture *t = slot->sts[0].t; int xs = t->xs, ys = t->ys; @@ -1705,49 +1471,39 @@ static void clampvslotoffset(VSlot &dst, Slot *slot = NULL) else dst.offset.max(0); } -static void propagatevslot(VSlot &dst, const VSlot &src, int diff, bool edit = false) -{ +static void propagatevslot(VSlot &dst, const VSlot &src, int diff, bool edit = false) { if(diff & (1<<VSLOT_SHPARAM)) loopv(src.params) dst.params.add(src.params[i]); if(diff & (1<<VSLOT_SCALE)) dst.scale = src.scale; - if(diff & (1<<VSLOT_ROTATION)) - { + if(diff & (1<<VSLOT_ROTATION)) { dst.rotation = src.rotation; if(edit && !dst.offset.iszero()) clampvslotoffset(dst); } - if(diff & (1<<VSLOT_OFFSET)) - { + if(diff & (1<<VSLOT_OFFSET)) { dst.offset = src.offset; if(edit) clampvslotoffset(dst); } if(diff & (1<<VSLOT_SCROLL)) dst.scroll = src.scroll; if(diff & (1<<VSLOT_LAYER)) dst.layer = src.layer; - if(diff & (1<<VSLOT_ALPHA)) - { + if(diff & (1<<VSLOT_ALPHA)) { dst.alphafront = src.alphafront; dst.alphaback = src.alphaback; } if(diff & (1<<VSLOT_COLOR)) dst.colorscale = src.colorscale; } -static void propagatevslot(VSlot *root, int changed) -{ - for(VSlot *vs = root->next; vs; vs = vs->next) - { +static void propagatevslot(VSlot *root, int changed) { + for(VSlot *vs = root->next; vs; vs = vs->next) { int diff = changed & ~vs->changed; if(diff) propagatevslot(*vs, *root, diff); } } -static void mergevslot(VSlot &dst, const VSlot &src, int diff, Slot *slot = NULL) -{ - if(diff & (1<<VSLOT_SHPARAM)) loopv(src.params) - { +static void mergevslot(VSlot &dst, const VSlot &src, int diff, Slot *slot = NULL) { + if(diff & (1<<VSLOT_SHPARAM)) loopv(src.params) { const SlotShaderParam &sp = src.params[i]; - loopvj(dst.params) - { + loopvj(dst.params) { SlotShaderParam &dp = dst.params[j]; - if(sp.name == dp.name) - { + if(sp.name == dp.name) { memcpy(dp.val, sp.val, sizeof(dp.val)); goto nextparam; } @@ -1755,42 +1511,35 @@ static void mergevslot(VSlot &dst, const VSlot &src, int diff, Slot *slot = NULL dst.params.add(sp); nextparam:; } - if(diff & (1<<VSLOT_SCALE)) - { + if(diff & (1<<VSLOT_SCALE)) { dst.scale = clamp(dst.scale*src.scale, 1/8.0f, 8.0f); } - if(diff & (1<<VSLOT_ROTATION)) - { + if(diff & (1<<VSLOT_ROTATION)) { dst.rotation = clamp(dst.rotation + src.rotation, 0, 7); if(!dst.offset.iszero()) clampvslotoffset(dst, slot); } - if(diff & (1<<VSLOT_OFFSET)) - { + if(diff & (1<<VSLOT_OFFSET)) { dst.offset.add(src.offset); clampvslotoffset(dst, slot); } if(diff & (1<<VSLOT_SCROLL)) dst.scroll.add(src.scroll); if(diff & (1<<VSLOT_LAYER)) dst.layer = src.layer; - if(diff & (1<<VSLOT_ALPHA)) - { + if(diff & (1<<VSLOT_ALPHA)) { dst.alphafront = src.alphafront; dst.alphaback = src.alphaback; } if(diff & (1<<VSLOT_COLOR)) dst.colorscale.mul(src.colorscale); } -void mergevslot(VSlot &dst, const VSlot &src, const VSlot &delta) -{ +void mergevslot(VSlot &dst, const VSlot &src, const VSlot &delta) { dst.changed = src.changed | delta.changed; propagatevslot(dst, src, (1<<VSLOT_NUM)-1); mergevslot(dst, delta, delta.changed, src.slot); } -static VSlot *reassignvslot(Slot &owner, VSlot *vs) -{ +static VSlot *reassignvslot(Slot &owner, VSlot *vs) { owner.variants = vs; - while(vs) - { + while(vs) { vs->slot = &owner; vs->linked = false; vs = vs->next; @@ -1798,21 +1547,17 @@ static VSlot *reassignvslot(Slot &owner, VSlot *vs) return owner.variants; } -static VSlot *emptyvslot(Slot &owner) -{ +static VSlot *emptyvslot(Slot &owner) { int offset = 0; loopvrev(slots) if(slots[i]->variants) { offset = slots[i]->variants->index + 1; break; } for(int i = offset; i < vslots.length(); i++) if(!vslots[i]->changed) return reassignvslot(owner, vslots[i]); return vslots.add(new VSlot(&owner, vslots.length())); } -static bool comparevslot(const VSlot &dst, const VSlot &src, int diff) -{ - if(diff & (1<<VSLOT_SHPARAM)) - { +static bool comparevslot(const VSlot &dst, const VSlot &src, int diff) { + if(diff & (1<<VSLOT_SHPARAM)) { if(src.params.length() != dst.params.length()) return false; - loopv(src.params) - { + loopv(src.params) { const SlotShaderParam &sp = src.params[i], &dp = dst.params[i]; if(sp.name != dp.name || memcmp(sp.val, dp.val, sizeof(sp.val))) return false; } @@ -1827,53 +1572,43 @@ static bool comparevslot(const VSlot &dst, const VSlot &src, int diff) return true; } -void packvslot(vector<uchar> &buf, const VSlot &src) -{ - if(src.changed & (1<<VSLOT_SHPARAM)) - { - loopv(src.params) - { +void packvslot(vector<uchar> &buf, const VSlot &src) { + if(src.changed & (1<<VSLOT_SHPARAM)) { + loopv(src.params) { const SlotShaderParam &p = src.params[i]; buf.put(VSLOT_SHPARAM); sendstring(p.name, buf); loopj(4) putfloat(buf, p.val[j]); } } - if(src.changed & (1<<VSLOT_SCALE)) - { + if(src.changed & (1<<VSLOT_SCALE)) { buf.put(VSLOT_SCALE); putfloat(buf, src.scale); } - if(src.changed & (1<<VSLOT_ROTATION)) - { + if(src.changed & (1<<VSLOT_ROTATION)) { buf.put(VSLOT_ROTATION); putint(buf, src.rotation); } - if(src.changed & (1<<VSLOT_OFFSET)) - { + if(src.changed & (1<<VSLOT_OFFSET)) { buf.put(VSLOT_OFFSET); putint(buf, src.offset.x); putint(buf, src.offset.y); } - if(src.changed & (1<<VSLOT_SCROLL)) - { + if(src.changed & (1<<VSLOT_SCROLL)) { buf.put(VSLOT_SCROLL); putfloat(buf, src.scroll.x); putfloat(buf, src.scroll.y); } - if(src.changed & (1<<VSLOT_LAYER)) - { + if(src.changed & (1<<VSLOT_LAYER)) { buf.put(VSLOT_LAYER); putuint(buf, vslots.inrange(src.layer) && !vslots[src.layer]->changed ? src.layer : 0); } - if(src.changed & (1<<VSLOT_ALPHA)) - { + if(src.changed & (1<<VSLOT_ALPHA)) { buf.put(VSLOT_ALPHA); putfloat(buf, src.alphafront); putfloat(buf, src.alphaback); } - if(src.changed & (1<<VSLOT_COLOR)) - { + if(src.changed & (1<<VSLOT_COLOR)) { buf.put(VSLOT_COLOR); putfloat(buf, src.colorscale.r); putfloat(buf, src.colorscale.g); @@ -1882,28 +1617,22 @@ void packvslot(vector<uchar> &buf, const VSlot &src) buf.put(0xFF); } -void packvslot(vector<uchar> &buf, int index) -{ +void packvslot(vector<uchar> &buf, int index) { if(vslots.inrange(index)) packvslot(buf, *vslots[index]); else buf.put(0xFF); } -void packvslot(vector<uchar> &buf, const VSlot *vs) -{ +void packvslot(vector<uchar> &buf, const VSlot *vs) { if(vs) packvslot(buf, *vs); else buf.put(0xFF); } -bool unpackvslot(ucharbuf &buf, VSlot &dst, bool delta) -{ - while(buf.remaining()) - { +bool unpackvslot(ucharbuf &buf, VSlot &dst, bool delta) { + while(buf.remaining()) { int changed = buf.get(); if(changed >= 0x80) break; - switch(changed) - { - case VSLOT_SHPARAM: - { + switch(changed) { + case VSLOT_SHPARAM: { string name; getstring(name, buf); SlotShaderParam p = { name[0] ? getshaderparamname(name) : NULL, -1, { 0, 0, 0, 0 } }; @@ -1929,8 +1658,7 @@ bool unpackvslot(ucharbuf &buf, VSlot &dst, bool delta) dst.scroll.x = getfloat(buf); dst.scroll.y = getfloat(buf); break; - case VSLOT_LAYER: - { + case VSLOT_LAYER: { int tex = getuint(buf); dst.layer = vslots.inrange(tex) ? tex : 0; break; @@ -1953,10 +1681,8 @@ bool unpackvslot(ucharbuf &buf, VSlot &dst, bool delta) return true; } -VSlot *findvslot(Slot &slot, const VSlot &src, const VSlot &delta) -{ - for(VSlot *dst = slot.variants; dst; dst = dst->next) - { +VSlot *findvslot(Slot &slot, const VSlot &src, const VSlot &delta) { + for(VSlot *dst = slot.variants; dst; dst = dst->next) { if((!dst->changed || dst->changed == (src.changed | delta.changed)) && comparevslot(*dst, src, src.changed & ~delta.changed) && comparevslot(*dst, delta, delta.changed)) @@ -1965,8 +1691,7 @@ VSlot *findvslot(Slot &slot, const VSlot &src, const VSlot &delta) return NULL; } -static VSlot *clonevslot(const VSlot &src, const VSlot &delta) -{ +static VSlot *clonevslot(const VSlot &src, const VSlot &delta) { VSlot *dst = vslots.add(new VSlot(src.slot, vslots.length())); dst->changed = src.changed | delta.changed; propagatevslot(*dst, src, ((1<<VSLOT_NUM)-1) & ~delta.changed); @@ -1976,28 +1701,23 @@ static VSlot *clonevslot(const VSlot &src, const VSlot &delta) VARP(autocompactvslots, 0, 256, 0x10000); -VSlot *editvslot(const VSlot &src, const VSlot &delta) -{ +VSlot *editvslot(const VSlot &src, const VSlot &delta) { VSlot *exists = findvslot(*src.slot, src, delta); if(exists) return exists; - if(vslots.length()>=0x10000) - { + if(vslots.length()>=0x10000) { compactvslots(); allchanged(); if(vslots.length()>=0x10000) return NULL; } - if(autocompactvslots && ++clonedvslots >= autocompactvslots) - { + if(autocompactvslots && ++clonedvslots >= autocompactvslots) { compactvslots(); allchanged(); } return clonevslot(src, delta); } -static void fixinsidefaces(cube *c, const ivec &o, int size, int tex) -{ - loopi(8) - { +static void fixinsidefaces(cube *c, const ivec &o, int size, int tex) { + loopi(8) { ivec co(i, o, size); if(c[i].children) fixinsidefaces(c[i].children, co, size>>1, tex); else loopj(6) if(!visibletris(c[i], j, co, size)) @@ -2005,40 +1725,35 @@ static void fixinsidefaces(cube *c, const ivec &o, int size, int tex) } } -ICOMMAND(fixinsidefaces, "i", (int *tex), -{ +ICOMMAND(fixinsidefaces, "i", (int *tex), { extern int nompedit; if(noedit(true) || (nompedit && multiplayer())) return; fixinsidefaces(worldroot, ivec(0, 0, 0), worldsize>>1, *tex && vslots.inrange(*tex) ? *tex : DEFAULT_GEOM); allchanged(); }); -const struct slottex -{ +const struct slottex { const char *name; int id; -} slottexs[] = -{ - {"c", TEX_DIFFUSE}, - {"u", TEX_UNKNOWN}, - {"d", TEX_DECAL}, - {"n", TEX_NORMAL}, - {"s", TEX_SPEC}, - {"z", TEX_DEPTH}, - {"a", TEX_ALPHA} +} slottexs[] = { + { + "c", TEX_DIFFUSE}, { + "u", TEX_UNKNOWN}, { + "d", TEX_DECAL}, { + "n", TEX_NORMAL}, { + "s", TEX_SPEC}, { + "z", TEX_DEPTH}, { + "a", TEX_ALPHA} }; -int findslottex(const char *name) -{ - loopi(sizeof(slottexs)/sizeof(slottex)) - { +int findslottex(const char *name) { + loopi(sizeof(slottexs)/sizeof(slottex)) { if(!strcmp(slottexs[i].name, name)) return slottexs[i].id; } return -1; } -void texture(char *type, char *name, int *rot, int *xoffset, int *yoffset, float *scale) -{ +void texture(char *type, char *name, int *rot, int *xoffset, int *yoffset, float *scale) { if(slots.length()>=0x10000) return; int tnum = findslottex(type); if(tnum<0) tnum = atoi(type); @@ -2052,8 +1767,7 @@ void texture(char *type, char *name, int *rot, int *xoffset, int *yoffset, float st.t = NULL; copystring(st.name, name); path(st.name); - if(tnum==TEX_DIFFUSE) - { + if(tnum==TEX_DIFFUSE) { setslotshader(s); VSlot &vs = *emptyvslot(s); vs.reset(); @@ -2066,8 +1780,7 @@ void texture(char *type, char *name, int *rot, int *xoffset, int *yoffset, float COMMAND(texture, "ssiiif"); -void texscroll(float *scrollS, float *scrollT) -{ +void texscroll(float *scrollS, float *scrollT) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->scroll = vec2(*scrollS, *scrollT).div(1000.0f); @@ -2075,8 +1788,7 @@ void texscroll(float *scrollS, float *scrollT) } COMMAND(texscroll, "ff"); -void texoffset_(int *xoffset, int *yoffset) -{ +void texoffset_(int *xoffset, int *yoffset) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->offset = ivec2(*xoffset, *yoffset).max(0); @@ -2084,8 +1796,7 @@ void texoffset_(int *xoffset, int *yoffset) } COMMANDN(texoffset, texoffset_, "ii"); -void texrotate_(int *rot) -{ +void texrotate_(int *rot) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->rotation = clamp(*rot, 0, 7); @@ -2093,8 +1804,7 @@ void texrotate_(int *rot) } COMMANDN(texrotate, texrotate_, "i"); -void texscale(float *scale) -{ +void texscale(float *scale) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->scale = *scale <= 0 ? 1 : *scale; @@ -2102,8 +1812,7 @@ void texscale(float *scale) } COMMAND(texscale, "f"); -void texlayer(int *layer, char *name, int *mode, float *scale) -{ +void texlayer(int *layer, char *name, int *mode, float *scale) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->layer = *layer < 0 ? max(slots.length()-1+*layer, 0) : *layer; @@ -2114,8 +1823,7 @@ void texlayer(int *layer, char *name, int *mode, float *scale) } COMMAND(texlayer, "isif"); -void texalpha(float *front, float *back) -{ +void texalpha(float *front, float *back) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->alphafront = clamp(*front, 0.0f, 1.0f); @@ -2124,8 +1832,7 @@ void texalpha(float *front, float *back) } COMMAND(texalpha, "ff"); -void texcolor(float *r, float *g, float *b) -{ +void texcolor(float *r, float *g, float *b) { if(slots.empty()) return; Slot &s = *slots.last(); s.variants->colorscale = vec(clamp(*r, 0.0f, 1.0f), clamp(*g, 0.0f, 1.0f), clamp(*b, 0.0f, 1.0f)); @@ -2133,48 +1840,40 @@ void texcolor(float *r, float *g, float *b) } COMMAND(texcolor, "fff"); -static int findtextype(Slot &s, int type, int last = -1) -{ +static int findtextype(Slot &s, int type, int last = -1) { for(int i = last+1; i<s.sts.length(); i++) if((type&(1<<s.sts[i].type)) && s.sts[i].combined<0) return i; return -1; } -static void mergespec(ImageData &c, ImageData &s) -{ +static void mergespec(ImageData &c, ImageData &s) { if(s.bpp < 3) { readwritergbatex(c, s, dst[3] = src[0]; ); } else { readwritergbatex(c, s, dst[3] = (int(src[0]) + int(src[1]) + int(src[2]))/3; ); } } -static void mergedepth(ImageData &c, ImageData &z) -{ +static void mergedepth(ImageData &c, ImageData &z) { readwritergbatex(c, z, dst[3] = src[0]; ); } -static void mergealpha(ImageData &c, ImageData &s) -{ +static void mergealpha(ImageData &c, ImageData &s) { if(s.bpp < 3) { readwritergbatex(c, s, dst[3] = src[0]; ); } else if(s.bpp == 3) { readwritergbatex(c, s, dst[3] = (int(src[0]) + int(src[1]) + int(src[2]))/3; ); } else { readwritergbatex(c, s, dst[3] = src[3]; ); } } -static void addname(vector<char> &key, Slot &slot, Slot::Tex &t, bool combined = false, const char *prefix = NULL) -{ +static void addname(vector<char> &key, Slot &slot, Slot::Tex &t, bool combined = false, const char *prefix = NULL) { if(combined) key.add('&'); if(prefix) { while(*prefix) key.add(*prefix++); } defformatstring(tname, "packages/%s", t.name); for(const char *s = path(tname); *s; key.add(*s++)); } -static void texcombine(Slot &s, int index, Slot::Tex &t, bool forceload = false) -{ +static void texcombine(Slot &s, int index, Slot::Tex &t, bool forceload = false) { vector<char> key; addname(key, s, t); int texmask = 0; - if(!forceload) switch(t.type) - { + if(!forceload) switch(t.type) { case TEX_DIFFUSE: - case TEX_NORMAL: - { + case TEX_NORMAL: { int i = findtextype(s, t.type==TEX_DIFFUSE ? (s.texmask&(1<<TEX_SPEC) ? 1<<TEX_SPEC : 1<<TEX_ALPHA) : (s.texmask&(1<<TEX_DEPTH) ? 1<<TEX_DEPTH : 1<<TEX_ALPHA)); if(i<0) break; texmask |= 1<<s.sts[i].type; @@ -2189,20 +1888,17 @@ static void texcombine(Slot &s, int index, Slot::Tex &t, bool forceload = false) int compress = 0, wrap = 0; ImageData ts; if(!texturedata(ts, NULL, &t, true, &compress, &wrap)) { t.t = notexture; return; } - if(!ts.compressed) switch(t.type) - { + if(!ts.compressed) switch(t.type) { case TEX_DIFFUSE: case TEX_NORMAL: - loopv(s.sts) - { + loopv(s.sts) { Slot::Tex &a = s.sts[i]; if(a.combined!=index) continue; ImageData as; if(!texturedata(as, NULL, &a)) continue; //if(ts.bpp!=4) forcergbaimage(ts); if(as.w!=ts.w || as.h!=ts.h) scaleimage(as, ts.w, ts.h); - switch(a.type) - { + switch(a.type) { case TEX_SPEC: mergespec(ts, as); break; case TEX_DEPTH: mergedepth(ts, as); break; case TEX_ALPHA: mergealpha(ts, as); break; @@ -2214,15 +1910,12 @@ static void texcombine(Slot &s, int index, Slot::Tex &t, bool forceload = false) t.t = newtexture(NULL, key.getbuf(), ts, wrap, true, true, true, compress); } -static Slot &loadslot(Slot &s, bool forceload) -{ +static Slot &loadslot(Slot &s, bool forceload) { linkslotshader(s); - loopv(s.sts) - { + loopv(s.sts) { Slot::Tex &t = s.sts[i]; if(t.combined >= 0) continue; - switch(t.type) - { + switch(t.type) { default: texcombine(s, i, t, forceload); break; @@ -2232,17 +1925,14 @@ static Slot &loadslot(Slot &s, bool forceload) return s; } -Slot &lookupslot(int index, bool load) -{ +Slot &lookupslot(int index, bool load) { Slot &s = slots.inrange(index) ? *slots[index] : (slots.inrange(DEFAULT_GEOM) ? *slots[DEFAULT_GEOM] : dummyslot); return s.loaded || !load ? s : loadslot(s, false); } -VSlot &lookupvslot(int index, bool load) -{ +VSlot &lookupvslot(int index, bool load) { VSlot &s = vslots.inrange(index) && vslots[index]->slot ? *vslots[index] : (slots.inrange(DEFAULT_GEOM) && slots[DEFAULT_GEOM]->variants ? *slots[DEFAULT_GEOM]->variants : dummyvslot); - if(load && !s.linked) - { + if(load && !s.linked) { if(!s.slot->loaded) loadslot(*s.slot, false); linkvslotshader(s); s.linked = true; @@ -2250,17 +1940,14 @@ VSlot &lookupvslot(int index, bool load) return s; } -void linkslotshaders() -{ +void linkslotshaders() { loopv(slots) if(slots[i]->loaded) linkslotshader(*slots[i]); loopv(vslots) if(vslots[i]->linked) linkvslotshader(*vslots[i]); } -Texture *loadthumbnail(Slot &slot) -{ +Texture *loadthumbnail(Slot &slot) { if(slot.thumbnail) return slot.thumbnail; - if(!slot.variants) - { + if(!slot.variants) { slot.thumbnail = notexture; return slot.thumbnail; } @@ -2269,17 +1956,14 @@ Texture *loadthumbnail(Slot &slot) linkvslotshader(vslot, false); vector<char> name; if(vslot.colorscale == vec(1, 1, 1)) addname(name, slot, slot.sts[0], false, "<thumbnail>"); - else - { + else { defformatstring(prefix, "<thumbnail:%.2f/%.2f/%.2f>", vslot.colorscale.x, vslot.colorscale.y, vslot.colorscale.z); addname(name, slot, slot.sts[0], false, prefix); } VSlot *layer = vslot.layer ? &lookupvslot(vslot.layer, false) : NULL; - if(layer) - { + if(layer) { if(layer->colorscale == vec(1, 1, 1)) addname(name, *layer->slot, layer->slot->sts[0], true, "<layer>"); - else - { + else { defformatstring(prefix, "<layer:%.2f/%.2f/%.2f>", vslot.colorscale.x, vslot.colorscale.y, vslot.colorscale.z); addname(name, *layer->slot, layer->slot->sts[0], true, prefix); } @@ -2287,30 +1971,25 @@ Texture *loadthumbnail(Slot &slot) name.add('\0'); Texture *t = textures.access(path(name.getbuf())); if(t) slot.thumbnail = t; - else - { + else { ImageData s, g, l; texturedata(s, NULL, &slot.sts[0], false); if(layer) texturedata(l, NULL, &layer->slot->sts[0], false); if(!s.data) t = slot.thumbnail = notexture; - else - { + else { if(vslot.colorscale != vec(1, 1, 1)) texmad(s, vslot.colorscale, vec(0, 0, 0)); int xs = s.w, ys = s.h; if(s.w > 64 || s.h > 64) scaleimage(s, min(s.w, 64), min(s.h, 64)); - if(g.data) - { + if(g.data) { if(g.w != s.w || g.h != s.h) scaleimage(g, s.w, s.h); } - if(l.data) - { + if(l.data) { if(layer->colorscale != vec(1, 1, 1)) texmad(l, layer->colorscale, vec(0, 0, 0)); if(l.w != s.w/2 || l.h != s.h/2) scaleimage(l, s.w/2, s.h/2); forcergbimage(s); forcergbimage(l); uchar *dstrow = &s.data[s.pitch*l.h + s.bpp*l.w], *srcrow = l.data; - loop(y, l.h) - { + loop(y, l.h) { for(uchar *dst = dstrow, *src = srcrow, *end = &srcrow[l.w*l.bpp]; src < end; dst += s.bpp, src += l.bpp) loopk(3) dst[k] = src[k]; dstrow += s.pitch; @@ -2327,13 +2006,10 @@ Texture *loadthumbnail(Slot &slot) return t; } -void loadlayermasks() -{ - loopv(slots) - { +void loadlayermasks() { + loopv(slots) { Slot &slot = *slots[i]; - if(slot.loaded && slot.layermaskname && !slot.layermask) - { + if(slot.loaded && slot.layermaskname && !slot.layermask) { slot.layermask = new ImageData; texturedata(*slot.layermask, slot.layermaskname); if(!slot.layermask->data) DELETEP(slot.layermask); @@ -2341,34 +2017,28 @@ void loadlayermasks() } } -void cleanuptexture(Texture *t) -{ +void cleanuptexture(Texture *t) { DELETEA(t->alphamask); if(t->id) { glDeleteTextures(1, &t->id); t->id = 0; } if(t->type&Texture::TRANSIENT) textures.remove(t->name); } -void cleanuptextures() -{ +void cleanuptextures() { loopv(slots) slots[i]->cleanup(); loopv(vslots) vslots[i]->cleanup(); enumerate(textures, Texture, tex, cleanuptexture(&tex)); } -bool reloadtexture(const char *name) -{ +bool reloadtexture(const char *name) { Texture *t = textures.access(path(name, true)); if(t) return reloadtexture(*t); return true; } -bool reloadtexture(Texture &tex) -{ +bool reloadtexture(Texture &tex) { if(tex.id) return true; - switch(tex.type&Texture::TYPE) - { - case Texture::IMAGE: - { + switch(tex.type&Texture::TYPE) { + case Texture::IMAGE: { int compress = 0; ImageData s; if(!texturedata(s, tex.name, NULL, true, &compress) || !newtexture(&tex, NULL, s, tex.clamp, tex.mipmap, false, false, compress)) return false; @@ -2378,16 +2048,14 @@ bool reloadtexture(Texture &tex) return true; } -void reloadtex(char *name) -{ +void reloadtex(char *name) { Texture *t = textures.access(path(name, true)); if(!t) { conoutf(CON_ERROR, "texture %s is not loaded", name); return; } if(t->type&Texture::TRANSIENT) { conoutf(CON_ERROR, "can't reload transient texture %s", name); return; } DELETEA(t->alphamask); Texture oldtex = *t; t->id = 0; - if(!reloadtexture(*t)) - { + if(!reloadtexture(*t)) { if(t->id) glDeleteTextures(1, &t->id); *t = oldtex; conoutf(CON_ERROR, "failed to reload texture %s", name); @@ -2396,23 +2064,19 @@ void reloadtex(char *name) COMMAND(reloadtex, "s"); -void reloadtextures() -{ +void reloadtextures() { int reloaded = 0; - enumerate(textures, Texture, tex, - { + enumerate(textures, Texture, tex, { loadprogress = float(++reloaded)/textures.numelems; reloadtexture(tex); }); loadprogress = 0; } -void writepngchunk(stream *f, const char *type, uchar *data = NULL, uint len = 0) -{ +void writepngchunk(stream *f, const char *type, uchar *data = NULL, uint len = 0) { f->putbig<uint>(len); f->write(type, 4); f->write(data, len); - uint crc = crc32(0, Z_NULL, 0); crc = crc32(crc, (const Bytef *)type, 4); if(data) crc = crc32(crc, data, len); @@ -2421,11 +2085,9 @@ void writepngchunk(stream *f, const char *type, uchar *data = NULL, uint len = 0 VARP(compresspng, 0, 9, 9); -void savepng(const char *filename, ImageData &image, bool flip) -{ +void savepng(const char *filename, ImageData &image, bool flip) { uchar ctype = 0; - switch(image.bpp) - { + switch(image.bpp) { case 1: ctype = 0; break; case 2: ctype = 4; break; case 3: ctype = 2; break; @@ -2434,44 +2096,33 @@ void savepng(const char *filename, ImageData &image, bool flip) } stream *f = openfile(filename, "wb"); if(!f) { conoutf(CON_ERROR, "could not write to %s", filename); return; } - uchar signature[] = { 137, 80, 78, 71, 13, 10, 26, 10 }; f->write(signature, sizeof(signature)); - - struct pngihdr - { + struct pngihdr { uint width, height; uchar bitdepth, colortype, compress, filter, interlace; } ihdr = { bigswap<uint>(image.w), bigswap<uint>(image.h), 8, ctype, 0, 0, 0 }; writepngchunk(f, "IHDR", (uchar *)&ihdr, 13); - stream::offset idat = f->tell(); uint len = 0; f->write("\0\0\0\0IDAT", 8); uint crc = crc32(0, Z_NULL, 0); crc = crc32(crc, (const Bytef *)"IDAT", 4); - z_stream z; z.zalloc = NULL; z.zfree = NULL; z.opaque = NULL; - if(deflateInit(&z, compresspng) != Z_OK) goto error; - uchar buf[1<<12]; z.next_out = (Bytef *)buf; z.avail_out = sizeof(buf); - - loopi(image.h) - { + loopi(image.h) { uchar filter = 0; - loopj(2) - { + loopj(2) { z.next_in = j ? (Bytef *)image.data + (flip ? image.h-i-1 : i)*image.pitch : (Bytef *)&filter; z.avail_in = j ? image.w*image.bpp : 1; - while(z.avail_in > 0) - { + while(z.avail_in > 0) { if(deflate(&z, Z_NO_FLUSH) != Z_OK) goto cleanuperror; #define FLUSHZ do { \ int flush = sizeof(buf) - z.avail_out; \ @@ -2485,24 +2136,18 @@ void savepng(const char *filename, ImageData &image, bool flip) } } } - - for(;;) - { + for(;;) { int err = deflate(&z, Z_FINISH); if(err != Z_OK && err != Z_STREAM_END) goto cleanuperror; FLUSHZ; if(err == Z_STREAM_END) break; } - deflateEnd(&z); - f->seek(idat, SEEK_SET); f->putbig<uint>(len); f->seek(0, SEEK_END); f->putbig<uint>(crc); - writepngchunk(f, "IEND"); - delete f; return; @@ -2511,7 +2156,6 @@ cleanuperror: error: delete f; - conoutf(CON_ERROR, "failed saving png to %s", filename); } @@ -2522,31 +2166,25 @@ VARP(screenshotformat, 0, IMG_PNG, NUMIMG-1); const char *imageexts[NUMIMG] = { ".bmp", ".png", ".jpg" }; -int guessimageformat(const char *filename, int format = IMG_BMP) -{ +int guessimageformat(const char *filename, int format = IMG_BMP) { int len = strlen(filename); - loopi(NUMIMG) - { + loopi(NUMIMG) { int extlen = strlen(imageexts[i]); if(len >= extlen && !strcasecmp(&filename[len-extlen], imageexts[i])) return i; } return format; } -void saveimage(const char *filename, int format, ImageData &image, bool flip = false) -{ - switch(format) - { +void saveimage(const char *filename, int format, ImageData &image, bool flip = false) { + switch(format) { case IMG_PNG: savepng(filename, image, flip); break; - default: - { + default: { ImageData flipped(image.w, image.h, image.bpp, image.data); if(flip) texflip(flipped); SDL_Surface *s = wrapsurface(flipped.data, flipped.w, flipped.h, flipped.bpp); if(!s) break; stream *f = openfile(filename, "wb"); - if(f) - { + if(f) { switch(format) { case IMG_JPG: #if SDL_IMAGE_VERSION_ATLEAST(2, 0, 2) @@ -2565,8 +2203,7 @@ void saveimage(const char *filename, int format, ImageData &image, bool flip = f } } -bool loadimage(const char *filename, ImageData &image) -{ +bool loadimage(const char *filename, ImageData &image) { SDL_Surface *s = loadsurface(path(filename, true)); if(!s) return false; image.wrap(s); @@ -2575,51 +2212,41 @@ bool loadimage(const char *filename, ImageData &image) SVARP(screenshotdir, "screenshot"); -void screenshot(char *filename) -{ +void screenshot(char *filename) { static string buf; int format = -1, dirlen = 0; copystring(buf, screenshotdir); - if(screenshotdir[0]) - { + if(screenshotdir[0]) { dirlen = strlen(buf); if(buf[dirlen] != '/' && buf[dirlen] != '\\' && dirlen+1 < (int)sizeof(buf)) { buf[dirlen++] = '/'; buf[dirlen] = '\0'; } const char *dir = findfile(buf, "w"); if(!fileexists(dir, "w")) createdir(dir); } - if(filename[0]) - { + if(filename[0]) { concatstring(buf, filename); format = guessimageformat(buf, -1); } - else - { + else { string sstime; time_t t = time(NULL); size_t len = strftime(sstime, sizeof(sstime), "%Y-%m-%d_%H.%M.%S", localtime(&t)); sstime[min(len, sizeof(sstime)-1)] = '\0'; concatstring(buf, sstime); - const char *map = game::getclientmap(), *ssinfo = game::getscreenshotinfo(); - if(map && map[0]) - { + if(map && map[0]) { concatstring(buf, "_"); concatstring(buf, map); } - if(ssinfo && ssinfo[0]) - { + if(ssinfo && ssinfo[0]) { concatstring(buf, "_"); concatstring(buf, ssinfo); } - for(char *s = &buf[dirlen]; *s; s++) if(iscubespace(*s) || *s == '/' || *s == '\\') *s = '-'; } - if(format < 0) - { + if(format < 0) { format = screenshotformat; concatstring(buf, imageexts[format]); } - ImageData image(screenw, screenh, 3); glPixelStorei(GL_PACK_ALIGNMENT, texalign(image.data, screenw, 3)); glReadPixels(0, 0, screenw, screenh, GL_RGB, GL_UNSIGNED_BYTE, image.data); diff --git a/src/engine/texture.h b/src/engine/texture.h index 3679931..ef5a57b 100644 --- a/src/engine/texture.h +++ b/src/engine/texture.h @@ -1,43 +1,31 @@ -struct GlobalShaderParamState -{ +struct GlobalShaderParamState { const char *name; - union - { + union { float fval[32]; int ival[32]; uint uval[32]; uchar buf[32*sizeof(float)]; }; int version; - static int nextversion; - void resetversions(); - - void changed() - { + void changed() { if(++nextversion < 0) resetversions(); version = nextversion; } }; -struct ShaderParamBinding -{ +struct ShaderParamBinding { int loc, size; GLenum format; }; -struct GlobalShaderParamUse : ShaderParamBinding -{ - +struct GlobalShaderParamUse : ShaderParamBinding { GlobalShaderParamState *param; int version; - - void flush() - { + void flush() { if(version == param->version) return; - switch(format) - { + switch(format) { case GL_BOOL: case GL_FLOAT: glUniform1fv_(loc, size, param->fval); break; case GL_BOOL_VEC2: @@ -58,25 +46,20 @@ struct GlobalShaderParamUse : ShaderParamBinding } }; -struct LocalShaderParamState : ShaderParamBinding -{ +struct LocalShaderParamState : ShaderParamBinding { const char *name; }; -struct SlotShaderParam -{ +struct SlotShaderParam { const char *name; int loc; float val[4]; }; -struct SlotShaderParamState : LocalShaderParamState -{ +struct SlotShaderParamState : LocalShaderParamState { float val[4]; - SlotShaderParamState() {} - SlotShaderParamState(const SlotShaderParam &p) - { + SlotShaderParamState(const SlotShaderParam &p) { name = p.name; loc = -1; size = 1; @@ -85,12 +68,10 @@ struct SlotShaderParamState : LocalShaderParamState } }; -enum -{ +enum { SHADER_DEFAULT = 0, SHADER_NORMALSLMS = 1<<0, SHADER_OPTION = 1<<3, - SHADER_INVALID = 1<<8, SHADER_DEFERRED = 1<<9 }; @@ -103,25 +84,21 @@ extern int shaderdetail; struct Slot; struct VSlot; -struct UniformLoc -{ +struct UniformLoc { const char *name, *blockname; int loc, version, binding, stride, offset, size; void *data; UniformLoc(const char *name = NULL, const char *blockname = NULL, int binding = -1, int stride = -1) : name(name), blockname(blockname), loc(-1), version(-1), binding(binding), stride(stride), offset(-1), size(-1), data(NULL) {} }; -struct AttribLoc -{ +struct AttribLoc { const char *name; int loc; AttribLoc(const char *name = NULL, int loc = -1) : name(name), loc(loc) {} }; -struct Shader -{ +struct Shader { static Shader *lastshader; - char *name, *vsstr, *psstr, *defer; int type; GLuint program, vsobj, psobj; @@ -137,161 +114,115 @@ struct Shader vector<UniformLoc> uniformlocs; vector<AttribLoc> attriblocs; const void *owner; - - Shader() : name(NULL), vsstr(NULL), psstr(NULL), defer(NULL), type(SHADER_DEFAULT), program(0), vsobj(0), psobj(0), detailshader(NULL), variantshader(NULL), altshader(NULL), variantrows(NULL), standard(false), forced(false), used(false), reusevs(NULL), reuseps(NULL), owner(NULL) - { + Shader() : name(NULL), vsstr(NULL), psstr(NULL), defer(NULL), type(SHADER_DEFAULT), program(0), vsobj(0), psobj(0), detailshader(NULL), variantshader(NULL), altshader(NULL), variantrows(NULL), standard(false), forced(false), used(false), reusevs(NULL), reuseps(NULL), owner(NULL) { loopi(MAXSHADERDETAIL) fastshader[i] = this; } - - ~Shader() - { + ~Shader() { DELETEA(name); DELETEA(vsstr); DELETEA(psstr); DELETEA(defer); DELETEA(variantrows); } - void fixdetailshader(bool force = true, bool recurse = true); void allocparams(Slot *slot = NULL); void setslotparams(Slot &slot); void setslotparams(Slot &slot, VSlot &vslot); void bindprograms(); - - void flushparams(Slot *slot = NULL) - { + void flushparams(Slot *slot = NULL) { if(!used) { allocparams(slot); used = true; } loopv(globalparams) globalparams[i].flush(); } - void force(); - bool invalid() const { return (type&SHADER_INVALID)!=0; } bool deferred() const { return (type&SHADER_DEFERRED)!=0; } bool loaded() const { return detailshader!=NULL; } - static bool isnull(const Shader *s); - bool isnull() const { return isnull(this); } - - int numvariants(int row) const - { + int numvariants(int row) const { if(row < 0 || row >= MAXVARIANTROWS || !variantrows) return 0; return variantrows[row+1] - variantrows[row]; } - - Shader *getvariant(int col, int row) const - { + Shader *getvariant(int col, int row) const { if(row < 0 || row >= MAXVARIANTROWS || col < 0 || !variantrows) return NULL; int start = variantrows[row], end = variantrows[row+1]; return col < end - start ? variants[start + col] : NULL; } - - bool hasoption(int row) - { - if(detailshader) - { + bool hasoption(int row) { + if(detailshader) { Shader *s = getvariant(0, row); if(s) return (s->type&SHADER_OPTION)!=0; } return false; } - - void addvariant(int row, Shader *s) - { + void addvariant(int row, Shader *s) { if(row < 0 || row >= MAXVARIANTROWS || variants.length() >= USHRT_MAX) return; if(!variantrows) { variantrows = new ushort[MAXVARIANTROWS+1]; memset(variantrows, 0, (MAXVARIANTROWS+1)*sizeof(ushort)); } variants.insert(variantrows[row+1], s); for(int i = row+1; i <= MAXVARIANTROWS; ++i) ++variantrows[i]; } - - void setvariant_(int col, int row, Shader *fallbackshader) - { + void setvariant_(int col, int row, Shader *fallbackshader) { Shader *s = fallbackshader; - if(detailshader->variantrows) - { + if(detailshader->variantrows) { int start = detailshader->variantrows[row], end = detailshader->variantrows[row+1]; - for(col = min(start + col, end-1); col >= start; --col) - { + for(col = min(start + col, end-1); col >= start; --col) { if(!detailshader->variants[col]->invalid()) { s = detailshader->variants[col]; break; } } } if(lastshader!=s) s->bindprograms(); } - - void setvariant(int col, int row, Shader *fallbackshader) - { + void setvariant(int col, int row, Shader *fallbackshader) { if(isnull() || !loaded()) return; setvariant_(col, row, fallbackshader); lastshader->flushparams(); } - - void setvariant(int col, int row) - { + void setvariant(int col, int row) { if(isnull() || !loaded()) return; setvariant_(col, row, detailshader); lastshader->flushparams(); } - - void setvariant(int col, int row, Slot &slot, VSlot &vslot, Shader *fallbackshader) - { + void setvariant(int col, int row, Slot &slot, VSlot &vslot, Shader *fallbackshader) { if(isnull() || !loaded()) return; setvariant_(col, row, fallbackshader); lastshader->flushparams(&slot); lastshader->setslotparams(slot, vslot); } - - void setvariant(int col, int row, Slot &slot, VSlot &vslot) - { + void setvariant(int col, int row, Slot &slot, VSlot &vslot) { if(isnull() || !loaded()) return; setvariant_(col, row, detailshader); lastshader->flushparams(&slot); lastshader->setslotparams(slot, vslot); } - - void set_() - { + void set_() { if(lastshader!=detailshader) detailshader->bindprograms(); } - - void set() - { + void set() { if(isnull() || !loaded()) return; set_(); lastshader->flushparams(); } - - void set(Slot &slot, VSlot &vslot) - { + void set(Slot &slot, VSlot &vslot) { if(isnull() || !loaded()) return; set_(); lastshader->flushparams(&slot); lastshader->setslotparams(slot, vslot); } - bool compile(); void cleanup(bool invalid = false); - static int uniformlocversion(); }; -struct GlobalShaderParam -{ +struct GlobalShaderParam { const char *name; GlobalShaderParamState *param; - GlobalShaderParam(const char *name) : name(name), param(NULL) {} - - GlobalShaderParamState *resolve() - { + GlobalShaderParamState *resolve() { extern GlobalShaderParamState *getglobalparam(const char *name); if(!param) param = getglobalparam(name); param->changed(); return param; } - - void setf(float x = 0, float y = 0, float z = 0, float w = 0) - { + void setf(float x = 0, float y = 0, float z = 0, float w = 0) { GlobalShaderParamState *g = resolve(); g->fval[0] = x; g->fval[1] = y; @@ -305,12 +236,9 @@ struct GlobalShaderParam void set(const matrix2 &m) { memcpy(resolve()->fval, m.a.v, sizeof(m)); } void set(const matrix3 &m) { memcpy(resolve()->fval, m.a.v, sizeof(m)); } void set(const matrix4 &m) { memcpy(resolve()->fval, m.a.v, sizeof(m)); } - template<class T> void setv(const T *v, int n = 1) { memcpy(resolve()->buf, v, n*sizeof(T)); } - - void seti(int x = 0, int y = 0, int z = 0, int w = 0) - { + void seti(int x = 0, int y = 0, int z = 0, int w = 0) { GlobalShaderParamState *g = resolve(); g->ival[0] = x; g->ival[1] = y; @@ -320,33 +248,25 @@ struct GlobalShaderParam void set(const ivec &v, int w = 0) { seti(v.x, v.y, v.z, w); } void set(const ivec2 &v, int z = 0, int w = 0) { seti(v.x, v.y, z, w); } void set(const ivec4 &v) { seti(v.x, v.y, v.z, v.w); } - - void setu(uint x = 0, uint y = 0, uint z = 0, uint w = 0) - { + void setu(uint x = 0, uint y = 0, uint z = 0, uint w = 0) { GlobalShaderParamState *g = resolve(); g->uval[0] = x; g->uval[1] = y; g->uval[2] = z; g->uval[3] = w; } - template<class T> T *reserve(int n = 1) { return (T *)resolve()->buf; } }; -struct LocalShaderParam -{ +struct LocalShaderParam { const char *name; int loc; - LocalShaderParam(const char *name) : name(name), loc(-1) {} - - LocalShaderParamState *resolve() - { + LocalShaderParamState *resolve() { Shader *s = Shader::lastshader; if(!s) return NULL; - if(!s->localparamremap.inrange(loc)) - { + if(!s->localparamremap.inrange(loc)) { extern int getlocalparam(const char *name); if(loc == -1) loc = getlocalparam(name); if(!s->localparamremap.inrange(loc)) return NULL; @@ -354,12 +274,9 @@ struct LocalShaderParam uchar remap = s->localparamremap[loc]; return s->localparams.inrange(remap) ? &s->localparams[remap] : NULL; } - - void setf(float x = 0, float y = 0, float z = 0, float w = 0) - { + void setf(float x = 0, float y = 0, float z = 0, float w = 0) { ShaderParamBinding *b = resolve(); - if(b) switch(b->format) - { + if(b) switch(b->format) { case GL_BOOL: case GL_FLOAT: glUniform1f_(b->loc, x); break; case GL_BOOL_VEC2: @@ -389,13 +306,10 @@ struct LocalShaderParam void set(const matrix2 &m) { setv(&m); } void set(const matrix3 &m) { setv(&m); } void set(const matrix4 &m) { setv(&m); } - template<class T> - void sett(T x, T y, T z, T w) - { + void sett(T x, T y, T z, T w) { ShaderParamBinding *b = resolve(); - if(b) switch(b->format) - { + if(b) switch(b->format) { case GL_FLOAT: glUniform1f_(b->loc, x); break; case GL_FLOAT_VEC2: glUniform2f_(b->loc, x, y); break; case GL_FLOAT_VEC3: glUniform3f_(b->loc, x, y, z); break; @@ -442,35 +356,26 @@ struct LocalShaderParam name##shader->setvariant(__VA_ARGS__); \ } while(0) -struct ImageData -{ +struct ImageData { int w, h, bpp, levels, align, pitch; GLenum compressed; uchar *data; void *owner; void (*freefunc)(void *); - ImageData() - : data(NULL), owner(NULL), freefunc(NULL) - {} - + : data(NULL), owner(NULL), freefunc(NULL) { + } - ImageData(int nw, int nh, int nbpp, int nlevels = 1, int nalign = 0, GLenum ncompressed = GL_FALSE) - { + ImageData(int nw, int nh, int nbpp, int nlevels = 1, int nalign = 0, GLenum ncompressed = GL_FALSE) { setdata(NULL, nw, nh, nbpp, nlevels, nalign, ncompressed); } - ImageData(int nw, int nh, int nbpp, uchar *data) - : owner(NULL), freefunc(NULL) - { + : owner(NULL), freefunc(NULL) { setdata(data, nw, nh, nbpp); } - ImageData(SDL_Surface *s) { wrap(s); } ~ImageData() { cleanup(); } - - void setdata(uchar *ndata, int nw, int nh, int nbpp, int nlevels = 1, int nalign = 0, GLenum ncompressed = GL_FALSE) - { + void setdata(uchar *ndata, int nw, int nh, int nbpp, int nlevels = 1, int nalign = 0, GLenum ncompressed = GL_FALSE) { w = nw; h = nh; bpp = nbpp; @@ -481,16 +386,12 @@ struct ImageData data = ndata ? ndata : new uchar[calcsize()]; if(!ndata) { owner = this; freefunc = NULL; } } - int calclevelsize(int level) const { return ((max(w>>level, 1)+align-1)/align)*((max(h>>level, 1)+align-1)/align)*bpp; } - - int calcsize() const - { + int calcsize() const { if(!align) return w*h*bpp; int lw = w, lh = h, size = 0; - loopi(levels) - { + loopi(levels) { if(lw<=0) lw = 1; if(lh<=0) lh = 1; size += ((lw+align-1)/align)*((lh+align-1)/align)*bpp; @@ -500,31 +401,23 @@ struct ImageData } return size; } - - void disown() - { + void disown() { data = NULL; owner = NULL; freefunc = NULL; } - - void cleanup() - { + void cleanup() { if(owner==this) delete[] data; else if(freefunc) (*freefunc)(owner); disown(); } - - void replace(ImageData &d) - { + void replace(ImageData &d) { cleanup(); *this = d; if(owner == &d) owner = this; d.disown(); } - - void wrap(SDL_Surface *s) - { + void wrap(SDL_Surface *s) { setdata((uchar *)s->pixels, s->w, s->h, s->format->BytesPerPixel); pitch = s->pitch; owner = s; @@ -536,14 +429,11 @@ struct ImageData // each texture slot can have multiple texture frames, of which currently only the first is used // additional frames can be used for various shaders -struct Texture -{ - enum - { +struct Texture { + enum { IMAGE = 0, CUBEMAP = 1, TYPE = 0xFF, - STUB = 1<<8, TRANSIENT = 1<<9, COMPRESSED = 1<<10, @@ -551,18 +441,15 @@ struct Texture MIRROR = 1<<12, FLAGS = 0xFF00 }; - char *name; int type, w, h, xs, ys, bpp, clamp; bool mipmap, canreduce; GLuint id; uchar *alphamask; - Texture() : alphamask(NULL) {} }; -enum -{ +enum { TEX_DIFFUSE = 0, TEX_UNKNOWN, TEX_DECAL, @@ -572,8 +459,7 @@ enum TEX_ALPHA }; -enum -{ +enum { VSLOT_SHPARAM = 0, VSLOT_SCALE, VSLOT_ROTATION, @@ -585,8 +471,7 @@ enum VSLOT_NUM }; -struct VSlot -{ +struct VSlot { Slot *slot; VSlot *next; int index, changed; @@ -599,17 +484,12 @@ struct VSlot int layer; float alphafront, alphaback; vec colorscale; - - VSlot(Slot *slot = NULL, int index = -1) : slot(slot), next(NULL), index(index), changed(0) - { + VSlot(Slot *slot = NULL, int index = -1) : slot(slot), next(NULL), index(index), changed(0) { reset(); if(slot) addvariant(slot); } - void addvariant(Slot *slot); - - void reset() - { + void reset() { params.shrink(0); linked = false; scale = 1; @@ -621,23 +501,18 @@ struct VSlot alphaback = 0; colorscale = vec(1, 1, 1); } - - void cleanup() - { + void cleanup() { linked = false; } }; -struct Slot -{ - struct Tex - { +struct Slot { + struct Tex { int type; Texture *t; string name; int combined; }; - int index; vector<Tex> sts; Shader *shader; @@ -650,11 +525,8 @@ struct Slot int layermaskmode; float layermaskscale; ImageData *layermask; - Slot(int index = -1) : index(index), variants(NULL), layermaskname(NULL), layermask(NULL) { reset(); } - - void reset() - { + void reset() { sts.shrink(0); shader = NULL; params.shrink(0); @@ -666,13 +538,10 @@ struct Slot layermaskscale = 1; if(layermask) DELETEP(layermask); } - - void cleanup() - { + void cleanup() { loaded = false; thumbnail = NULL; - loopv(sts) - { + loopv(sts) { Tex &t = sts[i]; t.t = NULL; t.combined = -1; @@ -680,41 +549,32 @@ struct Slot } }; -inline void VSlot::addvariant(Slot *slot) -{ +inline void VSlot::addvariant(Slot *slot) { if(!slot->variants) slot->variants = this; - else - { + else { VSlot *prev = slot->variants; while(prev->next) prev = prev->next; prev->next = this; } } -struct MSlot : Slot, VSlot -{ +struct MSlot : Slot, VSlot { MSlot() : VSlot(this) {} - - void reset() - { + void reset() { Slot::reset(); VSlot::reset(); } - - void cleanup() - { + void cleanup() { Slot::cleanup(); VSlot::cleanup(); } }; -struct texrotation -{ +struct texrotation { bool flipx, flipy, swapxy; }; -struct cubemapside -{ +struct cubemapside { GLenum target; const char *name; bool flipx, flipy, swapxy; diff --git a/src/engine/vertmodel.h b/src/engine/vertmodel.h deleted file mode 100644 index e9af1b0..0000000 --- a/src/engine/vertmodel.h +++ /dev/null @@ -1,490 +0,0 @@ -struct vertmodel : animmodel -{ - struct vert { vec pos, norm; }; - struct vvert { vec pos; vec2 tc; }; - struct vvertn : vvert { vec norm; }; - struct vvertbump : vvert { squat tangent; }; - struct tcvert { vec2 tc; }; - struct bumpvert { vec4 tangent; }; - struct tri { ushort vert[3]; }; - - struct vbocacheentry - { - GLuint vbuf; - animstate as; - int millis; - - vbocacheentry() : vbuf(0) { as.cur.fr1 = as.prev.fr1 = -1; } - }; - - struct vertmesh : mesh - { - vert *verts; - tcvert *tcverts; - bumpvert *bumpverts; - tri *tris; - int numverts, numtris; - - int voffset, eoffset, elen; - ushort minvert, maxvert; - - vertmesh() : verts(0), tcverts(0), bumpverts(0), tris(0) - { - } - - virtual ~vertmesh() - { - DELETEA(verts); - DELETEA(tcverts); - DELETEA(bumpverts); - DELETEA(tris); - } - - void smoothnorms(float limit = 0, bool areaweight = true) - { - if(((vertmeshgroup *)group)->numframes == 1) mesh::smoothnorms(verts, numverts, tris, numtris, limit, areaweight); - else buildnorms(areaweight); - } - - void buildnorms(bool areaweight = true) - { - mesh::buildnorms(verts, numverts, tris, numtris, areaweight, ((vertmeshgroup *)group)->numframes); - } - - void calctangents(bool areaweight = true) - { - if(bumpverts) return; - bumpverts = new bumpvert[((vertmeshgroup *)group)->numframes*numverts]; - mesh::calctangents(bumpverts, verts, tcverts, numverts, tris, numtris, areaweight, ((vertmeshgroup *)group)->numframes); - } - - void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) - { - loopj(numverts) - { - vec v = m.transform(verts[j].pos); - loopi(3) - { - bbmin[i] = min(bbmin[i], v[i]); - bbmax[i] = max(bbmax[i], v[i]); - } - } - } - - void genBIH(BIH::mesh &m) - { - m.tris = (const BIH::tri *)tris; - m.numtris = numtris; - m.pos = (const uchar *)&verts->pos; - m.posstride = sizeof(vert); - m.tc = (const uchar *)&tcverts->tc; - m.tcstride = sizeof(tcvert); - } - - static inline void assignvert(vvertn &vv, int j, tcvert &tc, vert &v) - { - vv.pos = v.pos; - vv.norm = v.norm; - vv.tc = tc.tc; - } - - inline void assignvert(vvertbump &vv, int j, tcvert &tc, vert &v) - { - vv.pos = v.pos; - vv.tc = tc.tc; - vv.tangent = bumpverts[j].tangent; - } - - template<class T> - int genvbo(vector<ushort> &idxs, int offset, vector<T> &vverts, int *htdata, int htlen) - { - voffset = offset; - eoffset = idxs.length(); - minvert = 0xFFFF; - loopi(numtris) - { - tri &t = tris[i]; - loopj(3) - { - int index = t.vert[j]; - tcvert &tc = tcverts[index]; - vert &v = verts[index]; - T vv; - assignvert(vv, index, tc, v); - int htidx = hthash(v.pos)&(htlen-1); - loopk(htlen) - { - int &vidx = htdata[(htidx+k)&(htlen-1)]; - if(vidx < 0) { vidx = idxs.add(ushort(vverts.length())); vverts.add(vv); break; } - else if(!memcmp(&vverts[vidx], &vv, sizeof(vv))) { minvert = min(minvert, idxs.add(ushort(vidx))); break; } - } - } - } - minvert = min(minvert, ushort(voffset)); - maxvert = max(minvert, ushort(vverts.length()-1)); - elen = idxs.length()-eoffset; - return vverts.length()-voffset; - } - - int genvbo(vector<ushort> &idxs, int offset) - { - voffset = offset; - eoffset = idxs.length(); - loopi(numtris) - { - tri &t = tris[i]; - loopj(3) idxs.add(voffset+t.vert[j]); - } - minvert = voffset; - maxvert = voffset + numverts-1; - elen = idxs.length()-eoffset; - return numverts; - } - - template<class T> - static inline void fillvert(T &vv, int j, tcvert &tc, vert &v) - { - vv.tc = tc.tc; - } - - template<class T> - void fillverts(T *vdata) - { - vdata += voffset; - loopi(numverts) fillvert(vdata[i], i, tcverts[i], verts[i]); - } - - void interpverts(const animstate &as, bool tangents, void * RESTRICT vdata, skin &s) - { - const vert * RESTRICT vert1 = &verts[as.cur.fr1 * numverts], - * RESTRICT vert2 = &verts[as.cur.fr2 * numverts], - * RESTRICT pvert1 = as.interp<1 ? &verts[as.prev.fr1 * numverts] : NULL, - * RESTRICT pvert2 = as.interp<1 ? &verts[as.prev.fr2 * numverts] : NULL; - #define ipvert(attrib) v.attrib.lerp(vert1[i].attrib, vert2[i].attrib, as.cur.t) - #define ipbvert(attrib, type) v.attrib.lerp(bvert1[i].attrib, bvert2[i].attrib, as.cur.t) - #define ipvertp(attrib) v.attrib.lerp(pvert1[i].attrib, pvert2[i].attrib, as.prev.t).lerp(vec().lerp(vert1[i].attrib, vert2[i].attrib, as.cur.t), as.interp) - #define ipbvertp(attrib, type) v.attrib.lerp(type().lerp(bpvert1[i].attrib, bpvert2[i].attrib, as.prev.t), type().lerp(bvert1[i].attrib, bvert2[i].attrib, as.cur.t), as.interp) - #define iploop(type, body) \ - loopi(numverts) \ - { \ - type &v = ((type * RESTRICT)vdata)[i]; \ - body; \ - } - if(tangents) - { - const bumpvert * RESTRICT bvert1 = &bumpverts[as.cur.fr1 * numverts], - * RESTRICT bvert2 = &bumpverts[as.cur.fr2 * numverts], - * RESTRICT bpvert1 = as.interp<1 ? &bumpverts[as.prev.fr1 * numverts] : NULL, - * RESTRICT bpvert2 = as.interp<1 ? &bumpverts[as.prev.fr2 * numverts] : NULL; - if(as.interp<1) iploop(vvertbump, { ipvertp(pos); ipbvertp(tangent, vec4); }) - else iploop(vvertbump, { ipvert(pos); ipbvert(tangent, vec4); }) - } - else - { - if(as.interp<1) iploop(vvertn, { ipvertp(pos); ipvertp(norm); }) - else iploop(vvertn, { ipvert(pos); ipvert(norm); }) - } - #undef iploop - #undef ipvert - #undef ipbvert - #undef ipvertp - #undef ipbvertp - } - - void render(const animstate *as, skin &s, vbocacheentry &vc) - { - if(!Shader::lastshader) return; - glDrawRangeElements_(GL_TRIANGLES, minvert, maxvert, elen, GL_UNSIGNED_SHORT, &((vertmeshgroup *)group)->edata[eoffset]); - glde++; - xtravertsva += numverts; - } - }; - - struct tag - { - char *name; - matrix4x3 transform; - - tag() : name(NULL) {} - ~tag() { DELETEA(name); } - }; - - struct vertmeshgroup : meshgroup - { - int numframes; - tag *tags; - int numtags; - - static const int MAXVBOCACHE = 16; - vbocacheentry vbocache[MAXVBOCACHE]; - - ushort *edata; - GLuint ebuf; - bool vtangents; - int vlen, vertsize; - uchar *vdata; - - vertmeshgroup() : numframes(0), tags(NULL), numtags(0), edata(NULL), ebuf(0), vtangents(false), vlen(0), vertsize(0), vdata(NULL) - { - } - - virtual ~vertmeshgroup() - { - DELETEA(tags); - if(ebuf) glDeleteBuffers_(1, &ebuf); - loopi(MAXVBOCACHE) - { - if(vbocache[i].vbuf) glDeleteBuffers_(1, &vbocache[i].vbuf); - } - DELETEA(vdata); - } - - int findtag(const char *name) - { - loopi(numtags) if(!strcmp(tags[i].name, name)) return i; - return -1; - } - - int totalframes() const { return numframes; } - - void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) - { - n.mul(m, tags[numtags + i].transform); - n.posttranslate(m.transformnormal(p->translate), p->model->scale); - } - - void calctagmatrix(part *p, int i, const animstate &as, matrix4 &matrix) - { - const matrix4x3 &tag1 = tags[as.cur.fr1*numtags + i].transform, - &tag2 = tags[as.cur.fr2*numtags + i].transform; - matrix4x3 tag; - tag.lerp(tag1, tag2, as.cur.t); - if(as.interp<1) - { - const matrix4x3 &tag1p = tags[as.prev.fr1*numtags + i].transform, - &tag2p = tags[as.prev.fr2*numtags + i].transform; - matrix4x3 tagp; - tagp.lerp(tag1p, tag2p, as.prev.t); - tag.lerp(tagp, tag, as.interp); - } - tag.d.add(p->translate).mul(p->model->scale); - matrix = matrix4(tag); - } - - void genvbo(bool tangents, vbocacheentry &vc) - { - if(!vc.vbuf) glGenBuffers_(1, &vc.vbuf); - if(ebuf) return; - - vector<ushort> idxs; - - if(tangents) loopv(meshes) ((vertmesh *)meshes[i])->calctangents(); - - vtangents = tangents; - vertsize = tangents ? sizeof(vvertbump) : sizeof(vvertn); - vlen = 0; - if(numframes>1) - { - loopv(meshes) vlen += ((vertmesh *)meshes[i])->genvbo(idxs, vlen); - DELETEA(vdata); - vdata = new uchar[vlen*vertsize]; - #define FILLVDATA(type) do { \ - loopv(meshes) ((vertmesh *)meshes[i])->fillverts((type *)vdata); \ - } while(0) - if(tangents) FILLVDATA(vvertbump); - else FILLVDATA(vvertn); - #undef FILLVDATA - } - else - { - gle::bindvbo(vc.vbuf); - #define GENVBO(type) do { \ - vector<type> vverts; \ - loopv(meshes) vlen += ((vertmesh *)meshes[i])->genvbo(idxs, vlen, vverts, htdata, htlen); \ - glBufferData_(GL_ARRAY_BUFFER, vverts.length()*sizeof(type), vverts.getbuf(), GL_STATIC_DRAW); \ - } while(0) - int numverts = 0, htlen = 128; - loopv(meshes) numverts += ((vertmesh *)meshes[i])->numverts; - while(htlen < numverts) htlen *= 2; - if(numverts*4 > htlen*3) htlen *= 2; - int *htdata = new int[htlen]; - memset(htdata, -1, htlen*sizeof(int)); - if(tangents) GENVBO(vvertbump); - else GENVBO(vvertn); - delete[] htdata; - #undef GENVBO - gle::clearvbo(); - } - - glGenBuffers_(1, &ebuf); - gle::bindebo(ebuf); - glBufferData_(GL_ELEMENT_ARRAY_BUFFER, idxs.length()*sizeof(ushort), idxs.getbuf(), GL_STATIC_DRAW); - gle::clearebo(); - } - - void bindvbo(const animstate *as, vbocacheentry &vc) - { - vvert *vverts = 0; - bindpos(ebuf, vc.vbuf, &vverts->pos, vertsize); - if(as->cur.anim&ANIM_NOSKIN) - { - if(enabletc) disabletc(); - if(enablenormals) disablenormals(); - if(enabletangents) disabletangents(); - } - else - { - if(vtangents) - { - if(enablenormals) disablenormals(); - vvertbump *vvertbumps = 0; - bindtangents(&vvertbumps->tangent, vertsize); - } - else - { - if(enabletangents) disabletangents(); - vvertn *vvertns = 0; - bindnormals(&vvertns->norm, vertsize); - } - - bindtc(&vverts->tc, vertsize); - } - if(enablebones) disablebones(); - } - - void cleanup() - { - loopi(MAXVBOCACHE) - { - vbocacheentry &c = vbocache[i]; - if(c.vbuf) { glDeleteBuffers_(1, &c.vbuf); c.vbuf = 0; } - c.as.cur.fr1 = -1; - } - if(ebuf) { glDeleteBuffers_(1, &ebuf); ebuf = 0; } - } - - void preload(part *p) - { - if(numframes > 1) return; - bool tangents = p->tangents(); - if(tangents!=vtangents) cleanup(); - if(!vbocache->vbuf) genvbo(tangents, *vbocache); - } - - void render(const animstate *as, float pitch, const vec &axis, const vec &forward, dynent *d, part *p) - { - if(as->cur.anim&ANIM_NORENDER) - { - loopv(p->links) calctagmatrix(p, p->links[i].tag, *as, p->links[i].matrix); - return; - } - - bool tangents = p->tangents(); - if(tangents!=vtangents) { cleanup(); disablevbo(); } - vbocacheentry *vc = NULL; - if(numframes<=1) vc = vbocache; - else - { - loopi(MAXVBOCACHE) - { - vbocacheentry &c = vbocache[i]; - if(!c.vbuf) continue; - if(c.as==*as) { vc = &c; break; } - } - if(!vc) loopi(MAXVBOCACHE) { vc = &vbocache[i]; if(!vc->vbuf || vc->millis < lastmillis) break; } - } - if(!vc->vbuf) genvbo(tangents, *vc); - if(numframes>1) - { - if(vc->as!=*as) - { - vc->as = *as; - vc->millis = lastmillis; - loopv(meshes) - { - vertmesh &m = *(vertmesh *)meshes[i]; - m.interpverts(*as, tangents, vdata + m.voffset*vertsize, p->skins[i]); - } - gle::bindvbo(vc->vbuf); - glBufferData_(GL_ARRAY_BUFFER, vlen*vertsize, vdata, GL_STREAM_DRAW); - } - vc->millis = lastmillis; - } - - bindvbo(as, *vc); - loopv(meshes) - { - vertmesh *m = (vertmesh *)meshes[i]; - p->skins[i].bind(m, as); - m->render(as, p->skins[i], *vc); - } - - loopv(p->links) calctagmatrix(p, p->links[i].tag, *as, p->links[i].matrix); - } - }; - - vertmodel(const char *name) : animmodel(name) - { - } -}; - -template<class MDL> struct vertloader : modelloader<MDL, vertmodel> -{ - vertloader(const char *name) : modelloader<MDL, vertmodel>(name) {} -}; - -template<class MDL> struct vertcommands : modelcommands<MDL, struct MDL::vertmesh> -{ - typedef struct MDL::part part; - typedef struct MDL::skin skin; - - static void loadpart(char *model, float *smooth) - { - if(!MDL::loading) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } - defformatstring(filename, "%s/%s", MDL::dir, model); - part &mdl = MDL::loading->addpart(); - if(mdl.index) mdl.pitchscale = mdl.pitchoffset = mdl.pitchmin = mdl.pitchmax = 0; - mdl.meshes = MDL::loading->sharemeshes(path(filename), double(*smooth > 0 ? cos(clamp(*smooth, 0.0f, 180.0f)*RAD) : 2)); - if(!mdl.meshes) conoutf(CON_ERROR, "could not load %s", filename); - else mdl.initskins(); - } - - static void setpitch(float *pitchscale, float *pitchoffset, float *pitchmin, float *pitchmax) - { - if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } - part &mdl = *MDL::loading->parts.last(); - - mdl.pitchscale = *pitchscale; - mdl.pitchoffset = *pitchoffset; - if(*pitchmin || *pitchmax) - { - mdl.pitchmin = *pitchmin; - mdl.pitchmax = *pitchmax; - } - else - { - mdl.pitchmin = -360*fabs(mdl.pitchscale) + mdl.pitchoffset; - mdl.pitchmax = 360*fabs(mdl.pitchscale) + mdl.pitchoffset; - } - } - - static void setanim(char *anim, int *frame, int *range, float *speed, int *priority) - { - if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } - vector<int> anims; - findanims(anim, anims); - if(anims.empty()) conoutf(CON_ERROR, "could not find animation %s", anim); - else loopv(anims) - { - MDL::loading->parts.last()->setanim(0, anims[i], *frame, *range, *speed, *priority); - } - } - - vertcommands() - { - if(MDL::multiparted()) this->modelcommand(loadpart, "load", "sf"); - this->modelcommand(setpitch, "pitch", "ffff"); - if(MDL::animated()) this->modelcommand(setanim, "anim", "siiff"); - } -}; - diff --git a/src/engine/world.cpp b/src/engine/world.cpp index 46aaa0f..489ea65 100644 --- a/src/engine/world.cpp +++ b/src/engine/world.cpp @@ -10,29 +10,23 @@ SVARR(maptitle, "Untitled Map by Unknown"); VAR(octaentsize, 0, 64, 1024); VAR(entselradius, 0, 2, 10); -static inline void mmboundbox(const entity &e, model *m, vec ¢er, vec &radius) -{ +static inline void mmboundbox(const entity &e, model *m, vec ¢er, vec &radius) { m->boundbox(center, radius); rotatebb(center, radius, e.attr1); } -static inline void mmcollisionbox(const entity &e, model *m, vec ¢er, vec &radius) -{ +static inline void mmcollisionbox(const entity &e, model *m, vec ¢er, vec &radius) { m->collisionbox(center, radius); rotatebb(center, radius, e.attr1); } -bool getentboundingbox(const extentity &e, ivec &o, ivec &r) -{ - switch(e.type) - { +bool getentboundingbox(const extentity &e, ivec &o, ivec &r) { + switch(e.type) { case ET_EMPTY: return false; - case ET_MAPMODEL: - { + case ET_MAPMODEL: { model *m = loadmapmodel(e.attr2); - if(m) - { + if(m) { vec center, radius; mmboundbox(e, m, center, radius); center.add(e.o); @@ -52,32 +46,25 @@ bool getentboundingbox(const extentity &e, ivec &o, ivec &r) return true; } -enum -{ +enum { MODOE_ADD = 1<<0, MODOE_UPDATEBB = 1<<1, MODOE_LIGHTENT = 1<<2 }; -void modifyoctaentity(int flags, int id, extentity &e, cube *c, const ivec &cor, int size, const ivec &bo, const ivec &br, int leafsize, vtxarray *lastva = NULL) -{ - loopoctabox(cor, size, bo, br) - { +void modifyoctaentity(int flags, int id, extentity &e, cube *c, const ivec &cor, int size, const ivec &bo, const ivec &br, int leafsize, vtxarray *lastva = NULL) { + loopoctabox(cor, size, bo, br) { ivec o(i, cor, size); vtxarray *va = c[i].ext && c[i].ext->va ? c[i].ext->va : lastva; if(c[i].children != NULL && size > leafsize) modifyoctaentity(flags, id, e, c[i].children, o, size>>1, bo, br, leafsize, va); - else if(flags&MODOE_ADD) - { + else if(flags&MODOE_ADD) { if(!c[i].ext || !c[i].ext->ents) ext(c[i]).ents = new octaentities(o, size); octaentities &oe = *c[i].ext->ents; - switch(e.type) - { + switch(e.type) { case ET_MAPMODEL: - if(loadmapmodel(e.attr2)) - { - if(va) - { + if(loadmapmodel(e.attr2)) { + if(va) { va->bbmin.x = -1; if(oe.mapmodels.empty()) va->mapmodels.add(&oe); } @@ -92,26 +79,20 @@ void modifyoctaentity(int flags, int id, extentity &e, cube *c, const ivec &cor, oe.other.add(id); break; } - } - else if(c[i].ext && c[i].ext->ents) - { + else if(c[i].ext && c[i].ext->ents) { octaentities &oe = *c[i].ext->ents; - switch(e.type) - { + switch(e.type) { case ET_MAPMODEL: - if(loadmapmodel(e.attr2)) - { + if(loadmapmodel(e.attr2)) { oe.mapmodels.removeobj(id); - if(va) - { + if(va) { va->bbmin.x = -1; if(oe.mapmodels.empty()) va->mapmodels.removeobj(&oe); } oe.bbmin = oe.bbmax = oe.o; oe.bbmin.add(oe.size); - loopvj(oe.mapmodels) - { + loopvj(oe.mapmodels) { extentity &e = *entities::getents()[oe.mapmodels[j]]; ivec eo, er; if(getentboundingbox(e, eo, er)) @@ -134,10 +115,8 @@ void modifyoctaentity(int flags, int id, extentity &e, cube *c, const ivec &cor, freeoctaentities(c[i]); } if(c[i].ext && c[i].ext->ents) c[i].ext->ents->query = NULL; - if(va && va!=lastva) - { - if(lastva) - { + if(va && va!=lastva) { + if(lastva) { if(va->bbmin.x < 0) lastva->bbmin.x = -1; } else if(flags&MODOE_UPDATEBB) updatevabb(va); @@ -147,24 +126,18 @@ void modifyoctaentity(int flags, int id, extentity &e, cube *c, const ivec &cor, vector<int> outsideents; -static bool modifyoctaent(int flags, int id, extentity &e) -{ +static bool modifyoctaent(int flags, int id, extentity &e) { if(flags&MODOE_ADD ? e.flags&EF_OCTA : !(e.flags&EF_OCTA)) return false; - ivec o, r; if(!getentboundingbox(e, o, r)) return false; - - if(!insideworld(e.o)) - { + if(!insideworld(e.o)) { int idx = outsideents.find(id); - if(flags&MODOE_ADD) - { + if(flags&MODOE_ADD) { if(idx < 0) outsideents.add(id); } else if(idx >= 0) outsideents.removeunordered(idx); } - else - { + else { int leafsize = octaentsize, limit = max(r.x - o.x, max(r.y - o.y, r.z - o.z)); while(leafsize < limit) leafsize *= 2; int diff = ~(leafsize-1) & ((o.x^r.x)|(o.y^r.y)|(o.z^r.z)); @@ -178,8 +151,7 @@ static bool modifyoctaent(int flags, int id, extentity &e) return true; } -static inline bool modifyoctaent(int flags, int id) -{ +static inline bool modifyoctaent(int flags, int id) { vector<extentity *> &ents = entities::getents(); return ents.inrange(id) && modifyoctaent(flags, id, *ents[id]); } @@ -187,68 +159,56 @@ static inline bool modifyoctaent(int flags, int id) static inline void addentity(int id) { modifyoctaent(MODOE_ADD|MODOE_UPDATEBB|MODOE_LIGHTENT, id); } static inline void removeentity(int id) { modifyoctaent(MODOE_UPDATEBB, id); } -void freeoctaentities(cube &c) -{ +void freeoctaentities(cube &c) { if(!c.ext) return; - if(entities::getents().length()) - { + if(entities::getents().length()) { while(c.ext->ents && !c.ext->ents->mapmodels.empty()) removeentity(c.ext->ents->mapmodels.pop()); while(c.ext->ents && !c.ext->ents->other.empty()) removeentity(c.ext->ents->other.pop()); } - if(c.ext->ents) - { + if(c.ext->ents) { delete c.ext->ents; c.ext->ents = NULL; } } -void entitiesinoctanodes() -{ +void entitiesinoctanodes() { vector<extentity *> &ents = entities::getents(); loopv(ents) modifyoctaent(MODOE_ADD, i, *ents[i]); } -static inline void findents(octaentities &oe, int low, int high, bool notspawned, const vec &pos, const vec &invradius, vector<int> &found) -{ +static inline void findents(octaentities &oe, int low, int high, bool notspawned, const vec &pos, const vec &invradius, vector<int> &found) { vector<extentity *> &ents = entities::getents(); - loopv(oe.other) - { + loopv(oe.other) { int id = oe.other[i]; extentity &e = *ents[id]; if(e.type >= low && e.type <= high && (e.spawned() || notspawned) && vec(e.o).sub(pos).mul(invradius).squaredlen() <= 1) found.add(id); } } -static inline void findents(cube *c, const ivec &o, int size, const ivec &bo, const ivec &br, int low, int high, bool notspawned, const vec &pos, const vec &invradius, vector<int> &found) -{ - loopoctabox(o, size, bo, br) - { +static inline void findents(cube *c, const ivec &o, int size, const ivec &bo, const ivec &br, int low, int high, bool notspawned, const vec &pos, const vec &invradius, vector<int> &found) { + loopoctabox(o, size, bo, br) { if(c[i].ext && c[i].ext->ents) findents(*c[i].ext->ents, low, high, notspawned, pos, invradius, found); - if(c[i].children && size > octaentsize) - { + if(c[i].children && size > octaentsize) { ivec co(i, o, size); findents(c[i].children, co, size>>1, bo, br, low, high, notspawned, pos, invradius, found); } } } -void findents(int low, int high, bool notspawned, const vec &pos, const vec &radius, vector<int> &found) -{ +void findents(int low, int high, bool notspawned, const vec &pos, const vec &radius, vector<int> &found) { vec invradius(1/radius.x, 1/radius.y, 1/radius.z); ivec bo(vec(pos).sub(radius).sub(1)), br(vec(pos).add(radius).add(1)); int diff = (bo.x^br.x) | (bo.y^br.y) | (bo.z^br.z) | octaentsize, scale = worldscale-1; - if(diff&~((1<<scale)-1) || uint(bo.x|bo.y|bo.z|br.x|br.y|br.z) >= uint(worldsize)) - { + if(diff&~((1<<scale)-1) || uint(bo.x|bo.y|bo.z|br.x|br.y|br.z) >= uint(worldsize)) { findents(worldroot, ivec(0, 0, 0), 1<<scale, bo, br, low, high, notspawned, pos, invradius, found); return; } cube *c = &worldroot[octastep(bo.x, bo.y, bo.z, scale)]; if(c->ext && c->ext->ents) findents(*c->ext->ents, low, high, notspawned, pos, invradius, found); scale--; - while(c->children && !(diff&(1<<scale))) - { + while(c->children && !(diff&(1<<scale))) { c = &c->children[octastep(bo.x, bo.y, bo.z, scale)]; if(c->ext && c->ext->ents) findents(*c->ext->ents, low, high, notspawned, pos, invradius, found); scale--; @@ -256,13 +216,11 @@ void findents(int low, int high, bool notspawned, const vec &pos, const vec &rad if(c->children && 1<<scale >= octaentsize) findents(c->children, ivec(bo).mask(~((2<<scale)-1)), 1<<scale, bo, br, low, high, notspawned, pos, invradius, found); } -char *entname(entity &e) -{ +char *entname(entity &e) { static string fullentname; copystring(fullentname, entities::entname(e.type)); const char *einfo = entities::entnameinfo(e); - if(*einfo) - { + if(*einfo) { concatstring(fullentname, ": "); concatstring(fullentname, einfo); } @@ -277,14 +235,12 @@ bool undonext = true; VARF(entediting, 0, 0, 1, { if(!entediting) { entcancel(); efocus = enthover = -1; } }); -bool noentedit() -{ +bool noentedit() { if(!editmode) { conoutf(CON_ERROR, "operation only allowed in edit mode"); return true; } return !entediting; } -bool pointinsel(const selinfo &sel, const vec &o) -{ +bool pointinsel(const selinfo &sel, const vec &o) { return(o.x <= sel.o.x+sel.s.x*sel.grid && o.x >= sel.o.x && o.y <= sel.o.y+sel.s.y*sel.grid @@ -295,31 +251,26 @@ bool pointinsel(const selinfo &sel, const vec &o) vector<int> entgroup; -bool haveselent() -{ +bool haveselent() { return entgroup.length() > 0; } -void entcancel() -{ +void entcancel() { entgroup.shrink(0); } -void entadd(int id) -{ +void entadd(int id) { undonext = true; entgroup.add(id); } -undoblock *newundoent() -{ +undoblock *newundoent() { int numents = entgroup.length(); if(numents <= 0) return NULL; undoblock *u = (undoblock *)new uchar[sizeof(undoblock) + numents*sizeof(undoent)]; u->numents = numents; undoent *e = (undoent *)(u + 1); - loopv(entgroup) - { + loopv(entgroup) { e->i = entgroup[i]; e->e = *entities::getents()[entgroup[i]]; e++; @@ -327,8 +278,7 @@ undoblock *newundoent() return u; } -void makeundoent() -{ +void makeundoent() { if(!undonext) return; undonext = false; oldhover = enthover; @@ -336,8 +286,7 @@ void makeundoent() if(u) addundo(u); } -void detachentity(extentity &e) -{ +void detachentity(extentity &e) { if(!e.attached) return; e.attached->attached = NULL; e.attached = NULL; @@ -345,40 +294,31 @@ void detachentity(extentity &e) VAR(attachradius, 1, 100, 1000); -void attachentity(extentity &e) -{ - switch(e.type) - { +void attachentity(extentity &e) { + switch(e.type) { case ET_SPOTLIGHT: break; - default: if(e.type<ET_GAMESPECIFIC || !entities::mayattach(e)) return; break; } - detachentity(e); - vector<extentity *> &ents = entities::getents(); int closest = -1; float closedist = 1e10f; - loopv(ents) - { + loopv(ents) { extentity *a = ents[i]; if(a->attached) continue; - switch(e.type) - { + switch(e.type) { case ET_SPOTLIGHT: if(a->type!=ET_LIGHT) continue; break; - default: if(e.type<ET_GAMESPECIFIC || !entities::attachent(e, *a)) continue; break; } float dist = e.o.dist(a->o); - if(dist < closedist) - { + if(dist < closedist) { closest = i; closedist = dist; } @@ -388,8 +328,7 @@ void attachentity(extentity &e) ents[closest]->attached = &e; } -void attachentities() -{ +void attachentities() { vector<extentity *> &ents = entities::getents(); loopv(ents) attachentity(*ents[i]); } @@ -400,10 +339,10 @@ void attachentities() #define addimplicit(f) { if(entgroup.empty() && enthover>=0) { entadd(enthover); undonext = (enthover != oldhover); f; entgroup.drop(); } else f; } #define entfocusv(i, f, v){ int n = efocus = (i); if(n>=0) { extentity &e = *v[n]; f; } } #define entfocus(i, f) entfocusv(i, f, entities::getents()) -#define enteditv(i, f, v) \ -{ \ - entfocusv(i, \ - { \ +#define enteditv(i, f, v) { \ + \ + entfocusv(i, { \ + \ int oldtype = e.type; \ removeentity(n); \ f; \ @@ -413,23 +352,21 @@ void attachentities() }, v); \ } #define entedit(i, f) enteditv(i, f, entities::getents()) -#define addgroup(exp) { vector<extentity *> &ents = entities::getents(); loopv(ents) entfocusv(i, if(exp) entadd(n), ents); } -#define setgroup(exp) { entcancel(); addgroup(exp); } +#define addgroup(exp) { vector<extentity *> &ents = entities::getents(); loopv(ents) entfocusv(i, if(exp) entadd(n), ents); } +#define setgroup(exp) { entcancel(); addgroup(exp); } #define groupeditloop(f){ vector<extentity *> &ents = entities::getents(); entlooplevel++; int _ = efocus; loopv(entgroup) enteditv(entgroup[i], f, ents); efocus = _; entlooplevel--; } #define groupeditpure(f){ if(entlooplevel>0) { entedit(efocus, f); } else groupeditloop(f); } #define groupeditundo(f){ makeundoent(); groupeditpure(f); } #define groupedit(f) { addimplicit(groupeditundo(f)); } -vec getselpos() -{ +vec getselpos() { vector<extentity *> &ents = entities::getents(); if(entgroup.length() && ents.inrange(entgroup[0])) return ents[entgroup[0]]->o; if(ents.inrange(enthover)) return ents[enthover]->o; return vec(sel.o); } -undoblock *copyundoents(undoblock *u) -{ +undoblock *copyundoents(undoblock *u) { entcancel(); undoent *e = u->ents(); loopi(u->numents) @@ -440,8 +377,7 @@ undoblock *copyundoents(undoblock *u) return c; } -void pasteundoent(int idx, const entity &ue) -{ +void pasteundoent(int idx, const entity &ue) { if(idx < 0 || idx >= MAXENTS) return; vector<extentity *> &ents = entities::getents(); while(ents.length() < idx) ents.add(entities::newentity())->type = ET_EMPTY; @@ -449,23 +385,20 @@ void pasteundoent(int idx, const entity &ue) entedit(idx, (entity &)e = ue); } -void pasteundoents(undoblock *u) -{ +void pasteundoents(undoblock *u) { undoent *ue = u->ents(); loopi(u->numents) entedit(ue[i].i, (entity &)e = ue[i].e); } -void entflip() -{ +void entflip() { if(noentedit()) return; int d = dimension(sel.orient); float mid = sel.s[d]*sel.grid/2+sel.o[d]; groupeditundo(e.o[d] -= (e.o[d]-mid)*2); } -void entrotate(int *cw) -{ +void entrotate(int *cw) { if(noentedit()) return; int d = dimension(sel.orient); int dd = (*cw<0) == dimcoord(sel.orient) ? R[d] : C[d]; @@ -479,12 +412,10 @@ void entrotate(int *cw) ); } -void entselectionbox(const entity &e, vec &eo, vec &es) -{ +void entselectionbox(const entity &e, vec &eo, vec &es) { model *m = NULL; const char *mname = entities::entmodel(e); - if(mname && (m = loadmodel(mname))) - { + if(mname && (m = loadmodel(mname))) { m->collisionbox(eo, es); if(es.x > es.y) es.y = es.x; else es.x = es.y; // square es.z = (es.z + eo.z + 1 + entselradius)/2; // enclose ent radius box and model box @@ -492,14 +423,12 @@ void entselectionbox(const entity &e, vec &eo, vec &es) eo.y += e.o.y; eo.z = e.o.z - entselradius + es.z; } - else if(e.type == ET_MAPMODEL && (m = loadmapmodel(e.attr2))) - { + else if(e.type == ET_MAPMODEL && (m = loadmapmodel(e.attr2))) { mmcollisionbox(e, m, eo, es); es.max(entselradius); eo.add(e.o); } - else - { + else { es = vec(entselradius); eo = e.o; } @@ -517,31 +446,24 @@ extern bool editmoveplane(const vec &o, const vec &ray, int d, float off, vec &h int entmoving = 0; -void entdrag(const vec &ray) -{ +void entdrag(const vec &ray) { if(noentedit() || !haveselent()) return; - float r = 0, c = 0; static vec v, handle; vec eo, es; int d = dimension(entorient), dc= dimcoord(entorient); - entfocus(entgroup.last(), entselectionbox(e, eo, es); - if(!editmoveplane(e.o, ray, d, eo[d] + (dc ? es[d] : 0), handle, v, entmoving==1)) return; - ivec g(v); int z = g[d]&(~(sel.grid-1)); g.add(sel.grid/2).mask(~(sel.grid-1)); g[d] = z; - r = (entselsnap ? g[R[d]] : v[R[d]]) - e.o[R[d]]; c = (entselsnap ? g[C[d]] : v[C[d]]) - e.o[C[d]]; ); - if(entmoving==1) makeundoent(); groupeditpure(e.o[R[d]] += r; e.o[C[d]] += c); entmoving = 2; @@ -549,13 +471,11 @@ void entdrag(const vec &ray) VAR(showentradius, 0, 1, 1); -void renderentring(const extentity &e, float radius, int axis) -{ +void renderentring(const extentity &e, float radius, int axis) { if(radius <= 0) return; gle::defvertex(); gle::begin(GL_LINE_LOOP); - loopi(15) - { + loopi(15) { vec p(e.o); const vec2 &sc = sincos360[i*(360/15)]; p[axis>=2 ? 1 : 0] += radius*sc.x; @@ -565,14 +485,12 @@ void renderentring(const extentity &e, float radius, int axis) xtraverts += gle::end(); } -void renderentsphere(const extentity &e, float radius) -{ +void renderentsphere(const extentity &e, float radius) { if(radius <= 0) return; loopk(3) renderentring(e, radius, k); } -void renderentattachment(const extentity &e) -{ +void renderentattachment(const extentity &e) { if(!e.attached) return; gle::defvertex(); gle::begin(GL_LINES); @@ -581,63 +499,50 @@ void renderentattachment(const extentity &e) xtraverts += gle::end(); } -void renderentarrow(const extentity &e, const vec &dir, float radius) -{ +void renderentarrow(const extentity &e, const vec &dir, float radius) { if(radius <= 0) return; float arrowsize = min(radius/8, 0.5f); vec target = vec(dir).mul(radius).add(e.o), arrowbase = vec(dir).mul(radius - arrowsize).add(e.o), spoke; spoke.orthogonal(dir); spoke.normalize(); spoke.mul(arrowsize); - gle::defvertex(); - gle::begin(GL_LINES); gle::attrib(e.o); gle::attrib(target); xtraverts += gle::end(); - gle::begin(GL_TRIANGLE_FAN); gle::attrib(target); loopi(5) gle::attrib(vec(spoke).rotate(2*M_PI*i/4.0f, dir).add(arrowbase)); xtraverts += gle::end(); } -void renderentcone(const extentity &e, const vec &dir, float radius, float angle) -{ +void renderentcone(const extentity &e, const vec &dir, float radius, float angle) { if(radius <= 0) return; vec spot = vec(dir).mul(radius*cosf(angle*RAD)).add(e.o), spoke; spoke.orthogonal(dir); spoke.normalize(); spoke.mul(radius*sinf(angle*RAD)); - gle::defvertex(); - gle::begin(GL_LINES); - loopi(8) - { + loopi(8) { gle::attrib(e.o); gle::attrib(vec(spoke).rotate(2*M_PI*i/8.0f, dir).add(spot)); } xtraverts += gle::end(); - gle::begin(GL_LINE_LOOP); loopi(8) gle::attrib(vec(spoke).rotate(2*M_PI*i/8.0f, dir).add(spot)); xtraverts += gle::end(); } -void renderentradius(extentity &e, bool color) -{ - switch(e.type) - { +void renderentradius(extentity &e, bool color) { + switch(e.type) { case ET_LIGHT: if(color) gle::colorf(e.attr2/255.0f, e.attr3/255.0f, e.attr4/255.0f); renderentsphere(e, e.attr1); break; - case ET_SPOTLIGHT: - if(e.attached) - { + if(e.attached) { if(color) gle::colorf(0, 1, 1); float radius = e.attached->attr1; if(!radius) radius = 2*e.o.dist(e.attached->o); @@ -647,15 +552,12 @@ void renderentradius(extentity &e, bool color) renderentcone(*e.attached, dir, radius, angle); } break; - case ET_SOUND: if(color) gle::colorf(0, 1, 1); renderentsphere(e, e.attr2); break; - case ET_MAPMODEL: - case ET_PLAYERSTART: - { + case ET_PLAYERSTART: { if(color) gle::colorf(0, 1, 1); entities::entradius(e, color); vec dir; @@ -663,10 +565,8 @@ void renderentradius(extentity &e, bool color) renderentarrow(e, dir, 4); break; } - default: - if(e.type>=ET_GAMESPECIFIC) - { + if(e.type>=ET_GAMESPECIFIC) { if(color) gle::colorf(0, 1, 1); entities::entradius(e, color); } @@ -674,22 +574,18 @@ void renderentradius(extentity &e, bool color) } } -static void renderentbox(const vec &eo, vec es) -{ +static void renderentbox(const vec &eo, vec es) { es.add(eo); - // bottom quad gle::attrib(eo.x, eo.y, eo.z); gle::attrib(es.x, eo.y, eo.z); gle::attrib(es.x, eo.y, eo.z); gle::attrib(es.x, es.y, eo.z); gle::attrib(es.x, es.y, eo.z); gle::attrib(eo.x, es.y, eo.z); gle::attrib(eo.x, es.y, eo.z); gle::attrib(eo.x, eo.y, eo.z); - // top quad gle::attrib(eo.x, eo.y, es.z); gle::attrib(es.x, eo.y, es.z); gle::attrib(es.x, eo.y, es.z); gle::attrib(es.x, es.y, es.z); gle::attrib(es.x, es.y, es.z); gle::attrib(eo.x, es.y, es.z); gle::attrib(eo.x, es.y, es.z); gle::attrib(eo.x, eo.y, es.z); - // sides gle::attrib(eo.x, eo.y, eo.z); gle::attrib(eo.x, eo.y, es.z); gle::attrib(es.x, eo.y, eo.z); gle::attrib(es.x, eo.y, es.z); @@ -697,13 +593,10 @@ static void renderentbox(const vec &eo, vec es) gle::attrib(eo.x, es.y, eo.z); gle::attrib(eo.x, es.y, es.z); } -void renderentselection(const vec &o, const vec &ray, bool entmoving) -{ +void renderentselection(const vec &o, bool entmoving) { if(noentedit()) return; vec eo, es; - - if(entgroup.length()) - { + if(entgroup.length()) { gle::colorub(0, 40, 0); gle::defvertex(); gle::begin(GL_LINES, entgroup.length()*24); @@ -713,14 +606,11 @@ void renderentselection(const vec &o, const vec &ray, bool entmoving) ); xtraverts += gle::end(); } - - if(enthover >= 0) - { + if(enthover >= 0) { gle::colorub(0, 40, 0); entfocus(enthover, entselectionbox(e, eo, es)); // also ensures enthover is back in focus boxs3D(eo, es, 1); - if(entmoving && entmovingshadow==1) - { + if(entmoving && entmovingshadow==1) { vec a, b; gle::colorub(20, 20, 20); (a = eo).x = eo.x - fmod(eo.x, worldsize); (b = es).x = a.x + worldsize; boxs3D(a, b, 1); @@ -731,9 +621,7 @@ void renderentselection(const vec &o, const vec &ray, bool entmoving) boxs(entorient, eo, es); boxs(entorient, eo, es, clamp(0.015f*camera1->o.dist(eo)*tan(fovy*0.5f*RAD), 0.1f, 1.0f)); } - - if(showentradius && (entgroup.length() || enthover >= 0)) - { + if(showentradius && (entgroup.length() || enthover >= 0)) { glDepthFunc(GL_GREATER); gle::colorf(0.25f, 0.25f, 0.25f); loopv(entgroup) entfocus(entgroup[i], renderentradius(e, false)); @@ -744,8 +632,7 @@ void renderentselection(const vec &o, const vec &ray, bool entmoving) } } -bool enttoggle(int id) -{ +bool enttoggle(int id) { undonext = true; int i = entgroup.find(id); if(i < 0) @@ -755,8 +642,7 @@ bool enttoggle(int id) return i < 0; } -bool hoveringonent(int ent, int orient) -{ +bool hoveringonent(int ent, int orient) { if(noentedit()) return false; entorient = orient; if((efocus = enthover = ent) >= 0) @@ -768,28 +654,22 @@ bool hoveringonent(int ent, int orient) VAR(entitysurf, 0, 0, 1); -ICOMMAND(entadd, "", (), -{ - if(enthover >= 0 && !noentedit()) - { +ICOMMAND(entadd, "", (), { + if(enthover >= 0 && !noentedit()) { if(entgroup.find(enthover) < 0) entadd(enthover); if(entmoving > 1) entmoving = 1; } }); -ICOMMAND(enttoggle, "", (), -{ +ICOMMAND(enttoggle, "", (), { if(enthover < 0 || noentedit() || !enttoggle(enthover)) { entmoving = 0; intret(0); } else { if(entmoving > 1) entmoving = 1; intret(1); } }); -ICOMMAND(entmoving, "b", (int *n), -{ - if(*n >= 0) - { +ICOMMAND(entmoving, "b", (int *n), { + if(*n >= 0) { if(!*n || enthover < 0 || noentedit()) entmoving = 0; - else - { + else { if(entgroup.find(enthover) < 0) { entadd(enthover); entmoving = 1; } else if(!entmoving) entmoving = 1; } @@ -797,27 +677,23 @@ ICOMMAND(entmoving, "b", (int *n), intret(entmoving); }); -void entpush(int *dir) -{ +void entpush(int *dir) { if(noentedit()) return; int d = dimension(entorient); int s = dimcoord(entorient) ? -*dir : *dir; - if(entmoving) - { + if(entmoving) { groupeditpure(e.o[d] += float(s*sel.grid)); // editdrag supplies the undo } else groupedit(e.o[d] += float(s*sel.grid)); - if(entitysurf==1) - { + if(entitysurf==1) { player->o[d] += float(s*sel.grid); player->resetinterp(); } } VAR(entautoviewdist, 0, 25, 100); -void entautoview(int *dir) -{ +void entautoview(int *dir) { if(!haveselent()) return; static int s = 0; vec v(player->o); @@ -839,15 +715,13 @@ COMMAND(entflip, ""); COMMAND(entrotate, "i"); COMMAND(entpush, "i"); -void delent() -{ +void delent() { if(noentedit()) return; groupedit(e.type = ET_EMPTY;); entcancel(); } -int findtype(char *what) -{ +int findtype(char *what) { for(int i = 0; *entities::entname(i); i++) if(strcmp(what, entities::entname(i))==0) return i; conoutf(CON_ERROR, "unknown entity type \"%s\"", what); return ET_EMPTY; @@ -855,15 +729,12 @@ int findtype(char *what) VAR(entdrop, 0, 2, 3); -bool dropentity(entity &e, int drop = -1) -{ +bool dropentity(entity &e, int drop = -1) { vec radius(4.0f, 4.0f, 4.0f); if(drop<0) drop = entdrop; - if(e.type == ET_MAPMODEL) - { + if(e.type == ET_MAPMODEL) { model *m = loadmapmodel(e.attr2); - if(m) - { + if(m) { vec center; mmboundbox(e, m, center, radius); radius.x += fabs(center.x); @@ -871,8 +742,7 @@ bool dropentity(entity &e, int drop = -1) } radius.z = 0.0f; } - switch(drop) - { + switch(drop) { case 1: if(e.type != ET_LIGHT && e.type != ET_SPOTLIGHT) dropenttofloor(&e); @@ -880,8 +750,7 @@ bool dropentity(entity &e, int drop = -1) case 2: case 3: int cx = 0, cy = 0; - if(sel.cxs == 1 && sel.cys == 1) - { + if(sel.cxs == 1 && sel.cys == 1) { cx = (sel.cx ? 1 : -1) * sel.grid / 2; cy = (sel.cy ? 1 : -1) * sel.grid / 2; } @@ -893,7 +762,6 @@ bool dropentity(entity &e, int drop = -1) e.o[D[d]] -= radius[D[d]]; else e.o[D[d]] += sel.grid + radius[D[d]]; - if(drop == 3) dropenttofloor(&e); break; @@ -901,14 +769,12 @@ bool dropentity(entity &e, int drop = -1) return true; } -void dropent() -{ +void dropent() { if(noentedit()) return; groupedit(dropentity(e)); } -void attachent() -{ +void attachent() { if(noentedit()) return; groupedit(attachentity(e)); } @@ -919,11 +785,9 @@ VARP(entcamdir, 0, 1, 1); static int keepents = 0; -extentity *newentity(bool local, const vec &o, int type, int v1, int v2, int v3, int v4, int v5, int &idx) -{ +extentity *newentity(bool local, const vec &o, int type, int v1, int v2, int v3, int v4, int v5, int &idx) { vector<extentity *> &ents = entities::getents(); - if(local) - { + if(local) { idx = -1; for(int i = keepents; i < ents.length(); i++) if(ents[i]->type == ET_EMPTY) { idx = i; break; } if(idx < 0 && ents.length() >= MAXENTS) { conoutf(CON_ERROR, "too many entities"); return NULL; } @@ -940,10 +804,8 @@ extentity *newentity(bool local, const vec &o, int type, int v1, int v2, int v3, e.reserved = 0; e.light.color = vec(1, 1, 1); e.light.dir = vec(0, 0, 1); - if(local) - { - if(entcamdir) switch(type) - { + if(local) { + if(entcamdir) switch(type) { case ET_MAPMODEL: case ET_PLAYERSTART: e.attr5 = e.attr4; @@ -960,8 +822,7 @@ extentity *newentity(bool local, const vec &o, int type, int v1, int v2, int v3, return &e; } -void newentity(int type, int a1, int a2, int a3, int a4, int a5) -{ +void newentity(int type, int a1, int a2, int a3, int a4, int a5) { int idx; extentity *t = newentity(true, player->o, type, a1, a2, a3, a4, a5, idx); if(!t) return; @@ -972,8 +833,7 @@ void newentity(int type, int a1, int a2, int a3, int a4, int a5) entedit(idx, e.type = type); } -void newent(char *what, int *a1, int *a2, int *a3, int *a4, int *a5) -{ +void newent(char *what, int *a1, int *a2, int *a3, int *a4, int *a5) { if(noentedit()) return; int type = findtype(what); if(type != ET_EMPTY) @@ -983,8 +843,7 @@ void newent(char *what, int *a1, int *a2, int *a3, int *a4, int *a5) int entcopygrid; vector<entity> entcopybuf; -void entcopy() -{ +void entcopy() { if(noentedit()) return; entcopygrid = sel.grid; entcopybuf.shrink(0); @@ -992,14 +851,12 @@ void entcopy() entfocus(entgroup[i], entcopybuf.add(e).o.sub(vec(sel.o))); } -void entpaste() -{ +void entpaste() { if(noentedit()) return; if(entcopybuf.length()==0) return; entcancel(); float m = float(sel.grid)/float(entcopygrid); - loopv(entcopybuf) - { + loopv(entcopybuf) { entity &c = entcopybuf[i]; vec o(c.o); o.mul(m).add(vec(sel.o)); @@ -1020,8 +877,7 @@ COMMAND(dropent, ""); COMMAND(entcopy, ""); COMMAND(entpaste, ""); -void entset(char *what, int *a1, int *a2, int *a3, int *a4, int *a5) -{ +void entset(char *what, int *a1, int *a2, int *a3, int *a4, int *a5) { if(noentedit()) return; int type = findtype(what); if(type != ET_EMPTY) @@ -1033,14 +889,11 @@ void entset(char *what, int *a1, int *a2, int *a3, int *a4, int *a5) e.attr5=*a5); } -void printent(extentity &e, char *buf, int len) -{ - switch(e.type) - { +void printent(extentity &e, char *buf, int len) { + switch(e.type) { case ET_PARTICLES: if(printparticles(e, buf, len)) return; break; - default: if(e.type >= ET_GAMESPECIFIC && entities::printent(e, buf, len)) return; break; @@ -1048,19 +901,16 @@ void printent(extentity &e, char *buf, int len) nformatstring(buf, len, "%s %d %d %d %d %d", entities::entname(e.type), e.attr1, e.attr2, e.attr3, e.attr4, e.attr5); } -void nearestent() -{ +void nearestent() { if(noentedit()) return; int closest = -1; float closedist = 1e16f; vector<extentity *> &ents = entities::getents(); - loopv(ents) - { + loopv(ents) { extentity &e = *ents[i]; if(e.type == ET_EMPTY) continue; float dist = e.o.dist(player->o); - if(dist < closedist) - { + if(dist < closedist) { closest = i; closedist = dist; } @@ -1077,27 +927,21 @@ ICOMMAND(entindex, "", (), intret(efocus)); COMMAND(entset, "siiiii"); COMMAND(nearestent, ""); -void enttype(char *type, int *numargs) -{ - if(*numargs >= 1) - { +void enttype(char *type, int *numargs) { + if(*numargs >= 1) { int typeidx = findtype(type); if(typeidx != ET_EMPTY) groupedit(e.type = typeidx); } - else entfocus(efocus, - { + else entfocus(efocus, { result(entities::entname(e.type)); }) } -void entattr(int *attr, int *val, int *numargs) -{ - if(*numargs >= 2) - { +void entattr(int *attr, int *val, int *numargs) { + if(*numargs >= 2) { if(*attr >= 0 && *attr <= 4) groupedit( - switch(*attr) - { + switch(*attr) { case 0: e.attr1 = *val; break; case 1: e.attr2 = *val; break; case 2: e.attr3 = *val; break; @@ -1106,10 +950,8 @@ void entattr(int *attr, int *val, int *numargs) } ); } - else entfocus(efocus, - { - switch(*attr) - { + else entfocus(efocus, { + switch(*attr) { case 0: intret(e.attr1); break; case 1: intret(e.attr2); break; case 2: intret(e.attr3); break; @@ -1122,18 +964,15 @@ void entattr(int *attr, int *val, int *numargs) COMMAND(enttype, "sN"); COMMAND(entattr, "iiN"); -int findentity(int type, int index, int attr1, int attr2) -{ +int findentity(int type, int index, int attr1, int attr2) { const vector<extentity *> &ents = entities::getents(); if(index > ents.length()) index = ents.length(); - else for(int i = index; i<ents.length(); i++) - { + else for(int i = index; i<ents.length(); i++) { extentity &e = *ents[i]; if(e.type==type && (attr1<0 || e.attr1==attr1) && (attr2<0 || e.attr2==attr2)) return i; } - loopj(index) - { + loopj(index) { extentity &e = *ents[j]; if(e.type==type && (attr1<0 || e.attr1==attr1) && (attr2<0 || e.attr2==attr2)) return j; @@ -1145,12 +984,10 @@ struct spawninfo { const extentity *e; float weight; }; // Compiles a vector of available playerstarts, each with a non-zero weight // which serves as a measure of its desirability for a spawning player. -float gatherspawninfos(dynent *d, int tag, vector<spawninfo> &spawninfos) -{ +float gatherspawninfos(dynent *d, int tag, vector<spawninfo> &spawninfos) { const vector<extentity *> &ents = entities::getents(); float total = 0.0f; - loopv(ents) - { + loopv(ents) { const extentity &e = *ents[i]; if(e.type != ET_PLAYERSTART || e.attr2 != tag) continue; spawninfo &s = spawninfos.add(); @@ -1164,12 +1001,10 @@ float gatherspawninfos(dynent *d, int tag, vector<spawninfo> &spawninfos) // Randomly picks a weighted spawn from the provided vector and removes it. // The probability of a given spawn being picked is proportional to its weight. // If all weights are zero, the index is picked uniformly. -static const extentity *poprandomspawn(vector<spawninfo> &spawninfos, float &total) -{ +static const extentity *poprandomspawn(vector<spawninfo> &spawninfos, float &total) { if(spawninfos.empty()) return NULL; int index = 0; - if(total > 0.0f) - { + if(total > 0.0f) { float x = rndscale(total); do x -= spawninfos[index].weight; while(x > 0 && ++index < spawninfos.length()-1); } @@ -1179,15 +1014,13 @@ static const extentity *poprandomspawn(vector<spawninfo> &spawninfos, float &tot return s.e; } -static inline bool tryspawn(dynent *d, const extentity &e) -{ +static inline bool tryspawn(dynent *d, const extentity &e) { d->o = e.o; d->yaw = e.attr1; return entinmap(d, true); } -void findplayerspawn(dynent *d, int forceent, int tag) -{ +void findplayerspawn(dynent *d, int forceent, int tag) { const vector<extentity *> &ents = entities::getents(); d->pitch = 0; d->roll = 0; @@ -1200,18 +1033,15 @@ void findplayerspawn(dynent *d, int forceent, int tag) entinmap(d); } -void splitocta(cube *c, int size) -{ +void splitocta(cube *c, int size) { if(size <= 0x1000) return; - loopi(8) - { + loopi(8) { if(!c[i].children) c[i].children = newcubes(isempty(c[i]) ? F_EMPTY : F_SOLID); splitocta(c[i].children, size>>1); } } -void resetmap() -{ +void resetmap() { clearoverrides(); clearmapsounds(); resetlightmaps(); @@ -1222,101 +1052,74 @@ void resetmap() cancelsel(); pruneundos(); clearmapcrc(); - entities::clearents(); outsideents.setsize(0); } -void startmap(const char *name) -{ +void startmap(const char *name) { game::startmap(name); } -bool emptymap(int scale, bool force, const char *mname, bool usecfg) // main empty world creation routine -{ - if(!force && !editmode) - { +bool emptymap(int scale, bool force, const char *mname, bool usecfg) { // main empty world creation routine { + if(!force && !editmode) { conoutf(CON_ERROR, "newmap only allowed in edit mode"); return false; } - resetmap(); - setvar("mapscale", scale<10 ? 10 : (scale>16 ? 16 : scale), true, false); setvar("mapsize", 1<<worldscale, true, false); - texmru.shrink(0); freeocta(worldroot); worldroot = newcubes(F_EMPTY); loopi(4) solidfaces(worldroot[i]); - if(worldsize > 0x1000) splitocta(worldroot, worldsize>>1); - clearmainmenu(); - - if(usecfg) - { + if(usecfg) { identflags |= IDF_OVERRIDDEN; execfile("data/default_map.cfg", false); identflags &= ~IDF_OVERRIDDEN; } - initlights(); allchanged(true); - startmap(mname); - return true; } -bool enlargemap(bool force) -{ - if(!force && !editmode) - { +bool enlargemap(bool force) { + if(!force && !editmode) { conoutf(CON_ERROR, "mapenlarge only allowed in edit mode"); return false; } if(worldsize >= 1<<16) return false; - while(outsideents.length()) removeentity(outsideents.pop()); - worldscale++; worldsize *= 2; cube *c = newcubes(F_EMPTY); c[0].children = worldroot; loopi(3) solidfaces(c[i+1]); worldroot = c; - if(worldsize > 0x1000) splitocta(worldroot, worldsize>>1); - allchanged(); - return true; } -static bool isallempty(cube &c) -{ +static bool isallempty(cube &c) { if(!c.children) return isempty(c); loopi(8) if(!isallempty(c.children[i])) return false; return true; } -void shrinkmap() -{ +void shrinkmap() { extern int nompedit; if(noedit(true) || (nompedit && multiplayer())) return; if(worldsize <= 1<<10) return; - int octant = -1; - loopi(8) if(!isallempty(worldroot[i])) - { + loopi(8) if(!isallempty(worldroot[i])) { if(octant >= 0) return; octant = i; } if(octant < 0) return; - while(outsideents.length()) removeentity(outsideents.pop()); - if(!worldroot[octant].children) subdividecube(worldroot[octant], false, false); cube *root = worldroot[octant].children; worldroot[octant].children = NULL; @@ -1324,13 +1127,10 @@ void shrinkmap() worldroot = root; worldscale--; worldsize /= 2; - ivec offset(octant, ivec(0, 0, 0), worldsize); vector<extentity *> &ents = entities::getents(); loopv(ents) ents[i]->o.sub(vec(offset)); - allchanged(); - conoutf("shrunk map to size %d", worldscale); } @@ -1340,26 +1140,22 @@ COMMAND(newmap, "i"); COMMAND(mapenlarge, ""); COMMAND(shrinkmap, ""); -void mapname() -{ +void mapname() { result(game::getclientmap()); } COMMAND(mapname, ""); -void mpeditent(int i, const vec &o, int type, int attr1, int attr2, int attr3, int attr4, int attr5, bool local) -{ +void mpeditent(int i, const vec &o, int type, int attr1, int attr2, int attr3, int attr4, int attr5, bool local) { if(i < 0 || i >= MAXENTS) return; vector<extentity *> &ents = entities::getents(); - if(ents.length()<=i) - { + if(ents.length()<=i) { extentity *e = newentity(local, o, type, attr1, attr2, attr3, attr4, attr5, i); if(!e) return; addentity(i); attachentity(*e); } - else - { + else { extentity &e = *ents[i]; removeentity(i); int oldtype = e.type; diff --git a/src/engine/world.h b/src/engine/world.h index 43ec470..91812b4 100644 --- a/src/engine/world.h +++ b/src/engine/world.h @@ -1,12 +1,10 @@ -enum // hardcoded texture numbers -{ +enum { // hardcoded texture numbers { DEFAULT_GEOM }; #define MAPVERSION 34 // bump if map format changes, see worldio.cpp -struct octaheader -{ +struct octaheader { char magic[4]; // "OCTA" int version; // any >8bit quantity is little endian int headersize; // sizeof(header) @@ -18,8 +16,7 @@ struct octaheader int numvslots; }; -enum -{ +enum { MATSURF_NOT_VISIBLE = 0, MATSURF_VISIBLE, MATSURF_EDIT_ONLY @@ -28,4 +25,3 @@ enum #define TEX_SCALE 8.0f struct vertex { vec pos; bvec4 norm; vec2 tc; svec2 lm; bvec4 tangent; }; - diff --git a/src/engine/worldio.cpp b/src/engine/worldio.cpp index 4e309a8..898b2bb 100644 --- a/src/engine/worldio.cpp +++ b/src/engine/worldio.cpp @@ -2,12 +2,10 @@ #include "engine.h" -void validmapname(char *dst, const char *src, const char *prefix = NULL, const char *alt = "untitled", size_t maxlen = 100) -{ +void validmapname(char *dst, const char *src, const char *prefix = NULL, const char *alt = "untitled", size_t maxlen = 100) { if(prefix) while(*prefix) *dst++ = *prefix++; const char *start = dst; - if(src) loopi(maxlen) - { + if(src) loopi(maxlen) { char c = *src++; if(iscubealnum(c) || c == '_' || c == '-' || c == '/' || c == '\\') *dst++ = c; else break; @@ -16,32 +14,27 @@ void validmapname(char *dst, const char *src, const char *prefix = NULL, const c else if(dst != alt) copystring(dst, alt, maxlen); } -void fixmapname(char *name) -{ +void fixmapname(char *name) { validmapname(name, name, NULL, ""); } -void getmapfilenames(const char *fname, const char *cname, char *pakname, char *mapname, char *cfgname) -{ +void getmapfilenames(const char *fname, const char *cname, char *pakname, char *mapname, char *cfgname) { if(!cname) cname = fname; string name; validmapname(name, cname); char *slash = strpbrk(name, "/\\"); - if(slash) - { + if(slash) { copystring(pakname, name, slash-name+1); copystring(cfgname, slash+1, MAXSTRLEN); } - else - { + else { copystring(pakname, "maps", MAXSTRLEN); copystring(cfgname, name, MAXSTRLEN); } validmapname(mapname, fname, strpbrk(fname, "/\\") ? NULL : "maps/"); } -bool loadents(const char *fname, vector<entity> &ents, uint *crc) -{ +bool loadents(const char *fname, vector<entity> &ents, uint *crc) { string pakname, mapname, mcfgname, ogzname; getmapfilenames(fname, NULL, pakname, mapname, mcfgname); formatstring(ogzname, "packages/%s.ogz", mapname); @@ -53,21 +46,16 @@ bool loadents(const char *fname, vector<entity> &ents, uint *crc) lilswap(&hdr.version, 6); if(memcmp(hdr.magic, "OCTA", 4) || hdr.worldsize <= 0|| hdr.numents < 0) { conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false; } if(hdr.version>MAPVERSION) { conoutf(CON_ERROR, "map %s requires a newer version of Cube 2: Sauerbraten", ogzname); delete f; return false; } - lilswap(&hdr.numvslots, 1); - - loopi(hdr.numvars) - { + loopi(hdr.numvars) { int type = f->getchar(), ilen = f->getlil<ushort>(); f->seek(ilen, SEEK_CUR); - switch(type) - { + switch(type) { case ID_VAR: f->getlil<int>(); break; case ID_FVAR: f->getlil<float>(); break; case ID_SVAR: { int slen = f->getlil<ushort>(); f->seek(slen, SEEK_CUR); break; } } } - string gametype; copystring(gametype, "fps"); int eif = 0; @@ -76,32 +64,24 @@ bool loadents(const char *fname, vector<entity> &ents, uint *crc) eif = f->getlil<ushort>(); int extrasize = f->getlil<ushort>(); f->seek(extrasize, SEEK_CUR); - ushort nummru = f->getlil<ushort>(); f->seek(nummru*sizeof(ushort), SEEK_CUR); - - loopi(min(hdr.numents, MAXENTS)) - { + loopi(min(hdr.numents, MAXENTS)) { entity &e = ents.add(); f->read(&e, sizeof(entity)); lilswap(&e.o.x, 3); lilswap(&e.attr1, 5); if(eif > 0) f->seek(eif, SEEK_CUR); - if(e.type>=ET_GAMESPECIFIC) - { + if(e.type>=ET_GAMESPECIFIC) { ents.pop(); continue; } } - - if(crc) - { + if(crc) { f->seek(0, SEEK_END); *crc = f->getcrc(); } - delete f; - return true; } @@ -110,25 +90,21 @@ string ogzname, bakname, cfgname, picname; VARP(savebak, 0, 2, 2); -void setmapfilenames(const char *fname, const char *cname = NULL) -{ +void setmapfilenames(const char *fname, const char *cname = NULL) { string pakname, mapname, mcfgname; getmapfilenames(fname, cname, pakname, mapname, mcfgname); - formatstring(ogzname, "packages/%s.ogz", mapname); if(savebak==1) formatstring(bakname, "packages/%s.BAK", mapname); else formatstring(bakname, "packages/%s_%d.BAK", mapname, totalmillis); formatstring(cfgname, "packages/%s/%s.cfg", pakname, mcfgname); formatstring(picname, "packages/%s.png", mapname); - path(ogzname); path(bakname); path(cfgname); path(picname); } -void mapcfgname() -{ +void mapcfgname() { const char *mname = game::getclientmap(); string pakname, mapname, mcfgname; getmapfilenames(mname, NULL, pakname, mapname, mcfgname); @@ -139,8 +115,7 @@ void mapcfgname() COMMAND(mapcfgname, ""); -void backup(char *name, char *backupname) -{ +void backup(char *name, char *backupname) { string backupfile; copystring(backupfile, findfile(backupname, "wb")); remove(backupfile); @@ -151,30 +126,22 @@ enum { OCTSAV_CHILDREN = 0, OCTSAV_EMPTY, OCTSAV_SOLID, OCTSAV_NORMAL, OCTSAV_LO static int savemapprogress = 0; -void savec(cube *c, const ivec &o, int size, stream *f, bool nolms) -{ +void savec(cube *c, const ivec &o, int size, stream *f, bool nolms) { if((savemapprogress++&0xFFF)==0) renderprogress(float(savemapprogress)/allocnodes, "saving octree..."); - - loopi(8) - { + loopi(8) { ivec co(i, o, size); - if(c[i].children) - { + if(c[i].children) { f->putchar(OCTSAV_CHILDREN); savec(c[i].children, co, size>>1, f, nolms); } - else - { + else { int oflags = 0, surfmask = 0, totalverts = 0; if(c[i].material!=MAT_AIR) oflags |= 0x40; if(isempty(c[i])) f->putchar(oflags | OCTSAV_EMPTY); - else - { - if(!nolms) - { + else { + if(!nolms) { if(c[i].merged) oflags |= 0x80; - if(c[i].ext) loopj(6) - { + if(c[i].ext) loopj(6) { const surfaceinfo &surf = c[i].ext->surfaces[j]; if(!surf.used()) continue; oflags |= 0x20; @@ -182,34 +149,26 @@ void savec(cube *c, const ivec &o, int size, stream *f, bool nolms) totalverts += surf.totalverts(); } } - if(isentirelysolid(c[i])) f->putchar(oflags | OCTSAV_SOLID); - else - { + else { f->putchar(oflags | OCTSAV_NORMAL); f->write(c[i].edges, 12); } } - loopj(6) f->putlil<ushort>(c[i].texture[j]); - if(oflags&0x40) f->putlil<ushort>(c[i].material); if(oflags&0x80) f->putchar(c[i].merged); - if(oflags&0x20) - { + if(oflags&0x20) { f->putchar(surfmask); f->putchar(totalverts); - loopj(6) if(surfmask&(1<<j)) - { + loopj(6) if(surfmask&(1<<j)) { surfaceinfo surf = c[i].ext->surfaces[j]; vertinfo *verts = c[i].ext->verts() + surf.verts; int layerverts = surf.numverts&MAXFACEVERTS, numverts = surf.totalverts(), vertmask = 0, vertorder = 0, uvorder = 0, dim = dimension(j), vc = C[dim], vr = R[dim]; - if(numverts) - { - if(c[i].merged&(1<<j)) - { + if(numverts) { + if(c[i].merged&(1<<j)) { vertmask |= 0x04; if(layerverts == 4) { @@ -226,22 +185,19 @@ void savec(cube *c, const ivec &o, int size, stream *f, bool nolms) } } } - else - { + else { int vis = visibletris(c[i], j, co, size); if(vis&4 || faceconvexity(c[i], j) < 0) vertmask |= 0x01; if(layerverts < 4 && vis&2) vertmask |= 0x02; } bool matchnorm = true; - loopk(numverts) - { + loopk(numverts) { const vertinfo &v = verts[k]; if(v.u || v.v) vertmask |= 0x40; if(v.norm) { vertmask |= 0x80; if(v.norm != verts[0].norm) matchnorm = false; } } if(matchnorm) vertmask |= 0x08; - if(vertmask&0x40 && layerverts == 4) - { + if(vertmask&0x40 && layerverts == 4) { loopk(4) { const vertinfo &v0 = verts[k], &v1 = verts[(k+1)&3], &v2 = verts[(k+2)&3], &v3 = verts[(k+3)&3]; @@ -263,17 +219,14 @@ void savec(cube *c, const ivec &o, int size, stream *f, bool nolms) surf.verts = vertmask; f->write(&surf, sizeof(surfaceinfo)); bool hasxyz = (vertmask&0x04)!=0, hasuv = (vertmask&0x40)!=0, hasnorm = (vertmask&0x80)!=0; - if(layerverts == 4) - { - if(hasxyz && vertmask&0x01) - { + if(layerverts == 4) { + if(hasxyz && vertmask&0x01) { ivec v0 = verts[vertorder].getxyz(), v2 = verts[(vertorder+2)&3].getxyz(); f->putlil<ushort>(v0[vc]); f->putlil<ushort>(v0[vr]); f->putlil<ushort>(v2[vc]); f->putlil<ushort>(v2[vr]); hasxyz = false; } - if(hasuv && vertmask&0x02) - { + if(hasuv && vertmask&0x02) { const vertinfo &v0 = verts[uvorder], &v2 = verts[(uvorder+2)&3]; f->putlil<ushort>(v0.u); f->putlil<ushort>(v0.v); f->putlil<ushort>(v2.u); f->putlil<ushort>(v2.v); @@ -287,19 +240,16 @@ void savec(cube *c, const ivec &o, int size, stream *f, bool nolms) } } if(hasnorm && vertmask&0x08) { f->putlil<ushort>(verts[0].norm); hasnorm = false; } - if(hasxyz || hasuv || hasnorm) loopk(layerverts) - { + if(hasxyz || hasuv || hasnorm) loopk(layerverts) { const vertinfo &v = verts[(k+vertorder)%layerverts]; - if(hasxyz) - { + if(hasxyz) { ivec xyz = v.getxyz(); f->putlil<ushort>(xyz[vc]); f->putlil<ushort>(xyz[vr]); } if(hasuv) { f->putlil<ushort>(v.u); f->putlil<ushort>(v.v); } if(hasnorm) f->putlil<ushort>(v.norm); } - if(surf.numverts&LAYER_DUP) loopk(layerverts) - { + if(surf.numverts&LAYER_DUP) loopk(layerverts) { const vertinfo &v = verts[layerverts + (k+vertorder)%layerverts]; if(hasuv) { f->putlil<ushort>(v.u); f->putlil<ushort>(v.v); } } @@ -309,36 +259,30 @@ void savec(cube *c, const ivec &o, int size, stream *f, bool nolms) } } -struct surfacecompat -{ +struct surfacecompat { uchar texcoords[8]; uchar w, h; ushort x, y; uchar lmid, layer; }; -struct normalscompat -{ +struct normalscompat { bvec normals[4]; }; -struct mergecompat -{ +struct mergecompat { ushort u1, u2, v1, v2; }; cube *loadchildren(stream *f, const ivec &co, int size, bool &failed); -void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) -{ +void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) { bool haschildren = false; int octsav = f->getchar(); - switch(octsav&0x7) - { + switch(octsav&0x7) { case OCTSAV_CHILDREN: c.children = loadchildren(f, co, size>>1, failed); return; - case OCTSAV_LODCUBE: haschildren = true; break; case OCTSAV_EMPTY: emptyfaces(c); break; case OCTSAV_SOLID: solidfaces(c); break; @@ -346,12 +290,10 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) default: failed = true; return; } loopi(6) c.texture[i] = mapversion<14 ? f->getchar() : f->getlil<ushort>(); - - { + { if(octsav&0x40) c.material = f->getlil<ushort>(); if(octsav&0x80) c.merged = f->getchar(); - if(octsav&0x20) - { + if(octsav&0x20) { int surfmask, totalverts; surfmask = f->getchar(); totalverts = max(f->getchar(), 0); @@ -359,8 +301,7 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) memset(c.ext->surfaces, 0, sizeof(c.ext->surfaces)); memset(c.ext->verts(), 0, totalverts*sizeof(vertinfo)); int offset = 0; - loopi(6) if(surfmask&(1<<i)) - { + loopi(6) if(surfmask&(1<<i)) { surfaceinfo &surf = c.ext->surfaces[i]; f->read(&surf, sizeof(surfaceinfo)); int vertmask = surf.verts, numverts = surf.totalverts(); @@ -372,25 +313,21 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) int layerverts = surf.numverts&MAXFACEVERTS, dim = dimension(i), vc = C[dim], vr = R[dim], bias = 0; genfaceverts(c, i, v); bool hasxyz = (vertmask&0x04)!=0, hasuv = (vertmask&0x40)!=0, hasnorm = (vertmask&0x80)!=0; - if(hasxyz) - { + if(hasxyz) { ivec e1, e2, e3; n.cross((e1 = v[1]).sub(v[0]), (e2 = v[2]).sub(v[0])); if(n.iszero()) n.cross(e2, (e3 = v[3]).sub(v[0])); bias = -n.dot(ivec(v[0]).mul(size).add(vo)); } - else - { + else { int vis = layerverts < 4 ? (vertmask&0x02 ? 2 : 1) : 3, order = vertmask&0x01 ? 1 : 0, k = 0; verts[k++].setxyz(v[order].mul(size).add(vo)); if(vis&1) verts[k++].setxyz(v[order+1].mul(size).add(vo)); verts[k++].setxyz(v[order+2].mul(size).add(vo)); if(vis&2) verts[k++].setxyz(v[(order+3)&3].mul(size).add(vo)); } - if(layerverts == 4) - { - if(hasxyz && vertmask&0x01) - { + if(layerverts == 4) { + if(hasxyz && vertmask&0x01) { ushort c1 = f->getlil<ushort>(), r1 = f->getlil<ushort>(), c2 = f->getlil<ushort>(), r2 = f->getlil<ushort>(); ivec xyz; xyz[vc] = c1; xyz[vr] = r1; xyz[dim] = n[dim] ? -(bias + n[vc]*xyz[vc] + n[vr]*xyz[vr])/n[dim] : vo[dim]; @@ -403,16 +340,14 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) verts[3].setxyz(xyz); hasxyz = false; } - if(hasuv && vertmask&0x02) - { + if(hasuv && vertmask&0x02) { int uvorder = (vertmask&0x30)>>4; vertinfo &v0 = verts[uvorder], &v1 = verts[(uvorder+1)&3], &v2 = verts[(uvorder+2)&3], &v3 = verts[(uvorder+3)&3]; v0.u = f->getlil<ushort>(); v0.v = f->getlil<ushort>(); v2.u = f->getlil<ushort>(); v2.v = f->getlil<ushort>(); v1.u = v0.u; v1.v = v2.v; v3.u = v2.u; v3.v = v0.v; - if(surf.numverts&LAYER_DUP) - { + if(surf.numverts&LAYER_DUP) { vertinfo &b0 = verts[4+uvorder], &b1 = verts[4+((uvorder+1)&3)], &b2 = verts[4+((uvorder+2)&3)], &b3 = verts[4+((uvorder+3)&3)]; b0.u = f->getlil<ushort>(); b0.v = f->getlil<ushort>(); b2.u = f->getlil<ushort>(); b2.v = f->getlil<ushort>(); @@ -422,17 +357,14 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) hasuv = false; } } - if(hasnorm && vertmask&0x08) - { + if(hasnorm && vertmask&0x08) { ushort norm = f->getlil<ushort>(); loopk(layerverts) verts[k].norm = norm; hasnorm = false; } - if(hasxyz || hasuv || hasnorm) loopk(layerverts) - { + if(hasxyz || hasuv || hasnorm) loopk(layerverts) { vertinfo &v = verts[k]; - if(hasxyz) - { + if(hasxyz) { ivec xyz; xyz[vc] = f->getlil<ushort>(); xyz[vr] = f->getlil<ushort>(); xyz[dim] = n[dim] ? -(bias + n[vc]*xyz[vc] + n[vr]*xyz[vr])/n[dim] : vo[dim]; @@ -441,8 +373,7 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) if(hasuv) { v.u = f->getlil<ushort>(); v.v = f->getlil<ushort>(); } if(hasnorm) v.norm = f->getlil<ushort>(); } - if(surf.numverts&LAYER_DUP) loopk(layerverts) - { + if(surf.numverts&LAYER_DUP) loopk(layerverts) { vertinfo &v = verts[k+layerverts], &t = verts[k]; v.setxyz(t.x, t.y, t.z); if(hasuv) { v.u = f->getlil<ushort>(); v.v = f->getlil<ushort>(); } @@ -451,30 +382,24 @@ void loadc(stream *f, cube &c, const ivec &co, int size, bool &failed) } } } - c.children = (haschildren ? loadchildren(f, co, size>>1, failed) : NULL); } -cube *loadchildren(stream *f, const ivec &co, int size, bool &failed) -{ +cube *loadchildren(stream *f, const ivec &co, int size, bool &failed) { cube *c = newcubes(); - loopi(8) - { + loopi(8) { loadc(f, c[i], ivec(i, co, size), size, failed); if(failed) break; } return c; } -void savevslot(stream *f, VSlot &vs, int prev) -{ +void savevslot(stream *f, VSlot &vs, int prev) { f->putlil<int>(vs.changed); f->putlil<int>(prev); - if(vs.changed & (1<<VSLOT_SHPARAM)) - { + if(vs.changed & (1<<VSLOT_SHPARAM)) { f->putlil<ushort>(vs.params.length()); - loopv(vs.params) - { + loopv(vs.params) { SlotShaderParam &p = vs.params[i]; f->putlil<ushort>(strlen(p.name)); f->write(p.name, strlen(p.name)); @@ -483,39 +408,32 @@ void savevslot(stream *f, VSlot &vs, int prev) } if(vs.changed & (1<<VSLOT_SCALE)) f->putlil<float>(vs.scale); if(vs.changed & (1<<VSLOT_ROTATION)) f->putlil<int>(vs.rotation); - if(vs.changed & (1<<VSLOT_OFFSET)) - { + if(vs.changed & (1<<VSLOT_OFFSET)) { f->putlil<int>(vs.offset.x); f->putlil<int>(vs.offset.y); } - if(vs.changed & (1<<VSLOT_SCROLL)) - { + if(vs.changed & (1<<VSLOT_SCROLL)) { f->putlil<float>(vs.scroll.x); f->putlil<float>(vs.scroll.y); } if(vs.changed & (1<<VSLOT_LAYER)) f->putlil<int>(vs.layer); - if(vs.changed & (1<<VSLOT_ALPHA)) - { + if(vs.changed & (1<<VSLOT_ALPHA)) { f->putlil<float>(vs.alphafront); f->putlil<float>(vs.alphaback); } - if(vs.changed & (1<<VSLOT_COLOR)) - { + if(vs.changed & (1<<VSLOT_COLOR)) { loopk(3) f->putlil<float>(vs.colorscale[k]); } } -void savevslots(stream *f, int numvslots) -{ +void savevslots(stream *f, int numvslots) { if(vslots.empty()) return; int *prev = new int[numvslots]; for(int i=0;i<numvslots;++i)prev[i]=-1; - loopi(numvslots) - { + loopi(numvslots) { VSlot *vs = vslots[i]; if(vs->changed) continue; - for(;;) - { + for(;;) { VSlot *cur = vs; do vs = vs->next; while(vs && vs->index >= numvslots); if(!vs) break; @@ -523,8 +441,7 @@ void savevslots(stream *f, int numvslots) } } int lastroot = 0; - loopi(numvslots) - { + loopi(numvslots) { VSlot &vs = *vslots[i]; if(!vs.changed) continue; if(lastroot < i) f->putlil<int>(-(i - lastroot)); @@ -535,15 +452,12 @@ void savevslots(stream *f, int numvslots) delete[] prev; } -void loadvslot(stream *f, VSlot &vs, int changed) -{ +void loadvslot(stream *f, VSlot &vs, int changed) { vs.changed = changed; - if(vs.changed & (1<<VSLOT_SHPARAM)) - { + if(vs.changed & (1<<VSLOT_SHPARAM)) { int numparams = f->getlil<ushort>(); string name; - loopi(numparams) - { + loopi(numparams) { SlotShaderParam &p = vs.params.add(); int nlen = f->getlil<ushort>(); f->read(name, min(nlen, MAXSTRLEN-1)); @@ -556,43 +470,35 @@ void loadvslot(stream *f, VSlot &vs, int changed) } if(vs.changed & (1<<VSLOT_SCALE)) vs.scale = f->getlil<float>(); if(vs.changed & (1<<VSLOT_ROTATION)) vs.rotation = clamp(f->getlil<int>(), 0, 7); - if(vs.changed & (1<<VSLOT_OFFSET)) - { + if(vs.changed & (1<<VSLOT_OFFSET)) { vs.offset.x = f->getlil<int>(); vs.offset.y = f->getlil<int>(); } - if(vs.changed & (1<<VSLOT_SCROLL)) - { + if(vs.changed & (1<<VSLOT_SCROLL)) { vs.scroll.x = f->getlil<float>(); vs.scroll.y = f->getlil<float>(); } if(vs.changed & (1<<VSLOT_LAYER)) vs.layer = f->getlil<int>(); - if(vs.changed & (1<<VSLOT_ALPHA)) - { + if(vs.changed & (1<<VSLOT_ALPHA)) { vs.alphafront = f->getlil<float>(); vs.alphaback = f->getlil<float>(); } - if(vs.changed & (1<<VSLOT_COLOR)) - { + if(vs.changed & (1<<VSLOT_COLOR)) { loopk(3) vs.colorscale[k] = f->getlil<float>(); } } -void loadvslots(stream *f, int numvslots) -{ +void loadvslots(stream *f, int numvslots) { int *prev = new (false) int[numvslots]; if(!prev) return; for(int i=0;i<numvslots;++i)prev[i]=-1; - while(numvslots > 0) - { + while(numvslots > 0) { int changed = f->getlil<int>(); - if(changed < 0) - { + if(changed < 0) { loopi(-changed) vslots.add(new VSlot(NULL, vslots.length())); numvslots += changed; } - else - { + else { prev[vslots.length()] = f->getlil<int>(); loadvslot(f, *vslots.add(new VSlot(NULL, vslots.length())), changed); numvslots--; @@ -602,24 +508,19 @@ void loadvslots(stream *f, int numvslots) delete[] prev; } -bool save_world(const char *mname, bool nolms) -{ +bool save_world(const char *mname, bool nolms) { if(!*mname) mname = game::getclientmap(); setmapfilenames(mname); if(savebak) backup(ogzname, bakname); stream *f = opengzfile(ogzname, "wb"); if(!f) { conoutf(CON_WARN, "could not write map to %s", ogzname); return false; } - int numvslots = vslots.length(); - if(!nolms && !multiplayer(false)) - { + if(!nolms && !multiplayer(false)) { numvslots = compactvslots(); allchanged(); } - savemapprogress = 0; renderprogress(0, "saving map..."); - octaheader hdr; memcpy(hdr.magic, "OCTA", 4); hdr.version = MAPVERSION; @@ -632,36 +533,29 @@ bool save_world(const char *mname, bool nolms) hdr.lightmaps = nolms ? 0 : lightmaps.length(); hdr.numvars = 0; hdr.numvslots = numvslots; - enumerate(idents, ident, id, - { + enumerate(idents, ident, id, { if((id.type == ID_VAR || id.type == ID_FVAR || id.type == ID_SVAR) && id.flags&IDF_OVERRIDE && !(id.flags&IDF_READONLY) && id.flags&IDF_OVERRIDDEN) hdr.numvars++; }); lilswap(&hdr.version, 9); f->write(&hdr, sizeof(hdr)); - - enumerate(idents, ident, id, - { + enumerate(idents, ident, id, { if((id.type!=ID_VAR && id.type!=ID_FVAR && id.type!=ID_SVAR) || !(id.flags&IDF_OVERRIDE) || id.flags&IDF_READONLY || !(id.flags&IDF_OVERRIDDEN)) continue; f->putchar(id.type); f->putlil<ushort>(strlen(id.name)); f->write(id.name, strlen(id.name)); - switch(id.type) - { + switch(id.type) { case ID_VAR: f->putlil<int>(*id.storage.i); break; - case ID_FVAR: f->putlil<float>(*id.storage.f); break; - case ID_SVAR: f->putlil<ushort>(strlen(*id.storage.s)); f->write(*id.storage.s, strlen(*id.storage.s)); break; } }); - f->putchar((int)strlen(game::gameident())); f->write(game::gameident(), (int)strlen(game::gameident())+1); f->putlil<ushort>(entities::extraentinfosize()); @@ -669,14 +563,11 @@ bool save_world(const char *mname, bool nolms) game::writegamedata(extras); f->putlil<ushort>(extras.length()); f->write(extras.getbuf(), extras.length()); - f->putlil<ushort>(texmru.length()); loopv(texmru) f->putlil<ushort>(texmru[i]); char *ebuf = new char[entities::extraentinfosize()]; - loopv(ents) - { - if(ents[i]->type!=ET_EMPTY || nolms) - { + loopv(ents) { + if(ents[i]->type!=ET_EMPTY || nolms) { entity tmp = *ents[i]; lilswap(&tmp.o.x, 3); lilswap(&tmp.attr1, 5); @@ -685,21 +576,15 @@ bool save_world(const char *mname, bool nolms) } } delete[] ebuf; - savevslots(f, numvslots); - renderprogress(0, "saving octree..."); savec(worldroot, ivec(0, 0, 0), worldsize>>1, f, nolms); - - if(!nolms) - { + if(!nolms) { if(lightmaps.length()) renderprogress(0, "saving lightmaps..."); - loopv(lightmaps) - { + loopv(lightmaps) { LightMap &lm = lightmaps[i]; f->putchar(lm.type | (lm.unlitx>=0 ? 0x80 : 0)); - if(lm.unlitx>=0) - { + if(lm.unlitx>=0) { f->putlil<ushort>(ushort(lm.unlitx)); f->putlil<ushort>(ushort(lm.unlity)); } @@ -707,7 +592,6 @@ bool save_world(const char *mname, bool nolms) renderprogress(float(i+1)/lightmaps.length(), "saving lightmaps..."); } } - delete f; conoutf("wrote map file %s", ogzname); return true; @@ -718,8 +602,7 @@ static uint mapcrc = 0; uint getmapcrc() { return mapcrc; } void clearmapcrc() { mapcrc = 0; } -bool load_world(const char *mname, const char *cname) // still supports all map formats that have existed since the earliest cube betas! -{ +bool load_world(const char *mname, const char *cname) { // still supports all map formats that have existed since the earliest cube betas! { int loadingstart = SDL_GetTicks(); setmapfilenames(mname, cname); stream *f = opengzfile(ogzname, "rb"); @@ -729,32 +612,21 @@ bool load_world(const char *mname, const char *cname) // still supports all map lilswap(&hdr.version, 6); if(memcmp(hdr.magic, "OCTA", 4) || hdr.worldsize <= 0|| hdr.numents < 0) { conoutf(CON_ERROR, "map %s has malformatted header", ogzname); delete f; return false; } if(hdr.version>MAPVERSION) { conoutf(CON_ERROR, "map %s requires a newer version of Cube 2: Sauerbraten", ogzname); delete f; return false; } - resetmap(); - Texture *mapshot = textureload(picname, 3, true, false); renderbackground("loading...", mapshot, mname, game::getmapinfo()); - game::loadingmap(cname ? cname : mname); - setvar("mapversion", hdr.version, true, false); - lilswap(&hdr.numvslots, 1); - renderprogress(0, "clearing world..."); - freeocta(worldroot); worldroot = NULL; - int worldscale = 0; while(1<<worldscale < hdr.worldsize) worldscale++; setvar("mapsize", 1<<worldscale, true, false); setvar("mapscale", worldscale, true, false); - renderprogress(0, "loading vars..."); - - loopi(hdr.numvars) - { + loopi(hdr.numvars) { int type = f->getchar(), ilen = f->getlil<ushort>(); string name; f->read(name, min(ilen, MAXSTRLEN-1)); @@ -762,24 +634,18 @@ bool load_world(const char *mname, const char *cname) // still supports all map if(ilen >= MAXSTRLEN) f->seek(ilen - (MAXSTRLEN-1), SEEK_CUR); ident *id = getident(name); bool exists = id && id->type == type && id->flags&IDF_OVERRIDE; - switch(type) - { - case ID_VAR: - { + switch(type) { + case ID_VAR: { int val = f->getlil<int>(); if(exists && id->minval <= id->maxval) setvar(name, val); break; } - - case ID_FVAR: - { + case ID_FVAR: { float val = f->getlil<float>(); if(exists && id->minvalf <= id->maxvalf) setfvar(name, val); break; } - - case ID_SVAR: - { + case ID_SVAR: { int slen = f->getlil<ushort>(); string val; f->read(val, min(slen, MAXSTRLEN-1)); @@ -790,73 +656,54 @@ bool load_world(const char *mname, const char *cname) // still supports all map } } } - string gametype; copystring(gametype, "fps"); - int eif = 0; int len = f->getchar(); f->read(gametype, len+1); - eif = f->getlil<ushort>(); int extrasize = f->getlil<ushort>(); vector<char> extras; f->read(extras.pad(extrasize), extrasize); game::readgamedata(extras); - texmru.shrink(0); ushort nummru = f->getlil<ushort>(); loopi(nummru) texmru.add(f->getlil<ushort>()); - renderprogress(0, "loading entities..."); - vector<extentity *> &ents = entities::getents(); int einfosize = entities::extraentinfosize(); char *ebuf = einfosize > 0 ? new char[einfosize] : NULL; - loopi(min(hdr.numents, MAXENTS)) - { + loopi(min(hdr.numents, MAXENTS)) { extentity &e = *entities::newentity(); ents.add(&e); f->read(&e, sizeof(entity)); lilswap(&e.o.x, 3); lilswap(&e.attr1, 5); if(einfosize > 0) f->read(ebuf, einfosize); - if(!insideworld(e.o)) - { - if(e.type != ET_LIGHT && e.type != ET_SPOTLIGHT) - { + if(!insideworld(e.o)) { + if(e.type != ET_LIGHT && e.type != ET_SPOTLIGHT) { conoutf(CON_WARN, "warning: ent outside of world: enttype[%s] index %d (%f, %f, %f)", entities::entname(e.type), i, e.o.x, e.o.y, e.o.z); } } } if(ebuf) delete[] ebuf; - - if(hdr.numents > MAXENTS) - { + if(hdr.numents > MAXENTS) { conoutf(CON_WARN, "warning: map has %d entities", hdr.numents); f->seek((hdr.numents-MAXENTS)*(sizeof(entity) + einfosize), SEEK_CUR); } - renderprogress(0, "loading slots..."); loadvslots(f, hdr.numvslots); - renderprogress(0, "loading octree..."); bool failed = false; worldroot = loadchildren(f, ivec(0, 0, 0), hdr.worldsize>>1, failed); if(failed) conoutf(CON_ERROR, "garbage in map"); - renderprogress(0, "validating..."); validatec(worldroot, hdr.worldsize>>1); - - if(!failed) - { - loopi(hdr.lightmaps) - { + if(!failed) { + loopi(hdr.lightmaps) { renderprogress(i/(float)hdr.lightmaps, "loading lightmaps..."); - LightMap &lm = lightmaps.add(); - { + LightMap &lm = lightmaps.add(); { int type = f->getchar(); lm.type = type&0x7F; - if(type&0x80) - { + if(type&0x80) { lm.unlitx = f->getlil<ushort>(); lm.unlity = f->getlil<ushort>(); } @@ -867,37 +714,25 @@ bool load_world(const char *mname, const char *cname) // still supports all map lm.finalize(); } } - mapcrc = f->getcrc(); delete f; - conoutf("read map %s (%.1f seconds)", ogzname, (SDL_GetTicks()-loadingstart)/1000.0f); - clearmainmenu(); - identflags |= IDF_OVERRIDDEN; execfile("data/default_map.cfg", false); execfile(cfgname, false); identflags &= ~IDF_OVERRIDDEN; - preloadusedmapmodels(true); - game::preload(); flushpreloadedmodels(); - preloadmapsounds(); - entitiesinoctanodes(); attachentities(); initlights(); allchanged(true); - renderbackground("loading...", mapshot, mname, game::getmapinfo()); - if(maptitle[0] && strcmp(maptitle, "Untitled Map by Unknown")) conoutf(CON_ECHO, "%s", maptitle); - startmap(cname ? cname : mname); - return true; } |
