Skip to content

Commit 399584e

Browse files
authored
Merge branch 'master' into android-build
2 parents e9507cc + 973bd55 commit 399584e

File tree

4 files changed

+177
-15
lines changed

4 files changed

+177
-15
lines changed

code/particle/ParticleEffect.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ ParticleEffect::ParticleEffect(SCP_string name)
4747
m_spawnNoise(nullptr),
4848
m_manual_offset (std::nullopt),
4949
m_manual_velocity_offset(std::nullopt),
50+
m_light_source(std::nullopt),
5051
m_particleTrail(ParticleEffectHandle::invalid()),
5152
m_particleChance(1.f),
5253
m_distanceCulled(-1.f)
@@ -116,6 +117,7 @@ ParticleEffect::ParticleEffect(SCP_string name,
116117
m_spawnNoise(nullptr),
117118
m_manual_offset(offsetLocal),
118119
m_manual_velocity_offset(velocityOffsetLocal),
120+
m_light_source(std::nullopt),
119121
m_particleTrail(particleTrail),
120122
m_particleChance(particleChance),
121123
m_distanceCulled(distanceCulled) {}
@@ -335,14 +337,12 @@ auto ParticleEffect::processSourceInternal(float interp, const ParticleSource& s
335337
info.length = m_length.next() * lengthMultiplier;
336338

337339
int fps = 1;
338-
if (info.nframes < 0) {
339-
// Temporal WCS particle crash hack
340-
// DO NOT MERGE!
341-
if (!bm_is_valid(info.bitmap))
342-
continue;
343-
//Assertion(bm_is_valid(info.bitmap), "Invalid bitmap handle passed to particle create.");
344-
bm_get_info(info.bitmap, nullptr, nullptr, nullptr, &info.nframes, &fps);
345-
}
340+
// Temporal WCS particle crash hack
341+
// DO NOT MERGE!
342+
if (!bm_is_valid(info.bitmap))
343+
continue;
344+
//Assertion(bm_is_valid(info.bitmap), "Invalid bitmap handle passed to particle create.");
345+
bm_get_info(info.bitmap, nullptr, nullptr, nullptr, &info.nframes, &fps);
346346

347347
if (m_hasLifetime) {
348348
if (m_keep_anim_length_if_available && info.nframes > 1) {

code/particle/ParticleEffect.h

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,41 @@ class ParticleEffect {
8989
RADIUS_MULT,
9090
LENGTH_MULT,
9191
ANIM_STATE,
92+
LIGHT_RADIUS_MULT,
93+
LIGHT_SOURCE_RADIUS_MULT,
94+
LIGHT_INTENSITY_MULT,
95+
LIGHT_R_MULT,
96+
LIGHT_G_MULT,
97+
LIGHT_B_MULT,
98+
LIGHT_CONE_ANGLE_MULT,
99+
LIGHT_CONE_INNER_ANGLE_MULT,
92100

93101
NUM_VALUES
94102
};
95103

104+
struct LightInformation {
105+
float light_radius;
106+
float source_radius;
107+
float intensity;
108+
float r, g, b;
109+
float cone_angle, cone_inner_angle;
110+
111+
enum class LightSourceMode : uint8_t {
112+
POINT,
113+
AS_PARTICLE,
114+
TO_LAST_POS,
115+
CONE
116+
} light_source_mode;
117+
118+
constexpr LightInformation() : light_radius(0.f), source_radius(0.f), intensity(0.f), r(0.f), g(0.f), b(0.f), cone_angle(0.f), cone_inner_angle(0.f), light_source_mode(LightSourceMode::POINT) {}
119+
};
120+
96121
private:
97122
friend struct ParticleParse;
98123
friend class ParticleManager;
99124
friend int ::parse_weapon(int, bool, const char*);
100125
friend ParticleEffectHandle scripting::api::getLegacyScriptingParticleEffect(int bitmap, bool reversed);
126+
friend bool move_particle(float frametime, particle* part);
101127

102128
SCP_string m_name; //!< The name of this effect
103129

@@ -146,6 +172,8 @@ class ParticleEffect {
146172
std::optional<vec3d> m_manual_offset;
147173
std::optional<vec3d> m_manual_velocity_offset;
148174

175+
std::optional<LightInformation> m_light_source;
176+
149177
ParticleEffectHandle m_particleTrail;
150178

151179
float m_particleChance; //Deprecated. Use particle num random ranges instead.
@@ -260,10 +288,20 @@ class ParticleEffect {
260288

261289
constexpr static auto modular_curves_lifetime_definition = make_modular_curve_definition<particle, ParticleLifetimeCurvesOutput>(
262290
std::array {
263-
std::pair {"Radius", ParticleLifetimeCurvesOutput::RADIUS_MULT},
264-
std::pair {"Velocity", ParticleLifetimeCurvesOutput::VELOCITY_MULT},
265-
std::pair {"Length", ParticleLifetimeCurvesOutput::LENGTH_MULT},
266-
std::pair {"Anim State", ParticleLifetimeCurvesOutput::ANIM_STATE},
291+
std::pair {"Radius", ParticleLifetimeCurvesOutput::RADIUS_MULT},
292+
std::pair {"Velocity", ParticleLifetimeCurvesOutput::VELOCITY_MULT},
293+
std::pair {"Radius Mult", ParticleLifetimeCurvesOutput::RADIUS_MULT}, // Modern Naming Alias
294+
std::pair {"Velocity Mult", ParticleLifetimeCurvesOutput::VELOCITY_MULT}, // Modern Naming Alias
295+
std::pair {"Length Mult", ParticleLifetimeCurvesOutput::LENGTH_MULT},
296+
std::pair {"Anim State Mult", ParticleLifetimeCurvesOutput::ANIM_STATE},
297+
std::pair {"Light Radius Mult", ParticleLifetimeCurvesOutput::LIGHT_RADIUS_MULT},
298+
std::pair {"Light Source Radius Mult", ParticleLifetimeCurvesOutput::LIGHT_SOURCE_RADIUS_MULT},
299+
std::pair {"Light Intensity Mult", ParticleLifetimeCurvesOutput::LIGHT_INTENSITY_MULT},
300+
std::pair {"Light R Mult", ParticleLifetimeCurvesOutput::LIGHT_R_MULT},
301+
std::pair {"Light G Mult", ParticleLifetimeCurvesOutput::LIGHT_G_MULT},
302+
std::pair {"Light B Mult", ParticleLifetimeCurvesOutput::LIGHT_B_MULT},
303+
std::pair {"Light Cone Angle Mult", ParticleLifetimeCurvesOutput::LIGHT_CONE_ANGLE_MULT},
304+
std::pair {"Light Cone Inner Angle Mult", ParticleLifetimeCurvesOutput::LIGHT_CONE_INNER_ANGLE_MULT},
267305
},
268306
//Should you ever need to access something from the effect as a modular curve input:
269307
//std::pair {"", modular_curves_submember_input<&particle::parent_effect, &ParticleSubeffectHandle::getParticleEffect, &ParticleEffect::>{}}

code/particle/ParticleParse.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,55 @@ namespace particle {
282282
}
283283
}
284284

285+
static void parseLightEmissionSettings(ParticleEffect& effect) {
286+
if (optional_string("$Emits Light:")) {
287+
ParticleEffect::LightInformation& light = effect.m_light_source.emplace();
288+
289+
required_string("+Type:");
290+
switch(required_string_one_of(4, "Point", "As Particle", "To Last Position", "Cone")) {
291+
case 0:
292+
Mp += 5;
293+
light.light_source_mode = ParticleEffect::LightInformation::LightSourceMode::POINT;
294+
break;
295+
case 1:
296+
Mp += 11;
297+
light.light_source_mode = ParticleEffect::LightInformation::LightSourceMode::AS_PARTICLE;
298+
break;
299+
case 2:
300+
Mp += 16;
301+
light.light_source_mode = ParticleEffect::LightInformation::LightSourceMode::TO_LAST_POS;
302+
break;
303+
case 3:
304+
Mp+=4;
305+
light.light_source_mode = ParticleEffect::LightInformation::LightSourceMode::CONE;
306+
break;
307+
}
308+
309+
required_string("+Light Radius:");
310+
stuff_float(&light.light_radius);
311+
312+
if (optional_string("+Light Source Radius:")) {
313+
stuff_float(&light.source_radius);
314+
}
315+
316+
required_string("+Intensity:");
317+
stuff_float(&light.intensity);
318+
319+
required_string("+Color:");
320+
stuff_float(&light.r);
321+
stuff_float(&light.g);
322+
stuff_float(&light.b);
323+
324+
if (optional_string("+Cone Angle:")) {
325+
stuff_float(&light.cone_angle);
326+
}
327+
328+
if (optional_string("+Cone Inner Angle:")) {
329+
stuff_float(&light.cone_inner_angle);
330+
}
331+
}
332+
}
333+
285334
static void parseModularCurvesLifetime(ParticleEffect& effect) {
286335
effect.m_lifetime_curves.parse("$Particle Lifetime Curve:");
287336
}
@@ -324,6 +373,7 @@ namespace particle {
324373
parseLength(effect);
325374
parseLifetime(effect);
326375
parseParentLocal(effect);
376+
parseLightEmissionSettings(effect);
327377

328378
//Spawner Settings
329379
parseTiming(effect);

code/particle/particle.cpp

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "debugconsole/console.h"
1616
#include "globalincs/systemvars.h"
1717
#include "graphics/2d.h"
18+
#include "lighting/lighting.h"
1819
#include "math/curve.h"
1920
#include "render/3d.h"
2021
#include "render/batching.h"
@@ -192,7 +193,7 @@ namespace particle
192193
* @param part The particle to process for movement
193194
* @return @c true if the particle has expired and should be removed, @c false otherwise
194195
*/
195-
static bool move_particle(float frametime, particle* part) {
196+
bool move_particle(float frametime, particle* part) {
196197
if (part->age == 0.0f)
197198
{
198199
part->age = 0.00001f;
@@ -232,11 +233,84 @@ namespace particle
232233

233234
const auto& source_effect = part->parent_effect.getParticleEffect();
234235

235-
float vel_scalar = source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::VELOCITY_MULT, std::forward_as_tuple(*part, vm_vec_mag_quick(&part->velocity)) );
236+
float part_velocity = vm_vec_mag_quick(&part->velocity);
237+
float vel_scalar = source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::VELOCITY_MULT, std::forward_as_tuple(*part, part_velocity) );
236238

237239
// move as a regular particle
240+
vec3d prev_pos = part->pos;
238241
part->pos += (part->velocity * vel_scalar) * frametime;
239242

243+
const auto& curve_input = std::forward_as_tuple(*part, part_velocity * vel_scalar);
244+
245+
if (source_effect.m_light_source) {
246+
const auto& light_source = *source_effect.m_light_source;
247+
248+
vec3d p_pos;
249+
if (part->attached_objnum >= 0)
250+
{
251+
vm_vec_unrotate(&p_pos, &part->pos, &Objects[part->attached_objnum].orient);
252+
vm_vec_add2(&p_pos, &Objects[part->attached_objnum].pos);
253+
}
254+
else
255+
{
256+
p_pos = part->pos;
257+
}
258+
259+
float light_radius = light_source.light_radius * source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::LIGHT_RADIUS_MULT, curve_input);
260+
float source_radius = light_source.source_radius * source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::LIGHT_SOURCE_RADIUS_MULT, curve_input);
261+
float intensity = light_source.intensity * source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::LIGHT_INTENSITY_MULT, curve_input);
262+
float r = light_source.r * source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::LIGHT_R_MULT, curve_input);
263+
float g = light_source.g * source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::LIGHT_G_MULT, curve_input);
264+
float b = light_source.b * source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::LIGHT_B_MULT, curve_input);
265+
266+
switch (light_source.light_source_mode) {
267+
case ParticleEffect::LightInformation::LightSourceMode::POINT:
268+
light_add_point(&p_pos, light_radius, light_radius, intensity, r, g, b, source_radius);
269+
break;
270+
case ParticleEffect::LightInformation::LightSourceMode::TO_LAST_POS: {
271+
vec3d p_prev_pos;
272+
if (part->attached_objnum >= 0)
273+
{
274+
vm_vec_unrotate(&p_prev_pos, &prev_pos, &Objects[part->attached_objnum].last_orient);
275+
vm_vec_add2(&p_prev_pos, &Objects[part->attached_objnum].last_pos);
276+
}
277+
else
278+
{
279+
p_prev_pos = prev_pos;
280+
}
281+
light_add_tube(&p_prev_pos, &p_pos, light_radius, light_radius, intensity, r, g, b, source_radius);
282+
}
283+
break;
284+
case ParticleEffect::LightInformation::LightSourceMode::AS_PARTICLE:
285+
if (part->length != 0.0f) {
286+
vec3d p1;
287+
vm_vec_copy_normalize_safe(&p1, &part->velocity);
288+
if (part->attached_objnum >= 0) {
289+
vm_vec_unrotate(&p1, &p1, &Objects[part->attached_objnum].orient);
290+
}
291+
p1 *= part->length * source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::LENGTH_MULT, curve_input);
292+
p1 += p_pos;
293+
light_add_tube(&p_pos, &p1, light_radius, light_radius, intensity, r, g, b, source_radius);
294+
}
295+
else {
296+
light_add_point(&p_pos, light_radius, light_radius, intensity, r, g, b, source_radius);
297+
}
298+
break;
299+
case ParticleEffect::LightInformation::LightSourceMode::CONE: {
300+
float cone_angle = light_source.cone_angle * source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::LIGHT_CONE_ANGLE_MULT, curve_input);
301+
float cone_inner_angle = light_source.cone_inner_angle * source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::LIGHT_CONE_INNER_ANGLE_MULT, curve_input);
302+
vec3d p1;
303+
vm_vec_copy_normalize_safe(&p1, &part->velocity);
304+
if (part->attached_objnum >= 0) {
305+
vm_vec_unrotate(&p1, &p1, &Objects[part->attached_objnum].orient);
306+
}
307+
308+
light_add_cone(&p_pos, &p1, cone_angle, cone_inner_angle, false, light_radius, light_radius, intensity, r, g, b, source_radius);
309+
}
310+
break;
311+
}
312+
}
313+
240314
return false;
241315
}
242316

@@ -370,7 +444,7 @@ namespace particle
370444

371445
Assert( (cur_frame < part->nframes) || (part->nframes == 0 && cur_frame == 0) );
372446

373-
float radius = part->radius * source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::VELOCITY_MULT, curve_input);
447+
float radius = part->radius * source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::RADIUS_MULT, curve_input);
374448

375449
if (part->length != 0.0f) {
376450
vec3d p0 = p_pos;

0 commit comments

Comments
 (0)