summaryrefslogtreecommitdiff
path: root/src/engine/renderparticles.cpp
diff options
context:
space:
mode:
authorxolatile2025-08-06 22:54:55 +0200
committerxolatile2025-08-06 22:54:55 +0200
commit0a1172b75f571685c264a8b9d8ee224bbf11381f (patch)
treed041fdc68a60f0ebb48a3852bbcce6d9432f83d5 /src/engine/renderparticles.cpp
parentaffde05dc07a94643f1fd2751b2b441f57f73d7d (diff)
downloadxolatile-badassbug-0a1172b75f571685c264a8b9d8ee224bbf11381f.tar.xz
xolatile-badassbug-0a1172b75f571685c264a8b9d8ee224bbf11381f.tar.zst
Please do not hate me, it makes sense...
Diffstat (limited to 'src/engine/renderparticles.cpp')
-rw-r--r--src/engine/renderparticles.cpp675
1 files changed, 196 insertions, 479 deletions
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);