]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_particles.c
minor update to texture flags and logic stuff
[xonotic/darkplaces.git] / cl_particles.c
index 4cc8ec062848cd6e1ab378f766ffbd5cdbb4021d..c858654d178354c38e81e2ecc03624396bb41924 100644 (file)
@@ -71,6 +71,83 @@ void R_CalcBeamVerts (float *vert, vec3_t org1, vec3_t org2, float width)
        vert[13] = org2[1] + width * right2[1];
        vert[14] = org2[2] + width * right2[2];
 }
+void fractalnoise(qbyte *noise, int size, int startgrid)
+{
+       int x, y, g, g2, amplitude, min, max, size1 = size - 1, sizepower, gridpower;
+       int *noisebuf;
+#define n(x,y) noisebuf[((y)&size1)*size+((x)&size1)]
+
+       for (sizepower = 0;(1 << sizepower) < size;sizepower++);
+       if (size != (1 << sizepower))
+               Sys_Error("fractalnoise: size must be power of 2\n");
+
+       for (gridpower = 0;(1 << gridpower) < startgrid;gridpower++);
+       if (startgrid != (1 << gridpower))
+               Sys_Error("fractalnoise: grid must be power of 2\n");
+
+       startgrid = bound(0, startgrid, size);
+
+       amplitude = 0xFFFF; // this gets halved before use
+       noisebuf = malloc(size*size*sizeof(int));
+       memset(noisebuf, 0, size*size*sizeof(int));
+
+       for (g2 = startgrid;g2;g2 >>= 1)
+       {
+               // brownian motion (at every smaller level there is random behavior)
+               amplitude >>= 1;
+               for (y = 0;y < size;y += g2)
+                       for (x = 0;x < size;x += g2)
+                               n(x,y) += (rand()&amplitude);
+
+               g = g2 >> 1;
+               if (g)
+               {
+                       // subdivide, diamond-square algorithm (really this has little to do with squares)
+                       // diamond
+                       for (y = 0;y < size;y += g2)
+                               for (x = 0;x < size;x += g2)
+                                       n(x+g,y+g) = (n(x,y) + n(x+g2,y) + n(x,y+g2) + n(x+g2,y+g2)) >> 2;
+                       // square
+                       for (y = 0;y < size;y += g2)
+                               for (x = 0;x < size;x += g2)
+                               {
+                                       n(x+g,y) = (n(x,y) + n(x+g2,y) + n(x+g,y-g) + n(x+g,y+g)) >> 2;
+                                       n(x,y+g) = (n(x,y) + n(x,y+g2) + n(x-g,y+g) + n(x+g,y+g)) >> 2;
+                               }
+               }
+       }
+       // find range of noise values
+       min = max = 0;
+       for (y = 0;y < size;y++)
+               for (x = 0;x < size;x++)
+               {
+                       if (n(x,y) < min) min = n(x,y);
+                       if (n(x,y) > max) max = n(x,y);
+               }
+       max -= min;
+       max++;
+       // normalize noise and copy to output
+       for (y = 0;y < size;y++)
+               for (x = 0;x < size;x++)
+                       *noise++ = (qbyte) (((n(x,y) - min) * 256) / max);
+       free(noisebuf);
+#undef n
+}
+void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up)
+{
+       float d;
+
+       right[0] = forward[2];
+       right[1] = -forward[0];
+       right[2] = forward[1];
+
+       d = DotProduct(forward, right);
+       right[0] -= d * forward[0];
+       right[1] -= d * forward[1];
+       right[2] -= d * forward[2];
+       VectorNormalizeFast(right);
+       CrossProduct(right, forward, up);
+}
 #else
 #include "cl_collision.h"
 #endif
@@ -80,7 +157,7 @@ void R_CalcBeamVerts (float *vert, vec3_t org1, vec3_t org2, float width)
 
 typedef enum
 {
-       pt_static, pt_rain, pt_bubble, pt_blood
+       pt_static, pt_rain, pt_bubble, pt_blood, pt_grow
 }
 ptype_t;
 
