diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 04ee6e33b..1c20ea8f0 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -36,6 +36,7 @@ struct plitem_s; struct cvar_s; struct skin_s; +struct particle_s; /* All video plugins must export these functions @@ -70,13 +71,13 @@ typedef struct vid_particle_funcs_s { void (*R_DarkFieldParticles) (struct entity_s *ent); void (*R_EntityParticles) (struct entity_s *ent); - void (*R_Particle_New) (ptype_t type, int texnum, const vec3_t org, + void (*R_Particle_New) (const char *type, int texnum, const vec3_t org, float scale, const vec3_t vel, float die, int color, float alpha, float ramp); - void (*R_Particle_NewRandom) (ptype_t type, int texnum, const vec3_t org, - int org_fuzz, float scale, int vel_fuzz, - float die, int color, float alpha, - float ramp); + void (*R_Particle_NewRandom) (const char *type, int texnum, + const vec3_t org, int org_fuzz, float scale, + int vel_fuzz, float die, int color, + float alpha, float ramp); } vid_particle_funcs_t; typedef struct vid_model_funcs_s { @@ -160,6 +161,10 @@ typedef struct vid_render_funcs_s { void (*R_DecayLights) (double frametime); void (*R_ViewChanged) (float aspect); + qboolean (*R_CompileParticlePhysics) (const char *name, const char *code); + qboolean (*R_AddParticlePhysicsFunction) + (const char *name, qboolean (*func) (struct particle_s *, void *), + void *data); void (*R_ClearParticles) (void); void (*R_InitParticles) (void); void (*SCR_ScreenShot_f) (void); diff --git a/include/QF/render.h b/include/QF/render.h index 55514632b..3ff4af2ac 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -33,25 +33,6 @@ #include "QF/qdefs.h" // FIXME #include "QF/vid.h" -typedef enum { - pt_static, - pt_grav, - pt_slowgrav, - pt_fire, - pt_explode, - pt_explode2, - pt_blob, - pt_blob2, - pt_smoke, - pt_smokecloud, - pt_bloodcloud, - pt_fadespark, - pt_fadespark2, - pt_fallfade, - pt_fallfadespark, - pt_flame -} ptype_t; - extern struct vid_render_funcs_s *r_funcs; extern struct vid_render_data_s *r_data; diff --git a/include/d_iface.h b/include/d_iface.h index f7d6a72a2..df6336a40 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -63,9 +63,16 @@ typedef enum { } ptextype_t; typedef struct particle_s particle_t; -typedef void (*pt_phys_func)(particle_t *); -pt_phys_func R_ParticlePhysics (ptype_t type); +void R_LoadParticles (void); +qboolean R_CompileParticlePhysics (const char *name, const char *code); +void R_RunParticlePhysics (particle_t *part); +const union pt_phys_op_s *R_ParticlePhysics (const char *type); +qboolean R_AddParticlePhysicsFunction (const char *name, + qboolean (*func) (struct particle_s *, + void *), + void *data); +extern const char particle_types[]; // !!! if this is changed, it must be changed in d_ifacea.h too !!! struct particle_s @@ -78,10 +85,9 @@ struct particle_s float scale; // drivers never touch the following fields vec3_t vel; - ptype_t type; float die; float ramp; - pt_phys_func phys; + const union pt_phys_op_s *physics; particle_t *next; }; diff --git a/include/r_dynamic.h b/include/r_dynamic.h index 1dd54fc11..0adeb4839 100644 --- a/include/r_dynamic.h +++ b/include/r_dynamic.h @@ -49,10 +49,10 @@ void R_PushDlights (const vec3_t entorigin); struct cvar_s; void R_MaxDlightsCheck (struct cvar_s *var); void R_Particles_Init_Cvars (void); -void R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, - float ramp); -void R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, +void R_Particle_New (const char *type, int texnum, const vec3_t org, + float scale, const vec3_t vel, float die, int color, + float alpha, float ramp); +void R_Particle_NewRandom (const char *type, int texnum, const vec3_t org, int org_fuzz, float scale, int vel_fuzz, float die, int color, float alpha, float ramp); void R_InitBubble (void); diff --git a/libs/video/renderer/Makefile.am b/libs/video/renderer/Makefile.am index 2c234fe33..7f7119c14 100644 --- a/libs/video/renderer/Makefile.am +++ b/libs/video/renderer/Makefile.am @@ -10,9 +10,17 @@ plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir) plugin_libadd= @plugin_libadd@ EXEEXT= +particles_src= particles.part +particles_gen= particles.pc + +SUFFICES=.part .pc +.part.pc: + sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ + #lib_LTLIBRARIES= @VID_REND_TARGETS@ plugin_LTLIBRARIES= @vid_render_plugins@ noinst_LTLIBRARIES= libQFrenderer.la @vid_render_static_plugins@ +BUILT_SOURCES= $(particles_gen) EXTRA_LTLIBRARIES= \ vid_render_sw.la vid_render_sw32.la \ @@ -63,3 +71,6 @@ vid_render_sw32_la_LDFLAGS= $(plugin_ldflags) vid_render_sw32_la_LIBADD= $(sw32_libs) vid_render_sw32_la_DEPENDENCIES=$(sw32_libs) vid_render_sw32_la_SOURCES= $(common_sources) vid_render_sw32.c + +EXTRA_DIST = $(particles_src) +CLEANFILES= *.pc diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index 77428573b..f249624b6 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -70,7 +70,7 @@ static varray_t2f_c4ub_v3f_t *particleVertexArray; static mtstate_t mt; // private PRNG state inline static void -particle_new (ptype_t type, int texnum, const vec3_t org, float scale, +particle_new (const char *type, int texnum, const vec3_t org, float scale, const vec3_t vel, float die, int color, float alpha, float ramp) { particle_t *part; @@ -91,10 +91,9 @@ particle_new (ptype_t type, int texnum, const vec3_t org, float scale, part->scale = scale; part->alpha = alpha; VectorCopy (vel, part->vel); - part->type = type; part->die = die; part->ramp = ramp; - part->phys = R_ParticlePhysics (type); + part->physics = R_ParticlePhysics (type); } /* @@ -104,7 +103,8 @@ particle_new (ptype_t type, int texnum, const vec3_t org, float scale, going to bother using this function. */ inline static void -particle_new_random (ptype_t type, int texnum, const vec3_t org, int org_fuzz, +particle_new_random (const char *type, int texnum, + const vec3_t org, int org_fuzz, float scale, int vel_fuzz, float die, int color, float alpha, float ramp) { @@ -153,6 +153,8 @@ gl_R_InitParticles (void) { int i; + R_LoadParticles (); + mtwist_seed (&mt, 0xdeadbeef); if (r_maxparticles && r_init) { @@ -234,7 +236,7 @@ gl_R_ReadPointFile_f (void) Sys_MaskPrintf (SYS_DEV, "Not enough free particles\n"); break; } else { - particle_new (pt_static, part_tex_dot, org, 1.5, vec3_origin, + particle_new ("pt_static", part_tex_dot, org, 1.5, vec3_origin, 99999, (-c) & 15, 1.0, 0.0); } } @@ -248,7 +250,7 @@ R_ParticleExplosion_QF (const vec3_t org) // R_NewExplosion (org); if (numparticles >= r_maxparticles) return; - particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, + particle_new_random ("pt_smokecloud", part_tex_smoke, org, 4, 30, 8, vr_data.realtime + 5.0, (mtwist_rand (&mt) & 7) + 8, 0.5 + qfrandom (0.25), 0.0); } @@ -264,7 +266,7 @@ R_ParticleExplosion2_QF (const vec3_t org, int colorStart, int colorLength) j = r_maxparticles - numparticles; for (i = 0; i < j; i++) { - particle_new_random (pt_blob, part_tex_dot, org, 16, 2, 256, + particle_new_random ("pt_blob", part_tex_dot, org, 16, 2, 256, vr_data.realtime + 0.3, colorStart + (i % colorLength), 1.0, 0.0); } @@ -282,12 +284,12 @@ R_BlobExplosion_QF (const vec3_t org) j = r_maxparticles - numparticles; for (i = 0; i < j >> 1; i++) { - particle_new_random (pt_blob, part_tex_dot, org, 12, 2, 256, + particle_new_random ("pt_blob", part_tex_dot, org, 12, 2, 256, vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, 66 + i % 6, 1.0, 0.0); } for (i = 0; i < j / 2; i++) { - particle_new_random (pt_blob2, part_tex_dot, org, 12, 2, 256, + particle_new_random ("pt_blob2", part_tex_dot, org, 12, 2, 256, vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, 150 + i % 6, 1.0, 0.0); } @@ -298,7 +300,7 @@ R_RunSparkEffect_QF (const vec3_t org, int count, int ofuzz) { if (numparticles >= r_maxparticles) return; - particle_new (pt_smokecloud, part_tex_smoke, org, ofuzz * 0.08, + particle_new ("pt_smokecloud", part_tex_smoke, org, ofuzz * 0.08, vec3_origin, vr_data.realtime + 9, 12 + (mtwist_rand (&mt) & 3), 0.25 + qfrandom (0.125), 0.0); @@ -312,7 +314,7 @@ R_RunSparkEffect_QF (const vec3_t org, int count, int ofuzz) while (count--) { int color = mtwist_rand (&mt) & 7; - particle_new_random (pt_fallfadespark, part_tex_dot, org, orgfuzz, + particle_new_random ("pt_fallfadespark", part_tex_dot, org, orgfuzz, 0.7, 96, vr_data.realtime + 5.0, ramp1[color], 1.0, color); } @@ -325,7 +327,7 @@ R_BloodPuff_QF (const vec3_t org, int count) if (numparticles >= r_maxparticles) return; - particle_new (pt_bloodcloud, part_tex_smoke, org, count / 5, vec3_origin, + particle_new ("pt_bloodcloud", part_tex_smoke, org, count / 5, vec3_origin, vr_data.realtime + 99.0, 70 + (mtwist_rand (&mt) & 3), 0.5, 0.0); } @@ -353,14 +355,14 @@ R_LightningBloodEffect_QF (const vec3_t org) if (numparticles >= r_maxparticles) return; - particle_new (pt_smokecloud, part_tex_smoke, org, 3.0, vec3_origin, + particle_new ("pt_smokecloud", part_tex_smoke, org, 3.0, vec3_origin, vr_data.realtime + 9.0, 12 + (mtwist_rand (&mt) & 3), 0.25 + qfrandom (0.125), 0.0); if (numparticles + count >= r_maxparticles) count = r_maxparticles - numparticles; while (count--) - particle_new_random (pt_fallfade, part_tex_spark, org, 12, 2.0, 128, + particle_new_random ("pt_fallfade", part_tex_spark, org, 12, 2.0, 128, vr_data.realtime + 5.0, 244 + (count % 3), 1.0, 0.0); } @@ -388,7 +390,7 @@ R_RunParticleEffect_QF (const vec3_t org, const vec3_t dir, int color, porg[1] = org[1] + scale * (((rnd >> 7) & 15) - 7.5); porg[2] = org[2] + scale * (((rnd >> 11) & 15) - 7.5); // Note that ParseParticleEffect handles (dir * 15) - particle_new (pt_grav, part_tex_dot, porg, 1.5, dir, + particle_new ("pt_grav", part_tex_dot, porg, 1.5, dir, vr_data.realtime + 0.1 * (i % 5), (color & ~7) + (rnd & 7), 1.0, 0.0); } @@ -413,13 +415,13 @@ R_KnightSpikeEffect_QF (const vec3_t org) if (numparticles >= r_maxparticles) return; - particle_new (pt_smokecloud, part_tex_smoke, org, 1.0, vec3_origin, + particle_new ("pt_smokecloud", part_tex_smoke, org, 1.0, vec3_origin, vr_data.realtime + 9.0, 234, 0.25 + qfrandom (0.125), 0.0); if (numparticles + count >= r_maxparticles) count = r_maxparticles - numparticles; while (count--) - particle_new_random (pt_fallfade, part_tex_dot, org, 6, 0.7, 96, + particle_new_random ("pt_fallfade", part_tex_dot, org, 6, 0.7, 96, vr_data.realtime + 5.0, 234, 1.0, 0.0); } @@ -430,13 +432,13 @@ R_WizSpikeEffect_QF (const vec3_t org) if (numparticles >= r_maxparticles) return; - particle_new (pt_smokecloud, part_tex_smoke, org, 2.0, vec3_origin, + particle_new ("pt_smokecloud", part_tex_smoke, org, 2.0, vec3_origin, vr_data.realtime + 9.0, 63, 0.25 + qfrandom (0.125), 0.0); if (numparticles + count >= r_maxparticles) count = r_maxparticles - numparticles; while (count--) - particle_new_random (pt_fallfade, part_tex_dot, org, 12, 0.7, 96, + particle_new_random ("pt_fallfade", part_tex_dot, org, 12, 0.7, 96, vr_data.realtime + 5.0, 63, 1.0, 0.0); } @@ -469,7 +471,7 @@ R_LavaSplash_QF (const vec3_t org) rnd = mtwist_rand (&mt); vel = 50.0 + 0.5 * (float) (rnd & 127); VectorScale (dir, vel, pvel); - particle_new (pt_grav, part_tex_dot, porg, 3, pvel, + particle_new ("pt_grav", part_tex_dot, porg, 3, pvel, vr_data.realtime + 2.0 + ((rnd >> 7) & 31) * 0.02, 224 + ((rnd >> 12) & 7), 0.75, 0.0); } @@ -507,7 +509,7 @@ R_TeleportSplash_QF (const vec3_t org) vel = 50 + ((rnd >> 6) & 63); VectorScale (pdir, vel, pvel); - particle_new (pt_grav, part_tex_spark, porg, 0.6, pvel, + particle_new ("pt_grav", part_tex_spark, porg, 0.6, pvel, (vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 15) * 0.01), (7 + ((rnd >> 12) & 7)), 1.0, 0.0); } @@ -536,7 +538,7 @@ R_RocketTrail_QF (entity_t *ent) dist = (pscale + pscalenext) * 3.0; percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, + particle_new ("pt_smoke", part_tex_smoke, old_origin, pscale + percent * 4.0, vec3_origin, vr_data.realtime + 2.0 - percent * 2.0, 12 + (mtwist_rand (&mt) & 3), @@ -570,7 +572,7 @@ R_GrenadeTrail_QF (entity_t *ent) dist = (pscale + pscalenext) * 2.0; percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, + particle_new ("pt_smoke", part_tex_smoke, old_origin, pscale + percent * 4.0, vec3_origin, vr_data.realtime + 2.0 - percent * 2.0, 1 + (mtwist_rand (&mt) & 3), @@ -612,7 +614,7 @@ R_BloodTrail_QF (entity_t *ent) percent = len * origlen; pvel[2] -= percent * 40.0; - particle_new (pt_grav, part_tex_smoke, porg, pscale, pvel, + particle_new ("pt_grav", part_tex_smoke, porg, pscale, pvel, vr_data.realtime + 2.0 - percent * 2.0, 68 + (mtwist_rand (&mt) & 3), 1.0, 0.0); if (numparticles >= r_maxparticles) @@ -652,7 +654,7 @@ R_SlightBloodTrail_QF (entity_t *ent) percent = len * origlen; pvel[2] -= percent * 40; - particle_new (pt_grav, part_tex_smoke, porg, pscale, pvel, + particle_new ("pt_grav", part_tex_smoke, porg, pscale, pvel, vr_data.realtime + 1.5 - percent * 1.5, 68 + (mtwist_rand (&mt) & 3), 0.75, 0.0); if (numparticles >= r_maxparticles) @@ -693,7 +695,7 @@ R_WizTrail_QF (entity_t *ent) } pvel[2] = 0.0; - particle_new (pt_flame, part_tex_smoke, old_origin, + particle_new ("pt_flame", part_tex_smoke, old_origin, 2.0 + qfrandom (1.0) - percent * 2.0, pvel, vr_data.realtime + 0.5 - percent * 0.5, 52 + (mtwist_rand (&mt) & 4), 1.0 - percent * 0.125, 0.0); @@ -734,7 +736,7 @@ R_FlameTrail_QF (entity_t *ent) } pvel[2] = 0.0; - particle_new (pt_flame, part_tex_smoke, old_origin, + particle_new ("pt_flame", part_tex_smoke, old_origin, 2.0 + qfrandom (1.0) - percent * 2.0, pvel, vr_data.realtime + 0.5 - percent * 0.5, 234, 1.0 - percent * 0.125, 0.0); @@ -768,7 +770,7 @@ R_VoorTrail_QF (entity_t *ent) for (j = 0; j < 3; j++) porg[j] = old_origin[j] + qfrandom (16.0) - 8.0; - particle_new (pt_static, part_tex_dot, porg, 1.0 + qfrandom (1.0), + particle_new ("pt_static", part_tex_dot, porg, 1.0 + qfrandom (1.0), vec3_origin, vr_data.realtime + 0.3 - percent * 0.3, 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 1.0, 0.0); if (numparticles >= r_maxparticles) @@ -803,7 +805,7 @@ R_GlowTrail_QF (entity_t *ent, int glow_color) org[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; org[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - particle_new (pt_smoke, part_tex_dot, org, 1.0, vec3_origin, + particle_new ("pt_smoke", part_tex_dot, org, 1.0, vec3_origin, vr_data.realtime + 2.0 - percent * 0.2, glow_color, 1.0, 0.0); if (numparticles >= r_maxparticles) @@ -821,7 +823,7 @@ R_ParticleExplosion_EE (const vec3_t org) */ if (numparticles >= r_maxparticles) return; - particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, + particle_new_random ("pt_smokecloud", part_tex_smoke, org, 4, 30, 8, vr_data.realtime + 5.0, mtwist_rand (&mt) & 255, 0.5 + qfrandom (0.25), 0.0); } @@ -855,7 +857,7 @@ R_TeleportSplash_EE (const vec3_t org) VectorNormalize (dir); vel = 50 + ((rnd >> 6) & 63); VectorScale (dir, vel, pvel); - particle_new (pt_grav, part_tex_spark, porg, 0.6, pvel, + particle_new ("pt_grav", part_tex_spark, porg, 0.6, pvel, (vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 15) * 0.01), qfrandom (1.0), 1.0, 0.0); } @@ -884,7 +886,7 @@ R_RocketTrail_EE (entity_t *ent) dist = (pscale + pscalenext) * 3.0; percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, + particle_new ("pt_smoke", part_tex_smoke, old_origin, pscale + percent * 4.0, vec3_origin, vr_data.realtime + 2.0 - percent * 2.0, mtwist_rand (&mt) & 255, @@ -919,7 +921,7 @@ R_GrenadeTrail_EE (entity_t *ent) dist = (pscale + pscalenext) * 2.0; percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, + particle_new ("pt_smoke", part_tex_smoke, old_origin, pscale + percent * 4.0, vec3_origin, vr_data.realtime + 2.0 - percent * 2.0, mtwist_rand (&mt) & 255, @@ -945,11 +947,11 @@ R_ParticleExplosion_ID (const vec3_t org) j = r_maxparticles - numparticles; for (i = 0; i < j >> 1; i++) { - particle_new_random (pt_explode, part_tex_dot, org, 16, 1.0, 256, + particle_new_random ("pt_explode", part_tex_dot, org, 16, 1.0, 256, vr_data.realtime + 5.0, ramp1[0], 1.0, i & 3); } for (i = 0; i < j / 2; i++) { - particle_new_random (pt_explode2, part_tex_dot, org, 16, 1.0, 256, + particle_new_random ("pt_explode2", part_tex_dot, org, 16, 1.0, 256, vr_data.realtime + 5.0, ramp1[0], 1.0, i & 3); } } @@ -966,12 +968,12 @@ R_BlobExplosion_ID (const vec3_t org) j = r_maxparticles - numparticles; for (i = 0; i < j >> 1; i++) { - particle_new_random (pt_blob, part_tex_dot, org, 12, 1.0, 256, + particle_new_random ("pt_blob", part_tex_dot, org, 12, 1.0, 256, vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 8) * 0.05, 66 + i % 6, 1.0, 0.0); } for (i = 0; i < j / 2; i++) { - particle_new_random (pt_blob2, part_tex_dot, org, 12, 1.0, 256, + particle_new_random ("pt_blob2", part_tex_dot, org, 12, 1.0, 256, vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 8) * 0.05, 150 + i % 6, 1.0, 0.0); } @@ -1006,7 +1008,7 @@ R_RunParticleEffect_ID (const vec3_t org, const vec3_t dir, int color, porg[2] = org[2] + scale * (((rnd >> 11) & 15) - 8); // Note that ParseParticleEffect handles (dir * 15) - particle_new (pt_grav, part_tex_dot, porg, 1.0, dir, + particle_new ("pt_grav", part_tex_dot, porg, 1.0, dir, vr_data.realtime + 0.1 * (i % 5), (color & ~7) + (rnd & 7), 1.0, 0.0); } @@ -1083,7 +1085,7 @@ R_LavaSplash_ID (const vec3_t org) rnd = mtwist_rand (&mt); vel = 50 + (rnd & 63); VectorScale (dir, vel, pvel); - particle_new (pt_grav, part_tex_dot, porg, 1.0, pvel, + particle_new ("pt_grav", part_tex_dot, porg, 1.0, pvel, vr_data.realtime + 2 + ((rnd >> 7) & 31) * 0.02, 224 + ((rnd >> 12) & 7), 1.0, 0.0); } @@ -1121,7 +1123,7 @@ R_TeleportSplash_ID (const vec3_t org) vel = 50 + ((rnd >> 6) & 63); VectorScale (pdir, vel, pvel); - particle_new (pt_grav, part_tex_dot, porg, 1.0, pvel, + particle_new ("pt_grav", part_tex_dot, porg, 1.0, pvel, (vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 7) * 0.02), (7 + ((rnd >> 12) & 7)), 1.0, 0.0); } @@ -1160,7 +1162,7 @@ R_DarkFieldParticles_ID (entity_t *ent) VectorNormalize (dir); vel = 50 + ((rnd >> 9) & 63); VectorScale (dir, vel, pvel); - particle_new (pt_slowgrav, part_tex_dot, porg, 1.5, pvel, + particle_new ("pt_slowgrav", part_tex_dot, porg, 1.5, pvel, (vr_data.realtime + 0.2 + (rnd & 7) * 0.02), (150 + mtwist_rand (&mt) % 6), 1.0, 0.0); } @@ -1215,7 +1217,7 @@ R_EntityParticles_ID (entity_t *ent) forward[1] * beamlength; porg[2] = ent->origin[2] + r_avertexnormals[i][2] * dist + forward[2] * beamlength; - particle_new (pt_explode, part_tex_dot, porg, 1.0, vec3_origin, + particle_new ("pt_explode", part_tex_dot, porg, 1.0, vec3_origin, vr_data.realtime + 0.01, 0x6f, 1.0, 0); } } @@ -1243,7 +1245,7 @@ R_RocketTrail_ID (entity_t *ent) org[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; ramp = rnd & 3; - particle_new (pt_fire, part_tex_dot, org, 1.0, vec3_origin, + particle_new ("pt_fire", part_tex_dot, org, 1.0, vec3_origin, vr_data.realtime + 2.0, ramp3[ramp], 1.0, ramp); if (numparticles >= r_maxparticles) break; @@ -1275,7 +1277,7 @@ R_GrenadeTrail_ID (entity_t *ent) org[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; ramp = (rnd & 3) + 2; - particle_new (pt_fire, part_tex_dot, org, 1.0, vec3_origin, + particle_new ("pt_fire", part_tex_dot, org, 1.0, vec3_origin, vr_data.realtime + 2.0, ramp3[ramp], 1.0, ramp); if (numparticles >= r_maxparticles) break; @@ -1306,7 +1308,7 @@ R_BloodTrail_ID (entity_t *ent) porg[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; porg[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - particle_new (pt_grav, part_tex_dot, porg, 1.0, vec3_origin, + particle_new ("pt_grav", part_tex_dot, porg, 1.0, vec3_origin, vr_data.realtime + 2.0, 67 + (rnd & 3), 1.0, 0.0); if (numparticles >= r_maxparticles) break; @@ -1337,7 +1339,7 @@ R_SlightBloodTrail_ID (entity_t *ent) porg[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; porg[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - particle_new (pt_grav, part_tex_dot, porg, 1.0, vec3_origin, + particle_new ("pt_grav", part_tex_dot, porg, 1.0, vec3_origin, vr_data.realtime + 1.5, 67 + (rnd & 3), 1.0, 0.0); if (numparticles >= r_maxparticles) break; @@ -1373,7 +1375,7 @@ R_WizTrail_ID (entity_t *ent) } pvel[2] = 0.0; - particle_new (pt_static, part_tex_dot, old_origin, 1.0, pvel, + particle_new ("pt_static", part_tex_dot, old_origin, 1.0, pvel, vr_data.realtime + 0.5, 52 + ((tracercount & 4) << 1), 1.0, 0.0); if (numparticles >= r_maxparticles) @@ -1410,7 +1412,7 @@ R_FlameTrail_ID (entity_t *ent) } pvel[2] = 0.0; - particle_new (pt_static, part_tex_dot, old_origin, 1.0, pvel, + particle_new ("pt_static", part_tex_dot, old_origin, 1.0, pvel, vr_data.realtime + 0.5, 230 + ((tracercount & 4) << 1), 1.0, 0.0); if (numparticles >= r_maxparticles) @@ -1442,7 +1444,7 @@ R_VoorTrail_ID (entity_t *ent) porg[1] = old_origin[1] + ((rnd >> 7) & 15) - 7.5; porg[2] = old_origin[2] + ((rnd >> 11) & 15) - 7.5; - particle_new (pt_static, part_tex_dot, porg, 1.0, vec3_origin, + particle_new ("pt_static", part_tex_dot, porg, 1.0, vec3_origin, vr_data.realtime + 0.3, 9 * 16 + 8 + (rnd & 3), 1.0, 0.0); if (numparticles >= r_maxparticles) @@ -1550,7 +1552,7 @@ gl_R_DrawParticles (void) } } - part->phys (part); + R_RunParticlePhysics (part); // LordHavoc: immediate removal of unnecessary particles (must be done // to ensure compactor below operates properly in all cases) @@ -1777,7 +1779,7 @@ gl_R_Particles_Init_Cvars (void) } void -gl_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, +gl_R_Particle_New (const char *type, int texnum, const vec3_t org, float scale, const vec3_t vel, float die, int color, float alpha, float ramp) { @@ -1787,7 +1789,7 @@ gl_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, } void -gl_R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, +gl_R_Particle_NewRandom (const char *type, int texnum, const vec3_t org, int org_fuzz, float scale, int vel_fuzz, float die, int color, float alpha, float ramp) { diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index b9fab5a60..e681aa01f 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -228,7 +228,7 @@ free_point (particle_t *point) } inline static void -particle_new (ptype_t type, int texnum, const vec3_t org, float scale, +particle_new (const char *type, int texnum, const vec3_t org, float scale, const vec3_t vel, float die, int color, float alpha, float ramp) { particle_t *part; @@ -249,10 +249,9 @@ particle_new (ptype_t type, int texnum, const vec3_t org, float scale, part->scale = scale; part->alpha = alpha; VectorCopy (vel, part->vel); - part->type = type; part->die = die; part->ramp = ramp; - part->phys = R_ParticlePhysics (type); + part->physics = R_ParticlePhysics (type); } /* @@ -262,9 +261,9 @@ particle_new (ptype_t type, int texnum, const vec3_t org, float scale, going to bother using this function. */ inline static void -particle_new_random (ptype_t type, int texnum, const vec3_t org, int org_fuzz, - float scale, int vel_fuzz, float die, int color, - float alpha, float ramp) +particle_new_random (const char *type, int texnum, const vec3_t org, + int org_fuzz, float scale, int vel_fuzz, float die, + int color, float alpha, float ramp) { float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; int rnd; @@ -317,6 +316,8 @@ glsl_R_InitParticles (void) byte data[64][64][2]; tex_t *tex; + R_LoadParticles (); + mtwist_seed (&mt, 0xdeadbeef); qfeglEnable (GL_VERTEX_PROGRAM_POINT_SIZE); @@ -447,7 +448,7 @@ glsl_R_ReadPointFile_f (void) Sys_MaskPrintf (SYS_DEV, "Not enough free particles\n"); break; } else { - particle_new (pt_static, part_tex_dot, org, 1.5, vec3_origin, + particle_new ("pt_static", part_tex_dot, org, 1.5, vec3_origin, 99999, (-c) & 15, 1.0, 0.0); } } @@ -461,7 +462,7 @@ R_ParticleExplosion_QF (const vec3_t org) // R_NewExplosion (org); if (numparticles >= r_maxparticles) return; - particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, + particle_new_random ("pt_smokecloud", part_tex_smoke, org, 4, 30, 8, vr_data.realtime + 5.0, (mtwist_rand (&mt) & 7) + 8, 0.5 + qfrandom (0.25), 0.0); } @@ -477,7 +478,7 @@ R_ParticleExplosion2_QF (const vec3_t org, int colorStart, int colorLength) j = r_maxparticles - numparticles; for (i = 0; i < j; i++) { - particle_new_random (pt_blob, part_tex_dot, org, 16, 2, 256, + particle_new_random ("pt_blob", part_tex_dot, org, 16, 2, 256, vr_data.realtime + 0.3, colorStart + (i % colorLength), 1.0, 0.0); } @@ -495,12 +496,12 @@ R_BlobExplosion_QF (const vec3_t org) j = r_maxparticles - numparticles; for (i = 0; i < j >> 1; i++) { - particle_new_random (pt_blob, part_tex_dot, org, 12, 2, 256, + particle_new_random ("pt_blob", part_tex_dot, org, 12, 2, 256, vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, 66 + i % 6, 1.0, 0.0); } for (i = 0; i < j / 2; i++) { - particle_new_random (pt_blob2, part_tex_dot, org, 12, 2, 256, + particle_new_random ("pt_blob2", part_tex_dot, org, 12, 2, 256, vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, 150 + i % 6, 1.0, 0.0); } @@ -511,7 +512,7 @@ R_RunSparkEffect_QF (const vec3_t org, int count, int ofuzz) { if (numparticles >= r_maxparticles) return; - particle_new (pt_smokecloud, part_tex_smoke, org, ofuzz * 0.08, + particle_new ("pt_smokecloud", part_tex_smoke, org, ofuzz * 0.08, vec3_origin, vr_data.realtime + 9, 12 + (mtwist_rand (&mt) & 3), 0.25 + qfrandom (0.125), 0.0); @@ -525,7 +526,7 @@ R_RunSparkEffect_QF (const vec3_t org, int count, int ofuzz) while (count--) { int color = mtwist_rand (&mt) & 7; - particle_new_random (pt_fallfadespark, part_tex_dot, org, orgfuzz, + particle_new_random ("pt_fallfadespark", part_tex_dot, org, orgfuzz, 0.7, 96, vr_data.realtime + 5.0, ramp1[color], 1.0, color); } @@ -538,7 +539,7 @@ R_BloodPuff_QF (const vec3_t org, int count) if (numparticles >= r_maxparticles) return; - particle_new (pt_bloodcloud, part_tex_smoke, org, count / 5, vec3_origin, + particle_new ("pt_bloodcloud", part_tex_smoke, org, count / 5, vec3_origin, vr_data.realtime + 99.0, 70 + (mtwist_rand (&mt) & 3), 0.5, 0.0); } @@ -566,14 +567,14 @@ R_LightningBloodEffect_QF (const vec3_t org) if (numparticles >= r_maxparticles) return; - particle_new (pt_smokecloud, part_tex_smoke, org, 3.0, vec3_origin, + particle_new ("pt_smokecloud", part_tex_smoke, org, 3.0, vec3_origin, vr_data.realtime + 9.0, 12 + (mtwist_rand (&mt) & 3), 0.25 + qfrandom (0.125), 0.0); if (numparticles + count >= r_maxparticles) count = r_maxparticles - numparticles; while (count--) - particle_new_random (pt_fallfade, part_tex_spark, org, 12, 2.0, 128, + particle_new_random ("pt_fallfade", part_tex_spark, org, 12, 2.0, 128, vr_data.realtime + 5.0, 244 + (count % 3), 1.0, 0.0); } @@ -601,7 +602,7 @@ R_RunParticleEffect_QF (const vec3_t org, const vec3_t dir, int color, porg[1] = org[1] + scale * (((rnd >> 7) & 15) - 7.5); porg[2] = org[2] + scale * (((rnd >> 11) & 15) - 7.5); // Note that ParseParticleEffect handles (dir * 15) - particle_new (pt_grav, part_tex_dot, porg, 1.5, dir, + particle_new ("pt_grav", part_tex_dot, porg, 1.5, dir, vr_data.realtime + 0.1 * (i % 5), (color & ~7) + (rnd & 7), 1.0, 0.0); } @@ -626,13 +627,13 @@ R_KnightSpikeEffect_QF (const vec3_t org) if (numparticles >= r_maxparticles) return; - particle_new (pt_smokecloud, part_tex_smoke, org, 1.0, vec3_origin, + particle_new ("pt_smokecloud", part_tex_smoke, org, 1.0, vec3_origin, vr_data.realtime + 9.0, 234, 0.25 + qfrandom (0.125), 0.0); if (numparticles + count >= r_maxparticles) count = r_maxparticles - numparticles; while (count--) - particle_new_random (pt_fallfade, part_tex_dot, org, 6, 0.7, 96, + particle_new_random ("pt_fallfade", part_tex_dot, org, 6, 0.7, 96, vr_data.realtime + 5.0, 234, 1.0, 0.0); } @@ -643,13 +644,13 @@ R_WizSpikeEffect_QF (const vec3_t org) if (numparticles >= r_maxparticles) return; - particle_new (pt_smokecloud, part_tex_smoke, org, 2.0, vec3_origin, + particle_new ("pt_smokecloud", part_tex_smoke, org, 2.0, vec3_origin, vr_data.realtime + 9.0, 63, 0.25 + qfrandom (0.125), 0.0); if (numparticles + count >= r_maxparticles) count = r_maxparticles - numparticles; while (count--) - particle_new_random (pt_fallfade, part_tex_dot, org, 12, 0.7, 96, + particle_new_random ("pt_fallfade", part_tex_dot, org, 12, 0.7, 96, vr_data.realtime + 5.0, 63, 1.0, 0.0); } @@ -682,7 +683,7 @@ R_LavaSplash_QF (const vec3_t org) rnd = mtwist_rand (&mt); vel = 50.0 + 0.5 * (float) (rnd & 127); VectorScale (dir, vel, pvel); - particle_new (pt_grav, part_tex_dot, porg, 3, pvel, + particle_new ("pt_grav", part_tex_dot, porg, 3, pvel, vr_data.realtime + 2.0 + ((rnd >> 7) & 31) * 0.02, 224 + ((rnd >> 12) & 7), 0.75, 0.0); } @@ -720,7 +721,7 @@ R_TeleportSplash_QF (const vec3_t org) vel = 50 + ((rnd >> 6) & 63); VectorScale (pdir, vel, pvel); - particle_new (pt_grav, part_tex_spark, porg, 0.6, pvel, + particle_new ("pt_grav", part_tex_spark, porg, 0.6, pvel, (vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 15) * 0.01), (7 + ((rnd >> 12) & 7)), 1.0, 0.0); } @@ -764,10 +765,9 @@ R_RocketTrail_trail (entity_t *ent) point->scale = pscale + percent * 4.0; point->alpha = 0.5 + qfrandom (0.125) - percent * 0.40; VectorCopy (vec3_origin, point->vel); - point->type = pt_smoke; point->die = vr_data.realtime + 2.0 - percent * 2.0; point->ramp = 0.0; - point->phys = R_ParticlePhysics (point->type); + point->physics = R_ParticlePhysics ("pt_fire"); *ent->trail->head = point; ent->trail->head = &point->next; @@ -800,7 +800,7 @@ R_RocketTrail_QF (entity_t *ent) dist = (pscale + pscalenext) * 3.0; percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, + particle_new ("pt_smoke", part_tex_smoke, old_origin, pscale + percent * 4.0, vec3_origin, vr_data.realtime + 2.0 - percent * 2.0, 12 + (mtwist_rand (&mt) & 3), @@ -834,7 +834,7 @@ R_GrenadeTrail_QF (entity_t *ent) dist = (pscale + pscalenext) * 2.0; percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, + particle_new ("pt_smoke", part_tex_smoke, old_origin, pscale + percent * 4.0, vec3_origin, vr_data.realtime + 2.0 - percent * 2.0, 1 + (mtwist_rand (&mt) & 3), @@ -876,7 +876,7 @@ R_BloodTrail_QF (entity_t *ent) percent = len * origlen; pvel[2] -= percent * 40.0; - particle_new (pt_grav, part_tex_smoke, porg, pscale, pvel, + particle_new ("pt_grav", part_tex_smoke, porg, pscale, pvel, vr_data.realtime + 2.0 - percent * 2.0, 68 + (mtwist_rand (&mt) & 3), 1.0, 0.0); if (numparticles >= r_maxparticles) @@ -916,7 +916,7 @@ R_SlightBloodTrail_QF (entity_t *ent) percent = len * origlen; pvel[2] -= percent * 40; - particle_new (pt_grav, part_tex_smoke, porg, pscale, pvel, + particle_new ("pt_grav", part_tex_smoke, porg, pscale, pvel, vr_data.realtime + 1.5 - percent * 1.5, 68 + (mtwist_rand (&mt) & 3), 0.75, 0.0); if (numparticles >= r_maxparticles) @@ -957,7 +957,7 @@ R_WizTrail_QF (entity_t *ent) } pvel[2] = 0.0; - particle_new (pt_flame, part_tex_smoke, old_origin, + particle_new ("pt_flame", part_tex_smoke, old_origin, 2.0 + qfrandom (1.0) - percent * 2.0, pvel, vr_data.realtime + 0.5 - percent * 0.5, 52 + (mtwist_rand (&mt) & 4), 1.0 - percent * 0.125, 0.0); @@ -998,7 +998,7 @@ R_FlameTrail_QF (entity_t *ent) } pvel[2] = 0.0; - particle_new (pt_flame, part_tex_smoke, old_origin, + particle_new ("pt_flame", part_tex_smoke, old_origin, 2.0 + qfrandom (1.0) - percent * 2.0, pvel, vr_data.realtime + 0.5 - percent * 0.5, 234, 1.0 - percent * 0.125, 0.0); @@ -1032,7 +1032,7 @@ R_VoorTrail_QF (entity_t *ent) for (j = 0; j < 3; j++) porg[j] = old_origin[j] + qfrandom (16.0) - 8.0; - particle_new (pt_static, part_tex_dot, porg, 1.0 + qfrandom (1.0), + particle_new ("pt_static", part_tex_dot, porg, 1.0 + qfrandom (1.0), vec3_origin, vr_data.realtime + 0.3 - percent * 0.3, 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 1.0, 0.0); if (numparticles >= r_maxparticles) @@ -1067,7 +1067,7 @@ R_GlowTrail_QF (entity_t *ent, int glow_color) org[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; org[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - particle_new (pt_smoke, part_tex_dot, org, 1.0, vec3_origin, + particle_new ("pt_smoke", part_tex_dot, org, 1.0, vec3_origin, vr_data.realtime + 2.0 - percent * 0.2, glow_color, 1.0, 0.0); if (numparticles >= r_maxparticles) @@ -1085,7 +1085,7 @@ R_ParticleExplosion_EE (const vec3_t org) */ if (numparticles >= r_maxparticles) return; - particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, + particle_new_random ("pt_smokecloud", part_tex_smoke, org, 4, 30, 8, vr_data.realtime + 5.0, mtwist_rand (&mt) & 255, 0.5 + qfrandom (0.25), 0.0); } @@ -1119,7 +1119,7 @@ R_TeleportSplash_EE (const vec3_t org) VectorNormalize (dir); vel = 50 + ((rnd >> 6) & 63); VectorScale (dir, vel, pvel); - particle_new (pt_grav, part_tex_spark, porg, 0.6, pvel, + particle_new ("pt_grav", part_tex_spark, porg, 0.6, pvel, (vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 15) * 0.01), qfrandom (1.0), 1.0, 0.0); } @@ -1148,7 +1148,7 @@ R_RocketTrail_EE (entity_t *ent) dist = (pscale + pscalenext) * 3.0; percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, + particle_new ("pt_smoke", part_tex_smoke, old_origin, pscale + percent * 4.0, vec3_origin, vr_data.realtime + 2.0 - percent * 2.0, mtwist_rand (&mt) & 255, @@ -1183,7 +1183,7 @@ R_GrenadeTrail_EE (entity_t *ent) dist = (pscale + pscalenext) * 2.0; percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, + particle_new ("pt_smoke", part_tex_smoke, old_origin, pscale + percent * 4.0, vec3_origin, vr_data.realtime + 2.0 - percent * 2.0, mtwist_rand (&mt) & 255, @@ -1209,11 +1209,11 @@ R_ParticleExplosion_ID (const vec3_t org) j = r_maxparticles - numparticles; for (i = 0; i < j >> 1; i++) { - particle_new_random (pt_explode, part_tex_dot, org, 16, 1.0, 256, + particle_new_random ("pt_explode", part_tex_dot, org, 16, 1.0, 256, vr_data.realtime + 5.0, ramp1[0], 1.0, i & 3); } for (i = 0; i < j / 2; i++) { - particle_new_random (pt_explode2, part_tex_dot, org, 16, 1.0, 256, + particle_new_random ("pt_explode2", part_tex_dot, org, 16, 1.0, 256, vr_data.realtime + 5.0, ramp1[0], 1.0, i & 3); } } @@ -1230,12 +1230,12 @@ R_BlobExplosion_ID (const vec3_t org) j = r_maxparticles - numparticles; for (i = 0; i < j >> 1; i++) { - particle_new_random (pt_blob, part_tex_dot, org, 12, 1.0, 256, + particle_new_random ("pt_blob", part_tex_dot, org, 12, 1.0, 256, vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 8) * 0.05, 66 + i % 6, 1.0, 0.0); } for (i = 0; i < j / 2; i++) { - particle_new_random (pt_blob2, part_tex_dot, org, 12, 1.0, 256, + particle_new_random ("pt_blob2", part_tex_dot, org, 12, 1.0, 256, vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 8) * 0.05, 150 + i % 6, 1.0, 0.0); } @@ -1270,7 +1270,7 @@ R_RunParticleEffect_ID (const vec3_t org, const vec3_t dir, int color, porg[2] = org[2] + scale * (((rnd >> 11) & 15) - 8); // Note that ParseParticleEffect handles (dir * 15) - particle_new (pt_grav, part_tex_dot, porg, 1.0, dir, + particle_new ("pt_grav", part_tex_dot, porg, 1.0, dir, vr_data.realtime + 0.1 * (i % 5), (color & ~7) + (rnd & 7), 1.0, 0.0); } @@ -1347,7 +1347,7 @@ R_LavaSplash_ID (const vec3_t org) rnd = mtwist_rand (&mt); vel = 50 + (rnd & 63); VectorScale (dir, vel, pvel); - particle_new (pt_grav, part_tex_dot, porg, 1.0, pvel, + particle_new ("pt_grav", part_tex_dot, porg, 1.0, pvel, vr_data.realtime + 2 + ((rnd >> 7) & 31) * 0.02, 224 + ((rnd >> 12) & 7), 1.0, 0.0); } @@ -1385,7 +1385,7 @@ R_TeleportSplash_ID (const vec3_t org) vel = 50 + ((rnd >> 6) & 63); VectorScale (pdir, vel, pvel); - particle_new (pt_grav, part_tex_dot, porg, 1.0, pvel, + particle_new ("pt_grav", part_tex_dot, porg, 1.0, pvel, (vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 7) * 0.02), (7 + ((rnd >> 12) & 7)), 1.0, 0.0); } @@ -1424,7 +1424,7 @@ R_DarkFieldParticles_ID (entity_t *ent) VectorNormalize (dir); vel = 50 + ((rnd >> 9) & 63); VectorScale (dir, vel, pvel); - particle_new (pt_slowgrav, part_tex_dot, porg, 1.5, pvel, + particle_new ("pt_slowgrav", part_tex_dot, porg, 1.5, pvel, (vr_data.realtime + 0.2 + (rnd & 7) * 0.02), (150 + mtwist_rand (&mt) % 6), 1.0, 0.0); } @@ -1477,7 +1477,7 @@ R_EntityParticles_ID (entity_t *ent) forward[1] * beamlength; porg[2] = ent->origin[2] + vertex_normals[i][2] * dist + forward[2] * beamlength; - particle_new (pt_explode, part_tex_dot, porg, 1.0, vec3_origin, + particle_new ("pt_explode", part_tex_dot, porg, 1.0, vec3_origin, vr_data.realtime + 0.01, 0x6f, 1.0, 0); } } @@ -1505,7 +1505,7 @@ R_RocketTrail_ID (entity_t *ent) org[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; ramp = rnd & 3; - particle_new (pt_fire, part_tex_dot, org, 1.0, vec3_origin, + particle_new ("pt_fire", part_tex_dot, org, 1.0, vec3_origin, vr_data.realtime + 2.0, ramp3[ramp], 1.0, ramp); if (numparticles >= r_maxparticles) break; @@ -1537,7 +1537,7 @@ R_GrenadeTrail_ID (entity_t *ent) org[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; ramp = (rnd & 3) + 2; - particle_new (pt_fire, part_tex_dot, org, 1.0, vec3_origin, + particle_new ("pt_fire", part_tex_dot, org, 1.0, vec3_origin, vr_data.realtime + 2.0, ramp3[ramp], 1.0, ramp); if (numparticles >= r_maxparticles) break; @@ -1568,7 +1568,7 @@ R_BloodTrail_ID (entity_t *ent) porg[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; porg[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - particle_new (pt_grav, part_tex_dot, porg, 1.0, vec3_origin, + particle_new ("pt_grav", part_tex_dot, porg, 1.0, vec3_origin, vr_data.realtime + 2.0, 67 + (rnd & 3), 1.0, 0.0); if (numparticles >= r_maxparticles) break; @@ -1599,7 +1599,7 @@ R_SlightBloodTrail_ID (entity_t *ent) porg[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; porg[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - particle_new (pt_grav, part_tex_dot, porg, 1.0, vec3_origin, + particle_new ("pt_grav", part_tex_dot, porg, 1.0, vec3_origin, vr_data.realtime + 1.5, 67 + (rnd & 3), 1.0, 0.0); if (numparticles >= r_maxparticles) break; @@ -1635,7 +1635,7 @@ R_WizTrail_ID (entity_t *ent) } pvel[2] = 0.0; - particle_new (pt_static, part_tex_dot, old_origin, 1.0, pvel, + particle_new ("pt_static", part_tex_dot, old_origin, 1.0, pvel, vr_data.realtime + 0.5, 52 + ((tracercount & 4) << 1), 1.0, 0.0); if (numparticles >= r_maxparticles) @@ -1672,7 +1672,7 @@ R_FlameTrail_ID (entity_t *ent) } pvel[2] = 0.0; - particle_new (pt_static, part_tex_dot, old_origin, 1.0, pvel, + particle_new ("pt_static", part_tex_dot, old_origin, 1.0, pvel, vr_data.realtime + 0.5, 230 + ((tracercount & 4) << 1), 1.0, 0.0); if (numparticles >= r_maxparticles) @@ -1704,7 +1704,7 @@ R_VoorTrail_ID (entity_t *ent) porg[1] = old_origin[1] + ((rnd >> 7) & 15) - 7.5; porg[2] = old_origin[2] + ((rnd >> 11) & 15) - 7.5; - particle_new (pt_static, part_tex_dot, porg, 1.0, vec3_origin, + particle_new ("pt_static", part_tex_dot, porg, 1.0, vec3_origin, vr_data.realtime + 0.3, 9 * 16 + 8 + (rnd & 3), 1.0, 0.0); if (numparticles >= r_maxparticles) @@ -1763,7 +1763,7 @@ build_verts (trailvtx_t *v, GLushort *e) *e++ = index++; *e++ = index++; last_point = point; - point->phys (point); + R_RunParticlePhysics (point); } set_vertex (v++, last_point, -1, bary + bind++, index/2 + 1); set_vertex (v++, last_point, 1, bary + bind++, index/2 + 1); @@ -1964,7 +1964,7 @@ draw_qf_particles (void) vacount += 6; } - part->phys (part); + R_RunParticlePhysics (part); // LordHavoc: immediate removal of unnecessary particles (must be done // to ensure compactor below operates properly in all cases) @@ -2052,7 +2052,7 @@ draw_id_particles (void) vacount++; } - part->phys (part); + R_RunParticlePhysics (part); // LordHavoc: immediate removal of unnecessary particles (must be done // to ensure compactor below operates properly in all cases) @@ -2316,9 +2316,9 @@ glsl_R_Particles_Init_Cvars (void) } void -glsl_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, - float ramp) +glsl_R_Particle_New (const char *type, int texnum, const vec3_t org, + float scale, const vec3_t vel, float die, int color, + float alpha, float ramp) { if (numparticles >= r_maxparticles) return; @@ -2326,7 +2326,7 @@ glsl_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, } void -glsl_R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, +glsl_R_Particle_NewRandom (const char *type, int texnum, const vec3_t org, int org_fuzz, float scale, int vel_fuzz, float die, int color, float alpha, float ramp) { diff --git a/libs/video/renderer/particles.part b/libs/video/renderer/particles.part new file mode 100644 index 000000000..23db9a2d4 --- /dev/null +++ b/libs/video/renderer/particles.part @@ -0,0 +1,83 @@ +All of QuakeForge's standard particle physics functions converted to a script +-- pt_static +add_vel + +-- pt_grav +add_vel +add_grav + +-- pt_slowgrav +add_vel +add_grav + +-- pt_fire +add_ramp 5 6 +add_vel +color_ramp3 +alpha_ramp 6 +sub_grav + +-- pt_explode +add_ramp 10 8 +add_vel +color_ramp1 +explode_vel 4 +add_grav + +-- pt_explode2 +add_ramp 15 8 +add_vel +color_ramp2 +explode_vel 1 +add_grav + +-- pt_blob +add_vel +explode_vel 4 +add_grav + +-- pt_blob2 +add_vel +damp_vel 4 +add_grav + +-- pt_smoke +fade_alpha 0.4 +add_vel +grow_scale 4 +//sub_slowgrav + +-- pt_smokecloud +fade_alpha 0.55 +add_vel +grow_scale 50 +sub_slowgrav + +-- pt_bloodcloud +fade_alpha 0.25 +add_vel +grow_scale 4 +add_grav + +-- pt_fadespark +add_vel + +-- pt_fadespark2 +add_vel + +-- pt_fallfade +fade_alpha 1 +add_vel +add_fastgrav + +-- pt_fallfadespark +add_ramp 15 8 +fade_alpha 1 +color_ramp1 +add_vel +add_fastgrav + +-- pt_flame +fade_alpha 0.125 +add_vel +shrink_scale 2 diff --git a/libs/video/renderer/r_part.c b/libs/video/renderer/r_part.c index d49c224b7..cfb7baac9 100644 --- a/libs/video/renderer/r_part.c +++ b/libs/video/renderer/r_part.c @@ -28,14 +28,101 @@ # include "config.h" #endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/alloc.h" +#include "QF/cbuf.h" #include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/hash.h" #include "QF/qargs.h" #include "QF/render.h" +#include "QF/script.h" +#include "QF/segtext.h" #include "QF/sys.h" #include "compat.h" #include "r_internal.h" +typedef enum { + pt_phys_done, + pt_phys_add_vel, + pt_phys_sub_slowgrav, + pt_phys_add_grav, + pt_phys_sub_grav, + pt_phys_add_fastgrav, + pt_phys_add_ramp, // die + pt_phys_fade_alpha, // die + pt_phys_color_ramp1, + pt_phys_color_ramp2, + pt_phys_color_ramp3, + pt_phys_alpha_ramp, + pt_phys_explode_vel, + pt_phys_damp_vel, + pt_phys_grow_scale, + pt_phys_shrink_scale, // die + pt_phys_custom, // die +} pt_phys_e; + +typedef struct { + const char *name; + pt_phys_e opcode; + int num_params; +} pt_phys_opcode_t; + +typedef struct { + char *name; + qboolean (*func) (particle_t *part, void *data); + void *data; +} pt_phys_func_t; + +typedef union pt_phys_op_s { + int32_t op; + float parm; +} pt_phys_op_t; + +typedef struct pt_phys_script_s { + struct pt_phys_script_s *next; + char *name; + pt_phys_op_t *script; +} pt_phys_script_t; + +const char particle_types[] = +#include "particles.pc" +; + +static pt_phys_func_t *phys_funcs; +static int num_phys_funcs; +static int max_phys_funcs; +static pt_phys_script_t *phys_script_freelist; +static hashtab_t *phys_scripts; + +static pt_phys_opcode_t part_phys_opcodes[] = +{ + {"add_vel", pt_phys_add_vel, 0}, + {"sub_slowgrav", pt_phys_sub_slowgrav, 0}, + {"add_grav", pt_phys_add_grav, 0}, + {"sub_grav", pt_phys_sub_grav, 0}, + {"add_fastgrav", pt_phys_add_fastgrav, 0}, + {"add_ramp", pt_phys_add_ramp, 2}, + {"fade_alpha", pt_phys_fade_alpha, 1}, + {"color_ramp1", pt_phys_color_ramp1, 0}, + {"color_ramp2", pt_phys_color_ramp2, 0}, + {"color_ramp3", pt_phys_color_ramp3, 0}, + {"alpha_ramp", pt_phys_alpha_ramp, 1}, + {"explode_vel", pt_phys_explode_vel, 1}, + {"damp_vel", pt_phys_damp_vel, 1}, + {"grow_scale", pt_phys_grow_scale, 1}, + {"shrink_scale", pt_phys_shrink_scale, 1}, + + {0, pt_phys_done, 0}, +}; + unsigned int r_maxparticles, numparticles; particle_t *active_particles, *free_particles, *particles, **freeparticles; vec3_t r_pright, r_pup, r_ppn; @@ -160,152 +247,307 @@ fade_alpha (particle_t *part, float time) return false; } -static void -part_phys_static (particle_t *part) +static inline qboolean +custom_func (particle_t *part, int op) { - add_vel (part); + int func; + func = op - pt_phys_custom; + if (func < 0 || func >= num_phys_funcs) { + Sys_Error ("invalid custom particle physics opcode: %d", op); + } + if (phys_funcs[func].func (part, phys_funcs[func].data)) { + part->die = -1; + return true; + } + return false; } -static void -part_phys_grav (particle_t *part) +void +R_RunParticlePhysics (particle_t *part) { - add_vel (part); - add_grav (part); -} + const pt_phys_op_t *op; + float parm, max; -static void -part_phys_fire (particle_t *part) -{ - if (add_ramp (part, 5.0, 6)) + if (!part->physics) { + // safety net for physicsless particles + add_ramp (part, 1, 4); return; - add_vel (part); - part->color = ramp3[(int) part->ramp]; - part->alpha = (6.0 - part->ramp) / 6.0; - sub_grav (part); + } + for (op = part->physics; ; op++) { + if (op->op >= pt_phys_custom) { + if (custom_func (part, op->op)) + return; + } + + switch ((pt_phys_e) op->op) { + case pt_phys_done: + return; + case pt_phys_add_vel: + add_vel (part); + break; + case pt_phys_sub_slowgrav: + sub_slowgrav (part); + break; + case pt_phys_add_grav: + add_grav (part); + break; + case pt_phys_sub_grav: + sub_grav (part); + break; + case pt_phys_add_fastgrav: + add_fastgrav (part); + break; + case pt_phys_add_ramp: + parm = (++op)->parm; + max = (++op)->parm; + if (add_ramp (part, parm, max)) + return; + break; + case pt_phys_fade_alpha: + parm = (++op)->parm; + if (fade_alpha (part, parm)) + return; + break; + case pt_phys_color_ramp1: + part->color = ramp1[((int) part->ramp) % sizeof (ramp1)]; + break; + case pt_phys_color_ramp2: + part->color = ramp2[((int) part->ramp) % sizeof (ramp2)]; + break; + case pt_phys_color_ramp3: + part->color = ramp3[((int) part->ramp) % sizeof (ramp3)]; + break; + case pt_phys_alpha_ramp: + parm = (++op)->parm; + part->alpha = (parm - part->ramp) / parm; + break; + case pt_phys_explode_vel: + parm = (++op)->parm; + VectorMultAdd (part->vel, vr_data.frametime * parm, part->vel, + part->vel); + break; + case pt_phys_damp_vel: + parm = (++op)->parm; + part->vel[0] -= part->vel[0] * vr_data.frametime * parm; + part->vel[1] -= part->vel[1] * vr_data.frametime * parm; + break; + case pt_phys_grow_scale: + parm = (++op)->parm; + part->scale += vr_data.frametime * parm; + break; + case pt_phys_shrink_scale: + parm = (++op)->parm; + part->scale -= vr_data.frametime * parm; + if (part->scale <= 0.0) { + part->die = -1; + return; + } + break; + case pt_phys_custom: + // handled above + break; + } + } +} + +static pt_phys_opcode_t * +part_find_opcode (const char *name) +{ + pt_phys_opcode_t *op; + + for (op = part_phys_opcodes; op->name; op++) { + if (strcmp (op->name, name) == 0) + return op; + } + return 0; +} + +static pt_phys_func_t * +part_find_function (const char *name) +{ + pt_phys_func_t *func; + + //FIXME is a hash table worth it? + for (func = phys_funcs; func - phys_funcs < num_phys_funcs; func++) { + if (strcmp (func->name, name) == 0) + return func; + } + return 0; } static void -part_phys_explode (particle_t *part) +part_add_op (dstring_t *phys, int op) { - if (add_ramp (part, 10.0, 8)) - return; - add_vel (part); - part->color = ramp1[(int) part->ramp]; - VectorMultAdd (part->vel, vr_data.frametime * 4.0, part->vel, part->vel); - add_grav (part); + int offs = phys->size; + phys->size += sizeof (pt_phys_op_t); + dstring_adjust (phys); + ((pt_phys_op_t *) (phys->str + offs))->op = op; } static void -part_phys_explode2 (particle_t *part) +part_add_parm (dstring_t *phys, float parm) { - if (add_ramp (part, 15.0, 8)) - return; - add_vel (part); - part->color = ramp2[(int) part->ramp]; - VectorMultAdd (part->vel, vr_data.frametime, part->vel, part->vel); - add_grav (part); + int offs = phys->size; + phys->size += sizeof (pt_phys_op_t); + dstring_adjust (phys); + ((pt_phys_op_t *) (phys->str + offs))->parm = parm; +} + +static pt_phys_script_t * +new_phys_script (void) +{ + pt_phys_script_t *phys_script; + ALLOC (16, pt_phys_script_t, phys_script, phys_script); + return phys_script; } static void -part_phys_blob (particle_t *part) +free_phys_script (pt_phys_script_t *phys_script) { - add_vel (part); - VectorMultAdd (part->vel, vr_data.frametime * 4.0, part->vel, part->vel); - add_grav (part); + FREE (phys_script, phys_script); +} + +static const char * +part_script_get_key (const void *_s, void *unused) +{ + const pt_phys_script_t *s = (const pt_phys_script_t *) _s; + return s->name; } static void -part_phys_blob2 (particle_t *part) +part_script_free (void *_s, void *unused) { - add_vel (part); - part->vel[0] -= part->vel[0] * vr_data.frametime * 4.0; - part->vel[1] -= part->vel[1] * vr_data.frametime * 4.0; - add_grav (part); + pt_phys_script_t *s = (pt_phys_script_t *) _s; + free (s->name); + free (s->script); + free_phys_script (s); } -static void -part_phys_smoke (particle_t *part) +qboolean +R_CompileParticlePhysics (const char *name, const char *code) { - if (fade_alpha (part, 0.4)) - return; - add_vel (part); - part->scale += vr_data.frametime * 4.0; - //sub_slowgrav (part); + cbuf_args_t *args = Cbuf_ArgsNew (); + script_t *script = Script_New (); + pt_phys_opcode_t *opcode; + pt_phys_script_t *phys; + pt_phys_func_t *func; + dstring_t *phys_build = dstring_new (); + int i; + qboolean ret = false; + + if (!phys_scripts) { + phys_scripts = Hash_NewTable (61, part_script_get_key, + part_script_free, 0); + } + Script_Start (script, "name", code); + while (Script_GetToken (script, 1)) { + args->argc = 0; + Cbuf_ArgsAdd (args, Script_Token (script)); + while (Script_TokenAvailable (script, 0)) { + Script_GetToken (script, 0); + Cbuf_ArgsAdd (args, Script_Token (script)); + } + Sys_Printf ("%s:%d: %s\n", name, script->line, args->argv[0]->str); + if ((func = part_find_function (args->argv[0]->str))) { + if (args->argc > 1) { + Sys_Printf ("%s:%d: warning: ignoring extra args\n", + name, script->line); + } + part_add_op (phys_build, pt_phys_custom + (func - phys_funcs)); + } else if ((opcode = part_find_opcode (args->argv[0]->str))) { + part_add_op (phys_build, opcode->opcode); + if (args->argc - 1 > opcode->num_params) { + Sys_Printf ("%s:%d: warning: ignoring extra args\n", + name, script->line); + args->argc = opcode->num_params + 1; + } + for (i = 1; i < args->argc; i++) { + char *end; + float parm = strtof (args->argv[i]->str, &end); + if (end == args->argv[i]->str) { + Sys_Printf ("%s:%d: warning: bad float\n", + name, script->line); + } else if (*end) { + Sys_Printf ("%s:%d: warning: ignoring extra chars\n", + name, script->line); + } + part_add_parm (phys_build, parm); + } + if (args->argc - 1 > opcode->num_params) { + Sys_Printf ("%s:%d: warning: setting parms %d+ to zero\n", + name, script->line, args->argc - 1); + for (i--; i < opcode->num_params; i++) + part_add_parm (phys_build, 0); + } + } else { + Sys_Printf ("%s:%d: warning: unknown opcode/function: %s\n", + name, script->line, args->argv[0]->str); + } + } + if (phys_build->size) { + part_add_op (phys_build, pt_phys_done); + phys = new_phys_script (); + phys->name = strdup (name); + phys->script = (pt_phys_op_t *) dstring_freeze (phys_build); + Hash_Add (phys_scripts, phys); + ret = true; + } else { + dstring_delete (phys_build); + } + + Script_Delete (script); + Cbuf_ArgsDelete (args); + return ret; } -static void -part_phys_smokecloud (particle_t *part) +const pt_phys_op_t * +R_ParticlePhysics (const char *type) { - if (fade_alpha (part, 0.55)) - return; - add_vel (part); - part->scale += vr_data.frametime * 50.0; - sub_slowgrav (part); + pt_phys_script_t *phys; + + if (!phys_scripts) + return 0; + if ((phys = Hash_Find (phys_scripts, type))) + return phys->script; + return 0; } -static void -part_phys_bloodcloud (particle_t *part) +qboolean +R_AddParticlePhysicsFunction (const char *name, + qboolean (*func) (particle_t *part, void *data), + void *data) { - if (fade_alpha (part, 0.25)) - return; - add_vel (part); - part->scale += vr_data.frametime * 4.0; - add_grav (part); + int i; + + for (i = 0; i < num_phys_funcs; i++) { + if (strcmp (name, phys_funcs[i].name) == 0) + return false; + } + if (num_phys_funcs == max_phys_funcs) { + max_phys_funcs += 16; + phys_funcs = realloc (phys_funcs, + max_phys_funcs * sizeof (pt_phys_func_t)); + if (!phys_funcs) { + Sys_Error ("R_AddParticlePhysicsFunction: out of memory"); + } + } + phys_funcs[num_phys_funcs].name = strdup (name); + phys_funcs[num_phys_funcs].func = func; + phys_funcs[num_phys_funcs].data = data; + return true; } -static void -part_phys_fallfade (particle_t *part) +void +R_LoadParticles (void) { - if (fade_alpha (part, 1.0)) - return; - add_vel (part); - add_fastgrav (part); -} + segtext_t *text; + segchunk_t *chunk; -static void -part_phys_fallfadespark (particle_t *part) -{ - if (add_ramp (part, 15.0, 8)) - return; - if (fade_alpha (part, 1.0)) - return; - part->color = ramp1[(int) part->ramp]; - add_vel (part); - add_fastgrav (part); -} - -static void -part_phys_flame (particle_t *part) -{ - if (fade_alpha (part, 0.125)) - return; - add_vel (part); - part->scale -= vr_data.frametime * 2.0; -} - -static pt_phys_func part_phys[] = { - part_phys_static, // pt_static - part_phys_grav, // pt_grav - part_phys_grav, // pt_slowgrav - part_phys_fire, // pt_fire - part_phys_explode, // pt_explode - part_phys_explode2, // pt_explode2 - part_phys_blob, // pt_blob - part_phys_blob2, // pt_blob2 - part_phys_smoke, // pt_smoke - part_phys_smokecloud, // pt_smokecloud - part_phys_bloodcloud, // pt_bloodcloud - part_phys_static, // pt_fadespark - part_phys_static, // pt_fadespark2 - part_phys_fallfade, // pt_fallfade - part_phys_fallfadespark,// pt_fallfadespark - part_phys_flame, // pt_flame -}; - -pt_phys_func -R_ParticlePhysics (ptype_t type) -{ - if (type > pt_flame) - Sys_Error ("R_ParticlePhysics: invalid particle type"); - return part_phys[type]; + text = Segtext_new (particle_types); + for (chunk = text->chunk_list; chunk; chunk = chunk->next) { + if (chunk->tag) { + Sys_Printf ("compiling %s\n", chunk->tag); + R_CompileParticlePhysics (chunk->tag, chunk->text); + } + } } diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 5d38ae04d..0ed1655a7 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -128,6 +128,7 @@ sw_R_Init (void) #ifdef USE_INTEL_ASM R_InitVars (); #endif + R_InitParticles (); R_InitTurb (); diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index 4e113cc5b..71ee1fcf8 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -56,6 +56,7 @@ static mtstate_t mt; // private PRNG state void R_InitParticles (void) { + R_LoadParticles (); mtwist_seed (&mt, 0xdeadbeef); } @@ -119,8 +120,7 @@ R_ReadPointFile_f (void) p->die = 99999; p->color = (-c) & 15; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_static"); VectorZero (p->vel); VectorCopy (org, p->org); } @@ -150,10 +150,9 @@ R_ParticleExplosion_QF (const vec3_t org) p->color = ramp1[0]; p->ramp = mtwist_rand (&mt) & 3; if (i & 1) - p->type = pt_explode; + p->physics = R_ParticlePhysics ("pt_explode"); else - p->type = pt_explode2; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_explode2"); for (j = 0; j < 3; j++) { p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16); p->vel[j] = (mtwist_rand (&mt) % 512) - 256; @@ -180,8 +179,7 @@ R_ParticleExplosion2_QF (const vec3_t org, int colorStart, int colorLength) p->color = colorStart + (colorMod % colorLength); colorMod++; - p->type = pt_blob; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_blob"); for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((mtwist_rand (&mt)%32)-16); p->vel[j] = (mtwist_rand (&mt)%512)-256; @@ -209,13 +207,12 @@ R_BlobExplosion_QF (const vec3_t org) p->die = vr_data.realtime + 1 + (mtwist_rand (&mt) & 8) * 0.05; if (i & 1) { - p->type = pt_blob; p->color = 66 + mtwist_rand (&mt) % 6; + p->physics = R_ParticlePhysics ("pt_blob"); } else { - p->type = pt_blob2; p->color = 150 + mtwist_rand (&mt) % 6; + p->physics = R_ParticlePhysics ("pt_blob2"); } - p->phys = R_ParticlePhysics (p->type); for (j = 0; j < 3; j++) { p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16); p->vel[j] = (mtwist_rand (&mt) % 512) - 256; @@ -243,8 +240,7 @@ R_RunParticleEffect_QF (const vec3_t org, const vec3_t dir, int color, p->die = vr_data.realtime + 0.1 * (mtwist_rand (&mt) % 5); p->color = (color & ~7) + (mtwist_rand (&mt) & 7); - p->type = pt_grav; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_grav"); for (j = 0; j < 3; j++) { p->org[j] = org[j] + ((mtwist_rand (&mt) & 15) - 8); p->vel[j] = dir[j]; // + (mtwist_rand (&mt)%300)-150; @@ -317,8 +313,7 @@ R_LavaSplash_QF (const vec3_t org) p->die = vr_data.realtime + 2 + (mtwist_rand (&mt) & 31) * 0.02; p->color = 224 + (mtwist_rand (&mt) & 7); - p->type = pt_grav; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_grav"); dir[0] = j * 8 + (mtwist_rand (&mt) & 7); dir[1] = i * 8 + (mtwist_rand (&mt) & 7); @@ -357,8 +352,7 @@ R_TeleportSplash_QF (const vec3_t org) p->die = vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 7) * 0.02; p->color = 7 + (mtwist_rand (&mt) & 7); - p->type = pt_grav; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_grav"); dir[0] = j * 8; dir[1] = i * 8; @@ -403,8 +397,7 @@ R_DarkFieldParticles_ID (entity_t *ent) p->die = vr_data.realtime + 0.2 + (rnd & 7) * 0.02; p->color = 150 + mtwist_rand (&mt) % 6; - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_slowgrav"); dir[0] = j * 8; dir[1] = i * 8; dir[2] = k * 8; @@ -467,8 +460,7 @@ R_EntityParticles_ID (entity_t *ent) p->die = vr_data.realtime + 0.01; p->color = 0x6f; - p->type = pt_explode; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_explode"); p->org[0] = ent->origin[0] + r_avertexnormals[i][0] * dist + forward[0] * beamlength; @@ -509,8 +501,7 @@ R_RocketTrail_QF (entity_t *ent) p->die = vr_data.realtime + 2; p->ramp = (mtwist_rand (&mt) & 3); p->color = ramp3[(int) p->ramp]; - p->type = pt_fire; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_fire"); for (j = 0; j < 3; j++) p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); @@ -548,8 +539,7 @@ R_GrenadeTrail_QF (entity_t *ent) p->die = vr_data.realtime + 2; p->ramp = (mtwist_rand (&mt) & 3) + 2; p->color = ramp3[(int) p->ramp]; - p->type = pt_fire; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_fire"); for (j = 0; j < 3; j++) p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); @@ -585,8 +575,7 @@ R_BloodTrail_QF (entity_t *ent) VectorZero (p->vel); p->die = vr_data.realtime + 2; - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_slowgrav"); p->color = 67 + (mtwist_rand (&mt) & 3); for (j = 0; j < 3; j++) p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); @@ -624,8 +613,7 @@ R_SlightBloodTrail_QF (entity_t *ent) VectorZero (p->vel); p->die = vr_data.realtime + 2; - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_slowgrav"); p->color = 67 + (mtwist_rand (&mt) & 3); for (j = 0; j < 3; j++) p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); @@ -661,8 +649,7 @@ R_WizTrail_QF (entity_t *ent) active_particles = p; p->die = vr_data.realtime + 0.5; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_static"); p->color = 52 + ((tracercount & 4) << 1); tracercount++; @@ -708,8 +695,7 @@ R_FlameTrail_QF (entity_t *ent) active_particles = p; p->die = vr_data.realtime + 0.5; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_static"); p->color = 230 + ((tracercount & 4) << 1); tracercount++; @@ -756,8 +742,7 @@ R_VoorTrail_QF (entity_t *ent) VectorZero (p->vel); p->die = vr_data.realtime + 0.3; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_static"); p->color = 9 * 16 + 8 + (mtwist_rand (&mt) & 3); for (j = 0; j < 3; j++) p->org[j] = old_origin[j] + ((mtwist_rand (&mt) & 15) - 8); @@ -787,7 +772,7 @@ R_DrawParticles (void) D_DrawParticle (p); - p->phys (p); + R_RunParticlePhysics (p); } } } @@ -877,7 +862,7 @@ R_Particles_Init_Cvars (void) } void -R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, +R_Particle_New (const char *type, int texnum, const vec3_t org, float scale, const vec3_t vel, float die, int color, float alpha, float ramp) { particle_t *p; @@ -895,16 +880,15 @@ R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, p->scale = scale; p->alpha = alpha; VectorCopy (vel, p->vel); - p->type = type; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics (type); p->die = die; p->ramp = ramp; } void -R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, int org_fuzz, - float scale, int vel_fuzz, float die, int color, - float alpha, float ramp) +R_Particle_NewRandom (const char *type, int texnum, const vec3_t org, + int org_fuzz, float scale, int vel_fuzz, float die, + int color, float alpha, float ramp) { float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; int rnd; diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index fd204e587..9ff2dc40f 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -150,6 +150,7 @@ sw32_R_Init (void) sw32_Draw_Init (); SCR_Init (); + R_InitParticles (); sw32_R_InitTurb (); Cmd_AddCommand ("timerefresh", sw32_R_TimeRefresh_f, "Tests the current " diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c index 0ba04ca1b..24e6a7876 100644 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -60,6 +60,7 @@ static mtstate_t mt; // private PRNG state void sw32_R_InitParticles (void) { + R_LoadParticles (); mtwist_seed (&mt, 0xdeadbeef); } @@ -124,8 +125,7 @@ sw32_R_ReadPointFile_f (void) p->die = 99999; p->color = (-c) & 15; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_static"); VectorZero (p->vel); VectorCopy (org, p->org); } @@ -155,19 +155,18 @@ R_ParticleExplosion_QF (const vec3_t org) p->color = ramp1[0]; p->ramp = mtwist_rand (&mt) & 3; if (i & 1) { - p->type = pt_explode; + p->physics = R_ParticlePhysics ("pt_explode"); for (j = 0; j < 3; j++) { p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16); p->vel[j] = (mtwist_rand (&mt) % 512) - 256; } } else { - p->type = pt_explode2; + p->physics = R_ParticlePhysics ("pt_explode2"); for (j = 0; j < 3; j++) { p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16); p->vel[j] = (mtwist_rand (&mt) % 512) - 256; } } - p->phys = R_ParticlePhysics (p->type); } } @@ -191,8 +190,7 @@ R_ParticleExplosion2_QF (const vec3_t org, int colorStart, int colorLength) p->color = colorStart + (colorMod % colorLength); colorMod++; - p->type = pt_blob; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_blob"); for (j=0 ; j<3 ; j++) { p->org[j] = org[j] + ((mtwist_rand (&mt)%32)-16); @@ -221,21 +219,20 @@ R_BlobExplosion_QF (const vec3_t org) p->die = vr_data.realtime + 1 + (mtwist_rand (&mt) & 8) * 0.05; if (i & 1) { - p->type = pt_blob; + p->physics = R_ParticlePhysics ("pt_blob"); p->color = 66 + mtwist_rand (&mt) % 6; for (j = 0; j < 3; j++) { p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16); p->vel[j] = (mtwist_rand (&mt) % 512) - 256; } } else { - p->type = pt_blob2; + p->physics = R_ParticlePhysics ("pt_blob2"); p->color = 150 + mtwist_rand (&mt) % 6; for (j = 0; j < 3; j++) { p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16); p->vel[j] = (mtwist_rand (&mt) % 512) - 256; } } - p->phys = R_ParticlePhysics (p->type); } } @@ -262,8 +259,7 @@ R_LavaSplash_QF (const vec3_t org) p->die = vr_data.realtime + 2 + (mtwist_rand (&mt) & 31) * 0.02; p->color = 224 + (mtwist_rand (&mt) & 7); - p->type = pt_grav; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_grav"); dir[0] = j * 8 + (mtwist_rand (&mt) & 7); dir[1] = i * 8 + (mtwist_rand (&mt) & 7); @@ -302,8 +298,7 @@ R_TeleportSplash_QF (const vec3_t org) p->die = vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 7) * 0.02; p->color = 7 + (mtwist_rand (&mt) & 7); - p->type = pt_grav; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_grav"); dir[0] = j * 8; dir[1] = i * 8; @@ -347,8 +342,7 @@ R_DarkFieldParticles_ID (entity_t *ent) p->die = vr_data.realtime + 0.2 + (rnd & 7) * 0.02; p->color = 150 + mtwist_rand (&mt) % 6; - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_slowgrav"); dir[0] = j * 8; dir[1] = i * 8; @@ -409,8 +403,7 @@ R_EntityParticles_ID (entity_t *ent) p->die = vr_data.realtime + 0.01; p->color = 0x6f; - p->type = pt_explode; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_explode"); p->org[0] = ent->origin[0] + r_avertexnormals[i][0] * dist + forward[0] * beamlength; @@ -441,8 +434,7 @@ R_RunParticleEffect_QF (const vec3_t org, const vec3_t dir, int color, p->die = vr_data.realtime + 0.1 * (mtwist_rand (&mt) % 5); p->color = (color & ~7) + (mtwist_rand (&mt) & 7); - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_slowgrav"); for (j = 0; j < 3; j++) { p->org[j] = org[j] + ((mtwist_rand (&mt) & 15) - 8); p->vel[j] = dir[j]; // + (mtwist_rand (&mt)%300)-150; @@ -522,8 +514,7 @@ R_RocketTrail_QF (entity_t *ent) p->die = vr_data.realtime + 2; p->ramp = (mtwist_rand (&mt) & 3); p->color = ramp3[(int) p->ramp]; - p->type = pt_fire; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_fire"); for (j = 0; j < 3; j++) p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); @@ -561,8 +552,7 @@ R_GrenadeTrail_QF (entity_t *ent) p->die = vr_data.realtime + 2; p->ramp = (mtwist_rand (&mt) & 3) + 2; p->color = ramp3[(int) p->ramp]; - p->type = pt_fire; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_fire"); for (j = 0; j < 3; j++) p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); @@ -598,8 +588,7 @@ R_BloodTrail_QF (entity_t *ent) VectorZero (p->vel); p->die = vr_data.realtime + 2; - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_slowgrav"); p->color = 67 + (mtwist_rand (&mt) & 3); for (j = 0; j < 3; j++) p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); @@ -637,8 +626,7 @@ R_SlightBloodTrail_QF (entity_t *ent) VectorZero (p->vel); p->die = vr_data.realtime + 2; - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_slowgrav"); p->color = 67 + (mtwist_rand (&mt) & 3); for (j = 0; j < 3; j++) p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); @@ -674,8 +662,7 @@ R_WizTrail_QF (entity_t *ent) active_particles = p; p->die = vr_data.realtime + 0.5; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_static"); p->color = 52 + ((tracercount & 4) << 1); tracercount++; @@ -721,8 +708,7 @@ R_FlameTrail_QF (entity_t *ent) active_particles = p; p->die = vr_data.realtime + 0.5; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_static"); p->color = 230 + ((tracercount & 4) << 1); tracercount++; @@ -769,8 +755,7 @@ R_VoorTrail_QF (entity_t *ent) VectorZero (p->vel); p->die = vr_data.realtime + 0.3; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics ("pt_static"); p->color = 9 * 16 + 8 + (mtwist_rand (&mt) & 3); for (j = 0; j < 3; j++) p->org[j] = old_origin[j] + ((mtwist_rand (&mt) & 15) - 8); @@ -800,7 +785,7 @@ sw32_R_DrawParticles (void) sw32_D_DrawParticle (p); - p->phys (p); + R_RunParticlePhysics (p); } } } @@ -890,9 +875,9 @@ sw32_R_Particles_Init_Cvars (void) } void -sw32_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, - float ramp) +sw32_R_Particle_New (const char *type, int texnum, const vec3_t org, + float scale, const vec3_t vel, float die, int color, + float alpha, float ramp) { particle_t *p; @@ -909,14 +894,13 @@ sw32_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, p->scale = scale; p->alpha = alpha; VectorCopy (vel, p->vel); - p->type = type; - p->phys = R_ParticlePhysics (p->type); + p->physics = R_ParticlePhysics (type); p->die = die; p->ramp = ramp; } void -sw32_R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, +sw32_R_Particle_NewRandom (const char *type, int texnum, const vec3_t org, int org_fuzz, float scale, int vel_fuzz, float die, int color, float alpha, float ramp) { diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index c79bfaa20..d874a0258 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -114,6 +114,8 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_R_RenderView, R_DecayLights, gl_R_ViewChanged, + R_CompileParticlePhysics, + R_AddParticlePhysicsFunction, gl_R_ClearParticles, gl_R_InitParticles, gl_SCR_ScreenShot_f, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index f09820ab3..635e7b415 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -114,6 +114,8 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_R_RenderView, R_DecayLights, glsl_R_ViewChanged, + R_CompileParticlePhysics, + R_AddParticlePhysicsFunction, glsl_R_ClearParticles, glsl_R_InitParticles, glsl_SCR_ScreenShot_f, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 7ac10a4d4..1e933a0dd 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -107,6 +107,8 @@ vid_render_funcs_t sw_vid_render_funcs = { R_RenderView, R_DecayLights, R_ViewChanged, + R_CompileParticlePhysics, + R_AddParticlePhysicsFunction, R_ClearParticles, R_InitParticles, SCR_ScreenShot_f, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 9bc135c78..9660f5afb 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -112,6 +112,8 @@ vid_render_funcs_t sw32_vid_render_funcs = { sw32_R_RenderView, R_DecayLights, sw32_R_ViewChanged, + R_CompileParticlePhysics, + R_AddParticlePhysicsFunction, sw32_R_ClearParticles, sw32_R_InitParticles, sw32_SCR_ScreenShot_f, diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index edd048090..5661b1b0f 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -613,12 +613,12 @@ CL_EmitEntities (void) dl->color[3] = 0.7; } VectorCopy (nearloc->loc, trueloc); - r_funcs->particles->R_Particle_New (pt_smokecloud, part_tex_smoke, + r_funcs->particles->R_Particle_New ("pt_smokecloud", part_tex_smoke, trueloc, 2.0, vec3_origin, r_data->realtime + 9.0, 254, 0.25 + qfrandom (0.125), 0.0); for (i = 0; i < 15; i++) - r_funcs->particles->R_Particle_NewRandom (pt_fallfade, + r_funcs->particles->R_Particle_NewRandom ("pt_fallfade", part_tex_dot, trueloc, 12, 0.7, 96, r_data->realtime + 5.0, 104 + (rand () & 7), 1.0, 0.0);