diff --git a/source/src/cube.h b/source/src/cube.h index 95979043..e80ab70a 100644 --- a/source/src/cube.h +++ b/source/src/cube.h @@ -86,7 +86,7 @@ extern bool minimap, reflecting, refracting; extern bool demoplayback; extern bool intermission; extern int maxclients; -extern bool hasoverbright, hasmultitexture; +extern bool hasTE, hasMT; extern int VIRTW; // virtual screen size for text & HUD #define VIRTH 1800 diff --git a/source/src/protos.h b/source/src/protos.h index 8043fcad..deed590f 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -65,12 +65,18 @@ struct Texture }; extern Texture *crosshair; -extern void overbright(float amount); 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 int lookuptexture(int tex, int &xs, int &ys); extern void draw_envbox(int fogdist); +extern int maxtmus; +extern void inittmus(); +extern void resettmu(int n); +extern void scaletmu(int n, int rgbscale, int alphascale = 0); +extern void colortmu(int n, float r = 0, float g = 0, float b = 0, float a = 0); +extern void setuptmu(int n, const char *rgbfunc = NULL, const char *alphafunc = NULL); + // rendercubes 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); @@ -336,9 +342,10 @@ extern bool intersect(entity *e, vec &from, vec &to, vec *end=NULL); extern void perlinarea(block &b, int scale, int seed, int psize); // GL_ARB_multitexture -extern PFNGLACTIVETEXTUREARBPROC glActiveTexture_; -extern PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2f_; -extern PFNGLMULTITEXCOORD3FARBPROC glMultiTexCoord3f_; +extern PFNGLACTIVETEXTUREARBPROC glActiveTexture_; +extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTexture_; +extern PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2f_; +extern PFNGLMULTITEXCOORD3FARBPROC glMultiTexCoord3f_; // doc extern void renderdoc(int x, int y); diff --git a/source/src/rendercubes.cpp b/source/src/rendercubes.cpp index a8939e06..bf270b2a 100644 --- a/source/src/rendercubes.cpp +++ b/source/src/rendercubes.cpp @@ -6,26 +6,6 @@ vector verts; 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_SOURCE2_RGB_EXT GL_SOURCE2_RGB_ARB - #define GL_OPERAND0_RGB_EXT GL_OPERAND0_RGB_ARB - #define GL_OPERAND1_RGB_EXT GL_OPERAND1_RGB_ARB - #define GL_OPERAND2_RGB_EXT GL_OPERAND2_RGB_ARB - #define GL_COMBINE_ALPHA_EXT GL_COMBINE_ALPHA_ARB - #define GL_SOURCE0_ALPHA_EXT GL_SOURCE0_ALPHA_ARB - #define GL_SOURCE1_ALPHA_EXT GL_SOURCE1_ALPHA_ARB - #define GL_OPERAND0_ALPHA_EXT GL_OPERAND0_ALPHA_ARB - #define GL_OPERAND1_ALPHA_EXT GL_OPERAND1_ALPHA_ARB - #define GL_PREVIOUS_EXT GL_PREVIOUS_ARB - #define GL_PRIMARY_COLOR_EXT GL_PRIMARY_COLOR_ARB - #define GL_CONSTANT_EXT GL_CONSTANT_ARB - #define GL_RGB_SCALE_EXT GL_RGB_SCALE_ARB -#endif - void setupstrips() { finishstrips(); @@ -38,14 +18,6 @@ void setupstrips() 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; }; @@ -81,6 +53,10 @@ void renderstrips() sb.strips.setsizenodelete(0); } renderedtexs = 0; + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } void addstrip(int type, int tex, int start, int n) @@ -449,32 +425,17 @@ void setprojtexmatrix() void setupmultitexrefract(GLuint reflecttex, GLuint refracttex) { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_CONSTANT_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_CONSTANT_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); + setuptmu(0, "K , T @ Ka"); - float wc[4] = { hdr.watercolor[0]/255.0f, hdr.watercolor[1]/255.0f, hdr.watercolor[2]/255.0f, hdr.watercolor[3]/255.0f }; - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, wc); + colortmu(0, hdr.watercolor[0]/255.0f, hdr.watercolor[1]/255.0f, hdr.watercolor[2]/255.0f, hdr.watercolor[3]/255.0f); glBindTexture(GL_TEXTURE_2D, refracttex); setprojtexmatrix(); glActiveTexture_(GL_TEXTURE1_ARB); glEnable(GL_TEXTURE_2D); - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_ONE_MINUS_SRC_ALPHA); + + setuptmu(1, "P , T @ C~a"); glBindTexture(GL_TEXTURE_2D, reflecttex); setprojtexmatrix(); @@ -484,24 +445,10 @@ void setupmultitexrefract(GLuint reflecttex, GLuint refracttex) void setupmultitexreflect(GLuint reflecttex) { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_CONSTANT_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); - - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_CONSTANT_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA); + setuptmu(0, "T , K @ Ca", "Ka * P~a"); float a = hdr.watercolor[3]/255.0f; - float wc[4] = { hdr.watercolor[0]/255.0f*a, hdr.watercolor[1]/255.0f*a, hdr.watercolor[2]/255.0f*a, 1.0f-a }; - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, wc); + colortmu(0, hdr.watercolor[0]/255.0f*a, hdr.watercolor[1]/255.0f*a, hdr.watercolor[2]/255.0f*a, 1.0f-a); glBindTexture(GL_TEXTURE_2D, reflecttex); setprojtexmatrix(); @@ -509,22 +456,14 @@ void setupmultitexreflect(GLuint reflecttex) void cleanupmultitex(GLuint reflecttex, GLuint refracttex) { - if(!refracttex) - { - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA); - } - 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); - + resettmu(0); glLoadIdentity(); if(refracttex) { glActiveTexture_(GL_TEXTURE1_ARB); glDisable(GL_TEXTURE_2D); + resettmu(1); glLoadIdentity(); glActiveTexture_(GL_TEXTURE0_ARB); } @@ -542,7 +481,7 @@ int renderwater(float hf, GLuint reflecttex, GLuint refracttex) float t = lastmillis/300.0f; - if(mtwater && hasmultitexture && hasoverbright && reflecttex) + if(mtwater && maxtmus>=2 && reflecttex) { if(refracttex) { diff --git a/source/src/rendergl.cpp b/source/src/rendergl.cpp index 0cfa5532..e0300e85 100644 --- a/source/src/rendergl.cpp +++ b/source/src/rendergl.cpp @@ -3,20 +3,19 @@ #include "cube.h" #include "bot/bot.h" -bool hasoverbright = false, hasmultitexture = false; +bool hasTE = false, hasMT = false; // GL_ARB_multitexture -PFNGLACTIVETEXTUREARBPROC glActiveTexture_ = NULL; -PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2f_ = NULL; -PFNGLMULTITEXCOORD3FARBPROC glMultiTexCoord3f_ = NULL; +PFNGLACTIVETEXTUREARBPROC glActiveTexture_ = NULL; +PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTexture_ = NULL; +PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2f_ = NULL; +PFNGLMULTITEXCOORD3FARBPROC glMultiTexCoord3f_ = NULL; void *getprocaddress(const char *name) { return SDL_GL_GetProcAddress(name); } -VAR(maxtexsize, 0, 0, 4096); - void gl_init(int w, int h, int bpp, int depth, int fsaa) { //#define fogvalues 0.5f, 0.6f, 0.7f, 1.0f @@ -49,22 +48,22 @@ void gl_init(int w, int h, int bpp, int depth, int fsaa) conoutf("Renderer: %s (%s)", renderer, vendor); conoutf("Driver: %s", version); - if(strstr(exts, "GL_EXT_texture_env_combine")) hasoverbright = true; - else if(strstr(exts, "GL_ARB_texture_env_combine")) hasoverbright = true; + if(strstr(exts, "GL_EXT_texture_env_combine") || strstr(exts, "GL_ARB_texture_env_combine")) hasTE = true; else conoutf("WARNING: cannot use overbright lighting, using old lighting model!"); if(strstr(exts, "GL_ARB_multitexture")) { - hasmultitexture = true; - glActiveTexture_ = (PFNGLACTIVETEXTUREARBPROC) getprocaddress("glActiveTextureARB"); - glMultiTexCoord2f_ = (PFNGLMULTITEXCOORD2FARBPROC)getprocaddress("glMultiTexCoord2fARB"); - glMultiTexCoord3f_ = (PFNGLMULTITEXCOORD3FARBPROC)getprocaddress("glMultiTexCoord3fARB"); + glActiveTexture_ = (PFNGLACTIVETEXTUREARBPROC) getprocaddress("glActiveTextureARB"); + glClientActiveTexture_ = (PFNGLCLIENTACTIVETEXTUREARBPROC)getprocaddress("glClientActiveTextureARB"); + glMultiTexCoord2f_ = (PFNGLMULTITEXCOORD2FARBPROC) getprocaddress("glMultiTexCoord2fARB"); + glMultiTexCoord3f_ = (PFNGLMULTITEXCOORD3FARBPROC) getprocaddress("glMultiTexCoord3fARB"); + hasMT = true; } - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxtexsize); - if(fsaa) glEnable(GL_MULTISAMPLE); + inittmus(); + camera1 = player1; } @@ -389,20 +388,20 @@ void drawreflection(float hf, int w, int h, float changelod, bool refract) glEnable(GL_FOG); glPopMatrix(); - overbright(2); + setuptmu(0, "T * P x 2"); renderstrips(); renderentities(); renderclients(); - overbright(1); + resettmu(0); render_particles(0); if(refract) glLoadIdentity(); glMatrixMode(GL_PROJECTION); extern int mtwater; - if(refract && !mtwater) + if(refract && (!mtwater || maxtmus<2)) { glLoadIdentity(); glOrtho(0, 1, 0, 1, -1, 1); @@ -499,12 +498,12 @@ void drawminimap(int w, int h) setupstrips(); - overbright(2); + setuptmu(0, "T * P x 2"); glDepthFunc(GL_ALWAYS); renderstrips(); glDepthFunc(GL_LESS); renderentities(); - overbright(1); + resettmu(0); float hf = hdr.waterlevel-0.3f; renderwater(hf, 0, 0); @@ -658,8 +657,8 @@ void gl_drawframe(int w, int h, float changelod, float curfps) glEnable(GL_FOG); transplayer(); - - overbright(2); + + setuptmu(0, "T * P x 2"); renderstrips(); @@ -684,7 +683,7 @@ void gl_drawframe(int w, int h, float changelod, float curfps) drawhudgun(w, h, aspect, farplane); - overbright(1); + resettmu(0); render_particles(curtime); diff --git a/source/src/renderparticles.cpp b/source/src/renderparticles.cpp index 70d0b422..6dfa6d08 100644 --- a/source/src/renderparticles.cpp +++ b/source/src/renderparticles.cpp @@ -2,6 +2,168 @@ #include "cube.h" +static GLushort *hemiindices = NULL; +static vec *hemiverts = NULL; +static int heminumverts = 0, heminumindices = 0; + +static void subdivide(int &nIndices, int &nVerts, int depth, int face); + +static void genface(int &nIndices, int &nVerts, int depth, int i1, int i2, int i3) +{ + int face = nIndices; nIndices += 3; + hemiindices[face] = i1; + hemiindices[face+1] = i2; + hemiindices[face+2] = i3; + subdivide(nIndices, nVerts, depth, face); +} + +static void subdivide(int &nIndices, int &nVerts, int depth, int face) +{ + if(depth-- <= 0) return; + int idx[6]; + loopi(3) idx[i] = hemiindices[face+i]; + loopi(3) + { + int vert = nVerts++; + hemiverts[vert] = vec(hemiverts[idx[i]]).add(hemiverts[idx[(i+1)%3]]).normalize(); //push on to unit sphere + idx[3+i] = vert; + hemiindices[face+i] = vert; + } + subdivide(nIndices, nVerts, depth, face); + loopi(3) genface(nIndices, nVerts, depth, idx[i], idx[3+i], idx[3+(i+2)%3]); +} + +//subdiv version wobble much more nicely than a lat/longitude version +static void inithemisphere(int hres, int depth) +{ + const int tris = hres << (2*depth); + heminumverts = heminumindices = 0; + DELETEA(hemiverts); + DELETEA(hemiindices); + hemiverts = new vec[tris+1]; + hemiindices = new GLushort[tris*3]; + hemiverts[heminumverts++] = vec(0.0f, 0.0f, 1.0f); //build initial 'hres' sided pyramid + loopi(hres) + { + float a = PI2*float(i)/hres; + hemiverts[heminumverts++] = vec(cosf(a), sinf(a), 0.0f); + } + loopi(hres) genface(heminumindices, heminumverts, depth, 0, i+1, 1+(i+1)%hres); +} + +GLuint createexpmodtex(int size, float minval) +{ + uchar *data = new uchar[size*size], *dst = data; + loop(y, size) loop(x, size) + { + float dx = 2*float(x)/(size-1) - 1, dy = 2*float(y)/(size-1) - 1; + float z = 1 - dx*dx - dy*dy; + if(minval) z = sqrtf(max(z, 0)); + else loopk(2) z *= z; + *dst++ = uchar(max(z, minval)*255); + } + GLuint tex = 0; + glGenTextures(1, &tex); + createtexture(tex, size, size, data, 3, true, GL_ALPHA); + delete[] data; + return tex; +} + +static struct expvert +{ + vec pos; + float u, v; +} *expverts = NULL; + +static GLuint expmodtex[2] = {0, 0}; +static GLuint lastexpmodtex = 0; + +void setupexplosion() +{ + const int hres = 5; + const int depth = 2; + if(!hemiindices) inithemisphere(hres, depth); + + static int lastexpmillis = 0; + if(lastexpmillis != lastmillis || !expverts) + { + vec center = vec(13.0f, 2.3f, 7.1f); //only update once per frame! - so use the same center for all... + lastexpmillis = lastmillis; + if(!expverts) expverts = new expvert[heminumverts]; + loopi(heminumverts) + { + expvert &e = expverts[i]; + vec &v = hemiverts[i]; + //texgen - scrolling billboard + e.u = v.x*0.5f + 0.001f*lastmillis; + e.v = v.y*0.5f + 0.001f*lastmillis; + //wobble - similar to shader code + float wobble = v.dot(center) + 0.002f*lastmillis; + wobble -= floor(wobble); + wobble = 1.0f + fabs(wobble - 0.5f)*0.5f; + e.pos = vec(v).mul(wobble); + } + } + + if(maxtmus>=2) + { + setuptmu(0, "C * T", "= Ca"); + glActiveTexture_(GL_TEXTURE1_ARB); + glEnable(GL_TEXTURE_2D); + + GLfloat s[4] = { 0.5f, 0, 0, 0.5f }, t[4] = { 0, 0.5f, 0, 0.5f }; + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGenfv(GL_S, GL_OBJECT_PLANE, s); + glTexGenfv(GL_T, GL_OBJECT_PLANE, t); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + + setuptmu(1, "P * Ta x 4", "Pa * Ta x 4"); + + glActiveTexture_(GL_TEXTURE0_ARB); + + if(!expmodtex[0]) expmodtex[0] = createexpmodtex(64, 0); + if(!expmodtex[1]) expmodtex[1] = createexpmodtex(64, 0.25f); + lastexpmodtex = 0; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(expvert), &expverts->pos); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(expvert), &expverts->u); +} + +void drawexplosion(bool inside) +{ + if(maxtmus>=2 && lastexpmodtex != expmodtex[inside ? 1 : 0]) + { + glActiveTexture_(GL_TEXTURE1_ARB); + lastexpmodtex = expmodtex[inside ? 1 :0]; + glBindTexture(GL_TEXTURE_2D, lastexpmodtex); + glActiveTexture_(GL_TEXTURE0_ARB); + } + + glDrawElements(GL_TRIANGLES, heminumindices, GL_UNSIGNED_SHORT, hemiindices); +} + +void cleanupexplosion() +{ + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + if(maxtmus>=2) + { + resettmu(0); + glActiveTexture_(GL_TEXTURE1_ARB); + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + resettmu(1); + glActiveTexture_(GL_TEXTURE0_ARB); + } +} + #define MAXPARTYPES 8 struct particle { vec o, d; int fade, type; int millis; particle *next; }; @@ -17,16 +179,6 @@ void particleinit() parttex[1] = textureload("packages/misc/smoke.png"); parttex[2] = textureload("packages/misc/explosion.jpg"); parttex[3] = textureload("packages/misc/hole.png"); - - GLUquadricObj *qsphere = gluNewQuadric(); - if(!qsphere) fatal("glu sphere"); - gluQuadricDrawStyle(qsphere, GLU_FILL); - gluQuadricOrientation(qsphere, GLU_OUTSIDE); - gluQuadricTexture(qsphere, GL_TRUE); - glNewList(1, GL_COMPILE); - gluSphere(qsphere, 1, 12, 6); - glEndList(); - gluDeleteQuadric(qsphere); } void particlereset() @@ -109,6 +261,7 @@ void render_particles(int time) } parttype &pt = parttypes[i]; + if(pt.type!=PT_FIREBALL) continue; float sz = pt.sz*particlesize/100.0f; if(pt.tex>=0) glBindTexture(GL_TEXTURE_2D, parttex[pt.tex]->id); @@ -122,6 +275,7 @@ void render_particles(int time) break; case PT_FIREBALL: + setupexplosion(); glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; @@ -150,19 +304,27 @@ void render_particles(int time) break; case PT_FIREBALL: + { sz = 1.0f + (pt.sz-1.0f)*min(p->fade, lastmillis-p->millis)/p->fade; - glColor4f(pt.r, pt.g, pt.b, 1.0f-sz/pt.sz); glPushMatrix(); glTranslatef(p->o.x, p->o.y, p->o.z); - glRotatef(lastmillis/5.0f, 1, 1, 1); - glScalef(sz, sz, sz); - glCallList(1); - glScalef(0.8f, 0.8f, 0.8f); - glCallList(1); + bool inside = p->o.dist(camera1->o) <= sz*1.25f; //1.25 is max wobble scale + vec oc(p->o); + oc.sub(camera1->o); + glRotatef(inside ? camera1->yaw - 180 : atan2(oc.y, oc.x)/RAD - 90, 0, 0, 1); + glRotatef((inside ? camera1->pitch : asin(oc.z/oc.magnitude())/RAD) - 90, 1, 0, 0); + glColor4f(pt.r, pt.g, pt.b, 1.0f-sz/pt.sz); + + glRotatef(lastmillis/7.0f, 0, 0, 1); + glScalef(-sz, sz, inside ? sz : -sz); + if(inside) glDisable(GL_DEPTH_TEST); + drawexplosion(inside); + if(inside) glEnable(GL_DEPTH_TEST); glPopMatrix(); - xtraverts += 12*6*2; + xtraverts += heminumverts; break; - + } + case PT_SHOTLINE: glVertex3f(p->o.x, p->o.y, p->o.z); glVertex3f(p->d.x, p->d.y, p->d.z); @@ -183,7 +345,7 @@ void render_particles(int time) break; } } - + if(!time) pp = &p->next; else if(lastmillis-p->millis>p->fade) { @@ -198,8 +360,19 @@ void render_particles(int time) pp = &p->next; } } - - if(pt.type==PT_PART || pt.type==PT_SHOTLINE || pt.type==PT_DECAL) glEnd(); + + switch(pt.type) + { + case PT_PART: + case PT_SHOTLINE: + case PT_DECAL: + glEnd(); + break; + + case PT_FIREBALL: + cleanupexplosion(); + break; + } if(pt.tex<0) glEnable(GL_TEXTURE_2D); }