diff --git a/source/src/Makefile b/source/src/Makefile index 2c402e27..a8a40b92 100644 --- a/source/src/Makefile +++ b/source/src/Makefile @@ -18,8 +18,8 @@ CLIENT_OBJS= \ physics.o \ protocol.o \ rendercubes.o \ - renderextras.o \ rendergl.o \ + renderhud.o \ rendermodel.o \ renderparticles.o \ rendertext.o \ @@ -30,6 +30,7 @@ CLIENT_OBJS= \ serverbrowser.o \ serverms.o \ sound.o \ + texture.o \ tools.o \ weapon.o \ world.o \ diff --git a/source/src/cube.h b/source/src/cube.h index c662b4a4..c84bb837 100644 --- a/source/src/cube.h +++ b/source/src/cube.h @@ -121,6 +121,7 @@ extern bool demoplayback; extern bool intermission; extern bool arenajoin; extern int maxclients; +extern bool hasoverbright; extern int VIRTW; // virtual screen size for text & HUD #define VIRTH 1800 diff --git a/source/src/editing.cpp b/source/src/editing.cpp index 0484ffd6..f26436b8 100644 --- a/source/src/editing.cpp +++ b/source/src/editing.cpp @@ -56,6 +56,17 @@ void toggleedit() COMMANDN(edittoggle, toggleedit, ARG_NONE); +char *editinfo() +{ + static string info; + if(!editmode) return NULL; + int e = closestent(); + if(e<0) return NULL; + entity &c = ents[e]; + s_sprintf(info)("closest entity = %s (%d, %d, %d, %d), selection = (%d, %d)", entnames[c.type], c.attr1, c.attr2, c.attr3, c.attr4, sel.xs, sel.ys); + return info; +} + void correctsel() // ensures above invariant { selset = !OUTBORD(sel.x, sel.y); diff --git a/source/src/entities.cpp b/source/src/entities.cpp index cb79ab46..f939f5a6 100644 --- a/source/src/entities.cpp +++ b/source/src/entities.cpp @@ -4,6 +4,14 @@ vector ents; +char *entnames[] = +{ + "none?", "light", "playerstart", + "clips", "ammobox","grenades", + "health", "armour", "akimbo", + "mapmodel", "trigger", + "ladder", "ctf-flag", "?", "?", "?", +}; char *entmdlnames[] = { //FIXME : fix the "pickups" infront @@ -17,8 +25,6 @@ void renderent(entity &e, char *mdlname, float z, float yaw, int anim = ANIM_MAP rendermodel(mdlname, anim, 0, 1.1f, e.x, z+S(e.x, e.y)->floor, e.y, yaw, 0, speed, basetime); } -extern void newparticle(vec &o, vec &d, int fade, int type, int tex = -1); - int triggeranim(entity &e) { int anim = ANIM_TRIGGER; @@ -28,6 +34,13 @@ int triggeranim(entity &e) void renderentities() { + if(editmode) loopv(ents) + { + entity &e = ents[i]; + if(e.type==NOTUSED) continue; + vec v(e.x, e.y, e.z); + particle_splash(2, 2, 40, v); + } if(lastmillis>triggertime+1000) triggertime = 0; loopv(ents) { diff --git a/source/src/hudgun.cpp b/source/src/hudgun.cpp index 496a1e7a..ce21aaed 100644 --- a/source/src/hudgun.cpp +++ b/source/src/hudgun.cpp @@ -95,6 +95,10 @@ struct weaponmove } }; +VARP(hudgun,0,1,1); + +char *hudgunnames[] = { "knife", "pistol", "shotgun", "subgun", "sniper", "assault", "grenade" }; + void renderhudgun(int gun, int lastaction, int index = 0) { vec unitv; @@ -115,6 +119,7 @@ void renderhudgun(int gun, int lastaction, int index = 0) void renderhudgun() { + if(!hudgun) return; if(player1->akimbo && player1->gunselect==GUN_PISTOL) // akimbo { renderhudgun(GUN_PISTOL, player1->akimbolastaction[0], 0); diff --git a/source/src/main.cpp b/source/src/main.cpp index 61813c31..7478c3cd 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -166,6 +166,16 @@ void screenres(int w, int h, int bpp = 0) COMMAND(screenres, ARG_3INT); +VARFP(gamma, 30, 100, 300, +{ + float f = gamma/100.0f; + if(SDL_SetGamma(f,f,f)==-1) + { + conoutf("Could not set gamma (card/driver doesn't support it?)"); + conoutf("sdl: %s", SDL_GetError()); + } +}); + VARP(maxfps, 5, 200, 500); void limitfps(int &millis, int curmillis) diff --git a/source/src/physics.cpp b/source/src/physics.cpp index bfd53274..e28b6d73 100644 --- a/source/src/physics.cpp +++ b/source/src/physics.cpp @@ -399,3 +399,39 @@ void clearbounceents() loopv(bounceents) if(bounceents[i]) { delete bounceents[i]; bounceents.remove(i); } } +VARP(gibnum, 0, 6, 1000); +VARP(gibttl, 0, 5000, 15000); +VARP(gibspeed, 1, 30, 100); + +void addgib(playerent *d) +{ + if(!d) return; + playsound(S_GIB, &d->o); + + loopi(gibnum) + { + bounceent *p = newbounceent(); + p->owner = d; + p->millis = lastmillis; + p->timetolife = gibttl+rnd(10)*100; + p->bouncestate = GIB; + + p->o = d->o; + p->o.z -= d->aboveeye; + + p->yaw = (float)rnd(360); + p->pitch = (float)rnd(360); + + p->maxspeed = 30.0f; + p->rotspeed = 3.0f; + + const float angle = (float)rnd(360); + const float speed = (float)gibspeed; + + p->vel.x = sinf(RAD*angle)*rnd(1000)/1000.0f; + p->vel.y = cosf(RAD*angle)*rnd(1000)/1000.0f; + p->vel.z = rnd(1000)/1000.0f; + p->vel.mul(speed/100.0f); + } +} + diff --git a/source/src/protos.h b/source/src/protos.h index 19388064..b3145db2 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -41,6 +41,19 @@ extern void writeservercfg(); extern void refreshservers(); // rendergl +extern void gl_init(int w, int h, int bpp, int depth, int fsaa); +extern void cleangl(); +extern void line(int x1, int y1, float z1, int x2, int y2, float z2); +extern void box(block &b, float z1, float z2, float z3, float z4); +extern void dot(int x, int y, float z); +extern void linestyle(float width, int r, int g, int b); +extern void blendbox(int x1, int y1, int x2, int y2, bool border, int tex = -1); +extern void quad(GLuint tex, float x, float y, float s, float tx, float ty, float ts); +extern void circle(GLuint tex, float x, float y, float r, float tx, float ty, float tr, int subdiv = 32); +extern void gl_drawframe(int w, int h, float changelod, float curfps); +extern void clearminimap(); + +// texture struct Texture { char *name; @@ -48,27 +61,23 @@ struct Texture GLuint id; }; extern Texture *crosshair; -extern void gl_init(int w, int h, int bpp, int depth, int fsaa); -extern void cleangl(); -extern void gl_drawframe(int w, int h, float changelod, float curfps); + extern void createtexture(int tnum, int w, int h, void *pixels, int clamp, bool mipmap, GLenum format); extern Texture *textureload(const char *name, int clamp = 0); -extern void mipstats(int a, int b, int c); -extern void addstrip(int type, int tex, int start, int n); extern int lookuptexture(int tex, int &xs, int &ys); -extern char *hudgunnames[]; -extern void clearminimap(); // rendercubes -extern void resetcubes(); +extern void mipstats(int a, int b, int c); extern void render_flat(int tex, int x, int y, int size, int h, sqr *l1, sqr *l2, sqr *l3, sqr *l4, bool isceil); extern void render_flatdelta(int wtex, int x, int y, int size, float h1, float h2, float h3, float h4, sqr *l1, sqr *l2, sqr *l3, sqr *l4, bool isceil); extern void render_square(int wtex, float floor1, float floor2, float ceil1, float ceil2, int x1, int y1, int x2, int y2, int size, sqr *l1, sqr *l2, bool topleft); extern void render_tris(int x, int y, int size, bool topleft, sqr *h1, sqr *h2, sqr *s, sqr *t, sqr *u, sqr *v); extern void addwaterquad(int x, int y, int size); extern int renderwater(float hf); -extern void finishstrips(); -extern void setarraypointers(); +extern void resetcubes(); +extern void setupstrips(); +extern void renderstripssky(); +extern void renderstrips(); // client extern void localservertoclient(int chan, uchar *buf, int len); @@ -128,9 +137,7 @@ extern void arenarespawn(); extern void respawn(); extern void mastercommand(int cmd, int arg1); -// clientextras -extern void renderclients(); -extern void renderclient(playerent *d, char *mdlname, char *vwepname, int tex = 0); +// scoreboard extern void showscores(bool on); extern void renderscores(); @@ -181,6 +188,7 @@ extern void text_endcolumns(); // editing extern void cursorupdate(); extern void toggleedit(); +extern char *editinfo(); extern void editdrag(bool isdown); extern void setvdeltaxy(int delta, block &sel); extern void editequalisexy(bool isfloor, block &sel); @@ -190,20 +198,10 @@ extern void editheightxy(bool isfloor, int amount, block &sel); extern bool noteditmode(); extern void pruneundos(int maxremain = 0); -// renderextras -extern void line(int x1, int y1, float z1, int x2, int y2, float z2); -extern void box(block &b, float z1, float z2, float z3, float z4); -extern void dot(int x, int y, float z); -extern void linestyle(float width, int r, int g, int b); -extern void newsphere(vec &o, float max, int type); -extern void renderspheres(int time); +// renderhud extern void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater); -extern void readdepth(int w, int h, vec &pos = worldpos); -extern void blendbox(int x1, int y1, int x2, int y2, bool border, int tex = -1); extern void damageblend(int n); -extern void renderbounceents(); extern bool scoped; -extern void addgib(playerent *d); extern void loadingscreen(); // renderparticles @@ -238,6 +236,7 @@ extern void physicsframe(); extern bounceent *newbounceent(); extern void mbounceents(); extern void clearbounceents(); +extern void addgib(playerent *d); // sound extern void playsound(int n, vec *loc = 0); @@ -256,8 +255,13 @@ extern model *loadmodel(const char *name, int i = -1); extern void preload_playermodels(); extern void preload_hudguns(); extern void preload_mapmodels(); +extern void renderclients(); +extern void renderclient(playerent *d, char *mdlname, char *vwepname, int tex = 0); +extern void renderbounceents(); // hudgun +extern char *hudgunnames[]; + extern void renderhudgun(); // server @@ -304,7 +308,8 @@ extern bool intersect(dynent *d, vec &from, vec &to, vec *end = NULL); // End add by Rick // entities -extern void renderents(); +extern char *entnames[]; + extern void putitems(ucharbuf &p); extern void realpickup(int n, playerent *d); extern void renderentities(); diff --git a/source/src/rendercubes.cpp b/source/src/rendercubes.cpp index c2ee97e9..92bfbeea 100644 --- a/source/src/rendercubes.cpp +++ b/source/src/rendercubes.cpp @@ -4,12 +4,106 @@ vector verts; -void setarraypointers() +void finishstrips(); + +#ifdef __APPLE__ + #define GL_COMBINE_EXT GL_COMBINE_ARB + #define GL_COMBINE_RGB_EXT GL_COMBINE_RGB_ARB + #define GL_SOURCE0_RGB_EXT GL_SOURCE0_RGB_ARB + #define GL_SOURCE1_RGB_EXT GL_SOURCE1_RGB_ARB + #define GL_RGB_SCALE_EXT GL_RGB_SCALE_ARB + #define GL_PRIMARY_COLOR_EXT GL_PRIMARY_COLOR_ARB +#endif + +void setupstrips() { - vertex *buf = verts.getbuf(); + finishstrips(); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + vertex *buf = verts.getbuf(); glVertexPointer(3, GL_FLOAT, sizeof(vertex), &buf->x); glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), &buf->r); glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), &buf->u); + + if(hasoverbright) + { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); + } +} + +struct strip { int type, start, num; }; + +struct stripbatch +{ + int tex; + vector strips; +}; + +vector skystrips; +stripbatch stripbatches[256]; +uchar renderedtex[256]; +int renderedtexs = 0; + +void renderstripssky() +{ + if(skystrips.empty()) return; + int xs, ys; + glBindTexture(GL_TEXTURE_2D, lookuptexture(DEFAULT_SKY, xs, ys)); + loopv(skystrips) glDrawArrays(skystrips[i].type, skystrips[i].start, skystrips[i].num); + skystrips.setsizenodelete(0); +} + +void renderstrips() +{ + int xs, ys; + loopj(renderedtexs) + { + stripbatch &sb = stripbatches[j]; + glBindTexture(GL_TEXTURE_2D, lookuptexture(sb.tex, xs, ys)); + loopv(sb.strips) glDrawArrays(sb.strips[i].type, sb.strips[i].start, sb.strips[i].num); + sb.strips.setsizenodelete(0); + } + renderedtexs = 0; +} + +void addstrip(int type, int tex, int start, int n) +{ + vector *strips; + + if(tex==DEFAULT_SKY) + { + if(minimap) return; + strips = &skystrips; + } + else + { + stripbatch *sb = &stripbatches[renderedtex[tex]]; + if(sb->tex!=tex || sb>=&stripbatches[renderedtexs]) + { + sb = &stripbatches[renderedtex[tex] = renderedtexs++]; + sb->tex = tex; + } + strips = &sb->strips; + } + if(type!=GL_TRIANGLE_STRIP && !strips->empty()) + { + strip &last = strips->last(); + if(last.type==type && last.start+last.num==start) + { + last.num += n; + return; + } + } + strip &s = strips->add(); + s.type = type; + s.start = start; + s.num = n; } // generating the actual vertices is done dynamically every frame and sits at the diff --git a/source/src/rendergl.cpp b/source/src/rendergl.cpp index b54dffed..5389232c 100644 --- a/source/src/rendergl.cpp +++ b/source/src/rendergl.cpp @@ -3,15 +3,6 @@ #include "cube.h" #include "bot/bot.h" -#ifdef __APPLE__ - #define GL_COMBINE_EXT GL_COMBINE_ARB - #define GL_COMBINE_RGB_EXT GL_COMBINE_RGB_ARB - #define GL_SOURCE0_RGB_EXT GL_SOURCE0_RGB_ARB - #define GL_SOURCE1_RGB_EXT GL_SOURCE1_RGB_ARB - #define GL_RGB_SCALE_EXT GL_RGB_SCALE_ARB - #define GL_PRIMARY_COLOR_EXT GL_PRIMARY_COLOR_ARB -#endif - bool hasoverbright = false; VAR(maxtexsize, 0, 0, 4096); @@ -54,221 +45,155 @@ void gl_init(int w, int h, int bpp, int depth, int fsaa) camera1 = player1; } -Texture *crosshair = NULL; -hashtable textures; - void cleangl() { } -void createtexture(int tnum, int w, int h, void *pixels, int clamp, bool mipmap, GLenum format) -{ - glBindTexture(GL_TEXTURE_2D, tnum); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp&1 ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp&2 ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - int tw = w, th = h; - if(maxtexsize) while(tw>maxtexsize || th>maxtexsize) { tw /= 2; th /= 2; } - if(tw!=w) - { - if(gluScaleImage(format, w, h, GL_UNSIGNED_BYTE, pixels, tw, th, GL_UNSIGNED_BYTE, pixels)) - { - tw = w; - th = h; - } - } - if(mipmap) - { - if(gluBuild2DMipmaps(GL_TEXTURE_2D, format, tw, th, format, GL_UNSIGNED_BYTE, pixels)) fatal("could not build mipmaps"); - } - else glTexImage2D(GL_TEXTURE_2D, 0, format, tw, th, 0, format, GL_UNSIGNED_BYTE, pixels); -} - -GLuint loadsurface(const char *texname, int &xs, int &ys, int clamp) -{ - SDL_Surface *s = IMG_Load(texname); - if(!s) { conoutf("couldn't load texture %s", texname); return 0; } - if(s->format->BitsPerPixel!=24 && s->format->BitsPerPixel!=32) - { - SDL_FreeSurface(s); - conoutf("texture must be 24bpp or 32bpp: %s", texname); - return 0; - } - GLuint tnum; - glGenTextures(1, &tnum); - createtexture(tnum, s->w, s->h, s->pixels, clamp, true, s->format->BitsPerPixel==24 ? GL_RGB : GL_RGBA); - xs = s->w; - ys = s->h; - SDL_FreeSurface(s); - return tnum; -} - -// management of texture slots -// each texture slot can have multople texture frames, of which currently only the first is used -// additional frames can be used for various shaders - -Texture *textureload(const char *name, int clamp) -{ - string pname; - s_strcpy(pname, name); - path(pname); - Texture *t = textures.access(pname); - if(t) return t; - int xs, ys; - GLuint id = loadsurface(pname, xs, ys, clamp); - if(!id) return crosshair; - char *key = newstring(pname); - t = &textures[key]; - t->name = key; - t->xs = xs; - t->ys = ys; - t->id = id; - return t; -} - -struct Slot -{ - string name; - Texture *tex; - bool loaded; -}; - -vector slots; - -void texturereset() { slots.setsizenodelete(0); } - -void texture(char *aframe, char *name) -{ - Slot &s = slots.add(); - s_strcpy(s.name, name); - path(s.name); - s.tex = NULL; - s.loaded = false; -} - -COMMAND(texturereset, ARG_NONE); -COMMAND(texture, ARG_2STR); - -int lookuptexture(int tex, int &xs, int &ys) -{ - Texture *t = crosshair; - if(slots.inrange(tex)) - { - Slot &s = slots[tex]; - if(!s.loaded) - { - s_sprintfd(pname)("packages/textures/%s", s.name); - s.tex = textureload(pname); - s.loaded = true; - } - if(s.tex) t = s.tex; - } - - xs = t->xs; - ys = t->ys; - return t->id; -} - -void setupworld() -{ - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - setarraypointers(); - - if(hasoverbright) - { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); - } -} - -struct strip { int type, start, num; }; - -struct stripbatch -{ - int tex; - vector strips; -}; - -vector skystrips; -stripbatch stripbatches[256]; -uchar renderedtex[256]; -int renderedtexs = 0; - -void renderstripssky() -{ - if(skystrips.empty()) return; - int xs, ys; - glBindTexture(GL_TEXTURE_2D, lookuptexture(DEFAULT_SKY, xs, ys)); - loopv(skystrips) glDrawArrays(skystrips[i].type, skystrips[i].start, skystrips[i].num); - skystrips.setsizenodelete(0); -} - -void renderstrips() -{ - int xs, ys; - loopj(renderedtexs) - { - stripbatch &sb = stripbatches[j]; - glBindTexture(GL_TEXTURE_2D, lookuptexture(sb.tex, xs, ys)); - loopv(sb.strips) glDrawArrays(sb.strips[i].type, sb.strips[i].start, sb.strips[i].num); - sb.strips.setsizenodelete(0); - } - renderedtexs = 0; -} - void overbright(float amount) { if(hasoverbright) glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, amount ); } -void addstrip(int type, int tex, int start, int n) +void line(int x1, int y1, float z1, int x2, int y2, float z2) { - vector *strips; + glBegin(GL_POLYGON); + glVertex3f((float)x1, z1, (float)y1); + glVertex3f((float)x1, z1, y1+0.01f); + glVertex3f((float)x2, z2, y2+0.01f); + glVertex3f((float)x2, z2, (float)y2); + glEnd(); + xtraverts += 4; +} - if(tex==DEFAULT_SKY) +void linestyle(float width, int r, int g, int b) +{ + glLineWidth(width); + glColor3ub(r,g,b); +} + +void box(block &b, float z1, float z2, float z3, float z4) +{ + glBegin(GL_POLYGON); + glVertex3f((float)b.x, z1, (float)b.y); + glVertex3f((float)b.x+b.xs, z2, (float)b.y); + glVertex3f((float)b.x+b.xs, z3, (float)b.y+b.ys); + glVertex3f((float)b.x, z4, (float)b.y+b.ys); + glEnd(); + xtraverts += 4; +} + +void quad(GLuint tex, float x, float y, float s, float tx, float ty, float ts) +{ + glBindTexture(GL_TEXTURE_2D, tex); + glBegin(GL_QUADS); + glTexCoord2f(tx, ty); glVertex2f(x, y); + glTexCoord2f(tx+ts, ty); glVertex2f(x+s, y); + glTexCoord2f(tx+ts, ty+ts); glVertex2f(x+s, y+s); + glTexCoord2f(tx, ty+ts); glVertex2f(x, y+s); + glEnd(); + xtraverts += 4; +} + +void circle(GLuint tex, float x, float y, float r, float tx, float ty, float tr, int subdiv) +{ + glBindTexture(GL_TEXTURE_2D, tex); + glBegin(GL_TRIANGLE_FAN); + glTexCoord2f(tx, ty); + glVertex2f(x, y); + loopi(subdiv+1) { - if(minimap) return; - strips = &skystrips; + float c = cosf(2*M_PI*i/float(subdiv)), s = sinf(2*M_PI*i/float(subdiv)); + glTexCoord2f(tx + tr*c, ty + tr*s); + glVertex2f(x + r*c, y + r*s); + } + glEnd(); + xtraverts += subdiv+2; +} + +void dot(int x, int y, float z) +{ + const float DOF = 0.1f; + glBegin(GL_POLYGON); + glVertex3f(x-DOF, (float)z, y-DOF); + glVertex3f(x+DOF, (float)z, y-DOF); + glVertex3f(x+DOF, (float)z, y+DOF); + glVertex3f(x-DOF, (float)z, y+DOF); + glEnd(); + xtraverts += 4; +} + +void blendbox(int x1, int y1, int x2, int y2, bool border, int tex) +{ + glDepthMask(GL_FALSE); + glDisable(GL_TEXTURE_2D); + if(tex>=0) + { + glBindTexture(GL_TEXTURE_2D, tex); + glEnable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glColor3f(1, 1, 1); + + int texw = 512; + int texh = texw; + int cols = (int)((x2-x1)/texw+1); + int rows = (int)((y2-y1)/texh+1); + xtraverts += cols*rows*4; + + loopj(rows) + { + float ytexcut = 0.0f; + float yboxcut = 0.0f; + if((j+1)*texh>y2-y1) // cut last row to match the box height + { + yboxcut = (float)(((j+1)*texh)-(y2-y1)); + ytexcut = (float)(((j+1)*texh)-(y2-y1))/texh; + } + + loopi(cols) + { + float xtexcut = 0.0f; + float xboxcut = 0.0f; + if((i+1)*texw>x2-x1) + { + xboxcut = (float)(((i+1)*texw)-(x2-x1)); + xtexcut = (float)(((i+1)*texw)-(x2-x1))/texw; + } + + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f((float)x1+texw*i, (float)y1+texh*j); + glTexCoord2f(1-xtexcut, 0); glVertex2f(x1+texw*(i+1)-xboxcut, (float)y1+texh*j); + glTexCoord2f(1-xtexcut, 1-ytexcut); glVertex2f(x1+texw*(i+1)-xboxcut, (float)y1+texh*(j+1)-yboxcut); + glTexCoord2f(0, 1-ytexcut); glVertex2f((float)x1+texw*i, y1+texh*(j+1)-yboxcut); + glEnd(); + } + } } else { - stripbatch *sb = &stripbatches[renderedtex[tex]]; - if(sb->tex!=tex || sb>=&stripbatches[renderedtexs]) - { - sb = &stripbatches[renderedtex[tex] = renderedtexs++]; - sb->tex = tex; - } - strips = &sb->strips; + if(border) glColor3f(0.7f, 0.7f, 0.7f); //glColor3d(0.5, 0.3, 0.4); + else glColor3f(1, 1, 1); + glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(x1, y1); + glTexCoord2f(1, 0); glVertex2i(x2, y1); + glTexCoord2f(1, 1); glVertex2i(x2, y2); + glTexCoord2f(0, 1); glVertex2i(x1, y2); + glEnd(); + xtraverts += 4; } - if(type!=GL_TRIANGLE_STRIP && !strips->empty()) - { - strip &last = strips->last(); - if(last.type==type && last.start+last.num==start) - { - last.num += n; - return; - } - } - strip &s = strips->add(); - s.type = type; - s.start = start; - s.num = n; -} -VARFP(gamma, 30, 100, 300, -{ - float f = gamma/100.0f; - if(SDL_SetGamma(f,f,f)==-1) - { - conoutf("Could not set gamma (card/driver doesn't support it?)"); - conoutf("sdl: %s", SDL_GetError()); - } -}); + glDisable(GL_BLEND); + if(tex>=0) glDisable(GL_TEXTURE_2D); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glBegin(GL_POLYGON); + glColor3f(0.6f, 0.6f, 0.6f); //glColor3d(0.2, 0.7, 0.4); + glVertex2i(x1, y1); + glVertex2i(x2, y1); + glVertex2i(x2, y2); + glVertex2i(x1, y2); + glEnd(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glEnable(GL_BLEND); + glEnable(GL_TEXTURE_2D); + glDepthMask(GL_TRUE); +} physent *camera1 = NULL; @@ -369,9 +294,8 @@ void drawminimap() render_world(camera1->o.x, camera1->o.y, camera1->o.z, 1.0f, (int)camera1->yaw, (int)camera1->pitch, 90.0f, size, size); - finishstrips(); - setupworld(); + setupstrips(); overbright(2); glDepthFunc(GL_ALWAYS); @@ -404,10 +328,6 @@ int xtraverts; VAR(fog, 64, 180, 1024); VAR(fogcolour, 0, 0x8099B3, 0xFFFFFF); -VARP(hudgun,0,1,1); - -char *hudgunnames[] = { "knife", "pistol", "shotgun", "subgun", "sniper", "assault", "grenade" }; - void drawhudgun(int w, int h, float aspect, int farplane) { if(scoped && player1->gunselect==GUN_SNIPER) return; @@ -419,7 +339,7 @@ void drawhudgun(int w, int h, float aspect, int farplane) gluPerspective((float)100.0f*h/w, aspect, 0.3f, farplane); // fov fixed at 100° glMatrixMode(GL_MODELVIEW); - if(hudgun && player1->state!=CS_DEAD) renderhudgun(); + if(player1->state!=CS_DEAD) renderhudgun(); rendermenumdl(); glMatrixMode(GL_PROJECTION); @@ -439,6 +359,58 @@ bool outsidemap(physent *pl) || pl->o.z > s->ceil + (s->type==CHF ? s->vdelta/4 : 0); } +float cursordepth = 0.9f; +GLint viewport[4]; +GLdouble mm[16], pm[16]; +vec worldpos, camup, camright; + +void readmatrices() +{ + glGetIntegerv(GL_VIEWPORT, viewport); + glGetDoublev(GL_MODELVIEW_MATRIX, mm); + glGetDoublev(GL_PROJECTION_MATRIX, pm); + camright = vec(float(mm[0]), float(mm[4]), float(mm[8])); + camup = vec(float(mm[1]), float(mm[5]), float(mm[9])); +} + +// stupid function to cater for stupid ATI linux drivers that return incorrect depth values + +float depthcorrect(float d) +{ + return (d<=1/256.0f) ? d*256 : d; +} + +// find out the 3d target of the crosshair in the world easily and very acurately. +// sadly many very old cards and drivers appear to fuck up on glReadPixels() and give false +// coordinates, making shooting and such impossible. +// also hits map entities which is unwanted. +// could be replaced by a more acurate version of monster.cpp los() if needed + +void readdepth(int w, int h, vec &pos) +{ + glReadPixels(w/2, h/2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &cursordepth); + double worldx = 0, worldy = 0, worldz = 0; + gluUnProject(w/2, h/2, depthcorrect(cursordepth), mm, pm, viewport, &worldx, &worldz, &worldy); + pos.x = (float)worldx; + pos.y = (float)worldy; + pos.z = (float)worldz; +} + +void invertperspective() +{ + // This only generates a valid inverse matrix for matrices generated by gluPerspective() + GLdouble inv[16]; + memset(inv, 0, sizeof(inv)); + + inv[0*4+0] = 1.0/pm[0*4+0]; + inv[1*4+1] = 1.0/pm[1*4+1]; + inv[2*4+3] = 1.0/pm[3*4+2]; + inv[3*4+2] = -1.0; + inv[3*4+3] = pm[2*4+2]/pm[3*4+2]; + + glLoadMatrixd(inv); +} + void gl_drawframe(int w, int h, float changelod, float curfps) { drawminimap(); @@ -480,9 +452,8 @@ void gl_drawframe(int w, int h, float changelod, float curfps) render_world(camera1->o.x, camera1->o.y, camera1->o.z, changelod, (int)camera1->yaw, (int)camera1->pitch, (float)fov, w, h); - finishstrips(); - setupworld(); + setupstrips(); renderstripssky(); @@ -507,14 +478,13 @@ void gl_drawframe(int w, int h, float changelod, float curfps) renderentities(); - readdepth(w, h); + readmatrices(); + readdepth(w, h, worldpos); renderclients(); if(player1->state==CS_ALIVE) readdepth(w, h, hitpos); - renderents(); - renderbounceents(); // Added by Rick: Need todo here because of drawing the waypoints @@ -535,6 +505,15 @@ void gl_drawframe(int w, int h, float changelod, float curfps) glDisable(GL_FOG); glDisable(GL_TEXTURE_2D); + if(editmode) + { + if(cursordepth==1.0f) worldpos = camera1->o; + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + cursorupdate(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + + invertperspective(); extern vector verts; gl_drawhud(w, h, (int)curfps, nquads, verts.length(), underwater); diff --git a/source/src/renderextras.cpp b/source/src/renderhud.cpp similarity index 59% rename from source/src/renderextras.cpp rename to source/src/renderhud.cpp index 2b7bf2f3..2602105d 100644 --- a/source/src/renderextras.cpp +++ b/source/src/renderhud.cpp @@ -1,217 +1,7 @@ -// renderextras.cpp: misc gl render code and the HUD +// renderhud.cpp: HUD rendering #include "cube.h" -void line(int x1, int y1, float z1, int x2, int y2, float z2) -{ - glBegin(GL_POLYGON); - glVertex3f((float)x1, z1, (float)y1); - glVertex3f((float)x1, z1, y1+0.01f); - glVertex3f((float)x2, z2, y2+0.01f); - glVertex3f((float)x2, z2, (float)y2); - glEnd(); - xtraverts += 4; -} - -void linestyle(float width, int r, int g, int b) -{ - glLineWidth(width); - glColor3ub(r,g,b); -} - -void box(block &b, float z1, float z2, float z3, float z4) -{ - glBegin(GL_POLYGON); - glVertex3f((float)b.x, z1, (float)b.y); - glVertex3f((float)b.x+b.xs, z2, (float)b.y); - glVertex3f((float)b.x+b.xs, z3, (float)b.y+b.ys); - glVertex3f((float)b.x, z4, (float)b.y+b.ys); - glEnd(); - xtraverts += 4; -} - -void quad(GLuint tex, float x, float y, float s, float tx, float ty, float ts) -{ - glBindTexture(GL_TEXTURE_2D, tex); - glBegin(GL_QUADS); - glTexCoord2f(tx, ty); glVertex2f(x, y); - glTexCoord2f(tx+ts, ty); glVertex2f(x+s, y); - glTexCoord2f(tx+ts, ty+ts); glVertex2f(x+s, y+s); - glTexCoord2f(tx, ty+ts); glVertex2f(x, y+s); - glEnd(); - xtraverts += 4; -} - -void circle(GLuint tex, float x, float y, float r, float tx, float ty, float tr, int subdiv = 32) -{ - glBindTexture(GL_TEXTURE_2D, tex); - glBegin(GL_TRIANGLE_FAN); - glTexCoord2f(tx, ty); - glVertex2f(x, y); - loopi(subdiv+1) - { - float c = cosf(2*M_PI*i/float(subdiv)), s = sinf(2*M_PI*i/float(subdiv)); - glTexCoord2f(tx + tr*c, ty + tr*s); - glVertex2f(x + r*c, y + r*s); - } - glEnd(); - xtraverts += subdiv+2; -} - -void dot(int x, int y, float z) -{ - const float DOF = 0.1f; - glBegin(GL_POLYGON); - glVertex3f(x-DOF, (float)z, y-DOF); - glVertex3f(x+DOF, (float)z, y-DOF); - glVertex3f(x+DOF, (float)z, y+DOF); - glVertex3f(x-DOF, (float)z, y+DOF); - glEnd(); - xtraverts += 4; -} - -void blendbox(int x1, int y1, int x2, int y2, bool border, int tex) -{ - glDepthMask(GL_FALSE); - glDisable(GL_TEXTURE_2D); - if(tex>=0) - { - glBindTexture(GL_TEXTURE_2D, tex); - glEnable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - glColor3f(1, 1, 1); - - int texw = 512; - int texh = texw; - int cols = (int)((x2-x1)/texw+1); - int rows = (int)((y2-y1)/texh+1); - xtraverts += cols*rows*4; - - loopj(rows) - { - float ytexcut = 0.0f; - float yboxcut = 0.0f; - if((j+1)*texh>y2-y1) // cut last row to match the box height - { - yboxcut = (float)(((j+1)*texh)-(y2-y1)); - ytexcut = (float)(((j+1)*texh)-(y2-y1))/texh; - } - - loopi(cols) - { - float xtexcut = 0.0f; - float xboxcut = 0.0f; - if((i+1)*texw>x2-x1) - { - xboxcut = (float)(((i+1)*texw)-(x2-x1)); - xtexcut = (float)(((i+1)*texw)-(x2-x1))/texw; - } - - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f((float)x1+texw*i, (float)y1+texh*j); - glTexCoord2f(1-xtexcut, 0); glVertex2f(x1+texw*(i+1)-xboxcut, (float)y1+texh*j); - glTexCoord2f(1-xtexcut, 1-ytexcut); glVertex2f(x1+texw*(i+1)-xboxcut, (float)y1+texh*(j+1)-yboxcut); - glTexCoord2f(0, 1-ytexcut); glVertex2f((float)x1+texw*i, y1+texh*(j+1)-yboxcut); - glEnd(); - } - } - } - else - { - if(border) glColor3f(0.7f, 0.7f, 0.7f); //glColor3d(0.5, 0.3, 0.4); - else glColor3f(1, 1, 1); - glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2i(x1, y1); - glTexCoord2f(1, 0); glVertex2i(x2, y1); - glTexCoord2f(1, 1); glVertex2i(x2, y2); - glTexCoord2f(0, 1); glVertex2i(x1, y2); - glEnd(); - xtraverts += 4; - } - - glDisable(GL_BLEND); - if(tex>=0) glDisable(GL_TEXTURE_2D); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glBegin(GL_POLYGON); - glColor3f(0.6f, 0.6f, 0.6f); //glColor3d(0.2, 0.7, 0.4); - glVertex2i(x1, y1); - glVertex2i(x2, y1); - glVertex2i(x2, y2); - glVertex2i(x1, y2); - glEnd(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glDepthMask(GL_TRUE); -} - -string closeent; -char *entnames[] = -{ - "none?", "light", "playerstart", - "clips", "ammobox","grenades", - "health", "armour", "akimbo", - "mapmodel", "trigger", - "ladder", "ctf-flag", "?", "?", "?", -}; - -void renderents() // show sparkly thingies for map entities in edit mode -{ - closeent[0] = 0; - if(!editmode) return; - loopv(ents) - { - entity &e = ents[i]; - if(e.type==NOTUSED) continue; - vec v(e.x, e.y, e.z); - particle_splash(2, 2, 40, v); - } - int e = closestent(); - if(e>=0) - { - entity &c = ents[e]; - s_sprintf(closeent)("closest entity = %s (%d, %d, %d, %d), selection = (%d, %d)", entnames[c.type], c.attr1, c.attr2, c.attr3, c.attr4, getvar("selxs"), getvar("selys")); - } -} - -float cursordepth = 0.9f; -GLint viewport[4]; -GLdouble mm[16], pm[16]; -vec worldpos, camup, camright; - -void readmatrices() -{ - glGetIntegerv(GL_VIEWPORT, viewport); - glGetDoublev(GL_MODELVIEW_MATRIX, mm); - glGetDoublev(GL_PROJECTION_MATRIX, pm); - camright = vec(float(mm[0]), float(mm[4]), float(mm[8])); - camup = vec(float(mm[1]), float(mm[5]), float(mm[9])); -} - -// stupid function to cater for stupid ATI linux drivers that return incorrect depth values - -float depthcorrect(float d) -{ - return (d<=1/256.0f) ? d*256 : d; -} - -// find out the 3d target of the crosshair in the world easily and very acurately. -// sadly many very old cards and drivers appear to fuck up on glReadPixels() and give false -// coordinates, making shooting and such impossible. -// also hits map entities which is unwanted. -// could be replaced by a more acurate version of monster.cpp los() if needed - -void readdepth(int w, int h, vec &pos) -{ - glReadPixels(w/2, h/2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &cursordepth); - double worldx = 0, worldy = 0, worldz = 0; - gluUnProject(w/2, h/2, depthcorrect(cursordepth), mm, pm, viewport, &worldx, &worldz, &worldy); - pos.x = (float)worldx; - pos.y = (float)worldy; - pos.z = (float)worldz; -} - void drawicon(Texture *tex, float x, float y, float s, int col, int row, float ts) { if(tex && tex->xs == tex->ys) quad(tex->id, x, y, s, ts*col, ts*row, ts); @@ -248,21 +38,6 @@ void drawctficon(float x, float y, float s, int col, int row, float ts) if(tex) drawicon(tex, x, y, s, col, row, ts); } -void invertperspective() -{ - // This only generates a valid inverse matrix for matrices generated by gluPerspective() - GLdouble inv[16]; - memset(inv, 0, sizeof(inv)); - - inv[0*4+0] = 1.0/pm[0*4+0]; - inv[1*4+1] = 1.0/pm[1*4+1]; - inv[2*4+3] = 1.0/pm[3*4+2]; - inv[3*4+2] = -1.0; - inv[3*4+3] = pm[2*4+2]/pm[3*4+2]; - - glLoadMatrixd(inv); -} - VARP(crosshairsize, 0, 15, 50); int dblend = 0; @@ -436,17 +211,7 @@ void drawradar(int w, int h) void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater) { - readmatrices(); - if(editmode) - { - if(cursordepth==1.0f) worldpos = camera1->o; - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - cursorupdate(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } - glDisable(GL_DEPTH_TEST); - invertperspective(); glPushMatrix(); glOrtho(0, VIRTW, VIRTH, 0, -1, 1); @@ -491,8 +256,9 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat glPushMatrix(); glOrtho(0, VIRTW*2, VIRTH*2, 0, -1, 1); + char *infostr = editinfo(); if(getcurcommand()) rendercommand(40, 3140); - else if(closeent[0]) draw_text(closeent, 40, 3140); + else if(infostr) draw_text(infostr, 40, 3140); else if(targetplayer) draw_text(targetplayer->name, 40, 3140); renderconsole(); @@ -572,75 +338,6 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat glEnable(GL_DEPTH_TEST); } -void renderbounceents() -{ - loopv(bounceents) - { - bounceent *p = bounceents[i]; - if(!p) continue; - string model; - float z = p->o.z; - - switch(p->bouncestate) - { - case NADE_THROWED: - s_strcpy(model, "weapons/grenade/static"); - break; - case GIB: - default: - { - uint n = (((4*(uint)(size_t)p)+(uint)p->timetolife)%3)+1; - s_sprintf(model)("misc/gib0%u", n); - int t = lastmillis-p->millis; - if(t>p->timetolife-2000) - { - t -= p->timetolife-2000; - z -= t*t/4000000000.0f*t; - } - break; - } - } - path(model); - rendermodel(model, ANIM_MAPMODEL|ANIM_LOOP, 0, 1.1f, p->o.x, z, p->o.y, p->yaw, p->pitch, 10.0f); - } -} - -VARP(gibnum, 0, 6, 1000); -VARP(gibttl, 0, 5000, 15000); -VARP(gibspeed, 1, 30, 100); - -void addgib(playerent *d) -{ - if(!d) return; - playsound(S_GIB, &d->o); - - loopi(gibnum) - { - bounceent *p = newbounceent(); - p->owner = d; - p->millis = lastmillis; - p->timetolife = gibttl+rnd(10)*100; - p->bouncestate = GIB; - - p->o = d->o; - p->o.z -= d->aboveeye; - - p->yaw = (float)rnd(360); - p->pitch = (float)rnd(360); - - p->maxspeed = 30.0f; - p->rotspeed = 3.0f; - - const float angle = (float)rnd(360); - const float speed = (float)gibspeed; - - p->vel.x = sinf(RAD*angle)*rnd(1000)/1000.0f; - p->vel.y = cosf(RAD*angle)*rnd(1000)/1000.0f; - p->vel.z = rnd(1000)/1000.0f; - p->vel.mul(speed/100.0f); - } -} - void loadingscreen() { static Texture *logo = NULL; diff --git a/source/src/rendermodel.cpp b/source/src/rendermodel.cpp index 12064d42..77e783d6 100644 --- a/source/src/rendermodel.cpp +++ b/source/src/rendermodel.cpp @@ -245,3 +245,36 @@ void renderclients() if(player1->state==CS_DEAD) renderplayer(player1); } +void renderbounceents() +{ + loopv(bounceents) + { + bounceent *p = bounceents[i]; + if(!p) continue; + string model; + float z = p->o.z; + + switch(p->bouncestate) + { + case NADE_THROWED: + s_strcpy(model, "weapons/grenade/static"); + break; + case GIB: + default: + { + uint n = (((4*(uint)(size_t)p)+(uint)p->timetolife)%3)+1; + s_sprintf(model)("misc/gib0%u", n); + int t = lastmillis-p->millis; + if(t>p->timetolife-2000) + { + t -= p->timetolife-2000; + z -= t*t/4000000000.0f*t; + } + break; + } + } + path(model); + rendermodel(model, ANIM_MAPMODEL|ANIM_LOOP, 0, 1.1f, p->o.x, z, p->o.y, p->yaw, p->pitch, 10.0f); + } +} + diff --git a/source/src/texture.cpp b/source/src/texture.cpp new file mode 100644 index 00000000..2b9a350b --- /dev/null +++ b/source/src/texture.cpp @@ -0,0 +1,120 @@ +// texture.cpp: texture management + +#include "cube.h" + +Texture *crosshair = NULL; +hashtable textures; + +void createtexture(int tnum, int w, int h, void *pixels, int clamp, bool mipmap, GLenum format) +{ + glBindTexture(GL_TEXTURE_2D, tnum); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp&1 ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp&2 ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + extern int maxtexsize; + int tw = w, th = h; + if(maxtexsize) while(tw>maxtexsize || th>maxtexsize) { tw /= 2; th /= 2; } + if(tw!=w) + { + if(gluScaleImage(format, w, h, GL_UNSIGNED_BYTE, pixels, tw, th, GL_UNSIGNED_BYTE, pixels)) + { + tw = w; + th = h; + } + } + if(mipmap) + { + if(gluBuild2DMipmaps(GL_TEXTURE_2D, format, tw, th, format, GL_UNSIGNED_BYTE, pixels)) fatal("could not build mipmaps"); + } + else glTexImage2D(GL_TEXTURE_2D, 0, format, tw, th, 0, format, GL_UNSIGNED_BYTE, pixels); +} + +GLuint loadsurface(const char *texname, int &xs, int &ys, int clamp) +{ + SDL_Surface *s = IMG_Load(texname); + if(!s) { conoutf("couldn't load texture %s", texname); return 0; } + if(s->format->BitsPerPixel!=24 && s->format->BitsPerPixel!=32) + { + SDL_FreeSurface(s); + conoutf("texture must be 24bpp or 32bpp: %s", texname); + return 0; + } + GLuint tnum; + glGenTextures(1, &tnum); + createtexture(tnum, s->w, s->h, s->pixels, clamp, true, s->format->BitsPerPixel==24 ? GL_RGB : GL_RGBA); + xs = s->w; + ys = s->h; + SDL_FreeSurface(s); + return tnum; +} + +// management of texture slots +// each texture slot can have multople texture frames, of which currently only the first is used +// additional frames can be used for various shaders + +Texture *textureload(const char *name, int clamp) +{ + string pname; + s_strcpy(pname, name); + path(pname); + Texture *t = textures.access(pname); + if(t) return t; + int xs, ys; + GLuint id = loadsurface(pname, xs, ys, clamp); + if(!id) return crosshair; + char *key = newstring(pname); + t = &textures[key]; + t->name = key; + t->xs = xs; + t->ys = ys; + t->id = id; + return t; +} + +struct Slot +{ + string name; + Texture *tex; + bool loaded; +}; + +vector slots; + +void texturereset() { slots.setsizenodelete(0); } + +void texture(char *aframe, char *name) +{ + Slot &s = slots.add(); + s_strcpy(s.name, name); + path(s.name); + s.tex = NULL; + s.loaded = false; +} + +COMMAND(texturereset, ARG_NONE); +COMMAND(texture, ARG_2STR); + +int lookuptexture(int tex, int &xs, int &ys) +{ + Texture *t = crosshair; + if(slots.inrange(tex)) + { + Slot &s = slots[tex]; + if(!s.loaded) + { + s_sprintfd(pname)("packages/textures/%s", s.name); + s.tex = textureload(pname); + s.loaded = true; + } + if(s.tex) t = s.tex; + } + + xs = t->xs; + ys = t->ys; + return t->id; +} + diff --git a/source/src/worldlight.cpp b/source/src/worldlight.cpp index 4b0f2174..beedcb2e 100644 --- a/source/src/worldlight.cpp +++ b/source/src/worldlight.cpp @@ -2,8 +2,6 @@ #include "cube.h" -extern bool hasoverbright; - VAR(lightscale,1,4,100); void lightray(float bx, float by, persistent_entity &light) // done in realtime, needs to be fast