@@ -439,8 +516,8 @@ CL_ParticleExplosion
 void CL_ParticleExplosion (vec3_t org)
 {
        int i, k;
-       vec3_t v;
-       vec3_t v2;
+       //vec3_t v;
+       //vec3_t v2;
        if (cl_stainmaps.integer)
                R_Stain(org, 96, 80, 80, 80, 64, 176, 176, 176, 64);
 
@@ -454,11 +531,18 @@ void CL_ParticleExplosion (vec3_t org)
        }
        else
        {
+               /*
+               // LordHavoc: smoke effect similar to UT2003, chews fillrate too badly up close
                // smoke puff
                if (cl_particles_smoke.integer)
                {
                        for (i = 0;i < 64;i++)
                        {
+#ifdef WORKINGLQUAKE
+                               v2[0] = lhrandom(-64, 64);
+                               v2[1] = lhrandom(-64, 64);
+                               v2[2] = lhrandom(-8, 24);
+#else
                                for (k = 0;k < 16;k++)
                                {
                                        v[0] = org[0] + lhrandom(-64, 64);
@@ -468,10 +552,12 @@ void CL_ParticleExplosion (vec3_t org)
                                                break;
                                }
                                VectorSubtract(v2, org, v2);
+#endif
                                VectorScale(v2, 2.0f, v2);
                                particle(pt_static, PARTICLE_BILLBOARD, 0x101010, 0x202020, tex_smoke[rand()&7], true, true, 12, 12, 255, 512, 9999, 0, 0, org[0], org[1], org[2], v2[0], v2[1], v2[2], 0, 0, 0, 0, 0, 0);
                        }
                }
+               */
 
                if (cl_particles_sparks.integer)
                {
@@ -562,7 +648,13 @@ void CL_SparkShower (vec3_t org, vec3_t dir, int count)
        {
                // smoke puff
                if (cl_particles_smoke.integer)
-                       particle(pt_static, PARTICLE_BILLBOARD, 0x606060, 0xA0A0A0, tex_smoke[rand()&7], true, true, 4, 4, 255, 1024, 9999, -0.2, 0, org[0], org[1], org[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16), 0, 0, 0, 0, 0, 0);
+               {
+                       k = count / 4;
+                       while(k--)
+                       {
+                               particle(pt_grow, PARTICLE_BILLBOARD, 0x101010, 0x202020, tex_smoke[rand()&7], true, true, 3, 3, 255, 1024, 9999, -0.2, 0, org[0] + 0.125f * lhrandom(-count, count), org[1] + 0.125f * lhrandom (-count, count), org[2] + 0.125f * lhrandom(-count, count), lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16), 15, 0, 0, 0, 0, 0);
+                       }
+               }
 
                if (cl_particles_sparks.integer)
                {
@@ -831,7 +923,7 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
 #ifdef WORKINGLQUAKE
        len = VectorNormalize (vec);
        dec = 0;
-       speed = 1.0f / (cl.time - cl.oldtime);
+       speed = 1.0f / cl.frametime;
        VectorSubtract(end, start, vel);
 #else
        len = VectorNormalizeLength (vec);
@@ -868,7 +960,7 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                dec = 3;
                                if (smoke)
                                {
-                                       particle(pt_static, PARTICLE_BILLBOARD, 0x303030, 0x606060, tex_smoke[rand()&7], false, true, dec, dec, 32, 64, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-5, 5), lhrandom(-5, 5), lhrandom(-5, 5), 0, 0, 0, 0, 0, 0);
+                                       particle(pt_grow,   PARTICLE_BILLBOARD, 0x303030, 0x606060, tex_smoke[rand()&7], false, true, dec, dec, 32, 64, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-5, 5), lhrandom(-5, 5), lhrandom(-5, 5), 6, 0, 0, 0, 0, 0);
                                        particle(pt_static, PARTICLE_BILLBOARD, 0x801010, 0xFFA020, tex_smoke[rand()&7], false, true, dec, dec, 128, 768, 9999, 0, 0, pos[0], pos[1], pos[2], lhrandom(-20, 20), lhrandom(-20, 20), lhrandom(-20, 20), 0, 0, 0, 0, 0, 0);
                                }
                                if (bubbles)
@@ -1080,6 +1172,10 @@ void CL_MoveParticles (void)
                                if (a != CONTENTS_EMPTY && a != CONTENTS_SKY)
                                        p->die = -1;
                                break;
+                       case pt_grow:
+                               p->scalex += frametime * p->time2;
+                               p->scaley += frametime * p->time2;
+                               break;
                        default:
                                printf("unknown particle type %i\n", p->type);
                                p->die = -1;
@@ -1310,7 +1406,7 @@ static void R_InitParticleTexture (void)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 #else
-       particlefonttexture = R_LoadTexture (particletexturepool, "particlefont", 256, 256, particletexturedata, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
+       particlefonttexture = R_LoadTexture2D(particletexturepool, "particlefont", 256, 256, particletexturedata, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
 #endif
 }
 
@@ -1327,6 +1423,7 @@ static void r_part_shutdown(void)
 
 static void r_part_newmap(void)
 {
+       cl_numparticles = 0;
 }
 
 void R_Particles_Init (void)
@@ -1407,14 +1504,10 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2)
        cg *= r_colorscale;
        cb *= r_colorscale;
 
-       varray_color[ 0] = varray_color[ 4] = varray_color[ 8] = varray_color[12] = cr;
-       varray_color[ 1] = varray_color[ 5] = varray_color[ 9] = varray_color[13] = cg;
-       varray_color[ 2] = varray_color[ 6] = varray_color[10] = varray_color[14] = cb;
-       varray_color[ 3] = varray_color[ 7] = varray_color[11] = varray_color[15] = ca;
        varray_texcoord[0][0] = tex->s2;varray_texcoord[0][1] = tex->t1;
-       varray_texcoord[0][2] = tex->s1;varray_texcoord[0][3] = tex->t1;
-       varray_texcoord[0][4] = tex->s1;varray_texcoord[0][5] = tex->t2;
-       varray_texcoord[0][6] = tex->s2;varray_texcoord[0][7] = tex->t2;
+       varray_texcoord[0][4] = tex->s1;varray_texcoord[0][5] = tex->t1;
+       varray_texcoord[0][8] = tex->s1;varray_texcoord[0][9] = tex->t2;
+       varray_texcoord[0][12] = tex->s2;varray_texcoord[0][13] = tex->t2;
 #endif
 
        if (orientation == PARTICLE_BEAM)
@@ -1476,6 +1569,7 @@ void R_DrawParticleCallback(const void *calldata1, int calldata2)
        glTexCoord2f(tex->s2, tex->t2);glVertex3f(varray_vertex[12], varray_vertex[13], varray_vertex[14]);
        glEnd();
 #else
+       GL_Color(cr, cg, cb, ca);
        R_Mesh_Draw(4, 2, polygonelements);
 #endif
 }
@@ -1486,6 +1580,10 @@ void R_DrawParticles (void)
        float minparticledist;
        particle_t *p;
 
+#ifdef WORKINGLQUAKE
+       CL_MoveParticles();
+#endif
+
        // LordHavoc: early out conditions
        if ((!cl_numparticles) || (!r_drawparticles.integer))
                return;
@@ -1493,16 +1591,17 @@ void R_DrawParticles (void)
        minparticledist = DotProduct(r_origin, vpn) + 16.0f;
 
 #ifdef WORKINGLQUAKE
-       // helper code if anyone wants to port this to stock glquake engines
        glBindTexture(GL_TEXTURE_2D, particlefonttexture);
        glEnable(GL_BLEND);
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+       glDepthMask(0);
        // LordHavoc: only render if not too close
        for (i = 0, p = particles;i < cl_numparticles;i++, p++)
                if (DotProduct(p->org, vpn) >= minparticledist)
                        R_DrawParticleCallback(p, 0);
-       // helper code if anyone wants to port this to stock glquake engines
+       glDepthMask(1);
        glDisable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 #else
        // LordHavoc: only render if not too close
        c_particles += cl_numparticles;