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()&litude);
+
+ 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
typedef enum
{
- pt_static, pt_rain, pt_bubble, pt_blood
+ pt_static, pt_rain, pt_bubble, pt_blood, pt_grow
}
ptype_t;
// these must match r_part.c's textures
static const int tex_smoke[8] = {0, 1, 2, 3, 4, 5, 6, 7};
-static const int tex_rainsplash[16] = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
+//static const int tex_rainsplash[16] = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
static const int tex_particle = 24;
-static const int tex_rain = 25;
+//static const int tex_rain = 25;
static const int tex_bubble = 26;
static int cl_maxparticles;
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);
}
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);
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)
{
{
// 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)
{
#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);
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)
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;
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
}
static void r_part_newmap(void)
{
+ cl_numparticles = 0;
}
void R_Particles_Init (void)
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)
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
}
float minparticledist;
particle_t *p;
+#ifdef WORKINGLQUAKE
+ CL_MoveParticles();
+#endif
+
// LordHavoc: early out conditions
if ((!cl_numparticles) || (!r_drawparticles.integer))
return;
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;